PixivRSSのログを解析してみた

ちょっと気になったこともあったので、PixivRSSのログを見てみた。

解析内容

・ユーザーエージェント(何を使って見ているか)
・タグ検索(何を見ているか)

前提

内容ごとにバラバラにデータをとっているため、「誰が」「何を」「何を使って」見ているかという情報はわからない。

解析方法

grep | sed | sort | uniqで重複なしのソート済みテキストを作成して、流し見。

解析対象

2013年6月10日のPixivRSSのログ

ユーザーエージェント

685種類(内、GoogleReaderだけで642種類。GoogleReaderを除けば43種類。)
GoogleReaderは来月止まるから放っとくとして、それ以外にもHatenaやYahoo Pipe,livedoor,tinytinyrssなどWebサービスが多かった。(と言いつつ自分もtinytinyrssユーザー)
デスクトップ用としては、各種ブラウザとWindows-RSS-Platform/2.0があった。どっちかわからないのが「Ruby」。Webサービスなのかデスクトップアプリなのか…
Windows XP+IE6という組み合わせらしきアクセスも。大きなお世話になるが、更新した方がいいぞ…

タグ検索

2桁程度ならどんな割合か出そうかと思ったけど、809種類あるんで諦めた。
パッと見た感じ「○○users入り」が多い。あとはR-18系。
意外と英語も混じってる。かと言って外国人が使ってるとは限らないけど。そのへんはIPアドレスから引いてこないとわからんし。

感想

「これ、どうせ俺か多くても数人だろう」とか考えてログ見てみたら、ユーザーエージェント基準で40人以上。GoogleReaderのfeed-idの基準がよくわからないけど、一人1個なら600人ってところか…バグ修正ミスるとこの人達全員に迷惑がかかるのか…((((;゚Д゚))))ガクガクブルブル
これサーバーからダウンロードするのに30分かかったからもうやらない。次やるときはサーバーサイドで欲しいデータ全部作ってからダウンロードすることにする。
以下ログデータ。結構膨大かつ一部R-18データに注意。
続きを読む PixivRSSのログを解析してみた

OpenCVのキャプチャ画像をwxWidgetsのイメージ形式に変換してみた

OpenCVのCvCaptureで取得したIplImage構造体のデータをwxImageに変換する方法を調べたけどあんまり見つからなかったから作ってみた。
続きを読む OpenCVのキャプチャ画像をwxWidgetsのイメージ形式に変換してみた

絵チャ、始めました。

…と言っても俺が絵を描くわけではなく。
ちょっと前から作ってたお絵描きチャットアプリケーションがβテストという名の放置長期間連続稼動試験を終わらせて、正式版にバージョンアップ。
クライアント側にhtml5とjavascriptを、サーバー側にpythonを用いてWebSocket通信でリアルタイムにお絵かきするようなシステムにしてみた。
仕様上、アンドゥ,リドゥは無い。
URL http://mattyan.net/pictchat/
あと、zlib/libpngライセンスでソースコードも公開。
ただし、どこのサーバーにでも設置できるわけではなく、pythonプログラムを任意に実行できるなど制限あり。

絵チャを作ってみた

WebSocketを使ってお絵描きチャットを作ってみた。
クライアントサイドのcanvasタグ上でのマウスの動きをサーバーに送って、接続済みクライアント全員にばら撒くくらいの簡単なものだけど。
クライアントはhtml5とJavascriptで殆どを実装。
サーバーはPHPとphp-websocketを使って実装。
php-websocketのライセンス文を見るといきなりFuck youとか言われるけど、よくよく読んでみると「PUBLIC LICENCEなんて糞食らえ」っぽいからそのまま採用。
簡単な仕様でクライアント側はhtml5ネイティブのおかげか、Androdid上のfirefoxでも動作。絵は描けないけど、ログ再生とチャットと他人が描いてるのを見てることくらいは可能。
昨日1日でGUI作って今日サーバーと細かい部分を実装。実際に絵を描く友だちに試してもらって意見もらいつつ調整。
深く設計せずに思いつきで作ったのを早速後悔中…この分だと将来的に修正できなくなる…
早速もらった要望を検討すると、今の仕様だと無理っぽいことが判明。さぁてどうするか…
あとサーバーが若干不安定だからそっちも直さないとな。
つうか、JavascriptからWacomの筆圧検知できるのか…レイヤーはcanvasタグを重ねるとしてカラーピッカーは…

