2013年12月21日土曜日

Nexus 5がWEB版Google Playに表示されない問題及びAndroidデバイスマネージャーに表示されない問題をGoogleに問い合わせてみた話 ( 解決しませんでした )

最初に言っておきますが、解決しませんでした。

ただ、原因が分かった事と、場合によっては改善するかもしれない方法を中の人にご教授頂いたので、それをここに載せておきたいと思います。

Nexus 5がWEB版Google Playに表示されない理由とAndroidデバイスマネージャーに表示されない理由


Nexus 5が上記の問題を引き起こす原因は、Android 4.4にその原因がある。Android 4.4 KitKatにおいて、Google Play開発者サービスに包含されるアプリケーションであるGoogle設定の位置情報の管理方法が変更されたことが直接の原因だ。

Android 4.3のGoogle設定->位置情報

Android 4.4のGoogle設定->位置情報

WEB版Google Playを介して端末にアプリケーションや、その他のコンテンツをダウンロードするには、「位置情報へのアクセス」する必要があるが、「Android 4.4 を搭載する Nexus 端末では利用できない」。

参考 : [Google設定] での位置情報の管理 - Google アカウント ヘルプ

Google Play ヘルプのお問い合わせから問い合わせて、Google Playストアに表示されない問題に対する4つの解決方法(後述)を試した後、Androidのバージョン、Google Playストアのビルドバージョン等の追加情報と共に再度問い合わせた所、Google設定で位置情報アクセスが利用出来ないことが原因である、と伝えられた。

非常に迅速な対応をして頂き、理由が明確に分かったのも素晴らしいが、Android 4.4にバージョンアップしたことで利用できなくなる、というのは甚だ残念だ。出来れば早めに改善して頂けると喜ばしい。

Androidデバイスマネージャーを利用出来ないのも同じ理由だろう。どう考えても同アプリは位置情報へのアクセスが必須であるので、その為利用できないのだろう。


Androidデバイスマネージャーは上記の画面で延々とロードし続ける。

もしNexus 5で上記の問題が発生していない方、解決した方は連絡下さると嬉しいです。

問題を解決しうる4つの方法

残念ながらAndroid 4.4では解決しなかったが、4.3以下では以下の方法で解決しうることをGoogleサポートの中の人からご享受いただいたのでここに載せる(原文ママ)

-------

【 A 】 アカウントの入れ直し
※アカウントの情報が消えることはございませんので、ご安心ください。

1. メニュー > [設定] > [アカウントと同期] に移動します。

2. 削除するアカウントの名前をタップして、メニュー > [アカウントを削除] をタップします。

アカウントの削除後に、次の手順を行うことで再度アカウントを端末に追加することができます。

3. メニュー > [設定] > [アカウントと同期] に移動し、[アカウントを追加] をタップします。

4. 表示される手順どおりにアカウント情報を入力し再度追加します。

-------

【 B 】 端末の再起動

-------

【 C 】 Play ストア アプリのキャッシュとデータの消去

1. [設定] > [アプリ] > [すべて] を開きます。

2. 下にスクロールして [Google Play ストア] をタップします。

3. [キャッシュを消去] [データを消去] をタップします。

-------

【 D 】 Play ストアのアップデートをアン インストール

1. [設定] > [アプリ] > [すべて] を開きます。

2. 下にスクロールして [Google Play ストア] をタップします。

3. [アップデートのアン インストール] をタップし、出荷状態に戻します。

4. 再度 Play ストア アプリ を開き、しばらくすると、最新版に 更新されます。

-------

2013年12月14日土曜日

初めてテンプレートメタプログラミングに触れてみた

初めてテンプレートメタプログラミングというものに触れた。 正直今でも何が起こっているのかは理解できてない。 以下はテンプレートメタプログラミングで整数の整数乗を求めるプログラム。 尚、型は全てint。

#include <iostream>

// default
template< int base, int iexp, bool = iexp >= 0 >
struct Pow{
	// fallback for iexp < 0
	static const int value = 0;
};

// specialization for iexp >= 0
template< int base, int iexp >
struct Pow< base, iexp, true >{
	// base ^ iexp = base * base ^ ( iexp - 1 )
	static const int value = base * Pow< base, iexp - 1 >::value;
};

