summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.htaccess5
-rwxr-xr-xBulletLabRemix/index.html110
-rw-r--r--about_l.html413
-rw-r--r--blog/blogext.css3
-rw-r--r--blog/content/.htaccess2
-rw-r--r--blog/content/util/indexer.cpp48
-rw-r--r--blog/list/.htaccess1
-rw-r--r--blog/list/0.html26
-rw-r--r--blog/list/1.html36
-rw-r--r--blog/list/10.html91
-rw-r--r--blog/list/11.html71
-rw-r--r--blog/list/2.html36
-rw-r--r--blog/list/3.html36
-rw-r--r--blog/list/4.html36
-rw-r--r--blog/list/5.html36
-rw-r--r--blog/list/6.html36
-rw-r--r--blog/list/7.html36
-rw-r--r--blog/list/8.html36
-rw-r--r--blog/list/9.html34
-rw-r--r--blog/list/acmicpc/0.html44
-rw-r--r--blog/list/c++/0.html40
-rw-r--r--blog/list/computer-repairing/0.html52
-rw-r--r--blog/list/contest/0.html42
-rw-r--r--blog/list/daily-life/0.html42
-rw-r--r--blog/list/daily-life/1.html40
-rw-r--r--blog/list/design/0.html40
-rw-r--r--blog/list/devel/0.html40
-rw-r--r--blog/list/devel/1.html40
-rw-r--r--blog/list/device-review/0.html34
-rw-r--r--blog/list/device-review/1.html21
-rw-r--r--blog/list/electronics/0.html76
l---------blog/list/electronics/index.html1
-rw-r--r--blog/list/fiction/0.html71
l---------blog/list/fiction/index.html1
-rw-r--r--blog/list/garbage/0.html30
-rw-r--r--blog/list/garbage/1.html36
-rw-r--r--blog/list/garbage/2.html34
-rw-r--r--blog/list/garbage/3.html35
-rw-r--r--blog/list/garbage/4.html76
-rw-r--r--blog/list/hands-on/0.html13
-rw-r--r--blog/list/interactive/0.html42
-rw-r--r--blog/list/js/0.html40
-rw-r--r--blog/list/linux/0.html40
-rw-r--r--blog/list/midi/0.html18
-rw-r--r--blog/list/music/0.html36
-rw-r--r--blog/list/music/1.html76
-rw-r--r--blog/list/opengl/0.html40
-rw-r--r--blog/list/qmidiplayer/0.html40
-rw-r--r--blog/list/qt/0.html40
-rw-r--r--blog/list/random-xp/0.html42
-rw-r--r--blog/list/sophistry/0.html26
-rw-r--r--blog/list/sophistry/1.html14
-rw-r--r--blog/list/special-page/0.html42
-rw-r--r--blog/list/web/0.html44
-rw-r--r--blog/list/webgl/0.html40
-rw-r--r--blog/post/2014-11-14.html143
-rw-r--r--blog/post/2015-10-29.html44
-rw-r--r--blog/post/2015-10-30.html42
-rw-r--r--blog/post/2015-10-31.html42
-rw-r--r--blog/post/2015-11-01.html42
-rw-r--r--blog/post/2015-11-22.html42
-rw-r--r--blog/post/2015-12-20.html42
-rw-r--r--blog/post/2015-12-23.html42
-rw-r--r--blog/post/2015-12-27.html42
-rw-r--r--blog/post/2016-01-03.html42
-rw-r--r--blog/post/2016-01-16.html42
-rw-r--r--blog/post/2016-01-25.html42
-rw-r--r--blog/post/2016-02-14.html42
-rw-r--r--blog/post/2016-02-18.html42
-rw-r--r--blog/post/2016-03-26.html42
-rw-r--r--blog/post/2016-04-09.html56
-rw-r--r--blog/post/2016-05-12.html42
-rw-r--r--blog/post/2016-06-21.html56
-rw-r--r--blog/post/2016-09-24.html42
-rw-r--r--blog/post/2017-01-09.html42
-rw-r--r--blog/post/2017-01-18.html54
-rw-r--r--blog/post/2017-02-13.html44
-rw-r--r--blog/post/2017-04-11.html42
-rw-r--r--blog/post/2017-05-08.html42
-rw-r--r--blog/post/2017-06-09.html42
-rw-r--r--blog/post/2017-06-29.html56
-rw-r--r--blog/post/2017-11-25.html42
-rw-r--r--blog/post/2017-12-21.html54
-rw-r--r--blog/post/2018-01-05.html42
-rw-r--r--blog/post/2018-01-07.html50
-rw-r--r--blog/post/2018-02-05.html42
-rw-r--r--blog/post/2018-03-17.html42
-rw-r--r--blog/post/2018-04-17.html42
-rw-r--r--blog/post/2018-04-22.html82
-rw-r--r--blog/post/2018-05-03.html92
-rw-r--r--blog/post/2018-05-08.html42
-rw-r--r--blog/post/2018-05-18.html42
-rw-r--r--blog/post/2018-06-05.html42
-rw-r--r--blog/post/2018-06-07.html42
-rw-r--r--blog/post/2018-10-11.html71
-rw-r--r--blog/post/2018-12-06.html240
-rw-r--r--blog/post/2019-02-13.html174
-rw-r--r--blog/post/2019-04-25.html862
-rw-r--r--blog/post/2019-06-24.html473
-rw-r--r--blog/post/2019-09-04.html83
-rw-r--r--blog/post/2020-11-20.html2522
-rw-r--r--blog/post/2021-06-03.html41
-rw-r--r--blog/post/2021-10-10.html972
-rw-r--r--blog/post/2022-07-23.html503
-rw-r--r--blog/post/2022-11-27.html661
-rw-r--r--blog/post/2023-11-13.html471
-rw-r--r--blog/post/2024-02-02.html612
-rw-r--r--blog/post/2024-02-04.html600
-rw-r--r--blog/post/2024-02-29.html165
-rw-r--r--blog/post/2024-03-02.html394
-rw-r--r--blog/post/Privacy.html104
-rw-r--r--blog/post/TOP.html60
-rw-r--r--blog/post/rbus-adat-m.html533
-rw-r--r--blog/sbs_1/bloglist.php77
-rw-r--r--blog/sbs_1/bloglista.php202
-rw-r--r--blog/sbs_1/blogreader.php90
-rw-r--r--blog/sbs_1/blossom.pngbin140486 -> 0 bytes
-rw-r--r--blog/sbs_1/dbloglist.php75
-rw-r--r--blog/sbs_1/dblogreader.php90
-rw-r--r--blog/sbs_1/decryptor.js73
-rw-r--r--blog/sbs_1/extras.css50
-rw-r--r--blog/sbs_1/footnoter.js24
-rw-r--r--blog/sbs_1/simple_html_dom.php975
-rw-r--r--blog/sbs_2/blogext.css65
-rw-r--r--blog/sbs_2/bloglist.js216
-rw-r--r--blog/sbs_2/blogpost.js103
-rw-r--r--blog/sbs_2/cgi-bin/.htaccess3
l---------blog/sbs_2/cgi-bin/get-archive-list.cgi1
l---------blog/sbs_2/cgi-bin/get-post-content.cgi1
-rw-r--r--blog/sbs_2/cgi-src/cgiutils.hpp245
-rwxr-xr-xblog/sbs_2/cgi-src/get-archive-listbin515680 -> 0 bytes
-rw-r--r--blog/sbs_2/cgi-src/get-archive-list.cpp200
-rwxr-xr-xblog/sbs_2/cgi-src/get-post-contentbin39024 -> 0 bytes
-rw-r--r--blog/sbs_2/cgi-src/get-post-content.cpp83
-rw-r--r--blog/sbs_2/decryptor.js73
-rw-r--r--blog/sbs_2/footnoter.js24
-rw-r--r--blog/sbs_2/index.html1
-rw-r--r--blog/sbs_2/list94
-rw-r--r--blog/sbs_2/post108
-rw-r--r--common.css82
-rw-r--r--index.shtml (renamed from index.html)129
-rw-r--r--leave-a-message/.htaccess1
-rw-r--r--leave-a-message/blossom.pngbin140486 -> 0 bytes
-rw-r--r--leave-a-message/extras.css20
-rw-r--r--leave-a-message/index.php91
-rw-r--r--leave-a-message/writemessage.php66
-rwxr-xr-xlibs/code/index.html24
-rw-r--r--libs/music/pcm18
-rw-r--r--libs/music/player32
-rwxr-xr-xlibs/music/player.d/cgi-bin/m3u8.cgi2
-rwxr-xr-xlibs/music/player.d/cgi-bin/pcm.cgi81
-rw-r--r--libs/music/player.d/jquery-3.0.0.js10037
-rw-r--r--libs/music/player.d/jquery-3.0.0.min.js4
-rw-r--r--libs/music/player.d/main.js610
-rw-r--r--libs/music/player.d/main_static.js179
-rw-r--r--libs/music/player.d/pcm.js200
-rw-r--r--libs/music/player.d/player.php147
-rw-r--r--libs/music/player.d/playlists/01
-rw-r--r--libs/music/player.d/playlists/11
-rw-r--r--libs/music/player.d/playlists/Converted-Modules.playlist20
-rw-r--r--libs/music/player.d/plistcreator.php20
-rw-r--r--libs/music/player.d/plisteditor.php146
-rw-r--r--libs/music/player.d/progress-bar.js97
-rw-r--r--libs/music/player.d/styles.css13
-rwxr-xr-xlibs/pictures/.header.html23
-rwxr-xr-xlibs/pictures/.htaccess4
-rw-r--r--libs/pictures/osunix-logo_sq_thicken.pngbin692232 -> 0 bytes
-rwxr-xr-xlibs/pictures/pliba.php63
-rwxr-xr-xlibs/pictures/plibb.php63
-rw-r--r--rbusif/index.html75
-rw-r--r--rbusif/index.md64
-rw-r--r--theme0a.css80
-rw-r--r--theme0b.css80
-rw-r--r--theme1a.css80
-rw-r--r--theme1b.css80
-rw-r--r--theme2a.css80
-rw-r--r--theme2b.css80
-rw-r--r--theme3a.css80
-rw-r--r--theme3b.css80
179 files changed, 11765 insertions, 17989 deletions
diff --git a/.htaccess b/.htaccess
index f9e8f01..3f044bb 100755
--- a/.htaccess
+++ b/.htaccess
@@ -1,4 +1,7 @@
-Options +FollowSymlinks
+Options +FollowSymlinks +Includes
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+DirectoryIndex index.shtml index.html
<Files ~ "^.*\.([Hh][Tt][Aa])">
Order allow,deny
Deny from all
diff --git a/BulletLabRemix/index.html b/BulletLabRemix/index.html
index 408a2fa..fac7a1b 100755
--- a/BulletLabRemix/index.html
+++ b/BulletLabRemix/index.html
@@ -27,10 +27,19 @@ div.TPartitle
<span style="float:right;">Meet the power of open source!</span></td>
</tr>
<tr>
- <td class="TText"><div class="TPartitle">Over view</div><br>
+ <td class="TText"><div class="TPartitle">Notice</div><br>
+ All development of Bullet Lab Remix ceased in 2017, and as of August 2023 there's no plan to resume. In fact it's
+ probably never going to resume unless I literally have a brain tumor.
+ </tr>
+ <tr>
+ <td class="TText"><div class="TPartitle">Overview</div><br>
<img src="./scrot/BLRIII_Menu.png" width="480" height="360" alt="BLRIII menu screenshot"><br>
Bullet Lab Remix
- is an open source game project inspired by Gameboltz's <a href="http://www.funny-games.biz/bullet-lab.html">Bullet Lab</a> <a href="http://www.gameboltz.com/game/337/bulletlab">(Original link, dead)</a> and (somehow) <a href="http://www16.big.or.jp/~zun/">the Touhou Project</a>. However, this is a strange game with its own style.<br>
+ is an open source game project and an attempt to further develop <a href="https://github.com/styxtwo">styxtwo's</a>
+ <a href="http://www.funny-games.biz/bullet-lab.html">BulletLAB</a>
+ <a href="http://www.gameboltz.com/game/337/bulletlab">(Original link, dead)</a>.
+ Level design is heavily influenced by
+ <a href="http://www16.big.or.jp/~zun/">the Touhou Project</a>. However, this is a strange game with its own style.<br>
(Surprisingly, this game has native Linux support!)</td>
</tr>
<tr>
@@ -40,22 +49,103 @@ div.TPartitle
</tr>
<tr>
<td class="TText"><div class="TPartitle">Development Status</div><br>
- [20150912]Bullet Lab Remix III is now in its main development phase.<br>
- [20150614]Bullet Lab Remix III first development phase finished... The whole development folder can be found <a href="./public/BLRScriptTestbed">here</a>.<br>
- [20150217]Bullet Lab Remix II 1.0.0-0 completed! Get source code <a href="https://github.com/chirs241097/bullet-lab-remix">Here</a>!<br>
- [20130828]Bullet Lab Remix I 1.0.3 (stable release) Released!
+ [20150912] Bullet Lab Remix III is now in its main development phase.<br>
+ [20150614] Bullet Lab Remix III first development phase finished... <s>The whole development folder can be found <a href="#">here</a>.</s><br>
+ [20150217] Bullet Lab Remix II 1.0.0-0 completed! Get source code <a href="https://github.com/chirs241097/bullet-lab-remix">Here</a>!<br>
+ [20130828] Bullet Lab Remix I 1.0.3 (stable release) Released!
</td>
</tr>
<tr>
<td class="TText"><div class="TPartitle">Distribution</div><br>
- <a href="./public">Click here</a> to visit the download folder, which includes all binaries for different operating systems and, of course, the source code!
- <br><br>
- <a href="https://github.com/chirs241097/bullet-lab-remix">Project git repository</a>
+ <a href="https://filestorage.chrisoft.org/blr/">Click here</a> to visit the download folder. All versions -- from BLR I o BLR III Test Bed
+ are there, including the original modded flash version.<br>
+ To get the source code, please check out the
+ <a href="https://cgit.chrisoft.org/bullet-lab-remix.git/">project git repository</a>. I unfortunately no longer
+ have the sources for the modded flash version, but any decent Flash decompiler should be helpful here.
</td>
</tr>
<tr>
<td class="TText"><div class="TPartitle">Screen Shots</div><br>
- View Screen Shots <a href="./scrot.html">Here</a>(not maintained and outdated).</td>
+ View Screen Shots <a href="./scrot.html">Here</a> (not maintained and outdated).</td>
+ </tr>
+ <tr>
+ <td class="TText"><div class="TPartitle">Untold back story of the project</div><br>
+ <p>
+ The year was 2012. I was a high school freshman deeply sucked into the Touhou rabbit hole. (yeah, yeah, I know. Weeb and nerd stuff. But calling me
+ a weeb isn't appropriate since I myself is Asian...) One day when I was randomly roaming on the Internet I noticed the game "BulletLAB". I played
+ it for a bit, and thanks to my Touhou addiction I cleared the entire game in medium difficulty on the same day. It turns out if you are accustomed
+ to Touhou-level bullet hell (well, I wasn't even that good back then, only playing the normal difficulty. And it was all down hill from there),
+ this game is pretty much a walk in the park.
+ </p>
+ <p>
+ "This game needs some desperate help," so I thought. So I busted out my flash decompiler and adobe flash (both pirated, of course). Before long a
+ modded version came into being. Basically I buffed the sh*t out of certain levels and, cough cough, totally play tested all of them (not the truth
+ lol). I also removed momentum from player movement completely since that's a completely foreign concept to Touhou players.
+ </p>
+ <p>
+ But soon I found myself strangled by the poor performance of Flash. The game quickly slows down to a crawl when there's too many bullets on screen.
+ I had to move on to something other than flash.
+ </p>
+ <p>
+ Coincidentally I was playing another shooter game called "Beat Hazard" at the time. I learned about the 2D game engine
+ <a href="https://web.archive.org/web/20120918044348/http://hge.relishgames.com/">"HGE"</a> by going through its game files.
+ Soon enough I started rewriting the entire game using HGE and C++.
+ </p>
+ <p>
+ By the following year (early 2013), the first iteration of Bullet Lab Remix entered maturity. Thanks to the hardware accelerated nature of HGE,
+ it ran at a solid 1000 FPS on my crappy laptop. And no - the code does not look good, thanks to my competitive programming entrenched ass.
+ </p>
+ <p>
+ At around the same time, I started daily driving Linux, which gave me the motivation to port the game to Linux. I found out
+ <a href="https://icculus.org/hge-unix/">hge-unix</a>, a port to hge to any platform supported by SDL. Without much trouble, a Linux port was soon
+ released. Unfortunately I didn't learn how to write a makefile until years later, so for quite a long time these games are built with a shell
+ script.
+ </p>
+ <p>
+ Soon after I started the development of Bullet Lab Remix II, this time almost exclusively done on Linux. I took a much more liberal approach
+ designing the levels, that is, completely unhinged from the original game and taking direct inspiration from Touhou. Some levels are even just
+ blatant rip-off of Touhou spell cards. The game took shape fairly quickly and entered finalizing phase in 2014, at which point however I got
+ stuck in trying to come up with in-game music for it. Untalented and unfamiliar with music production tool, it wasn't an easy task for me back
+ then.
+ </p>
+ <p>
+ While I was busy worrying about the music, I also ported HGE to DirectX 9 on Windows, which turned out to be a trivial task as DirectX 9 kept
+ almost everything from DirectX 8 and is more or less a find-and-replace job. I also started experimenting with extending the feature set of HGE,
+ giving it basic support for rendering 3D-transformed sprites and 3D objects, as well as truetype font rendering. With these new features I started
+ working on a new secret project called BLRScriptTestBed in which I tested all these new library features and laid down the foundation
+ of what was supposed to be the level scripting engine used in BLR III.
+ </p>
+ <p>
+ But time was merciless. Before I could come up with a single track of my own, my free time is almost up -- it was the final year of high school
+ and I'm soon facing the National College Entrance Examination (more notoriously known as "Gaokao"). I had no choice but to give BLR II a rushed
+ finish. I pulled a few (2, to be precise) tracks from modarchive.org, chopped them up as the tracks, and called it done.
+ </p>
+ <p>
+ In the final year of my high school, during which I had to actually attend classes instead of doing my competitive programming nonsense, I was
+ planning for the third game non-stop. I had an entire notebook that contains nothing but level design, code design and supposed story line for
+ BLR III. All that effort turned out to be in vain though, because the third game, as you already know, is never finished.
+ </p>
+ <p>
+ When I started college in 2015, development of BLR III briefly resumed for a bit. Curiously the first thing I decided to do is to fork HGE, perhaps
+ because I decided that I've outgrown this purely 2D-oriented engine. The original fork wasn't too much of a divergence from the original at all.
+ I just unified the original HGE code base and hge-unix's code base, merged my added 3D and truetype functionalities, and called it my fork.
+ Later the fork was given a major API overhaul, migrated to GLFW instead of SDL and rewritten in OpenGL 3.2, at which point I gave it the name
+ "SMELT".
+ </p>
+ <p>
+ Development continued fairly smoothly until late December 2015, when I decided I need to start a new project (now known as QMidiPlayer). I was super
+ passionate about this new project, so passionate that I already have a prototype with 3D MIDI visualization by mid January 2016 (which is also
+ implemented using SMELT). This new project quickly took precedence over everything about BLR III. With that and my decreasing interest in danmaku
+ (or bullet hell) type games in general, unsurprisingly, BLR was neglected to its final demise.
+ </p>
+ <p>
+ If you ask me if I've ever got anything out of this project, I'd answer that with a definite yes, despite that there are few people outside of my
+ tiny circle that know the existence of this game. Besides the priceless experience dealing with accelerated graphics and a few other programming
+ tricks, the most significant self-discovery from the project is that ... I should probably never work on a game on my own again.
+ </p>
+ <p>
+ Ah yes I forgot to apologize for the terrible l33t haxxor style of the page. Average 16yo behavior.
+ </p>
</tr>
<tr>
<td colspan="4" class="TText"><div align="center">Copyright Chrisoft 2015&nbsp;&nbsp;<a href="../about.html">About</a>&nbsp;&nbsp;Site Map</div></td>
diff --git a/about_l.html b/about_l.html
index 181345d..e088122 100644
--- a/about_l.html
+++ b/about_l.html
@@ -13,7 +13,7 @@
<li>hardware terminator (as always)</li>
<ul>
<li>server of this site use to be a self-built machine</li>
- <li>many failed attempts to repear my gadgets (a few of them did succeed though)</li>
+ <li>many failed attempts to repair my gadgets (a few of them did succeed though)</li>
<li>now trying to collect vintage hardware (to mess around with)</li>
<li>tried to build a 'computer' out of redstone in Minecraft (does not look like it will be finished anytime soon)</li>
</ul>
@@ -33,13 +33,14 @@
</ul>
</p>
<p>
- <s>Religious</s> beliefs: Free software, K.I.S.S., Linux (or rather, GNU/Linux), LF for line breaks, UTF-8, <s>FSF</s>.
+ <s>Religious</s> beliefs: Free software, K.I.S.S., Linux (or GNU/Linux if you so prefer), LF for line breaks, UTF-8, <s>FSF</s>.
</p>
<p>
Chris Xiong is a young coder from a small city of China. Now aged more
than 20, this hacker is still just writing code for fun. Crazy follower
- of &quot;Free Software&quot;. Develops free software alone but seldom
- feels lonely. Sincere friends are always cherished.
+ of &quot;Free Software&quot; (but not FSF's ideology in particular).
+ Develops free software alone but seldom feels lonely. Sincere friends
+ are always cherished.
</p>
<p>
This site is written from scratch in XHTML without using any kind of framework whatsoever.
@@ -49,8 +50,9 @@
</p>
<p style="text-indent:0;">
- Twitter: <a href="https://twitter.com/chirs241097">@chirs241097</a><br>
- E-Mail: chirs241097 'at' gmail 'dot' com<br>
+ Mastodon: <a href="https://c.im/@chirs241097">chirs241097@c.im</a><br>
+ Twitter: <a href="https://twitter.com/chirs241097">(sorry I blocked the entire website but in case you still want to visit that cesspool)</a><br>
+ E-Mail: <code style="font-weight:bold;text-decoration:underline dotted;" class="TText" title="Paste this into a UNIX terminal. Sorry Windows users.">tr '\!-~' 'P-~\!-O' <<< '49:CDac`_hfo8>2:=]4@>'</code><br>
Discord: Chris Xiong#1024<br>
<a href="/pubkey.txt">GPG key</a><br>
Tox:<br>
@@ -75,12 +77,12 @@
<td>1997-10-24 17:36</td>
</tr>
<tr>
- <td>Hometown</td>
+ <td>Ancestry</td>
<td>重慶&nbsp;涪陵&nbsp;&nbsp;Chongqing Fuling</td>
</tr>
<tr>
<td>Occupation</td>
- <td>MSCS grad student somewhere<br>"Free" free software developer</td>
+ <td>(pre-candidacy) PhD student in CS somewhere<br>"Free" free software developer</td>
</tr>
<tr>
<td>Personality</td>
@@ -93,123 +95,300 @@
<tr>
<td>Skills</td>
<td>
- <a class="TText" onclick="this.innerHTML=&quot;\
- C++ (63 out of 100)&lt;br&gt;\
- C (65 out of 100)&lt;br&gt;\
- Pascal (64 out of 100, declining, though)&lt;br&gt;\
- HTML (59 out of 100)&lt;br&gt;\
- CSS (58 out of 100)&lt;br&gt;\
- JavaScript (61 out of 100)&lt;br&gt;\
- Java (53 out of 100)&lt;br&gt;\
- PHP (36 out of 100)&lt;br&gt;\
- Python (61 out of 100)&lt;br&gt;\
- C# (28 out of 100)&lt;br&gt;\
- Modern OpenGL (58 out of 100, GL 3.0+, GLES, WebGL)&lt;br&gt;\
- Legacy OpenGL (65 out of 100, GL 1.x~2.x)&lt;br&gt;\
- &quot;;">Messing around</a><br>
- <a class="TText" onclick="this.innerHTML=&quot;\
- Competitive programming (56 out of 100) &lt;br&gt;\
- Software engineering (26 out of 100) (wtf is this bs?) &lt;br&gt;\
- Reverse engineering (42 out of 100) &lt;br&gt;\
- Minecraft modding (33 out of 100) &lt;br&gt;\
- &quot;;">Messing around</a><br>
- <a class="TText" onclick="this.innerHTML=&quot;\
- Linux (62 out of 100) (Daily usage/server maintaince and troubleshooting only. Kernel hacking not (really) included.)&lt;br&gt;\
- Windows (55 out of 100) (Even lesser than above)&lt;br&gt;\
- macOS (33 out of 100) (Worst OS, ever!)&lt;br&gt;\
- &quot;;">Messing around</a><br>
- <a class="TText" onclick="this.innerHTML=&quot;\
- Piano (45 out of 100, declining)&lt;br&gt;\
- Cakewalk SONAR (65 out of 100)&lt;br&gt;\
- Cubase (36 out of 100)&lt;br&gt;\
- &quot;;">Messing around</a><br>
- <a class="TText" onclick="this.innerHTML=&quot;\
- GIMP (63 out of 100, image processing only)&lt;br&gt;\
- Inkscape (61 out of 100, simple patterns only)&lt;br&gt;\
- Kdenlive (58 out of 100, simple projects only)&lt;br&gt;\
- Blender (47 out of 100, never learn hotkeys)&lt;br&gt;\
- Photoshop (40 out of 100, declining)&lt;br&gt;\
- Flash (nvm, it's dead now!)&lt;br&gt;\
- &quot;;">Messing around</a><br>
- <a class="TText" onclick="this.innerHTML=&quot;\
- Repearing &lt;s&gt;disassembling&lt;/s&gt; (mostly electric) gadgets. (65 out of 100)\
- &quot;;">Messing around</a><br>
+ <details>
+ <summary>Messing around</summary>
+ C++ (63 out of 100)<br>
+ C (65 out of 100)<br>
+ Pascal (64 out of 100, declining, though)<br>
+ Rust (60 out of 100)<br>
+ Scheme and other LISP-like stuff (55 out of 100)<br>
+ Standard ML and OCaml (52 out of 100)<br>
+ HTML and XML (59 out of 100)<br>
+ CSS (58 out of 100)<br>
+ JavaScript (61 out of 100)<br>
+ Java (53 out of 100)<br>
+ PHP (36 out of 100)<br>
+ Python (61 out of 100)<br>
+ Shell scripting (60 out of 100)<br>
+ C# (28 out of 100)<br>
+ "Modern" OpenGL (58 out of 100, GL 3.0+, GLES, WebGL)<br>
+ "Legacy" OpenGL (65 out of 100, GL 1.x~2.x)<br>
+ "Legacy" DirectX (60 out of 100, DX 7, 8 and 9)<br>
+ Vulkan (Copy-pasting tutorial out of 100)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ Competitive programming (56 out of 100) <br>
+ Software engineering (26 out of 100) (wtf is this bs?) <br>
+ Reverse engineering (40 out of 100) <br>
+ Starting side projects and never finishing them (101 out of 100) <br>
+ Minecraft modding (33 out of 100)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ Linux (62 out of 100) (Daily usage/server maintenance and troubleshooting only. Kernel hacking not (really) included.)<br>
+ Windows (55 out of 100) (Even lesser than above)<br>
+ macOS (33 out of 100) (Worst OS, ever!)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ Piano (45 out of 100, declining)<br>
+ Cakewalk SONAR (65 out of 100)<br>
+ Cubase (36 out of 100)<br>
+ Collecting hardware synth that I'll never master (95 out of 100)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ GIMP (63 out of 100, image processing only)<br>
+ Inkscape (61 out of 100, simple patterns only)<br>
+ Kdenlive (58 out of 100, simple projects only)<br>
+ Blender (47 out of 100, never learned hotkeys)<br>
+ Photoshop (40 out of 100, declining)<br>
+ Flash (nvm, it's dead now!)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ Chinese (3 out of 100, simplified and traditional)<br>
+ English (4 out of 100)<br>
+ Latin (3 out of 100, classical Latin)<br>
+ French (1 out of 100)<br>
+ Japanese (0 out of 100)
+ </details>
+ <details>
+ <summary>Messing around</summary>
+ Repairing <s>disassembling</s> (mostly electric) gadgets. (65 out of 100)
+ </details>
</td>
</tr>
<tr>
- <td>Current Devices<br>(Click to expand)</td>
+ <td>Current Devices (plus previous devices in HTML comment blocks)</td>
<td>
- <a onclick="this.innerHTML=&quot;Self-built machine (former server of this site)&lt;ul&gt;\
- &lt;li&gt;Intel Core i7-2960XM&lt;/li&gt;\
- &lt;li&gt;16GB DDR3L-1600 Samsung RAM&lt;/li&gt;\
- &lt;li&gt;Supermicro X9SCV-QV4&lt;/li&gt;\
- &lt;li&gt;NVIDIA RTX 2080 FE&lt;/li&gt;\
- &lt;li&gt;Crucial M4-CT256M4SSD2 (256GB)&lt;/li&gt;\
- &lt;li&gt;Hitachi HTS725032A9A364 (320GB)&lt;/li&gt;\
- &lt;li&gt;HGST HTS721010A9E630 (1TB)&lt;/li&gt;\
- &lt;li&gt;Debian GNU/Linux sid (unstable) amd64&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Self-built machine (former server of this site)</a><br>
- <a onclick="this.innerHTML=&quot;Lenovo ThinkPad X1 yoga 1st Gen.&lt;ul&gt;\
- &lt;li&gt;Intel Core i7-6600U&lt;/li&gt;\
- &lt;li&gt;16GB DDR3L-1866 Samsung RAM&lt;/li&gt;\
- &lt;li&gt;Intel HD Graphics 520&lt;/li&gt;\
- &lt;li&gt;512GB Samsung NVMe SSD&lt;/li&gt;\
- &lt;li&gt;Gentoo GNU/Linux amd64&lt;/li&gt;\
- &lt;li&gt;Windows 10 Insider Pro x64&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Lenovo ThinkPad X1 yoga 1st Gen.</a><br>
- <a onclick="this.innerHTML=&quot;Xiao Mi MIX 3&lt;ul&gt;\
- &lt;li&gt;256GB Internal Storage&lt;/li&gt;\
- &lt;li&gt;Custom built LineageOS 16&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Xiao Mi MIX 3</a></br>
- <a onclick="this.innerHTML=&quot;Samsung Galaxy Note 4&lt;ul&gt;\
- &lt;li&gt;SM-N9100&lt;/li&gt;\
- &lt;li&gt;16GB Internal Storage&lt;/li&gt;\
- &lt;li&gt;Custom built LineageOS 16.0&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Samsung Galaxy Note 4</a></br>
- <a onclick="this.innerHTML=&quot;Samsung Galaxy S III&lt;ul&gt;\
- &lt;li&gt;GT-I9300&lt;/li&gt;\
- &lt;li&gt;16GB Internal Storage&lt;/li&gt;\
- &lt;li&gt;LineageOS 14.1&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Samsung Galaxy S III</a><br>
- <a onclick="this.innerHTML=&quot;Samsung Galaxy Tab 2 7.0&lt;ul&gt;\
- &lt;li&gt;GT-P3100&lt;/li&gt;\
- &lt;li&gt;8GB Internal Storage&lt;/li&gt;\
- &lt;li&gt;LineageOS 13.0&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Samsung Galaxy Tab 2 7.0</a><br>
- <a onclick="this.innerHTML=&quot;Raspberry Pi 2&lt;ul&gt;\
- &lt;li&gt;8GB MicroSD Card&lt;/li&gt;\
- &lt;li&gt;rev 1.1&lt;/li&gt;\
- &lt;li&gt;Raspbian testing (buster)&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Raspberry Pi 2</a><br>
- <a onclick="this.innerHTML=&quot;Raspberry Pi 3B+&lt;ul&gt;\
- &lt;li&gt;32GB MicroSD Card&lt;/li&gt;\
- &lt;li&gt;Arch Linux ARM (aarch64)&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Raspberry Pi 3B+</a><br>
- <a onclick="this.innerHTML=&quot;Raspberry Pi 4B&lt;ul&gt;\
- &lt;li&gt;4GB RAM&lt;/li&gt;\
- &lt;li&gt;32GB MicroSD Card&lt;/li&gt;\
- &lt;li&gt;Custom FrankenDebian (aarch64)&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Raspberry Pi 4B</a><br>
- <a onclick="this.innerHTML=&quot;iPod Classic 120G (Modded)&lt;ul&gt;\
- &lt;li&gt;Rev. 3 logic board&lt;/li&gt;\
- &lt;li&gt;128GB SSD&lt;/li&gt;\
- &lt;li&gt;Rockbox&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">iPod Classic 120G (Modded)</a><br>
- <a onclick="this.innerHTML=&quot;Xiaomi MAX (DEAD)&lt;ul&gt;\
- &lt;li&gt;Standard edition&lt;/li&gt;\
- &lt;li&gt;32GB Internal Storage&lt;/li&gt;\
- &lt;li&gt;Stock MIUI Beta ROM&lt;/li&gt;\
- &lt;/ul&gt;&quot;;">Xiaomi MAX (DEAD)</a><br>
- Lenovo Ideapad Y570 (defunct)<br>
- BlackBerry Curve 8900<br>
- NOKIA C5-03<br>
- NOKIA 500
+ <details>
+ <summary>Homelab "Harena"</summary><ul>
+ <li>2×Intel Xeon Gold 6130T</li>
+ <li>8×32GB DDR4-2666 Samsung ECC RAM</li>
+ <li>Supermicro X11DPH-T</li>
+ <li>NVIDIA RTX A4000 (PNY)</li>
+ <li>AMD RX 7900 XTX (Yeston)</li>
+ <li>Intel Arc A770 16GB (ASRock)</li>
+ <li>Samsung 980 Pro (2TB)</li>
+ <li>Samsung 990 Pro (2TB)</li>
+ <li>Gentoo GNU/Linux ~amd64</li>
+ <li>Windows 11 Pro x64 (virtualized)</li>
+ </ul></details>
+ <details>
+ <summary>DIY ITX tower "Alice" (former server of this site)</summary><ul>
+ <li>Intel Core i7-2960XM (4.5 GHz max turbo, 96W PL2, 72W PL1)</li>
+ <li>2×8GB DDR3L-1600 Samsung RAM</li>
+ <li>Supermicro X9SCV-QV4</li>
+ <li>NVIDIA RTX 2080 FE</li>
+ <li>Crucial M4-CT256M4SSD2 (256GB)</li>
+ <li>Hitachi HTS725032A9A364 (320GB)</li>
+ <li>HGST HTS721010A9E630 (1TB)</li>
+ <li>Debian GNU/Linux sid (unstable) amd64</li>
+ </ul></details>
+ <details>
+ <summary>Semi-retro tower "Concordia"</summary><ul>
+ <li>Intel Core 2 Extreme QX9650 (running at 3.6 GHz)</li>
+ <li>4×4GB DDR3-1600 Kingston RAM</li>
+ <li>Gigabyte GA-EP43T-USB3 rev 1.0</li>
+ <li>NVIDIA GTX 960 (ZOTAC), OR</li>
+ <li>AMD RX 550 4GB LP (Yeston)</li>
+ <li>Crucial M4-CT128M4SSD2 (128GB)</li>
+ <li>Segate Barracuda 7200.12 (500GB)</li>
+ <li>Debian GNU/Linux stable amd64</li>
+ <li>Windows 7 Ultimate x64</li>
+ <li>Windows XP Professional x64 Edition</li>
+ </ul></details>
+ <!-- SECOND FAMILY PC, DISASSEMBLED FOR PARTS
+ <details>
+ <summary>Lenovo ideacenter K300 (unnamed)</summary><ul>
+ <li>Intel Core 2 Duo Q8300</li>
+ <li>4×2GB DDR3-1066 RAM</li>
+ <li>NVIDIA GT 320</li>
+ <li>Crucial M4-CT128M4SSD2 (128GB)</li>
+ <li>Segate Barracuda 7200.12 (500GB)</li>
+ <li>Windows 7 Ultimate x64</li>
+ </ul></details>-->
+ <!-- FIRST FAMILY PC, SOLD FOR SCRAP
+ <details>
+ <summary>LEGEND (now Lenovo) 1+1 "天麟" (unnamed)</summary><ul>
+ <li>Intel Pentium 4 2.4 GHz Northwood (Non-HT)</li>
+ <li>512 MB RAM</li>
+ <li>NVIDIA GeForce4 MX440</li>
+ <li>80GB Segate HDD</li>
+ <li>Windows XP Home</li>
+ </ul></details>-->
+ <details>
+ <summary>Framework Laptop (11th gen Intel) "Freddy"</summary><ul>
+ <li>4th batch</li>
+ <li>Intel Core i7-1185G7</li>
+ <li>64GB DDR4-3200 Crucial RAM</li>
+ <li>Intel Iris Xe Graphics</li>
+ <li>1TB Samsung 970 Pro</li>
+ <li>Gentoo GNU/Linux ~amd64</li>
+ <li>Windows 11 Insider Pro x64</li>
+ </ul></details>
+ <details>
+ <summary>Lenovo ThinkPad X1 Yoga 1st Gen. 20FQ "Terry"</summary><ul>
+ <li>Intel Core i7-6600U</li>
+ <li>16GB DDR3L-1866 Samsung RAM</li>
+ <li>Intel HD Graphics 520</li>
+ <li>512GB Samsung NVMe SSD</li>
+ <li>Gentoo GNU/Linux ~amd64</li>
+ <li>Windows 11 Insider Pro x64</li>
+ </ul></details>
+ <details>
+ <summary>Steam Deck "Shannon"</summary><ul>
+ <li>I have no idea why I got this</li>
+ <li>Custom AMD Zen2 APU</li>
+ <li>16 GB LPDDR5</li>
+ <li>AMD RDNA2 Integrated</li>
+ <li>256GB PCIe 3.0 x4 NVMe SSD</li>
+ <li>Arch Linux amd64</li>
+ </ul></details>
+ <details>
+ <summary>IBM ThinkPad X60 Tablet 6363-C7U "Tegan"</summary><ul>
+ <li>Intel Core 2 Duo L7400</li>
+ <li>4GB DDR2-667 Samsung RAM</li>
+ <li>Intel GMA 950</li>
+ <li>240GB Sandisk SSD</li>
+ <li>Debian sid amd64</li>
+ <li>Windows 7 Ultimate x64</li>
+ </ul></details>
+ <details>
+ <summary>IBM ThinkPad T43 2686-DGU "Terrenum"</summary><ul>
+ <li>Intel Pentium M 750</li>
+ <li>2GB DDR2-667 Samsung RAM (running at 533 MT/s)</li>
+ <li>ATI Mobility Radeon X300</li>
+ <li>60GB Hitachi PATA HDD (SATA Mod in process)</li>
+ <li>Debian sid i386</li>
+ <li>Windows XP Professional SP3</li>
+ </ul></details>
+ <details>
+ <summary>Apple PowerBook G4 A1138 "Marian"</summary><ul>
+ <li>PowerPC 7447A</li>
+ <li>2GB DDR2-667 Samsung RAM (running at 533 MT/s)</li>
+ <li>ATI Mobility Radeon 9700</li>
+ <li>100GB Hitachi PATA HDD</li>
+ <li>OpenBSD 7.2 macppc</li>
+ <li>Mac OS X 10.5.8</li>
+ </ul></details>
+ <!-- FIRST PRIVATE LAPTOP, DISASSEMBLED FOR PARTS, REINCARNATED AS "ALICE"
+ <details>
+ <summary>Lenovo IdeaPad Y570 (unnamed)</summary><ul>
+ <li>Intel Core i7-2670QM -> i7-2960XM</li>
+ <li>2×8GB DDR3L-1600 Samsung RAM</li>
+ <li>NVIDIA GT 555M (GF108, 1GB GDDR5)</li>
+ <li>Crucial M4-CT256M4SSD2 (256GB)</li>
+ </ul></details>-->
+ <!-- PARENTS' WORK LAPTOP, NO LONGER IN POSSESSION
+ <details>
+ <summary>IBM ThinkPad R52 (unnamed, unknown type number)</summary><ul>
+ <li>Intel Pentium M 725A</li>
+ <li>768MB RAM</li>
+ <li>ATI Mobility Radeon X300</li>
+ <li>40GB Hitachi PATA HDD</li>
+ <li>Windows XP Professional SP3</li>
+ </ul></details>-->
+ <!-- PARENTS' WORK LAPTOP, NO DISK
+ <details>
+ <summary>ASUS A8M (unnamed)</summary><ul>
+ <li>AMD Mobile Sempron 3200+</li>
+ <li>3GB RAM</li>
+ <li>NVIDIA GeForce Go 6100 (integrated)</li>
+ </ul></details>-->
+ <details>
+ <summary>Raspberry Pi 2 "Regan" (NIU)</summary><ul>
+ <li>8GB MicroSD Card</li>
+ <li>rev 1.1</li>
+ <li>Raspbian testing (buster)</li>
+ </ul></details>
+ <details>
+ <summary>Raspberry Pi 3B+ "Raven" (NIU)</summary><ul>
+ <li>Broken MicroSD card slot</li>
+ <li>Arch Linux ARM (aarch64) on USB</li>
+ </ul></details>
+ <details>
+ <summary>Raspberry Pi 4B "Royce"</summary><ul>
+ <li>4GB RAM, rev 1.1</li>
+ <li>32GB MicroSD Card</li>
+ <li>Custom FrankenDebian (aarch64)</li>
+ </ul></details>
+ <details>
+ <summary>Raspberry Pi 4B "Rubrica"</summary><ul>
+ <li>8GB RAM, rev 1.5</li>
+ <li>64GB MicroSD Card</li>
+ <li>Arch Linux ARM</li>
+ </ul></details>
+ <details>
+ <summary>Raspberry Pi Zero WH "Rhodes"</summary><ul>
+ <li>32GB MicroSD Card</li>
+ <li>Raspbian testing</li>
+ </ul></details>
+ <details>
+ <summary>Sony XPERIA 1 II</summary><ul>
+ <li>256GB Internal Storage</li>
+ <li>Custom built LineageOS 20</li>
+ </ul></details>
+ <details>
+ <summary>Xiao Mi MIX 3</summary><ul>
+ <li>256GB Internal Storage</li>
+ <li>Custom built crDroid 7.9</li>
+ </ul></details>
+ <!-- BACKUP PHONE FOR PARENTS
+ <details>
+ <summary>Samsung Galaxy Note 4</summary><ul>
+ <li>SM-N9100</li>
+ <li>16GB Internal Storage</li>
+ <li>Custom built LineageOS 16.0</li>
+ </ul></details>
+ -->
+ <!-- NO LONGER IN POSSESSION
+ <details>
+ <summary>Samsung Galaxy S III</summary><ul>
+ <li>GT-I9300</li>
+ <li>16GB Internal Storage</li>
+ <li>LineageOS 14.1</li>
+ </ul></details>-->
+ <!-- NO LONGER IN POSSESSION
+ <details>
+ <summary>Samsung Galaxy Tab 2 7.0</summary><ul>
+ <li>GT-P3100</li>
+ <li>8GB Internal Storage</li>
+ <li>LineageOS 13.0</li>
+ </ul></details>-->
+ <!-- SMASHED SCREEN
+ <details>
+ <summary>Xiaomi MAX</summary><ul>
+ <li>Standard edition (msm8956)</li>
+ <li>32GB Internal Storage</li>
+ <li>Stock MIUI Beta ROM</li>
+ </ul></details>-->
+ <!-- NO LONGER IN POSSESSION
+ <details>
+ <summary>BlackBerry Curve 8900</summary><ul>
+ </ul></details>-->
+ <!-- NO LONGER IN POSSESSION
+ <details>
+ <summary>NOKIA 500</summary><ul>
+ </ul></details>-->
+ <!-- NO LONGER IN POSSESSION
+ <details>
+ <summary>NOKIA C5-03</summary><ul>
+ </ul></details>-->
+ <details>
+ <summary>iPod classic 120GB (Modded)</summary><ul>
+ <li>Rev. 3 logic board</li>
+ <li>128GB SSD</li>
+ <li>Rockbox</li>
+ </ul></details>
</td>
</tr>
<tr>
<td>Wishlist</td>
<td>
- Something something threadripper, or epyc<br>
+ <s>Something something threadripper, or epyc</s><br>
<s>All kinds of vintage tech gadgets</s>
</td>
</tr>
@@ -238,4 +417,4 @@
</td>
</tr>
</table>
-<div>
+</div>
diff --git a/blog/blogext.css b/blog/blogext.css
index 9048a49..3ce40d0 100644
--- a/blog/blogext.css
+++ b/blog/blogext.css
@@ -4,6 +4,9 @@ span.right{
white-space:nowrap;
min-width:12em;
}
+span.tipped{
+ text-decoration: underline dotted;
+}
a.toctarg{
margin-left:-160px;
padding-left:160px !important;
diff --git a/blog/content/.htaccess b/blog/content/.htaccess
deleted file mode 100644
index 93169e4..0000000
--- a/blog/content/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-Order deny,allow
-Deny from all
diff --git a/blog/content/util/indexer.cpp b/blog/content/util/indexer.cpp
deleted file mode 100644
index b072633..0000000
--- a/blog/content/util/indexer.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//filename title date tags
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <cstdio>
-#include <cstring>
-#include <algorithm>
-#include <functional>
-#include <string>
-#include <vector>
-#define stripr(s) s[strlen(s)-1]=='\n'?s[strlen(s)-1]=0:0
-std::vector<std::string> fn;
-char buf1[65536],buf2[65536],buf3[65536];
-int main()
-{
- struct dirent* pd;DIR* pdir;
- pdir=opendir("/var/www/html/blog/content");
- while((pd=readdir(pdir))!=NULL)
- {
- std::string s(pd->d_name);
- if(s.length()<4)continue;
- if(s.substr(s.length()-4)==".txt")
- fn.push_back(s.substr(0,s.length()-4));
- }
- closedir(pdir);
- std::sort(fn.begin(),fn.end(),std::greater<std::string>());
- FILE *f,*rf;
- f=fopen("/var/www/html/blog/content/pindex","w");
- for(size_t i=0;i<fn.size();++i)
- {
- puts(("/var/www/html/blog/content/"+fn[i]+".txt").c_str());
- struct stat st;struct tm* mt;
- stat(("/var/www/html/blog/content/"+fn[i]+".txt").c_str(),&st);
- mt=localtime(&st.st_mtime);
- rf=fopen(("/var/www/html/blog/content/"+fn[i]+".txt").c_str(),"r");
- fgets(buf1,65536,rf);stripr(buf1);
- fgets(buf2,65536,rf);stripr(buf2);
- fgets(buf3,65536,rf);stripr(buf3);
- if(strstr(buf2,"WIP")){puts(" SKIPPED");continue;}
- fprintf(f,"%s\t",fn[i].c_str());
- fprintf(f,"%s\t",buf1);
- fprintf(f,"%s/%d-%02d-%02d\t",buf2,mt->tm_year+1900,mt->tm_mon+1,mt->tm_mday);
- fprintf(f,"%s\n",buf3);
- fclose(rf);
- }
- fclose(f);
-}
diff --git a/blog/list/.htaccess b/blog/list/.htaccess
index 2651228..49e93ae 100644
--- a/blog/list/.htaccess
+++ b/blog/list/.htaccess
@@ -1 +1,2 @@
+Options +FollowSymlinks
Header set Cache-Control no-cache
diff --git a/blog/list/0.html b/blog/list/0.html
index 8f52684..b2c321d 100644
--- a/blog/list/0.html
+++ b/blog/list/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -55,28 +55,28 @@ function ol()
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/Privacy.html">Privacy Policy &amp; Terms</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#special-page</span>
- <span class="right" id="">2019-09-03/2019-09-04</span></div>
+ <span class="right" id="">2019-09-03/2019-09-03</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-06-03.html">No, I'm not dead</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-03-02.html">The Station of Elyssima</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2021-06-03/2021-06-03</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#fiction #garbage</span>
+ <span class="right" id="">2024-03-02/2024-03-08</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-09-04.html">September 2019 Site Update</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-29.html">2024 Site Update</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web</span>
- <span class="right" id="">2019-09-04/2019-11-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2024-02-29/2024-02-29</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-04.html">RBUS-ADAT devlog</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
- <span class="right" id="">2019-04-25/2021-01-31</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-04/2024-02-17</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="#">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">1/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">1/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/1.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/1.html b/blog/list/1.html
index 23020b2..dbffe2a 100644
--- a/blog/list/1.html
+++ b/blog/list/1.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-02.html">R-BUS Technical Information</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
- <span class="right" id="">2019-02-13/2019-07-25</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-02/2024-02-18</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-12-06.html">小米 MIX 3 上手体验</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2023-11-13.html">Framework Laptop: Repasting &amp; Two Year Report</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on</span>
- <span class="right" id="">2018-12-06/2021-01-31</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #computer-repairing</span>
+ <span class="right" id="">2023-11-13/2023-11-28</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-10-11.html">The stupid blogging system evolved!</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-11-27.html">(Not really) Musical Answers &amp; Rants</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #devel #js</span>
- <span class="right" id="">2018-10-11/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #midi</span>
+ <span class="right" id="">2022-11-27/2022-12-02</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-07.html">Should this site still be alive by 2035...</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-07-23.html">Framework Laptop: The next thing in the laptop world?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2018-06-07/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on #computer-repairing</span>
+ <span class="right" id="">2022-07-23/2023-11-14</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-05.html">Software Project Management in the Free Software World</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-10-10.html">EDIROL SD-20: the Crumbling of the Canvas?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry</span>
- <span class="right" id="">2018-06-05/2018-10-16</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2021-10-10/2022-07-01</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/0.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">2/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">2/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/2.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/10.html b/blog/list/10.html
new file mode 100644
index 0000000..ddd50e3
--- /dev/null
+++ b/blog/list/10.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-20.html">忙</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#random-xp</span>
+ <span class="right" id="">2015-12-20/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-22.html">Raspberry Pi2 初体验</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#hands-on #device-review</span>
+ <span class="right" id="">2015-11-22/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-01.html">Hackathon 2015乱搞记</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#random-xp</span>
+ <span class="right" id="">2015-11-01/2015-11-22</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-31.html">大学入学两个月了……</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2015-10-31/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-30.html">First CCPC sightseeing tour</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest</span>
+ <span class="right" id="">2015-10-30/2018-10-11</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="/blog/list/9.html">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">11/12</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/11.html">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/11.html b/blog/list/11.html
new file mode 100644
index 0000000..637551e
--- /dev/null
+++ b/blog/list/11.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-29.html">noname01.pas</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2015-10-29/2018-10-11</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="/blog/list/10.html">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">12/12</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/2.html b/blog/list/2.html
index 98f9833..1d321d2 100644
--- a/blog/list/2.html
+++ b/blog/list/2.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-06-03.html">No, I'm not dead</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2018-05-18/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2021-06-03/2021-06-02</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
- <span class="right" id="">2018-05-08/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2020-11-20/2024-02-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-03.html">Are you an Apple fanboy/fangirl?</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-09-04.html">September 2019 Site Update</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #interactive</span>
- <span class="right" id="">2018-05-03/2019-02-10</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web</span>
+ <span class="right" id="">2019-09-04/2019-11-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-22.html">ICPC类比赛中计算几何问题之「乱象」</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-06-24.html">Working as an intern for "the spyware corporation"</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #acmicpc</span>
- <span class="right" id="">2018-04-22/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #sophistry</span>
+ <span class="right" id="">2019-06-24/2024-02-17</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-17.html">The "Deepin is spyware" problem</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#linux #garbage #sophistry</span>
- <span class="right" id="">2018-04-17/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
+ <span class="right" id="">2019-04-25/2022-06-30</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/1.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">3/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">3/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/3.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/3.html b/blog/list/3.html
index 40c42e7..6c3c834 100644
--- a/blog/list/3.html
+++ b/blog/list/3.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-03-17.html">Some rants on SMELT, QMidiPlayer and Virtools</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #opengl</span>
- <span class="right" id="">2018-03-17/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
+ <span class="right" id="">2019-02-13/2019-07-24</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-02-05.html">Does gaming make me merrier &amp; more relaxed or the opposite?</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-12-06.html">小米 MIX 3 上手体验</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2018-02-05/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on</span>
+ <span class="right" id="">2018-12-06/2021-01-30</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-07.html">Trash dump for the fifth semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-10-11.html">The stupid blogging system evolved!</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2018-01-07/2018-10-30</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #devel #js</span>
+ <span class="right" id="">2018-10-11/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-05.html">Now using reverse proxy to deliver content</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-07.html">Should this site still be alive by 2035...</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp</span>
- <span class="right" id="">2018-01-05/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
+ <span class="right" id="">2018-06-07/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-05.html">Software Project Management in the Free Software World</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
- <span class="right" id="">2017-12-21/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry</span>
+ <span class="right" id="">2018-06-05/2018-10-16</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/2.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">4/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">4/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/4.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/4.html b/blog/list/4.html
index 1b31f55..af290dd 100644
--- a/blog/list/4.html
+++ b/blog/list/4.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
- <span class="right" id="">2017-11-25/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
+ <span class="right" id="">2018-05-18/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-29.html">Trash dump for the fourth semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2017-06-29/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
+ <span class="right" id="">2018-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-09.html">Fuck Windows et cetera</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-03.html">Are you an Apple fanboy/fangirl?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#daily-life</span>
- <span class="right" id="">2017-06-08/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #interactive</span>
+ <span class="right" id="">2018-05-03/2019-02-09</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-05-08.html">2017省赛流水帐</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-22.html">ICPC类比赛中计算几何问题之「乱象」</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
- <span class="right" id="">2017-05-08/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #acmicpc</span>
+ <span class="right" id="">2018-04-22/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-04-11.html">SBS 2.0 is now the default blog browser</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-17.html">The "Deepin is spyware" problem</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #web</span>
- <span class="right" id="">2017-04-11/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#linux #garbage #sophistry</span>
+ <span class="right" id="">2018-04-17/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/3.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">5/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">5/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/5.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/5.html b/blog/list/5.html
index ae61983..09ff9a1 100644
--- a/blog/list/5.html
+++ b/blog/list/5.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-02-13.html">[多大图警告]ls /dev</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-03-17.html">Some rants on SMELT, QMidiPlayer and Virtools</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
- <span class="right" id="">2017-02-13/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #opengl</span>
+ <span class="right" id="">2018-03-17/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-18.html">Trash dump for the third semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-02-05.html">Does gaming make me merrier &amp; more relaxed or the opposite?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2017-01-09/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2018-02-05/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-09.html">[多大图警告]终究还是改不了修电脑的命</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-07.html">Trash dump for the fifth semester</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#computer-repairing #garbage</span>
- <span class="right" id="">2017-01-09/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2018-01-07/2018-10-30</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-09-24.html">2-in-1</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-05.html">Now using reverse proxy to deliver content</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #c++ #qt</span>
- <span class="right" id="">2016-09-24/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp</span>
+ <span class="right" id="">2018-01-05/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-06-21.html">Trash dump for the first academic year</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2016-06-21/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
+ <span class="right" id="">2017-12-21/2019-02-12</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/4.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">6/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">6/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/6.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/6.html b/blog/list/6.html
index a3becf5..1d562a6 100644
--- a/blog/list/6.html
+++ b/blog/list/6.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-05-12.html">ThinkPad X1 Yoga初体验</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
- <span class="right" id="">2016-05-12/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
+ <span class="right" id="">2017-11-25/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-04-09.html">The MIDI File Format Specification and MIDI Implementation in QMidiPlayer</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-29.html">Trash dump for the fourth semester</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #midi</span>
- <span class="right" id="">2016-04-09/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2017-06-29/2021-06-26</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-03-26.html">ACM校赛水题组酱油记</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-09.html">Fuck Windows et cetera</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
- <span class="right" id="">2016-03-26/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#daily-life</span>
+ <span class="right" id="">2017-06-08/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-02-18.html">Cross Noodles Recooked</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-05-08.html">2017省赛流水帐</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #js #webgl</span>
- <span class="right" id="">2016-02-18/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
+ <span class="right" id="">2017-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-02-14.html">Why Do I Prefer a Computer over a Girlfriend/<s>(Boyfriend)</s></a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-04-11.html">SBS 2.0 is now the default blog browser</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry</span>
- <span class="right" id="">2016-02-14/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #web</span>
+ <span class="right" id="">2017-04-11/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/5.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">7/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">7/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/7.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/7.html b/blog/list/7.html
index bb44d07..5b8d1cc 100644
--- a/blog/list/7.html
+++ b/blog/list/7.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-25.html">放假...</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-02-13.html">[多大图警告]ls /dev</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#daily-life</span>
- <span class="right" id="">2016-01-25/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
+ <span class="right" id="">2017-02-13/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-16.html">QMidiPlayer Progress-2016-01-16</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-18.html">Trash dump for the third semester</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer</span>
- <span class="right" id="">2016-01-16/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2017-01-09/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-03.html">The Design and The Real Product</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-09.html">[多大图警告]终究还是改不了修电脑的命</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #design</span>
- <span class="right" id="">2016-01-03/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#computer-repairing #garbage</span>
+ <span class="right" id="">2017-01-09/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-27.html">QMidiPlayer got its repo</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-09-24.html">2-in-1</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer</span>
- <span class="right" id="">2015-12-27/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #c++ #qt</span>
+ <span class="right" id="">2016-09-24/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-23.html">Chris' First Development Blog</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-06-21.html">Trash dump for the first academic year</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel</span>
- <span class="right" id="">2015-12-23/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2016-06-21/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/6.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">8/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">8/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/8.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/8.html b/blog/list/8.html
index ef6e19f..643fa40 100644
--- a/blog/list/8.html
+++ b/blog/list/8.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-20.html">忙</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-05-12.html">ThinkPad X1 Yoga初体验</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#random-xp</span>
- <span class="right" id="">2015-12-20/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
+ <span class="right" id="">2016-05-12/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-22.html">Raspberry Pi2 初体验</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-04-09.html">The MIDI File Format Specification and MIDI Implementation in QMidiPlayer</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#hands-on #device-review</span>
- <span class="right" id="">2015-11-22/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer #midi</span>
+ <span class="right" id="">2016-04-09/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-01.html">Hackathon 2015乱搞记</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-03-26.html">ACM校赛水题组酱油记</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#random-xp</span>
- <span class="right" id="">2015-11-01/2015-11-22</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
+ <span class="right" id="">2016-03-26/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-31.html">大学入学两个月了……</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-02-18.html">Cross Noodles Recooked</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2015-10-31/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #js #webgl</span>
+ <span class="right" id="">2016-02-18/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-30.html">First CCPC sightseeing tour</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-02-14.html">Why Do I Prefer a Computer over a Girlfriend/<s>(Boyfriend)</s></a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest</span>
- <span class="right" id="">2015-10-30/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry</span>
+ <span class="right" id="">2016-02-14/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/7.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">9/10</span>
+ <span style="text-align:center;display:table-cell;" id="page">9/12</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/9.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/9.html b/blog/list/9.html
index 2cfd383..0c7c39c 100644
--- a/blog/list/9.html
+++ b/blog/list/9.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,17 +47,37 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-29.html">noname01.pas</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-25.html">放假...</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2015-10-29/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#daily-life</span>
+ <span class="right" id="">2016-01-25/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-16.html">QMidiPlayer Progress-2016-01-16</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer</span>
+ <span class="right" id="">2016-01-16/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-01-03.html">The Design and The Real Product</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #design</span>
+ <span class="right" id="">2016-01-03/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-27.html">QMidiPlayer got its repo</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel #qmidiplayer</span>
+ <span class="right" id="">2015-12-27/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-12-23.html">Chris' First Development Blog</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#devel</span>
+ <span class="right" id="">2015-12-23/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/8.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">10/10</span>
- <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">10/12</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/10.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
diff --git a/blog/list/acmicpc/0.html b/blog/list/acmicpc/0.html
index a89d8ad..209d887 100644
--- a/blog/list/acmicpc/0.html
+++ b/blog/list/acmicpc/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a class="active" href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a class="active" href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,7 +50,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
- <span class="right" id="">2018-05-08/2019-02-13</span></div>
+ <span class="right" id="">2018-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-22.html">ICPC类比赛中计算几何问题之「乱象」</a></h3>
<br>
@@ -92,7 +60,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-05-08.html">2017省赛流水帐</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
- <span class="right" id="">2017-05-08/2019-02-13</span></div>
+ <span class="right" id="">2017-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-03-26.html">ACM校赛水题组酱油记</a></h3>
<br>
diff --git a/blog/list/c++/0.html b/blog/list/c++/0.html
index 3e894bd..eb021a6 100644
--- a/blog/list/c++/0.html
+++ b/blog/list/c++/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a class="active" href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a class="active" href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/computer-repairing/0.html b/blog/list/computer-repairing/0.html
index b6ed5a8..614d234 100644
--- a/blog/list/computer-repairing/0.html
+++ b/blog/list/computer-repairing/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a class="active" href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a class="active" href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -79,10 +47,20 @@ loadTheme();
<div id="postslist">
<div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2023-11-13.html">Framework Laptop: Repasting &amp; Two Year Report</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #computer-repairing</span>
+ <span class="right" id="">2023-11-13/2023-11-28</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-07-23.html">Framework Laptop: The next thing in the laptop world?</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on #computer-repairing</span>
+ <span class="right" id="">2022-07-23/2023-11-14</span></div>
+ </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-09.html">[多大图警告]终究还是改不了修电脑的命</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#computer-repairing #garbage</span>
- <span class="right" id="">2017-01-09/2019-02-13</span></div>
+ <span class="right" id="">2017-01-09/2019-02-12</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
diff --git a/blog/list/contest/0.html b/blog/list/contest/0.html
index d84e8b2..a5c3702 100644
--- a/blog/list/contest/0.html
+++ b/blog/list/contest/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a class="active" href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a class="active" href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,7 +50,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-05-08.html">2017省赛流水帐</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#contest #acmicpc</span>
- <span class="right" id="">2017-05-08/2019-02-13</span></div>
+ <span class="right" id="">2017-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-03-26.html">ACM校赛水题组酱油记</a></h3>
<br>
diff --git a/blog/list/daily-life/0.html b/blog/list/daily-life/0.html
index 3701e9c..713cfa4 100644
--- a/blog/list/daily-life/0.html
+++ b/blog/list/daily-life/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a class="active" href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a class="active" href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -87,7 +55,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-29.html">Trash dump for the fourth semester</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2017-06-29/2018-10-11</span></div>
+ <span class="right" id="">2017-06-29/2021-06-26</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-09.html">Fuck Windows et cetera</a></h3>
<br>
diff --git a/blog/list/daily-life/1.html b/blog/list/daily-life/1.html
index 3e81752..37ba1a9 100644
--- a/blog/list/daily-life/1.html
+++ b/blog/list/daily-life/1.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a class="active" href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a class="active" href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/design/0.html b/blog/list/design/0.html
index 293d18e..16458cf 100644
--- a/blog/list/design/0.html
+++ b/blog/list/design/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a class="active" href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a class="active" href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/devel/0.html b/blog/list/devel/0.html
index 34bccd8..71570b2 100644
--- a/blog/list/devel/0.html
+++ b/blog/list/devel/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a class="active" href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a class="active" href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/devel/1.html b/blog/list/devel/1.html
index a0ff8bd..b647777 100644
--- a/blog/list/devel/1.html
+++ b/blog/list/devel/1.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a class="active" href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a class="active" href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/device-review/0.html b/blog/list/device-review/0.html
index 0add56a..f899df6 100644
--- a/blog/list/device-review/0.html
+++ b/blog/list/device-review/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a class="active" href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a class="active" href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,30 +47,30 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2023-11-13.html">Framework Laptop: Repasting &amp; Two Year Report</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
- <span class="right" id="">2020-11-20/2021-03-04</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #computer-repairing</span>
+ <span class="right" id="">2023-11-13/2023-11-28</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-07-23.html">Framework Laptop: The next thing in the laptop world?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
- <span class="right" id="">2019-04-25/2021-01-31</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on #computer-repairing</span>
+ <span class="right" id="">2022-07-23/2023-11-14</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-12-06.html">小米 MIX 3 上手体验</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-10-10.html">EDIROL SD-20: the Crumbling of the Canvas?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on</span>
- <span class="right" id="">2018-12-06/2021-01-31</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2021-10-10/2022-07-01</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
- <span class="right" id="">2017-12-21/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2020-11-20/2024-02-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-02-13.html">[多大图警告]ls /dev</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
- <span class="right" id="">2017-02-13/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
+ <span class="right" id="">2019-04-25/2022-06-30</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
diff --git a/blog/list/device-review/1.html b/blog/list/device-review/1.html
index 646b341..ef30e52 100644
--- a/blog/list/device-review/1.html
+++ b/blog/list/device-review/1.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a class="active" href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a class="active" href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,10 +47,25 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-12-06.html">小米 MIX 3 上手体验</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on</span>
+ <span class="right" id="">2018-12-06/2021-01-30</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
+ <span class="right" id="">2017-12-21/2019-02-12</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-02-13.html">[多大图警告]ls /dev</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
+ <span class="right" id="">2017-02-13/2019-02-12</span></div>
+ </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-05-12.html">ThinkPad X1 Yoga初体验</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review</span>
- <span class="right" id="">2016-05-12/2019-02-13</span></div>
+ <span class="right" id="">2016-05-12/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-22.html">Raspberry Pi2 初体验</a></h3>
<br>
diff --git a/blog/list/electronics/0.html b/blog/list/electronics/0.html
new file mode 100644
index 0000000..03ee299
--- /dev/null
+++ b/blog/list/electronics/0.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a class="active" href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-04.html">RBUS-ADAT devlog</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-04/2024-02-17</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-02.html">R-BUS Technical Information</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-02/2024-02-18</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="#">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">1/1</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/electronics/index.html b/blog/list/electronics/index.html
new file mode 120000
index 0000000..359ee56
--- /dev/null
+++ b/blog/list/electronics/index.html
@@ -0,0 +1 @@
+0.html \ No newline at end of file
diff --git a/blog/list/fiction/0.html b/blog/list/fiction/0.html
new file mode 100644
index 0000000..bb8099b
--- /dev/null
+++ b/blog/list/fiction/0.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a class="active" href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-03-02.html">The Station of Elyssima</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#fiction #garbage</span>
+ <span class="right" id="">2024-03-02/2024-03-08</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="#">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">1/1</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/fiction/index.html b/blog/list/fiction/index.html
new file mode 120000
index 0000000..359ee56
--- /dev/null
+++ b/blog/list/fiction/index.html
@@ -0,0 +1 @@
+0.html \ No newline at end of file
diff --git a/blog/list/garbage/0.html b/blog/list/garbage/0.html
index 63d6bfd..443c0d7 100644
--- a/blog/list/garbage/0.html
+++ b/blog/list/garbage/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -52,31 +52,31 @@ function ol()
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
<span class="right" id="">2016-02-13/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-06-03.html">No, I'm not dead</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-03-02.html">The Station of Elyssima</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2021-06-03/2021-06-03</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#fiction #garbage</span>
+ <span class="right" id="">2024-03-02/2024-03-08</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-29.html">2024 Site Update</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
- <span class="right" id="">2019-02-13/2019-07-25</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2024-02-29/2024-02-29</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-07.html">Should this site still be alive by 2035...</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-06-03.html">No, I'm not dead</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2018-06-07/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2021-06-03/2021-06-02</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-06-24.html">Working as an intern for "the spyware corporation"</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2018-05-18/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #sophistry</span>
+ <span class="right" id="">2019-06-24/2024-02-17</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="#">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">1/4</span>
+ <span style="text-align:center;display:table-cell;" id="page">1/5</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/garbage/1.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/garbage/1.html b/blog/list/garbage/1.html
index 0b7cd89..b491fe8 100644
--- a/blog/list/garbage/1.html
+++ b/blog/list/garbage/1.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
- <span class="right" id="">2018-05-08/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
+ <span class="right" id="">2019-02-13/2019-07-24</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-03.html">Are you an Apple fanboy/fangirl?</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-07.html">Should this site still be alive by 2035...</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #interactive</span>
- <span class="right" id="">2018-05-03/2019-02-10</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
+ <span class="right" id="">2018-06-07/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-22.html">ICPC类比赛中计算几何问题之「乱象」</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #acmicpc</span>
- <span class="right" id="">2018-04-22/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
+ <span class="right" id="">2018-05-18/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-17.html">The "Deepin is spyware" problem</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#linux #garbage #sophistry</span>
- <span class="right" id="">2018-04-17/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
+ <span class="right" id="">2018-05-08/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-02-05.html">Does gaming make me merrier &amp; more relaxed or the opposite?</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-03.html">Are you an Apple fanboy/fangirl?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2018-02-05/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #interactive</span>
+ <span class="right" id="">2018-05-03/2019-02-09</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/garbage/0.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">2/4</span>
+ <span style="text-align:center;display:table-cell;" id="page">2/5</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/garbage/2.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/garbage/2.html b/blog/list/garbage/2.html
index c161b21..60053ab 100644
--- a/blog/list/garbage/2.html
+++ b/blog/list/garbage/2.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,36 +47,36 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-07.html">Trash dump for the fifth semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-22.html">ICPC类比赛中计算几何问题之「乱象」</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2018-01-07/2018-10-30</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #acmicpc</span>
+ <span class="right" id="">2018-04-22/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-17.html">The "Deepin is spyware" problem</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
- <span class="right" id="">2017-12-21/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#linux #garbage #sophistry</span>
+ <span class="right" id="">2018-04-17/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-02-05.html">Does gaming make me merrier &amp; more relaxed or the opposite?</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
- <span class="right" id="">2017-11-25/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2018-02-05/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-29.html">Trash dump for the fourth semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-07.html">Trash dump for the fifth semester</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2017-06-29/2018-10-11</span></div>
+ <span class="right" id="">2018-01-07/2018-10-30</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-18.html">Trash dump for the third semester</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-12-21.html">为什么我<i>就是不</i>使用Mac</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2017-01-09/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #device-review</span>
+ <span class="right" id="">2017-12-21/2019-02-12</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/garbage/1.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">3/4</span>
+ <span style="text-align:center;display:table-cell;" id="page">3/5</span>
<span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/garbage/3.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
diff --git a/blog/list/garbage/3.html b/blog/list/garbage/3.html
index 803ba41..2adfd75 100644
--- a/blog/list/garbage/3.html
+++ b/blog/list/garbage/3.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,32 +47,37 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-09.html">[多大图警告]终究还是改不了修电脑的命</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#computer-repairing #garbage</span>
- <span class="right" id="">2017-01-09/2019-02-13</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
+ <span class="right" id="">2017-11-25/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-06-21.html">Trash dump for the first academic year</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-06-29.html">Trash dump for the fourth semester</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
- <span class="right" id="">2016-06-21/2018-10-11</span></div>
+ <span class="right" id="">2017-06-29/2021-06-26</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-18.html">Trash dump for the third semester</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2017-01-09/2018-10-11</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-31.html">大学入学两个月了……</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-01-09.html">[多大图警告]终究还是改不了修电脑的命</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2015-10-31/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#computer-repairing #garbage</span>
+ <span class="right" id="">2017-01-09/2019-02-12</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-29.html">noname01.pas</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-06-21.html">Trash dump for the first academic year</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
- <span class="right" id="">2015-10-29/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #daily-life</span>
+ <span class="right" id="">2016-06-21/2018-10-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="/blog/list/garbage/2.html">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">4/4</span>
- <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">4/5</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/garbage/4.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
diff --git a/blog/list/garbage/4.html b/blog/list/garbage/4.html
new file mode 100644
index 0000000..470f1bd
--- /dev/null
+++ b/blog/list/garbage/4.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a class="active" href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-31.html">大学入学两个月了……</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2015-10-31/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-10-29.html">noname01.pas</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage</span>
+ <span class="right" id="">2015-10-29/2018-10-11</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="/blog/list/garbage/3.html">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">5/5</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/hands-on/0.html b/blog/list/hands-on/0.html
index 2b2abc5..993d061 100644
--- a/blog/list/hands-on/0.html
+++ b/blog/list/hands-on/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a class="active" href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a class="active" href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,15 +47,20 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-07-23.html">Framework Laptop: The next thing in the laptop world?</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on #computer-repairing</span>
+ <span class="right" id="">2022-07-23/2023-11-14</span></div>
+ </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
- <span class="right" id="">2019-04-25/2021-01-31</span></div>
+ <span class="right" id="">2019-04-25/2022-06-30</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-12-06.html">小米 MIX 3 上手体验</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #hands-on</span>
- <span class="right" id="">2018-12-06/2021-01-31</span></div>
+ <span class="right" id="">2018-12-06/2021-01-30</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2015-11-22.html">Raspberry Pi2 初体验</a></h3>
<br>
diff --git a/blog/list/interactive/0.html b/blog/list/interactive/0.html
index 23d5329..69aacf5 100644
--- a/blog/list/interactive/0.html
+++ b/blog/list/interactive/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a class="active" href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a class="active" href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,7 +50,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-03.html">Are you an Apple fanboy/fangirl?</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #interactive</span>
- <span class="right" id="">2018-05-03/2019-02-10</span></div>
+ <span class="right" id="">2018-05-03/2019-02-09</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
diff --git a/blog/list/js/0.html b/blog/list/js/0.html
index c1b5cdc..9441179 100644
--- a/blog/list/js/0.html
+++ b/blog/list/js/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a class="active" href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a class="active" href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/linux/0.html b/blog/list/linux/0.html
index 0cd1d65..40547b3 100644
--- a/blog/list/linux/0.html
+++ b/blog/list/linux/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a class="active" href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a class="active" href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/midi/0.html b/blog/list/midi/0.html
index 305cafe..01f556d 100644
--- a/blog/list/midi/0.html
+++ b/blog/list/midi/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a class="active" href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a class="active" href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,15 +47,25 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-11-27.html">(Not really) Musical Answers &amp; Rants</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #midi</span>
+ <span class="right" id="">2022-11-27/2022-12-02</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-10-10.html">EDIROL SD-20: the Crumbling of the Canvas?</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2021-10-10/2022-07-01</span></div>
+ </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
- <span class="right" id="">2020-11-20/2021-03-04</span></div>
+ <span class="right" id="">2020-11-20/2024-02-11</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
- <span class="right" id="">2019-04-25/2021-01-31</span></div>
+ <span class="right" id="">2019-04-25/2022-06-30</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2016-04-09.html">The MIDI File Format Specification and MIDI Implementation in QMidiPlayer</a></h3>
<br>
diff --git a/blog/list/music/0.html b/blog/list/music/0.html
index 6fc26fb..aa99d50 100644
--- a/blog/list/music/0.html
+++ b/blog/list/music/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a class="active" href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a class="active" href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,27 +47,37 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-04.html">RBUS-ADAT devlog</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
- <span class="right" id="">2020-11-20/2021-03-04</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-04/2024-02-17</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2024-02-02.html">R-BUS Technical Information</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
- <span class="right" id="">2019-04-25/2021-01-31</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #electronics</span>
+ <span class="right" id="">2024-02-02/2024-02-18</span></div>
</div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2022-11-27.html">(Not really) Musical Answers &amp; Rants</a></h3>
<br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
- <span class="right" id="">2017-11-25/2018-10-11</span></div>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #midi</span>
+ <span class="right" id="">2022-11-27/2022-12-02</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2021-10-10.html">EDIROL SD-20: the Crumbling of the Canvas?</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2021-10-10/2022-07-01</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-11-20.html">EDIROL SD-80: The Adventure Continues</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music</span>
+ <span class="right" id="">2020-11-20/2024-02-11</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
<div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
<span style="display:table-cell;"><a id="prepage" href="#">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="page">1/1</span>
- <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">1/2</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="/blog/list/music/1.html">&gt;&gt;</a></span>
</div>
<div style="text-align:center;" class="TText">
Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
diff --git a/blog/list/music/1.html b/blog/list/music/1.html
new file mode 100644
index 0000000..9641efc
--- /dev/null
+++ b/blog/list/music/1.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog</title>
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><span>Tags filter</span>
+ <ul id="tagslist">
+
+
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a class="active" href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ </li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="postslist">
+
+ <div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-04-25.html">EDIROL SD-80: A Trapped Beast</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#device-review #midi #music #hands-on</span>
+ <span class="right" id="">2019-04-25/2022-06-30</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2017-11-25.html">A short post on Cakewalk's death and my music production</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#music #garbage</span>
+ <span class="right" id="">2017-11-25/2018-10-11</span></div>
+ </div></div>
+ <div id="insanch" style="height:5em;"></div>
+ <div id="footer">
+ <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
+ <span style="display:table-cell;"><a id="prepage" href="/blog/list/music/0.html">&lt;&lt;</a></span>
+ <span style="text-align:center;display:table-cell;" id="page">2/2</span>
+ <span style="text-align:right;display:table-cell;"><a id="nexpage" href="#">&gt;&gt;</a></span>
+ </div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0.
+ </div>
+ </div>
+ </div>
+
+
+</body></html> \ No newline at end of file
diff --git a/blog/list/opengl/0.html b/blog/list/opengl/0.html
index 00700a2..8dd582e 100644
--- a/blog/list/opengl/0.html
+++ b/blog/list/opengl/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a class="active" href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a class="active" href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/qmidiplayer/0.html b/blog/list/qmidiplayer/0.html
index 9b8b0f3..5c2931a 100644
--- a/blog/list/qmidiplayer/0.html
+++ b/blog/list/qmidiplayer/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a class="active" href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a class="active" href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/qt/0.html b/blog/list/qt/0.html
index 813db07..17f74b0 100644
--- a/blog/list/qt/0.html
+++ b/blog/list/qt/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a class="active" href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a class="active" href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/list/random-xp/0.html b/blog/list/random-xp/0.html
index 23d9b11..7028113 100644
--- a/blog/list/random-xp/0.html
+++ b/blog/list/random-xp/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a class="active" href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a class="active" href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,7 +50,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
- <span class="right" id="">2019-02-13/2019-07-25</span></div>
+ <span class="right" id="">2019-02-13/2019-07-24</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-01-05.html">Now using reverse proxy to deliver content</a></h3>
<br>
diff --git a/blog/list/sophistry/0.html b/blog/list/sophistry/0.html
index af7f76d..d87d80f 100644
--- a/blog/list/sophistry/0.html
+++ b/blog/list/sophistry/0.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a class="active" href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a class="active" href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,20 +47,10 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-06-30.html">A Transvestite Adventure</a></h3>
- <br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#toxic-stuff #sophistry</span>
- <span class="right" id="">2020-06-30/2020-07-13</span></div>
- </div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2020-04-11.html">"The Open Source Mindset"</a></h3>
- <br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2020-04-11/2020-11-17</span></div>
- </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-06-24.html">Working as an intern for "the spyware corporation"</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#garbage #sophistry</span>
- <span class="right" id="">2019-06-24/2020-05-25</span></div>
+ <span class="right" id="">2019-06-24/2024-02-17</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-06-07.html">Should this site still be alive by 2035...</a></h3>
<br>
@@ -71,6 +61,16 @@ function ol()
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry</span>
<span class="right" id="">2018-06-05/2018-10-16</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
+ <span class="right" id="">2018-05-18/2018-10-11</span></div>
+ </div><div class="block TText" id="" style="display:block;">
+ <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
+ <br>
+ <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
+ <span class="right" id="">2018-05-08/2019-02-12</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
diff --git a/blog/list/sophistry/1.html b/blog/list/sophistry/1.html
index 59113cc..29274af 100644
--- a/blog/list/sophistry/1.html
+++ b/blog/list/sophistry/1.html
@@ -1,4 +1,4 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
@@ -39,7 +39,7 @@ function ol()
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a class="active" href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/toxic-stuff">toxic-stuff</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a class="active" href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -47,16 +47,6 @@ function ol()
<div id="postslist">
<div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-18.html">Ideology vs Pragmatism &amp;c.</a></h3>
- <br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage</span>
- <span class="right" id="">2018-05-18/2018-10-11</span></div>
- </div><div class="block TText" id="" style="display:block;">
- <h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-05-08.html">Respecting your job</a></h3>
- <br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#sophistry #garbage #acmicpc</span>
- <span class="right" id="">2018-05-08/2019-02-13</span></div>
- </div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-04-17.html">The "Deepin is spyware" problem</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#linux #garbage #sophistry</span>
diff --git a/blog/list/special-page/0.html b/blog/list/special-page/0.html
index cdda9cb..09c3d10 100644
--- a/blog/list/special-page/0.html
+++ b/blog/list/special-page/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a class="active" href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a class="active" href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,7 +50,7 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/Privacy.html">Privacy Policy &amp; Terms</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#special-page</span>
- <span class="right" id="">2019-09-03/2019-09-04</span></div>
+ <span class="right" id="">2019-09-03/2019-09-03</span></div>
</div></div>
<div id="insanch" style="height:5em;"></div>
<div id="footer">
diff --git a/blog/list/web/0.html b/blog/list/web/0.html
index 8828be7..3386bb0 100644
--- a/blog/list/web/0.html
+++ b/blog/list/web/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a class="active" href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a class="active" href="/blog/list/web">web</a></li><li id=""><a href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
@@ -82,12 +50,12 @@ loadTheme();
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-09-04.html">September 2019 Site Update</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web</span>
- <span class="right" id="">2019-09-04/2019-11-13</span></div>
+ <span class="right" id="">2019-09-04/2019-11-12</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2019-02-13.html">Site Revamp and Other Rants -- 2019 Edition</a></h3>
<br>
<div style="display:table;width:100%;table-layout:fixed;"><span class="left" id="">#web #random-xp #garbage</span>
- <span class="right" id="">2019-02-13/2019-07-25</span></div>
+ <span class="right" id="">2019-02-13/2019-07-24</span></div>
</div><div class="block TText" id="" style="display:block;">
<h3 style="line-height:1.5em;"><a id="" href="/blog/post/2018-10-11.html">The stupid blogging system evolved!</a></h3>
<br>
diff --git a/blog/list/webgl/0.html b/blog/list/webgl/0.html
index 2704318..66c6da9 100644
--- a/blog/list/webgl/0.html
+++ b/blog/list/webgl/0.html
@@ -1,9 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
<title>Chrisoft::Blog</title>
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<link rel="stylesheet" type="text/css" href="/common.css">
<link rel="stylesheet" type="text/css" href="/panel.css">
<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
@@ -25,41 +26,8 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -71,7 +39,7 @@ loadTheme();
<ul id="tagslist">
- <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a class="active" href="/blog/list/webgl">webgl</a></li></ul>
+ <li id=""><a href="/blog/list/acmicpc">acmicpc</a></li><li id=""><a href="/blog/list/c++">c++</a></li><li id=""><a href="/blog/list/computer-repairing">computer-repairing</a></li><li id=""><a href="/blog/list/contest">contest</a></li><li id=""><a href="/blog/list/daily-life">daily-life</a></li><li id=""><a href="/blog/list/design">design</a></li><li id=""><a href="/blog/list/devel">devel</a></li><li id=""><a href="/blog/list/device-review">device-review</a></li><li id=""><a href="/blog/list/electronics">electronics</a></li><li id=""><a href="/blog/list/fiction">fiction</a></li><li id=""><a href="/blog/list/garbage">garbage</a></li><li id=""><a href="/blog/list/hands-on">hands-on</a></li><li id=""><a href="/blog/list/interactive">interactive</a></li><li id=""><a href="/blog/list/js">js</a></li><li id=""><a href="/blog/list/linux">linux</a></li><li id=""><a href="/blog/list/midi">midi</a></li><li id=""><a href="/blog/list/music">music</a></li><li id=""><a href="/blog/list/opengl">opengl</a></li><li id=""><a href="/blog/list/qmidiplayer">qmidiplayer</a></li><li id=""><a href="/blog/list/qt">qt</a></li><li id=""><a href="/blog/list/random-xp">random-xp</a></li><li id=""><a href="/blog/list/sophistry">sophistry</a></li><li id=""><a href="/blog/list/special-page">special-page</a></li><li id=""><a href="/blog/list/web">web</a></li><li id=""><a class="active" href="/blog/list/webgl">webgl</a></li></ul>
</li>
</ul>
</div>
diff --git a/blog/post/2014-11-14.html b/blog/post/2014-11-14.html
new file mode 100644
index 0000000..af49c2f
--- /dev/null
+++ b/blog/post/2014-11-14.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"喷当代中国大陆的“考场作文”制度 (校注版)")</title>
+<meta name="description" content="«喷当代中国大陆的“考场作文”制度 (校注版)» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">喷当代中国大陆的“考场作文”制度 (校注版)</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/garbage/">garbage</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">转写前言</a></li><li><a class="toctarg" href="#tocanch1">正文</a></li><li><a class="toctarg" href="#tocanch2">转写后记</a></li></ul>
+ </li>
+
+
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">喷当代中国大陆的“考场作文”制度 (校注版)</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2014-11-14<br>#garbage</div>
+ <hr><div id="article" class="TText"><article>
+<h2 id="tocanch0" class="tvis">转写前言</h2>
+<p>看到此篇日期比这个博客系统诞生还早的文章的你请不要恐慌。这是我高中三年级写的一篇沙雕文章。原文以我的除自己之外无人可以辨认的手写体记录于高中考试时所发的草稿纸上。今天(2021年6月26日)转写出来,供世人鄙视。</p>
+<p>(为了免去各位识别我的手写体的痛苦,在此不会发布扫描版。请相信我的转写是
+100% 准确的)</p>
+<h2 id="tocanch1" class="tvis">正文</h2>
+<p>喷当代中国大陆的“考场作文”制度</p>
+<p>浅显的中国历史我们都学过。教科书上说什么“八股取士”是一种怎么怎么样的做法(诸如钳制思想,阻碍人类发展之类,我早就还给我可亲可敬的历史老师了)。那么,现在我的观点是:现代中国大陆的考场作文制度毒害人的程度,比八股取士什么玩意儿的深十倍乃至百倍!</p>
+<p>写得一手好文章,原是一件好事,在许多方面都有用的。但是,对于像我这样的,编一篇考场作文比便秘拉不出
+(bi——)
+还困难的人来说,写那种东西基本就是对我们的残害了。拿到作文题目,搜肠刮肚完还不知道如何去作的时候,已经十分惆怅了。然而,还有人追在你屁股后面,要你拉出来的
+(bi——)!(这个比喻一点儿也不失当,因为这样憋出来的作文往往跟 (bi——)
+一样臭)。便秘了还要逼人家拉出来,这是一种多么不人道的行为!肠在这种摧残之下,尚有发生直肠癌的可能性,而我们的榆木脑袋……</p>
+<p>好好好!你说写这种东西对我们有好处,那我们来看看到底有什么好处!我们来随便看几篇“考场佳作”的题目:什么“熄灭蜡烛,莫惊扰美”,什么“心有猛虎,细嗅蔷薇”,什么“纸梯”,超浓的“文学气息”,一看就不是实用的文章。(我不是故意挑的——因为那本书上可以找到的题目全都这样…)那么,这种题目,善于写作的人写出来,叫“美文”;我这号人写出来,必然就是
+(bi——)
+了。将来,善于写作的人从办公室里出来,可以写上两篇作为娱乐,陶冶身心。而我扫完大街回窝之后还要玩上一次便秘?!别开玩笑了!我不是
+masochist (受虐狂)!再者,我还要为我仅剩的一点大脑负责呢!</p>
+<p>那么又有人说话了(我妈就是其中的一位):“这对你将来写论文还有用处哩!”我对此实在无话可说。那么假设有万分之一的可能性,我高中毕业没去扫大街,还考上了名校——石油大学,我该写论文了。然后我的论文落笔一个“人生如梦,年华似雪”,抬笔又是“自然而缓慢的优雅的成长”……
+(bi————————)! Pardon my French
+(对不起我爆粗了)!便秘的事就不用提了,因为光想象一下论文里要出现这种东西就得让我恶心上一个小时!</p>
+<p>如果你同意以上我的观点,你现在应该同意考场作文对我这样的废物一点儿好处也没有了。(如果你认为我还有救,那一定是因为你没救了。)那么为什么我要说这东西对普天下都有害呢?下面我就要喷喷这制度了。</p>
+<p>警告:以下内容有一定的政治倾向。共产主义的<ruby>拥护者<rp>(</rp><rt>sǐ
+dǎng</rt><rp>)</rp></ruby>们,为了保持你们高贵的贞操,以及确保你们不被当作政治犯处理掉,我建议你们立即停止阅读并重新读一遍《共产党宣言》或《毛选》。(其实我的政治倾向还是很温和的,我既不认为共产主义阻碍人类发展,也不认为“西方国家”就是一肚子坏水。我只是不想被跨省而已……不要来抓我啊!)</p>
+<p>首先,最为可恨的一点,是每道作文题目必有的“自定立意”。第一次我看到这四个字,欣喜若狂,以为就可以把自己扫遍全天下大街大志表达出来了。殊不知有人已经在背后把立意分了三六九等,而我这个恰好处在下下等,发下来一看,20分!</p>
+<p>那么我是这玩意儿的受害者,有没有受益者呢?有!有些极度狡猾圆润的人,敏锐地捕捉到了一个事实:出题人和批卷人似乎总是坚定的共产党员。于是他们想尽一切办法讨好党。再加上最近时事紧张,他们更有的可写了:把日本和德国拿出来对比,或者“西方国家鼓吹‘中国威胁论’”,预计不久之后还会有一批宣传社会主义核心价值观的。这是什么玩意儿?潜伏在身边的地下党员么?!另外,马克思的“高考”作文题目是“青年在选择职业时的考虑”,他们的觉悟已经超越马克思啦!这
+(bi——)
+深藏功与名啊!(顺便,我听说老金一家三个都在这个年纪写过很高端的东西……)</p>
+<p>与此相比,英语作文就开明得多(或许是考虑到我们英语水平太低的缘故)。要写“十年后的我”,我就写我十年后扫大街,居无定所,饥一顿饱一顿,这还得了
+80%
+的分。这种东西上了语文考场作文,估计直接就零分啦!可今年某省的高考作文还要人大谈“大学的门与路”。故意歧视我们这些没学上的学渣是不是!这种出题人,就该让他们在全省乃至全国学渣的口水中淹死!</p>
+<p>嘛,我差不多喷完了。在此我特地公布一下前段时间我做的一个调查的结果。问题是:“你认为现在所写的语文考场作文,对你的将来……”调查的对象是本校本年级学生45名,其中不乏作文常被当作范文的。没有人选择“非常有用”或“不知道”,而选择“有一定用处”和“完全没用”的人数比大约为1:2——和我的预测基本相同。从此我们至少可以看出一点问题。但我们伟大的出题人们还在命这种题:“贴近社会生活,有人文气息,让考生有话说”。这种题,让我这种学渣有什么话说!</p>
+<p>*注:本文引用的“考场佳作”,均来自《步步高大一轮复习讲义语文新课标》及万能的一中语文组所编的《语文天地》。</p>
+<p>Chris Xiong</p>
+<p>2014.11.14</p>
+<h2 id="tocanch2" class="tvis">转写后记</h2>
+<p>文中提到的英语作文一事,是确有其事的。某种程度上是为写本文故意做的一次试验。</p>
+<p>文中提到的调查是存在的。不过调查对象全都是理科生(文科生当时和我们不在同一座教学楼里),结果自然是自动偏向对我的结论有利的。</p>
+<p>文中充满着我高中时代典型的自嘲。如果你看了本文的纸质版,你会感到(当时的)我对这种考场作文的痛恨从纸上渗出来(转写到屏幕上之后这种效果虽然有所减弱,但从标点符号和语言的使用上还是能看出一些来的——虽然什么东西从屏幕上渗出来听起来有些奇怪)。这种痛恨是如此的强烈,以至于我高中几乎没有写过一篇严肃的考场作文。大部分写出来的,都是用来气老师的。如此一来即使我不写作文作业,或者模拟考试答题纸作文面直接空白,老师也不会找我的麻烦——既免去我写作文的痛苦,又免去老师读我写的东西的折磨,真是两全其美。</p>
+<p>要是说高中从不练习写作如今有没有什么后悔之处,那么我 GRE
+的作文不过关可以说勉强算是一点。但 GRE
+作文不像高考英语,CET或者托福英语。后者考的是语言使用能力,而 GRE
+考查的是思辨能力。所以从这个角度讲,就算我的高中语文考场作文次次满分,
+GRE 作文估计也达不到一半人的水平,那么也没有什么可后悔的地方了。</p>
+<p>举个随便编的例子来说, GRE
+的作文题目可能是这样的:当地政府人员宣布了一项计划,计划在本地的河上建造一座水库。并且声称由于甲、乙、丙原因,水库建造后当地的居民人均寿命可以翻
+10 倍。要求答题者分析政府的主张是否存在漏洞(当然是有的)。</p>
+<p>而中国的高考作文考的是什么?似乎首要是学生的政治“觉悟”,其次是使用华丽词句的能力。前者加上近年来越来越红的作文题目(见我2018年与山东考生一起写的高考作文(<a href="/blog/post/2018-06-07.html">链接</a>)),让人不得不怀疑考场作文成了灌输特定价值观的工具。至于使用华丽词句的能力,我想也许不是所有人都需要的吧。朴实无华的文字,只要传递了作者想要表达的信息,也就达到了目的;华丽的辞藻,反倒可能提高阅读的门槛,即便要表达的思想是如何卓越,也许也无法为大众所接受。</p>
+<p>思辨(或者称为批判性思维)能力,至少让人在与人争论时能够发现对方是否存在逻辑上的漏洞和谬误,并且可以帮助自己避免类似的错误。而对固定价值观的灌输,则恰恰相反:让人不问一切地接受得到的信息,成为容易上当受骗的天真幼稚之人。这两种教育方式,高下立判。</p>
+<p>如果你认为我在对我的“美国主子”表忠心,那你就错了。请不要忘记 GRE
+是研究生水平的考试。在研究生考试考如此水平的思辨,还是太晚了。不然的话美国也不会有如此大数量的疫苗反对者
+(anti-vaxxer) 或者地平说支持者 (flat
+earther)。我认为基本的思辨能力应该放在基础教育阶段。那样至少可以减少一些所谓保健品的诈骗案的数量。</p>
+<p>阁下看到这里,心里的感觉若是“哇这人他写了些什么我怎么什么都看不懂”,那确实怪不得阁下。表达能力低下大概是我另一个略微后悔高中从不写作文的地方。这种表达能力的低下,是跨越语言的——可能有人读到我的英文博客文章,感觉还相对通顺,但并不知道背后是经过我自己好多遍审阅改写才成为最终版本的。很多时候脑中根本无法组织用来描述我的想法的语言,这时才后悔年轻的时候没有练习写作;但一想到当时练习写作就意味要着写违心的或者毫无营养文字,这种后悔就直接烟消云散了。</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2015-10-29.html b/blog/post/2015-10-29.html
index f6dd0a5..b46f207 100644
--- a/blog/post/2015-10-29.html
+++ b/blog/post/2015-10-29.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"noname01.pas")</title>
+<meta name="description" content="«noname01.pas» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -83,7 +53,7 @@ loadTheme();
<ul id="tocroot">
</ul>
</li>
- <li style="margin-left:-0.5em"><a id="prevp">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2014-11-14.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2015-10-30.html">Next post</a></li>
</ul>
</div>
diff --git a/blog/post/2015-10-30.html b/blog/post/2015-10-30.html
index 8329511..24d857b 100644
--- a/blog/post/2015-10-30.html
+++ b/blog/post/2015-10-30.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"First CCPC sightseeing tour")</title>
+<meta name="description" content="«First CCPC sightseeing tour» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-10-31.html b/blog/post/2015-10-31.html
index 0615a80..c15e5d6 100644
--- a/blog/post/2015-10-31.html
+++ b/blog/post/2015-10-31.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"大学入学两个月了……")</title>
+<meta name="description" content="«大学入学两个月了……» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-11-01.html b/blog/post/2015-11-01.html
index e697372..15adf27 100644
--- a/blog/post/2015-11-01.html
+++ b/blog/post/2015-11-01.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Hackathon 2015乱搞记")</title>
+<meta name="description" content="«Hackathon 2015乱搞记» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-11-22.html b/blog/post/2015-11-22.html
index 5968642..830231e 100644
--- a/blog/post/2015-11-22.html
+++ b/blog/post/2015-11-22.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Raspberry Pi2 初体验")</title>
+<meta name="description" content="«Raspberry Pi2 初体验» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-12-20.html b/blog/post/2015-12-20.html
index 840373e..e7d9aac 100644
--- a/blog/post/2015-12-20.html
+++ b/blog/post/2015-12-20.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"忙")</title>
+<meta name="description" content="«忙» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-12-23.html b/blog/post/2015-12-23.html
index 5f5b374..a2bb577 100644
--- a/blog/post/2015-12-23.html
+++ b/blog/post/2015-12-23.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Chris' First Development Blog")</title>
+<meta name="description" content="«Chris' First Development Blog» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2015-12-27.html b/blog/post/2015-12-27.html
index e0f7515..16db4e0 100644
--- a/blog/post/2015-12-27.html
+++ b/blog/post/2015-12-27.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"QMidiPlayer got its repo")</title>
+<meta name="description" content="«QMidiPlayer got its repo» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-01-03.html b/blog/post/2016-01-03.html
index b60e695..ab0ff93 100644
--- a/blog/post/2016-01-03.html
+++ b/blog/post/2016-01-03.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"The Design and The Real Product")</title>
+<meta name="description" content="«The Design and The Real Product» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-01-16.html b/blog/post/2016-01-16.html
index 81d740e..b733594 100644
--- a/blog/post/2016-01-16.html
+++ b/blog/post/2016-01-16.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"QMidiPlayer Progress-2016-01-16")</title>
+<meta name="description" content="«QMidiPlayer Progress-2016-01-16» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-01-25.html b/blog/post/2016-01-25.html
index c1d2542..8fdfcde 100644
--- a/blog/post/2016-01-25.html
+++ b/blog/post/2016-01-25.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"放假...")</title>
+<meta name="description" content="«放假...» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-02-14.html b/blog/post/2016-02-14.html
index b47d4f1..a9a530f 100644
--- a/blog/post/2016-02-14.html
+++ b/blog/post/2016-02-14.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Why Do I Prefer a Computer over a Girlfriend/&amp;lt;s&amp;gt;(Boyfriend)&amp;lt;/s&amp;gt;")</title>
+<meta name="description" content="«Why Do I Prefer a Computer over a Girlfriend/<s>(Boyfriend)</s>» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-02-18.html b/blog/post/2016-02-18.html
index 5d4f155..aad9320 100644
--- a/blog/post/2016-02-18.html
+++ b/blog/post/2016-02-18.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Cross Noodles Recooked")</title>
+<meta name="description" content="«Cross Noodles Recooked» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-03-26.html b/blog/post/2016-03-26.html
index 20be317..5c07896 100644
--- a/blog/post/2016-03-26.html
+++ b/blog/post/2016-03-26.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"ACM校赛水题组酱油记")</title>
+<meta name="description" content="«ACM校赛水题组酱油记» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-04-09.html b/blog/post/2016-04-09.html
index 56d4aea..6d3c468 100644
--- a/blog/post/2016-04-09.html
+++ b/blog/post/2016-04-09.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"The MIDI File Format Specification and MIDI Implementation in QMidiPlayer")</title>
+<meta name="description" content="«The MIDI File Format Specification and MIDI Implementation in QMidiPlayer» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,15 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style><style scoped="">
+ul{list-style-type:none;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -92,9 +66,7 @@ loadTheme();
<div id="datetags" class="TText" style="margin-bottom:1em;">2016-04-09<br>#devel #qmidiplayer #midi</div>
<hr><div id="article" class="TText">
<article>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<h2 id="tocanch0" class="tvis">Abstract</h2>
<p>
@@ -107,9 +79,7 @@ For the Chinese version, please visit &lt;Chinese version link here&gt;.
<div style="text-align:center;">
<b>Contents</b> [<a href="#" onclick="var e=document.getElementById(&quot;toc&quot;);if(e.style.display==&quot;block&quot;){e.style.display=&quot;none&quot;;this.innerHTML=&quot;show&quot;;}else {e.style.display=&quot;block&quot;;this.innerHTML=&quot;hide&quot;;}">hide</a>]
</div>
-<style scoped="">
-ul{list-style-type:none;}
-</style>
+
<ul style="font-size:0.9em;display:block;" id="toc">
<li>1 Data Representations
<ul>
diff --git a/blog/post/2016-05-12.html b/blog/post/2016-05-12.html
index b2c9640..51bb65a 100644
--- a/blog/post/2016-05-12.html
+++ b/blog/post/2016-05-12.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"ThinkPad X1 Yoga初体验")</title>
+<meta name="description" content="«ThinkPad X1 Yoga初体验» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2016-06-21.html b/blog/post/2016-06-21.html
index b3fea73..1eb54c3 100644
--- a/blog/post/2016-06-21.html
+++ b/blog/post/2016-06-21.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Trash dump for the first academic year")</title>
+<meta name="description" content="«Trash dump for the first academic year» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,13 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -162,9 +134,7 @@ Most posts are in Chinese...
</li>
</ul>
</li></ul></div>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<h2 id="tocanch0" class="tvis">课程相关</h2>
<p>
这个学期在我以为它还没开始多久的时候就要结束了。于是现在我来随便看看这学期都学了些什么……
@@ -493,7 +463,7 @@ SMELT其实最初是作为给BLR3用的一个hge的替代品出现的。也算
</p>
<h3 id="tocanch26" class="tvis">神秘组织「BKT」</h3>
<a id="n27" href="#note27" class="note">[27]</a>
-<br><encrypted hint="The full name of BKT <br>with space stripped and <br>all letters in lowercase?" hash="454d2df9d1048b3fdd0d5c6799b834921432fce94b500ba16d057c10b0feea66" encont="VWg32D4U8Axy64+iLJvnEFZg9WmhI3dmzJnWv9/QgLwb+ZPaVzGgVlpYVDwR0J1nqYMZLQQdcJ20DBpy2RhC25kHMWlKmLMTLnvUzRx3hXLbeimzk98pqRq7KntVrUQHrWrkdLIrYelIPLr50fTXNKw+o95SkII7XMhrX9KR5DoZOkkW3WF4X/2PQXtafSMAN3ZEzJovASkSFqPXp6+czXR0OBMAJndz0fnjSEUQTrF3BS2hRHFpB2qVW7/UjomzRS+ib9upFpSlEhDOtiXEElowAhujQxAZkqsuxL/JjFELnTykLvahRc15injvjnYnkNvO1qSkWwnM1xoucQz57TElUKwg/9eyvhIttYeYBMBp56CmjJ+oLcvcylSxI7ZPLP8SkEouLD/60/s7xsAa1vDNraIyhoNsvdb4VI0fpexAIck2GPCJ+ujtaETZeKt5FNnjhV+vKzRbTo1HgKIcztAWzqxlzfEfNC17e1/pSkmavFypQP7aKP1y++wYyXbnyfGJVzHn194X1aspjL2+/eKqKh/AxiKDQmNorzIkdYnGMx13Mft6M/Wvh1Pm75/Yzve1P0PRRYTd9ydOtQEsi54kf9fi1KT/rL1L9qXP9QX4Kpx4o/Kkt7CUiU9gAN9M3M98ZlAPRCw5WJdI+medjlIcwegPerc8SFBTKNgW0Aq9FeSYxu3V2x3G4w/7fLRc8xcpuRUXCbxRXwol3eSiMJP8AFpdqRTSGYsEzUboJH0k/RvMhdEVlcCdotdcapID2iNELa79Ak4ej8T+CL99bZY/q6koBmdMCok04qxJ1PsHIlgbuD/Vz5aXH3xCGKjaNC7+F4mm1sUjsyJbRxGu/yL5dyTUpTDbmUxgWPaMv4+mZVpwYDERHDxc+8OFccmOpiqAIiy8v1w4K5Da8S5Dm7+wSOCD+HeS3XAe7dBDc/RpuwbdmaLmQyId2RXwxx63pB6Ho0YJxgcRiBTXhFFyfeE0wqnMpzIITXaFdUimu/xJnc6IdbwoE1yWn4Lwkz/M9MDzHZ2nhTwgA38C6fqQt2Y0jqywmZohfcSqQQGacqlML0QkV8BDX9paOM4zGksr0EeHsCqv97h1Plqj4HSpe8pL9idbStpgK8we7KF3ckRDpBeJV/GGqX/y8LgEAu7VSRU7aQCfOpebGeynLCiN6coJWA0Gwnu1Awi3fPAZsXsZxP9cLZtaiMHi5X//QGPJpAGhHHpKQvihZNQB564ZMb9XGPbm01knl01pzNWD1WVF6nDT+jiF4oOX0Tn4ESaNLdrNBZcPnQCtFT36QBYQxBmLPfSQgxBHWTrtajxdullr+kEujvJV7ISR8S5jejH/eE5+4UZs5/3V+IZ54+scJaTR5JFQWMOO0cOy/euVYt2NwalFW9FfpTcDlAgWG8Z/ZJq9EyIyNK7Kar9zStOaC882NGtP4RIQF3rB3yHOBkmu9Axa+JfZn5AUGmsgVhyAd467u7m9lsVxQsqM2lyd3zoSsM3SLuMSINWELP1Dt1BWVevTklKzdIrD7z4hQ808lHT9vy1PbxSSCJ8gk+2QmfuhNg4LGd7ZNgU+CAMhM7Zb819H+OxIvt76lknyJTyuoDsvmzMiQMspqo02/+duvycVqBsW3JnxGN9HQSN7B+jAg7RBZfI263wtOM4m4IN5YqQQZEkpRWvH3hRtCNgUoq5iB/vgO8+n9fgjhpQF4XrCEX9BLPwjjDJmfzstAGmgeKiJxvA2agbVqTdjIdqwoN2qt+Tbw4S4CeFjraickGJXC9c/RfZnDvSfdDjZSvq8q85Vf7Xd5PpdmWlLUmmlXqt0Hud8kFLo1pvIII11wWB5vfzFtZZ2HQXl9O3UkegQcOIeWRy69tdL5HWi9tR6HXdT4nY0YJx3QBGGKn1lUwZPlfzcdaxEH1sNCjRBsU9juTsCMvRRAbV4BD6Ux07pNM31AYVsmH+hfcYGDGwQpHbVRU2X1uhygqwv+I8oCnu400fc6n0Ef+6ReLvTLo5NumvWiFQq6N8/9786HpihM+VxWYicMuUeYkWDeUQdl32etQGnt3MInjVqRHFcefVv1RdYjST1/MiMNyy60TRkpx3B3EbSVncn6Z5FMeJpE14BfZkMLSL8oQeYKTx3TXUbl8PBwQV6ZwWhwypfW/HhIVDkYouSAnVkGI59YIspOKCILUunZ//sRhVnijv5RoWoPs/JNYcGIiez9KskazT0PfFNOMe/Cxdxz5M8LN+MGUT46ujHyR5nVjoNfc8n0jedM7lzY+YY6j0ZHIapC9daB+RT0IrbalrOCLJ/jhw26SpTtqhjYP3vzmCvIZq8mRQyYy+FoFu4FsNfvNGCTlDFItUTXXwxDEc90u+nZiBxBbMdP1e6f/gvZM4Z1oeQladow4C72CG0VHD5EvVMbdJDkp8uP8dz93zAVNZj3afJreDZ20YP3lj4/Bjq1hgYmfmYhwmgEngDe1DunY5/+Mt7vbqOLzony7wrkLHwERaEjNv+LOmwi0vQkbbYgO0u5jXnSxEsq21M3Z1+U0vFO9MJzmMu2rJV0x+7YBKoleEOUy9aXgMbgER8u+WDlzjzOBIQNa0nKS4z4IKxQk6rUUunSNlPdwMGoqiFLlSGYF2+9F7uwsJF/Ur3irJtzIigfFwdG/WZTmwayEcXoGAVPCe5noDXE+2pX3oZpnknQfJTnUAejkh9Qvd5gs2At++8bbrQIMo9VDyVEAC9Fms1o2GZq7A4290NlEDuf6nXDjDiD1e/TPSMi/v/8AfvrHfYtf/E63ta8i0NINLuLz55u9Wuhpo1IayISkFL2ZNEHls2wCTtP0l3XVWUW9r983+Z+Dubv810hTeZAWsp8tua2pwoQQBrzTSPbmqZO7qRcPbrsBq2AjGydJew1ybtpaarWBqbqObSOUuez1duLr8ICy4f6a6OiC/UbxhGLO1HCBZYWJtG13GGACTJfKkpGrnA3JUNQBnNIKPNAsadGQYJyizHDEWMVisiaao7hC07TBdfrM2R8QYRb6dk/ndtSm/34PtrQdn724kfIiqmmP3E9x0yoSJbSlId27xTf6yyoFLDwVXjawl7RQf0yjJfFFraufLHtGBUWKj/8ZqCRnSpbnTvifSb4a5brDBqKWHGU8poMyJUasdYPr3HCGoxiSDOAeEQGoXg1JsZ2kp/aJkAgV/W4hzFDgwiasq14Ps/4/wGpgC4dfDG1zZ3tg04cMKmetwkbxmMXClrmL5dQImdPx0EsgAaHYYshdZrgzTOuRUVnNfzxEoxoC16K64FCfe8Vfyk0KyU0v40Y1X6RC9/BggS/cwJzPD7GM7BFr6ayE2PfnQWNnvHDUFUnRyvWh5MGRV+vYK7VshsWra7P1tjMoTWSGTts8tN1gtl5gU0A43I+carfActtoj43RQv8vBx9zeTbkNTj9l8MeC9hAw3EY5h1S0tq1GHHPgvaykRJzIHsPoMYDMVyvGDUzS/C1U5ipE2fAvQhid22AnbXHPfO+ouf9zSjoP6EJAZ0LTmKhxabFg7TuJO9QFhSTjnjCcbYAtgMLa8teYhDI8pdSWL6PPgmTw7LZzqzuqq2MoP/glrQPlHRwvDqXShYsdaM3aoKuROCy2xjxBfiYsOkneR4CLzY/yabuPFO/m8/LQpWPGl63fdfpdYM2NkIl1Q5ZOswipIJAXtbnF9EM88WjOoZVrs1ORaLlrFWYTPHnnGsA9Y8hjFmd2DqVPLrNnVRFVAZPPXyYd1X+OiLRd9v/BNziqAvIT7HA9CgRPn71Xb9pvkFbj24c2xSxqXJ6rMbb8TvcvThZ4p7HonfH5Ce4esqDew624NrhBVJigkjmJlfBs7D1k0V1DJ2OlHr65ZThGSTeeyZnnW10CX4z/AufaXTticyzgqrGx5SbSA/gT0wFe9Yft6ko1vzUa20H30K9oyxR5xgI5R2xhxAvAvX9TEySvoBr1qzq990SPGwffsgfCGKZybSy+vvxzgkJqipRMzaMQEYl4xYXiBXjvQYTsC5rJHXdRDDIQMKwyGvvlSqnM5t99Ua30tJNN0C9dCwRPdi74B84UJ/V+rnKVGw7LFpkPBEUuQwSiUbGdG4UtsQr4ACIiLkuQMa6jO6O7UThgEKeBEJyJBoL2BCLBjJUnPj0wkvoqGgGvnkSNZMN2hzCoSHMLNFm7ykNM2MFvxufiUPkYBFu5A0lJBd5oX5a2KfkEOoiAv9Tg4+3dY+M/JHkoC6jsiRX6pl04uLNUtXqyvH0jf7ivxqJcI2l/guQHmg7prAaXdzp05MtjF4gGBuZqAeAX/rWGQw4y6YtM98HiSCn6pij48wYzjy/DuUxiygL/RBfGrd9rSADFn9x1CV2vEThEFTzdG0hyVTzZG+PDDvu4MhxJs2VgTcM1udQUbVLI9ysjXNL4oqtzUZUfZ2Jq9+7lAWNyQda/6VZEPMmr8nEOhuzdpGbgyhT7gwnQEcefSb+Q9c6cr3UhLEVcSmuUvPmUe10ZdmIVzaU1p1qt55Mej7RaeRwf4pAFeuYVkaAHqGjaCzqtoGKaeRGawEAA+GKwrOVT0ioN9G3v3grZVLYL3gQqKiCcDqXPqzLFMQFs7N9l5NSUqf9/Pb57+k5hUa6HzhgSTEivxQMJJtcQJIEBkW/cnQw8wKOtO3wb9OsO7ZRtHCZ81vEecv/2hRcM0/snvhyiiHeTYYxvTU9b8d1X+pISIDc93EWRCL+2vcoQmOseaVgQkxp8cY4lI87CeT9/ZpqAQkKPcieFCbPCMpHRzB76zL74U6/w/nrdA+0Kd2kts9gp0Njy1sj6T2Ivla7ZgMyGodXcW572+npP6MEAuPa8kVsxJGkZeXRp335DNL0VS5CKQm1gwoyWm99DBY/2Zkx4D1lUYbQ84OTI4unuh/mOZDOiCJgaePai98GUQTWfipd2LIXE+VzE1qHz6Y7WQ0fUDWDl2U1d5KQvKWVIhkSBo3o4aZdYnlw/U89W8FAABMmFlPu2b7amxCr4ER6aQVTtz3ojYVFpPgHXPpu/sa1idRavi1IfaZS/WFbZ0NUmjP69s9Xkyl7X7dffYNFtKf+y3MgIeIYhlngBDImiUfmk5j87jrKjuyHT4IMPyAglrIMSwve/wi6RkCnXvfGP4B7CU8KG5L88V6WzXYYMXfGhGrk0On9BLHCptPnQE6g39SJogzbaW6w3rSp30/gBGXVAF6zAp0DQTSOHQaAY2MhNghFhFmpVlbF3SRMTQ83Qe6RaGY5iLic1D9wmO6IHmh1q+Uiepv5GT3ocgl3DKor192czyyZjOTzMa4OJcdYYuojbM3pm3Dq4Eu6IBBCr4HT8qSjPizWcNEdWGpyCUTj66AnL17RcYiC+5BUIZJD7K3jfXhmcPiXq+MDxcUF1fBgTB6fHeyUlAiEGDZwZZWsnswhWCL6aT8jqncYJ0/EKoO/unqS68q698E63cEk5SYZPkBzC3AWC5PUM5OXOP0AwmC5Tes5YlevbYsfOj6NpGjyOJF5Fb5rxZfCfHq+68AcnmfPW/ddh3rHaiO/dyvwA5v0ojNxoKEoVkkoBy1aSRVLf6Xom081OOiXwRz7i+jfVldgYF/q3qptv8BhAD5piO1x2sENyQl52ruPBlAtCTo6Tz2upNQAtt8cHuAuivHoBcEp7wunaMz5UOQJr+zuqGBNp9LQq1iwx1Gqxab3HOUjX3p+3qxgKuKNPCPwSaVGARbc9lm+vJE3nN46XRa8IkoAgI/NExYJhgNhJSOS0CM6he9+6Maht827UtU69J+mucKmRBYRkhBUwRBhlZYpP0kvbq66eSDJkkd+ae3mWhw2ApD9PAk5QKmkRRTHIRt2TQcYnEXNMYTafEFjiTUhWr94pWivv0yYcpb9wzwztUB2+xjdE0eGOU1h1+99YcJDwbAo8L/X7c+1KtBQoEdq1IvQy9WVAATzNy3AywAmBk6Y/5RN+FVKVTbrlaDxo2mbcZpksduT5uBhCTHgNWRhIDQ5ZxOFo8IW2/sHSgXRZup7Mgwh51sAShVCQrSH0rxKJzf00wk/Bzb/mBRtSGqhsiVwmBlxE8wWyLzeNhtJNiYMiWYkleA++QkekHKUiDFTVXrqoJwQSWFrt8BDR2WeALORwONPe8O23s49p1dfXYKvEEuQs3rLaBRcMEJ/0zBFdcQOWvDjuPmVTG96lQopc/Q4iLzGs85KdfQYA7EOZnm7yyCCmZLI5r2NpYgnDR4ZBwflBYjBBalqzAox7p2K2DumE5HoQZa0Cn8Z5jI41o+XiDSg8P0cdLJQIbVvi7HgbPBwp6LPSoWQ3EXClLSP887eS1Hv8gq2n7NDIMS6y5jw+QPSkKgvHR7SWuo+R+X3iRXsq+6s8VCSNCVpjzHZgv5elx2SSiHpJYbmEdnLD7POHA" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
+<br><encrypted hint="The full name of BKT <br>with space stripped and <br>all letters in lowercase?" hash="454d2df9d1048b3fdd0d5c6799b834921432fce94b500ba16d057c10b0feea66" encont="wxRvK+JITL32f91nW2uAKEO7HAisS5NCx8XeBj83wta6AhZi1I4K5fgN22a892ay7uc6W+GUr+j0HpJol3rmqk/zt/SJMxqNkVLgPJ2mEodsMPyrPD03wd6d7pB/WA/vWtQYvExbyS6IDSlxOnluy2lIdMiZTniaSZL0/UdLWvXwW3iQv/zOQ70DY3oB3ncSkWTUBwg23NBsxDW8koyt+TyfloU5oCa/y1aOQ9y2oh7ObfrvB5kAoyZ241dAo0L2w0ETFc+Ve0K7zTRkGItMTDeVyxwjL4l3niJmbfZr5uXA49qJQ23+Hk69brwf7aH+uOmhnSf39/sx5pjt2lMhKQU3K/t0qsSxP/Iu+hJBhyJ14ARTs7dWDa8xpqiPGLx0+VRTW17pDrQA3SLIZzPiTH+o2RnEszwYLhKbb4BrQjcPQ3mfYBcSW+I+22Pu0g3OGLdm9pL/xnTc5yDve5eKK455feV7lorp79LK4VRyY7DB8Jt3wuPynY5N29no9BxCCL4rk90oMTPMKjt202g16WDRJnX8l7tScFvb2PLvZXQeMo129jd+NU4WSPEDM5xZavDRsYkVrF9ltKE3P3o64gsH9vOoHmAVhU/h/jCZIZPR4TSW7thO/x9pRYCqwcwgf7PmSVB6g1qKxQcYMpqnZS49UmHpwWI6dLzM+QKe+9VEfs2+O7If2GB4+H1SW/6Fp0Pnc2l/P0QdDlBxTIomTgYLXJxFbYQswxCgVz++QQEnKdOwwm5Fr8l2MR1pU+mf7JPqt+qToe6NTcygdT0HwdpQxpl0UCGZ/MNDNSFJ/XU1TndBxs5iQXL1vI2ukCi4dMhpQxwY6q7Qpf6Q6pYcB+2BXYjkuBX8HhPgq9or+jlbLSNdgMjSHVSTkd/wHO6hCE/3dYGBoRlCp/bQ1psWWev1hy6nTrvlASv+PO1eCuJ91wtpTZESSe0Ku81uvtSAkv5RWyQh5/gw6lYvyvJ8X8iCWo0bH6LgCGxWGiavqdLCDXb4+KNnOUrRwuWUEChVlcSmvsqZRjT1bwKx13GFf+jY1bhhT4DFHTbbQQkIDPSPORjE6NX3Yd6gLP/8c0/ETIFZHRbGvA2zlUxS4txC58zcr3BHwtQr52oNj2T37KmIq1TGUa9JnJvHBJQkZPnjPwCRVvHaBn912HDsJ3r2gx/SQ+d+aklHSj/fMRm/UPPpzP33LmWrm1NiGl++vEsmbj7GFEKkBfbtTrZfAa/yT05PpBEI4dSvkXFrcUaWjwZADjYvXYI6AtGO6QRy8Sdzq6rHuFrjaXariLxea3sQjIDLlp7zaECVZ+vqVljQyuOCUZpoojaio54LWnJfshR5hrkzk/t3uyUHcMvrUf1h7tG3mZACV0vWPWH6cZ4YuMPnksavqZ8HLNOx2O6e8CIMv9ixMSr2OJXEkSVi6GXYG4VPxqAfkXt1fS7Z8y/lZGhWAh71dQsmQ5KHJ+9zdlA3Jtjdf0k5lPAjZAg0C7SMIQ6QpSo0yfr+besnjhYzd26i42VUmC48xKW5vItO9YIeqU5ZCVeDv3gyF7Goe/DtjaTrWpyGnhbKNyH9OfLmru9tDDDOvHEJ+pNB2LqWM2yjWFrMQkIr/pErrBvVtwN250EUY7gnZpBmv+xZub9V7uZH0xuVpZ/TIHCwH6R9g78WNHCNjJP25zwdLtlze1RC+BhsifZsmngbrEb8HL88BfvSccKQawLYCwlp3GVXZ9y50+aKSoKlYnIJVz+fe3OhqoJokJ50nZmTnyefnVcX6aWb6MCg1KqnBadASEySiy+c5w/SGJptauc18wj/oh3CDTOpO6GAUIIhqacn7UaV77SFGjrYIaHEmk+fEz0tTauWfeXYF0rYhfmplqcCeu2zDTALd7j+MUDs8kV/ajDxa0xB4YWH3Zf2MRyBd5LQuB3McNH8CEbzn8XkCZer/MT2mqjQ9zeQIrOUUOrxZPVsJNdJ8wimn+EnpZe0xJNErIOxhFXzXLxpw8dDRzetXixzLlBAJHeGdGByvfEZjLXeeh/5eI2chjCEsbUcpZ/n9uNvisTZZ6DC2ZC3PlX1S2tMVHJjto/MF6z4XydKRwkCgC7992fTfVWgxci4DNUm+wVKdh4zGPm0Y0GMxA7srbjh1/Mwf3PdelTukDRR75WaS1iINeymR0VE7ELr7KE8qetbpSwtX3AmZhB8WbJ797HAXzinc0wo0v3QC3MeMwoFH0U5r+9X9DsuAjXQCfDkAQx2mll25z/oyYAWl6uSPFJURFvUjdW99501k0WjOj9hs++UIKoA06KIdR3v4vOmMlJ757Gd7bUrPrpKTm47K3RJhqxOrKaQ8mBRXBrPMkuz/hgR8k2UhVTuThEuBE36u4yESB8qC8L8ymYBk69VO2CoAfxdbRdKsXb/MNtgrdekR1iXRI90FJtM+veWw+t6/2ht/pVi0it+iZ5Y6Dsd6NzWyrnHG1iFwGo4NYAxGNuQIZ6GyQypqRxoeh5bmSUfbMo7povlBV7lX17E21nb2e648fH4BEyLBU3Ec5yOz9mYk3hc92VOnXVkVa90jlKgaB6m8pTBBu+83xNvuoYEPWEl0Il6ix21EsVAv2pmHcGj3cxo1pwd2T1AMPK+KX3gYBQALl0EhWgNwChZoLMXDZCKzsDfjCaxdGoi0uGFz5bM49ARs3tjov/xWJOxx+Z2xoA774UJKKzWGTE4IVlV0P9c77MHjk3GDD8+iZTLLHSln5xb8Fmm4eWhAfJeVldgfjbzClfQsLsW0vscLIPRRwKYH7Gy0jlafpSQRBwxTZNggOqT2KxLVF9elOBi9tTlWdsPQhRW1p2YICrvPAdiB2F5IozVuWitNzXN9fMnAiybOZo2Yd/vV26T0aKBCT3bwf9wiuEz01lZ5DfVEt9Zu04nmL292vDs7be/3J8ETzUOjyzY6q8oi7bIQ1g7q4MVui4VQskIxhpblIT5AxjjyYEeB4CwzJmY8XEgabCMiGgS8f+mJ1U83k+1goT39nyxM/G5eGuDlXiKyYckj0rpYlJJbFguFS6qNwCxFpjuJ+RcqZklgnWI/AtWGtEZZxczk3QgbclJfx3pcGH4CSpd30436/IB9FQbdqy8TwjB87P/mKsmH/3L7ScQ0zO6bU9aolfJuzIZRpDHnyN7Elfd5Y8nxQ4YIcYVxczgN9QB7GTpOxzHHhbWVd93uNVebZjA4a5ekGtle0NL+H/zwZnPO/ZDIma3KSsPqVjmVQX7zAoJMI8hbq9428ndPqn87hfXr1R2FhGTw+7dJ4NXN1YZ3Sr2auwP3HX4/7HJwfOVq0UoQ4Q8hxYUOsbE1Zgjy81oG2EW52ZHgMsDW2PQxpms9J32pvrPacbyRWm7SotRbQQ/qQphkZWEsuqf+ZmDvMH/LlrV1Lw2clQBDeBs2mkTOW81Du1OZ968KsowD2es4nuNGJxOBMb2BYRuxkTbEh50OHwU5ltfB4ZU2zKMeJ8Ch6cOeA8ekv/bGRsvKC0v0v1/m+qNRGDq1dM9EuhBlNxpt4mPQgeCkBFNSY2fwOLXVcbsvUjBndHvV9ehGL2uyOOmmp8ZY52SzsWc1e9p1qDyKTkZ4lbnuWsENlI6MD3dWgcKby654aeVhYS3e5f3HPBrM6Iak08fyLoFZNtKyRKZP4Eju5876A23fHfDSpnpI6hXrUxnCVtwsWFF7QeBpaBHxZT+r6tXXG+l9+oi7kC37j1eHSlqcjsuMD84uvm8xpyU5dlr5V0mqtLyoifYd87V/i41KutTqjE2qPrKESrUjkKCqqHuK0vRjEKB5CwYv+m68WZfYcyn0erSaUcPpjreTJjOKglT2ruuQc98IMuwJCjtQhbxsG9N1czJjSq+JS1Pr0NpQf1qvIGGWiCsDtD3g7Wqzm5PguCt+yXOirMWNr1ji1H+6Ea615vCUhG3bUw1TfdcPOV4wsMFuUhiuNzGZIeJe/GuPYqewIZmNfc0fmKJlpqr1o7fZ/8Q6R3oKtfUtYMBg7WSC7nE7zddIIb0NmuoWJbPE0/UMlY2xa2+DJeQZkkFKjILFSsdfF9yrJU1xCEZmumjGKbKXerF+7HEKrUuvrMcW9+IP6z/ZXn92TbDDKHbNAtJZRaA3dhLpYKYjkqRwNP5Q9nt25sOPO+C6RC/E7vXAmPmtwfoJB5NXugan3lWlQmIxeslBfe57YSlcfyCts74CAMjoVyqBaVdVWHcXiK1XA28Ahfl9w9/kcmaH6qeQy77KZTQS6IUznKNqmOGfjHjZ0CaUmwmKrOjWHMB1y+zKp1L4oGaLsQQKFHTggxQmxr4y+yhVtDltC45rg0vgY2AinXZcJCO3KTNGW+dgG3a+zYSeYbHBMOj+fJIxcGc0yBgtoTOnWrrLZZZ4txhc5bG+RTbZJFLogMSlRfRaEmUtintfLWJjxEHvDMQYE/cPwcbDmWvFrhpiRqqgh0fGaCWBd+GaZGv1yqCu+1zgeeTBCiSv1k9UQpSvOKWLVBfrejQHIQnyFkv0fz87x/o0D+edwa0U49Su6K5Jp+32f3eXvXZtojhmXBskqE3wyRiYlAg5LnlURbeVv6j2eoG9ItQjU8SMr84ovw6SKCk9YPb40MTJv0EpfpuiE3lRB9nRYz1foxBHuha7isIx5VYmX2E+BGnsJ8RrN4/0KR7F4v3UDAa9mz+A08QHt2Tq2njIXi+RB8vFMwIC1/1iq6MUBtw0rbupM+EebhJOl5RQTZZQhkVW4NUkgB+Q/vEMH9WPxGiziUatLEmi5InbYrbSmSHBGvUymvsDqkwqRy4MgLjomM28BQFBPyFLasVIyIIQ0pD8VhJY5jTAK6nPCgMl/dRflWnIG6h1HHaUDRjjLS67OO7UKniR0btm+o9gxl8/o9X0KBLACv2EVGkIykbqoSA1z880CZZ9f8475ErnkaBRia9ai6QPieEyS6Mn+p5Qjb2gtq9r8s7HHlYoLv06sB3CFEyPPcivtuB8tg4k/pNAbODazCQXlwBlbv+t34qbkFeWxm1fzxRyzban9o97l5LpWmzW3lV+hOeJtrzUmrME+MLORvnam0L1p80u65rJ7gJ2O0WXsRzfp4VWAegv/6bV3jTtzH7blAm3euqwMUQpkuaDEuCqA0Eiabjih0cHldNhaIusiawDWHocSL1LVW+Ivl6Z5hUXvsZg4ZiVuDxQcw9iNE6Mg1ifjbhnWklvepg+Ts1/BV9onbGreXjwzTDU/SjdmdPy2UUxKN998Iv9YvJxPxqs+LEBvJPBVgqpofgMXn27pKvsF2Q4Bc9KVFgseMJVPZdj3QSG2QzREamr75m8QdaUrbPHeQE73bUm2ndUw9UgxePI5UI2zQ6bEYaVlYDut14fUPFbslrPZDHQtA+H4UadMETu8AR5wTmwNGxCSip4SQ2ghIZ+wm/4WzPi1QCtbNJk9vzXvE7m+wK7+1jG0RRO07A/AVQBfXiMnPI6NQsFGtIJbFTCdKePrPXF4+riWZdCosby6UnPZp/ltaTFsQsOubHXA2MtNZaQMloacpHd0JJ2+CElcbEqbIyENiJYg2zeC3xzC+O9uhVHvRpH2o8kBmcT6EfKXS7+Rp+L9LFJZL/yf41PEGac6QiK3akHlCp2X+gPBnDUsC1aL8L0f0gLW60fhCAWyH5fXFBqnBSc9bQkeenfhupkFb+paN2vPiLFVskVdKb107AanAVVMQRMvxYh0uLbcAIWeIaZJuEyazHmk3RHnseW3tTMG9VlitzFbNKv7uqJ92VHn0PGTKntAqDp+yqTJuEGugC0inP0h/1ih0DF0mne3CB6yRh4seK8IYsj/MGzdDN9m42btW5Bw6EDavvWQIBZyLxdZxY3a54beHFsWiN7uhIXYZoSCVaesA6twKb0oqxo30/jJur6btbbhzD/n43ZKyLDeKnmsebKFBei8qVvzVlagHGqMNfaaDdvETWPwe2tGDA1wVa8Nc2y/YNOXrl12Lpok5OCAxXmyL6D1BTtaz+wYzJj5KQMncsjDJUlCZpfn0Um1TtNHxQQ42zSfwHsDFRHtNgGAM121xLwg1PBbhsniiIAeUdmkEQApUP3uSAASxMYJ6Bd4c8sFbIP1qBR2o2CiygnLrzx/d+LH4r0Upe3jNPmP22Ivnjeo6sYxLYPcBHVeljR+24FJdNvqAVQCnQJyuZdTGJswX6agCujQQrdJ442BmhS/cNUQpa2Ewhj/9rXzHzNB/8U+JPP8U34lawOxl5bVe1SriTr2/Ru8gmN5uOFeGkxUvLOanj57NcCEA09R5vFjhZoKOargWkElbeOSznhkptm6RCQBOJQE+wgTwiUsRohZuYeVcAQuPJe5wuQmqytcGyln8Cz9FCoQYkFVnH2Bj1MnmLMkH7OTzDE8YB+mzqLsQh5fPMYEwK" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted><br>
一些额外的话
<a id="n28" href="#note28" class="note">[28]</a>
@@ -532,7 +502,7 @@ to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.
<br><br>
……然后祝他们幸福。<a id="n30" href="#note30" class="note">[30]</a>
<h3 id="tocanch28" class="tvis">宿舍和宿舍风气</h3>
-<encrypted hint="请用基本拉丁字母输入我的<br>一个含一个希腊字母的网名" hash="39932de669f3e48d5fe22219188e19a02d45352fae101df1761e4014607566ae" encont="gekNt94fGQSLkMCHmr/tLxv/aFA15af2cz7hTV/13SpRcV2bSNmr4R8xae0pgLJPEJwQi8VBTiwN0RQpWOivuI8cYdGBF81ghvt854xo9Xto0u1q3ymBwZke1IA4s16G5T9sjffuSNRxaI44/SHwQhXyG81ivmAGi8qGRmkV/THsVRzWBGY6iVz6Tp1kCnjm+rdDRGk3TyZAPo/GDzYutzbnXRPnK3r7kVEu6UNAnP/Xm0hkAECnh2s5Tj4q8Yf/CBSSeOiEVJhxToQvkUaLgMZw02JLGTuWFZbQ+nijsTGlxutMjUa/X2AiThuIUqDj8HYLDiutEep488sW0hjzqnsP8GzTBRZXaVnXfS11jmMJ7FR0oQDfDgcfTd8h9JR2XLnrz5hPXyvk5aScVswGZ4VAtautIlJ+1FLW73W8+LhVdD2LPzURth7IOktNaU3Rrqjt0CuRJPvkSQdJaWPZePo/twGgtw2RIccdBvFrDMaI2Fd1GxybnhRZY3eXT5DmSv1ggkQo/12v27BDQKS7ChHGTW6k6JchqFV/t3WxENi2l1G2cgSK8ytzJKSlXrPpoV4u0fAJfgwryjjw3SiOEn4eoPlu0Ust0nS3VJBEx1Yk+ZgtRAfhHOlqVccZtq6qmjHilXs0CS1g2Z8E6JJtszoBfUjZ/FGCW/2chnsEQ/Mjf2b4rHB4ZpOKkaSZtRPEfmJLWDbtEc1ilrd8d4ezEwXKQDcJSkNNC0cNBGxfbI+RhmRtS422TSIFPPPci2Cf4JKs0p7tZvuHSqUJlcYbCA+i+WBTd0AxNze7ko74vuL+WAhTfBHqIs4zcDEBWnA3wJHTR+XOR2au5e+uz9rJFVWiHkBOtRvhbkLDfNGixah1P+ioy+LkY+uFx/iosBD7X7hr+IS/lvVwJontx9x60Zp8JpUA6mt0n+RyBfNialrmC07zL6tRdbrFK9YSg/RemJ/0QshY1z0Os3y7WAQRpOZFYBpydiLewZbFj2dub4nN36Fx5xEiK4VCasn7ViOhubvALfn9B19DYk6baopu1trVFgC+6gB9kqboSSFxHEGC/IAAyNv+fnnRiahOU6IHzC7XiN5aWywQwM4U5DbHo+6H87NU0HRWyowybjlChVhO3U/hKbvEBVQ35TG58IvIHyUZ4BDgn3PNzIcZU+rcmgXby+N1Kt884QkL0C0Ab3F8STW/xyrw3x4/n4F2SiP1vUejCYJymkPeUB+Dz2zTZoGWiqpNaevAiqWqxp/akbtKUXKcrnsMwDw41kIAeLvHiSDow3oP7tjSKfvVFw9MhBYSOd71HpRz/9VCD9QTsPnE8wHUVoZpI2u9bINGtjs4+ZYbsl1dRAMdQQfcZ9rhaKDTjsJJuNzwYcWbyeVeE4r0n7ZETNp/KJT3wOlRq81aWezwqKuwFPrQmmb9MjaldriJAkAsO+PCopIDeB3IKI7gJEVMkYXgQz/+zTRdEplWgPI22h0/CjvHTwIOJ9u0VH59ylutoq3hit68IzTEd+FSBrZUpLHYN53MVkHcUbPfwTUllNGOY4nB3EmuqJWfSYq5O1hea6u258RcnVEVZsPOl5g8e3wGx1+ha8/qWizigEatqk1l2wX3RmP745km/MBVpAGrNPNRprpNo91A63PThChtickQ13cWhVYAP6jJddJwUx3NSxEjRh+aDVvAiVuUlKC8H60JyNSzIykNtSorfsfh0I1AgU0mJIto1IcNNEVQyidfvnTtneXYZ3Ngbp3kgOmr+ZkB4Rh1GHrOq9yJBktzYTvR0qcg8Vla8mSX6uyFBemC8DptBJatEqqitg32xIVnaXFNeybdXAx4pAFH28qDPdfR/SIQ4g16JVMXJaPr5nC/ZokPqhpEfS+fJ07HOK1OPt/sqzxNL2Ce3gcTgO3DP9tDmzKYfbXnSQxbRHQ2x8YXdrg84b8YFz5tzyahEk8EO3iV6RM/Nr7xkSC9RGxvLL5ohZ1yQUwY7fMt/uBBTlly69htNtTMVOnpyLxCdTiWA62D031YuBwtGKfRUZcA697onAy9N504jyoA5z6b5HUFogwlbnZ4ioPpG704QyVkO/rXOlbizTwv" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
+<encrypted hint="请用基本拉丁字母输入我的<br>一个含一个希腊字母的网名" hash="39932de669f3e48d5fe22219188e19a02d45352fae101df1761e4014607566ae" encont="KbCGqDTHT60NMSID4x69k+IzgpqdCkuH9x/YrpkdwQGAU4khkegSBsfhdHS2uRh25HtdYch3UM/NUKPKgypxpOIflGfUsrwVS7pwHSwqqoD57P4epGWmJcVhWL8thi5WMkkfJkE27YwMyuXEFkHB9omNDLCih/4bV3YqLow3xed60b1/EajUIacPtXXluL9Yfc3hZpc3EzQ0L7gz4eQxzG4B2ZJLCzb0hdnHu442BkmunrvJPsOUfjrlmt7wK9lSye9O5m8bQJ6x4XH7lIxtZQ85qEVJxyXKBIbaBG2PesfBPcsBy7IHF7a++ejvMM5dw59btJyKMp2SSx6xeog+BuXqEaViMSMTWz1NWhj54OcUCn67jupu0zGt9FslnqtrO6U675o6jbZEDAQEpd8L3nqi4iWh5s+kvUidchNgFSIhy+ja5b4ziy2CifBHXulk0lBWnkbBO7ScFAQw5iKar9yUT+b2z0Ir8D8bNH1nuaf0n+gkooiWf+Gtxy7gm3TC95CRHwdDOQYO3iYBde+LUqAZaWsZ0rAbBpiiveLHPMPcyFmIvHz1qRMoGMnWwSeZfv1hVIpYprK275tnUTyEdJGVcI587qj4R9sdbjbTv+fUgxRDm5Hj4uUQ33CngrWSNQrf0T8Y4Dm4AhJiVAes/ORLbgCAcjxseJ2Qt66rEEY9yRNTWS5MdOUbQUSlmtNtJUt5ekh5rmzv94q0z83s6VTL++j/eT6zE4du0ptGLDz8Sl8e2dCWsbj0ouUy6w9FI4uuvEh751Sowon8TEpSR98Isaoka0zxvt9uXjb9UV7zBB82afqfvHrk2EgslMbm13VgjyzdKR5Bp4xO8gCu0zI1+AnTllnWguuFiGN36RNRTab5Q31FpUdDNaNJZPS8KkX4MkS/HY1nGDGGBscEojUN0zE0ImGyag5Lt2HMyRhRHJZLeyeiA18G/DNN4fATZ0B0gytQ1xWcvX8BqZr3jeZIX1WCYx/mKtLkSCLpg4kTjSKP9VV/CwBvFYdN5M9gkrJkjxRFINgScq/gdPEWN9sxhqIJXzIuUMHbU06zdBraen7ATizVmlVtfQTgd1STte4wmmEGZY6iKCCAbm8cmAyxePjo7SOYw/oFLBpcSBDtPPfjqEfc3hxmN6/1FKLSOOPvC7Df9IMbgrbQ1l2Fi01g/CxB4GSnNJWESnG9IIj+Wha26Aud8H2HPqW0XvP2suh5cbSJsH2o89Vc3wFcyOHyp3f8gjK+4pJP9ZDn8Wa3xTkrATbexACfxbR96LPEiGHW3tHYsK1f0BnNeJS+Q9RnTeT0W9jUQ17Alm1bQSVuQQNB0q9+bov8UHrxq7RE0b6okT10y8fIf92HHi9yGY+GhQKQ1pc8c1hmmnm3pIdB7WmrX5vdVG7naNS3jYcyLC5wFZMberZbpmEOehSrLvpVV3QRQHzkCJwC4qoKnerNwuGFVCjclmJVVpAXkO+0fumi0yU4eJwynUQFo3gyrh4keHp0uHFon/4zYMnS4CtVz/+3UMbsauF2yp5B5kHa0Z8HMZyB2sGRaPnjpWTvLrmdN27l8VoU4PqJX3/RxuFDRfn4CakmNWUqKyS0mzw0snx7IdyRCpjAALIeLHVgnBBbYAu6iTuXW2iwSnCXrVyF9OgCbeuuAYhncdoiqaHRQZy7xDkkg/ANXlEQvSd0FUj46N22Xax0B9g4iq97uzRT4FOdLvPIXWrXjPN0T+wT46xvnH8xKNSD+GrwZ6+JkLeErECZYpQUqdKAU9AAJ9p//+KS6Gt9GG9btgAL4ZTlwWOOyDhB3f7ki28dpRYoXRV21f+62InpdybiCSOFrH/dAAP1ey0idtml+bCdoiqJC9+WcK10TVh9m9nMx9rghvOT9PEceIPPtGJFillOKj16f2TQ4yhpUDJEhYlKX4pfkol6ECT4C8GaWWziDqzH1JjARdaw9/za5HYwe3SSM10utWke+gCztenhCHLmdTpUcP1OQGTJ1SYN3cJsA3SuqvaljkQPi8ha3QFBByZI/zOt0dPvskEUJCqc2hlCqW2pL0hfQeKMqqbl35qOmuYTPYFuU+mQX40zVPtxUoH3" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<h3 id="tocanch29" class="tvis">钱</h3>
<p>
@@ -547,7 +517,7 @@ to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.
当然我感觉这些钱应该也算花在该花的地方了吧。
</p>
<h3 id="tocanch30" class="tvis">关于我自己的健康状况</h3>
-<encrypted hint="php?" hash="2cfe798301e9d0db91f3c012440cb773831244877ae799f260a69741ed1569f8" encont="rfTzpb8xSYVcnlEWm+mJVtBOYCdGRGiIzA7vxET0tyOusF2KGYYqaP3PNppXk9E+HsjsmMriSS3fMgvo0irwJeE2EHWl/WRLWGaexxuHtLACT3MBzcWp/UcwxqBiMynETaJH5erHqrM6vSJH50rYl5lF58jG+gKfH1i7RBFgXJJfSjy9MTLOHDVmyvxjb96xIuDaexCLg8itfoIeoa7k4UfP7eFb7wLqobDmRr8iEAAmEWuYLqBoSf7QAKRSoFIHmxX+63deeapihtwcpOJjFYveNwffHFXoEN5FLbflxtC+UmeF+lDCYZkRapfgODYK4cnCre3JiULK8RTjCtRMCD5F5960Vcums214PwBzSqvi9nMV7qnVoMIX4yDtPa0R4OtIdSlXStbXZ82bkbFg/o6yxqrjxaF5YBVV4AN9wgKGCMuu8ZuNRDd8Bsgb3BJqXFTyd6NQqrPpOyI8fyDKjK7rvrK5HXqOlHZ+yNYuRqNHLRBtWIv36CEKmetkMy/tZJ+Crx188T/kOyixhudEN/aNDwdwq6R512u0dbtWbjalh5Bhzv8MERqJA5lfRPE24NrUoG9jhXrOrzUBfpYtqF9xlHLfiJD5v9sgGnNMHyFMA4qM9jttUZ12XsxngksYLdIeZkYOXHWm4kidcrvtMxgE0FYdwIFqVt9Q/e0W8Um7RIa4QIuTX2WC4jALG/VJuQCaITlyXD6ZLgp1wtHFoLRuvnQB9yMfO/O+/3z3BMp3Fv87JQzo49aErpC0zOMRzOQsybDr/luZBoLofiFkpS7JzQS1/K6zUk1MnR/2e4pXu2ukU8sMdgB+fWJAMWbVk9a5nZcF5Ti7Z/NtRyGBmfpYEAhoBKo2DYJSeZChhGpXb40XGdG1zE3H2oJk+cFGb0Jl3scEOmR6izrRLfgCaElTFI22A3A6JbrZzEU7p+boREsLyibINZ6pQ8PjCx3V4yfyMGNJus//3c4IUpbLpYht0crCylJeiLLbC4U8gNcykETMoU0ehiH08c95xGMJ3wp6F5yod6LsFzMG0Louk8h0VfxtI6j2AsmBG7GUee2F5MDmDNPmWbr5oAdH1aq2HgmP0AMWIzCsY2vP5HaW0FkoBm+fRUauiN1abq0GBP3Ajhg0G2UhHSwi/uaHcuq+OS5qZ/3A5ab5ccgvIp6J0PuhCoKknw4oI7wif5hSQOYtOVX45J+jn+NC4Ev5di49i9A4UwuMaUJstRauNzzanN+ZHq12aIWAHbN3ziwitFmvunWFDW4gh/mBHcrf6b3yz2GjKuZQjpWGVKfoKEDJPTNfn7Pc0JsObnKj9jStNDjbYEZKwsEjf87VsGtzoGAU/9buNoZIm/eIrqPeLLg+NLTw26RWeQ2t2i766aW7Fv7eNJhoIP3DXP/vssQg3+1UX8rC4I1ZvDbye9Uh82CN1MuK4np1xHRk4LXBUDWk/R5pMUZx7xU6guVT6mLo3zD78DgCdpidIIwVzmM6uxTXaX5KPvEGgmEDViiu6ttQUL3yMJsktlpO6KwGpddg8FEQEfp6vX4AygOcCbVgwOZgX8mxWsMsZGgoP4CEDPVnneQvla4zVJnR9X/wa0sI6vp7WO/8I3Xid4i9P9+CZg6hnvh7DlyIZcIMopV8Hx//nBIc3SRX8cXMuT3HidFVPTYbw5ToWPNcEzEXw0/SK6h3u63B18TDRWJOEVr/Hy8VK7zQboBnwKO6ejt7KSJszJ4ieWFN0OlNwfjkT1L0DXlaJNfYoiqmlWBF1BxJmhFsfgiXQ0aYILbjwJkSi0oq51rGXpSiqHaSNnuL+qfPuPBXzv3gmw5mWyeIsIRoLGSJvnpaXUWs6aWSTVvTtKmacOc703I5EpAa8Oc2TU5J9xxXD/bmZoTSRa9Bhudy5I1j6fjsxopAZ63pshgSTa6wclU6YzukEizcV+rhw5r5QHHHdl9zwCniZGKTp0aSW/Xnk0ZOK7wFhbjSnGAmhvBZ5AiervgdPVLQDOh+LvQ3YUKT9FF1jJKRqtTOkTR7J8j+yW1pigzwqrff9bWoHGkqneORMblUPy922eSxsgyLaxQ9IMZmq8o9YIPOMSa4IFWZor/PMyxdp3Nj4SVxBJq4kT9C6nttU5OsmP1MIYXzf22yRFUe7Z+1mGuzE6dAd0zNhqsktG9ROLsVXWP3n9cQSG1dV5I7hI3fySY4oFSpzLXiPlwLXb7/A0nxStB1UH5tG+27f9PQBfEiUCGtws6k1ZaIKJyxE/ISKgUDx/UpiADiV2kG/zz4lXSO" enid="2">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(2)">here</a>
+<encrypted hint="php?" hash="2cfe798301e9d0db91f3c012440cb773831244877ae799f260a69741ed1569f8" encont="CHv1MdArGv1KBpayI1G+8bYIYX6pSZL94SIpCNJ2W8Y8TsaHo8B169uUUDotjug7DGdtikLMLEX8DrB8hhe3O09rA4d1UNxhfh1rhr4D3af51tqxyAntUQWxIzfDgBoaNHE+SUBHXbkaiYpcgwb0bXroq0+cZtTm5oNfsdCwz/4YQUMhTs7gUHJmiiJMSxC7v7lVAc+71iosZJjTNkCIFZOTTYnECmCVGqZuP8JMec/zDBFvL0sSzQRpx5FZbZYjnFSjvFsbGZu4gcQCPlbXVumEF5fYPpCpgUQKJVZ71LXrwUpeUPUbhTvXiYp/WLNVA0T/OlnxASZasmGVeTTbM2A5lgZjtWqPmYEHE/wCw2TYPrY7/T/yIqTgUgUmW+Nu+fQJ7Qnh4azHBMP1T8U26/XFVzj026nTAeRUPR6zp6AnurE11/v+L7gFFeD/ejfRDUYjQKRGqB1gfDGvzy/Eaeiql7T0pV03e2EeEdnWi1yJSk89n/zUzbPoZiY57J3cuqMlxxS34DnOk6IYkO/aczPng4weO3xNiG/PAKdzaH6OmaVj9Z22u+3KcfTQvKvCnsId8kGiivP0cI4iUp/Z2iGNE3TBFFTGRsII/eF4KlmgQKTQmsctSTILNQhSoAWwbHaFyOccN5Rp5Ocaaz+PRSkKxeEueyvlEUH4ESo4QwGc/GFKAZqu0j86972zfgir087hiaMouMs+uFNTra8AkeWfFDFy6uRroBFFa1qUjv9dF3oDx2ZI/udF51NgfeFsQF/kGR/dkdRvlllFIymqtgxzuAuXwPhLRwwdOm+fQzl3XcD9bigHkKxlP/VWcgEZ4/oU5cwIYx8agUq88H1mxsXVbHqNNtMngLEZFik3tr4doFau8ADXTMJCqP+Al4msI5ugwpQH3NbM0fQ6992t9HKDfLrIBE7dqq0Bbzu+uMJg6Th+N4kIADCyt9t1/pCIYqyiRRgnkm5XzH2+5NXtR0/Oab3pJZI388XAQLQphw+i8Y9rTMU+LFI63wspRjLAqugJv5JxJdoM7Ig5DmnN3OsBcTJzc1PFQknpCeYxZnfPuuc61qGeX5WO+PVHbn1UaxkX+Vqn8jWItExg2mcwpxsNB+ZkT0XPnBaEMLSqz75D+HjqvWc3Py9auonsWb3VJCutpVbvmksON7rX9KoUQZpTWSfRrpgZ20mlnCwoD65FCguV2oiSkBPRAqRWY3xoqdp9lC1ofvWBcDCvv7SycAg8mvu7Q2ANtVifIhRuIJ2uCqtW6MLqG816LDJyPdYtuPV61veVKWcVNYg9mdjP8zMIhZUWaY1Dsl4PrKvPBU2FseDzvlkHaNPfPE7cTU/IaAh0X1Unwd63stllwkIh8qJsD/edQJLJNle0W2vIVeeYN8/zKzdEHNvM7eAzHqE9WueMPotaEb9zU0XYt2Xw6TNkhWHcISaVBxLQoyDciNq/RVNbSDjHW+Fdr6I26HzMV4VJIFtKli158yrVRH9i119gOnaUpp6umW4+XnlpHnWPywccqktWi4ngG2mjM79uV3qVCe6GBnENIS5L6QYigajedOu7ITDwlPajI4STFPU1htmr+cT7gfFDFQ/qJHJJAMIgzoBKr5LTc5VJ3L2egXQMvaK6ZZwk/VJAgk64oqXPU53hHftbPVm8t5Eo7NVHWisEuaFLP8XwY3iYlvPoRTjmwsP6R4DFm8p0NPM0Ju73nHrNkVqK6srEddpKhkLdiv2qr//okUc9zSo16PCubmPd/KORaIuUyasUogtwsajs1TlLUdkNaMHZYywLjIjTuotPKGI/C9ATxMBv0pEABzjyCzlHuCq/ubFMqusr/BH5+YoczKSmFgWAKyGv5r+vfzsdG3C25gGMpiPlDb/pEpF6dMR8wyfZ6PO9s3RlJXvtTayYMysEic+boD9u50xIU1+8qon9GhmIvnVjGuIc+xyJM57P5xKX8g+1RS0MehiFKehflW6imIbkxqh1KhaUGUE5+ySmSh0b8zAeQEkF2L+efrM2FeIlc7NaKPvWOkMpfP6MiDzBwoeWmE6r9TyXk5qarWomOVeiqfRI5S3cpg/4VdMbpm5R0vDkPKt5H3rFjPafa+apkLXP964HWILBaaP853lmhucaCKis5usSkI4AsbRCgBMQyWt2Xc9RRtLlJzy9SSA8/kkmkfd8fp795WiWsnc418KHA3RkMsCq8hxOQ3fk+iGQvecitVyCQkMVqZLd1hfBZiMJj9WLBcH3iFFdr+dwOPfuhNKDS5ev25TZ13Ljx6sH" enid="2">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(2)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<h3 id="tocanch31" class="tvis">技能树</h3>
<p>
diff --git a/blog/post/2016-09-24.html b/blog/post/2016-09-24.html
index 0de4d43..f3c95b2 100644
--- a/blog/post/2016-09-24.html
+++ b/blog/post/2016-09-24.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"2-in-1")</title>
+<meta name="description" content="«2-in-1» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-01-09.html b/blog/post/2017-01-09.html
index 778124f..10cc606 100644
--- a/blog/post/2017-01-09.html
+++ b/blog/post/2017-01-09.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"[多大图警告]终究还是改不了修电脑的命")</title>
+<meta name="description" content="«[多大图警告]终究还是改不了修电脑的命» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-01-18.html b/blog/post/2017-01-18.html
index d42c03c..5d7538e 100644
--- a/blog/post/2017-01-18.html
+++ b/blog/post/2017-01-18.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Trash dump for the third semester")</title>
+<meta name="description" content="«Trash dump for the third semester» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,13 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -95,9 +67,7 @@ loadTheme();
<p>
从本学期开始,垃圾桶改为每学期一期。(目录消失啦,看左边吧。)
</p>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<h2 id="tocanch0" class="tvis">课程相关</h2>
<p>
都说文化课最重要……<a id="n1" href="#note1" class="note">[1]</a>
@@ -322,7 +292,7 @@ Canonical自己雇来的、专门维护Compiz的Sam Spilsbury也离开了Canonic
<p>
那个东西指的是「神秘组织」BKT。
</p>
-<encrypted hint="和上次密码一样" hash="5ce53fdbcc6a1f7b63d9e104e9073ae213daac41ea86f4ec4462584322c51afe" encont="VWg32D4Z6ihx44ejMJbqKWpuwmesIGxn9qrZisbaoqYe94XdSz+hWGBWaCAd0aRkhaYaCiERTa60LTB80D9A67sGPE1EsJQYG0DR4hGbFfxNzbBqX2HL9RDFcGfRII/kqVHuc4knbdRRMILh09XOP6k8o/lMkY0jX8leU+606gggO2Mc1H1DXu+dTmdUfQg6MlZ/IDqslayWzE5MRMmHqSBLQmYUXidQtrTeAxMQJ9VNYk2vJxVdWwa/PcPC4cGjO3KlM7WeQ/m/Yl7S03zecwccUEe9IEMx6NMqtOXJ/j0W3mC4kHZWhVyQX+gwPnUYk9nhyqSiUQjhyxsLRg/g2DwaUaAt0da0uhIvs4S1CMpd7a+TlZKyNcj+5FOLBWP7zHjLbsLc/bJytqIHXcwfyfHloKQIkGH/N0J+01XTAQA4E7ZGOr/u4oS0SjqGQs8qPp+9iijmCk4hdus5vsNi8ZVvysEx7qBmMlUbRSWUQBzykBz+aYuEGZAuw4tk2hyf8ZjRfW+rzLZB4ttPmePb97X3EGOs70fRVysys3N/X+OaLX4qMoArH5XbszaUzfu5xZ3hABGNRsoxN6as3WMo5OY4N67NpfjmyudDkP7lkqtj4VTaQWtrbQL/51AhUvs5sdEcOWlmHA5EBrU+pnn+QbSKIniZo0q/tIrb9ioXyxy9Gvea0czS6yrB+BkY2iXOTbv3SY0X0Smvh5i2SFUHPaDwDm1UqzTXGYkzzmXaKGsb+gHBhNA1mOmCrOxGb78i1iZWIJXqDUg2jMfDCIJ4YKwPqLglAENpCaAZ7Ldb2doGIX0buSPYzYaFHkxzG7nrNwTHF7681sUjtSpfRAG49RboeAHJpjbVmlhAW/GtvKmyak5dYy4eHxFj+8S6c8KMpguxmM1pvnQaKJPk8S9rm5eNRvmv+Fel30Ee7sF8c/RpujXKm6jFQyIdNXj6j3G7xmOM4BolhFolwGrr3TVElCLWh8vB6XUhGj6PJhyey0rquILQEO8sQzkFVzX/gS/I7Mn0OZwTZOogE0EB3+CRkE43q6+xqbYuQv+sZDp09ADZuf/8nm6tAvcueOFEfU5Dk0fH1inYqa4ydErhqnXOBfcnqCUhN885VMx5q7sSDkAQ7zPrENnVz3O/mI5Hc92ZKDNQBBTNZ7znY8/LQSHytOlRNzO2CplsiexX9hjUZvapAhLAwxyqUnJbO9Fykvxac1ypcRJP2Sr9fYVKy9dEFNAQK7Og1CJ5iDoPz4rh/AUZ7RO16lnqyfLo0GuIJUvJIo+oCOl8uF/PLmeyc3NK15NRjg1JEpjR6ZXgdBtTiWTRAowshOhQzL+S0ydsTTr/WH1x0VJr3fbd3o6Wv/RmR6+pvoUZN+n1t9bRu87qHNzeuZggCeo1+jRp6RVEQNATAp7JTidMSYSdNbcgCcLVXOxQheyDEa7/sKobbX26JCLN+W4l7PSBkflJEhV9R0DvTeLIu9XcspoXf7fb6zfk8kJ7nLOsNrJ3MpnUD40FpBs6RoeLoinVeva+0F1+f4dkkx+cnmA3UUH+NOhPr5fphZfSEW9QAaK4F21qEWeqQf5nrR5rqIBmyJbU3TXrZkWe+HYv3XQNL6Mz8/EnuYdU33w/zY6HG0Zi91OGmbEzYN6pfEjfPv9cm2VMUfJ5voIHOKx6FHlgJ3KwvBYabuF4/4oGb8uJUOjfrPpe26VovV+8e10XeMxFxAUHEQ1FWW/PEJ3Lkd57JTyb8A0IW9bY+9DDawZLpq3hVPsDz4rG7kA+VdRcDfM0Qun0Ez+/L9/3+eMrA6q1l9Y3+lMhIGTvK7gcbu4N3Gsskiood/VMgSlR07TB3etVW3vOnqfw/503IZ82EXqwbdV44nmmyNR7MXFrxHIac3Dc2YgvlKed/Ok7pKi8ffM8IRRwJXQZmhEwmWtdFpc2PdMdMlfVzQ6rD6OsJ9cbixXmTbpEBT5rlhuxSSjuzqUDhctAwdJ3LRzszCyz0y1+TKz3eciJJd0djwSOhgJV6Z5g8dN5Ie32KoA+UuPiD59odwflZ8fEI61GEpk+HsAKnTlrbnRfdN5qyDBWiRL5xsKPARy54T1phC3ExGXRVVcm/rhBD8tuK3EAWoMOCQTxvTyXEzR1b1wXu8fM5QJ4fRqm+SBYYdfjLFHkWJORJlViBKtzUZckN66JEkeieuIBOhgB9BG5IYrWau2ITZdVejbHnZRODgeUb/EpXNz0bTcyvbhhSOTkU0memealuCIZDxlQKcxajB70aLkaO9xZqwN+Yr/1Uus9Y847gKG4AnOoQZk+2jNKfYqZehaM+C9nSuxwzXFhE3BZckneshvLCasXtJTYdBWnLpdMYQdiJxlD5ajMbFstCMRiPQjgY5ZESJpWx+IA9NNKqtmRslOzDBnIYIpXCJJd/N8wUrpTnh/mNLBNqeDl7Kv/jh0MS4J6L8F6bo66GPSolQqaFHQmT1Lcno9uynGsaB5NR0QYOT3id7jAHxWDkNv8J0xvd0jQsLnyiuAW6zXlUhkLn2xk0ZxUSEDyJtYB0mgq+LNg/xCmToR1b2lHZmsiQW9jhSI5tInetmWMNFF3L8lyHUFn1hm+TVOnQ3ioeM5Ecw8JqZGFCWuBWmu850nt88lE91D3ials+6mlRGkcCf6WYXYfwWcdmmkbBBK6r4XVM9usR1gVmnnIPfse1nJ36n4PH8cy28n37PzME6mgQ+FYKh3rTAL/XGJd6EX19IZuvslw6VSEC4e8TyiPUFvYK+T97PyArzKUwGSD7+2yuWEDrg9Gft2bbAsS38fC4LlZXLLqLV4hmqE9Rml5qBl/PUlvXne9Uen583yB+DyivOFchhOsAngC8P2k3oYgTCFSzA+tZVWPOr2wdtnQUkOodGmGEduor2TX8dq+NXax+IDFdgqljzZ5b/YEfVwslcazG/dDqZbDojaQ5s/IOvZSghK6U27AAcQnaeXdgM8eB1v+avzPfZemeXMwrXPIadU0nOeWhD3kVZteKToL8NndrhliGoIyq3E5NVqQqsc+NcSeuIt4bBP3+P2JmzZt6iM+Jl5YhIg8FoPl+n+VvHuaByknAQabrDgraWKR5fWD7nQIB5qjqprrGmYYuOR9ThVIdly7Pc+cuqwpUepKntaG2ahmuLzeKWoUuCPaOOMwNYfq35gy4UhOeZwzmF3bxxHfOgsaZ8iF2vYm1/Uvmg2XQPL20jhakgEuW86hcN8DRha0cyl/g7xxQ42HNxc1nu5BL9BmpIoPtEGzpkhtlbqM6hhRsHc/Ic5dFo/9WpPG5sjx8K1sZRObV0wrNXR56o5typyjO6++I9zgwQ7fSjtxOCC6CCsKg3bQWHAqA7CkGn831VG2oWlttgI8Hf6dSii8vqgYx08Lw1tAHO2gwJb2ZUVxq++ex0Zy34wZ/FvSbAc5sJUEMKPovkNJL+0F9UtwvCT9A6Z3dkh5HHFWj7dzUlCjoYarnZxH1f9YjPZeXnKPkGsz2WOKVSWgJJdPaJaJpNyFKetD+dS+C309dDVOTJEs5msfbk+TokpEZHk5KeLjr6hOB+xUUGju1KWanndhDdiM47nx3HjbbvTl5HefkdgVIhjNRooOKhv1Gr8XIm3lvXEIkupqlC/CwXSsfJT2f4SqAZLS0O1mXr7Z5wKBQOA3Pg82HDU5//jTyVchJHCvVhMlIYdkeHnETxC226ouCQeNeseKKwahqIGBQcRKMW5QOqqtdmk=" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
+<encrypted hint="和上次密码一样" hash="5ce53fdbcc6a1f7b63d9e104e9073ae213daac41ea86f4ec4462584322c51afe" encont="wxRvK+JFVpn1d9VmR2aNEX+1KwahSIhD/fbRMyY94My/DABlyIAL68ID53qw9l+xwsI5fMSYktv0P7hmnl3kmm3yutCHGz2GpGnlE5BKggn6h2Vy8IPVndTjtIz71cQMXu8Su3dXxRORARFpOFh3wGxKdO+HT3eCSpPB8XtuVMfJWlKatuD1Qq8RbGYP3lwolETv66i1SFXoHtgnceq2nWig7PAt2HacrBuzCIq2y3r0CprhZP00/0pchStWzArmvRwUSaGiLi+hvXp4fdJWLWq5mUA9TNpf5FpiHaxrlIndoIaV/e0J3t9UuyzAXaLBu+uOgSfx/foc+pnI7VA4HAgIKvd5hMW3O/Is/BFsiyhB6gtmqrpMFawTiK+1PmnAGdOKpdYb3zmIuHv0/D/nU36A1B/+pd6LpIYd6Fin5tt3cQbvQlh1Q45n+R2x6GmdMvE4+eW25w6m30aRRfb0FMsAeYgvtduQ6aqq3y4PaeWp3Nsg65asrOMR476U53Y6MNdzuYNkKluaHUsQxjZQ4zeMHAmQvt4AZROBxLO0Tx5CLO4r9UwvGS5ifJRxEfg4YZqFjttJrxGJdCDVVxg+jXMbvoqHbzwM4xXpmGuzRj1KKvw0DEGBJa0CK5/rk+hVEq2GFmkT23j3myVuboTEqsirsfF/GJ+5iGZEJ/Cf4MNEcd68LJMY6Fd/42ux/W8XGe85g/F/59Hj1sLi2TuDQzUHUqtMb6QpwxKXVByMTRcYLsm9w29louBpPyZzVsS+4Jb4utGEruilTs+ddQACzOBgxYh5VgW8/+puOzpb8FQ0TVJBx9JvQ2Lnvb2fkzmJd+JQQysC6q7Qo/aU6YYKDdmQUq35uxPyHQfAqN0K+R9PIjdwg9fdHnmskdjPHuWjCG7Gz2BUoDFgpPXu1po+WcPIiTeLTpvSAxr+P/xhCuJ91jh+T5sxSe0KV6Bk9ruM8INaGHgNpaUEoigTk5ZKtgtgH+8WUeXJXyRcSXKX2WRhKDqgnfBjaS9CClKbAjhRjc2hmsstp+L1fzyy4WuEWMDb8Ltgf6zKIg3dZDLmil0ar6McIXsZPPPUbNCLFEqsD4EZexWx4hv031wQqN0lmfGw8XI9v8FymGpqyH6SkK3b4HCkFoca+peKbKJnFcqvXib6O+WIW1QJolOASnOJ3jyKLNnOoquewNs/u/Fyh35ZChBrwOJbQeDbxPEzbtS1uWPOeSqhniSxV+cULdavaiEIl1RO5q/xjgYNchn0pmYcCVVJTeNVKaDx6FYCxUo3pP+itSSQTCnJs+YWWB5KnwoRJWcq+cgD10TnSH/e+d44qVdqqCyng6UIeHtQhR95poo8o+9wgS4PVsMEDeIbjNrPw4RLOGGtW3SZN7tnxsK06vfK+6Rtc9DbpfPMqzRg2dzFbC+IRb+Tzi0xq3SXTKYpdyfTYcea2v4DQXORRgM1D3yKYWh+TfvaL5EuZwxYHLSufyVYsK9FWXVjOt/1DHb5iVRK0aubf6d3rWZ1ZCXO8AkMqFVaytnEg+gRychGriU4KBr7gS1eK8bHR4qUkciYff3dhmqrFkmpIJZt3KdRUnHi7B0njNtvk8aPcBWTABfMBAUEkfkx9WfE8WNMhxo+Bi22oU/1UGCYYS0didAuLOcL/pK5UGnRdpgi3b5obnjn/KO/hSVqTNsEHW0upTwI4cYF8V9j9USBQY5RWd6sG+DGPzK+Qz4IslM/PtrWu9PIHazoLUhHDgX0AX/J8Y8BTHzk+LDKwj3//3VNl4fytsPDnK/0SborL0v07grXtSKsZIUFGctfkDKV0BCIeCDBS6jxHLvl7RbHuj6sr/2tdHLcSdzn3DG0eXcJI96xLJjwXyzSHvuakKsGRO2yITYzUbzQIqxHa9zW1OoJxKM10NHn1ciOD1P8WNKIk0OfUIGjLCWUo6OBP/7q9oS0ocaJ0WXnMdnTYJazbacXFrot/23fh6xWovDb/c4bi+Tlmz6cZewT8IUlRkT3VX8jGz8YKiH5dSEtu51as8CJY3q2c+biu0rypPd6uxw+QjO3LVxAzhPA2py2FFD2RkBJSVVtsrnALab7aRdJdwAPox7470TQfnWh0u68MvwhwypLUQQxPN+5f3qD/gbuj5Ht+/c9W3TfYEvpqj5W1bOYRlmID/SlY2VC8Gfl3b0xpuVamiAoQm3LGh0aJ5g7kL6+CxrmC1x7iuykYkx0VjllTUVdy/QckhttcB6NbcuMSwEQ6VcUlgOWkKNLw6jvYns9H1u91e/8tqNS7Xz/YwMG18X8cIFju4vuPDauttzapvKxKw9ydWejujaVooXmoRAil8oVvubj7QgZVF+VCA7R8lpOzjbHrgqQeVZFDjamtvv7SkBwF6yX5jJOgsrFWhSKaKV3B2VN6R/OQqR7yJe6KRiJKfJUffhqmpG4t6xWviNLq85hR/H8WkfIUK2/adHm2Lr9HVSg9GgKNoEgKmFH9DpFoXKWW52hnRdrlyYYcMo5rS46+V3lflHu0VTj1O666PnfME2jCUzuaJe50tyQj3NY1WR7sXp5ezmpdNrpXVre7fi5A4n50H8ym9t7MSJCyu0vv3LhJF5PsHdqD/Ks7dtj0pAS0gRAF825E0vicwMDH1YFj3INwzNYl5ISNaWL3MvQozy0fUoo6OiL96PP0tUTk01mut39ZJNeu+87jbJSi7N7dZydQDVPekolruwsjJhi8Gy4UD18w52jZ1DJwKoNlU3bnPHLddw1F08NITqUbUeh17xpjc5nQJCKHRDuTavrjhsRIJvlBylaKYEM5sn/pbIpM0A019IbruaqMeadQBRO1b+xKhnrPAR6B2ZAIaD9ukyYNCbm99UZBjaTNLsPYOTNXFGF0KWgDxLgI6Zu/LkHthVBnHXvRqNM1iINyNuqlbHXrdaondYIOUc980TleXe/TThNzYPsRVqF2EMBF6o0lVBS6en3cET+ldsNQMKDhsaajiAbCcW17zcdlG8e7ZmIM9hqUzKSk1Hlb+X1J3Tw4F3cnIFw8H+OKG4cGEVLdizNeTngdpijS88D4phA7nnNoz85c/5OPTpl7lpZAekVOxyGFmuMdBIWg0lzseZdq2ZHLazVExpwJSNtX0r1iA8rfNjmQP5Vb294D6MbCF0nwJHeviNeI1TJ3I0H6gwSKsU+/s7RJtEy9WbkHhHdKhHuWN1HgthHWZHp3aNxpWlVfk1m3HPl6pXIMfVkC2mPBisbslrKVgHhxAA4HGF6XPky+pW5CdyB8UqvpjkJOEPz07SYLeMPKC5Y0kWUXIhq/iag+feo0pDBmDlDVMZYgXpMGae74PpZwo44Ly5x6T06haFdRQmvxPfK7jgsAQdD6l8ovrZtw9IOQn50q0YwnPbRo67x3Mf3o6GXFwqIzf5qbzNnF7Ix9xV7MgN0DKkkWJLEK4llNSjS3BjpOPoTE7OMGto22yWzKV0lBzFr1DjpbPF8FZp0pjVjgcBmWnZBhLOeGHF+IXtQzYAejKDWbj+V7KhnO4gZtb0Or+T6QHTgg3szbvrr7o+IUbS1pByeh5+AXLTcPfDL9LXcndRDQ9n045bH0V29Rl18jbfBNIUxMgdoEh9uKVCAalxTRm7t08bCnuXTfc+kPaY0LMp2gihw8tFrSIIFz13lM/R/hehU5WHlQh+qUPKWKNU+rTklMTkogCkdz03tj+odytqKiPYffyzgwpVF9s5uXeHRtZq54cJI6o8=" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<h2 id="tocanch20" class="tvis">婊一婊辣鸡专科学校</h2>
<p>
@@ -400,7 +370,7 @@ to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.
这大概是入学以来我第一次后悔来到这里。
</p>
<h2 id="tocanch22" class="tvis">神秘内容</h2>
-<encrypted hint="b******phi" hash="5be136371f1b6925c4ac672a7f31c9c327a3bededdc935d785c7004478053a47" encont="Lvt/LfQA64K8Q7m1EBseDcAlE8yDV3ctlZIBpJQ5achEZz9iQiKDf9gJTGOkAiQ2n82nF8AnyKg8eMVOQbCoFwiq6fsNt6kD32I7c+EMwcvbFhLvfN6ZyrOAzTzbCxAMtKtdVkiPQII9yvmANyer9MIe3MNSB5NTtQFMfzfhaProdeKUFQMRvcv4EbN43s9ig2TGkQ/ilmVp/NlxEYFvcWh/QXdczCnOzW6RhTvtMuyQFaSarfzNOGKxKpereTMVfyXGnuy5Lqb2YORhQoAe+2xLMZ66u9It1Tj+CPAhviN48oJGZzBjA7RegitAZ310LQp0oGtHZt+4Uj4ndsL8mL3kURqpzEtBlyVPHXZYf8qwmB232QZFsVZ4Wk2dcDKXeRfuJFfXbE+2EJDsiFng5ItXsg2cAQgrV3a294OV0+bd5QJx8nLSl0kWpk9SdlI3rf6heups6+IlGsCjfImcpdd6LzAHu7syoz3F0CeHD3bELh8jzupCa3MnpGMs/JikdOss+ryMJiScdFEU2i4z7yfHq26ZhpAkfya1+CMBZgvspESYg6LMXEzjCoEbx/ZwihMh0gUd9xGpr+HMN3mfgtfM2LM6NHdN/CDqvR0AX3ktAPKe6T57N46Z9GxFQsrng76kQaH/ygeawmCP8fQ18VEXhnmtOhLLcgrCbVhdt9N72MzBgqeEeGIEmZTcNu6vVGmrcdTHGh8SqWJGOs16TADbJrFPRhyVy13O7MWHJFa5ECmpDEoOSq2AzL5DlQk6oiItH9oUNWiBeALCg4gHqJrWx4Pi4vkVSZgBNgZNHWy/0soQ552pshofyvV1Esr+4g6JWQdQDyRGKgeK0I8EHcOhWSknGQ9fiTbEWhFzLMkWdTc30ZwxidOHiH2+koefTTv1dUysxLLVnf6ODzFd" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
+<encrypted hint="b******phi" hash="5be136371f1b6925c4ac672a7f31c9c327a3bededdc935d785c7004478053a47" encont="X2LfQVVOwrIk0N8tzSzj3tz5+HFF0n/Z/kdDllYhJpcK9MeOE3/X0EqOkbsRhIWPI4FM8dsp49eU6Gxh4iZoTAnXh89ziCVpBj/fC9Ip+BgEWNpKIZRH2ZUS7JyroKe7rjLF6ylB3R/WiONI4erdlxlw7hli15jd4hFmGhLm5xs9ql7a16MXzAiRKYlMNi/ecCoI/k6c6/zont2igKo4VNwhwIvQCwq7E+W1P72vy+RS1YyAQRlwcdj3qw0huEv2i/v2pZD0cf2F9+hvCBobcmH+0N9bDZDANedgy0NIlcW3GVIOFCWRqiJZePPscycl/AlsuXLerTez49xEfPxCysOwY+4FDFPNiSraS48pzAro140fD3wyDXlb/ZeXdMZ8uNm3O/+0iJAE6VhrrXxGlztPFSznYgeLgbilQiVjWp0wy9c98VVcmqCEUMlTBnCElh83P0IMcJY1tv3ATgA7iglEC+WE1Ce3HQiBERWriyOc9P+615wHfOeJiGWpSu3jqMAalv3X1QCT9ke9yVWf+OOJ8bSCecrjpqzACr9v5LETRfxyDKEh3+uhnH1/UdVbBiJl0Jj+c8RPf8ll7z6tkAB0su2ZMbmdYTmq9u0rgAnuIHvstNICDaV31ZEr3jlm3xyHCi6Ixuf3C376vnkapZaUe7rMk06SCpk4+K6WR8fipdfSrSdVRTWM3ZJG0dJhg8Y17EQYq1Af+qp7MDLpnYyv+xpARCxGQ2Xa4NRHg3b3m0HhWds/w1Ge1NiNUGT/1Te9VyQnELvdimA4jLlbFehnTyz9BUQYB5WmPh/QJ9n54sXx7h4Jkh277R9rhpc9OPbb7tuXSO5FlGDYhS8hlB4YlF/kfEVBngjy3T9Q5eIcmYNvq+7EdxjTiq6LDwu5qF2TbrZ88vp813p2KBxP" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<h2 id="tocanch23" class="tvis">「技能树」</h2>
<p>
diff --git a/blog/post/2017-02-13.html b/blog/post/2017-02-13.html
index a8904a1..8961059 100644
--- a/blog/post/2017-02-13.html
+++ b/blog/post/2017-02-13.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"[多大图警告]ls /dev")</title>
+<meta name="description" content="«[多大图警告]ls /dev» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -81,7 +51,7 @@ loadTheme();
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">Overview</a></li><li><a class="toctarg" href="#tocanch1">Actively used devices</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">/dev/computer/srv0 -&gt; ../comp7</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch3">Gallery</a></li></ul></li><li><a class="toctarg" href="#tocanch4">/dev/computer/tio0 -&gt; ../comp6</a></li><li><a class="toctarg" href="#tocanch5"><s>/dev/mobi/mob0 -&gt; </s>../mobi7</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">UPD 2017-03-12</a></li></ul></li><li><a class="toctarg" href="#tocanch7">/dev/mobi/mob0 -&gt; ../mobi8</a></li><li><a class="toctarg" href="#tocanch8">/dev/mobi/ipod0 -&gt; ../ipod0</a></li><li><a class="toctarg" href="#tocanch9">/dev/arm/rpi0 -&gt; ../rpi0</a></li><li><a class="toctarg" href="#tocanch10">/dev/printer/lp0 -&gt; ../lp0</a></li><li><a class="toctarg" href="#tocanch11">/dev/input/kb0 -&gt; ../uhid0</a></li></ul></li><li><a class="toctarg" href="#tocanch12">Deprecated/Inactive devices</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch13">/dev/comp0../dev/comp4</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch14">/dev/comp0</a></li><li><a class="toctarg" href="#tocanch15">/dev/comp1</a></li><li><a class="toctarg" href="#tocanch16">/dev/comp2</a></li><li><a class="toctarg" href="#tocanch17">/dev/comp3</a></li><li><a class="toctarg" href="#tocanch18">/dev/comp4</a></li><li><a class="toctarg" href="#tocanch19">/dev/comp5</a></li></ul></li><li><a class="toctarg" href="#tocanch20">/dev/mobi0../dev/mobi6</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch21">/dev/mobi0</a></li><li><a class="toctarg" href="#tocanch22">/dev/mobi1</a></li><li><a class="toctarg" href="#tocanch23">/dev/mobi2</a></li><li><a class="toctarg" href="#tocanch24">/dev/mobi3</a></li><li><a class="toctarg" href="#tocanch25">/dev/mobi4</a></li><li><a class="toctarg" href="#tocanch26">/dev/mobi5</a></li><li><a class="toctarg" href="#tocanch27">/dev/mobi6</a></li></ul></li></ul></li></ul>
+ <li><a class="toctarg" href="#tocanch0">Overview</a></li><li><a class="toctarg" href="#tocanch1">Actively used devices</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">/dev/computer/srv0 -&gt; ../comp7</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch3">Gallery</a></li></ul></li><li><a class="toctarg" href="#tocanch4">/dev/computer/tio0 -&gt; ../comp6</a></li><li><a class="toctarg" href="#tocanch5">/dev/mobi/mob0 -&gt; ../mobi7</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">UPD 2017-03-12</a></li></ul></li><li><a class="toctarg" href="#tocanch7">/dev/mobi/mob0 -&gt; ../mobi8</a></li><li><a class="toctarg" href="#tocanch8">/dev/mobi/ipod0 -&gt; ../ipod0</a></li><li><a class="toctarg" href="#tocanch9">/dev/arm/rpi0 -&gt; ../rpi0</a></li><li><a class="toctarg" href="#tocanch10">/dev/printer/lp0 -&gt; ../lp0</a></li><li><a class="toctarg" href="#tocanch11">/dev/input/kb0 -&gt; ../uhid0</a></li></ul></li><li><a class="toctarg" href="#tocanch12">Deprecated/Inactive devices</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch13">/dev/comp0../dev/comp4</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch14">/dev/comp0</a></li><li><a class="toctarg" href="#tocanch15">/dev/comp1</a></li><li><a class="toctarg" href="#tocanch16">/dev/comp2</a></li><li><a class="toctarg" href="#tocanch17">/dev/comp3</a></li><li><a class="toctarg" href="#tocanch18">/dev/comp4</a></li><li><a class="toctarg" href="#tocanch19">/dev/comp5</a></li></ul></li><li><a class="toctarg" href="#tocanch20">/dev/mobi0../dev/mobi6</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch21">/dev/mobi0</a></li><li><a class="toctarg" href="#tocanch22">/dev/mobi1</a></li><li><a class="toctarg" href="#tocanch23">/dev/mobi2</a></li><li><a class="toctarg" href="#tocanch24">/dev/mobi3</a></li><li><a class="toctarg" href="#tocanch25">/dev/mobi4</a></li><li><a class="toctarg" href="#tocanch26">/dev/mobi5</a></li><li><a class="toctarg" href="#tocanch27">/dev/mobi6</a></li></ul></li></ul></li></ul>
</li>
<li style="margin-left:-0.5em"><a id="prevp" href="2017-01-18.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2017-04-11.html">Next post</a></li>
diff --git a/blog/post/2017-04-11.html b/blog/post/2017-04-11.html
index 9d6fc84..9774983 100644
--- a/blog/post/2017-04-11.html
+++ b/blog/post/2017-04-11.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"SBS 2.0 is now the default blog browser")</title>
+<meta name="description" content="«SBS 2.0 is now the default blog browser» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-05-08.html b/blog/post/2017-05-08.html
index 8931dc7..e85bc79 100644
--- a/blog/post/2017-05-08.html
+++ b/blog/post/2017-05-08.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"2017省赛流水帐")</title>
+<meta name="description" content="«2017省赛流水帐» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-06-09.html b/blog/post/2017-06-09.html
index a20e560..50312b5 100644
--- a/blog/post/2017-06-09.html
+++ b/blog/post/2017-06-09.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Fuck Windows et cetera")</title>
+<meta name="description" content="«Fuck Windows et cetera» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-06-29.html b/blog/post/2017-06-29.html
index 3f47e7e..01f0311 100644
--- a/blog/post/2017-06-29.html
+++ b/blog/post/2017-06-29.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Trash dump for the fourth semester")</title>
+<meta name="description" content="«Trash dump for the fourth semester» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,13 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -81,7 +53,7 @@ loadTheme();
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">课程相关</a></li><li><a class="toctarg" href="#tocanch1">ACM相关</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">校赛</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch3">榜单</a></li><li><a class="toctarg" href="#tocanch4">「<s>Net&nbsp;Celebrity</s>」??</a></li></ul></li><li><a class="toctarg" href="#tocanch5">省赛</a></li><li><a class="toctarg" href="#tocanch6">陕西邀请赛</a></li><li><a class="toctarg" href="#tocanch7">实验室没收与暑期集训</a></li><li><a class="toctarg" href="#tocanch8">真的成为运维了?</a></li><li><a class="toctarg" href="#tocanch9">以后我们还存在吗? &amp; 再谈SDU对ACM的态度</a></li><li><a class="toctarg" href="#tocanch10">170722补</a></li><li><a class="toctarg" href="#tocanch11">Yet Another addition...</a></li></ul></li><li><a class="toctarg" href="#tocanch12">各种坑</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch13">QMP</a></li><li><a class="toctarg" href="#tocanch14">SMELT</a></li><li><a class="toctarg" href="#tocanch15">chrisoft.org</a></li><li><a class="toctarg" href="#tocanch16">其他</a></li></ul></li><li><a class="toctarg" href="#tocanch17">弃用QQ与Reddit中毒 &amp; SNS</a></li><li><a class="toctarg" href="#tocanch18">Gaming? WTF?</a></li><li><a class="toctarg" href="#tocanch19">「Freedom」</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch20">2017-08-23补记</a></li><li><a class="toctarg" href="#tocanch21">Who controls who</a></li><li><a class="toctarg" href="#tocanch22">Myths about the GPL</a></li><li><a class="toctarg" href="#tocanch23">Attempted assassination by Open Source</a></li><li><a class="toctarg" href="#tocanch24">Closing this part</a></li></ul></li><li><a class="toctarg" href="#tocanch25">接着婊辣鸡专科学校</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch26">山东挖地大学</a></li><li><a class="toctarg" href="#tocanch27">山东inf个校区大学</a></li><li><a class="toctarg" href="#tocanch28">山东草(4)房子大学</a></li><li><a class="toctarg" href="#tocanch29">山东不准坐高铁大学</a></li><li><a class="toctarg" href="#tocanch30">Closing...</a></li></ul></li><li><a class="toctarg" href="#tocanch31">Other random stuff</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch32">贴吧 &amp; Ballance</a></li><li><a class="toctarg" href="#tocanch33">「实名制」</a></li><li><a class="toctarg" href="#tocanch34">"The Hatred"</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch35">the Apple Hatred</a></li><li><a class="toctarg" href="#tocanch36">the JavaScript Hatred</a></li><li><a class="toctarg" href="#tocanch37">the Microsoft Hatred</a></li><li><a class="toctarg" href="#tocanch38">the &lt;insert Chinese mobile phone brand here&gt; Hatred</a></li></ul></li></ul></li><li><a class="toctarg" href="#tocanch39">生活垃圾</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch40">宿舍?寝室?</a></li><li><a class="toctarg" href="#tocanch41">Side B</a></li></ul></li></ul>
+ <li><a class="toctarg" href="#tocanch0">课程相关</a></li><li><a class="toctarg" href="#tocanch1">ACM相关</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">校赛</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch3">榜单</a></li><li><a class="toctarg" href="#tocanch4">「Net&nbsp;Celebrity」??</a></li></ul></li><li><a class="toctarg" href="#tocanch5">省赛</a></li><li><a class="toctarg" href="#tocanch6">陕西邀请赛</a></li><li><a class="toctarg" href="#tocanch7">实验室没收与暑期集训</a></li><li><a class="toctarg" href="#tocanch8">真的成为运维了?</a></li><li><a class="toctarg" href="#tocanch9">以后我们还存在吗? &amp; 再谈SDU对ACM的态度</a></li><li><a class="toctarg" href="#tocanch10">170722补</a></li><li><a class="toctarg" href="#tocanch11">Yet Another addition...</a></li></ul></li><li><a class="toctarg" href="#tocanch12">各种坑</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch13">QMP</a></li><li><a class="toctarg" href="#tocanch14">SMELT</a></li><li><a class="toctarg" href="#tocanch15">chrisoft.org</a></li><li><a class="toctarg" href="#tocanch16">其他</a></li></ul></li><li><a class="toctarg" href="#tocanch17">弃用QQ与Reddit中毒 &amp; SNS</a></li><li><a class="toctarg" href="#tocanch18">Gaming? WTF?</a></li><li><a class="toctarg" href="#tocanch19">「Freedom」</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch20">2017-08-23补记</a></li><li><a class="toctarg" href="#tocanch21">Who controls who</a></li><li><a class="toctarg" href="#tocanch22">Myths about the GPL</a></li><li><a class="toctarg" href="#tocanch23">Attempted assassination by Open Source</a></li><li><a class="toctarg" href="#tocanch24">Closing this part</a></li></ul></li><li><a class="toctarg" href="#tocanch25">接着婊辣鸡专科学校</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch26">山东挖地大学</a></li><li><a class="toctarg" href="#tocanch27">山东inf个校区大学</a></li><li><a class="toctarg" href="#tocanch28">山东草(4)房子大学</a></li><li><a class="toctarg" href="#tocanch29">山东不准坐高铁大学</a></li><li><a class="toctarg" href="#tocanch30">Closing...</a></li></ul></li><li><a class="toctarg" href="#tocanch31">Other random stuff</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch32">贴吧 &amp; Ballance</a></li><li><a class="toctarg" href="#tocanch33">「实名制」</a></li><li><a class="toctarg" href="#tocanch34">"The Hatred"</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch35">the Apple Hatred</a></li><li><a class="toctarg" href="#tocanch36">the JavaScript Hatred</a></li><li><a class="toctarg" href="#tocanch37">the Microsoft Hatred</a></li><li><a class="toctarg" href="#tocanch38">the <insert chinese="" mobile="" phone="" brand="" here=""> Hatred</insert></a></li></ul></li></ul></li><li><a class="toctarg" href="#tocanch39">生活垃圾</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch40">宿舍?寝室?</a></li><li><a class="toctarg" href="#tocanch41">Side B</a></li></ul></li></ul>
</li>
<li style="margin-left:-0.5em"><a id="prevp" href="2017-06-09.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2017-11-25.html">Next post</a></li>
@@ -92,9 +64,7 @@ loadTheme();
<div id="datetags" class="TText" style="margin-bottom:1em;">2017-06-29<br>#garbage #daily-life</div>
<hr><div id="article" class="TText">
<article>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<h2 id="tocanch0" class="tvis">课程相关</h2>
<s>于是这学期上了些什么课来着……</s>
<ul>
@@ -457,7 +427,7 @@ article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
<p>
这里是一些当时我混迹Ballance吧时的黑历史。
</p>
-<encrypted hint="Type in the phrase &quot;Yes, do as I say!&quot; to read this section." hash="9bcd7c3417087e3b22a5105f91923551d465add76a4b8b043cdd9ad030efff9b" encont="g6ZQrTW5Xt1hqCsn+ypUCvy1Y1u7IfItqqx/lZlRg18DQy5Vj0w35a4RPMBdorz55mhtI0Sr3/SmZnhZNVaLwMYtElVnuwrQhp0ihtTKSQOVhvu4oJNPt0koiztD42nSdVkXHOwQfwYyy1EbDLLOwfF0E+C6u9ONiBtm3BhmSvIpCA/fVqcACt7WdvR1O4MeL/W5lIfirYwRbiN0yKXJmtCTcG3ecr8PlsbJUg6Ei7oYDphG8WkGljOnDz17aJyRz+/cn3BzT+Ut9PWu1SAAU6GtEiMjbKYIRg8R9B0j1YqzLIuy1fXZKMymy5xGBZSccEGyCbUlMQ3xzC6x77wfvXOykr6DnqgrBTeTvk3Gjhdn7St2C0ZB4lz1Z05qPJ6M7L/vcXkob8Emyt1quENRMIvFrCEpQqgdLWUfdZFuK/uSGT+8j2MnaZUIXtDhixY/EstYf/OgE38d6OVy6ZXCt5QHbGSyS2gsrTCMMZc7VXigF7CwZx60vIaLodmMZaSN2fxfdZVsSyUGVdlHuVOkLP7/UtLHR38Mj7zv6iabvHPmx8D9FDgimroZoUEi5FIyXsleLPfYIw8UOAId36b1YTdkRFwdcyNpogU1fhmCoNpsfVWu2koWI4OADoBoCyJDg4ejyeyxiy7q8rn6sJZmrJ3skHvPud7VmnQtmjheQvkE4SAn5y2vSf4qKPjR/g4yk1mfUC2M7o7S49Gcu/8T9keyld/fmcOdoMeqew+PmozuLuENdaIVi1DkI3QhQnd+qZhNSzomuYx7BXLYtSxyysjNnZapwo9tCUmMF2VSiDZWpSwnyoJYBGBcH5qxyitVnLvW2soomWpKyis1T8tynr6fmFzDIMHQNzwWMBCQ3f2L5xppEu5lumpgxo8MHfJOSJ2q6cjbKFFFcgEN3j1bbVuftIb+ac3y0WEGGOAvSuuh0rW8zPy4GZTFxmv+nYIkPk5I+SuMKQvCkrGI09wlXVxhwfOehiZMRdAJnAUCSwcATfzujdk2CbgVe1Bi0iQ78ktCupLd2Hln7lwpLrBItkQP9BoU77JFj7kzUBG6YhBJy5S7qYd00e5UI03z+0P4JbqiIcGx3J/8Q5pvgau95uFctdD5EpvL8NFYx1fH3u1PYSncxVyydEvYMH+SvoUOTG5rHQXa+KUwQqgYDi+a26yo87sEMtPpCZkTPkL+WjGg4CHOJ2SMu97orgfypsTkI6eyULATtjayLs/ORM/hUq1KOV393fP2DOdPtMlLflDZUmnT5IXzd8UtPSgfMm5AzzrhrGi4hmjJgvx2mrl38n8grw7PXgCefSPwkKsoV3VlnZvbFwDsEj+OImNvDYZxl/LKUagH17JNQX351ry6iXaFWScL0vvzI+8vlPqweGTmk9ekf+bydGA6oDfRA1tjuIgEgALoxR2Lwn09e4/yspfnNViEJAT79ELwgfwyP8XWAoy4EUdxq5OIcbbykWh1YezU+vbVfNiW4mh98A7XIiZPp7ntIDjfTy5T+UwyPMNbf863QF+keVkmCBTOZ9BlBHt+1+L6hui8sJVSMEfwy4zOvc0MT8aV0h22bxHVYrXZRQhtUnAB2euKDA32qJfGvolwJArpaClJo6BG5Tb0I+atKll7rm/mHoSbMwLou5yd0dJ4p70KumB3jqkE/9qoybSyv7Xt+vM2zsibcyaJvLeR4XjIzsoXqLW7rmkZTJBvQtPqT7MFZ+55th5BktK7ppWZJiw5Wchu0ScZ7sKHKSOdpnuV142tyeljzCZgzAk1Va89SQJlO+VqkVjUI7gO6GP1Xwz7uYcnL6bsY+TjSrRfA+mchGcp39ZcHmYcRtk+2b8nc1G4qivaLRemz6yFWNU9iOHjU3q8P+a/BrQeBepBGz5vSZVsP6G6zpYP6E/UYMf8xWjW6J3TS28VzpKO/UidUY48YmplLD6EMgIYOSX7yljr50YSap1WhfZg/OThO5KpitZHPkY1VPIva/Ws1UzYRnY3Nenp2Gw4G7c5QJzBiOhNaa6nC+63AzU2UsFtqXlSYfiywYj7eaAPEjd7vnkgzMwGCT8UAxlXxOz2gp4edPA4juQfenAj3Vt7wcw0gVXqc6UIkLtuof14zIPA3yxyJvECdeVR+yZZps9g2k/cSeomLIOpopeX/bO08a7Dwk8OriYHusH7D6+hE86jtKItEGEuxYV8DertIJWEIf6TWbGKkoo9TliID0mwN1TAY38PQPovBNktPZAp2cT9qRoq0Yd5sZUaG9lLzAb77mLebBOHAm8X9BzRsCXI2lCFsf7wdc0+DCqlZgJoYfN7uPjkK5vzqqIJG65ubdU35UIt6ZK2sQGkmpLQlQQkwqyE+Txn7IpBlDLlMhT80BNgDPCX4kutNQo8rsbtaaNBEp9mhOZu8UOkxSz4xc54+rEKwY2GGPdMqkq4MGAGhPdTBSZV/GwgzdkNNm/MIc895WyrkH0PKfwH2G3GOMkpNG52KgspkQJzOSPiJ+PGj2LPX6Y1hN0IcHCVrxERInYsghe15vcnugCpp5wVB8FwNiJ2YseQv6S0Z5cFxV5B3aOtpwQjbg7h3UDgpiSAlvW3HkCf+ApX7YiX1mRkbdKKIpVjg7B4ND3CNNiv2NfGZVgwUjKF7F1zp23xW0pvDp4qY83pt6U50tCBktYB3OkPWpOxBuIzQxfWJ1/9UxiHNnPzvcV5POLOxym47Xw2gkQP7IiiYb7QB4gJE1Kazf2K4ZgSCWYs5eTTJErpOaSpZ35UthVNqVzHaf5DM3OTc8xQqwDI4sOQErDQ+akMwa6AM12/0WOkJ2So0gFQxZkOCw/35i5mL5X0zTxaHJlT6MH6J8yf/37GaqebF38J9P1iUcxygtNZJSv394DNAomKKgi/WOmUa7gKRjMvdLEZHvFjgNgNj8qSD77AJgwhkoPq7DUzTtTT8x01YYbBj91yJ6jb2FkT+yBaWky4d1ZmJlTUSdN95xWbiyq9fvN08eJ1IrxvbFdJd3LUE9GYkVHehRfQfVJHLTyZQy5z+HGKHqO8Ac78rU3GfdYtOYOlpcsC1LMTo0DQ+QFXmtnHYquXw05DOu/2jeo8ceB3i+Xg7zSPnkuAoesFPE7mQlv8w/glkeUURakW7kC4qbeEz/CSxeFP6sRDDmFsGjYuIsYkBplR4bqp8FRvWw3oXuRLmaDBVFHwebfhtWZ7w4qOLu+VsMMulNv019nurMM3EmORrvB9K2NxbTQ9a1qp6GeoILW5xc3Z7aQcjIKmt/r9l1DEKv/d3e3ok4G11twtszwCvPxqOOewOXwMXH5KAdVylyzulUkaO+nsO1KPySCL56IbapcTfpvWwwWJim/Zj3c5nvwjuAwcMxLXBmsxm71IISF38smPU1NiT6IeNXScb903rDYgK7iaWTkszbYKoigH+MVR1RizN/Nt6FsxLsMZG3vOKn4dxy2dmTbzi8EH9DJOqhjocanVEBMs1X4mMRTD23wxFMS/Lz8Dx89mACOzunTJboP1JPmYinHKSYVFXsDia1Sb+7nr2I9nSMVuhO4E3EF/MA9oTV4k0qTAL1Uujf7jyEVYL2nOwCw1M0q9Wgp7TwSatfrLl/MEXx5+SPCfAjCZ4MCT7+3ZxZobMfOGj7x3lszLgdP+k7wmiYJUNVnlk2F49VllG3boXdGvtivPy6oODzGLXjnrDjxxFGiQnS4RWTh2byhwQomBVZaYt0NrVJPgglPFc0qNyC5UC+29QZUK7eFaoh2+gSSztS675vxvLTa/IMXlw1Nf63p0dees1xXkjJy2iD49hXoktM+LCq9eel++4q7iHV5Zo9j8IuVI7OSDzP0GvBwhtcMUDeMWVd206e2JZB1PLhKv5hqtwVA8zy7dAo8LB/MNJpihNiU5ctMJrIFnWjV9c0K+E7xLPqHAAqn2hQ8mvditmyeHK72TJyTP48p27XSqrhQENvT3MIiI+zkT/NhbotnOTPDxtpm+kq9I4qUAgJVQC4u6Rdi77ocVs6ahegv/d0upK0awBscDNf2lXFrmhZXIFEVRT8Zd6jjka9Y0xHQRAylNY5HqcSNpgHcx5dLTAV83BYFyPuEw5ExPwHM2xNaZaSTQEjFaYj3FbgAjQm8gOPlMbJRMQ0aXPq4Smtn/2Ygo/K2f2CIqPpB9aZaQsE1A+07TONftE0rRQJSz4NBSxEckc4w8oTuElqD7sxa25/W4TsGtrj/DOZEG6VmSq3+5YBC9k/m1zSmij384Zf9AIZ62dIpvQLQm35mZewqT8ACktLEib8ulpzwCu8aLtr310v26mLRhsgq8NF6+1hbY/UBIzsORA471bh0jfoTkwe04p46CeWYvnWUxqE9vF2CPF1a+lF5z+o4KQyH4ISgA3+fzkMWoyxxmGT3/kFfELpYPVlUvPkWTT46c0iS7pEJ6PMJhiaP7x5vc6Tc9gNkbcdfwtI4lGPkrNvjISE5dTuFaxLxpN7uvdPnUapvAs37pbMuDi/OFD3eoYov31Z7iGDG6ZC7V4HxSsm+rhMkZOY1oj3398NLXF0XXok9zueO9pxTU53eXuV7wX27uGwKX7Qrl4itAmZekZ8TDr/O9pkKWhBUa6tbZF4TLYFpG03eViH1xJxYcLAaczsGEjf2jHeDYpLBqTxGYbqiREmIJLv0zMMqXFcRHZ4E9rD6VpoGEkSF8BJnLYr780ZUnflI+N0jZ6aNyNl+VLn8kLWbxEemfOtX4cKLI2ib4TXQZA93jLW5n22bcyzZ4B/wQIlZRVAS+eiQ1q21Xk31CNMkE60PHAkraH02jcU1BkYsGjqqNOpNXsh8WNKi49Faew3RxhefNtIUj36/9p2t1n86+RMLttD+DpEHcZk5t7l8CchZGovV585LEpGlD2COK5WkgMur7WEk/E5T8EKrcdhOkLB6qWwpwCHJQ5gKuDX/oKYcsg5t8BrDK/jnGllMIGQ0JltRUD6CRkKvAh/J7735pX6qfRE1aaoCAIEr7mZ6fK6TBy/oF06mB3Jl40wC+iggxBJ6Tu/7zwS2lHrhd2Ke0+FoyrQ+vdxp/pMjbbKMmfUonEKGP8DpNQaZgnaZhnP6q+mr6lChpIpI+MBO8P5UnUKzl5MHCNQLnuMdGLuVkUvi7+wqlq/txFrVjZ/61iYYQeuCO+bA+VG/oUi7Ebh/p3qbGqjL6a7OaEuU3yPznBBYCE5zUfYJA4z74IzIReE+carM1yr9MDJnyqjQV2rhqu9ujX+E9ymlBBOPPPdApmmJIxBNt9nFgPRX00ZtE9fAWMtr9ncuXn5LCez/jokQoIh9BDSMyH++WOWgTC5+vbj4GlzDxFvf+MMgE+EyP/8KoyOpEEi8l+8aSVuNtqYwXBYHKlDkxtXySP6zxaOKaCT+rDk5NoyCJwx/8MNDAl24+Lb45abSFw85hPJyKpQQ41+EZoTKy7SIX2rfCR87oPty+YT4WnM4pS3HqsUP8lemOgEjWXNSF8MW9ku1jDT05VL15to2tL1T4SIsAeVdtbRtCQNiTTsxKc2EW2VKrK5oD+peYP+qqxk7XWeHvpLfEzZguVpXTQvWtCjEIRkfgHEB+IJz0+0Yl1JtgfbtVNlrQ2UCc2JyRCI2tPakoa6DGy12WN+7hU1+lqt7J/L3cgXd0PWa1N7H947/84LmNZMaeL6RI8HTRrJ4qmuqHBUdZQk0Q5GWMno0OZ8EaK2PQlPD3ZcjBzwbKO2UPnnbWguLzUySEwqbNU+LmpjJK1+Yb6xkLCGsImTV9ispl5k+UI3px52jN/BmWJZJxj3CXqww2eRI1txK5jo5j0etpUYaAejmk89eJ3BlVvxO4l9gfj7OXqBnq540/b7l2SwDnnhcdIIZkd0kP6RmUz/te6QAIBEbB5GUZeT9TmuUDnNt3GRdwkoDbfGRy0H7MeLG4rzzReNd4q956h59kvAPTk/DeIeNxS1U+LQXajcCcw7Nax+Yxtut9rqJwv4H6oLRe+tn8FoYN54tNhPRX0ASWrUjcwzxjV//GxUTxsvN07s6ius/hcu89mgBGOzcXvzNonEZDyOdhHZa+gN4f5tvXo+C+1ll81kR/uasq1uqDJiiKEsDbilTjucf1NAKSJBkvmbqxIAoIK/hQFfOb3R8SKO43wgaR/jJFyPppfXNRABIdBQZ/KJZv9wJ1AUpYj2dptdv3abd8DBE9PV6VwHa504IUVJtljBlH4jYIgCTAh1l/Mj70+5YfqGipe+xWeu4dWc72MbGaHiaXTvoxECRul3xUuRbTVrKRBZdJBdoFzEdDljD+ARIgiayPRZfqgM6na9L6ZXaTS1LLkL0OULvZB6QcA8zzsfI1nt59TJfG8VXvg9Tk+usjMuHKR4LGnZGNirorN9QhG//+Mjt4Sgv3A5Ku5U0fSJQU1SBtLdYQ48Ii7ecvTGBxYOpUDgTI5TKq/ExHekEjItGxXhkQCICZQ4jYVyB15Zdg+QBGYvCsZacfso3Ui+xkJRG8bz0MkhENq1GbXLFjZO4XLXyaxjPam3J44vhSHa7jxtWPDmi2JZxjVg+mTdutFAfwtzE5UtLYUM/MkRLaCsRdYc4gEqd89SHT0vy4GGJ3b8y6qZLsj1QbSqOe3R4OxPDNkaTGVATIymJnVbzydVdUMLNkkZA3JhmI6NTdVQoBxdcavJxZ8epuPlEuA7o9mZt2Kiuw2/bVTGll9rUgLfIKRrts/CFrdSIlvRwMaU216klsbyb/IRKEO0+sRaMWYAVro0A04yETaYZ1gAZgd/kFcBM6z3APh56GfzWTxlnBiJ8GcopFyDaarNTRVXq0p3bHro031B/ndvH8JFtKwixb0I5TbRDfOKCAg9W0yeCnqloWxaKtmykgri0+7u91qt+pDQZxnEKmB5C/tbvf2v6IzR1hbkW1WesXKZdfyOBtyiZTqEpswsZQVAaCP8T3tr2QXl7r4y9zeyHML6LrPYC7Uxn2zEtP5JlxwsFmF3qJ8XrA+lWvsNg5EwX/4Qn2pdlBFkFsLLF+rOzgE6hqaIknhCaK8BMm5CwwbQthFl3Xhif2V+Pxo9y1mGVBPHUS1EthHvmMT7AoKsH0LCiVd/NNtEwIr4OZV4mwRVOVGVVTKC3eISTQDeukgkSOXNWISrL92YkVeusC5F4RnJlkrgcJyHtLHkiUpbusnmpQXuMhwccd+7UDKfWWt2OIy1PlC+tIGxPQHqprUuN6VKNg+23Kpx1s0XF2xLYNdR4Pa6ODDrXaOvF4itPP16xSMa//OakL3qXTA4vLyuOzrvHKv4U/gDGWERVHIhW0GNS8COngtx3vYGCXpjV8Yk9eNL0J8MzvLsvp424+b5swDDHdl9WFDVk/rHPfwWPaXjQsGgv1k6gcKhJgBsUG0xiyc9fWJY0g8vbjDcBzsL3B5eFYSVOI/DJcdPuOi2W8T/uWy8ZBXQWPKwI7Px1hnPn08XL0DmxsoNKOxTgvlv9yFa7TZGNmfvijmtyd/cxyISbOvHRfUUXfc5dNo6J5zzoAHlnaObHAIuvGTOIR+rDq+SdFqn2jt4360sKz7Rn12p7pCtZGTcrK0z/rcf1VXnyNSh3ljfiw0nFlPKG2NoWdNwcTdE/yPpsXT4wccGZyO2QtxKhMqAanuwSgKZb4b9KsoPUuhM72nWF6fHPq8cOX8ATtDxh65/0F/aKzdNuPI0NLbJNkyp5Y4CYxzist4XrBcWvlDxLpcqkvFee+RXLOAiOZtuQfx70Zjn61NoJiy7NKK0bIk3xDGy9ev/jbQ+BDbaGw6NPiBhL1ruQVc5FbjGXS7eYlx4JX9DnBvAJ2CqyiyDtogbaO+egRE0gHzPK3I+By4nWY2QizVgdLaJ/5F8PNYmUAMBTpGzUdTpUhlGTfWaAVL5V/xxno/LtaMGIMbSOA7RhTB541SZTu0MNfVhEzxCyXyTZUIoSVDwOTGbHydrhR+GKqtDX1Semde88bGHB5oOTtDQ4JHAe91sR8Lgo7MoN2WXRA4sTdWeiTzkIg/nTKfXzDmJTLD7iCeodxpj9whTxwNKWJdX/Ernx1P1edg+Z4IrNe6nEStc/tWSFlJHlVwVX2+vKeRf9CTXaEOZwr/oYsJeaRYie34FOq2d5gsmGoOAgeSnFaQ1sDY9VBBanJ2/K/MrIBs89rAPMygs3euQvxHqIwAkQGU9PSEAp6RXRHJfHnq0+XzvD4J3TfG7fiNI7hbD98etTuVMte8eM/AsxwTdQ88B6FqTtTGl6LQmcvFwGqRfLBG3+9qD6WPxozpKDJ5lLri3jdZ3v+QAsekb1MhmxdkVl5oounMOgiACV2cVg2l8Y4io5tnbCC7dcCxuheDKYhzqcCdGuDMk8fPsvabk6SqvV+N8Umedhut2stfbhp1raXJ6XFAWknh191AONhnPIxWy3Qkq/NIp8QcpXRX1QJOc5dHKMA5Zg4cHaq76itQfuOUDP/c7+fWYZLeGfHfKIgq+YmNKDRVIjhER7MPUUfz5WgtzQ2raz2i6OzYlNSXsaxrS8vYjkU4BjFbo0Yny63mbCVADEWAVJmsvXFSHZzGIz7AYp6XFpeaw4JEazUZb+gbVBtHyQRMQhiMp5IZD86Zf4W3D5xb+6T8iZCmdg+cq3aPwHCB+k1VYB7SEZtuyZODS0cH03Ijj6lmzjtvN6pVdYqlY2bzEHAq5wI4mvSKW91ovVewyFzqUPFiUEH6jdw2A3NPgIKhw55J9d3ebB3n9ac9NGqpxW6z3u28xdDnDP/G2YLqgGzc6MQGAOatJfCXzob8F3+/4TVy6l0/pSQOqdYLmbn7ifEPcpg2f6+cY5ReO+yJhS1Mn66qsB93/3J62i3H9qWyovaNQCqlPgTs3iDiCaPYR4QA1lJZFVMNX7lH9QAwzcamSroa0CO3TuPWZux+rvBYWSbCNcmsjz3w0L42TvLOwSNtfbUjpHqdNCx2yFCqCKD74t+v3yEqFrbRWgxCOKViouasyhpIQ3vnVlgt+1utPRtfsPHWaU4AcfKIBxt5yem4ua7PyFiWnO2zStIsc58+jVg14cRYWjGBOK9NbpeUvZB4qhKunFvd27OTJ1bQZsTpEpn8YeCXMKeTrzcx6vB00kjriGYyfakbPoILIGiz4ttojMxz5mrlQLgqTN5m2qrM4sMHS3OC+2uWk3cc8WrZTStt6yFSVeV+9hlmxi3ypoWZujQTKaiL023XUd1OE0UmZdQm9QJl4UgXZJ1pW/TuSetyXDppqa0ZkodFr4TlCa+D0kQMXsHrpJcBVXlh9Dar7nYhSe/+yNSAeNa/hPKlfiexVWJRfAEzD1C4/PwC4WogTBy/dThaG3X9CqQSvqIFeTwj5QNzhti3llwH0bIDVwZh9+hzt/YXhCYHyK9qRrUVZuLz/vBv6zNrlq0Hp5cXtKoMI850l7BZbnau1CgJKZrsWp5DxGwlvdgDLLV56ZbLafd+05rjHjJIsFtWWmzGZTXzZI7utmDrAYgFyeLq4PLqGOu/Yo7ljO1xFZcvThErDAFzMVhrFIOVnyRfqsTRICuZmhdICVQVxY+EOEmXTDYFBZ2M3Kf7zBe2tjeCb8HQ1tkmP47JOkPd6bhSSOSsbvHwODI+VZ5+dQ8zbEXUkwNsyveTSxGky+n/xOI62u/7X2UZVblHpBwKowfnwiq5sxjcg66xPgCjmabHJjWsFVOhM0JxYnztJN8TR8rPbmoeNEChhBwbrxLvtfY9vr3GMIzLSF6mQmZ9AeNk7DC7ASqoCpxJw0OyCOtKYJzqfMkq3a4G5qfClzCyMZwpqvJTYgEykAJxVXfCm8rfdVnHU1E/Ske" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
+<encrypted hint="Type in the phrase &quot;Yes, do as I say!&quot; to read this section." hash="9bcd7c3417087e3b22a5105f91923551d465add76a4b8b043cdd9ad030efff9b" encont="0ajt6XFe5ZhQ103ZK2XCGLEQjq39nX7JJTNsjb71GVXZa89yf1XerSHgmNLpRTXKe2m75FciBuTaWPx7JJckbQz8XADddK0+AfBNpZgJ7ftWbYoGo7eVlvKcFMuEP2t3Wg9bKcKEEOIrUpuQ6g8viG/4iuK3QVGL7tE7NqAqRZR0qjkaS1xDnZJWV5MID2Gd3nNl257hNLsa4U2xusV4XyzLuYxXXxr8WVdY4qYarQgEe/pqeaFF53Su+4iNepAj7G9nvtzG/jOfD3+PpVxQFHmbpleqt2/uLIwdDtEt5JxyQrn8QR+nTokC7vA8WXUwuVTphNS0SuX8vW1pIsGONuK9q/MvOOX+OumJ5VGWxkVNQjNU5960vgJM4fNsuWyKdRoDbvBO0hLZF6u37O+baTGTOBrvfhe7+7W3mwo93NxQzx3t0SK3elGgA9J2CwlByQDU+J81DWI4EbyuHYNB+cbODaC5w13/7aPb/l0HGj/7T4OmsJIA0Ew6sikqgiNS7JTGqfGA8WSH0ysqJ1FEw3A9t11Zj3gpYPeFzjYaym/FU5MdtDLO3pDbC/ay8W7cTikWuuIfSe+/2kRzp4uG73EFzml8riviVWcgpVEHnjqKY9QDHXVNk8J+4e9U1P03D3FV18cB9M7HS16S+tn7bVrQ36rh5GNuxX9TXcf/adqHQ+prI0Tw/nHA9i2F+6rPpskubmli91mpFnG9Iu5BY/uiQDVmsVQ/a0UHBIJn5ozVRdPujh5p4meFN6JTOv/DRlPNF1KT2OzImqXW7rx9/AeLgG9RltBI69GY+sExWj3A86OD2R1W5UZSsceuCc3L2cw97+sZ5gVllu5HxVoCGVEvvJSwpfT3zRpkLxUw5Xm9PruFsdHYK4GEGwNi5mYwFkN+sOinCfHImHLy4iUCJHW338/bW/IfQLxZyjQBB8A4qRaNsU2T6J7jxtnt62LzP6DgUd8DgIzoOPHqk0wBu8kVwynKqca8mtM48zSx2n+BPjHTI+OUUNa0CEPLpBnc3uKP7zut0C0KTVYDlXM5kbLQKXnNa8bAdEg6aG5h9+d4GNi9rBiBciQzXgyBqEMtj6qrHW4Fobi+mUhHgGb31TP7sqSUZp/zGB2j/Z8uvT1AAtTHP/BaM+C/CMqiwTkbM9psu6p+xFx3ZMcf4/75nlmQmSNco7NGOxHS6wKi+MuAC+Yj4UqlhoXM1vYPqJsO4g36RY+DiwhoUA+BlYAJV6OQI9QwPuY7VDeTY0ZbuSkRyo8bs9nvMhN3t9YufavELo292OG4T0a2mQjyetia+ShFA/pO4BYqhCht2OQrUWuPQYplqFl28L/21bJXSZ9aEf7/wnhfrJcw2KBnwEnmb3BbjC/c8wYftNixplgwsLRnVgVFua/d2j7K3D1TlTF0O53Oy9J0JFRRGYhy70X7cCdGAuzdHur752lVJxfYiaiPeucgtt+QUDY/CW8czHm7rACvMX0XF6JvFfrLWYBeohxUaWkkVXOoXXEpq61Uw6yKl/RK9AwS6U8Wk4VgrYlTgLWpt3jDyvLbpAY9uCkWoqy8g0/kO9h9/zyplzvzU88rivejhXyt2wJtt5mspggX7+WjPCqMq1V2cpHW2XzVTVzE8yP+LjFPO9GxtcIEAZ161WTzWAsjLPmFiA+3qPcy1kp+PZnJQXKvnYo6s5j1DNxXCddfvWdnafdNyzjFEmG11hReWeT8swEVvxAJrIUnG/7DHAL0u9Iord66dNm0cXplD7z1N7TlGvyFvtTeAyzA4WpvJjS4UsVZRW2HYyIJNkAOQYKqwi/l0MudU7bGNIjSaHLVRsWUva9nq7DPBRBp7VPq7rPvspaPOrlaclAVrtRqYRUT4/vuIXJJL8X/wsNKArebdAbZ6wq8GIhUjPqXERddRyyjvPucFQL9CAcxojsrVPTGWYa4Cf0yn7Zv6PcDcVAX61L6eeAPbe903a/4R4vIgwK7XPeSaj7q9v+7ZX/iV49zsuetyxW5JrG9nmR38yW9NQPt5mAiXSCQumu/lfbz+JX7i5Hl8KjdE+UhZ2+DgBUyCKh9hlqGsf86wrnUpK4hB0nSKboweMcSjveYj8tvQJef6RWOfUdwFQUGW8khKXCG1I8L160ezv4DNAZshKG2RjhGFuHOUm7KbCn6xPDUxoj3AABoSouKIZ5tRcYBicAyMlBbPlPmbvKyIG70kZ5Kw40i1te5jbMg2JWyklUpnsP8u44ysJd11EwdBCEk0mlSroIG7CkG39O8h7dP/mAh8alPcjsBwJmtM/YTqqXf6WZJfTB/6wdOW0hs5zvO1ngmebdG2JdvGcDgBcJtITcE8Inpf2RVzbj2PHUWY5C7Mj6WTaFCCo5u2rW9jB+lQDKJM3XsQ/LtuvZNghc1omZH4Vh+r5TrHr/qPbgs42WMwIeNtR0dKhEh4041Tec3n/HuqJDHSkoMBVRwgDyCrYCpDJHXDBuuAfvmUfqiz/eyBqjC1IBIti23Dmd5exSWekfQbxU1EJH4t0lSFWpxDNkKEQsKYRkcUuZ6BH8O4WB7EftRMTWf3H6zM1lDctWlJj6Rv1lNjJHsRJhfDl04/8BfBOKodhONBIZZcyq3OS+T4O0XTC1aicc+iazvXTt6sZ3BZMiiR18DSKXH4jMviBWXx237ult7rSYfIe272HfnPkdAJIZaGsGctVnnnV1iLSXb2QQpft6+V2+QfVGj+H4y678TWqfGRRpGve/h5Z+/BwRVq//2odjpVU332kzV6JKZ1ZdO8/dneYtaPlf+lWxQ95DI9XwawHoEQG012kM4VnoQcsVb8699mX3GQ9+dUlftJjwkZQFnP73PyOKMoXDMe/Pl/U3Rt5ETxki4cFiq1IQq9mjuIX/0OqfO4DSgLxTsZwlGikrs1WizVDaFSo7x2CHvlTaZxyrdsGoIRPvRobDfp8Dyo2T1jL1npXRjpsLQbczaMe2vmL4BXQsm56OCFE4xq+uvfDxPgtMqi26LfLtpMd9xqcCNV7pZGUXMO2Ne4QS7ehmSpYjB0Jb1oArA9RO7K+vMSADb/+CUmdglBqCe0RCB5fvfIo9tF4N6h12WNF0qmXaYtYb7bWLKLIAq1D7t5Wtf96RDJ3zzmYrUsXEtQq6aXSNCFz3ZxFrTxkRjuvaTrN22P2yArfAKL+ob/LKQq+JnLJNYAJ9u/IDGiDWTwIy+Olh5JS2gJXyPIUWKp7z8cya/wJ+Jb1qrsp2N1MZDdefW8In0Yb+nxJCOh7a9Y76JEMdNwPawO7OlKkgFCc1EYSrlipastEMiHHZDd4r+OJAsJ8BZ3/67MfhcgazvvUoTMn6mt1BKyy/KZ4HUSTgMeE/VRVMO1yHmD8wZMnOWP2tMEH17iy3LpKdDPEOTc2H1KbhY5l8luKbgUY4jfWS6iPufL3i/S/32VyN+iqRIbPWTxytEqqYDnRVk8tiqqw0HfzRLrXz98uv3WuGWdTVo7MsPbaPcxNlJh1zbUSgGS8G27oxgRFSRUM5PAopAn1VqJ7JyXIG4gpYwyfVvFA/nn+FATFTqCymazLmibyWbNBS6+MFhKrweTBcZqS+tHDzENmVudN6pPCAH6MXOlajThjZm/sEtJ1wYtK8jZCQI5R8L8FfoFwaVzBhJl1fcuXl9uZyPVGgFeikckxHv17Z5iSKhozppzPhT7b82/JQg9Pg2U99bN/0wVlcqDOi8BvSTBiNJxzQR4vgpOeSZ7skDkBywXJQwYuIgKqdU6SRK6nBoatnh+udT1wPo2D9ayO2Ja2SjtRBPrt6F6+Ilz5ym38f9+bHCNTCncfitfjoFt1H1i/XgPCIqYpqd36BSwtdDlppJVWe+jJ5/az3cIli9Czp+QztQgPEA5UijOU0zUuXxmrRv7Rr1XAg5vANJSBUGl4pEFw3Y6cqkBIlHNjOc2IVWq4al1ml+CMmT0zibzOcD9bg1aL/R2iItlbf3duJXGa0J2uyaRT/s/ukASq2imR+IdfAoq3PHXZpIYe/8NqKjZJgAbhH2O9Xmxo1BAECkyfOPTzIFNAZ/T5iqCa+venzw48FPm0AFusu9HApmt2quUnOdTBVlUwpy3vqYTFzimTlazaa9bFQSORHZ/mweW74gVKHG+fC3FgrfTGaQ1kYtVYmlWBBI8VQX4jwHaHiTq//9NZiOwjoG+/Un+P7KuSuS6UKgDoc6Lo5ZhUXtss1Fxzd+S8n11XxQe4+UmiYHHVpq5RspNLLHIC9POE4DdYysyhasK1F1oaob5taKRMJw9omkpi7W0IkPD3qqEy45IET2Z8fljaCLosARKhDzNf3YGHSns5ABKwRluBye56Yx30Wx9iHOHriVi2sRZHQuFlR9YLUwra0TJj3yf/vxLMJAdd+yhsyslkX8uU7B9aKq2ZWZVb6VnyuCvOmEyEloBUBH6ZWNYMbNzCVDVlnV8XUHCAI8esMI9G05GCufIDg9dnioYFpv8JCFTHI+uDeefJKpuIIkeP1sJjnnoa/9gch8oh8fMQ/iJV9o8/ltD9wUzr1knk/gloO7yIuXcTkBlq4xHR7CmVj75A4Kwu9sVVUoTJ1kAyXT78Ct+n0RHd09+vhXEX7342U8GsyekTLg+Rdtn67aM2PNJS3hRsHmNbrsoWWepYXugX506a5UpdIOcxmE3xyzF7oWU8M2OGfWnkLjBDEsduv+FeEH0ENvZ6TBBjMBz3Y2JDnoa44mZDz9BDbZlbx3Wz645T+HO43ykDRajL2QpOK7fl7e/kk0FExSZlQFurfQtoy5er3S2R809O3aet1cMcJPMe5syqVRqTYskI0zg0gqNKI7Vd26kg5RlmPy1LADWp3QlueAD3iPA8yK2OInBTWlu0nwYxOodWndzPHN3sbC4r/+lVelsfWWf1/p/zQmq1PErIB/lcH3pLxxvWgbEBUA/Qy69GuKheHWBGk9PvBiKoK+XFFjQnXxPBfThJhelXKcu1WHtsr7rHa0qwt/d/EIMlJYJYfHLpYfX8Qet7Hl/dC/WWJmjUf6QdSuEKVapbyccyZjOU2HDwuTZqnmUYzrZufRue6hC9rh6JOHv3+/0dqAmB+x2DNBuPrGctdpUIOGuHf5v/2MZqoJQC9qMIy7llFBZSYicZpdQdtL0BsDLTijT3i6bxucCWOmAv0we280CVENeMiVU0W6gTJF0UApq4EDujKxE756thURmcX3TfMDYsTQIUORXJ0WUdlHeXwZyWhkOFgQLvKS73w20N+cP48DJ5AmasKOBDAWYmltpREmrZ3MUw8JbsqVzTEuVfPDKWGcodsBnws+/tVlQ+uPJcU6nen5OjYfSLPDIfvxIYKhUMboHNGbGIuiH1+PhxfrzfKEczqB1xAji2L2eadMpLYXsUpUTv33rOBOyso4TegWHhJu1YZGpmk0S2ldqrn+yiddlMnZf+KnlhhpkmIKja8uqI1fERJzO08Fqdn5uvbgSrUc1AiM95zDc8ipLXiPeVZsk9UdRYJ9PQX9ycFZP03THfUWzaO/thLAEvHCMBUKcFMspgZ/VvEry+XMuG9w/4T7kHj32QKDfIDOZVxpvgptbxbICw6R3H1o0yaX0YbTwi6s8gcVZZudJ4HDx38TdGBMDKMqr6/PluW30jxNxfchcH1GDjHLG4bjVTQZ4hcMctBPmvO+dtbITy4uSXtyXeEGmzsqZwOGej/lWvMUhdlJtpo7VYoIv7j46lkUbD5r5UkSdDtZTNGt7uIt1zfZinE+oMkWAm2XievFo+HPajhQv2f1xvcT8nK00HT0nLpjOJUjYVBHaNj0aBWnrIdxgi5CDToler24jLlRbjoPAxgGBppLEJagNuArI+YnEL8WnoNcixvn9tsZ+Dw+ciHK7jTUzzyViPJ6ZGykALiSFcrC7j1BGnDbqrKj8nSPM25iLAlYvFq5QoMRhvxvssO3cYWTBYmI7MD8WaLETJhJzg5MWjw//4gMzvuPKE8y0W57RLDHRSiPxuQ7WfrzrTksK6FNX3TvFrKcR3AgUqaoeKQNe9Lp/qmPnZ3PsaBpFb8Yq0QnDJCPSYeEujfWBmYQ80Qjn359ZrGsIbY8Tuo70my50036FWVThxZdcdzY7xTzGP4qVvyHMapKZcQ8V+yAIkedJejBDNUhORyl4dApoTGFoVH35Z3fZUR8z4CdHfkxqnvlIh65NCCTTLKpUJUgWsa4T4DBKc7euQIejS8uMT3ms2TUZn2+pScasKgBeMkSD3jNt5JVM4ONsrLL28V9IaRzgB24xEf+BxddUEP5Y2rSU+y1H1TmBsWvt2CquUJ6aJKan8t2m610m7aW1SExwtgTeIJ4joXZwT0GokJIXZsTYY2bVx/eOtA82j97K5l71fUF3Ftu1iX3NPVeQuUZ3dsRo2zuVBNmSebuIbS5M/gXya5YXSxseN93kp2FLh90K7XCKbOk5K2a09XnfGjBqOvas/ZQV3ottnNCJiS0mDrUeSZmZKpxoPHhSqPfzcCGHyG2G5BH+EpBx+eoGuagMSlo5mFKoKDZ0OVxNTC5P73dDVbV/SbSjnvhf40YObGK+Ege4Pije/nt2UZ0cyW+ZXvN4Tp6NosBA511xg/L6mRxNAuCAH9Jz1bh/LurVaXt/SyeSqQXdR0yd1nZNp9G9xGF1tKr+R1XL4bqCYkGX9EQgbL8sjF7bnrRLft8STDv6Vco0Tk0RYDrMbGYuOoMLj/OQoYcWI4X+7hp5kvA1AE1jVFJ98w3LaUyDvMCRpFbUl7ZR9CPslKu3Ivc3d0TOS7rkW1u2L8TEf5PZRuZU8OrkEPKXiEljeNWsa/7VD5B/vvAffB/n3OWA7+EJhVvQSWUjXt03h5tr1ZLmcTRsQySGh6gPmUMjwun7dGi1vJhmSPjfvKd8pVC/jpGxXQSligYtaDGB5r71hVcHkh5bssgRCst6t+szN5CkRFyDsnTuwE1kqs0YTm+2CBwGb6IVH3Mcsq1dpix8hE5Dm/ekLlg9YTBj4AYFzDwxoHTCAiOixwc3KUR3XYETnO2Txgpik7SVhukebOiMZYwM0NxFN5eFkM8cIXs6y8E+mGhhLQr0pOUppJbJUUV4TJl4O5P4YsnxRpIMseZ8jVc3R2amUS3jtKXJJ14W9Bdo3SMy0cBmvXBVqRSdwoeh11bD8FVKzDrmUEy2XEz8PKNS7wyAQxxI0/N8MS6N2J5b8SEOMf/HyxXUnFyh/C0vAcXmyDttSm6bCFzHP2UfGXyXlF1cCadSr7684A96FkqzxS40iayc+DPVXHasz+McUtQBUvZV7/C75m70IyPXtLV0/7ZwTgln7f3Zzr1NssBqVW/HqbUmqWpDrLMGbLNiHy+GPhU8udoO5hwf//KIzJyRT/xE2QpIKtd+m/5XDsBn9k20o6TdBPX3kirxpHAZ4eGIL33fnf8nvsZ+qSnoim5vbLEsGc7gvn4eyLRix5YleW7t+C8F/s1wyGQrZQiGG+ig4K30OYn/F+h7GghbkmY0lj9megWRuekJIdOU2Mt1uhgmkbJMRlmGWReZjqVh/jerjk2nCQNKbkmcz+weSxUyE7r+T9U6XdwrYOdxrOVZthgABFiFtP8DxHInj/GhYpYf+4rIrr1g1aGEjB9pDb7lvwGwLbDQF5awwTm78xvZc+iE4CHDb4gAJw9sj5B/2FQ9MRgPmOIr685pTfRO6/hEnT8HoSZNh3Vwb1Rd1d3ROsKFGMJqMLinwbbY2oU51Wj+Cqn5UvpSHRUnvRPMk9zC6OJ50slI1kVItE95XVBDhCttCEl88S24NKrCX3kS9eUjaj5WK/axgeFMkMm4F7T0AnG5tcDiS93rSy8ZwzGAmyX7U1LHDaxPbsCLq3iS8dsznKlRdke8FoghCYLiM5TYBRwDLK9ew5iOml2Hcl44TiiI9clz6HdtwYdwCcNRv/uHufOl7Ty2UFddQ3UVr83YhPjTeIxHa0sJYXxjRz7e4QVoTlldY9+qmGimjMG3A8WVGli45MUqON97X/2G+fiS9J2AbMyB2cOYIcaMRGZ9E7U68xljcOEkAn+IcYeGW7l8FWGcOn6B1VMSDf1tmtnwdYtLueq9F1NnMpfYtsAg9iPqWmAcHohVUhvHRFARd3lo6Q9TLGQOc/wLgIgxVynyfbnTBapJPKcX9tDIn/JiushUPolin6v01T5mEVD/rKXJn6JBl5TeoUU7m0rxFpntYa0l88pAuu4fZfSOVxbTnwEKl3Z1R7ywMXFmm5aCxGDpHPmvPEjVppIKyXd09Os0tQMD/F9MJ5jDApfTmM8wYlTCbmJ6WnvSTtVjtFGm3y0q+nGvR0h8bd9FBy9wL7M9pMooR5qkq+IBQrEGJKdk83cUIDS/2olyNaNHNQksJOhslDgVSbJ9raR3/gYZnmoSYI3EAP3VqaMYvf7JHVqWXQcDK92y8tKPbHUUyYK0pzFvV6oh0br8HYAyjIece2FKljRPSxvhZ/HBQRt2cWruKLhcUKxNAxskqbH3MpxL7OmlK5aHtR1UEvsAL5poVwOZgKR95FRyi7vjoJJUmuIO0I/cdmdFxHziwHg3Mpr80Q6+AKZrv7lAIHSF49iMBKdFKJT7NwT7fEoY6pi42/OKbcu5+fS8zTIGSTCo8wVGtNkMs5c0CeHdOfa6A3jMgxk8C9QSq90wgryX2L1hEbOirWZZhn51ahp1bVEtbJ+vH0MXsfvlrDuYhHCK8MqkEYV0OblL5pPxR7TYMCeGxZBLRAACYsfRMwr09v/72qlxBncOayQ1+LskUKXTN/ywI0c0UHzjzVDhVqYTFajLC5ihe8iXdZ/xer98BtPypa5I9oLBNCF58YRBXj+BheyR+VjJGFyI7jot4mlH7cec/+iBBZK3FCYYnK/BJ+vaQBwCjLl8LSLpRsN3RXOPDhTkJ55//byNA0eITCxxhailFs41wb/iguXtXZYwKwQAcInyRoq+17/RY8eSaIm4TF+SSpV2gG05QtTAC47TMbNuifS6XA47ZgGwYV8SfpmMcDji97lPjn8mEMGprRzUGxBOVpD35nsRluPerm/AosNRACjrGkt0Pl5kQ6mAJTZirmcgVOpW4pEu7GHwRU3i4s5XujRs9R/iafQCmONjCV2lHDjnvo3zkyKUCMVtiypSCY26wtOrIDut0CYqIyWI6cV5U/tyeY/CvigqYjtRG+ktcstMzJF9nied6tzqMTGLkvADzViIKn5qtlpig+KejAJ/m8khupbivf/TMnxpaF8p+YYatk+xMEZjLj4V0cuT+rRejP4+LCQdXrV1L+aQKt7ygK0J4wGj4njv1ztnzC5iQMAAv9rbAmALu2iHFLvk2BItLGhY+rsEd3HtyJCg/aDEvlOW7tWtMT4P5RqzHNZPdapr7TP+M7iDDyhdLfxsVd2DsOt03+YJRqVE2d5T30Ww5mQ4Gj+1idmD3lEIEI7gxLCEbQyu/4Nu3uZuIyULHt2PoS8SiFYCuyup55bisvnIZIwmb/6kpa8t4F7u5dtaCY8h+bJkhqDYJkMXIw66ocVUKqiDQtJ3NCJ/9nr9SaIMv5o1gny64ZqHW9XRDWf0g2XGlgLb8Sn//u4MDXcDfMevo2rnT0O3aMZhXowV7YAnhaYTMy7OS9r+P0Ll26SIOlSDdYvsyV7sQe+z7/EhI6LGTzUsXszIxyPHdbwXV5fExx8Re1g/bzK2473iw+WAkaOql8txew4CEQ5iuo29vCoauVW4t/Ugg0HMbAkWyBqeHA9y2utjGglbWgFyAlWneV2EPLM47KrI4IrguxmKcPotwAbjviOnUjlbHgIe8R9xTre" enid="0">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(0)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<h3 id="tocanch33" class="tvis">「实名制」</h3>
<p>
@@ -660,7 +630,7 @@ that millions of fools would beg to be jailed.
<p>
Broken pipe.
</p>
-<encrypted hint="Don't read it." hash="6a3c5979d02cf25274065788a7128d2a7734bea70bcf7fff2afe1f5bfe9a3e86" encont="XEYqv08FzpVV0TD3zCHqVDBcjI+evdHu5FSev6OLJyXylkQ5fe3hPHPx6Wbxo3C4kvbrwy0F+G02aKu41tjuAEPu/ZPkeZ2V1CnRVE6FXgAzn1jfSqoiKWq/QYzTizh/IdavQQnQhgg6D4QRlZmeP7NJGoKCjfcW+UtI8+SucTUSAIp9z1XcOZQ+75vwSiodNwOH50hs5l2w4HUzwyGv/JJQDUGZWT9vnQ3bgJXOiGzl0RtMMNE=" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
+<encrypted hint="Don't read it." hash="4d35086eef63234bf06581d1a11d4e6258ada0bda4e7fca62e6450251f74a650" encont="8BZ58RiHYpZTtmvp0BHcSWfXHYuMEs0r1jF7uHqWd0/DUylP7PSzljO4YzaWrMuP7cc/YsMxHAzJKM1Sn0qXQQPyHLXvfiULvjbpQYC5JTUwFmbxdxYEl5sVFPViFmC2kjiSeFkTZxAC2ZZtIcD4APzt9/LW1F5E6bQZphDX9JaL6/v8YpeVQWCTG3cKVIeCHFCytIw700UC6C4kZK7U4hc8y2uU+qPF8q700NvSMwuWmbVQTXQQwQ==" enid="1">This section is encrypted. Click <a href="javascript:void(0)" onclick="decryptui(1)">here</a>
to decrypt. <noscript>Note that you need have JavaScript enabled for decryption.</noscript></encrypted>
<p>
Did you regret reading it?
diff --git a/blog/post/2017-11-25.html b/blog/post/2017-11-25.html
index a3e1a14..c8d1e6c 100644
--- a/blog/post/2017-11-25.html
+++ b/blog/post/2017-11-25.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"A short post on Cakewalk's death and my music production")</title>
+<meta name="description" content="«A short post on Cakewalk's death and my music production» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2017-12-21.html b/blog/post/2017-12-21.html
index 51268fe..0067a81 100644
--- a/blog/post/2017-12-21.html
+++ b/blog/post/2017-12-21.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"为什么我&amp;lt;i&amp;gt;就是不&amp;lt;/i&amp;gt;使用Mac")</title>
+<meta name="description" content="«为什么我<i>就是不</i>使用Mac» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,15 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+table,td,th{border:1px solid grey;}
+table{border-collapse:collapse;width:98%;}
+td{padding:1em;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -106,11 +80,7 @@ loadTheme();
<p>
<a href="https://www.tail0r.com/why-choose-mac/">原文链接</a>
</p>
-<style>
-table,td,th{border:1px solid grey;}
-table{border-collapse:collapse;width:98%;}
-td{padding:1em;}
-</style>
+
<table>
<tbody><tr>
<td width="56%"><p>
diff --git a/blog/post/2018-01-05.html b/blog/post/2018-01-05.html
index b5731e2..5a64323 100644
--- a/blog/post/2018-01-05.html
+++ b/blog/post/2018-01-05.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Now using reverse proxy to deliver content")</title>
+<meta name="description" content="«Now using reverse proxy to deliver content» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-01-07.html b/blog/post/2018-01-07.html
index 07f4e8b..ddf3801 100644
--- a/blog/post/2018-01-07.html
+++ b/blog/post/2018-01-07.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Trash dump for the fifth semester")</title>
+<meta name="description" content="«Trash dump for the fifth semester» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,13 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -92,9 +64,7 @@ loadTheme();
<div id="datetags" class="TText" style="margin-bottom:1em;">2018-01-07<br>#garbage #daily-life</div>
<hr><div id="article" class="TText">
<article>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<p>
这个系列的文章自开始写作以来,似乎都没有按照一开始预想的「这学期发生了什么」
这样的思路来写。而是变成了「这学期发生了什么+这学期的各种胡言乱语的聚集地」……
diff --git a/blog/post/2018-02-05.html b/blog/post/2018-02-05.html
index 1476c38..02a088c 100644
--- a/blog/post/2018-02-05.html
+++ b/blog/post/2018-02-05.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Does gaming make me merrier &amp;amp; more relaxed or the opposite?")</title>
+<meta name="description" content="«Does gaming make me merrier &amp;amp; more relaxed or the opposite?» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-03-17.html b/blog/post/2018-03-17.html
index aa9734f..bd32d58 100644
--- a/blog/post/2018-03-17.html
+++ b/blog/post/2018-03-17.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Some rants on SMELT, QMidiPlayer and Virtools")</title>
+<meta name="description" content="«Some rants on SMELT, QMidiPlayer and Virtools» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-04-17.html b/blog/post/2018-04-17.html
index 59b99f0..76f0bd4 100644
--- a/blog/post/2018-04-17.html
+++ b/blog/post/2018-04-17.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"The &amp;quot;Deepin is spyware&amp;quot; problem")</title>
+<meta name="description" content="«The &amp;quot;Deepin is spyware&amp;quot; problem» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-04-22.html b/blog/post/2018-04-22.html
index 7311f13..ac7ef03 100644
--- a/blog/post/2018-04-22.html
+++ b/blog/post/2018-04-22.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"ICPC类比赛中计算几何问题之「乱象」")</title>
+<meta name="description" content="«ICPC类比赛中计算几何问题之「乱象」» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,29 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+frac{
+ text-indent:0;
+ display:inline-block;
+ font-size:50%;
+ text-align:center;
+ position:relative;
+ top:4px;
+}
+frac>sup{
+ display:block;
+ border-bottom:1px solid;
+ font:inherit;
+}
+frac>sub{
+ display:block;
+ font:inherit;
+}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -91,25 +79,7 @@ loadTheme();
<h2 id="titleh" class="TText" style="font-wight:normal;">ICPC类比赛中计算几何问题之「乱象」</h2>
<div id="datetags" class="TText" style="margin-bottom:1em;">2018-04-22<br>#garbage #acmicpc</div>
<hr><div id="article" class="TText">
-<style>
-frac{
- text-indent:0;
- display:inline-block;
- font-size:50%;
- text-align:center;
- position:relative;
- top:4px;
-}
-frac>sup{
- display:block;
- border-bottom:1px solid;
- font:inherit;
-}
-frac>sub{
- display:block;
- font:inherit;
-}
-</style>
+
<article>
<p>
虽然我还从未在博客里面写过一篇仅与ACM/ICPC相关的文章,但是今天情况发生了改变……
diff --git a/blog/post/2018-05-03.html b/blog/post/2018-05-03.html
index 1cc52bd..7f82bb9 100644
--- a/blog/post/2018-05-03.html
+++ b/blog/post/2018-05-03.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Are you an Apple fanboy/fangirl?")</title>
+<meta name="description" content="«Are you an Apple fanboy/fangirl?» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,67 +33,10 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
-<body onload="ol()" style="overflow-x:hidden;">
- <div id="panel" class="TText">
- <ul id="panellist">
- <li><a href="/"><h1>Chrisoft</h1></a></li>
- <li><a href="/blog"><h2>Blog</h2></a></li>
- <li><a href="#"><h3 id="title">Are you an Apple fanboy/fangirl?</h3></a></li>
- <li><span>Tags</span>
- <ul id="tagslist">
- <li><a href="/blog/list/garbage/">garbage</a></li><li><a href="/blog/list/interactive/">interactive</a></li></ul>
- </li>
- <li id="tocouter" style="display: none;">
- <span>Table of Contents</span>
- <ul id="tocroot">
- </ul>
- </li>
- <li style="margin-left:-0.5em"><a id="prevp" href="2018-04-22.html">Prev post</a></li>
- <li style="margin-left:-0.5em"><a id="nextp" href="2018-05-08.html">Next post</a></li>
- </ul>
- </div>
- <div id="content">
- <h2 id="titleh" class="TText" style="font-wight:normal;">Are you an Apple fanboy/fangirl?</h2>
- <div id="datetags" class="TText" style="margin-bottom:1em;">2018-05-03<br>#garbage #interactive</div>
- <hr><div id="article" class="TText">
<style>
input[type=radio],input[type=checkbox]{
-webkit-appearance:none;
@@ -124,7 +70,31 @@ input[type=radio]:checked{
input[type=checkbox]:checked.check:after{
display:block;
}
-</style>
+</style></head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">Are you an Apple fanboy/fangirl?</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/garbage/">garbage</a></li><li><a href="/blog/list/interactive/">interactive</a></li></ul>
+ </li>
+ <li id="tocouter" style="display: none;">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ </ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2018-04-22.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2018-05-08.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">Are you an Apple fanboy/fangirl?</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2018-05-03<br>#garbage #interactive</div>
+ <hr><div id="article" class="TText">
+
<article>
<p>
<b>DISCLAIMER:</b> This poll does not send any of your response to the server.
diff --git a/blog/post/2018-05-08.html b/blog/post/2018-05-08.html
index b716be6..cf22d53 100644
--- a/blog/post/2018-05-08.html
+++ b/blog/post/2018-05-08.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Respecting your job")</title>
+<meta name="description" content="«Respecting your job» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-05-18.html b/blog/post/2018-05-18.html
index 191626f..76fe048 100644
--- a/blog/post/2018-05-18.html
+++ b/blog/post/2018-05-18.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Ideology vs Pragmatism &amp;amp;c.")</title>
+<meta name="description" content="«Ideology vs Pragmatism &amp;amp;c.» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-06-05.html b/blog/post/2018-06-05.html
index a68f33e..f825c24 100644
--- a/blog/post/2018-06-05.html
+++ b/blog/post/2018-06-05.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Software Project Management in the Free Software World")</title>
+<meta name="description" content="«Software Project Management in the Free Software World» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-06-07.html b/blog/post/2018-06-07.html
index fc6e175..927db02 100644
--- a/blog/post/2018-06-07.html
+++ b/blog/post/2018-06-07.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Should this site still be alive by 2035...")</title>
+<meta name="description" content="«Should this site still be alive by 2035...» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
diff --git a/blog/post/2018-10-11.html b/blog/post/2018-10-11.html
index 25c4f8b..ed80ab3 100644
--- a/blog/post/2018-10-11.html
+++ b/blog/post/2018-10-11.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"The stupid blogging system evolved!")</title>
+<meta name="description" content="«The stupid blogging system evolved!» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -91,18 +61,33 @@ loadTheme();
<h2 id="titleh" class="TText" style="font-wight:normal;">The stupid blogging system evolved!</h2>
<div id="datetags" class="TText" style="margin-bottom:1em;">2018-10-11<br>#web #devel #js</div>
<hr><div id="article" class="TText"><article>
-<p>As you may not have noticed this time, the blogging system I am currently on received yet another major revamp: unlike the previous SBS, which will not work at all if you have JavaScript disabled or trying to browse with lynx/links/w3m, the new SSBS is almost fully static: no JavaScript involved on the client side if you decide not to read my encrypted crap!</p>
-<p>This is a rather small update on the visual side: it shouldn't have a huge impact on the reading experience by only stripping away some animations. More changes are actually under the hood.</p>
-<p>SBS 2.0 is archived and retired immediately. Old URLs will not be redirected. Substantial changes may still come up to the current version and may break unless a complete reload is performed.</p>
+<p>As you may not have noticed this time, the blogging system I am
+currently on received yet another major revamp: unlike the previous SBS,
+which will not work at all if you have JavaScript disabled or trying to
+browse with lynx/links/w3m, the new SSBS is almost fully static: no
+JavaScript involved on the client side if you decide not to read my
+encrypted crap!</p>
+<p>This is a rather small update on the visual side: it shouldn’t have a
+huge impact on the reading experience by only stripping away some
+animations. More changes are actually under the hood.</p>
+<p>SBS 2.0 is archived and retired immediately. Old URLs will not be
+redirected. Substantial changes may still come up to the current version
+and may break unless a complete reload is performed.</p>
<p>Full changelog below:</p>
<ul>
<li>+ Static page generator using node.js.</li>
<li>+ Content encryption with AES instead of simple XOR.</li>
-<li>+ Decryptor now remembers every correct passphrases in local storage and try to decrypt once the page has been loaded.</li>
-<li>+ Optional custom preprocessor pass for markdown/reStructuredText support.</li>
-<li>- Vim-like command buffer, animations and key bindings removed on the posts listing page.</li>
+<li>+ Decryptor now remembers every correct passphrases in local storage
+and try to decrypt once the page has been loaded.</li>
+<li>+ Optional custom preprocessor pass for markdown/reStructuredText
+support.</li>
+<li>- Vim-like command buffer, animations and key bindings removed on
+the posts listing page.</li>
</ul>
-<p>The decryptor requires a ES7-enabled browser to work. All testing was done in Chromium 71 and Firefox 62. I don't use 'JavaScript best practices' or 'industrial standard testing processes'. It <em>just</em> works.</p>
+<p>The decryptor requires a ES7-enabled browser to work. All testing was
+done in Chromium 71 and Firefox 62. I don’t use ‘JavaScript best
+practices’ or ‘industrial standard testing processes’. It <em>just</em>
+works.</p>
Find out more <a href="https://cgit.chrisoft.org/sbs.git/about/">here</a>.
</article>
</div><br><hr>
diff --git a/blog/post/2018-12-06.html b/blog/post/2018-12-06.html
index 21faccb..d990f4e 100644
--- a/blog/post/2018-12-06.html
+++ b/blog/post/2018-12-06.html
@@ -1,8 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"小米 MIX 3 上手体验")</title>
+<meta name="description" content="«小米 MIX 3 上手体验» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
@@ -49,7 +51,7 @@ function ol()
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">前言</a></li><li><a class="toctarg" href="#tocanch1">购买前</a></li><li><a class="toctarg" href="#tocanch2">剁手</a></li><li><a class="toctarg" href="#tocanch3">到货</a></li><li><a class="toctarg" href="#tocanch4">第一印象</a></li><li><a class="toctarg" href="#tocanch5">「偷工减料」和「虚假宣传」</a></li><li><a class="toctarg" href="#tocanch6">换掉令人<sup>我</sup>痛苦的 MIUI</a></li><li><a class="toctarg" href="#tocanch7">终于,小米脱掉了……</a></li></ul>
+ <li><a class="toctarg" href="#tocanch0">前言</a></li><li><a class="toctarg" href="#tocanch1">购买前</a></li><li><a class="toctarg" href="#tocanch2">剁手</a></li><li><a class="toctarg" href="#tocanch3">到货</a></li><li><a class="toctarg" href="#tocanch4">第一印象</a></li><li><a class="toctarg" href="#tocanch5">「偷工减料」和「虚假宣传」</a></li><li><a class="toctarg" href="#tocanch6">换掉令人我痛苦的 MIUI</a></li><li><a class="toctarg" href="#tocanch7">终于,小米脱掉了……</a></li></ul>
</li>
<li style="margin-left:-0.5em"><a id="prevp" href="2018-10-11.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2019-02-13.html">Next post</a></li>
@@ -60,9 +62,14 @@ function ol()
<div id="datetags" class="TText" style="margin-bottom:1em;">2018-12-06<br>#device-review #hands-on</div>
<hr><div id="article" class="TText"><article>
<h2 id="tocanch0" class="tvis">前言</h2>
-<p>第三次买小米的东西,同时也是第二次买小米的手机。跟很多「米粉」相比, 这个数量应该还不到他们的零头。</p>
-<p>前两次使用小米的产品,印象都不能算好。<a href="https://chrisoft.org/blog/post/2017-02-13.html#tocanch5">小米 MAX</a> 不到一年开始自动重启, 至于小米<del>铁圈</del>圈铁 Pro <a id="n1" href="#note1" class="note">[1]</a>, 说好的大概都是骨灰级米粉。</p>
-<p>怎奈 Galaxy Note 4 里与奔腾 4 一样辣鸡的骁龙 805 实在不争气,不光能让塑料壳手机当暖手宝用,续航更是尿崩。 于是就又有了败家的想法。</p>
+<p>第三次买小米的东西,同时也是第二次买小米的手机。跟很多「米粉」相比,
+这个数量应该还不到他们的零头。</p>
+<p>前两次使用小米的产品,印象都不能算好。<a href="https://chrisoft.org/blog/post/2017-02-13.html#tocanch5">小米
+MAX</a> 不到一年开始自动重启, 至于小米<del>铁圈</del>圈铁 Pro
+<a id="n1" href="#note1" class="note">[1]</a>, 说好的大概都是骨灰级米粉。</p>
+<p>怎奈 Galaxy Note 4 里与奔腾 4 一样辣鸡的骁龙 805
+实在不争气,不光能让塑料壳手机当暖手宝用,续航更是尿崩。
+于是就又有了败家的想法。</p>
<h2 id="tocanch1" class="tvis">购买前</h2>
<p>早在去年,我就给自己以后的手机选择立下了三条规矩:</p>
<ul>
@@ -71,59 +78,157 @@ function ol()
<li>拒绝将两个摄像头纵向排列在背面角落的机型</li>
</ul>
<p><a id="n3" href="#note3" class="note">[3]</a></p>
-<p>除此之外还有额外的几条加分项: - 可以有办法获得接近 AOSP 的体验,官方提供则更好。 - OLED 2k 屏 <a id="n4" href="#note4" class="note">[4]</a></p>
-<p>上面的三条规矩的重要程度基本上是递减的:我不能忍受任何屏幕被啃掉一块的机型, 然而耳机插孔和摄像头排列相对就没有那么重要了。尤其是在给 Galaxy Note 4 配上无线充电后,发现 Micro-USB 的使用频率已经非常低了。这么一来后面两个规矩就几乎形同虚设了。</p>
-<p>至于加分项,得益于 Project Treble ,现在的大多数 Android 手机大概都能满足第一项。 第二条则相对比较难以满足了,于是后来它就被拆分成了两个单独的条目。</p>
-<p>机型选择上,首先看上的还是「老朋友」 Nokia 的 Nokia 8,然而该机型在中国实在难以购得。 于是又盯上了它的后续版本 Nokia 8 Sirocco。然而它的价格对于一款采用过时平台的手机来说有点高了。 后来又想到了用了6年多的三星,可惜三星现在的高端机型也是完全买不起的。于是我打算11月中旬去香港的时候顺便看一圈再决定了。 <a id="n5" href="#note5" class="note">[5]</a></p>
-<p>就在这个时候,小米发布了 MIX 3。我向来不是非常关注小米的产品。发布会看了5秒就关掉了, 只看到一个雷军在故宫的什么建筑物前面「做现场的表演」。过了几天看了一眼相关信息,觉得好像还可以(除了犯了规矩的后两条, 以及小米万年的 1080p 屏幕)。于是就计划再给小米一次改变我对它的看法的机会,做了「先买再说,不行7天退货」的打算。</p>
-<p>当然在购买前我已经做好了一部分钱会打水漂的心理准备:因为从来不用前置摄像头, 所以花在这些东西连同被吹得特别厉害的滑盖<a id="n6" href="#note6" class="note">[6]</a> 上的钱就相当于浪费掉了;还有永远不会用到的 16GB 之后的存储空间。<del>这些钱是永远也会不来了。</del></p>
+<p>除此之外还有额外的几条加分项: - 可以有办法获得接近 AOSP
+的体验,官方提供则更好。 - OLED 2k 屏
+<a id="n4" href="#note4" class="note">[4]</a></p>
+<p>上面的三条规矩的重要程度基本上是递减的:我不能忍受任何屏幕被啃掉一块的机型,
+然而耳机插孔和摄像头排列相对就没有那么重要了。尤其是在给 Galaxy Note 4
+配上无线充电后,发现 Micro-USB
+的使用频率已经非常低了。这么一来后面两个规矩就几乎形同虚设了。</p>
+<p>至于加分项,得益于 Project Treble ,现在的大多数 Android
+手机大概都能满足第一项。
+第二条则相对比较难以满足了,于是后来它就被拆分成了两个单独的条目。</p>
+<p>机型选择上,首先看上的还是「老朋友」 Nokia 的 Nokia
+8,然而该机型在中国实在难以购得。 于是又盯上了它的后续版本 Nokia 8
+Sirocco。然而它的价格对于一款采用过时平台的手机来说有点高了。
+后来又想到了用了6年多的三星,可惜三星现在的高端机型也是完全买不起的。于是我打算11月中旬去香港的时候顺便看一圈再决定了。
+<a id="n5" href="#note5" class="note">[5]</a></p>
+<p>就在这个时候,小米发布了 MIX
+3。我向来不是非常关注小米的产品。发布会看了5秒就关掉了,
+只看到一个雷军在故宫的什么建筑物前面「做现场的表演」。过了几天看了一眼相关信息,觉得好像还可以(除了犯了规矩的后两条,
+以及小米万年的 1080p
+屏幕)。于是就计划再给小米一次改变我对它的看法的机会,做了「先买再说,不行7天退货」的打算。</p>
+<p>当然在购买前我已经做好了一部分钱会打水漂的心理准备:因为从来不用前置摄像头,
+所以花在这些东西连同被吹得特别厉害的滑盖<a id="n6" href="#note6" class="note">[6]</a>
+上的钱就相当于浪费掉了;还有永远不会用到的 16GB
+之后的存储空间。<del>这些钱是永远也会不来了。</del></p>
<h2 id="tocanch2" class="tvis">剁手</h2>
-<p>有着「猴王」美称的雷军怎么可能让我这只不谙世道的小猴子顺利购买他们的最新机型呢。11月1号第一批在最多20秒之后就……没有了。 于是只好等11月11号。</p>
-<p>11月11号的开卖时间是凌晨0点。这对在23:00以后只能在宿舍玩手机的我是极大的一个不利。0点过去了, 小米官网的购买通道果然进入了预期中的无限排队模式。无奈只好试一下小米的×猫官方旗舰店,发现还有货, 不过只剩下了 6/128 和 8/256 的型号。这就让本来计划购买 8/128 版本的我十分为难了。后来在 「既然已经被小米坑了3000多元了,再多被坑400元也不是什么大问题」的思想的唆使下,剁了 8/256 的型号。 (于是永远被浪费掉得存储空间变得更多了)</p>
+<p>有着「猴王」美称的雷军怎么可能让我这只不谙世道的小猴子顺利购买他们的最新机型呢。11月1号第一批在最多20秒之后就……没有了。
+于是只好等11月11号。</p>
+<p>11月11号的开卖时间是凌晨0点。这对在23:00以后只能在宿舍玩手机的我是极大的一个不利。0点过去了,
+小米官网的购买通道果然进入了预期中的无限排队模式。无奈只好试一下小米的×猫官方旗舰店,发现还有货,
+不过只剩下了 6/128 和 8/256 的型号。这就让本来计划购买 8/128
+版本的我十分为难了。后来在
+「既然已经被小米坑了3000多元了,再多被坑400元也不是什么大问题」的思想的唆使下,剁了
+8/256 的型号。 (于是永远被浪费掉得存储空间变得更多了)</p>
<h2 id="tocanch3" class="tvis">到货</h2>
-<p>付款之后,小米迟迟没有发货的迹象。直到15号我的飞机已经在香港落地之后货才发出。当然顺丰依然是跟往常一样快, 似乎根本没有受到「双十一」<a id="n7" href="#note7" class="note">[7]</a>的影响, 第二天就到货了。托了一个同学帮忙去取。他在拿到快递之后的第一句话是「包装好简陋啊」。嗯……不祥的预感。</p>
-<p>从香港回来之后看到了静静躺在我的桌子上的 MIX 3 包装盒,还有一张「价值300元」 <a id="n8" href="#note8" class="note">[8]</a>的小米移动电话卡。开箱做了各种检查之后,发现不幸并没有降临在我的头上。 真是万幸(</p>
+<p>付款之后,小米迟迟没有发货的迹象。直到15号我的飞机已经在香港落地之后货才发出。当然顺丰依然是跟往常一样快,
+似乎根本没有受到「双十一」<a id="n7" href="#note7" class="note">[7]</a>的影响,
+第二天就到货了。托了一个同学帮忙去取。他在拿到快递之后的第一句话是「包装好简陋啊」。嗯……不祥的预感。</p>
+<p>从香港回来之后看到了静静躺在我的桌子上的 MIX 3
+包装盒,还有一张「价值300元」
+<a id="n8" href="#note8" class="note">[8]</a>的小米移动电话卡。开箱做了各种检查之后,发现不幸并没有降临在我的头上。
+真是万幸(</p>
<h2 id="tocanch4" class="tvis">第一印象</h2>
<ul>
-<li>重。MIX 3 用了一段时间再次拿起 Galaxy Note 4 的时候,会觉得塑料壳手机好轻(</li>
-<li>滑。后盖简直可以当镜子用。比塑料壳手机看起来不知道要高到那里去了。<del>然而滑到不加壳根本不敢用,所以最后还是塑料壳手机。</del> 同时后壳还是指纹收集器。</li>
+<li>重。MIX 3 用了一段时间再次拿起 Galaxy Note 4
+的时候,会觉得塑料壳手机好轻(</li>
+<li>滑。后盖简直可以当镜子用。比塑料壳手机看起来不知道要高到那里去了。<del>然而滑到不加壳根本不敢用,所以最后还是塑料壳手机。</del>
+同时后壳还是指纹收集器。</li>
</ul>
-<p>整部手机的外形尺寸与 Galaxy Note 4 几乎一致(宽度稍窄,长度略长),却比 Galaxy Note 4 重了 25%。 「半斤米」真是名不虚传。</p>
-<p>没有遇到网传的屏幕左右晃动问题。我手里这台的屏幕晃动幅度不比任何一台曾经用过的滑盖手机大。 1080p 的屏幕当然没有 1440p 的细腻,但是「又不是不能用」(</p>
-<p>至于被小米吹爆的拍照,感觉实际表现一般般。下面这张是从辣鸡专科学校宿舍里拍的 (point-and-shoot,全为自动设定)。 作为对比,右边一张是 Galaxy Note 4 <a id="n9" href="#note9" class="note">[9]</a> 拍的。 (其实我关掉过拍照水印。但是为了拍这张照片专门恢复了全部初始设定。另外我认为拍照上打水印属于作弊行为 —— 与考试在试卷上做答题以外的记号毫无区别。)</p>
+<p>整部手机的外形尺寸与 Galaxy Note 4
+几乎一致(宽度稍窄,长度略长),却比 Galaxy Note 4 重了 25%。
+「半斤米」真是名不虚传。</p>
+<p>没有遇到网传的屏幕左右晃动问题。我手里这台的屏幕晃动幅度不比任何一台曾经用过的滑盖手机大。
+1080p 的屏幕当然没有 1440p 的细腻,但是「又不是不能用」(</p>
+<p>至于被小米吹爆的拍照,感觉实际表现一般般。下面这张是从辣鸡专科学校宿舍里拍的
+(point-and-shoot,全为自动设定)。 作为对比,右边一张是 Galaxy Note 4
+<a id="n9" href="#note9" class="note">[9]</a> 拍的。
+(其实我关掉过拍照水印。但是为了拍这张照片专门恢复了全部初始设定。另外我认为拍照上打水印属于作弊行为
+—— 与考试在试卷上做答题以外的记号毫无区别。)</p>
<p>(图丢了,请自行想象两个不同时期的菜鸡互啄的场景(不是))</p>
-<p>与人眼的感受相比,MIX 3 的图像明显过亮。相比之下 Galaxy Note 4 的结果更接近实际感受(噪点数量不接近)。 <del>至于什么 DxOMark,都是钱买来的,当笑话看就好。</del> <a id="n10" href="#note10" class="note">[10]</a></p>
+<p>与人眼的感受相比,MIX 3 的图像明显过亮。相比之下 Galaxy Note 4
+的结果更接近实际感受(噪点数量不接近)。 <del>至于什么
+DxOMark,都是钱买来的,当笑话看就好。</del> <a id="n10" href="#note10" class="note">[10]</a></p>
<h2 id="tocanch5" class="tvis">「偷工减料」和「虚假宣传」</h2>
<p>首先放一张扫图跟官方渲染图的叠加照片</p>
<div style="position:relative;top:0;left:0;">
-<p><img style="position:relative;top:0;left:0;opacity:0.5;z-index:0;" id="s" width="400" src="//filestorage.chrisoft.org/blog/img/mix3_woprotectcover.png" decoding="async"> <img style="position:absolute;top:0;left:2px;opacity:0.5;z-index:1;" id="r" width="396" src="//filestorage.chrisoft.org/blog/img/mix3_render.png" decoding="async"></p>
+<p><img style="position:relative;top:0;left:0;opacity:0.5;z-index:0;" id="s" width="400" src="//filestorage.chrisoft.org/blog/img/mix3_woprotectcover.png" decoding="async">
+<img style="position:absolute;top:0;left:2px;opacity:0.5;z-index:1;" id="r" width="396" src="//filestorage.chrisoft.org/blog/img/mix3_render.png" decoding="async"></p>
</div>
<p><input style="width:100%" type="range" min="0" max="100" value="50" oninput="document.getElementById('r').style.opacity=this.value/100;document.getElementById('s').style.opacity=1-this.value/100;"></p>
-<p>可以看到,四侧边框均有所膨胀(由于对齐问题,左侧的边框看起来似乎比右侧膨胀得多些)。 作为一个3元的方便面包装上能画出牛肉的国家的公民,对这样的「虚假宣传」当然是司空见惯。 但是毕竟苹果都不会拿渲染图来糊弄人,小米这种「果粉」企业,就不能从苹果身上学点好东西吗(</p>
-<p>另外在官网参数的传感器一栏,MIX 3 似乎缺少了气压计和霍尔传感器。当时我在付款后才发现这点。 于是对阉割旗舰机传感器的小米感到失望。然而机器到手之后,发现实际上是有这两个传感器的。 <del>这应该也算虚假宣传吧?</del></p>
-<p>最后,看到 gsmarena 上写的屏幕玻璃是 Corning Gorilla Glass (unspecified version) 就感到了一丝不安。 没过多久我刚离开桌子几步手机就(由于未知的原因)从桌子上掉了下去。背面着地,捡起来一看好像没事。(还好已经套了壳,不然……) 过了几天仔细观察才发现屏幕上已经有了划痕(一处相对不明显的面积约中号记号笔点一个点那么大,另一处是一个凹坑)。 已知是 Corning Gorilla Glass 4 的 Galaxy Note 4 用了一年半还没有什么肉眼可见的划痕。嗯……可以确定 MIX 3 的屏幕玻璃肯定不是 Corning Gorilla Glass 4 了。 <a id="n11" href="#note11" class="note">[11]</a></p>
-<p>19年2月14日更新: gsmarena 上更新了信息,发现确实不是 Corning Gorilla Glass 4,而是 Corning Gorilla Glass 5 。 看来还是怪我我艹机太狠了(<a id="n12" href="#note12" class="note">[12]</a></p>
+<p>可以看到,四侧边框均有所膨胀(由于对齐问题,左侧的边框看起来似乎比右侧膨胀得多些)。
+作为一个3元的方便面包装上能画出牛肉的国家的公民,对这样的「虚假宣传」当然是司空见惯。
+但是毕竟苹果都不会拿渲染图来糊弄人,小米这种「果粉」企业,就不能从苹果身上学点好东西吗(</p>
+<p>另外在官网参数的传感器一栏,MIX 3
+似乎缺少了气压计和霍尔传感器。当时我在付款后才发现这点。
+于是对阉割旗舰机传感器的小米感到失望。然而机器到手之后,发现实际上是有这两个传感器的。
+<del>这应该也算虚假宣传吧?</del></p>
+<p>最后,看到 gsmarena 上写的屏幕玻璃是 Corning Gorilla Glass
+(unspecified version) 就感到了一丝不安。
+没过多久我刚离开桌子几步手机就(由于未知的原因)从桌子上掉了下去。背面着地,捡起来一看好像没事。(还好已经套了壳,不然……)
+过了几天仔细观察才发现屏幕上已经有了划痕(一处相对不明显的面积约中号记号笔点一个点那么大,另一处是一个凹坑)。
+已知是 Corning Gorilla Glass 4 的 Galaxy Note 4
+用了一年半还没有什么肉眼可见的划痕。嗯……可以确定 MIX 3
+的屏幕玻璃肯定不是 Corning Gorilla Glass 4 了。
+<a id="n11" href="#note11" class="note">[11]</a></p>
+<p>19年2月14日更新: gsmarena 上更新了信息,发现确实不是 Corning Gorilla
+Glass 4,而是 Corning Gorilla Glass 5 。
+看来还是怪我我艹机太狠了(<a id="n12" href="#note12" class="note">[12]</a></p>
<h2 id="tocanch6" class="tvis">换掉令人<sup>我</sup>痛苦的 MIUI</h2>
<p>可以说 MIUI 是我关于这台手机最担心的特性了。</p>
-<p>说实话只要不是北朝鲜那种不准安装任何第三方应用的安卓机,好像都可以凑合用一下。 但是花那么多钱买来的手机肯定还是要自己怎么舒服怎么用的(</p>
-<p>因为我个人的手机使用习惯与 &gt;90% 的国人都不同,所以 MIUI 的许多优势特性我都体会不到。 而且小米手机的硬件本身又不像 Galaxy Note 一样提供与可以将它和其他手机一下子区分开的功能 <a id="n13" href="#note13" class="note">[13]</a>, 所以直接解锁手机换掉系统并不会让我对 MIUI 有任何留恋。</p>
-<p>于是就开始换系统吧。首先就是要解锁 bootloader。我对手机厂商锁住 bootloader 的做法是完全不在意的 – 在不影响我换系统的前提下<a id="n14" href="#note14" class="note">[14]</a>。 由于以前使用小米 MAX 的时候解锁过手机,所以不需要重新申请解锁资格。打开当时的解锁工具, 连接上处于 fastboot 模式的手机,点一下解锁……本来以为就这么简单的,结果要我换最新的解锁工具。 「还能不让我解锁不成」,我想道。然后就照做了,紧接着就撞上了小米最新的防……我也不知道他们在防什么用的技巧:</p>
+<p>说实话只要不是北朝鲜那种不准安装任何第三方应用的安卓机,好像都可以凑合用一下。
+但是花那么多钱买来的手机肯定还是要自己怎么舒服怎么用的(</p>
+<p>因为我个人的手机使用习惯与 &gt;90% 的国人都不同,所以 MIUI
+的许多优势特性我都体会不到。 而且小米手机的硬件本身又不像 Galaxy Note
+一样提供与可以将它和其他手机一下子区分开的功能
+<a id="n13" href="#note13" class="note">[13]</a>,
+所以直接解锁手机换掉系统并不会让我对 MIUI 有任何留恋。</p>
+<p>于是就开始换系统吧。首先就是要解锁 bootloader。我对手机厂商锁住
+bootloader 的做法是完全不在意的 –
+在不影响我换系统的前提下<a id="n14" href="#note14" class="note">[14]</a>。
+由于以前使用小米 MAX
+的时候解锁过手机,所以不需要重新申请解锁资格。打开当时的解锁工具,
+连接上处于 fastboot
+模式的手机,点一下解锁……本来以为就这么简单的,结果要我换最新的解锁工具。
+「还能不让我解锁不成」,我想道。然后就照做了,紧接着就撞上了小米最新的防……我也不知道他们在防什么用的技巧:</p>
<p><a href="//filestorage.chrisoft.org/blog/img/lajixiaomi.png"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_lajixiaomi.png"></a></p>
-<p>还好我只需要等三天。论坛里看到有些要等十五天甚至三十天的就比较惨了 <a id="n15" href="#note15" class="note">[15]</a>。</p>
+<p>还好我只需要等三天。论坛里看到有些要等十五天甚至三十天的就比较惨了
+<a id="n15" href="#note15" class="note">[15]</a>。</p>
<p>我的不自愿三天 MIUI 体验就这么开始了。</p>
-<p>虽然以前用过小米的手机,但是因为对充满 iOS 味的 MIUI 的抵制,所以实际交互时间可能不到 12 个小时。 这次发现好像除了整个系统弥漫着果味和几个小 bug 之外,好像明确可以指出的缺点也没那么多 —— 至少在登录 Google 账号,换掉没有 App drawer 的 MIUI 默认 launcher 之后还是可以凑合用的。</p>
-<p>至于前面提到的小 bug,大概都是些许多人都碰不到的毛病。因为用手机习惯把控件大小调小些用, 所以拿到之后第一步就是去设置里找显示大小的选项。然而在当时版本的系统里并没有发现这个选项 <a id="n16" href="#note16" class="note">[16]</a>。于是我就只好去开发者选项里调最小宽度了。 调完之后就出现了各种奇怪的状况……</p>
-<p>各种界面元素错位还有莫名其妙被砍了一刀的图标什么的。顺便右边的图里还有我这三天中看到的唯一一条 M(A)I(D)UI 广告,看到之后内置浏览器就被我设法禁用了。当然,这些问题远未达到影响正常使用的程度,只是看起来不爽罢了。</p>
-<p>MIUI 体验日的最后一天,收到一个 OTA。装上之后发现图标里出白框的毛病没有了,但是界面元素错位的问题还在。 此时我早已不在乎这些小毛病 —— 因为马上就可以刷机了。</p>
-<p>托 Project Treble 的福,这台刚出的设备也有很大概率能找到适合日常使用的第三方系统。 行动的时间到了,解锁,刷 vbmeta ,刷 A/B device 用的 system<a id="n17" href="#note17" class="note">[17]</a></p>
+<p>虽然以前用过小米的手机,但是因为对充满 iOS 味的 MIUI
+的抵制,所以实际交互时间可能不到 12 个小时。
+这次发现好像除了整个系统弥漫着果味和几个小 bug
+之外,好像明确可以指出的缺点也没那么多 —— 至少在登录 Google
+账号,换掉没有 App drawer 的 MIUI 默认 launcher
+之后还是可以凑合用的。</p>
+<p>至于前面提到的小
+bug,大概都是些许多人都碰不到的毛病。因为用手机习惯把控件大小调小些用,
+所以拿到之后第一步就是去设置里找显示大小的选项。然而在当时版本的系统里并没有发现这个选项
+<a id="n16" href="#note16" class="note">[16]</a>。于是我就只好去开发者选项里调最小宽度了。
+调完之后就出现了各种奇怪的状况……</p>
+<p>各种界面元素错位还有莫名其妙被砍了一刀的图标什么的。顺便右边的图里还有我这三天中看到的唯一一条
+M(A)I(D)UI
+广告,看到之后内置浏览器就被我设法禁用了。当然,这些问题远未达到影响正常使用的程度,只是看起来不爽罢了。</p>
+<p>MIUI 体验日的最后一天,收到一个
+OTA。装上之后发现图标里出白框的毛病没有了,但是界面元素错位的问题还在。
+此时我早已不在乎这些小毛病 —— 因为马上就可以刷机了。</p>
+<p>托 Project Treble
+的福,这台刚出的设备也有很大概率能找到适合日常使用的第三方系统。
+行动的时间到了,解锁,刷 vbmeta ,刷 A/B device 用的
+system<a id="n17" href="#note17" class="note">[17]</a></p>
<h2 id="tocanch7" class="tvis">终于,小米脱掉了……</h2>
<p>我给它戴上的「二流品牌」的帽子?</p>
<p>也许还没有。至少没有完全脱掉。</p>
<hr>
-<p>2021-01-30: 因为个人无限的拖延,这篇文章可能永远也无法完成了……因为现在再写的话就不叫上手体验了。</p>
-<p>那么说下这两年来的使用感受吧。实际上纯粹使用MIX 3的时间可能也就一年半多一点,因为大部分时间是同时带着 Galaxy Note 4和MIX 3的(当然Galaxy Note 4的角色基本沦为了刷机刷砖或者送修时的备用机)。 中间用过数种不同的系统:Pixel Experience, Resurrection Remix, (自己编译的和别人编译的)Lineage OS, Arrow OS,甚至 Google 的 AOSP GIS,当然少不了 xiaomi.eu 和国行的MIUI。</p>
+<p>2021-01-30:
+因为个人无限的拖延,这篇文章可能永远也无法完成了……因为现在再写的话就不叫上手体验了。</p>
+<p>那么说下这两年来的使用感受吧。实际上纯粹使用MIX
+3的时间可能也就一年半多一点,因为大部分时间是同时带着 Galaxy Note 4和MIX
+3的(当然Galaxy Note 4的角色基本沦为了刷机刷砖或者送修时的备用机)。
+中间用过数种不同的系统:Pixel Experience, Resurrection Remix,
+(自己编译的和别人编译的)Lineage OS, Arrow OS,甚至 Google 的 AOSP
+GIS,当然少不了 xiaomi.eu 和国行的MIUI。</p>
<p>在武汉的时候用国行MIUI里的小米钱包刷过几次地铁,是有点厉害。不过后来还是滚回了老套的支付方式。</p>
-<p>用得最久的当然还是Lineage OS。主要原因还是他们的基础设施和编译指南文档都不错,想自己做点小定制也容易。 事实上如今的Lineage OS,在CM挂掉经历了数次功能上的阉割后,已经与AOSP相差无几了。当然对我这种 <code>~/bin</code> 里好几十个自制脚本,<code>.zshrc</code> 里也有好多自制函数的用户来说,问题并不大。再加上平时用的国产流氓应用极少 (TIM和微信)以及我有独特的制伏国产流氓应用的技巧,就这么一直用下来了。至于别人说的bug多, 也许是因为我的手机基本只有打电话看网页刷reddit的功能,并没有遇到过因为系统bug导致掉链子的事情。 (我坚信微信的任何问题都必然是疼讯的问题(</p>
+<p>用得最久的当然还是Lineage
+OS。主要原因还是他们的基础设施和编译指南文档都不错,想自己做点小定制也容易。
+事实上如今的Lineage
+OS,在CM挂掉经历了数次功能上的阉割后,已经与AOSP相差无几了。当然对我这种
+<code>~/bin</code> 里好几十个自制脚本,<code>.zshrc</code>
+里也有好多自制函数的用户来说,问题并不大。再加上平时用的国产流氓应用极少
+(TIM和微信)以及我有独特的制伏国产流氓应用的技巧,就这么一直用下来了。至于别人说的bug多,
+也许是因为我的手机基本只有打电话看网页刷reddit的功能,并没有遇到过因为系统bug导致掉链子的事情。
+(我坚信微信的任何问题都必然是疼讯的问题(</p>
<p>接下来说说售后和手机本身的质量吧。</p>
<ul>
<li>滑盖的缝里能插纸,这已经不是什么新鲜事了<a id="n18" href="#note18" class="note">[18]</a></li>
@@ -131,25 +236,66 @@ function ol()
<li>使用一年多后,有一片“匚”形金属片从滑盖机关中掉落出来,但似乎并未对滑盖功能造成影响。</li>
<li>一年半时从约1.2米处摔落,屏幕一角的玻璃破碎。</li>
</ul>
-<p>虽然都是些边边角角的小问题,对日常使用影响不大(玻璃碎了除外)。看到小米有399换屏幕玻璃的维修项目, 还是选择换了屏幕玻璃。送修之前做了factory reset。从学校寄到天津维修工厂之后被通知玻璃更换需要转寄到深圳工厂, 从寄出到重新拿到手总共花了一周时间。比较令人欣慰的是小米的维修工厂保留了我的第三方系统(尽管我跟客服说了可以刷机)。 然而使用不过一个月之后,屏幕却完全无法显示了(有数条水平亮线)。听说小米有维修后保修一个月的政策, 于是决定尝试再修一次。手机被天津维修工厂收到之后,被通知查不到维修记录,需要寄到上次维修的工厂。如此一来, 这次维修又花了一周。这次维修我的第三方系统仍然得以保留,而且算下来我只用了400元就换掉了整个屏幕总成 (原价850)……</p>
+<p>虽然都是些边边角角的小问题,对日常使用影响不大(玻璃碎了除外)。看到小米有399换屏幕玻璃的维修项目,
+还是选择换了屏幕玻璃。送修之前做了factory
+reset。从学校寄到天津维修工厂之后被通知玻璃更换需要转寄到深圳工厂,
+从寄出到重新拿到手总共花了一周时间。比较令人欣慰的是小米的维修工厂保留了我的第三方系统(尽管我跟客服说了可以刷机)。
+然而使用不过一个月之后,屏幕却完全无法显示了(有数条水平亮线)。听说小米有维修后保修一个月的政策,
+于是决定尝试再修一次。手机被天津维修工厂收到之后,被通知查不到维修记录,需要寄到上次维修的工厂。如此一来,
+这次维修又花了一周。这次维修我的第三方系统仍然得以保留,而且算下来我只用了400元就换掉了整个屏幕总成
+(原价850)……</p>
<p>当然小米的售后也不是没有问题的……:</p>
<ul>
-<li>线下售后对MIX 3这种小众机型几乎相当于毫无作用。他们无法提供任何检查和零件更换服务。</li>
+<li>线下售后对MIX
+3这种小众机型几乎相当于毫无作用。他们无法提供任何检查和零件更换服务。</li>
<li>维修后,屏幕边缘的塑料边框上有几处被刀片划伤的痕迹。</li>
<li>第二次返修后,后盖没有完全合上。</li>
</ul>
-<p>第二次修完后,还有一段小故事:没过两天手机掉进装满水的盆子里了。虽然没过两秒就捞了出来, 不过因为当时还没有发现后盖没有完全合上,所以……</p>
-<p>随后很快就发现了后盖没有合上(而且也相当于是因祸得福了)。 于是立刻把手机拆了个稀烂然后和几包干燥剂一起放在密封袋中置于北京滚烫的暖气上。放了大约四个多小时之后, 袋中不再出现水汽。于是重新组装起来,战战兢兢地使用到现在(三个月),暂时还没有爆炸(</p>
-<p>再扯点别的东西吧。如今的手机厂商,都一心想着如何出头露面,做出来的设计和功能,十有八九无非只是噱头。 从所谓的全面屏,到五花八门的异形屏,对实际的交互和观感的改进,都基本可以忽略不计 (观感方面,异形屏甚至可以说是相当大的破坏——当然观感是主观感受)。手机背面的摄像头从一个变成两个三个甚至四五个, 手里这台DxOMark曾经第一的手机却还是连个电路板都拍不清楚,也是不知让人从何说起。充电速度也变成了纯粹的数字竞争。 真不知道再换手机的时候这里将是什么样的一派景象。</p>
-<p>至于小米,起初作为「搅局者」,起到的作用自然不可小觑。在更加深入地了解手机从硬件到系统开发的流程和成本后, 小米能把手机价格压到这个水平,也是相当令人印象深刻的。当然小米不会就这么容易地放弃利润,这些压下来的价格, 还是要通过各种方式赚回来的。不过对于我这种买手机只是买硬件,对于自带软件,包括系统,则一视同仁地直接抹掉的用户, 小米之流就无法从我这里赚到什么东西了。</p>
-<p>当然还有Pinephone, Librem 5这类的「搅局者」。这些设备一旦售出,用户和厂商基本就不会产生金钱上的关系了。 于是回本的重任就全都落到了售价上。这也导致了这些机型(相对它们的配置)高到离谱的售价。即便售价下来以后, 考虑到它们的可用度,现在将这类机型作为日常机型对我个人来说还是为时尚早。</p>
+<p>第二次修完后,还有一段小故事:没过两天手机掉进装满水的盆子里了。虽然没过两秒就捞了出来,
+不过因为当时还没有发现后盖没有完全合上,所以……</p>
+<p>随后很快就发现了后盖没有合上(而且也相当于是因祸得福了)。
+于是立刻把手机拆了个稀烂然后和几包干燥剂一起放在密封袋中置于北京滚烫的暖气上。放了大约四个多小时之后,
+袋中不再出现水汽。于是重新组装起来,战战兢兢地使用到现在(三个月),暂时还没有爆炸(</p>
+<p>再扯点别的东西吧。如今的手机厂商,都一心想着如何出头露面,做出来的设计和功能,十有八九无非只是噱头。
+从所谓的全面屏,到五花八门的异形屏,对实际的交互和观感的改进,都基本可以忽略不计
+(观感方面,异形屏甚至可以说是相当大的破坏——当然观感是主观感受)。手机背面的摄像头从一个变成两个三个甚至四五个,
+手里这台DxOMark曾经第一的手机却还是连个电路板都拍不清楚,也是不知让人从何说起。充电速度也变成了纯粹的数字竞争。
+真不知道再换手机的时候这里将是什么样的一派景象。</p>
+<p>至于小米,起初作为「搅局者」,起到的作用自然不可小觑。在更加深入地了解手机从硬件到系统开发的流程和成本后,
+小米能把手机价格压到这个水平,也是相当令人印象深刻的。当然小米不会就这么容易地放弃利润,这些压下来的价格,
+还是要通过各种方式赚回来的。不过对于我这种买手机只是买硬件,对于自带软件,包括系统,则一视同仁地直接抹掉的用户,
+小米之流就无法从我这里赚到什么东西了。</p>
+<p>当然还有Pinephone, Librem
+5这类的「搅局者」。这些设备一旦售出,用户和厂商基本就不会产生金钱上的关系了。
+于是回本的重任就全都落到了售价上。这也导致了这些机型(相对它们的配置)高到离谱的售价。即便售价下来以后,
+考虑到它们的可用度,现在将这类机型作为日常机型对我个人来说还是为时尚早。</p>
<p>所以这篇体验文写了两年多最后还是这么烂,以后还是不要写这种东西了。</p>
</article>
<!--
vim: tw=0 syntax=markdown
-->
</div><br><hr>
- <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: <del>听音乐只能听到_Hi_-hat,所以是_Hi_-Res Audio(</del><br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: 圆角屏幕并不在此列<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: 将符合上面三条的手机筛选出来,你会发现某水果公司生产的奢侈品赫然在列。 当然原因并不全是因为我是 “Apple Hater”,主要还是对其他厂商无故跟风的嫌弃(<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: <s>主要是不想要一台比旧手机屏幕更差的新机(</s><br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: <del>全怪苹果恶意哄抬物价</del> 尽管三星的旧机型价格跳水仍然很厉害,然而这次不太想买过时平台的机型了。<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: 我曾经宣称到手就会吧屏幕用502粘起来, 但是现在发现玩起来找回了当年玩高中同学的 Nokia X3 的感觉(lbz是不是打喷嚏了),所以就没有粘。<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: 有人能告诉我这个东西是怎么被硬生生地从无到有造出来的吗?<br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: 实际价值&lt;10元<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: 非官方系统 (LineageOS 15.1)<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: <a href="https://www.gsmarena.com/dxomark_the_iphone_xr_is_unrivaled_among_singlecamera_phones-news-34592.php">一向看不上DxOMark的苹果最终忍不住也来给他们塞钱了</a><br></span><span class="TText"><a id="note11" href="#n11">[11]</a>: 我从不把手机和钥匙放在一起。唯一跟 MIX 3 放在一起的就是 Galaxy Note 4。塑料不可能划伤玻璃, 有作案能力的只剩 Note 4 可怜的两圈金属边框了。<br></span><span class="TText"><a id="note12" href="#n12">[12]</a>: 不过我怎么艹机了来着?(<br></span><span class="TText"><a id="note13" href="#n13">[13]</a>: 这类硬件一般在通用的第三方系统下的集成支持都远不如官方系统。若是读者认为小米的滑盖属于此列, 我只能提醒一句数位屏能提供的交互量跟滑盖应该不是在一个数量级上的。<br></span><span class="TText"><a id="note14" href="#n14">[14]</a>: 某爱国厂 —— shame on you!<br></span><span class="TText"><a id="note15" href="#n15">[15]</a>: <a href="https://en.miui.com/forum.php?mod=viewthread&amp;tid=3806453&amp;highlight=bootloader%2Bunlock%2B72%2Bhours">[1]</a> <a href="https://www.miui.com/forum.php?mod=viewthread&amp;tid=21323385&amp;highlight=%E8%A7%A3%E9%94%81%2Bbootloader">[2]</a> <a href="https://www.miui.com/forum.php?mod=viewthread&amp;tid=18163530&amp;highlight=%E8%A7%A3%E9%94%81%2Bbootloader">[3]</a> <br></span><span class="TText"><a id="note16" href="#n16">[16]</a>: 后来我还去小米之家把所有展示机看了一遍,三台小米 MIX 3 里只有一台没有此选项, 其他机型的展示机基本都有<br></span><span class="TText"><a id="note17" href="#n17">[17]</a>: 小米 MIX 3 不是使用 A/B 分区模式的设备, 但是因为 Android Pie 出现之前 Android 要求采用 A/B Update 的设备合并 ramdisk (/) 和 /system (即 <a href="https://source.android.com/devices/bootloader/system-as-root">System-as-root</a>), 所以 Treble GSI 的开发者直接使用 a/ab 来区分 system 镜像是否包含 ramdisk。 而 Android Pie 发布后,Android 要求所有发布时搭载 Android Pie 的设备使用 System-as-root 分区方案。 所以这里也需要用标注为 ab 的GSI镜像。<br></span><span class="TText"><a id="note18" href="#n18">[18]</a>: <s>其实插个登机牌什么的还挺有用的</s><a id="n19" href="#note19" class="note">[19]</a><br></span><span class="TText"><a id="note19" href="#n19">[19]</a>: 。<br></span></div>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: <del>听音乐只能听到_Hi_-hat,所以是_Hi_-Res
+Audio(</del><br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: 圆角屏幕并不在此列<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: 将符合上面三条的手机筛选出来,你会发现某水果公司生产的奢侈品赫然在列。
+当然原因并不全是因为我是 “Apple
+Hater”,主要还是对其他厂商无故跟风的嫌弃(<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: <s>主要是不想要一台比旧手机屏幕更差的新机(</s><br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: <del>全怪苹果恶意哄抬物价</del>
+尽管三星的旧机型价格跳水仍然很厉害,然而这次不太想买过时平台的机型了。<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: 我曾经宣称到手就会吧屏幕用502粘起来,
+但是现在发现玩起来找回了当年玩高中同学的 Nokia X3
+的感觉(lbz是不是打喷嚏了),所以就没有粘。<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: 有人能告诉我这个东西是怎么被硬生生地从无到有造出来的吗?<br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: 实际价值&lt;10元<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: 非官方系统 (LineageOS 15.1)<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: <a href="https://www.gsmarena.com/dxomark_the_iphone_xr_is_unrivaled_among_singlecamera_phones-news-34592.php">一向看不上DxOMark的苹果最终忍不住也来给他们塞钱了</a><br></span><span class="TText"><a id="note11" href="#n11">[11]</a>: 我从不把手机和钥匙放在一起。唯一跟 MIX 3 放在一起的就是 Galaxy
+Note 4。塑料不可能划伤玻璃, 有作案能力的只剩 Note 4
+可怜的两圈金属边框了。<br></span><span class="TText"><a id="note12" href="#n12">[12]</a>: 不过我怎么艹机了来着?(<br></span><span class="TText"><a id="note13" href="#n13">[13]</a>: 这类硬件一般在通用的第三方系统下的集成支持都远不如官方系统。若是读者认为小米的滑盖属于此列,
+我只能提醒一句数位屏能提供的交互量跟滑盖应该不是在一个数量级上的。<br></span><span class="TText"><a id="note14" href="#n14">[14]</a>: 某爱国厂 —— shame on you!<br></span><span class="TText"><a id="note15" href="#n15">[15]</a>: <a href="https://en.miui.com/forum.php?mod=viewthread&amp;tid=3806453&amp;highlight=bootloader%2Bunlock%2B72%2Bhours">[1]</a>
+<a href="https://www.miui.com/forum.php?mod=viewthread&amp;tid=21323385&amp;highlight=%E8%A7%A3%E9%94%81%2Bbootloader">[2]</a>
+<a href="https://www.miui.com/forum.php?mod=viewthread&amp;tid=18163530&amp;highlight=%E8%A7%A3%E9%94%81%2Bbootloader">[3]</a>
+<br></span><span class="TText"><a id="note16" href="#n16">[16]</a>: 后来我还去小米之家把所有展示机看了一遍,三台小米 MIX 3
+里只有一台没有此选项,
+其他机型的展示机基本都有<br></span><span class="TText"><a id="note17" href="#n17">[17]</a>: 小米 MIX 3 不是使用 A/B 分区模式的设备, 但是因为
+Android Pie 出现之前 Android 要求采用 A/B Update 的设备合并 ramdisk (/)
+和 /system (即 <a href="https://source.android.com/devices/bootloader/system-as-root">System-as-root</a>),
+所以 Treble GSI 的开发者直接使用 a/ab 来区分 system 镜像是否包含
+ramdisk。 而 Android Pie 发布后,Android 要求所有发布时搭载 Android Pie
+的设备使用 System-as-root 分区方案。 所以这里也需要用标注为 ab
+的GSI镜像。<br></span><span class="TText"><a id="note18" href="#n18">[18]</a>: <s>其实插个登机牌什么的还挺有用的</s><a id="n19" href="#note19" class="note">[19]</a><br></span><span class="TText"><a id="note19" href="#n19">[19]</a>: 。<br></span></div>
<div id="insanch" style="height:3em;"></div>
<div id="footer" style="">
<div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
diff --git a/blog/post/2019-02-13.html b/blog/post/2019-02-13.html
index 64094ee..b947258 100644
--- a/blog/post/2019-02-13.html
+++ b/blog/post/2019-02-13.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Site Revamp and Other Rants -- 2019 Edition")</title>
+<meta name="description" content="«Site Revamp and Other Rants -- 2019 Edition» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -81,7 +51,10 @@ loadTheme();
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">Mirror in Japan</a></li><li><a class="toctarg" href="#tocanch1">An Eruditus from Waseda and An Illiterate in China</a></li><li><a class="toctarg" href="#tocanch2">A world in which everyone can program</a></li><li><a class="toctarg" href="#tocanch3">The world of smartphone...</a></li><li><a class="toctarg" href="#tocanch4">Googlephobia</a></li><li><a class="toctarg" href="#tocanch5">Software Subscription Model Sucks</a></li></ul>
+ <li><a class="toctarg" href="#tocanch0">Mirror in Japan</a></li><li><a class="toctarg" href="#tocanch1">An Eruditus
+from Waseda and An Illiterate in China</a></li><li><a class="toctarg" href="#tocanch2">A world in which everyone
+can program</a></li><li><a class="toctarg" href="#tocanch3">The world of smartphone…</a></li><li><a class="toctarg" href="#tocanch4">Googlephobia</a></li><li><a class="toctarg" href="#tocanch5">Software Subscription Model
+Sucks</a></li></ul>
</li>
<li style="margin-left:-0.5em"><a id="prevp" href="2018-12-06.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2019-04-25.html">Next post</a></li>
@@ -91,49 +64,120 @@ loadTheme();
<h2 id="titleh" class="TText" style="font-wight:normal;">Site Revamp and Other Rants -- 2019 Edition</h2>
<div id="datetags" class="TText" style="margin-bottom:1em;">2019-02-13<br>#web #random-xp #garbage</div>
<hr><div id="article" class="TText"><article>
-<p>If you are reading this, your browser probably fetched all data it required to display the page directly from my VPS hosted by ConoHa.</p>
+<p>If you are reading this, your browser probably fetched all data it
+required to display the page directly from my VPS hosted by ConoHa.</p>
<h2 id="tocanch0" class="tvis">Mirror in Japan</h2>
<p>(No pun intended)</p>
-<p>I set up my own git server half a year ago. Now I've found <a href="https://cgit.chrisoft.org/web.git/">the perfect use for it</a>. I create the git repository right in <code>/var/www/html</code> on my local server. The remote server has a post-receive hook that automatically pulls in the document root. Any volatile large files are moved to a new virtual host <code>filestorage.chrisoft.org</code> and kept in sync with <code>rsync</code>.</p>
-<p>The site also underwent a major cleanup. Many legacy stuff got either removed or relocated.</p>
-<p>Generally this means you should experience major speedup visiting this site. If, however, you are exeriencing problems, please do not hesitate to contact me.</p>
-<p>The reverse proxy is now moved to <code>rp.chrisoft.org</code>. It's not yet accessible at the time of writing because my local server is hidden super stealthily under multiple layers of NAT.</p>
-<h2 id="tocanch1" class="tvis">An Eruditus from Waseda and An Illiterate in China</h2>
+<p>I set up my own git server half a year ago. Now I’ve found <a href="https://cgit.chrisoft.org/web.git/">the perfect use for it</a>. I
+create the git repository right in <code>/var/www/html</code> on my
+local server. The remote server has a post-receive hook that
+automatically pulls in the document root. Any volatile large files are
+moved to a new virtual host <code>filestorage.chrisoft.org</code> and
+kept in sync with <code>rsync</code>.</p>
+<p>The site also underwent a major cleanup. Many legacy stuff got either
+removed or relocated.</p>
+<p>Generally this means you should experience major speedup visiting
+this site. If, however, you are exeriencing problems, please do not
+hesitate to contact me.</p>
+<p>The reverse proxy is now moved to <code>rp.chrisoft.org</code>. It’s
+not yet accessible at the time of writing because my local server is
+hidden super stealthily under multiple layers of NAT.</p>
+<h2 id="tocanch1" class="tvis">An Eruditus
+from Waseda and An Illiterate in China</h2>
<p>Everyone except me has made significant progress.</p>
-<p>I was actually shocked to learn that he's now majoring in something related to aviation machinery.</p>
+<p>I was actually shocked to learn that he’s now majoring in something
+related to aviation machinery.</p>
<p>Shame on me, I guess.</p>
-<h2 id="tocanch2" class="tvis">A world in which everyone can program</h2>
+<h2 id="tocanch2" class="tvis">A world in which everyone
+can program</h2>
<p>I shall probably quit programming and move on by then.</p>
-<h2 id="tocanch3" class="tvis">The world of smartphone...</h2>
-<p>... is now a wasteland. Literally all flagship models are mutants from the Chernobyl exclusion zone.</p>
+<h2 id="tocanch3" class="tvis">The world of smartphone…</h2>
+<p>… is now a wasteland. Literally all flagship models are mutants from
+the Chernobyl exclusion zone.</p>
<h2 id="tocanch4" class="tvis">Googlephobia</h2>
<p>Shit. They are probably also watching me writing this.</p>
-<p>Thanks to (?) the GrandeFreakWitless, my reliance on Google is not that strong -- nope. It's actually my general fear and distrust of those tech giants.</p>
-<p>My fear was magnified by my recent findings of just how much Google knows about me -- they probably know me better than myself; and again by Louis Rossmann <a id="n1" href="#note1" class="note">[1]</a>.</p>
-<p>When those Google fanboys are still enjoying the great convenience they provide, I'm already planning to flee from Google. It's probably just me being hyperallergic, but it also could be Google doing something really unfair to their users.</p>
-<h2 id="tocanch5" class="tvis">Software Subscription Model Sucks</h2>
-<p>Reading through Roland Cloud's product page triggers me everytime: I sincerely cannot figure out why they make it a subscription service rather than a one-time purchase (with a fee for each upgrade).</p>
+<p>Thanks to (?) the GrandeFreakWitless, my reliance on Google is not
+that strong – nope. It’s actually my general fear and distrust of those
+tech giants.</p>
+<p>My fear was magnified by my recent findings of just how much Google
+knows about me – they probably know me better than myself; and again by
+Louis Rossmann <a id="n1" href="#note1" class="note">[1]</a>.</p>
+<p>When those Google fanboys are still enjoying the great convenience
+they provide, I’m already planning to flee from Google. It’s probably
+just me being hyperallergic, but it also could be Google doing something
+really unfair to their users.</p>
+<h2 id="tocanch5" class="tvis">Software Subscription Model
+Sucks</h2>
+<p>Reading through Roland Cloud’s product page triggers me everytime: I
+sincerely cannot figure out why they make it a subscription service
+rather than a one-time purchase (with a fee for each upgrade).</p>
<p>Usually people subscribe for:</p>
<ul>
-<li>Publication or media services, e.g. television, newspapers and magazines. These services provide frequently updated information to the subscriber.</li>
+<li>Publication or media services, e.g.&nbsp;television, newspapers and
+magazines. These services provide frequently updated information to the
+subscriber.</li>
<li>Physically consumable material, such as dairy product.</li>
</ul>
-<p>Roland Cloud falls into neither of these two categories. It's not updated as frequent, and it's certainly not physically consumable. The most triggering detail is that if you end your subscription, you will not be able to use any of the products you previously owned, which is ridiculous because you can always keep older issues of a newspaper even you unsubscribed from it.</p>
-<p>Supporters of the subscription model may reject me saying 'if you can get access to everything when you join and keep it after unsubscribing, you are essentially purchasing it with ultra-low price', which brings up my next point: Roland Cloud's subscription model is flawed from the beginning:</p>
+<p>Roland Cloud falls into neither of these two categories. It’s not
+updated as frequent, and it’s certainly not physically consumable. The
+most triggering detail is that if you end your subscription, you will
+not be able to use any of the products you previously owned, which is
+ridiculous because you can always keep older issues of a newspaper even
+you unsubscribed from it.</p>
+<p>Supporters of the subscription model may reject me saying ‘if you can
+get access to everything when you join and keep it after unsubscribing,
+you are essentially purchasing it with ultra-low price’, which brings up
+my next point: Roland Cloud’s subscription model is flawed from the
+beginning:</p>
<ul>
-<li>Get everything on subscribe: this differs from traditional subscription a lot, which seems a great bounty to the customer. But it causes problems such as ...</li>
-<li>Lose everything on unsubscribe: this is <em>very</em> unfair to the subscriber and makes short-term subscription worth almost nothing. For example if I just want Sound Canvas VA really badly, I would imagine subscribing shortly before its release and unsubscribe after I'm eligible for keeping the product permanently. But this is simply not possible.</li>
-<li>Weird pricing. To be honest the current pricing is pretty fair for long-term subscribers. But if Roland somehow decided to fix the 'lose everything on unsubscribe' problem (which is very unlikely to happen), the pricing would become super complex: they probably do not want people to keep a virtual TB-303 for just $19.99.</li>
-<li>Potentially unsustainable. Every good thing must come to an end. The most attractive products in Roland Cloud is the software models of Roland's synthesizers from its golden years. But Roland will run out of models to recreate one day. What would Roland do by then? Release everything as a one-time purchase so that every long-term subscriber feels ripped off?</li>
+<li>Get everything on subscribe: this differs from traditional
+subscription a lot, which seems a great bounty to the customer. But it
+causes problems such as …</li>
+<li>Lose everything on unsubscribe: this is <em>very</em> unfair to the
+subscriber and makes short-term subscription worth almost nothing. For
+example if I just want Sound Canvas VA really badly, I would imagine
+subscribing shortly before its release and unsubscribe after I’m
+eligible for keeping the product permanently. But this is simply not
+possible.</li>
+<li>Weird pricing. To be honest the current pricing is pretty fair for
+long-term subscribers. But if Roland somehow decided to fix the ‘lose
+everything on unsubscribe’ problem (which is very unlikely to happen),
+the pricing would become super complex: they probably do not want people
+to keep a virtual TB-303 for just $19.99.</li>
+<li>Potentially unsustainable. Every good thing must come to an end. The
+most attractive products in Roland Cloud is the software models of
+Roland’s synthesizers from its golden years. But Roland will run out of
+models to recreate one day. What would Roland do by then? Release
+everything as a one-time purchase so that every long-term subscriber
+feels ripped off?</li>
</ul>
-<p>I'm an absolute supporter of Roland releasing authentic-sounding digitialized version of their legendary synthesizer models. But their subscription model pisses me off so hard. I know it's not a big deal for a professional producer. However this is a real deal-breaker for amateurs such as me.</p>
-<p>Unfortunately there's no real competitors out there when things come to reproducing their own synthesizers. Also a little bit off-topic: the music producing industry deserves more high quality free (as in freedom) software.</p>
-<p>Now let's move on and talk about Office 365 by Microsoft and Creative Cloud from Adobe. They bundles software with value-add services such as e-mail service and (optinal) creativity material. IMHO these products they are trying to turn into a service resemble a tool, such as a screwdriver, rather than an apartment that people actually go for renting instead of purchasing.</p>
-<p>Paying a monthly fee for a screwdriver makes absolutely no sense. That said, I would stick with my plain old screwdriver, rather than that shiny gold-plated screwdriver with 10 heads which I will lose whenever I stop paying them. <strong>Green is my pepper.</strong></p>
-<p>The purpose of this entire rant is to remind the reader of just how many ways proprietary software vendors could come up with to screw their users up. What they care the most has always been money and this will simply not change any time soon. Get ready for more!</p>
+<p>I’m an absolute supporter of Roland releasing authentic-sounding
+digitialized version of their legendary synthesizer models. But their
+subscription model pisses me off so hard. I know it’s not a big deal for
+a professional producer. However this is a real deal-breaker for
+amateurs such as me.</p>
+<p>Unfortunately there’s no real competitors out there when things come
+to reproducing their own synthesizers. Also a little bit off-topic: the
+music producing industry deserves more high quality free (as in freedom)
+software.</p>
+<p>Now let’s move on and talk about Office 365 by Microsoft and Creative
+Cloud from Adobe. They bundles software with value-add services such as
+e-mail service and (optinal) creativity material. IMHO these products
+they are trying to turn into a service resemble a tool, such as a
+screwdriver, rather than an apartment that people actually go for
+renting instead of purchasing.</p>
+<p>Paying a monthly fee for a screwdriver makes absolutely no sense.
+That said, I would stick with my plain old screwdriver, rather than that
+shiny gold-plated screwdriver with 10 heads which I will lose whenever I
+stop paying them. <strong>Green is my pepper.</strong></p>
+<p>The purpose of this entire rant is to remind the reader of just how
+many ways proprietary software vendors could come up with to screw their
+users up. What they care the most has always been money and this will
+simply not change any time soon. Get ready for more!</p>
</article>
</div><br><hr>
- <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: <a href="https://vimeo.com/329297480">link to video</a><br></span></div>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: <a href="https://vimeo.com/329297480">link to
+video</a><br></span></div>
<div id="insanch" style="height:3em;"></div>
<div id="footer" style="">
<div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
diff --git a/blog/post/2019-04-25.html b/blog/post/2019-04-25.html
index e2f6b08..01ceb09 100644
--- a/blog/post/2019-04-25.html
+++ b/blog/post/2019-04-25.html
@@ -1,8 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"EDIROL SD-80: A Trapped Beast")</title>
+<meta name="description" content="«EDIROL SD-80: A Trapped Beast» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
@@ -49,7 +51,10 @@ function ol()
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0"><em>STUDIO Canvas</em> acquired</a></li><li><a class="toctarg" href="#tocanch1">The configuration</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">Connection to the computer</a></li><li><a class="toctarg" href="#tocanch3">Settings things up in Linux</a></li><li><a class="toctarg" href="#tocanch4">Setting things up in Windows</a></li></ul></li><li><a class="toctarg" href="#tocanch5">What does it sound like?</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">Relation to EDIROL HyperCanvas and the Cakewalk TTS-1</a></li><li><a class="toctarg" href="#tocanch7">UPDATE: 2019-10-12</a></li></ul></li><li><a class="toctarg" href="#tocanch8">Working with the SD-80</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch9">Fighting against latency</a></li><li><a class="toctarg" href="#tocanch10">Recording</a></li><li><a class="toctarg" href="#tocanch11">Editing the sounds</a></li><li><a class="toctarg" href="#tocanch12">Impact on the workflow</a></li></ul></li><li><a class="toctarg" href="#tocanch13">Quirks</a></li><li><a class="toctarg" href="#tocanch14">Beneath the chassis</a></li><li><a class="toctarg" href="#tocanch15">What the manual doesn’t tell</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch16">Testing mode</a></li><li><a class="toctarg" href="#tocanch17">Messing around sans the chassis</a></li><li><a class="toctarg" href="#tocanch18">Chart A</a></li><li><a class="toctarg" href="#tocanch19">Chart B</a></li></ul></li><li><a class="toctarg" href="#tocanch20">Verdict</a></li><li><a class="toctarg" href="#tocanch21">Things to do besides imitating ZUN</a></li><li><a class="toctarg" href="#tocanch22">Newer Roland sound modules?</a></li><li><a class="toctarg" href="#tocanch23">Trivia</a></li><li><a class="toctarg" href="#tocanch24">If you want to learn more …</a></li></ul>
+ <li><a class="toctarg" href="#tocanch0">STUDIO Canvas acquired</a></li><li><a class="toctarg" href="#tocanch1">The configuration</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">Connection to the computer</a></li><li><a class="toctarg" href="#tocanch3">Settings things up in Linux</a></li><li><a class="toctarg" href="#tocanch4">Setting things up in Windows</a></li></ul></li><li><a class="toctarg" href="#tocanch5">What does it sound like?</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">Relation
+to EDIROL HyperCanvas and the Cakewalk TTS-1</a></li><li><a class="toctarg" href="#tocanch7">UPDATE: 2019-10-12</a></li></ul></li><li><a class="toctarg" href="#tocanch8">Working with the SD-80</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch9">Fighting against latency</a></li><li><a class="toctarg" href="#tocanch10">Recording</a></li><li><a class="toctarg" href="#tocanch11">Editing the sounds</a></li><li><a class="toctarg" href="#tocanch12">Impact on the workflow</a></li></ul></li><li><a class="toctarg" href="#tocanch13">Quirks</a></li><li><a class="toctarg" href="#tocanch14">Beneath the chassis</a></li><li><a class="toctarg" href="#tocanch15">What the manual doesn’t tell</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch16">Testing mode</a></li><li><a class="toctarg" href="#tocanch17">Messing around sans the
+chassis</a></li><li><a class="toctarg" href="#tocanch18">Chart A</a></li><li><a class="toctarg" href="#tocanch19">Chart B</a></li></ul></li><li><a class="toctarg" href="#tocanch20">Verdict</a></li><li><a class="toctarg" href="#tocanch21">Things to do besides
+imitating ZUN</a></li><li><a class="toctarg" href="#tocanch22">Newer Roland sound modules?</a></li><li><a class="toctarg" href="#tocanch23">Trivia</a></li><li><a class="toctarg" href="#tocanch24">If you want to learn more …</a></li></ul>
</li>
<li style="margin-left:-0.5em"><a id="prevp" href="2019-02-13.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="2019-06-24.html">Next post</a></li>
@@ -77,7 +82,10 @@ for(let x of cl)
a.setAttribute('x',n-1);
a.innerHTML='show';
a.href='javascript:void(0)';
+ if (dd.hasAttribute('caption'))
b.innerHTML=dd.getAttribute('caption');
+ else
+ b.innerHTML=dd.getAttribute('data-caption');
s.appendChild(b);
s.appendChild(document.createTextNode(' ['));
s.appendChild(a);
@@ -115,14 +123,54 @@ for(let x of al)
});
</script>
<article>
-<p>This article is about my hands on of the EDIROL STUDIO Canvas SD-80. Even though I’m a newcomer to the STUDIO Canvas owners community, veterans may still find something interesting here.</p>
+<p>This article is about my hands on of the EDIROL STUDIO Canvas SD-80.
+Even though I’m a newcomer to the STUDIO Canvas owners community,
+veterans may still find something interesting here.</p>
<p><strong>UPDATE</strong>: links to board shots are fixed.</p>
-<p><strong>UPDATE</strong>: <a href="https://chrisoft.org/blog/list/2020-11-20.html">A sequel</a> to this article has been posted. The sequel contains new updates, discoveries and corrections to this article.</p>
+<p><strong>UPDATE</strong>: <a href="https://chrisoft.org/blog/post/2020-11-20.html">A sequel</a> to
+this article has been posted. The sequel contains new updates,
+discoveries and corrections to this article.</p>
+<p><strong>UPDATE</strong> (2022-06-30): the sequel is now
+<em>actually</em> published.</p>
<h2 id="tocanch0" class="tvis"><em>STUDIO Canvas</em> acquired</h2>
-<p>Ever since I learned that ZUN uses a SD-90 as one of his major synthesizers <a href="https://www12.atwiki.jp/touhousoundfont/pages/22.html">here</a>, I’ve always been dreaming to get my hands on one of those. But these things are not particularly easy to find in China. There are plenty of deals on ebay though. However, after a failed purchase attempt made in 2016 which also led to the ridiculous suspension of my ebay account, I left the idea alone for multiple years. Things changed earlier this month, when <a href="https://owner203.com">owner203</a> helped me acquire my very own SD-80 and kindly delivered it from Japan.</p>
-<p>I did not go for a SD-90 since they are all ridiculously priced in 2019. The deal I tried to make back in 2016 would cost me around $300 (shipping included). Now they are all way beyond $400. This forced me to resort to lower-end models, namely the SD-80 and SD-20. There’s also the SD-50 which I almost bought back in 2014, before I found out it is essentially a stripped-down version of Roland SonicCell without the SRX expandability. Therefore although the SD-50 retains the compatibility with the synth engine found in SD-90 (both are from models supporting SRX, namely the XV-5080 and SonicCell), it comes with a complete new set of waveforms and patches which makes it sounds totally different. So the SD-50 is definitely a no go.</p>
-<p>The only choices left are SD-80 and SD-20. SD-20 can be found very cheap online (from $59). However SD-20 does have half of the polyphony and most editability of other STUDIO Canvas’ axed. Also gone are 3 entire sound banks (and presumably some waveforms). On the other hand, SD-80 costs a lot more (starting from ~$200), but is capable of generating everything the SD-90 can (the only missing part in SD-80 compared to SD-90 is the audio interface). After deciding no more compromise should be made, I went straight for the SD-80.</p>
-<p>The module arrived two weeks after the order was placed. It certainly wasn’t the happiest SD-80 in the world: the chassis bears quite a lot of scratches all around. The value knob takes a lot of force to turn and has a good amount of friction on it, to which I found a quick solution by simply pushing the knob downwards a little bit while turning it. Aside from the looks, the module itself is in perfect working order. It came with a power cord and its rack mount ears, but without any of its original paperwork or the CD-ROM. As most of the documentation and drivers can be found online, the only things I’ve lost are the demo midi files, which is still a shame.</p>
+<p>Ever since I learned that ZUN uses a SD-90 as one of his major
+synthesizers <a href="https://www12.atwiki.jp/touhousoundfont/pages/22.html">here</a>,
+I’ve always been dreaming to get my hands on one of those. But these
+things are not particularly easy to find in China. There are plenty of
+deals on ebay though. However, after a failed purchase attempt made in
+2016 which also led to the ridiculous suspension of my ebay account, I
+left the idea alone for multiple years. Things changed earlier this
+month, when <a href="https://owner203.com">owner203</a> helped me
+acquire my very own SD-80 and kindly delivered it from Japan.</p>
+<p>I did not go for a SD-90 since they are all ridiculously priced in
+2019. The deal I tried to make back in 2016 would cost me around $300
+(shipping included). Now they are all way beyond $400. This forced me to
+resort to lower-end models, namely the SD-80 and SD-20. There’s also the
+SD-50 which I almost bought back in 2014, before I found out it is
+essentially a stripped-down version of Roland SonicCell without the SRX
+expandability. Therefore although the SD-50 retains the compatibility
+with the synth engine found in SD-90 (both are from models supporting
+SRX, namely the XV-5080 and SonicCell), it comes with a complete new set
+of waveforms and patches which makes it sounds totally different. So the
+SD-50 is definitely a no go.</p>
+<p>The only choices left are SD-80 and SD-20. SD-20 can be found very
+cheap online (from $59). However SD-20 does have half of the polyphony
+and most editability of other STUDIO Canvas’ axed. Also gone are 3
+entire sound banks (and presumably some waveforms). On the other hand,
+SD-80 costs a lot more (starting from ~$200), but is capable of
+generating everything the SD-90 can (the only missing part in SD-80
+compared to SD-90 is the audio interface). After deciding no more
+compromise should be made, I went straight for the SD-80.</p>
+<p>The module arrived two weeks after the order was placed. It certainly
+wasn’t the happiest SD-80 in the world: the chassis bears quite a lot of
+scratches all around. The value knob takes a lot of force to turn and
+has a good amount of friction on it, to which I found a quick solution
+by simply pushing the knob downwards a little bit while turning it.
+Aside from the looks, the module itself is in perfect working order. It
+came with a power cord and its rack mount ears, but without any of its
+original paperwork or the CD-ROM. As most of the documentation and
+drivers can be found online, the only things I’ve lost are the demo midi
+files, which is still a shame.</p>
<table>
<tbody><tr>
<td>
@@ -132,79 +180,154 @@ for(let x of al)
</td>
<td>
<div style="text-align:center;max-width:98%;">
-<a href="//filestorage.chrisoft.org/blog/img/SD-80_label.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_label.jpg"></a> <br>Label with S/N removed. Visible on top left corner is a foot pad that seems to be a slice of cork.
+<a href="//filestorage.chrisoft.org/blog/img/SD-80_label.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_label.jpg"></a> <br>Label with S/N
+removed. Visible on top left corner is a foot pad that seems to be a
+slice of cork.
</div>
</td>
-</tr><tr>
+</tr>
+<tr>
<td>
<div style="text-align:center;max-width:98%;">
-<a href="//filestorage.chrisoft.org/blog/img/SD-80_front.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_front.jpg"></a> <br>Left half of the front panel. Buttons yellowed out, showing the module’s age. Scratches and dents are visible.
+<a href="//filestorage.chrisoft.org/blog/img/SD-80_front.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_front.jpg"></a> <br>Left half of
+the front panel. Buttons yellowed out, showing the module’s age.
+Scratches and dents are visible.
</div>
</td>
<td>
<div style="text-align:center;max-width:98%;">
-<a href="//filestorage.chrisoft.org/blog/img/SD-80_back.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_back.jpg"></a> <br>Wow! Such Optical! Much MIDI!
+<a href="//filestorage.chrisoft.org/blog/img/SD-80_back.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_back.jpg"></a> <br>Wow! Such
+Optical! Much MIDI!
</div>
</td>
</tr>
</tbody></table>
<h2 id="tocanch1" class="tvis">The configuration</h2>
<h3 id="tocanch2" class="tvis">Connection to the computer</h3>
-<p>Without the audio interface portion, it’s impossible to use the SD-80 with only a USB connection: you need something for it to connect to in order to make a recording.</p>
-<p>To begin with, I wanted to get something that accepts S/PDIF input for the audio interface. But those kind of things are scarce today. The closet model I could find in Chinese market was from an unknown vendor and comes with a very sketchy chip, whose official driver only supports up to Windows 7 32-bit. As a crappy digital interface may sound worse than a more decent analog one, I went for one of the cheapest audio interfaces available: a Focusrite Scarlett Solo (which is more than 5 times the price of the weird digital interface and probably still better than the one comes with SD-90 as it supports up to 192 KHz sampling rate).</p>
-<p>For a audio equipment novice, connecting things up wasn’t that straightforward: I tried connecting the phone output on the SD-80 to the line in of the audio interface and it kind of works. There is just one <em>tiny</em> problem: the left and right channels got mixed up into one, and is only on the right channel in a stereo recording. At first I thought it was my cable. But after a couple minutes of researching, I found out that every input on an audio interface is actually mono. <strong>WHY</strong>? Guess I’ll never know.</p>
-<p>So I got another TRS to XLR connector. After connecting the left channel of output 1 on the SD-80 to the microphone input on the audio interface and the right channel to line level input, it produces stereo recordings as expected. The resulting audio is very unbalanced though, due to the microphone input being much more sensitive than the line level input. In order to balance them I played a sine wave on the SD-80 and adjust the input level of each channel so that while turning down the volume knob on the SD-80, the level indicators on all channels stop blinking at the same time.</p>
-<p>The ‘direct monitor’ switch on Scarlett Solo enables live monitoring of the input without operating system intervention and therefore, without latency. However the direct monitor feature on Scarlett Solo is limited to mono only, so in order to get stereo monitoring, a round-trip through the computer is required.</p>
+<p>Without the audio interface portion, it’s impossible to use the SD-80
+with only a USB connection: you need something for it to connect to in
+order to make a recording.</p>
+<p>To begin with, I wanted to get something that accepts S/PDIF input
+for the audio interface. But those kind of things are scarce today. The
+closet model I could find in Chinese market was from an unknown vendor
+and comes with a very sketchy chip, whose official driver only supports
+up to Windows 7 32-bit. As a crappy digital interface may sound worse
+than a more decent analog one, I went for one of the cheapest audio
+interfaces available: a Focusrite Scarlett Solo (which is more than 5
+times the price of the weird digital interface and probably still better
+than the one comes with SD-90 as it supports up to 192 KHz sampling
+rate).</p>
+<p>For a audio equipment novice, connecting things up wasn’t that
+straightforward: I tried connecting the phone output on the SD-80 to the
+line in of the audio interface and it kind of works. There is just one
+<em>tiny</em> problem: the left and right channels got mixed up into
+one, and is only on the right channel in a stereo recording. At first I
+thought it was my cable. But after a couple minutes of researching, I
+found out that every input on an audio interface is actually mono.
+<strong>WHY</strong>? Guess I’ll never know.</p>
+<p>So I got another TRS to XLR connector. After connecting the left
+channel of output 1 on the SD-80 to the microphone input on the audio
+interface and the right channel to line level input, it produces stereo
+recordings as expected. The resulting audio is very unbalanced though,
+due to the microphone input being much more sensitive than the line
+level input. In order to balance them I played a sine wave on the SD-80
+and adjust the input level of each channel so that while turning down
+the volume knob on the SD-80, the level indicators on all channels stop
+blinking at the same time.</p>
+<p>The ‘direct monitor’ switch on Scarlett Solo enables live monitoring
+of the input without operating system intervention and therefore,
+without latency. However the direct monitor feature on Scarlett Solo is
+limited to mono only, so in order to get stereo monitoring, a round-trip
+through the computer is required.</p>
<h3 id="tocanch3" class="tvis">Settings things up in Linux</h3>
-<p>If you are absolutely insane and using Gentoo Linux just like me, make sure you’ve already got working audio and have the following kernel configuration items enabled:</p>
+<p>If you are absolutely insane and using Gentoo Linux just like me,
+make sure you’ve already got working audio and have the following kernel
+configuration items enabled:</p>
<pre><code>Device Drivers ---&gt;
&lt;*&gt; Sound card support
&lt;*&gt; Advanced Linux Sound Architecture ---&gt;
[*] USB sound devices
&lt;*&gt; USB Audio/MIDI driver</code></pre>
-<p>Both SD-80 and Scarlett Solo should then just work out of box (if you are using pulseaudio <a id="n1" href="#note1" class="note">[1]</a>).</p>
-<p>At first I thought only the ‘generic’ USB mode of SD-80 is supported by this kernel module, however it turns out the ‘vendor’ USB mode works just fine as well. It also suffers a lot less stuttering.</p>
-<p>The USB vendor ID and product ID is 0582:0029. Changing the USB mode to generic makes it 0582:002a.</p>
+<p>Both SD-80 and Scarlett Solo should then just work out of box (if you
+are using pulseaudio <a id="n1" href="#note1" class="note">[1]</a>).</p>
+<p>At first I thought only the ‘generic’ USB mode of SD-80 is supported
+by this kernel module, however it turns out the ‘vendor’ USB mode works
+just fine as well. It also suffers a lot less stuttering.</p>
+<p>The USB vendor ID and product ID is 0582:0029. Changing the USB mode
+to generic makes it 0582:002a.</p>
<p>In order to monitor the input, load the loopback module first:</p>
<pre><code>pactl load-module module-loopback latency_msec=1</code></pre>
<p>(<code>latency_msec</code> means exactly what the name suggests)</p>
<p>then move it to the audio input of the audio interface:</p>
<pre><code>pacmd move-source-output 7 alsa_input.usb-Focusrite_Scarlett_Solo_USB-00.analog-stereo</code></pre>
-<p>where 7 is the index of the loopback followed by the name of the input of your audio interface. Usually you can use tab completion, however if you are still unsure, you may also use a GUI utility such as <code>pavucontrol</code>.</p>
-<p>I haven’t tried JACK yet. But using QjackCtl should make everything a breeze.</p>
+<p>where 7 is the index of the loopback followed by the name of the
+input of your audio interface. Usually you can use tab completion,
+however if you are still unsure, you may also use a GUI utility such as
+<code>pavucontrol</code>.</p>
+<p>I haven’t tried JACK yet. But using QjackCtl should make everything a
+breeze.</p>
<p>The editor for SD-80 works perfectly using wine.</p>
<h3 id="tocanch4" class="tvis">Setting things up in Windows</h3>
-<p>Setting things up in Windows is somehow more tedious than it should be. Roland didn’t bother releasing a driver for Windows 10, but a web search indicates the driver for Windows 8/8.1 works on Windows 10 with a minor tweak. As the device works with a generic driver on Linux even when the USB mode is set to ‘vendor’, it will probably work on Windows without the Roland driver too. Although I’d rather install the official driver for Windows 8/8.1 because there is one.</p>
-<p>The tweak is simple. Open up <code>RDIF1023.INF</code> in a text editor, copy everything under section <code>[Roland.NTamd64.6.2]</code> to section <code>[Roland.NTamd64.7]</code> and you are good to go. Driver signature enforcement has to be disabled as stated in the quick start manual.</p>
-<p>Settings up monitoring is as simple as clicking on a checkbox in the control panel or a button in your DAW. You just don’t see one use the command prompt for this purpose on Windows.</p>
+<p>Setting things up in Windows is somehow more tedious than it should
+be. Roland didn’t bother releasing a driver for Windows 10, but a web
+search indicates the driver for Windows 8/8.1 works on Windows 10 with a
+minor tweak. As the device works with a generic driver on Linux even
+when the USB mode is set to ‘vendor’, it will probably work on Windows
+without the Roland driver too. Although I’d rather install the official
+driver for Windows 8/8.1 because there is one.</p>
+<p>The tweak is simple. Open up <code>RDIF1023.INF</code> in a text
+editor, copy everything under section <code>[Roland.NTamd64.6.2]</code>
+to section <code>[Roland.NTamd64.7]</code> and you are good to go.
+Driver signature enforcement has to be disabled as stated in the quick
+start manual.</p>
+<p>Settings up monitoring is as simple as clicking on a checkbox in the
+control panel or a button in your DAW. You just don’t see one use the
+command prompt for this purpose on Windows.</p>
<h2 id="tocanch5" class="tvis">What does it sound like?</h2>
-<p>Well, it sounds super ‘ZUNish’, if you’ve ever listened to Touhou music. It’s definitely the best sounding module back in 2002 (barring those extendable modules such as XV-5080).</p>
+<p>Well, it sounds super ‘ZUNish’, if you’ve ever listened to Touhou
+music. It’s definitely the best sounding module back in 2002 (barring
+those extendable modules such as XV-5080).</p>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/clouds_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/clouds_SD-80.ogg">
</audio>
<p>SD-80’s take on clouds.mid (an easter egg thing in Windows 95)</p>
</div>
-<p>All instruments are from the ‘solo’ set. The trumpet is ‘Tp.Dark vib’, which is the famous ‘Romantic Tp’ with a significant lower filter cutoff. Everything else is the basic variant.</p>
+<p>All instruments are from the ‘solo’ set. The trumpet is ‘Tp.Dark
+vib’, which is the famous ‘Romantic Tp’ with a significant lower filter
+cutoff. Everything else is the basic variant.</p>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_02_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_02_SD-80.ogg">
</audio>
<p>SD-80’s take on th06_02.mid</p>
</div>
-<p>In general the STUDIO Canvas sounds more expressive than most other tone generators, virtual or not. This is probably related to its default non-zero modulation level (10) on every part. <a id="n2" href="#note2" class="note">[2]</a> Technically this makes it GM2-incompatible as section 3.3.2 of the GM2 specification says the default value for modulation depth should be 0.</p>
-<p>Also the STUDIO Canvas has a bunch of waveforms of instruments played with vibrato, which is absent on some expandable modules such as the XV-5080 <a id="n3" href="#note3" class="note">[3]</a>, making vibrato sounds much more natural than simulating with LFO modulating the pitch and other parameters.</p>
-<h3 id="tocanch6" class="tvis">Relation to EDIROL HyperCanvas and the Cakewalk TTS-1</h3>
-<p>There’s a rumor saying HyperCanvas and TTS-1 is essentially the ‘classical’ set from the STUDIO Canvas. And I believed the rumor has been around for quite some time. Finally I can check it out myself.</p>
+<p>In general the STUDIO Canvas sounds more expressive than most other
+tone generators, virtual or not. This is probably related to its default
+non-zero modulation level (10) on every part. <a id="n2" href="#note2" class="note">[2]</a> Technically this makes it GM2-incompatible as
+section 3.3.2 of the GM2 specification says the default value for
+modulation depth should be 0.</p>
+<p>Also the STUDIO Canvas has a bunch of waveforms of instruments played
+with vibrato, which is absent on some expandable modules such as the
+XV-5080 <a id="n3" href="#note3" class="note">[3]</a>, making vibrato sounds
+much more natural than simulating with LFO modulating the pitch and
+other parameters.</p>
+<h3 id="tocanch6" class="tvis">Relation
+to EDIROL HyperCanvas and the Cakewalk TTS-1</h3>
+<p>There’s a rumor saying HyperCanvas and TTS-1 is essentially the
+‘classical’ set from the STUDIO Canvas. And I believed the rumor has
+been around for quite some time. Finally I can check it out myself.</p>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/SD-80.ogg">
</audio>
-<p>flourish.mid on SD-80 with every instrument from the ‘classical’ set and basic variant selected.</p>
+<p>flourish.mid on SD-80 with every instrument from the ‘classical’ set
+and basic variant selected.</p>
</div>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/TTS-1.ogg">
</audio>
<p>flourish.mid on Cakewalk TTS-1, everything also from bank 0.</p>
</div>
-<p>The first impression is they do sound quite alike. But as soon as the drums kick in, you’ll find out they actually sound different.</p>
+<p>The first impression is they do sound quite alike. But as soon as the
+drums kick in, you’ll find out they actually sound different.</p>
<div>
<table style="position:relative;left:50%;transform:translate(-50%,0);">
<tbody><tr style="text-align:center">
@@ -222,11 +345,11 @@ TTS-1
Piano
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Piano_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Piano_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Piano_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Piano_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -235,11 +358,11 @@ Piano
Marimba
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Marimba_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Marimba_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Marimba_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Marimba_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -248,11 +371,11 @@ Marimba
Nylon Guitar
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Guitar_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Guitar_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Guitar_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Guitar_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -261,11 +384,11 @@ Nylon Guitar
Fingered Bass
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Bass_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Bass_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Bass_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Bass_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -274,11 +397,11 @@ Fingered Bass
Soprano Sax
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Sax_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Sax_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Sax_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Sax_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -287,11 +410,11 @@ Soprano Sax
Sweep Pad
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Sweep_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Sweep_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Sweep_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Sweep_TTS-1.ogg">
</audio>
</td>
</tr>
@@ -300,103 +423,270 @@ Sweep Pad
Drums
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_SD-80.ogg">
</audio>
</td>
<td>
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_TTS-1.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_TTS-1.ogg">
</audio>
</td>
</tr>
</tbody></table>
</div>
-<p>It’s quite obvious that the drums set of TTS-1 is actually taken from SC-88Pro (except Elec. Snare, which is taken from Electric Set). The piano sounds almost identical<a id="n4" href="#note4" class="note">[4]</a>. Sax, marimba and sweep pad also sounds identical. Bass seems to heve different velocity curves and guitar in TTS-1 sounds more bright.</p>
-<p>Further more, if you have Super Quartet, which is also made by Edirol, you may find out they also share many similar sounds, namely ‘Rockabilly’, ‘Jazz Bass’, ‘Rock Bass’ and ‘Acoustic Set’, which correspond to ‘Rockabilly’, ‘Jazz Bass’, ‘Fingered Bs2’ and ‘St.Standard’<a id="n5" href="#note5" class="note">[5]</a>.</p>
-<p>These old Edirol software synthesizers might have a very different engine compared to the XV engine found in the STUDIO Canvasses considering the DSP power of PCs of that time period. So it’s normal that the TTS-1 produces subtly different sound even when the same samples are used.</p>
+<p>It’s quite obvious that the drums set of TTS-1 is actually taken from
+SC-88Pro (except Elec. Snare, which is taken from Electric Set). The
+piano sounds almost identical<a id="n4" href="#note4" class="note">[4]</a>. Sax, marimba and sweep pad
+also sounds identical. Bass seems to heve different velocity curves and
+guitar in TTS-1 sounds more bright.</p>
+<p>Further more, if you have Super Quartet, which is also made by
+Edirol, you may find out they also share many similar sounds, namely
+‘Rockabilly’, ‘Jazz Bass’, ‘Rock Bass’ and ‘Acoustic Set’, which
+correspond to ‘Rockabilly’, ‘Jazz Bass’, ‘Fingered Bs2’ and
+‘St.Standard’<a id="n5" href="#note5" class="note">[5]</a>.</p>
+<p>These old Edirol software synthesizers might have a very different
+engine compared to the XV engine found in the STUDIO Canvasses
+considering the DSP power of PCs of that time period. So it’s normal
+that the TTS-1 produces subtly different sound even when the same
+samples are used.</p>
<div>
<table style="position:relative;left:50%;transform:translate(-50%,0);">
<tbody><tr>
<td style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/SCVA%2088Pro.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/SCVA%2088Pro.ogg">
</audio>
<br>bonus clip: flourish.mid on SOUND Canvas VA (SC-88Pro Map)
</td>
<td style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_SCVA.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Drums_SCVA.ogg">
</audio>
-<br>bonus clip: Drums from flourish.mid on SOUND Canvas VA (SC-88Pro Map)
+<br>bonus clip: Drums from flourish.mid on SOUND Canvas VA (SC-88Pro
+Map)
</td>
</tr>
</tbody></table>
</div>
-<p>SOUND Canvas VA doesn’t simulate anything it claims to perfectly, but it’s the best result someone who doesn’t physically own a SC-88Pro can achieve I guess.</p>
-<p>All audio files above were recorded using Cakewalk by Bandlab. <del>The Cubase Pro purchase was just for more instruments to be added to my HALion library.</del></p>
-<p>Here are more bonus clips recorded using <code>arecord</code> on Linux.</p>
+<p>SOUND Canvas VA doesn’t simulate anything it claims to perfectly, but
+it’s the best result someone who doesn’t physically own a SC-88Pro can
+achieve I guess.</p>
+<p>All audio files above were recorded using Cakewalk by Bandlab.
+<del>The Cubase Pro purchase was just for more instruments to be added
+to my HALion library.</del></p>
+<p>Here are more bonus clips recorded using <code>arecord</code> on
+Linux.</p>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_13_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_13_SD-80.ogg">
</audio>
<p>th06_13.mid</p>
</div>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_15_SD-80.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/th06_15_SD-80.ogg">
</audio>
-<p>th06_15.mid (I didn’t bother adjusting fade in value for the vibrato LFO.)</p>
+<p>th06_15.mid (I didn’t bother adjusting fade in value for the vibrato
+LFO.)</p>
</div>
-<p>And finally SD-80 in a mix, featuring two signature instruments ZUN used a lot in recent games (‘Romantic Tp’ and ‘Reed Romance’) and also ‘St.Sm Choir’.</p>
+<p>And finally SD-80 in a mix, featuring two signature instruments ZUN
+used a lot in recent games (‘Romantic Tp’ and ‘Reed Romance’) and also
+‘St.Sm Choir’.</p>
<div style="text-align:center">
-<audio controls="" src="//filestorage.chrisoft.org/music/ogg/%E6%B7%B1%E6%B5%B7%E4%B8%83%E8%8A%B1%EF%BD%9EForgotten%20Benefit_extended_remix.ogg">
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/music/ogg/%E6%B7%B1%E6%B5%B7%E4%B8%83%E8%8A%B1%EF%BD%9EForgotten%20Benefit_extended_remix.ogg">
</audio>
<p>深海七花~Forgotten Benefit_extended_remix<br>
-(Theme of stage 6 boss of <a href="http://rgbxyz.org/th_kaikeidou/top.html">Touhou Kaikeidou</a>, arranged a bit. Originally by <a href="https://blogs.yahoo.co.jp/crystalwings6">Crystalwings</a>)</p>
+(Theme of stage 6 boss of <a href="http://rgbxyz.org/th_kaikeidou/top.html">Touhou Kaikeidou</a>,
+arranged a bit. Originally by <a href="https://blogs.yahoo.co.jp/crystalwings6">Crystalwings</a>)</p>
</div>
<h3 id="tocanch7" class="tvis">UPDATE: 2019-10-12</h3>
-<p>Now that I’ve been using my SD-80 for some time, I could say more about the sounds built into it.</p>
-<p>Piano sounds in the SD-80 are not super compelling, mainly because it’s too bright and thin. Sure it has improved a lot since the early days, but it’s still nowhere near the real thing.</p>
-<p>Guitars and basses are in a similar situation. Most of these are also nowhere near realistic. However there <em>is</em> something worth of noting in this category, which is distortion guitar. Dist guitar presets with MFX pre-applied are much more better sounding than the old plain sample-based sounds.</p>
-<p>Orchestral sounds are expressive, sometimes overly expressive. There are not much variations either: no spiccato or solo pizzicato sounds. With a bit of tweaking though, symphony tracks do sound decent on the SD-80.</p>
-<p>Lead sounds and pads are superb, especially those from the special sets. With the editor a lot more nice sounds could be created. A lot of presets with step modulation typical of that days could be found both built-in and on the Internet (as midi system exclusive messages).</p>
-<p>Drums are half decent. Somehow I don’t really like Roland’s choice of their acoustic drum sets. I would always turn to other virtual drums for acoustic drums. Electric drum sounds are pretty good, but there are simply not enough electric drum sounds inside the SD-80.</p>
-<p>Also I don’t really like how Roland arranges the sounds into 4 GM2 sound sets. This severely limits the number of different kind of instruments. For example, rather than a lot of different vocal sounds that can be found in the SC-8850, in the SD-80 we only have Voice Oohs, Voices Oohs 2, St.&nbsp;Vox Oohs and Enh.Vox Oohs.</p>
-<p>The GS and XG lite modes don’t sound very good, which contain sounds that are more like stripped down version of its native presets than a genuine GS or XG lite synthesizer. The GS sounds are almost pathetic: it only come with the same instrument map as the SC-55, and sounds really cheap. Compatibility wise, however, the SD-80 does a nice job. It does seem to support all NRPNs and control messages of these standards (even though it sometimes screw up parameter scaling). But due to the fact that there aren’t really a lot of usable sounds in these modes, I don’t find these modes particularly useful.</p>
-<p>The SD-80 has 32MB of sample content <a id="n6" href="#note6" class="note">[6]</a>, which is on par with both SC-8850 and XV-5080. This is quite surprising because some of the sounds in XV-5080 are so much more realistic than those in SD-80 or SC-8850. The XV-5080 managed to squeeze 1083 samples into the 32MB wave ROM while the SD-80 only comes with 589 samples, which are often of lower quality. I don’t quite get why Roland did this.</p>
+<p>Now that I’ve been using my SD-80 for some time, I could say more
+about the sounds built into it.</p>
+<p>Piano sounds in the SD-80 are not super compelling, mainly because
+it’s too bright and thin. Sure it has improved a lot since the early
+days, but it’s still nowhere near the real thing.</p>
+<p>Guitars and basses are in a similar situation. Most of these are also
+nowhere near realistic. However there <em>is</em> something worth of
+noting in this category, which is distortion guitar. Dist guitar presets
+with MFX pre-applied are much more better sounding than the old plain
+sample-based sounds.</p>
+<p>Orchestral sounds are expressive, sometimes overly expressive. There
+are not much variations either: no spiccato or solo pizzicato sounds.
+With a bit of tweaking though, symphony tracks do sound decent on the
+SD-80.</p>
+<p>Lead sounds and pads are superb, especially those from the special
+sets. With the editor a lot more nice sounds could be created. A lot of
+presets with step modulation typical of that days could be found both
+built-in and on the Internet (as midi system exclusive messages).</p>
+<p>Drums are half decent. Somehow I don’t really like Roland’s choice of
+their acoustic drum sets. I would always turn to other virtual drums for
+acoustic drums. Electric drum sounds are pretty good, but there are
+simply not enough electric drum sounds inside the SD-80.</p>
+<p>Also I don’t really like how Roland arranges the sounds into 4 GM2
+sound sets. This severely limits the number of different kind of
+instruments. For example, rather than a lot of different vocal sounds
+that can be found in the SC-8850, in the SD-80 we only have Voice Oohs,
+Voices Oohs 2, St.&nbsp;Vox Oohs and Enh.Vox Oohs.</p>
+<p>The GS and XG lite modes don’t sound very good, which contain sounds
+that are more like stripped down version of its native presets than a
+genuine GS or XG lite synthesizer. The GS sounds are almost pathetic: it
+only come with the same instrument map as the SC-55, and sounds really
+cheap. Compatibility wise, however, the SD-80 does a nice job. It does
+seem to support all NRPNs and control messages of these standards (even
+though it sometimes screw up parameter scaling). But due to the fact
+that there aren’t really a lot of usable sounds in these modes, I don’t
+find these modes particularly useful.</p>
+<p>The SD-80 has 32MB of sample content <a id="n6" href="#note6" class="note">[6]</a>, which is on par with
+both SC-8850 and XV-5080. This is quite surprising because some of the
+sounds in XV-5080 are so much more realistic than those in SD-80 or
+SC-8850. The XV-5080 managed to squeeze 1083 samples into the 32MB wave
+ROM while the SD-80 only comes with 589 samples, which are often of
+lower quality. I don’t quite get why Roland did this.</p>
<h2 id="tocanch8" class="tvis">Working with the SD-80</h2>
<h3 id="tocanch9" class="tvis">Fighting against latency</h3>
-<p>Even though Scarlett Solo can achieve a very low latency, there’s no way I can squeeze out enough processing power out of my ULV dual core i7 to handle it. Therefore I was forced to live with ~11 ms latency, which is not <em>that</em> high, but still a quite significant amount to deal with.</p>
-<p>Cakewalk’s glitchy latency compensation makes things even worse: it works in some projects but completely out of order for the others. In order to listen to a full mix, I have to make a short recording, which is really annoying. As this is much more expensive time-wise, I started using more guesswork before trying a full mix and it’s probably not good.</p>
+<p>Even though Scarlett Solo can achieve a very low latency, there’s no
+way I can squeeze out enough processing power out of my ULV dual core i7
+to handle it. Therefore I was forced to live with ~11 ms latency, which
+is not <em>that</em> high, but still a quite significant amount to deal
+with.</p>
+<p>Cakewalk’s glitchy latency compensation makes things even worse: it
+works in some projects but completely out of order for the others. In
+order to listen to a full mix, I have to make a short recording, which
+is really annoying. As this is much more expensive time-wise, I started
+using more guesswork before trying a full mix and it’s probably not
+good.</p>
<h3 id="tocanch10" class="tvis">Recording</h3>
-<p>Recording is simple and works as expected. However I seem to suffer from quite a high SNR value, which hovers around ~90 dB. Perhaps it’s my crappy cables making me pay.</p>
+<p>Recording is simple and works as expected. However I seem to suffer
+from quite a high SNR value, which hovers around ~90 dB. Perhaps it’s my
+crappy cables making me pay.</p>
<h3 id="tocanch11" class="tvis">Editing the sounds</h3>
-<p>The best thing about SD-80 is its editability. Neither SD-90 nor SD-20 came with the same level of editability upon launch. <a id="n7" href="#note7" class="note">[7]</a></p>
-<p>As claimed by the <a href="https://www.soundonsound.com/reviews/edirol-SD80">Sound On Sound review</a>, the editor for SD-80 is very similar to the one for XV-2020. The editor exposes a generic sample-based synthesis engine quite comparable to the one found in HALion (with more restrictions, of course). It lets you take full control of the synthesis engine and even create new patches not found anywhere else.</p>
-<p>The synthesis engine consists of four layers (with up to two samples <a id="n8" href="#note8" class="note">[8]</a> for each layer, plus frequency modulation), four filters (one for each layer), eight envelope generators (amplitude EG and filter EG for each layer), two LFOs <a id="n9" href="#note9" class="note">[9]</a> and a 4*4 modulation matrix. There are also 90 post-processing effects (some of which are combinations of multiple simple effects, hence the name ‘MFX’) to choose from for each channel.</p>
-<p>Restrictions aforementioned include inability to use external samples so you are essentially locked in to 589 built-in waveforms (which is probably fine because it’s not what the STUDIO Canvas line is aimed at), limited number of envelope nodes, limited modulation routing, restricted number of different MFX’s that can be used at the same time (3).</p>
-<p>The editor has quite terrible user experience. Guess it’s common for such decades-old software. It comes with a twenty-page pdf manual (which contains a lot of excerpts from the XV-5080 owner’s manual), which focus on the internals of the synthesizer, and a html manual, which focus on the interface of the editor.</p>
-<p>I’ve also tried editor software for other STUDIO Canvas modules using the same generation of XV engine. The SD-20 editor works seamlessly with SD-80, and it only offers basic parameters editing just like TTS-1. The SD-90 editor, despite being extremely similar to the SD-20 editor, doesn’t work at all, which is not surprising as it’s essentially the SD-20 editor plus an editor for the audio mixer and audio effects processor found in the SD-90, which the SD-80 lacks.</p>
-<p>By the way, if you have hi-dpi display and use Windows 10, be sure to use ‘System (Enhanced)’ scaling behavior for the SD-80 Editor. It scales perfectly that way.</p>
-<p>I’m not going to scatter the post with even more pictures, so please follow the links for selected screenshots of the editor:</p>
-<p><a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_a.png">main screen</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_b.png">‘part survey’</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_c.png">layers</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_e.png">amp EG</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_f.png">LFO</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_h.png">layers mapping</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_i.png">modulation matrix</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_k.png">patch options</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_l.png">‘part all’</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_m.png">MFX editing</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_r.png">Rhythm layers editor</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_u.png">Rhythm amp EG</a></p>
+<p>The best thing about SD-80 is its editability. Neither SD-90 nor
+SD-20 came with the same level of editability upon launch. <a id="n7" href="#note7" class="note">[7]</a></p>
+<p>As claimed by the <a href="https://www.soundonsound.com/reviews/edirol-SD80">Sound On Sound
+review</a>, the editor for SD-80 is very similar to the one for XV-2020.
+The editor exposes a generic sample-based synthesis engine quite
+comparable to the one found in HALion (with more restrictions, of
+course). It lets you take full control of the synthesis engine and even
+create new patches not found anywhere else.</p>
+<p>The synthesis engine consists of four layers (with up to two samples
+<a id="n8" href="#note8" class="note">[8]</a> for each layer, plus
+frequency modulation), four filters (one for each layer), eight envelope
+generators (amplitude EG and filter EG for each layer), two LFOs
+<a id="n9" href="#note9" class="note">[9]</a> and a 4*4 modulation matrix. There are also 90
+post-processing effects (some of which are combinations of multiple
+simple effects, hence the name ‘MFX’) to choose from for each
+channel.</p>
+<p>Restrictions aforementioned include inability to use external samples
+so you are essentially locked in to 589 built-in waveforms (which is
+probably fine because it’s not what the STUDIO Canvas line is aimed at),
+limited number of envelope nodes, limited modulation routing, restricted
+number of different MFX’s that can be used at the same time (3).</p>
+<p>The editor has quite terrible user experience. Guess it’s common for
+such decades-old software. It comes with a twenty-page pdf manual (which
+contains a lot of excerpts from the XV-5080 owner’s manual), which focus
+on the internals of the synthesizer, and a html manual, which focus on
+the interface of the editor.</p>
+<p>I’ve also tried editor software for other STUDIO Canvas modules using
+the same generation of XV engine. The SD-20 editor works seamlessly with
+SD-80, and it only offers basic parameters editing just like TTS-1. The
+SD-90 editor, despite being extremely similar to the SD-20 editor,
+doesn’t work at all, which is not surprising as it’s essentially the
+SD-20 editor plus an editor for the audio mixer and audio effects
+processor found in the SD-90, which the SD-80 lacks.</p>
+<p>By the way, if you have hi-dpi display and use Windows 10, be sure to
+use ‘System (Enhanced)’ scaling behavior for the SD-80 Editor. It scales
+perfectly that way.</p>
+<p>I’m not going to scatter the post with even more pictures, so please
+follow the links for selected screenshots of the editor:</p>
+<p><a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_a.png">main
+screen</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_b.png">‘part
+survey’</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_c.png">layers</a>
+/ <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_e.png">amp
+EG</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_f.png">LFO</a> /
+<a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_h.png">layers
+mapping</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_i.png">modulation
+matrix</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_k.png">patch
+options</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_l.png">‘part
+all’</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_m.png">MFX
+editing</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_r.png">Rhythm
+layers editor</a> / <a href="//filestorage.chrisoft.org/blog/img/SD-80_editor_u.png">Rhythm amp
+EG</a></p>
<h3 id="tocanch12" class="tvis">Impact on the workflow</h3>
-<p>First of all I’ve to record and thus, deal with latency, noise and clipping. It’s pretty annoying as already mentioned above.</p>
-<p>Also the SD-80 doesn’t integrate very well with any DAW. There’s no way your settings of this hardware synth get saved automatically with your project like a virtual synth. Also forget about automation and all sort of things. You have to use MIDI events and system exclusive messages (especially tuning some obscure parameters) for this purpose, and DAW software doesn’t have great support for system exclusive messages in general.</p>
+<p>First of all I’ve to record and thus, deal with latency, noise and
+clipping. It’s pretty annoying as already mentioned above.</p>
+<p>Also the SD-80 doesn’t integrate very well with any DAW. There’s no
+way your settings of this hardware synth get saved automatically with
+your project like a virtual synth. Also forget about automation and all
+sort of things. You have to use MIDI events and system exclusive
+messages (especially tuning some obscure parameters) for this purpose,
+and DAW software doesn’t have great support for system exclusive
+messages in general.</p>
<h2 id="tocanch13" class="tvis">Quirks</h2>
-<p>The SD-80 is GM2 compatible. However many midi files you randomly find may not play on it even when the device is in GM2 mode. If the midi file being played has any sort of bank selection event not recognized by the SD-80, the corresponding part will produce no sound at all.</p>
-<p>If your midi file has NRPN messages, things will get even worse. These things are essentially undocumented for the SD-80. All I could say is good luck keeping your eardrum intact. <a id="n10" href="#note10" class="note">[10]</a></p>
-<p>The manual says ‘This set (“classical” set) is also used when GM2 data compatibility is important’. However upon receiving the GM2 on message, the module automatically selects ‘contemporary’ set for every part. It seems impossible to change this behavior.</p>
-<p>The XG Lite mode has way more instruments available than what the manual has listed. Bank 18 patch 1 gives you ‘Piano 1d’ (presumably ‘Mellow Grand Piano’ in XG specification), which is not listed in the manual. It actually has 489 normal patches, 49 sfx patches, 2 sfx kits and 9 drum kits <a id="n11" href="#note11" class="note">[11]</a>. It’s quite irony to find out that they have more patches for their competitor’s standard than their own legacy standard. However these sounds are relatively lame when compared with authentic YAMAHA XG synthesizers of the same period. Particularly some sounds in different variant slot of the same patch number sounds almost identical. Roland obvious put less effort in these sounds in terms of sound designing.</p>
-<p>MIDI timing messes up if events flood in within a demisemiquaver worth of time. This quirk resembles the problem QMidiPlayer for Windows suffered from in its early days. But I’m pretty sure the cause is completely different. <a id="n12" href="#note12" class="note">[12]</a> Also this could be a common issue of old MIDI devices, as my old YAMAHA keyboards does the exact same thing.</p>
-<p>The sound generated by the SD-80/90 is phasey as could be heard in ZUN’s early works. If unsure, take a look at the spectrogram.</p>
-<p>The module, as all electric appliances do, generates heat. The manual says “A small amount of heat will radiate from the unit during normal operation”, and the chassis do get quite warm even when it is completely idle. This didn’t become an issue until later.</p>
-<p>Finally there are a couple of quirks in Roland’s former partner Cakewalk. Whenever the input signal level exceeds 0dB, instead of clipping the audio, it produces a loud cracking or popping sound in the record. Cubase and arecord have no such problem.</p>
-<p>Another quirk with Cakewalk is its metronome. Metronome settings in Cakewalk is saved on a per-project basis and there’s no way to change the default value (unless creating a template, which is useless for existing projects). By default it sends the metronome to the default MIDI device, which result in records with metronome clicks in them.</p>
+<p>The SD-80 is GM2 compatible. However many midi files you randomly
+find may not play on it even when the device is in GM2 mode. If the midi
+file being played has any sort of bank selection event not recognized by
+the SD-80, the corresponding part will produce no sound at all.</p>
+<p>If your midi file has NRPN messages, things will get even worse.
+These things are essentially undocumented for the SD-80. All I could say
+is good luck keeping your eardrum intact. <a id="n10" href="#note10" class="note">[10]</a></p>
+<p>The manual says ‘This set (“classical” set) is also used when GM2
+data compatibility is important’. However upon receiving the GM2 on
+message, the module automatically selects ‘contemporary’ set for every
+part. It seems impossible to change this behavior.</p>
+<p>The XG Lite mode has way more instruments available than what the
+manual has listed. Bank 18 patch 1 gives you ‘Piano 1d’ (presumably
+‘Mellow Grand Piano’ in XG specification), which is not listed in the
+manual. It actually has 489 normal patches, 49 sfx patches, 2 sfx kits
+and 9 drum kits <a id="n11" href="#note11" class="note">[11]</a>. It’s quite irony to find out that they have more patches
+for their competitor’s standard than their own legacy standard. However
+these sounds are relatively lame when compared with authentic YAMAHA XG
+synthesizers of the same period. Particularly some sounds in different
+variant slot of the same patch number sounds almost identical. Roland
+obvious put less effort in these sounds in terms of sound designing.</p>
+<p>MIDI timing messes up if events flood in within a demisemiquaver
+worth of time. This quirk resembles the problem QMidiPlayer for Windows
+suffered from in its early days. But I’m pretty sure the cause is
+completely different. <a id="n12" href="#note12" class="note">[12]</a> Also this could be a
+common issue of old MIDI devices, as my old YAMAHA keyboards does the
+exact same thing.</p>
+<p>The sound generated by the SD-80/90 is phasey as could be heard in
+ZUN’s early works. If unsure, take a look at the spectrogram.</p>
+<p>The module, as all electric appliances do, generates heat. The manual
+says “A small amount of heat will radiate from the unit during normal
+operation”, and the chassis do get quite warm even when it is completely
+idle. This didn’t become an issue until later.</p>
+<p>Finally there are a couple of quirks in Roland’s former partner
+Cakewalk. Whenever the input signal level exceeds 0dB, instead of
+clipping the audio, it produces a loud cracking or popping sound in the
+record. Cubase and arecord have no such problem.</p>
+<p>Another quirk with Cakewalk is its metronome. Metronome settings in
+Cakewalk is saved on a per-project basis and there’s no way to change
+the default value (unless creating a template, which is useless for
+existing projects). By default it sends the metronome to the default
+MIDI device, which result in records with metronome clicks in them.</p>
<h2 id="tocanch14" class="tvis">Beneath the chassis</h2>
-<p>Although I cherish the module quite a lot and there are warning text on top of it (which I can’t read because it’s in Japanese and … well, English), I disassembled the unit.</p>
+<p>Although I cherish the module quite a lot and there are warning text
+on top of it (which I can’t read because it’s in Japanese and … well,
+English), I disassembled the unit.</p>
<div style="text-align:center;max-width:90%;">
-<a href="//filestorage.chrisoft.org/blog/img/SD-80_caution.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_caution.jpg"></a> <br>CAUTION!! 注意!! ATTENTION!! (/a.tɑ̃.sjɔ̃/)
+<a href="//filestorage.chrisoft.org/blog/img/SD-80_caution.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_SD-80_caution.jpg"></a> <br>CAUTION!!
+注意!! ATTENTION!! (/a.tɑ̃.sjɔ̃/)
</div>
-<p>As most other vendors does, Roland build their audio equipment ‘like a tank’. The entire chassis is made out of aluminium and steel, and has an absolutely crazy amount of screws on it. The front panel came off after taking out 5 screws on top and bottom, after which I took out the value knob and the rubber button sheet for a cleanup.</p>
-<p>The top cover was freed after taking out 11 screws. Under the top cover lies the guts of SD-80. All boards except the power supply board uses SMD components extensively. The main board is made exclusively using SMD components, which is probably quite impressive back in the early 2000s.</p>
-<p>The power supply module is surrounded with thick plastic sheet presumably for insulation. Rated voltage for the module seems to be changeable by using different pin layouts on the input side. The power supply module is made of two separate boards. The two boards are connected with two wide connectors that only have a few pins on them. I would guess the pin layout on the connectors sets the rated voltage of the module but I’m not sure. I would definitely test that out someday.</p>
-<p>I took note of the engravment of every chip on the main board, which could be found below.</p>
+<p>As most other vendors does, Roland build their audio equipment ‘like
+a tank’. The entire chassis is made out of aluminium and steel, and has
+an absolutely crazy amount of screws on it. The front panel came off
+after taking out 5 screws on top and bottom, after which I took out the
+value knob and the rubber button sheet for a cleanup.</p>
+<p>The top cover was freed after taking out 11 screws. Under the top
+cover lies the guts of SD-80. All boards except the power supply board
+uses SMD components extensively. The main board is made exclusively
+using SMD components, which is probably quite impressive back in the
+early 2000s.</p>
+<p>The power supply module is surrounded with thick plastic sheet
+presumably for insulation. Rated voltage for the module seems to be
+changeable by using different pin layouts on the input side. The power
+supply module is made of two separate boards. The two boards are
+connected with two wide connectors that only have a few pins on them. I
+would guess the pin layout on the connectors sets the rated voltage of
+the module but I’m not sure. I would definitely test that out
+someday.</p>
+<p>I took note of the engravment of every chip on the main board, which
+could be found in chart B below.</p>
<table>
<tbody><tr>
<td>
@@ -423,11 +713,40 @@ Drums
</td></tr>
</tbody></table>
<h2 id="tocanch15" class="tvis">What the manual doesn’t tell</h2>
-<p>A very sensible thing to do after the disassembly is to search the engravment on the chips online. Searching ‘RA08-503’ found on the largest Roland-labled chips <a id="n13" href="#note13" class="note">[13]</a> brings up a whole new world to me: service manuals for Roland synths. Sadly there are no manuals for any STUDIO Canvas models, nevertheless, they are very useful for learning more about the insides of a Roland synthesizer.</p>
-<p>There are a couple of models bearing the ‘RA08-503’ chip found in the SD-80. Examples include XV-5080 and MC-909. This chip is referred to as ‘XV’ in their service manuals (also in the SD-80, as you will find out later). It’s safe to guess they handle the most important work of a sound module – tone generation. Also I observed that all modules supporting 32 parts and 128 polyphony have two of these chips in them, while the ones with only one chip only supports up to 16 parts and 64 polyphony. Maybe that’s the limitation of the single chip. Also one can tell the chip also handles some weird job such as LED indicators from the circuit board schematic.</p>
-<p>A very lonely chip on the right side has ‘6417706’ on it. Turns out this is a microprocessor implementing the SuperH architecture. It’s the same CPU as found in MC-909 (which makes sense as they are produced around the same time). Linux kernel has support for this processor<a id="n14" href="#note14" class="note">[14]</a>. The processor has a maximum clock speed of 133 MHz and is underclocked to 128MHz in the MC-909. It’s probably underclocked even more in the SD-80. There’s an unpopulated D-sub connector presumably for debugging near the CPU.</p>
+<p>A very sensible thing to do after the disassembly is to search the
+engravment on the chips online. Searching ‘RA08-503’ found on the
+largest Roland-labled chips <a id="n13" href="#note13" class="note">[13]</a> brings up a whole
+new world to me: service manuals for Roland synths. Sadly there are no
+manuals for any STUDIO Canvas models, nevertheless, they are very useful
+for learning more about the insides of a Roland synthesizer.</p>
+<p>There are a couple of models bearing the ‘RA08-503’ chip found in the
+SD-80. Examples include XV-5080 and MC-909. This chip is referred to as
+‘XV’ in their service manuals (also in the SD-80, as you will find out
+later). It’s safe to guess they handle the most important work of a
+sound module – tone generation. Also I observed that all modules
+supporting 32 parts and 128 polyphony have two of these chips in them,
+while the ones with only one chip only supports up to 16 parts and 64
+polyphony. Maybe that’s the limitation of the single chip. Also one can
+tell the chip also handles some weird job such as LED indicators from
+the circuit board schematic.</p>
+<p>A very lonely chip on the right side has ‘6417706’ on it. Turns out
+this is a microprocessor implementing the SuperH architecture. It’s the
+same CPU as found in MC-909 (which makes sense as they are produced
+around the same time). Linux kernel has support for this
+processor<a id="n14" href="#note14" class="note">[14]</a>. The processor has a maximum clock speed of 133 MHz and is
+underclocked to 128MHz in the MC-909. It’s probably underclocked even
+more in the SD-80. There’s an unpopulated D-sub connector presumably for
+debugging near the CPU.</p>
<h3 id="tocanch16" class="tvis">Testing mode</h3>
-<p>According to the service manuals available for other models, they all have a hidden test mode. Some also have the ability to update system firmware. Entering testing mode often involves turning the power on with a combination of keys pressed. Every model have its own way to enter testing mode and there’s no obvious pattern. At that point, I was desperate to dive into it. So I simply tried all button combinations consisting of one to three buttons. The result didn’t let me down. I found three combinations that make the SD-80 boot into special modes.</p>
+<p>According to the service manuals available for other models, they all
+have a hidden test mode. Some also have the ability to update system
+firmware. Entering testing mode often involves turning the power on with
+a combination of keys pressed. Every model have its own way to enter
+testing mode and there’s no obvious pattern. At that point, I was
+desperate to dive into it. So I simply tried all button combinations
+consisting of one to three buttons. The result didn’t let me down. I
+found three combinations that make the SD-80 boot into special
+modes.</p>
<ul>
<li>INST + SHIFT + PART▶ = Test Mode</li>
<li>INST + PAGE◀ + PREVIEW = Program Updater</li>
@@ -441,35 +760,58 @@ Drums
<p>(Preview blinks, pressing it doesn’t seem to do anything)</p>
<pre><code>01 Device Check
ALL OK!!</code></pre>
-<p>(I got <code>NG:XV2</code> shortly after heavily using the module for a while. MFX in test 7 produces no sound at all, system delay only has the dry sound, everything else was normal. More on this later.)</p>
+<p>(I got <code>NG:XV2</code> shortly after heavily using the module for
+a while. MFX in test 7 produces no sound at all, system delay only has
+the dry sound, everything else was normal. More on this later.)</p>
<pre><code>02 MIDI Check
MID1:x MID2:x THRU:x</code></pre>
-<p>(No MIDI cable for me until I’m home… Input from USB does not count.)</p>
+<p>(No MIDI cable for me until I’m home… Input from USB does not
+count.)</p>
<pre><code>03 LCD Check
PAGE:Sel / ENC: Contr</code></pre>
-<p>(PAGE buttons switch among the following four patterns: none, full, chequerboard 0, reversed chequerboard. Contr=Contrast)</p>
+<p>(PAGE buttons switch among the following four patterns: none, full,
+chequerboard 0, reversed chequerboard. Contr=Contrast)</p>
<pre><code>04 SW/LED Check
ooooo ooooo</code></pre>
-<p>(All buttons and indicators light up. Transparent buttons turns off its light, opaque buttons turns off LED above or below it, ENTER button turns off nothing. The five <code>o</code>’s on the left corresponds to the upper row, others corresponds to the lower row. Pressing a button turns its character to <code>#</code>, releasing it causes it to change to <code>.</code>.)</p>
+<p>(All buttons and indicators light up. Transparent buttons turns off
+its light, opaque buttons turns off LED above or below it, ENTER button
+turns off nothing. The five <code>o</code>’s on the left corresponds to
+the upper row, others corresponds to the lower row. Pressing a button
+turns its character to <code>#</code>, releasing it causes it to change
+to <code>.</code>.)</p>
<pre><code>05 Encoder Check
Value(0-23) = xx</code></pre>
-<p>(+ Plays C3, - Plays E3, both using the piano voice. Value starts at 00. Interestingly if the encoder is turned too fast, the value on screen does not change until you stop.)</p>
+<p>(+ Plays C3, - Plays E3, both using the piano voice. Value starts at
+00. Interestingly if the encoder is turned too fast, the value on screen
+does not change until you stop.)</p>
<pre><code>06 Sound Check
Push button to check
Left channel
Center channel
Right channel</code></pre>
-<p>(INST/EFFECTS/SYSTEM blink, pushing one makes it constantly on while others still blinking and plays the corresponding check. Plays sine wave on the selected channel(s))</p>
+<p>(INST/EFFECTS/SYSTEM blink, pushing one makes it constantly on while
+others still blinking and plays the corresponding check. Plays sine wave
+on the selected channel(s))</p>
<pre><code>07 Effect Check
Push button to check
MFX(Delay)
System Delay
System Reverb</code></pre>
-<p>(Same as test 06. The sounds used for these checks are snare, castanets and side stick respectively.)</p>
+<p>(Same as test 06. The sounds used for these checks are snare,
+castanets and side stick respectively.)</p>
<pre><code>08 Factory Reset
Push [PREVIEW]</code></pre>
<p>(PREVIEW blinks, pressing it really resets!)</p>
-<p>The SD-80 still works as a sound module in test mode – it will play any incoming midi stream. The module is in native mode regardless of your settings. MFX doesn’t seem to be working normally (likely due to it’s reserved for test 07). Switching between tests resets some (if not all, depending on the test switching to) of the synthesizer’s states. Switching to test 05 sets some of the instrumental parts to piano and others to a certain synth lead patch. Switching to test 06 sets sine wave and piano on all instrumental parts just like test 05. Switching to test 07 sets certain instrument parts to a drum patch, the patch ‘Xtremities’ could also be heard. Other parts are set to piano.</p>
+<p>The SD-80 still works as a sound module in test mode – it will play
+any incoming midi stream. The module is in native mode regardless of
+your settings. MFX doesn’t seem to be working normally (likely due to
+it’s reserved for test 07). Switching between tests resets some (if not
+all, depending on the test switching to) of the synthesizer’s states.
+Switching to test 05 sets some of the instrumental parts to piano and
+others to a certain synth lead patch. Switching to test 06 sets sine
+wave and piano on all instrumental parts just like test 05. Switching to
+test 07 sets certain instrument parts to a drum patch, the patch
+‘Xtremities’ could also be heard. Other parts are set to piano.</p>
<p><strong>Program Updater</strong></p>
<pre><code>Program Updater
Version: 1.03</code></pre>
@@ -491,17 +833,51 @@ Boot:5170[5170]1.01</code></pre>
<li>PART◀ = Update by MIDI</li>
<li>PART▶ = Update by USB</li>
</ul>
-<p>MIDI and USB indicators blink on any screen with the top row saying <code>Program Updater</code>. Selecting a source makes the corresponding indicator constantly lit and the other go out.</p>
-<p>If this mode is entered with the combination SYSTEM + PAGE◀ + PREVIEW, INST, EFFECTS, SYSTEM will do nothing instead. This combination is probably reserved for consumers.</p>
+<p>MIDI and USB indicators blink on any screen with the top row saying
+<code>Program Updater</code>. Selecting a source makes the corresponding
+indicator constantly lit and the other go out.</p>
+<p>If this mode is entered with the combination SYSTEM + PAGE◀ +
+PREVIEW, INST, EFFECTS, SYSTEM will do nothing instead. This combination
+is probably reserved for consumers.</p>
<p>Sound generation does not work in the program updater.</p>
-<p>Presumably the update MIDI files are similar to earlier models: stream of system exclusive events containing firmware blobs. No program update could be found for the SD-80 on the Internet. There are update files for the SD-90 however, which updates its system software to version 1.03.</p>
+<p>Presumably the update MIDI files are similar to earlier models:
+stream of system exclusive events containing firmware blobs. No program
+update could be found for the SD-80 on the Internet. There are update
+files for the SD-90 however, which updates its system software to
+version 1.03.</p>
</div>
-<h3 id="tocanch17" class="tvis">Messing around sans the chassis</h3>
-<p>As the two XV chips are arranged in a master-slave manner, I tried figuring out which one is acting as the master. I threw a bunch of midi files at it while measuring the temperature of the XV chips… with my fingers. Both chips turn quite toasty but IC19 is always warmer than IC27, sometimes it’s even a little difficult to keep my finger stay on that chip.</p>
-<p>When the action gets more intense, IC27 starts to warm up. Before I was just going to conclude that IC27 is acting as the master, I realized that I will never come into a meaningful conclusion without further reverse engineering: I have absolutely no idea how the load is distributed between the two XV’s!</p>
-<p>Frustrated, I entered testing mode to find out whether there’s anything interesting if it’s run with chassis removed. To my surprise, the device check failed with <code>NG:XV2</code> and a bunch of other errors in the following tests. I thought I was doomed, but a reboot of the module solved the problem completely and it never show any trace of abnormality that day.</p>
-<p>The other day, however, the problem returned. After messing with the SD-80 editor and creating random complex patches for an hour, I randomly decided to check out the testing mode again, where I was greeted by the <code>NG:XV2</code> failure the second time. Again, a reboot solved the problem for the day. No amount of hardwork will put the SD-80 into a buggy state if it boot straight into normal mode. At this point I thought it could be a bug in the test or the device check could be quite sensitive to temperature, which is probably not a very good thing as there are no vent holes for airflow on the module whatsoever.</p>
-<p>A few more days, I found my SD-80 frozen after keeping it on doing almost nothing for a day. In yet another case, it just randomly froze during playback after half day of usage. I’m unsure these instability are specific to my machine.</p>
+<h3 id="tocanch17" class="tvis">Messing around sans the
+chassis</h3>
+<p>As the two XV chips are arranged in a master-slave manner, I tried
+figuring out which one is acting as the master. I threw a bunch of midi
+files at it while measuring the temperature of the XV chips… with my
+fingers. Both chips turn quite toasty but IC19 is always warmer than
+IC27, sometimes it’s even a little difficult to keep my finger stay on
+that chip.</p>
+<p>When the action gets more intense, IC27 starts to warm up. Before I
+was just going to conclude that IC27 is acting as the master, I realized
+that I will never come into a meaningful conclusion without further
+reverse engineering: I have absolutely no idea how the load is
+distributed between the two XV’s!</p>
+<p>Frustrated, I entered testing mode to find out whether there’s
+anything interesting if it’s run with chassis removed. To my surprise,
+the device check failed with <code>NG:XV2</code> and a bunch of other
+errors in the following tests. I thought I was doomed, but a reboot of
+the module solved the problem completely and it never show any trace of
+abnormality that day.</p>
+<p>The other day, however, the problem returned. After messing with the
+SD-80 editor and creating random complex patches for an hour, I randomly
+decided to check out the testing mode again, where I was greeted by the
+<code>NG:XV2</code> failure the second time. Again, a reboot solved the
+problem for the day. No amount of hardwork will put the SD-80 into a
+buggy state if it boot straight into normal mode. At this point I
+thought it could be a bug in the test or the device check could be quite
+sensitive to temperature, which is probably not a very good thing as
+there are no vent holes for airflow on the module whatsoever.</p>
+<p>A few more days, I found my SD-80 frozen after keeping it on doing
+almost nothing for a day. In yet another case, it just randomly froze
+during playback after half day of usage. I’m unsure these instability
+are specific to my machine.</p>
<h3 id="tocanch18" class="tvis">Chart A</h3>
<div class="collapse" data-caption="Comparison of internal components found in selected Roland devices">
<p><a id="n15" href="#note15" class="note">[15]</a></p>
@@ -535,7 +911,8 @@ Boot:5170[5170]1.01</code></pre>
</tr>
<tr class="even">
<td style="text-align: center;">SC-88</td>
-<td style="text-align: center;">MBCS30109 (Custom Sound Generator) ‘XP’</td>
+<td style="text-align: center;">MBCS30109 (Custom Sound Generator)
+‘XP’</td>
<td style="text-align: center;"><a href="https://en.wikipedia.org/wiki/H8_Family">H8/510</a></td>
<td>EPROM/Mask ROM, SRAM*2, Wave ROM*4, DRAM*2</td>
<td style="text-align: center;">32</td>
@@ -543,7 +920,8 @@ Boot:5170[5170]1.01</code></pre>
</tr>
<tr class="odd">
<td style="text-align: center;">SC-88Pro</td>
-<td style="text-align: center;">RA01-005 (Custom Sound Generator) ‘XP3’</td>
+<td style="text-align: center;">RA01-005 (Custom Sound Generator)
+‘XP3’</td>
<td style="text-align: center;"><a href="https://en.wikipedia.org/wiki/H8_Family">H8/510</a></td>
<td>EPROM, SRAM*2, Wave ROM*5, DRAM*3</td>
<td style="text-align: center;">32</td>
@@ -553,7 +931,9 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">SC-8850</td>
<td style="text-align: center;">2*RA09-002 (Custom) ‘XP6’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7010/sh7014.html">SH7017</a></td>
-<td>64KB System ROM, 8M System Flash, 256K SRAM (USB controller), 2*4M DRAM (EFX effects + System), 16M Data ROM or Flash, 2*128Mbit Wave ROM, 2*4M DRAM (XP effects), 256k SRAM (framebuffer)</td>
+<td>64KB System ROM, 8M System Flash, 256K SRAM (USB controller), 2*4M
+DRAM (EFX effects + System), 16M Data ROM or Flash, 2*128Mbit Wave ROM,
+2*4M DRAM (XP effects), 256k SRAM (framebuffer)</td>
<td style="text-align: center;">64</td>
<td style="text-align: center;">128</td>
</tr>
@@ -561,7 +941,9 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">SC-8820</td>
<td style="text-align: center;">RA09-002 (Custom) ‘XP6’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7010/sh7014.html">SH7017</a></td>
-<td>64KB System ROM, 256K SRAM (USB controller), 16M Data ROM or Flash, 2*4M DRAM (EFX effects + System), 128Mbit+164Mbit Wave Rom, 4M DRAM (XP effects)</td>
+<td>64KB System ROM, 256K SRAM (USB controller), 16M Data ROM or Flash,
+2*4M DRAM (EFX effects + System), 128Mbit+164Mbit Wave Rom, 4M DRAM (XP
+effects)</td>
<td style="text-align: center;">32</td>
<td style="text-align: center;">64</td>
</tr>
@@ -569,7 +951,8 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">JV-1080</td>
<td style="text-align: center;">MBCS30109B (XP Chip) ‘XP’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7030/sh7032.html">SH7034</a></td>
-<td>CPU has 64KB Program Flash + 4KB SRAM built-in, 512kbit SRAM, 1Mbit DRAM, 8Mbit Data ROM, 2*1M DRAM (XP effects), 4*Wave ROM</td>
+<td>CPU has 64KB Program Flash + 4KB SRAM built-in, 512kbit SRAM, 1Mbit
+DRAM, 8Mbit Data ROM, 2*1M DRAM (XP effects), 4*Wave ROM</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">64</td>
</tr>
@@ -577,7 +960,8 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">JV-2080</td>
<td style="text-align: center;">TC170C200AF-005 (TG) ‘XP’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7030/sh7032.html">SH7034</a></td>
-<td>CPU has 64KB Program Flash + 4KB SRAM built-in, 2*DRAM, DRAM (XP effects), DRAM (LCD framebuffer), DRAM, SRAM, ROM or Flash</td>
+<td>CPU has 64KB Program Flash + 4KB SRAM built-in, 2*DRAM, DRAM (XP
+effects), DRAM (LCD framebuffer), DRAM, SRAM, ROM or Flash</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">64</td>
</tr>
@@ -585,7 +969,8 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">XV-5080</td>
<td style="text-align: center;">2*TC223C660CF-503 (RA08-503) ‘XV’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7040/sh7040.html">SH7042</a></td>
-<td>2*1Mbit SRAM, 256kbit (LCD framebuffer), 2*16Mbit (DRAM), 16Mbit Flash, 2*16Mbit DRAM (XV effects), 2*128Mbit Wave ROM</td>
+<td>2*1Mbit SRAM, 256kbit (LCD framebuffer), 2*16Mbit (DRAM), 16Mbit
+Flash, 2*16Mbit DRAM (XV effects), 2*128Mbit Wave ROM</td>
<td style="text-align: center;">32</td>
<td style="text-align: center;">128</td>
</tr>
@@ -593,15 +978,19 @@ Boot:5170[5170]1.01</code></pre>
<td style="text-align: center;">XV-5050</td>
<td style="text-align: center;">TC223C660CF-503 (RA08-503) ‘XV’</td>
<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7010/sh7014.html">SH7016</a></td>
-<td>8Kbit EEPROM, 32Mbit Flash, 16Mbit DRAM, 16Mbit DRAM (XV effects), 2*128Mbit Wave ROM</td>
+<td>8Kbit EEPROM, 32Mbit Flash, 16Mbit DRAM, 16Mbit DRAM (XV effects),
+2*128Mbit Wave ROM</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">64</td>
</tr>
<tr class="even">
<td style="text-align: center;">MC-909</td>
<td style="text-align: center;">TC223C660CF-503 (RA08-503) ‘XV’</td>
-<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7700/sh7706.html">SH7706</a> @ 128MHz</td>
-<td>2*64Mbit SDRAM (system), 16Mbit Flash (program), 256Mbit Flash (program, user), 16Mbit DRAM (external effects RAM), 4Mbit DRAM (XV effects), 2*64Mbit Wave SDRAM, 128Mbit Wave ROM</td>
+<td style="text-align: center;"><a href="https://www.renesas.com/us/en/products/microcontrollers-microprocessors/superh/sh7700/sh7706.html">SH7706</a>
+@ 128MHz</td>
+<td>2*64Mbit SDRAM (system), 16Mbit Flash (program), 256Mbit Flash
+(program, user), 16Mbit DRAM (external effects RAM), 4Mbit DRAM (XV
+effects), 2*64Mbit Wave SDRAM, 128Mbit Wave ROM</td>
<td style="text-align: center;">16</td>
<td style="text-align: center;">64</td>
</tr>
@@ -618,7 +1007,8 @@ Boot:5170[5170]1.01</code></pre>
</div>
<h3 id="tocanch19" class="tvis">Chart B</h3>
<div class="collapse" data-caption="List of integrated circuit chips on SD-80 main board">
-<p>Follow the link in the first column for a board photo with that chip visible. Sorry for the shaky photo and poor depth of field.</p>
+<p>Follow the link in the first column for a board photo with that chip
+visible. Sorry for the shaky photo and poor depth of field.</p>
<table>
<tbody><tr>
<th>
@@ -644,7 +1034,8 @@ IC 1
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">IC 2</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">IC
+2</a>
</td>
<td>
6417706 SH3 BC13008 133 0413
@@ -655,7 +1046,8 @@ IC 1
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC3.jpg">IC 3</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC3.jpg">IC
+3</a>
</td>
<td>
LH28F 160BJE-BTL80 SHARP JAPAN 0428 7xN
@@ -666,7 +1058,8 @@ Flash Memory (16Mbit)
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC4.jpg">IC 4, 6</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC4.jpg">IC 4,
+6</a>
</td>
<td>
SANYO LC381616IET-70 KZA7G0CD1 0042
@@ -677,7 +1070,8 @@ SDRAM (16Mbit)
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">IC 5</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">IC
+5</a>
</td>
<td>
‘H5’ or ‘115’ (illegible)
@@ -699,7 +1093,8 @@ NAND Gate
</tr>
<tr>
<td>
-IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">8</a>, <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">20, 22~25</a>
+IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC2.jpg">8</a>, <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">20,
+22~25</a>
</td>
<td>
4C1Y LV 245A
@@ -721,7 +1116,8 @@ F P42AB VT245A
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">IC 10, 12</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">IC
+10, 12</a>
</td>
<td>
0431H LVXC3245
@@ -754,7 +1150,8 @@ IC 14
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_datecode.jpg">IC 15</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_datecode.jpg">IC
+15</a>
</td>
<td>
4D36 LV 04A
@@ -765,7 +1162,8 @@ Hex Inverter
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC 16</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC
+16</a>
</td>
<td>
4D16 LV 14A
@@ -776,7 +1174,8 @@ Hex Schmitt-Trigger Inverter
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC17.jpg">IC 17</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC17.jpg">IC
+17</a>
</td>
<td>
Roland R02902867 137 352B100
@@ -798,7 +1197,8 @@ Dual 2/4 Decoder
</tr>
<tr>
<td>
-IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC19.jpg">19</a>, <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">27</a>
+IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC19.jpg">19</a>,
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC27.jpg">27</a>
</td>
<td>
Roland R01455956 RA08-503 JAPAN 0330EAI F0032ZAC
@@ -820,7 +1220,8 @@ Inverter (CMOS)
</tr>
<tr>
<td>
-IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC26.jpg">26</a>, <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC29.jpg">30</a>
+IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC26.jpg">26</a>,
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC29.jpg">30</a>
</td>
<td>
HYUNDAI GM71C18163CJ6 0040 AG1 KOREA
@@ -831,7 +1232,8 @@ EDO DRAM (16Mbit)
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC28.jpg">IC 28</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC28.jpg">IC
+28</a>
</td>
<td>
Roland R02678601 23C128L-529J 0224E7007
@@ -842,7 +1244,8 @@ Wave ROM (128Mbit?) <a id="n16" href="#note16" class="note">[16]</a>
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC29.jpg">IC 29</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_IC29.jpg">IC
+29</a>
</td>
<td>
Roland R02678612 23C128L-535K 0222E7005
@@ -853,7 +1256,8 @@ Wave ROM (128Mbit?)
</tr>
<tr>
<td>
-IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">31</a>, 35
+IC <a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">31</a>,
+35
</td>
<td>
4570 431
@@ -864,7 +1268,8 @@ Regulator
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC 32, 34</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC
+32, 34</a>
</td>
<td>
PCM1716E 27ZDHFM
@@ -875,7 +1280,8 @@ DAC
</tr>
<tr>
<td>
-<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC 33</a>
+<a href="https://filestorage.chrisoft.org/blog/img/SD-80_audio.jpg">IC
+33</a>
</td>
<td>
04 16H TC9271FS
@@ -898,35 +1304,143 @@ A E
</tbody></table>
</div>
<h2 id="tocanch20" class="tvis">Verdict</h2>
-<p>The SD-80, a product in Roland’s more budget-friendly Sound Canvas (Studio Canvas) line up, is a great sound module mainly focused at standards compliance at its time. In my opinion it’s the direct successor of the SC-8850, while the SD-90 is the direct successor of the SC-D70 (both are audio interfaces with a sound module integrated).</p>
-<p>The Studio Canvas family is Roland’s first and last line up of sound modules that map nearly all instruments to the GM2 instrument map. While making the instrument mapping less confusing, this instrument mapping has its limitations. No later Roland sound module does the same thing.</p>
-<p>Hardware wise, the SD-80 is extremely close to the XV-5080. But the SD-80 being a ‘Rompler’, its hardware capability is severely limited by Roland by matching them with worse wave ROM contents than its professional counterpart. This seems to be true across almost all professional and budget-friendly Roland synths in the 90s. (SC-88 has the same tone generator as JP-1080 (‘XP’), SC-88Pro has the same tone generator as JP-2080 (‘XP3’). SC-8850 and SC-8820 use a newer revision of the ‘XP’ chip (‘XP6’), which seems to be unused in a professional product.)</p>
-<p>Roland no longer makes ‘romplers’ today. Due to their unique sounds, these canvases might become a collector’s item in the future.</p>
-<h2 id="tocanch21" class="tvis">Things to do besides imitating ZUN</h2>
-<p>The SD-80 does not like QMidiPlayer very much. So the first thing to do is quite clear.</p>
-<p>Giving it a total makeup is the second thing on my bucket list. I’ll probably ditch the original top cover and front panel altogether and make some custom acrylic glass parts for it.</p>
-<p>Porting Linux to it might be a very fun (also atrocious) thing to do. The internals of the SD-80 is capable of doing much more than what it does as a STUDIO Canvas. It’s got the same main processor as the MC-909, just think about the possibility out there (this is also the reason why I call it a ‘trapped beast’ in the title of this post). The only thing against this is that I am shy of any experience with this level of hardware hacking.</p>
-<p>Setting up a web service where people upload their midi files and have them rendered with the SD-80 also sounds pretty cool. But I’m afraid I’ll receive something from Roland by then and it wouldn’t be fine for me. Is it really illegal to use a instrument on a time-sharing basis?</p>
-<p>Seriously though if I could pull it off, I’ll probably add a donation button and buy more classic sound modules for the site. Eventually it will turn into an online museum for sound modules… screw it I’m talking utter nonsense again.</p>
-<p>Also somehow extracting the waveforms and creating a instrument bank for HALion or Kontact is tempting. But the odds of being sued by Roland is even higher even though they did not explicitly disallow sampling their early products. To be honest I found it disturbing about the sampling restriction on these ‘unconventional’ instruments.</p>
+<p>The SD-80, a product in Roland’s more budget-friendly Sound Canvas
+(Studio Canvas) line up, is a great sound module mainly focused at
+standards compliance at its time. In my opinion it’s the direct
+successor of the SC-8850, while the SD-90 is the direct successor of the
+SC-D70 (both are audio interfaces with a sound module integrated).</p>
+<p>The Studio Canvas family is Roland’s first and last line up of sound
+modules that map nearly all instruments to the GM2 instrument map. While
+making the instrument mapping less confusing, this instrument mapping
+has its limitations. No later Roland sound module does the same
+thing.</p>
+<p>Hardware wise, the SD-80 is extremely close to the XV-5080. But the
+SD-80 being a ‘Rompler’, its hardware capability is severely limited by
+Roland by matching them with worse wave ROM contents than its
+professional counterpart. This seems to be true across almost all
+professional and budget-friendly Roland synths in the 90s. (SC-88 has
+the same tone generator as JP-1080 (‘XP’), SC-88Pro has the same tone
+generator as JP-2080 (‘XP3’). SC-8850 and SC-8820 use a newer revision
+of the ‘XP’ chip (‘XP6’), which seems to be unused in a professional
+product.)</p>
+<p>Roland no longer makes ‘romplers’ today. Due to their unique sounds,
+these canvases might become a collector’s item in the future.</p>
+<h2 id="tocanch21" class="tvis">Things to do besides
+imitating ZUN</h2>
+<p>The SD-80 does not like QMidiPlayer very much. So the first thing to
+do is quite clear.</p>
+<p>Giving it a total makeup is the second thing on my bucket list. I’ll
+probably ditch the original top cover and front panel altogether and
+make some custom acrylic glass parts for it.</p>
+<p>Porting Linux to it might be a very fun (also atrocious) thing to do.
+The internals of the SD-80 is capable of doing much more than what it
+does as a STUDIO Canvas. It’s got the same main processor as the MC-909,
+just think about the possibility out there (this is also the reason why
+I call it a ‘trapped beast’ in the title of this post). The only thing
+against this is that I am shy of any experience with this level of
+hardware hacking.</p>
+<p>Setting up a web service where people upload their midi files and
+have them rendered with the SD-80 also sounds pretty cool. But I’m
+afraid I’ll receive something from Roland by then and it wouldn’t be
+fine for me. Is it really illegal to use a instrument on a time-sharing
+basis?</p>
+<p>Seriously though if I could pull it off, I’ll probably add a donation
+button and buy more classic sound modules for the site. Eventually it
+will turn into an online museum for sound modules… screw it I’m talking
+utter nonsense again.</p>
+<p>Also somehow extracting the waveforms and creating a instrument bank
+for HALion or Kontact is tempting. But the odds of being sued by Roland
+is even higher even though they did not explicitly disallow sampling
+their early products. To be honest I found it disturbing about the
+sampling restriction on these ‘unconventional’ instruments.</p>
<h2 id="tocanch22" class="tvis">Newer Roland sound modules?</h2>
-<p>Newer Roland sound modules such as SonicCell and the latest INTEGRA-7 seems to maintain the compatibility with their original ‘XP’ synthesis engine to some extent – as they all support SRX expansion in a certain way. The synthesis engines are obviously improving over the years as Roland says the SRX expansion sounds built into INTEGRA-7 will sound a little different compared to earlier modules.</p>
-<p>However, disappointment strikes as soon as I saw the ‘READ’ button on screenshots of the editor software for the INTEGRA-7. I felt Roland really need to make more use of the USB bandwidth: the presence of that button implies the editor software still can’t reflect the realtime status of the synthesizer. <a id="n17" href="#note17" class="note">[17]</a> This is a huge drawback of using a hardware synthesizer that Roland still fails to fix to this day.</p>
-<p>Also, the INTEGRA-7 is super expensive for an amateur and Roland ended their budget <a id="n18" href="#note18" class="note">[18]</a> SOUND Canvas / STUDIO Canvas product line years ago. So no more Roland sound modules for me I guess.</p>
+<p>Newer Roland sound modules such as SonicCell and the latest INTEGRA-7
+seems to maintain the compatibility with their original ‘XP’ synthesis
+engine to some extent – as they all support SRX expansion in a certain
+way. The synthesis engines are obviously improving over the years as
+Roland says the SRX expansion sounds built into INTEGRA-7 will sound a
+little different compared to earlier modules.</p>
+<p>However, disappointment strikes as soon as I saw the ‘READ’ button on
+screenshots of the editor software for the INTEGRA-7. I felt Roland
+really need to make more use of the USB bandwidth: the presence of that
+button implies the editor software still can’t reflect the realtime
+status of the synthesizer. <a id="n17" href="#note17" class="note">[17]</a> This is a huge
+drawback of using a hardware synthesizer that Roland still fails to fix
+to this day.</p>
+<p>Also, the INTEGRA-7 is super expensive for an amateur and Roland
+ended their budget <a id="n18" href="#note18" class="note">[18]</a> SOUND Canvas / STUDIO Canvas product line years
+ago. So no more Roland sound modules for me I guess.</p>
<h2 id="tocanch23" class="tvis">Trivia</h2>
<ul>
-<li><p>A XML file in the SD-80 editor (Script/SD-80EditorScript.xml) contains patch list and wave list for all SRX expansion cards, confirming the fact that the editor is based on an editor for some other sound module with expansion slots.</p></li>
-<li><p>There are two crystal oscillators on the main board of SD-80. X1 is a 24 MHz one and X2 is a 16.934 MHz one. Both are out of range of SH7706’s allowed external clock frequency (clock mode 0 has a input range of 25 MHz to 66.67 MHz, clock mode 1 has a input range 6.25 MHz to 16.67 MHz). MC-909, which has the same CPU as the SD-80, has a 16 MHz crystal as the CPU clock source and the CPU operates at 128 MHz. There’s also a 16.934 MHz crystal in the MC-909, which is tied to its tone generator (the same tone generator as the one inside SD-80, RA08-503 or ‘XV’). X2 in SD-80 is also very close to one of its tone generator chip. My blind guess is that the output from X1 in SD-80 goes through a frequency divider and the CPU operates at 96 MHz. XV-5050 also has a 16.934 MHz clock source tied to its XV chip. XV-5080 however doesn’t have a 16.935 MHz crystal directly tied to its XV chip, but rather a 11.2886 MHz one going through a 3:2 PLL producing a 16.9329 MHz clock.</p></li>
+<li><p>A XML file in the SD-80 editor (Script/SD-80EditorScript.xml)
+contains patch list and wave list for all SRX expansion cards,
+confirming the fact that the editor is based on an editor for some other
+sound module with expansion slots.</p></li>
+<li><p>There are two crystal oscillators on the main board of SD-80. X1
+is a 24 MHz one and X2 is a 16.934 MHz one. Both are out of range of
+SH7706’s allowed external clock frequency (clock mode 0 has a input
+range of 25 MHz to 66.67 MHz, clock mode 1 has a input range 6.25 MHz to
+16.67 MHz). MC-909, which has the same CPU as the SD-80, has a 16 MHz
+crystal as the CPU clock source and the CPU operates at 128 MHz. There’s
+also a 16.934 MHz crystal in the MC-909, which is tied to its tone
+generator (the same tone generator as the one inside SD-80, RA08-503 or
+‘XV’). X2 in SD-80 is also very close to one of its tone generator chip.
+My blind guess is that the output from X1 in SD-80 goes through a
+frequency divider and the CPU operates at 96 MHz. XV-5050 also has a
+16.934 MHz clock source tied to its XV chip. XV-5080 however doesn’t
+have a 16.935 MHz crystal directly tied to its XV chip, but rather a
+11.2886 MHz one going through a 3:2 PLL producing a 16.9329 MHz
+clock.</p></li>
</ul>
<h2 id="tocanch24" class="tvis">If you want to learn more …</h2>
<ul>
-<li><a href="http://www.gigadenza.co.uk/?page_id=5116&amp;all=1">Gigadenza</a>, owns multiple sound modules, including the latest INTEGRA-7.</li>
-<li><a href="https://twitter.com/Romantique_Tp">Romantique Tp</a>, a Touhou music addict that I came across on Steinberg user forum.</li>
+<li><a href="http://www.gigadenza.co.uk/?page_id=5116&amp;all=1">Gigadenza</a>,
+owns multiple sound modules, including the latest INTEGRA-7.</li>
+<li><a href="https://twitter.com/Romantique_Tp">Romantique Tp</a>, a
+Touhou music addict that I came across on Steinberg user forum.</li>
</ul>
-If you spot a mistake or have anything you wish to share on this topic, please do not hesitate to drop me a message.
+If you spot a mistake or have anything you wish to share on this topic,
+please do not hesitate to drop me a message.
</article>
</div><br><hr>
- <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Pulseaudio sucks a lot less compared to the old days, it even switch automatically between built in Intel HD Audio and external USB audio device when it’s plugged in / unplugged.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: SD-90 doesn’t seem to have a non-zero modulation level according to its manual. Interesting.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: You can find the waveform list of SD-90/80 and XV-5080 online and do the comparison yourself.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: ‘Piano 1 st.’ in TTS-1 is actually ‘St.Piano 1’ from STUDIO Canvas’ ‘solo’ set. TTS-1 doesn’t have a ‘key scale panning’ (this is XG terminology, which means ‘wide’ in Roland’s wordbook) piano preset.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: The drum set mapping of Super Quartet is not GM compatible. It comes with a couple of sounds the STUDIO Canvas lacks.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: This is a reasonable guess, see chart B below for details.<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: The SD-90 do have <em>almost</em> the same level of editability as the SD-80, which can be achieved with the use of an updated version of SD-80’s editor, however it seems that SD-90 can’t save user patches. The SD-20, on the other hand, never enjoy the same level of editability. (The SD-20 is probably still editable by sending system exclusive messages directly?)<br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: One on each stereo channel.<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: Vibrato uses a separate LFO, so technically it’s three.<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: NRPN message setting expression to 100% on one device may set filter resonance to 100% on another. Imagine that.<br></span><span class="TText"><a id="note11" href="#n11">[11]</a>: I counted the instruments by turning the knob. The knob sometimes skips forward and backward, so there’s no way I count them accurately in a rush. I will probably make a complete patch list another day. UPDATE: the complete patch list could be found <a href="https://filestorage.chrisoft.org/blog/data/SD-80/SD80XGLiteInstList.ods">here</a> <br></span><span class="TText"><a id="note12" href="#n12">[12]</a>: The problem found in QMidiPlayer can be solved by simply lowering buffer size. <br></span><span class="TText"><a id="note13" href="#n13">[13]</a>: In case you haven’t yet noticed, there are two of those chips on the board.<br></span><span class="TText"><a id="note14" href="#n14">[14]</a>: <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/sh/kernel/cpu/sh3/clock-sh7706.c">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/sh/kernel/cpu/sh3/clock-sh7706.c</a> <br></span><span class="TText"><a id="note15" href="#n15">[15]</a>: Data for all models except the SD-80 are from their service notes.<br></span><span class="TText"><a id="note16" href="#n16">[16]</a>: The text on this chip together with the next one suspiciously resembles the part number of XV-5080’s wave ROM chips, plus the 128 Mbit wave ROM chips found in SC-8850 and SC-8820. (SC-8850 has 2*128Mbit wave ROM, while SC-8820 has 128Mbit + 64Mbit. The part number of the 64Mbit wave ROM chip has a completely different naming scheme.)<br></span><span class="TText"><a id="note17" href="#n17">[17]</a>: I did not do much research on this and I could be completely wrong on this topic.<br></span><span class="TText"><a id="note18" href="#n18">[18]</a>: compared to their JV/XV products.<br></span></div>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Pulseaudio sucks a lot less compared to
+the old days, it even switch automatically between built in Intel HD
+Audio and external USB audio device when it’s plugged in /
+unplugged.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: SD-90 doesn’t
+seem to have a non-zero modulation level according to its manual.
+Interesting.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: You can find the waveform list of SD-90/80 and XV-5080
+online and do the comparison yourself.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: ‘Piano 1 st.’ in TTS-1 is
+actually ‘St.Piano 1’ from STUDIO Canvas’ ‘solo’ set. TTS-1 doesn’t have
+a ‘key scale panning’ (this is XG terminology, which means ‘wide’ in
+Roland’s wordbook) piano preset.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: The drum set mapping of Super Quartet is not GM
+compatible. It comes with a couple of sounds the STUDIO Canvas
+lacks.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: This is a reasonable
+guess, see chart B below for details.<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: The
+SD-90 do have <em>almost</em> the same level of editability as the
+SD-80, which can be achieved with the use of an updated version of
+SD-80’s editor, however it seems that SD-90 can’t save user patches. The
+SD-20, on the other hand, never enjoy the same level of editability.
+(The SD-20 is probably still editable by sending system exclusive
+messages directly?)<br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: One on each stereo channel.<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: Vibrato uses a separate LFO, so technically it’s
+three.<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: NRPN message setting
+expression to 100% on one device may set filter resonance to 100% on
+another. Imagine that.<br></span><span class="TText"><a id="note11" href="#n11">[11]</a>: I counted the instruments by turning the knob.
+The knob sometimes skips forward and backward, so there’s no way I count
+them accurately in a rush. I will probably make a complete patch list
+another day. UPDATE: the complete patch list could be found
+<a href="https://filestorage.chrisoft.org/blog/data/SD-80/SD80XGLiteInstList.ods">here</a>
+<br></span><span class="TText"><a id="note12" href="#n12">[12]</a>: The problem found in QMidiPlayer can be
+solved by simply lowering buffer size. <br></span><span class="TText"><a id="note13" href="#n13">[13]</a>: In case you haven’t yet noticed,
+there are two of those chips on the board.<br></span><span class="TText"><a id="note14" href="#n14">[14]</a>: <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/sh/kernel/cpu/sh3/clock-sh7706.c">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/sh/kernel/cpu/sh3/clock-sh7706.c</a>
+<br></span><span class="TText"><a id="note15" href="#n15">[15]</a>: Data for all models except the SD-80 are from their service
+notes.<br></span><span class="TText"><a id="note16" href="#n16">[16]</a>: The text on this chip together with the
+next one suspiciously resembles the part number of XV-5080’s wave ROM
+chips, plus the 128 Mbit wave ROM chips found in SC-8850 and SC-8820.
+(SC-8850 has 2*128Mbit wave ROM, while SC-8820 has 128Mbit + 64Mbit. The
+part number of the 64Mbit wave ROM chip has a completely different
+naming scheme.)<br></span><span class="TText"><a id="note17" href="#n17">[17]</a>: I did not do much research on this
+and I could be completely wrong on this topic.<br></span><span class="TText"><a id="note18" href="#n18">[18]</a>: compared to their JV/XV
+products.<br></span></div>
<div id="insanch" style="height:3em;"></div>
<div id="footer" style="">
<div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
diff --git a/blog/post/2019-06-24.html b/blog/post/2019-06-24.html
new file mode 100644
index 0000000..77611e7
--- /dev/null
+++ b/blog/post/2019-06-24.html
@@ -0,0 +1,473 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"Working as an intern for "the spyware corporation"")</title>
+<meta name="description" content="«Working as an intern for &quot;the spyware corporation&quot;» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">Working as an intern for "the spyware corporation"</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/garbage/">garbage</a></li><li><a href="/blog/list/sophistry/">sophistry</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">A few notes upfront…</a></li><li><a class="toctarg" href="#tocanch1">The Decision</a></li><li><a class="toctarg" href="#tocanch2">The Workplace, the
+Colleagues and the Life</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch3">My work</a></li><li><a class="toctarg" href="#tocanch4">Payment</a></li><li><a class="toctarg" href="#tocanch5">Final Days &amp; The days after</a></li></ul></li><li><a class="toctarg" href="#tocanch6">Shitty Code</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch7">pasteFilesV2 also deletes
+file</a></li><li><a class="toctarg" href="#tocanch8">Practically no coding
+conventions.</a></li></ul></li><li><a class="toctarg" href="#tocanch9">Weirdness, quirks and
+other strange things</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch10">“Developers’ lives matter!”</a></li><li><a class="toctarg" href="#tocanch11">Incompetent coworkers
+start to pop up</a></li><li><a class="toctarg" href="#tocanch12">“Designer-driven” development</a></li><li><a class="toctarg" href="#tocanch13">Code review, or “code
+flattery”?</a></li><li><a class="toctarg" href="#tocanch14">Privacy issues?</a></li></ul></li><li><a class="toctarg" href="#tocanch15">Dick moves</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch16">… as taken literally</a></li><li><a class="toctarg" href="#tocanch17">Rushing V20</a></li><li><a class="toctarg" href="#tocanch18">Lacking / bad community
+interaction</a></li><li><a class="toctarg" href="#tocanch19">Illegal business practice</a></li><li><a class="toctarg" href="#tocanch20">Restructure shenanigans</a></li><li><a class="toctarg" href="#tocanch21">Walking away from “the
+founders’ spirits”</a></li></ul></li><li><a class="toctarg" href="#tocanch22">Epilogue</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2019-04-25.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2019-09-04.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">Working as an intern for "the spyware corporation"</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2019-06-24<br>#garbage #sophistry</div>
+ <hr><div id="article" class="TText"><article>
+<h2 id="tocanch0" class="tvis">A few notes upfront…</h2>
+<p>This post was supposed to come out as soon as it was finished. Well
+it looks complete but for some reason I couldn’t remember, I never made
+it public. Published 2024-02-17 without further modification.</p>
+<p>Original post starts below.</p>
+<p>If you are still unaware, the title is just sarcasm. As far as I
+know, the division I was working for does not work on any spyware.</p>
+<p>Also, this article is <strong>not</strong> approved by the propaganda
+division whatsoever. Everything is straight up garbage.</p>
+<h2 id="tocanch1" class="tvis">The Decision</h2>
+<p>As I have made up my mind to ‘strategically’ delay my graduation by a
+year, I initially hoped for taking the following months off and I did
+not plan for my graduation thesis at all. Therefore I intentionally
+skipped the subject selection process. All I wanted to do is chill for
+half an year and maybe make some contributions to several free software
+projects. Teachers noticed this and managed to persuade me to finish the
+graduation thesis this year. Only at this time did I realize how stupid
+I was – I am going to contribute to projects anyway, why don’t I take
+the chance to finish my thesis?</p>
+<p>However, as I have missed the opportunity to work on projects led by
+professors in my college, I had to look for intern jobs elsewhere. As I
+am not going to work for unethical companies, many companies my
+classmates are rushing into are not feasible for me. But actually I
+already have my choice in my mind: cause I am really interested in
+spying on how the ‘spyware corporation’ works on a daily basis.</p>
+<p>Finally, the choice was made. I tossed in my CV, which was put
+together in 5 minutes to them. Before long I got a quick reply. With
+everything settled down rather quickly, off I went.</p>
+<p>To sum it up, it was because:</p>
+<ul>
+<li>I was curious.</li>
+<li>I had plenty of time to waste.</li>
+<li>I wanted to get away from the campus I already spent 3 years
+in.</li>
+<li>with the additional benefit of finishing my graduation project.</li>
+</ul>
+<h2 id="tocanch2" class="tvis">The Workplace, the
+Colleagues and the Life</h2>
+<p>The workplace is nothing fancy. Dimly lighted, the work area is
+fairly cozy, possibly designed specially for us cavern-dwelling
+programmers. Computing devices are scattered throughout the enormous
+room, in which 90% of the local employees work.</p>
+<p>Co-workers here are competent to say at least (until they started
+rushing V20, as noted below). To list a few:</p>
+<ul>
+<li><a href="https://www.blumia.net/about.html">BLumia</a>: no more
+elaboration needed.</li>
+<li><a href="https://blog.justforlxz.com/about/">Kirigaya</a>: a little
+bit mean, a little bit naughty, but still nice guy to chat with.</li>
+<li><a href="https://github.com/zccrs">zccrs</a>: damn this guy
+definitely knows what he is doing when reviewing my shitty code. Rumors
+has it that he was once a wizard working for Nokia.</li>
+<li><a href="https://hualet.org/">Hualet</a>: that one who interviewed
+me. Passionate about free software. We talk quite a lot in private.</li>
+</ul>
+<p>Life quality in Wuhan was not a huge degradation compared to that of
+my university times, I’d put it that way. Commute times weren’t super
+long, foods here are nice (at least it rids me of the same kind of foods
+I had to have everyday on the campus), also I could for the first time
+cook for myself.</p>
+<p>Stereotype of the climate in southern China was broken: your clothes
+<strong>will</strong> be able to dry within a day, and you couldn’t
+really squeeze water out of the air.</p>
+<p>Public transit in Wuhan was tolerable until you got out of reach of
+the metro: the bus service was <strong>horrendous</strong>. There was no
+indication of where the actual station was, and the bus stops randomly
+‘roughly around’. I tried it once and dreaded having to take a bus ever
+since (fortunately, I didn’t).</p>
+<p>I lived in a rental room provided by Ziroom, which is essentially an
+apartment rental service broker. The apartment was shared by 5 persons,
+from which formed 2 couples, and … you guessed it, me. The room was
+relatively small (around 14m<sup>2</sup> in area), but super snug
+compared to my dorm in university. The real reason I find it that way,
+however, could ultimately be the fact that I was the only one inside and
+could do what ever I want.</p>
+<p>Interactions with roommates were minimal. In fact, I intentionally
+avoid interactions with my roommates because I was that type of a
+person.</p>
+<p>By the way, cooking is really deep a rabbit hole and I’m just getting
+down into it.</p>
+<p>All in all, it was a freshing experience for ‘an extremely spoiled
+child’ (as all my family members told me). I had fun, and I came back
+with every body part intact. I’m content with it.</p>
+<h3 id="tocanch3" class="tvis">My work</h3>
+<p>I mainly worked on the following things:</p>
+<ul>
+<li>Adding basic optical disc authoring functionality to the file
+manager.</li>
+<li>Move network configuration in the control center to the new code
+base.</li>
+<li>Giving the computer view in the file manager its new look.</li>
+<li>Random bug fixes in the file manager.</li>
+<li>A small portion of utility classes in DTK.</li>
+</ul>
+<p>There’s a lot of other miscellaneous stuff I did, some of which
+involves seizure-inducing programming languages
+<a id="n1" href="#note1" class="note">[1]</a>. I’m not going to list those things here.</p>
+<p>Actually, I promised to help revamping the infrastructure when I
+entered Deepin, mainly to improve its transparency (like Debian).
+However…</p>
+<ul>
+<li>They didn’t care.</li>
+<li>I wasn’t given time to do anything about it.</li>
+<li>I barely learned enough about how the current infrastructure
+works.</li>
+</ul>
+<p>And the promise was thrown straight out of the window.</p>
+<h3 id="tocanch4" class="tvis">Payment</h3>
+<p>Now looking back, I guess I was basically free labor <a id="n2" href="#note2" class="note">[2]</a> , donating my time to Deepin. I
+literately don’t care though, because I didn’t came for the money. It
+could be cringe-inducing to say, but their payment actually exceeded my
+initial expectation.</p>
+<p>By the way I actually even saved up a couple thousand during my time
+there. (Setting aside the fee ETS charged me for TOEFL and GRE of
+course. Those are nothing but f*cking cash grabs.) Guess it’s due to my
+extremely thrifty (stingy even) nature <a id="n3" href="#note3" class="note">[3]</a>.</p>
+<h3 id="tocanch5" class="tvis">Final Days &amp; The days after</h3>
+<p>I made my final commit on November 15th, and ended my internship on
+the same day.</p>
+<p>I stayed in Wuhan for another 30 days intermittently, finishing my
+final TOEFL test, visiting places, meeting with people, and most
+frequently of all, chilling in my ‘secret bear den’ (which refers to my
+rental room, obviously). Quite shockingly, I somehow managed to keep
+basically the same sleep schedule as the one before my internship
+ended.</p>
+<p>I returned home on January 3rd, and I was as lucky as one can ever
+be, cause all the coronavirus shenanigans just started to cook up.</p>
+<h2 id="tocanch6" class="tvis">Shitty Code</h2>
+<p>Never have I felt so involved with a programmer humor post until I
+have to actually deal with an old code base.</p>
+<h3 id="tocanch7" class="tvis">pasteFilesV2 also deletes
+file</h3>
+<p>When called with some obscene parameters, this function actually
+delete a file. What the hell.</p>
+<p>Even my code is arguably less shitty in this regard.</p>
+<h3 id="tocanch8" class="tvis">Practically no coding
+conventions.</h3>
+<p>Mixing tabs and spaces. Different indentation conventions.
+Incompatible naming schemes and even misspelled words in identifiers.
+You name it.</p>
+<p>In fact, deepin does have coding conventions, as listed <a href="https://hualet.org/blog/2019/07/23/deepin-qt/c-%E4%BB%A3%E7%A0%81%E9%A3%8E%E6%A0%BC%E6%8C%87%E5%8D%97/">here</a>
+and <a href="https://hualet.org/blog/2019/07/30/deepin-%E5%BC%80%E5%8F%91%E8%80%85%E8%A7%84%E8%8C%83/">here</a>.
+<a id="n4" href="#note4" class="note">[4]</a>
+Unfortunately, they are actively broken everyday in most projects.</p>
+<p>In defense of deepin though, this problem bothers a lot of other open
+source projects as well. My limited experience working with KDE’s
+codebase has already exposed that at least parts of KDE (namely
+libksysguard) suffers from the same problem.</p>
+<h2 id="tocanch9" class="tvis">Weirdness, quirks and
+other strange things</h2>
+<h3 id="tocanch10" class="tvis">“Developers’ lives matter!”</h3>
+<p>C’mon. If you have to equip your developers with computers that have
+inferior specs than your system requirements, don’t expect them to be
+super productive.</p>
+<p>Of course I understand they are currently under a rather tight
+budget, but they are offering quad core Core i5 to testers and new
+employees (some of which are quite incompetent, as described in the next
+section).</p>
+<p>Also, they refrain to provide necessary hardware for development.
+When I was adding optical disc authoring functionality to the file
+manager, my request to have a dedicated external optical drive was
+denied for some bizarre reason, and I had to share two optical drives
+with the testing department and the technical support department. This
+significantly hindered the development of the said feature, until I
+found a spare internal drive in the warehouse.</p>
+<p>Sometimes my friends there joked about the dessert as promised by the
+recruiter wasn’t being resupplied in time. For me, the dessert was
+really a surplus – I just want a computer that takes less than half an
+hour to build something!</p>
+<h3 id="tocanch11" class="tvis">Incompetent coworkers
+start to pop up</h3>
+<p>At a certain point of time (around June), I noticed a significant
+increase of personnel inside deepin. Many of these new employees are
+improperly trained. They don’t know how to incorporate git into the work
+flow (some know nothing about basic git concepts, or even about Linux at
+all), don’t look up documentation when troubled (instead they turn to
+CSDN <a id="n5" href="#note5" class="note">[5]</a> for help). As a result, the company had to spend
+extra time teaching them basic stuff, which to me seems a real waste of
+time.</p>
+<p>These incompetent employees are a major source of pain for project
+leaders. Some of them spent an entire day trying to figure out the cause
+of a very simple bug, without any level of success. Fortunately for
+deepin, most of them can reach some degree of competency after a few
+weeks of work (although they are still sometimes seen typing git
+commands from their notebooks).</p>
+<h3 id="tocanch12" class="tvis">“Designer-driven” development</h3>
+<p>This is a truly hilarious one. Here at Deepin (especially the project
+I’m personally working on, the file manager), product manager doesn’t
+decide what the program should be capable to do, the artistic designer
+does. The artistic designer almost has sole dictation on the
+specification of the product in this regard. We as developers can
+certainly dispute, but cases in which the designers changed their minds
+were rather rare, and most effort we made to persuade them was
+futile.</p>
+<p>By the way the current artistic designer is a very dedicated Apple
+fanboy. Expect some very Apple-ish bullshit in the next release.</p>
+<h3 id="tocanch13" class="tvis">Code review, or “code
+flattery”?</h3>
+<p>Code review is mandatory for every commit in Deepin. However policy
+of code review varied from people to people. The only one that really
+took it seriously was zccrs, who could almost always pick out the code
+where I screwed up <a id="n6" href="#note6" class="note">[6]</a>.</p>
+<p>On the other end of the spectrum was my friend, BLumia. His code
+review was usually just going through my code once, and seldom demand
+changes. At first I thought he was just giving me free passes, until I
+noticed obvious mistakes made by other coworkers that somehow slipped
+through code review. <a id="n7" href="#note7" class="note">[7]</a></p>
+<h3 id="tocanch14" class="tvis">Privacy issues?</h3>
+<p>I didn’t get to work on anything that actively connects to the
+Internet. So my position basically stayed the same as stated in my last
+article. To reiterate:</p>
+<ul>
+<li>They did a poor job dealing with public relationship.</li>
+<li>Telemetry should be off by default, or the user should be prompted
+whether they want it on installation.</li>
+<li>It’s free software though! You can check the code and strip
+everything unwanted.</li>
+</ul>
+<p>However, it’s probably getting even worse for Deepin (the
+distribution) users. I was told that an identifier of the user’s
+computer along with its specification might be used in the future. If
+you want to keep using DDE, but you still value your privacy, maybe
+consider moving to another distribution and install DDE there
+<a id="n8" href="#note8" class="note">[8]</a>.</p>
+<h2 id="tocanch15" class="tvis">Dick moves</h2>
+<h3 id="tocanch16" class="tvis">… as taken literally</h3>
+<p>As the amount of employees increases, space originally designated for
+everything else was re-purposed into work area. We had to move around
+while still working. Things were not looking good.</p>
+<p>Finally at the end of September, the company moved. This is regarded
+as the reaction to their increasing demand of workforces (as the old
+place has become very jam packed due to the sky rocketing number of
+staff), but it was also a very under-prepared dick move. Formal
+announcement of the move wasn’t published until the very last day. The
+new place is in the middle of nowhere and barely furnished. There are
+also two more completely empty floors, which are the source of later
+pains.</p>
+<p>The new place is much farther away, taking almost an hour by metro,
+or 40 minutes by commute shuttles. This forces me to get up a lot
+earlier, which is very disturbing. My overall life quality had
+definitely taken a punch after that.</p>
+<p>The place is actually bought from Huawei, who left a complete mess
+behind when they withdrew themselves from the place. Soon after we moved
+in, drilling and hammering sounds could be heard up stairs left and
+right. It was actually very nerve wrecking.</p>
+<p>As the company hasn’t yet settled down completely, many promised
+treatments are thrown out of the window. These include: desserts served
+during work hours (which are actually served as usual, but the amount
+didn’t increase as the number of employee rises. As a result, it’s
+basically gone.), monthly birthday celebration for employees, showering
+facilities, etc.</p>
+<p>This dick move made some of the coworkers staring to reconsider their
+life choices seriously.</p>
+<h3 id="tocanch17" class="tvis">Rushing V20</h3>
+<p>V20 is going to be the next major release of Deepin. Initially the
+planning for this release was rather relaxed: this major overhaul was
+projected to take about a year to mature, during which another one or
+two maintenance releases of the current Deepin 15 were planned. However,
+for some reason unknown to us <a id="n9" href="#note9" class="note">[9]</a>, the deadline was pushed back by a huge margin: now it’s
+expected to be released somewhere between Q4 2019 and Q1 2020.</p>
+<p>Now, suddenly the rapid increase of personnel makes sense. But I have
+to question the quality of the resulting software – and it’s not looking
+too good for them either. Many of the new applications suffer from major
+performance deficiency: one of the development snapshots of Deepin
+picture viewer takes more than two minutes to startup, and completely
+blacks out if the window is resized, the new archive manager can cause
+major lags on the file manager. Hell, even my own creation, the new
+computer view for Deepin file manager, suffers from some performance
+issues while resizing. But I simply didn’t have the time to address it
+completely.</p>
+<p>Wheels have been reinvented during the sprint, lots of them. In fact,
+it seems to be one of their goals to out-source no applications from
+other desktop environments. They even created a browser (based on the
+Chromium code base, of course) with the help from Qihoo 360 and an IME
+with the help from Sougou. I could give Deepin credit for the effort,
+but the quality of these wheels are questionable at best.</p>
+<h3 id="tocanch18" class="tvis">Lacking / bad community
+interaction</h3>
+<p>This is more or less the same thing as what I have already wrote in
+‘The “Deepin is spyware” problem’. But now that I have more insight, I
+could write more on this topic.</p>
+<p>Deepin is a for-profit company, feature requests from commercial
+customers always take priority. As the number of employees barely meets
+the need to develop those features, requests from the community are
+usually ignored straight away. Such filtering happens before the
+developers could see the feature requests – we won’t know about them
+unless we browse the support forum ourselves.</p>
+<p>The ‘designer-central’ process is very problematic too. In my
+opinion, Deepin’s chief designer is extremely self-centric, narcissistic
+even. This resulted in some very serious uproar in the community such as
+this one:
+https://github.com/linuxdeepin/developer-center/issues/1210#issuecomment-496341368
+Sometimes even the developers couldn’t put up with these design choices,
+and added hidden options for switching to something more sensible.</p>
+<h3 id="tocanch19" class="tvis">Illegal business practice</h3>
+<p>Namely, deepin-wine breaking GNU LGPL.</p>
+<p>Deepin has been distributing a fork of an outdated branch of wine
+without releasing the source code for quite some time, which is a very
+explicit disregard to wine’s license.</p>
+<p>They have promised to release the source code, but has yet to do so.
+In the mean time, wine has made three stable releases. So far they have
+only came up with a single justification: the fear of their domestic
+commercial competitors <a id="n10" href="#note10" class="note">[10]</a>‘stealing’ their hard work. If
+this bullshit stands for even a second, everybody on this planet would
+have been a drug dealer ’cause laws don’t do shit.</p>
+<p>To be frank, we have dozens of (L)GPL breakers here in China and we
+never stop producing even more of them. We have Allwinner and XiaoMi, to
+name a few. FFmpeg’s original hall of shame page would give you a even
+longer list, and you will find the names of some gargantuan Chinese tech
+companies in it.</p>
+<p>I don’t even think Deepin’s international acceptance has anything to
+do with its commercial success (or lack thereof). Do they even have any
+overseas commercial customers? If Deepin has really been a commercial
+success, I probably wouldn’t have to develop with a computer equipped a
+shitty Pentium that otherwise would find its home in the dumpster.</p>
+<h3 id="tocanch20" class="tvis">Restructure shenanigans</h3>
+<h3 id="tocanch21" class="tvis">Walking away from “the
+founders’ spirits”</h3>
+<p>This is definitely, definitely a huge misstep and a real deal
+breaker.</p>
+<p>IMO Deepin was once among the best meritocracy free software
+community in China. However with the changes applying to their roadmap
+since v20, everything started to disintegrate.</p>
+<p>Barriers were deliberately added to the community contribution
+process (the repositories on GitHub are now merely synced with internal
+repositories). Writing documentation was considered slacking (happened
+to me a couple of times), making the already terrible documentation
+situation even worse. They basically stopped even trying to make the
+development process transparent to the public.</p>
+<p>User’s freedom was thrown out of the window. Community edition now
+requires logging into an online account to enable root access, which is
+basically the first step to a complete vendor lock down. I imagine many
+users would resort to other distros and install DDE instead (if they
+still fancy using DDE in its new look and feel).</p>
+<p>Don’t get me wrong. DDE was (and still is) a beautiful desktop
+environment (even only superficially as some people might thought). It
+has followers who will use it no matter what. However, it demands a
+fork. A fork with its founders’ spirits in mind.</p>
+<h2 id="tocanch22" class="tvis">Epilogue</h2>
+<p>I’ve actually tried out the current public beta of Deepin V20 as of
+writing this section, and the majority of the issues I mentioned above
+still hold up. Grave performance degradation seems a lot less common
+though, although my shitty-performing computer view code has barely been
+touched since I left. A lot of applications are still in dare need of
+polishing. They’d better keep those commits flowin’.</p>
+<p>At this point of time I don’t even know what I was rambling about. It
+was 1:40 in the morning. Did I just typed over 15000 characters only to
+diss Deepin? Nope. Dwelling on our past success never makes us progress.
+It’s the reflection upon the mistakes we made that does.</p>
+<p>https://www.zhihu.com/question/344339517/answer/817025546</p>
+</article>
+<!--
+vim: tw=0 syntax=markdown spell spelllang=en_us
+-->
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: vala?<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: and
+definitely not a shitty one that only does repetitive work! In fact
+while I was once chatting with Hualet, he told me I was probably among
+the best interns ever here.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: cough cough, RTX 2080,
+cough cough.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: These were formerly available on a documentation website on
+one of deepin’s domains, but were somehow taken down later.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: CSDN is a blogging platform and a forum for Chinese
+developers. We don’t have stackoverflow or a clone of it here in China,
+so CSDN became the savior of many Chinese programmers. Unfortunately
+most of the user base of CSDN are equally bad as these new
+employees.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: His code reviews were sometimes even to a
+degree of nitpicking, but I’m not really complaining since my code is
+shit.<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: To BLumia: if you are reading this, I’m
+not trying to be harsh here. It’s just a small reminder that you should
+probably pay more attention to code review (if you’re still doing
+it).<br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: A lot of this stuff is specific to Deepin (the distribution),
+so you can get rid of most (but not all) of them by doing
+so.<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: everyone has their own
+speculations, of course. Mine is that they wish to hand out a surprising
+present to their users, which I don’t feel super positive
+for.<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: Please, don’t mention the ones backed
+by the government (or in other words, ‘GuanXi’). They are not an excuse
+for breaking laws or licenses.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2019-09-04.html b/blog/post/2019-09-04.html
index 5d1ee95..64e0510 100644
--- a/blog/post/2019-09-04.html
+++ b/blog/post/2019-09-04.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"September 2019 Site Update")</title>
+<meta name="description" content="«September 2019 Site Update» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -83,30 +53,47 @@ loadTheme();
<ul id="tocroot">
<li><a class="toctarg" href="#tocanch0">The Privacy Update</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch1">Getting rid of recaptcha</a></li><li><a class="toctarg" href="#tocanch2">The “Privacy Policy”</a></li><li><a class="toctarg" href="#tocanch3">And … that’s all?</a></li></ul></li></ul>
</li>
- <li style="margin-left:-0.5em"><a id="prevp" href="2019-04-25.html">Prev post</a></li>
- <li style="margin-left:-0.5em"><a id="nextp" href="2020-04-11.html">Next post</a></li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2019-06-24.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2020-11-20.html">Next post</a></li>
</ul>
</div>
<div id="content">
<h2 id="titleh" class="TText" style="font-wight:normal;">September 2019 Site Update</h2>
<div id="datetags" class="TText" style="margin-bottom:1em;">2019-09-04<br>#web</div>
<hr><div id="article" class="TText"><article>
-<p>It’s been a while since the last site update. It’s time for one now.</p>
+<p>It’s been a while since the last site update. It’s time for one
+now.</p>
<h2 id="tocanch0" class="tvis">The Privacy Update</h2>
-<p><a href="https://cgit.chrisoft.org/web.git/commit/?id=3778fbfebf1cecda4036cd2a50e3b8239c80f1eb">The commit</a></p>
-<p>This is <strong>not</strong> a visually significant update. Aside from some wording changes and new links, there’s nothing much more to it. The most important stuff is (again) all under the hood.</p>
+<p><a href="https://cgit.chrisoft.org/web.git/commit/?id=3778fbfebf1cecda4036cd2a50e3b8239c80f1eb">The
+commit</a></p>
+<p>This is <strong>not</strong> a visually significant update. Aside
+from some wording changes and new links, there’s nothing much more to
+it. The most important stuff is (again) all under the hood.</p>
<h3 id="tocanch1" class="tvis">Getting rid of recaptcha</h3>
-<p>In the February site update, I upgraded the site from recaptcha 2 to recaptcha 3. Now it’s time to remove it.</p>
-<p>As a privacy update, the task of the highest priority is to free users of this site from lengthy and obscure privacy terms (also non-free scripts) made by monopolistic tech giants like Google. And I was actually planning to do so for quite some time. It finally happened.</p>
-<p>I have now switched to a relatively relaxed backend-only check that only checks whether your public IP address is in a blacklist (abuseipdb.com).</p>
+<p>In the February site update, I upgraded the site from recaptcha 2 to
+recaptcha 3. Now it’s time to remove it.</p>
+<p>As a privacy update, the task of the highest priority is to free
+users of this site from lengthy and obscure privacy terms (also non-free
+scripts) made by monopolistic tech giants like Google. And I was
+actually planning to do so for quite some time. It finally happened.</p>
+<p>I have now switched to a relatively relaxed backend-only check that
+only checks whether your public IP address is in a blacklist
+(abuseipdb.com).</p>
<h3 id="tocanch2" class="tvis">The “Privacy Policy”</h3>
<p>If you haven’t read it yet, read it <a href="https://chrisoft.org/blog/post/Privacy.html">here</a>.</p>
-<p>This is not a very serious privacy policy, but rather just random rambling on privacy-related topics.</p>
-<p>Anyway this fulfilled quite an important missing part of my website, be it good or not.</p>
+<p>This is not a very serious privacy policy, but rather just random
+rambling on privacy-related topics.</p>
+<p>Anyway this fulfilled quite an important missing part of my website,
+be it good or not.</p>
<h3 id="tocanch3" class="tvis">And … that’s all?</h3>
-<p>Um… there’s also a new ‘hosted by ConoHa’ banner on the main page to reflect the current state of this site. It leads to their ‘ConoHa mode’ index (as opposed to the plain main page without their virtual character). It’s not a sponsored link so I don’t earn anything if you click it.</p>
+<p>Um… there’s also a new ‘hosted by ConoHa’ banner on the main page to
+reflect the current state of this site. It leads to their ‘ConoHa mode’
+index (as opposed to the plain main page without their virtual
+character). It’s not a sponsored link so I don’t earn anything if you
+click it.</p>
<p>Also also, I’ve got hold of a new domain name (<a href="https://pineapple.cat">pineapple.cat</a>. Check it out!</p>
-<p>With that said, everything in this update should be covered now. Not a huge update is it?</p>
+<p>With that said, everything in this update should be covered now. Not
+a huge update is it?</p>
</article>
<!--
vim: tw=0 syntax=markdown spell spelllang=en_us
diff --git a/blog/post/2020-11-20.html b/blog/post/2020-11-20.html
new file mode 100644
index 0000000..938ebf5
--- /dev/null
+++ b/blog/post/2020-11-20.html
@@ -0,0 +1,2522 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"EDIROL SD-80: The Adventure Continues")</title>
+<meta name="description" content="«EDIROL SD-80: The Adventure Continues» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">EDIROL SD-80: The Adventure Continues</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/device-review/">device-review</a></li><li><a href="/blog/list/midi/">midi</a></li><li><a href="/blog/list/music/">music</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">“Official” Service Manual</a></li><li><a class="toctarg" href="#tocanch1">USB-PD Mod</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">(Accidentally) Circuit bent
+SD-80</a></li></ul></li><li><a class="toctarg" href="#tocanch3">Recording Setup Update Part
+1</a></li><li><a class="toctarg" href="#tocanch4">Recording Setup Update Part
+2</a></li><li><a class="toctarg" href="#tocanch5">Recording Setup Update Part
+3, 4, 5…</a></li><li><a class="toctarg" href="#tocanch6">Rompler Preservation</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch7">Emulation</a></li><li><a class="toctarg" href="#tocanch8">Sampling the Rompler</a></li><li><a class="toctarg" href="#tocanch9">Dumping and Deciphering</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch10">Extra rambling about the ROM
+chip</a></li></ul></li><li><a class="toctarg" href="#tocanch11">SD-20 MIDI File Converter</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch12">FrankenTTS-1</a></li><li><a class="toctarg" href="#tocanch13">Other observations</a></li><li><a class="toctarg" href="#tocanch14">So… is this it?</a></li></ul></li><li><a class="toctarg" href="#tocanch15">Roland Cloud</a></li></ul></li><li><a class="toctarg" href="#tocanch16">A
+History lesson from someone who barely knows anything about it</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch17">LA</a></li><li><a class="toctarg" href="#tocanch18">(Unnamed synth engine in
+U-110)</a></li><li><a class="toctarg" href="#tocanch19">EP</a></li><li><a class="toctarg" href="#tocanch20">GP</a></li><li><a class="toctarg" href="#tocanch21">XP</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch22">Original XP</a></li><li><a class="toctarg" href="#tocanch23">XP2</a></li><li><a class="toctarg" href="#tocanch24">XP3</a></li><li><a class="toctarg" href="#tocanch25">XP6</a></li><li><a class="toctarg" href="#tocanch26">XP7</a></li></ul></li><li><a class="toctarg" href="#tocanch27">XV</a></li><li><a class="toctarg" href="#tocanch28">WX</a></li><li><a class="toctarg" href="#tocanch29">Beyond WX</a></li></ul></li><li><a class="toctarg" href="#tocanch30">Role played by the
+CPU in sound generation</a></li><li><a class="toctarg" href="#tocanch31">Other Curious Stuff</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch32">SD-80 is an XV-5080 …</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch33">SD-80’s sound content</a></li></ul></li><li><a class="toctarg" href="#tocanch34">More on SD-80 vs SD-90 vs
+SD-20</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch35">What does a SD-90 have
+that SD-80 doesn’t?</a></li><li><a class="toctarg" href="#tocanch36">What does a SD-80 have
+that SD-90 doesn’t?</a></li><li><a class="toctarg" href="#tocanch37">What’s the SD-20 anyway?</a></li><li><a class="toctarg" href="#tocanch38">What role does MFX play?</a></li></ul></li><li><a class="toctarg" href="#tocanch39">Light Load vs
+High Load</a></li><li><a class="toctarg" href="#tocanch40">Block Diagram</a></li><li><a class="toctarg" href="#tocanch41">Other weird and interesting
+stuff</a></li></ul></li><li><a class="toctarg" href="#tocanch42">Errata of the original post</a></li><li><a class="toctarg" href="#tocanch43">References</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2019-09-04.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2021-06-03.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">EDIROL SD-80: The Adventure Continues</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2020-11-20<br>#device-review #midi #music</div>
+ <hr><div id="article" class="TText"><script>
+window.addEventListener("DOMContentLoaded",function(){
+const cl=document.querySelectorAll('div.collapse');
+let n=0;
+for(let x of cl)
+{
+ const d=document.createElement('blockquote');
+ const dd=x.cloneNode(true);
+ x.parentNode.insertBefore(d,x);
+ x.parentNode.removeChild(x);
+ dd.id=`cc${n++}`;
+ dd.style.display='none';
+ const s=document.createElement('span');
+ const b=document.createElement('b');
+ const a=document.createElement('a');
+ a.classList.add('ca');
+ a.setAttribute('x',n-1);
+ a.innerHTML='show';
+ a.href='javascript:void(0)';
+ if (dd.hasAttribute('caption'))
+ b.innerHTML=dd.getAttribute('caption');
+ else
+ b.innerHTML=dd.getAttribute('data-caption');
+ s.appendChild(b);
+ s.appendChild(document.createTextNode(' ['));
+ s.appendChild(a);
+ s.appendChild(document.createTextNode(']'));
+ d.appendChild(s);
+ d.appendChild(dd);
+ a.onclick=function()
+ {
+ let x='none';
+ if(a.innerHTML=='show')
+ {
+ a.innerHTML='hide';
+ x='block';
+ }
+ else
+ {
+ a.innerHTML='show'
+ }
+ document.getElementById(`cc${a.getAttribute('x')}`).style.display=x;
+ }
+}
+const al=document.querySelectorAll('audio');
+n=0;
+for(let x of al)
+{
+ x.id=`a${n++}`;
+ x.onplay=function()
+ {
+ for(let x of al)
+ {
+ if(x.id!=this.id)x.pause();
+ }
+ }
+}
+});
+</script>
+<article>
+<p>This the follow up article of my first post on the SD-80. View it <a href="https://chrisoft.org/blog/post/2019-04-25.html">here</a>.</p>
+<p>It’s been <del>one year and a half</del>
+<del style="text-decoration-style: double">two years</del> three years
+since I got my SD-80. A lot of stuff happened (including the great
+pandemic of COVID-19 and my escape from Wuhan). I’ve also discovered a
+lot more about the SD-80. Instead of updating the original post (which
+is already excessively long), I decided to start a new post instead.</p>
+<p>The actual publish date of this post is 2022-06-30 <del>because I
+have crippling procrastination</del>.</p>
+<p>My special thanks go to:</p>
+<ul>
+<li>Kalas, who contacted me for my original SD-80 post, without whom
+half of this article wouldn’t even exist.</li>
+<li>Discord user KR.Palto#7592, who also has a <a href="https://www.youtube.com/c/KRPalto47_th_MIDI">YouTube channel</a>,
+for providing plenty of useful information and PCB shots of various
+Roland synth modules.</li>
+</ul>
+<p>I’ve been procrastinating the release of this post for too long
+(almost 2 years by now). For this reason, the information I had on these
+modules may have updated half-way through the writing of this post.
+Therefore this post may contain self-contradicting statements. I’ll try
+to clear up any confusing parts. Feel free to reach to me if you find
+any, or just for any thoughts you have on this post. I would encourage
+anyone reading this post to get in touch with me if you have anything to
+discuss or find a mistake in this post. Every message will be greatly
+apprecitated. You can find ways to contact me in the “about” section of
+the home page.</p>
+<h2 id="tocanch0" class="tvis">“Official” Service Manual</h2>
+<p>The site where I got my other service manuals for Roland synths (none
+of which I really own) has been updated with a service manual for SD-80.
+I got one copy immediately once I knew about this (Special thanks go to
+Kalas for letting me know).</p>
+<p>Most of the service manual goes as expected: the general format, most
+chips (I correctly identified all chips that has Roland marking on them
+somehow), the block diagram and testing mode. There’s really not that
+much information in this manual that is new to me. The schematics are
+extremely useful for modding and repairing though.</p>
+<div class="collapse" data-caption="Updated list of integrated circuit chips on SD-80 main board">
+<table>
+<colgroup>
+<col style="width: 8%">
+<col style="width: 18%">
+<col style="width: 21%">
+<col style="width: 51%">
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: center;">Label</th>
+<th style="text-align: center;">Engravement</th>
+<th style="text-align: center;">Model</th>
+<th style="text-align: center;">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">IC 1</td>
+<td style="text-align: center;">62292 361</td>
+<td style="text-align: center;">M62292FP-D60J</td>
+<td style="text-align: center;">Regulator</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 2</td>
+<td style="text-align: center;">6417706 SH3 BC13008 133 0413</td>
+<td style="text-align: center;">HD6417706</td>
+<td style="text-align: center;">SH3 CPU</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 3</td>
+<td style="text-align: center;">LH28F 160BJE-BTL80 SHARP JAPAN 0428
+7xN</td>
+<td style="text-align: center;">LH28F 160BJE-BTL80</td>
+<td style="text-align: center;">16Mbit Flash Memory</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 4, IC 6</td>
+<td style="text-align: center;">SANYO LC381616IET-70 KZA7G0CD1 0042</td>
+<td style="text-align: center;">SDRAM LC3816161ET-70-TLM</td>
+<td style="text-align: center;">16Mbit SDRAM (System RAM)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 5, IC 37</td>
+<td style="text-align: center;">‘H5’ or ‘115’ (illegible)</td>
+<td style="text-align: center;">TC7SH04FU</td>
+<td style="text-align: center;">Inverter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 7</td>
+<td style="text-align: center;">4D46 LV 00A</td>
+<td style="text-align: center;">HD74LV00A</td>
+<td style="text-align: center;">NAND Gate</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 8, IC 20, IC 22~25</td>
+<td style="text-align: center;">4C1Y LV 245A</td>
+<td style="text-align: center;">HD74LV245A</td>
+<td style="text-align: center;">8-bit Transceiver</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 9, IC 11</td>
+<td style="text-align: center;">F P42AB VT245A</td>
+<td style="text-align: center;">74VHCT245A</td>
+<td style="text-align: center;">8-bit Transceiver</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 10, IC 12</td>
+<td style="text-align: center;">0431H LVXC3245</td>
+<td style="text-align: center;">TC74LVXC3245FS</td>
+<td style="text-align: center;">Configurable 8-bit Transceiver</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 13</td>
+<td style="text-align: center;">VHC T139A 4 23</td>
+<td style="text-align: center;">TC74VHCT139AFT</td>
+<td style="text-align: center;">Dual 2/4 Decoder</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 14</td>
+<td style="text-align: center;">‘H12’ or ‘H2’ (illegible)</td>
+<td style="text-align: center;">TC7SH08FU</td>
+<td style="text-align: center;">AND Gate</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 15</td>
+<td style="text-align: center;">4D36 LV 04A</td>
+<td style="text-align: center;">HD74LV04A</td>
+<td style="text-align: center;">Hex Inverter</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 16</td>
+<td style="text-align: center;">4D16 LV 14A</td>
+<td style="text-align: center;">HD74LV14A</td>
+<td style="text-align: center;">Hex Schmitt-Trigger Inverter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 17</td>
+<td style="text-align: center;">Roland R02902867 137 352B100</td>
+<td style="text-align: center;">M37641M8-137FP</td>
+<td style="text-align: center;">7641 8-bit microcontroller, MIDI/USB
+interface</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 18</td>
+<td style="text-align: center;">VH3 139 4 24</td>
+<td style="text-align: center;">TC74VHC139FT</td>
+<td style="text-align: center;">Dual 2/4 Decoder</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 19, IC 27</td>
+<td style="text-align: center;">Roland R01455956 RA08-503 JAPAN 0330EAI
+F0032ZAC</td>
+<td style="text-align: center;">TC223C660CF-503</td>
+<td style="text-align: center;">Tone Generator + Effects Processor with
+integrated LCD &amp; Input Controller</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 21</td>
+<td style="text-align: center;">7WU04 4.F</td>
+<td style="text-align: center;">TC7WU04FU</td>
+<td style="text-align: center;">Inverter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 26, IC 30</td>
+<td style="text-align: center;">HYUNDAI GM71C18163CJ6 0040 AG1
+KOREA</td>
+<td style="text-align: center;">GM71C18163CJ-6</td>
+<td style="text-align: center;">16Mbit EDO DRAM (XV RAM / Effects delay
+line)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 28</td>
+<td style="text-align: center;">Roland R02678601 23C128L-529J
+0224E7007</td>
+<td style="text-align: center;">UPD23C128040ALGY-***-MJH</td>
+<td style="text-align: center;">128Mbit Mask ROM (Wave ROM)</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 29</td>
+<td style="text-align: center;">Roland R02678612 23C128L-535K
+0222E7005</td>
+<td style="text-align: center;">UPD23C128040ALGY-***-MKH</td>
+<td style="text-align: center;">128Mbit Mask ROM (Wave ROM)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 31, IC 35</td>
+<td style="text-align: center;">4570 431</td>
+<td style="text-align: center;">UPC4570G2</td>
+<td style="text-align: center;">Operational Amplifiers</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 32, IC 34</td>
+<td style="text-align: center;">PCM1716E 27ZDHFM</td>
+<td style="text-align: center;">PCM1716E</td>
+<td style="text-align: center;">DAC</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 33</td>
+<td style="text-align: center;">04 16H TC9271FS</td>
+<td style="text-align: center;">TC9271FS</td>
+<td style="text-align: center;">Digital Audio Modulator/Transmitter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 36</td>
+<td style="text-align: center;">A E</td>
+<td style="text-align: center;">TA78L05F</td>
+<td style="text-align: center;">Regulator</td>
+</tr>
+</tbody>
+</table>
+<p>The CPU is in clock mode 1 (MD2=MD1=0, MD0=1). Input clock is 12MHz
+from the 8-bit 7641 controller. Actual clock of the SH-3 CPU depends on
+the value of its FRQCR register. However, the only possible values of
+the internal clock speed is either 48MHz or 96MHz (refer to the
+datasheet of SH7706 for details) <a id="n1" href="#note1" class="note">[1]</a>. Either way, the CPU is downclocked by quite a
+large margin.</p>
+<p>The tone generator RA08-503 “XV” is an ASIC manufactured by Toshiba
+on a 300nm process (type TC223C).</p>
+</div>
+<h2 id="tocanch1" class="tvis">USB-PD Mod</h2>
+<p>WARNING: I’m a computer scientist (in its loosest sense), not an
+electrical engineer. Do not take any part of this section as advice. If
+you fried your equipment (I did!!) following this as an instruction,
+don’t blame it on me.</p>
+<p>The 220V to 110V converter brick I have to carry around has been
+bugging me since the very first day I got my SD-80. Because the unit
+only consumes around 10 watts of power, I’ve always been dreaming of
+alternative ways to power it. When I first cracked my module open, I
+measured the power rails going out from the power supply unit: there is
+a ±15V pair, plus a +5V rail.</p>
+<p>My top candidate was a solution based around USB-PD. I’ve seen people
+modding their ThinkPads to charge through USB Type-C on r/ThinkPad, so I
+thought that module plus some DC-DC converter circuitry will do the job.
+I also had a fallback plan, which is basically to use any switching mode
+power supply that accepts universal voltage has two output rails (one
+positive and one negative), and stick some additional regulator
+circuitry to generate the 5V output.</p>
+<p>The USB-PD trigger module is actually very easy to come by nowadays,
+especially for someone in China. While others struggles to find these
+weird stuff on ebay and aliexpress, we just source them straight from
+taobao (which is essentially aliexpress for domestic users). There are
+even ready-to-use multi-rail voltage converter modules out there (they
+are either based around LM337/LM317, or TPS543x). Finally I picked the
+(seemingly) most popular PD trigger module people use to mod laptops
+from YZXstudio, and an adjustable voltage converter module based around
+TPS5430. The pictures below are from their sellers.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sdp2_pdtrigerboard.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sdp2_pdtrigerboard.jpg"></a> <br>USB-PD
+trigger board
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sdp2_vrm.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sdp2_vrm.jpg"></a> <br>Adjustable VRM
+Module
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>I also bought some basic tools for soldering (Chinese knock-off of
+Quick 936A, lead-based solder and solder wick – I was too dumb to
+remember purchasing any flux) to make sure I can do the modding in my
+dorm.</p>
+<p>I waited a few days for all packages to arrive. After that I tested
+every component I need and they worked just fine. It’s time to pull the
+trigger. I started with desoldering the AC input socket. That went
+decently smoothly. My confidence started to build up and proceeded to
+desolder the original SMPS module, which is a rectangular daughter board
+that has quite a few pins soldered on both sides of the board. Things
+went horribly wrong (particularly because I didn’t have any flux and the
+original lead-free solder refused to flow or blend with my leaded
+solder) and I started ripping tracks off the base board. Finally I
+decided it was an impossible task for me to desolder it without
+completely destroying both boards, so I simply drilled the pins out of
+the board. While the base board wasn’t totally destroyed, it was pretty
+close. I soldered wires directly to the components on the base board
+(because tracks on the other end have been ripped off). At this time my
+soldering job was just totally awful because I was pissed and it was
+super late into the night. Anyway, when I finally piecing everything
+together, it somehow worked.</p>
+<p>Next it was time to put everything back into place. I had the idea of
+designing a 3d-printed holder for the USB Type-C extension cable that
+fills the hole for the original AC socket, however I couldn’t even
+afford a proper 2d-printing setup, let alone a 3d one. So I have to
+scrap that idea for now. None of the screw holes on the converter board
+can fit the holes on the chassis, so I just taped the module down. It
+was a complete mess inside my SD-80 now, but at least everything still
+worked (until a couple minutes later). I did mention that I had the wish
+to make custom acrylic chassis for my SD-80 some day in the future,
+hopefully I can get this mess fixed by then.</p>
+<div style="text-align:center;max-width:90%;">
+<a href="//filestorage.chrisoft.org/blog/img/sdp2_pdmodded.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sdp2_pdmodded.jpg"></a> <br>The USB-PD
+modded SD-80
+</div>
+<h3 id="tocanch2" class="tvis">(Accidentally) Circuit bent
+SD-80</h3>
+<p>I started messing around and decided to try to run the SD-80 without
+the ±15V rail. Everything except the front panel phones output and
+output 1 on the back panel worked just fine. This is not very surprising
+– all chips on the main board only takes &lt;= 5V, and it makes sense to
+derivate all those voltages from the 5V rail. After a quick look at the
+service notes, I found that the ±15V rail is only used by the OpAmps in
+the final output stage of output 1, which is on the volume board.</p>
+<p>And then something extremely stupid happened. Any proper electrical
+engineer will cringe hard. At this point I was getting cocky, and
+started randomly probing around with my multimeter on the volume board.
+I “accidentally” shorted the first two pins of the connector going from
+the main board into the volume board (pin 1 and pin 2 on CN7 of volume
+board). The output from the headphone jack immediately turns into
+complete garbage (severe distortions on low frequencies). The OpAmps
+chip on the volume board started getting ridiculously hot… crap! I still
+managed to fry something for an otherwise “perfect” modding project!</p>
+<p>Of course this is undesirable. So I had to find a fix to this.</p>
+<p>Fortunately, nothing on the main board seemed to be hurt. I can just
+bypass the volume control and get the correct output on output 1 using
+some jumper wires. So the fault is contained in the volume board. I’ve
+basically sent -15V straight into the base of two transistors, but
+measuring those transistors didn’t reveal anything wrong with them. So I
+had to assume I have fried the amp chip (NJM4565). I got a few
+replacements (NJM4580, compatible spec-wise) from taobao, and replaced
+the “faulty” NJM4565 (still without using flux). But the audio output is
+still messed up and the opamp chip still gets very hot after the
+replacement. I decided to give up for now, and look into the thing
+later. Meanwhile I just tucked some of the wires from CN6 into CN7 so
+that I can still get analog output from output 1 on the back panel.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sdp2_volbrd_fixattempt.jpg"><img style="width: 33%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sdp2_volbrd_fixattempt.jpg"></a> <br>My
+terrible SMD soldering
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sdp2_bypass.jpg"><img style="width: 33%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sdp2_bypass.jpg"></a> <br>Recombined plug
+for volume board bypass
+</div>
+</td>
+</tr>
+</tbody></table>
+<div style="text-align:center;max-width:90%;">
+<br>
+</div>
+<h2 id="tocanch3" class="tvis">Recording Setup Update Part
+1</h2>
+<p>Since I have always wanted to record my SD-80 through a digital link
+(even before frying the analog output), I have been keeping an eye on
+cheap digital recording solutions. Modern professional audio interfaces
+never come with digital input on budget models. Among the older
+interfaces, UA-25(EX) from Roland (EDIROL / Cakewalk) seems to be a
+reasonable choice. There are also a bunch of different models from
+various brands of the same era that have digital inputs. However these
+models are virtually impossible to get in China. Then some cheapo
+consumer grade stuff caught my attention – several relatively nameless
+brands have “sound cards” for home theater uses that have digital I/O.
+Those are priced at roughly 200~300 Chinese yuan. Among those I found a
+more widely recognized brand called Terratec. They have PCI-e and USB
+sound cards that comes with digital I/O and are available for purchase
+in China. Price are on the higher end (300+ CNY), however still way
+cheaper than the cheapest professional audio interface that doesn’t have
+digital I/O (those start from ~800 CNY). Plus these models seem to have
+a reasonable Linux user base, so I got their Aureon 7.1 USB.</p>
+<p>This thing feels extremely cheap on first sight, weights close to
+nothing, and is made entirely out of plastic. It comes with an extremely
+thin S/PDIF fiber optical cable which looks so fragile that a single
+touch may break it. It does work out of the box. ALSA recognizes it as
+“Aureon 7.1 USB” without further clue about the chip it uses, however
+the Windows driver is more telling. Its control panel associates the
+chip with a Taiwanese company called Cmedia, and the kernel driver is
+named <code>cm106.sys</code>. Upon further investigation this thing is
+likely to be based on their CM106 chip (which is an ancient solution
+from 2003), or its pin-compatible successor CM6206. I don’t have
+interest in disassembling it right now (update: confirmed by a teardown
+later. It’s indeed based around the CM6206), but either way it’s a cheap
+consumer grade solution.</p>
+<p>SD-80’s digital output is fixed at 44100 Hz sample rate. So the sound
+card must also record at 44100 Hz to make a correct recording (unless it
+has internal resampling). This is easily doable under Windows (just
+select the appropriate sampling rate in the device properties dialog).
+It’s also reasonably easy with Jack, where you can just start the server
+on that specific device with the correct sampling rate. But this is not
+that easy to achieve for pulseaudio. By default, recent versions of
+pulseaudio auto detects cards with the <code>module-udev-detect</code>
+module, which doesn’t allow setting a different sample rate for a single
+sound card. Setting <code>alternate-sample-rate</code> doesn’t work
+either because this card supports digital signals at 48000Hz which in my
+case is the value for <code>default-sample-rate</code>, and therefore
+would not fallback to <code>alternate-sample-rate</code>. I had to write
+a small function to fix this:</p>
+<pre><code>spdif_samplerate()
+{
+ pacmd unload-module `pacmd list-modules | grep -B 2 Aureon_7 | awk '/index:/ {print $2}'`
+ pacmd load-module module-alsa-card device_id=`awk '/Aureon 7\.1 USB$/{print $1}' /proc/asound/cards` name="usb-0ccd_Aureon_7.1_USB-00" card_name="alsa_card.usb-0ccd_Aureon_7.1_USB-00" namereg_fail=false tsched=yes fixed_latency_range=no ignore_dB=no deferred_volume=yes use_ucm=yes avoid_resampling=no rate=44100
+}</code></pre>
+<p><del>Using a cheap consumer grade card does come with consequences.
+The recording seems to have a small DC bias – it’s not real DC though,
+the offset changes from time to time. When the input signal goes silent,
+the offset might differ from the offset when the signal was silent last
+time.</del> <a id="n2" href="#note2" class="note">[2]</a> For this reason, I always add a high-pass filter
+when using the material recorded by this sound card. With the HPF
+applied, this sound card does produce clearer digital recording than my
+Scarlett Solo with very cheap cables.</p>
+<p>There’s no ASIO driver for this card either (Aureon 7.1 PCIe does
+have ASIO driver, but I can’t install that card on my laptop), which
+means I have to either use Steinberg’s generic ASIO driver, or ASIO4ALL,
+both of which are… kind of trash, but still usable. The card doesn’t
+have a bad latency issue though: it’s obviously way worse than the
+Scarlett, but still tolerable.</p>
+<p>So that’s my <del>current</del> recording setup. I’m currently OK
+with it. However I’m not going to stick with it forever. I’ll upgrade to
+a UA-25(EX), or better yet, an SD-90 because that way I can use its ASIO
+output directly, plus I’ll be able to chain my SD-80 to it and use both
+at the same time.</p>
+<h2 id="tocanch4" class="tvis">Recording Setup Update Part
+2</h2>
+<p>(This part is written Q4 2021)</p>
+<p>Yes I did upgrade to a UA-25 (non-EX). I got mine for about $60
+(after a long struggle against eBay’s virtually non-existent customer
+service to lift a stupid suspension on my account).</p>
+<p>Gentoo Linux handles this new interface without any problem. The
+troublesome part is Windows (again). Just like the SD-80, Roland didn’t
+release any Windows 10 driver for the UA-25. <a href="https://chrisoft.org/blog/post/2019-04-25.html#tocanch4">The
+trick</a> I used to make their SD-80 Windows 8/8.1 driver install on
+Windows 10 worked fine, and the driver installed correctly. But things
+quickly went down hill. Whenever I open an application that uses ASIO,
+the driver freaks out and causes audio dropouts like crazy. This glitch
+makes the driver basically unusable.</p>
+<p>I tried drivers for different Windows versions. Nothing changed. When
+I was desperate and searching around the web, I discovered that UA-25EX
+has an official Windows 10 driver. UA-25EX is virtually the same as
+UA-25 except it comes with an improved limiter section which I assume
+has largely nothing to do with the driver. So I decided to try some “mad
+hax”.</p>
+<p>Windows driver for UA-25EX is only available from Microsoft as a
+Windows update package. Roland says if you have a UA-25EX, the package
+will automatically install itself once you plug it in. But I don’t have
+a UA-25EX: I only have a UA-25. So I had to go to the Windows Update
+Catalog, looked for the driver package there, and download the build for
+my computer (which turned out to be much harder than it needs to be, but
+I won’t go deeper into that here). I extracted the package, and modified
+the USB product ID the driver is designed for in the INF file:</p>
+<pre><code>%DriverDeviceDesc%=DriverInstall, USB\VID_0582&amp;PID_00E6 ; UA-25EX</code></pre>
+<p>Just change <code>PID_00E6</code> to <code>PID_0074</code> (and also
+the comment if you wish). AND IT FRICKING INSTALLED. ASIO also worked
+perfectly. (Insert a thousand-word essay trashing Roland’s bad practice
+here.)</p>
+<p>So did the upgrade work? Nope. The DC bias is still there. Now it’s
+more likely that the DC bias is from the SD-80 itself. Also another very
+telling clue is that when the sound generator inside the SD-80 is reset,
+the DC bias immediately goes away. I did some additional research on the
+Internet and discovered people have theorized that the DC bias is from
+the effect processor. They are having a <a href="https://gearspace.com/board/electronic-music-instruments-and-electronic-music-production/1302162-roland-xv5080-spdif-issue.html">similar
+problem</a> with their XV-5080 and XV-5050 as well, both of which have
+the same synth engine as the SD-80. By replicating their experiments and
+getting the same result, I personally conclude that the DC bias comes
+from the amp / gain / filter section of the integrated effects
+processor. So I guess I’ll have to keep using high-pass filters on the
+output for now.</p>
+<p>So the only upgrade is that now I can record S/PDIF signal with
+native ASIO. Besides that, it’s actually a downgrade: Output from the
+computer will be muted if the digital input of the UA-25 is enabled.
+This forced me to keep using the analog input for monitoring.</p>
+<h2 id="tocanch5" class="tvis">Recording Setup Update Part
+3, 4, 5…</h2>
+<p>Yes I did upgrade. (again!!)</p>
+<p>I saw a UA-101 in a listing for $80. I bought it. Then there was a
+whole saga which ended in me getting two of them for the price of one.
+And then I saw a SD-90 for $120… you know what happened.</p>
+<p>This is getting too long to write in detail here. I’ll give detailed
+information on my current recording setup in a new post, if I care to
+write it at all.</p>
+<h2 id="tocanch6" class="tvis">Rompler Preservation</h2>
+<p>Kalas was extremely keen on preserving the sounds of SD-90/80 during
+our communications. I have the intention to keep these legendary Roland
+sounds around long into the future as well. We discussed the following
+possibilities. Note that due to the locked-down nature of SD-90/80, we
+referred to them mostly as “Romplers”, but these methods listed below
+apply to those expandable models as well, especially considering they
+are nothing but romplers that you can add more ROMs to, and the
+architecture of Roland’s PCM synth.</p>
+<p>In this section I’ll start using the word “SD-90” and “SD-80”
+interchangeably, and by saying “SD-90”, I’m actually referring to the
+synthesizer module built into it. If Roland was being honest when they
+were saying “the newly developed multitimbral MIDI sound module, as
+built into the well-received SD-90” when they were introducing the SD-80
+<a id="n3" href="#note3" class="note">[3]</a>, it should be
+safe to assume they are virtually the same thing. I know this is kind of
+sloppy. If you want to read more on this, checkout the <a href="#tocanch33">“More on SD-80 vs SD-90 vs SD-20”</a> section.</p>
+<h3 id="tocanch7" class="tvis">Emulation</h3>
+<p>This method was brought up by Kalas. Indeed there are a couple of
+sound modules / synthesizers that has been emulated with reasonable
+success. <a href="https://github.com/munt/munt">Munt</a> has an amazing
+emulation of Roland’s LA synthesis found in the MT-32 or D-50.
+<a id="n4" href="#note4" class="note">[4]</a> Yamaha’s FM
+synthesis chips have been reverse engineered from inside out: there are
+<a href="https://github.com/gtaylormb/opl3_fpga">implementations on
+FPGA</a>, multiple nearly perfect software implementations, and other
+bizarre stuff. MAME has emulation for multiple MU-series models, plus
+work has been put into making an emulated SC-55 in MAME.</p>
+<p>However, I personally don’t think emulation is the way to go for
+SD-90/80. The success (or lack thereof) of these emulated models does
+have their reasons:</p>
+<ul>
+<li>Emulation of Yamaha’s FM chips is a success because those chips are
+available to third-party sound card makers, and therefore have public
+datasheets that contains critical information for emulating the chip,
+which includes register mapping, and the detailed architecture of the FM
+synthesizer. This drastically decreased the amount of reverse
+engineering required to get a perfect emulated implementation. Roland
+has never made their synthesizer chips available to third-party vendors,
+and therefore it’s impossible to take advantage of public
+datasheets.</li>
+<li>Emulation of several early gaming consoles’ sound system has been
+successful because
+<ul>
+<li>They are relatively sample.</li>
+<li>Similar to Yamaha’s FM chips, programmers can also directly
+interface with them. Therefore their programming manuals have detailed
+description on how sound generation works in the chips. SD-90/80’s
+synthesizer chip XV meets neither of these two criteria.</li>
+</ul></li>
+<li>Most emulated sound modules in MAME have been a failure in terms of
+real-world usability. The emulated MU-series either freezes, produces no
+sound at all, or makes loud unexpected noise when playing the demo
+track. The SC-55 emulation barely works – they only got the CPU working
+and running its dumped control ROM. Please don’t get me wrong: the fact
+that some emulated MU model could make any sound is almost a miracle for
+me, and definitely a huge achievement despite the far-from-ideal results
+it currently has, as Yamaha’s sample based synth chips
+(<code>GEW/SWP</code> stuff) are no easy nut to crack. This approach is
+highly unlikely to work for the SD-90/80 because unlike gaming consoles,
+getting the CPU to run its system code doesn’t mean much for synthesizer
+emulation. It’s the emulation of the actual synth/DSP chip that matters.
+And the XV chip found in SD-90/80 is a <strong>monstrosity</strong>
+compared to the early SWP chip in the MU-series. For this reason, I find
+a pure emulation based solution difficult to implement for
+SD-90/80.</li>
+<li>Munt is successful because instead of an instruction-to-instruction
+emulation, it’s more like a software reimplementation of the LA synth.
+It doesn’t try to run the control ROM on an emulated Intel 8098 CPU, but
+instead only use it for determining some characteristics of the software
+implementation of the LA synth. This approach makes the most sense when
+trying to recreate SD-90/80 in software form, but still definitely
+require tons of reverse engineering (either blackbox or whitebox).</li>
+</ul>
+<p>For these reasons, I don’t think an OPL3-level emulation of SD-90/80
+is possible <a id="n5" href="#note5" class="note">[5]</a>. However, I will discuss an approach that
+resembles Munt’s in the <a href="#tocanch8">Dumping and Deciphering</a>
+section.</p>
+<h3 id="tocanch8" class="tvis">Sampling the Rompler</h3>
+<p>Many people have attempted to sample the SD-90. We already have the
+(in)famous THFont from forever ago that contains some samples from the
+SD-90, plus <a href="https://musical-artifacts.com/artifacts/1367">these</a> efforts to
+create a complete set of sampled instruments from the SD-90. However,
+these folks aren’t doing it in the most efficient way IMHO. Since the
+SD-90/80 is extremely editable, one can craft presets ideal for raw
+sample extraction (no filters, no LFO, just a plain tone with a constant
+amplitude envelope). Since many preset instruments in the SD-90/80
+consist of multiple layers using different samples, instead of sampling
+the patches, one can sample every individual waveform and layer the
+samples in a way similar to the original presets to make close
+imitations of SD-90/80 instruments. If done properly under ideal
+conditions, the resulting sample library should be around the same size
+of SD-90/80’s sample ROM, but decompressed (my guess is ~64 MiB
+<a id="n6" href="#note6" class="note">[6]</a>).</p>
+<p>If you’re only going to use the vanilla SD patches without any sort
+of modification (including filter response, envelope, and effect
+parameters), those existing samples will work just fine and they are
+probably the most accurate out there if recorded properly. Of course,
+the “efficient” approach of sampling sacrifices some level of that
+accuracy (due to a different engine being used for playing back the
+samples). But in exchange you get the highest level of freedom to
+recombine the raw samples into custom patches including tweaking all
+possible parameters and effects available in the synth engine of your
+choice (which is a huge plus for me personally, as I love to create
+whacky patches).</p>
+<p>One problem for extracting the samples is that, a single waveform in
+the SD-80 may contain different samples assigned for different key
+ranges. This is often called a “multisample” by some sources. The way
+the samples are mapped to the keys must be figured out before actually
+sampling them. I have written a small(ish) python script to do exactly
+that. It records the SD-80 playing two different keys at the same pitch
+one after another, and compare them by calculating the correlation. If
+the correlation is lower than a threshold, the two keys use different
+samples. This approach works reasonably well for most samples, but for a
+few analog synth samples, it works poorly. For those samples, I had to
+resort to relying on the human ear (DTW, dynamic time warping, is also
+used sometimes, but it usually has poor results for these samples as
+well). Also the XV engine have some weird quirks near the keys C7-D8
+(96-110). The actual waveform produced within that range varies very
+slightly from time to time. This is possibly due to the effect of <a href="https://en.wikipedia.org/wiki/Aliasing">aliasing</a> becoming
+prominent for these high-pitched notes. I have already figured out
+key-sample mapping for all multisamples (they are not guaranteed to be
+correct, due to reasons mentioned above).</p>
+<p>Another problem is looping. Roland uses sample looping extensively in
+their PCM synths. It’s basically their secret sauce to squeeze thousands
+of instruments into a unit with only tens of megabytes of samples.
+Sample loop points can also be computed using cross-correlation. But is
+nowhere near perfect. Of course it can be done manually, but that would
+be a tedious task.</p>
+<p>No actual recording of the raw samples have been done by me yet.</p>
+<p>I have also dumped the instrument configuration for all preset
+instruments and rhythm sets as part of my SD-80 dumping project (for
+SD-80’s native mode only. I’m not sure whether this is doable for its
+GS/XGLite instruments without a lot of reverse engineering, but nobody
+cares about those anyway). For now, it can be used to recreate
+parameter-accurate SD-80 patches in Roland’s SRX/Zenology plugins.
+However it’s not yet in a very human-readable form (either raw binary
+registers dump or decimal values with field names).</p>
+<p>Once the samples are there, one can easily piece them together within
+the sample playback engine of their choice, be it HALion, KONTAKT, or
+even just soundfont synthesizers. Sure the feature set of each
+sample-based synth engine is not exactly the same, but I think decent
+results could be achieved for most instruments.</p>
+<h3 id="tocanch9" class="tvis">Dumping and Deciphering</h3>
+<p>The wave ROM in the SD-80 is a standard part despite the custom
+Roland engravement on it <a id="n7" href="#note7" class="note">[7]</a>. This is expected because Roland has been
+using standard mask ROM parts from various manufacturers for the wave
+ROM. This means the content of SD-80’s wave ROM can be easily
+dumped.</p>
+<p>This might be shocking for some of the readers, but Roland does
+compress their samples. This is evident from the specification of
+XV-5080 “Wave memory: 64MB (16-bit linear format)” while the XV-5080
+only has 32 MiB wave ROM. The compression, previously unknown to me, has
+been identified to be a variant of the differential pulse-code
+modulation (DPCM) called FCE-DPCM by <a href="http://www.dtech.lv/techarticles_roland_exp.html">some amazing
+person</a>. The same person seemed also figured out the structure of the
+wave ROM used by sample-based synthesizers from Roland of that general
+era. Unfortunately, I wasn’t able to find the article on the technical
+details of the compression method at the time of writing. Anyway, hats
+off to Edward of dtech.lv!</p>
+<p>I <strong>will surely</strong> make a dump of the wave ROMs of my
+SD-80. However, I want to do it in an nondestructive manner – I don’t
+want to get a ROM dump and an unusable SD-80 (or end up with no valid
+ROM dump and an unusable SD-80). Since I have proved my SMT soldering
+job is terrible and shall never be in the vicinity of a SMT board
+holding a soldering iron or hot air gun, I might try some clipping the
+chip instead. I’m considering to try <a href="https://www.360-clip.com/uni-48.htm">this</a> clip from 360-clip.
+It claims to be applicable to any 48-pin TSOP chips. If that’s true,
+with the help of this clip and a Raspberry Pi <a id="n8" href="#note8" class="note">[8]</a>, I
+can suck that juicy content out of the wave ROM chips of the SD-80.</p>
+<p>Once we have the ROM dump, we can start trying to figure out its
+structure. If we somehow managed to do that, we would be able to feed
+the decompressed samples together with the already dumped patch
+parameters to some existing or new, custom sample-based software
+synthesizer, and achieve decent results mimicking the SD-90/80. Patches
+that make use of MFX would certainly be a pain to deal with. However one
+can always simulate MFX with external DAW effects. To hear the
+difference MFX makes for various preset patches that use it, see the <a href="#tocanch37">“What role does MFX play?”</a> section.</p>
+<p>I believe this approach is very similar to that one used by Munt
+(although I only read a small part of Munt’s code base, and I didn’t
+read anything about their reverse engineering approach). The SH3 CPU
+plays a relatively minor part in the tone generation of SD-80. Instead,
+we should focus on replicating the sounds of the XV engine. Also, an
+logic-level reverse engineering of the XV chip doesn’t seem reasonable
+because it’s such a huge and complex chip (or rather, a huge gate
+array). Just save the hassle, treat it like a blackbox and try to
+reproduce its output using a software implementation should be able to
+produce acceptable result on its own.</p>
+<h4 id="tocanch10" class="tvis">Extra rambling about the ROM
+chip</h4>
+<p>In the part number of <code>μPD23C128040ALGY-***-MJH/MKH</code>, the
+<code>***</code> part is the ROM code. When a mask ROM chip is
+commissioned, the customer (Roland in this case) needs to submit the
+desired ROM content and their choice for various other options (in case
+of <code>μPD23C128040ALGY</code>, they can choose how the logic level on
+a certain pin controls the outputs). The manufacturer then arrange the
+mask according to this information and assigns a ROM code to this
+specific mask <a id="n9" href="#note9" class="note">[9]</a>. Therefore, for two
+chips of the same type, if they have the same ROM code, their contents
+should be identical. This way we can guess with fair amount of certainty
+that the XV-3080, XV-5080 and XV-5050 have identical wave ROM contents
+(they all use <code>μPD23C128040ALGY-849-MJH</code> and
+<code>μPD23C128040ALGY-850-MJH</code>).</p>
+<p>Among the chips with Roland markings in the SD-80, the XV chip and
+8-bit MCU with Roland-programmed ROM has other markings that matches
+Roland’s internal part numbers (the numbers with a prefix R, like
+<code>R01455956</code> and <code>R02902867</code>), and followed by a
+indicative part number of the actual chip (<code>137</code> and
+<code>RA08-503</code>). However, none of these features matches on the
+wave ROM chips. The wave ROM chips has internal part number
+<code>R02678601</code> and <code>R02678612</code>, while the numbers on
+the service manual are <code>03010612</code> and <code>03010623</code>
+respectively. The indicative part also doesn’t match either: the chips
+in my unit have <code>23C128L-529J</code> and <code>23C128L-535K</code>.
+While the J/K variant and the <code>23C128L</code> part does match, what
+I presumed is the ROM code doesn’t (529 vs 525 on IC28, 535 vs 526 on
+IC29). What does this mean? I don’t really know. My SD-80 is built
+relatively late into production (date code on the main board is
+2004-08-27, date on the service manual is May 2002 – when the SD-80 was
+initially released). Maybe Roland did revise the wave ROM content. If
+that’s the case, it would be interesting to find one with the original
+ROMs and compare them. I wouldn’t expect there to be any significant
+differences, though.</p>
+<h3 id="tocanch11" class="tvis">SD-20 MIDI File Converter</h3>
+<p>This extremely intriguing piece of software is brought up by Kalas
+during our communications. At the time of writing, this application can
+be still found <a href="https://www.roland.com/jp/support/by_product/sd-20/">here</a>. The
+installer can only proceed if an SD-20 is detected. This can be easily
+circumvented by using a InstallSheld extractor. The converter does try
+to access a registry key
+<code>HKLM\Software\Wow6432Node\Edirol\SD-20 MIDI File Converter\BaseDataFile</code>,
+which should be set to a string pointing to the url of its param.dat
+file. However, even with this key set, the converter still refuse to do
+anything, saying it failed to initialize. By the way even with an SD-20
+connected to the computer via USB, the converter still refuses to start
+on Windows 10.</p>
+<p>However, this kind of nonsense is not going to stop me. I quickly
+found cracks floating around on the Internet. This converter is
+extremely simplistic: you pick the midi file to convert, it spits the
+wav file into the same folder. Here are some quick samples.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<td>
+SD-80
+</td>
+<td>
+SD-20 Converter
+</td>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/AMEDLEY.SD80.N.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/AMEDLEY.SD80.SD20C.N.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="2">
+AMEDLEY.MID by Earl Gray Fowler from Voyetra Technologies, arranged for
+SD-80 (Native Mode)
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>Used instruments: St.Strings, St.Timpani, St.Harp, St.Fr Horns, Flute
+vib, St.Tubular, St.Harp, St.Xylophone, St.Music Box, St.Room, Bassoon
+vib, SpaceVoice 3, Atmosphere 3, Ice Rain 3, PanFlute vib, Bird Tweet,
+Seashore, Sweep Pad 3, Rockabilly, St.Kalimba, Piccolo vib, Steel Drums,
+Tuba vib, Romantic Tp, St.Banjo, Trombone vib, JazzClarinet, Gunshot,
+Clavi Bass 3, St.Brass, Dist.Gt 2, St.Orc Hit, Jazz Organ 2,
+PhaseFrtless, Solo Vox 3, Reed Romance, Ice Rain 2, St.Power, Oct.JP
+Saw, SH-2 Lead, Jazz Slap, OverdriveGt2, Applause.</p>
+<p>Reed Romance and SH-2 Lead are from the special 2 set, therefore
+cannot be used by the SD-20 MIDI File Converter. They are substituted by
+Violin 2 vib and Warm SynHorn automatically. A single SD-80 system
+exclusive DT1 message is used to change the patch volume of SH-2
+Lead.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<td>
+SD-80
+</td>
+<td>
+SD-20 Converter
+</td>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/YOSEMITE.SD80.N.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/YOSEMITE.SD80.SD20C.N.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="2">
+YOSEMITE.MID by Passport Designs, arranged for SD-80 (Native Mode)
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>Used instruments: Enh.Nylon o, Ocarina vib, St.Slow Str2,
+PhaseFrtless, Celtic Ens, St.Standard, Soft60’Organ, Pre Bass,
+St.BritePno.</p>
+<p>St.BritePno is a custom patch. It’s selected using system exclusive
+messages generated by SD-80’s bulk dump feature. Enh.Nylon o, Celtic
+Ens, Pre Bass are not available in the SD-20 Converter.</p>
+<p>The output from the converter is significantly louder than SD-80’s
+digital output. I normalized all recordings before uploading them.
+Despite the lack of a lot of features and patches, the converter
+actually sounded exceptionally good, and exceeded my expectation by
+quite a large margin.</p>
+<p>The converter is not a software implementation of SD-20’s internals.
+There’s misinformation out there claiming so, but that’s simply not the
+case. Roland explicitly disclosed this in the readme file of the
+converter.</p>
+<h4 id="tocanch12" class="tvis">FrankenTTS-1</h4>
+<p>Something smells fishy instantly when I got this converter. That file
+name “param.dat” looks really familiar. If you have used any of Roland’s
+HQ software synthesizer products from the early 2000s
+<a id="n10" href="#note10" class="note">[10]</a>, you might feel the same. They all use this file to
+store their samples and patch data.</p>
+<p>One natural thing to do is to replace the param.dat file of these
+plugins with the one supplied with the converter. The result are as
+follows:</p>
+<ul>
+<li>HQ-OR/HQ-QT refuses to load at all after the swap.</li>
+<li>HQ-GM2 loads correctly. Instrument names changes to the names from
+SD-20’s Classical set (for example, 1:0 changes from Piano 1 st. to
+Piano 1w). Only instruments from the Classical set are available. No
+NRPN messages can change the instrument set. The sound is pretty much
+identical to that from the converter.</li>
+<li>GrooveSynth (P5antom) also loads correctly. Besides all instruments
+from the Classical set, a couple of instruments from the Contemporary
+set and Solo set are also available, but there’s no obvious pattern
+there. All rhythm sets are available in the Franken-GrooveSynth.</li>
+</ul>
+<p>This reveals that the synthesizer engine is identical to that used by
+these HQ software synthesizers, proving the claim that this converter is
+a software implementation of SD-20 wrong again.</p>
+<p>There’s not much information about the structure of this “param.dat”
+file online, nor could I figure it out myself (I’m not a huge fan of
+doing such work). However this interchangeablility is somewhat
+delighting.</p>
+<h4 id="tocanch13" class="tvis">Other observations</h4>
+<p>The executable of the converter is a mere ~500KiB and doesn’t seem to
+use an executable packer. This suggests the “HQ” engine couldn’t be
+super complex.</p>
+<p>The executable contains references to “Automation”, “User Rhythm” and
+such. Apparently they still left some code from the plugin version of
+the HQ engine in this converter.</p>
+<p>I think I found the entry to the function where param.dat is loaded
+(0x004228e0). No idea where to go from there though.</p>
+<h4 id="tocanch14" class="tvis">So… is this it?</h4>
+<p>Nah, we should not depend on a piece of proprietary junk for the
+preservation of anything.</p>
+<p>Maybe some wizards could find a way to hack the plugins and make all
+instruments available in TTS-1 or something. But that doesn’t really
+work as a way to preserve the synth if the binary code it depends on
+could stop working at an arbitrary point of time in the future, does
+it?</p>
+<h3 id="tocanch15" class="tvis">Roland Cloud</h3>
+<p>Roland has been pushing their subscription service “Roland Cloud”
+since 2018. When it first came out there was no plugin of my interest.
+The deal breaker for me back then was there was no permanent licensing
+option. If you know me, I’m strongly opposed to the subscription model
+used for software products.</p>
+<p>Starting from May 2020 though, Roland started offering “lifetime
+keys”, which now puts this service within my radar. I took the ultimate
+tier trial and installed every piece of plugin replicating SRX boards
+and the XV-5080, as well as the then-new “Zenology” synth. I’ve got
+mixed results.</p>
+<p>The software aspect is okay. It’s much better than SoundCanvas VA
+I’ve used years ago, which has glitchy TVA and TVF and was never fixed.
+The user interface scales perfectly on high DPI screens. Editing
+experience of the SRX/XV plugins is basically the same as the editors
+for later Roland PCM synths (such as the SonicCell and the Integra-7) –
+that is, much better than the original XV or SD-80 editor. These plugins
+still have terrible performance as most previous Roland software synths
+do (each instance needs plenty of processing power – if you use a
+computer that predates the release of these plugins, the performance
+will probably suffer).</p>
+<p>The sound is … fine? Didn’t give me the same astonishment when I
+heard a real XV-5080 on YouTube though (I thought “no way this thing
+only has 32 MiB of sample content!”). For most patches, they sound
+“close enough” to an actual XV-5080, despite a handful of caveats. The
+synth engine do behave nearly identical to actual XV-based synths, at
+least according to my tests. The XV-5080 plugin is especially
+underwhelming, considering the original XV-5080 is expandable and can
+also load external samples. If only the XV-5080 plugin could load
+samples and patches from other SRX plugins installed, it would have been
+a lot better (although this is solved by Zenology, it has its own
+issues). The MFX uses a different set of effect types from the original
+XV-5080 and SD-80: they are modeled after synths after the Fantom-S
+era). However I’d say the effects bearing the same name as XV effects do
+sound largely the same.</p>
+<p>The executables contain a resource folder named “WROM”, and it
+contains the wave ROMs used by the plugins. They are all exactly 32 MiB.
+The wave ROM files contains a similar 32-byte header to dumps of actual
+wave ROM of earlier Roland PCM synths (see the JD-800 wave ROM dump from
+Edward of dtech.lv).</p>
+<p>I do have some major complaints though. Each executable contains a
+copy of the wave ROMs. If you choose to install all plugin formats, that
+will install 4 copy of exactly the same wave ROM on your computer. Also
+it’s impossible to combine the sounds of different SRX boards. Most
+samples originated from Spectrasonics are missing from the SRX plugins
+but are reincluded in the EXZ expansions which can be used in Zenology,
+indicating a copyright dispute between the two companies that was
+resolved later <a id="n11" href="#note11" class="note">[11]</a>. These problems
+can be partially solved if you use the newer Zenology plugin instead.
+But Zenology is riddled with its own issues. It uses a nearly entirely
+new set of MFX (identical to the MFX from their 2019 Fantom-6/7/8
+workstations and other “ZEN-CORE” based products), and completely lacks
+reverb effects. Effects that have the same name in Zenology and XV-based
+synths doesn’t necessarily behave the same. And Zenology still can’t
+load samples from different sample groups to left and right channels of
+a single voice. I know it’s a thing in the original XV, but since it’s a
+software reimplementation, they don’t have to stick to the same
+restrictions do they? Also, why are all these plugins monotimbral? If
+your answer is “just use multiple instances”, I would remind you that
+these are Roland software synths, and they don’t perform well if you add
+multiple to your virtual rack…</p>
+<p>Recreating patches of the SD-80 using these plugins does seem to be
+possible, and there are already plenty of people doing that. See the
+section <a href="#tocanch32">“SD-80’s sound content”</a> for details.
+However it does still rely on proprietary Roland software products
+(which, if they want to, can cease the support at any time), requires
+pricy licenses, and on top of all that, a crappy authenticating
+system.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<td>
+SD-80
+</td>
+<td>
+XV-5080 VST
+</td>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/passport_Driving.sd_pretending_to_be_xv.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/passport_Driving.xvvst.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+SD-80 using patch parameters pulled from XV-5080 &nbsp;&nbsp;
+</td>
+<td>
+&nbsp;&nbsp; 5 instances of XV-5080 VST using factory patches
+</td>
+</tr>
+<tr>
+<td colspan="2">
+“Driving”, by Passport Designs
+</td>
+</tr>
+</tbody></table>
+</div>
+<h2 id="tocanch16" class="tvis">A
+History lesson from someone who barely knows anything about it</h2>
+<p>AKA a short history of Roland’s sample-based synths from someone who
+has used almost none of them.</p>
+<p>Below is a comparison chart of selected sample-based synths from
+Roland using information available from their manuals (mostly sysex
+address mapping in the MIDI implementation) and service manuals. In a
+few occasions sources from the Internet are used as well.</p>
+<div class="collapse" data-caption="More detailed comparison of various Roland's PCM based sound modules">
+<p>Chip information on following modules are from actual units:</p>
+<ul>
+<li>SD-90</li>
+<li>SD-80</li>
+<li>SD-20</li>
+<li>SC-8850</li>
+<li>SC-D70 (courtesy of Palto)</li>
+<li>SC-55 (courtesy of Palto)</li>
+<li>SC-55mkII (courtesy of Palto)</li>
+<li>Fantom-XR</li>
+<li>XV-5080</li>
+</ul>
+<p>Others come from service notes.</p>
+<table>
+<tbody><tr>
+<th>
+Model
+</th>
+<th>
+Synth Tone Generator
+</th>
+<th>
+Effects Processor
+</th>
+<th>
+Wave ROM
+</th>
+<th>
+CPU
+</th>
+<th>
+Multitimbral Parts
+</th>
+<th>
+Polyphony (partials / voices)
+</th>
+<th>
+Preset Patches
+</th>
+<th>
+Synth Effects
+</th>
+</tr>
+<tr>
+<td>
+MT-32
+</td>
+<td>
+MB87136A (LA32)
+</td>
+<td>
+HG61H20R36F (Reverb), 4*64Kbit RAM
+</td>
+<td>
+4 Mbit = 0.5 MiB
+</td>
+<td>
+Intel 8098
+</td>
+<td>
+9
+</td>
+<td>
+32
+</td>
+<td>
+128i + 30r
+</td>
+<td>
+Reverb
+</td>
+</tr>
+<tr>
+<td>
+JD-990
+</td>
+<td>
+MB87731A (EP) + MB87424A (TVF)
+</td>
+<td>
+2 * TC6088AF (CSP), 4 Mbit RAM
+</td>
+<td>
+3 * 16 Mbit = 6 MiB, expandable w/ SL-JD80, SO-PCM1, PN-JV80 and SR-JV80
+boards
+</td>
+<td>
+H8/570
+</td>
+<td>
+8
+</td>
+<td>
+24
+</td>
+<td>
+128i + 2r + 32p
+</td>
+<td>
+JD Multi (EQ + Dist + Phaser + Spectrum + Enhancer + Chorus + Delay +
+Reverb)
+</td>
+</tr>
+<tr>
+<td>
+SC-55
+</td>
+<td>
+24201F002, TC24SC201AF-002 (GP)
+</td>
+<td>
+Integrated, 256 Kbit RAM
+</td>
+<td>
+3 * 8 Mbit = 3 MiB
+</td>
+<td>
+H8/532
+</td>
+<td>
+16
+</td>
+<td>
+24
+</td>
+<td>
+317i + 10r
+</td>
+<td>
+Reverb, Chorus
+</td>
+</tr>
+<tr>
+<td>
+SC-55MkII
+</td>
+<td>
+TC6116AF (GP4)
+</td>
+<td>
+Integrated, 256 Kbit RAM
+</td>
+<td>
+16 Mbit + 8 Mbit = 3 MiB
+</td>
+<td>
+H8/532
+</td>
+<td>
+16
+</td>
+<td>
+28
+</td>
+<td>
+354i + 10r
+</td>
+<td>
+Reverb, Chorus
+</td>
+</tr>
+<tr>
+<td>
+JV-880
+</td>
+<td>
+TC6116AF (GP4)
+</td>
+<td>
+Integrated, 256 Kbit RAM
+</td>
+<td>
+2 * 16 Mbit = 4 MiB, expandable w/ SR-JV80 boards &amp; PN-JV80 / SO-PCM
+cards
+</td>
+<td>
+H8/532
+</td>
+<td>
+8
+</td>
+<td>
+28
+</td>
+<td>
+192i + 3r + 48p
+</td>
+<td>
+Reverb, Chorus
+</td>
+</tr>
+<tr>
+<td>
+SC-88
+</td>
+<td>
+MBCS30109 (XP)
+</td>
+<td>
+Integrated, 2 * 1 Mbit RAM
+</td>
+<td>
+4 * 16 Mbit = 8 MiB
+</td>
+<td>
+H8/510
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+654i + 24r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ
+</td>
+</tr>
+<tr>
+<td>
+JV-1080
+</td>
+<td>
+MBCS30109B (XP)
+</td>
+<td>
+Integrated, 2 * 1 Mbit RAM
+</td>
+<td>
+4 * 16 Mbit = 8 MiB, expandable w/ SR-JV80 boards &amp; PN-JV80 / SO-PCM
+cards
+</td>
+<td>
+HD6477034, SH7034 (SH1)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+512i + 8r + 64p
+</td>
+<td>
+Reverb, Chorus, EFX (40 types)
+</td>
+</tr>
+<tr>
+<td>
+SC-88VL
+</td>
+<td>
+MB87B105PF-G RHR-2342 (XP2) <a id="n12" href="#note12" class="note">[12]</a>
+</td>
+<td>
+Integrated, 2 * 1 MBit RAM
+</td>
+<td>
+4 * 16 Mbit = 8 MiB
+</td>
+<td>
+H8/510
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+654i + 24r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ
+</td>
+</tr>
+<tr>
+<td>
+SC-88Pro
+</td>
+<td>
+TC170C200AF-005, RA01-005 (XP3), 2 * 1 MBit RAM
+</td>
+<td>
+MB87837PF, 1 MBit RAM
+</td>
+<td>
+5 * 32 Mbit = 20 MiB
+</td>
+<td>
+H8/510
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+1117i + 42r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ, EFX (64 types)
+</td>
+</tr>
+<tr>
+<td>
+JV-2080
+</td>
+<td>
+TC170C200AF-005, RA01-005 (XP3), 4 MBit RAM
+</td>
+<td>
+TC170C110AF-002, RA03-002, 4 MBit + 1 MBit RAM
+</td>
+<td>
+2 * 32 Mbit = 8 MiB, expandable w/ SR-JV80 boards
+</td>
+<td>
+HD6437034, SH7034 (SH1)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+640i + 10r + 64p
+</td>
+<td>
+Reverb, Chorus, EFX (3 slots, 40 types)
+</td>
+</tr>
+<tr>
+<td>
+SC-8850
+</td>
+<td>
+2 * TC203C180AF-002, RA09-002 (XP6), 2 * 4 MBit RAM
+</td>
+<td>
+MB87837PF, 4 MBit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB
+</td>
+<td>
+HD6437016E09F, SH7016 (SH2) <a id="n13" href="#note13" class="note">[13]</a>
+</td>
+<td>
+64
+</td>
+<td>
+128
+</td>
+<td>
+1640i + 63r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ, EFX (64 types)
+</td>
+</tr>
+<tr>
+<td>
+SC-8820
+</td>
+<td>
+TC203C180AF-002, RA09-002 (XP6), 4 MBit RAM
+</td>
+<td>
+MB87837PF, 4 MBit RAM
+</td>
+<td>
+128 Mbit + 64 Mbit = 24 MiB
+</td>
+<td>
+HD64F7017F28, SH7017 (SH2)
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+1608i + 63r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ, EFX (64 types)
+</td>
+</tr>
+<tr>
+<td>
+SC-D70
+</td>
+<td>
+TC203C180AF-002, RA09-002 (XP6), 4 MBit RAM
+</td>
+<td>
+MB87837PF, 4 MBit RAM; TC223C080AF-101, RA0A-101 (ESP4), 4 Mbit RAM
+</td>
+<td>
+128 Mbit + 64 Mbit = 24 MiB
+</td>
+<td>
+HD6437016E19F, SH7016 (SH2)
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+1608i + 63r
+</td>
+<td>
+Reverb, Chorus, Delay, EQ, EFX (64 types)
+</td>
+</tr>
+<tr>
+<td>
+XV-3080
+</td>
+<td>
+2 * TC203C180AF-002, RA09-002 (XP6)
+</td>
+<td>
+Integrated, 2 * 4 MBit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB, expandable w/ SRX &amp; SR-JV80 boards
+</td>
+<td>
+HD6437042F33, SH7042 (SH2)
+</td>
+<td>
+16
+</td>
+<td>
+128
+</td>
+<td>
+1024i + 16r + 64p
+</td>
+<td>
+Reverb, Chorus, MFX (1 slot, 63 types)
+</td>
+</tr>
+<tr>
+<td>
+JV-1010
+</td>
+<td>
+TC203C180AF-002, RA09-002 (XP6)
+</td>
+<td>
+Integrated, 4 MBit RAM
+</td>
+<td>
+2 * 64 Mbit = 16 MiB, expandable w/ SR-JV80 boards
+</td>
+<td>
+HD6437016F28, SH7016 (SH2)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+895i + 18r + 64p
+</td>
+<td>
+Reverb, Chorus, EFX (40 types)
+</td>
+</tr>
+<tr>
+<td>
+SD-80
+</td>
+<td>
+2 * TC223C660CF-503, RA08-503 (XV)
+</td>
+<td>
+Integrated, 2 * 16 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB
+</td>
+<td>
+HD6417706, SH7706 (SH3)
+</td>
+<td>
+32
+</td>
+<td>
+128
+</td>
+<td>
+1050i + 30r
+</td>
+<td>
+Reverb, Chorus, EQ, MFX (3 slots, 90 types)
+</td>
+</tr>
+<tr>
+<td>
+SD-90
+</td>
+<td>
+2 * TC223C660CF-503, RA08-503 (XV)
+</td>
+<td>
+Integrated, 2 * 16 Mbit RAM; RA0B-B01 for AFX
+</td>
+<td>
+2 * 128 Mbit = 32 MiB
+</td>
+<td>
+HD6417709A, SH7709 (SH3)
+</td>
+<td>
+32
+</td>
+<td>
+128
+</td>
+<td>
+1050i + 30r
+</td>
+<td>
+Reverb, Chorus, EQ, MFX (3 slots, 90 types)
+</td>
+</tr>
+<tr>
+<td>
+SD-20
+</td>
+<td>
+TC203C180AF-003, RA0C-003 (XP7)
+</td>
+<td>
+Integrated, 4 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB
+</td>
+<td>
+HD6437016E29FV, SH7016 (SH2)
+</td>
+<td>
+32
+</td>
+<td>
+64
+</td>
+<td>
+660i + 23r
+</td>
+<td>
+Reverb, Chorus, EQ
+</td>
+</tr>
+<tr>
+<td>
+XV-5080
+</td>
+<td>
+2 * TC223C660CF-503, RA08-503 (XV)
+</td>
+<td>
+Integrated, 2 * 16 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB (expandable w/ SRX &amp; SR-JV80 boards and EDO
+DRAM up to 128 MiB)
+</td>
+<td>
+HD6437042A13F, SH7042 (SH2)
+</td>
+<td>
+32
+</td>
+<td>
+128
+</td>
+<td>
+1152i + 23r + 64p
+</td>
+<td>
+Reverb, Chorus, EQ, MFX (3 slots, 90 types)
+</td>
+</tr>
+<tr>
+<td>
+XV-5050
+</td>
+<td>
+TC223C660CF-503, RA08-503 (XV)
+</td>
+<td>
+Integrated, 16 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB (expandable w/ SRX boards)
+</td>
+<td>
+HD6437016E22, SH7016 (SH2)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+1280i + 25r + 64p
+</td>
+<td>
+Reverb, Chorus, EQ, MFX (3 slots with restrictions <a id="n14" href="#note14" class="note">[14]</a>, 90 types)
+</td>
+</tr>
+<tr>
+<td>
+XV-2020
+</td>
+<td>
+TC203C180AF-003, RA0C-003 (XP7)
+</td>
+<td>
+Integrated, 4 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB (expandable w/ SRX boards)
+</td>
+<td>
+HD6437016E, SH7016 (SH2)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+768i + 17r + 64p
+</td>
+<td>
+Reverb, Chorus, MFX (1 slot, 40 types)
+</td>
+</tr>
+<tr>
+<td>
+Fantom S-88
+</td>
+<td>
+TC223C660CF-503, RA08-503 (XV), 4 Mbit RAM
+</td>
+<td>
+TC223C080AF-101, RA0A-101 (ESP4), 16 Mbit RAM
+</td>
+<td>
+2 * 128 Mbit = 32 MiB (w/ 2 * 128 Mbit = 32 MiB sampling RAM, expandable
+up to 288 MiB, plus SRX boards)
+</td>
+<td>
+HD6417706, SH7706 (SH3)
+</td>
+<td>
+16
+</td>
+<td>
+64
+</td>
+<td>
+904i + 41r + 64p
+</td>
+<td>
+Reverb, Chorus, MFX (3 slots, 78 types), Mastering &amp; Input Effects
+</td>
+</tr>
+<tr>
+<td>
+Fantom XR/X6/X7/X8
+</td>
+<td>
+T6TV2TBG-0002 (WX)
+</td>
+<td>
+Integrated, 64 Mbit RAM
+</td>
+<td>
+4 * 128 Mbit = 64 MiB (w/ 2 * 64 Mbit = 16 MiB sampling RAM, expandable
+up to 528 MiB, plus SRX boards)
+</td>
+<td>
+HD6417706, SH7706 (SH3)
+</td>
+<td>
+16
+</td>
+<td>
+128
+</td>
+<td>
+1280i + 49r + 64p
+</td>
+<td>
+Reverb, Chorus, MFX (3 slots, 78 types), Mastering &amp; Input Effects
+</td>
+</tr>
+<tr>
+<td>
+Fantom G6/G7/G8
+</td>
+<td>
+T6TV2TBG-0002 (WX)
+</td>
+<td>
+2 * T6TZ3AFG-0001 (WSP) w/ 64 Mbit RAM each + WX Integrated, 64 Mbit RAM
+</td>
+<td>
+2 * 512 Mbit = 128 MiB (w/ 2 * 128Mbit = 32MiB sampling RAM, expandable
+upto 544 MiB, plus ARX boards (external SSC synthesis))
+</td>
+<td>
+SH7785 (SH4A)
+</td>
+<td>
+16
+</td>
+<td>
+128
+</td>
+<td>
+1920i + 73r + 8p
+</td>
+<td>
+Reverb, Chorus, PFX (16 slots, one per channel, 76 types), MFX (2 slots,
+78 types), Mastering &amp; Input Effects
+</td>
+</tr>
+<tr>
+<td>
+INTEGRA-7
+</td>
+<td>
+R8A02021ABG (SSC7, CPU w/ integrated DSP?) + MB8AA4181 (ESC2)
+</td>
+<td>
+ESC2 256Mbit Effect RAM + SSC7 64Mbit Effect RAM
+</td>
+<td>
+3 * 1Gbit = 384MiB (w/ 4 * 256Mbit = 128MiB DRAM)
+</td>
+<td>
+R8A02021ABG (SSC7), SH4?
+</td>
+<td>
+16
+</td>
+<td>
+128
+</td>
+<td>
+6030i + 258r + 64p
+<!--64 "Studio Sets" (performances), SuperNATURAL (256 Ac, 1109 Sy, 26 Dr) + XV-5080 PCM (896i, 14d) + GM2 (256i, 9d) + ExSN1-6 (17i, 17i, 50i, 12i, 12i, 7d) + SRX01-12 (41i + 79d, 50i, 128i + 12d, 128i, 312i + 34d, 449i + 5d, 475i + 11d, 448i + 21d, 414i + 12d, 100i, 42i, 50i) + HQGM2 (256i, 9d) + HQPCM (512i, 19d)-->
+</td>
+<td>
+Reverb, Chorus, MFX (16 slots, 67 types), EQ, compressor (drum part),
+Surround, Mastering (EQ)
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>The following section summarizes generation-over-generation
+improvements of the synth engine noticed by me reading the manuals.
+There is a little bit of technical assessment of the chips, however most
+of it is <strong>not</strong> based on analysis of the actual chip,
+instead it’s based on analysis of the most capable synth model using
+that chip. Some of the features might be added with newer version of
+system software (such as the multisampling feature on XV-based synths
+mentioned below) rather than improvements on the actual synth chip. It’s
+in no way, shape or form complete. A lot of synthesizer keyboard models
+are not listed. It could be way too technical for some readers. If
+that’s the case, feel free to skip this section.</p>
+<h3 id="tocanch17" class="tvis">LA</h3>
+<p>Not strictly a PCM synth. Only uses PCM for the attack phase of the
+sound. Already showing Roland’s base designs for later PCM synths: 4
+“partials” (this term is from 80s Roland samplers, and was referred to
+as either voices or tones in later products) for each patch. Each
+partial has its “timbre”, which consists of a WG (“wave generator”),
+5-stage envelope generators for filters and amplifiers (which in later
+PCM synths were reduced to 4-stage), and a single LFO for mod wheel.
+Filters are always low-pass. Poor panning resolution (15 steps instead
+of GM’s 128). Rhythm patches reference to individual “timbres” on each
+key. Usually paired with external reverb and chorus processing chips. Up
+to 32 polyphony.</p>
+<p>Used in MT-32, CM-64, CM-32L, D-110 (as MB87136A “LA32”, QFP), and
+D-50 (as MB87136, PGA).</p>
+<p>Due to the popularity of MT-32, which is supported by a whole bunch
+of DOS games, emulation of this engine is pretty well-developed already
+(see the aforementioned Munt project).</p>
+<h3 id="tocanch18" class="tvis">(Unnamed synth engine in
+U-110)</h3>
+<p>An early (late-1980s) incarnation of Roland’s PCM only synth. No
+filters at all. Amp env reduced to 3 stages (?). The synth structure
+looks more closely related to that of LA rather than later Roland PCM
+synths. 31 polyphony. The synth consists of two chips: MB87419 and
+MB87420. The former seems to act as a controller, while the latter does
+the actual sound generation. There’s an additional chip to handle output
+selection. Also relies on external chips for effects.</p>
+<p>Interestingly, MAME has a partial implementation of this synth engine
+(src/devices/sound/rolandpcm.cpp).</p>
+<p>Found in U-110, U-220, CM-32P and various R-8 variants.</p>
+<h3 id="tocanch19" class="tvis">EP</h3>
+<p>Early-1990s PCM synth. Has filters but requires an external TVF
+chip.</p>
+<p>The models using this engine seems to have roughly the same feature
+set as GP-based models. However they lack a lot of controls for rhythm
+patches. Some models come with a much more powerful effects engine
+(which is external to the EP chip).</p>
+<p>Used in HP-3700/2700 (as MB87731), and JD-800/990 (as MB87731A).</p>
+<h3 id="tocanch20" class="tvis">GP</h3>
+<p>Uses 4-stage envelope generators for filter and amplitude. Has two
+filter modes (LPF and HPF). Individual tones can be delayed after the
+note is triggered. Each tone has 2 independent LFOs. Has a rudimentary
+modulation matrix (with fixed modulation sources). Reverb and chorus
+effects are integrated in the chip. Most parameters now accepts values
+from 0 to 127 (rather than 0 to 100 in LA-based units). Has FxM
+(frequency modulation) capability. More parameters can be modulated by
+key follow or velocity, which now also supports velocity curves and
+sensitivity offsets. Up to 28 polyphony on GP4 (24 on the original
+GP).</p>
+<p>The original GP (TC24SC201AF-002) is used in JV-80 and SC-55.</p>
+<p>A later variant “GP4” (TC6116AF) is used in JV-880, SC-55mkII and
+MC-303. It contains an additional gate array as LCD controller and
+handles extra IO.</p>
+<h3 id="tocanch21" class="tvis">XP</h3>
+<p>This iteration has a lot of variants.</p>
+<h4 id="tocanch22" class="tvis">Original XP</h4>
+<p>Two additional filter modes (BPF and PKG). Modulation matrix has
+partially configurable modulation sources. Introduced random panning and
+alternate panning. Key ranges of tones can be limited. Voice priority
+(which note to steal when a new note is played if polyphony is maxed)
+can be adjusted. Has integrated effects processor with 40 available
+effect types. Up to 64 polyphony. This chip seems to have the facilities
+for pairing two of them together, but none of the production rack units
+make use of this feature as far as I know. 24-bit wave address bus for a
+maximum of 16777216 words (=32 MiB) addressable wave ROM per chip.</p>
+<p>Used in JV-1080 (as MBCS30109B), and SC-88 (as MBCS30109).</p>
+<h4 id="tocanch23" class="tvis">XP2</h4>
+<p>Seems to be a drop-in replacement of the original XP.</p>
+<p>Used in production units of XP-80 (designed with the original XP) and
+SC-88VL (both as MB87B105PF-G or RHR-2342).</p>
+<h4 id="tocanch24" class="tvis">XP3</h4>
+<p>Seems pin-compatible with the original XP.</p>
+<p>Used in JV-2080, SC-88Pro, and JX-305 (as TC170C200AF-005 or
+RA01-005).</p>
+<h4 id="tocanch25" class="tvis">XP6</h4>
+<p>Tones can have different samples on each stereo channel. Two extra
+filter modes (LPF2 and LPF3). Fully configurable modulation matrix. 63
+internal effect types. Up to 64 polyphony. Actual models with two of
+these chips exist (XV-3080 and SC-8850).</p>
+<p>Used in XV-3080, JV-1010, XV-88, SC-8850, SC-8820 and SC-D70 (as
+TC203C180AF-002 or RA09-002). XV-88, XV-3080 and SC-8850 use a pair of
+XP6.</p>
+<h4 id="tocanch26" class="tvis">XP7</h4>
+<p>Cut-down variant used in low cost models. Only the 40 “classical”
+JV/XP effect types are present. All XP chips <em>before</em> XP7 work at
+a 32 kHz output sampling rate (24.576 MHz clock input, 768 clock cycles
+per output sample, or 12 clock cycles per voice). XP7 is also capable of
+operating at 44.1 kHz with a 33.868 MHz clock input (found in the SD-20
+and DR-880).</p>
+<p>Used in XV-2020, SD-20, DR-880, and E-09 (as TC203C180AF-003 or
+RA0C-003).</p>
+<h3 id="tocanch27" class="tvis">XV</h3>
+<p>Mostly the same as XP6, but with COSM effects (guitar/bass
+amplifiers, speaker &amp; microphone emulation) and two additional
+effect slots. 90 internal effect types. 3 insertion effect slots (40 of
+the 90 effect types takes all 3 slots if only one chip is used). Up to
+64 polyphony. Has an additional memory controller for sample RAM,
+enabling dynamic sampling. Can be paired to double the maximum polyphony
+and improve effects DSP power. 25-bit wave address bus for a maximum of
+33554432 words (=64 MiB) addressable wave ROM per chip (all XPs have a
+24-bit wave address bus).</p>
+<p>Used in XV-5080, XV-5050, SD-90, SD-80, Fantom, Fantom S/S88,
+MV-8800, and MC-909 (as TC223C660CF-503 or RA08-503). XV-5080, SD-90 and
+SD-80 use a pair of XV.</p>
+<p>XV-5080 seems unique among these models as it has a (software) switch
+between two master clocks for the XV chip that allows for switching
+between 44.1 kHz and 48 kHz output. The XV engine in all other models
+listed above outputs at 44.1 kHz. Twice efficient compared to the XP
+series, the XV chip needs 6 clock cycles to process each voice, which
+translate to a input clock of 16.9344 MHz (44.1 kHz output) or 18.432
+MHz (48 kHz output).</p>
+<p>Earlier models with sampling capability using this chip doesn’t have
+proper external multisample support until Fantom S/S88, suggesting the
+multisample support is added with system firmware rather modifications
+to the synth engine.</p>
+<h3 id="tocanch28" class="tvis">WX</h3>
+<p>Capability wise, WX seems to be the equivalent of dual XV with the
+external effects chip used in Fantom S/S88 (TC223C080AF-101, RA0A-101)
+integrated. 78 internal effect types plus mastering + input effects.
+Also added proper multisample support for external samples, which the
+XV-5080 lacks. <a id="n15" href="#note15" class="note">[15]</a> Up to 128 polyphony. 25-bit
+wave address bus for a maximum of 33554432 words (=64 MiB) addressable
+wave ROM per chip. Wave RAM on general data bus instead of wave bus. WX
+chip is only seen operating at a 44.1 kHz output, and uses a input clock
+of 16.9344 MHz (3 clock cycles per voice).</p>
+<p>Found in the Fantom-X series and Fantom-G series, as well as MC-808.
+(SonicCell and SD-50 are also likely equipped with this chip, but I’m
+not 100% sure.)</p>
+<h3 id="tocanch29" class="tvis">Beyond WX</h3>
+<p>From this point on the service manuals from Roland have become less
+useful. They stopped listing the ICs in their parts list. However the
+block diagram and schematics remain.</p>
+<p>Roland introduced the so-called “SuperNATURAL” sounds with their
+Fantom-G series, together with its new expansion board format (ARX).
+These boards has a CPU built on it (the same SSC7 CPU used in
+Integra-7). The CPU is connected to a set of RAM named “Effects RAM” in
+Roland service manuals. Fantom-G by itself doesn’t appear to have any
+“SuperNATURAL” sounds preloaded, and these new sounds clearly breaks
+some of the limitations of the old synth engines. This leads to my
+suspicion that the ARX boards have self-contained synth engines on
+board, and the new “SuperNATURAL” engine is either software based, or
+the SSC7 chip has some sort of extra bits that doesn’t belong to the CPU
+(that is, an integrated ASIC DSP block). The SSC/SSC7 chip is seen on
+all ARX boards, as well as the Integra-7.</p>
+<p>Along with this new CPU thing, there are new effect processors/DSPs:
+WSP and ESC2. WSP is found in a few relatively earlier (2009-ish)
+models, while ESC2 is appears in almost all post 2010 Roland synths
+(Integra-7, probably all Boutique models, and the latest Fantom-6/7/8
+series). A single ESC2 chip is able to provide 16 individual effect
+slots in the Integra-7. However sometimes two of these chips can be seen
+in some of the Boutique units. It also has a JTAG interface, and handles
+USB connectivity in the Integra-7, leading to the suspicion that it also
+has a microcontroller built-in.</p>
+<h2 id="tocanch30" class="tvis">Role played by the
+CPU in sound generation</h2>
+<p>When I started writing this post, my thoughts were the vast majority
+of the synth functionality is contained in the synth chip. In other
+words, the synth chip provides a very high level of abstraction, and the
+CPU only needs to pass processed voice events to the synth chip. In
+retrospect this is not plausible, due to the following facts:</p>
+<ul>
+<li>Models with the same chips sometimes have significant feature
+disparity (Fantom-S with external multisamples which is not found on any
+other XV-based models).</li>
+<li>Only the CPU has direct access to the memory that stores patch
+parameters.</li>
+<li>There’s no reason for such a powererful CPU in some low-end
+models.</li>
+</ul>
+<p>My current hypothesis is the CPU handles:</p>
+<ul>
+<li>control matrix mapping, preprocessing of some parameters (velocity
+curves, for example)</li>
+<li>voice (individual tone) allocation and parameter specification</li>
+<li>effect and output routing configuration (actual routing happens in
+the synth chip/DSP obviously)</li>
+<li>certain LFOs (maybe? <a id="n16" href="#note16" class="note">[16]</a>). Envelopes (even less likely).</li>
+</ul>
+<p>This means the synth chip could contain basic blocks for various
+subsystems (sample playback, modulation, effect processing, etc).
+Routing among these blocks is controlled by the CPU. If you are somewhat
+familiar with hardware accelerated rasterization in computer graphics,
+you may find this architecture has resemblance to the old fixed function
+graphics pipeline.</p>
+<h2 id="tocanch31" class="tvis">Other Curious Stuff</h2>
+<h3 id="tocanch32" class="tvis">SD-80 is an XV-5080 …</h3>
+<p>… locked into performance mode and with samples cherry-picked by
+Roland?</p>
+<p>Indeed, the address mapping <a id="n17" href="#note17" class="note">[17]</a> for the SD-80 is almost
+fully compatible with that of XV-5080. Even a lot of parameters that
+make no sense for the SD-80 are preserved: SD-80 has a parameter to
+select which wave expansion board to use, wave groups (which the SD-80
+only has one), as well as parameters for “multi-partial” patches, which
+on the XV-5080 is a way to put together patches that use samples loaded
+into the RAM. Only the first one has its description changed to
+“reserved” in the documentation. The SD-80 doesn’t have any wave
+expansion board slots hidden inside, nor does it have support for
+external sample loading.</p>
+<p>Of course from the form factor side of things, the SD-80 looks more
+like a cut-down version of XV-5050 which is a full 1U rack unit while
+the SD-80 has a 3/4 rack design. However the SD-80 does retain XV-5080’s
+128 polyphony and dual XV guts.</p>
+<p>What is called “Performance” in XV-5080’s address map is called
+“Multitimbre” in SD-80’s address map. They have the exact same content
+inside (well, not really exact – SD-80 has quite a few extra parameters
+in the “Multitimbre Common” section, mainly to expose some GM2
+parameters and parameters that earlier SoundCanvases had in their
+address maps). On the XV-5080, you can save the performance to one of
+its 64 performance memory slots. Configuration of all 32 parts of the
+synthesizer is restored from the save slot when a performance is loaded.
+Just like the XV-5080, the SD-80 has a name assigned to its
+“Multitimbre”, which is set to “Native Mode” upon entering its native
+mode. But there are no memory slots for “multitimbres” in the SD-80, nor
+is the name of multitimbre shown anywhere (either on the LCD screen, or
+in the SD-80 Editor), rendering this name useless. This name is not
+read-only. You can change it as you wish using system exclusive
+messages, and is preserved until the next native mode reset message is
+received.</p>
+<p>Since the SD-80 is straight up the same when compared to the XV-5080
+in terms of synthesizer engine, and also has extremely similar MIDI
+implementation <a id="n18" href="#note18" class="note">[18]</a>, the SD-80 can be seen as a
+XV-5080 with locked-down samples. What the StudioCanvas series does
+improve over its SoundCanvas predecessors, is its editability in native
+mode, which is brought on par with its professional counterparts and
+allow the user take full control of the sound for the first time
+<a id="n19" href="#note19" class="note">[19]</a>. This is a huge step forward from the
+lame set of a few parameters offered by earlier GS models. However there
+is also stuff found in earlier models that’s no longer available in the
+StudioCanvas, which we are going to touch on in a moment.</p>
+<h4 id="tocanch33" class="tvis">SD-80’s sound content</h4>
+<p>Only a small chunk of SD-80’s content is brand new (at least to me) –
+for example, the harpsichord <a id="n20" href="#note20" class="note">[20]</a>, the clarinet, a few saxes and stereo crash cymbals.
+The rest are either from other Roland products, or modified from their
+existing content.</p>
+<ul>
+<li>The sample “Trumpet Vib” used by the now infamous Romantic Tp
+(thanks to ZUN) is from SR-JV80-18 Latin expansion board. The original
+sample name is “Tp Vib MariA” (or B, or less likely C) <a id="n21" href="#note21" class="note">[21]</a> There are a lot more samples for various trumpet
+techniques in SR-JV80-18, particularly designed for Mexican mariachi
+music. These samples are also found in SRX-09 World Collection, which
+contains all samples from SR-JV80-18.</li>
+<li>Acoustic drum set from the solo set is a cut down version of the
+studio kit from SRX-03 Studio, which is also the source of Super
+Quartet’s drums.</li>
+<li>Piano patches are pulled straight from SR-JV80-09, which is also
+included in SRX-07. <del>SC-8850 has the same Piano sound.</del> No it
+doesn’t. It uses the stereo piano samples from XV. Thanks for Arie on
+Discord to point this out.</li>
+<li>Clavi is almost identical to one of the many clavi patches from
+SC-8820/8850, and is likely ultimately from the JVs and SR-JV80
+boards.</li>
+<li>Samples of Flute vib sound identical to those with the same name
+(“Flute Vib3 A/B/C”) in SRX-03.</li>
+<li>Samples of St.Brass and St.Sm Choir also come straight from
+SRX-03.</li>
+<li>Multiple sound effects are from earlier SC models. Some are also
+used by XV-5080’s GM2 mode.</li>
+<li>A lot of patches in the special sets are pulled from the XV-5080.
+They use the exact same parameters, except the waveforms. If you can
+find a preset with the same name as an instrument from SD-80’s special
+set in the XV-5080, chances are they sound almost identical, especially
+since a lot of them are analog/digital synth patches, and waveforms
+don’t matter as much. There are a few exceptions – a preset with the
+name “Cascade” is found in both instruments, but they have nothing in
+common except the name. There are also a lot of XV-5080 “inspired”
+patches: they have different names from the original XV-5080 patch, but
+very similar sound design. In fact, the “Cascade” patch mentioned above
+is one of these XV-5080 “inspired” patch, but you have to figure out the
+original yourself as I forgot which one it is.</li>
+<li>Rave Set, Rust Set and Bully Set are adapted versions of XV’s
+RaveDrumSet, XV Rust Kit and XV Bully Kit respectively. The original XV
+kits are not GM-compatible.</li>
+<li>Multiple orchestral instruments from the contemporary set and solo
+set use samples from SRX-06 (SR-JV80-02/16).</li>
+<li>Bass and guitar are a mishmash from SR-JV80-09, SRX-03, SRX-07,
+SRX-09 and XV-5080. Some of them are used in other Roland products.
+(Fingered Bs2 vs SC-8850 Heart Bass, which is also almost identical to
+Rock Bass in Super Quartet, and the sample is from SR-JV80-09).</li>
+</ul>
+<p>This list is far from complete. There has been extensive efforts to
+map the multisamples in the SD-80 to XV-5080 and SRX multisamples. <a href="//filestorage.chrisoft.org/blog/data/SD-80/SD-80_Waveform_Comparison.pdf">Here</a>
+is one made by Palto. These mappings are extremely useful if you wish to
+recreate SD-80 patches with Roland’s VSTi plugins.</p>
+<p>So the content of the SD-80 is actually a mixture of XV-5080, SRX
+wave expansion boards, SR-JV80 boards, earlier SoundCanvas patches and
+maybe a few new sounds. Reusing stuff isn’t surprising for Roland, nor
+should it be considered “bad”. They’ve been known to do this <a href="https://www.soundonsound.com/reviews/roland-sc88">since the early
+SC days</a>, where they used JV- and SR-JV80 expansion board sounds in
+the old SC series. Evidently, the waveforms come with XV-5080 itself
+include everything from the JV-2080/1080, which are in turn partially
+from the JV-880, and eventually from the JD-800… I’ve also noted that
+SuperQuartet has a substantial overlapping set of instruments with
+SRX-03. All I want to say in this section is that if you want to get
+some particular sounds from the Studio Canvas, instead of waiting for a
+second-hand offering, maybe look somewhere else.</p>
+<p>Since the content of SD-80 is mostly just cherrypicked XV/SRX
+content, it really doesn’t need any additional praise from me. However I
+think it’s worth pointing out that Roland’s samples of that era, just
+like sounds from most other vendors, are heavily looped. They have loop
+periods that are quite short (usually less than a second). They are also
+usually heavily preprocessed. As the amount of memory used for
+reproducing the instruments saw a huge boom in the 2000s, they no longer
+sound downright “fake” or “plasticky” compared to romplers from a decade
+ago. However when compared against huge modern sample libraries, most
+instruments from these 2000s Roland romplers sound more “idealistic”
+rather than “realistic”, just like your average Japanese anime girls
+with unrealistically huge eyes. Not saying that such sound is bad,
+though.</p>
+<p>The GS sounds and XGLite sounds of the SD-80 are completely trash.
+The GS sound set is pretty much just the SC-55 map in later SoundCanvas
+models using SD-80 samples. The XGLite sound set however, is notably
+larger than the average bottom-of-the-line Yamaha Portatones from the
+early 2000s (the XGLite instrument listing in SD-80/90’s manual is
+incomplete. Check my first SD-80 post for a complete list). There are
+probably only 5 or so usable sounds offered in these modes in total
+(most of which are in the XGLite sound set, which is kind of ironic for
+a Roland sound module). It’s not worth it to switch modes just for those
+sounds, especially since these modes don’t support low-level editing
+like the native mode.</p>
+<p>The SD-80 features 1050 instruments and 30 drum sets, which is a
+significant decrease from the last generation SC-8850 (1640 instruments
+and 63 drum sets). The loss of SC-8850’s ethnic and analog instruments
+is a shame. But the quality of instruments does receive a general
+uplift.</p>
+<h3 id="tocanch34" class="tvis">More on SD-80 vs SD-90 vs
+SD-20</h3>
+<h4 id="tocanch35" class="tvis">What does a SD-90 have
+that SD-80 doesn’t?</h4>
+<p>Easy. The audio interface (together with post-processing effects) and
+the large screen.</p>
+<p>It is a shame that Roland didn’t implement full XV-level editability
+of patches on such a large screen though.</p>
+<p>SD-80 is also not capable of switching the output sample rate on its
+digital audio outputs.</p>
+<h4 id="tocanch36" class="tvis">What does a SD-80 have
+that SD-90 doesn’t?</h4>
+<p>This may come as a shocker, because the list is surprisingly
+long.</p>
+<ul>
+<li>User instruments and user rhythm sets. <a id="n22" href="#note22" class="note">[22]</a></li>
+<li>A few weird switches controlling its global state (MFX on/off,
+reverb/chorus switch). They are weird because they are not affected by
+the native mode reset message. These switches are also featured in the
+SD-80 editor, which Roland says don’t do anything if used with an SD-90.
+They are also present in the professional XV line-up.</li>
+<li>Multiple outputs from the synthesizer. The SD-90 does have a
+secondary output, but the internal synthesizer can only use one of them.
+The SD-80 has two stereo outputs, which can also be used as four mono
+outputs. This also allows the SD-80 to have…</li>
+<li>Ability to output synthesizer effects to a separate bus. You can
+specify the output for the internal reverb, chorus and multi-effects as
+well.</li>
+</ul>
+<h4 id="tocanch37" class="tvis">What’s the SD-20 anyway?</h4>
+<p>Turns out it’s not much.</p>
+<p><a href="https://chrisoft.org/blog/post/2021-10-10.html">There’s
+going to be a separate article on this.</a></p>
+<h4 id="tocanch38" class="tvis">What role does MFX play?</h4>
+<p>It depends. If the MFX is just some reverb, EQ, or chorus, it really
+doesn’t make a whole world of difference and can be easily replaced with
+basic external effects. If its an amplifier simulator, a pitch shifter,
+or an auto filter, disabling MFX will result in a drastic sound change.
+Plugins simulating these effects are also usually harder to come by /
+more expensive. A few demonstrations of patches with and without MFX are
+in the table below.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+Patch
+</th>
+<th>
+MFX Type
+</th>
+<th>
+Audio demo (with MFX, then without MFX)
+</th>
+</tr>
+<tr>
+<td>
+3D Crystal
+</td>
+<td>
+Modulation Delay
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/3D_Crystal.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+96 Year
+</td>
+<td>
+Rotary
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/96_Year.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+Celtic Ens
+</td>
+<td>
+Reverb
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Celtic_Ens.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+MonoDLY Dist
+</td>
+<td>
+Guitar Multi A
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/MonoDLY_Dist.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+Oxigenizer
+</td>
+<td>
+Keysync Flanger
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Oxigenizer.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+Quasar
+</td>
+<td>
+Ring Modulator
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Quasar.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+Reed Romance
+</td>
+<td>
+Enhancer
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Reed_Romance.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+<td>
+Wah Ana.Clav
+</td>
+<td>
+Stereo Auto Wah
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-80/Wah_Ana.Clav.ogg">
+</audio>
+</td>
+</tr>
+</tbody></table>
+</div>
+<h3 id="tocanch39" class="tvis"><code>Light Load</code> vs
+<code>High Load</code></h3>
+<p>There is a toggle for “Light Load” mode in the driver for SD-80 on
+all platforms, including Linux. What this option actually does is not
+documented. The only thing I know is that in the Linux driver this is
+implemented with a single <code>usb_set_interface</code> call.</p>
+<p>This setting doesn’t seem to affect the synth engine, only the way
+how midi data is transmitted / processed (because the drivers for UA-25
+has this option as well). Weirdly, Roland’s contemporary software
+synthesizers (HyperCanvas/TTS-1, SuperQuartet, Orchestral) also have
+this option.</p>
+<h3 id="tocanch40" class="tvis">Block Diagram</h3>
+<p>I made <a href="//filestorage.chrisoft.org/blog/data/SD-80/sd80blk_notext_o.svg">this
+vectorized version</a> of SD-80’s block diagram printed on its chassis
+when I was bored. You can also get a <a href="//filestorage.chrisoft.org/blog/data/SD-80/sd80blk_notext_o_nt.png">rasterized
+version</a>.</p>
+<h3 id="tocanch41" class="tvis">Other weird and interesting
+stuff</h3>
+<ul>
+<li>Very few (if any) preset patches uses the modulation matrix of the
+XV engine correctly. All of them has the modulation source set to
+‘OFF’.</li>
+<li>Only 5 of all preset patches used non-default tone structures:
+“Runaway Rez”, “Purple Spin”, “FM layer”, “FM Delight”, and “Xmod EP”.
+All of them are in the special sets. 3 of them are unmodified XV-5080
+patches.</li>
+<li>There doesn’t seem to be a way to set the system tempo of the
+SD-80/90 with MIDI messages, nor can the SD-80/90 sync its MIDI clock
+with a host, rendering the system clock mostly useless. Neither of these
+two is true for the XV-5080.</li>
+<li>Ever wondered why some patches have seemingly nonsensical waveforms
+selected in disabled tones <a id="n23" href="#note23" class="note">[23]</a>? Just look up those wave
+numbers in the waveform list of XV-5080 or the corresponding SRX board!
+<a id="n24" href="#note24" class="note">[24]</a> This, once again, suggests
+Roland used the XV-5080 as the development platform for the
+StudioCanvas.</li>
+<li>From Sound On Sound’s review of the SD-90: “To me, however, USB
+audio and the Sound Canvas sound set don’t add up to £799, and although
+I grew to like the SD90, I’m not sure how many people will find it
+attractive at this price point.” – ZUN, apparently.</li>
+</ul>
+<h2 id="tocanch42" class="tvis">Errata of the original post</h2>
+<ul>
+<li>The non-zero “modulation level” (which is actually “modulation
+depth”) on the SD-80 isn’t the value of the modulation wheel itself, but
+rather how deep a modulation wheel pushed all the way to the top will
+modulate the sound. SD-90 also has a default value of 10 for it (“Mod
+LFO Pitch Depth” in the address mapping). There’s no GM incompatibility
+here.</li>
+<li>Instruments sampled with vibrato are not from the XV-5080, they are
+from the SRX / SR-JV80 boards. Duh.</li>
+<li>XP6 <em>was</em> used in professional products. In fact, a handful
+of them (XV-3080, XV-88, JV-1010 and possibly more).</li>
+<li>Roland still makes romplers today. It’s a model from a decade ago.
+You’ll have to guess which model it is.</li>
+</ul>
+<h2 id="tocanch43" class="tvis">References</h2>
+<ul>
+<li><a href="https://www.dtech.lv/techarticles_roland_exp.html">Roland
+Wave Expansion Cards by Edward D-tech</a></li>
+<li><a href="http://www.donsolaris.com/?p=404">Don Solaris’ ultimate
+Roland JV/JD/XV FAQ</a></li>
+<li><a href="https://www.sweetwater.com/insync/cosm/">What is
+COSM?</a></li>
+<li><a href="https://www.soundonsound.com/reviews/roland-xv5080">SOS
+Review of XV-5080</a></li>
+<li><a href="https://www.soundonsound.com/reviews/edirol-sd90">SOS
+Review of SD-90</a></li>
+<li><a href="https://www.soundonsound.com/reviews/edirol-sd80">SOS
+Review of SD-80</a></li>
+<li><a href="https://www.soundonsound.com/reviews/roland-sc88">SOS
+Review of SC-88</a></li>
+</ul>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Judging by the way Roland
+utilized the SH-3 CPU in MC-909, which has a 16MHz external clock input
+and a 8x multiplier (128MHz internal clock), I would guess the CPU in
+SD-80 also works at 8x multiplier and therefore 96MHz
+internally.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Later the source of this DC bias is determined to
+be SD-80 itself, not the recording device. See the next
+section.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: オールインワン・モデルSD-90でご好評いただいた、新開発MIDI音源部を搭載したマルチティンバー音源が登場。
+As seen <a href="https://web.archive.org/web/20020604015208/http://www.roland.co.jp/products/dtm/SD-80.html">here</a>.
+I don’t actually know any Japanese and just pieced stuff together
+randomly. Sorry if I butchered your language.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: Munt isn’t strictly an emulation. It doesn’t emulate the CPU
+or actual circuitry of the MT-32. See below.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: without Roland losing their mind and releasing all
+internal documentation on the XV engine, or some absolute madlad
+spending 15 hours everyday on reverse engineering the thing for half a
+year, that is.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: SD-80 has 32MiB of compressed wave ROM, see the “list of
+integrated circuit chips on SD-80 main board” in the first section.
+Roland’s waveform compression scheme usually results in a ~50%
+compression ratio. Therefore the content is roughly equal to 64 MiB of
+uncompressed 16-bit PCM wave.<br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: The “23C128” kind of gave it away –
+they are the <code>μPD23C128040ALGY</code> mask ROM chips from NEC,
+which is the exact same type of ROM used in XV-5080. Unlike the XV-5080
+though, the SD-80 makes use of both its J variant and K variant, while
+the XV-5080 only uses the J variant (these variants have symmetric pin
+configuration). <br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: Well, the
+Raspberry Pi isn’t really suitable for this task because it doesn’t have
+enough GPIO pins. But there’s an easy workaround for that.<br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: For readers who wonders what “mask” means in
+this context: you can treat a mask ROM as a huge array of tiny switches
+that can’t be turned on or off once manufactured. You can access the
+state of a group of switches by giving an address to its input pins. The
+mask is used as a template of the states of these switches during the
+manufacture process. This is electrical engineering amateur Chris trying
+to explain mask ROM in layman’s terms.<br></span><span class="TText"><a id="note10" href="#n10">[10]</a>: HyperCanvas (HQ-GM2) or Cakewalk TTS-1, which is a rebranding
+of the former; SuperQuartet (HQ-QT) and Orchestral (HQ-OR). A plugin
+called GrooveSynth (P5antom) bundled with several earlier Cakewalk
+products providing patches from the MC-303 Groovebox also uses this
+engine.<br></span><span class="TText"><a id="note11" href="#n11">[11]</a>: which is kind of weird considering
+Spectrasonics basically spun off from Roland<br></span><span class="TText"><a id="note12" href="#n12">[12]</a>: Also used in XP-80, see the errata
+section of its service manual.<br></span><span class="TText"><a id="note13" href="#n13">[13]</a>: HD64F7017F28, SH7017 in parts
+list<br></span><span class="TText"><a id="note14" href="#n14">[14]</a>: 40 of the
+90 types will take up all three slots, most likely due to the reduced
+DSP power.<br></span><span class="TText"><a id="note15" href="#n15">[15]</a>: Support for multisamples also exist in Fantom
+S/S88, so this is more likely due to an updated system software rather
+than changes of the synth engine.<br></span><span class="TText"><a id="note16" href="#n16">[16]</a>: There is evidence that some of them
+are handled by software (SD-80 having one more LFO per part than the
+XV-5080). However it can also be using LFO blocks in the XV chip that is
+unused in the XV-5080.<br></span><span class="TText"><a id="note17" href="#n17">[17]</a>: This mapping is used for
+DT1/RQ1 system exclusive messages.<br></span><span class="TText"><a id="note18" href="#n18">[18]</a>: The first half is also true for earlier SC
+models (SC-55 &lt;-&gt; JV-880, SC-88 &lt;-&gt; JV-1080, SC-88Pro
+&lt;-&gt; JV-2080, SC-8850 &lt;-&gt; XV-3080). However the second half
+isn’t. Earlier SC models employs a GS-specific address map which looks
+nothing like their counterparts.<br></span><span class="TText"><a id="note19" href="#n19">[19]</a>: And also the last time, since neither the SD-20 nor the SD-50
+has such editability.<br></span><span class="TText"><a id="note20" href="#n20">[20]</a>: Apparently it’s from the
+SC-8850.<br></span><span class="TText"><a id="note21" href="#n21">[21]</a>: The
+multisample from Roland Cloud seem to have an extra sample in the
+highest register, which sounds like it’s processed with a low-pass
+filter with very low cut off frequency and makes it sound like garbage.
+This is also the case for the version included in the original SRX-09
+boards.<br></span><span class="TText"><a id="note22" href="#n22">[22]</a>: The owner’s manual
+of the SD-80 contains blatant lies. It says “It is not possible for the
+edited sounds to be saved in the internal memory of the SD-80” (which is
+directly copied from SD-90’s manual), and goes on to teach you how to
+save a user patch.<br></span><span class="TText"><a id="note23" href="#n23">[23]</a>: For example, nearly all acoustic
+bass patches have a disabled tone with wave number 249 “TenBlwSaxVib”
+selected, and the Fiddle 2 vib patch have a disabled tone with wave
+number 276 “Blow Pipe” selected.<br></span><span class="TText"><a id="note24" href="#n24">[24]</a>: Wave #249 in XV-5080 is UprightBs 2A, and Wave #276 in SRX-09
+is Fdl Pizz 1C (Fiddle Pizzicato).<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2021-06-03.html b/blog/post/2021-06-03.html
index 9a3379d..17e9ee2 100644
--- a/blog/post/2021-06-03.html
+++ b/blog/post/2021-06-03.html
@@ -1,8 +1,10 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"No, I'm not dead")</title>
+<meta name="description" content="«No, I'm not dead» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
@@ -49,31 +51,44 @@ function ol()
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">Quick status update</a></li><li><a class="toctarg" href="#tocanch1">What have I done</a></li><li><a class="toctarg" href="#tocanch2">When are the unfinished posts gonna be finished?</a></li></ul>
+ <li><a class="toctarg" href="#tocanch0">Quick status update</a></li><li><a class="toctarg" href="#tocanch1">What have I done</a></li><li><a class="toctarg" href="#tocanch2">When are the
+unfinished posts gonna be finished?</a></li></ul>
</li>
- <li style="margin-left:-0.5em"><a id="prevp" href="2019-09-04.html">Prev post</a></li>
- <li style="margin-left:-0.5em"><a id="nextp" href="Privacy.html">Next post</a></li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2020-11-20.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2021-10-10.html">Next post</a></li>
</ul>
</div>
<div id="content">
<h2 id="titleh" class="TText" style="font-wight:normal;">No, I'm not dead</h2>
<div id="datetags" class="TText" style="margin-bottom:1em;">2021-06-03<br>#garbage</div>
<hr><div id="article" class="TText"><article>
-<p>No I’m not dead. Sure this blog has been snubbed for quite a while now, and I just marked 5 old unfinished posts (from 2019 all the way to 2021) as WIP so that they do not appear here. Just not feeling finishing them up (or writing anything) right now.</p>
+<p>No I’m not dead. Sure this blog has been snubbed for quite a while
+now, and I just marked 5 old unfinished posts (from 2019 all the way to
+2021) as WIP so that they do not appear here. Just not feeling finishing
+them up (or writing anything) right now.</p>
<h2 id="tocanch0" class="tvis">Quick status update</h2>
-<p>I’m doing random, stupid researches – as an average computer scientist wannabe. Also I’m learning Latin. Nondum possum loqui. (or write, for that matter – sudden code-switching)</p>
+<p>I’m doing random, stupid researches – as an average computer
+scientist wannabe. Also I’m learning Latin. Nondum possum loqui. (or
+write, for that matter – sudden code-switching)</p>
<h2 id="tocanch1" class="tvis">What have I done</h2>
<ul>
-<li><a href="https://github.com/chirs241097/jline4mcdsrv">My first Minecraft mod</a> (server only, and unrelated to gameplay – so probably uninteresting to anyone but server maintainers)</li>
-<li><a href="https://github.com/FluidSynth/fluidsynth/commits?author=chirs241097">A few fluidsynth commits</a></li>
-<li>Trying to extract stuff from my SD-80 (and failing no-so-spectacularly)</li>
+<li><a href="https://github.com/chirs241097/jline4mcdsrv">My first
+Minecraft mod</a> (server only, and unrelated to gameplay – so probably
+uninteresting to anyone but server maintainers)</li>
+<li><a href="https://github.com/FluidSynth/fluidsynth/commits?author=chirs241097">A
+few fluidsynth commits</a></li>
+<li>Trying to extract stuff from my SD-80 (and failing
+no-so-spectacularly)</li>
<li>Messing on a shitty block game server called 2b2t</li>
<li>Writing a skyblock datapack, and playing it</li>
-<li>Random researches in various CS fields until I could settle somewhere firmly</li>
+<li>Random researches in various CS fields until I could settle
+somewhere firmly</li>
<li>Falling into the functional programming cult</li>
</ul>
-<h2 id="tocanch2" class="tvis">When are the unfinished posts gonna be finished?</h2>
-<p>I don’t know. I reckon that would be somewhere in &lt;redacted&gt;.</p>
+<h2 id="tocanch2" class="tvis">When are the
+unfinished posts gonna be finished?</h2>
+<p>I don’t know. I reckon that would be somewhere in
+&lt;redacted&gt;.</p>
</article>
</div><br><hr>
<div class="TText" id="notediv" style="font-size:80%;"></div>
diff --git a/blog/post/2021-10-10.html b/blog/post/2021-10-10.html
new file mode 100644
index 0000000..f18b75a
--- /dev/null
+++ b/blog/post/2021-10-10.html
@@ -0,0 +1,972 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"EDIROL SD-20: the Crumbling of the Canvas?")</title>
+<meta name="description" content="«EDIROL SD-20: the Crumbling of the Canvas?» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">EDIROL SD-20: the Crumbling of the Canvas?</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/device-review/">device-review</a></li><li><a href="/blog/list/midi/">midi</a></li><li><a href="/blog/list/music/">music</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">The Encounter</a></li><li><a class="toctarg" href="#tocanch1">The Module</a></li><li><a class="toctarg" href="#tocanch2">The Setup</a></li><li><a class="toctarg" href="#tocanch3">The Sounds</a></li><li><a class="toctarg" href="#tocanch4">The Editability</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch5">The Quirks</a></li></ul></li><li><a class="toctarg" href="#tocanch6">The Manual</a></li><li><a class="toctarg" href="#tocanch7">The Insides</a></li><li><a class="toctarg" href="#tocanch8">The Secrets</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch9">Test mode</a></li><li><a class="toctarg" href="#tocanch10">unknown (likely firmware
+update) mode</a></li></ul></li><li><a class="toctarg" href="#tocanch11">The Conclusion</a></li><li><a class="toctarg" href="#tocanch12">The … Death?</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2021-06-03.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2022-07-23.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">EDIROL SD-20: the Crumbling of the Canvas?</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2021-10-10<br>#device-review #midi #music</div>
+ <hr><div id="article" class="TText"><script>
+window.addEventListener("DOMContentLoaded",function(){
+const cl=document.querySelectorAll('div.collapse');
+let n=0;
+for(let x of cl)
+{
+ const d=document.createElement('blockquote');
+ const dd=x.cloneNode(true);
+ x.parentNode.insertBefore(d,x);
+ x.parentNode.removeChild(x);
+ dd.id=`cc${n++}`;
+ dd.style.display='none';
+ const s=document.createElement('span');
+ const b=document.createElement('b');
+ const a=document.createElement('a');
+ a.classList.add('ca');
+ a.setAttribute('x',n-1);
+ a.innerHTML='show';
+ a.href='javascript:void(0)';
+ if (dd.hasAttribute('caption'))
+ b.innerHTML=dd.getAttribute('caption');
+ else
+ b.innerHTML=dd.getAttribute('data-caption');
+ s.appendChild(b);
+ s.appendChild(document.createTextNode(' ['));
+ s.appendChild(a);
+ s.appendChild(document.createTextNode(']'));
+ d.appendChild(s);
+ d.appendChild(dd);
+ a.onclick=function()
+ {
+ let x='none';
+ if(a.innerHTML=='show')
+ {
+ a.innerHTML='hide';
+ x='block';
+ }
+ else
+ {
+ a.innerHTML='show'
+ }
+ document.getElementById(`cc${a.getAttribute('x')}`).style.display=x;
+ }
+}
+const al=document.querySelectorAll('audio');
+n=0;
+for(let x of al)
+{
+ x.id=`a${n++}`;
+ x.onplay=function()
+ {
+ for(let x of al)
+ {
+ if(x.id!=this.id)x.pause();
+ }
+ }
+}
+});
+</script>
+<article>
+<p>I was intrigued by the insides of EDIROL’s SD-20. How on earth did
+Roland squeeze half of SD-80’s content in to a package that’s smaller
+than SD-80’s main board? Turns out it was by crippling the product…</p>
+<h2 id="tocanch0" class="tvis">The Encounter</h2>
+<p>I didn’t get my SD-20 for $50 as promised in my SD-80 article. The
+lowest price I found when I started watching for spares again was $75.
+It stayed there for over half a year. But just weeks before I got into
+the States, it was gone. All the rest of the listings asked for
+ridiculous prices ranging from $150 to $250. There’s no way I will pay
+over $100 for a SD-20. So I waited and waited…</p>
+<p>Until one day a new listing popped up. It was exactly $100 (with free
+shipping). “Well,” I thought, “this is it.” It accepts best offer, but
+nobody else offered to buy it until the listing ended. That’s the
+bizarre story of me getting my SD-20 at my max acceptable price…</p>
+<h2 id="tocanch1" class="tvis">The Module</h2>
+<p>I felt the cheapness inside instantly when I picked up the package:
+the SD-20 (with the included, somewhat dodgy aftermarket power adapter)
+weights absolutely nothing! It’s even lighter than the ThinkPad mouse I
+occasionally use. That doesn’t inspire much faith on its insides.</p>
+<p>The exterior of the module is made of plastic exclusively. No metal
+whatsoever (except on the connectors). SD-80’s metal front cover weights
+more than this entire thing…</p>
+<p>Flipping the module around reveals the dreaded three word phrase:
+“Made in China”. I wonder how many products that are never available in
+China at all are assembled in China.</p>
+<p>There’s only one button and one knob on the front panel of the SD-20.
+This is even more cut down than the SC-8820, which also has only one
+button and one knob, but the volume knob doubles as a preview
+button.</p>
+<p>Roland clearly made SD-20 the intended successor of SC-8820. Just
+look at the pictures in the manuals. They have nearly identical form
+factors. Let’s see how their sounds will compare.</p>
+<p>The choice of ports is kind of weird on the SD-20. It’s almost
+identical to the ports on the back of the SC-8820, except the audio
+input being replaced by a 3.5mm combo jack, addition of an optical
+S/PDIF TOSLINK port, and omission of the DIN MIDI out port. The serial
+port (mini DIN 8-pin) featured on all older SC models made its only
+reappearance in the SD series. Despite having an audio input port, the
+SD-20, just like its predecessors in the SC family, doesn’t have any
+digital audio interface functionality. The audio input is merely passed
+through to the analog output.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_module.jpg"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_module.jpg"></a> <br>SD-20 on top of
+the SD-80
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_bottom.jpg"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_bottom.jpg"></a> <br>Bottom with
+serial number censored
+</div>
+</td>
+</tr>
+</tbody></table>
+<h2 id="tocanch2" class="tvis">The Setup</h2>
+<p>Like the SD-80, Roland has discontinued driver support for the SD-20.
+The SD-20 will not even appear powered on if you choose to power the
+unit through USB bus power and have no driver installed. The same trick
+to make SD-80’s driver work on Windows 10 also works for the SD-20. You
+can search the Internet for the trick, or check out my first post on the
+SD-80 for the directions.</p>
+<p>The module works out of the box on Linux as long as you have proper
+kernel support (that is, you shouldn’t have to worry about this unless
+you build the kernel yourself). Required kernel modules are identical to
+those of the SD-80.</p>
+<p>The use of RCA jacks for analog audio output means that I don’t have
+the suitable cable to connect them to my audio interfaces at the moment.
+Fortunately I can still make digital recordings thanks to the inclusion
+of the S/PDIF output. The digital signal has a sample rate of 44100 Hz,
+the same as SD-80.</p>
+<h2 id="tocanch3" class="tvis">The Sounds</h2>
+<p>(Unless otherwise stated, all hardware demos in this section are
+recorded through the digital S/PDIF interface with EDIROL UA-25. All
+files are level normalized to -1 dB. Excerpts are not normalized after
+being extracted from the normalized original.)</p>
+<p>It’s the same StudioCanvas sound, but …</p>
+<p>With a few exceptions, preset instruments shared by the SD-20 and the
+SD-80 sound roughly identical. However, note the different mix levels on
+each model.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+SD-20
+</th>
+<th>
+SD-20 Converter
+</th>
+<th>
+SD-80
+</th>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD20.NCREX.OGG">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD20C.NCREX.OGG">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD80.NCREX.OGG">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="3">
+Excerpt from AMEDLEY.MID by Earl Gray Fowler from Voyetra Technologies,
+arranged for SD-80 (Native Mode)
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>However significant differences show up as soon as you start tuning
+any non-GM1 controls (this includes new controls defined by GM2, e.g.&nbsp;cc
+74).</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+SD-20
+</th>
+<th>
+SD-20 Converter
+</th>
+<th>
+SD-80
+</th>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd20.ncrex.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd20c.ncrex.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd80.ncrex.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="3">
+Excerpt from th06_13.mid
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>Note the very different filter characteristics on the piano.</p>
+<p>What make this module nearly unusable is its 64 voices polyphony.
+Roland has been using this “voice” concept for polyphony since the very
+beginning of their PCM based synths. An instrument can have up to four
+“layers” (or “WGs”, wave generators in Roland’s terms) in these Roland
+PCM synthesizers. Each layer can consist of up to two channels (for
+stereo samples). Each one of these channels takes up a “voice” when
+played. The contemporary set and solo set of the StudioCanvas make heavy
+use of layering, as well as stereo samples. Some of these patches
+casually use up to 4 voices per note, with a (theoretical) maximum of 8.
+Unlike the SC-8850 vs SC-8820, when Roland stripped down the polyphony
+of the SD-20, they did not create simplified patches that use fewer
+voices like they did for the SC-8820. This immediately brings down the
+actual note polyphony of the SD-20 down to the same (or even lower)
+level of SC-55, and is no where near usable. Hence in terms of
+polyphony, the SD-20 is a downgrade compared to its predecessor SC-8820:
+Even you have Roland’s (then) latest studio sounds inside a tiny box,
+you have to take great precaution while using them, as they deplete your
+available polyphony <em>very</em> fast. Both tracks below demonstrate
+how 64 voices is nowhere close to enough for the SD-20.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+SD-20
+</th>
+<th>
+SD-20 Converter
+</th>
+<th>
+SD-80
+</th>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd20.ncr.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd20c.ncr.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/th06_13.sd80.ncr.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="3">
+“Crude” replica of Septette for a Dead Princess by ZUN. The original
+tuning was not replicated.
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>The SD-20 drops notes like crazy in the final section. The SD-20 MIDI
+Converter drops percussion notes instead.</p>
+<p>Unlike my SD-80, which sometimes messes up timing a bit and slows
+down when the load is high, the SD-20 simply cut off existing notes
+instantly without causing timing errors.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+SD-20
+</th>
+<th>
+SD-20 Converter
+</th>
+<th>
+SD-80
+</th>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/kog_09.sd20.ncr.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/kog_09.sd20c.ncr.ogg">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/kog_09.sd80.ncr.ogg">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="3">
+“Crude” replica of Enigmatic Doll from KiohGyoku by ZUN.
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>Besides the obvious fact that Loose Lips is missing, pay attention to
+the way the piano notes are cut short. Also note each model has its own
+filter response for the synth bass.</p>
+<p>Finally, a GM-ish track for comparing vanilla GM2 patches without any
+tweaking. Reed Romance and SH-2 Lead from the SD special set are used in
+this adaptation.</p>
+<div>
+<table style="position:relative;left:50%;transform:translate(-50%,0);text-align:center">
+<tbody><tr>
+<th>
+SD-20
+</th>
+<th>
+SD-20 Converter
+</th>
+<th>
+SD-80
+</th>
+</tr>
+<tr>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD20.NCR.OGG">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD20C.NCR.OGG">
+</audio>
+</td>
+<td>
+<audio controls="" preload="none" src="//filestorage.chrisoft.org/blog/data/SD-20/AMEDLEY.SD80.NCR.OGG">
+</audio>
+</td>
+</tr>
+<tr>
+</tr><tr>
+<td colspan="3">
+AMEDLEY.MID by Earl Gray Fowler from Voyetra Technologies, arranged for
+SD-80 (Native Mode)
+</td>
+</tr>
+</tbody></table>
+</div>
+<p>Patches in SD-80’s special set are substituted with patches in the
+solo set when played with the SD-20 Converter. However hardware SD-20
+doesn’t do this substitution and doesn’t produce any sound if a patch
+from SD-80’s special set is selected, making the last two segments sound
+like a backing track on the SD-20. The choir in the ballad segment also
+has a notably shorter release on the hardware SD-20, possibly to
+mitigate the impact of a reduced polyphony.</p>
+<p>The SD-20 MIDI Converter is actually a reasonably good recreation of
+the SD-20 sounds. That is not saying so much, as the hardware of SD-20
+itself is simply not capable of recreate the StudioCanvas sounds very
+well if the MIDI sequence you feed to it has any complexity to it at
+all. Sometimes the output from converter is actually closer to the SD-80
+than the SD-20, especially if you take parameter response curves into
+consideration.</p>
+<h2 id="tocanch4" class="tvis">The Editability</h2>
+<p>It’s virtually nothing compared to the SD-80.</p>
+<p>The official SD-20 editor can only tune GM2 parameters. The available
+parameters are even fewer than the HyperCanvas (HQ-GM2) or TTS-1, mostly
+because the SD-20 doesn’t expose those parameters at all. As mentioned
+in my first post on the SD-80, the SD-20 editor is essentially the SD-90
+editor with the audio / AFX section removed.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_editor_main.png"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sd20_editor_main.png"></a> <br>SD-20
+editor. SD-90 GM2 editor on the right for comparison.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_editor_mixer.png"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sd20_editor_mixer.png"></a> <br>The mixer.
+It has a very similar layout to the main page of HyperCanvas / TTS-1.
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_editor_synth.png"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sd20_editor_synth.png"></a> <br>The
+instrument editor. Only GM2 parameters are exposed.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_editor_instp.png"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_600x600_sd20_editor_instp.png"></a> <br>The
+instrument picker. The instrument picker of the SD-90 GM2 editor is on
+the right.
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>The SD-80 editor doesn’t work on the SD-20. Nor does the XV-2020
+(which uses the same synth engine as the SD-20) editor. This makes the
+SD-20 far less editable than the SD-80. Forget about manually piecing
+together presets on the SD-20 to mimic the SD-80. I don’t even know how
+to change the samples used by a part on the SD-20 or is it even possible
+(the MIDI implementation doesn’t mention it).</p>
+<h3 id="tocanch5" class="tvis">The Quirks</h3>
+<p>The address mapping used by SD-20’s DT1 system exclusive messages is
+similar to that employed by GS-based Sound Canvas models. Therefore the
+SD-20 is still somewhat editable, but nowhere close to the level offered
+by the SD-80. GSAE (GS Advanced Editor) may work with the SD-20, but
+there could be major compatibility issues.</p>
+<p>The SD-20 still responds to GS NRPN messages in native and GM2 mode.
+SD-90 and SD-80 doesn’t have such behavior.</p>
+<p>SD-20 has a special NRPN for selecting sound sets (MSB:
+<code>0x41</code> LSB: <code>0x00</code>, send set # to value MSB) in
+GM2 mode. On the SD-90 and SD-80, only system exclusive messages can be
+used to select sound sets in GM2 mode. The manual mentioned this
+feature, however it doesn’t tell you which NRPN to use.</p>
+<h2 id="tocanch6" class="tvis">The Manual</h2>
+<p>This really doesn’t deserve its own paragraph, but here it is. Unless
+otherwise noted, this is referring to the English manual, not the
+Japanese version (which is somewhat better, but still horrible).</p>
+<p>The user manual of Roland products has been criticized for being
+convoluted, unclear and difficult to navigate through for a long time.
+The user manual for SD-20 is on a whole new level. It’s an absolute
+abomination.</p>
+<p>To be fair, it’s not like one can write a lot about a product that
+only have one button and one knob on the front panel. Someone in Roland
+must have been forced through this …</p>
+<p>Content wise, it’s an amalgamation of SD-80’s “owner’s manual” and
+“quick start guide”. This make the entire thing even more confusing. You
+can find traces of SD-80’s manual everywhere. Just take a look at the
+huge gaps in the instrument list and drum set list. That sad drum set
+table even has a missing border. There’s also the sentence that goes
+something like this “you can’t edit the sounds in GS mode using the
+front panel” <a id="n1" href="#note1" class="note">[1]</a>, which is copied
+straight from SD-80’s manual. Well, duh … you can’t do much editing with
+one button (which instantly erases all changed parameters when pressed)
+and one knob in any mode!</p>
+<p>Since the SD-20 can only be controlled through MIDI, there would be
+plenty of information on how to operate the module using MIDI messages
+in the manual, right? Here Roland took the worst move imaginable and
+included ZERO information on that in the English manual, not even the
+system exclusive messages to switch between sound generator modes (the
+Japanese manual does include this), nor does it include a list of
+parameters that can be controlled by MIDI. It’s almost like Roland
+doesn’t want you to learn about the parameters it has at all, unless you
+read the ultra technical MIDI implementation (which, to make it even
+better, only has a download for the Japanese version left on the
+official website. Screw everyone who can’t read Japanese I guess).</p>
+<h2 id="tocanch7" class="tvis">The Insides</h2>
+<p>I spent $100 on this thing mostly because I’m curious about its
+insides. After testing it out, I don’t have any hope that there’s a
+chance this thing could have an XV chip inside. Having no screwdrivers
+did not hinder me even a little bit. I used the scissors in my nail care
+kit to remove the only 4 screws in the bottom of the module, and one
+screw holding the board. The board came out without any resistance.</p>
+<div style="text-align:center;max-width:90%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_board_bottom.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_board_bottom.jpg"></a> <br>No ICs on
+the bottom side of the board. The scissor used to undo the screws is
+visible.
+</div>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<p><a href="//filestorage.chrisoft.org/blog/img/sd20_icmap.jpg"><img style="width: 80%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_icmap.jpg"></a></p>
+</div>
+</td>
+<td>
+<div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#ff0000;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_cpu.jpg">CPU
+(SH7016)</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#ffa000;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_io.jpg">8bit MCU, I/O
+Controller</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#fff300;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_cpu.jpg">4 Mb System
+DRAM</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#00f300;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_cpu.jpg">16 Mb
+Flash</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#00ffff;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_io.jpg">RS-232
+driver</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#00a0ff;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_xp.jpg">Synth DSP
+(RA0C-003, “XP7”)</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#00c060;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_audioio.jpg">4Mb
+Effects DRAM</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#0000ff;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_wrom.jpg">2 * 128 Mb
+Wave ROM</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#a000ff;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_audioio.jpg">Digital
+Audio Modulator, S/PDIF interface</a></p>
+</div>
+<div>
+<p><x style="display:inline-block;width:0.9em;height:0.9em;border:solid 2px #888;background-color:#ff60ff;margin-right:0.5em;transform: translateY(0.2em);"></x>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_audioio.jpg">DAC
+(AK4382A)</a></p>
+</div>
+</div>
+Click any IC above for a detailed shot of components around that
+chip.<br>
+<a href="//filestorage.chrisoft.org/blog/img/sd20_board_top.jpg">Click
+here for the whole board shot without the IC markings.</a>
+</td>
+</tr>
+</tbody></table>
+<p>No, it isn’t an XV chip. It’s an XP7 (RA0C-003) chip. This chip is
+also used by the bottom-of-the-barrel model in the XV line-up, the
+XV-2020. This is likely the final iteration of the codename XP. The CPU
+is a SH7016, same as SC-8850 and SC-D70. Other major chips include two
+4Mbit EDO DRAM chips (one for CPU and one for XP7), a 16Mbit flash
+memory for system and parameters, and two 128Mbit Wave ROM chips. The
+part number and mask ID of the wave ROMs are different from those used
+by the SD-80 (either in the service manual or my particular module),
+suggesting they may contain different data.</p>
+<p>This is a major let down, sort of speak. The hardware is almost as
+capable as the XV-2020 (which has a larger CPU RAM and flash memory
+chip, 16Mbit and 32Mbit respectively). The XP7 is even capable of using
+40 types of classical JV/XP insertion effects (MFX), which is not used
+at all by the SD-20. Maybe the reduced system resources prevented Roland
+to squeeze the XV-level editability inside.</p>
+<p>The XP7 chip runs much hotter compared to the XV chip in the SD-80.
+It’s almost too hot to touch when the synthesizer load is high. The XP7
+chip in the SD-20 is clock much higher than any previous XP chips
+(33.868 MHz vs 24.576 MHz) to achieve the 44.1 kHz digital output, which
+is probably the cause of the excessive heat. For a more detailed
+technical assessment of the chip (and other Roland PCM synth chips), see
+<a href="https://chrisoft.org/blog/post/2020-11-20.html#tocanch16">my
+second post on SD-80</a>.</p>
+<p>There are 4 unpopulated switch headers on the board. Two are DPDT
+switches (SW4 and SW2), two seem to be buttons (SW3 and SW5). SW4 and
+SW5 seem to be electrically connected to the peripherals of the USB
+controller, SW2 and SW3 seem to be connected to the CPU. One side of SW4
+seems to short the USB power. SW2 resets the unit. SW3 puts the unit
+into an inoperable state (USB indicator turns off, SPIDF output shuts
+down, does not respond to any key press / MIDI input). SW2 is weird. One
+side of the upper pole shorts the power to ground. The same side of the
+lower pole puts the unit into another inoperable state (just like frozen
+in place). The other side doesn’t do anything consistent. Sometimes the
+upper pole acts like a perpetual sustain pedal if engaged (no notes are
+released even after letting the connection go). All of these switches
+behave the same in test mode and doesn’t seem to affect boot mode
+selection.</p>
+<div class="collapse" data-caption="Incomplete list of integrated circuit chips in the SD-20">
+<table>
+<colgroup>
+<col style="width: 9%">
+<col style="width: 30%">
+<col style="width: 59%">
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: center;">Label</th>
+<th style="text-align: center;">Engravement</th>
+<th style="text-align: center;">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">IC 1</td>
+<td style="text-align: center;">2360 6061B JRC</td>
+<td style="text-align: center;">DC to DC converter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 2,5</td>
+<td style="text-align: center;">4570 652</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 3</td>
+<td style="text-align: center;">4556A G034F JRC</td>
+<td style="text-align: center;">OpAmp</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 4</td>
+<td style="text-align: center;">AKM 4382AT 4N647</td>
+<td style="text-align: center;">DAC</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 6</td>
+<td style="text-align: center;">ROHM BP5220A 0707S</td>
+<td style="text-align: center;">Regulator</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 7</td>
+<td style="text-align: center;">PC401L SOK V2</td>
+<td style="text-align: center;">Optocoupler</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 8,18,12,15</td>
+<td style="text-align: center;">VHC 245 G43</td>
+<td style="text-align: center;">74xx245 Transceiver / Buffer</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 9</td>
+<td style="text-align: center;">E 6</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 10,13</td>
+<td style="text-align: center;">0634H LVX4245 404495</td>
+<td style="text-align: center;">74xx245 Transceiver / Buffer</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 11</td>
+<td style="text-align: center;">Roland R03017389 HD6437016E29FV 6J1</td>
+<td style="text-align: center;">CPU (SH7016), SH2</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 14</td>
+<td style="text-align: center;">E ? (covered)</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 16</td>
+<td style="text-align: center;">H 4</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 17,25</td>
+<td style="text-align: center;">7WU04F 6X</td>
+<td style="text-align: center;">74xx04 Inverter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 19</td>
+<td style="text-align: center;">0625H VHC04 301303</td>
+<td style="text-align: center;">74xx04 Inverter</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 20</td>
+<td style="text-align: center;">953B 69B</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 21</td>
+<td style="text-align: center;">2933 G2 5L</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 22</td>
+<td style="text-align: center;">0626H TC9271FSG</td>
+<td style="text-align: center;">Digital Audio Modulator</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 23</td>
+<td style="text-align: center;">7W14F 6W</td>
+<td style="text-align: center;">74xx14 Schmitt-Trigger Inverter</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 24</td>
+<td style="text-align: center;">Roland R02677490 RA0C-003 JAPAN 0645EGI
+B0106ZAC</td>
+<td style="text-align: center;">ASIC DSP, “XP7” Synth Engine</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 26</td>
+<td style="text-align: center;">Roland R03010612 23C128BL832J
+0620K7002</td>
+<td style="text-align: center;">128 Mbit Mask ROM, Wave ROM</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 27</td>
+<td style="text-align: center;">Roland R03010623 23C128BL833K
+0620K7005</td>
+<td style="text-align: center;">128 Mbit Mask ROM, Wave ROM</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 28</td>
+<td style="text-align: center;">VHC T245A F5 51</td>
+<td style="text-align: center;">74xx245 Transceiver / Buffer</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 29</td>
+<td style="text-align: center;">EliteMT M11L416256SA- 35T SZV2C51GR
+0627</td>
+<td style="text-align: center;">EDO DRAM 4 Mbit, XP Effects RAM</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 30</td>
+<td style="text-align: center;">LH28F160BJE-BTL80 SHARP JAPAN 0631 5
+XN</td>
+<td style="text-align: center;">Flash Memory, 16 Mbit, System /
+Parameters</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 31</td>
+<td style="text-align: center;">ti 71CN1RKG4 75C1168</td>
+<td style="text-align: center;">RS-232 driver</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 32</td>
+<td style="text-align: center;">EliteMT M11L416256SA- 35T SZV2C51GR
+0627</td>
+<td style="text-align: center;">EDO DRAM 4 Mbit, System RAM</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 33</td>
+<td style="text-align: center;">Roland R03011089 138 620B100</td>
+<td style="text-align: center;">USB Controller, 8-bit MCU</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 34</td>
+<td style="text-align: center;">2008 680</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 35</td>
+<td style="text-align: center;">7W04F 6V</td>
+<td style="text-align: center;">74xx04 Inverter</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">IC 36</td>
+<td style="text-align: center;">E 1</td>
+<td style="text-align: center;">?</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">IC 37</td>
+<td style="text-align: center;">7W139F 61</td>
+<td style="text-align: center;">74xx139 Decoder</td>
+</tr>
+</tbody>
+</table>
+</div>
+<h2 id="tocanch8" class="tvis">The Secrets</h2>
+<p>It seems dead easy to enter the secret test mode on the SD-20 –
+there’s only one button. Hold the button and turn the power on, the USB
+indicator will light up. This is the boot mode selection prompt. Release
+the button. Now you have around 4 seconds to do one of the
+following:</p>
+<ul>
+<li>Pressing the button twice. The unit will boot into test mode.</li>
+<li>Pressing the button three times. The unit will boot into an unknown
+mode (likely firmware update).</li>
+</ul>
+<p>If your action matches none of these, the unit will boot into normal
+mode.</p>
+<p>This section will employ the following notation for the status of the
+indicator LEDs.</p>
+<pre><code> PWR USB OUTPUT o o o o
+ o o MODE o o o o
+ GM2 G X
+ S G
+o=on
+-=off
+*=faint</code></pre>
+<h3 id="tocanch9" class="tvis">Test mode</h3>
+<p>The test mode is far less interesting than that of the SD-80 because
+I don’t necessarily understand what does every indicators pattern
+mean.</p>
+<div class="collapse" data-caption="SD-20 Tests">
+<pre><code> test 1 (some sort of version?)
+ PWR USB OUTPUT - - - o
+ o - MODE - - - o
+
+Mode key pressed = next
+
+ test 2 (some other sort of version? self test? serial port test? midi test?)
+ PWR USB OUTPUT - - - o
+ o o MODE - - o o
+
+Mode key pressed = next
+
+ test 3 (same as 2)
+ PWR USB OUTPUT - - - o
+ - o MODE - - - -
+
+Mode key pressed = power LED flashes once, enters next test
+
+ test 4 (LED test)
+ LEDs lights up in sequence, one by one:
+ output 1, 2, 3, 4, mode 1, 2, 3, 4 (GM2 L, GM2 R, GS, XG),
+ all lights off, power, usb
+
+Mode key pressed = next
+
+ test 5a (Sound test 1)
+ PWR USB OUTPUT - o o -
+ o - MODE - - o -
+Resets synthesizer to native mode.
+MIDI Channel 1 is set to play a sine waveform.
+Plays sine wave on both channels.
+
+Mode key pressed = next
+
+ test 5b (Sound test 2)
+ PWR USB OUTPUT o - - -
+ o - MODE - - o -
+Plays sine wave on left channel.
+
+Mode key pressed = next
+
+ test 5c (Sound test 3)
+ PWR USB OUTPUT - - - o
+ o - MODE - - o -
+Plays sine wave on right channel.
+
+Mode key pressed = next
+
+ test 5d (Effects test)
+ PWR USB OUTPUT o o o o
+ o - MODE - - - o
+Resets synthesizer to native mode.
+MIDI Channel 1 is set to play a melodic tom sound.
+Plays a tom sound with loud reverb periodically.
+
+Mode key pressed = next
+
+ test 6 (probably hardware check)
+ PWR USB OUTPUT - - o -
+ o - MODE - - - -
+
+Synthesizer resets again.
+The module no longer respond to any key presses from this point.</code></pre>
+</div>
+<h3 id="tocanch10" class="tvis">unknown (likely firmware
+update) mode</h3>
+<pre><code> PWR USB OUTPUT o o o o
+ o - MODE o o o *
+ Doesn't respond to any key presses. (long, short, multiple presses)
+ Shows up as a USB device with normal ID (0582:0027).
+ Does not function as synthesizer.</code></pre>
+<h2 id="tocanch11" class="tvis">The Conclusion</h2>
+<p>For a low, low price of $300 in 2002, you get 3 set of mediocre (with
+a few exceptions) GM2 patches. The sounds themselves are reasonably new
+and refreshing back then, but the higher average voice-per-note of the
+new StudioCanvas sounds make the SD-20 a less desirable choice than
+previous 64-polyphony models. The lack of advanced editing of any sort
+removes all possibility to explore custom sound design with the module.
+It’s a cheaply built unit that Roland asked for too much. Even for a
+Touhou music fanatic today, there are much cheaper ways to get access to
+the most sought-after instruments.</p>
+<h2 id="tocanch12" class="tvis">The … Death?</h2>
+<p>My SD-20 is in temporary coma right now, as it’s receiving a brain
+surgery …</p>
+<p>I will give updates in a separate post when it’s complete.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_wromds.jpg"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_wromds.jpg"></a> <br>I don’t know
+what I’m doing …
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/sd20_wromdmp.jpg"><img style="width: 48%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_sd20_wromdmp.jpg"></a> <br>… or do I?
+</div>
+</td>
+</tr>
+</tbody></table>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Had to paraphrase this, because Roland prohibits
+reproducing contents from their manuals…<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2022-07-23.html b/blog/post/2022-07-23.html
new file mode 100644
index 0000000..7e10b7b
--- /dev/null
+++ b/blog/post/2022-07-23.html
@@ -0,0 +1,503 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"Framework Laptop: The next thing in the laptop world?")</title>
+<meta name="description" content="«Framework Laptop: The next thing in the laptop world?» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">Framework Laptop: The next thing in the laptop world?</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/device-review/">device-review</a></li><li><a href="/blog/list/hands-on/">hands-on</a></li><li><a href="/blog/list/computer-repairing/">computer-repairing</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">Rationale for a new laptop</a></li><li><a class="toctarg" href="#tocanch1">Why Framework?</a></li><li><a class="toctarg" href="#tocanch2">Important dates</a></li><li><a class="toctarg" href="#tocanch3">Configuration ordered</a></li><li><a class="toctarg" href="#tocanch4">Unboxing and setting up</a></li><li><a class="toctarg" href="#tocanch5">Performance</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">Processing power</a></li><li><a class="toctarg" href="#tocanch7">Graphics</a></li><li><a class="toctarg" href="#tocanch8">Thermal &amp; Emissions</a></li><li><a class="toctarg" href="#tocanch9">Others</a></li></ul></li><li><a class="toctarg" href="#tocanch10">Issues</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch11">Instabilities</a></li><li><a class="toctarg" href="#tocanch12">Port interference? …</a></li><li><a class="toctarg" href="#tocanch13">… and a general lack of ports</a></li><li><a class="toctarg" href="#tocanch14">Keyboard</a></li></ul></li><li><a class="toctarg" href="#tocanch15">Customer Service</a></li><li><a class="toctarg" href="#tocanch16">Y no upgrade to 12th gen?</a></li><li><a class="toctarg" href="#tocanch17">Any buyer’s remorse?</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2021-10-10.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2022-11-27.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">Framework Laptop: The next thing in the laptop world?</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2022-07-23<br>#device-review #hands-on #computer-repairing</div>
+ <hr><div id="article" class="TText"><article>
+<p>This review came at the very least 6 months too late.</p>
+<h2 id="tocanch0" class="tvis">Rationale for a new laptop</h2>
+<p>My old trusty first gen ThinkPad X1 yoga is showing its age: its
+U-tier ultra-low voltage processor is having trouble keeping up with the
+“modern web” that is constantly putting increasing pressure on the
+browser. Its integrated GPU can barely handle Minecraft at 60 fps, not
+to mention hundreds of virtual instruments I mess with are struggling
+with the processing power of this machine which wasn’t anything to brag
+about even when it first came out. It also took a lot of beatings, which
+are mainly from my own abuse, like <a href="https://chrisoft.org/blog/post/2017-01-09.html">this one</a>
+(warning: post is in Chinese), and is nearly falling apart. Considering
+I’m not well settled in this land that is alien to me, a full fledged
+desktop is hard to justify. So a new laptop it is.</p>
+<p>Additionally, unlike their 11th gen desktop processors, Intel’s 11th
+gen ultrabook offerings looks extremely compelling due to the new Xe
+integrated graphics introduced in this generation. Its (theoretical)
+performance is finally catching up with previous generation entry-level
+gaming graphics and current generation dedicated graphics found in slim
+laptops (1050 Ti and MX 350/450). Of course this is Intel and
+theoretical performance doesn’t mean much when their driver kind of
+sucks (severe performance drops and incompatibilities in some games).
+But it’s been rock solid for daily desktop usage (and Minecraft gaming
+because that’s literally the only game I play now). So I decided I’m
+just going to roll with it.</p>
+<h2 id="tocanch1" class="tvis">Why Framework?</h2>
+<p>I’m not a fan of laptops in the desktop replacement category, even I
+often use mine as one (in terms of the workload I run on it). They are
+just too chunky for liking.</p>
+<p>Trackpoint is essential for my survival when using a laptop. Instead
+with torturing myself with a huge touchpad, I’d rather stick with an old
+ThinkPad with no touchpad.</p>
+<p>Wait, don’t these two criteria alone restrict my choice to ThinkPads
+and a few other business laptops?</p>
+<p>Well, true… but when I laid my hands on a 9th generation X1 Carbon,
+it feels so different that I wasn’t even convinced that I was
+interacting with a ThinkPad anymore: especially the new keyboard with
+further reduced travel and the trackpoint buttons with virtually no
+tactile response. I decided to extend my radar to include models that
+don’t have a trackpoint, and use an external trackpoint keyboard with it
+if I get one of such models instead. Of course I was not ruling out
+ThinkPads, I was just allowing myself to get something other than a
+ThinkPad.</p>
+<p>In Feburary 2021 I saw a few news articles about this new “Framework”
+thing popping up. I find it interesting, but the modular expansion thing
+is just a gimmick, and I had suspicion that they are trying to ride the
+hype around right to repair – not to say that is wrong. Of course the
+hardware configuration is all fine and dandy, but I’m no buying
+something with a single selling point of expansion modules (which at the
+time of writing offers nothing but ports and features found on almost
+every single laptop on the market).</p>
+<p>When further details on the laptop surfaced, it started to get
+interesting. It was suggested that motherboard of future revisions can
+act as drop-in upgrades, and that the motherboard can be easily
+transformed into a small form-factor PC. Also display and keyboard
+assembly would be available for consumers to purchase online in case a
+replacement is necessary. This immediately bring this laptop to a level
+higher in my tier list, as it was becoming apparent that they are doing
+actual work.</p>
+<p>And then just a few weeks after I got into the States, my X1 yoga
+started experiencing random system-wide freezes once again. It was a
+good excuse for a new laptop, I thought. I checked Lenovo’s website but
+found out (pretty shockingly) that there was no discount active during
+that time, and all X1s were ludicrously priced. And then I placed my
+pre-order of the Framework Laptop. (Of course I ordered the DIY edition,
+saved me a decent chunk of funds!)</p>
+<h2 id="tocanch2" class="tvis">Important dates</h2>
+<ul>
+<li>Pre-order placed: 2021-09-16, Batch 4 (I swear this is totally
+unrelated to Linus Sebastian’s Framework investment video)</li>
+<li>Remaining balance charged: 2021-10-06</li>
+<li>Shipped: 2021-10-11</li>
+<li>Received: 2021-10-13 (probably leaks my rough geological location,
+but whatever)</li>
+</ul>
+<h2 id="tocanch3" class="tvis">Configuration ordered</h2>
+<ul>
+<li>DIY edition</li>
+<li>i7-1185G7</li>
+<li>64 GB RAM (2x Crucial CT32G4SFD832A shipped)</li>
+<li>No SSD (Bring your own). 1 TB Samsung 970 Pro installed.</li>
+<li>Intel AX210 wireless</li>
+<li>ANSI keyboard (US layout)</li>
+<li>2x USB Type-A expansion modules, 4x USB Type-C expansion modules,
+and 1x HDMI expansion module</li>
+<li>With power adapter</li>
+<li>Windows 10 Professional license</li>
+<li>$2153 before tax + $230 for the SSD</li>
+</ul>
+<h2 id="tocanch4" class="tvis">Unboxing and setting up</h2>
+<p>The laptop arrived in an inconspicuous shipping box, with symbols on
+it suggesting it contains stuff that may explode. Inside is the actual
+box with intriguing designs. There was only minimal amount of paperwork
+in the package.</p>
+<p>Despite being the DIY edition, the laptop comes almost completely
+pre-assembled. There’s <a href="https://frame.work/blog/the-evolution-of-the-framework-laptop-diy-edition">a
+blog post</a> on the official website explaining why that is the case.
+For this reason putting the thing together is incredibly straight
+forward. Within minutes I got the thing up and running (while booting
+into nothing of course).</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwbox.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwbox.jpg"></a> <br>The box
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwunbox.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwunbox.jpg"></a> <br>Unboxing
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwunbox2.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwunbox2.jpg"></a> <br>The box inside the
+box
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwpaperwork.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwpaperwork.jpg"></a> <br>Paperwork
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwinternals.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwinternals.jpg"></a> <br>Internals
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwassembled.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwassembled.jpg"></a> <br>Components in
+place
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>I decided to get Windows working first, even it hasn’t been my
+primary operating system for almost a decade. I prepared the first
+release of Windows 11 on a USB stick. But of course I decided to torture
+myself by not using the official installation media (it doesn’t matter
+anyway, as after the first attempt failed I tried the official
+installation media and it also failed for some reason, see the pictures
+below). Eventually I got the dism installation procedure working.</p>
+<p>Windows, being Windows, gave me a few silly errors when I was going
+through the OOBE. The official driver package is necessary to get all
+devices working.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<p><a href="//filestorage.chrisoft.org/blog/img/fwwindowsfail1.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwwindowsfail1.jpg"></a></p>
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<p><a href="//filestorage.chrisoft.org/blog/img/fwwindowsfail2.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwwindowsfail2.jpg"></a></p>
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<p><a href="//filestorage.chrisoft.org/blog/img/fwwindowsfail3.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwwindowsfail3.jpg"></a></p>
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<p><a href="//filestorage.chrisoft.org/blog/img/fwwindowsfail4.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwwindowsfail4.jpg"></a></p>
+</div>
+</td>
+</tr>
+<tr>
+<td style="text-align:center;" colspan="2">
+1 hour of Windows failing
+</td>
+</tr>
+</tbody></table>
+<p>Next step will be my daily driving operating system. Of course it’s
+going to be Gentoo. What do you mean I’m insane?</p>
+<p>I used the Arch Linux ISO to bootstrap the installation. Now I made
+people from both distros hate me.</p>
+<p>After roughly 10 hours of CPU stress testing, a basic KDE plasma
+desktop was emerged. Not too bad for a slim laptop.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwarchtrigger.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwarchtrigger.jpg"></a> <br>Trigger
+warning
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwfirstfetch.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwfirstfetch.jpg"></a> <br>First neofetch
+</div>
+</td>
+</tr>
+</tbody></table>
+<h2 id="tocanch5" class="tvis">Performance</h2>
+<p>For a comprehensive performance review of the Framework laptop, you
+should be reading a more professional review, not this article. This
+section will focus on my personal use cases instead.</p>
+<h3 id="tocanch6" class="tvis">Processing power</h3>
+<p>My daily work, when it comes to the processing power intense parts,
+mainly involves running tests, building small-to-moderate sized
+projects, and performance profiling. Of course there is also routine
+rebuilds of huge applications due to my choice of distro. Plus some
+music mixing when I have the time for it.</p>
+<p>Thanks to the two additional cores and drastically improved clocks
+and IPC, the 11th gen i7 is more than 3 times more powerful than my old
+6th gen i7 for code compilation workloads, while having similar
+sustained power consumption under such workload (RAPL reports ~28 watts
+for both machines). As an example, Chromium 98.0.4710.4 took 883 minutes
+to emerge on my old i7, while on the Framework it took 273 minutes. The
+new processor is also able to handle music projects with over 100
+tracks, even with a decent performance headroom. In some other cases
+where the load is less than “all-cores”, it even had more than 4 times
+the performance of its older counterpart. To achieve an even better
+result the only option is to go AMD, which they hadn’t yet offer
+<a id="n1" href="#note1" class="note">[1]</a>. Overall the performance is
+a win for me.</p>
+<h3 id="tocanch7" class="tvis">Graphics</h3>
+<p>As mentioned above, the performance of the integrated Xe graphics is
+finally catching up with entry-level gaming GPUs within the last 2
+generations. While the Linux Mesa driver has been rock solid for desktop
+usage for quite some time, a lot more could be expected for gaming as
+online benchmark results show wild variations among different titles.
+Not to mention the erroneous behavior with certain aspects of legacy
+rendering APIs. Modern APIs behave a lot better in general.</p>
+<p>On real-world performance, for the first time in history, Minecraft
+with ultra shaders (BSL) can run (correctly!) on one of my laptops with
+a stable 60 fps. They wouldn’t even apply correctly on any of the older
+Intel GPUs I’ve used. With compromises, Microsoft Flight Simulator runs
+(with Valve’s Proton) at a stable-ish 30 fps with acceptable
+visuals.</p>
+<h3 id="tocanch8" class="tvis">Thermal &amp; Emissions</h3>
+<p>One word: bad.</p>
+<p>Not intolerable, but pretty bad.</p>
+<p>Maybe this is just the inescapable curse of all ultrabooks. But under
+heavy load the upper region of the keyboard is almost too hot to touch.
+To make things worse, the unibody-inspired design (where the gaps
+between keys is part of the top cover of the machine’s lower half,
+rather than part of the keyboard assembly) means the metal part that is
+between keys are at a even higher temperature. It’s not exactly
+enjoyable to type on the built-in keyboard when the processor is under
+heavy load.</p>
+<p>Under constant max load, the processor temperature maintains steadily
+at around 100 degrees Celcius. This is considerably higher than my X1
+yoga, which peaks at 95 degrees and drops to 85 degrees if the load is
+sustained.</p>
+<p>The fan noise is also way worse on the Framework. The fan curve is
+quite aggressive, ramping up rapidly when the processor temperature
+reaches 60 degrees, and maxes out at 80 degrees and beyond. The noise is
+audible even in a moderately noisy room. In contrast the fan in my X1
+ramps up much slower with more steps.</p>
+<p>Also there’s no manual undervolting on tigerlake-U platforms, likely
+as a mitigation to the plundervolt vulnerability.</p>
+<h3 id="tocanch9" class="tvis">Others</h3>
+<p>One of the last consumer MLC SSDs, Samsung 970 Pro, performs well in
+benchmarks.</p>
+<p>Keyboard is not great (see below). Trackpad is … meh. I don’t use
+that thing anyway.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwssdspeeds.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwssdspeeds.jpg"></a> <br>The best
+consumer grade PCIe 3.0 SSD in the west (asterisk)
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fwbadarrowklayout.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fwbadarrowklayout.jpg"></a> <br>Awkward
+arrow key layout
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>ACPI reports a 8-hour estimate on battery. Running on battery for 90
+minutes with light-to-moderate usage usually uses 20% of the capacity
+(screen always on, wireless on, typing with browser running in
+background), give or take, consistent with the estimation. I’ve yet to
+run the battery until it’s flat.</p>
+<p>The screen is fabulous. Way more vibrant than that LCD on my first
+generation X1 yoga. Not a professional graphic designer or in any other
+job that depends on an accurate display, so that’s just my personal
+opinion.</p>
+<p>Speaker is at least 10 times better than any ThinkPads I’ve ever
+used. Still not on par with an Apple laptop though.</p>
+<h2 id="tocanch10" class="tvis">Issues</h2>
+<h3 id="tocanch11" class="tvis">Instabilities</h3>
+<p>The system sometimes goes into a complete lockup, unresponsive to any
+inputs (except a forceful power off), when it has been left idle for an
+extended period. This never happens if the system is loaded. I could not
+obtain any useful diagnostics.</p>
+<p>With the release of BIOS version 3.09, which claims to resolve an
+“issue where the system will sometimes abnormally shutdown
+unexpectedly”, hopefully this such freezes will be gone. However I
+haven’t been running 3.09/3.10 for long enough to come to such
+conclusion.</p>
+<h3 id="tocanch12" class="tvis">Port interference? …</h3>
+<p>My ThinkPad wireless mouse suffers from stuttery movement when used
+on the Framework laptop. I’ve never had similar issues with this mouse
+before. This affects both operating systems installed. It doesn’t happen
+all the time, the chance of it happening is higher when the system is
+more heavily loaded.</p>
+<p>Occasionally, the ports on the right side stop working altogether,
+and the kernel message gets flooded with output like this:</p>
+<pre><code>[75512.894957] usb usb2-port2: Cannot enable. Maybe the USB cable is bad?
+[75517.158969] usb usb2-port2: Cannot enable. Maybe the USB cable is bad?
+[75521.422973] usb usb2-port2: Cannot enable. Maybe the USB cable is bad?
+[75525.686857] usb usb2-port2: Cannot enable. Maybe the USB cable is bad?
+[75529.950973] usb usb2-port2: Cannot enable. Maybe the USB cable is bad?</code></pre>
+<p>On Windows, a notification “USB Device not recognized” is repeatedly
+displayed.</p>
+<p><a href="https://knowledgebase.frame.work/en_us/one-port-on-my-laptop-does-not-function-correctly-r1mqMnTet">This
+knowledge base article</a> is not relevant to my particular case, as my
+unit doesn’t have the problematic EMI shield.</p>
+<p>However I’ve noticed that this issue hasn’t reoccurred for a while.
+Perhaps It could be a BIOS issue that has been patched since.</p>
+<h3 id="tocanch13" class="tvis">… and a general lack of ports</h3>
+<p>But this one can’t be resolved by a BIOS patch. With the laptop
+plugged in, I have a whopping 3 USB ports for USB peripherals. It
+reduces to 2 when I use it with the trackpoint keyboard (which is pretty
+much all the time as I need a trackpoint to survive). This is nowhere
+close to enough – considering my old X1 also has 3 USB ports, not to
+mention it has dedicated ports for two external monitors.</p>
+<p>This is why I maintain my opinion that the expansion modules are
+currently a gimmick. There are no expansion cards that are unique enough
+to justify them – no WWAN card, no full size SD card reader, nor even an
+ethernet port (until very recently). Full size DisplayPort and storage
+expansion are cool, but they take up precious USB ports which means for
+my use case a dock is mandatory anyway if one of those cards is
+installed, nullifying the point of using these cards. I personally would
+favor a design with more fixed ports (which is already the case for the
+audio jack on the Framework), maybe 3 fixed USB Type-C ports on the left
+and 2 expansion card slots on the right. More useful expansion cards
+could also be a solution, like a mini hub with two USB Type-C ports.
+Even a proprietary port for connecting expansion cards to the computer
+(like two sets of USB 4 signals in a single port) is acceptable for me,
+to allow simpler designs of some dual function cards (e.g. storage card
+with a USB port); as these on board connectors aren’t meant to be used
+directly, users are always expected to plug an expansion card into
+them.</p>
+<h3 id="tocanch14" class="tvis">Keyboard</h3>
+<p>Like many people coming from a ThinkPad with 1.8 mm key travel, I
+find the keyboard of the Framework laptop lacking in tactile response.
+Even when compared to the keyboard on a 9th gen X1 Carbon which has the
+same 1.5 mm travel, Framework’s keyboard still loses by quite a large
+margin. Also the keyboard features the rather bad (in my opinion) layout
+of arrow keys.</p>
+<p>This is not to say the built-in keyboard is completely unusable as
+such. But I do still prefer using a ThinkPad keyboard, whenever it’s
+available to me.</p>
+<h2 id="tocanch15" class="tvis">Customer Service</h2>
+<p>This is where Framework really shines as a new player in the world of
+laptop manufacturers. I wouldn’t expect to get in touch directly with
+someone on their hardware team by simply reporting a firmware issue.</p>
+<p>So I decided to try out the latest development version of memtest86+.
+I built it myself, however it booted on all my machines but the
+Framework laptop. I reported the issue to memtest86+ developers, and
+came to the conclusion that it has something to do with the firmware. So
+I contacted support, and linked the github issue in the support request.
+The support team wrote back pretty fast (within 24 hours), and to my
+surprise, agreed to connect me with the hardware team directly. After a
+few back and forth between the hardware team and memtest86+ developers,
+it was determined that the cause is 8254 timer gating. Later I heard
+back from the person on the hardware team that the relevant setting will
+be added in BIOS version 3.09, which was released a few days ago. I
+installed the update and set 8254 timer gating to disabled, and
+memtest86+ worked as expected.</p>
+<p>That was my only, yet pretty bizarre experience of Framework’s
+customer service. I don’t think there could be any chance ever that I
+could get in touch with someone on the hardware team of any prominent
+laptop brands, but Framework can do it. Kudos to the Framework support
+team, and I hope they would be able to maintain this level of customer
+service when they get bigger.</p>
+<p>The full issue report on github is <a href="https://github.com/memtest86plus/memtest86plus/issues/40">here</a>.</p>
+<h2 id="tocanch16" class="tvis">Y no upgrade to 12th gen?</h2>
+<p>Intel’s 12th gen processors are winning grounds on the desktop front,
+but in the mobile sector they don’t look so hot. I’ve seen people with
+their shiny new 10th gen X1 Carbon complaining about poor battery life
+and even worse thermal performances. Also in order to upgrade without
+letting the original motherboard fall into disuse, I would either buy
+new RAM and SSD for it, or sell it somehow. Either option is hard to
+justify for me. That’s why I decided against upgrading for now. I may
+consider upgrading to 13th gen whenever that gets released.</p>
+<h2 id="tocanch17" class="tvis">Any buyer’s remorse?</h2>
+<p>Hate to break it for you, but I’m still not daily driving my
+Framework laptop – in fact, I’m typing this sentence on my old X1.</p>
+<p>But there’s no buyer’s remorse in general. Not being a daily driver
+doesn’t mean it has fallen out of favor. Instead, there are now clear
+roles assigned to these two laptops. I’ve moved all my music production
+setup and games to the Framework laptop. It also functions as a build
+server now (both for binary Gentoo packages, and as a networked build
+server). The X1 only functions as a typewriter and web browser
+nowadays.</p>
+<p>All current issues I had with this machine have either been resolved,
+or have existing workarounds. There is no trackpoint, no WWAN, no touch
+screen or digitizer, or connecting to 3 USB devices and an external
+monitor while charging compared to my old X1 – this is not a ThinkPad
+after all. But it does have third party board level repair with support
+from the company itself (they have started to provide full schematics to
+third party repair shops under NDA), easy access to parts, open source
+firmware, upgradable platform, and promise of a coreboot BIOS. These are
+the reasons I chose to support Framework as a company. So let my first
+purchase be a small contribution to them.</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: and I’m not going to choose even if there is one, due to
+previous traumatic experience I had with AMD platforms. Unreasonable I
+know, but it’s hard to overcome.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2022-11-27.html b/blog/post/2022-11-27.html
new file mode 100644
index 0000000..e22f3d8
--- /dev/null
+++ b/blog/post/2022-11-27.html
@@ -0,0 +1,661 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"(Not really) Musical Answers &amp; Rants")</title>
+<meta name="description" content="«(Not really) Musical Answers &amp; Rants» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+<style>
+details {
+ border: 1px solid #888;
+ border-radius: 4px;
+ margin: .5em .5em 0;
+ padding: .5em;
+}
+</style></head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">(Not really) Musical Answers &amp; Rants</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/music/">music</a></li><li><a href="/blog/list/midi/">midi</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">Backgrounds</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch1">Do you play any instruments?</a></li><li><a class="toctarg" href="#tocanch2">How good are you at them?</a></li><li><a class="toctarg" href="#tocanch3">Any knowledge in musical
+theory?</a></li><li><a class="toctarg" href="#tocanch4">Anything else interesting?</a></li></ul></li><li><a class="toctarg" href="#tocanch5">Backgrounds, Computer Music</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch6">How did you get into
+computer music?</a></li><li><a class="toctarg" href="#tocanch7">Any formal training on this
+stuff?</a></li><li><a class="toctarg" href="#tocanch8">How long have you been doing
+this?</a></li><li><a class="toctarg" href="#tocanch9">What
+specific skills do you have in computer music?</a></li><li><a class="toctarg" href="#tocanch10">What computer
+music projects have you worked on?</a></li><li><a class="toctarg" href="#tocanch11">Is any of this fun?</a></li><li><a class="toctarg" href="#tocanch12">How do you find joy in any
+of this?</a></li></ul></li><li><a class="toctarg" href="#tocanch13">Personal Preference</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch14">Favorite genre(s)?</a></li><li><a class="toctarg" href="#tocanch15">Favorite hardware
+synth in your collection?</a></li><li><a class="toctarg" href="#tocanch16">Favorite production software?</a></li><li><a class="toctarg" href="#tocanch17">Is it “GIF” or “JIF”?</a></li><li><a class="toctarg" href="#tocanch18">Genres that you listen to
+most often?</a></li></ul></li><li><a class="toctarg" href="#tocanch19">Touhou Music</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch20">The
+f**k is going on with your obsession with Touhou Music?</a></li><li><a class="toctarg" href="#tocanch21">Why don’t
+you transcribe something new from him then?</a></li></ul></li><li><a class="toctarg" href="#tocanch22">Production</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch23">Do you earn money from
+your production?</a></li><li><a class="toctarg" href="#tocanch24">So why even bother?</a></li><li><a class="toctarg" href="#tocanch25">Why
+are most of your stuff remixes? Why not more originals?</a></li><li><a class="toctarg" href="#tocanch26">Ever considered
+doing Touhou-style originals?</a></li><li><a class="toctarg" href="#tocanch27">Commission? Collabs?</a></li><li><a class="toctarg" href="#tocanch28">Production Gear?</a></li><li><a class="toctarg" href="#tocanch29">Why
+stick to hardware synths when software synths nowadays are so
+powerful?</a></li><li><a class="toctarg" href="#tocanch30">Since you don’t
+earn money from you production, …</a></li><li><a class="toctarg" href="#tocanch31">Can I use your music for X?</a></li></ul></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2022-07-23.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2023-11-13.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">(Not really) Musical Answers &amp; Rants</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2022-11-27<br>#music #midi</div>
+ <hr><div id="article" class="TText">
+<article>
+<p>I’ve got this <a href="https://chrisoft.org/libs/music/player">pretty
+large music collection</a> on my website and sometimes I get people
+asking why is it there. This post serves as an FAQ for all those
+questions that I can remember, plus some bonus rant.</p>
+<p>This post may be updated regularly to reflect any changes that might
+happen.</p>
+<h2 id="tocanch0" class="tvis">Backgrounds</h2>
+<h3 id="tocanch1" class="tvis">Do you play any instruments?</h3>
+<p>I use to play keyboard instruments, specifically arranger keyboard
+for 4 years, and the piano for 6 years. I started when I was 7.</p>
+<h3 id="tocanch2" class="tvis">How good are you at them?</h3>
+<p>I’ve got certifications from the CMA (China Musicians Association)
+for amateur musicians (colloquially, they are referred to as “考级” in
+China), level 5 for arranger keyboard, and level 9 for the piano
+<a id="n1" href="#note1" class="note">[1]</a>.</p>
+<p>Do note the wording I used in the answer to the previous question:
+“use to”. I haven’t practiced seriously for quite some time (5 years at
+least).</p>
+<p>I never spent a lot of time practicing, even I was actively learning
+to play. Longest uninterrupted practice session I had was probably 4
+hours (one tenth of Lingling’s typical practice session, ugh
+<a id="n2" href="#note2" class="note">[2]</a>). Clearly I was more into
+messing with computers back then (still very much the case right
+now).</p>
+<h3 id="tocanch3" class="tvis">Any knowledge in musical
+theory?</h3>
+<p>The only “formal” lesson I had on musical theory was given by my
+piano teacher, which didn’t touch on any of the advanced topics – just
+basic intervals, chords, and progression stuff.</p>
+<p>I’ve read books on music theory, namely</p>
+<ul>
+<li>“Introduction to Basic Music Theory” (probably the most widely used
+book on this topic in China, original title 《基本乐理通用教材》,
+authored by Li Chongguang (李重光). English title is my own
+translation and I have no idea what the official translation is.)</li>
+<li>“Music Theory for Computer Musicians”, Michael Hewitt</li>
+<li>“Composition for Computer Musicians”, Michael Hewitt</li>
+<li>“The Complete Idiots Guide to Music Theory”, Michael Miller (didn’t
+finish reading)</li>
+</ul>
+<p>But I can’t say I remembered a single thing from them.</p>
+<p>I also know a few things on acoustics and computing stuff related to
+music. See the “Backgrounds, computer music” section for more on
+this.</p>
+<h3 id="tocanch4" class="tvis">Anything else interesting?</h3>
+<p>I’m quite convinced that I have (at least partial) perfect pitch.</p>
+<p>Certain part inside my head reacts very strongly to notes of some
+pitches (A and C are the most notable ones, E, G, and for some reason F#
+are also up there). I can also sing any given notes on the chromatic
+scale pretty accurately.</p>
+<p>However, since I don’t react to all notes equally, and I’m quite sure
+“partial perfect pitch” is not really a thing, I don’t know what
+condition I <em>really</em> have. But if your instrument is out of tune
+(even if the whole thing is tuned consistently), I’ll be really
+upset.</p>
+<h2 id="tocanch5" class="tvis">Backgrounds, Computer Music</h2>
+<h3 id="tocanch6" class="tvis">How did you get into
+computer music?</h3>
+<p>‘Twas a typical calm day when I was browsing around in the System32
+folder (yes I was a fulltime Windows user once upon a time). I found a
+file named “town.mid” in the Media folder, and it looked like a music
+file to me. “How could a music file be like 20KB in size?” I wondered. I
+thought it would sound like crap (low bit-rate type of crappiness, not
+MSGS-type of crappiness), but I listened to it and turned out that
+wasn’t the case. Later that day I sent the file to my parents’ cell
+phones, and to my surprise they all sounded quite different, despite all
+the devices were playing the same melody. I was deeply intrigued by this
+format, and that planted a seed in my heart.</p>
+<p>I searched the 2000s web for information on this format,
+unfortunately being a noob as I was back then, I was only able to find
+out it was a format called “MIDI”, but not any application that’s
+capable of reading or producing them. I had to set it aside.</p>
+<p>A few years later, in early 2009, when I was randomly going through
+tech magazine my parents had piled up at home, I found a software
+catalogue from the 90s. One title in the ToC read “Make your music
+production dreams come true – Cakewalk Music Software”. It didn’t quite
+caught my attention just yet, but when I got to the content, they
+mentioned its MIDI capabilities. I realized this could be the thing I’m
+looking for. And very fortunately for me, the CD that came with the
+catalogue included a trail version of Cakewalk Pro Audio 5.0. There
+began my journey.</p>
+<p>But wait, there was, in fact, a second path to this. There was a
+video (<a href="https://www.youtube.com/watch?v=dsU3B0W3TMs">Music using
+ONLY sounds from Windows XP and 98!</a>) that went viral in China in
+2009. The look of the software shown in the video got my attention, and
+that brought me into the world of tracker modules (and later
+demoscenes).</p>
+<p>There was also the whole “black midi” shenanigans that I got myself
+into. However I think that should be considered “deep lore” and not
+really appropriate to mention here. So let’s just leave this section as
+is.</p>
+<h3 id="tocanch7" class="tvis">Any formal training on this
+stuff?</h3>
+<p>Nope. I taught myself everything, just like most other stuff I know
+in computing. One major difference is that I didn’t receive any formal
+training after I’ve taught myself this topic, unlike some other topics
+in computer science. The thing is it’s quite difficult to enroll courses
+from the music department while I’m in a frankly completely unrelated
+major.</p>
+<h3 id="tocanch8" class="tvis">How long have you been doing
+this?</h3>
+<p>I’ve been messing with MIDI since 2009, doing transcription since
+2011. However until 2014 I didn’t bother learning any DAWs with virtual
+instruments support (I was only using Cakewalk Pro Audio 9.0 and a
+certain Japanese application called 音楽ツクールDX back then). For this
+reason everything I made until 2014 was just a bunch of MIDI files. I’ve
+been collecting (mostly pirated) software synths since then. However
+since 2017 I started replacing pirated software I used in production,
+and nowadays I’m only using software and sound libraries the I have
+legal rights to use in production, except the Unobtainium legacy
+products.</p>
+<p>I started programming music-related stuff in 2010, it was a random
+silly sequencer for PC speaker. And I’ve been doing it ever since.</p>
+<h3 id="tocanch9" class="tvis">What
+specific skills do you have in computer music?</h3>
+<p>(This list includes both music production related stuff and
+programming stuff)</p>
+<ul>
+<li>Using a DAW (mostly Cakewalk of course)</li>
+<li>Make random patches for synthesizers</li>
+<li>Basic mixing and mastering</li>
+<li>MIDI and tracker module data processing (I/O, data extraction)</li>
+<li>Basic DSP knowledge, computer assisted music production</li>
+<li>High-level interfacing with musical hardware</li>
+</ul>
+<h3 id="tocanch10" class="tvis">What computer
+music projects have you worked on?</h3>
+<p>(This list also includes both music production related stuff and
+programming stuff)</p>
+<ul>
+<li>Production: see <a href="https://chrisoft.org/libs/music/player">Music Library</a></li>
+<li>Experimental GPU-powered virtual-analog synth (private project):
+CUDA only, pretty basic function wise, nothing special really.</li>
+<li><a href="https://cgit.chrisoft.org/QMidiPlayer.git/">QMidiPlayer</a>: A
+feature-rick MIDI player.</li>
+<li>Modsearch (private project): Module indexing and searching
+tool.</li>
+<li><a href="https://cgit.chrisoft.org/fifteen-thieves.git/">Fifteen
+Thieves</a>: Tools for interfacing with Roland synthesizers.</li>
+</ul>
+<h3 id="tocanch11" class="tvis">Is any of this fun?</h3>
+<p>Yes.</p>
+<h3 id="tocanch12" class="tvis">How do you find joy in any
+of this?</h3>
+<p>I don’t know.</p>
+<h2 id="tocanch13" class="tvis">Personal Preference</h2>
+<h3 id="tocanch14" class="tvis">Favorite genre(s)?</h3>
+<p>Nothing specific really. However I can tell you about the genre I
+loath the most: it’s … (drum rolls) … rap.</p>
+<p>The thing that I dislike about rap is its excessive use of autotune
+and highly repetitive trap-style drum patterns. I actually kind of
+admire some rapper’s skillful rapping, but spoken words don’t really
+count as music do they?</p>
+<h3 id="tocanch15" class="tvis">Favorite hardware
+synth in your collection?</h3>
+<p>Again, nothing specific really. But I do know it’s not the Yamaha.
+It’s never the Yamaha.</p>
+<h3 id="tocanch16" class="tvis">Favorite production software?</h3>
+<p>Considering I’ve pretty much used nothing but Cakewalk products, I
+can give you an actual answer to this one – Cakewalk of course.</p>
+<p>I do also find OpenMPT interesting, however I haven’t made anything
+with it really.</p>
+<p>Funny trivia: when Gibson announced they were ceasing all development
+of Cakewalk products, I wrote <a href="https://chrisoft.org/blog/post/2017-11-25.html">this rant</a>.
+Soon after that rant was posted, a couple of vendors annouced discounted
+pricing for former SONAR users, one of which was Steinberg (their
+so-called “competitive crossgrade”). So I got my copy of Cubase 9 Pro at
+50% off (but they did not provide an e-licenser with the purchase, which
+was still bundled with a normal purchase back then, which was frankly
+dumb). But … before I could get used to the workflow of Cubase, Cakewalk
+was resurrected by Bandlab.</p>
+<h3 id="tocanch17" class="tvis">Is it “GIF” or “JIF”?</h3>
+<p>Of course it’s “Graphics Interchange Format”! Wait, why is this
+here…</p>
+<h3 id="tocanch18" class="tvis">Genres that you listen to
+most often?</h3>
+<p>Okay you got me. I’ll just warn you that the list could be quite
+shocking to some people…</p>
+<p>Recent notable trend for me is folk music. The rest includes
+classical, heavy metal, and ambient music. Also sometimes I randomly
+browse through various module hosting websites where the vast majority
+of the uploads are just pure turds, but occasionally I come across
+hidden gems in those giant turd piles.</p>
+<p>Also don’t forget about the dreaded: Touhou music…</p>
+<h2 id="tocanch19" class="tvis">Touhou Music</h2>
+<h3 id="tocanch20" class="tvis">The
+f**k is going on with your obsession with Touhou Music?</h3>
+<p>… literally 18 of 21 tabs in your music library contain only Touhou
+Music!</p>
+<p>Well, this has to start with how I got myself into the thing known as
+“Touhou Project”. (There should’ve been an entire post written on this,
+but I’m too lazy, so let me just recap here.)</p>
+<p>A friend of mine was playing <em>Imperishable Night</em> one day in
+2009. I sat there and watched him play for a while. He paused the game
+and asked, “Interested?”, to which I replied “eh…” (Do note that I’ve
+never been interested in Japanese anime or manga before, or since, for
+that matter. But I did play similar shoot-’em-up before.) He offered me
+a copy anyway. Not really interested in the game itself, I just left it
+sitting in my hard drive for quite a while.</p>
+<p>Nothing really happened until some day in 2010 when I was sorting
+through files on my disk. I found the game and noted that the biggest
+file inside is called <code>thbgm.dat</code>. “Must have a lot of
+tracks,” I thought. And I went ahead and chose the most logical next
+step – not to play the game (because I did notice the game itself was
+quite intense when I watched my friend play), but to find some Touhou
+track player and listen to the music. Any my first impression was
+something like “holy f****** sh** this is horrible”, which was
+reasonable now that I thought about it, considering ZUN’s “unique” style
+(which I’ll touch on later) and his unsalvageable mixing in those early
+works.</p>
+<p>After that I just occasionally opened up the player, listened to
+random tracks and ended up quickly closing it off. Unbeknownst to me,
+ZUN’s “magic” worked on me and finally in 2012 I decided to play the
+game. Unfortunately I made another critical error to play his very first
+release on Windows instead (<em>Embodiment of Scarlet Devil</em>)
+because I had the stupid assumption that the first one could be
+easier.</p>
+<p>Of course I couldn’t be more wrong about that assumption. It took me
+over a year of playing off and on to clear normal difficulty, during
+which I listened to the tracks hundreds of times. And my comment on the
+music of that release was “interesting ideas but somehow made to sound
+‘thit’ (a blend of thick and sh*t, probably because I realized he had
+overdone the effects)“.</p>
+<p>Being an ultra nerd myself, I extracted the game files and found the
+MIDI files inside. And that’s where everything went downhill.</p>
+<p>The magical aspect of ZUN’s music is that it probably sounds quite
+twisted and weird on first listen. However after a few loops the charm
+in the track becomes apparent. Certain easily memorizable riffs could
+also played a part. But I did notice that the most highly acclaimed
+tracks from him (e.g.&nbsp;上海紅茶館 ~ Chinese Tea and 神々が恋した幻想郷)
+usually have less of the twisted part, or none at all.</p>
+<h3 id="tocanch21" class="tvis">Why don’t
+you transcribe something new from him then?</h3>
+<p>Nice observation. I haven’t transcribed anything beyond <em>Wily
+Beast and Weakest Creature</em> because I found ZUN’s magic has stopped
+working on me – I have listened to the tracks enough times that should
+have already worked if it’s some earlier works of him, but up till now I
+find most of the newer tracks just plain weird and uninteresting. (There
+are a couple of ones that clears my bar, but that makes it like the
+modarchive situation – picking out the gems in a pile of turds. And if I
+have to go through the turds, I’d rather look for gems from a more
+diverse set of composers).</p>
+<p>It’s not just me either – I’ve heard from other people who commented
+that ZUN’s composition went downhill since <em>Hidden Star in Four
+Seasons</em>. I have to agree with them.</p>
+<h2 id="tocanch22" class="tvis">Production</h2>
+<h3 id="tocanch23" class="tvis">Do you earn money from
+your production?</h3>
+<p>No.&nbsp;I’ve earned a grand total of $0/¥0 from my production so far. But
+I did earn a few complimentary remarks (either genuine or satirical, I
+don’t know) from my friends.</p>
+<h3 id="tocanch24" class="tvis">So why even bother?</h3>
+<p>It’s fun. I’ve explained it in a previous question (not really). But
+I find the process therapeutic and I really enjoy tweaking the knobs (no
+pun intended I swear).</p>
+<h3 id="tocanch25" class="tvis">Why
+are most of your stuff remixes? Why not more originals?</h3>
+<p>Because remixes are much lower effort, and no creativity
+required.</p>
+<p>I’m not the type of person oozing creativity. I don’t even think the
+vast majority of my stuff should be called “remix” (despite I do name
+the files that way) – I refer to them as “reinstrumentation” privately –
+no changes to the music itself whatsoever, only with different mixing
+and instruments.</p>
+<p>When I do create originals, I want to be serious about it. I don’t
+want them to sound crappy of course (just like most other people I’d
+imagine). However it’s fairly hard for me to get inspired. The most
+frequent way I get inspired is a random riff just gotten stuck in my
+head for a while, usually after a solid 10 hours of rest or a shower.
+Unfortunately for me, there are two things that prevent me from
+transforming these ideas into productions: <strong>a)</strong> The only
+keyboard that I have right now is a 32-key controller that had to be
+stowed in a drawer due to space constraints, and I’m usually too lazy to
+bust it out. Attempts of concretizing the ideas to handwritten notations
+mostly failed miserably. So for now the only way for me to solidify an
+idea is to let it stuck in there for long enough that I can memorize it.
+<strong>b)</strong> Recently I’ve discovered a tendency that melodies
+that get stuck in my head could just be me regurgitating stuff that I’ve
+listened to but could not name (the most recent example is an “original”
+I did a year ago called “Spoolka” which turns out to be just a rendition
+of Säkkijärven polkka). For these reasons I’m currently refraining from
+doing OCs unless I’m absolutely sure it’s really an original.</p>
+<p>However there are indeed a few unfinished originals sitting in my
+hard disk, snubbed to death…</p>
+<h3 id="tocanch26" class="tvis">Ever considered
+doing Touhou-style originals?</h3>
+<p>No, not really. There are already plenty of creative people in this
+space.</p>
+<p>In fact I did make attempts to create Touhou-style originals quite a
+while ago, but the results were deemed “too formulaic and mediocre” by
+myself and never got released.</p>
+<h3 id="tocanch27" class="tvis">Commission? Collabs?</h3>
+<p>Commission? No.&nbsp;I won’t further burden myself with obligated content
+creation.</p>
+<p>Collabs? Maybe. Although I’m not sure who’s ever willing to do it
+with me – but I’m pretty damn sure there will not be any Touhou-style
+collab from me any time soon.</p>
+<p>I’d be happy to write music-related code for you though. Contact me
+if you think I can do something for you in that regard.</p>
+<h3 id="tocanch28" class="tvis">Production Gear?</h3>
+<p>Current main production computer:</p>
+<ul>
+<li>Framework Laptop</li>
+<li>First generation, 4th batch</li>
+<li>i7-1185G7</li>
+<li>64 GB DDR4-3200 RAM</li>
+<li>1 TB SSD</li>
+</ul>
+<p>(Click on the following categories to expand them)</p>
+<details>
+<summary>
+Production software
+</summary>
+<ul>
+<li>Cakewalk by Bandlab</li>
+<li>Cubase Pro 12</li>
+<li>SONAR Platinum</li>
+<li>Cakewalk Pro Audio 9.0</li>
+<li>OpenMPT</li>
+</ul>
+</details>
+<details>
+<summary>
+Audio Interfaces
+</summary>
+<ul>
+<li>Focusrite Scarlett Solo 2nd Generation</li>
+<li>Terratec Aureon 7.1 USB</li>
+<li>Edirol UA-25</li>
+<li>Roland UA-101 * 2 (one Edirol-branded, one Cakewalk-branded)</li>
+<li>Edirol SD-90</li>
+</ul>
+</details>
+<details>
+<summary>
+Hardware synths
+</summary>
+<ul>
+<li>Edirol SD-80</li>
+<li>Edirol SD-20</li>
+<li>Roland XV-5080
+<ul>
+<li>SR-JV80-17 “Country Collection”</li>
+<li>SR-JV80-09 “Session”</li>
+<li>SR-JV80-08 “Keyboards of ’60s &amp; ’70s”</li>
+<li>SR-JV80-07 “Super Sound Set”</li>
+<li>SRX-09 “World Collection”</li>
+<li>SRX-07 “Ultimate Keys”</li>
+<li>SRX-06 “Complete Orchestra”</li>
+<li>SRX-03 “Studio SRX”</li>
+</ul></li>
+<li>Roland Fantom-XR
+<ul>
+<li>SRX-08 “Platinum Trax”</li>
+<li>SRX-07 “Ultimate Keys” (Yes I have two physical SRX-07 boards)</li>
+<li>SRX-05 “Supreme Dance”</li>
+<li>SRX-04 “Symphonique Strings”</li>
+<li>SRX-02 “Concert Piano”</li>
+<li>SRX-01 “Dynamic Drum Kits”</li>
+</ul></li>
+<li>Edirol SD-90</li>
+<li>Roland SC-8850</li>
+<li>Yamaha Motif Rack ES
+<ul>
+<li>PLG-150 DX “Advanced DX/TX Plug-in Board”</li>
+</ul></li>
+</ul>
+</details>
+<details>
+<summary>
+Keyboards / Controllers
+</summary>
+<ul>
+<li>Yamaha PSR-275</li>
+<li>Edirol PCR-300</li>
+</ul>
+</details>
+<details>
+<summary>
+Software synths
+</summary>
+<ul>
+<li>Steinberg Absolute 5
+<ul>
+<li>HALion 6</li>
+<li>HALion Sonic 3
+<ul>
+<li>Skylab</li>
+<li>Anima</li>
+<li>Voltage</li>
+<li>Auron</li>
+<li>Triebwerk</li>
+<li>Hypnotic Dance</li>
+<li>Trium</li>
+<li>HALiotron</li>
+<li>Hot Brass</li>
+<li>Model C</li>
+<li>Eagle</li>
+<li>Raven</li>
+<li>Amped Elektra</li>
+<li>World Percussion</li>
+<li>B-Box</li>
+<li>Electric Bass</li>
+<li>World Instruments</li>
+<li>Dark Planet</li>
+<li>Studio Strings</li>
+<li>HALion Symphonic Orchestra</li>
+<li>Olympus Choir Micro</li>
+</ul></li>
+<li>Groove Agent 5
+<ul>
+<li>Future Past Perfect</li>
+<li>Prime Cuts</li>
+<li>Rock Essentials</li>
+</ul></li>
+<li>Backbone</li>
+<li>The Grand 3</li>
+<li>Retrologue 2
+<ul>
+<li>Sounds of Soul</li>
+</ul></li>
+<li>Padshop 2
+<ul>
+<li>Polarities</li>
+<li>Granular Guitars</li>
+</ul></li>
+</ul></li>
+<li>HALion Expansions
+<ul>
+<li>4Knob PopD</li>
+<li>Iconica Opus</li>
+<li>Cinematique Instruments Lute</li>
+<li>Realsamples German Harpsichord 1738</li>
+<li>e-instruments Vibrant</li>
+<li>Cinematique Instruments Alto Glockenspiel</li>
+<li>Olympus Choir Elements</li>
+</ul></li>
+<li>Groove Agent Expansions
+<ul>
+<li>ElekDrums</li>
+</ul></li>
+<li>Trilian</li>
+<li>Omnisphere 2</li>
+<li>Roland Cloud
+<ul>
+<li>TR-909</li>
+<li>XV-5080</li>
+<li>SRX World</li>
+<li>SRX Studio</li>
+<li>Zenology</li>
+<li>SoundCanvas VA</li>
+</ul></li>
+<li>Groove Agent 2</li>
+<li>Groove Agent ONE</li>
+<li>HALion 3</li>
+<li>LM4 Mark II</li>
+<li>Edirol Super Quartet</li>
+<li>Edirol Orchestral</li>
+<li>Addictive Drums 2</li>
+<li>Addictive Keys</li>
+<li>EZDrummer 3
+<ul>
+<li>Pop/Rock EZX</li>
+<li>Electronic EZX</li>
+</ul></li>
+<li>Kontakt 5
+<ul>
+<li>Vir Electri6ity</li>
+</ul></li>
+<li>Music Lab Real Guitar</li>
+<li>Music Lab Real LPC</li>
+<li>Music Lab Real Strat</li>
+<li>Virtual Guitarist</li>
+<li>Virtual Guitarist Electric Edition</li>
+<li>Z3TA+</li>
+<li>Z3TA+ 2</li>
+<li>DropZone</li>
+<li>SFZ</li>
+<li>True Piano</li>
+<li>Square I</li>
+<li>Triangle II</li>
+<li>Pentagon I</li>
+<li>Ultra Analog Session 2</li>
+<li>Lounge Lizard Session</li>
+<li>Session Drummer 2</li>
+<li>Session Drummer 3</li>
+<li>Strum Acoustic Session</li>
+<li>SI Studio Instruments</li>
+<li>P5antom / Roland GrooveSynth</li>
+<li>Roland TTS-1</li>
+</ul>
+</details>
+<div style="text-align:center;max-width:90%;">
+<a href="//filestorage.chrisoft.org/blog/img/rack_220924.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_rack_220924.jpg"></a> <br>My synth rack
+as of September 2022
+</div>
+<h3 id="tocanch29" class="tvis">Why
+stick to hardware synths when software synths nowadays are so
+powerful?</h3>
+<p>There are pros and cons to this.</p>
+<p>Pros:</p>
+<ul>
+<li>Unique architecture allows for exclusive sounds and sound shaping
+techniques</li>
+<li>Unique sound libraries that are not found elsewhere</li>
+<li>While software recreations of certain hardware synths are decently
+accurate, authenticity is still often sacrificed</li>
+<li>Offload sound generation from the production computer</li>
+</ul>
+<p>Cons:</p>
+<ul>
+<li>Sometimes recording hardware synths can be a pain in the a**</li>
+<li>They often have seemingly arbitrary limitations on the synth engine
+that are no longer an issue for modern software synths</li>
+<li>Aging hardware synth can become a liability, or even fire hazard
+<a id="n3" href="#note3" class="note">[3]</a></li>
+</ul>
+<p>Of course there’s the sunk costs fallacy – why stop using them since
+the money is already spent?</p>
+<h3 id="tocanch30" class="tvis">Since you don’t
+earn money from you production, …</h3>
+<p>where’s the money that fuels your gear addiction from?</p>
+<p>I have a decently stable income that covers all my daily expenses,
+plus some extra that can go straight into buying more crap.</p>
+<h3 id="tocanch31" class="tvis">Can I use your music for X?</h3>
+<p>Maybe.</p>
+<ul>
+<li>Unless otherwise noted, everything in the “Original” folder are
+released under the <a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode">CC BY-SA
+4.0 license</a>. MIDI data and project files will be available on
+request.</li>
+<li>Unless otherwise noted, everything else in my music library are
+released under the same terms as their originals. This means:
+<ul>
+<li>For my remixes of original Touhou sound tracks, you can use them in
+accordance to the <a href="https://touhou-project.news/guideline/">Touhou Project guidelines
+on derivative works</a>.</li>
+<li>For other works, it is suggested to refer to their original license
+(would be inside its notes if there is one), or contact their original
+author before using them.</li>
+</ul></li>
+</ul>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: The max level one can obtain is level 10 for both
+instruments<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: TwoSetViolin reference<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: <a href="https://forums.rolandclan.com/viewtopic.php?t=56539">cough
+cough</a>, Roland SR-JV80 boards, <a href="https://gearspace.com/board/electronic-music-instruments-and-electronic-music-production/1112520-exploding-jv2080-expansion-card.html">cough
+cough</a><br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2023-11-13.html b/blog/post/2023-11-13.html
new file mode 100644
index 0000000..313d0aa
--- /dev/null
+++ b/blog/post/2023-11-13.html
@@ -0,0 +1,471 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"Framework Laptop: Repasting &amp; Two Year Report")</title>
+<meta name="description" content="«Framework Laptop: Repasting &amp; Two Year Report» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">Framework Laptop: Repasting &amp; Two Year Report</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/device-review/">device-review</a></li><li><a href="/blog/list/computer-repairing/">computer-repairing</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">“Repasting” with PTM 7950</a></li><li><a class="toctarg" href="#tocanch1">Semi-long term review</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch2">Disassembly reveals …</a></li><li><a class="toctarg" href="#tocanch3">Other early adopter issues</a></li><li><a class="toctarg" href="#tocanch4">How well did it hold up?</a></li><li><a class="toctarg" href="#tocanch5">Random rants</a></li></ul></li><li><a class="toctarg" href="#tocanch6">Contemplating upgrades</a></li><li><a class="toctarg" href="#tocanch7">RTC
+battery substitute module installation and upgrades</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch8">Troubleshooting the modded
+laptop</a></li><li><a class="toctarg" href="#tocanch9">Other upgrades</a></li></ul></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2022-11-27.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2024-02-02.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">Framework Laptop: Repasting &amp; Two Year Report</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2023-11-13<br>#device-review #computer-repairing</div>
+ <hr><div id="article" class="TText"><article>
+<p>Updated 2023-11-27: Added stuff on the RTC battery replacement module
+installation and part swap.</p>
+<h2 id="tocanch0" class="tvis">“Repasting” with PTM 7950</h2>
+<p>I’ve been reading testimonials from people replacing thermal paste in
+their laptops with
+<a href="https://thermalmanagement.honeywell.com/content/dam/thermalmanagement/en/documents/document-lists/technical/pmt-am-tims-ltm6300-pcm45f-ptm5000-series-data-sheet.pdf">PTM
+7950</a>, mostly praising the amazing effectiveness of the material,
+with some reporting a drastic 20 degrees C reduction. I was skeptical of
+such claims. Such temperature reduction just seemed impossible to me,
+especially considering the conductivity of PTM 7950 is pretty much the
+same as most non-terrible thermal pastes on paper.</p>
+<p>Anyway I decided to give it a try myself when I saw this mystic
+material on sale for barely above $10 the other day.</p>
+<p>The repasting process went pretty smoothly. However I did notice that
+the screw marked “3” on the heatsink seemed a lot looser than the other
+two. Maybe that has something to do with the horrible thermal I had
+before…</p>
+<p>Time for the results. Spoiler alert: it’s impressive. I cannot do a
+scientific before and after comparison, but I did run a few of my
+day-to-day tasks as tests. Idle temperatures are already much better:
+50°C before vs 38°C after. Under a short code compilation load (around 5
+minutes), the initial temperatures are similar (~100°C before vs 96°C
+after), but the CPU was able to boost much closer to its designated PL2
+power (58W vs 45W, advertised PL2 being 60W). After the processor
+stabilizes at its PL1 power it goes down to below 80°C, while the under
+the old paste it was a constant 90+°C. The task also finishes ~10%
+faster than before.</p>
+<p>While my results aren’t as insane as some others got, it was still
+huge. The biggest improvement is that merely browsing the Internet
+without setting CPU power policy to powersave is now bearable – I’ve
+mentioned in my previous post that the fan noise of the Framework laptop
+is a pretty big issue for me personally, as the noise it emits when the
+processor is above 55°C is extremely distracting in a quiet room. I also
+got ~10% more performance out of this CPU, which probably makes this the
+best $10 I spent on tech-related products for the past few years.</p>
+<p>So would I recommend the PTM 7950? Yes, but only when you
+<em>have</em> to do a repaste. As I mention before, I was skeptical of
+claims about the magical power of PTM 7950. To be clear I wasn’t
+doubting the thermal conductivity of the material, but rather the cause
+of the temperature reduction people have been reporting – maybe their
+old paste had completely dried out, or the factory paste application is
+utter garbage. For my specific case – I have my reasons to suspect the
+same due to the aforementioned loose screw on the heatsink I had. While
+I have never touched the heatsink assembly myself since day one until
+today, and the thermal profile of the machine was fairly consistent for
+the past 2 years, I couldn’t rule out everything. So I don’t really know
+if it is a factory defect or something else. Also I’ve seen reports that
+<a href="https://www.reddit.com/r/LenovoLegion/comments/tfxomi/">certain
+newer laptops already use similar phase change material as its <span title="Thermal Interface Material" style="text-decoration-line:underline;text-decoration-style:dotted;">TIM</span></a>.
+So if you’re considering to repaste your brand new laptop (which isn’t
+always a great idea in the first place) with PTM 7950, do remember to
+check if that’s the case.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-factorypaste.jpg"><img style="width: 33%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-factorypaste.jpg"></a> <br>Factory
+thermal paste application
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-unp.jpg"><img style="width: 33%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-unp.jpg"></a> <br>Factory paste
+removed
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-ptm7.jpg"><img style="width: 33%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-ptm7.jpg"></a> <br>PTM 7950 applied
+</div>
+</td>
+</tr>
+</tbody></table>
+<h2 id="tocanch1" class="tvis">Semi-long term review</h2>
+<h3 id="tocanch2" class="tvis">Disassembly reveals …</h3>
+<div style="text-align:center;max-width:90%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-batsw.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1536x1536_fw-batsw.jpg"></a> <br>First disassembly
+in 2 years.
+</div>
+<p>A few things jumped out when I opened up the laptop for repasting.
+The first, very obvious and somewhat worrying one is the mildly swollen
+battery (also known as SpicyPillows). I did not run the laptop a lot on
+battery during the first year, but the second year saw more usage with
+it unplugged (still not as frequent as my ThinkPad X1 yoga 1st gen). The
+swelling isn’t anywhere near extreme, and there hasn’t been a
+significant reduction of battery life since I got the machine. For this
+reason I’m not yet very compelled to replace it. But I will definitely
+be monitoring it much more closely from this point on, as it’s very well
+known that SpicyPillows are potentially dangerous.</p>
+<p>The second, less obvious one is also about a battery, but this time
+the CMOS battery. It was completely flat. I was aware of a
+<a href="https://community.frame.work/t/rework-instructions-for-11th-gen-mainboards-to-enable-powering-the-rtc-circuit-from-the-main-battery/26922">design
+flaw</a> in these 11th gen Intel machines that the CMOS battery only
+gets charged when the laptop is on AC power. However I’m not sure this
+is the cause in my case as my laptop spends most of its lifetime powered
+on and connected to AC power. While I do appreciate the original,
+extremely detailed makeshift solution (which is under the “Archived”
+section of the post linked above), I’m not comfortable with the idea of
+scratching a trace off an expensive motherboard. Anyway now that there’s
+a solution that doesn’t involve scratching a trace off the motherboard,
+I’m going to install the
+<a href="https://guides.frame.work/Guide/RTC+Battery+Substitution+on+11th+Gen+Intel%C2%AE+Core%E2%84%A2/203">RTC
+battery substitute module</a> and update this post when that’s done.</p>
+<h3 id="tocanch3" class="tvis">Other early adopter issues</h3>
+<p>The touchpad is flaky. Being a touchpad hater as I am (and a
+trackpoint user for more than half my life), I had to deal with it when
+I’m on the go. A few months ago I found that physical clicks on the
+touchpad no longer works, and apparently I’m not the only one.
+<a id="n1" href="#note1" class="note">[1]</a> There appears to be a
+<a href="https://framework.kustomer.help/articles/-SJQQqt2Hu">simple
+fix</a> which consists of a single step that sounds a little ridiculous
+(“Try pressing the bottom middle of the Touchpad firmly a few times”),
+but it worked for me.</p>
+<p>I do venture out to become an early adopter of certain products
+sometimes, My ThinkPad X1 yoga 1st gen being another example where
+Lenovo experimented with the “yoga” form factor in their ThinkPad
+line-up for the first time. Being an early(-ish) adopter of the
+Framework laptop, I fully expected that there could be issues. So far
+I’ve come across the CMOS battery design flaw, touchpad issue, BIOS
+bugs, unreasonable level of CPU throttling and fingerprint reader driver
+overheating the power button. None of these are severe enough to be a
+deal breaker for me, and all of the listed issues have been more or less
+fixed. I guess my overall experience of being an early adopter has been
+overall positive.</p>
+<h3 id="tocanch4" class="tvis">How well did it hold up?</h3>
+<p>Performance wise, it’s still a beast in its class. These Willow Cove
+cores still eats the Rust compilation workload that I now have to deal
+with on a daily basis as breakfast. Gaming still is an option for me
+considering the only game that I play nowadays is Minecraft, but is
+likely a no-no for any heavier games. While it’s not the most power
+efficient solution available today, it still meets the requirements of
+my setup just fine.</p>
+<p>Battery life isn’t too great in the first place. But the lifetime
+seems to hold up decently despite having a slightly swollen battery
+pack. Again, still fulfills my needs.</p>
+<p>Internals…
+<a href="//filestorage.chrisoft.org/blog/img/fw-fanfilth.jpg">don’t look
+great</a> (CW: filthy looking fan). The fan seems to attract dust much
+faster than the one in my ThinkPad X1 yoga.</p>
+<h3 id="tocanch5" class="tvis">Random rants</h3>
+<p>I still find the default fan curve of the laptop downright stupid.
+Ramping it up to 80% of full speed at 60°C doesn’t seem wise to me. Yes
+there are third party tools that can force a fan speed, but I’d rather
+program a more sane fan curve instead.</p>
+<p>Intel’s Xe driver for Windows is still hot garbage for graphics
+development.</p>
+<p>I do not like the forum software Framework uses (Discourse). The idea
+of infinite scrolling never clicked with me. You simultaneously get the
+worst from pagination and single-paged designs. And their page search is
+still crippled to this day. Okay I’ll stop here and keep my other 10
+objections to Discourse with myself.</p>
+<h2 id="tocanch6" class="tvis">Contemplating upgrades</h2>
+<p>Framework promised to provide an upgrade path to owners of their
+laptops and they delivered. Now I have the choice of replacing the
+motherboard in my Framework with a 12th/13th gen Intel board, or a Zen 4
+based AMD board. I’ve explained why I didn’t upgrade to the 12th gen
+Intel board in my previous post, and I’ll state the most important part
+here again: I don’t want to ditch my old board that’s perfectly
+functional. I’ll also say the silent part that was omitted in the
+previous post aloud: I don’t want to purchase the extra parts to build a
+complete computer out of the old board either.</p>
+<p>There are additional reasons that I didn’t upgrade to specific
+available boards. 13th gen Intel boards are especially objectionable due
+to the fact that they still use DDR4 memory. This is year 2023 and DDR5
+memory isn’t hard to find now. Yes I guess you get to keep your old
+memory sticks, but I don’t want an upgrade that seems half-baked thank
+you very much.</p>
+<p>AMD boards seem way more compelling, especially considering the
+performance boost they could bring at the price point they are sold at.
+But I’ve heard that they produce pretty much the exact same noise as the
+original boards once installed, runs as hot under heavy load, and would
+result in increased pain just by the virtue of being AMD <a id="n2" href="#note2" class="note">[2]</a>.
+And I would need to reconfigure the entire kernel <a id="n3" href="#note3" class="note">[3]</a>. For this reason
+I’ve pretty much shelved the idea of upgrading the motherboard in the
+very near future. The only reason for a motherboard upgrade for me now
+would be the old one straight up failing or become unsuitable for my
+tasks.</p>
+<p>There is one upgrade I want to make though. I would absolutely love
+to replace the glossy screen from factory with the new matte one. I was
+never a fan of glossy screens on any laptop and will take a matte
+replacement any day of the week. The price is a little steep though.</p>
+<p>There’s another upgrade that I’d love to get. A trackpoint keyboard
+with proper mouse buttons. I’m sure Lenovo would do anything to sabotage
+it, but I can always dream.</p>
+<h2 id="tocanch7" class="tvis">RTC
+battery substitute module installation and upgrades</h2>
+<p>The battery module was sent out the day before US Thanksgiving. I
+also decided to treat myself with the aforementioned matte screen
+upgrade and a proper Chinese keyboard, which were sent out on the same
+day.</p>
+<p>Following the official guide linked above, the installation was
+pretty straight forward. I don’t have stellar soldering skills or very
+stable hands, but here are a few photos from the installation plus my
+commentry.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtcmp.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtcmp.jpg"></a> <br>RTC battery
+substitute module packing. Unassuming.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtcmi.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtcmi.jpg"></a> <br>The module itself.
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtcmt.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtcmt.jpg"></a> <br>After soldering. I
+applied a <em>little</em> bit too much solder.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtcmf.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtcmf.jpg"></a> <br>Final position.
+</div>
+</td>
+</tr>
+</tbody></table>
+<h3 id="tocanch8" class="tvis">Troubleshooting the modded
+laptop</h3>
+<p>Unfortunately, as things usually are for me, it didn’t go right after
+this point. Immediately after finishing the mod the machine still
+refused to turn on with the AC adaptor unplugged. It could boot with the
+adaptor plugged in and stay on after unplugging it while the laptop is
+running. Unplugging the machine with it turned off would erase all CMOS
+data. This was the exact same behavior exhibited before I performed the
+RTC battery modification.</p>
+<p>So I had to start the troubleshooting process. The power wire to the
+RTC battery substitute module measured 17.5 V to ground when the machine
+was powered on, so I didn’t mess up the soldering <a id="n4" href="#note4" class="note">[4]</a>. The outer ring of the module measured 3.2 V to ground,
+so the module itself is good. Neither values changed when I turned the
+machine off or had it unplugged after that. At this point pretty much
+all hardware faults that I could think of have been ruled out.</p>
+<p>Then I remembered that my machine is on BIOS version 3.17, while the
+latest release was 3.19 for this motherboard. So I decided to give that
+a shot. I quickly grabbed the update from their website and installed
+it, and voilà: the machine was able to turn on without the AC power
+attached once the BIOS has been updated.</p>
+<p>I still felt a bit iffy with my installation though, so I decided to
+go through the official installation guide again to make sure I followed
+everything – and of course I did not. There is apparently a specific
+orientation requirement for the module (a working one is shown in the
+second picture of step 3 in the guide). So I adjusted mine to match the
+picture for good measure, which resulted in the final installation photo
+shown above. There was also a comment under the official mentioning the
+module orientation issue.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtctv0.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtctv0.jpg"></a> <br>3.2 V present on
+outer ring of the module with the computer powered on and plugged in.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtctv1.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtctv1.jpg"></a> <br>17.5 V going into
+the module with the computer powered on and plugged in.
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtctv2.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtctv2.jpg"></a> <br>3.2 V still
+present when the machine is turned off but remain plugged in.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-rtctv3.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-rtctv3.jpg"></a> <br>3.2 V still
+present when the machine is both turned off and unplugged.
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>By now I have the RTC battery substitute module fully working as
+Framework intended. However I couldn’t help but notice that this still
+doesn’t give the laptop the normally expected behavior according to the
+schematic of the module and a statement from Framework themselves, both
+of which can be found
+<a href="https://github.com/FrameworkComputer/RTCRework">here</a>. For a
+normal laptop one would expect when its main battery runs out it would
+still be able to keep time and the BIOS configuration. However with this
+modification being essentially just a voltage regulator (NCP718) and
+having no significant energy storage at all, the machine
+<strong>will</strong> lose all CMOS data once the main battery cuts out,
+which functions more like a normal laptop with a dead CMOS battery. But
+I guess it’s probably better than losing CMOS data even with a fully
+charged main battery…</p>
+<h3 id="tocanch9" class="tvis">Other upgrades</h3>
+<p>I actually performed these part swaps between soldering the battery
+module thingy in and the troubleshooting process. But that didn’t really
+matter because these upgrades went pretty smoothly without any drama.
+There were a lot of screws to undo and screw back in though (25 black
+ones and <strong>48</strong> silver ones?? I couldn’t really keep track
+of the number.) <a id="n5" href="#note5" class="note">[5]</a> These screws are pretty annoying to
+handle because they have incredibly short shanks and are incredibly easy
+to strip. With the official screw driver they easily stick together and
+the ifixit screw driver couldn’t reliably pick them up. The sheer number
+of them only added to the trouble I had to go through to replace my
+perfectly working keyboard with one that has additional legends on the
+keys that I will barely look at. Is it really worth the trouble? (Yes…
+if it had a trackpoint goddammit!)</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-scr.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-scr.jpg"></a> <br>The screen. Wanky
+Apple-esque packaging.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-scp.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-scp.jpg"></a> <br>Screen unboxed.
+Apparently the newer 13 inch AMD model comes with this type of screen.
+<br>(which is objectively superior btw)
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-kbp.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-kbp.jpg"></a> <br>Keyboard unboxed. I
+can type Chinese using bopomofo at like 3 ch/min and I barely remember
+anything about Cangjie.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-ksc.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-ksc.jpg"></a> <br>National guild of
+screws. Nobody will get this reference.
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-scc.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-scc.jpg"></a> <br>The screens side by
+side. Original screen on the left. The matte screen actually looked very
+good for what it is.
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-scb.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-scb.jpg"></a> <br>Back of the screens.
+Original on the left. Both made by BOE.
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/fw-kbb.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_fw-kbb.jpg"></a> <br>The new keyboard
+with backlight on. Fun fact: practically all computers sold in mainland
+China come with a standard US ANSI keyboard.
+</div>
+</td>
+<td>
+</td>
+</tr>
+</tbody></table>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>:
+<a href="https://community.frame.work/t/touchpad-clicking-issues/37059">[1]</a>
+<a href="https://community.frame.work/t/touchpad-click-not-working-and-getting-loose/16408">[2]</a>
+<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Their
+crappy GPU driver being a major PITA for me – my experience with AMD
+graphics seems very inconsistent with most Linux users. No I refuse to
+elaborate here because that would derail the entire post.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: Because I
+run Gentoo. Now laugh at me as you wish.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: Even
+admittedly it looked pretty bad as all my soldering jobs have been so
+far.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: So many that they actually forgot to circle
+out two of them in their official guide. Multiple comments under the
+guide already pointed this out, but Framework hasn’t modified the guide
+at the time of writing.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2024-02-02.html b/blog/post/2024-02-02.html
new file mode 100644
index 0000000..58fc59c
--- /dev/null
+++ b/blog/post/2024-02-02.html
@@ -0,0 +1,612 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"R-BUS Technical Information")</title>
+<meta name="description" content="«R-BUS Technical Information» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+<style>
+table tr:nth-child(odd) { background-color: rgba(160, 160, 160, 0.3); }
+</style></head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">R-BUS Technical Information</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/music/">music</a></li><li><a href="/blog/list/electronics/">electronics</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">Background</a></li><li><a class="toctarg" href="#tocanch1">Devices with R-BUS support</a></li><li><a class="toctarg" href="#tocanch2">Pin definition</a></li><li><a class="toctarg" href="#tocanch3">Official cable wiring</a></li><li><a class="toctarg" href="#tocanch4">Electrical
+characteristics of the interface</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch5">Power</a></li><li><a class="toctarg" href="#tocanch6">Digital Audio</a></li><li><a class="toctarg" href="#tocanch7">MIDI</a></li></ul></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2023-11-13.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2024-02-04.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">R-BUS Technical Information</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2024-02-02<br>#music #electronics</div>
+ <hr><div id="article" class="TText">
+<article>
+<h2 id="tocanch0" class="tvis">Background</h2>
+<p>R-BUS (also called RMDB2 / RMDB II on older products) is an obsolete
+proprietary interconnect format that carries bidirectional MIDI and
+digital audio data created by Roland. It was used on Roland products
+released from the late 90s to early 2000s.</p>
+<p>There was a physically incompatible and much rarer predecessor of
+R-BUS called RMDB (Roland Multipurpose Digital Bus). RMDB is not the
+subject of this article.</p>
+<p>Much of the information here is gathered from schematics inside
+service manuals for various Roland products, mainly the XV-5080 and
+VS-2400. These can be easily found with a search through the
+interwebz.</p>
+<p>This article assumes minimal electronics knowledge from the reader.
+As a matter of fact, the author is also a layperson in this space.
+Report of any issues in the article would be appreciated.</p>
+<p>For other R-BUS related stuff on this website, please visit <a href="/rbusif">this page</a>.</p>
+<h2 id="tocanch1" class="tvis">Devices with R-BUS support</h2>
+<p>Here is a not necessarily complete list of Roland products that comes
+with at least one R-BUS connector:</p>
+<ul>
+<li>Mixing Console
+<ul>
+<li>VM-3100Pro</li>
+<li>VM-7100 / VM-7200 (3 ports on optional VM-24E I/O expansion)</li>
+</ul></li>
+<li>Studio Workstation
+<ul>
+<li>VS-2400</li>
+<li>VS-2480 (2 ports)</li>
+<li>VSR-880</li>
+</ul></li>
+<li>Production Studio
+<ul>
+<li>MV-8000 / MV-8800 (available through the MV8-OP1 audio I/O
+expansion)</li>
+</ul></li>
+<li>Synthesizer
+<ul>
+<li>XV-5080 (output only)</li>
+</ul></li>
+<li>Interface Modules
+<ul>
+<li>RPC-1 (Conventional PCI R-BUS interface)</li>
+<li>ADA-7000 (A/D converter)</li>
+<li>AE-7000 (R-BUS &lt;=&gt; AES/EBU converter)</li>
+<li>DIF-AT (R-BUS &lt;=&gt; TDIF &amp; ADAT converter)</li>
+<li>DIF-AT24 (R-BUS to ADAT and MIDI interface, 24-bit)</li>
+</ul></li>
+</ul>
+<h2 id="tocanch2" class="tvis">Pin definition</h2>
+<p>Connection for VS-2400 and XV-5080 is extracted from their respective
+service manuals. Pin usage inferred from these connections.</p>
+<table>
+<colgroup>
+<col style="width: 13%">
+<col style="width: 31%">
+<col style="width: 31%">
+<col style="width: 22%">
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: center;">PIN</th>
+<th style="text-align: center;">VS-2400</th>
+<th style="text-align: center;">XV-5080</th>
+<th style="text-align: left;">Usage</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">+5V</td>
+<td style="text-align: center;">+5V</td>
+<td style="text-align: left;">Power output</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">2</td>
+<td style="text-align: center;">RBOUT11</td>
+<td style="text-align: center;">SDO4</td>
+<td style="text-align: left;">Channel 1/2 output (<span style="text-decoration: overline;">SDOUT1</span><a id="n1" href="#note1" class="note">[1]</a>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">3</td>
+<td style="text-align: center;">RBOUT12</td>
+<td style="text-align: center;">SDO5</td>
+<td style="text-align: left;">Channel 3/4 output (<span style="text-decoration: overline;">SDOUT2</span>)</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">4</td>
+<td style="text-align: center;">RBOUT13</td>
+<td style="text-align: center;">SDO6</td>
+<td style="text-align: left;">Channel 5/6 output (<span style="text-decoration: overline;">SDOUT3</span>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">5</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">6</td>
+<td style="text-align: center;">RBOUT14</td>
+<td style="text-align: center;">SDO7</td>
+<td style="text-align: left;">Channel 7/8 output (<span style="text-decoration: overline;">SDOUT4</span>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">7</td>
+<td style="text-align: center;">NC <a id="n2" href="#note2" class="note">[2]</a></td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: left;">Unused?</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">8</td>
+<td style="text-align: center;">RBIN14</td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: left;">Channel 7/8 input (<span style="text-decoration: overline;">SDIN4</span>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">9</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">RBIN13</td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: left;">Channel 5/6 input (<span style="text-decoration: overline;">SDIN3</span>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">11</td>
+<td style="text-align: center;">RBIN12</td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: left;">Channel 3/4 input (<span style="text-decoration: overline;">SDIN2</span>)</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">12</td>
+<td style="text-align: center;">RBIN11</td>
+<td style="text-align: center;">SDI2</td>
+<td style="text-align: left;">Channel 1/2 input (<span style="text-decoration: overline;">SDIN1</span>)</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">13</td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: center;">NC</td>
+<td style="text-align: left;">Power reception for bus-powered devices
+<a id="n3" href="#note3" class="note">[3]</a></td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">14</td>
+<td style="text-align: center;">PC_TXD1</td>
+<td style="text-align: center;">RBUS_TX</td>
+<td style="text-align: left;">MIDI transmit <a id="n4" href="#note4" class="note">[4]</a></td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">15</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">16</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">17</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">18</td>
+<td style="text-align: center;">1FS</td>
+<td style="text-align: center;">LRCK4</td>
+<td style="text-align: left;">Frame sync (word clock) output</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">19</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">20</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">21</td>
+<td style="text-align: center;">RBFS1</td>
+<td style="text-align: center;">RBUS-WDCLK</td>
+<td style="text-align: left;">Frame sync (word clock) input</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">22</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">23</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="even">
+<td style="text-align: center;">24</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: center;">GND</td>
+<td style="text-align: left;">Ground</td>
+</tr>
+<tr class="odd">
+<td style="text-align: center;">25</td>
+<td style="text-align: center;">PC_RXD1</td>
+<td style="text-align: center;">RBUS_RX</td>
+<td style="text-align: left;">MIDI receive <a id="n5" href="#note5" class="note">[5]</a></td>
+</tr>
+</tbody>
+</table>
+<h2 id="tocanch3" class="tvis">Official cable wiring</h2>
+<p>Roland has only disclosed partial information on the wiring scheme
+used by the official R-BUS cables. <a id="n6" href="#note6" class="note">[6]</a>
+However, it’s rather easy to infer the full wiring scheme from that
+information. This has been confirmed by other third-party sources.
+<a id="n7" href="#note7" class="note">[7]</a> <a id="n8" href="#note8" class="note">[8]</a></p>
+<table>
+<colgroup>
+<col style="width: 25%">
+<col style="width: 18%">
+<col style="width: 11%">
+<col style="width: 18%">
+<col style="width: 25%">
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: right;">Usage 🖙</th>
+<th style="text-align: center;">Pin on one side</th>
+<th style="text-align: center;">is connected to</th>
+<th style="text-align: center;">Pin on the other side</th>
+<th style="text-align: left;">🖘 Usage</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: right;">+5V</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">13</td>
+<td style="text-align: left;">+5V In</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDOUT1</td>
+<td style="text-align: center;">2</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">12</td>
+<td style="text-align: left;">SDIN1</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">SDOUT2</td>
+<td style="text-align: center;">3</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">11</td>
+<td style="text-align: left;">SDIN2</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDOUT3</td>
+<td style="text-align: center;">4</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">10</td>
+<td style="text-align: left;">SDIN3</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">5</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">9</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDOUT4</td>
+<td style="text-align: center;">6</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">8</td>
+<td style="text-align: left;">SDIN4</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">NC</td>
+<td style="text-align: center;">7</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">7</td>
+<td style="text-align: left;">NC</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDIN4</td>
+<td style="text-align: center;">8</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">6</td>
+<td style="text-align: left;">SDOUT4</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">9</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">5</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDIN3</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">4</td>
+<td style="text-align: left;">SDOUT3</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">SDIN2</td>
+<td style="text-align: center;">11</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">3</td>
+<td style="text-align: left;">SDOUT2</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">SDIN1</td>
+<td style="text-align: center;">12</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">2</td>
+<td style="text-align: left;">SDIN1</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">+5V In</td>
+<td style="text-align: center;">13</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">1</td>
+<td style="text-align: left;">+5V</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">MIDI TX</td>
+<td style="text-align: center;">14</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">25</td>
+<td style="text-align: left;">MIDI RX</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">15</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">24</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">16</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">23</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">17</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">22</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">FS Out</td>
+<td style="text-align: center;">18</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">21</td>
+<td style="text-align: left;">FS In</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">19</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">20</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">20</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">19</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">FS In</td>
+<td style="text-align: center;">21</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">18</td>
+<td style="text-align: left;">FS Out</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">22</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">17</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">23</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">16</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="even">
+<td style="text-align: right;">GND</td>
+<td style="text-align: center;">24</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">15</td>
+<td style="text-align: left;">GND</td>
+</tr>
+<tr class="odd">
+<td style="text-align: right;">MIDI RX</td>
+<td style="text-align: center;">25</td>
+<td style="text-align: center;"></td>
+<td style="text-align: center;">14</td>
+<td style="text-align: left;">MIDI TX</td>
+</tr>
+</tbody>
+</table>
+<h2 id="tocanch4" class="tvis">Electrical
+characteristics of the interface</h2>
+<h3 id="tocanch5" class="tvis">Power</h3>
+<p>The +5V supply is derived straight from the +5V rail that goes into
+the main board, with polarity protection (both in the XV-5080 and
+VS-2400) provided with a Schottky diode, and sometimes current protected
+with a thermistor (not present in the XV-5080).</p>
+<p>The +5V pin measured 5.28V to ground on my XV-5080.</p>
+<h3 id="tocanch6" class="tvis">Digital Audio</h3>
+<p>The format of digital audio portion of R-BUS resembles <a href="https://en.wikipedia.org/wiki/I%C2%B2S">I²S</a>, but with a few
+key differences:</p>
+<ul>
+<li>There’s no bit clock.</li>
+<li>Sample data are transmitted as if they are 32-bit, despite only the
+first 24-bit is being used.</li>
+<li>Logic level on the data line is inverted.</li>
+</ul>
+<p>To give a standalone description of the R-BUS digital audio
+protocol:</p>
+<ul>
+<li>The frame sync (word clock) signal runs at the same frequency as the
+audio sampling rate.</li>
+<li>When frame sync is low, left channel of each channel pair is being
+transmitted, otherwise right channel is being transmitted.</li>
+<li>Each half cycle of the frame sync clock is divided into 32 periods,
+during each of which a bit of sample data is sent on every serial data
+line.</li>
+<li>Sample data are sent most significant bit (MSB) first. Each sample
+is 24-bit long, leaving 8 bits unused at the end of each half cycle of
+frame sync.</li>
+<li>Logic low on the data line means the bit being sent is 1, and high
+means it’s a 0.</li>
+</ul>
+<p>If you’d like a timing diagram of all this, please look up the
+datasheet of TC9271 made by Toshiba (used in the XV-5080 as its S/PDIF
+encoder chip). Figure 1b is a good representation of the relationship
+between frame sync (LRCK in the datasheet) and audio data. The LRS=H
+case in figure 3a shows how the frame sync signal sent over R-BUS should
+be interpreted.</p>
+<p>There are 4 serial data lines in each direction, giving the 8
+channels in total for each direction. Each direction has its own frame
+sync signal, which is shared among all data lines in that direction.</p>
+<h3 id="tocanch7" class="tvis">MIDI</h3>
+<p>What is sent over the MIDI wires in the R-BUS cable has not been
+confirmed by me.</p>
+<p>The MIDI interface is used differently on different Roland
+products:</p>
+<ul>
+<li>XV-5080 seem to ignore everything on the R-BUS MIDI interface,
+despite having all the facilities to handle it. Roland disclosed this in
+RPC-1’s user manual (see the section on XV-5080). I have not tested this
+claim.</li>
+<li>MV-8000 series with MV8-OP1 installed can use the R-BUS MIDI output
+as a separate MIDI port. Data going into the R-BUS MIDI port will be
+mixed with the built-in MIDI input.</li>
+<li>VM-3100Pro can pass through the MIDI data to its built-in MIDI
+ports, and can control the host sequencer if connected to a
+computer.</li>
+<li>V-Studio products can receive MIDI clock over R-BUS.</li>
+<li>Any aspects / products not mentioned here are unknown to me.</li>
+</ul>
+<p>Roland calls the signals that go in to / out of these pins “IPC” or
+“PC”. <a id="n9" href="#note9" class="note">[9]</a></p>
+<p>Inside both the VS-2400 and the XV-5080, the signal is generated /
+goes into a dedicated microcontroller (a M3888 1M2), specifically, a
+pair of its UART ports. An inverter is between the R-BUS connector and
+the MCU in each direction of the signal.</p>
+<p>Roland claims in VS-2480’s manual that R-BUS carries 8 channels of
+bidirectional digital audio (which are already fully accounted for in
+the previous section), plus MIDI, MMC (MIDI Machine Control) and MTC
+(MIDI Timecode).</p>
+<p>The factual portion of this section ends here. Everything below is my
+guesswork. Since MMC commands and MTC are both usually just sent as
+normal MIDI messages, it’s a reasonable assumption that, the only thing
+that is transmitted over these wires is MIDI, which is also why I named
+them MIDI TX/RX in my pin usage chart.</p>
+<p>Since MIDI is pretty much just UART with a bit of isolation, I would
+venture a guess that the signal sent / expected on these two pins is
+just inverted MIDI UART signal.</p>
+<p>It would be pretty trivial to build some experimental circuitry to
+test my theory. Maybe I’ll do it one day. However this may end up with
+nothing – as the XV-5080 will probably just ignore the MIDI data going
+through R-BUS.</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Serial data
+output (input). Overline indicates that 1-bit is represented with low
+logic level and 0-bit with high logic level. Same
+below.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Not connected. Same
+below.<br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: Inferred from wiring scheme<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: Often abbreviated
+as TX.<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: Often abbreviated
+as RX.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: <a href="https://support.roland.com/hc/en-us/articles/201978779-R-BUS-RBUS-RBC-RBC-5-Where-Can-I-Find-an-R-BUS-Cable">R-BUS,
+RBUS, RBC, RBC-5: Where Can I Find an R-BUS Cable?</a><br></span><span class="TText"><a id="note7" href="#n7">[7]</a>: <a href="https://web.archive.org/web/20240204170917/https://www.vsplanet.com/ubbthreads/ubbthreads.php?ubb=showflat&amp;Number=450346">Roll
+your own: R-Bus Cable Pin Out.</a><br></span><span class="TText"><a id="note8" href="#n8">[8]</a>: <a href="https://web.archive.org/web/20211204221550/https://themidimaniac.com/diy-r-bus-cable-for-20e/">DIY
+R-BUS cable for 20€</a><br></span><span class="TText"><a id="note9" href="#n9">[9]</a>: I have no idea what these could mean. My
+software-dominated brain tells me they stand for “Inter-Process
+Communication” and “Program Counter” but they clearly stand for
+something else here.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2024-02-04.html b/blog/post/2024-02-04.html
new file mode 100644
index 0000000..6c2fcae
--- /dev/null
+++ b/blog/post/2024-02-04.html
@@ -0,0 +1,600 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"RBUS-ADAT devlog")</title>
+<meta name="description" content="«RBUS-ADAT devlog» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">RBUS-ADAT devlog</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/music/">music</a></li><li><a href="/blog/list/electronics/">electronics</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">Origins</a></li><li><a class="toctarg" href="#tocanch1">Background check on the chip</a></li><li><a class="toctarg" href="#tocanch2">Ill-fated commencement</a></li><li><a class="toctarg" href="#tocanch3">Designing the board</a></li><li><a class="toctarg" href="#tocanch4">Board production and final
+assembly</a></li><li><a class="toctarg" href="#tocanch5">Full project timeline</a></li><li><a class="toctarg" href="#tocanch6">Full material cost</a></li><li><a class="toctarg" href="#tocanch7">Potential future work</a></li><li><a class="toctarg" href="#tocanch8">I want one! What should I do?</a></li><li><a class="toctarg" href="#tocanch9">You’re an idiot and
+your design is trash!</a></li><li><a class="toctarg" href="#tocanch10">Acknowledgment</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2024-02-02.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2024-02-29.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">RBUS-ADAT devlog</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2024-02-04<br>#music #electronics</div>
+ <hr><div id="article" class="TText"><article>
+<h2 id="tocanch0" class="tvis">Origins</h2>
+<p>Funny enough, the origins of this project has nothing to do with
+R-BUS <strong>or</strong> ADAT.</p>
+<p>Ideas to build a digital only version of the EDIROL SD-80 surfaced in
+early 2023 as an extension to my SD-80 modding plan. Beacuse my SD-80 is
+half broken (headphone amp on analog output 1 fried due to my stupidity,
+see my <a href="https://chrisoft.org/blog/post/2020-11-20.html#tocanch2">second
+SD-80 post</a> for how it happened) and I only ever record it through
+its digital outputs anyway, I believe I can drastically reduce the
+footprint of it by taking out all the analog outputs and removing the
+now unused ±15V rail, making the device USB bus powered at the same
+time. There was also plans to add a second digital output to the modded
+SD-80, however the plan was never finalized, let alone implemented
+because of my lack of proper electronics knowledge and soldering skills.
+The idea was therefore shelved.</p>
+<p>Meanwhile in early 2022, I acquired a Roland XV-5080 (which I still
+have a long overdue review to write). I was also only recording that
+thing digitally and sometimes felt that wasting the other 3 stereo
+outputs is a shame. I did a bit of research and apparently the R-BUS
+port on its back outputs all 4 stereo outputs of the synth. Later I
+found out there was the DIF-AT and DIF-AT24 that can convert R-BUS to
+ADAT which is still fairly common on modern audio interfaces. However
+for a small box that doesn’t really do much, asking price for the DIF-AT
+is absolutely crazy – every single listing I saw was ~$200. And the
+DIF-AT24, which supports 24-bit ADAT output (in contrast to DIF-AT’s
+20-bit output), is pretty much unobtainium. So I decided to live with
+recording through its S/PDIF output for the time being.</p>
+<p>In September 2023, by pure coincidence, I found a listing on ebay of
+a chip described as “ADAT optical encoder/generator”, which was the <a href="https://www.coolaudio.com/docs/COOLAUDIO_V1401_DATASHEET.pdf">coolaudio
+V1401</a> that later would become the heart of my design. After reading
+its datasheet I decided it would pretty much make my SD-80 digital mod
+trivial, with the added benefit of carrying both stereo output channels
+on a single port. So I opened up the service manual for SD-80 and
+started to study which pin each signal should go to. However I quickly
+realized that performing the mod would require soldering around the XV
+chip inside the SD-80, which is still a thing that I’m not really
+willing to do; and that I could easily test out my theory on XV-5080’s
+R-BUS port because the digital audio output pins on XV-5080’s R-BUS port
+is pretty much directly connected to the XV chip through an
+inverter.</p>
+<p>To summerize … I came up with a solution for a problem that I made up
+for myself.</p>
+<h2 id="tocanch1" class="tvis">Background check on the chip</h2>
+<p>The seller of the chip claims the chip is an equivalent of the AL1401
+from Alesis, which sounds quite interesting as Alesis is actually the
+company behind ADAT (<u>Alesis</u> Digital Audio Tape, as for why it’s a
+tape not a optical interface… that’s a story for another time).
+Suspicion that this chip is a Chinese clone arose. So I did a bit of
+background on the company … <a id="n1" href="#note1" class="note">[1]</a></p>
+<p>Turns out, of course it is. While its roots can be traced to the US
+in the 90s, design team of coolaudio is now located in China
+<a id="n2" href="#note2" class="note">[2]</a>. Better still, it’s a brand
+of Music Tribe, which is Uli Behringer’s company. Yes it’s the same
+person who founded Behringer which is best known as the legal (/s) clone
+audio equipment manufacturer. <del>No wonder why coolaudio’s product
+portfolio is all clone chips.</del></p>
+<p>Well, the original AL1401 is pretty much impossible to find nowadays,
+so I really have no choice don’t I?</p>
+<h2 id="tocanch2" class="tvis">Ill-fated commencement</h2>
+<p>I ordered the V1401 chips before my end-of-year vacation travel. When
+I returned from my vacation, I found these in my mail box:</p>
+<div style="text-align:center;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-pk.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-pk.jpg"></a><br>Suspicious packets
+</div>
+<p>which may look suspicious to law enforcement… but they are actually
+just chips. Not the edible kind.</p>
+<p>My prior experience with electronics is only limited to reading
+schematics and disassembling (and destroying in the process) hundreds of
+home appliances. So I guess I have seen hundreds of printed circuit
+boards but I haven’t ever made or designed one of my own. I did take a
+class during my undergrad that involved programming FPGAs, which did
+have a “drawing schematics on a computer” component to it, but that
+didn’t have anything to do with PCB design.</p>
+<p>Since I do not have any prior experience working with EDA software, I
+toyed with an Chinese online EDA toolkit that literally has “easy” in
+its name (EasyEDA) and drew a tentative schematic for the supporting
+components. Apparently it wasn’t that different from what I used when I
+was taking the FPGA class, but at this stage I still haven’t confirmed
+many aspects of the characteristics of R-BUS yet. As a result there were
+a multitude of issues with this schematic. However it did help me come
+up with a list of components (“bill of materials” in more professional
+terms) needed for the project. I ordered these together with some
+prototyping supplies online, hoping to actually build a prototype once
+they have arrived.</p>
+<div style="text-align:center;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-es.png"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-es.png"></a> <br>The error-riddled
+schematic
+</div>
+<p>I need an audio interface with ADAT inputs because none of the bunch
+I already own has one. Since the Scarlett 18i8 3rd gen was on sale for
+$360 at the time, I decided to get one.</p>
+<p>When I was reviewing the datasheet for the components I ordered
+<a id="n3" href="#note3" class="note">[3]</a>, I
+found out that I’ve ordered the wrong optical transmitter. The part I
+ordered was TOTX1353 which only supports up to 500 kb/s data rate … less
+than 1/20 required by an ADAT data stream. However for some stupid
+reason that I couldn’t recall, I decided to try prototyping with it
+anyway.</p>
+<p>I soldered one of the V1401 chips to the SOIC carrier board. As this
+time I used plenty of proper, good quality flux as suggested the MacBook
+repair guy Louis Rossmann <a id="n4" href="#note4" class="note">[4]</a>, the result didn’t look
+nearly as bad as my previous SMD soldering attempts and I was quite
+happy with it.</p>
+<p>On the following day I started showing mild symptoms of a common
+cold. Later that night a fever kicked in. The next day I decided to use
+an expired Cornweed <a id="n5" href="#note5" class="note">[5]</a> test kit on myself and found out Cornweed was
+growing inside me (hence the name of this subsection).</p>
+<p>I got a week off from my workplace to get rid of the Cornweed. Since
+I already felt much better after one day, I started breadboarding. It
+was finished pretty quickly. But soon after that I found out there was
+more than one thing wrong with the optical transmitter module I chose –
+the module doesn’t have a drive circuitry built in and it pretty much
+just a bare LED. There is no way in hell that it can be directly driven
+from the output of a 74LS04. The LED in the transmitter only barely
+lights up when the output is active. At this point I finally realized
+that I can’t use this out of spec piece of crap in the final design
+anyway, so I placed order for a few transmitters that are more fit for
+the job.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-bo.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-bo.jpg"></a> <br>The chip on its
+breakout board
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-b0.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-b0.jpg"></a> <br>The breadboard
+prototype before it was working
+</div>
+</td>
+</tr>
+</tbody></table>
+<p>When I was trying to wire in the DB-25 terminal block, I found out
+that I don’t have the proper flathead driver for the screws. So I had to
+get one of those as well.</p>
+<p>Once I really had all the items I need, I started putting things
+together. The process was fairly easy but the audio interface didn’t see
+the ADAT signal on the first attempt. I double checked all the
+breadboard connections and inputs to the chip, which appeared to be all
+correct. Feeling tired, I removed the prototype from my desk to work on
+it the following day, unplugging all the cables in the process.</p>
+<p>To my utter surprise, the thing straight up worked when I plugged it
+in on the next day. It turns out that the port on the new transmitter is
+very tight and takes quite a bit of force to insert the plug all the way
+in.</p>
+<div style="text-align:center;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-b1.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-b1.jpg"></a><br>Working prototype!
+</div>
+<h2 id="tocanch3" class="tvis">Designing the board</h2>
+<p>I decided to switch to KiCad soon after I started the actual
+prototyping process, probably due to my bias towards free software.</p>
+<p>Drawing the schematics wasn’t hard. Although I did have to read the
+manuals to find out how buses work in KiCad.</p>
+<p>There is no symbol for the V1401 chip in KiCad’s default library, and
+no symbol or footprint for the optical transmitter. I had to learn how
+to draw these and make them myself. Fortunately the process is pretty
+straightforward and the datasheet has everything I need.</p>
+<p>I spent some additional time studying the digital / analog audio
+output section of XV-5080 to find out the format of digital audio data
+coming out of the XV chip. Once that was done I was able finalize the
+schematic. I started learning routing in KiCad soon after that. However
+that effort was put on hold as soon as I realized I should really
+validate the schematic on breadboard first.</p>
+<p>Once I got the breadboard version working, I started working on
+routing the board again. It started pretty difficult, as certain
+crossings couldn’t really be avoided. However once I started making
+liberal use of vias the problems got solved pretty quickly. I then
+recalled seeing large ground plane on most circuit boards that I’ve laid
+my eyes on and found out those can be made in KiCad with “zones”.
+However for some (not completely insane, but still pretty stupid) reason
+I thought adding too much copper could add to the manufacturing cost, so
+I was … quite stingy with the zones. Maybe I should fix it in the next
+revision.</p>
+<p>Finally I added some personal markings on the board. I decided to try
+the svg import feature of KiCad and drew something in Inkscape within a
+minute. Once placed on the board it actually looked pretty nice. Yes it
+is a Touhou reference, now stop asking why.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-ks.png"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-ks.png"></a> <br>Unfinished
+schematic in KiCad
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-rt.png"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-rt.png"></a> <br>First attempt at
+routing. The board was laid out very differently.
+</div>
+</td>
+</tr>
+</tbody></table>
+<h2 id="tocanch4" class="tvis">Board production and final
+assembly</h2>
+<p>The design was now ready and I started looking for PCB manufacturers.
+I settled between a few Chinese manufacturing providers for price
+considerations. My final manufacturer of choice was JLCPCB, mostly
+because they have the best reviews in China. I submitted the files and
+waited anxiously for the boards to arrive.</p>
+<p>The boards arrived astonishingly fast. In just 5 days it went through
+the entire production sequence as well as the Pacific Ocean, and arrived
+at my door steps. I test fit all the components, which all fit just
+fine. Next was the final assembly which also went pretty smoothly. After
+a quick test the board was found to work perfectly. I was actually
+shocked that the very first PCB designed by me worked first try. To be
+fair the board itself is pretty simple. It was figuring out the R-BUS
+protocol that made the project slightly tricky. Actually I’m pretty
+surprised to find out that nobody has done the work already given the
+service manual of XV-5080 has been floating around on the Internet for
+many years now. Anyway, this has been a fantastic starter electronics
+project for me and the process has been quite enjoyable.</p>
+<table>
+<tbody><tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-pp.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-pp.jpg"></a> <br>Box from JLCPCB
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-bs.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-bs.jpg"></a> <br>It’s between my
+fingers…
+</div>
+</td>
+</tr>
+<tr>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-pa.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-pa.jpg"></a> <br>First two
+components installed
+</div>
+</td>
+<td>
+<div style="text-align:center;max-width:98%;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-fp.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-fp.jpg"></a> <br>Assembly finished
+</div>
+</td>
+</tr>
+</tbody></table>
+<div style="text-align:center;">
+<a href="//filestorage.chrisoft.org/blog/img/rbdt-pw.jpg"><img style="width: 50%;" src="//filestorage.chrisoft.org/blog/img/ssbsthumb_1024x1024_rbdt-pw.jpg"></a><br>IT’S ALIVE!!
+</div>
+<h2 id="tocanch5" class="tvis">Full project timeline</h2>
+<ul>
+<li>2023-09-27: V1401 chip found on ebay.</li>
+<li>2023-12-09: V1401 chips bought from ebay seller.</li>
+<li>2024-01-10: Schematic attempt with EasyEDA.</li>
+<li>2024-01-11: First batch of components ordered.</li>
+<li>2024-01-17: V1401 soldered to breadboard adapter.</li>
+<li>2024-01-18: Second batch of components ordered.</li>
+<li>2024-01-20: Switched to KiCad. Schematic finished except missing
+symbol and footprint for optical transmitter.</li>
+<li>2024-01-21: Breadboard built. Created symbols and footprint for
+optical transmitter in KiCad.</li>
+<li>2024-01-22: Started learning PCB layout in KiCad. First attempt to
+route the PCB made. Routing halted later that day.</li>
+<li>2024-01-26: First working breadboard prototype. Routing resumed and
+finished the same day. Learned how to use zones in KiCad. PCB design
+revised.</li>
+<li>2024-01-27: PCB submitted to JLCPCB for production. 10 boards
+ordered.</li>
+<li>2024-02-01: PCB arrived. First board assembled and passed
+testing.</li>
+</ul>
+<h2 id="tocanch6" class="tvis">Full material cost</h2>
+<p>This includes all orders placed specifically for this project,
+including stuff that can be later used for other purposes. Prices listed
+before VAT.</p>
+<table>
+<colgroup>
+<col style="width: 25%">
+<col style="width: 10%">
+<col style="width: 25%">
+<col style="width: 39%">
+</colgroup>
+<thead>
+<tr class="header">
+<th style="text-align: left;">Item</th>
+<th style="text-align: center;">Qty</th>
+<th style="text-align: center;">Vendor</th>
+<th style="text-align: center;">Price Total</th>
+</tr>
+</thead>
+<tbody>
+<tr class="odd">
+<td style="text-align: left;">Half-size breadboard</td>
+<td style="text-align: center;">5</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">25.00</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">Breadboarding wire bundle</td>
+<td style="text-align: center;">2</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">9.90</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">Adafruit Perma-Proto Super Pack</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">34.95</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">Hook-up Wire Spool Set - 22AWG Solid Core
+- 6 x 25 ft</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">15.95</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">Hakko Professional Quality 20-30 AWG Wire
+Strippers</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">17.50</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">SOIC-20 breakout 3 Pack</td>
+<td style="text-align: center;">2</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">9.00</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">Adafruit Parts Pal</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Adafruit</td>
+<td style="text-align: center;">19.95</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">TOTX1353(F)</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">92.88</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">16SEPC100M+TSS</td>
+<td style="text-align: center;">20</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">11.56</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">SN74LS04N</td>
+<td style="text-align: center;">25</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">19.30</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">CTS 208-4</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">5.76</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">DB25-SL-25</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">12.60</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">CFR-25JB-52-1K</td>
+<td style="text-align: center;">100</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">2.47</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">CFR25SJT-52-2K2</td>
+<td style="text-align: center;">100</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">2.47</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">1N4002B-G</td>
+<td style="text-align: center;">30</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">4.32</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">25SEP10M+TSS</td>
+<td style="text-align: center;">20</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">18.84</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">C320C104K5R5TA</td>
+<td style="text-align: center;">50</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">5.05</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">FCR684208T</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">DigiKey</td>
+<td style="text-align: center;">33.75</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">V1401</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">ebay (av13)</td>
+<td style="text-align: center;">30.00</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">JUXINICE DB25 Male to Male Cable 3 feet,
+26awg Tinned Copper Wires,Double-Shielded with Foil &amp;Metal Braid,
+D-SUB 25 pin Cable RS232 Serial Cable in Black</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Amazon</td>
+<td style="text-align: center;">12.99</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">Antrader 2PCS DB25 Breakout Connector
+D-sub 25-pin Female Adapter RS232 to Terminal Board Signal Module</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Amazon</td>
+<td style="text-align: center;">11.99</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">Focusrite Scarlett 18i8 3rd Gen USB Audio
+Interface</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">Sweetwater</td>
+<td style="text-align: center;">359.99</td>
+</tr>
+<tr class="odd">
+<td style="text-align: left;">Mako Driver Kit - 64 Precision Bits</td>
+<td style="text-align: center;">1</td>
+<td style="text-align: center;">iFixit</td>
+<td style="text-align: center;">39.95</td>
+</tr>
+<tr class="even">
+<td style="text-align: left;">PCB Production</td>
+<td style="text-align: center;">10</td>
+<td style="text-align: center;">JLCPCB</td>
+<td style="text-align: center;">14.50</td>
+</tr>
+</tbody>
+</table>
+<p>Grand Total = $810.67</p>
+<h2 id="tocanch7" class="tvis">Potential future work</h2>
+<p><del>First of all I need to fix the stingy ground plane.</del></p>
+<p>V1401’s datasheet isn’t very clear on whether it can generate a
+24-bit ADAT stream. Recordings made with the Scarlett 18i8 seem to have
+the full 24-bit resolution, but that could be due to interpolation done
+by the audio interface or operating system. Testing this requires an
+oscilloscope which I currently don’t have.</p>
+<p>It is highly feasible to implement an ADAT encoder / decoder in
+software on cheap microcontrollers like the rp2040. The ADAT protocol is
+documented <a href="https://ackspace.nl/wiki/ADAT_project">here</a> and
+seems fairly straightforward to implement. This also has the added
+benefit of making sure that 24-bit ADAT is really supported. However
+this will also more than likely require an oscilloscope for debugging.
+I’ll also have to learn rp2040’s PIO programming and theories on PLL
+operation, both from scratch.</p>
+<p>Exposing the MIDI interface on R-BUS also seems possible. However it
+seems that XV-5080 doesn’t make use of the MIDI interface on R-BUS
+<a id="n6" href="#note6" class="note">[6]</a>.</p>
+<p><del>Maybe I’ll add more Touhou references to the silkscreen, who
+knows.</del></p>
+<h2 id="tocanch8" class="tvis">I want one! What should I do?</h2>
+<p>First of all I’d suggest giving the <a href="https://filestorage.chrisoft.org/blog/data/rbus_adat_m.pdf">manual</a>
+a read to make sure this board really does what you want.</p>
+<p>If you have made up your mind to get a board, I have some bad news
+for you. Unfortunately right now there’s no straightforward way obtain
+this board. Mainly because I have never sold anything online. Also this
+board is bound to be a very niche product, and possibly can’t even
+recover the development costs if I decided to sell them. Those are the
+reasons why I currently have no plans to sell the board.</p>
+<p>So right now your options are:</p>
+<ul>
+<li>Build the board yourself. The design is fully open source and build
+instruction is included in the manual. If you are comfortable with
+electronics DIY projects, this is probably your best bet.</li>
+<li>Let me know you want one! Right now I still have a few
+pre-production boards lying around. As long as you’re willing to cover
+the terrible USPS shipping rates I’m willing to assemble a board and
+send it your way. Of course you’re welcome to pay a little bit more… but
+any excess for now will be treated as donations (a “pay what you think
+it’s worth” model) – as I don’t have pricing fixed yet. Also if enough
+people have expressed interest in the board I might actually start
+selling them…</li>
+</ul>
+<h2 id="tocanch9" class="tvis">You’re an idiot and
+your design is trash!</h2>
+<p>First of all, thank you. I am indeed a massive idiot.</p>
+<p>If you have suggestions on how this board could be improved, please
+consider sending them to me. As a beginner in electronics design I can
+definitely use any piece of advice coming from pretty much anyone in
+this field. Any constructive suggestion will be greatly appreciated.</p>
+<p>Of course other types of contributions will also be appreciated. For
+example this board currently lacks any kind of enclosure as I have zero
+idea how to create 3D models for real-life object manufacturing. Help in
+this space is desperately needed.</p>
+<h2 id="tocanch10" class="tvis">Acknowledgment</h2>
+<p>I’d like to thank <a href="https://www.youtube.com/@KRPalto47">Palto</a> for being extremely
+supportive towards this project, including putting up with my endless
+DMs on Discord.</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Not to shit on the country or
+anything, after all I’m from said country … but Chinese clone chips are
+notorious for being unreliable in general or straight up not
+working.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: <a href="https://www.coolaudio.com/aboutus-page.php">“World
+Class Management &amp;Technical Team: One of the most extensive design
+service companies in China”</a><br></span><span class="TText"><a id="note3" href="#n3">[3]</a>: which is probably a dumb thing to do. I should have read
+through all of them <em>before</em> placing the order.<br></span><span class="TText"><a id="note4" href="#n4">[4]</a>: He doesn’t really do the repairs
+himself nowadays any more, does he?<br></span><span class="TText"><a id="note5" href="#n5">[5]</a>: That thing which destroyed 2020 to 2022
+for countless people misspelled deliberately to avoid unwanted
+attention.<br></span><span class="TText"><a id="note6" href="#n6">[6]</a>: See the section on XV-5080 in RPC-1’s manual.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2024-02-29.html b/blog/post/2024-02-29.html
new file mode 100644
index 0000000..0634199
--- /dev/null
+++ b/blog/post/2024-02-29.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"2024 Site Update")</title>
+<meta name="description" content="«2024 Site Update» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+</head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">2024 Site Update</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/garbage/">garbage</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">Blog</a></li><li><a class="toctarg" href="#tocanch1">Home Page</a></li><li><a class="toctarg" href="#tocanch2">Serving the Website</a></li><li><a class="toctarg" href="#tocanch3">Other Online-presence Stuff</a></li></ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2024-02-04.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="2024-03-02.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">2024 Site Update</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2024-02-29<br>#garbage</div>
+ <hr><div id="article" class="TText"><article>
+<p>I figured I wanted to give an update on this website (and my current
+state in general), so why don’t do it on the leap day…</p>
+<h2 id="tocanch0" class="tvis">Blog</h2>
+<p>The blog has been renamed. Its new name is “Specluncam Ursae”
+(Bearess’ Den). And the link has been condensed into a single one
+“Specluncam Ursae visere” (Visit the Bearess’ Den).</p>
+<p>The name change has been on my mind for years actually. I enjoy word
+play quite a lot, and my surname (which literally means “bear” in the
+language) is an excellent subject of word play – also a source of
+bullying when I was a kid. Since the blog is a place where I just
+randomly dump stuff, I figured the name “bear’s den” would be a suiting
+name, as I treat it as the home to my thoughts. (Well, not
+<em>every</em> single one of them, as you’ll see soon…) As for why it’s
+in Latin, that’s because I started naming things in Latin whenever I
+feel like it since I started learning the language.</p>
+<p>Removing the categories “Development blog” and “Nonsense blog” is
+another long overdue change. They were actually a leftover of the
+original PHP-based version of <span class="tipped" title="the Stupid Blogging System">SBS</span>. By the time tags were
+introduced to SBS version 2, those links have been <em>de facto</em>
+obsolete. I just didn’t find the excuse to remove them.</p>
+<p>“Why are you using the feminine version of the word ‘bear’?” you may
+ask. Well the reason is twofold: first is to disassociate with the
+hairy, non-heterosexual male stereotypical imagery of bears. The second
+reason is the same as why I wrote “However according to the Haskell
+tutorial found at haskell.org, <code>"chirs" == sort "chris"</code> and
+is her twin nemesis. That would be a very playful joke.” on the
+homepage. <a id="n1" href="#note1" class="note">[1]</a></p>
+<p>One last point here. I decided to shift the focus of this blog to
+more technical subjects. The majority of future posts will be on
+technical aspects of my personal projects – I’m going to leave my
+profession work (if I can call it that) elsewhere. Reviews and relevant
+personal updates will still be posted. Political stuff will still be
+kept at a minimum. But I promise those old, extremely cringeworthy posts
+on trifling matters will be no more – I was reviewing some of those old
+posts recently and part of me <strong>really</strong> wanted to take
+them off the website… It’s really for everybody’s interest that I keep
+those to myself…</p>
+<p>As for the unfinished posts… no they will probably never get
+finished, ever.</p>
+<h2 id="tocanch1" class="tvis">Home Page</h2>
+<p>There were a few readability improvements made to the home page. One
+of them is that the about section no longer requires JavaScript to load.
+This “noscript support improvement program” might extend to other
+sections in the future as well. Besides that, nothing really changed.
+There will be no design change to the home page in the foreseeable
+future. The random design I used for QMidiPlayer’s documentation is a
+surprisingly serviceable template (at least to my eyes).</p>
+<p>I may reorganize the list of projects in a different way some
+day.</p>
+<h2 id="tocanch2" class="tvis">Serving the Website</h2>
+<p>The URL on the filestorage subdomain is now served through
+Cloudflare’s CDN. This will have a positive impact on the load time of
+blog images and tracks in the music library, but not much else.</p>
+<h2 id="tocanch3" class="tvis">Other Online-presence Stuff</h2>
+<p>I’m not on Twitter anymore. <a id="n2" href="#note2" class="note">[2]</a> I have uninstalled their mobile application and blocked
+their website (at my own discretion). I’m only keeping the account
+because Musk is a narcissistic dick, and doesn’t let me see shit on that
+website if I somehow have to obtain a certain piece of information from
+it without logging in (I really should use a burner account for that
+purpose shouldn’t I?). I now post my random crap on Mastodon, on a
+public instance (c.im).</p>
+<p>I’m considering to set up a private email server (once again) as my
+personal gmail account is flooded with useless junk and my work email is
+flooded with another type of junk. Once that’s done I will update my
+homepage to reflect that.</p>
+<p>Also I somehow restored access to my supposedly deleted Bilibili
+account. I don’t intend to post much there but I guess it’s back
+now.</p>
+<p>I think that’s it? Now I should really get some sleep to recover from
+my sleep deprived ass…</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: Well, the reason I listed on the homepage is
+actually a lie, but the real reason doesn’t really matter
+here.<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Fuck Melon Husk. I repeat, FUCK
+MELON HUSK! No I don’t want to have sexual intercourse with
+him.<br></span></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/2024-03-02.html b/blog/post/2024-03-02.html
new file mode 100644
index 0000000..4a4c4c2
--- /dev/null
+++ b/blog/post/2024-03-02.html
@@ -0,0 +1,394 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"The Station of Elyssima")</title>
+<meta name="description" content="«The Station of Elyssima» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+<style>
+div.tf-gates-container {
+ display: flex;
+ justify-content: space-around;
+ flex-wrap: wrap;
+}
+div.tf-gates {
+ flex: 1 240px;
+ display: inline-block;
+ margin: 1em;
+ padding: 1em;
+ border: solid 2px;
+}
+div.tf-gates-filler {
+ flex: 100 0px;
+ display: inline-block;
+}
+div.tf-gates > p {
+ text-indent:0 !important;
+}
+hr.tf {
+ border: none;
+ border-top: 3px double;
+ overflow: visible;
+ text-align: center;
+ height: 2em;
+}
+hr.tf::after {
+ background-color: var(--principal-bg);
+ background-image: var(--bg-pattern);
+ background-repeat: repeat;
+ content: '§';
+ padding: 0 1em;
+ position: relative;
+ top: -13px;
+}
+</style></head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">The Station of Elyssima</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/fiction/">fiction</a></li><li><a href="/blog/list/garbage/">garbage</a></li></ul>
+ </li>
+ <li id="tocouter" style="display: none;">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ </ul>
+ </li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2024-02-29.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="Privacy.html">Next post</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">The Station of Elyssima</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2024-03-02<br>#fiction #garbage</div>
+ <hr><div id="article" class="TText">
+<script src="https://filestorage.chrisoft.org/blog/data/polyfill.min.js"></script>
+<script src="https://filestorage.chrisoft.org/blog/data/mathjax/mathjax.js"></script>
+<article>
+<p>Chris hung up her last phone call of the day and started packing up.
+She was on her final stop of an important business trip to the capital
+city of Elysionia that lasted a week. She’s having a vacation once this
+trip concludes, and now she’s dying for getting back her cozy little
+home.</p>
+<p>In Elysionia, people get around mostly by trains. There is an
+extremely elaborate railway system that connects every single place of
+importance in Elysionia. Its foundations laid out hundreds years ago,
+the Elysionia Railways has been serving the country loyally and
+contentedly over the years. Being inside continental Europe, it also
+links to other surrounding countries.</p>
+<p>Chris works for upper management of a private company. As part of her
+job she travels around the country frequently and take the trains more
+than a few dozens of times each year. Being a frequent rider of
+Elysionia Railways, she’s familiar with the system enough that she can
+recite the time table of various larger stations. With still well more
+than an hour from her planned departure time, she is not in a hurry.</p>
+<p>Chris is anxious for this very special train ride too, as the new
+train station in the capital began to operate yesterday. She booked
+specifically for a train that would depart the city from the new
+station. She has heard that this new station was designed and built like
+no other train stations in Elysionia, and she was ready to find out
+what’s so special about this new station that supposedly will
+revolutionize railway transportation in Elysionia.</p>
+<p>A taxi is called and Chris tells the driver her destination. “Huh,
+the new station?” Says the driver, “I heard a multitude was there
+yesterday just to check it out. Are you going there just for a visit
+too?” “A multitude of people… it must be really well designed,” thought
+Chris. She’s busy being distracted by her own thoughts and didn’t pay
+attention to answering the driver’s unsolicited question at all except
+letting out an unclear murmur of “yes”.</p>
+<p>Before long she is dropped off at the station. When she laid her eyes
+on the station for the first time Chris was utterly stunned – the
+exterior of the station looks exactly like a gigantic Gothic castle. She
+is standing at least a few hundred meters away from the main entrance
+yet the entire building barely fits in her field of view. A triplet of
+sharp spires with beautifully engraved patterns point straight into the
+sky. Towers surrounding them must still be as tall as the tallest radio
+tower she has ever seen. Flamboyant traceries made up most of the
+exterior openings. Born into a rural farming family, Chris could not
+fathom the sheer amount of work that was put into the construction of
+this station (nor could she understand why the city decided to erect a
+huge Gothic castle in pretty much the dead center of Elyssima). There is
+not a single railway track in sight – they are all cleverly well hidden.
+The square in front of the station is still flooded with a large crowd
+of people, all admiring this gorgeous building.</p>
+<p>But Chris is here to take a train ride and she really does not have
+the time to give this building a good look that it deserves, so she
+proceeds into the station. However again her eyes are instantly hooked –
+the pointed arches, the vault ribs which forms an endless mesmerizing
+geometric pattern, oh and the intricately decorated crystal chandeliers
+hanging around the center of the ticketing hall, which are even more
+opulent than the ones that appeared in her childhood dreams. Chris could
+not take a single step without getting amazed by something new that goes
+into her sight.</p>
+<p>A clock with hands long as a bus in the hallway brought Chris back to
+real life – it’s 20 minutes before the train she is planning to take
+will depart. The railway system of Elysionia works like a massive subway
+– as long as one has paid the appropriate fare, they will be permitted
+to travel between any places below a distance corresponding to the fare
+on that day. Still, trains are run at different frequencies for each
+destination. And in Chris’ case, if she missed this one she would have
+to wait 3 more hours, which would mean she won’t be in her house until
+midnight. Willing as she is to stick around, she still wants to be home
+more, just by a little bit. She says to herself, “I shall give this
+place a good visit someday,” and immediately got back into business –
+looking up the gate on the information display and following the signs.
+Everything is still so familiar.</p>
+<p>Chris followed the signage to a three-way junction. It appears that
+each path leads to a different set of gates. She took a sharp turn
+following where the arrow points and heads to a lower floor, not even
+noticing her dress almost being caught in the escalator.</p>
+<p>She finds herself in a delightfully decorated corridor with gates on
+one side and fine art exhibits on the other. She has some walking to do
+though – the corridor is for gates 80 to 1, and her gate is 15 – so she
+really doesn’t have time to appreciate the art, or to think about how
+they managed to squeeze so many gates into a single corridor,
+<em>or</em> why are there so many gates in this station in the first
+place.</p>
+<p>As the station was put into use only a day ago, it’s still early in
+the transitional period: there are not a whole lot of trains here, nor
+are there too many people who are actually taking a train. It soon
+becomes apparent to her that the gates are fairly far apart from each
+other, and even at her fastest walking pace, she will probably not make
+it on time. So she started running. Chris is not good runner. She never
+has been. And the fact that she is wearing an ankle-length dress
+definitely isn’t helping. She looks at the wall of arts and sees her own
+reflection on the fresh glazed wall tiles – her long, unblemished white
+dress flying high from all the velocity that she usually never gets to
+have. Similarly set in motion is her long, black hair, which is
+spreading in midair. The reflection is so clear that she can even make
+out the frills and cutwork on the hemline – even threads on the needle
+lace, which are not unlike the ribs of the traceries she saw moments
+ago, just vastly different in scale. She got a strong sensation of déjà
+vu from what she just saw, as it reminded her of a series of daydreams
+she often had when she was a little girl. But this isn’t a great time to
+fantasize about her prior dreams, is it?</p>
+<p>50, 49, 48 … Chris is steadily passing by the gates. It still puzzles
+her why are there so many gates in this station. She must have seen
+number as large as 200 when she was at the junction. Is there ever going
+to be enough rolling stock in Elysionia to warrant so many gates? Also
+why are they using <em>gates</em> at all? Train stations usually have
+just platforms don’t they? Is this why they said the new station would
+revolutionize railway transportation in Elysionia?</p>
+<p>30, 29, 28 … Chris is running out of her breath. She takes a look at
+her watch and realizes that she still has 10 minutes left. “Surely I can
+make it to gate 15 in ten minutes,” she says to herself. There are few
+people in this section of the station, and all the benches are vacant.
+She stops to take a quick breather. Mindlessly she glances at the floor
+brilliantly lit up from atop and saw her own image. “Holy heck,” mutters
+Chris, “it must take a lot of work to keep this station under such
+condition in the future.”</p>
+<p>When Chris passes by gate 25 she notices something is off. She halts
+her steps and looks back.</p>
+<div class="tf-gates-container">
+<div class="tf-gates">
+Gate<br>27
+</div>
+<div class="tf-gates">
+Gate<br>26
+</div>
+<div class="tf-gates">
+Porte<br>25
+</div>
+<div class="tf-gates-filler">
+
+</div>
+</div>
+<p>The language of the sign changed for some reason. This baffles Chris
+and makes her freeze in place for a good second. She has learned a
+little bit of French in her youth and can indeed understand the word.
+She just couldn’t understand why – Elysionia is an English speaking
+country and as long as English remains the lingua franca of the world,
+there really isn’t a good reason to change the language midway here.
+Maybe this gate is reserved for trains to and from France? Who
+knows…</p>
+<p>It didn’t take long until she notes another change in language. This
+time it’s German.</p>
+<div class="tf-gates-container">
+<div class="tf-gates">
+Porte<br>22
+</div>
+<div class="tf-gates">
+Bahnsteig<br>21
+</div>
+<div class="tf-gates-filler">
+
+</div>
+</div>
+<p>Only that Chris doesn’t know any German and wouldn’t be able to tell
+if the sign stands for “Slaughterhouse 21” with their scary long
+compound words. But she also feels a little bit reassured as her
+suspicion that these gates may be reserved for trains that connect to a
+different country could be right, or so she thought.</p>
+<p>As she assumes the bizarreness would end here, she finds out she was
+wrong, VERY wrong. Because this is what she sees next:</p>
+<div class="tf-gates-container">
+<div class="tf-gates">
+Imbarchi<br>19
+</div>
+<div class="tf-gates">
+INTROIRE·IN·CVRRVM<br>19⅓
+</div>
+<div class="tf-gates">
+INTROIRE·IN·CVRRVM<br>18
+</div>
+<div class="tf-gates-filler">
+
+</div>
+</div>
+<p>“What on earth is happening,” says Chris, “is this station going to
+pull a Platform 9¾ on me? Where would trains using this gate go anyway,
+Vatican City?”</p>
+<p>Just as she couldn’t stop admiring the exterior of the station when
+she just arrived, these signs don’t stop surprising her, and in an
+increasingly disturbing manner.</p>
+<div class="tf-gates-container">
+<div class="tf-gates">
+<p>INTROIRE·IN·CVRRVM<br> <span class="math inline">\(\begin{vmatrix} 3
+&amp; 5 &amp; 7 &amp; 4 \\ 1 &amp; \pi &amp; 6 &amp; 3 \\ 0 &amp; 7
+&amp; 5 &amp; 9 \\ 5 &amp; 4 &amp; 6 &amp;1 \end{vmatrix}\)</span></p>
+</div>
+<div class="tf-gates">
+<p>INTROIRE·IN·CVRRVM<br> <span class="math inline">\(|\mathrm{e}^{(\ln(61)+\mathrm{e}i)(-4-\frac{7274}{1024}i)}|\)</span></p>
+</div>
+<div class="tf-gates">
+<p>ᚷᛠᛏ<br> <span class="math inline">\(\displaystyle\int_{3}^{\frac{45}{7}} \sinh^{-1}(x)
+\cosh^{-1}(x)\,\mathrm{d}x\)</span></p>
+</div>
+<div class="tf-gates-filler">
+
+</div>
+</div>
+<p>Chris wasn’t good at math when she was in high school. She doesn’t
+even know what half of these symbols could ever mean. She doesn’t think
+she has seen the symbols on the last sign in any of the languages alive
+in the world nowadays either. What is this now, a time machine? As her
+confusion reaches the peak, Chris hears from the PA system:</p>
+<p>“Dear passenger Chris Xephyr, the train you are taking is departing
+in 3 minutes. Please board the train from Gate 15. Thank you.</p>
+<p>Cara Chris Xephyr viatrix, currus qui veheris abibit in tribus
+minutae. Amabo te, introi vehiculum ab porta XV. Gratias tibi.”</p>
+<p>“Who designed this godforsaken place…” exclaims Chris, “how does it
+know my name? This isn’t an airport is it?” She checks the gate closest
+to her, and there is no jet bridge to be seen, only rail tracks. Chris
+has never heard a single word from the PA system ever at any station she
+has been to in Elysionia. She scrambles to find her booking information,
+only to find out that it does say “New Elyssima” there. There is no time
+of departure or name of the passenger, as the booking system never asked
+for them. The station should never have known her name <em>or</em> which
+train she is taking. Her confusion grown into fear, Chris starts running
+again, even faster than before, almost like she’s being chased by a
+deadly monster that would instantly consume her if she gets caught.</p>
+<p>As Chris runs on, she feels the passing of time is slowing down, her
+limbs increasingly heavier, and gates seemingly becoming farther
+separated from each other. She could not hear a thing, not even the
+sough of wind passing by her ears. Her vision becoming darker, Chris
+starts to wonder how long she could keep running. She hasn’t seen a
+single person since the signs started speaking nonsense. She starts to
+contemplate her life choices, as one would inevitably start doing under
+such situation: why she couldn’t end the last call a bit earlier; why
+she had to book a ticket from the new station; is it really worth the
+agony she is experiencing right now; what if she went down the wrong way
+at the junction; why she wouldn’t choose to inherit her family land and
+be a farm girl staying at her hometown – after all if that were the case
+she wouldn’t have to endure any of what she has gone through in the last
+20 minutes. She no longer has the desire to revisit this place
+afterwards – if this is the future of railway transportation in
+Elysionia she might also avoid travelling by train altogether in the
+future – still she’s kind of curious what could be inside those tall
+towers she saw when she was outside the station. But obviously this is
+not the time to find out. The only thought in her head right now is to
+get out of this cursed place somehow.</p>
+<p>Chris runs into a person when she’s deep in her thoughts. She
+apologizes for her carelessness and is about to move on, only to realize
+that she would likely be able to find nobody that could help her if she
+missed this chance. Desperately she asks the person whether they know
+where gate 15 is. The person, not to Chris’ surprise at this point,
+started to speak complete gibberish in response.</p>
+<p>Chris doesn’t want to give up this easily. She continued, with the
+heavy breathing she got from all this running and almost in a pleading
+voice:</p>
+<p>“Did you hear the PA? <em>I</em> am that Chris Xephyr. Does hearing
+the PA calling out your name in a train station seem perfectly normal to
+you?!”</p>
+<p>Again, the person started to speak gibberish. Their demeanor seems
+confident, so they probably understood Chris just fine. But she isn’t to
+able to make out anything whatsoever from their speech, not even their
+body language. Frustrated, she thanks the person and resumes her
+seemingly impossible quest for gate 15.</p>
+<p>Before she is able to run more than a couple of steps, Chris
+collapses to the floor. The hem of her dress, still moving under
+inertia, flies ahead and covers her torso. A gentle breeze from the deep
+side of the corridor, presumably for the purpose of ventilation, blows
+it back to where it belongs, with the cutwork flapping around in the
+breeze. The person from whom she just sought help is now nowhere to be
+found, almost like they have never been there.</p>
+<hr class="tf">
+<p>Chris wakes up finding herself in the warm afternoon sun lying
+against her broom. She was again daydreaming during her housemaid duty.
+Fortunately there isn’t anyone home to catch her in the act. She rushes
+to the living room to find today’s newspaper, its headline reading “New
+Elyssima Train Station Project Dismissed”. She lets out a sigh of relief
+and continued her work.</p>
+</article>
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/post/Privacy.html b/blog/post/Privacy.html
index 578c056..91b3a1d 100644
--- a/blog/post/Privacy.html
+++ b/blog/post/Privacy.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Privacy Policy &amp; Terms")</title>
+<meta name="description" content="«Privacy Policy &amp; Terms» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,42 +33,9 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
</head>
<body onload="ol()" style="overflow-x:hidden;">
@@ -81,9 +51,10 @@ loadTheme();
<li id="tocouter">
<span>Table of Contents</span>
<ul id="tocroot">
- <li><a class="toctarg" href="#tocanch0">1. This site uses Cookies.</a></li><li><a class="toctarg" href="#tocanch1">2. Information collected by this site.</a></li><li><a class="toctarg" href="#tocanch2">3. Guestbook.</a></li><li><a class="toctarg" href="#tocanch3">4. Data retention.</a></li><li><a class="toctarg" href="#tocanch4">5. Backups.</a></li><li><a class="toctarg" href="#tocanch5">6. Your rights.</a></li></ul>
+ <li><a class="toctarg" href="#tocanch0">1. This site uses Cookies.</a></li><li><a class="toctarg" href="#tocanch1">2. Information collected by
+this site.</a></li><li><a class="toctarg" href="#tocanch2">3. Guestbook.</a></li><li><a class="toctarg" href="#tocanch3">4. Data retention.</a></li><li><a class="toctarg" href="#tocanch4">5. Backups.</a></li><li><a class="toctarg" href="#tocanch5">6. Your rights.</a></li></ul>
</li>
- <li style="margin-left:-0.5em"><a id="prevp" href="2019-04-25.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="2024-03-02.html">Prev post</a></li>
<li style="margin-left:-0.5em"><a id="nextp" href="TOP.html">Next post</a></li>
</ul>
</div>
@@ -92,19 +63,28 @@ loadTheme();
<div id="datetags" class="TText" style="margin-bottom:1em;">2019-09-03<br>#special-page</div>
<hr><div id="article" class="TText"><article>
<p>last updated 2019-09-03</p>
-<p>These clauses might be super unprofessional. The only goal is to inform the users of this site (i.e. <a href="https://chrisoft.org">chrisoft.org</a>) about their rights and duties.</p>
+<p>These clauses might be super unprofessional. The only goal is to
+inform the users of this site (i.e.&nbsp;<a href="https://chrisoft.org">chrisoft.org</a>) about their rights and
+duties.</p>
<p>Take footnotes with a pinch of salt!</p>
<h2 id="tocanch0" class="tvis">1. This site uses Cookies.</h2>
-<p>... to store your browsing preferences and to improve your browsing experience. Below is a list of saved items:</p>
+<p>… to store your browsing preferences and to improve your browsing
+experience. Below is a list of saved items:</p>
<ul>
<li>color scheme of your choice.</li>
<li>loop / shuffle states, last used music visualizer.</li>
-<li>password of encrypted section in blog posts (if you decrypted one successfully).</li>
+<li>password of encrypted section in blog posts (if you decrypted one
+successfully).</li>
</ul>
<p>These cookies are not used by the server to do analytics.</p>
-<p>If you don't like cookies for whatever reason, feel free to disable them. The basic functionality of the site will still work perfectly fine.</p>
-<h2 id="tocanch1" class="tvis">2. Information collected by this site.</h2>
-<p>This site collects a minimal set of your data to make the site work and do some basic level of spam prevention. Collected information includes:</p>
+<p>If you don’t like cookies for whatever reason, feel free to disable
+them. The basic functionality of the site will still work perfectly
+fine.</p>
+<h2 id="tocanch1" class="tvis">2. Information collected by
+this site.</h2>
+<p>This site collects a minimal set of your data to make the site work
+and do some basic level of spam prevention. Collected information
+includes:</p>
<ul>
<li>Your public IP address.</li>
<li>User agent string of your browser.</li>
@@ -113,32 +93,48 @@ loadTheme();
</ul>
<p>The collected data are also retained in log files.</p>
<h2 id="tocanch2" class="tvis">3. Guestbook.</h2>
-<p>The guestbook page is where you can leave me a note. Your message will be <strong>permanently</strong> archived in a private location not accessible on this site. In case of a message being deleted from the guestbook page, the message <strong>doesn't</strong> also get removed in the private archive.</p>
-<p>You <strong>can't</strong>:</p>
+<p>The guestbook page is where you can leave me a note. Your message
+will be <strong>permanently</strong> archived in a private location not
+accessible on this site. In case of a message being deleted from the
+guestbook page, the message <strong>doesn’t</strong> also get removed in
+the private archive.</p>
+<p>You <strong>can’t</strong>:</p>
<ul>
<li>Advertise.</li>
<li>Be offensive.</li>
</ul>
-<p>Messages violating rules above will be deleted without further notice.</p>
+<p>Messages violating rules above will be deleted without further
+notice.</p>
<p>You <strong>may</strong>:</p>
<ul>
-<li>Request deletion of <strong>your</strong> messages. Contact the owner of this site for further information on this.</li>
+<li>Request deletion of <strong>your</strong> messages. Contact the
+owner of this site for further information on this.</li>
</ul>
<p>This site <strong>will never</strong>:</p>
<ul>
<li>Alter your message.</li>
<li>Take responsibility of the message you left.</li>
</ul>
-<p>When leaving a message, your IP address will be checked against a spamming blacklist. You can review the source code on this section <a href="https://cgit.chrisoft.org/web.git/tree/cgi/gb_newentry.cgi#n40">here</a>.</p>
+<p>When leaving a message, your IP address will be checked against a
+spamming blacklist. You can review the source code on this section <a href="https://cgit.chrisoft.org/web.git/tree/cgi/gb_newentry.cgi#n40">here</a>.</p>
<h2 id="tocanch3" class="tvis">4. Data retention.</h2>
-<p>Your data collected by this site will be kept indefinitely unless there is a data loss, about which you will not be informed, and might be covered by ...</p>
+<p>Your data collected by this site will be kept indefinitely unless
+there is a data loss, about which you will not be informed, and might be
+covered by …</p>
<h2 id="tocanch4" class="tvis">5. Backups.</h2>
-<p>Like every site ever existed <a id="n1" href="#note1" class="note">[1]</a>, data stored on this site, including those submitted by you, is backed up in a timely manner. <a id="n2" href="#note2" class="note">[2]</a> These backups may contain deleted data.</p>
+<p>Like every site ever existed <a id="n1" href="#note1" class="note">[1]</a>, data stored on this site, including those submitted by
+you, is backed up in a timely manner. <a id="n2" href="#note2" class="note">[2]</a> These backups may contain deleted
+data.</p>
<h2 id="tocanch5" class="tvis">6. Your rights.</h2>
-<p>You hold the right to decide whether to use this site. If you feel uncomfortable about these terms, you might as well consider stop using this site immediately.</p>
-<p>Your rights on your submitted comments in the guestbook are already stated in section 3.</p>
+<p>You hold the right to decide whether to use this site. If you feel
+uncomfortable about these terms, you might as well consider stop using
+this site immediately.</p>
+<p>Your rights on your submitted comments in the guestbook are already
+stated in section 3.</p>
</article></div><br><hr>
- <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: except the old Gentoo Wiki<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Of course they are also deleted in a timely manner.<br></span></div>
+ <div class="TText" id="notediv" style="font-size:80%;"><span class="TText"><a id="note1" href="#n1">[1]</a>: except the old Gentoo
+Wiki<br></span><span class="TText"><a id="note2" href="#n2">[2]</a>: Of course they are also
+deleted in a timely manner.<br></span></div>
<div id="insanch" style="height:3em;"></div>
<div id="footer" style="">
<div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
diff --git a/blog/post/TOP.html b/blog/post/TOP.html
index 742239e..d247048 100644
--- a/blog/post/TOP.html
+++ b/blog/post/TOP.html
@@ -1,9 +1,12 @@
-<html><head>
+<!DOCTYPE html><html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#000000">
-<title>Chrisoft::Blog</title>
+<title>Chrisoft::Blog(r#"Readme_en")</title>
+<meta name="description" content="«Readme_en» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
<script type="text/javascript" src="/blog/footnoter.js"></script>
<script type="text/javascript" src="/blog/aes-js.js"></script>
<script type="text/javascript" src="/blog/scrypt.js"></script>
@@ -30,44 +33,15 @@ function ol()
else unsetevents();
}
window.onresize();
+ loadTheme();
_decryptonload();
}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
- var thmcolor="";
- switch(thm[0])
- {
- case '0':thmcolor=thm[1]=='a'?'#f59dda':'#2f0933';break;
- case '1':thmcolor=thm[1]=='a'?'#9df59d':'#090933';break;
- case '2':thmcolor=thm[1]=='a'?'#edb47b':'#1f1205';break;
- case '3':thmcolor=thm[1]=='a'?'#a0cdfa':'#051933';break;
- }
- document.querySelector("meta[name=theme-color]").setAttribute('content',thmcolor);
-}
-loadTheme();
</script>
-</head>
+<style>
+td{padding-top:5px;padding-bottom:5px;vertical-align:top;}
+</style><style>
+article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
+</style></head>
<body onload="ol()" style="overflow-x:hidden;">
<div id="panel" class="TText">
<ul id="panellist">
@@ -83,8 +57,8 @@ loadTheme();
<ul id="tocroot">
<li><a class="toctarg" href="#tocanch0">Early life</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch1">Preschool and elementary school life</a></li></ul></li><li><a class="toctarg" href="#tocanch2">Known problems</a></li></ul>
</li>
- <li style="margin-left:-0.5em"><a id="prevp" href="2018-12-06.html">Prev post</a></li>
- <li style="margin-left:-0.5em"><a id="nextp">Next post</a></li>
+ <li style="margin-left:-0.5em"><a id="prevp" href="Privacy.html">Prev post</a></li>
+ <li style="margin-left:-0.5em"><a id="nextp" href="rbus-adat-m.html">Next post</a></li>
</ul>
</div>
<div id="content">
@@ -93,9 +67,7 @@ loadTheme();
<hr><div id="article" class="TText">
<article>
<table style="float:right;width:320px;background-color:rgba(255,255,255,0.2);text-align:left;font-size:0.8em;margin-left:10px;">
-<style>
-td{padding-top:5px;padding-bottom:5px;vertical-align:top;}
-</style>
+
<tbody><tr><td colspan="2" style="text-align:center;font-size:1.25em;">
Chris Xiong<br>熊??
</td></tr>
@@ -206,9 +178,7 @@ any significant contribution to the world of computer yet.
<li><a href="#c6">6 Known problems</a></li>
</ul>
</div>
-<style>
-article h2,article h3{border-bottom:1px solid #c0c0c0;overflow:hidden;}
-</style>
+
<h2 id="tocanch0" class="tvis">Early life</h2>
As a child of two outer party members, Chris Xiong's childhood life differs from most peers.
As a result, his childhood life is often described as "dull" by others.
diff --git a/blog/post/rbus-adat-m.html b/blog/post/rbus-adat-m.html
new file mode 100644
index 0000000..2b2a879
--- /dev/null
+++ b/blog/post/rbus-adat-m.html
@@ -0,0 +1,533 @@
+<!DOCTYPE html><html><head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<meta name="theme-color" content="#000000">
+<title>Chrisoft::Blog(r#"RBUS-ADAT User Manual")</title>
+<meta name="description" content="«RBUS-ADAT User Manual» de spelunca ursae">
+<meta name="author" content="Chris Xiong">
+<script type="text/javascript" src="/panel.js"></script>
+<script type="text/javascript" src="/themer.js"></script>
+<script type="text/javascript" src="/blog/footnoter.js"></script>
+<script type="text/javascript" src="/blog/aes-js.js"></script>
+<script type="text/javascript" src="/blog/scrypt.js"></script>
+<script type="text/javascript" src="/blog/sha256.js"></script>
+<script type="text/javascript" src="/blog/decryptor.js"></script>
+<link rel="stylesheet" type="text/css" href="/common.css">
+<link rel="stylesheet" type="text/css" href="/panel.css">
+<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
+<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
+<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
+<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
+<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
+<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
+<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
+<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
+<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
+<script>
+function ol()
+{
+ window.onresize=function()
+ {
+ if(window.innerWidth<768)
+ setupevents();
+ else unsetevents();
+ }
+ window.onresize();
+ loadTheme();
+ _decryptonload();
+}
+</script>
+<style>
+/* start css.sty */
+.cmr-10x-x-109{}
+.ec-qplr-x-x-109{}
+.ec-qplr-x-x-248{font-size:225%;}
+.LinBiolinumT-tlf-t1-x-x-248{font-size:225%; not-font-family: 'Linux Biolinum T', serif;}
+.LinBiolinumTB-tlf-t1-x-x-248{font-size:225%; font-weight: bold; not-font-family: 'Linux Biolinum T', serif;}
+.ec-qplb-x-x-109{}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.ectt-1095{ not-font-family: monospace,monospace;}
+.cmmi-10x-x-109{font-style: italic;}
+.cmsy-10x-x-109{}
+.ec-qplri-{font-size:90%;}
+.ec-qplr-x-x-90{font-size:81%;}
+p{margin-top:0;margin-bottom:0}
+p.indent{text-indent:0;}
+p + p{margin-top:1em;}
+p + div, p + pre {margin-top:1em;}
+div + p, pre + p {margin-top:1em;}
+a { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; hyphens: auto; }
+@media print {div.crosslinks {visibility:hidden;}}
+a img { border-top: 0; border-left: 0; border-right: 0; }
+center { margin-top:1em; margin-bottom:1em; }
+td center { margin-top:0em; margin-bottom:0em; }
+.Canvas { position:relative; }
+img.math{vertical-align:middle;}
+div.par-math-display, div.math-display{text-align:center;}
+li p.indent { text-indent: 0em }
+li p:first-child{ margin-top:0em; }
+li p:last-child, li div:last-child { margin-bottom:0.5em; }
+li p~ul:last-child, li p~ol:last-child{ margin-bottom:0.5em; }
+.enumerate1 {list-style-type:decimal;}
+.enumerate2 {list-style-type:lower-alpha;}
+.enumerate3 {list-style-type:lower-roman;}
+.enumerate4 {list-style-type:upper-alpha;}
+div.newtheorem { margin-bottom: 2em; margin-top: 2em;}
+.obeylines-h,.obeylines-v {white-space: nowrap; }
+div.obeylines-v p { margin-top:0; margin-bottom:0; }
+.overline{ text-decoration:overline; }
+.overline img{ border-top: 1px solid black; }
+td.displaylines {text-align:center; white-space:nowrap;}
+.centerline {text-align:center;}
+.rightline {text-align:right;}
+pre.verbatim {not-font-family: monospace,monospace; text-align:left; clear:both; }
+.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
+div.fbox {display:table}
+div.center div.fbox {text-align:center; clear:both; padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
+div.minipage{width:100%;}
+div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;}
+div.center div {text-align: left;}
+div.flushright, div.flushright div.flushright {text-align: right;}
+div.flushright div {text-align: left;}
+div.flushleft {text-align: left;}
+.underline{ text-decoration:underline; }
+.underline img{ border-bottom: 1px solid black; margin-bottom:1pt; }
+.framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; }
+.framebox-c {text-align:center;}
+.framebox-l {text-align:left;}
+.framebox-r {text-align:right;}
+span.thank-mark{ vertical-align: super }
+span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript{ font-size:80%; }
+div.footnotes{border-top:solid 1px black; border-bottom:solid 1px black; padding-bottom:1ex; padding-top:0.5ex; margin-right:15%; margin-top:2ex; font-style:italic; font-size:85%;}
+div.footnotes p{margin-top:0; margin-bottom:0; text-indent:0;}
+div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; }
+table.tabular td p{margin-top:0em;}
+table.tabular {margin-left: auto; margin-right: auto;}
+td p:first-child{ margin-top:0em; }
+td p:last-child{ margin-bottom:0em; }
+div.td00{ margin-left:0pt; margin-right:0pt; }
+div.td01{ margin-left:0pt; margin-right:5pt; }
+div.td10{ margin-left:5pt; margin-right:0pt; }
+div.td11{ margin-left:5pt; margin-right:5pt; }
+table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
+td.td00{ padding-left:0pt; padding-right:0pt; }
+td.td01{ padding-left:0pt; padding-right:5pt; }
+td.td10{ padding-left:5pt; padding-right:0pt; }
+td.td11{ padding-left:5pt; padding-right:5pt; }
+table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
+.hline hr, .cline hr{ height : 0px; margin:0px; }
+.hline td, .cline td{ padding: 0; }
+.hline hr, .cline hr{border:none;border-top:1px solid black;}
+.tabbing-right {text-align:right;}
+div.float, div.figure {margin-left: auto; margin-right: auto;}
+div.float img {text-align:center;}
+div.figure img {text-align:center;}
+.marginpar,.reversemarginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;}
+.marginpar p,.reversemarginpar p{margin-top:0.4em; margin-bottom:0.4em;}
+.reversemarginpar{float:left;}
+table.equation {width:100%;}
+.equation td{text-align:center; }
+td.equation { margin-top:1em; margin-bottom:1em; }
+td.equation-label { width:5%; text-align:center; }
+td.eqnarray4 { width:5%; white-space: normal; }
+td.eqnarray2 { width:5%; }
+table.eqnarray-star, table.eqnarray {width:100%;}
+div.eqnarray{text-align:center;}
+div.array {text-align:center;}
+div.pmatrix {text-align:center;}
+table.pmatrix {width:100%;}
+span.pmatrix img{vertical-align:middle;}
+div.pmatrix {text-align:center;}
+table.pmatrix {width:100%;}
+span.bar-css {text-decoration:overline;}
+table.tabular{border-collapse: collapse; border-spacing: 0;}
+img.cdots{vertical-align:middle;}
+.partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;}
+.chapterToc a, .chapterToc, .likechapterToc a, .likechapterToc, .appendixToc a, .appendixToc {line-height: 200%; font-weight:bold;}
+.index-item, .index-subitem, .index-subsubitem {display:block}
+div.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:left;}
+div.caption span.id{font-weight: bold; white-space: nowrap; }
+h1.partHead{text-align: center}
+p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; }
+p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; }
+.paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;}
+.subparagraphHead, .likesubparagraphHead { font-weight: bold;}
+.verse{white-space:nowrap; margin-left:2em}
+div.maketitle {text-align:center;}
+h2.titleHead{text-align:center;}
+div.maketitle{ margin-bottom: 2em; }
+div.author, div.date {text-align:center;}
+div.thanks{text-align:left; margin-left:10%; font-size:85%; font-style:italic; }
+div.abstract p {margin-left:5%; margin-right:5%;}
+div.abstract {width:100%;}
+.abstracttitle{text-align:center;margin-bottom:1em;}
+figure.float, div.figure {margin-left: auto; margin-right: auto;}
+figure.float img, figure.figure img {display: block; margin-left: auto; margin-right: auto;}
+figure.figure {text-align:center;}
+figcaption.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:center;}
+figcaption.caption span.id{font-weight: bold; white-space: nowrap; }
+.abstract{margin:1em;}
+div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; }
+table.tabular td p{margin-top:0em;}
+table.tabular {margin-left: auto; margin-right: auto;}
+td p:first-child{ margin-top:0em; }
+td p:last-child{ margin-bottom:0em; }
+div.td00{ margin-left:0pt; margin-right:0pt; }
+div.td01{ margin-left:0pt; margin-right:5pt; }
+div.td10{ margin-left:5pt; margin-right:0pt; }
+div.td11{ margin-left:5pt; margin-right:5pt; }
+table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
+td.td00{ padding-left:0pt; padding-right:0pt; }
+td.td01{ padding-left:0pt; padding-right:5pt; }
+td.td10{ padding-left:5pt; padding-right:0pt; }
+td.td11{ padding-left:5pt; padding-right:5pt; }
+table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; }
+.hline hr, .cline hr{ height : 0px; margin:0px; }
+.hline td, .cline td{ padding: 0; }
+.hline hr, .cline hr{border:none;border-top:1px solid black;}
+div.array {text-align:center;}
+.rotatebox{display: inline-block;}
+#TBL-4 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-4{border-collapse:collapse;}
+#TBL-4 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-4{border-collapse:collapse;}
+#TBL-4 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-4{border-collapse:collapse;}
+#TBL-5 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-5{border-collapse:collapse;}
+#TBL-5 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-5{border-collapse:collapse;}
+#TBL-5 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-5{border-collapse:collapse;}
+#TBL-5 colgroup{border-left: 1px solid black;border-right:1px solid black;}
+#TBL-5{border-collapse:collapse;}
+/* end css.sty */
+
+</style></head>
+<body onload="ol()" style="overflow-x:hidden;">
+ <div id="panel" class="TText">
+ <ul id="panellist">
+ <li><a href="/"><h1>Chrisoft</h1></a></li>
+ <li><a href="/blog"><h2>Blog</h2></a></li>
+ <li><a href="#"><h3 id="title">RBUS-ADAT User Manual</h3></a></li>
+ <li><span>Tags</span>
+ <ul id="tagslist">
+ <li><a href="/blog/list/music/">music</a></li><li><a href="/blog/list/electronics/">electronics</a></li></ul>
+ </li>
+ <li id="tocouter">
+ <span>Table of Contents</span>
+ <ul id="tocroot">
+ <li><a class="toctarg" href="#tocanch0">1 Preface</a></li><li><a class="toctarg" href="#tocanch1">2 NO WARRANTY</a></li><li><a class="toctarg" href="#tocanch2">3 Open hardware</a></li><li><a class="toctarg" href="#tocanch3">4 Safety notice</a></li><li><a class="toctarg" href="#tocanch4">5 Intended usage and applicable devices</a></li><li><a class="toctarg" href="#tocanch5">6 What’s on the board</a></li><li><a class="toctarg" href="#tocanch6">7 Quick start</a></li><li><a class="toctarg" href="#tocanch7">8 Choosing a suitable cable</a></li><li><a class="toctarg" href="#tocanch8">9 Notes</a></li><li><a class="toctarg" href="#tocanch9">10 Specifications</a></li><li><a class="toctarg" href="#tocanch10">11 Appendices</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch11">11.1 Build instructions</a></li><li><ul class="tocnode"><li><a class="toctarg" href="#tocanch12">11.1.1 PCB production</a></li><li><a class="toctarg" href="#tocanch13">11.1.2 Bill of materials</a></li><li><a class="toctarg" href="#tocanch14">11.1.3 Assembling</a></li><li><a class="toctarg" href="#tocanch15">11.1.4 Testing</a></li></ul></li><li><a class="toctarg" href="#tocanch16">11.2 Useful links</a></li><li><a class="toctarg" href="#tocanch17">11.3 Schematic</a></li><li><a class="toctarg" href="#tocanch18">11.4 Circuit board</a></li></ul></li></ul>
+ </li>
+
+
+ </ul>
+ </div>
+ <div id="content">
+ <h2 id="titleh" class="TText" style="font-wight:normal;">RBUS-ADAT User Manual</h2>
+ <div id="datetags" class="TText" style="margin-bottom:1em;">2024-02-03<br>#music #electronics</div>
+ <hr><div id="article" class="TText">
+ <div class="maketitle">
+
+
+
+<h1>RBUS-ADAT User Manual</h1>
+ <div class="author"></div><br>
+<img height="426" alt="PIC" src="//filestorage.chrisoft.org/blog/img/rbus-adat-cvc.png" decoding="async">
+<div class="date"></div>
+This version of the manual is for <span class="ec-qplb-x-x-109">revision 1 </span>of the board.
+Copyright Chris Xiong 2024. Copying of this hardware and its design as well as this documentation is permitted
+under the terms of CERN-OHL-P v2.
+
+
+ </div>
+<p><a id="x1-2r1"></a></p>
+ <h2 id="tocanch0" class="tvis"><span class="titlemark">1 </span> <a id="x1-10001"></a>Preface</h2>
+<!-- l. 57 --><p class="noindent">If you are reading this, chances are you have become an unfortunate test subject of the RBUS-ADAT conversion
+board (or have the nerves to think about becoming one). Well, here is (almost) everything you will want to know
+about the board. If you want to learn about some less useful information about this thing, consider checking out
+the devlog, which can be found by following the link to the project homepage listed under “Useful
+links”.
+</p><!-- l. 64 --><p class="indent"> As this manual is written as if it’s a blog post, which is prone to being very rambly, I’ll try to keep the rambling
+low, at least make an attempt to do so.
+</p><!-- l. 67 --><p class="indent"> Pictures in this manual are renders (computer-generated) and are for illustration purposes only.
+</p><!-- l. 71 --><p class="indent"> <span class="ec-qplb-x-x-109">This product is neither affiliated with or endorsed by Roland Corporation. Roland does not approve
+</span><span class="ec-qplb-x-x-109">connecting unofficial accessories to proprietary Roland interfaces.</span>
+</p><!-- l. 76 --><p class="indent"> Visit <a href="https://chrisoft.org/rbusif">chrisoft.org/rbusif</a> for any future updates to this manual and the hardware.
+<a id="x1-1001r1"></a>
+</p>
+ <h2 id="tocanch1" class="tvis"><span class="titlemark">2 </span> <a id="x1-20002"></a>NO WARRANTY</h2>
+<!-- l. 81 --><p class="noindent">THIS BOARD IS HOMEBREW AND EXPERIMENTAL HARDWARE. THERE IS NO WARRANTY FOR THIS
+HARDWARE, INCLUDING ITS DESIGN AND THE FINISHED PRODUCT, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. THE DESIGNER SHALL NOT BE HELD LIABLE FOR ANY DAMAGE CAUSED BY USING
+THIS HARDWARE, UNLESS REQUIRED BY APPLICABLE LAW.
+</p><!-- l. 86 --><p class="indent"> For the full legalese text on warranty and liability, please refer to the <a href="https://ohwr.org/cern_ohl_p_v2.txt">license text</a>.
+</p><!-- l. 89 --><p class="indent"> If this board fried your equipment, don’t try to extract anything from me. That’s what this section is trying to
+say.
+<a id="x1-2001r2"></a>
+</p>
+ <h2 id="tocanch2" class="tvis"><span class="titlemark">3 </span> <a id="x1-30003"></a>Open hardware</h2>
+<!-- l. 94 --><p class="noindent">This board is open hardware licensed under the <a href="https://ohwr.org/cern_ohl_p_v2.txt">CERN Open Hardware Licence Version 2 - Permissive</a>
+license. Feel free to make as many of this board as you wish and sell them, as long as your follow the
+terms.
+</p><!-- l. 99 --><p class="indent"> Contributions welcome and will be appreciated. If you have any suggestions to improve the board,
+please feel free to contact the author. The author’s contact information can be found on the project
+homepage.
+<a id="x1-3001r3"></a>
+</p>
+ <h2 id="tocanch3" class="tvis"><span class="titlemark">4 </span> <a id="x1-40004"></a>Safety notice</h2>
+<!-- l. 105 --><p class="noindent">There’s no enclosure for this board. As a result there would be exposed conductors on both sides of the board.
+You’re advised to take measures to prevent them from shorting out. You may try any combination of the
+following:
+</p>
+ <ul class="itemize1">
+ <li class="itemize">
+ <!-- l. 110 --><p class="noindent">Placing the board on an non-conductive surface.
+ </p></li>
+ <li class="itemize">
+ <!-- l. 111 --><p class="noindent">There are two M2 mounting holes in the board. Using two M2 screws and nuts, install a plastic sheet
+ (or cardboard even) under and / or over the board.
+
+
+ </p></li>
+ <li class="itemize">
+ <!-- l. 113 --><p class="noindent">Don’t use the board at all. Don’t even think about it.</p></li></ul>
+<!-- l. 116 --><p class="indent"> Again, if you fried your equipment while using this board, it’s all your fault. I mean not really – I would still
+want to know what happened. But it’s all your fault.
+
+
+<a id="x1-4001r4"></a>
+</p>
+ <h2 id="tocanch4" class="tvis"><span class="titlemark">5 </span> <a id="x1-50005"></a>Intended usage and applicable devices</h2>
+<!-- l. 124 --><p class="noindent">RBUS-ADAT is designed for use with the Roland XV-5080. It converts the 8 digital outputs exposed by XV-5080’s
+R-BUS port to a standard ADAT lightpipe stream which can be recorded with any audio interface with an ADAT
+input.
+</p><!-- l. 128 --><p class="indent"> The ADAT output from this converter is 20-bit and has the same sampling rate as the input supplied from the
+R-BUS port.
+</p><!-- l. 131 --><p class="indent"> This converter <span class="ec-qplb-x-x-109">cannot</span>:
+</p>
+ <ul class="itemize1">
+ <li class="itemize">
+ <!-- l. 134 --><p class="noindent">Convert ADAT back to R-BUS input. i.e. you can’t record an ADAT stream on a V-Studio through
+ R-BUS with this converter.
+ </p></li>
+ <li class="itemize">
+ <!-- l. 136 --><p class="noindent">Serve as a clock source for the connected R-BUS device. You should always select “internal” as the
+ clock source for the connected R-BUS device.
+ </p></li>
+ <li class="itemize">
+ <!-- l. 138 --><p class="noindent">Expose the MIDI interface on the R-BUS port.</p></li></ul>
+<!-- l. 141 --><p class="indent"> The converter is designed and tested with the XV-5080. In addition, the only audio interface that
+has been verified to work is Focusrite Scarlett 18i8 3rd gen. I don’t have the resources to test other
+devices.
+</p><!-- l. 145 --><p class="indent"> The converter has not been tested against VM- or VS- devices that feature RMDB 2 / R-BUS ports
+or MV-8<span class="cmsy-10x-x-109">××× </span>fitted with the MV8-OP1 expansion but may still work as a unidirectional converter
+as intended. If you decide to try this converter with these devices, reporting the results would be
+appreciated.
+</p><!-- l. 151 --><p class="indent"> The converter is not compatible with devices with the older RMDB port.
+<a id="x1-5001r5"></a>
+</p>
+ <h2 id="tocanch5" class="tvis"><span class="titlemark">6 </span> <a id="x1-60006"></a>What’s on the board</h2>
+<div class="center">
+<!-- l. 155 --><p class="noindent">
+</p><!-- l. 156 --><p class="noindent"><img height="341" alt="PIC" src="//filestorage.chrisoft.org/blog/img/rbus-adat-tvp.png" decoding="async"></p></div>
+ <ol class="enumerate1">
+<li class="enumerate" id="x1-6002x1">
+ <!-- l. 160 --><p class="noindent"><span class="ec-qplb-x-x-109">R-BUS DB-25 Connector</span>. See “Choosing a suitable cable” for what you should and shouldn’t plug
+ into this connector.
+ </p></li>
+<li class="enumerate" id="x1-6004x2">
+ <!-- l. 162 --><p class="noindent"><span class="ec-qplb-x-x-109">Power indicator</span>. Illuminates if the board is receiving power.
+
+
+ </p></li>
+<li class="enumerate" id="x1-6006x3">
+ <!-- l. 164 --><p class="noindent"><span class="ec-qplb-x-x-109">ADAT Lightpipe output</span>. Connect to a device capable of recording ADAT data stream with a
+ TOSLINK cable.
+ </p></li>
+<li class="enumerate" id="x1-6008x4">
+ <!-- l. 166 --><p class="noindent"><span class="ec-qplb-x-x-109">Pure hecking magic</span>.</p></li></ol>
+<p><a id="x1-6009r6"></a></p>
+ <h2 id="tocanch6" class="tvis"><span class="titlemark">7 </span> <a id="x1-70007"></a>Quick start</h2>
+ <ol class="enumerate1">
+<li class="enumerate" id="x1-7002x1">
+ <!-- l. 172 --><p class="noindent">Using a suitable cable (see the following chapter), connect the R-BUS DB-25 connector on the board
+ to the R-BUS port on your Roland device.
+ </p></li>
+<li class="enumerate" id="x1-7004x2">
+ <!-- l. 174 --><p class="noindent">Connect the ADAT output on the board to the ADAT input of your recording equipment with a
+ TOSLINK optical fiber cable.
+ </p></li>
+<li class="enumerate" id="x1-7006x3">
+ <!-- l. 176 --><p class="noindent">Turn on the Roland device, then turn on your recording equipment.</p></li></ol>
+<p><a id="x1-7007r7"></a></p>
+ <h2 id="tocanch7" class="tvis"><span class="titlemark">8 </span> <a id="x1-80008"></a>Choosing a suitable cable</h2>
+<!-- l. 181 --><p class="noindent">DO <span class="ec-qplb-x-x-109">NOT </span>USE ROLAND’S OFFICIAL R-BUS CABLE!!!
+</p><!-- l. 183 --><p class="indent"> Please use a straight through DB-25 male-to-male (pins on both ends) cable to connect the R-BUS port on your
+device to the port on the converter. These cables connect pin 1 to pin 1, pin 2 to pin 2, pin 3 to pin 3
+etc. These cables are usually sold as “DB-25 RS-232 serial cable”. Do NOT use any of the following
+cables:
+</p>
+ <ul class="itemize1">
+ <li class="itemize">
+ <!-- l. 190 --><p class="noindent">Roland’s official R-BUS / RMDB 2 cable
+ </p></li>
+ <li class="itemize">
+ <!-- l. 191 --><p class="noindent">Parallel port cable
+ </p></li>
+ <li class="itemize">
+ <!-- l. 192 --><p class="noindent">SCSI cable
+ </p></li>
+ <li class="itemize">
+
+
+ <!-- l. 193 --><p class="noindent">LPT port Printer cable
+ </p></li>
+ <li class="itemize">
+ <!-- l. 194 --><p class="noindent">Null modem cable</p></li></ul>
+<!-- l. 197 --><p class="indent"> These cables all use the same DB-25 connector but are wired differently. Using the wrong cable may damage the
+converter and / or your device.
+</p><!-- l. 200 --><p class="indent"> Note that many RS-232 serial cables designed for relatively newer computers use the DE-9 connector. You’ll
+need the older style with DB-25 connectors (which conveniently have 25 pins).
+</p><!-- l. 204 --><p class="indent"> DO <span class="ec-qplb-x-x-109">NOT </span>USE ROLAND’S OFFICIAL R-BUS CABLE!!!
+<a id="x1-8001r8"></a>
+</p>
+ <h2 id="tocanch8" class="tvis"><span class="titlemark">9 </span> <a id="x1-90009"></a>Notes</h2>
+ <ul class="itemize1">
+ <li class="itemize">
+ <!-- l. 209 --><p class="noindent">Digital recording made from Scarlett 18i8 of the converted ADAT stream seem to have the full 24-bit
+ resolution. However this might be due to interpolation done by the audio interface or the operating
+ system. I do not have proper equipment to verify the bit depth of the output data stream. As such,
+ only 20 bits out output resolution is guaranteed.
+ </p></li>
+ <li class="itemize">
+ <!-- l. 215 --><p class="noindent">The optical output port is a tight fit. You have to insert the plug all the way in until you hear a click.</p></li></ul>
+<p><a id="x1-9001r9"></a></p>
+ <h2 id="tocanch9" class="tvis"><span class="titlemark">10 </span> <a id="x1-1000010"></a>Specifications</h2>
+<div class="center">
+<!-- l. 220 --><p class="noindent">
+</p>
+ <table class="tabular" id="TBL-4"><colgroup id="TBL-4-1g"><col id="TBL-4-1"></colgroup><colgroup id="TBL-4-2g"><col id="TBL-4-2"></colgroup><tbody><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-1-"><td class="td11" id="TBL-4-1-1" style="white-space:nowrap; text-align:left;"> Signal processing </td><td class="td11" id="TBL-4-1-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent">24-bit internal, 20-bit output </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-2-"><td class="td11" id="TBL-4-2-1" style="white-space:nowrap; text-align:left;"> Sampling rate </td><td class="td11" id="TBL-4-2-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent">44.1 kHz, 48 kHz </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-3-"><td class="td11" id="TBL-4-3-1" style="white-space:nowrap; text-align:left;"> Connectors </td><td class="td11" id="TBL-4-3-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent">R-BUS (Input only): DB-25<br class="newline">Digital output: ADAT Lightpipe (JIS F05 connector) </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-4-"><td class="td11" id="TBL-4-4-1" style="white-space:nowrap; text-align:left;"> Chipset </td><td class="td11" id="TBL-4-4-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent">coolaudio V1401 (Alesis AL1401 equiv.) </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-5-"><td class="td11" id="TBL-4-5-1" style="white-space:nowrap; text-align:left;"> Rated current </td><td class="td11" id="TBL-4-5-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent"><span class="cmmi-10x-x-109">&lt;</span>8 mA </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-4-6-"><td class="td11" id="TBL-4-6-1" style="white-space:nowrap; text-align:left;"> Rated power </td><td class="td11" id="TBL-4-6-2" style="white-space:normal; text-align:left;"> <!-- l. 232 --><p class="noindent"><span class="cmmi-10x-x-109">&lt;</span>0.04 W </p></td>
+</tr><tr class="hline"><td><hr></td><td><hr></td></tr></tbody></table></div>
+<p><a id="x1-10001r10"></a></p>
+ <h2 id="tocanch10" class="tvis"><span class="titlemark">11 </span> <a id="x1-1100011"></a>Appendices</h2>
+<p><a id="x1-11001r1"></a></p>
+ <h3 id="tocanch11" class="tvis"><span class="titlemark">11.1 </span> <a id="x1-120001"></a>Build instructions</h3>
+<!-- l. 240 --><p class="noindent">This is intended for people who didn’t end up with a pre-assembled board. If you already have a fully assembled
+board, you may ignore this section.
+</p><!-- l. 243 --><p class="indent"> If you have a kit, you may skip to step 3.
+<a id="x1-12001r1"></a>
+</p>
+ <h4 id="tocanch12" class="tvis"><span class="titlemark">11.1.1 </span> <a id="x1-130001"></a>PCB production</h4>
+<!-- l. 247 --><p class="noindent">I assume if you have chosen to take this route, you know what you are doing.
+
+
+</p><!-- l. 249 --><p class="indent"> You’ll find Gerber files in the <span class="obeylines-h"><span class="verb"><span class="ectt-1095">out</span></span></span> directory of the project repository that you can upload to your favorite PCB
+production service provider. Or alternatively if you want to tweak the board you can open up the KiCad project
+files, which are also found in the project repository.
+</p><!-- l. 254 --><p class="indent"> Many PCB manufacturers will add a board identifier to each PCB they make and allow customization of where
+this identifier will be placed. The front side silkscreen text “Production ID” is reserved for this purpose. Please refer
+to the ordering instructions of your PCB manufacturer for the details. Usually this will involve changing
+the text to something specific to that manufacturer and selecting an option before submitting your
+order.
+<a id="x1-13001r13"></a>
+</p>
+ <h4 id="tocanch13" class="tvis"><span class="titlemark">11.1.2 </span> <a id="x1-140002"></a>Bill of materials</h4>
+ <div class="minipage"><div class="center">
+<!-- l. 264 --><p class="noindent">
+</p>
+<div class="tabular"> <table class="tabular" id="TBL-5"><colgroup id="TBL-5-1g"><col id="TBL-5-1"></colgroup><colgroup id="TBL-5-2g"><col id="TBL-5-2"></colgroup><colgroup id="TBL-5-3g"><col id="TBL-5-3"></colgroup><tbody><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-1-"><td class="td11" id="TBL-5-1-1" style="white-space:nowrap; text-align:center;"> Designator </td><td class="td11" id="TBL-5-1-2" style="white-space:nowrap; text-align:center;"> Part </td><td class="td11" id="TBL-5-1-3" style="white-space:nowrap; text-align:center;"> Qty </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-2-"><td class="td11" id="TBL-5-2-1" style="white-space:nowrap; text-align:center;"> C1 </td><td class="td11" id="TBL-5-2-2" style="white-space:nowrap; text-align:center;"> 16V 100<span class="cmmi-10x-x-109">μ</span>F electrolytic </td><td class="td11" id="TBL-5-2-3" style="white-space:nowrap; text-align:center;"> 1 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-3-"><td class="td11" id="TBL-5-3-1" style="white-space:nowrap; text-align:center;"> C2, C3, C4 </td><td class="td11" id="TBL-5-3-2" style="white-space:nowrap; text-align:center;"> 50V 0.1<span class="cmmi-10x-x-109">μ</span>F ceramic </td><td class="td11" id="TBL-5-3-3" style="white-space:nowrap; text-align:center;"> 3 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-4-"><td class="td11" id="TBL-5-4-1" style="white-space:nowrap; text-align:center;"> CN1 </td><td class="td11" id="TBL-5-4-2" style="white-space:nowrap; text-align:center;"> Cliff FCR684208T </td><td class="td11" id="TBL-5-4-3" style="white-space:nowrap; text-align:center;"> 1 </td></tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-5-"><td class="td11" id="TBL-5-5-1" style="white-space:nowrap; text-align:center;"> D1 </td> <td class="td11" id="TBL-5-5-2" style="white-space:nowrap; text-align:center;"> 1N4002 </td> <td class="td11" id="TBL-5-5-3" style="white-space:nowrap; text-align:center;"> 1</td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-6-"><td class="td11" id="TBL-5-6-1" style="white-space:nowrap; text-align:center;"> D2 </td><td class="td11" id="TBL-5-6-2" style="white-space:nowrap; text-align:center;"> Red GaAsP / GaP LED 3mm <span class="footnote-mark"><a id="fn1x2-bk" href="#fn1x2"><sup class="textsuperscript">a</sup></a></span><a id="x1-14001f0"></a> </td><td class="td11" id="TBL-5-6-3" style="white-space:nowrap; text-align:center;"> 1 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-7-"><td class="td11" id="TBL-5-7-1" style="white-space:nowrap; text-align:center;"> J1 </td><td class="td11" id="TBL-5-7-2" style="white-space:nowrap; text-align:center;"> Adam Tech DB25-SL-25 <span class="footnote-mark"><a id="fn2x2-bk" href="#fn2x2"><sup class="textsuperscript">b</sup></a></span><a id="x1-14002f0"></a> </td><td class="td11" id="TBL-5-7-3" style="white-space:nowrap; text-align:center;"> 1 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-8-"><td class="td11" id="TBL-5-8-1" style="white-space:nowrap; text-align:center;"> R1 </td><td class="td11" id="TBL-5-8-2" style="white-space:nowrap; text-align:center;"> 1/4W 1k<span class="cmr-10x-x-109">Ω </span></td><td class="td11" id="TBL-5-8-3" style="white-space:nowrap; text-align:center;"> 1 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-9-"><td class="td11" id="TBL-5-9-1" style="white-space:nowrap; text-align:center;"> R2 </td><td class="td11" id="TBL-5-9-2" style="white-space:nowrap; text-align:center;"> 1/4W 2.2k<span class="cmr-10x-x-109">Ω </span></td><td class="td11" id="TBL-5-9-3" style="white-space:nowrap; text-align:center;"> 1 </td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-10-"><td class="td11" id="TBL-5-10-1" style="white-space:nowrap; text-align:center;"> U1 </td><td class="td11" id="TBL-5-10-2" style="white-space:nowrap; text-align:center;"> SN74LS04N </td><td class="td11" id="TBL-5-10-3" style="white-space:nowrap; text-align:center;"> 1 </td></tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr><tr style="vertical-align:baseline;" id="TBL-5-11-"><td class="td11" id="TBL-5-11-1" style="white-space:nowrap; text-align:center;"> U2 </td> <td class="td11" id="TBL-5-11-2" style="white-space:nowrap; text-align:center;"> coolaudio V1401 </td> <td class="td11" id="TBL-5-11-3" style="white-space:nowrap; text-align:center;"> 1</td>
+</tr><tr class="hline"><td><hr></td><td><hr></td><td><hr></td></tr></tbody></table>
+</div></div></div>
+<p><a id="x1-14003r14"></a></p>
+ <h4 id="tocanch14" class="tvis"><span class="titlemark">11.1.3 </span> <a id="x1-150003"></a>Assembling</h4>
+<!-- l. 284 --><p class="noindent">Again, I assume if you are assembling the board yourself, you possess the appropriate set of skills. It’s now time for
+them to shine. Most components are through hole so it should be easy. If it’s not already obvious, solder the only
+SMD chip first.
+<a id="x1-15001r15"></a>
+</p>
+ <h4 id="tocanch15" class="tvis"><span class="titlemark">11.1.4 </span> <a id="x1-160004"></a>Testing</h4>
+<!-- l. 291 --><p class="noindent">If you have a 5V power source, it is suggested to test your assembled board first. Supply 5V between the anode of
+the D1 and the metal shell of the DB-25 connector (GND). Check if anything pops.
+<a id="x1-16001r12"></a>
+</p>
+ <h3 id="tocanch16" class="tvis"><span class="titlemark">11.2 </span> <a id="x1-170002"></a>Useful links</h3>
+ <ul class="itemize1">
+ <li class="itemize">
+ <!-- l. 298 --><p class="noindent">R-BUS project homepage: <a class="url" href="https://chrisoft.org/rbusif"><span class="ectt-1095">https://chrisoft.org/rbusif</span></a>
+ </p></li>
+ <li class="itemize">
+ <!-- l. 299 --><p class="noindent">Project repository for this board: <a class="url" href="https://cgit.chrisoft.org/rbus-adat.git"><span class="ectt-1095">https://cgit.chrisoft.org/rbus-adat.git</span></a>
+ </p></li>
+ <li class="itemize">
+ <!-- l. 300 --><p class="noindent">Online version of this manual: <br class="newline"><a class="url" href="https://chrisoft.org/blog/post/rbus-adat-m.html"><span class="ectt-1095">https://chrisoft.org/blog/post/rbus-adat-m.html</span></a> (html version)<br class="newline"><a class="url" href="https://filestorage.chrisoft.org/blog/data/rbus_adat_m.pdf"><span class="ectt-1095">https://filestorage.chrisoft.org/blog/data/rbus_adat_m.pdf</span></a> (pdf version)</p></li></ul>
+<p><a id="x1-17001r17"></a></p>
+ <h3 id="tocanch17" class="tvis"><span class="titlemark">11.3 </span> <a id="x1-180003"></a>Schematic</h3><div class="center">
+<!-- l. 306 --><p class="noindent">
+
+
+</p><!-- l. 307 --><p class="noindent"> <img alt="PIC" width="398" src="//filestorage.chrisoft.org/blog/img/schr-.png" decoding="async"></p></div>
+
+
+<p><a id="x1-18001r18"></a></p>
+ <h3 id="tocanch18" class="tvis"><span class="titlemark">11.4 </span> <a id="x1-190004"></a>Circuit board</h3>
+<!-- l. 312 --><p class="noindent">Front side </p>
+<div class="center">
+<!-- l. 313 --><p class="noindent">
+</p><!-- l. 314 --><p class="noindent"> <img alt="PIC" width="683" src="//filestorage.chrisoft.org/blog/img/pcbfr-.png" decoding="async"></p></div>
+
+
+<!-- l. 317 --><p class="noindent">Back side </p>
+<div class="center">
+<!-- l. 318 --><p class="noindent">
+</p><!-- l. 319 --><p class="noindent"> <img alt="PIC" width="683" src="//filestorage.chrisoft.org/blog/img/pcbbr-.png" decoding="async"></p></div>
+
+
+ <div class="footnotes"><!-- l. 272 --><p class="noindent"><span class="footnote-mark"><a id="fn1x2" href="#fn1x2-bk"><sup class="textsuperscript">a</sup></a></span><span class="ec-qplr-x-x-90">5mm used in prototypes</span></p>
+<!-- l. 273 --><p class="noindent"><span class="footnote-mark"><a id="fn2x2" href="#fn2x2-bk"><sup class="textsuperscript">b</sup></a></span><span class="ec-qplr-x-x-90">Or any right angle DB-25 receptacle with 8.1mm backset spacing</span></p> </div>
+
+
+</div><br><hr>
+ <div class="TText" id="notediv" style="font-size:80%;"></div>
+ <div id="insanch" style="height:3em;"></div>
+ <div id="footer" style="">
+ <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
+ <div style="text-align:center;" class="TText">
+ Proudly powered by SSBS <reduced style="font-size:70%;">(the static stupid blogging system)</reduced> 2.5
+ <br>
+ Content licensed under CC BY-SA 4.0. <span id="purgep" style="display:none;font-size:70%;">This page has passphrase(s) stored. Click <a href="javascript:_purgep()">here</a> to purge.</span>
+ </div>
+ </div>
+ <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
+ </div>
+ </div>
+ <div id="decryptui" style="display:none;opacity:0;color:white;z-index:1000;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
+ <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
+ <div id="keyhint" style="margin-bottom:8px;"></div>
+ <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text" style="color:#fff;"></div>
+ <div style="height:2.25em;">
+ <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
+ <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
+ </div>
+
+ </div>
+
+
+</div></body></html> \ No newline at end of file
diff --git a/blog/sbs_1/bloglist.php b/blog/sbs_1/bloglist.php
deleted file mode 100644
index 32e59b7..0000000
--- a/blog/sbs_1/bloglist.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
-<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Chrisoft::Blog</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <script type="text/javascript">
-function ol()
-{
-if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- document.getElementById("tab").style.width="96%";
-}
- </script>
-</head>
-<body onload="ol()">
- <table id="tab" border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;" colspan="2">
- <a href="../">Chrisoft</a>::Blog
- </td>
- </tr>
- <tr>
- <td class="TText" colspan="2" style="padding:10px;">
- <div style="font-size:200%">Deprecated. The new blog system is available <a href="/blog">here</a>.</div>
- WARNING: You've entered the dangerous zone.<br>
- I occasionally empty the trash in my brain here...<br>
- Browse with care!<br>
- Most posts are in Chinese...
- </td>
- </tr>
- <tr><td class="TText" colspan="2">
- <?php
- $files=scandir("/var/www/html/blog/content",1);
- for($i=0,$c=count($files);$i<$c;$i++)
- {
- if(!(strstr($files[$i],"txt")))continue;
- if(strstr($files[$i],"swp"))continue;
- $fn=sprintf("/var/www/html/blog/content/%s",$files[$i]);
- $handle=fopen($fn, "r");
- $title="";$date="";$tags="";
- if($handle)
- {
- $title=fgets($handle,4096);
- $date=fgets($handle,4096);
- $tags=fgets($handle,4096);
- fclose($handle);
- }
- if(!strstr($tags,"devel"))
- {
- echo "<tr><td class=\"TText\" style=\"width:50%;\">";
- $cur=sprintf("<a href=\"./blogreader.php?p=%s\">%s</a>",substr($files[$i],0,strlen($files[$i])-4),$title);
- echo $cur;
- echo "</td><td class=\"TText\" style=\"width:50%;\">";
- echo $date;
- echo "</td></tr>";
- }
- }
- ?>
- </td></tr>
- <tr>
- <td class="TText" colspan="2" style="padding:10px;text-align:center;">
- Proudly powered by SBS <reduced>(the stupid blogging system)</reduced>.<br>
- Content licensed under CC BY-SA 4.0.
- </td>
- </tr>
- </table>
-</body>
diff --git a/blog/sbs_1/bloglista.php b/blog/sbs_1/bloglista.php
deleted file mode 100644
index bb762b7..0000000
--- a/blog/sbs_1/bloglista.php
+++ /dev/null
@@ -1,202 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <title>Chrisoft::Blog</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <style type="text/css">
- div#button
- {
- display:table;
- position:fixed;
- top:50%;
- margin-top:-3.5em;
- width:4em;
- height:7em;
- text-align:center;
- font-weight:bold;
- background-color:rgba(255,204,255,0.5);
- color:#EE8899;
- }
- div#button:hover
- {
- background-color:rgba(255,220,255,0.7);
- color:#FF66CC;
- }
- </style>
- <script type="text/javascript">
- var titles=[],dates=[],links=[],elems=[],oldelems=[],xs=[],ys=[];
- var numPost=5;
- var startIdx=0;
- var dragging=null;
- var xp=0,yp=0,xe=0,ye=0;
- function chk(tx,ty)
- {
- for(var i=0;i<xs.length;++i)
- if(Math.hypot(tx-xs[i],ty-ys[i])<100)return 1;
- return 0;
- }
- function dragInit(e)
- {
- dragging=e;xe=xp-dragging.offsetLeft;ye=yp-dragging.offsetTop;
- e.style.transition="none";
- }
- function onMove(e)
- {
- xp=document.all?window.event.clientX:e.pageX;
- yp=document.all?window.event.clientY:e.pageY;
- if(dragging!==null)
- {
- dragging.style.left=(xp-xe)+'px';
- dragging.style.top=(yp-ye)+'px';
- }
- }
- function initTile(obj,inv)
- {
- var t=0;
- t=Math.random()*window.innerHeight;
- obj.style.top=t.toString()+'px';
- t=window.innerWidth+Math.random()*window.innerWidth*0.7+window.innerWidth*0.1;
- if(inv==1)t-=2*window.innerWidth;
- obj.style.left=t.toString()+'px';
- t=Math.random()*360;
- obj.style.transform='rotate('+t.toString()+'deg)';
- }
- function launchTileIn(obj)
- {
- var tx=0,ty=0;
- obj.style.transition="all 0.5s ease-out";
- do{
- tx=Math.random()*window.innerHeight*0.35+window.innerHeight*0.35;
- ty=Math.random()*window.innerWidth*0.6+window.innerWidth*0.1;
- }while(chk(tx,ty)==1);
- obj.style.top=tx.toString()+'px';
- obj.style.left=ty.toString()+'px';
- xs.push(tx);ys.push(ty);
- tx=Math.random()*90-45;
- obj.style.transform='rotate('+tx.toString()+'deg)';
- }
- function launchTileOut(obj,inv)
- {
- var t=0;
- obj.style.transition="all 0.5s ease-in";
- t=Math.random()*window.innerHeight;
- obj.style.top=t.toString()+'px';
- t=0-obj.offsetWidth-Math.random()*window.innerWidth;
- if(inv==1)t=window.innerWidth-t;
- obj.style.left=t.toString()+'px';
- t=Math.random()*90-45;
- obj.style.transform='rotate('+t.toString()+'deg)';
- }
- function createTile(id)
- {
- var e=document.createElement("table");
- e.className="TText";
- e.style.position="fixed";
- e.style.cursor="move";
- e.style.boxShadow="1px 1px 1px 1px #333333";
- e.innerHTML="<tr><td><a href=\""+links[id]+"\">"+titles[id]+"</a></td></tr><tr><td>"+dates[id]+"</td></tr>";
- e.onmousedown=function(){dragInit(e);return false;};
- elems.push(e);
- document.getElementsByTagName("body")[0].appendChild(e);
- return e;
- }
- function createGroup(inv)
- {
- xs.length=ys.length=0;
- for(var i=0;i<numPost;++i)
- {
- if(startIdx+i>=titles.length)break;
- var e=createTile(startIdx+i);
- initTile(e,inv);
- }
- setTimeout(
- function(){for(var i=0;i<elems.length;++i)launchTileIn(elems[i]);}
- ,500);
- }
- function lastGroup()
- {
- if(startIdx-numPost<0)return;
- oldelems=elems.slice(0);elems.length=0;
- for(var i=0;i<oldelems.length;++i)launchTileOut(oldelems[i],1);
- setTimeout(
- function(){for(var i=0;i<oldelems.length;++i)oldelems[i].remove();}
- ,500);
- startIdx-=numPost;
- createGroup(1);
- }
- function nextGroup()
- {
- if(startIdx+numPost>=titles.length)return;
- oldelems=elems.slice(0);elems.length=0;
- for(var i=0;i<oldelems.length;++i)launchTileOut(oldelems[i],0);
- setTimeout(
- function(){for(var i=0;i<oldelems.length;++i)oldelems[i].remove();}
- ,500);
- startIdx+=numPost;
- createGroup(0);
- }
- function onWheel(e)
- {
- var wdelta=e.wheelDelta||-e.detail;
- if(wdelta<0)nextGroup();
- if(wdelta>0)lastGroup();
- }
- function init()
- {
- document.addEventListener("mousewheel",onWheel,false);
- document.addEventListener("DOMMouseScroll",onWheel,false);
- document.onmousemove=onMove;
- document.onmouseup=function(){dragging=null;};
- createGroup();
- }
- </script>
-</head>
-<body onload="init();">
- <table border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;" colspan="2">
- <a href="../">Chrisoft</a>::Blog
- </td>
- </tr>
- <tr>
- <td class="TText" colspan="2" style="padding:10px;">
- WARNING: You've entered the dangerous zone.<br>
- I occasionally empty the trash in my brain here...<br>
- Browse with care!<br>
- Most posts are in Chinese...
- </td>
- </tr>
- </table>
- <div onmousedown="lastGroup();" id="button" style="left:0;">
- <span style="display:table-cell;vertical-align:middle;">&lt;</span>
- </div>
- <div onmousedown="nextGroup();" id="button" style="right:0;">
- <span style="display:table-cell;vertical-align:middle;">&gt;</span>
- </div>
- <script type="text/javascript">
- <?php
- $files=scandir("/var/www/html/blog/content",1);
- for($i=0,$c=count($files);$i<$c;$i++)
- {
- if(!(strstr($files[$i],"txt")))continue;
- if(strstr($files[$i],"swp"))continue;
- $fn=sprintf("/var/www/html/blog/content/%s",$files[$i]);
- $handle=fopen($fn, "r");
- $title="";$date="";
- if($handle)
- {
- $title=fgets($handle,4096);
- $date=fgets($handle,4096);
- fclose($handle);
- }
- $title=substr($title,0,strlen($title)-1);
- $date=substr($date,0,strlen($date)-1);
- $cur=sprintf("links.push(\"./blogreader.php?p=%s\");titles.push(\"%s\");dates.push(\"%s\");\n",substr($files[$i],0,strlen($files[$i])-4),$title,$date);
- echo $cur;
- }
- ?>
- </script>
-</body>
diff --git a/blog/sbs_1/blogreader.php b/blog/sbs_1/blogreader.php
deleted file mode 100644
index 5f55cc7..0000000
--- a/blog/sbs_1/blogreader.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
-<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Chrisoft::Blog</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <script type="text/javascript" src="footnoter.js"></script>
- <script type="text/javascript" src="decryptor.js"></script>
- <script type="text/javascript">
-function ol()
-{
-if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- document.getElementById("tab").style.width="96%";
- footnoter();
-}
- </script>
-</head>
-<body onload="ol()">
- <table id="tab" border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;">
- <a href="../">Chrisoft</a>::<a href="./bloglist.php">Blog</a>
- </td>
- </tr>
- <tr>
- <td class="TText">
- <?php
- require_once("simple_html_dom.php");
- $path=sprintf("/var/www/html/blog/content/%s.txt",$_GET["p"]);
- $file=fopen($path,"r");
- if(!$file)
- {echo "Invalid parameter...";exit;}
- $str=fgets($file,4096);
- echo "<div style=\"text-align:center;font-size:1.7em\">".$str."</div><br>";
- $str=fgets($file,4096);
- echo "<div style=\"text-align:center;\">".$str."</div><br>";
- $str=fgets($file,4096);
- $str=fread($file,262144);
- $html=str_get_html($str);
- $encrypted=$html->find("encrypted");
- for($i=0;$i<count($encrypted);++$i)
- {
- $key=$html->find("encrypted",$i)->key;
- $html->find("encrypted",$i)->key=null;
- $cont=$html->find("encrypted",$i)->innertext;
- $html->find("encrypted",$i)->innertext="Encrypted content here. Click <a href=\"javascript:void(0)\" onclick=\"decryptui(".$i.")\">here</a> to decrypt.";
- $contarr=str_split($cont);
- $lcont=count($contarr);
- $keyarr=str_split($key);
- $lkey=count($keyarr);
- $hash=5381;
- for($j=0;$j<$lcont;++$j)
- {
- $hash=(($hash<<5)+$hash)+ord($contarr[$j]);
- $hash&=0xFFFFFFFF;
- $contarr[$j]^=$keyarr[$j%$lkey];
- }
- $retstr='';
- array_walk($contarr,function($value)use(&$retstr){$retstr.=chr(ord($value));});
- $html->find("encrypted",$i)->encont=base64_encode($retstr);
- $html->find("encrypted",$i)->hash=$hash;
- $html->find("encrypted",$i)->id="encrypted".$i;
- }
- echo $html;
- fclose($file);
- ?>
- </td>
- </tr>
- <tr><td><hr><reduced id="notediv"></reduced></td></tr>
- </table>
- <div id="decryptui" style="display:none;opacity:0;color:white;z-index:10;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
- <div class="TText" style="padding:20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
- <span id="keyhint"></span><br><br>
- Key: <input id="keyinp" type="text"><br><br>
- <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
- <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
- </form>
- </div>
- </body>
-</html>
diff --git a/blog/sbs_1/blossom.png b/blog/sbs_1/blossom.png
deleted file mode 100644
index 6f2c304..0000000
--- a/blog/sbs_1/blossom.png
+++ /dev/null
Binary files differ
diff --git a/blog/sbs_1/dbloglist.php b/blog/sbs_1/dbloglist.php
deleted file mode 100644
index c2bd137..0000000
--- a/blog/sbs_1/dbloglist.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
-<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Chrisoft::Development Blog</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <script type="text/javascript">
-function ol()
-{
-if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- document.getElementById("tab").style.width="96%";
-}
- </script>
-</head>
-<body onload="ol()">
- <table id="tab" border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;" colspan="2">
- <a href="../">Chrisoft</a>::Development Blog
- </td>
- </tr>
- <tr>
- <td class="TText" colspan="2" style="padding:10px;">
- <div style="font-size:200%">Deprecated. The new blog system is available <a href="/blog">here</a>.</div>
- Development blog.<br>
- Most posts here are in English...
- </td>
- </tr>
- <tr><td class="TText" colspan="2">
- <?php
- $files=scandir("/var/www/html/blog/content",1);
- for($i=0,$c=count($files);$i<$c;$i++)
- {
- if(!(strstr($files[$i],"txt")))continue;
- if(strstr($files[$i],"swp"))continue;
- $fn=sprintf("/var/www/html/blog/content/%s",$files[$i]);
- $handle=fopen($fn, "r");
- $title="";$date="";$tags="";
- if($handle)
- {
- $title=fgets($handle,4096);
- $date=fgets($handle,4096);
- $tags=fgets($handle,4096);
- fclose($handle);
- }
- if(strstr($tags,"devel"))
- {
- echo "<tr><td class=\"TText\" style=\"width:50%;\">";
- $cur=sprintf("<a href=\"./dblogreader.php?p=%s\">%s</a>",substr($files[$i],0,strlen($files[$i])-4),$title);
- echo $cur;
- echo "</td><td class=\"TText\" style=\"width:50%;\">";
- echo $date;
- echo "</td></tr>";
- }
- }
- ?>
- </td></tr>
- <tr>
- <td class="TText" colspan="2" style="padding:10px;text-align:center;">
- Proudly powered by SBS <reduced>(the stupid blogging system)</reduced>.<br>
- Content licensed under CC BY-SA 4.0.
- </td>
- </tr>
- </table>
-</body>
diff --git a/blog/sbs_1/dblogreader.php b/blog/sbs_1/dblogreader.php
deleted file mode 100644
index d252c19..0000000
--- a/blog/sbs_1/dblogreader.php
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
-<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Chrisoft::Development Blog</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <script type="text/javascript" src="footnoter.js"></script>
- <script type="text/javascript" src="decryptor.js"></script>
- <script type="text/javascript">
-function ol()
-{
-if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- document.getElementById("tab").style.width="96%";
- footnoter();
-}
- </script>
-</head>
-<body onload="ol()">
- <table id="tab" border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;">
- <a href="../">Chrisoft</a>::<a href="./dbloglist.php">Development Blog</a>
- </td>
- </tr>
- <tr>
- <td class="TText">
- <?php
- require_once("simple_html_dom.php");
- $path=sprintf("/var/www/html/blog/content/%s.txt",$_GET["p"]);
- $file=fopen($path,"r");
- if(!$file)
- {echo "Invalid parameter...";exit;}
- $str=fgets($file,4096);
- echo "<div style=\"text-align:center;font-size:1.7em\">".$str."</div><br>";
- $str=fgets($file,4096);
- echo "<div style=\"text-align:center;\">".$str."</div><br>";
- $str=fgets($file,4096);
- $str=fread($file,262144);
- $html=str_get_html($str);
- $encrypted=$html->find("encrypted");
- for($i=0;$i<count($encrypted);++$i)
- {
- $key=$html->find("encrypted",$i)->key;
- $html->find("encrypted",$i)->key=null;
- $cont=$html->find("encrypted",$i)->innertext;
- $html->find("encrypted",$i)->innertext="Encrypted content here. Click <a href=\"javascript:void(0)\" onclick=\"decryptui(".$i.")\">here</a> to decrypt.";
- $contarr=str_split($cont);
- $lcont=count($contarr);
- $keyarr=str_split($key);
- $lkey=count($keyarr);
- $hash=5381;
- for($j=0;$j<$lcont;++$j)
- {
- $hash=(($hash<<5)+$hash)+ord($contarr[$j]);
- $hash&=0xFFFFFFFF;
- $contarr[$j]^=$keyarr[$j%$lkey];
- }
- $retstr='';
- array_walk($contarr,function($value)use(&$retstr){$retstr.=chr(ord($value));});
- $html->find("encrypted",$i)->encont=base64_encode($retstr);
- $html->find("encrypted",$i)->hash=$hash;
- $html->find("encrypted",$i)->id="encrypted".$i;
- }
- echo $html;
- fclose($file);
- ?>
- </td>
- </tr>
- <tr><td><hr><reduced id="notediv"></reduced></td></tr>
- </table>
- <div id="decryptui" style="display:none;opacity:0;color:white;z-index:10;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
- <div class="TText" style="padding:20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
- <span id="keyhint"></span><br><br>
- Key: <input id="keyinp" type="text"><br><br>
- <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
- <button onclick="hidedecryptui();">Cancel</button>
- </form>
- </div>
- </body>
-</html>
diff --git a/blog/sbs_1/decryptor.js b/blog/sbs_1/decryptor.js
deleted file mode 100644
index dcd64e3..0000000
--- a/blog/sbs_1/decryptor.js
+++ /dev/null
@@ -1,73 +0,0 @@
-//License: Expat(MIT)
-//Chrisoft Xiong 2017
-// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
-function Utf8ArrayToStr(array){
- var out,i,len,c;
- var char2,char3;
- out="";
- len=array.length;
- i=0;
- while(i<len){
- c=array[i++];
- switch(c>>4)
- {
- case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:
- // 0xxxxxxx
- out+=String.fromCharCode(c);
- break;
- case 12:case 13:
- // 110x xxxx 10xx xxxx
- char2=array[i++];
- out+=String.fromCharCode(((c&0x1F)<<6)|(char2&0x3F));
- break;
- case 14:
- // 1110 xxxx 10xx xxxx 10xx xxxx
- char2=array[i++];
- char3=array[i++];
- out+=String.fromCharCode(((c&0x0F)<<12)|
- ((char2&0x3F)<<6)|
- ((char3&0x3F)<<0));
- break;
- }
- }
- return out;
-}
-var decid;
-function decryptui(id)
-{
- document.getElementById("decryptui").style.display="block";
- document.getElementById("keyinp").focus();
- setTimeout(function(){document.getElementById("decryptui").style.opacity="1";},20);
- decid=id;
- document.getElementById("keyhint").innerHTML="Hint: "+document.getElementById("encrypted"+id).getAttribute("hint");
- document.getElementById("keyinp").onkeypress=function(e){if(e.keyCode==13)document.getElementById('btndecrypt').click();}
-}
-function hidedecryptui()
-{
- document.getElementById("decryptui").style.opacity="0";
- setTimeout(function(){
- document.getElementById("decryptui").style.display="none";
- document.getElementById("keyinp").value="";
- },500);
-}
-function decryptor(id,key)
-{
- var e=document.getElementById("encrypted"+id);
- var cont=e.getAttribute("encont");
- var bc=atob(cont);
- var b=new Array(bc.length);
- for(var i=0;i<bc.length;++i)b[i]=bc.charCodeAt(i);
- var lkey=key.length;
- var u8arr=new Uint8Array(b);
- var hash=5381;
- for(var i=0;i<u8arr.length;++i){u8arr[i]^=key.charCodeAt(i%lkey);hash=(hash*33)+u8arr[i];hash%=4294967296;}
- if(hash!=parseInt(e.getAttribute("hash")))
- {
- alert("The decryption key you have entered could be wrong, please try again.");
- return;
- }
- //e.innerHTML=new TextDecoder("utf-8").decode(u8arr);
- e.innerHTML=Utf8ArrayToStr(u8arr);
- footnoter();
- hidedecryptui();
-}
diff --git a/blog/sbs_1/extras.css b/blog/sbs_1/extras.css
deleted file mode 100644
index 6409ebe..0000000
--- a/blog/sbs_1/extras.css
+++ /dev/null
@@ -1,50 +0,0 @@
-.CTitle {
- color: #fff;
-}
-.TText {
- color: #fff;
-}
-body {
- background: #000;
- background-image: url(blossom.png);
-}
-table {
- background: rgba(0,0,0,0.8);
-}
-p {
- text-indent: 2em;
-}
-note, .note {
- vertical-align: super;
- font-size: 60%;
-}
-reduced, .reduced {
- font-size: 75%;
-}
-blockquote {
- padding: 1em;
- margin-left:4em;margin-right:4em;
-}
-enlarged, .enlarged {
- font-size: 125%;
-}
-button {
- border:none;
- color:white;
- padding:0.5em 2em;
- text-align:center;
- background-color:#C6C;
- -webkit-transition-duration:0.4s;
- transition-duration:0.4s;
-}
-button:hover {
- background-color:#E9E;
-}
-input {
- border: none;
- border-bottom: 2px solid #C6C;
- outline: none !important;
- background-color: rgba(0,0,0,0) !important;
- color: white;
-}
-
diff --git a/blog/sbs_1/footnoter.js b/blog/sbs_1/footnoter.js
deleted file mode 100644
index a1b2d8b..0000000
--- a/blog/sbs_1/footnoter.js
+++ /dev/null
@@ -1,24 +0,0 @@
-//License: MIT
-//Chrisoft Xiong 2017
-var starting=0;
-function footnoter()
-{
- var footnotes=document.body.getElementsByTagName("footnote");
- for(var i=0;i<footnotes.length;++i)
- {
- var s=footnotes[i].innerHTML;
- footnotes[i].innerHTML="";//IE is stupid
- var a=document.createElement("a");
- a.setAttribute("id","n"+(starting+i+1));
- a.setAttribute("href","#note"+(starting+i+1));
- a.setAttribute("class","note");
- a.innerHTML="["+(starting+i+1)+"]";
- footnotes[i].parentNode.insertBefore(a,footnotes[i]);
- var span=document.createElement("span");
- span.setAttribute("class","TText");
- span.innerHTML="<a id=\"note"+(starting+i+1)+"\" href=\"#n"+(starting+i+1)+"\">["+(starting+i+1)+"]</a>: "+s+"<br>";
- document.getElementById("notediv").appendChild(span);
- }
- starting+=footnotes.length;
- while(footnotes.length)footnotes[0].remove();
-}
diff --git a/blog/sbs_1/simple_html_dom.php b/blog/sbs_1/simple_html_dom.php
deleted file mode 100644
index 19e5f66..0000000
--- a/blog/sbs_1/simple_html_dom.php
+++ /dev/null
@@ -1,975 +0,0 @@
-<?php
-/*******************************************************************************
-Version: 1.11 ($Rev: 175 $)
-Website: http://sourceforge.net/projects/simplehtmldom/
-Author: S.C. Chen <me578022@gmail.com>
-Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
-Contributions by:
- Yousuke Kumakura (Attribute filters)
- Vadim Voituk (Negative indexes supports of "find" method)
- Antcs (Constructor with automatically load contents either text or file/url)
-Licensed under The MIT License
-Redistributions of files must retain the above copyright notice.
-*******************************************************************************/
-
-define('HDOM_TYPE_ELEMENT', 1);
-define('HDOM_TYPE_COMMENT', 2);
-define('HDOM_TYPE_TEXT', 3);
-define('HDOM_TYPE_ENDTAG', 4);
-define('HDOM_TYPE_ROOT', 5);
-define('HDOM_TYPE_UNKNOWN', 6);
-define('HDOM_QUOTE_DOUBLE', 0);
-define('HDOM_QUOTE_SINGLE', 1);
-define('HDOM_QUOTE_NO', 3);
-define('HDOM_INFO_BEGIN', 0);
-define('HDOM_INFO_END', 1);
-define('HDOM_INFO_QUOTE', 2);
-define('HDOM_INFO_SPACE', 3);
-define('HDOM_INFO_TEXT', 4);
-define('HDOM_INFO_INNER', 5);
-define('HDOM_INFO_OUTER', 6);
-define('HDOM_INFO_ENDSPACE',7);
-
-// helper functions
-// -----------------------------------------------------------------------------
-// get html dom form file
-function file_get_html() {
- $dom = new simple_html_dom;
- $args = func_get_args();
- $dom->load(call_user_func_array('file_get_contents', $args), true);
- return $dom;
-}
-
-// get html dom form string
-function str_get_html($str, $lowercase=true) {
- $dom = new simple_html_dom;
- $dom->load($str, $lowercase);
- return $dom;
-}
-
-// dump html dom tree
-function dump_html_tree($node, $show_attr=true, $deep=0) {
- $lead = str_repeat(' ', $deep);
- echo $lead.$node->tag;
- if ($show_attr && count($node->attr)>0) {
- echo '(';
- foreach($node->attr as $k=>$v)
- echo "[$k]=>\"".$node->$k.'", ';
- echo ')';
- }
- echo "\n";
-
- foreach($node->nodes as $c)
- dump_html_tree($c, $show_attr, $deep+1);
-}
-
-// get dom form file (deprecated)
-function file_get_dom() {
- $dom = new simple_html_dom;
- $args = func_get_args();
- $dom->load(call_user_func_array('file_get_contents', $args), true);
- return $dom;
-}
-
-// get dom form string (deprecated)
-function str_get_dom($str, $lowercase=true) {
- $dom = new simple_html_dom;
- $dom->load($str, $lowercase);
- return $dom;
-}
-
-// simple html dom node
-// -----------------------------------------------------------------------------
-class simple_html_dom_node {
- public $nodetype = HDOM_TYPE_TEXT;
- public $tag = 'text';
- public $attr = array();
- public $children = array();
- public $nodes = array();
- public $parent = null;
- public $_ = array();
- private $dom = null;
-
- function __construct($dom) {
- $this->dom = $dom;
- $dom->nodes[] = $this;
- }
-
- function __destruct() {
- $this->clear();
- }
-
- function __toString() {
- return $this->outertext();
- }
-
- // clean up memory due to php5 circular references memory leak...
- function clear() {
- $this->dom = null;
- $this->nodes = null;
- $this->parent = null;
- $this->children = null;
- }
-
- // dump node's tree
- function dump($show_attr=true) {
- dump_html_tree($this, $show_attr);
- }
-
- // returns the parent of node
- function parent() {
- return $this->parent;
- }
-
- // returns children of node
- function children($idx=-1) {
- if ($idx===-1) return $this->children;
- if (isset($this->children[$idx])) return $this->children[$idx];
- return null;
- }
-
- // returns the first child of node
- function first_child() {
- if (count($this->children)>0) return $this->children[0];
- return null;
- }
-
- // returns the last child of node
- function last_child() {
- if (($count=count($this->children))>0) return $this->children[$count-1];
- return null;
- }
-
- // returns the next sibling of node
- function next_sibling() {
- if ($this->parent===null) return null;
- $idx = 0;
- $count = count($this->parent->children);
- while ($idx<$count && $this!==$this->parent->children[$idx])
- ++$idx;
- if (++$idx>=$count) return null;
- return $this->parent->children[$idx];
- }
-
- // returns the previous sibling of node
- function prev_sibling() {
- if ($this->parent===null) return null;
- $idx = 0;
- $count = count($this->parent->children);
- while ($idx<$count && $this!==$this->parent->children[$idx])
- ++$idx;
- if (--$idx<0) return null;
- return $this->parent->children[$idx];
- }
-
- // get dom node's inner html
- function innertext() {
- if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER];
- if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
-
- $ret = '';
- foreach($this->nodes as $n)
- $ret .= $n->outertext();
- return $ret;
- }
-
- // get dom node's outer text (with tag)
- function outertext() {
- if ($this->tag==='root') return $this->innertext();
-
- // trigger callback
- if ($this->dom->callback!==null)
- call_user_func_array($this->dom->callback, array($this));
-
- if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER];
- if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
-
- // render begin tag
- $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
-
- // render inner text
- if (isset($this->_[HDOM_INFO_INNER]))
- $ret .= $this->_[HDOM_INFO_INNER];
- else {
- foreach($this->nodes as $n)
- $ret .= $n->outertext();
- }
-
- // render end tag
- if(isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0)
- $ret .= '</'.$this->tag.'>';
- return $ret;
- }
-
- // get dom node's plain text
- function text() {
- if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER];
- switch ($this->nodetype) {
- case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
- case HDOM_TYPE_COMMENT: return '';
- case HDOM_TYPE_UNKNOWN: return '';
- }
- if (strcasecmp($this->tag, 'script')===0) return '';
- if (strcasecmp($this->tag, 'style')===0) return '';
-
- $ret = '';
- foreach($this->nodes as $n)
- $ret .= $n->text();
- return $ret;
- }
-
- function xmltext() {
- $ret = $this->innertext();
- $ret = str_ireplace('<![CDATA[', '', $ret);
- $ret = str_replace(']]>', '', $ret);
- return $ret;
- }
-
- // build node's text with tag
- function makeup() {
- // text, comment, unknown
- if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
-
- $ret = '<'.$this->tag;
- $i = -1;
-
- foreach($this->attr as $key=>$val) {
- ++$i;
-
- // skip removed attribute
- if ($val===null || $val===false)
- continue;
-
- $ret .= $this->_[HDOM_INFO_SPACE][$i][0];
- //no value attr: nowrap, checked selected...
- if ($val===true)
- $ret .= $key;
- else {
- switch($this->_[HDOM_INFO_QUOTE][$i]) {
- case HDOM_QUOTE_DOUBLE: $quote = '"'; break;
- case HDOM_QUOTE_SINGLE: $quote = '\''; break;
- default: $quote = '';
- }
- $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote;
- }
- }
- $ret = $this->dom->restore_noise($ret);
- return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
- }
-
- // find elements by css selector
- function find($selector, $idx=null) {
- $selectors = $this->parse_selector($selector);
- if (($count=count($selectors))===0) return array();
- $found_keys = array();
-
- // find each selector
- for ($c=0; $c<$count; ++$c) {
- if (($levle=count($selectors[0]))===0) return array();
- if (!isset($this->_[HDOM_INFO_BEGIN])) return array();
-
- $head = array($this->_[HDOM_INFO_BEGIN]=>1);
-
- // handle descendant selectors, no recursive!
- for ($l=0; $l<$levle; ++$l) {
- $ret = array();
- foreach($head as $k=>$v) {
- $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k];
- $n->seek($selectors[$c][$l], $ret);
- }
- $head = $ret;
- }
-
- foreach($head as $k=>$v) {
- if (!isset($found_keys[$k]))
- $found_keys[$k] = 1;
- }
- }
-
- // sort keys
- ksort($found_keys);
-
- $found = array();
- foreach($found_keys as $k=>$v)
- $found[] = $this->dom->nodes[$k];
-
- // return nth-element or array
- if (is_null($idx)) return $found;
- else if ($idx<0) $idx = count($found) + $idx;
- return (isset($found[$idx])) ? $found[$idx] : null;
- }
-
- // seek for given conditions
- protected function seek($selector, &$ret) {
- list($tag, $key, $val, $exp, $no_key) = $selector;
-
- // xpath index
- if ($tag && $key && is_numeric($key)) {
- $count = 0;
- foreach ($this->children as $c) {
- if ($tag==='*' || $tag===$c->tag) {
- if (++$count==$key) {
- $ret[$c->_[HDOM_INFO_BEGIN]] = 1;
- return;
- }
- }
- }
- return;
- }
-
- $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
- if ($end==0) {
- $parent = $this->parent;
- while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) {
- $end -= 1;
- $parent = $parent->parent;
- }
- $end += $parent->_[HDOM_INFO_END];
- }
-
- for($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) {
- $node = $this->dom->nodes[$i];
- $pass = true;
-
- if ($tag==='*' && !$key) {
- if (in_array($node, $this->children, true))
- $ret[$i] = 1;
- continue;
- }
-
- // compare tag
- if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;}
- // compare key
- if ($pass && $key) {
- if ($no_key) {
- if (isset($node->attr[$key])) $pass=false;
- }
- else if (!isset($node->attr[$key])) $pass=false;
- }
- // compare value
- if ($pass && $key && $val && $val!=='*') {
- $check = $this->match($exp, $val, $node->attr[$key]);
- // handle multiple class
- if (!$check && strcasecmp($key, 'class')===0) {
- foreach(explode(' ',$node->attr[$key]) as $k) {
- $check = $this->match($exp, $val, $k);
- if ($check) break;
- }
- }
- if (!$check) $pass = false;
- }
- if ($pass) $ret[$i] = 1;
- unset($node);
- }
- }
-
- protected function match($exp, $pattern, $value) {
- switch ($exp) {
- case '=':
- return ($value===$pattern);
- case '!=':
- return ($value!==$pattern);
- case '^=':
- return preg_match("/^".preg_quote($pattern,'/')."/", $value);
- case '$=':
- return preg_match("/".preg_quote($pattern,'/')."$/", $value);
- case '*=':
- if ($pattern[0]=='/')
- return preg_match($pattern, $value);
- return preg_match("/".$pattern."/i", $value);
- }
- return false;
- }
-
- protected function parse_selector($selector_string) {
- // pattern of CSS selectors, modified from mootools
- $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
- preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER);
- $selectors = array();
- $result = array();
- //print_r($matches);
-
- foreach ($matches as $m) {
- $m[0] = trim($m[0]);
- if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue;
- // for borwser grnreated xpath
- if ($m[1]==='tbody') continue;
-
- list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false);
- if(!empty($m[2])) {$key='id'; $val=$m[2];}
- if(!empty($m[3])) {$key='class'; $val=$m[3];}
- if(!empty($m[4])) {$key=$m[4];}
- if(!empty($m[5])) {$exp=$m[5];}
- if(!empty($m[6])) {$val=$m[6];}
-
- // convert to lowercase
- if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);}
- //elements that do NOT have the specified attribute
- if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;}
-
- $result[] = array($tag, $key, $val, $exp, $no_key);
- if (trim($m[7])===',') {
- $selectors[] = $result;
- $result = array();
- }
- }
- if (count($result)>0)
- $selectors[] = $result;
- return $selectors;
- }
-
- function __get($name) {
- if (isset($this->attr[$name])) return $this->attr[$name];
- switch($name) {
- case 'outertext': return $this->outertext();
- case 'innertext': return $this->innertext();
- case 'plaintext': return $this->text();
- case 'xmltext': return $this->xmltext();
- default: return array_key_exists($name, $this->attr);
- }
- }
-
- function __set($name, $value) {
- switch($name) {
- case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value;
- case 'innertext':
- if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value;
- return $this->_[HDOM_INFO_INNER] = $value;
- }
- if (!isset($this->attr[$name])) {
- $this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
- $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
- }
- $this->attr[$name] = $value;
- }
-
- function __isset($name) {
- switch($name) {
- case 'outertext': return true;
- case 'innertext': return true;
- case 'plaintext': return true;
- }
- //no value attr: nowrap, checked selected...
- return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
- }
-
- function __unset($name) {
- if (isset($this->attr[$name]))
- unset($this->attr[$name]);
- }
-
- // camel naming conventions
- function getAllAttributes() {return $this->attr;}
- function getAttribute($name) {return $this->__get($name);}
- function setAttribute($name, $value) {$this->__set($name, $value);}
- function hasAttribute($name) {return $this->__isset($name);}
- function removeAttribute($name) {$this->__set($name, null);}
- function getElementById($id) {return $this->find("#$id", 0);}
- function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
- function getElementByTagName($name) {return $this->find($name, 0);}
- function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);}
- function parentNode() {return $this->parent();}
- function childNodes($idx=-1) {return $this->children($idx);}
- function firstChild() {return $this->first_child();}
- function lastChild() {return $this->last_child();}
- function nextSibling() {return $this->next_sibling();}
- function previousSibling() {return $this->prev_sibling();}
-}
-
-// simple html dom parser
-// -----------------------------------------------------------------------------
-class simple_html_dom {
- public $root = null;
- public $nodes = array();
- public $callback = null;
- public $lowercase = false;
- protected $pos;
- protected $doc;
- protected $char;
- protected $size;
- protected $cursor;
- protected $parent;
- protected $noise = array();
- protected $token_blank = " \t\r\n";
- protected $token_equal = ' =/>';
- protected $token_slash = " />\r\n\t";
- protected $token_attr = ' >';
- // use isset instead of in_array, performance boost about 30%...
- protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1);
- protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1);
- protected $optional_closing_tags = array(
- 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1),
- 'th'=>array('th'=>1),
- 'td'=>array('td'=>1),
- 'li'=>array('li'=>1),
- 'dt'=>array('dt'=>1, 'dd'=>1),
- 'dd'=>array('dd'=>1, 'dt'=>1),
- 'dl'=>array('dd'=>1, 'dt'=>1),
- 'p'=>array('p'=>1),
- 'nobr'=>array('nobr'=>1),
- );
-
- function __construct($str=null) {
- if ($str) {
- if (preg_match("/^http:\/\//i",$str) || is_file($str))
- $this->load_file($str);
- else
- $this->load($str);
- }
- }
-
- function __destruct() {
- $this->clear();
- }
-
- // load html from string
- function load($str, $lowercase=true) {
- // prepare
- $this->prepare($str, $lowercase);
- // strip out comments
- $this->remove_noise("'<!--(.*?)-->'is");
- // strip out cdata
- $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
- // strip out <style> tags
- $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
- $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
- // strip out <script> tags
- $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
- $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
- // strip out preformatted tags
- $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
- // strip out server side scripts
- $this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
- // strip smarty scripts
- $this->remove_noise("'(\{\w)(.*?)(\})'s", true);
-
- // parsing
- while ($this->parse());
- // end
- $this->root->_[HDOM_INFO_END] = $this->cursor;
- }
-
- // load html from file
- function load_file() {
- $args = func_get_args();
- $this->load(call_user_func_array('file_get_contents', $args), true);
- }
-
- // set callback function
- function set_callback($function_name) {
- $this->callback = $function_name;
- }
-
- // remove callback function
- function remove_callback() {
- $this->callback = null;
- }
-
- // save dom as string
- function save($filepath='') {
- $ret = $this->root->innertext();
- if ($filepath!=='') file_put_contents($filepath, $ret);
- return $ret;
- }
-
- // find dom node by css selector
- function find($selector, $idx=null) {
- return $this->root->find($selector, $idx);
- }
-
- // clean up memory due to php5 circular references memory leak...
- function clear() {
- foreach($this->nodes as $n) {$n->clear(); $n = null;}
- if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);}
- if (isset($this->root)) {$this->root->clear(); unset($this->root);}
- unset($this->doc);
- unset($this->noise);
- }
-
- function dump($show_attr=true) {
- $this->root->dump($show_attr);
- }
-
- // prepare HTML data and init everything
- protected function prepare($str, $lowercase=true) {
- $this->clear();
- $this->doc = $str;
- $this->pos = 0;
- $this->cursor = 1;
- $this->noise = array();
- $this->nodes = array();
- $this->lowercase = $lowercase;
- $this->root = new simple_html_dom_node($this);
- $this->root->tag = 'root';
- $this->root->_[HDOM_INFO_BEGIN] = -1;
- $this->root->nodetype = HDOM_TYPE_ROOT;
- $this->parent = $this->root;
- // set the length of content
- $this->size = strlen($str);
- if ($this->size>0) $this->char = $this->doc[0];
- }
-
- // parse html content
- protected function parse() {
- if (($s = $this->copy_until_char('<'))==='')
- return $this->read_tag();
-
- // text
- $node = new simple_html_dom_node($this);
- ++$this->cursor;
- $node->_[HDOM_INFO_TEXT] = $s;
- $this->link_nodes($node, false);
- return true;
- }
-
- // read tag info
- protected function read_tag() {
- if ($this->char!=='<') {
- $this->root->_[HDOM_INFO_END] = $this->cursor;
- return false;
- }
- $begin_tag_pos = $this->pos;
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
-
- // end tag
- if ($this->char==='/') {
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- $this->skip($this->token_blank_t);
- $tag = $this->copy_until_char('>');
-
- // skip attributes in end tag
- if (($pos = strpos($tag, ' '))!==false)
- $tag = substr($tag, 0, $pos);
-
- $parent_lower = strtolower($this->parent->tag);
- $tag_lower = strtolower($tag);
-
- if ($parent_lower!==$tag_lower) {
- if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) {
- $this->parent->_[HDOM_INFO_END] = 0;
- $org_parent = $this->parent;
-
- while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
- $this->parent = $this->parent->parent;
-
- if (strtolower($this->parent->tag)!==$tag_lower) {
- $this->parent = $org_parent; // restore origonal parent
- if ($this->parent->parent) $this->parent = $this->parent->parent;
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
- return $this->as_text_node($tag);
- }
- }
- else if (($this->parent->parent) && isset($this->block_tags[$tag_lower])) {
- $this->parent->_[HDOM_INFO_END] = 0;
- $org_parent = $this->parent;
-
- while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
- $this->parent = $this->parent->parent;
-
- if (strtolower($this->parent->tag)!==$tag_lower) {
- $this->parent = $org_parent; // restore origonal parent
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
- return $this->as_text_node($tag);
- }
- }
- else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) {
- $this->parent->_[HDOM_INFO_END] = 0;
- $this->parent = $this->parent->parent;
- }
- else
- return $this->as_text_node($tag);
- }
-
- $this->parent->_[HDOM_INFO_END] = $this->cursor;
- if ($this->parent->parent) $this->parent = $this->parent->parent;
-
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return true;
- }
-
- $node = new simple_html_dom_node($this);
- $node->_[HDOM_INFO_BEGIN] = $this->cursor;
- ++$this->cursor;
- $tag = $this->copy_until($this->token_slash);
-
- // doctype, cdata & comments...
- if (isset($tag[0]) && $tag[0]==='!') {
- $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
-
- if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') {
- $node->nodetype = HDOM_TYPE_COMMENT;
- $node->tag = 'comment';
- } else {
- $node->nodetype = HDOM_TYPE_UNKNOWN;
- $node->tag = 'unknown';
- }
-
- if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>';
- $this->link_nodes($node, true);
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return true;
- }
-
- // text
- if ($pos=strpos($tag, '<')!==false) {
- $tag = '<' . substr($tag, 0, -1);
- $node->_[HDOM_INFO_TEXT] = $tag;
- $this->link_nodes($node, false);
- $this->char = $this->doc[--$this->pos]; // prev
- return true;
- }
-
- if (!preg_match("/^[\w-:]+$/", $tag)) {
- $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
- if ($this->char==='<') {
- $this->link_nodes($node, false);
- return true;
- }
-
- if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>';
- $this->link_nodes($node, false);
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return true;
- }
-
- // begin tag
- $node->nodetype = HDOM_TYPE_ELEMENT;
- $tag_lower = strtolower($tag);
- $node->tag = ($this->lowercase) ? $tag_lower : $tag;
-
- // handle optional closing tags
- if (isset($this->optional_closing_tags[$tag_lower]) ) {
- while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
- $this->parent->_[HDOM_INFO_END] = 0;
- $this->parent = $this->parent->parent;
- }
- $node->parent = $this->parent;
- }
-
- $guard = 0; // prevent infinity loop
- $space = array($this->copy_skip($this->token_blank), '', '');
-
- // attributes
- do {
- if ($this->char!==null && $space[0]==='') break;
- $name = $this->copy_until($this->token_equal);
- if($guard===$this->pos) {
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- continue;
- }
- $guard = $this->pos;
-
- // handle endless '<'
- if($this->pos>=$this->size-1 && $this->char!=='>') {
- $node->nodetype = HDOM_TYPE_TEXT;
- $node->_[HDOM_INFO_END] = 0;
- $node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name;
- $node->tag = 'text';
- $this->link_nodes($node, false);
- return true;
- }
-
- // handle mismatch '<'
- if($this->doc[$this->pos-1]=='<') {
- $node->nodetype = HDOM_TYPE_TEXT;
- $node->tag = 'text';
- $node->attr = array();
- $node->_[HDOM_INFO_END] = 0;
- $node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1);
- $this->pos -= 2;
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- $this->link_nodes($node, false);
- return true;
- }
-
- if ($name!=='/' && $name!=='') {
- $space[1] = $this->copy_skip($this->token_blank);
- $name = $this->restore_noise($name);
- if ($this->lowercase) $name = strtolower($name);
- if ($this->char==='=') {
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- $this->parse_attr($node, $name, $space);
- }
- else {
- //no value attr: nowrap, checked selected...
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
- $node->attr[$name] = true;
- if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev
- }
- $node->_[HDOM_INFO_SPACE][] = $space;
- $space = array($this->copy_skip($this->token_blank), '', '');
- }
- else
- break;
- } while($this->char!=='>' && $this->char!=='/');
-
- $this->link_nodes($node, true);
- $node->_[HDOM_INFO_ENDSPACE] = $space[0];
-
- // check self closing
- if ($this->copy_until_char_escape('>')==='/') {
- $node->_[HDOM_INFO_ENDSPACE] .= '/';
- $node->_[HDOM_INFO_END] = 0;
- }
- else {
- // reset parent
- if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node;
- }
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return true;
- }
-
- // parse attributes
- protected function parse_attr($node, $name, &$space) {
- $space[2] = $this->copy_skip($this->token_blank);
- switch($this->char) {
- case '"':
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"'));
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- break;
- case '\'':
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE;
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\''));
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- break;
- default:
- $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
- $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr));
- }
- }
-
- // link node's parent
- protected function link_nodes(&$node, $is_child) {
- $node->parent = $this->parent;
- $this->parent->nodes[] = $node;
- if ($is_child)
- $this->parent->children[] = $node;
- }
-
- // as a text node
- protected function as_text_node($tag) {
- $node = new simple_html_dom_node($this);
- ++$this->cursor;
- $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
- $this->link_nodes($node, false);
- $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return true;
- }
-
- protected function skip($chars) {
- $this->pos += strspn($this->doc, $chars, $this->pos);
- $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- }
-
- protected function copy_skip($chars) {
- $pos = $this->pos;
- $len = strspn($this->doc, $chars, $pos);
- $this->pos += $len;
- $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- if ($len===0) return '';
- return substr($this->doc, $pos, $len);
- }
-
- protected function copy_until($chars) {
- $pos = $this->pos;
- $len = strcspn($this->doc, $chars, $pos);
- $this->pos += $len;
- $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
- return substr($this->doc, $pos, $len);
- }
-
- protected function copy_until_char($char) {
- if ($this->char===null) return '';
-
- if (($pos = strpos($this->doc, $char, $this->pos))===false) {
- $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
- $this->char = null;
- $this->pos = $this->size;
- return $ret;
- }
-
- if ($pos===$this->pos) return '';
- $pos_old = $this->pos;
- $this->char = $this->doc[$pos];
- $this->pos = $pos;
- return substr($this->doc, $pos_old, $pos-$pos_old);
- }
-
- protected function copy_until_char_escape($char) {
- if ($this->char===null) return '';
-
- $start = $this->pos;
- while(1) {
- if (($pos = strpos($this->doc, $char, $start))===false) {
- $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
- $this->char = null;
- $this->pos = $this->size;
- return $ret;
- }
-
- if ($pos===$this->pos) return '';
-
- if ($this->doc[$pos-1]==='\\') {
- $start = $pos+1;
- continue;
- }
-
- $pos_old = $this->pos;
- $this->char = $this->doc[$pos];
- $this->pos = $pos;
- return substr($this->doc, $pos_old, $pos-$pos_old);
- }
- }
-
- // remove noise from html content
- protected function remove_noise($pattern, $remove_tag=false) {
- $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
-
- for ($i=$count-1; $i>-1; --$i) {
- $key = '___noise___'.sprintf('% 3d', count($this->noise)+100);
- $idx = ($remove_tag) ? 0 : 1;
- $this->noise[$key] = $matches[$i][$idx][0];
- $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
- }
-
- // reset the length of content
- $this->size = strlen($this->doc);
- if ($this->size>0) $this->char = $this->doc[0];
- }
-
- // restore noise to html content
- function restore_noise($text) {
- while(($pos=strpos($text, '___noise___'))!==false) {
- $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13];
- if (isset($this->noise[$key]))
- $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+14);
- }
- return $text;
- }
-
- function __toString() {
- return $this->root->innertext();
- }
-
- function __get($name) {
- switch($name) {
- case 'outertext': return $this->root->innertext();
- case 'innertext': return $this->root->innertext();
- case 'plaintext': return $this->root->text();
- }
- }
-
- // camel naming conventions
- function childNodes($idx=-1) {return $this->root->childNodes($idx);}
- function firstChild() {return $this->root->first_child();}
- function lastChild() {return $this->root->last_child();}
- function getElementById($id) {return $this->find("#$id", 0);}
- function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
- function getElementByTagName($name) {return $this->find($name, 0);}
- function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);}
- function loadFile() {$args = func_get_args();$this->load(call_user_func_array('file_get_contents', $args), true);}
-}
-?> \ No newline at end of file
diff --git a/blog/sbs_2/blogext.css b/blog/sbs_2/blogext.css
deleted file mode 100644
index 7b6916c..0000000
--- a/blog/sbs_2/blogext.css
+++ /dev/null
@@ -1,65 +0,0 @@
-span.right{
- display:table-cell;
- text-align:right;
- white-space:nowrap;
- min-width:12em;
-}
-a.toctarg{
- margin-left:-160px;
- padding-left:160px !important;
-}
-ul#tagslist{
- list-style-type:none;
- padding-left:0;
-}
-ul#tocroot{
- list-style-type:none;
- padding-left:24px;
-}
-ul.tocnode{
- list-style-type:none;
- padding-left:16px;
-}
-span.left{
- display:table-cell;
- text-align:left;
- text-overflow:ellipsis;
- overflow:hidden;
- white-space:nowrap;
-}
-div h3{
- margin: 0.5em 0;
-}
-#content .block{
- margin: 1em 0;
-}
-p{
- text-indent:2em;
-}
-.noindent{
- text-indent:0 !important;
-}
-note, .note {
- vertical-align: super;
- font-size: 60%;
-}
-reduced, .reduced {
- font-size: 75%;
-}
-enlarged, .enlarged {
- font-size: 125%;
-}
-blockquote {
- padding: 1em;
- margin-left:4em;margin-right:4em;
-}
-.rightaligned {
- text-align: right;
-}
-.nospace{font-size:0;}
-.nospace>span{font-size:16px;}
-#decryptdlg{max-width:30%;}
-@media (max-width:768px)
-{
- #decryptdlg{max-width:90%;}
-}
diff --git a/blog/sbs_2/bloglist.js b/blog/sbs_2/bloglist.js
deleted file mode 100644
index c117afb..0000000
--- a/blog/sbs_2/bloglist.js
+++ /dev/null
@@ -1,216 +0,0 @@
-//License: Expat(MIT)
-//Chris Xiong 2017
-var pp=5,pn=0,animating,adir=1;
-var t,c,psw,curp,cbuf,cmdtl,flt;
-function request(url,func)
-{
- var h=new XMLHttpRequest();
- h.open("GET",url);
- h.onload=()=>{func(h.response,h.status)};
- h.send();
-}
-function parsetags(tgs)
-{
- var r="";
- var a=tgs.split(",");
- r="#"+a[0];
- for(var i=1;i<a.length;++i)r+=" #"+a[i];
- return r;
-}
-function rmblk(i)
-{
- var l=c.querySelectorAll("div.pendingrm");
- if(i>=l.length)
- {
- setTimeout(function(){for(var i of l)c.removeChild(i);},500);
- return;
- }
- var e=l.item(i);
- var w=e.getBoundingClientRect().width;
- e.style.left=adir*-1.3*w+"px";
- setTimeout(rmblk,100,i+1);
-}
-function etrblk(i)
-{
- var l=c.querySelectorAll("div.block:not(.pendingrm)");
- if(!i)
- {
- for(var e of l)
- if(e.id!="ptemplate")e.style.left=(adir*1.2*e.getBoundingClientRect().width)+"px";
- }
- if(i>=l.length)
- {
- setTimeout(()=>{animating=false;},500);
- return;
- }
- var e=l.item(i);
- if(e.id!="ptemplate")
- e.style.left="0";
- setTimeout(etrblk,100,i+1);
-}
-function setfilter(f,nlp)
-{
- if(animating)return;
- if(f[0]=='#')f=f.substr(1);
- var ch=document.getElementById('tagslist').children;
- var ff=false;
- for(var i=0;i<ch.length;++i)
- if(ch[i].children[0].innerHTML=="#"+f)
- if(ch[i].children[0].classList.contains('active'))ch[i].children[0].classList.remove('active'),ff=true;
- else ch[i].children[0].classList.add('active');else ch[i].children[0].classList.remove('active');
- flt=f;if(ff)flt="";
- pn=-1;if(!nlp)loadpage(0);
-}
-function modloc()
-{
- var base=window.location.toString().substr(0,window.location.toString().search('/blog/list')+10);
- var ret=base+(flt.length?'/'+flt:'')+'/'+pn;
- window.history.replaceState("","Chrisoft::Blog",ret);
-}
-function loadpage(_pn)
-{
- if(animating||_pn==pn)return;
- if(_pn>pn)adir=1;else adir=-1;
- pn=_pn;animating=true;modloc();
- var l=c.querySelectorAll("div.block");
- for(var i of l)
- if(i.id!="ptemplate")
- {
- i.classList.add("pendingrm");
- r=i.getBoundingClientRect();
- i.style.top=(r.top-16)+"px";
- i.style.left=r.left+"px";
- i.style.width=r.width+"px";
- }
- for(var i of l)if(i.id!="ptemplate")i.style.position="fixed";
- setTimeout(rmblk,10,0);
- curp.innerHTML=(pn+1)+"/";
- request("/blog/cgi-bin/get-archive-list.cgi?pp="+pp+"&pc"+(flt.length?"&f="+flt:""),
- function(r){curp.innerHTML+=Number(r).toString();});
- request("/blog/cgi-bin/get-archive-list.cgi?pp="+pp+"&pn="+pn+(flt.length?"&f="+flt:""),
- function(r,s)
- {
- if(s!=200){animating=false;return;}
- o=JSON.parse(r);
- for(var i=0;i<o.postsOnPage;++i)
- {
- var e=t.cloneNode(true);
- e.style.display="block";e.id="";
- e.querySelector("h3").innerHTML='<a href=/blog/post/'+o.posts[i].filename+'>'+o.posts[i].title+'</a>';
- e.querySelector("span.left").innerHTML=parsetags(o.posts[i].tags);
- e.querySelector("span.right").innerHTML=o.posts[i].date;
- c.insertBefore(e,psw);
- }
- setTimeout(etrblk,10,0);
- }
- );
-}
-function lastpage(){loadpage(pn-1<0?0:pn-1);}
-function nextpage(){request("/blog/cgi-bin/get-archive-list.cgi?pp="+pp+"&pc"+(flt.length?"&f="+flt:""),function(r){var pc=Number(r);if(pn+1<pc)loadpage(pn+1);});}
-function blinit()
-{
- var parr=window.location.pathname.substr(10).split('/');
- var pflt="";ppn=0;
- if(parr.length>1&&parr[1].length)
- {
- if(!isNaN(parr[1]))ppn=Number(parr[1]);
- else if(parr.length>2&&parr[2].length&&!isNaN(parr[2])){pflt=parr[1];ppn=Number(parr[2]);}
- else if(parr.length>=2)pflt=parr[1];
- }
- t=document.getElementById("ptemplate");
- c=document.getElementById("content");
- psw=document.getElementById("insanch");
- curp=document.getElementById("curp");
- cbuf=document.getElementById("cmdbuf");
- document.onkeypress=keypress;
- document.onkeydown=(e)=>{switch(e.key){case "ArrowLeft":lastpage();break;case "ArrowRight":nextpage();break;}};
- request("/blog/cgi-bin/get-archive-list.cgi?gt",
- (r)=>
- {
- o=JSON.parse(r);
- for(var i=0;i<o.length;++i)
- {
- var l=document.createElement('li');
- l.innerHTML='<a href="javascript:void(0);" onclick="setfilter(\''+o[i]+'\');">'+o[i]+"</a>";
- document.getElementById('tagslist').appendChild(l);
- }
- pn=-1;setfilter("#"+pflt,true);loadpage(ppn);
- }
- );
-}
-
-function showcmdbuf()
-{
- cbuf.style.opacity="1";
- if(cmdtl){clearTimeout(cmdtl);cmdtl=0;}
- cmdtl=setTimeout(execcmd,1000);
-}
-function execcmd()
-{
- var v=false;
- switch(cbuf.innerHTML)
- {
- case "h":case "k":
- lastpage();v=true;
- break;
- case "j":case "l":
- nextpage();v=true;
- break;
- case "gg":
- loadpage(0);v=true;
- break;
- case "G":
- v=true;
- request("/blog/cgi-bin/get-archive-list.cgi?pp="+pp+"&pc",
- function(r){var pc=Number(r);loadpage(pc-1);}
- );
- break;
- case "xyzzy":
- cbuf.innerHTML="Going minesweeping!";
- v=true;setTimeout(()=>{window.location.href="/minesweeper";},500);
- break;
- }
- if(parseInt(cbuf.innerHTML).toString()+"G"==cbuf.innerHTML.trim())
- {
- v=true;
- request("/blog/cgi-bin/get-archive-list.cgi?pp="+pp+"&pc",
- function(r)
- {var pc=Number(r),tpn=parseInt(cbuf.innerHTML)-1;if(tpn>=pc)tpn=pc-1;if(tpn<0)tpn=0;loadpage(tpn);}
- );
- }
- if(cbuf.innerHTML[0]==':')
- {
- var sparr=cbuf.innerHTML.split(' ');
- switch(sparr[0])
- {
- case ':setfilter':
- case ':filter':
- case ':flt':
- v=true;
- if(sparr.length<2)
- {
- cbuf.innerHTML='require 1 parameter';
- }
- else setfilter(sparr[1]);
- break;
- case ':nofilter':
- case ':noflt':
- v=true;
- setfilter('');
- break;
- }
- }
- cbuf.style.opacity="0";
- if(!v)cbuf.innerHTML="Unknown command.";
-}
-function keypress(e)
-{
- if(cbuf.style.opacity=="0")cbuf.innerHTML="";
- if(e.key.length==1)
- {
- cbuf.innerHTML+=e.key;showcmdbuf();
- if(cbuf.innerHTML.length==1&&'hjkl'.search(cbuf.innerHTML)!=-1)
- execcmd();
- }
- if(e.key=="Enter")execcmd();
-}
diff --git a/blog/sbs_2/blogpost.js b/blog/sbs_2/blogpost.js
deleted file mode 100644
index 4c17772..0000000
--- a/blog/sbs_2/blogpost.js
+++ /dev/null
@@ -1,103 +0,0 @@
-//License: Expat (MIT)
-//Chrisoft Xiong 2017
-var prev,succ,tocid=0,headerlist=[];
-function request(url,func)
-{
- var h=new XMLHttpRequest();
- h.open("GET",url);
- h.onload=()=>{func(h.response,h.status)};
- h.send();
-}
-function parsetags(tgs)
-{
- var r="";
- var a=tgs.split(",");
- r="#"+a[0];
- for(var i=1;i<a.length;++i)r+=" #"+a[i];
- return r;
-}
-function dfs(el,le,p)
-{
- var e=document.createElement('li');
- e.innerHTML='<a class="toctarg" href="#tocanch'+tocid+'">'+el.innerHTML+'</a>';
- le.appendChild(e);
- el.id='tocanch'+(tocid++);
- el.classList.add('tvis');
- var che=null,i;
- for(i=p+1;i<headerlist.length;)
- {
- if(headerlist[i].tagName<=el.tagName)break;
- if(headerlist[i].classList.contains('notoc'))continue;
- if(che===null)
- {
- var te=document.createElement('li');
- che=document.createElement('ul');
- che.classList.add('tocnode');
- te.appendChild(che);
- le.appendChild(te);
- }
- i=dfs(headerlist[i],che,i);
- }
- return i;
-}
-function bpinit()
-{
- var parr=window.location.pathname.substr(10).split('/');
- var pflt="";ppn=0;
- if(parr.length>1&&parr[1].length)
- {
- request("/blog/cgi-bin/get-post-content.cgi?p="+parr[1],
- (r,s)=>
- {
- if(s>=400)window.location="/blog";
- var p1=r.search('\n');
- var title=r.substr(0,r.search('\n'));
- var p2=r.substr(p1+1).search('\n');
- var date=r.substr(p1+1,p2);
- var p3=r.substr(p1+p2+2).search('\n');
- var tags=r.substr(p1+p2+2,p3);
- document.getElementById("title").innerHTML=title;
- document.getElementById("titleh").innerHTML=title;
- document.getElementById("datetags").innerHTML=date+"<br>"+parsetags(tags);
- document.getElementById("article").innerHTML=r.substr(p1+p2+p3+3);
- var l=document.getElementById("article").querySelectorAll("script");
- for(var i of l)
- {
- var s=document.createElement("script");
- s.async=true;
- s.src=i.src;
- document.getElementById("article").appendChild(s);
- }
- var tgs=tags.split(',');
- for(var i=0;i<tgs.length;++i)
- {
- var l=document.createElement('li');
- l.innerHTML='<a href="/blog/list/'+tgs[i]+'/">'+tgs[i]+"</a>";
- document.getElementById('tagslist').appendChild(l);
- }
- request("/blog/cgi-bin/get-archive-list.cgi?qn="+parr[1],
- (r,s)=>
- {
- if(s>=400)return;
- var o=JSON.parse(r);
- prev=o.prev;succ=o.succ;
- }
- );
- l=document.getElementById('article').querySelectorAll('h2,h3,h4,h5,h6');
- var tocroot=document.getElementById('tocroot');
- for(var i of l)
- {
- if(!i.classList.contains('notoc'))headerlist.push(i);
- }
- for(var i=0;i<headerlist.length;)i=dfs(headerlist[i],tocroot,i);
- if(!tocroot.children.length)document.getElementById('tocouter').style.display='none';
- for(var i=0;i<tgs.length;++i)
- footnoter();
- if(window.location.hash.length&&document.querySelector(window.location.hash))
- window.scroll(window.scrollX,document.querySelector(window.location.hash).getBoundingClientRect().top);
- }
- );
- }
-}
-function prevpost(){if(prev.length)window.location="/blog/post/"+prev;}
-function succpost(){if(succ.length)window.location="/blog/post/"+succ;}
diff --git a/blog/sbs_2/cgi-bin/.htaccess b/blog/sbs_2/cgi-bin/.htaccess
deleted file mode 100644
index 84df3ac..0000000
--- a/blog/sbs_2/cgi-bin/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-Options +ExecCGI
-AddHandler cgi-script cgi pl
-
diff --git a/blog/sbs_2/cgi-bin/get-archive-list.cgi b/blog/sbs_2/cgi-bin/get-archive-list.cgi
deleted file mode 120000
index 4024897..0000000
--- a/blog/sbs_2/cgi-bin/get-archive-list.cgi
+++ /dev/null
@@ -1 +0,0 @@
-../cgi-src/get-archive-list \ No newline at end of file
diff --git a/blog/sbs_2/cgi-bin/get-post-content.cgi b/blog/sbs_2/cgi-bin/get-post-content.cgi
deleted file mode 120000
index 17ef753..0000000
--- a/blog/sbs_2/cgi-bin/get-post-content.cgi
+++ /dev/null
@@ -1 +0,0 @@
-../cgi-src/get-post-content \ No newline at end of file
diff --git a/blog/sbs_2/cgi-src/cgiutils.hpp b/blog/sbs_2/cgi-src/cgiutils.hpp
deleted file mode 100644
index 3eca4dc..0000000
--- a/blog/sbs_2/cgi-src/cgiutils.hpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2017 Chris Xiong
- *
- * 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.
- */
-#ifndef CGILIB_HPP
-#define CGILIB_HPP
-#include <cstdlib>
-#include <map>
-#include <string>
-#include <vector>
-const char* base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-std::string base64_encode(std::string s)
-{
- std::string r="";
- for(unsigned i=0;i<s.length();i+=3)
- {
- int b=(s[i]&0xFC)>>2;
- r+=base64_table[b];
- b=(s[i]&0x03)<<4;
- if(i+1<s.length())
- {
- b|=(s[i+1]&0xF0)>>4;
- r+=base64_table[b];
- b=(s[i+1]&0x0F)<<2;
- if(i+2<s.length())
- {
- b|=(s[i+2]&0xC0)>>6;
- r+=base64_table[b];
- b=s[i+2]&0x3F;
- r+=base64_table[b];
- }else r+=base64_table[b],r+='=';
- }else r+=base64_table[b],r+="==";
- }
- return r;
-}
-void split(std::string s,char c,std::vector<std::string>& v)
-{
- v.clear();
- for(size_t anch=0;;)
- {
- std::string sec;
- if(s.find(c,anch)==std::string::npos)
- sec=s.substr(anch);
- else sec=s.substr(anch,s.find(c,anch)-anch);
- v.push_back(sec);
- if(s.find(c,anch)==std::string::npos)break;
- anch=s.find(c,anch)+1;
- }
-}
-std::string trim(std::string s)
-{
- int l=0;for(;isblank(s[l]);++l)
- s=s.substr(l);
- while(isblank(s.back()))s.pop_back();
- return s;
-}
-class QueryStrParser
-{
- private:
- std::map<std::string,std::string> q;
- void parse(std::string es)
- {
- for(size_t anch=0;;)
- {
- std::string sec;
- if(es.find('&',anch)==std::string::npos)
- sec=es.substr(anch);
- else sec=es.substr(anch,es.find('&',anch)-anch);
- if(sec.find('=')==std::string::npos)
- q[sec.substr(0)]="";
- else
- q[sec.substr(0,sec.find('='))]=sec.substr(sec.find('=')+1);
- if(es.find('&',anch)==std::string::npos)break;
- anch=es.find('&',anch)+1;
- }
- }
- public:
- QueryStrParser()
- {
- char* e=getenv("QUERY_STRING");
- if(!e)return;
- parse(std::string(e));
- }
- QueryStrParser(std::string s)
- {
- parse(s);
- }
- bool exist(std::string s)
- {
- return q.find(s)!=q.end();
- }
- std::string value(std::string s)
- {
- if(!exist(s))return "";
- return q.find(s)->second;
- }
-};
-class RequestCookies
-{
- private:
- std::map<std::string,std::string> m;
- void parse(std::string cookie)
- {
- std::vector<std::string> v;
- split(cookie,';',v);
- }
- public:
- RequestCookies()
- {
- char* e=getenv("HTTP_COOKIE");
- if(!e)return;
- parse(std::string(e));
- }
-};
-class DOMAttrib
-{
- private:
- std::map<std::string,std::string> m;
- public:
- DOMAttrib(std::string s="")
- {
- for(size_t anch=0;;)
- {
- std::string sec;
- if(s.find('"',anch)==std::string::npos)
- sec=s.substr(anch);
- else sec=s.substr(anch,s.find('"',s.find('"',anch)+1)-anch+1);
- if(sec.find('=')==std::string::npos)
- m[sec.substr(0)]="";
- else
- m[sec.substr(0,sec.find('='))]=sec.substr(sec.find('=')+2),
- m[sec.substr(0,sec.find('='))].pop_back();
- if(s.find(' ',anch+sec.length())==std::string::npos)break;
- anch=s.find(' ',anch+sec.length())+1;
- }
- }
- void setAttrib(std::string a,std::string v){m[a]=v;}
- void eraseAttrib(std::string a){if(existAttrib(a))m.erase(m.find(a));}
- bool existAttrib(std::string a){return m.find(a)!=m.end();}
- std::string getAttrib(std::string a){if(!existAttrib(a))return "";return m[a];}
- std::string to_string()
- {
- std::string r;bool cf=false;
- for(auto i=m.begin();i!=m.end();++i)
- {
- if(cf)r+=' ';else cf=true;
- r+=i->first+"=\""+i->second+"\"";
- }
- return r;
- }
-};
-static const char* twoxx[]={
- "OK",
- "Created",
- "Accepted",
- "Non-Authoritative Information",
- "No Content",
- "Reset Content",
- "Partial Content",
- "Multi-Status",
- "Already Reported"
-};
-static const char* threexx[]={
- "Multiple Choices",
- "Moved Permanently",
- "Found",
- "See Other",
- "Not Modified",
- "Use Proxy",
- "???",
- "Temporary Redirect"
-};
-static const char* fourxx[]={
- "Bad Request",
- "Unauthorized",
- "Payment Required",
- "Forbidden",
- "Not Found",
- "Method Not Allowed",
- "Not Acceptable",
- "Proxy Authentication Required",
- "Request Timeout",
- "Conflict",
- "Gone",
- "Length Required",
- "Precondition Failed",
- "Request Entity Too Large",
- "Request-URI Too Long",
- "Unsupported Media Type",
- "Requested Range Not Satisfiable",
- "Expectation Failed"
-};
-static const char* fivexx[]={
- "Internal Server Error",
- "Not Implemented",
- "Bad Gateway",
- "Service Unavailable",
- "Gateway Timeout",
- "HTTP Version Not Supported"
-};
-class HTTPHeader
-{
-private:
- int status;
- std::vector<std::string> hdr;
-public:
- HTTPHeader(){status=200;}
- void setStatusCode(int c){status=c;}
- int statusCode(){return status;}
- void appendHeader(std::string s){hdr.push_back(s);}
- void print()
- {
- if(status>=200&&status<=208)
- printf("Status: %d %s\r\n",status,twoxx[status-200]);
- if(status>=300&&status<=307)
- printf("Status: %d %s\r\n",status,threexx[status-300]);
- if(status>=400&&status<=417)
- printf("Status: %d %s\r\n",status,fourxx[status-400]);
- if(status>=500&&status<=505)
- printf("Status: %d %s\r\n",status,fivexx[status-500]);
- for(unsigned i=0;i<hdr.size();++i)
- printf("%s\r\n",hdr[i].c_str());
- printf("\r\n");
- }
-};
-#endif
diff --git a/blog/sbs_2/cgi-src/get-archive-list b/blog/sbs_2/cgi-src/get-archive-list
deleted file mode 100755
index 4285a4d..0000000
--- a/blog/sbs_2/cgi-src/get-archive-list
+++ /dev/null
Binary files differ
diff --git a/blog/sbs_2/cgi-src/get-archive-list.cpp b/blog/sbs_2/cgi-src/get-archive-list.cpp
deleted file mode 100644
index 28f316d..0000000
--- a/blog/sbs_2/cgi-src/get-archive-list.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2017 Chris Xiong
- *
- * 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.
- */
-/*
- * Get list of archives
- * query parameters:
- * pn=<int>: page number, defaults to 0
- * pp=<int>: number of posts per page, defaults to 20
- * pc: if exists, gets how many pages are there from the current pp value
- * f: tag filter.
- * gt: get a list of tags used by posts instead.
- * qn=<filename>: query the neibouring posts of the given post.
- * returned object:
- * A number if pc exists denoting number of pages.
- * Or the following JSON object if gf exists.
- * ["tag1","tag2",...]
- * Or the following JSON object if qn exists.
- * {
- * "prev": <last post>
- * "succ": <next post>
- * }
- * Otherwise returns archive list in JSON:
- * {
- * "postsPerPage": <requested pp>
- * "postsOnPage": <number of posts on this page>
- * "page": <requested pn>
- * "posts": [
- * {
- * "filename": ...
- * "title": ...
- * "date": ...
- * "tags": ...
- * },
- * ...
- * ]
- * }
- */
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <cstdio>
-#include <cstring>
-#include <algorithm>
-#include <functional>
-#include <vector>
-#include <map>
-#include <set>
-#include <string>
-#include "cgiutils.hpp"
-#define stripr(s) s[strlen(s)-1]=='\n'?s[strlen(s)-1]=0:0
-struct post
-{
- std::string t,d,tg;
-};
-std::map<std::string,post,std::greater<std::string>> f;
-char buf[65536];
-int main(int argc,char** argv,char** envp)
-{
- struct stat idxs,cdirs;
- stat("/var/www/html/blog/content/pindex",&idxs);
- stat("/var/www/html/blog/content",&cdirs);
- if(cdirs.st_mtim.tv_sec>idxs.st_mtim.tv_sec)
- system("/var/www/html/blog/content/util/indexer > /dev/null 2> /dev/null");
- QueryStrParser a;
- FILE *fidx=fopen("/var/www/html/blog/content/pindex","r");
- while(fgets(buf,65536,fidx))
- {
- stripr(buf);std::vector<std::string> v;
- split(std::string(buf),'\t',v);
- if(v.size()==4)
- f[v[0]]=post{v[1],v[2],v[3]};
- }
- fclose(fidx);
- HTTPHeader h;
- if(a.exist("gt"))
- {
- std::set<std::string> s;
- std::vector<std::string> v;
- for(auto i=f.begin();i!=f.end();++i)
- {
- split(i->second.tg,',',v);
- for(size_t j=0;j<v.size();++j)
- s.insert("\"#"+v[j]+"\"");
- }
- h.appendHeader("Content-type: text/plain; charset=utf-8");
- h.print();
- printf("[");
- auto it=s.begin();
- printf("%s",it->c_str());
- while(++it!=s.end())printf(",%s",it->c_str());
- printf("]");
- }
- else
- {
- if(a.exist("f"))
- for(auto i=f.begin();i!=f.end();)
- {
- std::vector<std::string> v;
- split(i->second.tg,',',v);
- std::set<std::string> sv=std::set<std::string>(v.begin(),v.end());
- if(sv.find(a.value("f"))==sv.end()){auto t=i++;f.erase(t);}
- else i++;
- }
- if(a.exist("pc"))
- {
- int pp=0;
- if(!a.exist("pp"))pp=20;
- else{
- try{
- pp=std::stoi(a.value("pp"));
- }catch(std::exception e){h.setStatusCode(400);}
- }
- if(!pp)h.setStatusCode(400);
- h.appendHeader("Content-type: text/plain; charset=utf-8");
- h.print();
- printf("%lu\n",f.size()/pp+((f.size()%pp)?1:0));
- return 0;
- }
- else if(a.exist("qn"))
- {
- if(f.find(a.value("qn"))==f.end())
- h.setStatusCode(400);
- h.print();if(h.statusCode()>=400)return 0;
- auto i=f.find(a.value("qn"));
- std::string pr="",sc="";
- auto t=i;if(t!=f.begin())pr=(--t)->first;
- t=i;if(!(++t==f.end()))sc=t->first;
- printf("{\"prev\":\"%s\",\"succ\":\"%s\"}",sc.c_str(),pr.c_str());
- return 0;
- }
- else
- {
- unsigned pp=20,pn=0;
- if(!a.exist("pp"))pp=20;
- else{
- try{
- pp=std::stoi(a.value("pp"));
- }catch(std::exception e){h.setStatusCode(400);}
- }
- if(!a.exist("pn"))pn=0;
- else{
- try{
- pn=std::stoi(a.value("pn"));
- }catch(std::exception e){h.setStatusCode(400);}
- }
- if(!pp)h.setStatusCode(400);
- if(pn>=f.size()/pp+((f.size()%pp)?1:0))h.setStatusCode(400);
- int rpp=(pn!=f.size()/pp+((f.size()%pp)?1:0)-1)?pp:
- f.size()-pp*(f.size()/pp+((f.size()%pp)?1:0)-1);
- h.appendHeader("Content-type: text/plain; charset=utf-8");
- h.print();
- if(h.statusCode()>=400)return 0;
- puts("{");
- printf("\t\"postsPerPage\":%d,\n",pp);
- printf("\t\"postsOnPage\":%d,\n",rpp);
- printf("\t\"page\":%d,\n",pn);
- puts("\t\"posts\": [");
- auto it=f.begin();std::advance(it,pn*pp);
- for(int i=0;i<rpp-1;++i)
- {
- puts("\t\t{");
- printf("\t\t\t\"filename\":\"%s\",\n",it->first.c_str());
- printf("\t\t\t\"title\":\"%s\",\n",it->second.t.c_str());
- printf("\t\t\t\"date\":\"%s\",\n",it->second.d.c_str());
- printf("\t\t\t\"tags\":\"%s\"\n",it->second.tg.c_str());
- puts("\t\t},");++it;
- }
- puts("\t\t{");
- printf("\t\t\t\"filename\":\"%s\",\n",it->first.c_str());
- printf("\t\t\t\"title\":\"%s\",\n",it->second.t.c_str());
- printf("\t\t\t\"date\":\"%s\",\n",it->second.d.c_str());
- printf("\t\t\t\"tags\":\"%s\"\n",it->second.tg.c_str());
- puts("\t\t}");
- puts("\t]");
- puts("}");
- }
- }
- return 0;
-}
diff --git a/blog/sbs_2/cgi-src/get-post-content b/blog/sbs_2/cgi-src/get-post-content
deleted file mode 100755
index e6701c8..0000000
--- a/blog/sbs_2/cgi-src/get-post-content
+++ /dev/null
Binary files differ
diff --git a/blog/sbs_2/cgi-src/get-post-content.cpp b/blog/sbs_2/cgi-src/get-post-content.cpp
deleted file mode 100644
index 62cd5d8..0000000
--- a/blog/sbs_2/cgi-src/get-post-content.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2017 Chris Xiong
- *
- * 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.
- */
-/*
- * Get content of a post
- * query parameters:
- * p=<string>: post file name
- * returned object:
- * HTML fragment of the post
- */
-#include <dirent.h>
-#include <cstdio>
-#include <cstring>
-#include <algorithm>
-#include <functional>
-#include <vector>
-#include <string>
-#include "cgiutils.hpp"
-#define stripr(s) s[strlen(s)-1]=='\n'?s[strlen(s)-1]=0:0
-std::vector<std::string> fn;
-char buf[262144];
-size_t sz;
-void encrypt()
-{
- std::string b(buf,sz);
- for(size_t p=b.find("<encrypted"),i=0;p!=std::string::npos;p=b.find("<encrypted",p),++i)
- {
- size_t tag_end=b.find(">",p);
- std::string attrib=b.substr(p+11,tag_end-p-11);
- DOMAttrib a(attrib);
- std::string cont=b.substr(tag_end+1,b.find("</encrypted>",p)-tag_end-1);
- unsigned hash=5381;
- std::string key=a.getAttrib("key");
- a.eraseAttrib("key");
- for(size_t j=0;j<cont.length();++j)
- {
- hash=((hash<<5)+hash)+*reinterpret_cast<unsigned char*>(&cont[j]);
- cont[j]^=key[j%key.length()];
- }
- a.setAttrib("encont",base64_encode(cont));
- a.setAttrib("hash",std::to_string(hash));
- a.setAttrib("id","encrypted"+std::to_string(i));
- cont="Encrypted content here. Click <a href=\"javascript:void(0)\" onclick=\"decryptui("+std::to_string(i)+")\">here</a> to decrypt.";
- b.replace(p,b.find("</encrypted>",p)-p,"<encrypted "+a.to_string()+">"+cont);
- p=b.find("</encrypted>",p);
- }
- memcpy(buf,b.c_str(),b.length());sz=b.length();
-}
-int main(int argc,char** argv,char** envp)
-{
- QueryStrParser a;
- HTTPHeader h;
- if(!a.exist("p")){h.setStatusCode(400);h.print();return 0;}
- FILE* f=fopen(("/var/www/html/blog/content/"+a.value("p")+".txt").c_str(),"r");
- if(!f){h.setStatusCode(400);h.print();return 0;}
- h.appendHeader("Content-type: text/plain; charset=utf-8");
- h.print();
- sz=fread(buf,sizeof(char),262144,f);
- encrypt();
- fwrite(buf,sizeof(char),sz,stdout);
- fclose(f);
- return 0;
-}
diff --git a/blog/sbs_2/decryptor.js b/blog/sbs_2/decryptor.js
deleted file mode 100644
index dcd64e3..0000000
--- a/blog/sbs_2/decryptor.js
+++ /dev/null
@@ -1,73 +0,0 @@
-//License: Expat(MIT)
-//Chrisoft Xiong 2017
-// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
-function Utf8ArrayToStr(array){
- var out,i,len,c;
- var char2,char3;
- out="";
- len=array.length;
- i=0;
- while(i<len){
- c=array[i++];
- switch(c>>4)
- {
- case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:
- // 0xxxxxxx
- out+=String.fromCharCode(c);
- break;
- case 12:case 13:
- // 110x xxxx 10xx xxxx
- char2=array[i++];
- out+=String.fromCharCode(((c&0x1F)<<6)|(char2&0x3F));
- break;
- case 14:
- // 1110 xxxx 10xx xxxx 10xx xxxx
- char2=array[i++];
- char3=array[i++];
- out+=String.fromCharCode(((c&0x0F)<<12)|
- ((char2&0x3F)<<6)|
- ((char3&0x3F)<<0));
- break;
- }
- }
- return out;
-}
-var decid;
-function decryptui(id)
-{
- document.getElementById("decryptui").style.display="block";
- document.getElementById("keyinp").focus();
- setTimeout(function(){document.getElementById("decryptui").style.opacity="1";},20);
- decid=id;
- document.getElementById("keyhint").innerHTML="Hint: "+document.getElementById("encrypted"+id).getAttribute("hint");
- document.getElementById("keyinp").onkeypress=function(e){if(e.keyCode==13)document.getElementById('btndecrypt').click();}
-}
-function hidedecryptui()
-{
- document.getElementById("decryptui").style.opacity="0";
- setTimeout(function(){
- document.getElementById("decryptui").style.display="none";
- document.getElementById("keyinp").value="";
- },500);
-}
-function decryptor(id,key)
-{
- var e=document.getElementById("encrypted"+id);
- var cont=e.getAttribute("encont");
- var bc=atob(cont);
- var b=new Array(bc.length);
- for(var i=0;i<bc.length;++i)b[i]=bc.charCodeAt(i);
- var lkey=key.length;
- var u8arr=new Uint8Array(b);
- var hash=5381;
- for(var i=0;i<u8arr.length;++i){u8arr[i]^=key.charCodeAt(i%lkey);hash=(hash*33)+u8arr[i];hash%=4294967296;}
- if(hash!=parseInt(e.getAttribute("hash")))
- {
- alert("The decryption key you have entered could be wrong, please try again.");
- return;
- }
- //e.innerHTML=new TextDecoder("utf-8").decode(u8arr);
- e.innerHTML=Utf8ArrayToStr(u8arr);
- footnoter();
- hidedecryptui();
-}
diff --git a/blog/sbs_2/footnoter.js b/blog/sbs_2/footnoter.js
deleted file mode 100644
index a1b2d8b..0000000
--- a/blog/sbs_2/footnoter.js
+++ /dev/null
@@ -1,24 +0,0 @@
-//License: MIT
-//Chrisoft Xiong 2017
-var starting=0;
-function footnoter()
-{
- var footnotes=document.body.getElementsByTagName("footnote");
- for(var i=0;i<footnotes.length;++i)
- {
- var s=footnotes[i].innerHTML;
- footnotes[i].innerHTML="";//IE is stupid
- var a=document.createElement("a");
- a.setAttribute("id","n"+(starting+i+1));
- a.setAttribute("href","#note"+(starting+i+1));
- a.setAttribute("class","note");
- a.innerHTML="["+(starting+i+1)+"]";
- footnotes[i].parentNode.insertBefore(a,footnotes[i]);
- var span=document.createElement("span");
- span.setAttribute("class","TText");
- span.innerHTML="<a id=\"note"+(starting+i+1)+"\" href=\"#n"+(starting+i+1)+"\">["+(starting+i+1)+"]</a>: "+s+"<br>";
- document.getElementById("notediv").appendChild(span);
- }
- starting+=footnotes.length;
- while(footnotes.length)footnotes[0].remove();
-}
diff --git a/blog/sbs_2/index.html b/blog/sbs_2/index.html
deleted file mode 100644
index d7c31c9..0000000
--- a/blog/sbs_2/index.html
+++ /dev/null
@@ -1 +0,0 @@
-<script>window.location="list/"</script>
diff --git a/blog/sbs_2/list b/blog/sbs_2/list
deleted file mode 100644
index e1f751e..0000000
--- a/blog/sbs_2/list
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta name="viewport" content="width=device-width,initial-scale=1">
-<title>Chrisoft::Blog</title>
-<script type="text/javascript" src="/panel.js"></script>
-<script type="text/javascript" src="/blog/bloglist.js"></script>
-<link rel="stylesheet" type="text/css" href="/common.css">
-<link rel="stylesheet" type="text/css" href="/panel.css">
-<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
-<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
-<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
-<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
-<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
-<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
-<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
-<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
-<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
-<script>
-function ol()
-{
- window.onresize=function()
- {
- if(window.innerWidth<768)
- setupevents();
- else unsetevents();
- }
- window.onresize();
- blinit();
-}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
-}
-loadTheme();
-</script>
-</head>
-<body onload="ol()" style="overflow-x:hidden;">
- <div id="panel" class="TText">
- <ul id="panellist">
- <li><a href="/"><h1>Chrisoft</h1></a></li>
- <li><a href="/blog"><h2>Blog</h2></a></li>
- <li><span>Tags filter</span>
- <ul id="tagslist">
- </ul>
- </li>
- </ul>
- </div>
- <div id="content">
- <div class="block TText" id="ptemplate" style="position:relative;transition:500ms;">
- <h3 style="line-height:1.5em;">Title</h3>
- <br>
- <div style="display:table;width:100%;table-layout:fixed;"><span class="left">tags</span>
- <span class="right">time</span></div>
- </div>
- <div id="insanch" style="height:5em;"></div>
- <div id="footer" style="">
- <div id="pagesw" class="TText" style="display:table;width:100%;padding:1em 0;">
- <span style="display:table-cell;"><a href="javascript:void(0);" onclick="lastpage();">&lt;&lt;</a></span>
- <span style="text-align:center;display:table-cell;" id="curp"></span>
- <span style="text-align:right;display:table-cell;"><a href="javascript:void(0);" onclick="nextpage();">&gt;&gt;</a></span>
- </div>
- <div style="text-align:center;" class="TText">
- Proudly powered by SBS <reduced style="font-size:70%;">(the stupid blogging system)</reduced> 2.1
- <br>
- Content licensed under CC BY-SA 4.0.
- </div>
- </div>
- <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
- </div>
- </div>
-</body>
-</html>
diff --git a/blog/sbs_2/post b/blog/sbs_2/post
deleted file mode 100644
index 4ea512d..0000000
--- a/blog/sbs_2/post
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta name="viewport" content="width=device-width,initial-scale=1">
-<title>Chrisoft::Blog</title>
-<script type="text/javascript" src="/panel.js"></script>
-<script type="text/javascript" src="/blog/blogpost.js"></script>
-<script type="text/javascript" src="/blog/footnoter.js"></script>
-<script type="text/javascript" src="/blog/decryptor.js"></script>
-<link rel="stylesheet" type="text/css" href="/common.css">
-<link rel="stylesheet" type="text/css" href="/panel.css">
-<link rel="stylesheet" type="text/css" href="/theme0a.css" id="theme0a">
-<link rel="stylesheet" type="text/css" href="/theme0b.css" id="theme0b">
-<link rel="stylesheet" type="text/css" href="/theme1a.css" id="theme1a">
-<link rel="stylesheet" type="text/css" href="/theme1b.css" id="theme1b">
-<link rel="stylesheet" type="text/css" href="/theme2a.css" id="theme2a">
-<link rel="stylesheet" type="text/css" href="/theme2b.css" id="theme2b">
-<link rel="stylesheet" type="text/css" href="/theme3a.css" id="theme3a">
-<link rel="stylesheet" type="text/css" href="/theme3b.css" id="theme3b">
-<link rel="stylesheet" type="text/css" href="/blog/blogext.css">
-<script>
-function ol()
-{
- window.onresize=function()
- {
- if(window.innerWidth<768)
- setupevents();
- else unsetevents();
- }
- window.onresize();
- bpinit();
-}
-function loadTheme(){
- var thm=document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)thm\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");
- if(thm.length<2||'0123z'.indexOf(thm[0])==-1||'abz'.indexOf(thm[1])==-1)thm='zz';
- var ent="";
- var d=new Date();
- if(thm[0]=='z')
- {
- var m=d.getMonth()+1;
- if(m>=3&&m<6)thm='0'+thm[1];
- else if(m>=6&&m<9)thm='1'+thm[1];
- else if(m>=9&&m<12)thm='2'+thm[1];
- else thm='3'+thm[1];
- }
- if(thm[1]=='z')
- {if(d.getHours()>=18||d.getHours()<6)thm=thm[0]+'b';else thm=thm[0]+'a';}
- ent=`theme${thm}`;
- var R=new RegExp('theme[0-4][ab]');
- for(var i=0;i<document.styleSheets.length;++i)
- {
- if(R.exec(document.styleSheets[i].ownerNode.id)!==null&&document.styleSheets[i].ownerNode.id!=ent)
- document.styleSheets[i].disabled=true;
- else document.styleSheets[i].disabled=false;
- }
-}
-loadTheme();
-</script>
-</head>
-<body onload="ol()" style="overflow-x:hidden;">
- <div id="panel" class="TText">
- <ul id="panellist">
- <li><a href="/"><h1>Chrisoft</h1></a></li>
- <li><a href="/blog"><h2>Blog</h2></a></li>
- <li><a href="#"><h3 id="title"></h3></a></li>
- <li><span>Tags</span>
- <ul id="tagslist">
- </ul>
- </li>
- <li id="tocouter">
- <span>Table of Contents</span>
- <ul id="tocroot">
- </ul>
- </li>
- <li style="margin-left:-0.5em"><a href="javascript:void(0);" onclick="prevpost();">Prev post</a></li>
- <li style="margin-left:-0.5em"><a href="javascript:void(0);" onclick="succpost();">Next post</a></li>
- </ul>
- </div>
- <div id="content">
- <h2 id="titleh" class="TText" style="font-wight:normal;"></h2>
- <div id="datetags" class="TText" style="margin-bottom:1em;"></div>
- <div id="article" class="TText"></div><br><hr>
- <div class="TText" id="notediv" style="font-size:80%;"></div>
- <div id="insanch" style="height:3em;"></div>
- <div id="footer" style="">
- <div id="pagesw" class="TText" style="width:100%;height:0.5em;"></div>
- <div style="text-align:center;" class="TText">
- Proudly powered by SBS <reduced style="font-size:70%;">(the stupid blogging system)</reduced> 2.1
- <br>
- Content licensed under CC BY-SA 4.0.
- </div>
- </div>
- <div id="cmdbuf" class="TText" style="transition:500ms;padding:1em;font-size:2em;color:white;position:absolute;background-color:rgba(0,0,0,0.6);left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none;opacity:0;">
- </div>
- </div>
- <div id="decryptui" style="display:none;opacity:0;color:white;z-index:10;position:fixed;left:0;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.4);transition:opacity 0.5s;">
- <div id="decryptdlg" class="TText" style="padding:10px 20px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:rgba(0,0,0,0.6);">
- <div id="keyhint" style="margin-bottom:8px;"></div>
- <div style="margin-bottom:8px;">Key: <input id="keyinp" type="text"></div>
- <div style="height:2.25em;">
- <button id="btndecrypt" onclick="decryptor(decid,document.getElementById('keyinp').value);" style="position:absolute;left:20px;">Decrypt</button>
- <button onclick="hidedecryptui();" style="position:absolute;right:20px;">Cancel</button>
- </div>
- </form>
- </div>
-</body>
-</html>
diff --git a/common.css b/common.css
index 41585eb..d9b6a99 100644
--- a/common.css
+++ b/common.css
@@ -11,22 +11,11 @@
font-variant-ligatures: none;
}
a{
-text-decoration:none;
-}
-a:link{
-color:#1194FF;
-}
-a:visited{
-color:#20ACFF;
-}
-a:hover{
-color:#3FBFFF;
-}
-a:active{
-color:#CCCCFF;
+ text-decoration:none;
}
div.comment{
- border:1px solid #CCC;
+ border:1px solid;
+ border-color: var(--secondary-fg);
margin:1em;
}
div.author{
@@ -70,3 +59,68 @@ textarea{
outline:none !important;
background-color:rgba(0,0,0,0) !important;
}
+body{
+ background-color: var(--principal-bg);
+ background-image: var(--bg-pattern);
+ background-repeat: repeat;
+ color: var(--principal-fg);
+}
+del{
+ text-decoration-color: var(--principal-fg);
+}
+#panel li a.active{
+ background-color: var(--list-active-bg);
+}
+#panel li a:hover:not(.active){
+ background-color: var(--list-highlighted-bg);
+}
+#panel,#footer{
+ background-color: var(--secondary-bg);
+ background-image: var(--bg-pattern);
+ background-repeat: repeat;
+}
+#content .block{
+ border: 1px solid;
+ border-color: var(--secondary-fg);
+}
+a.highlighted{color: var(--link-highlighted-fg) !important;}
+a:link{
+ color: var(--link-fg);
+}
+a:visited{
+ color: var(--link-visited-fg);
+}
+a:hover{
+ color: var(--link-hover-fg);
+}
+a:active{
+ color: var(--link-active-fg);
+}
+blockquote{
+ border: 1px solid;
+ border-color: var(--secondary-fg);
+}
+button,.fakebtn{
+ color: var(--interactive-fg);
+ background-color: var(--interactive-bg);
+}
+button:hover,.fakebtn:hover{
+ background-color: var(--interactive-hover-bg);
+}
+button:active,.fakebtn:active{
+ background-color: var(--interactive-active-bg);
+}
+button:disabled{
+ background-color: var(--interactive-disabled-bg);
+}
+input[type="text"]{
+ color: var(--principal-fg);
+ border-bottom-color: var(--interactive-bg);
+}
+textarea{
+ color: var(--principal-fg);
+ border-color: var(--interactive-bg);
+}
+.widgetbg{background-color: var(--widget-area-bg);}
+.sliderb1{background-color: var(--slider-empty-bg);}
+.sliderb2{background-color: var(--slider-filled-bg);}
diff --git a/index.html b/index.shtml
index 2611968..8c80b7b 100644
--- a/index.html
+++ b/index.shtml
@@ -4,9 +4,12 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#000000">
+<meta name="description" content="Chris Xiong's personal homepage">
+<meta name="author" content="Chris Xiong">
<title>Chrisoft::Home</title>
<link rel="icon" href="./favicon.png">
<link rel="preload" href="/themes.svg" as="image">
+<link rel="me" href="https://c.im/@chirs241097">
<link rel="stylesheet" type="text/css" href="common.css">
<link rel="stylesheet" type="text/css" href="panel.css">
<link rel="stylesheet" type="text/css" href="theme0a.css" id="theme0a">
@@ -19,6 +22,7 @@
<link rel="stylesheet" type="text/css" href="theme3b.css" id="theme3b">
<style>
reduced{font-size:75%;}
+ details{padding:.5em .5em 0 .2em;}
#msgform{width:50%;margin:auto;}
@media (max-width:768px)
{#msgform{width:auto;margin:1em;}}
@@ -81,9 +85,9 @@ function swonload(){
loadTheme();
if(!location.hash.length)contsw('main');
else contsw(location.hash.substr(1));
- var unsupportedpf=['Macintosh','MacIntel','MacPPC','Mac68K','iPhone','iPad','iPod'];
+ /*var unsupportedpf=['Macintosh','MacIntel','MacPPC','Mac68K','iPhone','iPad','iPod'];
if(unsupportedpf.indexOf(window.navigator.platform)!==-1)
- document.getElementById('appleouter').style.display='block';
+ document.getElementById('appleouter').style.display='block';*/
}
</script>
<div id="panel" class="TText">
@@ -102,7 +106,7 @@ function swonload(){
<div class="block" id="main">
<h2>Yet another wandering programmer</h2><hr>
<p>
- Welcome to the home page of Chris Xiong, a Chinese programmer.
+ Welcome to the home page of Chris Xiong, a Chinese programmer living overseas.
</p>
<p>
You will find my works, collections and pieces of thoughts here.
@@ -110,12 +114,12 @@ function swonload(){
<p>
Have fun exploring!
</p>
- <p id="appleouter" style="display:none;">
+ <!--<p id="appleouter" style="display:none;">
<b>Please read [<a href="https://stallman.org/apple.html" rel="external" target="_blank" onclick="document.getElementById('apple').style.display='block';">this</a>] in case of any trouble, Your Excellency.</b>
<div id="apple" class="block" style="display:none;"><p>
- The owner of this site doesn't have any Apple devices that can go online so you may experience major problems browsing this site. If you consider this unacceptable, you may donate me an Apple device. Please mail your generous donation to <code>/dev/null</code>.
+ <s>The owner of this site doesn't have any Apple devices that can go online so</s> you may experience major problems browsing this site. If you consider this unacceptable, you may donate me an Apple device. Please mail your generous donation to <code>/dev/null</code>.
</p></div>
- </p>
+ </p>-->
</div>
<div class="block" id="projects">
<h2>Projects</h2><hr>
@@ -129,13 +133,42 @@ function swonload(){
</p>
<h3 style="font-weight:normal;">Active Projects</h3>
<ul>
+ <li>deduper
+ <reduced>
+ <a href="https://cgit.chrisoft.org/deduper.git/">
+ [details]</a>
+ <a href="javascript:toggleblkdisplay('dedp-desc')">
+ [short desc.]</a></reduced>
+ <div class="block" id="dedp-desc">
+ Scans local images for duplicates.
+ Also provides reverse image search for your local images.
+ Implements a variant of the algorithm described in "An
+ image signature for any kind of image", doi:
+ 10.1109/ICIP.2002.1038047.
+ </div>
+ </reduced>
+ </li>
+ <li>it2midi
+ <reduced>
+ <a href="https://cgit.chrisoft.org/it2midi.git/">
+ [details]</a>
+ <a href="javascript:toggleblkdisplay('it2m-desc')">
+ [short desc.]</a></reduced>
+ <div class="block" id="it2m-desc">
+ An effort to rewrite my old it2midi.cpp in Rust.
+ A versatile IT (impulse tracker) to MIDI converter.
+ Currently it's moulting into a fully-fledged mod
+ player.
+ </div>
+ </reduced>
+ </li>
<li>QMidiPlayer
<reduced><a href="./QMidiPlayer">[details]</a>
<a href="javascript:toggleblkdisplay('qmp-desc')">
[short desc.]</a></reduced>
<div class="block" id="qmp-desc">
- A feature-rich cross-platform MIDI player loosely
- based on vanBasco's Karaoke Player and QSynth.
+ A feature-rich cross-platform MIDI player with UI
+ inspired by vanBasco's Karaoke Player and QSynth.
It has a comprehensive plugin interface to
provide extra functionalities.
</div>
@@ -147,10 +180,9 @@ function swonload(){
<a href="javascript:toggleblkdisplay('smlt-desc')">
[short desc.]</a></reduced>
<div class="block" id="smlt-desc">
- SMELT is a wrapper class for hardware-accelerated
- graphics rendering, input handling and optionally,
- audio outputting. SMELT is extensively used in
- some of my projects.
+ SMELT is a set of classes that provide hardware-accelerated
+ graphics, input handling and optionally, audio output.
+ SMELT is used extensively in my other projects.
</div>
</li>
<li>lightsd
@@ -232,13 +264,27 @@ function swonload(){
I worked for Deepin as an intern for almost a year starting from February 2019. My work there
includes implementing optical disc authoring for the file manager and reworking the computer
pseudo-folder. I also worked on the networking section of the settings application for some
- time. Chances are if you have ever used DDE v20 (the redesign released in 2020), my code has
- passed through the pipelines of your processor.
+ time, as well as a few other system components (DTK being one of them). Chances are if you
+ have ever used DDE v20 (the redesign released in 2020), my code has passed through the
+ pipelines of your processor.
</p>
<p>I have mixed views on Deepin the company. You may find out more in my blog posts.</p>
</div>
</reduced>
</li>
+ <li>CKRasterizer
+ <reduced>
+ <a href="https://github.com/Swung0x48/CKRasterizer">[details]</a>
+ <a href="javascript:toggleblkdisplay('ckrst-desc')">
+ [short desc.]</a></reduced>
+ <div class="block" id="ckrst-desc">
+ Rasterizers for Virtools (an old interactive 3D toolkit). I shifted the project from a
+ reverse-engineering approach to a "just wing it" approach. Helped with completing the
+ DirectX 9 rasterizer. Additionally created two new rasterizer modules
+ for modern graphics from scratch (CKGLRasterizer and CKVkRasterizer).
+ </div>
+ </reduced>
+ </li>
<li>SDUOJ
<reduced>
<a href="javascript:toggleblkdisplay('soj-desc')">
@@ -289,8 +335,10 @@ function swonload(){
</reduced>
<div class="block" id="br-desc">
Old project attempting to recreate the game Ballance from Cyparade.
- It uses the same engine but without custom extensions to the engine.
- Playable, but in no way resemble the original game.
+ It uses the same Virtools engine but without using custom extensions
+ to the engine.
+ Playable, but in no way resemble the "feel" of the original game in
+ terms of controls.
</div>
</li>
<li>Chris' Timidity Player (2012)
@@ -310,6 +358,7 @@ function swonload(){
</reduced>
<div class="block" id="testr-desc">
Local judger for OI problems. Doesn't really have any advanced features.
+ Written in FreePascal.
</div>
</li>
<li>the <s>Ultimate</s> Data Visualiser (2015)
@@ -318,7 +367,7 @@ function swonload(){
</reduced>
<div class="block" id="dvis-desc">
A data visualizer for some very specific purpose.
- This project is never made public.
+ This project is never made public. Written in C++. Uses SMELT.
</div>
</li>
<li>World's Hardest Game 3D (2010-2011)
@@ -337,7 +386,8 @@ function swonload(){
<a href="javascript:toggleblkdisplay('crxnd-desc')">[short desc.]</a>
</reduced>
<div class="block" id="crxnd-desc">
- A stupid game made with Virtools. A new version using HTML5 is <a href="https://chrisoft.org/CrossNoodlesJS/">available</a>.
+ A stupid game made with Virtools. A new version written for modern(-ish)
+ browser is <a href="https://chrisoft.org/CrossNoodlesJS/">available</a>.
</div>
</li>
<li>Compiz 0.9.7.99 (2012-2016)
@@ -346,7 +396,8 @@ function swonload(){
<a href="javascript:toggleblkdisplay('cmpz-desc')">[short desc.]</a>
</reduced>
<div class="block" id="cmpz-desc">
- The ultimate compiz distribution with extra features added by me.
+ The ultimate pre-GLES port compiz distribution with extra features
+ added by me, as well as backports of a few new features added later.
It was forked off the 0.9.7 branch for Ubuntu 12.04. It comes with
probably every single plugin ever available for compiz.
</div>
@@ -415,32 +466,37 @@ function swonload(){
<a href="javascript:toggleblkdisplay('dntm-desc')">[short desc.]</a>
</reduced>
<div class="block" id="dntm-desc">
- Clock, alarm and stopwatch.
+ Text mode clock, alarm and stopwatch written in FreePascal.
</div>
</li>
</ul>
</div>
<div class="block" id="blog">
<h2>Blog</h2><hr>
- <h3><a href="./blog/list/devel">Development Blog</a></h3>
+ <h3><a href="/blog/list">SPELVNCAM·VRSAE·VISERE</a></h3>
<p>
- Sharing thoughts on software development and recording progress of my projects.
+ As its name suggests, this place is dangerous. However if you
+ do know what you're looking for, you might be able to find
+ the hidden gems.
</p>
- <h3><a href="./blog/list">Nonsense Blog</a></h3>
<p>
- Pure garbage. <em>Caveat emptor.</em>
+ Note: some of the posts there are quite old and might no longer
+ reflect my current views on various topics. Certain posts may
+ contain stuff that not everyone would like to see. May contain
+ nuts.
</p>
<p>
- No RSS feed provided.
+ Does not appear to contain a significant amount of cerebral
+ activity.
</p>
</div>
<div class="block" id="library">
<h2>Library</h2><hr>
- <h3><a href="./libs/music/player">Music Library</a></h3>
+ <h3><a href="/libs/music/player">Music Library</a></h3>
<p>
Music arranged and some, composed, by me.
</p>
- <h3><a href="./libs/pictures/osunix-logo_sq_thicken.png">Picture Library</a></h3>
+ <h3><a href="//filestorage.chrisoft.org/blog/data/osunix-logo_sq_thicken.png">Picture Library</a></h3>
<p>
Nothin'.
</p>
@@ -536,19 +592,7 @@ function swonload(){
</div>
<div class="block" id="about">
<h2>About</h2><hr>
- <script>
- var r=new XMLHttpRequest();
- r.open("GET","/about_l.html");
- r.responseType="document";
- r.send();
- r.onload=function()
- {
- cont=r.response;
- e=cont.querySelector('.TText');
- document.getElementById('about').appendChild(e.cloneNode(true));
- document.getElementById('ti').src="toxid.png";
- }
- </script>
+ <!--#include virtual="about_l.html" -->
</div>
<div class="block" id="links">
<h2>Links</h2><hr>
@@ -569,14 +613,15 @@ function swonload(){
<li><a rel="external" target="_blank" href="https://yyc12345.github.io/MyBlog/">yyc12345 の Blog</a></li>
<li><a rel="external" target="_blank" href="https://oing9179.github.io/blog">oing9179 的笔记本儿</a></li>
<li><a rel="external" target="_blank" href="https://baka719.top">719daze</a></li>
- <li><a rel="external" target="_blank" href="https://owner.pw">OWNER203'S WORLD</a></li>
+ <li><a rel="external" target="_blank" href="https://world.203.jp/">OWNER203'S WORLD</a></li>
<li><a rel="external" target="_blank" href="https://un1c0de.xyz">UN1C0DE</a></li>
+ <li><a rel="external" target="_blank" href="https://www.swung0x48.com/">Excerpt &#8211; A Blog of Swung</a></li>
</ul>
</div>
<div style="text-align:center;padding:0.5em;">
<a href="https://www.debian.org"><img src="debianpowered.svg" alt="Powered by Debian"></a>
<a href="https://www.conoha.jp/conoha"><img src="conohahosted.svg" alt="Hosted by Conoha"></a><br>
- <a href="/blog/post/Privacy.html">Privacy</a> | Copyright Chris Xiong 2021
+ <a href="/blog/post/Privacy.html">Privacy</a> | Copyright Chris Xiong 2024
</div>
</div>
<div id="themesw" style="position:fixed;top:0;left:0;width:100%;height:100%;display:none;opacity:0;background-color:rgba(0,0,0,0.6);z-index:999;transition:opacity 0.5s;" onclick="hidethemesw()">
diff --git a/leave-a-message/.htaccess b/leave-a-message/.htaccess
index 1604995..db52361 100644
--- a/leave-a-message/.htaccess
+++ b/leave-a-message/.htaccess
@@ -1,3 +1,4 @@
+Options -Indexes
<Files "archive.txt">
Require all denied
</Files>
diff --git a/leave-a-message/blossom.png b/leave-a-message/blossom.png
deleted file mode 100644
index 6f2c304..0000000
--- a/leave-a-message/blossom.png
+++ /dev/null
Binary files differ
diff --git a/leave-a-message/extras.css b/leave-a-message/extras.css
deleted file mode 100644
index 907e88c..0000000
--- a/leave-a-message/extras.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.CTitle {
- color: #fff;
-}
-.TText {
- color: #fff;
-}
-body {
- background: #000;
- background-image: url(blossom.png);
-}
-table {
- background: rgba(0,0,0,0.8);
-}
-note, .note {
- vertical-align: super;
- font-size: 60%;
-}
-reduced, .reduced {
- font-size: 75%;
-}
diff --git a/leave-a-message/index.php b/leave-a-message/index.php
deleted file mode 100644
index 3589515..0000000
--- a/leave-a-message/index.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Chrisoft::Leave a message</title>
- <link rel=stylesheet href='../common.css' type='text/css'>
- <link rel=stylesheet href='extras.css' type='text/css'>
- <style type="text/css">
- div.comment{
- border:1px solid #CCC;
- }
- div.author{
- text-align:right;
- }
- </style>
- <script src='https://www.google.com/recaptcha/api.js'></script>
- <script type="text/javascript">
- function verify()
- {
- if(document.getElementById("content").value.length+document.getElementById("name").value.length>16300)return;
- try
- {
- if(grecaptcha.getResponse().length===0)
- document.getElementById("ann").style.display="inline-block";
- else document.getElementById("msgform").submit();
- }
- catch(e){return;}
- }
- function ol()
- {
- if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- document.getElementById("tab").style.width="98%",
- document.getElementById("msgform").style.width="96%";
- }
- </script>
- <?php
- if(isset($_POST['name']))
- echo "<script>
- window.onload=function()
- {
- document.getElementById(\"ann\").style.display=\"inline-block\";
- document.getElementById(\"name\").value=\"".$_POST['name']."\";
- document.getElementById(\"content\").value=\"".$_POST['content']."\";
- }
- </script>";
- ?>
-</head>
-<body onload="ol()">
-<table id="tab" border="0" style="width:70%;margin:auto;">
- <tr>
- <td class="CTitle" style="font-size:2em;">
- <a href="../">Chrisoft</a>::Messages
- </td>
- </tr>
- <tr><td>
- <h1 class="TText">Deprecated. Use Guestbook found in the homepage instead.</h1>
- <div class="TText" style="margin:auto;width:80%">
- <?php
- $file=fopen("/var/www/html/leave-a-message/messages.txt","r");
- $comms;$i=0;
- while(($str=fgets($file,16384))!==false)$comms[$i++]=$str;
- fclose($file);
- while(--$i>=0)echo $comms[$i];
- ?>
- <form action="writemessage.php" id="msgform" method="post" style="width:50%;margin:auto;padding:5px;border:1px solid #CCC;">
- <span style="width:90%;display:table;">
- <label for="name" style="display:table-cell;width:1px;white-space:nowrap;">Your honourable name:</label>
- <input type="text" id="name" name="name" required style="margin-left:5px;display:table-cell;width:100%;">
- </span>
- <p>Message:</p>
- <textarea required id="content" name="content" rows="5" style="width:90%;margin-left:1px;"></textarea>
- <p>
- Something Annoying: <span id="ann" style="color:#F00;display:none;">Please complete the annoying challenge!</span></p>
- <div class="g-recaptcha" data-sitekey="6Lf1lAcUAAAAAGep8SpTETdIrEiw6w8uVy8IXp9U"></div><br>
- <div style="text-align:center;">
- <button onclick="verify();" type="button" style="border:none;color:white;padding:0.5em 2em;text-align:center;background-color:#44AA44;-webkit-transition-duration:0.4s;transition-duration:0.4s;">Leave the message!</button>
- </div>
- </form>
- </div>
- </td></tr>
-</table>
-</body>
diff --git a/leave-a-message/writemessage.php b/leave-a-message/writemessage.php
deleted file mode 100644
index 5308954..0000000
--- a/leave-a-message/writemessage.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<html>
-<?php
- function onerror($n,$m)
- {
- echo "<script>
- window.onload=function()
- {
- var f = document.createElement('form');
- f.action='https://chrisoft.org/leave-a-message/';
- f.method='POST';
- f.style.display='none';
-
- var i=document.createElement('input');
- i.type='hidden';
- i.name='name';
- i.value='".$n."';
- f.appendChild(i);
- i=document.createElement('input');
- i.type='hidden';
- i.name='content';
- i.value='".$m."';
- f.appendChild(i);
-
- document.body.appendChild(f);
- f.submit();
- }
- </script>";
- }
- $name;$mesg;$captcha;
- if(isset($_POST['name']))
- $name=$_POST['name'];
- if(isset($_POST['content']))
- $mesg=$_POST['content'];
- if(isset($_POST['g-recaptcha-response']))
- $captcha=$_POST['g-recaptcha-response'];
- if(!$captcha){
- onerror($name,$mesg);
- exit;
- }
- //OH SHIT I LEAKED MY OWN KEY!!!
- //$response=json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=6Lf1lAcUAAAAABRj_EJ1OzhzGfiorpfYFbcGQE5r&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);
- //if($response['success'] == false)onerror($name,$mesg);
- if(false)
- {
- if(strlen($mesg)+strlen($name)>16300)echo "Your message is too long!!!";
- $rmesg=htmlspecialchars($mesg);
- $rmesg=nl2br($rmesg,false);
- $rmesg=trim(preg_replace('/\s\s+/', ' ', $rmesg));
- $f=fopen("/var/www/html/leave-a-message/messages.txt","a");
- $str=sprintf("<div class=\"comment\"><p>%s</p><div class=\"author\">%s at %s</div></div><br>\n",$rmesg,htmlspecialchars($name),strftime("%Y-%m-%d %H:%M"));
- fwrite($f,$str);
- fclose($f);
- $f=fopen("/var/www/html/leave-a-message/messages.json","a");
- $str=sprintf("{\"cont\":\"%s\",\"author\":\"%s\",\"time\":\"%s\"}\n",$rmesg,htmlspecialchars($name),strftime("%Y-%m-%d %H:%M"));
- fwrite($f,$str);
- fclose($f);
- $f=fopen("/var/www/html/leave-a-message/archive.txt","a");
- $str=sprintf("comment: %s\nauthor: %s\ntime: %s\nIP: %s\n\n",$mesg,$name,strftime("%Y-%m-%d %H:%M:%S"),$_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']);
- fwrite($f,$str);
- fclose($f);
- echo "<script>window.location='https://chrisoft.org/#guestbook'</script>";
- }
-?>
-</html>
-<body>
-</body>
diff --git a/libs/code/index.html b/libs/code/index.html
deleted file mode 100755
index a023fd1..0000000
--- a/libs/code/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<html>
-<head>
-<title>Litter Rubbish Garbage Trash</title>
-<link rel=stylesheet href='../../common.css' type='text/css'>
-<style type="text/css">
-body
-{
- background: #acf;
- margin: 33px
-}
-pre, address
-{
- font-family: Courier, monospace;
-}
-</style>
-</head>
-<body>
-<font size="6"><div class="TText"><a href="../../">Chrisoft</a>::Code Library</div></font>
-<p class="TText">Why are you here?<br/>
-<a href="https://github.com/chirs241097">My github</a><br>
-<a href="http://chrisoft.org/codeforces-rating-cmp/">CodeForces Rating Comparator</a>
-</p>
-</body>
-</html>
diff --git a/libs/music/pcm b/libs/music/pcm
index adb3458..7152edf 100644
--- a/libs/music/pcm
+++ b/libs/music/pcm
@@ -6,6 +6,14 @@
<meta name="theme-color" content="#f44336">
<link rel="stylesheet" href="/libs/music/player.d/w3.css">
<style>
+ @font-face{
+ font-family: 'CMU Typewriter Text w';
+ src: url(/cmunbtl.woff);
+ }
+ body, h1, h2, h3, h4 {
+ font-family: 'CMU Typewriter Text w', 'CMU Typewriter Text', 'TeX Gyre Cursor', 'FreeMono', 'Courier New', Courier, monospace;
+ font-variant-ligatures: none;
+ }
.w3-sidenav ul li {padding-left: 2px;}
#playlist li {word-break: break-all;}
.ellipsis {overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
@@ -52,7 +60,7 @@
<nav class="w3-sidenav w3-collapse w3-light-grey w3-animate-left w3-card-2" style="z-index: 3; width: 250px; display: none;" id="mySidenav">
<header class="w3-container w3-dark-grey">
- <h2>Albums <a href="javascript:void(0)" onclick="w3_close()" class="w3-right w3-xlarge w3-hide-large w3-closenav" title="close sidenav">×</a></h2>
+ <h2>Folders <a href="javascript:void(0)" onclick="w3_close()" class="w3-right w3-xlarge w3-hide-large w3-closenav" title="close sidenav">×</a></h2>
</header>
<ul class="w3-ul" style="margin-bottom: 120px;" id="folderlist">
</ul>
@@ -60,7 +68,7 @@
<div class="w3-overlay w3-hide-large w3-animate-opacity" onclick="w3_close()" style="cursor: pointer; display: none;" id="myOverlay"></div>
<div class="w3-main" style="margin-left:250px;">
<header class="w3-container w3-red w3-top">
- <h2 class="ellipsis"><span class="w3-opennav w3-xlarge w3-left w3-hide-large" onclick="w3_open()" id="openNav">&#9776;</span>&nbsp;Pineapple Cloud Music</h2>
+ <h2 class="ellipsis"><span class="w3-opennav w3-xlarge w3-left w3-hide-large" onclick="w3_open()" id="openNav">&#9776;</span>&nbsp;<span id="server-name">Private Cloud Music</span></h2>
</header>
<header class="w3-container w3-yellow"><h2 class="ellipsis">You can't see me</h2></header>
<ul class="w3-ul w3-hoverable w3-pale-yellow" id="subfolderlist">
@@ -83,10 +91,7 @@
</div>
</div>
<div class="w3-container">
- <div id="progressbar" class="w3-progress-container">
- <div id="bufferbar" class="w3-progressbar" style="background-color:#AAA; width:0%"></div>
- <div id="timebar" class="w3-progressbar w3-blue" style="width:0%"></div>
- </div>
+ <pcm-progress id="progress-bar"></pcm-progress>
</div>
<div class="w3-container w3-center" style="padding:6px 0px;">
<button class="w3-btn w3-tiny" id="btn-prev">&lt;&lt;</button>
@@ -98,6 +103,7 @@
</div>
</div>
+<script src="/libs/music/player.d/progress-bar.js"></script>
<script src="/libs/music/player.d/pcm.js"></script>
<script>
function w3_open() {
diff --git a/libs/music/player b/libs/music/player
index 29e90fd..ae89d67 100644
--- a/libs/music/player
+++ b/libs/music/player
@@ -25,6 +25,8 @@
The Stupid Online Player
License: Expat (MIT)
Changelog:
+2021.12.07 2.7.1
+Added help for the new player. Make format switcher available.
2021.04.05 2.7.0
Clicking the track name after "Now Playing" shows the note for it.
2020.08.04 2.6.1+b1
@@ -92,6 +94,32 @@ The online player was added.
-->
<body onload="init();">
<div id="overlay"><span style="text-align:center;" id="overlaytext" class="TText">LOADING...</span></div>
+ <div id="helpoverlay" class="TText">
+ <pre class="TText" style="padding:2em;overflow:auto scroll;white-space:pre-wrap;">
+The Simple Guide to The Stupid Online Player
+
+Use the links in the sidebar to select a playlist. Click on the name of the tracks to play.
+
+Playback controls at the bottom of the page should be self-explanatory. Use the visualization combo box to select a visualization to view.
+
+The m3u8 Playlist link gives you a m3u8 playlist that can be streamed in VLC and other players supporting them.
+
+Use the format link to switch the audio format to be played. Currently the following formats are served:
+
+ ogg vorbis 224 kbps | Very high quality, ideal choice if supported by your browser.
+ flac | Lossless, very large file size.
+ opus 96 kbps | Decent quality, small file size. Good for reducing data usage.
+ m4a aac 192 kbps | High quality, for legacy browsers without support of open formats.
+
+If the format shows an exclamation mark after it, it could be unsupported by your browser.
+
+To view the description of the currently selected album, click on the currently selected album in the sidebar. To view the description of the currently playing track, click on the link after "Now Playing: " in the bottom. Not all tracks have description texts.
+
+Some tracks offer "multi-mixes". They are only provided in the ogg format. You need to enable experimental features in your browser for them to work. For chromium-based browsers, turn on "enable-experimental-web-platform-features". For firefox-based browsers, turn on "media.track.enabled" (however firefox doesn't seem to support multitrack ogg files yet). Once the support is correctly enabled, you'll see "Press C to switch tracks" over the seek bar for these tracks.
+
+All tracks on this site are available for download. You can simply right click the links in the playlist and save the link. Alternatively you can go to the "Downloads" link in the sidebar, where you can find all tracks in all formats, a few unlisted tracks, and some MIDI exports. Unless otherwise stated, all finished tracks here can be used under a permissive CC-BY 4.0 license. Please contact the owner of the site if you want to use the MIDI exports.
+ </pre><a href="javascript:NSUI.hideHelp()" style="right:2em;bottom:1em;position:absolute;">close</a>
+ </div>
<div id="notes" class="TText" style="display:none;"><div class="TText" id="ntext"></div>
<a href="javascript:NSUI.hideNotes()" style="right:1em;bottom:.5em;position:absolute;">close</a></div>
<div id="panel" class="TText">
@@ -100,7 +128,8 @@ The online player was added.
<li><a href="/libs/music/player"><h2>Music Library</h2></a></li>
<li><ul id="plists"></ul></li>
<li><a href="//filestorage.chrisoft.org/music/" target="_blank">Downloads</a></li>
- <li><a>TSOP 2.7.0</a></li>
+ <li><a href="javascript:NSUI.showHelp()">Help</a></li>
+ <li><a>TSOP 2.7.1</a></li>
</ul>
</div>
<div id="content">
@@ -113,6 +142,7 @@ The online player was added.
<div class="switches" style="text-align:right;padding-top:0.25em 0 0.25em 0;">
<div style="text-align:center;width:100%;" id="nowplaying"></div>
<span id="mt" style="display:none;">Press C to switch tracks</span>
+ <a id="formatsw" href="#">[PCM wave 64 kbps]</a>
<a id="am3u8" href="#">[m3u8 Playlist]</a>
<a id="plistsw" href="javascript:void(0);">[Hide Playlist]</a>
</div>
diff --git a/libs/music/player.d/cgi-bin/m3u8.cgi b/libs/music/player.d/cgi-bin/m3u8.cgi
index 7e14493..506ce0e 100755
--- a/libs/music/player.d/cgi-bin/m3u8.cgi
+++ b/libs/music/player.d/cgi-bin/m3u8.cgi
@@ -18,7 +18,7 @@ print('Content-type: audio/mpegurl',end='\r\n')
print(end='\r\n')
f.readline()
try:
- fmt=d['type'][0] if d['type'][0] in ['ogg','wav','flac'] else 'ogg'
+ fmt=d['type'][0] if d['type'][0] in ['ogg','flac','opus','m4a'] else 'ogg'
except KeyError:
fmt='ogg'
for line in f:
diff --git a/libs/music/player.d/cgi-bin/pcm.cgi b/libs/music/player.d/cgi-bin/pcm.cgi
index e43262f..34539ad 100755
--- a/libs/music/player.d/cgi-bin/pcm.cgi
+++ b/libs/music/player.d/cgi-bin/pcm.cgi
@@ -1,31 +1,60 @@
#!/usr/bin/python3
import sys,os,cgi,json
from urllib.parse import quote,unquote
-d=cgi.parse(fp=sys.stdin)
-print('Status: 200 OK',end='\r\n')
-print('Content-type: application/json',end='\r\n')
-print(end='\r\n')
+def getfilelist(d):
+ fmt='ogg' if 'fmt' not in d else d['fmt']
+ AUDIO_BASE='//filestorage.chrisoft.org/music/ogg/'
+
+ ro={'status':200,'message':'OK'}
+ if 'folder' not in d or d['folder']=='':
+ plp=os.environ['DOCUMENT_ROOT']+'/libs/music/player.d/playlists/playlists'
+ alblist=list()
+ with open(plp,mode='r',encoding='utf-8') as f:
+ for line in f:
+ line=line.strip()
+ if len(line)>0:alblist.append(quote(line))
+ rro={'type':'fileList','data':{'subFolderList':alblist}}
+ ro['result']=rro
+ print(json.dumps(ro))
+ else:
+ alp=os.environ['DOCUMENT_ROOT']+'/libs/music/player.d/playlists/'+unquote(d['folder'][0]).strip('/')+'.playlist'
+ alblist=list()
+ with open(alp,mode='r',encoding='utf-8') as f:
+ for line in f:
+ line=line.strip()
+ if len(line)>0:
+ alblist.append({
+ 'fileName':quote(line+'.ogg'),
+ 'url':quote(AUDIO_BASE+line+'.ogg'),
+ 'displayName':line,
+ 'fileSize':0,
+ 'modifiedTime':0
+ })
+ rro={'type':'fileList','data':{'musicList':alblist[1:],'subFolderList':list()}}
+ ro['result']=rro
+ print(json.dumps(ro))
+
+def getserverinfo(d):
+ ro={'status': 200, 'message': 'OK'}
+ ro['result']={
+ 'serverName': 'Pineapple Cloud Music',
+ 'serverShortName': 'PCM',
+ 'baseFolderNameHint': '',
+ 'preferredFormatsHint': 'ogg',
+ 'apiVersion': 1,
+ 'mediaRootUrl': '//filestorage.chrisoft.org/music/ogg/'
+ }
+ print(json.dumps(ro))
+
+if __name__ == '__main__':
+ d=cgi.parse(fp=sys.stdin)
+
+ print('Status: 200 OK',end='\r\n')
+ print('Content-type: application/json',end='\r\n')
+ print(end='\r\n')
+
+ actionmap={'getserverinfo':getserverinfo, 'getfilelist':getfilelist}
+ if d['do'][0] in actionmap:
+ actionmap[d['do'][0]](d)
-ro={'status':200,'message':'OK'}
-if 'folder' not in d or d['folder']=='':
- plp=os.environ['DOCUMENT_ROOT']+'/libs/music/player.d/playlists/playlists'
- alblist=list()
- with open(plp,mode='r',encoding='utf-8') as f:
- for line in f:
- line=line.strip()
- if len(line)>0:alblist.append(quote(line))
- rro={'type':'fileList','data':{'subFolderList':alblist}}
- ro['result']=rro
- print(json.dumps(ro))
-else:
- alp=os.environ['DOCUMENT_ROOT']+'/libs/music/player.d/playlists/'+unquote(d['folder'][0]).strip('/')+'.playlist'
- alblist=list()
- with open(alp,mode='r',encoding='utf-8') as f:
- for line in f:
- line=line.strip()
- if len(line)>0:
- alblist.append({'fileName':quote(line),'fileSize':0,'modifiedTime':0})
- rro={'type':'fileList','data':{'musicList':alblist[1:],'subFolderList':list()}}
- ro['result']=rro
- print(json.dumps(ro))
diff --git a/libs/music/player.d/jquery-3.0.0.js b/libs/music/player.d/jquery-3.0.0.js
deleted file mode 100644
index aad916a..0000000
--- a/libs/music/player.d/jquery-3.0.0.js
+++ /dev/null
@@ -1,10037 +0,0 @@
-/*!
- * jQuery JavaScript Library v3.0.0
- * https://jquery.com/
- *
- * Includes Sizzle.js
- * https://sizzlejs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2016-06-09T18:02Z
- */
-( function( global, factory ) {
-
- "use strict";
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
-
- // For CommonJS and CommonJS-like environments where a proper `window`
- // is present, execute the factory and get jQuery.
- // For environments that do not have a `window` with a `document`
- // (such as Node.js), expose a factory as module.exports.
- // This accentuates the need for the creation of a real `window`.
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info.
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-}( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
-// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
-// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
-// enough that all such attempts are guarded in a try block.
-"use strict";
-
-var arr = [];
-
-var document = window.document;
-
-var getProto = Object.getPrototypeOf;
-
-var slice = arr.slice;
-
-var concat = arr.concat;
-
-var push = arr.push;
-
-var indexOf = arr.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var fnToString = hasOwn.toString;
-
-var ObjectFunctionString = fnToString.call( Object );
-
-var support = {};
-
-
-
- function DOMEval( code, doc ) {
- doc = doc || document;
-
- var script = doc.createElement( "script" );
-
- script.text = code;
- doc.head.appendChild( script ).parentNode.removeChild( script );
- }
-
-
-var
- version = "3.0.0",
-
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
-
- // The jQuery object is actually just the init constructor 'enhanced'
- // Need init if jQuery is called (just allow error to be thrown if not included)
- return new jQuery.fn.init( selector, context );
- },
-
- // Support: Android <=4.0 only
- // Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
- // Matches dashed string for camelizing
- rmsPrefix = /^-ms-/,
- rdashAlpha = /-([a-z])/g,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return letter.toUpperCase();
- };
-
-jQuery.fn = jQuery.prototype = {
-
- // The current version of jQuery being used
- jquery: version,
-
- constructor: jQuery,
-
- // The default length of a jQuery object is 0
- length: 0,
-
- toArray: function() {
- return slice.call( this );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num != null ?
-
- // Return just the one element from the set
- ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
-
- // Return all the elements in a clean array
- slice.call( this );
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
-
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- each: function( callback ) {
- return jQuery.each( this, callback );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map( this, function( elem, i ) {
- return callback.call( elem, i, elem );
- } ) );
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ) );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- eq: function( i ) {
- var len = this.length,
- j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
- },
-
- end: function() {
- return this.prevObject || this.constructor();
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: arr.sort,
- splice: arr.splice
-};
-
-jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[ 0 ] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
-
- // Skip the boolean and the target
- target = arguments[ i ] || {};
- i++;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
- target = {};
- }
-
- // Extend jQuery itself if only one argument is passed
- if ( i === length ) {
- target = this;
- i--;
- }
-
- for ( ; i < length; i++ ) {
-
- // Only deal with non-null/undefined values
- if ( ( options = arguments[ i ] ) != null ) {
-
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
- ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
-
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray( src ) ? src : [];
-
- } else {
- clone = src && jQuery.isPlainObject( src ) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend( {
-
- // Unique for each copy of jQuery on the page
- expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
-
- // Assume jQuery is ready without the ready module
- isReady: true,
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- noop: function() {},
-
- isFunction: function( obj ) {
- return jQuery.type( obj ) === "function";
- },
-
- isArray: Array.isArray,
-
- isWindow: function( obj ) {
- return obj != null && obj === obj.window;
- },
-
- isNumeric: function( obj ) {
-
- // As of jQuery 3.0, isNumeric is limited to
- // strings and numbers (primitives or objects)
- // that can be coerced to finite numbers (gh-2662)
- var type = jQuery.type( obj );
- return ( type === "number" || type === "string" ) &&
-
- // parseFloat NaNs numeric-cast false positives ("")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- !isNaN( obj - parseFloat( obj ) );
- },
-
- isPlainObject: function( obj ) {
- var proto, Ctor;
-
- // Detect obvious negatives
- // Use toString instead of jQuery.type to catch host objects
- if ( !obj || toString.call( obj ) !== "[object Object]" ) {
- return false;
- }
-
- proto = getProto( obj );
-
- // Objects with no prototype (e.g., `Object.create( null )`) are plain
- if ( !proto ) {
- return true;
- }
-
- // Objects with prototype are plain iff they were constructed by a global Object function
- Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
- return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
- },
-
- isEmptyObject: function( obj ) {
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
- },
-
- type: function( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
-
- // Support: Android <=2.3 only (functionish RegExp)
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call( obj ) ] || "object" :
- typeof obj;
- },
-
- // Evaluates a script in a global context
- globalEval: function( code ) {
- DOMEval( code );
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Support: IE <=9 - 11, Edge 12 - 13
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
- },
-
- each: function( obj, callback ) {
- var length, i = 0;
-
- if ( isArrayLike( obj ) ) {
- length = obj.length;
- for ( ; i < length; i++ ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
- break;
- }
- }
- }
-
- return obj;
- },
-
- // Support: Android <=4.0 only
- trim: function( text ) {
- return text == null ?
- "" :
- ( text + "" ).replace( rtrim, "" );
- },
-
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var ret = results || [];
-
- if ( arr != null ) {
- if ( isArrayLike( Object( arr ) ) ) {
- jQuery.merge( ret,
- typeof arr === "string" ?
- [ arr ] : arr
- );
- } else {
- push.call( ret, arr );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, arr, i ) {
- return arr == null ? -1 : indexOf.call( arr, elem, i );
- },
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- merge: function( first, second ) {
- var len = +second.length,
- j = 0,
- i = first.length;
-
- for ( ; j < len; j++ ) {
- first[ i++ ] = second[ j ];
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, invert ) {
- var callbackInverse,
- matches = [],
- i = 0,
- length = elems.length,
- callbackExpect = !invert;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- callbackInverse = !callback( elems[ i ], i );
- if ( callbackInverse !== callbackExpect ) {
- matches.push( elems[ i ] );
- }
- }
-
- return matches;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var length, value,
- i = 0,
- ret = [];
-
- // Go through the array, translating each of the items to their new values
- if ( isArrayLike( elems ) ) {
- length = elems.length;
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( i in elems ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
- }
-
- // Flatten any nested arrays
- return concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var tmp, args, proxy;
-
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- args = slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
- return proxy;
- },
-
- now: Date.now,
-
- // jQuery.support is not used in Core but other projects attach their
- // properties to it so it needs to exist.
- support: support
-} );
-
-// JSHint would error on this code due to the Symbol not being defined in ES5.
-// Defining this global in .jshintrc would create a danger of using the global
-// unguarded in another place, it seems safer to just disable JSHint for these
-// three lines.
-/* jshint ignore: start */
-if ( typeof Symbol === "function" ) {
- jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
-}
-/* jshint ignore: end */
-
-// Populate the class2type map
-jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
-function( i, name ) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-} );
-
-function isArrayLike( obj ) {
-
- // Support: real iOS 8.2 only (not reproducible in simulator)
- // `in` check used to prevent JIT error (gh-2145)
- // hasOwn isn't used here due to false negatives
- // regarding Nodelist length in IE
- var length = !!obj && "length" in obj && obj.length,
- type = jQuery.type( obj );
-
- if ( type === "function" || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- return type === "array" || length === 0 ||
- typeof length === "number" && length > 0 && ( length - 1 ) in obj;
-}
-var Sizzle =
-/*!
- * Sizzle CSS Selector Engine v2.3.0
- * https://sizzlejs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2016-01-04
- */
-(function( window ) {
-
-var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
-
- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
-
- // Instance-specific data
- expando = "sizzle" + 1 * new Date(),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
-
- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf as it's faster than native
- // https://jsperf.com/thor-indexof-vs-for/5
- indexOf = function( list, elem ) {
- var i = 0,
- len = list.length;
- for ( ; i < len; i++ ) {
- if ( list[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
-
- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
-
- // Regular expressions
-
- // http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
-
- // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
-
- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
-
- pseudos = ":(" + identifier + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
-
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rwhitespace = new RegExp( whitespace + "+", "g" ),
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
-
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
-
- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
-
- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
-
- matchExpr = {
- "ID": new RegExp( "^#(" + identifier + ")" ),
- "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
- "TAG": new RegExp( "^(" + identifier + "|[*])" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
-
- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
-
- rnative = /^[^{]+\{\s*\[native \w/,
-
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-
- rsibling = /[+~]/,
-
- // CSS escapes
- // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- },
-
- // CSS string/identifier serialization
- // https://drafts.csswg.org/cssom/#common-serializing-idioms
- rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,
- fcssescape = function( ch, asCodePoint ) {
- if ( asCodePoint ) {
-
- // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
- if ( ch === "\0" ) {
- return "\uFFFD";
- }
-
- // Control characters and (dependent upon position) numbers get escaped as code points
- return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
- }
-
- // Other potentially-special ASCII characters get backslash-escaped
- return "\\" + ch;
- },
-
- // Used for iframes
- // See setDocument()
- // Removing the function wrapper causes a "Permission Denied"
- // error in IE
- unloadHandler = function() {
- setDocument();
- },
-
- disabledAncestor = addCombinator(
- function( elem ) {
- return elem.disabled === true;
- },
- { dir: "parentNode", next: "legend" }
- );
-
-// Optimize for push.apply( _, NodeList )
-try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
-} catch ( e ) {
- push = { apply: arr.length ?
-
- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
-
- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
-}
-
-function Sizzle( selector, context, results, seed ) {
- var m, i, elem, nid, match, groups, newSelector,
- newContext = context && context.ownerDocument,
-
- // nodeType defaults to 9, since context defaults to document
- nodeType = context ? context.nodeType : 9;
-
- results = results || [];
-
- // Return early from calls with invalid selector or context
- if ( typeof selector !== "string" || !selector ||
- nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
-
- return results;
- }
-
- // Try to shortcut find operations (as opposed to filters) in HTML documents
- if ( !seed ) {
-
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
- context = context || document;
-
- if ( documentIsHTML ) {
-
- // If the selector is sufficiently simple, try using a "get*By*" DOM method
- // (excepting DocumentFragment context, where the methods don't exist)
- if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
-
- // ID selector
- if ( (m = match[1]) ) {
-
- // Document context
- if ( nodeType === 9 ) {
- if ( (elem = context.getElementById( m )) ) {
-
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
-
- // Element context
- } else {
-
- // Support: IE, Opera, Webkit
- // TODO: identify versions
- // getElementById can match elements by name instead of ID
- if ( newContext && (elem = newContext.getElementById( m )) &&
- contains( context, elem ) &&
- elem.id === m ) {
-
- results.push( elem );
- return results;
- }
- }
-
- // Type selector
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
-
- // Class selector
- } else if ( (m = match[3]) && support.getElementsByClassName &&
- context.getElementsByClassName ) {
-
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
-
- // Take advantage of querySelectorAll
- if ( support.qsa &&
- !compilerCache[ selector + " " ] &&
- (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
-
- if ( nodeType !== 1 ) {
- newContext = context;
- newSelector = selector;
-
- // qSA looks outside Element context, which is not what we want
- // Thanks to Andrew Dupont for this workaround technique
- // Support: IE <=8
- // Exclude object elements
- } else if ( context.nodeName.toLowerCase() !== "object" ) {
-
- // Capture the context ID, setting it first if necessary
- if ( (nid = context.getAttribute( "id" )) ) {
- nid = nid.replace( rcssescape, fcssescape );
- } else {
- context.setAttribute( "id", (nid = expando) );
- }
-
- // Prefix every selector in the list
- groups = tokenize( selector );
- i = groups.length;
- while ( i-- ) {
- groups[i] = "#" + nid + " " + toSelector( groups[i] );
- }
- newSelector = groups.join( "," );
-
- // Expand context for sibling selectors
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
- context;
- }
-
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch ( qsaError ) {
- } finally {
- if ( nid === expando ) {
- context.removeAttribute( "id" );
- }
- }
- }
- }
- }
- }
-
- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
-
-/**
- * Create key-value caches of limited size
- * @returns {function(string, object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
-function createCache() {
- var keys = [];
-
- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
-}
-
-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
-}
-
-/**
- * Support testing using an element
- * @param {Function} fn Passed the created element and returns a boolean result
- */
-function assert( fn ) {
- var el = document.createElement("fieldset");
-
- try {
- return !!fn( el );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( el.parentNode ) {
- el.parentNode.removeChild( el );
- }
- // release memory in IE
- el = null;
- }
-}
-
-/**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
-function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = arr.length;
-
- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
-}
-
-/**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
-function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- a.sourceIndex - b.sourceIndex;
-
- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
-
- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
-
- return a ? 1 : -1;
-}
-
-/**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
-function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
-function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for :enabled/:disabled
- * @param {Boolean} disabled true for :disabled; false for :enabled
- */
-function createDisabledPseudo( disabled ) {
- // Known :disabled false positives:
- // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset)
- // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
- return function( elem ) {
-
- // Check form elements and option elements for explicit disabling
- return "label" in elem && elem.disabled === disabled ||
- "form" in elem && elem.disabled === disabled ||
-
- // Check non-disabled form elements for fieldset[disabled] ancestors
- "form" in elem && elem.disabled === false && (
- // Support: IE6-11+
- // Ancestry is covered for us
- elem.isDisabled === disabled ||
-
- // Otherwise, assume any non-<option> under fieldset[disabled] is disabled
- /* jshint -W018 */
- elem.isDisabled !== !disabled &&
- ("label" in elem || !disabledAncestor( elem )) !== disabled
- );
- };
-}
-
-/**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
-function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
-
- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
-}
-
-/**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
-function testContext( context ) {
- return context && typeof context.getElementsByTagName !== "undefined" && context;
-}
-
-// Expose support vars for convenience
-support = Sizzle.support = {};
-
-/**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
-isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare, subWindow,
- doc = node ? node.ownerDocument || node : preferredDoc;
-
- // Return early if doc is invalid or already selected
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
-
- // Update global variables
- document = doc;
- docElem = document.documentElement;
- documentIsHTML = !isXML( document );
-
- // Support: IE 9-11, Edge
- // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
- if ( preferredDoc !== document &&
- (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
-
- // Support: IE 11, Edge
- if ( subWindow.addEventListener ) {
- subWindow.addEventListener( "unload", unloadHandler, false );
-
- // Support: IE 9 - 10 only
- } else if ( subWindow.attachEvent ) {
- subWindow.attachEvent( "onunload", unloadHandler );
- }
- }
-
- /* Attributes
- ---------------------------------------------------------------------- */
-
- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties
- // (excepting IE8 booleans)
- support.attributes = assert(function( el ) {
- el.className = "i";
- return !el.getAttribute("className");
- });
-
- /* getElement(s)By*
- ---------------------------------------------------------------------- */
-
- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( el ) {
- el.appendChild( document.createComment("") );
- return !el.getElementsByTagName("*").length;
- });
-
- // Support: IE<9
- support.getElementsByClassName = rnative.test( document.getElementsByClassName );
-
- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programmatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( el ) {
- docElem.appendChild( el ).id = expando;
- return !document.getElementsByName || !document.getElementsByName( expando ).length;
- });
-
- // ID find and filter
- if ( support.getById ) {
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
- var m = context.getElementById( id );
- return m ? [ m ] : [];
- }
- };
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- } else {
- // Support: IE6/7
- // getElementById is not reliable as a find shortcut
- delete Expr.find["ID"];
-
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== "undefined" &&
- elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
- }
-
- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- return context.getElementsByTagName( tag );
-
- // DocumentFragment nodes don't have gEBTN
- } else if ( support.qsa ) {
- return context.querySelectorAll( tag );
- }
- } :
-
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
- results = context.getElementsByTagName( tag );
-
- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
-
- return tmp;
- }
- return results;
- };
-
- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
-
- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
-
- // QSA and matchesSelector support
-
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
-
- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See https://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
-
- if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( el ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // https://bugs.jquery.com/ticket/12359
- docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
- "<select id='" + expando + "-\r\\' msallowcapture=''>" +
- "<option selected=''></option></select>";
-
- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( el.querySelectorAll("[msallowcapture^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
-
- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !el.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
-
- // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
- if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
- rbuggyQSA.push("~=");
- }
-
- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !el.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
-
- // Support: Safari 8+, iOS 8+
- // https://bugs.webkit.org/show_bug.cgi?id=136851
- // In-page `selector#id sibling-combinator selector` fails
- if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
- rbuggyQSA.push(".#.+[+~]");
- }
- });
-
- assert(function( el ) {
- el.innerHTML = "<a href='' disabled='disabled'></a>" +
- "<select disabled='disabled'><option/></select>";
-
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = document.createElement("input");
- input.setAttribute( "type", "hidden" );
- el.appendChild( input ).setAttribute( "name", "D" );
-
- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( el.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
-
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( el.querySelectorAll(":enabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Support: IE9-11+
- // IE's :disabled selector does not pick up the children of disabled fieldsets
- docElem.appendChild( el ).disabled = true;
- if ( el.querySelectorAll(":disabled").length !== 2 ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Opera 10-11 does not throw on post-comma invalid pseudos
- el.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
-
- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
-
- assert(function( el ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( el, "*" );
-
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( el, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
-
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
-
- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
-
- // Element contains another
- // Purposefully self-exclusive
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
-
- /* Sorting
- ---------------------------------------------------------------------- */
-
- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
-
- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
-
- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
-
- // Otherwise we know they are disconnected
- 1;
-
- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
-
- // Choose the first element that is related to our preferred document
- if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
-
- // Maintain original order
- return sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
- }
-
- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
-
- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === document ? -1 :
- b === document ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
- 0;
-
- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
-
- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
-
- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
-
- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
-
- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
-
- return document;
-};
-
-Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
-};
-
-Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
-
- if ( support.matchesSelector && documentIsHTML &&
- !compilerCache[ expr + " " ] &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
-
- try {
- var ret = matches.call( elem, expr );
-
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch (e) {}
- }
-
- return Sizzle( expr, document, null, [ elem ] ).length > 0;
-};
-
-Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
-};
-
-Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
-
- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
-};
-
-Sizzle.escape = function( sel ) {
- return (sel + "").replace( rcssescape, fcssescape );
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
-Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
-
- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
-
- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
-
- return results;
-};
-
-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
-
- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
-
- return ret;
-};
-
-Expr = Sizzle.selectors = {
-
- // Can be adjusted by the user
- cacheLength: 50,
-
- createPseudo: markFunction,
-
- match: matchExpr,
-
- attrHandle: {},
-
- find: {},
-
- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
-
- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
-
- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
-
- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
-
- return match.slice( 0, 4 );
- },
-
- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
-
- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
-
- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
-
- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
-
- return match;
- },
-
- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
-
- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
-
- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
-
- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
-
- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
-
- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
-
- filter: {
-
- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
-
- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
-
- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
- });
- },
-
- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
-
- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
-
- result += "";
-
- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
-
- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
-
- return first === 1 && last === 0 ?
-
- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
-
- function( elem, context, xml ) {
- var cache, uniqueCache, outerCache, node, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType,
- diff = false;
-
- if ( parent ) {
-
- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) {
-
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
-
- start = [ forward ? parent.firstChild : parent.lastChild ];
-
- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
-
- // Seek `elem` from a previously-cached index
-
- // ...in a gzip-friendly way
- node = parent;
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex && cache[ 2 ];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
-
- while ( (node = ++nodeIndex && node && node[ dir ] ||
-
- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
-
- } else {
- // Use previously-cached element index if available
- if ( useCache ) {
- // ...in a gzip-friendly way
- node = elem;
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- cache = uniqueCache[ type ] || [];
- nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
- diff = nodeIndex;
- }
-
- // xml :nth-child(...)
- // or :nth-last-child(...) or :nth(-last)?-of-type(...)
- if ( diff === false ) {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- if ( ( ofType ?
- node.nodeName.toLowerCase() === name :
- node.nodeType === 1 ) &&
- ++diff ) {
-
- // Cache the index of each encountered element
- if ( useCache ) {
- outerCache = node[ expando ] || (node[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ node.uniqueID ] ||
- (outerCache[ node.uniqueID ] = {});
-
- uniqueCache[ type ] = [ dirruns, diff ];
- }
-
- if ( node === elem ) {
- break;
- }
- }
- }
- }
- }
-
- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
-
- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
-
- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
-
- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
-
- return fn;
- }
- },
-
- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
-
- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
-
- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- // Don't keep the element (issue #299)
- input[0] = null;
- return !results.pop();
- };
- }),
-
- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
-
- "contains": markFunction(function( text ) {
- text = text.replace( runescape, funescape );
- return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
-
- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
-
- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
-
- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
-
- "root": function( elem ) {
- return elem === docElem;
- },
-
- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
-
- // Boolean properties
- "enabled": createDisabledPseudo( false ),
- "disabled": createDisabledPseudo( true ),
-
- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
-
- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
-
- return elem.selected === true;
- },
-
- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
-
- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
-
- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
-
- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
-
- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
-
- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
-
- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
-
- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
-
- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
-
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
-
- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
-};
-
-Expr.pseudos["nth"] = Expr.pseudos["eq"];
-
-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
-}
-
-// Easy API for creating new setFilters
-function setFilters() {}
-setFilters.prototype = Expr.filters = Expr.pseudos;
-Expr.setFilters = new setFilters();
-
-tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
-
- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
-
- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
-
- while ( soFar ) {
-
- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
-
- matched = false;
-
- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
-
- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
-
- if ( !matched ) {
- break;
- }
- }
-
- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
-};
-
-function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
-}
-
-function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- skip = combinator.next,
- key = skip || dir,
- checkNonElements = base && key === "parentNode",
- doneName = done++;
-
- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- } :
-
- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, uniqueCache, outerCache,
- newCache = [ dirruns, doneName ];
-
- // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
-
- // Support: IE <9 only
- // Defend against cloned attroperties (jQuery gh-1709)
- uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
-
- if ( skip && skip === elem.nodeName.toLowerCase() ) {
- elem = elem[ dir ] || elem;
- } else if ( (oldCache = uniqueCache[ key ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
-
- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- uniqueCache[ key ] = newCache;
-
- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- };
-}
-
-function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
-}
-
-function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
-}
-
-function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
-
- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
-
- return newUnmatched;
-}
-
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
-
- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
-
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
-
- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
-
- // ...intermediate processing is necessary
- [] :
-
- // ...otherwise use results directly
- results :
- matcherIn;
-
- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
-
- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
-
- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
-
- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
-
- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
-
- seed[temp] = !(results[temp] = elem);
- }
- }
- }
-
- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
-}
-
-function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
-
- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- // Avoid hanging onto element (issue #299)
- checkContext = null;
- return ret;
- } ];
-
- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
-
- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
-
- return elementMatcher( matchers );
-}
-
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
-
- if ( outermost ) {
- outermostContext = context === document || context || outermost;
- }
-
- // Add elements passing elementMatchers directly to results
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- if ( !context && elem.ownerDocument !== document ) {
- setDocument( elem );
- xml = !documentIsHTML;
- }
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context || document, xml) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
-
- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
-
- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
-
- // `i` is now the count of elements visited above, and adding it to `matchedCount`
- // makes the latter nonnegative.
- matchedCount += i;
-
- // Apply set filters to unmatched elements
- // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
- // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
- // no element matchers and no seed.
- // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
- // case, which will result in a "00" `matchedCount` that differs from `i` but is also
- // numerically zero.
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
-
- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
-
- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
-
- // Add matches to results
- push.apply( results, setMatched );
-
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
-
- Sizzle.uniqueSort( results );
- }
- }
-
- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
-
- return unmatched;
- };
-
- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
-}
-
-compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
-
- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
-
- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
-
- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
-};
-
-/**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
-select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
-
- results = results || [];
-
- // Try to minimize operations if there is only one selector in the list and no seed
- // (the latter of which guarantees us context)
- if ( match.length === 1 ) {
-
- // Reduce context if the leading compound selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- support.getById && context.nodeType === 9 && documentIsHTML &&
- Expr.relative[ tokens[1].type ] ) {
-
- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
-
- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
-
- selector = selector.slice( tokens.shift().value.length );
- }
-
- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
-
- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
-
- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
-
- break;
- }
- }
- }
- }
-
- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
-};
-
-// One-time assignments
-
-// Sort stability
-support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
-
-// Support: Chrome 14-35+
-// Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = !!hasDuplicate;
-
-// Initialize against the default document
-setDocument();
-
-// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
-// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( el ) {
- // Should return 1, but returns 4 (following)
- return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
-});
-
-// Support: IE<8
-// Prevent attribute/property "interpolation"
-// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( el ) {
- el.innerHTML = "<a href='#'></a>";
- return el.firstChild.getAttribute("href") === "#" ;
-}) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
-}
-
-// Support: IE<9
-// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( el ) {
- el.innerHTML = "<input/>";
- el.firstChild.setAttribute( "value", "" );
- return el.firstChild.getAttribute( "value" ) === "";
-}) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
-}
-
-// Support: IE<9
-// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( el ) {
- return el.getAttribute("disabled") == null;
-}) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
-}
-
-return Sizzle;
-
-})( window );
-
-
-
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-
-// Deprecated
-jQuery.expr[ ":" ] = jQuery.expr.pseudos;
-jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-jQuery.escapeSelector = Sizzle.escape;
-
-
-
-var dir = function( elem, dir, until ) {
- var matched = [],
- truncate = until !== undefined;
-
- while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
- if ( elem.nodeType === 1 ) {
- if ( truncate && jQuery( elem ).is( until ) ) {
- break;
- }
- matched.push( elem );
- }
- }
- return matched;
-};
-
-
-var siblings = function( n, elem ) {
- var matched = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- matched.push( n );
- }
- }
-
- return matched;
-};
-
-
-var rneedsContext = jQuery.expr.match.needsContext;
-
-var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
-
-
-
-var risSimple = /^.[^:#\[\.,]*$/;
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, not ) {
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep( elements, function( elem, i ) {
- /* jshint -W018 */
- return !!qualifier.call( elem, i, elem ) !== not;
- } );
-
- }
-
- if ( qualifier.nodeType ) {
- return jQuery.grep( elements, function( elem ) {
- return ( elem === qualifier ) !== not;
- } );
-
- }
-
- if ( typeof qualifier === "string" ) {
- if ( risSimple.test( qualifier ) ) {
- return jQuery.filter( qualifier, elements, not );
- }
-
- qualifier = jQuery.filter( qualifier, elements );
- }
-
- return jQuery.grep( elements, function( elem ) {
- return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
- } );
-}
-
-jQuery.filter = function( expr, elems, not ) {
- var elem = elems[ 0 ];
-
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return elems.length === 1 && elem.nodeType === 1 ?
- jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
- jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
- return elem.nodeType === 1;
- } ) );
-};
-
-jQuery.fn.extend( {
- find: function( selector ) {
- var i, ret,
- len = this.length,
- self = this;
-
- if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter( function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- } ) );
- }
-
- ret = this.pushStack( [] );
-
- for ( i = 0; i < len; i++ ) {
- jQuery.find( selector, self[ i ], ret );
- }
-
- return len > 1 ? jQuery.uniqueSort( ret ) : ret;
- },
- filter: function( selector ) {
- return this.pushStack( winnow( this, selector || [], false ) );
- },
- not: function( selector ) {
- return this.pushStack( winnow( this, selector || [], true ) );
- },
- is: function( selector ) {
- return !!winnow(
- this,
-
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- typeof selector === "string" && rneedsContext.test( selector ) ?
- jQuery( selector ) :
- selector || [],
- false
- ).length;
- }
-} );
-
-
-// Initialize a jQuery object
-
-
-// A central reference to the root jQuery(document)
-var rootjQuery,
-
- // A simple way to check for HTML strings
- // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
- // Strict HTML recognition (#11290: must start with <)
- // Shortcut simple #id case for speed
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
-
- init = jQuery.fn.init = function( selector, context, root ) {
- var match, elem;
-
- // HANDLE: $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
-
- // Method init() accepts an alternate rootjQuery
- // so migrate can support jQuery.sub (gh-2101)
- root = root || rootjQuery;
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector[ 0 ] === "<" &&
- selector[ selector.length - 1 ] === ">" &&
- selector.length >= 3 ) {
-
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = rquickExpr.exec( selector );
- }
-
- // Match html or make sure no context is specified for #id
- if ( match && ( match[ 1 ] || !context ) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[ 1 ] ) {
- context = context instanceof jQuery ? context[ 0 ] : context;
-
- // Option to run scripts is true for back-compat
- // Intentionally let the error be thrown if parseHTML is not present
- jQuery.merge( this, jQuery.parseHTML(
- match[ 1 ],
- context && context.nodeType ? context.ownerDocument || context : document,
- true
- ) );
-
- // HANDLE: $(html, props)
- if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
- for ( match in context ) {
-
- // Properties of context are called as methods if possible
- if ( jQuery.isFunction( this[ match ] ) ) {
- this[ match ]( context[ match ] );
-
- // ...and otherwise set as attributes
- } else {
- this.attr( match, context[ match ] );
- }
- }
- }
-
- return this;
-
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[ 2 ] );
-
- if ( elem ) {
-
- // Inject the element directly into the jQuery object
- this[ 0 ] = elem;
- this.length = 1;
- }
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || root ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(DOMElement)
- } else if ( selector.nodeType ) {
- this[ 0 ] = selector;
- this.length = 1;
- return this;
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return root.ready !== undefined ?
- root.ready( selector ) :
-
- // Execute immediately if ready is not present
- selector( jQuery );
- }
-
- return jQuery.makeArray( selector, this );
- };
-
-// Give the init function the jQuery prototype for later instantiation
-init.prototype = jQuery.fn;
-
-// Initialize central reference
-rootjQuery = jQuery( document );
-
-
-var rparentsprev = /^(?:parents|prev(?:Until|All))/,
-
- // Methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.fn.extend( {
- has: function( target ) {
- var targets = jQuery( target, this ),
- l = targets.length;
-
- return this.filter( function() {
- var i = 0;
- for ( ; i < l; i++ ) {
- if ( jQuery.contains( this, targets[ i ] ) ) {
- return true;
- }
- }
- } );
- },
-
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- matched = [],
- targets = typeof selectors !== "string" && jQuery( selectors );
-
- // Positional selectors never match, since there's no _selection_ context
- if ( !rneedsContext.test( selectors ) ) {
- for ( ; i < l; i++ ) {
- for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
-
- // Always skip document fragments
- if ( cur.nodeType < 11 && ( targets ?
- targets.index( cur ) > -1 :
-
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector( cur, selectors ) ) ) {
-
- matched.push( cur );
- break;
- }
- }
- }
- }
-
- return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
- },
-
- // Determine the position of an element within the set
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
- }
-
- // Index in selector
- if ( typeof elem === "string" ) {
- return indexOf.call( jQuery( elem ), this[ 0 ] );
- }
-
- // Locate the position of the desired element
- return indexOf.call( this,
-
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[ 0 ] : elem
- );
- },
-
- add: function( selector, context ) {
- return this.pushStack(
- jQuery.uniqueSort(
- jQuery.merge( this.get(), jQuery( selector, context ) )
- )
- );
- },
-
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter( selector )
- );
- }
-} );
-
-function sibling( cur, dir ) {
- while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
- return cur;
-}
-
-jQuery.each( {
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return siblings( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return siblings( elem.firstChild );
- },
- contents: function( elem ) {
- return elem.contentDocument || jQuery.merge( [], elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var matched = jQuery.map( this, fn, until );
-
- if ( name.slice( -5 ) !== "Until" ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- matched = jQuery.filter( selector, matched );
- }
-
- if ( this.length > 1 ) {
-
- // Remove duplicates
- if ( !guaranteedUnique[ name ] ) {
- jQuery.uniqueSort( matched );
- }
-
- // Reverse order for parents* and prev-derivatives
- if ( rparentsprev.test( name ) ) {
- matched.reverse();
- }
- }
-
- return this.pushStack( matched );
- };
-} );
-var rnotwhite = ( /\S+/g );
-
-
-
-// Convert String-formatted options into Object-formatted ones
-function createOptions( options ) {
- var object = {};
- jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
- object[ flag ] = true;
- } );
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- createOptions( options ) :
- jQuery.extend( {}, options );
-
- var // Flag to know if list is currently firing
- firing,
-
- // Last fire value for non-forgettable lists
- memory,
-
- // Flag to know if list was already fired
- fired,
-
- // Flag to prevent firing
- locked,
-
- // Actual callback list
- list = [],
-
- // Queue of execution data for repeatable lists
- queue = [],
-
- // Index of currently firing callback (modified by add/remove as needed)
- firingIndex = -1,
-
- // Fire callbacks
- fire = function() {
-
- // Enforce single-firing
- locked = options.once;
-
- // Execute callbacks for all pending executions,
- // respecting firingIndex overrides and runtime changes
- fired = firing = true;
- for ( ; queue.length; firingIndex = -1 ) {
- memory = queue.shift();
- while ( ++firingIndex < list.length ) {
-
- // Run callback and check for early termination
- if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
- options.stopOnFalse ) {
-
- // Jump to end and forget the data so .add doesn't re-fire
- firingIndex = list.length;
- memory = false;
- }
- }
- }
-
- // Forget the data if we're done with it
- if ( !options.memory ) {
- memory = false;
- }
-
- firing = false;
-
- // Clean up if we're done firing for good
- if ( locked ) {
-
- // Keep an empty list if we have data for future add calls
- if ( memory ) {
- list = [];
-
- // Otherwise, this object is spent
- } else {
- list = "";
- }
- }
- },
-
- // Actual Callbacks object
- self = {
-
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
-
- // If we have memory from a past run, we should fire after adding
- if ( memory && !firing ) {
- firingIndex = list.length - 1;
- queue.push( memory );
- }
-
- ( function add( args ) {
- jQuery.each( args, function( _, arg ) {
- if ( jQuery.isFunction( arg ) ) {
- if ( !options.unique || !self.has( arg ) ) {
- list.push( arg );
- }
- } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
-
- // Inspect recursively
- add( arg );
- }
- } );
- } )( arguments );
-
- if ( memory && !firing ) {
- fire();
- }
- }
- return this;
- },
-
- // Remove a callback from the list
- remove: function() {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
-
- // Handle firing indexes
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
- } );
- return this;
- },
-
- // Check if a given callback is in the list.
- // If no argument is given, return whether or not list has callbacks attached.
- has: function( fn ) {
- return fn ?
- jQuery.inArray( fn, list ) > -1 :
- list.length > 0;
- },
-
- // Remove all callbacks from the list
- empty: function() {
- if ( list ) {
- list = [];
- }
- return this;
- },
-
- // Disable .fire and .add
- // Abort any current/pending executions
- // Clear all callbacks and values
- disable: function() {
- locked = queue = [];
- list = memory = "";
- return this;
- },
- disabled: function() {
- return !list;
- },
-
- // Disable .fire
- // Also disable .add unless we have memory (since it would have no effect)
- // Abort any pending executions
- lock: function() {
- locked = queue = [];
- if ( !memory && !firing ) {
- list = memory = "";
- }
- return this;
- },
- locked: function() {
- return !!locked;
- },
-
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( !locked ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- queue.push( args );
- if ( !firing ) {
- fire();
- }
- }
- return this;
- },
-
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
-
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
-
- return self;
-};
-
-
-function Identity( v ) {
- return v;
-}
-function Thrower( ex ) {
- throw ex;
-}
-
-function adoptValue( value, resolve, reject ) {
- var method;
-
- try {
-
- // Check for promise aspect first to privilege synchronous behavior
- if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
- method.call( value ).done( resolve ).fail( reject );
-
- // Other thenables
- } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
- method.call( value, resolve, reject );
-
- // Other non-thenables
- } else {
-
- // Support: Android 4.0 only
- // Strict mode functions invoked without .call/.apply get global-object context
- resolve.call( undefined, value );
- }
-
- // For Promises/A+, convert exceptions into rejections
- // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
- // Deferred#then to conditionally suppress rejection.
- } catch ( /*jshint -W002 */ value ) {
-
- // Support: Android 4.0 only
- // Strict mode functions invoked without .call/.apply get global-object context
- reject.call( undefined, value );
- }
-}
-
-jQuery.extend( {
-
- Deferred: function( func ) {
- var tuples = [
-
- // action, add listener, callbacks,
- // ... .then handlers, argument index, [final state]
- [ "notify", "progress", jQuery.Callbacks( "memory" ),
- jQuery.Callbacks( "memory" ), 2 ],
- [ "resolve", "done", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 0, "resolved" ],
- [ "reject", "fail", jQuery.Callbacks( "once memory" ),
- jQuery.Callbacks( "once memory" ), 1, "rejected" ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- "catch": function( fn ) {
- return promise.then( null, fn );
- },
-
- // Keep pipe for back-compat
- pipe: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
-
- return jQuery.Deferred( function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
-
- // Map tuples (progress, done, fail) to arguments (done, fail, progress)
- var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
-
- // deferred.progress(function() { bind to newDefer or newDefer.notify })
- // deferred.done(function() { bind to newDefer or newDefer.resolve })
- // deferred.fail(function() { bind to newDefer or newDefer.reject })
- deferred[ tuple[ 1 ] ]( function() {
- var returned = fn && fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise()
- .progress( newDefer.notify )
- .done( newDefer.resolve )
- .fail( newDefer.reject );
- } else {
- newDefer[ tuple[ 0 ] + "With" ](
- this,
- fn ? [ returned ] : arguments
- );
- }
- } );
- } );
- fns = null;
- } ).promise();
- },
- then: function( onFulfilled, onRejected, onProgress ) {
- var maxDepth = 0;
- function resolve( depth, deferred, handler, special ) {
- return function() {
- var that = this,
- args = arguments,
- mightThrow = function() {
- var returned, then;
-
- // Support: Promises/A+ section 2.3.3.3.3
- // https://promisesaplus.com/#point-59
- // Ignore double-resolution attempts
- if ( depth < maxDepth ) {
- return;
- }
-
- returned = handler.apply( that, args );
-
- // Support: Promises/A+ section 2.3.1
- // https://promisesaplus.com/#point-48
- if ( returned === deferred.promise() ) {
- throw new TypeError( "Thenable self-resolution" );
- }
-
- // Support: Promises/A+ sections 2.3.3.1, 3.5
- // https://promisesaplus.com/#point-54
- // https://promisesaplus.com/#point-75
- // Retrieve `then` only once
- then = returned &&
-
- // Support: Promises/A+ section 2.3.4
- // https://promisesaplus.com/#point-64
- // Only check objects and functions for thenability
- ( typeof returned === "object" ||
- typeof returned === "function" ) &&
- returned.then;
-
- // Handle a returned thenable
- if ( jQuery.isFunction( then ) ) {
-
- // Special processors (notify) just wait for resolution
- if ( special ) {
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special )
- );
-
- // Normal processors (resolve) also hook into progress
- } else {
-
- // ...and disregard older resolution values
- maxDepth++;
-
- then.call(
- returned,
- resolve( maxDepth, deferred, Identity, special ),
- resolve( maxDepth, deferred, Thrower, special ),
- resolve( maxDepth, deferred, Identity,
- deferred.notifyWith )
- );
- }
-
- // Handle all other returned values
- } else {
-
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Identity ) {
- that = undefined;
- args = [ returned ];
- }
-
- // Process the value(s)
- // Default process is resolve
- ( special || deferred.resolveWith )( that, args );
- }
- },
-
- // Only normal processors (resolve) catch and reject exceptions
- process = special ?
- mightThrow :
- function() {
- try {
- mightThrow();
- } catch ( e ) {
-
- if ( jQuery.Deferred.exceptionHook ) {
- jQuery.Deferred.exceptionHook( e,
- process.stackTrace );
- }
-
- // Support: Promises/A+ section 2.3.3.3.4.1
- // https://promisesaplus.com/#point-61
- // Ignore post-resolution exceptions
- if ( depth + 1 >= maxDepth ) {
-
- // Only substitute handlers pass on context
- // and multiple values (non-spec behavior)
- if ( handler !== Thrower ) {
- that = undefined;
- args = [ e ];
- }
-
- deferred.rejectWith( that, args );
- }
- }
- };
-
- // Support: Promises/A+ section 2.3.3.3.1
- // https://promisesaplus.com/#point-57
- // Re-resolve promises immediately to dodge false rejection from
- // subsequent errors
- if ( depth ) {
- process();
- } else {
-
- // Call an optional hook to record the stack, in case of exception
- // since it's otherwise lost when execution goes async
- if ( jQuery.Deferred.getStackHook ) {
- process.stackTrace = jQuery.Deferred.getStackHook();
- }
- window.setTimeout( process );
- }
- };
- }
-
- return jQuery.Deferred( function( newDefer ) {
-
- // progress_handlers.add( ... )
- tuples[ 0 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onProgress ) ?
- onProgress :
- Identity,
- newDefer.notifyWith
- )
- );
-
- // fulfilled_handlers.add( ... )
- tuples[ 1 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onFulfilled ) ?
- onFulfilled :
- Identity
- )
- );
-
- // rejected_handlers.add( ... )
- tuples[ 2 ][ 3 ].add(
- resolve(
- 0,
- newDefer,
- jQuery.isFunction( onRejected ) ?
- onRejected :
- Thrower
- )
- );
- } ).promise();
- },
-
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return obj != null ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
-
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 5 ];
-
- // promise.progress = list.add
- // promise.done = list.add
- // promise.fail = list.add
- promise[ tuple[ 1 ] ] = list.add;
-
- // Handle state
- if ( stateString ) {
- list.add(
- function() {
-
- // state = "resolved" (i.e., fulfilled)
- // state = "rejected"
- state = stateString;
- },
-
- // rejected_callbacks.disable
- // fulfilled_callbacks.disable
- tuples[ 3 - i ][ 2 ].disable,
-
- // progress_callbacks.lock
- tuples[ 0 ][ 2 ].lock
- );
- }
-
- // progress_handlers.fire
- // fulfilled_handlers.fire
- // rejected_handlers.fire
- list.add( tuple[ 3 ].fire );
-
- // deferred.notify = function() { deferred.notifyWith(...) }
- // deferred.resolve = function() { deferred.resolveWith(...) }
- // deferred.reject = function() { deferred.rejectWith(...) }
- deferred[ tuple[ 0 ] ] = function() {
- deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
- return this;
- };
-
- // deferred.notifyWith = list.fireWith
- // deferred.resolveWith = list.fireWith
- // deferred.rejectWith = list.fireWith
- deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
- } );
-
- // Make the deferred a promise
- promise.promise( deferred );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( singleValue ) {
- var
-
- // count of uncompleted subordinates
- remaining = arguments.length,
-
- // count of unprocessed arguments
- i = remaining,
-
- // subordinate fulfillment data
- resolveContexts = Array( i ),
- resolveValues = slice.call( arguments ),
-
- // the master Deferred
- master = jQuery.Deferred(),
-
- // subordinate callback factory
- updateFunc = function( i ) {
- return function( value ) {
- resolveContexts[ i ] = this;
- resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( !( --remaining ) ) {
- master.resolveWith( resolveContexts, resolveValues );
- }
- };
- };
-
- // Single- and empty arguments are adopted like Promise.resolve
- if ( remaining <= 1 ) {
- adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject );
-
- // Use .then() to unwrap secondary thenables (cf. gh-3000)
- if ( master.state() === "pending" ||
- jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
-
- return master.then();
- }
- }
-
- // Multiple arguments are aggregated like Promise.all array elements
- while ( i-- ) {
- adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
- }
-
- return master.promise();
- }
-} );
-
-
-// These usually indicate a programmer mistake during development,
-// warn about them ASAP rather than swallowing them by default.
-var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
-
-jQuery.Deferred.exceptionHook = function( error, stack ) {
-
- // Support: IE 8 - 9 only
- // Console exists when dev tools are open, which can happen at any time
- if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
- window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
- }
-};
-
-
-
-
-// The deferred used on DOM ready
-var readyList = jQuery.Deferred();
-
-jQuery.fn.ready = function( fn ) {
-
- readyList.then( fn );
-
- return this;
-};
-
-jQuery.extend( {
-
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
-
- // Handle when the DOM is ready
- ready: function( wait ) {
-
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
- }
-} );
-
-jQuery.ready.then = readyList.then;
-
-// The ready event handler and self cleanup method
-function completed() {
- document.removeEventListener( "DOMContentLoaded", completed );
- window.removeEventListener( "load", completed );
- jQuery.ready();
-}
-
-// Catch cases where $(document).ready() is called
-// after the browser event has already occurred.
-// Support: IE <=9 - 10 only
-// Older IE sometimes signals "interactive" too soon
-if ( document.readyState === "complete" ||
- ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
-
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- window.setTimeout( jQuery.ready );
-
-} else {
-
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed );
-}
-
-
-
-
-// Multifunctional method to get and set values of a collection
-// The value/s can optionally be executed if it's a function
-var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- len = elems.length,
- bulk = key == null;
-
- // Sets many values
- if ( jQuery.type( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- access( elems, fn, i, key[ i ], true, emptyGet, raw );
- }
-
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
-
- if ( !jQuery.isFunction( value ) ) {
- raw = true;
- }
-
- if ( bulk ) {
-
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
-
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
- }
- }
-
- if ( fn ) {
- for ( ; i < len; i++ ) {
- fn(
- elems[ i ], key, raw ?
- value :
- value.call( elems[ i ], i, fn( elems[ i ], key ) )
- );
- }
- }
- }
-
- return chainable ?
- elems :
-
- // Gets
- bulk ?
- fn.call( elems ) :
- len ? fn( elems[ 0 ], key ) : emptyGet;
-};
-var acceptData = function( owner ) {
-
- // Accepts only:
- // - Node
- // - Node.ELEMENT_NODE
- // - Node.DOCUMENT_NODE
- // - Object
- // - Any
- /* jshint -W018 */
- return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
-};
-
-
-
-
-function Data() {
- this.expando = jQuery.expando + Data.uid++;
-}
-
-Data.uid = 1;
-
-Data.prototype = {
-
- cache: function( owner ) {
-
- // Check if the owner object already has a cache
- var value = owner[ this.expando ];
-
- // If not, create one
- if ( !value ) {
- value = {};
-
- // We can accept data for non-element nodes in modern browsers,
- // but we should not, see #8335.
- // Always return an empty object.
- if ( acceptData( owner ) ) {
-
- // If it is a node unlikely to be stringify-ed or looped over
- // use plain assignment
- if ( owner.nodeType ) {
- owner[ this.expando ] = value;
-
- // Otherwise secure it in a non-enumerable property
- // configurable must be true to allow the property to be
- // deleted when data is removed
- } else {
- Object.defineProperty( owner, this.expando, {
- value: value,
- configurable: true
- } );
- }
- }
- }
-
- return value;
- },
- set: function( owner, data, value ) {
- var prop,
- cache = this.cache( owner );
-
- // Handle: [ owner, key, value ] args
- // Always use camelCase key (gh-2257)
- if ( typeof data === "string" ) {
- cache[ jQuery.camelCase( data ) ] = value;
-
- // Handle: [ owner, { properties } ] args
- } else {
-
- // Copy the properties one-by-one to the cache object
- for ( prop in data ) {
- cache[ jQuery.camelCase( prop ) ] = data[ prop ];
- }
- }
- return cache;
- },
- get: function( owner, key ) {
- return key === undefined ?
- this.cache( owner ) :
-
- // Always use camelCase key (gh-2257)
- owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
- },
- access: function( owner, key, value ) {
-
- // In cases where either:
- //
- // 1. No key was specified
- // 2. A string key was specified, but no value provided
- //
- // Take the "read" path and allow the get method to determine
- // which value to return, respectively either:
- //
- // 1. The entire cache object
- // 2. The data stored at the key
- //
- if ( key === undefined ||
- ( ( key && typeof key === "string" ) && value === undefined ) ) {
-
- return this.get( owner, key );
- }
-
- // When the key is not a string, or both a key and value
- // are specified, set or extend (existing objects) with either:
- //
- // 1. An object of properties
- // 2. A key and value
- //
- this.set( owner, key, value );
-
- // Since the "set" path can have two possible entry points
- // return the expected data based on which path was taken[*]
- return value !== undefined ? value : key;
- },
- remove: function( owner, key ) {
- var i,
- cache = owner[ this.expando ];
-
- if ( cache === undefined ) {
- return;
- }
-
- if ( key !== undefined ) {
-
- // Support array or space separated string of keys
- if ( jQuery.isArray( key ) ) {
-
- // If key is an array of keys...
- // We always set camelCase keys, so remove that.
- key = key.map( jQuery.camelCase );
- } else {
- key = jQuery.camelCase( key );
-
- // If a key with the spaces exists, use it.
- // Otherwise, create an array by matching non-whitespace
- key = key in cache ?
- [ key ] :
- ( key.match( rnotwhite ) || [] );
- }
-
- i = key.length;
-
- while ( i-- ) {
- delete cache[ key[ i ] ];
- }
- }
-
- // Remove the expando if there's no more data
- if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
-
- // Support: Chrome <=35 - 45
- // Webkit & Blink performance suffers when deleting properties
- // from DOM nodes, so set to undefined instead
- // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
- if ( owner.nodeType ) {
- owner[ this.expando ] = undefined;
- } else {
- delete owner[ this.expando ];
- }
- }
- },
- hasData: function( owner ) {
- var cache = owner[ this.expando ];
- return cache !== undefined && !jQuery.isEmptyObject( cache );
- }
-};
-var dataPriv = new Data();
-
-var dataUser = new Data();
-
-
-
-// Implementation Summary
-//
-// 1. Enforce API surface and semantic compatibility with 1.9.x branch
-// 2. Improve the module's maintainability by reducing the storage
-// paths to a single mechanism.
-// 3. Use the same single mechanism to support "private" and "user" data.
-// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
-// 5. Avoid exposing implementation details on user objects (eg. expando properties)
-// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
-
-var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /[A-Z]/g;
-
-function dataAttr( elem, key, data ) {
- var name;
-
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
- name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
-
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? JSON.parse( data ) :
- data;
- } catch ( e ) {}
-
- // Make sure we set the data so it isn't changed later
- dataUser.set( elem, key, data );
- } else {
- data = undefined;
- }
- }
- return data;
-}
-
-jQuery.extend( {
- hasData: function( elem ) {
- return dataUser.hasData( elem ) || dataPriv.hasData( elem );
- },
-
- data: function( elem, name, data ) {
- return dataUser.access( elem, name, data );
- },
-
- removeData: function( elem, name ) {
- dataUser.remove( elem, name );
- },
-
- // TODO: Now that all calls to _data and _removeData have been replaced
- // with direct calls to dataPriv methods, these can be deprecated.
- _data: function( elem, name, data ) {
- return dataPriv.access( elem, name, data );
- },
-
- _removeData: function( elem, name ) {
- dataPriv.remove( elem, name );
- }
-} );
-
-jQuery.fn.extend( {
- data: function( key, value ) {
- var i, name, data,
- elem = this[ 0 ],
- attrs = elem && elem.attributes;
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = dataUser.get( elem );
-
- if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
- i = attrs.length;
- while ( i-- ) {
-
- // Support: IE 11 only
- // The attrs elements can be null (#14894)
- if ( attrs[ i ] ) {
- name = attrs[ i ].name;
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice( 5 ) );
- dataAttr( elem, name, data[ name ] );
- }
- }
- }
- dataPriv.set( elem, "hasDataAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each( function() {
- dataUser.set( this, key );
- } );
- }
-
- return access( this, function( value ) {
- var data;
-
- // The calling jQuery object (element matches) is not empty
- // (and therefore has an element appears at this[ 0 ]) and the
- // `value` parameter was not undefined. An empty jQuery object
- // will result in `undefined` for elem = this[ 0 ] which will
- // throw an exception if an attempt to read a data cache is made.
- if ( elem && value === undefined ) {
-
- // Attempt to get data from the cache
- // The key will always be camelCased in Data
- data = dataUser.get( elem, key );
- if ( data !== undefined ) {
- return data;
- }
-
- // Attempt to "discover" the data in
- // HTML5 custom data-* attrs
- data = dataAttr( elem, key );
- if ( data !== undefined ) {
- return data;
- }
-
- // We tried really hard, but the data doesn't exist.
- return;
- }
-
- // Set the data...
- this.each( function() {
-
- // We always store the camelCased key
- dataUser.set( this, key, value );
- } );
- }, null, value, arguments.length > 1, null, true );
- },
-
- removeData: function( key ) {
- return this.each( function() {
- dataUser.remove( this, key );
- } );
- }
-} );
-
-
-jQuery.extend( {
- queue: function( elem, type, data ) {
- var queue;
-
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = dataPriv.get( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || jQuery.isArray( data ) ) {
- queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
-
- if ( fn ) {
-
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- // Clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
-
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // Not public - generate a queueHooks object, or return the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
- empty: jQuery.Callbacks( "once memory" ).add( function() {
- dataPriv.remove( elem, [ type + "queue", key ] );
- } )
- } );
- }
-} );
-
-jQuery.fn.extend( {
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[ 0 ], type );
- }
-
- return data === undefined ?
- this :
- this.each( function() {
- var queue = jQuery.queue( this, type, data );
-
- // Ensure a hooks for this queue
- jQuery._queueHooks( this, type );
-
- if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- } );
- },
- dequeue: function( type ) {
- return this.each( function() {
- jQuery.dequeue( this, type );
- } );
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
-
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
-
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
-
- while ( i-- ) {
- tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
-} );
-var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
-
-var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
-
-
-var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
-
-var isHiddenWithinTree = function( elem, el ) {
-
- // isHiddenWithinTree might be called from jQuery#filter function;
- // in that case, element will be second argument
- elem = el || elem;
-
- // Inline style trumps all
- return elem.style.display === "none" ||
- elem.style.display === "" &&
-
- // Otherwise, check computed style
- // Support: Firefox <=43 - 45
- // Disconnected elements can have computed display: none, so first confirm that elem is
- // in the document.
- jQuery.contains( elem.ownerDocument, elem ) &&
-
- jQuery.css( elem, "display" ) === "none";
- };
-
-var swap = function( elem, options, callback, args ) {
- var ret, name,
- old = {};
-
- // Remember the old values, and insert the new ones
- for ( name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
- }
-
- ret = callback.apply( elem, args || [] );
-
- // Revert the old values
- for ( name in options ) {
- elem.style[ name ] = old[ name ];
- }
-
- return ret;
-};
-
-
-
-
-function adjustCSS( elem, prop, valueParts, tween ) {
- var adjusted,
- scale = 1,
- maxIterations = 20,
- currentValue = tween ?
- function() { return tween.cur(); } :
- function() { return jQuery.css( elem, prop, "" ); },
- initial = currentValue(),
- unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
-
- // Starting value computation is required for potential unit mismatches
- initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
- rcssNum.exec( jQuery.css( elem, prop ) );
-
- if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
-
- // Trust units reported by jQuery.css
- unit = unit || initialInUnit[ 3 ];
-
- // Make sure we update the tween properties later on
- valueParts = valueParts || [];
-
- // Iteratively approximate from a nonzero starting point
- initialInUnit = +initial || 1;
-
- do {
-
- // If previous iteration zeroed out, double until we get *something*.
- // Use string for doubling so we don't accidentally see scale as unchanged below
- scale = scale || ".5";
-
- // Adjust and apply
- initialInUnit = initialInUnit / scale;
- jQuery.style( elem, prop, initialInUnit + unit );
-
- // Update scale, tolerating zero or NaN from tween.cur()
- // Break the loop if scale is unchanged or perfect, or if we've just had enough.
- } while (
- scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
- );
- }
-
- if ( valueParts ) {
- initialInUnit = +initialInUnit || +initial || 0;
-
- // Apply relative offset (+=/-=) if specified
- adjusted = valueParts[ 1 ] ?
- initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
- +valueParts[ 2 ];
- if ( tween ) {
- tween.unit = unit;
- tween.start = initialInUnit;
- tween.end = adjusted;
- }
- }
- return adjusted;
-}
-
-
-var defaultDisplayMap = {};
-
-function getDefaultDisplay( elem ) {
- var temp,
- doc = elem.ownerDocument,
- nodeName = elem.nodeName,
- display = defaultDisplayMap[ nodeName ];
-
- if ( display ) {
- return display;
- }
-
- temp = doc.body.appendChild( doc.createElement( nodeName ) ),
- display = jQuery.css( temp, "display" );
-
- temp.parentNode.removeChild( temp );
-
- if ( display === "none" ) {
- display = "block";
- }
- defaultDisplayMap[ nodeName ] = display;
-
- return display;
-}
-
-function showHide( elements, show ) {
- var display, elem,
- values = [],
- index = 0,
- length = elements.length;
-
- // Determine new display value for elements that need to change
- for ( ; index < length; index++ ) {
- elem = elements[ index ];
- if ( !elem.style ) {
- continue;
- }
-
- display = elem.style.display;
- if ( show ) {
-
- // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
- // check is required in this first loop unless we have a nonempty display value (either
- // inline or about-to-be-restored)
- if ( display === "none" ) {
- values[ index ] = dataPriv.get( elem, "display" ) || null;
- if ( !values[ index ] ) {
- elem.style.display = "";
- }
- }
- if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
- values[ index ] = getDefaultDisplay( elem );
- }
- } else {
- if ( display !== "none" ) {
- values[ index ] = "none";
-
- // Remember what we're overwriting
- dataPriv.set( elem, "display", display );
- }
- }
- }
-
- // Set the display of the elements in a second loop to avoid constant reflow
- for ( index = 0; index < length; index++ ) {
- if ( values[ index ] != null ) {
- elements[ index ].style.display = values[ index ];
- }
- }
-
- return elements;
-}
-
-jQuery.fn.extend( {
- show: function() {
- return showHide( this, true );
- },
- hide: function() {
- return showHide( this );
- },
- toggle: function( state ) {
- if ( typeof state === "boolean" ) {
- return state ? this.show() : this.hide();
- }
-
- return this.each( function() {
- if ( isHiddenWithinTree( this ) ) {
- jQuery( this ).show();
- } else {
- jQuery( this ).hide();
- }
- } );
- }
-} );
-var rcheckableType = ( /^(?:checkbox|radio)$/i );
-
-var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
-
-var rscriptType = ( /^$|\/(?:java|ecma)script/i );
-
-
-
-// We have to close these tags to support XHTML (#13200)
-var wrapMap = {
-
- // Support: IE <=9 only
- option: [ 1, "<select multiple='multiple'>", "</select>" ],
-
- // XHTML parsers do not magically insert elements in the
- // same way that tag soup parsers do. So we cannot shorten
- // this by omitting <tbody> or other required elements.
- thead: [ 1, "<table>", "</table>" ],
- col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
- tr: [ 2, "<table><tbody>", "</tbody></table>" ],
- td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
-
- _default: [ 0, "", "" ]
-};
-
-// Support: IE <=9 only
-wrapMap.optgroup = wrapMap.option;
-
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-
-function getAll( context, tag ) {
-
- // Support: IE <=9 - 11 only
- // Use typeof to avoid zero-argument method invocation on host objects (#15151)
- var ret = typeof context.getElementsByTagName !== "undefined" ?
- context.getElementsByTagName( tag || "*" ) :
- typeof context.querySelectorAll !== "undefined" ?
- context.querySelectorAll( tag || "*" ) :
- [];
-
- return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
- jQuery.merge( [ context ], ret ) :
- ret;
-}
-
-
-// Mark scripts as having already been evaluated
-function setGlobalEval( elems, refElements ) {
- var i = 0,
- l = elems.length;
-
- for ( ; i < l; i++ ) {
- dataPriv.set(
- elems[ i ],
- "globalEval",
- !refElements || dataPriv.get( refElements[ i ], "globalEval" )
- );
- }
-}
-
-
-var rhtml = /<|&#?\w+;/;
-
-function buildFragment( elems, context, scripts, selection, ignored ) {
- var elem, tmp, tag, wrap, contains, j,
- fragment = context.createDocumentFragment(),
- nodes = [],
- i = 0,
- l = elems.length;
-
- for ( ; i < l; i++ ) {
- elem = elems[ i ];
-
- if ( elem || elem === 0 ) {
-
- // Add nodes directly
- if ( jQuery.type( elem ) === "object" ) {
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
-
- // Convert non-html into a text node
- } else if ( !rhtml.test( elem ) ) {
- nodes.push( context.createTextNode( elem ) );
-
- // Convert html into DOM nodes
- } else {
- tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
-
- // Deserialize a standard representation
- tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
- wrap = wrapMap[ tag ] || wrapMap._default;
- tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
-
- // Descend through wrappers to the right content
- j = wrap[ 0 ];
- while ( j-- ) {
- tmp = tmp.lastChild;
- }
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( nodes, tmp.childNodes );
-
- // Remember the top-level container
- tmp = fragment.firstChild;
-
- // Ensure the created nodes are orphaned (#12392)
- tmp.textContent = "";
- }
- }
- }
-
- // Remove wrapper from fragment
- fragment.textContent = "";
-
- i = 0;
- while ( ( elem = nodes[ i++ ] ) ) {
-
- // Skip elements already in the context collection (trac-4087)
- if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
- if ( ignored ) {
- ignored.push( elem );
- }
- continue;
- }
-
- contains = jQuery.contains( elem.ownerDocument, elem );
-
- // Append to fragment
- tmp = getAll( fragment.appendChild( elem ), "script" );
-
- // Preserve script evaluation history
- if ( contains ) {
- setGlobalEval( tmp );
- }
-
- // Capture executables
- if ( scripts ) {
- j = 0;
- while ( ( elem = tmp[ j++ ] ) ) {
- if ( rscriptType.test( elem.type || "" ) ) {
- scripts.push( elem );
- }
- }
- }
- }
-
- return fragment;
-}
-
-
-( function() {
- var fragment = document.createDocumentFragment(),
- div = fragment.appendChild( document.createElement( "div" ) ),
- input = document.createElement( "input" );
-
- // Support: Android 4.0 - 4.3 only
- // Check state lost if the name is set (#11217)
- // Support: Windows Web Apps (WWA)
- // `name` and `type` must use .setAttribute for WWA (#14901)
- input.setAttribute( "type", "radio" );
- input.setAttribute( "checked", "checked" );
- input.setAttribute( "name", "t" );
-
- div.appendChild( input );
-
- // Support: Android <=4.1 only
- // Older WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Support: IE <=11 only
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- div.innerHTML = "<textarea>x</textarea>";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
-} )();
-var documentElement = document.documentElement;
-
-
-
-var
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
-
-function returnTrue() {
- return true;
-}
-
-function returnFalse() {
- return false;
-}
-
-// Support: IE <=9 only
-// See #13393 for more info
-function safeActiveElement() {
- try {
- return document.activeElement;
- } catch ( err ) { }
-}
-
-function on( elem, types, selector, data, fn, one ) {
- var origFn, type;
-
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
-
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
-
- // ( types-Object, data )
- data = data || selector;
- selector = undefined;
- }
- for ( type in types ) {
- on( elem, type, selector, data, types[ type ], one );
- }
- return elem;
- }
-
- if ( data == null && fn == null ) {
-
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
-
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
-
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return elem;
- }
-
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
-
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
-
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return elem.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- } );
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- global: {},
-
- add: function( elem, types, handler, data, selector ) {
-
- var handleObjIn, eventHandle, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.get( elem );
-
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Ensure that invalid selectors throw exceptions at attach time
- // Evaluate against documentElement in case elem is a non-element node (e.g., document)
- if ( selector ) {
- jQuery.find.matchesSelector( documentElement, selector );
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- if ( !( events = elemData.events ) ) {
- events = elemData.events = {};
- }
- if ( !( eventHandle = elemData.handle ) ) {
- eventHandle = elemData.handle = function( e ) {
-
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
- jQuery.event.dispatch.apply( elem, arguments ) : undefined;
- };
- }
-
- // Handle multiple events separated by a space
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
-
- // There *must* be a type, no attaching namespace-only handlers
- if ( !type ) {
- continue;
- }
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend( {
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join( "." )
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- if ( !( handlers = events[ type ] ) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener if the special events handler returns false
- if ( !special.setup ||
- special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
-
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- },
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
-
- var j, origCount, tmp,
- events, t, handleObj,
- special, handlers, type, namespaces, origType,
- elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
-
- if ( !elemData || !( events = elemData.events ) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[ t ] ) || [];
- type = origType = tmp[ 1 ];
- namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[ 2 ] &&
- new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
-
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector ||
- selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
-
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown ||
- special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
-
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove data and the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- dataPriv.remove( elem, "handle events" );
- }
- },
-
- dispatch: function( nativeEvent ) {
-
- // Make a writable jQuery.Event from the native event object
- var event = jQuery.event.fix( nativeEvent );
-
- var i, j, ret, matched, handleObj, handlerQueue,
- args = new Array( arguments.length ),
- handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[ 0 ] = event;
-
- for ( i = 1; i < arguments.length; i++ ) {
- args[ i ] = arguments[ i ];
- }
-
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
-
- j = 0;
- while ( ( handleObj = matched.handlers[ j++ ] ) &&
- !event.isImmediatePropagationStopped() ) {
-
- // Triggered event must either 1) have no namespace, or 2) have namespace(s)
- // a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
-
- event.handleObj = handleObj;
- event.data = handleObj.data;
-
- ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
- handleObj.handler ).apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- if ( ( event.result = ret ) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- handlers: function( event, handlers ) {
- var i, matches, sel, handleObj,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
-
- // Support: IE <=9
- // Find delegate handlers
- // Black-hole SVG <use> instance trees (#13180)
- //
- // Support: Firefox <=42
- // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
- if ( delegateCount && cur.nodeType &&
- ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
-
- for ( ; cur !== this; cur = cur.parentNode || this ) {
-
- // Don't check non-elements (#13208)
- // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
- if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
- matches = [];
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
-
- // Don't conflict with Object.prototype properties (#13203)
- sel = handleObj.selector + " ";
-
- if ( matches[ sel ] === undefined ) {
- matches[ sel ] = handleObj.needsContext ?
- jQuery( sel, this ).index( cur ) > -1 :
- jQuery.find( sel, this, null, [ cur ] ).length;
- }
- if ( matches[ sel ] ) {
- matches.push( handleObj );
- }
- }
- if ( matches.length ) {
- handlerQueue.push( { elem: cur, handlers: matches } );
- }
- }
- }
- }
-
- // Add the remaining (directly-bound) handlers
- if ( delegateCount < handlers.length ) {
- handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
- }
-
- return handlerQueue;
- },
-
- addProp: function( name, hook ) {
- Object.defineProperty( jQuery.Event.prototype, name, {
- enumerable: true,
- configurable: true,
-
- get: jQuery.isFunction( hook ) ?
- function() {
- if ( this.originalEvent ) {
- return hook( this.originalEvent );
- }
- } :
- function() {
- if ( this.originalEvent ) {
- return this.originalEvent[ name ];
- }
- },
-
- set: function( value ) {
- Object.defineProperty( this, name, {
- enumerable: true,
- configurable: true,
- writable: true,
- value: value
- } );
- }
- } );
- },
-
- fix: function( originalEvent ) {
- return originalEvent[ jQuery.expando ] ?
- originalEvent :
- new jQuery.Event( originalEvent );
- },
-
- special: {
- load: {
-
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
- },
- focus: {
-
- // Fire native event if possible so blur/focus sequence is correct
- trigger: function() {
- if ( this !== safeActiveElement() && this.focus ) {
- this.focus();
- return false;
- }
- },
- delegateType: "focusin"
- },
- blur: {
- trigger: function() {
- if ( this === safeActiveElement() && this.blur ) {
- this.blur();
- return false;
- }
- },
- delegateType: "focusout"
- },
- click: {
-
- // For checkbox, fire native event so checked state will be right
- trigger: function() {
- if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
- this.click();
- return false;
- }
- },
-
- // For cross-browser consistency, don't fire native .click() on links
- _default: function( event ) {
- return jQuery.nodeName( event.target, "a" );
- }
- },
-
- beforeunload: {
- postDispatch: function( event ) {
-
- // Support: Firefox 20+
- // Firefox doesn't alert if the returnValue field is not set.
- if ( event.result !== undefined && event.originalEvent ) {
- event.originalEvent.returnValue = event.result;
- }
- }
- }
- }
-};
-
-jQuery.removeEvent = function( elem, type, handle ) {
-
- // This "if" is needed for plain objects
- if ( elem.removeEventListener ) {
- elem.removeEventListener( type, handle );
- }
-};
-
-jQuery.Event = function( src, props ) {
-
- // Allow instantiation without the 'new' keyword
- if ( !( this instanceof jQuery.Event ) ) {
- return new jQuery.Event( src, props );
- }
-
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
-
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = src.defaultPrevented ||
- src.defaultPrevented === undefined &&
-
- // Support: Android <=2.3 only
- src.returnValue === false ?
- returnTrue :
- returnFalse;
-
- // Create target properties
- // Support: Safari <=6 - 7 only
- // Target should not be a text node (#504, #13143)
- this.target = ( src.target && src.target.nodeType === 3 ) ?
- src.target.parentNode :
- src.target;
-
- this.currentTarget = src.currentTarget;
- this.relatedTarget = src.relatedTarget;
-
- // Event type
- } else {
- this.type = src;
- }
-
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
-
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
-
- // Mark it as fixed
- this[ jQuery.expando ] = true;
-};
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- constructor: jQuery.Event,
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse,
- isSimulated: false,
-
- preventDefault: function() {
- var e = this.originalEvent;
-
- this.isDefaultPrevented = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.preventDefault();
- }
- },
- stopPropagation: function() {
- var e = this.originalEvent;
-
- this.isPropagationStopped = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.stopPropagation();
- }
- },
- stopImmediatePropagation: function() {
- var e = this.originalEvent;
-
- this.isImmediatePropagationStopped = returnTrue;
-
- if ( e && !this.isSimulated ) {
- e.stopImmediatePropagation();
- }
-
- this.stopPropagation();
- }
-};
-
-// Includes all common event props including KeyEvent and MouseEvent specific props
-jQuery.each( {
- altKey: true,
- bubbles: true,
- cancelable: true,
- changedTouches: true,
- ctrlKey: true,
- detail: true,
- eventPhase: true,
- metaKey: true,
- pageX: true,
- pageY: true,
- shiftKey: true,
- view: true,
- "char": true,
- charCode: true,
- key: true,
- keyCode: true,
- button: true,
- buttons: true,
- clientX: true,
- clientY: true,
- offsetX: true,
- offsetY: true,
- pointerId: true,
- pointerType: true,
- screenX: true,
- screenY: true,
- targetTouches: true,
- toElement: true,
- touches: true,
-
- which: function( event ) {
- var button = event.button;
-
- // Add which for key events
- if ( event.which == null && rkeyEvent.test( event.type ) ) {
- return event.charCode != null ? event.charCode : event.keyCode;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
- return ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
- }
-
- return event.which;
- }
-}, jQuery.event.addProp );
-
-// Create mouseenter/leave events using mouseover/out and event-time checks
-// so that event delegation works in jQuery.
-// Do the same for pointerenter/pointerleave and pointerover/pointerout
-//
-// Support: Safari 7 only
-// Safari sends mouseenter too often; see:
-// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
-// for the description of the bug (it existed in older Chrome versions as well).
-jQuery.each( {
- mouseenter: "mouseover",
- mouseleave: "mouseout",
- pointerenter: "pointerover",
- pointerleave: "pointerout"
-}, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
-
- handle: function( event ) {
- var ret,
- target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj;
-
- // For mouseenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
-} );
-
-jQuery.fn.extend( {
-
- on: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn );
- },
- one: function( types, selector, data, fn ) {
- return on( this, types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- var handleObj, type;
- if ( types && types.preventDefault && types.handleObj ) {
-
- // ( event ) dispatched jQuery.Event
- handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace ?
- handleObj.origType + "." + handleObj.namespace :
- handleObj.origType,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
-
- // ( types-object [, selector] )
- for ( type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
-
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each( function() {
- jQuery.event.remove( this, types, fn, selector );
- } );
- }
-} );
-
-
-var
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
-
- // Support: IE <=10 - 11, Edge 12 - 13
- // In IE/Edge using regex groups here causes severe slowdowns.
- // See https://connect.microsoft.com/IE/feedback/details/1736512/
- rnoInnerhtml = /<script|<style|<link/i,
-
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptTypeMasked = /^true\/(.*)/,
- rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
-
-function manipulationTarget( elem, content ) {
- if ( jQuery.nodeName( elem, "table" ) &&
- jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
-
- return elem.getElementsByTagName( "tbody" )[ 0 ] || elem;
- }
-
- return elem;
-}
-
-// Replace/restore the type attribute of script elements for safe DOM manipulation
-function disableScript( elem ) {
- elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
- return elem;
-}
-function restoreScript( elem ) {
- var match = rscriptTypeMasked.exec( elem.type );
-
- if ( match ) {
- elem.type = match[ 1 ];
- } else {
- elem.removeAttribute( "type" );
- }
-
- return elem;
-}
-
-function cloneCopyEvent( src, dest ) {
- var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
-
- if ( dest.nodeType !== 1 ) {
- return;
- }
-
- // 1. Copy private data: events, handlers, etc.
- if ( dataPriv.hasData( src ) ) {
- pdataOld = dataPriv.access( src );
- pdataCur = dataPriv.set( dest, pdataOld );
- events = pdataOld.events;
-
- if ( events ) {
- delete pdataCur.handle;
- pdataCur.events = {};
-
- for ( type in events ) {
- for ( i = 0, l = events[ type ].length; i < l; i++ ) {
- jQuery.event.add( dest, type, events[ type ][ i ] );
- }
- }
- }
- }
-
- // 2. Copy user data
- if ( dataUser.hasData( src ) ) {
- udataOld = dataUser.access( src );
- udataCur = jQuery.extend( {}, udataOld );
-
- dataUser.set( dest, udataCur );
- }
-}
-
-// Fix IE bugs, see support tests
-function fixInput( src, dest ) {
- var nodeName = dest.nodeName.toLowerCase();
-
- // Fails to persist the checked state of a cloned checkbox or radio button.
- if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
- dest.checked = src.checked;
-
- // Fails to return the selected option to the default selected state when cloning options
- } else if ( nodeName === "input" || nodeName === "textarea" ) {
- dest.defaultValue = src.defaultValue;
- }
-}
-
-function domManip( collection, args, callback, ignored ) {
-
- // Flatten any nested arrays
- args = concat.apply( [], args );
-
- var fragment, first, scripts, hasScripts, node, doc,
- i = 0,
- l = collection.length,
- iNoClone = l - 1,
- value = args[ 0 ],
- isFunction = jQuery.isFunction( value );
-
- // We can't cloneNode fragments that contain checked, in WebKit
- if ( isFunction ||
- ( l > 1 && typeof value === "string" &&
- !support.checkClone && rchecked.test( value ) ) ) {
- return collection.each( function( index ) {
- var self = collection.eq( index );
- if ( isFunction ) {
- args[ 0 ] = value.call( this, index, self.html() );
- }
- domManip( self, args, callback, ignored );
- } );
- }
-
- if ( l ) {
- fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
- first = fragment.firstChild;
-
- if ( fragment.childNodes.length === 1 ) {
- fragment = first;
- }
-
- // Require either new content or an interest in ignored elements to invoke the callback
- if ( first || ignored ) {
- scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
- hasScripts = scripts.length;
-
- // Use the original fragment for the last item
- // instead of the first because it can end up
- // being emptied incorrectly in certain situations (#8070).
- for ( ; i < l; i++ ) {
- node = fragment;
-
- if ( i !== iNoClone ) {
- node = jQuery.clone( node, true, true );
-
- // Keep references to cloned scripts for later restoration
- if ( hasScripts ) {
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // push.apply(_, arraylike) throws on ancient WebKit
- jQuery.merge( scripts, getAll( node, "script" ) );
- }
- }
-
- callback.call( collection[ i ], node, i );
- }
-
- if ( hasScripts ) {
- doc = scripts[ scripts.length - 1 ].ownerDocument;
-
- // Reenable scripts
- jQuery.map( scripts, restoreScript );
-
- // Evaluate executable scripts on first document insertion
- for ( i = 0; i < hasScripts; i++ ) {
- node = scripts[ i ];
- if ( rscriptType.test( node.type || "" ) &&
- !dataPriv.access( node, "globalEval" ) &&
- jQuery.contains( doc, node ) ) {
-
- if ( node.src ) {
-
- // Optional AJAX dependency, but won't run scripts if not present
- if ( jQuery._evalUrl ) {
- jQuery._evalUrl( node.src );
- }
- } else {
- DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
- }
- }
- }
- }
- }
- }
-
- return collection;
-}
-
-function remove( elem, selector, keepData ) {
- var node,
- nodes = selector ? jQuery.filter( selector, elem ) : elem,
- i = 0;
-
- for ( ; ( node = nodes[ i ] ) != null; i++ ) {
- if ( !keepData && node.nodeType === 1 ) {
- jQuery.cleanData( getAll( node ) );
- }
-
- if ( node.parentNode ) {
- if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
- setGlobalEval( getAll( node, "script" ) );
- }
- node.parentNode.removeChild( node );
- }
- }
-
- return elem;
-}
-
-jQuery.extend( {
- htmlPrefilter: function( html ) {
- return html.replace( rxhtmlTag, "<$1></$2>" );
- },
-
- clone: function( elem, dataAndEvents, deepDataAndEvents ) {
- var i, l, srcElements, destElements,
- clone = elem.cloneNode( true ),
- inPage = jQuery.contains( elem.ownerDocument, elem );
-
- // Fix IE cloning issues
- if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
- !jQuery.isXMLDoc( elem ) ) {
-
- // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
- destElements = getAll( clone );
- srcElements = getAll( elem );
-
- for ( i = 0, l = srcElements.length; i < l; i++ ) {
- fixInput( srcElements[ i ], destElements[ i ] );
- }
- }
-
- // Copy the events from the original to the clone
- if ( dataAndEvents ) {
- if ( deepDataAndEvents ) {
- srcElements = srcElements || getAll( elem );
- destElements = destElements || getAll( clone );
-
- for ( i = 0, l = srcElements.length; i < l; i++ ) {
- cloneCopyEvent( srcElements[ i ], destElements[ i ] );
- }
- } else {
- cloneCopyEvent( elem, clone );
- }
- }
-
- // Preserve script evaluation history
- destElements = getAll( clone, "script" );
- if ( destElements.length > 0 ) {
- setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
- }
-
- // Return the cloned set
- return clone;
- },
-
- cleanData: function( elems ) {
- var data, elem, type,
- special = jQuery.event.special,
- i = 0;
-
- for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
- if ( acceptData( elem ) ) {
- if ( ( data = elem[ dataPriv.expando ] ) ) {
- if ( data.events ) {
- for ( type in data.events ) {
- if ( special[ type ] ) {
- jQuery.event.remove( elem, type );
-
- // This is a shortcut to avoid jQuery.event.remove's overhead
- } else {
- jQuery.removeEvent( elem, type, data.handle );
- }
- }
- }
-
- // Support: Chrome <=35 - 45+
- // Assign undefined instead of using delete, see Data#remove
- elem[ dataPriv.expando ] = undefined;
- }
- if ( elem[ dataUser.expando ] ) {
-
- // Support: Chrome <=35 - 45+
- // Assign undefined instead of using delete, see Data#remove
- elem[ dataUser.expando ] = undefined;
- }
- }
- }
- }
-} );
-
-jQuery.fn.extend( {
- detach: function( selector ) {
- return remove( this, selector, true );
- },
-
- remove: function( selector ) {
- return remove( this, selector );
- },
-
- text: function( value ) {
- return access( this, function( value ) {
- return value === undefined ?
- jQuery.text( this ) :
- this.empty().each( function() {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- this.textContent = value;
- }
- } );
- }, null, value, arguments.length );
- },
-
- append: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- var target = manipulationTarget( this, elem );
- target.appendChild( elem );
- }
- } );
- },
-
- prepend: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
- var target = manipulationTarget( this, elem );
- target.insertBefore( elem, target.firstChild );
- }
- } );
- },
-
- before: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.parentNode ) {
- this.parentNode.insertBefore( elem, this );
- }
- } );
- },
-
- after: function() {
- return domManip( this, arguments, function( elem ) {
- if ( this.parentNode ) {
- this.parentNode.insertBefore( elem, this.nextSibling );
- }
- } );
- },
-
- empty: function() {
- var elem,
- i = 0;
-
- for ( ; ( elem = this[ i ] ) != null; i++ ) {
- if ( elem.nodeType === 1 ) {
-
- // Prevent memory leaks
- jQuery.cleanData( getAll( elem, false ) );
-
- // Remove any remaining nodes
- elem.textContent = "";
- }
- }
-
- return this;
- },
-
- clone: function( dataAndEvents, deepDataAndEvents ) {
- dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
- deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
-
- return this.map( function() {
- return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
- } );
- },
-
- html: function( value ) {
- return access( this, function( value ) {
- var elem = this[ 0 ] || {},
- i = 0,
- l = this.length;
-
- if ( value === undefined && elem.nodeType === 1 ) {
- return elem.innerHTML;
- }
-
- // See if we can take a shortcut and just use innerHTML
- if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
- !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
-
- value = jQuery.htmlPrefilter( value );
-
- try {
- for ( ; i < l; i++ ) {
- elem = this[ i ] || {};
-
- // Remove element nodes and prevent memory leaks
- if ( elem.nodeType === 1 ) {
- jQuery.cleanData( getAll( elem, false ) );
- elem.innerHTML = value;
- }
- }
-
- elem = 0;
-
- // If using innerHTML throws an exception, use the fallback method
- } catch ( e ) {}
- }
-
- if ( elem ) {
- this.empty().append( value );
- }
- }, null, value, arguments.length );
- },
-
- replaceWith: function() {
- var ignored = [];
-
- // Make the changes, replacing each non-ignored context element with the new content
- return domManip( this, arguments, function( elem ) {
- var parent = this.parentNode;
-
- if ( jQuery.inArray( this, ignored ) < 0 ) {
- jQuery.cleanData( getAll( this ) );
- if ( parent ) {
- parent.replaceChild( elem, this );
- }
- }
-
- // Force callback invocation
- }, ignored );
- }
-} );
-
-jQuery.each( {
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
-}, function( name, original ) {
- jQuery.fn[ name ] = function( selector ) {
- var elems,
- ret = [],
- insert = jQuery( selector ),
- last = insert.length - 1,
- i = 0;
-
- for ( ; i <= last; i++ ) {
- elems = i === last ? this : this.clone( true );
- jQuery( insert[ i ] )[ original ]( elems );
-
- // Support: Android <=4.0 only, PhantomJS 1 only
- // .get() because push.apply(_, arraylike) throws on ancient WebKit
- push.apply( ret, elems.get() );
- }
-
- return this.pushStack( ret );
- };
-} );
-var rmargin = ( /^margin/ );
-
-var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
-
-var getStyles = function( elem ) {
-
- // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
- // IE throws on elements created in popups
- // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
- var view = elem.ownerDocument.defaultView;
-
- if ( !view || !view.opener ) {
- view = window;
- }
-
- return view.getComputedStyle( elem );
- };
-
-
-
-( function() {
-
- // Executing both pixelPosition & boxSizingReliable tests require only one layout
- // so they're executed at the same time to save the second computation.
- function computeStyleTests() {
-
- // This is a singleton, we need to execute it only once
- if ( !div ) {
- return;
- }
-
- div.style.cssText =
- "box-sizing:border-box;" +
- "position:relative;display:block;" +
- "margin:auto;border:1px;padding:1px;" +
- "top:1%;width:50%";
- div.innerHTML = "";
- documentElement.appendChild( container );
-
- var divStyle = window.getComputedStyle( div );
- pixelPositionVal = divStyle.top !== "1%";
-
- // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
- reliableMarginLeftVal = divStyle.marginLeft === "2px";
- boxSizingReliableVal = divStyle.width === "4px";
-
- // Support: Android 4.0 - 4.3 only
- // Some styles come back with percentage values, even though they shouldn't
- div.style.marginRight = "50%";
- pixelMarginRightVal = divStyle.marginRight === "4px";
-
- documentElement.removeChild( container );
-
- // Nullify the div so it wouldn't be stored in the memory and
- // it will also be a sign that checks already performed
- div = null;
- }
-
- var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
- container = document.createElement( "div" ),
- div = document.createElement( "div" );
-
- // Finish early in limited (non-browser) environments
- if ( !div.style ) {
- return;
- }
-
- // Support: IE <=9 - 11 only
- // Style of cloned element affects source element cloned (#8908)
- div.style.backgroundClip = "content-box";
- div.cloneNode( true ).style.backgroundClip = "";
- support.clearCloneStyle = div.style.backgroundClip === "content-box";
-
- container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
- "padding:0;margin-top:1px;position:absolute";
- container.appendChild( div );
-
- jQuery.extend( support, {
- pixelPosition: function() {
- computeStyleTests();
- return pixelPositionVal;
- },
- boxSizingReliable: function() {
- computeStyleTests();
- return boxSizingReliableVal;
- },
- pixelMarginRight: function() {
- computeStyleTests();
- return pixelMarginRightVal;
- },
- reliableMarginLeft: function() {
- computeStyleTests();
- return reliableMarginLeftVal;
- }
- } );
-} )();
-
-
-function curCSS( elem, name, computed ) {
- var width, minWidth, maxWidth, ret,
- style = elem.style;
-
- computed = computed || getStyles( elem );
-
- // Support: IE <=9 only
- // getPropertyValue is only needed for .css('filter') (#12537)
- if ( computed ) {
- ret = computed.getPropertyValue( name ) || computed[ name ];
-
- if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
- ret = jQuery.style( elem, name );
- }
-
- // A tribute to the "awesome hack by Dean Edwards"
- // Android Browser returns percentage for some values,
- // but width seems to be reliably pixels.
- // This is against the CSSOM draft spec:
- // https://drafts.csswg.org/cssom/#resolved-values
- if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
-
- // Remember the original values
- width = style.width;
- minWidth = style.minWidth;
- maxWidth = style.maxWidth;
-
- // Put in the new values to get a computed value out
- style.minWidth = style.maxWidth = style.width = ret;
- ret = computed.width;
-
- // Revert the changed values
- style.width = width;
- style.minWidth = minWidth;
- style.maxWidth = maxWidth;
- }
- }
-
- return ret !== undefined ?
-
- // Support: IE <=9 - 11 only
- // IE returns zIndex value as an integer.
- ret + "" :
- ret;
-}
-
-
-function addGetHookIf( conditionFn, hookFn ) {
-
- // Define the hook, we'll check on the first run if it's really needed.
- return {
- get: function() {
- if ( conditionFn() ) {
-
- // Hook not needed (or it's not possible to use it due
- // to missing dependency), remove it.
- delete this.get;
- return;
- }
-
- // Hook needed; redefine it so that the support test is not executed again.
- return ( this.get = hookFn ).apply( this, arguments );
- }
- };
-}
-
-
-var
-
- // Swappable if display is none or starts with table
- // except "table", "table-cell", or "table-caption"
- // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
- rdisplayswap = /^(none|table(?!-c[ea]).+)/,
- cssShow = { position: "absolute", visibility: "hidden", display: "block" },
- cssNormalTransform = {
- letterSpacing: "0",
- fontWeight: "400"
- },
-
- cssPrefixes = [ "Webkit", "Moz", "ms" ],
- emptyStyle = document.createElement( "div" ).style;
-
-// Return a css property mapped to a potentially vendor prefixed property
-function vendorPropName( name ) {
-
- // Shortcut for names that are not vendor prefixed
- if ( name in emptyStyle ) {
- return name;
- }
-
- // Check for vendor prefixed names
- var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
- i = cssPrefixes.length;
-
- while ( i-- ) {
- name = cssPrefixes[ i ] + capName;
- if ( name in emptyStyle ) {
- return name;
- }
- }
-}
-
-function setPositiveNumber( elem, value, subtract ) {
-
- // Any relative (+/-) values have already been
- // normalized at this point
- var matches = rcssNum.exec( value );
- return matches ?
-
- // Guard against undefined "subtract", e.g., when used as in cssHooks
- Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
- value;
-}
-
-function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
- var i = extra === ( isBorderBox ? "border" : "content" ) ?
-
- // If we already have the right measurement, avoid augmentation
- 4 :
-
- // Otherwise initialize for horizontal or vertical properties
- name === "width" ? 1 : 0,
-
- val = 0;
-
- for ( ; i < 4; i += 2 ) {
-
- // Both box models exclude margin, so add it if we want it
- if ( extra === "margin" ) {
- val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
- }
-
- if ( isBorderBox ) {
-
- // border-box includes padding, so remove it if we want content
- if ( extra === "content" ) {
- val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
- }
-
- // At this point, extra isn't border nor margin, so remove border
- if ( extra !== "margin" ) {
- val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
- }
- } else {
-
- // At this point, extra isn't content, so add padding
- val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
-
- // At this point, extra isn't content nor padding, so add border
- if ( extra !== "padding" ) {
- val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
- }
- }
- }
-
- return val;
-}
-
-function getWidthOrHeight( elem, name, extra ) {
-
- // Start with offset property, which is equivalent to the border-box value
- var val,
- valueIsBorderBox = true,
- styles = getStyles( elem ),
- isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
-
- // Support: IE <=11 only
- // Running getBoundingClientRect on a disconnected node
- // in IE throws an error.
- if ( elem.getClientRects().length ) {
- val = elem.getBoundingClientRect()[ name ];
- }
-
- // Some non-html elements return undefined for offsetWidth, so check for null/undefined
- // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
- // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
- if ( val <= 0 || val == null ) {
-
- // Fall back to computed then uncomputed css if necessary
- val = curCSS( elem, name, styles );
- if ( val < 0 || val == null ) {
- val = elem.style[ name ];
- }
-
- // Computed unit is not pixels. Stop here and return.
- if ( rnumnonpx.test( val ) ) {
- return val;
- }
-
- // Check for style in case a browser which returns unreliable values
- // for getComputedStyle silently falls back to the reliable elem.style
- valueIsBorderBox = isBorderBox &&
- ( support.boxSizingReliable() || val === elem.style[ name ] );
-
- // Normalize "", auto, and prepare for extra
- val = parseFloat( val ) || 0;
- }
-
- // Use the active box-sizing model to add/subtract irrelevant styles
- return ( val +
- augmentWidthOrHeight(
- elem,
- name,
- extra || ( isBorderBox ? "border" : "content" ),
- valueIsBorderBox,
- styles
- )
- ) + "px";
-}
-
-jQuery.extend( {
-
- // Add in style property hooks for overriding the default
- // behavior of getting and setting a style property
- cssHooks: {
- opacity: {
- get: function( elem, computed ) {
- if ( computed ) {
-
- // We should always get a number back from opacity
- var ret = curCSS( elem, "opacity" );
- return ret === "" ? "1" : ret;
- }
- }
- }
- },
-
- // Don't automatically add "px" to these possibly-unitless properties
- cssNumber: {
- "animationIterationCount": true,
- "columnCount": true,
- "fillOpacity": true,
- "flexGrow": true,
- "flexShrink": true,
- "fontWeight": true,
- "lineHeight": true,
- "opacity": true,
- "order": true,
- "orphans": true,
- "widows": true,
- "zIndex": true,
- "zoom": true
- },
-
- // Add in properties whose names you wish to fix before
- // setting or getting the value
- cssProps: {
- "float": "cssFloat"
- },
-
- // Get and set the style property on a DOM Node
- style: function( elem, name, value, extra ) {
-
- // Don't set styles on text and comment nodes
- if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
- return;
- }
-
- // Make sure that we're working with the right name
- var ret, type, hooks,
- origName = jQuery.camelCase( name ),
- style = elem.style;
-
- name = jQuery.cssProps[ origName ] ||
- ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
-
- // Gets hook for the prefixed version, then unprefixed version
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
- // Check if we're setting a value
- if ( value !== undefined ) {
- type = typeof value;
-
- // Convert "+=" or "-=" to relative numbers (#7345)
- if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
- value = adjustCSS( elem, name, ret );
-
- // Fixes bug #9237
- type = "number";
- }
-
- // Make sure that null and NaN values aren't set (#7116)
- if ( value == null || value !== value ) {
- return;
- }
-
- // If a number was passed in, add the unit (except for certain CSS properties)
- if ( type === "number" ) {
- value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
- }
-
- // background-* props affect original clone's values
- if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
- style[ name ] = "inherit";
- }
-
- // If a hook was provided, use that value, otherwise just set the specified value
- if ( !hooks || !( "set" in hooks ) ||
- ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
-
- style[ name ] = value;
- }
-
- } else {
-
- // If a hook was provided get the non-computed value from there
- if ( hooks && "get" in hooks &&
- ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
-
- return ret;
- }
-
- // Otherwise just get the value from the style object
- return style[ name ];
- }
- },
-
- css: function( elem, name, extra, styles ) {
- var val, num, hooks,
- origName = jQuery.camelCase( name );
-
- // Make sure that we're working with the right name
- name = jQuery.cssProps[ origName ] ||
- ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
-
- // Try prefixed name followed by the unprefixed name
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
- // If a hook was provided get the computed value from there
- if ( hooks && "get" in hooks ) {
- val = hooks.get( elem, true, extra );
- }
-
- // Otherwise, if a way to get the computed value exists, use that
- if ( val === undefined ) {
- val = curCSS( elem, name, styles );
- }
-
- // Convert "normal" to computed value
- if ( val === "normal" && name in cssNormalTransform ) {
- val = cssNormalTransform[ name ];
- }
-
- // Make numeric if forced or a qualifier was provided and val looks numeric
- if ( extra === "" || extra ) {
- num = parseFloat( val );
- return extra === true || isFinite( num ) ? num || 0 : val;
- }
- return val;
- }
-} );
-
-jQuery.each( [ "height", "width" ], function( i, name ) {
- jQuery.cssHooks[ name ] = {
- get: function( elem, computed, extra ) {
- if ( computed ) {
-
- // Certain elements can have dimension info if we invisibly show them
- // but it must have a current display style that would benefit
- return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
-
- // Support: Safari 8+
- // Table columns in Safari have non-zero offsetWidth & zero
- // getBoundingClientRect().width unless display is changed.
- // Support: IE <=11 only
- // Running getBoundingClientRect on a disconnected node
- // in IE throws an error.
- ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
- swap( elem, cssShow, function() {
- return getWidthOrHeight( elem, name, extra );
- } ) :
- getWidthOrHeight( elem, name, extra );
- }
- },
-
- set: function( elem, value, extra ) {
- var matches,
- styles = extra && getStyles( elem ),
- subtract = extra && augmentWidthOrHeight(
- elem,
- name,
- extra,
- jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
- styles
- );
-
- // Convert to pixels if value adjustment is needed
- if ( subtract && ( matches = rcssNum.exec( value ) ) &&
- ( matches[ 3 ] || "px" ) !== "px" ) {
-
- elem.style[ name ] = value;
- value = jQuery.css( elem, name );
- }
-
- return setPositiveNumber( elem, value, subtract );
- }
- };
-} );
-
-jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
- function( elem, computed ) {
- if ( computed ) {
- return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
- elem.getBoundingClientRect().left -
- swap( elem, { marginLeft: 0 }, function() {
- return elem.getBoundingClientRect().left;
- } )
- ) + "px";
- }
- }
-);
-
-// These hooks are used by animate to expand properties
-jQuery.each( {
- margin: "",
- padding: "",
- border: "Width"
-}, function( prefix, suffix ) {
- jQuery.cssHooks[ prefix + suffix ] = {
- expand: function( value ) {
- var i = 0,
- expanded = {},
-
- // Assumes a single number if not a string
- parts = typeof value === "string" ? value.split( " " ) : [ value ];
-
- for ( ; i < 4; i++ ) {
- expanded[ prefix + cssExpand[ i ] + suffix ] =
- parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
- }
-
- return expanded;
- }
- };
-
- if ( !rmargin.test( prefix ) ) {
- jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
- }
-} );
-
-jQuery.fn.extend( {
- css: function( name, value ) {
- return access( this, function( elem, name, value ) {
- var styles, len,
- map = {},
- i = 0;
-
- if ( jQuery.isArray( name ) ) {
- styles = getStyles( elem );
- len = name.length;
-
- for ( ; i < len; i++ ) {
- map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
- }
-
- return map;
- }
-
- return value !== undefined ?
- jQuery.style( elem, name, value ) :
- jQuery.css( elem, name );
- }, name, value, arguments.length > 1 );
- }
-} );
-
-
-function Tween( elem, options, prop, end, easing ) {
- return new Tween.prototype.init( elem, options, prop, end, easing );
-}
-jQuery.Tween = Tween;
-
-Tween.prototype = {
- constructor: Tween,
- init: function( elem, options, prop, end, easing, unit ) {
- this.elem = elem;
- this.prop = prop;
- this.easing = easing || jQuery.easing._default;
- this.options = options;
- this.start = this.now = this.cur();
- this.end = end;
- this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
- },
- cur: function() {
- var hooks = Tween.propHooks[ this.prop ];
-
- return hooks && hooks.get ?
- hooks.get( this ) :
- Tween.propHooks._default.get( this );
- },
- run: function( percent ) {
- var eased,
- hooks = Tween.propHooks[ this.prop ];
-
- if ( this.options.duration ) {
- this.pos = eased = jQuery.easing[ this.easing ](
- percent, this.options.duration * percent, 0, 1, this.options.duration
- );
- } else {
- this.pos = eased = percent;
- }
- this.now = ( this.end - this.start ) * eased + this.start;
-
- if ( this.options.step ) {
- this.options.step.call( this.elem, this.now, this );
- }
-
- if ( hooks && hooks.set ) {
- hooks.set( this );
- } else {
- Tween.propHooks._default.set( this );
- }
- return this;
- }
-};
-
-Tween.prototype.init.prototype = Tween.prototype;
-
-Tween.propHooks = {
- _default: {
- get: function( tween ) {
- var result;
-
- // Use a property on the element directly when it is not a DOM element,
- // or when there is no matching style property that exists.
- if ( tween.elem.nodeType !== 1 ||
- tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
- return tween.elem[ tween.prop ];
- }
-
- // Passing an empty string as a 3rd parameter to .css will automatically
- // attempt a parseFloat and fallback to a string if the parse fails.
- // Simple values such as "10px" are parsed to Float;
- // complex values such as "rotate(1rad)" are returned as-is.
- result = jQuery.css( tween.elem, tween.prop, "" );
-
- // Empty strings, null, undefined and "auto" are converted to 0.
- return !result || result === "auto" ? 0 : result;
- },
- set: function( tween ) {
-
- // Use step hook for back compat.
- // Use cssHook if its there.
- // Use .style if available and use plain properties where available.
- if ( jQuery.fx.step[ tween.prop ] ) {
- jQuery.fx.step[ tween.prop ]( tween );
- } else if ( tween.elem.nodeType === 1 &&
- ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
- jQuery.cssHooks[ tween.prop ] ) ) {
- jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
- } else {
- tween.elem[ tween.prop ] = tween.now;
- }
- }
- }
-};
-
-// Support: IE <=9 only
-// Panic based approach to setting things on disconnected nodes
-Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
- set: function( tween ) {
- if ( tween.elem.nodeType && tween.elem.parentNode ) {
- tween.elem[ tween.prop ] = tween.now;
- }
- }
-};
-
-jQuery.easing = {
- linear: function( p ) {
- return p;
- },
- swing: function( p ) {
- return 0.5 - Math.cos( p * Math.PI ) / 2;
- },
- _default: "swing"
-};
-
-jQuery.fx = Tween.prototype.init;
-
-// Back compat <1.8 extension point
-jQuery.fx.step = {};
-
-
-
-
-var
- fxNow, timerId,
- rfxtypes = /^(?:toggle|show|hide)$/,
- rrun = /queueHooks$/;
-
-function raf() {
- if ( timerId ) {
- window.requestAnimationFrame( raf );
- jQuery.fx.tick();
- }
-}
-
-// Animations created synchronously will run synchronously
-function createFxNow() {
- window.setTimeout( function() {
- fxNow = undefined;
- } );
- return ( fxNow = jQuery.now() );
-}
-
-// Generate parameters to create a standard animation
-function genFx( type, includeWidth ) {
- var which,
- i = 0,
- attrs = { height: type };
-
- // If we include width, step value is 1 to do all cssExpand values,
- // otherwise step value is 2 to skip over Left and Right
- includeWidth = includeWidth ? 1 : 0;
- for ( ; i < 4 ; i += 2 - includeWidth ) {
- which = cssExpand[ i ];
- attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
- }
-
- if ( includeWidth ) {
- attrs.opacity = attrs.width = type;
- }
-
- return attrs;
-}
-
-function createTween( value, prop, animation ) {
- var tween,
- collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
- index = 0,
- length = collection.length;
- for ( ; index < length; index++ ) {
- if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
-
- // We're done with this property
- return tween;
- }
- }
-}
-
-function defaultPrefilter( elem, props, opts ) {
- /* jshint validthis: true */
- var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
- isBox = "width" in props || "height" in props,
- anim = this,
- orig = {},
- style = elem.style,
- hidden = elem.nodeType && isHiddenWithinTree( elem ),
- dataShow = dataPriv.get( elem, "fxshow" );
-
- // Queue-skipping animations hijack the fx hooks
- if ( !opts.queue ) {
- hooks = jQuery._queueHooks( elem, "fx" );
- if ( hooks.unqueued == null ) {
- hooks.unqueued = 0;
- oldfire = hooks.empty.fire;
- hooks.empty.fire = function() {
- if ( !hooks.unqueued ) {
- oldfire();
- }
- };
- }
- hooks.unqueued++;
-
- anim.always( function() {
-
- // Ensure the complete handler is called before this completes
- anim.always( function() {
- hooks.unqueued--;
- if ( !jQuery.queue( elem, "fx" ).length ) {
- hooks.empty.fire();
- }
- } );
- } );
- }
-
- // Detect show/hide animations
- for ( prop in props ) {
- value = props[ prop ];
- if ( rfxtypes.test( value ) ) {
- delete props[ prop ];
- toggle = toggle || value === "toggle";
- if ( value === ( hidden ? "hide" : "show" ) ) {
-
- // Pretend to be hidden if this is a "show" and
- // there is still data from a stopped show/hide
- if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
- hidden = true;
-
- // Ignore all other no-op show/hide data
- } else {
- continue;
- }
- }
- orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
- }
- }
-
- // Bail out if this is a no-op like .hide().hide()
- propTween = !jQuery.isEmptyObject( props );
- if ( !propTween && jQuery.isEmptyObject( orig ) ) {
- return;
- }
-
- // Restrict "overflow" and "display" styles during box animations
- if ( isBox && elem.nodeType === 1 ) {
-
- // Support: IE <=9 - 11, Edge 12 - 13
- // Record all 3 overflow attributes because IE does not infer the shorthand
- // from identically-valued overflowX and overflowY
- opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
-
- // Identify a display type, preferring old show/hide data over the CSS cascade
- restoreDisplay = dataShow && dataShow.display;
- if ( restoreDisplay == null ) {
- restoreDisplay = dataPriv.get( elem, "display" );
- }
- display = jQuery.css( elem, "display" );
- if ( display === "none" ) {
- if ( restoreDisplay ) {
- display = restoreDisplay;
- } else {
-
- // Get nonempty value(s) by temporarily forcing visibility
- showHide( [ elem ], true );
- restoreDisplay = elem.style.display || restoreDisplay;
- display = jQuery.css( elem, "display" );
- showHide( [ elem ] );
- }
- }
-
- // Animate inline elements as inline-block
- if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
- if ( jQuery.css( elem, "float" ) === "none" ) {
-
- // Restore the original display value at the end of pure show/hide animations
- if ( !propTween ) {
- anim.done( function() {
- style.display = restoreDisplay;
- } );
- if ( restoreDisplay == null ) {
- display = style.display;
- restoreDisplay = display === "none" ? "" : display;
- }
- }
- style.display = "inline-block";
- }
- }
- }
-
- if ( opts.overflow ) {
- style.overflow = "hidden";
- anim.always( function() {
- style.overflow = opts.overflow[ 0 ];
- style.overflowX = opts.overflow[ 1 ];
- style.overflowY = opts.overflow[ 2 ];
- } );
- }
-
- // Implement show/hide animations
- propTween = false;
- for ( prop in orig ) {
-
- // General show/hide setup for this element animation
- if ( !propTween ) {
- if ( dataShow ) {
- if ( "hidden" in dataShow ) {
- hidden = dataShow.hidden;
- }
- } else {
- dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
- }
-
- // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
- if ( toggle ) {
- dataShow.hidden = !hidden;
- }
-
- // Show elements before animating them
- if ( hidden ) {
- showHide( [ elem ], true );
- }
-
- /* jshint -W083 */
- anim.done( function() {
-
- // The final step of a "hide" animation is actually hiding the element
- if ( !hidden ) {
- showHide( [ elem ] );
- }
- dataPriv.remove( elem, "fxshow" );
- for ( prop in orig ) {
- jQuery.style( elem, prop, orig[ prop ] );
- }
- } );
- }
-
- // Per-property setup
- propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
- if ( !( prop in dataShow ) ) {
- dataShow[ prop ] = propTween.start;
- if ( hidden ) {
- propTween.end = propTween.start;
- propTween.start = 0;
- }
- }
- }
-}
-
-function propFilter( props, specialEasing ) {
- var index, name, easing, value, hooks;
-
- // camelCase, specialEasing and expand cssHook pass
- for ( index in props ) {
- name = jQuery.camelCase( index );
- easing = specialEasing[ name ];
- value = props[ index ];
- if ( jQuery.isArray( value ) ) {
- easing = value[ 1 ];
- value = props[ index ] = value[ 0 ];
- }
-
- if ( index !== name ) {
- props[ name ] = value;
- delete props[ index ];
- }
-
- hooks = jQuery.cssHooks[ name ];
- if ( hooks && "expand" in hooks ) {
- value = hooks.expand( value );
- delete props[ name ];
-
- // Not quite $.extend, this won't overwrite existing keys.
- // Reusing 'index' because we have the correct "name"
- for ( index in value ) {
- if ( !( index in props ) ) {
- props[ index ] = value[ index ];
- specialEasing[ index ] = easing;
- }
- }
- } else {
- specialEasing[ name ] = easing;
- }
- }
-}
-
-function Animation( elem, properties, options ) {
- var result,
- stopped,
- index = 0,
- length = Animation.prefilters.length,
- deferred = jQuery.Deferred().always( function() {
-
- // Don't match elem in the :animated selector
- delete tick.elem;
- } ),
- tick = function() {
- if ( stopped ) {
- return false;
- }
- var currentTime = fxNow || createFxNow(),
- remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
-
- // Support: Android 2.3 only
- // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
- temp = remaining / animation.duration || 0,
- percent = 1 - temp,
- index = 0,
- length = animation.tweens.length;
-
- for ( ; index < length ; index++ ) {
- animation.tweens[ index ].run( percent );
- }
-
- deferred.notifyWith( elem, [ animation, percent, remaining ] );
-
- if ( percent < 1 && length ) {
- return remaining;
- } else {
- deferred.resolveWith( elem, [ animation ] );
- return false;
- }
- },
- animation = deferred.promise( {
- elem: elem,
- props: jQuery.extend( {}, properties ),
- opts: jQuery.extend( true, {
- specialEasing: {},
- easing: jQuery.easing._default
- }, options ),
- originalProperties: properties,
- originalOptions: options,
- startTime: fxNow || createFxNow(),
- duration: options.duration,
- tweens: [],
- createTween: function( prop, end ) {
- var tween = jQuery.Tween( elem, animation.opts, prop, end,
- animation.opts.specialEasing[ prop ] || animation.opts.easing );
- animation.tweens.push( tween );
- return tween;
- },
- stop: function( gotoEnd ) {
- var index = 0,
-
- // If we are going to the end, we want to run all the tweens
- // otherwise we skip this part
- length = gotoEnd ? animation.tweens.length : 0;
- if ( stopped ) {
- return this;
- }
- stopped = true;
- for ( ; index < length ; index++ ) {
- animation.tweens[ index ].run( 1 );
- }
-
- // Resolve when we played the last frame; otherwise, reject
- if ( gotoEnd ) {
- deferred.notifyWith( elem, [ animation, 1, 0 ] );
- deferred.resolveWith( elem, [ animation, gotoEnd ] );
- } else {
- deferred.rejectWith( elem, [ animation, gotoEnd ] );
- }
- return this;
- }
- } ),
- props = animation.props;
-
- propFilter( props, animation.opts.specialEasing );
-
- for ( ; index < length ; index++ ) {
- result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
- if ( result ) {
- if ( jQuery.isFunction( result.stop ) ) {
- jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
- jQuery.proxy( result.stop, result );
- }
- return result;
- }
- }
-
- jQuery.map( props, createTween, animation );
-
- if ( jQuery.isFunction( animation.opts.start ) ) {
- animation.opts.start.call( elem, animation );
- }
-
- jQuery.fx.timer(
- jQuery.extend( tick, {
- elem: elem,
- anim: animation,
- queue: animation.opts.queue
- } )
- );
-
- // attach callbacks from options
- return animation.progress( animation.opts.progress )
- .done( animation.opts.done, animation.opts.complete )
- .fail( animation.opts.fail )
- .always( animation.opts.always );
-}
-
-jQuery.Animation = jQuery.extend( Animation, {
-
- tweeners: {
- "*": [ function( prop, value ) {
- var tween = this.createTween( prop, value );
- adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
- return tween;
- } ]
- },
-
- tweener: function( props, callback ) {
- if ( jQuery.isFunction( props ) ) {
- callback = props;
- props = [ "*" ];
- } else {
- props = props.match( rnotwhite );
- }
-
- var prop,
- index = 0,
- length = props.length;
-
- for ( ; index < length ; index++ ) {
- prop = props[ index ];
- Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
- Animation.tweeners[ prop ].unshift( callback );
- }
- },
-
- prefilters: [ defaultPrefilter ],
-
- prefilter: function( callback, prepend ) {
- if ( prepend ) {
- Animation.prefilters.unshift( callback );
- } else {
- Animation.prefilters.push( callback );
- }
- }
-} );
-
-jQuery.speed = function( speed, easing, fn ) {
- var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
- complete: fn || !fn && easing ||
- jQuery.isFunction( speed ) && speed,
- duration: speed,
- easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
- };
-
- // Go to the end state if fx are off or if document is hidden
- if ( jQuery.fx.off || document.hidden ) {
- opt.duration = 0;
-
- } else {
- opt.duration = typeof opt.duration === "number" ?
- opt.duration : opt.duration in jQuery.fx.speeds ?
- jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
- }
-
- // Normalize opt.queue - true/undefined/null -> "fx"
- if ( opt.queue == null || opt.queue === true ) {
- opt.queue = "fx";
- }
-
- // Queueing
- opt.old = opt.complete;
-
- opt.complete = function() {
- if ( jQuery.isFunction( opt.old ) ) {
- opt.old.call( this );
- }
-
- if ( opt.queue ) {
- jQuery.dequeue( this, opt.queue );
- }
- };
-
- return opt;
-};
-
-jQuery.fn.extend( {
- fadeTo: function( speed, to, easing, callback ) {
-
- // Show any hidden elements after setting opacity to 0
- return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
-
- // Animate to the value specified
- .end().animate( { opacity: to }, speed, easing, callback );
- },
- animate: function( prop, speed, easing, callback ) {
- var empty = jQuery.isEmptyObject( prop ),
- optall = jQuery.speed( speed, easing, callback ),
- doAnimation = function() {
-
- // Operate on a copy of prop so per-property easing won't be lost
- var anim = Animation( this, jQuery.extend( {}, prop ), optall );
-
- // Empty animations, or finishing resolves immediately
- if ( empty || dataPriv.get( this, "finish" ) ) {
- anim.stop( true );
- }
- };
- doAnimation.finish = doAnimation;
-
- return empty || optall.queue === false ?
- this.each( doAnimation ) :
- this.queue( optall.queue, doAnimation );
- },
- stop: function( type, clearQueue, gotoEnd ) {
- var stopQueue = function( hooks ) {
- var stop = hooks.stop;
- delete hooks.stop;
- stop( gotoEnd );
- };
-
- if ( typeof type !== "string" ) {
- gotoEnd = clearQueue;
- clearQueue = type;
- type = undefined;
- }
- if ( clearQueue && type !== false ) {
- this.queue( type || "fx", [] );
- }
-
- return this.each( function() {
- var dequeue = true,
- index = type != null && type + "queueHooks",
- timers = jQuery.timers,
- data = dataPriv.get( this );
-
- if ( index ) {
- if ( data[ index ] && data[ index ].stop ) {
- stopQueue( data[ index ] );
- }
- } else {
- for ( index in data ) {
- if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
- stopQueue( data[ index ] );
- }
- }
- }
-
- for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this &&
- ( type == null || timers[ index ].queue === type ) ) {
-
- timers[ index ].anim.stop( gotoEnd );
- dequeue = false;
- timers.splice( index, 1 );
- }
- }
-
- // Start the next in the queue if the last step wasn't forced.
- // Timers currently will call their complete callbacks, which
- // will dequeue but only if they were gotoEnd.
- if ( dequeue || !gotoEnd ) {
- jQuery.dequeue( this, type );
- }
- } );
- },
- finish: function( type ) {
- if ( type !== false ) {
- type = type || "fx";
- }
- return this.each( function() {
- var index,
- data = dataPriv.get( this ),
- queue = data[ type + "queue" ],
- hooks = data[ type + "queueHooks" ],
- timers = jQuery.timers,
- length = queue ? queue.length : 0;
-
- // Enable finishing flag on private data
- data.finish = true;
-
- // Empty the queue first
- jQuery.queue( this, type, [] );
-
- if ( hooks && hooks.stop ) {
- hooks.stop.call( this, true );
- }
-
- // Look for any active animations, and finish them
- for ( index = timers.length; index--; ) {
- if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
- timers[ index ].anim.stop( true );
- timers.splice( index, 1 );
- }
- }
-
- // Look for any animations in the old queue and finish them
- for ( index = 0; index < length; index++ ) {
- if ( queue[ index ] && queue[ index ].finish ) {
- queue[ index ].finish.call( this );
- }
- }
-
- // Turn off finishing flag
- delete data.finish;
- } );
- }
-} );
-
-jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
- var cssFn = jQuery.fn[ name ];
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return speed == null || typeof speed === "boolean" ?
- cssFn.apply( this, arguments ) :
- this.animate( genFx( name, true ), speed, easing, callback );
- };
-} );
-
-// Generate shortcuts for custom animations
-jQuery.each( {
- slideDown: genFx( "show" ),
- slideUp: genFx( "hide" ),
- slideToggle: genFx( "toggle" ),
- fadeIn: { opacity: "show" },
- fadeOut: { opacity: "hide" },
- fadeToggle: { opacity: "toggle" }
-}, function( name, props ) {
- jQuery.fn[ name ] = function( speed, easing, callback ) {
- return this.animate( props, speed, easing, callback );
- };
-} );
-
-jQuery.timers = [];
-jQuery.fx.tick = function() {
- var timer,
- i = 0,
- timers = jQuery.timers;
-
- fxNow = jQuery.now();
-
- for ( ; i < timers.length; i++ ) {
- timer = timers[ i ];
-
- // Checks the timer has not already been removed
- if ( !timer() && timers[ i ] === timer ) {
- timers.splice( i--, 1 );
- }
- }
-
- if ( !timers.length ) {
- jQuery.fx.stop();
- }
- fxNow = undefined;
-};
-
-jQuery.fx.timer = function( timer ) {
- jQuery.timers.push( timer );
- if ( timer() ) {
- jQuery.fx.start();
- } else {
- jQuery.timers.pop();
- }
-};
-
-jQuery.fx.interval = 13;
-jQuery.fx.start = function() {
- if ( !timerId ) {
- timerId = window.requestAnimationFrame ?
- window.requestAnimationFrame( raf ) :
- window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
- }
-};
-
-jQuery.fx.stop = function() {
- if ( window.cancelAnimationFrame ) {
- window.cancelAnimationFrame( timerId );
- } else {
- window.clearInterval( timerId );
- }
-
- timerId = null;
-};
-
-jQuery.fx.speeds = {
- slow: 600,
- fast: 200,
-
- // Default speed
- _default: 400
-};
-
-
-// Based off of the plugin by Clint Helfers, with permission.
-// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
-jQuery.fn.delay = function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
-
- return this.queue( type, function( next, hooks ) {
- var timeout = window.setTimeout( next, time );
- hooks.stop = function() {
- window.clearTimeout( timeout );
- };
- } );
-};
-
-
-( function() {
- var input = document.createElement( "input" ),
- select = document.createElement( "select" ),
- opt = select.appendChild( document.createElement( "option" ) );
-
- input.type = "checkbox";
-
- // Support: Android <=4.3 only
- // Default value for a checkbox should be "on"
- support.checkOn = input.value !== "";
-
- // Support: IE <=11 only
- // Must access selectedIndex to make default options select
- support.optSelected = opt.selected;
-
- // Support: IE <=11 only
- // An input loses its value after becoming a radio
- input = document.createElement( "input" );
- input.value = "t";
- input.type = "radio";
- support.radioValue = input.value === "t";
-} )();
-
-
-var boolHook,
- attrHandle = jQuery.expr.attrHandle;
-
-jQuery.fn.extend( {
- attr: function( name, value ) {
- return access( this, jQuery.attr, name, value, arguments.length > 1 );
- },
-
- removeAttr: function( name ) {
- return this.each( function() {
- jQuery.removeAttr( this, name );
- } );
- }
-} );
-
-jQuery.extend( {
- attr: function( elem, name, value ) {
- var ret, hooks,
- nType = elem.nodeType;
-
- // Don't get/set attributes on text, comment and attribute nodes
- if ( nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === "undefined" ) {
- return jQuery.prop( elem, name, value );
- }
-
- // Attribute hooks are determined by the lowercase version
- // Grab necessary hook if one is defined
- if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
- hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
- ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
- }
-
- if ( value !== undefined ) {
- if ( value === null ) {
- jQuery.removeAttr( elem, name );
- return;
- }
-
- if ( hooks && "set" in hooks &&
- ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
- return ret;
- }
-
- elem.setAttribute( name, value + "" );
- return value;
- }
-
- if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
- return ret;
- }
-
- ret = jQuery.find.attr( elem, name );
-
- // Non-existent attributes return null, we normalize to undefined
- return ret == null ? undefined : ret;
- },
-
- attrHooks: {
- type: {
- set: function( elem, value ) {
- if ( !support.radioValue && value === "radio" &&
- jQuery.nodeName( elem, "input" ) ) {
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- return value;
- }
- }
- }
- },
-
- removeAttr: function( elem, value ) {
- var name,
- i = 0,
- attrNames = value && value.match( rnotwhite );
-
- if ( attrNames && elem.nodeType === 1 ) {
- while ( ( name = attrNames[ i++ ] ) ) {
- elem.removeAttribute( name );
- }
- }
- }
-} );
-
-// Hooks for boolean attributes
-boolHook = {
- set: function( elem, value, name ) {
- if ( value === false ) {
-
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- elem.setAttribute( name, name );
- }
- return name;
- }
-};
-
-jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
- var getter = attrHandle[ name ] || jQuery.find.attr;
-
- attrHandle[ name ] = function( elem, name, isXML ) {
- var ret, handle,
- lowercaseName = name.toLowerCase();
-
- if ( !isXML ) {
-
- // Avoid an infinite loop by temporarily removing this function from the getter
- handle = attrHandle[ lowercaseName ];
- attrHandle[ lowercaseName ] = ret;
- ret = getter( elem, name, isXML ) != null ?
- lowercaseName :
- null;
- attrHandle[ lowercaseName ] = handle;
- }
- return ret;
- };
-} );
-
-
-
-
-var rfocusable = /^(?:input|select|textarea|button)$/i,
- rclickable = /^(?:a|area)$/i;
-
-jQuery.fn.extend( {
- prop: function( name, value ) {
- return access( this, jQuery.prop, name, value, arguments.length > 1 );
- },
-
- removeProp: function( name ) {
- return this.each( function() {
- delete this[ jQuery.propFix[ name ] || name ];
- } );
- }
-} );
-
-jQuery.extend( {
- prop: function( elem, name, value ) {
- var ret, hooks,
- nType = elem.nodeType;
-
- // Don't get/set properties on text, comment and attribute nodes
- if ( nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
-
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
-
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks &&
- ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
- return ret;
- }
-
- return ( elem[ name ] = value );
- }
-
- if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
- return ret;
- }
-
- return elem[ name ];
- },
-
- propHooks: {
- tabIndex: {
- get: function( elem ) {
-
- // Support: IE <=9 - 11 only
- // elem.tabIndex doesn't always return the
- // correct value when it hasn't been explicitly set
- // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- // Use proper attribute retrieval(#12072)
- var tabindex = jQuery.find.attr( elem, "tabindex" );
-
- return tabindex ?
- parseInt( tabindex, 10 ) :
- rfocusable.test( elem.nodeName ) ||
- rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- -1;
- }
- }
- },
-
- propFix: {
- "for": "htmlFor",
- "class": "className"
- }
-} );
-
-// Support: IE <=11 only
-// Accessing the selectedIndex property
-// forces the browser to respect setting selected
-// on the option
-// The getter ensures a default option is selected
-// when in an optgroup
-if ( !support.optSelected ) {
- jQuery.propHooks.selected = {
- get: function( elem ) {
- var parent = elem.parentNode;
- if ( parent && parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- return null;
- },
- set: function( elem ) {
- var parent = elem.parentNode;
- if ( parent ) {
- parent.selectedIndex;
-
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- }
- };
-}
-
-jQuery.each( [
- "tabIndex",
- "readOnly",
- "maxLength",
- "cellSpacing",
- "cellPadding",
- "rowSpan",
- "colSpan",
- "useMap",
- "frameBorder",
- "contentEditable"
-], function() {
- jQuery.propFix[ this.toLowerCase() ] = this;
-} );
-
-
-
-
-var rclass = /[\t\r\n\f]/g;
-
-function getClass( elem ) {
- return elem.getAttribute && elem.getAttribute( "class" ) || "";
-}
-
-jQuery.fn.extend( {
- addClass: function( value ) {
- var classes, elem, cur, curValue, clazz, j, finalValue,
- i = 0;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( j ) {
- jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
- } );
- }
-
- if ( typeof value === "string" && value ) {
- classes = value.match( rnotwhite ) || [];
-
- while ( ( elem = this[ i++ ] ) ) {
- curValue = getClass( elem );
- cur = elem.nodeType === 1 &&
- ( " " + curValue + " " ).replace( rclass, " " );
-
- if ( cur ) {
- j = 0;
- while ( ( clazz = classes[ j++ ] ) ) {
- if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
- cur += clazz + " ";
- }
- }
-
- // Only assign if different to avoid unneeded rendering.
- finalValue = jQuery.trim( cur );
- if ( curValue !== finalValue ) {
- elem.setAttribute( "class", finalValue );
- }
- }
- }
- }
-
- return this;
- },
-
- removeClass: function( value ) {
- var classes, elem, cur, curValue, clazz, j, finalValue,
- i = 0;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( j ) {
- jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
- } );
- }
-
- if ( !arguments.length ) {
- return this.attr( "class", "" );
- }
-
- if ( typeof value === "string" && value ) {
- classes = value.match( rnotwhite ) || [];
-
- while ( ( elem = this[ i++ ] ) ) {
- curValue = getClass( elem );
-
- // This expression is here for better compressibility (see addClass)
- cur = elem.nodeType === 1 &&
- ( " " + curValue + " " ).replace( rclass, " " );
-
- if ( cur ) {
- j = 0;
- while ( ( clazz = classes[ j++ ] ) ) {
-
- // Remove *all* instances
- while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
- cur = cur.replace( " " + clazz + " ", " " );
- }
- }
-
- // Only assign if different to avoid unneeded rendering.
- finalValue = jQuery.trim( cur );
- if ( curValue !== finalValue ) {
- elem.setAttribute( "class", finalValue );
- }
- }
- }
- }
-
- return this;
- },
-
- toggleClass: function( value, stateVal ) {
- var type = typeof value;
-
- if ( typeof stateVal === "boolean" && type === "string" ) {
- return stateVal ? this.addClass( value ) : this.removeClass( value );
- }
-
- if ( jQuery.isFunction( value ) ) {
- return this.each( function( i ) {
- jQuery( this ).toggleClass(
- value.call( this, i, getClass( this ), stateVal ),
- stateVal
- );
- } );
- }
-
- return this.each( function() {
- var className, i, self, classNames;
-
- if ( type === "string" ) {
-
- // Toggle individual class names
- i = 0;
- self = jQuery( this );
- classNames = value.match( rnotwhite ) || [];
-
- while ( ( className = classNames[ i++ ] ) ) {
-
- // Check each className given, space separated list
- if ( self.hasClass( className ) ) {
- self.removeClass( className );
- } else {
- self.addClass( className );
- }
- }
-
- // Toggle whole class name
- } else if ( value === undefined || type === "boolean" ) {
- className = getClass( this );
- if ( className ) {
-
- // Store className if set
- dataPriv.set( this, "__className__", className );
- }
-
- // If the element has a class name or if we're passed `false`,
- // then remove the whole classname (if there was one, the above saved it).
- // Otherwise bring back whatever was previously saved (if anything),
- // falling back to the empty string if nothing was stored.
- if ( this.setAttribute ) {
- this.setAttribute( "class",
- className || value === false ?
- "" :
- dataPriv.get( this, "__className__" ) || ""
- );
- }
- }
- } );
- },
-
- hasClass: function( selector ) {
- var className, elem,
- i = 0;
-
- className = " " + selector + " ";
- while ( ( elem = this[ i++ ] ) ) {
- if ( elem.nodeType === 1 &&
- ( " " + getClass( elem ) + " " ).replace( rclass, " " )
- .indexOf( className ) > -1
- ) {
- return true;
- }
- }
-
- return false;
- }
-} );
-
-
-
-
-var rreturn = /\r/g,
- rspaces = /[\x20\t\r\n\f]+/g;
-
-jQuery.fn.extend( {
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[ 0 ];
-
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.type ] ||
- jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
- if ( hooks &&
- "get" in hooks &&
- ( ret = hooks.get( elem, "value" ) ) !== undefined
- ) {
- return ret;
- }
-
- ret = elem.value;
-
- return typeof ret === "string" ?
-
- // Handle most common string cases
- ret.replace( rreturn, "" ) :
-
- // Handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
-
- return;
- }
-
- isFunction = jQuery.isFunction( value );
-
- return this.each( function( i ) {
- var val;
-
- if ( this.nodeType !== 1 ) {
- return;
- }
-
- if ( isFunction ) {
- val = value.call( this, i, jQuery( this ).val() );
- } else {
- val = value;
- }
-
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
-
- } else if ( typeof val === "number" ) {
- val += "";
-
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map( val, function( value ) {
- return value == null ? "" : value + "";
- } );
- }
-
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- } );
- }
-} );
-
-jQuery.extend( {
- valHooks: {
- option: {
- get: function( elem ) {
-
- var val = jQuery.find.attr( elem, "value" );
- return val != null ?
- val :
-
- // Support: IE <=10 - 11 only
- // option.text throws exceptions (#14686, #14858)
- // Strip and collapse whitespace
- // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
- jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
- }
- },
- select: {
- get: function( elem ) {
- var value, option,
- options = elem.options,
- index = elem.selectedIndex,
- one = elem.type === "select-one",
- values = one ? null : [],
- max = one ? index + 1 : options.length,
- i = index < 0 ?
- max :
- one ? index : 0;
-
- // Loop through all the selected options
- for ( ; i < max; i++ ) {
- option = options[ i ];
-
- // Support: IE <=9 only
- // IE8-9 doesn't update selected after form reset (#2551)
- if ( ( option.selected || i === index ) &&
-
- // Don't return options that are disabled or in a disabled optgroup
- !option.disabled &&
- ( !option.parentNode.disabled ||
- !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
-
- // Get the specific value for the option
- value = jQuery( option ).val();
-
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- return values;
- },
-
- set: function( elem, value ) {
- var optionSet, option,
- options = elem.options,
- values = jQuery.makeArray( value ),
- i = options.length;
-
- while ( i-- ) {
- option = options[ i ];
- if ( option.selected =
- jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
- ) {
- optionSet = true;
- }
- }
-
- // Force browsers to behave consistently when non-matching value is set
- if ( !optionSet ) {
- elem.selectedIndex = -1;
- }
- return values;
- }
- }
- }
-} );
-
-// Radios and checkboxes getter/setter
-jQuery.each( [ "radio", "checkbox" ], function() {
- jQuery.valHooks[ this ] = {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
- }
- }
- };
- if ( !support.checkOn ) {
- jQuery.valHooks[ this ].get = function( elem ) {
- return elem.getAttribute( "value" ) === null ? "on" : elem.value;
- };
- }
-} );
-
-
-
-
-// Return jQuery for attributes-only inclusion
-
-
-var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
-
-jQuery.extend( jQuery.event, {
-
- trigger: function( event, data, elem, onlyHandlers ) {
-
- var i, cur, tmp, bubbleType, ontype, handle, special,
- eventPath = [ elem || document ],
- type = hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
-
- cur = tmp = elem = elem || document;
-
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf( "." ) > -1 ) {
-
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split( "." );
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf( ":" ) < 0 && "on" + type;
-
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
-
- // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
- event.isTrigger = onlyHandlers ? 2 : 3;
- event.namespace = namespaces.join( "." );
- event.rnamespace = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
- null;
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === ( elem.ownerDocument || document ) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
-
- // Fire handlers on the event path
- i = 0;
- while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
-
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
-
- // jQuery handler
- handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
- dataPriv.get( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
-
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && handle.apply && acceptData( cur ) ) {
- event.result = handle.apply( cur, data );
- if ( event.result === false ) {
- event.preventDefault();
- }
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( ( !special._default ||
- special._default.apply( eventPath.pop(), data ) === false ) &&
- acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name as the event.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
-
- if ( tmp ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- elem[ type ]();
- jQuery.event.triggered = undefined;
-
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
-
- return event.result;
- },
-
- // Piggyback on a donor event to simulate a different one
- // Used only for `focus(in | out)` events
- simulate: function( type, elem, event ) {
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- {
- type: type,
- isSimulated: true
- }
- );
-
- jQuery.event.trigger( e, null, elem );
- }
-
-} );
-
-jQuery.fn.extend( {
-
- trigger: function( type, data ) {
- return this.each( function() {
- jQuery.event.trigger( type, data, this );
- } );
- },
- triggerHandler: function( type, data ) {
- var elem = this[ 0 ];
- if ( elem ) {
- return jQuery.event.trigger( type, data, elem, true );
- }
- }
-} );
-
-
-jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
- "change select submit keydown keypress keyup contextmenu" ).split( " " ),
- function( i, name ) {
-
- // Handle event binding
- jQuery.fn[ name ] = function( data, fn ) {
- return arguments.length > 0 ?
- this.on( name, null, data, fn ) :
- this.trigger( name );
- };
-} );
-
-jQuery.fn.extend( {
- hover: function( fnOver, fnOut ) {
- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
- }
-} );
-
-
-
-
-support.focusin = "onfocusin" in window;
-
-
-// Support: Firefox <=44
-// Firefox doesn't have focus(in | out) events
-// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
-//
-// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
-// focus(in | out) events fire after focus & blur events,
-// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
-// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
-if ( !support.focusin ) {
- jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
- // Attach a single capturing handler on the document while someone wants focusin/focusout
- var handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
- };
-
- jQuery.event.special[ fix ] = {
- setup: function() {
- var doc = this.ownerDocument || this,
- attaches = dataPriv.access( doc, fix );
-
- if ( !attaches ) {
- doc.addEventListener( orig, handler, true );
- }
- dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
- },
- teardown: function() {
- var doc = this.ownerDocument || this,
- attaches = dataPriv.access( doc, fix ) - 1;
-
- if ( !attaches ) {
- doc.removeEventListener( orig, handler, true );
- dataPriv.remove( doc, fix );
-
- } else {
- dataPriv.access( doc, fix, attaches );
- }
- }
- };
- } );
-}
-var location = window.location;
-
-var nonce = jQuery.now();
-
-var rquery = ( /\?/ );
-
-
-
-// Cross-browser xml parsing
-jQuery.parseXML = function( data ) {
- var xml;
- if ( !data || typeof data !== "string" ) {
- return null;
- }
-
- // Support: IE 9 - 11 only
- // IE throws on parseFromString with invalid input.
- try {
- xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
- } catch ( e ) {
- xml = undefined;
- }
-
- if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
- }
- return xml;
-};
-
-
-var
- rbracket = /\[\]$/,
- rCRLF = /\r?\n/g,
- rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
- rsubmittable = /^(?:input|select|textarea|keygen)/i;
-
-function buildParams( prefix, obj, traditional, add ) {
- var name;
-
- if ( jQuery.isArray( obj ) ) {
-
- // Serialize array item.
- jQuery.each( obj, function( i, v ) {
- if ( traditional || rbracket.test( prefix ) ) {
-
- // Treat each array item as a scalar.
- add( prefix, v );
-
- } else {
-
- // Item is non-scalar (array or object), encode its numeric index.
- buildParams(
- prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
- v,
- traditional,
- add
- );
- }
- } );
-
- } else if ( !traditional && jQuery.type( obj ) === "object" ) {
-
- // Serialize object item.
- for ( name in obj ) {
- buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
- }
-
- } else {
-
- // Serialize scalar item.
- add( prefix, obj );
- }
-}
-
-// Serialize an array of form elements or a set of
-// key/values into a query string
-jQuery.param = function( a, traditional ) {
- var prefix,
- s = [],
- add = function( key, valueOrFunction ) {
-
- // If value is a function, invoke it and use its return value
- var value = jQuery.isFunction( valueOrFunction ) ?
- valueOrFunction() :
- valueOrFunction;
-
- s[ s.length ] = encodeURIComponent( key ) + "=" +
- encodeURIComponent( value == null ? "" : value );
- };
-
- // If an array was passed in, assume that it is an array of form elements.
- if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
-
- // Serialize the form elements
- jQuery.each( a, function() {
- add( this.name, this.value );
- } );
-
- } else {
-
- // If traditional, encode the "old" way (the way 1.3.2 or older
- // did it), otherwise encode params recursively.
- for ( prefix in a ) {
- buildParams( prefix, a[ prefix ], traditional, add );
- }
- }
-
- // Return the resulting serialization
- return s.join( "&" );
-};
-
-jQuery.fn.extend( {
- serialize: function() {
- return jQuery.param( this.serializeArray() );
- },
- serializeArray: function() {
- return this.map( function() {
-
- // Can add propHook for "elements" to filter or add form elements
- var elements = jQuery.prop( this, "elements" );
- return elements ? jQuery.makeArray( elements ) : this;
- } )
- .filter( function() {
- var type = this.type;
-
- // Use .is( ":disabled" ) so that fieldset[disabled] works
- return this.name && !jQuery( this ).is( ":disabled" ) &&
- rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
- ( this.checked || !rcheckableType.test( type ) );
- } )
- .map( function( i, elem ) {
- var val = jQuery( this ).val();
-
- return val == null ?
- null :
- jQuery.isArray( val ) ?
- jQuery.map( val, function( val ) {
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- } ) :
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
- } ).get();
- }
-} );
-
-
-var
- r20 = /%20/g,
- rhash = /#.*$/,
- rts = /([?&])_=[^&]*/,
- rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
-
- // #7653, #8125, #8152: local protocol detection
- rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
- rnoContent = /^(?:GET|HEAD)$/,
- rprotocol = /^\/\//,
-
- /* Prefilters
- * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
- * 2) These are called:
- * - BEFORE asking for a transport
- * - AFTER param serialization (s.data is a string if s.processData is true)
- * 3) key is the dataType
- * 4) the catchall symbol "*" can be used
- * 5) execution will start with transport dataType and THEN continue down to "*" if needed
- */
- prefilters = {},
-
- /* Transports bindings
- * 1) key is the dataType
- * 2) the catchall symbol "*" can be used
- * 3) selection will start with transport dataType and THEN go to "*" if needed
- */
- transports = {},
-
- // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
- allTypes = "*/".concat( "*" ),
-
- // Anchor tag for parsing the document origin
- originAnchor = document.createElement( "a" );
- originAnchor.href = location.href;
-
-// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
-function addToPrefiltersOrTransports( structure ) {
-
- // dataTypeExpression is optional and defaults to "*"
- return function( dataTypeExpression, func ) {
-
- if ( typeof dataTypeExpression !== "string" ) {
- func = dataTypeExpression;
- dataTypeExpression = "*";
- }
-
- var dataType,
- i = 0,
- dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
-
- if ( jQuery.isFunction( func ) ) {
-
- // For each dataType in the dataTypeExpression
- while ( ( dataType = dataTypes[ i++ ] ) ) {
-
- // Prepend if requested
- if ( dataType[ 0 ] === "+" ) {
- dataType = dataType.slice( 1 ) || "*";
- ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
-
- // Otherwise append
- } else {
- ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
- }
- }
- }
- };
-}
-
-// Base inspection function for prefilters and transports
-function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
-
- var inspected = {},
- seekingTransport = ( structure === transports );
-
- function inspect( dataType ) {
- var selected;
- inspected[ dataType ] = true;
- jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
- var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
- if ( typeof dataTypeOrTransport === "string" &&
- !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
-
- options.dataTypes.unshift( dataTypeOrTransport );
- inspect( dataTypeOrTransport );
- return false;
- } else if ( seekingTransport ) {
- return !( selected = dataTypeOrTransport );
- }
- } );
- return selected;
- }
-
- return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
-}
-
-// A special extend for ajax options
-// that takes "flat" options (not to be deep extended)
-// Fixes #9887
-function ajaxExtend( target, src ) {
- var key, deep,
- flatOptions = jQuery.ajaxSettings.flatOptions || {};
-
- for ( key in src ) {
- if ( src[ key ] !== undefined ) {
- ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
- }
- }
- if ( deep ) {
- jQuery.extend( true, target, deep );
- }
-
- return target;
-}
-
-/* Handles responses to an ajax request:
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
-function ajaxHandleResponses( s, jqXHR, responses ) {
-
- var ct, type, finalDataType, firstDataType,
- contents = s.contents,
- dataTypes = s.dataTypes;
-
- // Remove auto dataType and get content-type in the process
- while ( dataTypes[ 0 ] === "*" ) {
- dataTypes.shift();
- if ( ct === undefined ) {
- ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
- }
- }
-
- // Check if we're dealing with a known content-type
- if ( ct ) {
- for ( type in contents ) {
- if ( contents[ type ] && contents[ type ].test( ct ) ) {
- dataTypes.unshift( type );
- break;
- }
- }
- }
-
- // Check to see if we have a response for the expected dataType
- if ( dataTypes[ 0 ] in responses ) {
- finalDataType = dataTypes[ 0 ];
- } else {
-
- // Try convertible dataTypes
- for ( type in responses ) {
- if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
- finalDataType = type;
- break;
- }
- if ( !firstDataType ) {
- firstDataType = type;
- }
- }
-
- // Or just use first one
- finalDataType = finalDataType || firstDataType;
- }
-
- // If we found a dataType
- // We add the dataType to the list if needed
- // and return the corresponding response
- if ( finalDataType ) {
- if ( finalDataType !== dataTypes[ 0 ] ) {
- dataTypes.unshift( finalDataType );
- }
- return responses[ finalDataType ];
- }
-}
-
-/* Chain conversions given the request and the original response
- * Also sets the responseXXX fields on the jqXHR instance
- */
-function ajaxConvert( s, response, jqXHR, isSuccess ) {
- var conv2, current, conv, tmp, prev,
- converters = {},
-
- // Work with a copy of dataTypes in case we need to modify it for conversion
- dataTypes = s.dataTypes.slice();
-
- // Create converters map with lowercased keys
- if ( dataTypes[ 1 ] ) {
- for ( conv in s.converters ) {
- converters[ conv.toLowerCase() ] = s.converters[ conv ];
- }
- }
-
- current = dataTypes.shift();
-
- // Convert to each sequential dataType
- while ( current ) {
-
- if ( s.responseFields[ current ] ) {
- jqXHR[ s.responseFields[ current ] ] = response;
- }
-
- // Apply the dataFilter if provided
- if ( !prev && isSuccess && s.dataFilter ) {
- response = s.dataFilter( response, s.dataType );
- }
-
- prev = current;
- current = dataTypes.shift();
-
- if ( current ) {
-
- // There's only work to do if current dataType is non-auto
- if ( current === "*" ) {
-
- current = prev;
-
- // Convert response if prev dataType is non-auto and differs from current
- } else if ( prev !== "*" && prev !== current ) {
-
- // Seek a direct converter
- conv = converters[ prev + " " + current ] || converters[ "* " + current ];
-
- // If none found, seek a pair
- if ( !conv ) {
- for ( conv2 in converters ) {
-
- // If conv2 outputs current
- tmp = conv2.split( " " );
- if ( tmp[ 1 ] === current ) {
-
- // If prev can be converted to accepted input
- conv = converters[ prev + " " + tmp[ 0 ] ] ||
- converters[ "* " + tmp[ 0 ] ];
- if ( conv ) {
-
- // Condense equivalence converters
- if ( conv === true ) {
- conv = converters[ conv2 ];
-
- // Otherwise, insert the intermediate dataType
- } else if ( converters[ conv2 ] !== true ) {
- current = tmp[ 0 ];
- dataTypes.unshift( tmp[ 1 ] );
- }
- break;
- }
- }
- }
- }
-
- // Apply converter (if not an equivalence)
- if ( conv !== true ) {
-
- // Unless errors are allowed to bubble, catch and return them
- if ( conv && s.throws ) {
- response = conv( response );
- } else {
- try {
- response = conv( response );
- } catch ( e ) {
- return {
- state: "parsererror",
- error: conv ? e : "No conversion from " + prev + " to " + current
- };
- }
- }
- }
- }
- }
- }
-
- return { state: "success", data: response };
-}
-
-jQuery.extend( {
-
- // Counter for holding the number of active queries
- active: 0,
-
- // Last-Modified header cache for next request
- lastModified: {},
- etag: {},
-
- ajaxSettings: {
- url: location.href,
- type: "GET",
- isLocal: rlocalProtocol.test( location.protocol ),
- global: true,
- processData: true,
- async: true,
- contentType: "application/x-www-form-urlencoded; charset=UTF-8",
- /*
- timeout: 0,
- data: null,
- dataType: null,
- username: null,
- password: null,
- cache: null,
- throws: false,
- traditional: false,
- headers: {},
- */
-
- accepts: {
- "*": allTypes,
- text: "text/plain",
- html: "text/html",
- xml: "application/xml, text/xml",
- json: "application/json, text/javascript"
- },
-
- contents: {
- xml: /\bxml\b/,
- html: /\bhtml/,
- json: /\bjson\b/
- },
-
- responseFields: {
- xml: "responseXML",
- text: "responseText",
- json: "responseJSON"
- },
-
- // Data converters
- // Keys separate source (or catchall "*") and destination types with a single space
- converters: {
-
- // Convert anything to text
- "* text": String,
-
- // Text to html (true = no transformation)
- "text html": true,
-
- // Evaluate text as a json expression
- "text json": JSON.parse,
-
- // Parse text as xml
- "text xml": jQuery.parseXML
- },
-
- // For options that shouldn't be deep extended:
- // you can add your own custom options here if
- // and when you create one that shouldn't be
- // deep extended (see ajaxExtend)
- flatOptions: {
- url: true,
- context: true
- }
- },
-
- // Creates a full fledged settings object into target
- // with both ajaxSettings and settings fields.
- // If target is omitted, writes into ajaxSettings.
- ajaxSetup: function( target, settings ) {
- return settings ?
-
- // Building a settings object
- ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
-
- // Extending ajaxSettings
- ajaxExtend( jQuery.ajaxSettings, target );
- },
-
- ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
- ajaxTransport: addToPrefiltersOrTransports( transports ),
-
- // Main method
- ajax: function( url, options ) {
-
- // If url is an object, simulate pre-1.5 signature
- if ( typeof url === "object" ) {
- options = url;
- url = undefined;
- }
-
- // Force options to be an object
- options = options || {};
-
- var transport,
-
- // URL without anti-cache param
- cacheURL,
-
- // Response headers
- responseHeadersString,
- responseHeaders,
-
- // timeout handle
- timeoutTimer,
-
- // Url cleanup var
- urlAnchor,
-
- // Request state (becomes false upon send and true upon completion)
- completed,
-
- // To know if global events are to be dispatched
- fireGlobals,
-
- // Loop variable
- i,
-
- // uncached part of the url
- uncached,
-
- // Create the final options object
- s = jQuery.ajaxSetup( {}, options ),
-
- // Callbacks context
- callbackContext = s.context || s,
-
- // Context for global events is callbackContext if it is a DOM node or jQuery collection
- globalEventContext = s.context &&
- ( callbackContext.nodeType || callbackContext.jquery ) ?
- jQuery( callbackContext ) :
- jQuery.event,
-
- // Deferreds
- deferred = jQuery.Deferred(),
- completeDeferred = jQuery.Callbacks( "once memory" ),
-
- // Status-dependent callbacks
- statusCode = s.statusCode || {},
-
- // Headers (they are sent all at once)
- requestHeaders = {},
- requestHeadersNames = {},
-
- // Default abort message
- strAbort = "canceled",
-
- // Fake xhr
- jqXHR = {
- readyState: 0,
-
- // Builds headers hashtable if needed
- getResponseHeader: function( key ) {
- var match;
- if ( completed ) {
- if ( !responseHeaders ) {
- responseHeaders = {};
- while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
- responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
- }
- }
- match = responseHeaders[ key.toLowerCase() ];
- }
- return match == null ? null : match;
- },
-
- // Raw string
- getAllResponseHeaders: function() {
- return completed ? responseHeadersString : null;
- },
-
- // Caches the header
- setRequestHeader: function( name, value ) {
- if ( completed == null ) {
- name = requestHeadersNames[ name.toLowerCase() ] =
- requestHeadersNames[ name.toLowerCase() ] || name;
- requestHeaders[ name ] = value;
- }
- return this;
- },
-
- // Overrides response content-type header
- overrideMimeType: function( type ) {
- if ( completed == null ) {
- s.mimeType = type;
- }
- return this;
- },
-
- // Status-dependent callbacks
- statusCode: function( map ) {
- var code;
- if ( map ) {
- if ( completed ) {
-
- // Execute the appropriate callbacks
- jqXHR.always( map[ jqXHR.status ] );
- } else {
-
- // Lazy-add the new callbacks in a way that preserves old ones
- for ( code in map ) {
- statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
- }
- }
- }
- return this;
- },
-
- // Cancel the request
- abort: function( statusText ) {
- var finalText = statusText || strAbort;
- if ( transport ) {
- transport.abort( finalText );
- }
- done( 0, finalText );
- return this;
- }
- };
-
- // Attach deferreds
- deferred.promise( jqXHR );
-
- // Add protocol if not provided (prefilters might expect it)
- // Handle falsy url in the settings object (#10093: consistency with old signature)
- // We also use the url parameter if available
- s.url = ( ( url || s.url || location.href ) + "" )
- .replace( rprotocol, location.protocol + "//" );
-
- // Alias method option to type as per ticket #12004
- s.type = options.method || options.type || s.method || s.type;
-
- // Extract dataTypes list
- s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
-
- // A cross-domain request is in order when the origin doesn't match the current origin.
- if ( s.crossDomain == null ) {
- urlAnchor = document.createElement( "a" );
-
- // Support: IE <=8 - 11, Edge 12 - 13
- // IE throws exception on accessing the href property if url is malformed,
- // e.g. http://example.com:80x/
- try {
- urlAnchor.href = s.url;
-
- // Support: IE <=8 - 11 only
- // Anchor's host property isn't correctly set when s.url is relative
- urlAnchor.href = urlAnchor.href;
- s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
- urlAnchor.protocol + "//" + urlAnchor.host;
- } catch ( e ) {
-
- // If there is an error parsing the URL, assume it is crossDomain,
- // it can be rejected by the transport if it is invalid
- s.crossDomain = true;
- }
- }
-
- // Convert data if not already a string
- if ( s.data && s.processData && typeof s.data !== "string" ) {
- s.data = jQuery.param( s.data, s.traditional );
- }
-
- // Apply prefilters
- inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
-
- // If request was aborted inside a prefilter, stop there
- if ( completed ) {
- return jqXHR;
- }
-
- // We can fire global events as of now if asked to
- // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
- fireGlobals = jQuery.event && s.global;
-
- // Watch for a new set of requests
- if ( fireGlobals && jQuery.active++ === 0 ) {
- jQuery.event.trigger( "ajaxStart" );
- }
-
- // Uppercase the type
- s.type = s.type.toUpperCase();
-
- // Determine if request has content
- s.hasContent = !rnoContent.test( s.type );
-
- // Save the URL in case we're toying with the If-Modified-Since
- // and/or If-None-Match header later on
- // Remove hash to simplify url manipulation
- cacheURL = s.url.replace( rhash, "" );
-
- // More options handling for requests with no content
- if ( !s.hasContent ) {
-
- // Remember the hash so we can put it back
- uncached = s.url.slice( cacheURL.length );
-
- // If data is available, append data to url
- if ( s.data ) {
- cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
-
- // #9682: remove data so that it's not used in an eventual retry
- delete s.data;
- }
-
- // Add anti-cache in uncached url if needed
- if ( s.cache === false ) {
- cacheURL = cacheURL.replace( rts, "" );
- uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
- }
-
- // Put hash and anti-cache on the URL that will be requested (gh-1732)
- s.url = cacheURL + uncached;
-
- // Change '%20' to '+' if this is encoded form body content (gh-2658)
- } else if ( s.data && s.processData &&
- ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
- s.data = s.data.replace( r20, "+" );
- }
-
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
- if ( jQuery.lastModified[ cacheURL ] ) {
- jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
- }
- if ( jQuery.etag[ cacheURL ] ) {
- jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
- }
- }
-
- // Set the correct header, if data is being sent
- if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
- jqXHR.setRequestHeader( "Content-Type", s.contentType );
- }
-
- // Set the Accepts header for the server, depending on the dataType
- jqXHR.setRequestHeader(
- "Accept",
- s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
- s.accepts[ s.dataTypes[ 0 ] ] +
- ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
- s.accepts[ "*" ]
- );
-
- // Check for headers option
- for ( i in s.headers ) {
- jqXHR.setRequestHeader( i, s.headers[ i ] );
- }
-
- // Allow custom headers/mimetypes and early abort
- if ( s.beforeSend &&
- ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
-
- // Abort if not done already and return
- return jqXHR.abort();
- }
-
- // Aborting is no longer a cancellation
- strAbort = "abort";
-
- // Install callbacks on deferreds
- completeDeferred.add( s.complete );
- jqXHR.done( s.success );
- jqXHR.fail( s.error );
-
- // Get transport
- transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
-
- // If no transport, we auto-abort
- if ( !transport ) {
- done( -1, "No Transport" );
- } else {
- jqXHR.readyState = 1;
-
- // Send global event
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
- }
-
- // If request was aborted inside ajaxSend, stop there
- if ( completed ) {
- return jqXHR;
- }
-
- // Timeout
- if ( s.async && s.timeout > 0 ) {
- timeoutTimer = window.setTimeout( function() {
- jqXHR.abort( "timeout" );
- }, s.timeout );
- }
-
- try {
- completed = false;
- transport.send( requestHeaders, done );
- } catch ( e ) {
-
- // Rethrow post-completion exceptions
- if ( completed ) {
- throw e;
- }
-
- // Propagate others as results
- done( -1, e );
- }
- }
-
- // Callback for when everything is done
- function done( status, nativeStatusText, responses, headers ) {
- var isSuccess, success, error, response, modified,
- statusText = nativeStatusText;
-
- // Ignore repeat invocations
- if ( completed ) {
- return;
- }
-
- completed = true;
-
- // Clear timeout if it exists
- if ( timeoutTimer ) {
- window.clearTimeout( timeoutTimer );
- }
-
- // Dereference transport for early garbage collection
- // (no matter how long the jqXHR object will be used)
- transport = undefined;
-
- // Cache response headers
- responseHeadersString = headers || "";
-
- // Set readyState
- jqXHR.readyState = status > 0 ? 4 : 0;
-
- // Determine if successful
- isSuccess = status >= 200 && status < 300 || status === 304;
-
- // Get response data
- if ( responses ) {
- response = ajaxHandleResponses( s, jqXHR, responses );
- }
-
- // Convert no matter what (that way responseXXX fields are always set)
- response = ajaxConvert( s, response, jqXHR, isSuccess );
-
- // If successful, handle type chaining
- if ( isSuccess ) {
-
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
- if ( s.ifModified ) {
- modified = jqXHR.getResponseHeader( "Last-Modified" );
- if ( modified ) {
- jQuery.lastModified[ cacheURL ] = modified;
- }
- modified = jqXHR.getResponseHeader( "etag" );
- if ( modified ) {
- jQuery.etag[ cacheURL ] = modified;
- }
- }
-
- // if no content
- if ( status === 204 || s.type === "HEAD" ) {
- statusText = "nocontent";
-
- // if not modified
- } else if ( status === 304 ) {
- statusText = "notmodified";
-
- // If we have data, let's convert it
- } else {
- statusText = response.state;
- success = response.data;
- error = response.error;
- isSuccess = !error;
- }
- } else {
-
- // Extract error from statusText and normalize for non-aborts
- error = statusText;
- if ( status || !statusText ) {
- statusText = "error";
- if ( status < 0 ) {
- status = 0;
- }
- }
- }
-
- // Set data for the fake xhr object
- jqXHR.status = status;
- jqXHR.statusText = ( nativeStatusText || statusText ) + "";
-
- // Success/Error
- if ( isSuccess ) {
- deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
- } else {
- deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
- }
-
- // Status-dependent callbacks
- jqXHR.statusCode( statusCode );
- statusCode = undefined;
-
- if ( fireGlobals ) {
- globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
- [ jqXHR, s, isSuccess ? success : error ] );
- }
-
- // Complete
- completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
-
- if ( fireGlobals ) {
- globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
-
- // Handle the global AJAX counter
- if ( !( --jQuery.active ) ) {
- jQuery.event.trigger( "ajaxStop" );
- }
- }
- }
-
- return jqXHR;
- },
-
- getJSON: function( url, data, callback ) {
- return jQuery.get( url, data, callback, "json" );
- },
-
- getScript: function( url, callback ) {
- return jQuery.get( url, undefined, callback, "script" );
- }
-} );
-
-jQuery.each( [ "get", "post" ], function( i, method ) {
- jQuery[ method ] = function( url, data, callback, type ) {
-
- // Shift arguments if data argument was omitted
- if ( jQuery.isFunction( data ) ) {
- type = type || callback;
- callback = data;
- data = undefined;
- }
-
- // The url can be an options object (which then must have .url)
- return jQuery.ajax( jQuery.extend( {
- url: url,
- type: method,
- dataType: type,
- data: data,
- success: callback
- }, jQuery.isPlainObject( url ) && url ) );
- };
-} );
-
-
-jQuery._evalUrl = function( url ) {
- return jQuery.ajax( {
- url: url,
-
- // Make this explicit, since user can override this through ajaxSetup (#11264)
- type: "GET",
- dataType: "script",
- cache: true,
- async: false,
- global: false,
- "throws": true
- } );
-};
-
-
-jQuery.fn.extend( {
- wrapAll: function( html ) {
- var wrap;
-
- if ( this[ 0 ] ) {
- if ( jQuery.isFunction( html ) ) {
- html = html.call( this[ 0 ] );
- }
-
- // The elements to wrap the target around
- wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
-
- if ( this[ 0 ].parentNode ) {
- wrap.insertBefore( this[ 0 ] );
- }
-
- wrap.map( function() {
- var elem = this;
-
- while ( elem.firstElementChild ) {
- elem = elem.firstElementChild;
- }
-
- return elem;
- } ).append( this );
- }
-
- return this;
- },
-
- wrapInner: function( html ) {
- if ( jQuery.isFunction( html ) ) {
- return this.each( function( i ) {
- jQuery( this ).wrapInner( html.call( this, i ) );
- } );
- }
-
- return this.each( function() {
- var self = jQuery( this ),
- contents = self.contents();
-
- if ( contents.length ) {
- contents.wrapAll( html );
-
- } else {
- self.append( html );
- }
- } );
- },
-
- wrap: function( html ) {
- var isFunction = jQuery.isFunction( html );
-
- return this.each( function( i ) {
- jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
- } );
- },
-
- unwrap: function( selector ) {
- this.parent( selector ).not( "body" ).each( function() {
- jQuery( this ).replaceWith( this.childNodes );
- } );
- return this;
- }
-} );
-
-
-jQuery.expr.pseudos.hidden = function( elem ) {
- return !jQuery.expr.pseudos.visible( elem );
-};
-jQuery.expr.pseudos.visible = function( elem ) {
- return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
-};
-
-
-
-
-jQuery.ajaxSettings.xhr = function() {
- try {
- return new window.XMLHttpRequest();
- } catch ( e ) {}
-};
-
-var xhrSuccessStatus = {
-
- // File protocol always yields status code 0, assume 200
- 0: 200,
-
- // Support: IE <=9 only
- // #1450: sometimes IE returns 1223 when it should be 204
- 1223: 204
- },
- xhrSupported = jQuery.ajaxSettings.xhr();
-
-support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
-support.ajax = xhrSupported = !!xhrSupported;
-
-jQuery.ajaxTransport( function( options ) {
- var callback, errorCallback;
-
- // Cross domain only allowed if supported through XMLHttpRequest
- if ( support.cors || xhrSupported && !options.crossDomain ) {
- return {
- send: function( headers, complete ) {
- var i,
- xhr = options.xhr();
-
- xhr.open(
- options.type,
- options.url,
- options.async,
- options.username,
- options.password
- );
-
- // Apply custom fields if provided
- if ( options.xhrFields ) {
- for ( i in options.xhrFields ) {
- xhr[ i ] = options.xhrFields[ i ];
- }
- }
-
- // Override mime type if needed
- if ( options.mimeType && xhr.overrideMimeType ) {
- xhr.overrideMimeType( options.mimeType );
- }
-
- // X-Requested-With header
- // For cross-domain requests, seeing as conditions for a preflight are
- // akin to a jigsaw puzzle, we simply never set it to be sure.
- // (it can always be set on a per-request basis or even using ajaxSetup)
- // For same-domain requests, won't change header if already provided.
- if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
- headers[ "X-Requested-With" ] = "XMLHttpRequest";
- }
-
- // Set headers
- for ( i in headers ) {
- xhr.setRequestHeader( i, headers[ i ] );
- }
-
- // Callback
- callback = function( type ) {
- return function() {
- if ( callback ) {
- callback = errorCallback = xhr.onload =
- xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
-
- if ( type === "abort" ) {
- xhr.abort();
- } else if ( type === "error" ) {
-
- // Support: IE <=9 only
- // On a manual native abort, IE9 throws
- // errors on any property access that is not readyState
- if ( typeof xhr.status !== "number" ) {
- complete( 0, "error" );
- } else {
- complete(
-
- // File: protocol always yields status 0; see #8605, #14207
- xhr.status,
- xhr.statusText
- );
- }
- } else {
- complete(
- xhrSuccessStatus[ xhr.status ] || xhr.status,
- xhr.statusText,
-
- // Support: IE <=9 only
- // IE9 has no XHR2 but throws on binary (trac-11426)
- // For XHR2 non-text, let the caller handle it (gh-2498)
- ( xhr.responseType || "text" ) !== "text" ||
- typeof xhr.responseText !== "string" ?
- { binary: xhr.response } :
- { text: xhr.responseText },
- xhr.getAllResponseHeaders()
- );
- }
- }
- };
- };
-
- // Listen to events
- xhr.onload = callback();
- errorCallback = xhr.onerror = callback( "error" );
-
- // Support: IE 9 only
- // Use onreadystatechange to replace onabort
- // to handle uncaught aborts
- if ( xhr.onabort !== undefined ) {
- xhr.onabort = errorCallback;
- } else {
- xhr.onreadystatechange = function() {
-
- // Check readyState before timeout as it changes
- if ( xhr.readyState === 4 ) {
-
- // Allow onerror to be called first,
- // but that will not handle a native abort
- // Also, save errorCallback to a variable
- // as xhr.onerror cannot be accessed
- window.setTimeout( function() {
- if ( callback ) {
- errorCallback();
- }
- } );
- }
- };
- }
-
- // Create the abort callback
- callback = callback( "abort" );
-
- try {
-
- // Do send the request (this may raise an exception)
- xhr.send( options.hasContent && options.data || null );
- } catch ( e ) {
-
- // #14683: Only rethrow if this hasn't been notified as an error yet
- if ( callback ) {
- throw e;
- }
- }
- },
-
- abort: function() {
- if ( callback ) {
- callback();
- }
- }
- };
- }
-} );
-
-
-
-
-// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
-jQuery.ajaxPrefilter( function( s ) {
- if ( s.crossDomain ) {
- s.contents.script = false;
- }
-} );
-
-// Install script dataType
-jQuery.ajaxSetup( {
- accepts: {
- script: "text/javascript, application/javascript, " +
- "application/ecmascript, application/x-ecmascript"
- },
- contents: {
- script: /\b(?:java|ecma)script\b/
- },
- converters: {
- "text script": function( text ) {
- jQuery.globalEval( text );
- return text;
- }
- }
-} );
-
-// Handle cache's special case and crossDomain
-jQuery.ajaxPrefilter( "script", function( s ) {
- if ( s.cache === undefined ) {
- s.cache = false;
- }
- if ( s.crossDomain ) {
- s.type = "GET";
- }
-} );
-
-// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function( s ) {
-
- // This transport only deals with cross domain requests
- if ( s.crossDomain ) {
- var script, callback;
- return {
- send: function( _, complete ) {
- script = jQuery( "<script>" ).prop( {
- charset: s.scriptCharset,
- src: s.url
- } ).on(
- "load error",
- callback = function( evt ) {
- script.remove();
- callback = null;
- if ( evt ) {
- complete( evt.type === "error" ? 404 : 200, evt.type );
- }
- }
- );
-
- // Use native DOM manipulation to avoid our domManip AJAX trickery
- document.head.appendChild( script[ 0 ] );
- },
- abort: function() {
- if ( callback ) {
- callback();
- }
- }
- };
- }
-} );
-
-
-
-
-var oldCallbacks = [],
- rjsonp = /(=)\?(?=&|$)|\?\?/;
-
-// Default jsonp settings
-jQuery.ajaxSetup( {
- jsonp: "callback",
- jsonpCallback: function() {
- var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
- this[ callback ] = true;
- return callback;
- }
-} );
-
-// Detect, normalize options and install callbacks for jsonp requests
-jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
-
- var callbackName, overwritten, responseContainer,
- jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
- "url" :
- typeof s.data === "string" &&
- ( s.contentType || "" )
- .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
- rjsonp.test( s.data ) && "data"
- );
-
- // Handle iff the expected data type is "jsonp" or we have a parameter to set
- if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
-
- // Get callback name, remembering preexisting value associated with it
- callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
- s.jsonpCallback() :
- s.jsonpCallback;
-
- // Insert callback into url or form data
- if ( jsonProp ) {
- s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
- } else if ( s.jsonp !== false ) {
- s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
- }
-
- // Use data converter to retrieve json after script execution
- s.converters[ "script json" ] = function() {
- if ( !responseContainer ) {
- jQuery.error( callbackName + " was not called" );
- }
- return responseContainer[ 0 ];
- };
-
- // Force json dataType
- s.dataTypes[ 0 ] = "json";
-
- // Install callback
- overwritten = window[ callbackName ];
- window[ callbackName ] = function() {
- responseContainer = arguments;
- };
-
- // Clean-up function (fires after converters)
- jqXHR.always( function() {
-
- // If previous value didn't exist - remove it
- if ( overwritten === undefined ) {
- jQuery( window ).removeProp( callbackName );
-
- // Otherwise restore preexisting value
- } else {
- window[ callbackName ] = overwritten;
- }
-
- // Save back as free
- if ( s[ callbackName ] ) {
-
- // Make sure that re-using the options doesn't screw things around
- s.jsonpCallback = originalSettings.jsonpCallback;
-
- // Save the callback name for future use
- oldCallbacks.push( callbackName );
- }
-
- // Call if it was a function and we have a response
- if ( responseContainer && jQuery.isFunction( overwritten ) ) {
- overwritten( responseContainer[ 0 ] );
- }
-
- responseContainer = overwritten = undefined;
- } );
-
- // Delegate to script
- return "script";
- }
-} );
-
-
-
-
-// Support: Safari 8 only
-// In Safari 8 documents created via document.implementation.createHTMLDocument
-// collapse sibling forms: the second one becomes a child of the first one.
-// Because of that, this security measure has to be disabled in Safari 8.
-// https://bugs.webkit.org/show_bug.cgi?id=137337
-support.createHTMLDocument = ( function() {
- var body = document.implementation.createHTMLDocument( "" ).body;
- body.innerHTML = "<form></form><form></form>";
- return body.childNodes.length === 2;
-} )();
-
-
-// Argument "data" should be string of html
-// context (optional): If specified, the fragment will be created in this context,
-// defaults to document
-// keepScripts (optional): If true, will include scripts passed in the html string
-jQuery.parseHTML = function( data, context, keepScripts ) {
- if ( typeof data !== "string" ) {
- return [];
- }
- if ( typeof context === "boolean" ) {
- keepScripts = context;
- context = false;
- }
-
- var base, parsed, scripts;
-
- if ( !context ) {
-
- // Stop scripts or inline event handlers from being executed immediately
- // by using document.implementation
- if ( support.createHTMLDocument ) {
- context = document.implementation.createHTMLDocument( "" );
-
- // Set the base href for the created document
- // so any parsed elements with URLs
- // are based on the document's URL (gh-2965)
- base = context.createElement( "base" );
- base.href = document.location.href;
- context.head.appendChild( base );
- } else {
- context = document;
- }
- }
-
- parsed = rsingleTag.exec( data );
- scripts = !keepScripts && [];
-
- // Single tag
- if ( parsed ) {
- return [ context.createElement( parsed[ 1 ] ) ];
- }
-
- parsed = buildFragment( [ data ], context, scripts );
-
- if ( scripts && scripts.length ) {
- jQuery( scripts ).remove();
- }
-
- return jQuery.merge( [], parsed.childNodes );
-};
-
-
-/**
- * Load a url into a page
- */
-jQuery.fn.load = function( url, params, callback ) {
- var selector, type, response,
- self = this,
- off = url.indexOf( " " );
-
- if ( off > -1 ) {
- selector = jQuery.trim( url.slice( off ) );
- url = url.slice( 0, off );
- }
-
- // If it's a function
- if ( jQuery.isFunction( params ) ) {
-
- // We assume that it's the callback
- callback = params;
- params = undefined;
-
- // Otherwise, build a param string
- } else if ( params && typeof params === "object" ) {
- type = "POST";
- }
-
- // If we have elements to modify, make the request
- if ( self.length > 0 ) {
- jQuery.ajax( {
- url: url,
-
- // If "type" variable is undefined, then "GET" method will be used.
- // Make value of this field explicit since
- // user can override it through ajaxSetup method
- type: type || "GET",
- dataType: "html",
- data: params
- } ).done( function( responseText ) {
-
- // Save response for use in complete callback
- response = arguments;
-
- self.html( selector ?
-
- // If a selector was specified, locate the right elements in a dummy div
- // Exclude scripts to avoid IE 'Permission Denied' errors
- jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
-
- // Otherwise use the full result
- responseText );
-
- // If the request succeeds, this function gets "data", "status", "jqXHR"
- // but they are ignored because response was set above.
- // If it fails, this function gets "jqXHR", "status", "error"
- } ).always( callback && function( jqXHR, status ) {
- self.each( function() {
- callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
- } );
- } );
- }
-
- return this;
-};
-
-
-
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( [
- "ajaxStart",
- "ajaxStop",
- "ajaxComplete",
- "ajaxError",
- "ajaxSuccess",
- "ajaxSend"
-], function( i, type ) {
- jQuery.fn[ type ] = function( fn ) {
- return this.on( type, fn );
- };
-} );
-
-
-
-
-jQuery.expr.pseudos.animated = function( elem ) {
- return jQuery.grep( jQuery.timers, function( fn ) {
- return elem === fn.elem;
- } ).length;
-};
-
-
-
-
-/**
- * Gets a window from an element
- */
-function getWindow( elem ) {
- return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
-}
-
-jQuery.offset = {
- setOffset: function( elem, options, i ) {
- var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
- position = jQuery.css( elem, "position" ),
- curElem = jQuery( elem ),
- props = {};
-
- // Set position first, in-case top/left are set even on static elem
- if ( position === "static" ) {
- elem.style.position = "relative";
- }
-
- curOffset = curElem.offset();
- curCSSTop = jQuery.css( elem, "top" );
- curCSSLeft = jQuery.css( elem, "left" );
- calculatePosition = ( position === "absolute" || position === "fixed" ) &&
- ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
-
- // Need to be able to calculate position if either
- // top or left is auto and position is either absolute or fixed
- if ( calculatePosition ) {
- curPosition = curElem.position();
- curTop = curPosition.top;
- curLeft = curPosition.left;
-
- } else {
- curTop = parseFloat( curCSSTop ) || 0;
- curLeft = parseFloat( curCSSLeft ) || 0;
- }
-
- if ( jQuery.isFunction( options ) ) {
-
- // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
- options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
- }
-
- if ( options.top != null ) {
- props.top = ( options.top - curOffset.top ) + curTop;
- }
- if ( options.left != null ) {
- props.left = ( options.left - curOffset.left ) + curLeft;
- }
-
- if ( "using" in options ) {
- options.using.call( elem, props );
-
- } else {
- curElem.css( props );
- }
- }
-};
-
-jQuery.fn.extend( {
- offset: function( options ) {
-
- // Preserve chaining for setter
- if ( arguments.length ) {
- return options === undefined ?
- this :
- this.each( function( i ) {
- jQuery.offset.setOffset( this, options, i );
- } );
- }
-
- var docElem, win, rect, doc,
- elem = this[ 0 ];
-
- if ( !elem ) {
- return;
- }
-
- // Support: IE <=11 only
- // Running getBoundingClientRect on a
- // disconnected node in IE throws an error
- if ( !elem.getClientRects().length ) {
- return { top: 0, left: 0 };
- }
-
- rect = elem.getBoundingClientRect();
-
- // Make sure element is not hidden (display: none)
- if ( rect.width || rect.height ) {
- doc = elem.ownerDocument;
- win = getWindow( doc );
- docElem = doc.documentElement;
-
- return {
- top: rect.top + win.pageYOffset - docElem.clientTop,
- left: rect.left + win.pageXOffset - docElem.clientLeft
- };
- }
-
- // Return zeros for disconnected and hidden elements (gh-2310)
- return rect;
- },
-
- position: function() {
- if ( !this[ 0 ] ) {
- return;
- }
-
- var offsetParent, offset,
- elem = this[ 0 ],
- parentOffset = { top: 0, left: 0 };
-
- // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
- // because it is its only offset parent
- if ( jQuery.css( elem, "position" ) === "fixed" ) {
-
- // Assume getBoundingClientRect is there when computed position is fixed
- offset = elem.getBoundingClientRect();
-
- } else {
-
- // Get *real* offsetParent
- offsetParent = this.offsetParent();
-
- // Get correct offsets
- offset = this.offset();
- if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
- parentOffset = offsetParent.offset();
- }
-
- // Add offsetParent borders
- parentOffset = {
- top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
- left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
- };
- }
-
- // Subtract parent offsets and element margins
- return {
- top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
- left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
- };
- },
-
- // This method will return documentElement in the following cases:
- // 1) For the element inside the iframe without offsetParent, this method will return
- // documentElement of the parent window
- // 2) For the hidden or detached element
- // 3) For body or html element, i.e. in case of the html node - it will return itself
- //
- // but those exceptions were never presented as a real life use-cases
- // and might be considered as more preferable results.
- //
- // This logic, however, is not guaranteed and can change at any point in the future
- offsetParent: function() {
- return this.map( function() {
- var offsetParent = this.offsetParent;
-
- while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
- offsetParent = offsetParent.offsetParent;
- }
-
- return offsetParent || documentElement;
- } );
- }
-} );
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
- var top = "pageYOffset" === prop;
-
- jQuery.fn[ method ] = function( val ) {
- return access( this, function( elem, method, val ) {
- var win = getWindow( elem );
-
- if ( val === undefined ) {
- return win ? win[ prop ] : elem[ method ];
- }
-
- if ( win ) {
- win.scrollTo(
- !top ? val : win.pageXOffset,
- top ? val : win.pageYOffset
- );
-
- } else {
- elem[ method ] = val;
- }
- }, method, val, arguments.length );
- };
-} );
-
-// Support: Safari <=7 - 9.1, Chrome <=37 - 49
-// Add the top/left cssHooks using jQuery.fn.position
-// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
-// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
-// getComputedStyle returns percent when specified for top/left/bottom/right;
-// rather than make the css module depend on the offset module, just check for it here
-jQuery.each( [ "top", "left" ], function( i, prop ) {
- jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
- function( elem, computed ) {
- if ( computed ) {
- computed = curCSS( elem, prop );
-
- // If curCSS returns percentage, fallback to offset
- return rnumnonpx.test( computed ) ?
- jQuery( elem ).position()[ prop ] + "px" :
- computed;
- }
- }
- );
-} );
-
-
-// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
-jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
- jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
- function( defaultExtra, funcName ) {
-
- // Margin is only for outerHeight, outerWidth
- jQuery.fn[ funcName ] = function( margin, value ) {
- var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
- extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
-
- return access( this, function( elem, type, value ) {
- var doc;
-
- if ( jQuery.isWindow( elem ) ) {
-
- // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
- return funcName.indexOf( "outer" ) === 0 ?
- elem[ "inner" + name ] :
- elem.document.documentElement[ "client" + name ];
- }
-
- // Get document width or height
- if ( elem.nodeType === 9 ) {
- doc = elem.documentElement;
-
- // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
- // whichever is greatest
- return Math.max(
- elem.body[ "scroll" + name ], doc[ "scroll" + name ],
- elem.body[ "offset" + name ], doc[ "offset" + name ],
- doc[ "client" + name ]
- );
- }
-
- return value === undefined ?
-
- // Get width or height on the element, requesting but not forcing parseFloat
- jQuery.css( elem, type, extra ) :
-
- // Set width or height on the element
- jQuery.style( elem, type, value, extra );
- }, type, chainable ? margin : undefined, chainable );
- };
- } );
-} );
-
-
-jQuery.fn.extend( {
-
- bind: function( types, data, fn ) {
- return this.on( types, null, data, fn );
- },
- unbind: function( types, fn ) {
- return this.off( types, null, fn );
- },
-
- delegate: function( selector, types, data, fn ) {
- return this.on( types, selector, data, fn );
- },
- undelegate: function( selector, types, fn ) {
-
- // ( namespace ) or ( selector, types [, fn] )
- return arguments.length === 1 ?
- this.off( selector, "**" ) :
- this.off( types, selector || "**", fn );
- }
-} );
-
-jQuery.parseJSON = JSON.parse;
-
-
-
-
-// Register as a named AMD module, since jQuery can be concatenated with other
-// files that may use define, but not via a proper concatenation script that
-// understands anonymous AMD modules. A named AMD is safest and most robust
-// way to register. Lowercase jquery is used because AMD module names are
-// derived from file names, and jQuery is normally delivered in a lowercase
-// file name. Do this after creating the global so that if an AMD module wants
-// to call noConflict to hide this version of jQuery, it will work.
-
-// Note that for maximum portability, libraries that are not jQuery should
-// declare themselves as anonymous modules, and avoid setting a global if an
-// AMD loader is present. jQuery is a special case. For more information, see
-// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
-
-if ( typeof define === "function" && define.amd ) {
- define( "jquery", [], function() {
- return jQuery;
- } );
-}
-
-
-
-
-
-var
-
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
-
- // Map over the $ in case of overwrite
- _$ = window.$;
-
-jQuery.noConflict = function( deep ) {
- if ( window.$ === jQuery ) {
- window.$ = _$;
- }
-
- if ( deep && window.jQuery === jQuery ) {
- window.jQuery = _jQuery;
- }
-
- return jQuery;
-};
-
-// Expose jQuery and $ identifiers, even in AMD
-// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
-// and CommonJS for browser emulators (#13566)
-if ( !noGlobal ) {
- window.jQuery = window.$ = jQuery;
-}
-
-
-return jQuery;
-} ) );
diff --git a/libs/music/player.d/jquery-3.0.0.min.js b/libs/music/player.d/jquery-3.0.0.min.js
deleted file mode 100644
index 62d410d..0000000
--- a/libs/music/player.d/jquery-3.0.0.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v3.0.0 | (c) jQuery Foundation | jquery.org/license */
-!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.0.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return a&&"[object Object]"===k.call(a)?(b=e(a))?(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n):!0:!1},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;d>f;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;return"string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a)?(d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e):void 0},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"===c||r.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\x00-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\x00"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[0>c?c+b:c]}),even:pa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e)}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,e>i&&ya(a.slice(i,e)),f>e&&ya(a=a.slice(e)),f>e&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;d>b;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;d>b;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(f>b)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(1>=b&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){
-return j.call(r(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:X.test(c)?JSON.parse(c):c}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),Z(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=Z(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=V.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var $=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,_=new RegExp("^(?:([+-])=|)("+$+")([a-z%]*)$","i"),aa=["Top","Right","Bottom","Left"],ba=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ca=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function da(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&_.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ea={};function fa(a){var b,c=a.ownerDocument,d=a.nodeName,e=ea[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ea[d]=e,e)}function ga(a,b){for(var c,d,e=[],f=0,g=a.length;g>f;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ba(d)&&(e[f]=fa(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;g>f;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ga(this,!0)},hide:function(){return ga(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ba(this)?r(this).show():r(this).hide()})}});var ha=/^(?:checkbox|radio)$/i,ia=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;d>c;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var na=/<|&#?\w+;/;function oa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;o>n;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(na.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ia.exec(f)||["",""])[1].toLowerCase(),i=ka[h]||ka._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?r(e,this).index(i)>-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){return this.originalEvent?b(this.originalEvent):void 0}:function(){return this.originalEvent?this.originalEvent[a]:void 0},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==va()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===va()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&r.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return r.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ta:ua,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:ua,isPropagationStopped:ua,isImmediatePropagationStopped:ua,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ta,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ta,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ta,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&qa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ra.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return wa(this,a,b,c,d)},one:function(a,b,c,d){return wa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ua),this.each(function(){r.event.remove(this,a,c,b)})}});var xa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/<script|<style|<link/i,za=/checked\s*(?:[^=]|=\s*.checked.)/i,Aa=/^true\/(.*)/,Ba=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ga(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ha.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ha(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;m>l;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,la(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ea),l=0;i>l;l++)j=h[l],ja.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ba,""),k))}return a}function Ia(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(la(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&ma(la(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(xa,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;e>d;d++)Ga(f[d],g[d]);if(b)if(c)for(f=f||la(a),g=g||la(h),d=0,e=f.length;e>d;d++)Fa(f[d],g[d]);else Fa(a,h);return g=la(h,"script"),g.length>0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(la(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(la(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;f>=g;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ja=/^margin/,Ka=new RegExp("^("+$+")(?!px)[a-z%]+$","i"),La=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",pa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,pa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Ma(a,b,c){var d,e,f,g,h=a.style;return c=c||La(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ka.test(g)&&Ja.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Na(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Oa=/^(none|table(?!-c[ea]).+)/,Pa={position:"absolute",visibility:"hidden",display:"block"},Qa={letterSpacing:"0",fontWeight:"400"},Ra=["Webkit","Moz","ms"],Sa=d.createElement("div").style;function Ta(a){if(a in Sa)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ra.length;while(c--)if(a=Ra[c]+b,a in Sa)return a}function Ua(a,b,c){var d=_.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Va(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=r.css(a,c+aa[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+aa[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+aa[f]+"Width",!0,e))):(g+=r.css(a,"padding"+aa[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+aa[f]+"Width",!0,e)));return g}function Wa(a,b,c){var d,e=!0,f=La(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),0>=d||null==d){if(d=Ma(a,b,f),(0>d||null==d)&&(d=a.style[b]),Ka.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Va(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ma(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=_.exec(c))&&e[1]&&(c=da(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Ma(a,b,d)),"normal"===e&&b in Qa&&(e=Qa[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){return c?!Oa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Wa(a,b,d):ca(a,Pa,function(){return Wa(a,b,d)}):void 0},set:function(a,c,d){var e,f=d&&La(a),g=d&&Va(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=_.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ua(a,c,g)}}}),r.cssHooks.marginLeft=Na(o.reliableMarginLeft,function(a,b){return b?(parseFloat(Ma(a,"marginLeft"))||a.getBoundingClientRect().left-ca(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+aa[d]+b]=f[d]||f[d-2]||f[0];return e}},Ja.test(a)||(r.cssHooks[a+b].set=Ua)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=La(a),e=b.length;e>g;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function eb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ba(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],$a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ga([a],!0),j=a.style.display||j,k=r.css(a,"display"),ga([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ga([a],!0),m.done(function(){p||ga([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=db(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function fb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function gb(a,b,c){var d,e,f=0,g=gb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Ya||bb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Ya||bb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(fb(k,j.opts.specialEasing);g>f;f++)if(d=gb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,db,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(gb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return da(c.elem,a,_.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;e>d;d++)c=a[d],gb.tweeners[c]=gb.tweeners[c]||[],gb.tweeners[c].unshift(b)},prefilters:[eb],prefilter:function(a,b){b?gb.prefilters.unshift(a):gb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:e.duration="number"==typeof e.duration?e.duration:e.duration in r.fx.speeds?r.fx.speeds[e.duration]:r.fx.speeds._default,null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ba).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=gb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&_a.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(cb(b,!0),a,d,e)}}),r.each({slideDown:cb("show"),slideUp:cb("hide"),slideToggle:cb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Ya=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),Ya=void 0},r.fx.timer=function(a){r.timers.push(a),a()?r.fx.start():r.timers.pop()},r.fx.interval=13,r.fx.start=function(){Za||(Za=a.requestAnimationFrame?a.requestAnimationFrame(ab):a.setInterval(r.fx.tick,r.fx.interval))},r.fx.stop=function(){a.cancelAnimationFrame?a.cancelAnimationFrame(Za):a.clearInterval(Za),Za=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var hb,ib=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return S(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c);
-}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){return r.isArray(b)?a.checked=r.inArray(r(a).val(),b)>-1:void 0}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?r.event.trigger(a,b,c,!0):void 0}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",0>b&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;return o.cors||Pb&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Qb=[],Rb=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Qb.pop()||r.expando+"_"+rb++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Rb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Rb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Rb,"$1"+e):b.jsonp!==!1&&(b.url+=(sb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Qb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=B.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=oa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=r.trim(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length};function Sb(a){return r.isWindow(a)?a:9===a.nodeType&&a.defaultView}r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),d.width||d.height?(e=f.ownerDocument,c=Sb(e),b=e.documentElement,{top:d.top+c.pageYOffset-b.clientTop,left:d.left+c.pageXOffset-b.clientLeft}):d):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),r.nodeName(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||pa})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return S(this,function(a,d,e){var f=Sb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Na(o.pixelPosition,function(a,c){return c?(c=Ma(a,b),Ka.test(c)?r(a).position()[b]+"px":c):void 0})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return S(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.parseJSON=JSON.parse,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Tb=a.jQuery,Ub=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Ub),b&&a.jQuery===r&&(a.jQuery=Tb),r},b||(a.jQuery=a.$=r),r});
diff --git a/libs/music/player.d/main.js b/libs/music/player.d/main.js
deleted file mode 100644
index 4795e5f..0000000
--- a/libs/music/player.d/main.js
+++ /dev/null
@@ -1,610 +0,0 @@
-var audio;
-var playlist;
-var tracks;
-var current;
-var mbuttonstate=0;
-var plistshown=true;
-var shuffle=0,repeat=0;
-var plistRect;
-var dpiratio=window.devicePixelRatio?window.devicePixelRatio:1;
-
-var audioCtxt=null;
-var CtxtSource=null;
-var CtxtAnalyser=null;
-var canvas;
-var CSpectrum=1024,CSpectrumIF=128;
-var SpecWidth=0.7,SpecGap=0.08125;
-var caps=[];
-var visualselector=null;
-var SpecRingRadius=225;
-var spectrogrampos=0;
-var inkimg=[];
-var f1=0,f2=0,penv=0,btrig=0,beatp=0,lastbp=0;
-var lpbd=300,lpf=1./(2*Math.PI*lpbd),beatr=0.02;
-var frms=0,lastfpsupd=null,fps=0;
-var ic1=["#FF3333","#FF8800","#FFFF00","#CCFF00","#33CCFF","#0000FF","#9966FF"];
-var ic2=["rgba(204,51,51,0.6)","rgba(187,85,0,0.6)","rgba(255,204,0,0.6)","rgba(153,204,0,0.6)","rgba(51,153,255,0.6)","rgba(0,0,102,0.6)","rgba(153,51,204,0.6)"]
-var Ink=function(_vx,_vy,_c)
-{
- this.x=canvas.width/2;this.y=canvas.height/2;
- this.vx=_vx;this.vy=_vy;
- this.color=_c>6?6:_c;this.active=true;
-};
-Ink.prototype.update=function()
-{
- this.x+=this.vx;this.y+=this.vy;
- this.vx*=0.995;this.vy*=0.995;
- if(this.x<-10||this.x>canvas.width+10||this.y<-10||this.y>canvas.height+10)
- this.active=false;
-}
-Ink.prototype.draw=function(cctx)
-{
- cctx.drawImage(inkimg[this.color],this.x+5*window.devicePixelRatio,this.y+5*window.devicePixelRatio);
-}
-var inks=[];
-function inkPrepare()
-{
- for(var i=0;i<7;++i)
- {
- inkimg[i]=document.createElement('canvas');
- inkimg[i].width=inkimg[i].height=10*window.devicePixelRatio;
- var cctx=inkimg[i].getContext('2d');
- cctx.fillStyle=ic1[i];
- cctx.beginPath();
- cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,3*window.devicePixelRatio,0,2*Math.PI);
- cctx.fill();
- cctx.fillStyle=ic2[i];
- cctx.beginPath();
- cctx.arc(5*window.devicePixelRatio,5*window.devicePixelRatio,5*window.devicePixelRatio,0,2*Math.PI);
- cctx.fill();
- }
-}
-function createInk(_vx,_vy,_c1,_c2)
-{
- var f=false;
- for(var i=0;i<inks.length;++i)
- {
- if(!inks[i].active)
- {inks[i]=new Ink(_vx,_vy,_c1,_c2);f=true;break;}
- }
- if(!f&&inks.length<512)inks.push(new Ink(_vx,_vy,_c1,_c2));
-}
-
-function gup(name,url)
-{
- if(!url)url=location.href;
- name=name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
- var regexS="[\\?&]"+name+"=([^&#]*)";
- var regex=new RegExp(regexS);
- var results=regex.exec(url);
- return results==null?null:results[1];
-}
-function getcookie(key)
-{return document.cookie.replace(new RegExp("(?:(?:^|.*;\\s*)"+key+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1");}
-
-function initAPI()
-{
- window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext||window.msAudioContext;
- window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame;
- window.cancelAnimationFrame=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame;
- audioCtxt=new AudioContext;
- CtxtSource=audioCtxt.createBufferSource();
- CtxtAnalyser=audioCtxt.createAnalyser();
- CtxtAnalyser.fftSize=2*CSpectrum;
- for(var i=0;i<CSpectrum;++i)caps[i]=0;
-}
-
-function init()
-{
- if( navigator.userAgent.match(/Android/i)
- || navigator.userAgent.match(/webOS/i)
- || navigator.userAgent.match(/iPhone/i)
- || navigator.userAgent.match(/iPad/i)
- || navigator.userAgent.match(/iPod/i)
- || navigator.userAgent.match(/BlackBerry/i)
- || navigator.userAgent.match(/Windows Phone/i)
- )
- {
- visualselector=document.getElementById("playlist").style.width="90%";
- document.getElementById("help").style.maxWidth=window.innerWidth+"px";
- if(window.innerWidth<window.innerHeight)
- document.getElementById("cvs").width=screen.width*0.98,
- document.getElementById("cvs").height=(screen.width*0.98/16*9);
- else
- document.getElementById("cvs").width=(screen.height*0.98/9*16),
- document.getElementById("cvs").height=screen.height*0.98;
- }
- if(!window.devicePixelRatio)window.devicePixelRatio=1;
- document.getElementById("cvs").style.width=document.getElementById("cvs").width+"px";
- document.getElementById("cvs").style.height=document.getElementById("cvs").height+"px";
- document.getElementById("cvs").width=document.getElementById("cvs").width*window.devicePixelRatio;
- document.getElementById("cvs").height=document.getElementById("cvs").height*window.devicePixelRatio;
- current=0;
- visualselector=document.getElementById("visualizationsel");
- canvas=document.getElementById("cvs");
- audio=document.getElementById("audio");
- playlist=$('#playlist');
- tracks=playlist.find('li a');
- len=tracks.length;SpecRingRadius=canvas.width/2;
- audio.volume=.80;SpecWidth=canvas.width/CSpectrum;SpecGap=SpecWidth/10;SpecWidth*=0.9;
- initAPI();inkPrepare();document.onmousemove=mm;
- CtxtSource=audioCtxt.createMediaElementSource(audio);
- CtxtSource.connect(CtxtAnalyser);
- CtxtAnalyser.connect(audioCtxt.destination);
- plistRect=document.getElementById("playlist").getBoundingClientRect();
- for(var i=0;i<playlist.find('a').length;++i)
- {
- if(playlist.find('a')[i].textContent==decodeURIComponent(gup('title')))
- {current=i;run($(playlist.find('a')[i]));break;}
- }
- playlist.find('a').click(function(e){
- e.preventDefault();
- link=$(this);
- current=link.parent().index()-1;
- run(link);
- });
- visualselector.onchange=function(){
- if(this.value!="none"&&this.oldvalue=="none")requestAnimationFrame(updateVisualization);
- else canvas.getContext('2d').clearRect(0,0,canvas.width,canvas.height);
- document.cookie="playervisualization="+this.value;
- this.oldvalue=this.value;
- };
- window.onresize=windowresize;
- audio.ontimeupdate=timeUpdate;
- audio.addEventListener('ended',function(e){
- if(repeat==0)
- {
- current++;
- if(current==len){
- current=0;
- if(shuffle)shufflePlist();
- link=playlist.find('a')[0];
- }else{
- link=playlist.find('a')[current];
- }
- run($(link));
- }
- });
- document.getElementById("shufflesw").onclick=function(){
- shuffle=1-shuffle;
- if(shuffle==0)
- {
- document.getElementById("shufflesw").innerHTML="Off";
- document.cookie="playershuffle=0";
- sortPlist();
- }
- else
- {
- document.getElementById("shufflesw").innerHTML="On";
- document.cookie="playershuffle=1";
- shufflePlist();
- }
- }
- document.getElementById("repeatsw").onclick=function(){
- repeat=1-repeat;
- if(repeat==0)
- {
- document.getElementById("repeatsw").innerHTML="Off";
- document.cookie="playerrepeat=0";
- audio.loop=false;
- }
- else
- {
- document.getElementById("repeatsw").innerHTML="On";
- document.cookie="playerrepeat=1";
- audio.loop=true;
- }
- }
- document.getElementById("plistsw").onclick=togglePlist;
- document.body.onmousedown=function(e){if(e.buttons==1)mbuttonstate=1;}
- document.body.onmouseup=function(e){if(e.buttons!=1)mbuttonstate=0;}
- document.getElementById("tsliderbase").onclick=function(e)
- {
- var sr=this.getBoundingClientRect();
- var p=(e.clientX-sr.left)/sr.width;
- audio.currentTime=audio.duration*p;
- }
- document.getElementById("tsliderbase").onmousemove=function(e)
- {
- if(!mbuttonstate)return;
- var sr=this.getBoundingClientRect();
- var p=(e.clientX-sr.left)/sr.width;
- audio.currentTime=audio.duration*p;
- }
- document.getElementById("pbplaypause").onclick=function()
- {
- if(audio.src==""){run($(playlist.find('a')[0]));return;}
- if(audio.paused)
- {
- audio.play();
- document.getElementById("imgplaypause").src="pause.svg";
- }
- else
- {
- audio.pause();
- document.getElementById("imgplaypause").src="play.svg";
- }
- }
- document.getElementById("pbprev").onclick=function()
- {
- if(audio.currentTime>10)audio.currentTime=0;
- else
- {
- current--;
- if(current<0){
- current+=len;
- if(shuffle)shufflePlist();
- link=playlist.find('a')[len-1];
- }else{
- link=playlist.find('a')[current];
- }
- run($(link));
- }
- }
- document.getElementById("pbnext").onclick=function()
- {
- current++;
- if(current==len){
- current=0;
- if(shuffle)shufflePlist();
- link=playlist.find('a')[0];
- }else{
- link=playlist.find('a')[current];
- }
- run($(link));
- }
- switch(getcookie("playershuffle"))
- {
- case "1":
- document.getElementById("shufflesw").innerHTML="On";
- document.cookie="playershuffle=1";
- shufflePlist();
- break;
- default:
- case "0":
- document.getElementById("shufflesw").innerHTML="Off";
- document.cookie="playershuffle=0";
- sortPlist();
- break;
- }
- switch(getcookie("playerrepeat"))
- {
- case "1":
- document.getElementById("repeatsw").innerHTML="On";
- document.cookie="playerrepeat=1";
- audio.loop=true;
- break;
- default:
- case "0":
- document.getElementById("repeatsw").innerHTML="Off";
- document.cookie="playerrepeat=0";
- audio.loop=false;
- break;
- }
- if(getcookie("playervisualization").length!==0)
- visualselector.value=getcookie("playervisualization");
- requestAnimationFrame(updateVisualization);
-}
-function shufflePlist()
-{
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).attr("sord",Math.random()*playlist.find('a').length);
- var plli=$(playlist).children('li');
- plli.sort(
- function(a,b)
- {
- var as=Number($(a).children('a').attr("sord"));
- var bs=Number($(b).children('a').attr("sord"));
- return as>bs?1:as<bs?-1:0;
- }
- );
- plli.detach().appendTo($(playlist));
- var t=$("li.active").children().length?$("li.active").children()[0].textContent:"";
- for(var i=0;i<playlist.find('a').length;++i)
- {
- if(playlist.find('a')[i].textContent==t)
- {current=i;break;}
- }
-}
-function sortPlist()
-{
- var plli=$(playlist).children('li');
- plli.sort(
- function(a,b)
- {
- var as=Number($(a).children('a').attr("ord"));
- var bs=Number($(b).children('a').attr("ord"));
- return as>bs?1:as<bs?-1:0;
- }
- );
- plli.detach().appendTo($(playlist));
- var t=$("li.active").children().length?$("li.active").children()[0].textContent:"";
- for(var i=0;i<playlist.find('a').length;++i)
- {
- if(playlist.find('a')[i].textContent==t)
- {current=i;break;}
- }
-}
-function formatTime(t)
-{
- var m=Math.floor(t/60),s=Math.round(t-Math.floor(t/60)*60);
- if(s<10)return m+":0"+s;
- else if(s==60)return (m+1)+":00";
- else return m+":"+s;
-}
-function bufferedUpdate()
-{
- var r=0;
- for(var i=0;i<audio.buffered.length;++i)
- r=r<audio.buffered.end(i)?audio.buffered.end(i):r;
- document.getElementById("cbuff").style.width=r/audio.duration*100+"%";
-}
-function timeUpdate()
-{
- document.getElementById("timenow").innerHTML=formatTime(audio.currentTime);
- document.getElementById("timeleft").innerHTML="-"+formatTime(audio.duration-audio.currentTime);
- document.getElementById("ctime").style.width=audio.currentTime/audio.duration*100+"%";
- bufferedUpdate();
-}
-function mm(e)
-{
- /*if(e.clientX<320&&e.clientY>(window.innerHeight-383))
- {
- changeImage('../../../koishi_hovr.png');
- document.getElementById("aqt").style.opacity="0.5";
- }
- else
- {
- changeImage('../../../koishi_norm.png');
- document.getElementById("aqt").style.opacity="1.0";
- }*/
-}
-function windowresize()
-{
- if(plistshown)
- {
- document.getElementById("playlist").style.left=(window.innerWidth-plistRect.width)/2+"px";
- plistRect=document.getElementById("playlist").getBoundingClientRect();
- }
- else
- {
- }
-}
-function run(link)
-{
- var trurl="";
- if(window.location.href.indexOf("&title=")==-1)
- trurl=window.location.href;
- else
- trurl=window.location.href.substr(0,window.location.href.indexOf("&title="));
- trurl=trurl.concat("&title=");
- trurl=trurl.concat(link.attr('tr'));
- window.history.replaceState("","The Stupid Online Player",trurl);
- document.getElementById("imgplaypause").src="pause.svg";
- audio.src=link.attr('href');
- document.getElementById("nowplaying").innerHTML="Now Playing: "+link.attr('tr');
- par=link.parent();
- par.addClass('active').siblings().removeClass('active');
- audio.load();
- audio.play();
-}
-
-function togglePlist()
-{
- document.getElementById("plistsw").onclick=function(){};
- plistshown=!plistshown;
- if(plistshown)
- {
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).css("transition","0.8s");
- document.getElementById("plistsw").innerHTML="[↓Hide Playlist]";
- setTimeout(
- function(){
- document.getElementById("playlist").style.left=(window.innerWidth-plistRect.width)/2+"px";
- document.getElementById("playlist").style.top=document.getElementById("plistref").getBoundingClientRect().top+"px";
- document.getElementById("playlist").style.background="rgba(153,187,238,0.6)";
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).css("color","");
- }
- ,40);
- setTimeout(
- function(){
- document.getElementById("playlist").style.position="static";
- document.getElementById("plistsw").onclick=togglePlist;
- plistRect=document.getElementById("playlist").getBoundingClientRect();
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).css("transition","none");
- }
- ,840);
- }
- else
- {
- var d=$(document).scrollTop();
- $('html,body').stop().animate({scrollTop:0},d);
- setTimeout(
- function(){
- plistRect=document.getElementById("playlist").getBoundingClientRect();
- document.getElementById("playlist").style.position="fixed";
- document.getElementById("playlist").style.top=plistRect.top+"px";
- document.getElementById("playlist").style.left=plistRect.left+"px";
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).css("transition","0.8s");
- },
- d+1);
- setTimeout(
- function(){
- document.getElementById("playlist").style.top="100%";
- document.getElementById("playlist").style.background="rgba(153,187,238,0)";
- document.getElementById("plistsw").onclick=togglePlist;
- for(var i=0;i<playlist.find('a').length;++i)
- $(playlist.find('a')[i]).css("color",$(playlist.find('a')[i]).hasClass("active")?"rgba(255,204,0,0);":"rgba(32,172,255,0)");
- },
- d+5);
- document.getElementById("plistsw").innerHTML="[↑Show Playlist]";
- }
-}
-
-function updateVisualization()
-{
- if(visualselector.value=="spectrum")
- {
- var cctx=canvas.getContext('2d');
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getByteFrequencyData(freqarr);
- for(var i=0;i<CSpectrum;++i)
- {
- var color='hsl('+i*360.0/CSpectrum+',100%,50%)';
- cctx.fillStyle=color;
- cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-(canvas.height*freqarr[i]/255.),SpecWidth,canvas.height*freqarr[i]/255.);
- if(caps[i]<freqarr[i])caps[i]=freqarr[i];else if(caps[i]>0)--caps[i];
- color='hsl('+i*360.0/CSpectrum+',100%,25%)';
- cctx.fillStyle=color;
- cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-(canvas.height*caps[i]/255.)-1,SpecWidth,1);
- }
- }catch(e){
- if(caps[i]>0)--caps[i];
- color='hsl('+i*360.0/CSpectrum+',100%,25%)';
- cctx.fillStyle=color;
- cctx.fillRect(i*(SpecWidth+SpecGap),canvas.height-caps[i]-1,SpecWidth,1);
- };
- }
- if(visualselector.value=="spectrumring")
- {
- var cctx=canvas.getContext('2d');
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getByteFrequencyData(freqarr);
- for(var i=0;i<CSpectrum;++i)
- {
- var color='hsl('+i*360.0/CSpectrum+',100%,50%)';
- cctx.strokeStyle=color;
- cctx.beginPath();cctx.moveTo(canvas.width/2.,canvas.height/2.);
- cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*freqarr[i]/255.,
- canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*freqarr[i]/255.);
- cctx.stroke();
- if(caps[i]<freqarr[i])caps[i]=freqarr[i];else if(caps[i]>0)--caps[i];
- color='hsl('+i*360.0/CSpectrum+',100%,25%)';
- cctx.strokeStyle=color;
- cctx.beginPath();
- cctx.moveTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.,
- canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.);
- cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.,
- canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.);
- cctx.stroke();
- }
- }catch(e){
- if(caps[i]>0)--caps[i];
- color='hsl('+i*360.0/CSpectrum+',100%,25%)';
- cctx.strokeStyle=color;
- cctx.moveTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.,
- canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*(caps[i]+1)/255.);
- cctx.lineTo(canvas.width/2.-Math.cos(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.,
- canvas.height/2.-Math.sin(2*Math.PI*(i/CSpectrum))*SpecRingRadius*caps[i]/255.);
- cctx.stroke();
- };
- }
- if(visualselector.value=="scope")
- {
- var cctx=canvas.getContext('2d');
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- var tdomainarr=new Uint8Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getByteTimeDomainData(tdomainarr);
- cctx.lineWidth=dpiratio;
- cctx.strokeStyle="#000";
- cctx.beginPath();
- var x=0;
- for(var i=0;i<CSpectrum;++i)
- {
- if(i==0)cctx.moveTo(x,tdomainarr[i]/128.*canvas.height/2);
- else cctx.lineTo(x,tdomainarr[i]/128.*canvas.height/2);
- x+=canvas.width*1./CSpectrum;
- }
- cctx.stroke();
- }catch(e){
- console.log(e.message);
- };
- }
- if(visualselector.value=="spectrogram")
- {
- var cctx=canvas.getContext('2d');
- try{
- var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getByteFrequencyData(freqarr);
- cctx.clearRect(spectrogrampos/1800*canvas.width,0,canvas.width/1800,canvas.height);
- for(var i=0;i<CSpectrum;++i)
- {
- var color='rgba(0,0,0,'+freqarr[i]/256.+')';
- cctx.fillStyle=color;
- cctx.fillRect(spectrogrampos/1800*canvas.width,(CSpectrum-i)/CSpectrum*canvas.height,canvas.width/1800.,canvas.height/CSpectrum);
- }
- ++spectrogrampos;if(spectrogrampos>=1800)spectrogrampos=0;
- }catch(e){
- };
- }
- if(visualselector.value=="inkfountain")
- {
- var cctx=canvas.getContext('2d'),ts=Date.now(),tu;
- cctx.clearRect(0,0,canvas.width,canvas.height);
- ++frms;if(Date.now()-lastfpsupd>500){if(lastfpsupd)fps=1000*frms/(Date.now()-lastfpsupd),frms=0;lastfpsupd=Date.now();}
- try{
- var freqarr=new Uint8Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getByteFrequencyData(freqarr);
- for(var i=0;i<CSpectrumIF;++i)
- {
- var r=0;
- for(var j=0;j<8;++j)r+=freqarr[i*8+j];
- r/=8.;
- if(r-caps[i]>7)
- {
- var color=Math.floor(i*8.0/CSpectrumIF),rad=Math.random()*Math.PI*2;
- var ndrops=(128-i)/128.*3+1;ndrops*=(r/128.);ndrops=Math.floor(ndrops);if(ndrops<1)ndrops=1;
- for(var k=0;k<ndrops;++k)
- {
- createInk(((r-caps[i]-7)/32*24+12)*Math.cos(rad),((r-caps[i]-7)/32*24+12)*Math.sin(rad),color);
- rad=Math.random()*Math.PI*2;
- }
- }
- if(r>caps[i])caps[i]=r;else caps[i]-=2;
- }
- }catch(e){
- console.log(e.message);
- };
- tu=Date.now();
- var aa=0;
- for(var i=0;i<inks.length;++i){
- if(inks[i].active){inks[i].update();inks[i].draw(cctx);++aa}
- }
- cctx.fillStyle="#000";
- cctx.font="1em Courier, monospace";
- cctx.fillText("Active droplets "+aa+", "+fps.toFixed(2)+" FPS",0,10);
- cctx.fillText("Update time "+(tu-ts)+"ms, render time "+(Date.now()-tu)+"ms",0,24);
- }
- if(visualselector.value=="shakeurbody")
- {
- var cctx=canvas.getContext('2d');
- cctx.clearRect(0,0,canvas.width,canvas.height);
- try{
- var tdomainarr=new Float32Array(CtxtAnalyser.frequencyBinCount);
- CtxtAnalyser.getFloatTimeDomainData(tdomainarr);
- for(var i=0;i<CSpectrum;++i)
- {
- var kbf=1/(audioCtxt.sampleRate*lpf),br=Math.exp(-1/(audioCtxt.sampleRate*beatr));
- f1+=(kbf*(tdomainarr[i]-f1));
- f2+=(kbf*(f1-f2));
- var env=Math.abs(f2);
- if(env>penv)penv=env;else{penv*=br;penv+=(1-br)*env;}
- if(!btrig){if(penv>0.20)btrig=1;}else{if(penv<0.125)btrig=0;}
- beatp=0;if(btrig&&!lastbp)beatp=1;lastbp=beatp;
- if(beatp)document.body.style.transform='translateY(100px)';else document.body.style.transform='translateY(0px)';
- }
- }catch(e){
- document.body.style.transform='translateY(0px)';
- };
- }else document.body.style.transform='none';
- if(visualselector.value!="none")
- af=requestAnimationFrame(updateVisualization);
-}
diff --git a/libs/music/player.d/main_static.js b/libs/music/player.d/main_static.js
index 1a48297..7070e1d 100644
--- a/libs/music/player.d/main_static.js
+++ b/libs/music/player.d/main_static.js
@@ -15,8 +15,8 @@ const sh={
{return document.createElement(e);},
getcookie:function(key)
{return document.cookie.replace(new RegExp('(?:(?:^|.*;\\s*)'+key+'\\s*\\=\\s*([^;]*).*$)|^.*$'),'$1');},
- useFLAC:function()
- {return sh.elem('audio').canPlayType('audio/ogg')=='';}
+ setcookie:function(key,value)
+ {return document.cookie=`${key}=${value};max-age=31536000`;},
};
class Ink
@@ -47,15 +47,23 @@ NSPlayer={
current:null,
shuffle:0,
repeat:0,
+ served_formats:{'ogg':{'mime':'audio/ogg; codecs=vorbis','disp':'ogg 224 kbps'},'flac':{'mime':'audio/flac','disp':'flac'},'opus':{'mime':'audio/ogg; codecs=opus','disp':'opus 96 kbps'},'m4a':{'mime':'audio/aac','disp':'aac 192kbps'}},
+ get_preferred_or_default_format:function()
+ {
+ if (sh.getcookie('preferredformat') in this.served_formats)
+ return sh.getcookie('preferredformat');
+ for (let fmt in this.served_formats)
+ if (sh.elem('audio').canPlayType(this.served_formats[fmt].mime)!='')
+ return fmt;
+ },
load_playlist:async function(pln,ord)
{
let r=null;
- const resp=await fetch(new Request(`/libs/music/player.d/playlists/${pln}.playlist?${new Date().getTime()}`));
- if(!resp.ok)throw "shit";
- r=await resp.text();
+ const resp=await fetch(new Request(`/libs/music/player.d/playlists/${pln}.playlist?${new Date().getTime()}`));
+ if(!resp.ok)throw "shit";
+ r=await resp.text();
let rarr=r.split('\n');
let tarr=[];
- const fmt=sh.useFLAC()?'flac':'ogg';
for(let i=1;i<rarr.length;++i)
{
let t=rarr[i].trim();
@@ -63,7 +71,6 @@ NSPlayer={
let titem={};
titem.title=t;
titem.ord=i-1;
- titem.src=`//filestorage.chrisoft.org/music/${fmt}/${t}.${fmt}`;
tarr.push(titem);
}
return ({plistname:pln,playlist:tarr,plistord:ord});
@@ -76,16 +83,17 @@ NSPlayer={
NSUI.iplaypause.style.backgroundPosition=`${NSUI.bpauserect}`;
this.current=id;
NSUI.lbnowplaying.innerHTML="Now Playing: ";
- const a=sh.newelem("a");
- a.innerHTML=this.tracks[id].title;
- a.href=`javascript:NSUI.showNotes("${this.tracks[id].title}")`;
- NSUI.lbnowplaying.appendChild(a);
+ const a=sh.newelem("a");
+ a.innerHTML=this.tracks[id].title;
+ a.href=`javascript:NSUI.showNotes("${this.tracks[id].title}")`;
+ NSUI.lbnowplaying.appendChild(a);
if(navigator.mediaSession)
navigator.mediaSession.metadata=new MediaMetadata({title:this.tracks[id].title,album:this.plistname});
NSUI.set_highlighted(this.plistname,this.tracks[id].title);
- NSUI.audio.src=this.tracks[id].src;
+ const fmt=NSPlayer.get_preferred_or_default_format();
+ NSUI.audio.src=`//filestorage.chrisoft.org/music/${fmt}/${this.tracks[id].title}.${fmt}`;
NSUI.audio.load();
- NSUI.audio.play();
+ return NSUI.audio.play();
},
next:function()
{
@@ -139,6 +147,7 @@ NSUI={
pbprev:null,
ctrlcontainer:null,
am3u8:null,
+ swformat:null,
bplayrect:"0 -48px",
bpauserect:"-24px -48px",
brallrect:"-24px -24px",
@@ -171,28 +180,44 @@ NSUI={
this.pbprev=sh.elem('pbprev');
this.ctrlcontainer=sh.elem('ctrlcontainer');
this.am3u8=sh.elem('am3u8');
+ this.swformat=sh.elem('formatsw');
+ if(!(sh.getcookie('preferredformat') in NSPlayer.served_formats))
+ sh.setcookie('preferredformat','');
+ const fmt=NSPlayer.get_preferred_or_default_format();
+ const cantplay=(NSUI.audio.canPlayType(NSPlayer.served_formats[fmt].mime)=='')?' !':'';
+ this.swformat.innerHTML=`[${NSPlayer.served_formats[fmt].disp}${cantplay}]`;
NSUI.canvas.width=NSUI.canvas.clientWidth*window.devicePixelRatio;
NSUI.canvas.height=NSUI.canvas.clientHeight*window.devicePixelRatio;
NSUI.vissel.onchange=function(){
if(this.value!='none'&&this.oldvalue=='none')requestAnimationFrame(NSVisualization.updateVisualization);
else NSUI.canvas.getContext('2d').clearRect(0,0,NSUI.canvas.width,NSUI.canvas.height);
- document.cookie='playervisualization='+this.value;
+ sh.setcookie('playervisualization',this.value);
this.oldvalue=this.value;
};
- document.getElementById('shufflesw').onclick=function(){
+ sh.elem('shufflesw').onclick=function(){
NSUI.shuffle_switch(NSPlayer.shuffle=1-NSPlayer.shuffle);
NSUI.ishuffle.style.backgroundPosition=`${NSPlayer.shuffle?NSUI.bshonrect:NSUI.bsoffrect}`;
- document.cookie=`playershuffle=${NSPlayer.shuffle}`;
+ sh.setcookie('playershuffle',NSPlayer.shuffle);
};
- document.getElementById('repeatsw').onclick=function(){
+ sh.elem('repeatsw').onclick=function(){
NSPlayer.repeat=1-NSPlayer.repeat;
NSUI.audio.loop=NSPlayer.repeat?true:false;
NSUI.irepeat.style.backgroundPosition=`${NSPlayer.repeat?NSUI.bronerect:NSUI.brallrect}`;
- document.cookie=`playerrepeat=${NSPlayer.repeat}`;
+ sh.setcookie('playerrepeat',NSPlayer.repeat);
+ };
+ sh.elem('formatsw').onclick=function(){
+ const cfmt=NSPlayer.get_preferred_or_default_format();
+ fmts=Object.keys(NSPlayer.served_formats);
+ const nfmt=fmts[(fmts.indexOf(cfmt)+1)%fmts.length];
+ sh.setcookie('preferredformat',nfmt);
+ const cantplay=(NSUI.audio.canPlayType(NSPlayer.served_formats[nfmt].mime)=='')?' !':'';
+ NSUI.swformat.innerHTML=`[${NSPlayer.served_formats[nfmt].disp}${cantplay}]`;
+ if(NSUI.selectedplist)
+ NSUI.switch_playlist(NSUI.selectedplist);
};
- document.getElementById('plistsw').onclick=NSUI.togglePlist;
- document.getElementById('tsliderbase').onclick=
- document.getElementById('tsliderbase').onmousemove=function(e)
+ sh.elem('plistsw').onclick=NSUI.togglePlist;
+ sh.elem('tsliderbase').onclick=
+ sh.elem('tsliderbase').onmousemove=function(e)
{
if(e.type=='click'||(e.type=='mousemove'&&e.buttons==1))
{
@@ -257,9 +282,9 @@ NSUI={
{
const moi=this;
let r=null;
- const resp=await fetch(new Request(`/libs/music/player.d/playlists/playlists?${new Date().getTime()}`));
- if(!resp.ok)throw "shit";
- r=await resp.text();
+ const resp=await fetch(new Request(`/libs/music/player.d/playlists/playlists?${new Date().getTime()}`));
+ if(!resp.ok)throw "shit";
+ r=await resp.text();
let rarr=r.split('\n');
let tarr=[];
let cnt=0;
@@ -292,10 +317,10 @@ NSUI={
const ta=NSUI.ulplaylists.childNodes[i].firstChild;
if(ta.pid==this.pid)
{
- if(ta.classList.contains('highlighted'))
- NSUI.showNotes(this.innerHTML);
- ta.classList.add('highlighted');ta.classList.add('active');
- }
+ if(ta.classList.contains('highlighted'))
+ NSUI.showNotes(this.innerHTML);
+ ta.classList.add('highlighted');ta.classList.add('active');
+ }
else{ta.classList.remove('highlighted');ta.classList.remove('active');}
}
NSUI.present_playlist.bind(NSUI,this.pid)();
@@ -317,7 +342,8 @@ NSUI={
const l=sh.newelem('li');
const a=sh.newelem('a');
a.innerHTML=list[i].title;
- a.href=list[i].src;
+ const fmt=NSPlayer.get_preferred_or_default_format();
+ a.href=`//filestorage.chrisoft.org/music/${fmt}/${list[i].title}.${fmt}`;
a.ord=i;
a.onclick=function(e){e.preventDefault();NSUI.switch_track.bind(NSUI,this.ord)();};
l.appendChild(a);
@@ -326,7 +352,7 @@ NSUI={
const d=sh.newelem('div');d.style.height=`${NSUI.ctrlcontainer.getBoundingClientRect().height+16}px`;
this.playlist.appendChild(d);
this.selectedplist=this.playlists[id].plistname;
- this.am3u8.href=`https://chrisoft.org/libs/music/player.d/cgi-bin/m3u8.cgi?plist=${this.playlists[id].plistname}`;
+ this.am3u8.href=`https://chrisoft.org/libs/music/player.d/cgi-bin/m3u8.cgi?plist=${this.playlists[id].plistname}&type=${NSPlayer.get_preferred_or_default_format()}`;
},
switch_playlist:function(pl,setactive)
{
@@ -350,7 +376,7 @@ NSUI={
{
if(NSPlayer.plistname!=this.selectedplist)
this.switch_playlist(this.selectedplist);
- NSPlayer.play(id);
+ return NSPlayer.play(id);
},
set_highlighted:function(pl,t)
{
@@ -370,7 +396,7 @@ NSUI={
for(let i=0;i<this.playlists.length;++i)
{
NSPlayer.sort_playlist(shuffle,this.playlists[i].playlist);
- if(i==this.selectedplist)this.present_playlist(i);
+ if(this.playlists[i].plistname==this.selectedplist)this.present_playlist(i);
}
NSPlayer.sort_playlist(shuffle);
},
@@ -403,27 +429,39 @@ NSUI={
document.getElementById('ctime').style.width=NSUI.audio.currentTime/NSUI.audio.duration*100+'%';
NSUI.bufferedUpdate();
},
- showNotes:async function(title)
- {
- const nd=sh.elem("notes");
- const nt=sh.elem("ntext");
- nt.innerHTML="Loading..."
- nd.style.display="block";
- setTimeout(()=>{nd.style.opacity=1.;});
- const url=`//filestorage.chrisoft.org/music/notes/${title}.note`;
- try{
- const resp=await fetch(new Request(url));
- if(!resp.ok)throw "shit";
- r=await resp.text();
- nt.innerHTML=r;
- }catch(e){nt.innerHTML="This particular track doesn't seem to have a note.";}
- },
- hideNotes:function(title)
- {
- const nd=sh.elem("notes");
- nd.style.opacity=0.;
- setTimeout(()=>{nd.style.display="none";},500);
- }
+ showNotes:async function(title)
+ {
+ const nd=sh.elem("notes");
+ const nt=sh.elem("ntext");
+ nt.innerHTML="Loading..."
+ nd.style.display="block";
+ setTimeout(()=>{nd.style.opacity=1.;},5);
+ const url=`//filestorage.chrisoft.org/music/notes/${title}.note`;
+ try{
+ const resp=await fetch(new Request(url));
+ if(!resp.ok)throw "shit";
+ r=await resp.text();
+ nt.innerHTML=r;
+ }catch(e){nt.innerHTML="This particular track doesn't seem to have a note.";}
+ },
+ hideNotes:function(title)
+ {
+ const nd=sh.elem("notes");
+ nd.style.opacity=0.;
+ setTimeout(()=>{nd.style.display="none";},500);
+ },
+ showHelp:function()
+ {
+ const hd=sh.elem("helpoverlay");
+ hd.style.display="block";
+ setTimeout(()=>{hd.style.opacity=1.;},5);
+ },
+ hideHelp:function()
+ {
+ const hd=sh.elem("helpoverlay");
+ hd.style.opacity=0.;
+ setTimeout(()=>{hd.style.display="none";},500);
+ }
};
NSAudio={
@@ -434,16 +472,18 @@ NSAudio={
{
window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext||window.msAudioContext;
if(!window.AudioContext)alert('This page requires Web Audio API to work...');
- this.audioctx=new AudioContext;
- this.anlznode=this.audioctx.createAnalyser();
+ if(this.audioctx===null)this.audioctx=new AudioContext;
+ if(this.anlznode===null)this.anlznode=this.audioctx.createAnalyser();
this.anlznode.fftSize=2*NSVisualization.nbins;
NSUI.audio.volume=1;
},
connect:function()
{
+ if(this.srcnode===null)
this.srcnode=this.audioctx.createMediaElementSource(NSUI.audio);
this.srcnode.connect(this.anlznode);
this.anlznode.connect(this.audioctx.destination);
+ if(this.audioctx.state!="running")throw "resume required";
},
};
@@ -721,13 +761,16 @@ NSInk={
function init()
{
if(!window.devicePixelRatio)window.devicePixelRatio=1;
- loadTheme();
+ loadTheme();
NSUI.setup_ui();
NSUI.load_playlists()
.then(()=>{
sh.elem('overlaytext').innerHTML+="Done!<br>Click or tap anywhere to start."
sh.elem('overlay').onclick=function(){
- NSAudio.audioInit();NSAudio.connect();
+ let initerr=0;
+ try{
+ NSAudio.audioInit();NSAudio.connect();
+ }catch(e){initerr=1;console.log(e);if(NSAudio.audioctx!==null)NSAudio.audioctx.resume();}
if(window.location.hash.length)
{
let p=window.location.hash.substr(1).split('/');
@@ -735,19 +778,29 @@ function init()
NSUI.switch_playlist(p[0],true);
let id=0;
for(;id<NSPlayer.tracks.length&&NSPlayer.tracks[id].title!=p[1];++id);
- if(id<NSPlayer.tracks.length)NSUI.switch_track(id);
+ if(id<NSPlayer.tracks.length)
+ {
+ const p=NSUI.switch_track(id);
+ if(p!=undefined)
+ p.then(_=>{sh.elem('overlay').style.display='none';}).catch(e=>{});
+ else
+ //this browser is from an era before this autoplay policy mess,
+ //assume it succeeded
+ sh.elem('overlay').style.display='none';
+ }
}
- sh.elem('overlay').style.display='none';
+ else if(!initerr)sh.elem('overlay').style.display='none';
}
- sh.elem('overlay').onclick();
+ sh.elem('overlay').onclick();
},
- ()=>{
- sh.elem('overlaytext').innerHTML+="Failed...<br>Maybe try refreshing the page?"
- });
+ ()=>{
+ sh.elem('overlaytext').innerHTML+="Failed...<br>Maybe try refreshing the page?"
+ });
NSVisualization.init();NSInk.inkPrepare();
NSUI.audio.ontimeupdate=NSUI.timeUpdate;
NSUI.audio.onended=NSPlayer.next.bind(NSPlayer);
NSUI.audio.onplay=NSUI.audio.ondurationchange=function(){
+ if(!NSUI.audio.audioTracks)return;
if(NSUI.audio.audioTracks.length==2)
sh.elem('mt').style.display='inline';
else
diff --git a/libs/music/player.d/pcm.js b/libs/music/player.d/pcm.js
index 575b7f7..6e2022c 100644
--- a/libs/music/player.d/pcm.js
+++ b/libs/music/player.d/pcm.js
@@ -1,11 +1,8 @@
-; // Private Cloud Music - player.js
-; // Licence: WTFPL
-; // BLumia - 2016/11/11
+; // SPDX-FileCopyrightText: 2021 Gary Wang <toblumia@outlook.com>
+; // SPDX-License-Identifier: MIT
; // szO Chris && 2jjy && jxpxxzj Orz
; // ↑ Moe ↑ Moe ↑ Moe
-; // Modified to use on chrisoft.org by Chris Xiong
-; // szO BLumia Orz
-; // ↑ Moe
+
// formatTime,getCookie by Chrissssss
function formatTime(t) {
if(isNaN(t))return '--:--';
@@ -24,9 +21,9 @@ function setCookie(cookieName, cookieValue, maxAge = 0) {
if (maxAge > 0) cookieStr += ";max-age=" + maxAge;
document.cookie = cookieStr;
}
-
-const PCMAPI_URL='/libs/music/player.d/cgi-bin/pcm.cgi';
-const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
+function displayName(item) {
+ return item.displayName ? item.displayName : decodeURIComponent(item.fileName);
+}
(function() {
var Helper = function() {
@@ -49,8 +46,16 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
if(this.el) this.el.style.cssText += ';' + property + ":" + value;
return this;
},
- attr: function(property, value) {
- if(this.el) this.el.setAttribute(property, value);
+ attr: function(attr, value) {
+ if(this.el) this.el.setAttribute(attr, value);
+ return this;
+ },
+ removeData: function(attr) {
+ if(this.el) this.el.removeAttribute("data-" + attr);
+ return this;
+ },
+ data: function(attr, value) {
+ if(this.el) this.el.setAttribute("data-" + attr, JSON.stringify(value));
return this;
},
append: function(node) {
@@ -76,9 +81,17 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
var f = new Helper();
return f.entry(selector);
}
+ function TrickOrTreat(promiseRsp) {
+ if (!promiseRsp.ok) {
+ throw Error(promiseRsp.statusText); // to cancel the Promise chain...
+ }
+ return promiseRsp.json();
+ }
var Player = {
+ mediaRootUrl: '',
path: null, // sample: 'Test/'
data: null,
+ preferredFormats: undefined, // sample: 'mp3,ogg'
audio: document.getElementsByTagName('audio')[0],
currentIndex: -1,
loop: 0,
@@ -86,6 +99,14 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
playlist: H("playlist").el,
folderlist: H("folderlist").el,
nowPlaying: H("nowPlaying").el,
+ apiUrl: "/libs/music/player.d/cgi-bin/pcm.cgi",
+ _currentSongInfoJson: undefined,
+ _chapterNeedUpdate: true,
+
+ setInfoJson: (jsonData) => {
+ this._currentSongInfoJson = jsonData;
+ this._chapterNeedUpdate = true;
+ },
updateMetadata: function() {
if ('mediaSession' in navigator) {
@@ -96,25 +117,90 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
}
},
+ applyChapterData: () => {
+ if (!this._chapterNeedUpdate) return;
+ if (Player.audio.duration) {
+ if (this._currentSongInfoJson) {
+ let duration = Player.audio.duration;
+ let progressChapterData = [];
+ this._currentSongInfoJson.chapters.forEach((chapter) => {
+ let chapterObj = {};
+ chapterObj.start = chapter.start_time / duration * 100;
+ chapterObj.title = chapter.title;
+ progressChapterData.push(chapterObj);
+ });
+ H("progress-bar").data("chapters", progressChapterData);
+ } else {
+ H("progress-bar").removeData("chapters");
+ }
+ this._chapterNeedUpdate = false;
+ }
+ },
+
+ fetchAdditionalInfo: (infoJsonfileUrl) => {
+ fetch(infoJsonfileUrl).then(TrickOrTreat).then((data) => {
+ Player.setInfoJson(data);
+ });
+ },
+
playAtIndex: function(i) {
+ let fullPath = this.path + this.data[i].fileName;
+ let srcUrl = this.data[i].url ? this.data[i].url : (this.mediaRootUrl + fullPath);
// FIXME: trigger this when audio doesn't finished load will cause play promise error.
this.audio.pause();
this.currentIndex = i;
- this.audio.src = AUDIO_URL + this.data[i].fileName + '.ogg';
+ this.audio.src = srcUrl;
this.audio.load();
this.audio.play();
- window.history.replaceState("","Useless Title","#/"+this.path+this.data[i].fileName+"/"); // title seems be fucked.
- H(this.nowPlaying).innerHTML(decodeURIComponent(this.data[i].fileName));
+ window.history.replaceState("","Useless Title","#/" + fullPath + "/"); // title seems be fucked.
+ H(this.nowPlaying).innerHTML(displayName(this.data[i]));
+
+ if (this.data[i].additionalInfo) {
+ let infoJsonFile = (fullPath.substring(0, fullPath.lastIndexOf('.')) || fullPath) + ".info.json";
+ this.fetchAdditionalInfo(infoJsonFile);
+ } else {
+ this.setInfoJson(undefined);
+ }
+ },
+
+ fetchServerInfo: function(callback) {
+ var that = this;
+ fetch(this.apiUrl, {
+ method: 'POST',
+ body: new URLSearchParams({
+ 'do': 'getserverinfo'
+ })
+ }).then(TrickOrTreat).then((data) => {
+ if (data.result.mediaRootUrl && data.result.mediaRootUrl.length > 1) {
+ that.mediaRootUrl = data.result.mediaRootUrl;
+ if (!that.mediaRootUrl.endsWith('/')) {
+ that.mediaRootUrl = that.mediaRootUrl + '/';
+ }
+ }
+ if (data.result.serverName) {
+ let el = H("server-name");
+ if (el) {
+ el.text(data.result.serverName);
+ }
+ document.title = data.result.serverName;
+ }
+
+ typeof callback === 'function' && callback();
+ })
},
freshFolderlist: function(callback) {
- var xhr = new XMLHttpRequest();
- xhr.open("POST", PCMAPI_URL, true);
- xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var that = this;
- xhr.onreadystatechange = function () {
- if (xhr.readyState != 4 || xhr.status != 200) return;
- var data = JSON.parse(xhr.responseText);
+ requestBody = {
+ 'do': 'getfilelist',
+ };
+ if (that.preferredFormats) {
+ requestBody['preferredFormats'] = that.preferredFormats;
+ }
+ fetch(this.apiUrl, {
+ method: 'POST',
+ body: new URLSearchParams(requestBody)
+ }).then(TrickOrTreat).then((data) => {
if (data.status != 200) {
console.error("Fetch error. Reason: " + data.message + " Url: ./api.php");
return;
@@ -129,11 +215,7 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
).el
);
});
- };
- xhr.onerror = function() {
- console.error("Ajax load folders failed. Status: " + xhr.status + " Url: ./api.php");
- };
- xhr.onloadend = function() {
+
var nodeList = document.querySelectorAll('#folderlist a');
for(var i = 0; i < nodeList.length; i++) {
var el = nodeList[i];
@@ -142,41 +224,34 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
that.fetchData();
};
}
+
typeof callback === 'function' && callback();
- }
- xhr.send("do=getfilelist");
+ });
},
fetchData: function() {
var that = this;
- var xhr = new XMLHttpRequest();
- xhr.open("POST", PCMAPI_URL, true);
- xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- xhr.onreadystatechange = function () {
- if (xhr.readyState != 4 || xhr.status != 200) return;
- var data = JSON.parse(xhr.responseText);
- if (data.status != 200) {
- console.error("Fetch error. Reason: " + data.message + " Url: ./api.php");
- return;
- }
+
+ fetch(this.apiUrl, {
+ method: 'POST',
+ body: new URLSearchParams({
+ 'do': 'getfilelist',
+ 'folder': that.path
+ })
+ }).then(TrickOrTreat).then((data) => {
that.data = data.result.data.musicList;
that.freshPlaylist();
that.freshSubFolderList(data.result.data.subFolderList);
- };
- xhr.onerror = function() {
- console.error("Ajax load playlist failed. Status: " + xhr.status + " Url: ./api.php");
- that.data = [];
- };
- xhr.send("do=getfilelist&folder="+that.path);
+ });
},
-
+
freshPlaylist : function() {
var that = this;
var data = this.data;
var songTitle = '';
this.playlist.innerHTML = '';
data.forEach(function(item, i) {
- songTitle = decodeURIComponent(item.fileName);
+ songTitle = displayName(item);
H(that.playlist).append(
H("<a>").attr('index', i).append(
H("<li>").text(songTitle).el
@@ -218,13 +293,13 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
urlMatch : function() {
var isUrlMatched = false;
// Match folder name and song title.
- var re = new RegExp("[#][/](.*[/])(.*)[/]$");
+ var re = new RegExp("[#][/](.*[/])(.*.[a-zA-z0-9]{1,3})[/]");
var urlMatch = re.exec(location.href);
if (urlMatch != null) {
isUrlMatched = true;
this.path = urlMatch[1];
- this.audio.src = AUDIO_URL + urlMatch[2] + '.ogg';
- this.audio.play();
+ this.audio.src = (this.path + urlMatch[2]);
+ this.audio.play().catch((reason) => { console.log(reason); });
H(this.nowPlaying).innerHTML(decodeURIComponent(urlMatch[2]));
}
// Only match folder name.
@@ -261,30 +336,33 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
H("btn-order").innerHTML("Order: ×");
}
},
-
+
init : function() {
var that = this;
- this.freshFolderlist(function() {
- that.urlMatch();
- that.fetchData();
+ this.fetchServerInfo(function() {
+ that.freshFolderlist(function() {
+ that.urlMatch();
+ that.fetchData();
+ });
});
this.loop = getCookie("pcm-loop") == "1" ? 1 : 0;
this.order = getCookie("pcm-order") == "1" ? 1 : 0;
this.applyLoop();
this.applyOrder();
},
-
+
ready : function() {
var that = this;
- this.audio.ontimeupdate = function() {
+ this.audio.ontimeupdate = () => {
+ this.applyChapterData();
H("curTime").innerHTML(formatTime(Player.audio.currentTime));
H("totalTime").innerHTML(formatTime(Player.audio.duration));
- H("timebar").css("width", Player.audio.currentTime / Player.audio.duration*100+"%");
+ H("progress-bar").attr("value", Player.audio.currentTime / Player.audio.duration*100);
var r = 0;
- for(var i=0; i<Player.audio.buffered.length; ++i)
+ for (var i=0; i<Player.audio.buffered.length; ++i)
r = r<Player.audio.buffered.end(i) ? Player.audio.buffered.end(i) : r;
- H("bufferbar").css("width", r / Player.audio.duration*100+"%");
+ H("progress-bar").attr("buffer", r / Player.audio.duration*100);
};
this.audio.onpause = function() {
@@ -296,7 +374,7 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
that.updateMetadata();
}
- H("progressbar").click(function(e) {
+ H("progress-bar").click(function(e) {
var sr=this.getBoundingClientRect();
var p=(e.clientX-sr.left)/sr.width;
that.audio.currentTime=that.audio.duration*p;
@@ -306,7 +384,7 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
for(var i = 0; i < nodeList.length; i++) {
var el = nodeList[i];
el.onclick = function() {
- if(that.data[that.currentIndex]) H(that.nowPlaying).innerHTML(decodeURIComponent(that.data[that.currentIndex].fileName));
+ if(that.data[that.currentIndex]) H(that.nowPlaying).innerHTML(displayName(that.data[that.currentIndex]));
};
}
@@ -346,7 +424,7 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
that.applyLoop();
setCookie("pcm-loop", that.loop, 157680000);
});
-
+
H("btn-order").click(function() {
that.order = 1 - that.order;
that.applyOrder();
@@ -359,7 +437,7 @@ const AUDIO_URL='//filestorage.chrisoft.org/music/ogg/';
}
}
};
-
+
Player.init();
Player.ready();
}());
diff --git a/libs/music/player.d/player.php b/libs/music/player.d/player.php
deleted file mode 100644
index 6d20ddc..0000000
--- a/libs/music/player.d/player.php
+++ /dev/null
@@ -1,147 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>The Stupid Online Player</title>
- <link rel=stylesheet href='/common.css' type='text/css'>
- <link rel=stylesheet href='styles.css' type='text/css'>
- <script type="text/javascript" src="jquery-3.0.0.min.js"></script>
- <script type="text/javascript" src="main.js"></script>
- <script type="text/javascript">
- function changeImage(img){
- document.getElementById('aqt').src=img;
- }
- </script>
-</head>
-<body onload="init();">
- <div class="TText" style="font-size:2em"><a href="/">Chrisoft</a>::<a href="/libs/music/player">Music Library</a></div>
- <p class="TText" id="plname"></p>
- <div style="padding:7px;border:1px solid #aaa;display:table;">
- <div style="text-align:center;">
- <b>Help &amp; About</b> [<a href="#" onclick="var e=document.getElementById(&quot;help&quot;);if(e.style.display==&quot;block&quot;){e.style.display=&quot;none&quot;;this.innerHTML=&quot;show&quot;;}else {e.style.display=&quot;block&quot;;this.innerHTML=&quot;hide&quot;;}">show</a>]
- </div>
- <div id="help" style="display:none;">
- Click something to play.<br>
- Tested on Chrome, Firefox and Microsoft Edge. Doesn't work at all on Internet Explorer.<br>
- WARNING!!: Microsoft Edge and Safari plays huge wav streams!<br>
- As of 2016-07-03, visualization doesn't work on Chrome for Android unless "unified media pipeline" is enabled in chrome://flags.<br>
- Written in html, javascript, css and php. Uses html5 features, jQuery and some css3 transitions.<br>
- This page uses cookies to save your preferences.<br>
- History:
- <pre style="white-space: pre-wrap;">
-2016.11.03
-Canvas is no longer blurred on HiDPI screens. UI changes.
-Makes mobile version less painful to view. Code cleanup.
-Save preferences in cookies.
-2016.07.23
-UI bug fixes.
-2016.07.07
-Behavior changes. Custom audio controls.
-2016.07.03
-Ink fountain performance boost. Minor UI changes. Bug fixes.
-2016.07.02
-The online player received a major overhaul.
-Merged the experimental version.
-The playlist can now be hidden.
-2016.02.13
-Two new visualization modes for the experimental online player.
-New playlist mechanism for the online player, not added to the experimental version.
-2016.02.06
-New experimental online player with visualization.
-2015.11.7
-The online player was added.
- </pre>
- </div>
- </div>
- <div id="cvsdiv">
- <canvas width="800" height="450" id="cvs"></canvas>
- </div>
- <div id="ctrlcontainer">
- <div class="switches" style="text-align:right;padding-top:0.25em 0 0.25em 0;">
- <span style="text-align:center;color:#000;width:100%;display:inline-block;position:absolute;left:50%;top:0.1em;transform:translateX(-50%);z-index:-1" id="nowplaying"></span>
- <sw id="plistsw">[↓Hide Playlist]</sw>
- </div>
- <div class="centered-audio">
- <audio id="audio" preload="auto" tabindex="0" type="audio/ogg" autoplay="autoplay" style="display:none;">
- Sorry, but your browser does not support HTML5 audio.<br>
- 请使用支持HTML5音频的浏览器访问本页面.
- </audio>
- <div style="position:relative;height:1em;margin:0.25em;">
- <div id="tsliderbase" style="position:absolute;width:100%;height:100%;background-color:rgba(204,204,204,0.6);"></div>
- <div id="cbuff" style="position:absolute;width:0%;height:100%;background-color:rgba(64,192,255,0.6);pointer-events:none;"></div>
- <div id="ctime" style="position:absolute;width:0%;height:100%;background-color:#1194FF;pointer-events:none;"></div>
- </div>
- <span id="timenow" style="position:absolute;left:1em;">0:00</span>
- <div class="buttondiv" id="pbprev"><img src="prev.svg" alt="prev" width="24"></div>
- <div class="buttondiv" id="pbplaypause"><img src="play.svg" alt="playpause" width="24" id="imgplaypause"></div>
- <div class="buttondiv" id="pbnext"><img src="next.svg" alt="next" width="24"></div>
- <span id="timeleft" style="position:absolute;right:1em;">0:00</span>
- </div>
- <div class="switches">
- Shuffle: <sw id="shufflesw">Off</sw>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Repeat current: <sw id="repeatsw">Off</sw>
- <br>
- Visualization:
- <select id="visualizationsel" onfocus="this.oldvalue=this.value;">
- <option value="none">None</option>
- <option value="spectrum">Spectrum</option>
- <option value="spectrumring">Spectrum Ring</option>
- <option value="scope">Scope</option>
- <option value="spectrogram">Spectrogram</option>
- <option value="inkfountain">Ink Fountain</option>
- <option value="shakeurbody">Shake your body(defunct)</option>
- </select>
- </div>
- </div>
- <div id="plistref"></div>
- <ul id="playlist">
- <?php
- function useWav($user_agent)
- {
- if(strpos($user_agent,'Edge'))return true;
- elseif(strpos($user_agent,'Chrome'))return false;
- elseif(strpos($user_agent,'Safari'))return true;
- elseif(strpos($user_agent,'MSIE')||strpos($user_agent,'Trident/7'))return true;
- return false;
- }
- if(!isset($_GET["plistid"]))$_GET["plistid"]="0";
- if(intval($_GET["plistid"])<0||intval($_GET["plistid"])>=100)$_GET["plistid"]="0";
- $plist=sprintf("/var/www/html/libs/music/player.d/playlists/%s",$_GET["plistid"]);
- $file=fopen($plist,"r");
- $l=fgets($file);$l=substr($l,0,strlen($l)-1);
- echo "<script type=\"text/javascript\">","document.getElementById('plname').innerHTML=\"Playlist: ",$l," \";";
- echo "var a=document.createElement('a');a.href=\"plisteditor.php?plistid=",$_GET["plistid"],"\";a.innerHTML=\"Edit playlist\";document.getElementById('plname').appendChild(a);</script>";
- for($i=0;$item=fgets($file);$i++)
- {
- while(ord($item[strlen($item)-1])==10||ord($item[strlen($item)-1])==13)
- $item=substr($item,0,strlen($item)-1);
- if(useWav($_SERVER['HTTP_USER_AGENT']))
- {
- $tfilen=sprintf("/var/www/html/libs/music/wav/%s.wav",$item);
- if(!file_exists($tfilen))
- $cur=sprintf("<li><a href=\"../wav/%s.wav\" tr=\"%s\" ord=\"%d\" style=\"color:#f00;\">%s</a></li>",$item,$item,$i,$item);
- else
- $cur=sprintf("<li><a href=\"../wav/%s.wav\" tr=\"%s\" ord=\"%d\">%s</a></li>",$item,$item,$i,$item);
- echo $cur;
- }
- else
- {
- $tfilen=sprintf("/var/www/html/libs/music/ogg/%s.ogg",$item);
- if(!file_exists($tfilen))
- $cur=sprintf("<li><a href=\"../ogg/%s.ogg\" tr=\"%s\" ord=\"%d\" style=\"color:#f00;\">%s</a></li>",$item,$item,$i,$item);
- else
- $cur=sprintf("<li><a href=\"../ogg/%s.ogg\" tr=\"%s\" ord=\"%d\">%s</a></li>",$item,$item,$i,$item);
- echo $cur;
- }
- }
- ?>
- </ul>
- <div style="height:160px;"></div>
- <!--<div class="floatingl">
- <img src="../../../koishi_norm.png" alt="" width="320" id="aqt" style="transition:0.4s;">
- </div>-->
-</body>
-</html>
diff --git a/libs/music/player.d/playlists/0 b/libs/music/player.d/playlists/0
index 444f9fe..89427c1 100644
--- a/libs/music/player.d/playlists/0
+++ b/libs/music/player.d/playlists/0
@@ -48,7 +48,6 @@ Witching Dream
恋色マジック
悔恨の洞穴~Regret and Confession_remix
旅途_新乱搞
-明治十七年の上海アリス_cdversion_remix
星の器~Casket of Star
東方妖恋談
東方怪奇談
diff --git a/libs/music/player.d/playlists/1 b/libs/music/player.d/playlists/1
index 29ffe8e..0ccb610 100644
--- a/libs/music/player.d/playlists/1
+++ b/libs/music/player.d/playlists/1
@@ -1,6 +1,7 @@
Original
45canonrev
CanonTechno
+Maritima Sylva
noname03_preview
Spoolka
The Ware Rosette
diff --git a/libs/music/player.d/playlists/Converted-Modules.playlist b/libs/music/player.d/playlists/Converted-Modules.playlist
index 9af3954..b925524 100644
--- a/libs/music/player.d/playlists/Converted-Modules.playlist
+++ b/libs/music/player.d/playlists/Converted-Modules.playlist
@@ -1,16 +1,30 @@
Converted-Modules
-bardtale MIDI Edition
-bardtale SD Edition
Carl Larsson - Seasons' Passing - MIDI Edition
+Carl Larsson - The Steadfast - MIDI Edition
+Carl Larsson - Trickster - MIDI Edition
Carl Larsson - Wake - MIDI Edition
+Carl Larsson - Waylands - MIDI Edition
Chris Jarvis - Northern Sky - MIDI Edition
+Dan Nyman - Winds Of Compositions - MIDI Edition
+David Lenaerts - Under the Autumn Tree - MIDI Remix
+DipA - A Bard's Tale... - MIDI Edition
+DipA - A Bard's Tale... - SD Edition
+DreaMSectioN - One Last Hope - MIDI Edition
HyoChan - Farewell, My Friend
+Mads Orbesen Troest - Tick Tack Toe - MIDI Edition
minomus - Quicksilver - MIDI Edition
+Noby - Teh Windows Medley - XV Edition
+Reed - Clamberdown - MIDI Edition
Sphenx - Far Space Dance - MIDI Edition
Sphenx - Flutana Variata - MIDI Edition
-Sphenx - The Awakening of Evil - MIDI Version
+Sphenx - The Awakening of Evil - MIDI Edition
Sphenx - The Last Morning - MIDI Edition
+Traven - Pocket - SD Edition
+Traven - Pocket - XV Edition
Warder - Carra's Lament - MIDI Edition
+Warder - Emerald Isle Set - MIDI Edition
Warder - Moors of Ireland - MIDI Edition
Warder - Whistler's Bride - MIDI Edition
Warder - Tyhjan Pirtin Valssi - MIDI Edition
+Woolters - Bliss - SD Edition
+Woolters - Bliss - XV Edition
diff --git a/libs/music/player.d/plistcreator.php b/libs/music/player.d/plistcreator.php
deleted file mode 100644
index b4f12c7..0000000
--- a/libs/music/player.d/plistcreator.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<pre>
-<?php
- if(!isset($_POST["plistid"])){echo "E: invalid plistid.";exit();}
- if(intval($_POST["plistid"])<0||intval($_POST["plistid"])>=100)
- {echo "E: invalid plistid.";exit();}
- if(intval($_POST["plistid"])<16&&strcmp($_SERVER["REMOTE_ADDR"],"127.0.0.1")!=0&&strcmp($_SERVER["REMOTE_ADDR"],"::1")!=0&&strpos($_SERVER["REMOTE_ADDR"],"192.168")!==0&&strpos($_SERVER["REMOTE_ADDR"],"10.42")!==0)
- {echo "W: Protected play list. Doing nothing. " . $_SERVER["REMOTE_ADDR"];exit();}
- $fn=sprintf("/var/www/html/libs/music/player.d/playlists/%s",$_POST["plistid"]);
- $file=fopen($fn,"w");
- fwrite($file,$_POST["plistname"]);fwrite($file,"\n");
- for($i=0;$i<count($_POST["plist"]);++$i)
- {
- fwrite($file,$_POST["plist"][$i]);
- if(ord($_POST["plist"][$i][strlen($_POST["plist"][$i])-1])!=10)
- fwrite($file,"\n");
- }
- fclose($file);
- echo "I: Playlist created successfully. <a href=\"../player/",$_POST["plistid"],"\">Play it now!</a>";
-?>
-</pre>
diff --git a/libs/music/player.d/plisteditor.php b/libs/music/player.d/plisteditor.php
deleted file mode 100644
index 020623f..0000000
--- a/libs/music/player.d/plisteditor.php
+++ /dev/null
@@ -1,146 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <title>Playlist Editor</title>
- <link rel=stylesheet href='../../../common.css' type='text/css'>
- <link rel=stylesheet href='styles.css' type='text/css'>
- <script type="text/javascript">
- function changeImage(img){
- document.getElementById('aqt').src=img;
- }
- function ins()
- {
- var ea=document.getElementById('available');
- for(var i=0;i<ea.length;i++)
- {
- if(ea.options[i].selected)
- {
- var option=document.createElement("option");
- option.text=ea.options[i].text;
- document.getElementById('plist').add(option);
- }
- }
- }
- function rm()
- {
- var er=document.getElementById('plist');
- for(var i=0;i<er.length;i++)
- {
- if(er.options[i].selected)
- er.remove(i--);
- }
- }
- function mvup()
- {
- var er=document.getElementById('plist');
- for(var i=0;i<er.length;i++)
- {
- if(er.options[i].selected&&i!=0)
- {
- var t=er.options[i-1].text,tv=er.options[i-1].value;
- er.options[i-1].text=er.options[i].text;
- er.options[i-1].value=er.options[i].value;
- er.options[i].text=t;
- er.options[i].value=tv;
- er.options[i].selected=false;
- er.options[i-1].selected=true;
- }
- }
- }
- function mvdn()
- {
- var er=document.getElementById('plist');
- for(var i=er.length-1;i>=0;i--)
- {
- if(er.options[i].selected&&i!=er.length-1)
- {
- var t=er.options[i+1].text,tv=er.options[i+1].value;
- er.options[i+1].text=er.options[i].text;
- er.options[i+1].value=er.options[i].value;
- er.options[i].text=t;
- er.options[i].value=tv;
- er.options[i].selected=false;
- er.options[i+1].selected=true;
- }
- }
- }
- function submitplist()
- {
- var er=document.getElementById('plist');
- for(var i=0;i<er.length;i++)er.options[i].selected=true;
- document.getElementById("result").submit();
- }
- </script>
-</head>
-<body>
- <div class="TText" style="font-size:2em"><a href="../../../../">Chrisoft</a>::<a href="../">Music Library</a></div>
- <p class="TText">Note: Playlist ID 0~15 are reserved.</p>
- <table style="width:100%;">
- <tr>
- <td style="width:40%;">
- <form>
- <select multiple name="available" id="available" size="30" style="width:100%;">
- <?php
- $files=scandir("/var/www/html/libs/music/ogg/");
- for($i=0,$c=count($files);$i<$c;$i++)
- {
- if(!(strstr($files[$i],"ogg")))continue;
- $cur=sprintf("<option value=\"%s\">%s</option>",substr($files[$i],0,strlen($files[$i])-4),substr($files[$i],0,strlen($files[$i])-4));
- echo $cur;
- }
- ?>
- </select>
- </form>
- </td>
- <td style="width:10%;text-align:center;">
- <button onclick="ins();">&gt;</button><br>
- <button onclick="rm();">&lt;</button><br>
- <button onclick="mvup();">^</button><br>
- <button onclick="mvdn();">v</button><br>
- Play List ID: <input type="number" id="plistid" name="plistid" form="result" min="1" max="100"><br>
- Play List Name: <input type="text" id="plistname" name="plistname" form="result"><br>
- <button onclick="submitplist();">submit</button>
- </td>
- <td style="width:40%;">
- <form id="result" action="plistcreator.php" method="post">
- <select multiple name="plist[]" id="plist" size="30" style="width:100%;">
- <?php
- if(isset($_GET["plistid"]))
- {
- if(intval($_GET["plistid"])>=0&&intval($_GET["plistid"])<100)
- {
- $fn=sprintf("/var/www/html/libs/music/player.d/playlists/%s",$_GET["plistid"]);
- $file=fopen($fn,"r");
- fgets($file);
- while($item=fgets($file))
- echo "<option value=\"",$item,"\">",$item,"</option>";
- fclose($file);
- }
- }
- ?>
- </select>
- </form>
- <?php
- if(isset($_GET["plistid"]))
- {
- if(intval($_GET["plistid"])>=0&&intval($_GET["plistid"])<100)
- {
- echo "<script type=\"text/javascript\">document.getElementById(\"plistid\").value=",$_GET["plistid"];
- $fn=sprintf("/var/www/html/libs/music/player/playlists/%s",$_GET["plistid"]);
- $file=fopen($fn,"r");
- $name=fgets($file);$name=substr($name,0,strlen($name)-1);
- echo ";document.getElementById(\"plistname\").value=\"",$name,"\";</script>";
- fclose($file);
- }
- }
- ?>
- </td>
- </tr>
- </table>
- <div class="floatingl">
- <img src="../../../koishi_norm.png" alt="" width="320" id="aqt" onmouseover="changeImage('../../../koishi_hovr.png')" onmouseout="changeImage('../../../koishi_norm.png')" onclick="this.remove();">
- </div>
-</body>
-</html>
diff --git a/libs/music/player.d/progress-bar.js b/libs/music/player.d/progress-bar.js
new file mode 100644
index 0000000..c5850c2
--- /dev/null
+++ b/libs/music/player.d/progress-bar.js
@@ -0,0 +1,97 @@
+; // SPDX-FileCopyrightText: 2021 Gary Wang <toblumia@outlook.com>
+; // SPDX-License-Identifier: MIT
+class ProgressBar extends HTMLElement {
+
+ static get observedAttributes() {
+ return ['value', 'buffer', 'data-chapters'];
+ }
+
+ constructor() {
+ super(); // always call super() first in the constructor.
+ const shadow = this.attachShadow({mode: 'open'});
+
+ const container = document.createElement('div');
+ container.setAttribute('class', 'container');
+
+ const bufferBar = document.createElement('div');
+ bufferBar.setAttribute('id', 'bufferbar');
+
+ const timeBar = document.createElement('div');
+ timeBar.setAttribute('id', 'timebar');
+
+ const chapterContainer = document.createElement('div');
+ chapterContainer.setAttribute('id', 'chapter-container');
+
+ const style = document.createElement('style');
+ style.textContent = `
+ .container {
+ height: 1.5em;
+ position: relative;
+ background-color: #f1f1f1;
+ }
+ .container > div {
+ height: 100%;
+ position: absolute;
+ }
+ #timebar {
+ background-color: #2196F3;
+ }
+ #bufferbar {
+ background-color: #AAA;
+ }
+ .container, #chapter-container {
+ width: 100%;
+ }
+ .chapter {
+ height: 100%;
+ width: stretch; width: -moz-available; width: -webkit-fill-available;
+ border-left: .15em solid #0045F340;
+ position: absolute;
+ }
+ `;
+
+ shadow.appendChild(container);
+ shadow.appendChild(style);
+ container.appendChild(bufferBar);
+ container.appendChild(timeBar);
+ container.appendChild(chapterContainer);
+ }
+
+ connectedCallback() {
+ spawnChapters(this);
+ updateStyle(this);
+ };
+
+ attributeChangedCallback(name, oldValue, newValue) {
+ if (name == "data-chapters") {
+ spawnChapters(this);
+ }
+ updateStyle(this);
+ }
+}
+
+function spawnChapters(elem) {
+ const shadow = elem.shadowRoot;
+ let chapterContainer = shadow.querySelector('#chapter-container');
+ let chapters = elem.dataset.chapters ? JSON.parse(elem.dataset.chapters) : [];
+
+ if (!Array.isArray(chapters)) return;
+ chapterContainer.textContent = '';
+ chapters.forEach((chapter) => {
+ let chapterElem = document.createElement('div');
+ chapterElem.setAttribute('class', 'chapter');
+ chapterElem.setAttribute('title', `${chapter.title}`);
+ chapterElem.setAttribute('style', `left: ${chapter.start}%`);
+ chapterContainer.appendChild(chapterElem);
+ });
+}
+
+function updateStyle(elem) {
+ const shadow = elem.shadowRoot;
+ let timebar = shadow.querySelector('#timebar');
+ timebar.setAttribute('style', `width: ${elem.getAttribute('value')}%`);
+ let bufferbar = shadow.querySelector('#bufferbar');
+ bufferbar.setAttribute('style', `width: ${elem.getAttribute('buffer')}%`);
+}
+
+customElements.define('pcm-progress', ProgressBar);
diff --git a/libs/music/player.d/styles.css b/libs/music/player.d/styles.css
index bc4055c..7985f25 100644
--- a/libs/music/player.d/styles.css
+++ b/libs/music/player.d/styles.css
@@ -8,6 +8,19 @@
height:90vh;
list-style-type:none;
}
+#helpoverlay{
+ top:0;
+ left:0;
+ width:100%;
+ height:100%;
+ position:fixed;
+ z-index:99999999;
+ background-color:rgba(0,0,0,0.6);
+ opacity:0;
+ color:#FFF;
+ display:none;
+ transition:opacity 0.3s;
+}
#overlay{
top:0;
left:0;
diff --git a/libs/pictures/.header.html b/libs/pictures/.header.html
deleted file mode 100755
index 5d19c06..0000000
--- a/libs/pictures/.header.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-<title>Litter Rubbish Garbage Trash</title>
-<link rel=stylesheet href='../../common.css' type='text/css'>
-<style type="text/css">
-body
-{
- background: #acf;
- margin: 33px
-}
-pre, address
-{
- font-family: 'FreeMono', 'Courier New', Courier, monospace;
-}
-</style>
-</head>
-<body>
-<font size="6"><div class="TText"><a href="../../">Chrisoft</a>::Picture Library</div></font>
-<p class="TText">All pictures here are fetched from the Internet and most of them are Touhou-related...<br />
-Not all of these pictures are checked for "safety"! Protect your eyes yourself!</p>
-<!--<p class="TText">Try the new picture browser by clicking the following links:<br>
-<a href="pliba.php">a</a> <a href="plibb.php">b</a>
-</p>-->
diff --git a/libs/pictures/.htaccess b/libs/pictures/.htaccess
deleted file mode 100755
index 410ec07..0000000
--- a/libs/pictures/.htaccess
+++ /dev/null
@@ -1,4 +0,0 @@
-IndexOptions FancyIndexing SuppressHTMLPreamble
-HeaderName .header.html
-IndexIgnore .. *.php
-
diff --git a/libs/pictures/osunix-logo_sq_thicken.png b/libs/pictures/osunix-logo_sq_thicken.png
deleted file mode 100644
index 510bba2..0000000
--- a/libs/pictures/osunix-logo_sq_thicken.png
+++ /dev/null
Binary files differ
diff --git a/libs/pictures/pliba.php b/libs/pictures/pliba.php
deleted file mode 100755
index a0a4834..0000000
--- a/libs/pictures/pliba.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <title>Picture browser</title>
- <link rel=stylesheet href='../../common.css' type='text/css'>
- <script type="text/javascript">
- function changeImage(img){
- document.getElementById('aqt').src=img;
- }
- </script>
- <style>
- .inlinediv
- {
- display:inline-block;
- word-wrap:break-word;
- max-height:24em;
- max-width:24em;
- margin:1em;
- border:1px solid black;
- text-align:center;
- }
- .limimg{max-height:20em;max-width:20em;}
- </style>
-</head>
-<body style="background-color:#acf;">
- <div class="TText" style="font-size:2em"><a href="../../../">Chrisoft</a>::Picture Library</div>
- <div>
- <?php
- $startpage=0;
- if(!empty($_GET['p']))
- $startpage=intval($_GET['p']);
- $files=scandir("/var/www/html/libs/pictures/a/");
- for($i=$startpage*20,$c=count($files);$i<$c&&$i-$startpage*20<20;$i++)
- {
- if(!(strstr($files[$i],"jpg"))&&!(strstr($files[$i],"gif"))&&!(strstr($files[$i],"png")))continue;
- $ret=sprintf("
- <div class=\"inlinediv\"><a href=\"./a/%s\">
- <img class=\"limimg\" src=\"./a/%s\">
- <br>%s</a>
- </div>",$files[$i],$files[$i],$files[$i]);
- echo $ret;
- }
- $totalsp=count($files)/20+(count($files)%20==0?0:1)-1;
- $minsp=$startpage-5;if($minsp<0)$minsp=0;
- $maxsp=$startpage+6;if($maxsp>$totalsp)$maxsp=$totalsp;
- echo "<div style=\"text-align:center;\">";
- for($i=$minsp;$i<$maxsp;$i++)
- {
- if($i===$startpage)
- echo $i+1 . ' ';
- else
- {
- $t=sprintf("<a href=\"./pliba.php?p=%d\">%d</a> ",$i,$i+1);
- echo $t;
- }
- }
- echo "</div>";
- ?>
- </div>
-</body>
-</html>
diff --git a/libs/pictures/plibb.php b/libs/pictures/plibb.php
deleted file mode 100755
index 351f1ab..0000000
--- a/libs/pictures/plibb.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <meta http-equiv="expires" content="Friday 24 October 1997 09:30 GMT">
- <title>Picture browser</title>
- <link rel=stylesheet href='../../common.css' type='text/css'>
- <script type="text/javascript">
- function changeImage(img){
- document.getElementById('aqt').src=img;
- }
- </script>
- <style>
- .inlinediv
- {
- display:inline-block;
- word-wrap:break-word;
- max-height:24em;
- max-width:24em;
- margin:1em;
- border:1px solid black;
- text-align:center;
- }
- .limimg{max-height:20em;max-width:20em;}
- </style>
-</head>
-<body style="background-color:#acf;">
- <div class="TText" style="font-size:2em"><a href="../../../">Chrisoft</a>::Picture Library</div>
- <div>
- <?php
- $startpage=0;
- if(!empty($_GET['p']))
- $startpage=intval($_GET['p']);
- $files=scandir("/var/www/html/libs/pictures/b/");
- for($i=$startpage*20,$c=count($files);$i<$c&&$i-$startpage*20<20;$i++)
- {
- if(!(strstr($files[$i],"jpg"))&&!(strstr($files[$i],"gif"))&&!(strstr($files[$i],"png")))continue;
- $ret=sprintf("
- <div class=\"inlinediv\"><a href=\"./b/%s\">
- <img class=\"limimg\" src=\"./b/%s\">
- <br>%s</a>
- </div>",$files[$i],$files[$i],$files[$i]);
- echo $ret;
- }
- $totalsp=count($files)/20+(count($files)%20==0?0:1)-1;
- $minsp=$startpage-5;if($minsp<0)$minsp=0;
- $maxsp=$startpage+6;if($maxsp>$totalsp)$maxsp=$totalsp;
- echo "<div style=\"text-align:center;\">";
- for($i=$minsp;$i<$maxsp;$i++)
- {
- if($i===$startpage)
- echo $i+1 . ' ';
- else
- {
- $t=sprintf("<a href=\"./plibb.php?p=%d\">%d</a> ",$i,$i+1);
- echo $t;
- }
- }
- echo "</div>";
- ?>
- </div>
-</body>
-</html>
diff --git a/rbusif/index.html b/rbusif/index.html
new file mode 100644
index 0000000..c962970
--- /dev/null
+++ b/rbusif/index.html
@@ -0,0 +1,75 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>
+Chrisoft::RBUSIF
+</title>
+<link rel=stylesheet href='../common.css' type='text/css'>
+<style type="text/css">
+body
+{
+ color: #FFF;
+ background: #0A0A0A;
+}
+h1, h2, h3, h4, h5, h6
+{
+ font-weight: normal;
+}
+</style>
+</head>
+<body class="TText">
+<h1
+id="chrisoftrbusif"><a href="../">Chrisoft</a>::<a href="./">RBUSIF</a></h1>
+<p>Information on R-BUS / RMDB 2 and my related projects.</p>
+<p>Projects and technical information provided on this page and all
+linked pages are not approved or endorsed by Roland.</p>
+<hr>
+<p>R-BUS (also called RMDB2 / RMDB II on older products) is an obsolete
+proprietary interconnect format that carries bidirectional MIDI and
+digital audio data created by Roland. It was used on Roland products
+released from the late 90s to early 2000s. (Excerpt from the detailed
+information page)</p>
+<p>For more detailed information on the R-BUS format, including electric
+and signaling specifications, please visit <a
+href="https://chrisoft.org/blog/post/2024-02-02.html">this page</a>.</p>
+<p>A (currently very short) list of my projects related to R-BUS:</p>
+<table>
+<tr>
+<th>
+Name
+</th>
+<th>
+Image
+</th>
+<th>
+Description
+</th>
+<th>
+Resources
+</th>
+</tr>
+<tr>
+<td>
+RBUS-ADAT
+</td>
+<td style="text-align:center">
+<img src="//filestorage.chrisoft.org/blog/img/rbus-adat-cvc.png" width="40%">
+</td>
+<td>
+Record your XV-5080 without the cable clutter! This handy little board
+converts the 8-channel digital output on the XV-5080’s R-BUS port to the
+ADAT lightpipe format for easy recording with modern equipment.
+</td>
+<td>
+<a href="https://cgit.chrisoft.org/rbus-adat.git">Project
+Repository</a><br />
+<a
+href="https://filestorage.chrisoft.org/blog/data/rbus_adat_m.pdf">Manual</a><br />
+<a href="https://chrisoft.org/blog/post/2024-02-04.html">devlog</a>
+</td>
+</tr>
+</table>
+<hr>
+<p><a href="https://chrisoft.org/#about">Contact me!</a></p>
+</body>
+</html>
diff --git a/rbusif/index.md b/rbusif/index.md
new file mode 100644
index 0000000..0b9be86
--- /dev/null
+++ b/rbusif/index.md
@@ -0,0 +1,64 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>Chrisoft::RBUSIF</title>
+<link rel=stylesheet href='../common.css' type='text/css'>
+<style type="text/css">
+body
+{
+ color: #FFF;
+ background: #0A0A0A;
+}
+h1, h2, h3, h4, h5, h6
+{
+ font-weight: normal;
+}
+</style>
+</head>
+<body class="TText">
+# <a href="../">Chrisoft</a>::<a href="./">RBUSIF</a>
+
+Information on R-BUS / RMDB 2 and my related projects.
+
+Projects and technical information provided on this page and all linked pages
+are not approved or endorsed by Roland.
+
+<hr>
+
+R-BUS (also called RMDB2 / RMDB II on older products) is an obsolete
+proprietary interconnect format that carries bidirectional MIDI and digital
+audio data created by Roland. It was used on Roland products released from
+the late 90s to early 2000s. (Excerpt from the detailed information page)
+
+For more detailed information on the R-BUS format, including electric and
+signaling specifications, please visit [this page](https://chrisoft.org/blog/post/2024-02-02.html).
+
+A (currently very short) list of my projects related to R-BUS:
+
+<table>
+<tr>
+<th>Name</th><th>Image</th><th>Description</th><th>Resources</th>
+</tr>
+<tr>
+<td>RBUS-ADAT</td>
+<td style="text-align:center">
+<img src="//filestorage.chrisoft.org/blog/img/rbus-adat-cvc.png" width="40%"></td>
+<td>
+Record your XV-5080 without the cable clutter! This handy little board converts
+the 8-channel digital output on the XV-5080's R-BUS port to the ADAT lightpipe
+format for easy recording with modern equipment.
+</td>
+<td>
+[Project Repository](https://cgit.chrisoft.org/rbus-adat.git)
+[Manual](https://filestorage.chrisoft.org/blog/data/rbus_adat_m.pdf)
+[devlog](https://chrisoft.org/blog/post/2024-02-04.html)
+</td>
+</tr>
+</table>
+
+<hr>
+
+[Contact me!](https://chrisoft.org/#about)
+
+</body>
+</html>
diff --git a/theme0a.css b/theme0a.css
index ac5b599..c5bb30f 100644
--- a/theme0a.css
+++ b/theme0a.css
@@ -1,60 +1,22 @@
-body{
- background-color: #F9EFF6;
- background-image: url("/pattern0a.png");
- background-repeat: repeat;
- color: #000;
+:root{
+ --principal-bg: #F9EFF6;
+ --principal-fg: #000;
+ --secondary-bg: #EEE0E9;
+ --secondary-fg: #333;
+ --list-active-bg: #EEC0DD;
+ --list-highlighted-bg: #FCE;
+ --link-fg: #CF4AFF;
+ --link-visited-fg: #DA50FF;
+ --link-hover-fg: #DD40FF;
+ --link-active-fg: #EEAAFF;
+ --link-highlighted-fg: #EA0;
+ --interactive-bg: #C7B;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #D8C;
+ --interactive-active-bg: #E9D;
+ --interactive-disabled-bg: #999;
+ --widget-area-bg: rgba(204,204,204,0.6);
+ --slider-empty-bg: rgba(184,122,171,0.6);
+ --slider-filled-bg: #F0A0E0;
+ --bg-pattern: url("/pattern0a.png");
}
-#panel li a.active{
-background-color:#EEC0DD;
-}
-#panel li a:hover:not(.active){
-background-color:#FCE;
-}
-#panel,#footer{
- background-color:#EEE0E9;
- background-image: url("/pattern0a.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #333;
-}
-a.highlighted{color:#EA0 !important;}
-a:link{
-color:#CF4AFF;
-}
-a:visited{
-color:#DA50FF;
-}
-a:hover{
-color:#DD40FF;
-}
-a:active{
-color:#EEAAFF;
-}
-blockquote{
-border: 1px solid #333;
-}
-button,.fakebtn{
- color:white;
- background-color:#C7B;
-}
-button:hover,.fakebtn:hover{
- background-color:#D8C;
-}
-button:active,.fakebtn:active{
- background-color:#E9D;
-}
-button:disabled{
- background-color:#999;
-}
-input[type="text"]{
- color:#000;
- border-bottom-color:#C7B;
-}
-textarea{
- color:#000;
- border-color:#C7B;
-}
-.widgetbg{background-color:rgba(204,204,204,0.6);}
-.sliderb1{background-color:rgba(184,122,171,0.6);}
-.sliderb2{background-color:#F0A0E0;}
diff --git a/theme0b.css b/theme0b.css
index 0ac2a36..18c2c85 100644
--- a/theme0b.css
+++ b/theme0b.css
@@ -1,60 +1,22 @@
-body{
- background-color: #2F0933;
- background-image: url("/pattern0b.png");
- background-repeat: repeat;
- color: #FFF;
+:root{
+ --principal-bg: #2F0933;
+ --principal-fg: #FFF;
+ --secondary-bg: #440C48;
+ --secondary-fg: #738;
+ --list-active-bg: #849;
+ --list-highlighted-bg: #738;
+ --link-fg: #CF4AFF;
+ --link-visited-fg: #DA50FF;
+ --link-hover-fg: #DD40FF;
+ --link-active-fg: #EEAAFF;
+ --link-highlighted-fg: #FC0;
+ --interactive-bg: #746;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #958;
+ --interactive-active-bg: #A59;
+ --interactive-disabled-bg: #666;
+ --widget-area-bg: rgba(64,24,80,0.6);
+ --slider-empty-bg: rgba(163,108,152,0.6);
+ --slider-filled-bg: #C8B;
+ --bg-pattern: url("/pattern0b.png");
}
-#panel li a.active{
-background-color:#849;
-}
-#panel li a:hover:not(.active){
-background-color:#738;
-}
-#panel,#footer{
- background-color:#440C48;
- background-image: url("/pattern0b.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #738;
-}
-a.highlighted{color:#FC0 !important;}
-a:link{
-color:#CF4AFF;
-}
-a:visited{
-color:#DA50FF;
-}
-a:hover{
-color:#DD40FF;
-}
-a:active{
-color:#EEAAFF;
-}
-blockquote{
-border: 1px solid #738;
-}
-button,.fakebtn{
- color:white;
- background-color:#746;
-}
-button:hover,.fakebtn:hover{
- background-color:#958;
-}
-button:active,.fakebtn:active{
- background-color:#A59;
-}
-button:disabled{
- background-color:#666;
-}
-input[type="text"]{
- color:#FFF;
- border-bottom-color:#746;
-}
-textarea{
- color:#FFF;
- border-color:#746;
-}
-.widgetbg{background:rgba(64,24,80,0.6);}
-.sliderb1{background-color:rgba(163,108,152,0.6);}
-.sliderb2{background-color:#C8B;}
diff --git a/theme1a.css b/theme1a.css
index 142e5e3..927b5f9 100644
--- a/theme1a.css
+++ b/theme1a.css
@@ -1,60 +1,22 @@
-body{
- background-color: #FFF;
- background-image: url("/pattern1a.png");
- background-repeat: repeat;
- color: #000;
+:root{
+ --principal-bg: #FFF;
+ --principal-fg: #000;
+ --secondary-bg: #EEE;
+ --secondary-fg: #333;
+ --list-active-bg: #CEC;
+ --list-highlighted-bg: #DFD;
+ --link-fg: #1194FF;
+ --link-visited-fg: #20ACFF;
+ --link-hover-fg: #3FBFFF;
+ --link-active-fg: #CCCCFF;
+ --link-highlighted-fg: #EA0;
+ --interactive-bg: #4A4;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #5B5;
+ --interactive-active-bg: #6C6;
+ --interactive-disabled-bg: #999;
+ --widget-area-bg: rgba(204,204,204,0.6);
+ --slider-empty-bg: rgba(64,240,96,0.6);
+ --slider-filled-bg: #10C048;
+ --bg-pattern: url("/pattern1a.png");
}
-#panel li a.active{
-background-color:#CEC;
-}
-#panel li a:hover:not(.active){
-background-color:#DFD;
-}
-#panel,#footer{
- background-color:#EEE;
- background-image: url("/pattern1a.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #333;
-}
-a.highlighted{color:#EA0 !important;}
-a:link{
-color:#1194FF;
-}
-a:visited{
-color:#20ACFF;
-}
-a:hover{
-color:#3FBFFF;
-}
-a:active{
-color:#CCCCFF;
-}
-blockquote{
-border: 1px solid #333;
-}
-button,.fakebtn{
- color:white;
- background-color:#4A4;
-}
-button:hover,.fakebtn:hover{
- background-color:#5B5;
-}
-button:active,.fakebtn:active{
- background-color:#6C6;
-}
-button:disabled{
- background-color:#999;
-}
-input[type="text"]{
- color:#000;
- border-bottom-color:#4A4;
-}
-textarea{
- color:#000;
- border-color:#4A4;
-}
-.widgetbg{background-color:rgba(204,204,204,0.6);}
-.sliderb1{background-color:rgba(64,240,96,0.6);}
-.sliderb2{background-color:#10C048;}
diff --git a/theme1b.css b/theme1b.css
index 0e0d1aa..2374774 100644
--- a/theme1b.css
+++ b/theme1b.css
@@ -1,60 +1,22 @@
-body{
- background-color: #090933;
- background-image: url("/pattern1b.png");
- background-repeat: repeat;
- color: #FFF;
+:root{
+ --principal-bg: #090933;
+ --principal-fg: #FFF;
+ --secondary-bg: #116;
+ --secondary-fg: #338;
+ --list-active-bg: #449;
+ --list-highlighted-bg: #338;
+ --link-fg: #1194FF;
+ --link-visited-fg: #20ACFF;
+ --link-hover-fg: #3FBFFF;
+ --link-active-fg: #CCCCFF;
+ --link-highlighted-fg: #FC0;
+ --interactive-bg: #161;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #272;
+ --interactive-active-bg: #383;
+ --interactive-disabled-bg: #666;
+ --widget-area-bg: rgba(32,32,96,0.6);
+ --slider-empty-bg: rgba(49,184,73,0.6);
+ --slider-filled-bg: #0EA33D;
+ --bg-pattern: url("/pattern1b.png");
}
-#panel li a.active{
-background-color:#449;
-}
-#panel li a:hover:not(.active){
-background-color:#338;
-}
-#panel,#footer{
- background-color:#116;
- background-image: url("/pattern1b.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #338;
-}
-a.highlighted{color:#FC0 !important;}
-a:link{
-color:#1194FF;
-}
-a:visited{
-color:#20ACFF;
-}
-a:hover{
-color:#3FBFFF;
-}
-a:active{
-color:#CCCCFF;
-}
-blockquote{
-border: 1px solid #338;
-}
-button,.fakebtn{
- color:white;
- background-color:#161;
-}
-button:hover,.fakebtn:hover{
- background-color:#272;
-}
-button:active,.fakebtn:active{
- background-color:#383;
-}
-button:disabled{
- background-color:#666;
-}
-input[type="text"]{
- color:#FFF;
- border-bottom-color:#161;
-}
-textarea{
- color:#FFF;
- border-color:#161;
-}
-.widgetbg{background:rgba(32,32,96,0.6);}
-.sliderb1{background-color:rgba(49,184,73,0.6);}
-.sliderb2{background-color:#0EA33D;}
diff --git a/theme2a.css b/theme2a.css
index 53a61b1..15bdabd 100644
--- a/theme2a.css
+++ b/theme2a.css
@@ -1,60 +1,22 @@
-body{
- background-color: #F9F2EF;
- background-image: url("/pattern2a.png");
- background-repeat: repeat;
- color: #000;
+:root{
+ --principal-bg: #F9F2EF;
+ --principal-fg: #000;
+ --secondary-bg: #EEE5E0;
+ --secondary-fg: #333;
+ --list-active-bg: #EED0C0;
+ --list-highlighted-bg: #FDC;
+ --link-fg: #C89738;
+ --link-visited-fg: #B89433;
+ --link-hover-fg: #D6B637;
+ --link-active-fg: #D6C589;
+ --link-highlighted-fg: #A0E;
+ --interactive-bg: #CA7;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #DB8;
+ --interactive-active-bg: #EC9;
+ --interactive-disabled-bg: #999;
+ --widget-area-bg: rgba(204,204,204,0.6);
+ --slider-empty-bg: rgba(184,152,110,0.6);
+ --slider-filled-bg: #DA6;
+ --bg-pattern: url("/pattern2a.png");
}
-#panel li a.active{
-background-color:#EED0C0;
-}
-#panel li a:hover:not(.active){
-background-color:#FDC;
-}
-#panel,#footer{
- background-color:#EEE5E0;
- background-image: url("/pattern2a.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #333;
-}
-a.highlighted{color:#A0E !important;}
-a:link{
-color:#C89738;
-}
-a:visited{
-color:#B89433;
-}
-a:hover{
-color:#D6B637;
-}
-a:active{
-color:#D6C589;
-}
-blockquote{
-border: 1px solid #333;
-}
-button,.fakebtn{
- color:white;
- background-color:#CA7;
-}
-button:hover,.fakebtn:hover{
- background-color:#DB8;
-}
-button:active,.fakebtn:active{
- background-color:#EC9;
-}
-button:disabled{
- background-color:#999;
-}
-input[type="text"]{
- color:#000;
- border-bottom-color:#CA7;
-}
-textarea{
- color:#000;
- border-color:#CA7;
-}
-.widgetbg{background-color:rgba(204,204,204,0.6);}
-.sliderb1{background-color:rgba(184,152,110,0.6);}
-.sliderb2{background-color:#DA6;}
diff --git a/theme2b.css b/theme2b.css
index 2f5964d..6208c0f 100644
--- a/theme2b.css
+++ b/theme2b.css
@@ -1,60 +1,22 @@
-body{
- background-color: #1F1205;
- background-image: url("/pattern2b.png");
- background-repeat: repeat;
- color: #FFF;
+:root{
+ --principal-bg: #1F1205;
+ --principal-fg: #FFF;
+ --secondary-bg: #291806;
+ --secondary-fg: #873;
+ --list-active-bg: #974;
+ --list-highlighted-bg: #863;
+ --link-fg: #FF924A;
+ --link-visited-fg: #FF8A50;
+ --link-hover-fg: #FFA040;
+ --link-active-fg: #FFD7AA;
+ --link-highlighted-fg: #A1F;
+ --interactive-bg: #963;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #A74;
+ --interactive-active-bg: #B85;
+ --interactive-disabled-bg: #666;
+ --widget-area-bg: rgba(80,64,24,0.6);
+ --slider-empty-bg: rgba(163,133,98,0.6);
+ --slider-filled-bg: #C96;
+ --bg-pattern: url("/pattern2b.png");
}
-#panel li a.active{
-background-color:#974;
-}
-#panel li a:hover:not(.active){
-background-color:#863;
-}
-#panel,#footer{
- background-color:#291806;
- background-image: url("/pattern2b.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #873;
-}
-a.highlighted{color:#A1F !important;}
-a:link{
-color:#FF924A;
-}
-a:visited{
-color:#FF8A50;
-}
-a:hover{
-color:#FFA040;
-}
-a:active{
-color:#FFD7AA;
-}
-blockquote{
-border: 1px solid #863;
-}
-button,.fakebtn{
- color:white;
- background-color:#963;
-}
-button:hover,.fakebtn:hover{
- background-color:#A74;
-}
-button:active,.fakebtn:active{
- background-color:#B85;
-}
-button:disabled{
- background-color:#666;
-}
-input[type="text"]{
- color:#FFF;
- border-bottom-color:#863;
-}
-textarea{
- color:#FFF;
- border-color:#863;
-}
-.widgetbg{background:rgba(80,64,24,0.6);}
-.sliderb1{background-color:rgba(163,133,98,0.6);}
-.sliderb2{background-color:#C96;}
diff --git a/theme3a.css b/theme3a.css
index dfbe17f..34a0610 100644
--- a/theme3a.css
+++ b/theme3a.css
@@ -1,60 +1,22 @@
-body{
- background-color: #EFF4F9;
- background-image: url("/pattern3a.png");
- background-repeat: repeat;
- color: #000;
+:root{
+ --principal-bg: #EFF4F9;
+ --principal-fg: #000;
+ --secondary-bg: #E0E7EE;
+ --secondary-fg: #333;
+ --list-active-bg: #C0D7EE;
+ --list-highlighted-bg: #CEF;
+ --link-fg: #3898C8;
+ --link-visited-fg: #338CB8;
+ --link-hover-fg: #37A1D6;
+ --link-active-fg: #89BCD6;
+ --link-highlighted-fg: #A0E;
+ --interactive-bg: #6BD;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #6CF;
+ --interactive-active-bg: #9DF;
+ --interactive-disabled-bg: #999;
+ --widget-area-bg: rgba(204,204,204,0.6);
+ --slider-empty-bg: rgba(153,221,255,0.6);
+ --slider-filled-bg: #6BD;
+ --bg-pattern: url("/pattern3a.png");
}
-#panel li a.active{
-background-color:#C0D7EE;
-}
-#panel li a:hover:not(.active){
-background-color:#CEF;
-}
-#panel,#footer{
- background-color:#E0E7EE;
- background-image: url("/pattern3a.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #333;
-}
-a.highlighted{color:#A0E !important;}
-a:link{
-color:#3898C8;
-}
-a:visited{
-color:#338CB8;
-}
-a:hover{
-color:#37A1D6;
-}
-a:active{
-color:#89BCD6;
-}
-blockquote{
-border: 1px solid #333;
-}
-button,.fakebtn{
- color:white;
- background-color:#6BD;
-}
-button:hover,.fakebtn:hover{
- background-color:#6CF;
-}
-button:active,.fakebtn:active{
- background-color:#9DF;
-}
-button:disabled{
- background-color:#999;
-}
-input[type="text"]{
- color:#000;
- border-bottom-color:#6BD;
-}
-textarea{
- color:#000;
- border-color:#6BD;
-}
-.widgetbg{background-color:rgba(200,204,204,0.6);}
-.sliderb1{background-color:rgba(153,221,255,0.6);}
-.sliderb2{background-color:#6BD;}
diff --git a/theme3b.css b/theme3b.css
index 143f081..4ef8f12 100644
--- a/theme3b.css
+++ b/theme3b.css
@@ -1,60 +1,22 @@
-body{
- background-color: #051933;
- background-image: url("/pattern3b.png");
- background-repeat: repeat;
- color: #FFF;
+:root{
+ --principal-bg: #051933;
+ --principal-fg: #FFF;
+ --secondary-bg: #082040;
+ --secondary-fg: #358;
+ --list-active-bg: #469;
+ --list-highlighted-bg: #358;
+ --link-fg: #4A92FF;
+ --link-visited-fg: #508AFF;
+ --link-hover-fg: #40A0FF;
+ --link-active-fg: #AAD7FF;
+ --link-highlighted-fg: #F1C;
+ --interactive-bg: #469;
+ --interactive-fg: #FFF;
+ --interactive-hover-bg: #57A;
+ --interactive-active-bg: #68B;
+ --interactive-disabled-bg: #666;
+ --widget-area-bg: rgba(24,48,80,0.6);
+ --slider-empty-bg: rgba(85,119,170,0.6);
+ --slider-filled-bg: #469;
+ --bg-pattern: url("/pattern3b.png");
}
-#panel li a.active{
-background-color:#469;
-}
-#panel li a:hover:not(.active){
-background-color:#358;
-}
-#panel,#footer{
- background-color:#082040;
- background-image: url("/pattern3b.png");
- background-repeat: repeat;
-}
-#content .block{
-border: 1px solid #358;
-}
-a.highlighted{color:#F1C !important;}
-a:link{
-color:#4A92FF;
-}
-a:visited{
-color:#508AFF;
-}
-a:hover{
-color:#40A0FF;
-}
-a:active{
-color:#AAD7FF;
-}
-blockquote{
-border: 1px solid #358;
-}
-button,.fakebtn{
- color:white;
- background-color:#469;
-}
-button:hover,.fakebtn:hover{
- background-color:#57A;
-}
-button:active,.fakebtn:active{
- background-color:#68B;
-}
-button:disabled{
- background-color:#666;
-}
-input[type="text"]{
- color:#FFF;
- border-bottom-color:#469;
-}
-textarea{
- color:#FFF;
- border-color:#469;
-}
-.widgetbg{background:rgba(24,48,80,0.6);}
-.sliderb1{background-color:rgba(85,119,170,0.6);}
-.sliderb2{background-color:#469;}