luabindのメモ書き2とQtインストール

luabindでluaスクリプトからテーブルを関数の引数として受け取る方法
C++側の関数の引数には luabind::object 型の変数を設定して、


SDL_Rect drawRect = {0, 0, 0, 0};
if(luabind::type(rect) != LUA_TTABLE)return;
if(luabind::type(rect["x"]) == LUA_TNUMBER){drawRect.x = luabind::object_cast<Sint16>(rect["x"]);}
if(luabind::type(rect["y"]) == LUA_TNUMBER){drawRect.y = luabind::object_cast<Sint16>(rect["y"]);}
if(luabind::type(rect["w"]) == LUA_TNUMBER){drawRect.w = luabind::object_cast<Uint16>(rect["w"]);}
if(luabind::type(rect["h"]) == LUA_TNUMBER){drawRect.h = luabind::object_cast<Uint16>(rect["h"]);}

こんなかんじでテーブルのメンバを取得する。
型チェックが要らないなら、drawRect.x = luabind::object_cast(rect[“x”]);だけでもOK。

QTのインストール
Building Qt on Windows (MinGW)を見てインストール中。
makeではなく、mingw32-makeを使うらしい。

luabindのメモ

C++のクラスをLuaに公開するのにluabindが便利とのことで投入検討。
Ubuntuのパッケージは要求するboostが古すぎるのかインストール拒否。
しょうがないので、自前で.aファイル作成。
ただその際に、公式ページからリンクされてるluabindはlua5.2に対応してないっぽいので
https://bitbucket.org/jlsandell/luabind/downloadsにある別のバージョンを使用。(Branchesのdefaultってほう)
以下、適当なMakefile.am


noinst_LIBARIES = libluabind.a
lib_LIBRARIES = libluabind.a
libluabind_a_SOURCES = 							\
	lua/luabind/src/class.cpp					\
	lua/luabind/src/exception_handler.cpp		\
	lua/luabind/src/pcall.cpp					\
	lua/luabind/src/class_info.cpp				\
	lua/luabind/src/function.cpp				\
	lua/luabind/src/scope.cpp					\
	lua/luabind/src/class_registry.cpp			\
	lua/luabind/src/inheritance.cpp				\
	lua/luabind/src/stack_content_by_name.cpp	\
	lua/luabind/src/class_rep.cpp				\
	lua/luabind/src/link_compatibility.cpp		\
	lua/luabind/src/weak_ref.cpp				\
	lua/luabind/src/create_class.cpp			\
	lua/luabind/src/object_rep.cpp				\
	lua/luabind/src/wrapper_base.cpp			\
	lua/luabind/src/error.cpp					\
	lua/luabind/src/open.cpp

ゲームに組み込むだけだからnoinstでインストールしないように指定。
あとはlsでリストアップしたcppファイル列挙して終わり。
明日以降組み込んでみるか。

PixivRSS2になった

先週土曜日にPixivRSS2.0に入れ替えた。
PixivRSS2は殆どの部分をフレームワークにしてるから、ニコニコ静画RSSも簡単に移植できるはず。
ついでに、パラメーターの書式も整理。互換性は無くさないようにしたけど、短縮形もサポート。
表から見るとわからない(遅くなったくらい?)だけど保守に便利になるように、ログの出力もサポート。
ほぼ定期的にアクセスされるものだから、ログファイル数がヤバいけど…エラー発生時に大体どの辺かがわかるから便利。
あと、今まではエラー発生時に不正な文字列(エラーテキスト…orz)を返していたのを、500を返すように修正。
今のところ順調に稼働中。そのうち、ニコニコ静画RSSもこっちに移植しようかな。