// specialization for iexp == 0
template< int base >
struct Pow< base, 0, true >{
	// base ^ 0 = 1
	static const int value = 1;
};

int main( void ){
	std::cout << "2 ^ -2 = " << Pow< 2, -2 >::value << std::endl;
	std::cout << "2 ^ -1 = " << Pow< 2, -1 >::value << std::endl;
	std::cout << "2 ^  0 = " << Pow< 2,  0 >::value << std::endl;
	std::cout << "2 ^  1 = " << Pow< 2,  1 >::value << std::endl;
	std::cout << "2 ^  2 = " << Pow< 2,  2 >::value << std::endl;

	return 0;
}
コンパイル時定数では浮動小数点実数は扱えない(constexpr等の例外を除く)らしい(嘘をついているかも)ので、 扱う変数valueの型はstatic const int型としている。

そのため、負数乗は全て0とした。 iexpが0未満の時は全てデフォルトの定義になる。

0乗は1、自然数乗は再帰を行うように定義している。

よく分かっていないのは bool = iexp >= 0 という式。 型だけ書いて変数名(識別子)を書かないのはテンプレートだから許されるのだろうか。 おそらく、関数のプロトタイプ宣言をする時に、形名だけを書くのと似たようなものだろうと思っている。 どちらも同じ「引数」だし。

あと、2つ目の定義と3つ目の定義のどちらを使用するのかをコンパイラがどうやって決めているのかもよく分かんない。 C++怖い。

あ、間違いあったら教えて下さい。

2013.12.16追記 ※constexprが使える環境ならconstexprを使うべきと思われる。
このコードはMSVC++2008で書いたのでconstexprは使えなかった。

2013年11月24日日曜日

[ネタバレ] ECCO THE DOLPHIN 2の翻訳が英語と日本語訳で全く違う件について

ECCO THE DOLPHIN 2は私が特別に好きなゲームの一つである。
このゲームのラストでプレイヤーに提示される「SECRET PASSWORD」の意味が今の今まで分からず、
ふとしたきっかけで検索したら、以下のページを見つけた。

名作アルバム -『エコー・ザ・ドルフィン』-

セガの名作アルバムである。現在トップページからどのような経路で到達できるかは不明。
このコンテンツの中で興味深い記述を見つけた。
ローカライズを担当された長谷川亮一氏のインタビューだ。

P2
……私は機械的な翻訳は嫌だったので、無機質にならないように、血の通ってる翻訳がしたいと常々思っていました。だから、ただの翻訳だけでなく、プラスアルファとしてストーリーを語ったり、ルールの説明をしたり、かなりの情報を詰め込んだつもりです。
(引用ここまで)

P3
普通の本とか見て方眼紙に点を打つんですよ。(中略)向こうは何を打ってるのか全然わかってないわけですよ(笑)
(引用ここまで)

という事で、かなりの意訳が成されているらしい。

おもいでがいっぱい
今回驚かされたのはメッセージを長谷川さんが書かれていたことです。あのメッセージは谷川俊太郎顔負けの名訳だと思っています。
(引用ここまで)

感想の所には上記のようなメール内容も載せられていた。
私も本当に頑張ってクリアして、エンディングのメッセージには涙を流した。
小さな平仮名とカタカナだけの文章でありながら、今見ても胸が苦しくなる、本物の名訳である。

という訳で、エンディングの翻訳文と原文を比較してみた。

以下原文
Epilogue

The Queen retreats
within her machine.
When ecco leaves she
escapes in the form of
a Vortex larva.

The Queen makes her way
to the sunken city of
Atlantis. She finds the
time machine and escape
into Earth's past.

When the Queen arrives
in the prehistoric era,
She encounters creatures
that she cannot rule.
She has no choice but to
live within the life
cycles of the earth.

And, through the eons,
the Vortexkind integrate
with the life on earth.

Ecco finds the time
machine in the City of
forever. Instead of
destroying it, he uses
it and disappears into
the tides of time.

以下翻訳文
エピローグ

エコーは ながい たびのはてに
とうとう タイムマシンをみつけました。

マシンをはかいすれば すべてが
おわるのです。

、、、ほんとうにおわるのでしょうか、、、

かれは アステライトのことばを
おもいだします、、、
かれのそんざいじしんが
じかんの ぶんきてんなのです。

