yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/01 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
日本中で最も数学能力が低い実装者によるQRコードBCH符号実装
2009/03/09(Mon)19:50:54
日本中で最も数学能力が低い実装者によるQRコードBCH符号実装
 QRコードのエラー訂正に使用されているリード・ソロモン符号の作成方法、及びガロア拡大体などの付随する技術の習得は終わりましたが、QRコードの厄介な問題はまだ解決したわけではありません。QRコードにはまだ「BCH符号」なる意味不明なものが残っているのです。
 ところで、この「BCH符号」とは一体何なのでしょうか。いつもながら、まずはWikipediaの当該項目を読んでみましょう。「BCH」が発見者のイニシャルにちなむものであることや、リード・ソロモン同様にエラー訂正に使用されることが書いてあります。どうやらこれもエラー訂正に使用する手法のようです。
 ところが、それ以降の記述は何の役にも立ちません。一体何を書いているのかさっぱり分からないのです。Wikipediaの数学項目といえば、日本語版よりも英語版に良質な記事がそろっているのですが、残念ながら今回ばかりは英語版もまた理解不能です。Wikipedia日本語版の数学関係の項目が役に立ったためしなど一度たりともありませんが、英語版が役に立たないとなると、手の出しようがありません。
 現段階で何も分からない以上、この厄介なものを習得するにあたっては、まずは予備知識が必要でしょう。BCH符号は前述の通りエラー訂正符号の一種で、色々と派生型もあるようですが、QRコードで使用されているものは「データの2倍のコードを付加し、20%程度の復元能力を得る」コードです。エラー訂正のために元のデータの2倍もの容量を使用するのは無駄なようにも見えますが、重要かつ短いデータに対して使用するのであれば、利用価値はあるようです。
 仕様書を読んでみたところ、この符号は以下の部分に使用されているそうです。

1.マスクの種類とエラー訂正レベルの指定(5ビット)
2.コードの大きさがバージョン7以上の場合のみ、バージョン情報(6ビット)

 BCH符号は元のビットの倍の容量を要しますので、これらの符号はそれぞれ10ビット及び12ビットとなります。いずれも読み取りが必須とされているデータで、かつデータ量もさほど大きくありませんので、BCH符号が用いられているようです。
 それでは本題、BCH符号とは一体どのようにして作成するのでしょうか。これを理解する上でおすすめなのが、リード・ソロモン符号の際にもお世話になった久留米工業大学教授の渋谷氏のQRコード解説ページ、特に誤り訂正の解説PDFです。また、仕様を確認する以外に何の使い道もない、読み手の立場を一切考えていない「あの」仕様書も、手元にあった方が便利です。今回ばかりは付録に5ビット及び6ビットの場合の符号表が全部記載されているため、BCH符号の意味が理解できなかったとしても、これを丸写しすれば変換自体は可能です。
 この程度のビット数であれば、5ビットのデータは2^5 = 32パターンしかありませんので、十分に列挙できる範囲です。6ビットでは全パターンを網羅すれば64パターンと少々多いものの、バージョン情報の明記が必要になるのはバージョン7からですし、最大のコードはバージョン40ですので、6ビットの値が取る範囲は7〜40に限られ、実質的に使用する符号は34パターンにしかなりません。
 しかし、この両方をひたすら列挙するとなると手間ですし、応用も利きません。5ビット及び7〜40の範囲の6ビットはともかくとして、仮にこれ以外のビットのデータが必要になったり、7未満や41以上の6ビットのデータが必要となれば、手の出しようがありません。何とかBCH符号なるものの計算方法を理解し、算出するプログラムを書いてしまいたいものです。
 幸いにも資料や仕様書はありますが、読んで理解できなければ同じです。RS符号の際には半ばカンと開発思想のみを頼みにして、何とか生成プログラムを書くところまでこぎつけましたが、果たして「二匹目のドジョウ」など存在するのでしょうか。
 まずは久留米工業大学の渋谷氏のサイトにあるBCH符号のリストを見てみました。これは仕様書の付録にあるのと同様の、5ビットのBCH符号全32種のリストなのですが、ここには同時に次のように書いてありました。

5 bit の情報に対して,10 bit の誤り訂正ビットを作ります.5 bit の与え方は 32 通りしかないので,全部書いても大したことはありません.いちいち計算するよりこの表を使った方が楽です
(強調は引用者による)

 これはまさか、「開発するのはやめておけ」というお達しなのでしょうか。
 リストを見てみても、一体何が何なのかさっぱり分かりません。以下にリストの先頭のいくつかを記載しておきますが(このリストは渋谷氏のサイトからの引用ではなく、後述するプログラムで作成したものです)、一見する限りでは共通項と呼べるようなものはなく、完全に混沌としています。