MinGW-TDMでcrypto++をビルドした

MinGW TDMcrypto++をビルドするのに、いくつか変更点がいるからパッチにしてみた。
support_mingw_tdm.patch


*** original/GNUmakefile	Mon Aug  9 14:22:42 2010
--- GNUmakefile	Sun Jun 10 15:55:35 2012
***************
*** 32,37 ****
--- 32,38 ----
  GAS217_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.1[7-9]|2\.[2-9]|[3-9])")
  GAS219_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.19|2\.[2-9]|[3-9])")
  ISMINGW = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "mingw")
+ ISTDM = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "tdm")
  ifneq ($(GCC42_OR_LATER),0)
  ifeq ($(UNAME),Darwin)
***************
*** 69,74 ****
--- 70,79 ----
  LDLIBS += -lws2_32
  endif
+ ifeq ($(ISTDM),1)
+ LDLIBS += -lws2_32
+ endif
+
  endif	# ISX86
  ifeq ($(UNAME),)	# for DJGPP, where uname doesn't exist

TDMサポートパッチ。
TDMのgccはバージョン情報に”mingw”ではなく”tdm-1″と出力するため、そっちもMinGWと同じ扱いになるように修正。
ついでに、Ubuntuのパッケージのファイル名と公式GNUmakefileの出力ファイル名が違っているから、Ubutnu側に合わせるパッチ
change_file_name.patch


*** original/GNUmakefile	Mon Aug  9 14:22:42 2010
--- GNUmakefile	Sun Jun 10 15:53:16 2012
***************
*** 137,178 ****
  	./cryptest.exe v
  clean:
! 	$(RM) cryptest.exe libcryptopp.a $(LIBOBJS) $(TESTOBJS) cryptopp.dll libcryptopp.dll.a libcryptopp.import.a cryptest.import.exe dlltest.exe $(DLLOBJS) $(LIBIMPORTOBJS) $(TESTIMPORTOBJS) $(DLLTESTOBJS)
  install:
! 	$(MKDIR) -p $(PREFIX)/include/cryptopp $(PREFIX)/lib $(PREFIX)/bin
! 	$(CP) *.h $(PREFIX)/include/cryptopp
  	$(CP) *.a $(PREFIX)/lib
  	$(CP) *.so $(PREFIX)/lib
  	$(CP) *.exe $(PREFIX)/bin
! libcryptopp.a: $(LIBOBJS)
  	$(AR) $(ARFLAGS) $@ $(LIBOBJS)
  	$(RANLIB) $@
! libcryptopp.so: $(LIBOBJS)
  	$(CXX) -shared -o $@ $(LIBOBJS)