かれは なかまの イルカのことばを
おもいだします、、、

かれの あたまのもようは
うんめいの しるしなのです。

、、、ほんとうにおわるのでしょうか、、、

かれは すべてをおえる ただひとつの
ほうほうを みつけました、、、

タイムマシンを はかいするかわりに
エコーは ときのとびらをひらくと、
えいえんの じかんのながれのなかに
きえていったのです、、、

最後の部分以外がまるで違う文章に置き換えられている。
英語版は最後に何が起きたのかを、説明的な文章で解説している一方で、
日本語版は、エコーの決断を詩的かつ叙情的に表現している他、
何故エコー自身が何故時間の流れの中に消えていく必要があったのか(エコーの存在自身が時間の分岐点だから、という理由に納得が行くかどうかは別として)を説明している。

英語版のボルテックス・クイーンを倒した際に現れる謎の生物が何だったのかを解説の私による翻訳を載せる。
エピローグ

クイーンは彼女のマシンの中へと退却した。
エコーが去る時、彼女はボルテックスの幼生へと姿を変えて逃げた。

クイーンはアトランティスの水没都市への道を開いた。
彼女はそこでタイムマシンを見つけ、
過去の地球へと逃亡した。

クイーンが有史以前の時代に到着した時、
彼女は彼女には支配出来ない生物たちに遭遇した。
彼女はやむなく地球上のライフサイクルの中で生きていく他無かった。

そして、長い時の流れを経て、
ボルテックスの種は地球上の生命の中に統合されてしまった。

エコーは永遠の街でタイムマシンを見つけた。
彼はそれを破壊する代わりに、
それを使い、時の潮の中へと消えていったのだ。

以上である。ボルテックス・クイーン撃破時に現れ、
CITY OF FOREVERで登場する「かれら」はボルテックスの幼生が地球上の生物の系統の中に統合されたものだったのである。
これらの情報が欠けてしまっているのは残念ではあるが、心に訴えかける素晴らしい名訳であると思う。

ちなみに、最後のSECRET PASSWORDは以下の様な経緯で出来た代物らしい。

おもいでがいっぱい
エンディングのパスワードの件、真相をお教えしましょう。
実はあのパスワードを解析プログラムに入れると、総プレイ時間やミスの数、パズルを解いた効率の良さなどがかなり詳細に分かるのです。
これで「ゲームを一番上手くクリアできた人コンテスト」が出来るようにと開発元が仕込んでくれたのですが、残念ながら日本ではコンテストの企画が通らず(集計が大変だ、というのが理由です。今みたいにネットで応募、とか出来ませんしね)、あのパスワード画面だけが残ってしまった、という訳なのです。

(解析プログラムはフロッピーに入れてマスターROMと一緒に保管したので、今でもセガのどこかにあるんじゃないかなぁ?)
(引用ここまで)

この記述を見る限りは、無印の話なのか2の話かは判然としないが、
私は2しかやっておらず、このパスワードも2で表示されたので恐らく2の話だろう。

2013年11月5日火曜日

C++の名前空間のネストと識別子の衝突と無名名前空間について

私は普段DXライブラリを使っているのだが、 先日、以下の様なコードを書いた所エラーが出た。 ちなみに簡略化された全く意味のないコートであることに留意されたし。

#include "lua.hpp"
#include "DxLib.h"

namespace Lua{
	int Func( lua_State* pLuaState ){
		return 0;
	}
}
namespace DxLib{
	namespace Lua{
	}
}
void Test( void ){
	lua_State* p = NULL;
	Lua::Func( p );
}

エラーの内容は以下のとおり。

error C2872: 'Lua' : あいまいなシンボルです。
'Lua' である可能性があります。
または 'DxLib::Lua'

DXライブラリは、 DxLib.h 内で、名前空間 DxLib を using 宣言している。 このため、名前空間 DxLib::Lua と 名前空間 Lua をコンパイラが区別する事ができず、 コンパイルエラーとなっている。

C++において、普通に宣言した識別子は、無名名前空間(グローバル名前空間とも呼ばれる)に所属している。 無名名前空間に属している事を明示するためには、識別子をスコープ演算子から書き始める。 この記法を用いて修正したコードは以下のとおり。(関数 Test のみ)

void Test( void ){
	lua_State* p = NULL;
	::Lua::Func( p );
}