データ データ2進 符号2進
0 00000 0000000000
1 00001 0100110111
2 00010 1001101110
3 00011 1101011001
4 00100 0111101011
5 00101 0011011100
(後略...)

 見たところ、RS符号のように「魔法の変化」が発生するわけでもなさそうです。一体どのような原理で作られているのでしょうか。
 ひとまず仕様書を読んでみます。それにしても、この仕様書はPDFの制限によってクリップボードへのコピーが禁止されているため、引用が非常にやりづらくて困ります。コピーを禁止して情報の流通を妨げるのは、やはり日本の技術を衰退させるためでしょうか。
 なお、以下に出てくる足し算は、すべてXOR演算です。ビットには1と0の2つしかないため、1と1を足しても決して2にはならず、「1 + 1 = 0」となります。

C.1 誤り訂正ビット計算 Bose-Chaudhuri-Hocquenghem (15, 5) 符号を誤り訂正として使用する。データビット文字列を係数とする多項式を生成多項式G(x) =x^10+x^8+x^5+x^4+x^2+x+1で除算する。剰余多項式の係数文字列をデータビット文字列に付加し、(15, 5)BCH符号文字列を形成する。

 相変わらず、何を書いているのか分かりません。ただ、ここで「生成多項式」なる存在が明らかになりました。

G(x) = x^10 + x^8 + x^5 + x^4 + x^2 + x + 1

 何に使うのかは分かりませんが、重要なものではありそうです。
 それでは、一体どのようにしてBCH符号を求めるのでしょうか。仕様書と渋谷氏のPDFに異口同音に書いてあるらしいことを、順を追って考えてみます。ただし、いずれも5ビットの場合とします。

1.エラー訂正を入れるとデータは15ビットになるため、まずデータ5ビットをその先頭5ビットとする
 仕様書では「00101」がサンプルデータとして用いられていますので、これをそのまま流用して考えてみます。このデータをx^wに当てはめると、まずは以下のようになります。

x^4 x^3 x^2 x^1 1
0 0 1 0 1
(「1 = x^0」です。念のため)

 これを15ビットとし、先頭5ビットにデータを持ってきた場合、以下のようになります。

x^14 x^13 x^12 x^11 x^10 x^9以下全部
0 0 1 0 1 0

 これで「00101」が「x^12 + x^10」になりました。

2.上で求めた値を生成多項式で割る
 生成多項式は先ほど出てきましたが、これです。

G(x) = x^10 + x^8 + x^5 + x^4 + x^2 + x + 1

 先ほどの「x^12 + x^10」をこれで割り、余剰を得るのだそうです。このような式ばかりのものをどのようにして割れとおっしゃるのでしょうか
 やはり異口同音に述べられていることによれば、これがその式なのだそうです。完全に人知を超えています。カッコでくくられた部分は生成多項式として、後ろの部分は意味不明です。

x^12 + x^10 = x^2(x^10 + x^8 + x^5 + x^4 + x^2 + x + 1) + x^7 + x^6 + x^4 + x^3 + x^2

3.ビット化して値を算出する
 まず上記のうち、後ろの部分をビット化します。「0011011100」です。これの先頭に元のデータを連結すると、「00101 + 0011011100 = 001010011011100」となり、これがBCH符号なのだといいます。

 何が何だかさっぱり分かりません。計算式自体はRS符号よりも単純そうですが、意味が分からなくてはどうにもなりません。非常に困りましたので、ひとまず紙の上で算出してみました。
 まず(1)の手順は分かります。ただ単に「00101」のデータの末尾に10ビット加えて「001010000000000」にするだけです。実装上はただビットを左に10個シフトするだけですので、苦労する要素はありません。これで「x^12 + x^10」が得られます。
 問題は(2)の手順です。この式の意味が全く分からないのです。

x^12 + x^10 = x^2(x^10 + x^8 + x^5 + x^4 + x^2 + x + 1) + x^7 + x^6 + x^4 + x^3 + x^2

 左辺値は分かります。先ほどのビットです。右辺値のうち、最初のカッコの部分も分かります。これは生成多項式です。生成多項式はそれを使うべきと定められている定数のようなものですから、この内容に疑問を持つ必要はありません。円周率が3.14なのと似たようなものです。
 分からない点は2つあります。まず生成多項式がなぜかx^2倍されている点、それから生成多項式の右側の式です。x^2なるものがどこから登場したのか全く不明ですし、「x^7 + x^6 + x^4 + x^3 + x^2」が何なのかも分かりません。
 手がかりも何もありませんので、ひとまず計算を行ってみましょう。おそらく「x^2(x^10 + x^8 + x^5 + x^4 + x^2 + x + 1)」は計算できるはずです。指数がついた代数同士を掛け合わせる際には、指数を足し算すれば良いのですから、