! cryptest.exe: libcryptopp.a $(TESTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS)
  nolib: $(OBJS)		# makes it faster to test changes
  	$(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
  dll: cryptest.import.exe dlltest.exe
! cryptopp.dll: $(DLLOBJS)
  	$(CXX) -shared -o $@ $(CXXFLAGS) $(DLLOBJS) $(LDFLAGS) $(LDLIBS) -Wl,--out-implib=libcryptopp.dll.a
! libcryptopp.import.a: $(LIBIMPORTOBJS)
  	$(AR) $(ARFLAGS) $@ $(LIBIMPORTOBJS)
  	$(RANLIB) $@
! cryptest.import.exe: cryptopp.dll libcryptopp.import.a $(TESTIMPORTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(TESTIMPORTOBJS) -L. -lcryptopp.dll -lcryptopp.import $(LDFLAGS) $(LDLIBS)
! dlltest.exe: cryptopp.dll $(DLLTESTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(DLLTESTOBJS) -L. -lcryptopp.dll $(LDFLAGS) $(LDLIBS)
  adhoc.cpp: adhoc.cpp.proto
  ifeq ($(wildcard adhoc.cpp),)
--- 137,178 ----
  	./cryptest.exe v
  clean:
! 	$(RM) cryptest.exe libcrypto++.a $(LIBOBJS) $(TESTOBJS) crypto++.dll libcrypto++.dll.a libcrypto++.import.a cryptest.import.exe dlltest.exe $(DLLOBJS) $(LIBIMPORTOBJS) $(TESTIMPORTOBJS) $(DLLTESTOBJS)
  install:
! 	$(MKDIR) -p $(PREFIX)/include/crypto++ $(PREFIX)/lib $(PREFIX)/bin
! 	$(CP) *.h $(PREFIX)/include/crypto++
  	$(CP) *.a $(PREFIX)/lib
  	$(CP) *.so $(PREFIX)/lib
  	$(CP) *.exe $(PREFIX)/bin
! libcrypto++.a: $(LIBOBJS)
  	$(AR) $(ARFLAGS) $@ $(LIBOBJS)
  	$(RANLIB) $@
! libcrypto++.so: $(LIBOBJS)
  	$(CXX) -shared -o $@ $(LIBOBJS)
! cryptest.exe: libcrypto++.a $(TESTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcrypto++ $(LDFLAGS) $(LDLIBS)
  nolib: $(OBJS)		# makes it faster to test changes
  	$(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
  dll: cryptest.import.exe dlltest.exe
! crypto++.dll: $(DLLOBJS)
  	$(CXX) -shared -o $@ $(CXXFLAGS) $(DLLOBJS) $(LDFLAGS) $(LDLIBS) -Wl,--out-implib=libcryptopp.dll.a
! libcrypto++.import.a: $(LIBIMPORTOBJS)
  	$(AR) $(ARFLAGS) $@ $(LIBIMPORTOBJS)
  	$(RANLIB) $@
! cryptest.import.exe: crypto++.dll libcrypto++.import.a $(TESTIMPORTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(TESTIMPORTOBJS) -L. -lcrypto++.dll -lcrypto++.import $(LDFLAGS) $(LDLIBS)
! dlltest.exe: crypto++.dll $(DLLTESTOBJS)
! 	$(CXX) -o $@ $(CXXFLAGS) $(DLLTESTOBJS) -L. -lcrypto++.dll $(LDFLAGS) $(LDLIBS)
  adhoc.cpp: adhoc.cpp.proto
  ifeq ($(wildcard adhoc.cpp),)

まぁこっちは好みの問題か。

CMakeでtexのビルド

CMakeでtexをビルドする方法が大体わかったからメモ書き。これを応用すれば、texに限らず好きにビルドできるかな。
CMakeLists.txt


SET(Document_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(Document_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
ADD_CUSTOM_TARGET(DOCUMENT ALL echo DEPENDS ${Document_BINARY_DIR}/network.pdf)
ADD_CUSTOM_COMMAND(OUTPUT ${Document_BINARY_DIR}/network.pdf DEPENDS ${Document_SOURCE_DIR}/network.tex
	COMMAND platex ARGS ${Document_SOURCE_DIR}/network.tex
	COMMAND dvipdfmx ARGS ${Document_BINARY_DIR}/network.dvi
)

Document_BINARY_DIRとDocument_SOURCE_DIRは気分で変えてるだけだから割りとどうでもよくて。
ADD_CUSTOM_STAGETでビルドターゲットに「DOCUMENT」を追加し、Document_BINARY_DIR/network.pdfを完成バイナリに指定。
ADD_CUSTOM_COMMANDで出力をDocument_BINARY_DIR/network.pdfに、入力をDocument_SOURCE_DIR/network.texに指定。COMMANDでnetwork.texをビルドし、dviに続いてのCOMMANDでそれをpdfに変換。dviの出力先はDocument_BINARY_DIRになるので、そこだけ注意。
あとは、cmakeでMakefileを作って、make DOCUMENTでビルド。Document_BINARY_DIR/network.pdfができてた。