本当なら、関数 Func は名前空間 Lua にのみ存在するので、参照自体は出来ると思うのだが・・・ もしかしたらVC++ 2010でコンパイル出来ないだけで、他のコンパイラだと通るかもしれない。C++怖い。

ちなみに、以下の様な、識別子を使わない名前空間も無名名前空間と呼ぶ。

namespace{
	...
}

この名前空間内に記述した識別子は、同じソースコード内でしか参照できなくなる。 C++では、 static 修飾子よりも無名名前空間を使用することが推奨されている[要出典]

2013年11月4日月曜日

Luaを使ってクラスっぽい物を生成してCから使う方法 修正版

2013.11.04 追記

以前の投稿が激しく誤った情報を載せていたので修正。

Luaでクラス風のオブジェクトのメンバ関数を呼ぶ際は、 lua_pushvalue 関数を用いて、オブジェクトそのものを引数としてスタックにプッシュしてやる必要がある。

今回はメンバ関数内でオブジェクトのメンバを書き換えていないため、これでも正しく動作するが、 もしメンバ関数内でメンバを書き換える場合は、オブジェクト自身を return し、 lua_replace 関数を用いて返り値を元のオブジェクトに上書きしてやる必要がある。詳細は別途記事を書く予定。
2013.11.04 昨日はそうしないとうまく動かなかった筈ですが今日やったら動きました。 lua_pushvalue でコピーしたテーブルの内容を書き換えた場合って、参照元も書き換わるのかな… よく分からんのでもし分かる人がいらっしゃったらコメントとかで教えて下さい。

main.cpp

#include <lua.hpp>
#include <stdio.h>

int main( void ) {
	lua_State* L = luaL_newstate();	// Luaステートを生成
	luaL_openlibs( L );				// 標準ライブラリを読み込み

	// スクリプトの読み込み
	if( luaL_dofile(L, "script.lua") ){
		// エラー処理
		printf( "%s\n", lua_tostring( L, lua_gettop(L) ) );
		lua_close( L );
		return 0;
	}

	// 犬を生成
	lua_getglobal( L, "Dog" );					// グローバルなテーブル"Dog"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Neko" );				// 名前はNeko。犬なのにNeko。
	lua_pcall( L, 1, 1, 0 );					// 実行。関数と引数はスタックから除去され、返り値が積まれる
	lua_remove( L, -2 );						// 返り値の下にあるDogを除去
	int idx_dog = lua_gettop( L );				// Nekoのスタック上の位置を取得

	// 猫を生成
	lua_getglobal( L, "Cat" );					// グローバルなテーブル"Cat"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Inu" );					// 名前はInu。猫なのにInu。
	lua_pcall( L, 1, 1, 0 );					// 実行。関数と引数はスタックから除去され、返り値が積まれる
	lua_remove( L, -2 );						// 返り値の下にあるCatを除去
	int idx_cat = lua_gettop( L );				// Inuのスタック上の位置を取得
	
	printf( "%d object\n", lua_gettop( L ) );	// スタックのサイズが正しい事を確認

	// メンバ関数showを呼び出し
	lua_getfield( L, idx_dog, "show" );	// 関数をスタック
	printf( "%d object and function\n", lua_gettop( L ) );
	lua_pushvalue( L, idx_dog );		// 引数selfをスタック
	printf( "%d object, function, and argument\n", lua_gettop( L ) );

	// 実行
	if( lua_pcall( L, 1, 0, 0 ) ){
		// エラー出力
		printf( "%s\n", lua_tostring( L, lua_gettop( L ) ) );
	}
	
	printf( "%d objects\n", lua_gettop( L ) );
	
	// メンバ関数showを呼び出し
	lua_getfield( L, idx_cat, "show" );	// 関数をスタック
	printf( "%d object and function\n", lua_gettop( L ) );
	lua_pushvalue( L, idx_cat );		// 引数selfをスタック
	printf( "%d object, function, and argument\n", lua_gettop( L ) );

	// 実行
	if( lua_pcall( L, 1, 0, 0 ) ){
		// エラー出力
		printf( "%s\n", lua_tostring( L, lua_gettop( L ) ) );
	}
	
	printf( "%d object\n", lua_gettop( L ) );

    lua_close( L );	// 終了
    return 0;
}

script.lua