x^2(x^10 + x^8 + x^5 + x^4 + x^2 + x + 1) = x^12 + x^10 + x^7 + x^6 + x^4 + x^3 + x^2

 何ということでしょうか。謎が解けてしまいました。これでBCH符号の作り方が判明しました。

- データ エラー訂正
x^w 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
データ 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0
G(x) * x^2 0 0 1 0 1 0 0 1 1 0 1 1 1 0 0
XOR 0 0 0 0 0 0 0 1 1 0 1 1 1 0 0

 この通り、演算結果からはx^12とx^10が消滅し、エラー訂正符号として「0011011100」が残りました(「XOR」の下10桁)。
 それでは、「00100」を符号化する場合はどうなるのでしょうか。「00101」の場合とあまり違いはなさそうですので、まずは以上と同じ手順でやってみます。00100は「x^12」ですから、

- データ エラー訂正
x^w 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
データ 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
G(x) * x^2 0 0 1 0 1 0 0 1 1 0 1 1 1 0 0
XOR 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0

 こうなります。
 しかし、ここで問題が発生します。「XOR」の行を見てみると、「000010011011100」となってしまっています。エラー訂正符号は10桁でなければなりませんが、これでは11桁必要になってしまいます。かといって、この11桁目を無視していては、エラー訂正符号の値が「00101」の場合と全く同じになりますので、何とかしなければなりません。一体どうしたものでしょうか。
 鋭い方ならもうお気づきでしょうが、せっかくx^12をなくしたはずが、今度はx^10が出現して邪魔なのですから、再び生成多項式を持ち出して演算し、x^10を消してやれば良いのです。先ほどはx^12に対処するためにG(x) * x^2を使用しましたが、今回はx^10が問題なのですから、生成多項式「x^10 + x^8 + x^5 + x^4 + x^2 + x + 1」をそのまま使用できそうです。

- データ エラー訂正
x^w 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
先の結果 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0
G(x) 0 0 0 0 1 0 1 0 0 1 1 0 1 1 1
XOR 0 0 0 0 0 0 1 1 1 1 0 1 0 1 1

 これで無事に結果が得られました。この通り、エラー訂正符号は「0111101011」です。
 何のことはありません。BCH符号といいますものは、単に以下のようなパズルゲームに過ぎないのです。はっきり言って数学知識など全く必要ありません

問題
 ここに15個のスイッチが並んでいます。左の5個のスイッチは、パズルを始めるまではONかOFFか分かりません。右の10個のスイッチは必ずOFFになっています。
 プレイヤーが操作できるスイッチは左側の5個だけです。スイッチを切り替えると、操作したそのスイッチの他、それより右にある2、5、6、8、9、10個目のスイッチの状態も切り替わります。もともとがONならOFF、OFFならONとなります。
 左側のすべてのスイッチをOFFにしてください。

 ただこれだけです。左側のスイッチをすべてOFFにした際、右側10個のスイッチがそのままエラー訂正符合となります。スイッチを押した際に「そのスイッチ及び右の2、5、6、8、9、10個目のスイッチの状態が切り替わる」のは、単に生成多項式「x^10 + x^8 + x^5 + x^4 + x^2 + x + 1」のx^10を「押したスイッチ」とみなしただけです。生成多項式を厳密に解釈すれば、「押したスイッチより右側10個目にあるスイッチを基準にして、そこから左側の10、8、5、4、2、1、0個目のスイッチが切り替わる」とでもなるのでしょうが、この説明ではややこしいだけでしょう。ただ、実装時にはこの方法を使用します。
 この問題の解き方は実に簡単です。どのスイッチを押したとしても、それより左側のスイッチは切り替わらないわけですから、左側から順にONになっているスイッチを押していくだけです。
 以下にJavaScriptによるサンプルをご用意しました。Internet Explorer 6とFirefox 2で動作を確認しています。

- データ エラー訂正
スイッチ
操作 -


 最初に「シャッフル」ボタンを押してください。ボタンを押すたびにランダムに5ビットのデータが与えられます。操作ボタンを使ってスイッチの状態を反転し、左側5個のスイッチをすべてOFFにしてください。その際の右側のスイッチの状態がそのままエラー訂正符合となります。

 これがBCH符号の正体です。何とかBCH符号の変換を行おうと様々なサイトをめぐり、それでも理解できずにこのページにたどり着いた方は、面食らっているのではないでしょうか。仕様書やちまたの解説が、いかに要点をはずして難しく書いているかが分かります
 したがって、実装など考える必要もないほど簡単です。以下のJSPコードはBCH符号(データ5ビット、エラー訂正10ビット)のリストを生成します。
<%@page contentType="text/html;charset=Shift_JIS" %>

<%!
private String decToBin(int dec , int bit){
	StringBuffer buf = new StringBuffer(bit);
	for(int i = bit - 1; i >= 0; i--)
		buf.append((dec >> i) & 1);

	return buf.toString();
}

// data : データ
// len : データの長さ
// elen : エラー訂正データの長さ
// g : 生成多項式
private int makeBCH(int data , int len , int elen , int g){
	int result = data << elen;

	// データ部分のビットを読む
	for(int i = len - 1; i >= 0; i--){
		// ビットが1なら生成多項式を加算
		if((result & (1 << (i + elen))) != 0)
			result ^= (g << i);
	}

	return result;
}
%>

<html>
<head>
<title>BCH List</title>
</head>

<body>
 BCH 符号のリスト

<table border="1">
<tr>
<td bgcolor="#CCDDFF">データ</td>
<td bgcolor="#CCDDFF">符号</td>
<td bgcolor="#CCDDFF">データ2進</td>
<td bgcolor="#CCDDFF">符号2進</td>
<td bgcolor="#CCDDFF">全2進</td>
</tr>

<%
int data_bit = 5;	// データビット数
int ec_bit = 10;	// エラー訂正ビット数
int g = (1 << 10) | (1 << 8) | (1 << 5) |
	(1 << 4) | (1 << 2) | (1 << 1) | 1;	// 生成多項式

int max = (int)Math.pow(2 , data_bit);

for(int i = 0; i < max; i++){
	int value = makeBCH(i , data_bit , ec_bit , g);

%>

<tr>
<td><%=i%></td>
<td><%=value%></td>
<td><%=decToBin(i , data_bit)%></td>
<td><%=decToBin(value , ec_bit)%></td>
<td><%=decToBin((i << ec_bit) ^ value , data_bit + ec_bit)%></td>
</tr>

<%
}
%>

</table>

</body>
</html>
 これを実行すると、以下のような表が得られます。

(データ5ビット、エラー訂正10ビットの表)
データ 符号 データ2進 符号2進 全2進
0 0 00000 0000000000 000000000000000
1 311 00001 0100110111 000010100110111
2 622 00010 1001101110 000101001101110
3 857 00011 1101011001 000111101011001
4 491 00100 0111101011 001000111101011
5 220 00101 0011011100 001010011011100
6 901 00110 1110000101 001101110000101
7 690 00111 1010110010 001111010110010
8 982 01000 1111010110 010001111010110
9 737 01001 1011100001 010011011100001
10 440 01010 0110111000 010100110111000
11 143 01011 0010001111 010110010001111
12 573 01100 1000111101 011001000111101
13 778 01101 1100001010 011011100001010
14 83 01110 0001010011 011100001010011
15 356 01111 0101100100 011110101100100
16 667 10000 1010011011 100001010011011
17 940 10001 1110101100 100011110101100
18 245 10010 0011110101 100100011110101
19 450 10011 0111000010 100110111000010
20 880 10100 1101110000 101001101110000
21 583 10101 1001000111 101011001000111
22 286 10110 0100011110 101100100011110
23 41 10111 0000101001 101110000101001
24 333 11000 0101001101 110000101001101
25 122 11001 0001111010 110010001111010
26 803 11010 1100100011 110101100100011
27 532 11011 1000010100 110111000010100
28 166 11100 0010100110 111000010100110
29 401 11101 0110010001 111010110010001
30 712 11110 1011001000 111101011001000
31 1023 11111 1111111111 111111111111111

 ここまでは5ビットのデータのBCH符号を扱ってきましたが、QRコードでは6ビットのデータのBCH符号も生成しなければならない場合があります。QRコードのバージョン6までは必要ないのですが、バージョン7以上ではバージョン情報をコード内に付加しなければならず、これのエラー訂正としてBCH符号が用いられています。この情報に使用されるデータ量が6ビットで、算出されるエラー訂正符号が12ビット、合計長が18ビットとなります。
 とはいえ、これも5ビットの場合と変わるところはありません。単に「スイッチの問題」を解くだけです。ただし、5ビットの場合とは生成多項式が異なっていますので、スイッチを切り替えた際の変化パターンが異なります。
 以下、仕様書からの引用です。