-- Dog
Dog = {}
Dog.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the DOG.", self.name )
		print( s )
	end
	return obj
end

-- Cat
Cat = {}
Cat.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the CAT.", self.name )
		print( s )
	end
	return obj
end

2013年11月1日金曜日

BloggerでSyntaxHighlighterを利用する際のTIPS

前の記事で、SyntaxHighlighterを導入してソースコードをBlogger上で表示した。 Luaの表示には公式ウェブサイトからリンクされているサイトの追加ブラシのLua1を利用した。 SyntaxHighlighterを使う際に以下のような問題に遭遇したため、ここにその対処法を示す。
  • Bloggerでは任意のファイルをアップロード出来ない
  • 記事上で、<等の特殊文字がうまく表示できない
  • タブが半角スペースに置換され、インデントがずれる
  • 全ての行の背景が同じ色で表示されるため、少し見辛い
  • shThemeXxx.css と shCoreXxx.css の違いが分からない

Bloggerでは任意のファイルをアップロード出来ない

Bloggerでは、任意のファイルをアップロードする事はできない。よって、JavaScriptやCSSをBloggerのドメインでホスティングする事は出来ず、Alex氏がホスティングしているファイルを参照する事になる。
別にそれはそれで構わないのだが、出来れば自分でホスティングしたい。それに、Syntax Highlighterがサポートしていない形式のコードを扱う時は困る(これも、その作者がホスティングしてくれているファイルを参照すれば問題ないが、精神的によろしくない)。
Google サイトを使った方法や、Google ドライブを利用する方法等があるようだが、いずれも欠点を抱えているようなので、私のオススメはDropboxを利用することである。
ここで注意したいのが、DropboxでのファイルのURLを生成する方法は二種類あることだ。
Publicフォルダに置いたファイルは「公開リンクをコピー」することで、そのURLを取得出来る。この方法で取得するURLには一意なユーザIDと、Publicフォルダ内におけるディレクトリ情報が含まれる。複数のハンドルネームを使っている場合等、「このファイルとあのファイルが置かれているアカウントは同じアカウントだ」とバレたくなければ使わないほうがいいだろう。ただし、内部的に相対パスを利用するファイルではこちらの方法が必須となる。
尚、生成されるURLは https://dl.dropboxusercontent.com/u/userID/filename だ。
Publicフォルダ以外に置いたファイルは「Dropbox リンクを共有」の機能を使用することで、URLを生成することができる。こちらの方法で生成したURLは、どのアカウントのファイルなのかを含め、隠蔽される。相対パスは利用できないが、よりセキュアであると言える。
生成されるURLは https://www.dropbox.com/s/fileID/filename だ。
参考:

記事上で、<等の特殊文字がうまく表示できない

HTMLでは一部の特殊文字は文法上の記法に利用されるため、エスケープシーケンスが必要となる。 置換にはこのサイトを利用した。
HTML特殊文字変換|コードをホームページに載せる時に便利 | すぐに使える便利なWEBツール | Tech-Unlimited 他にもあるかも知れないし、ローカルで出来るようなプログラムがあった方が良いかもしれない。

タブが半角スペースに置換され、インデントがずれる

Bloggerでは、タブが半角スペースに勝手に置換されるため、ソースコードのインデントがずれる。 プレビューではちゃんと表示されるのに、保存、公開した途端に置換されるのが曲者だ。 投稿時の編集のモードをHTMLにし、タブを &#9; に置換して記述することで、この現象を避けることが出来る。 ただし、一度編集のモードを作成にすると、せっかく置き換えたタブが半角スペースに戻ってしまうため注意。 公開後、きちんと投稿後の記事を確認した方が良いだろう。

全ての行の背景が同じ色で表示されるため、少し見辛い

これは、SyntaxHighlighterのCSSを編集することで改善できる。 .syntaxhighlighter .line.alt1 と .syntaxhighlighter .line.alt2 のそれぞれに背景色を設定してやればよい。 詳細は Syntax Highlighterの背景色と行間を変更する | ジャイアントモリンキーのjavaテック を参照。

shThemeXxx.css と shCoreXxx.css の違いが分からない

shCoreXxx.css は shCore.css と shThemeXxx.css を合成したものである。 参考: そらとぶくじら。 SyntaxHighlighter

以上。