D.1 誤り訂正ビット計算 Bose-Chaudhuri-Hocquenghem (18, 6) 符号を誤り訂正として使用する。データビット文字列を係数とする多項式を生成多項式 G(x) =x^12+x^11+x^10+x^9+x^8+x^5+x^2+1 で除算する。

 なるほど、今回の生成多項式は

G(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1

 なのですか。これさえ分かれば実装は簡単です。
 先ほどのJSPの変数部分を、次のように書き換えます。
int data_bit = 6;	// データビット数
int ec_bit = 12;	// エラー訂正ビット数
int g = (1 << 12) | (1 << 11) | (1 << 10) |
	(1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | 1;	// 生成多項式
 これでBCH符号・全64種が得られます。

(データ6ビット、エラー訂正12ビットの表)
データ 符号 データ2進 符号2進 全2進
0 0 000000 000000000000 000000000000000000
1 3877 000001 111100100101 000001111100100101
2 367 000010 000101101111 000010000101101111
3 3658 000011 111001001010 000011111001001010
4 734 000100 001011011110 000100001011011110
5 3579 000101 110111111011 000101110111111011
6 945 000110 001110110001 000110001110110001
7 3220 000111 110010010100 000111110010010100
8 1468 001000 010110111100 001000010110111100
9 2713 001001 101010011001 001001101010011001
10 1235 001010 010011010011 001010010011010011
11 3062 001011 101111110110 001011101111110110
12 1890 001100 011101100010 001100011101100010
13 2119 001101 100001000111 001101100001000111
14 1549 001110 011000001101 001110011000001101
15 2344 001111 100100101000 001111100100101000
16 2936 010000 101101111000 010000101101111000
17 1117 010001 010001011101 010001010001011101
18 2583 010010 101000010111 010010101000010111
19 1330 010011 010100110010 010011010100110010
20 2470 010100 100110100110 010100100110100110
21 1667 010101 011010000011 010101011010000011
22 2249 010110 100011001001 010110100011001001
23 2028 010111 011111101100 010111011111101100
24 3780 011000 111011000100 011000111011000100
25 481 011001 000111100001 011001000111100001
26 4011 011010 111110101011 011010111110101011
27 142 011011 000010001110 011011000010001110
28 3098 011100 110000011010 011100110000011010
29 831 011101 001100111111 011101001100111111
30 3445 011110 110101110101 011110110101110101
31 592 011111 001001010000 011111001001010000
32 2517 100000 100111010101 100000100111010101
33 1776 100001 011011110000 100001011011110000
34 2234 100010 100010111010 100010100010111010
35 1951 100011 011110011111 100011011110011111
36 2827 100100 101100001011 100100101100001011
37 1070 100101 010000101110 100101010000101110
38 2660 100110 101001100100 100110101001100100
39 1345 100111 010101000001 100111010101000001
40 3177 101000 110001101001 101000110001101001
41 844 101001 001101001100 101001001101001100
42 3334 101010 110100000110 101010110100000110
43 547 101011 001000100011 101011001000100011
44 3767 101100 111010110111 101100111010110111
45 402 101101 000110010010 101101000110010010
46 4056 101110 111111011000 101110111111011000
47 253 101111 000011111101 101111000011111101
48 685 110000 001010101101 110000001010101101
49 3464 110001 110110001000 110001110110001000
50 962 110010 001111000010 110010001111000010
51 3303 110011 110011100111 110011110011100111
52 115 110100 000001110011 110100000001110011
53 3926 110101 111101010110 110101111101010110
54 284 110110 000100011100 110110000100011100
55 3641 110111 111000111001 110111111000111001
56 1809 111000 011100010001 111000011100010001
57 2100 111001 100000110100 111001100000110100
58 1662 111010 011001111110 111010011001111110
59 2395 111011 100101011011 111011100101011011
60 1487 111100 010111001111 111100010111001111
61 2794 111101 101011101010 111101101011101010
62 1184 111110 010010100000 111110010010100000
63 2949 111111 101110000101 111111101110000101

 これでBCH符号の実装も終了しました。この通り、開発者に数学など不要なのです。いつ、どこで、誰が、何のために、開発者は理系などと言い出したのでしょうか。
 RS符号は私より数学能力が高ければ確実に実装できますが、BCH符号は私より数学能力が低くても確実に実装できます(小学生・就学前以外でそのような人がいるのかは不明ですが)。数学的で意味不明な記述と、政治家の詭弁にはだまされないようにしましょう。
カテゴリ [開発魔法] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -