2013年12月24日火曜日

コマンドプロンプト ファイルリダイレクト

バッチひとつでコンソール形式の実行ファイルを開いてそこにコマンド流し込む。

/*---------------------------------------------------------------------------*/
$ hoge.exe
hoge> command;
/*---------------------------------------------------------------------------*/

上みたいな処理をバッチファイルに書いたら、
exeを実行するとexe用のコンソールが起動してそこで止まった。
そのコンソールを終了すると続く処理は実行されるんだけども、当然のごとくエラー。
どうにかできんのか、と思って調べてみたら、
コマンドプロンプトにはファイルリダイレクトという機能があるようだ。

参考サイト

コマンド部分を別のファイルに記述して保存。ここではhoge.commandとしておく。
そしてバッチファイルには以下を記述。

/*---------------------------------------------------------------------------*/
$ hoge.exe < hoge.command
/*---------------------------------------------------------------------------*/

これでhoge.commandの中身がhoge.exeに渡されてコマンドが実行される。

2013年12月20日金曜日

C# 定数

C#をやっていると、たまにメンバの定数ってどう宣言すんだっけ? となる。ぼけか?
とにかく、もうそんなことにならないためにメモ。

参考サイト
定数(C# によるプログラミング入門) - ++C++

メンバの定数を定義するためには、constとreadonlyの2つの方法がある。

/*---------------------------------------------------------------------------*/
private const int PI = 3.14;
private static readonly int PI = 3.14;
/*---------------------------------------------------------------------------*/

2つの違いは以下の通り。参考サイトからまるっとコピー!

constreadonly
ローカル変数にも使えるクラスのメンバー変数のみ。
常に静的変数と同じ扱い。static の有無を変えられる。
宣言時にのみ初期化可能。コンストラクタ内で値を書き換え可能。
コンパイル結果はリテラルと同等。コンパイル結果は変数と同等。
インスタンスを new で生成するようなものには使えない。new 可能。

ああ、bloggerのコピペするとhtml構文もコピーする機能ってこのためなのか。いまさら知った。

constは扱いがリテラル(直接記述したデータ。コンパイル時に値が展開される)なので、
バージョニング問題というものが発生するらしい。
constなデータを外部で参照している場合、コンパイル時に参照側も再コンパイルしないと、
値が変化しない現象。
privateなメンバ、ソースコード内からしか参照されない値なら問題ない。



まとめとして、privateな定数ならconst、publicな定数ならreadonlyを使用するのが無難っぽい。

2013年12月18日水曜日

php BLOB型を使ってみる

phpってバイナリ操作するためのものないのん? と思っていたらあった。
MySQLのBLOB型というやつとphpのgmp関連のメソッドを使う。

参考サイト
BLOB型とTEXT型
PHP: GMP 関数 - Manual

使用する上でやったことをいくつかメモ的に残しておく。

MySQL:BLOB型のデータを初期化する


バイナリデータを全部初期化したり、新しい行を挿入したりするときに使った。
BLOB型はデフォルト値が設定できないようなので、多分知らないと困る。

/*---------------------------------------------------------------------------*/
INSERT INTO hoge (blob_data) VALUES ("");
UPDATE hoge SET blob_data = "";
/*---------------------------------------------------------------------------*/

空の文字列を渡してやると、空のバイナリデータとして初期化される。
NULLを渡すと中身がNULLになるので注意。

PHP:BLOB型のデータを取得する


phpでデータを取得するときは、バイナリデータを文字列に変換。
さらにそれをgmpのデータに変換して取得する。

/*---------------------------------------------------------------------------*/
$gmpData = gmp_init(bin2hex($blobData), 16)
/*---------------------------------------------------------------------------*/

16進数のデータで受け取る例。他には10進数、8進数が使用可能。
まあ、基本16進数でいいやと思って試してはいない。

PHP:ビットを操作する


/*---------------------------------------------------------------------------*/
gmp_setbit($gmpData, $index, $set);
/*---------------------------------------------------------------------------*/

indexは調べたいビット。setはオンにするならtrue。オフにするならfalseを渡す。

PHP:ビットを取得する


/*---------------------------------------------------------------------------*/
gmp_testbit($gmpData, $index);
/*---------------------------------------------------------------------------*/

MySQL:PHPで操作したデータを更新する


取得したときとは逆に、16進数のデータに変換して、さらにバイナリに変換する。

/*---------------------------------------------------------------------------*/
$hex = gmp_strval($gmpData, 16);
$data =  hex2bin($hex);
/*---------------------------------------------------------------------------*/

gmp_strvalで変換できる。
hex2binに渡すときは、文字列データの長さが偶数じゃないと起こられるので気をつけよう。

以上。思っていたより長くなった。

2013年12月13日金曜日

C# CSVファイルを読み込み

なんてこったい。C#ではCSVファイルを読み込むのが超簡単ではないですかい。

参考サイト
CSVファイルを読み込むには?[2.0のみ、C#、VB]
TextFieldParser クラス (Microsoft.VisualBasic.FileIO) - MSDN

Microsoft.VisualBasic.FileIO名前空間のTextFieldParserというクラスを使用する。

/*---------------------------------------------------------------------------*/
TextFieldParser parser = new TextFieldParser("hoge.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData) {
   string[] row = parser.ReadFields();
}
/*---------------------------------------------------------------------------*/

これだけでオーケーさ!
処理としてはコンストラクタでファイルを読んで、フィールドの分割方法をデリミタに指定。
さらにデリミタをカンマに指定してループで最後まで読み込んでいる。
今回はCSVファイルだけど、調べてみたら色々なデータ構成に対応できそう。

今まで自力で実装してきたのはなんだったのやら。

C# アプリケーションを64bitOS上で32bitモードで動かす

以前作成したアプリケーションがwindows7上だと動かないという問題が発生した。

/*---------------------------------------------------------------------------*/
間違ったフォーマットのプログラムを読み込もうとしました。
(HRESULT からの例外: 0x800xxxxx)
/*---------------------------------------------------------------------------*/

こんなエラーが出る。
どうやらアプリケーションが64bitモードで動いているのが原因らしい。
使用しているdllが32bit環境のものだったので、それを読み込めないと怒られているようだ。

参考サイト

回避方法のひとつとして64bitOS上でも32bitモードで動かすというのがあったのでやってみた。
Expressを使用していたので、上記サイトで紹介されている方法は使用できない。
探してみたら、Expressでやる方法があったのでそちらを試す。

参考サイト
  1. メニューの「ツール(T)」から「オプション(O)」を開く。
  2. 左下の方にある「すべての設定を表示(A)」にチェックを入れる。
  3. 追加された「プロジェクトおよびソリューション」項目に移動。
  4. 「全般」の中にある「ビルド構成の詳細を表示(I)」にチェックを入れる。
  5. メニューの「ビルド(B)」から「構成マネージャ(O)」を開く。
  6. 「アクティブソリューションプラットフォーム」で「新規作成」。
  7. x86の項目を作成する。
以上。これでビルドしたら64bitOS上でも動いた。
よかったよかった。

2013年12月12日木曜日

SQLite csvデータをインポートする

これといって難しいことはないけど、ちょっとだけつまずいたのでメモる。

参考サイト
sqlite3 に CSV形式のデータを突っ込む

/*---------------------------------------------------------------------------*/
$ sqlite3 -separator , hoge.db ".import hoge.csv hoge"
sqlite> .import hoge.csv hoge
/*---------------------------------------------------------------------------*/

上がコマンドラインから直接突っ込む方法。
下がSQLiteを起動してからインポートする方法。
今回つまずいたのはSQLiteを起動してからのほう。

SQLiteはデフォルトのセパレータが"|"になっている。で、CSVは","区切り。
セパレータを設定してからインポートしてやろう。

/*---------------------------------------------------------------------------*/
sqlite> .separator ,
/*---------------------------------------------------------------------------*/

2013年12月11日水曜日

android-ndk stlを使う

せっかくC++でやるので、AndroidNDKでstlを使ってみた。

参考サイト
Android NDKが標準で備えるSTLを利用する
Android NDKでJNIを使用してアプリを高速化するには (2/3)

やり方は簡単で、Application.mkにstlを使うぞ、と教えてやるだけでいい。
これはstaticライブラリとして使用する例。

/*---------------------------------------------------------------------------*/
APP_STL := stlport_static
/*---------------------------------------------------------------------------*/

Application.mkは名前そのままで、アプリケーションの定義を行うファイルらしい。
今回はjniフォルダの直下に新しいApplication.mkを作成した。

2013年12月10日火曜日

CakePHP2.x ヘルパーでコンポーネントを使用する

MVC的に正しいのかどうかは置いておいて、ヘルパーでコンポーネントを無理やり使った。
他のページを見ると、自分でnewして使用するのが一般的(?)みたいだけど、
正直コントローラがすでに生成しているオブジェクトをわざわざnewするのもどうかと思ったので、
ClassRegistryに格納した。

コントローラ側の処理
ClassRegistryにコントローラが持っているHogeコンポーネントを追加。

/*---------------------------------------------------------------------------*/
ClassRegistry::addObject( "Hoge", $this->Hoge );
/*---------------------------------------------------------------------------*/

ヘルパー側の処理
ClassRegistryからコンポーネントを取得して使用する。

/*---------------------------------------------------------------------------*/
$hogeComponent = ClassRegistry::getObject( "Hoge" );
$hogeComponent->hogeru();
/*---------------------------------------------------------------------------*/

処理として正しいのかどうかは置いておいて、これでヘルパーからコンポーネントが使える。

2013年12月9日月曜日

android-ndk jniを使う

以前書いたndkのインストール及びテストの記事で最後のほうに空のプロジェクトが動いた、
とか書いたけど、改めて見直したら自分でもさっぱりなにをどうしたのか分からなかったので、
改めて適当なプロジェクトを作ってテストしてみた。

参考サイト
Android NDKを使った開発環境の構築

空のプロジェクトを作る


まずは環境だけが整ったプロジェクトを作る。
  1. メニューからAndroidApplicationProjectを作成する。
  2. プロジェクトを右クリック。「Androidツール」から「Add Native Suport」を選択
  3. 任意の名前を付けて「完了」。
これで環境だけが整った空のプロジェクトが完成。

jniファイルとの連携用のクラスを作成する


参考サイトではMainActivityに直接書き込んでいるけど、後述のjavahを使ったときに怒られた。
可読性もろもろのためにもネイティブと連携するファイルは個別にするのがいいと思う。

/*---------------------------------------------------------------------------*/
public class HogeJNI {
statis {
System.loadLibrary("hoge");
}
public static native void fuga();
}
/*---------------------------------------------------------------------------*/

System.loadLibraryには呼び出すsoファイルの名前を指定する。
C/C++のファイルと同じ名前になると思う。

C/C++のヘッダファイルを作成する


自分で打つと失敗する可能性大なので、jdkのjavahコマンドを使う。
コマンドプロンプトでプロジェクトのルートフォルダに移動して、以下のコマンドを実行。

/*---------------------------------------------------------------------------*/
$ javah -o jni/hogejni.hpp -classpath bin/classes com.example.test.HogeJNI
/*---------------------------------------------------------------------------*/

-oに出力先、-classpathに参照するクラスパス。最後が対象クラス。
詳しいことは参考サイトを見よう。
これでファイルが作成された。しかし、手動でインポートしないといけないの?
リフレッシュしてもいつまで経っても表示されないんだけども。

C/C++のソースファイルを作成


javahコマンドで作成したヘッダファイルをインクルード&そのまま使える部分をコピーして
ソースファイルに書き込み。
そのままコピペすると変数名を忘れる。
少なくとも自分は忘れた。30分以上、それに気づかず無駄にした。
C/C++側のエラーは感知してくれないんかね?

あとは必要なところでネイティブメソッドを呼び出せば動くはず。

2013年12月7日土曜日

android 開発環境は最新に保つのがいいらしい

android-ndkを本腰入れてやろうかと思って新しいプロジェクトを作ったら、エラーが出た。

/*---------------------------------------------------------------------------*/
[2013-12-07 16:37:59 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
[2013-12-07 16:37:59 - hoge] Conversion to Dalvik format failed: Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
/*---------------------------------------------------------------------------*/

なんでも、新しめの環境で古いビルドターゲットを指定すると起こるエラーらしい。

参考サイト
Android SDK をアップデートしたら BufferOverflowException が出るようになった

でも、ターゲットバージョンが古いやつならビルドバージョンも合わせようと思うのが普通では?
なんて思った。

2013年12月3日火曜日

php DateTimeなんてあったのね

phpで時間を求めるときに今まではdateとかtimeとかを使っていた。
が、php5.2だか5.3以降はDateTimeオブジェクトなるものが用意されているらしい。
2038年問題も解決されているようで、こちらを使ったほうが後々都合がよさそう。
というわけで使ってみた。

参考サイト
PHP 5.3 の DateTime オブジェクト関連の便利な新機能

現在時刻


/*---------------------------------------------------------------------------*/
$now = new DateTime();
/*---------------------------------------------------------------------------*/


文字列から時刻を求める


/*---------------------------------------------------------------------------*/
$time = new DateTime("2013-12-03 04:00:00"););
/*---------------------------------------------------------------------------*/

いくらか足した時間を求める


/*---------------------------------------------------------------------------*/
$interval = DateInterval::createFromDateString("+1 days");
$time = date_add( $updated, $interval );
/*---------------------------------------------------------------------------*/

DateIntervalオブジェクト相対的な日付を求めるために使用するオブジェクトだそうな。
コンストラクタに指定書式の文字列を渡すか、createFromDateStringを呼び出して、
strtotime見たいな使い方ができる。

date_addは読んで字のごとく。オブジェクトのメソッドにもaddがあるのでそっちを使ってもいい。

/*---------------------------------------------------------------------------*/
$time->add( $interval );
/*---------------------------------------------------------------------------*/

比較


/*---------------------------------------------------------------------------*/
$time == $now
$time < $now
$time > $now
/*---------------------------------------------------------------------------*/



他にも色々あるので、そちらは参考サイトや公式のマニュアルを参考に。
個人的には比較が楽でいい。


2013年11月27日水曜日

SQLite MySQLにインポートする

SQLiteで作成したデータベースをMySQLにインポートする。

参考サイト
sqlite エクスポート → mysql インポート - 0 _ 0

SQLiteのデータベースをエクスポートする


まずはSQLiteのデータベースをSQL文で出力する。

/*---------------------------------------------------------------------------*/
$ sqlite3 hoge.db
sqlite3> .output huga.sql
sqlite3> .dump
/*---------------------------------------------------------------------------*/

データベース開いて、出力先を変更して、ダンプする。

エクスポートしたデータを整形する


そのままMySQLにインポートしようとすると怒られる。
MySQLに対応したデータに形を整えてあげよう。
  • PRAGMA foreign_keys=OFF; を削除する
  • INSERT時のテーブルを囲っている"を削除する
  • BEGIN TRANSACTION を START TRANSACTION に書き換える
  • 文字列を使用しているところで文字化けする場合COLLATEで文字コードを指定
自分の環境で出てきたエラーしか対処していないので、対応すべき点は他にもあるかも。
MySQLからインポートしたデータベースでやったからか、テーブル構造では全く怒られなかった。

MySQLでインポート


エラーが出なければ完了。出たら対応。

2013年11月26日火曜日

C# SQLiteDataAdapterでUpdate

ぼちぼちSQLiteにも慣れたような気のせいのような。
Select文で取ってきたデータを処理する方法として、
SQLiteはSQLiteDataReaderを使う方法と、SQLiteDataAdapterを使う方法がある。
今回は、後者で取ってきたDataTableをいじったから
もとのデータベースに反映させたいよう、というお話。

基本的な流れ


参考サイト

SQLiteDataAdapterのUpdateメソッドにDataTableを渡せばよいとな?

/*---------------------------------------------------------------------------*/
// hoge.dbに接続
SQLiteConnection conn = new SQLiteConnection("hoge.db");
conn.open();

// fugaテーブルのデータを取ってくる
SQLiteDataAdapter adapter = new SQLiteDataAdapter("select * from fuga", conn );
DataTable data = new DataTable();
adapter.Fill(data);

// なんかデータテーブルをいじる

// 更新
adapter.Update(data);
/*---------------------------------------------------------------------------*/

で、ほんともう単純にやってみたら例外吐かれた。
なんでも「有効なUpdateCommandがないわよ。ばかね」だそうで。

SQLiteCommandBuilderでコマンドを自動生成する


参考サイト

テーブルごとに有効なコマンドを自分で設定するのなんて正気の沙汰じゃない。
そもそもそれなら自分でデータベースを直でいじるわい、と思っていたら、
自動生成してくれるクラスがあった。

/*---------------------------------------------------------------------------*/
SQLiteCommandBuilder bulider = new SQLiteCommandBuilder(adapter);
adapter.Update(data);
/*---------------------------------------------------------------------------*/

たったこれだけで勝手に各種コマンドを自動生成してくれるそうで。大助かり。
これでSQLiteDataAdapter を使ってのデータベース更新ができるようになった。

補足:PRIMARY KEYの設定


データベースのKEYの設定をちゃんとしていないと、SQLiteCommandBuilderで実は怒られる。
更新時のWHERE句の指定でプライマリキーを使用するのだと思う。多分。
ちゃんと設定してあげよう。

SQLite テーブル一覧を取得する

SQLiteでテーブル一覧を取得しようと思う。

SQLiteのコマンドを使う


参考サイト

.tablesなんていういかにもなコマンドがある。

/*---------------------------------------------------------------------------*/
.tables
/*---------------------------------------------------------------------------*/

これを使うとテーブル一覧がずらりと表形式で出てくる。

SQL文で取得する


参考サイト

上記の方法だと、直接SQLiteを実行しているときじゃないと一覧が取得できない。
他のプログラムで使用したいと思っていたので、SQL分を使って取得したい。

/*---------------------------------------------------------------------------*/
select name from sqlite_master where type='table' order by name;
/*---------------------------------------------------------------------------*/

そんなときはこのコマンドで一発さ!
order byは並び替えなので、あってもなくてもいいと思う。見易さが変わるだけ。
C#で試してみたら、結果は
1行1列名前だけ×テーブル数
のデータを持ったデータセットが返ってきた。

2013年11月25日月曜日

SQLite 外部ファイルからSQL文を読み込む

SQLiteでは.readコマンドを使うと、外部ファイルからSQL文を実行できる。
これを使えば外部のデータベースからSQL文をエクスポートして移植することも夢ではない!
今回はphpMyAdminを使ってMySQLから移植してみた。

参考サイト

MySQLからSQL文を出力する


phpMyAdminならデータベースのトップに移動してエクスポートから。
mysqldumpというコマンドを実行させてもいい、っぽい。

オプションを弄って1行ずつの出力にしておこう。
phpMyAdminなら「エクスポート方法」を「詳細」に設定して、
「すべての INSERT 文にカラム名を含める 」にチェックを入れればいい。
エラーが分かりやすくなる。

SQLiteに入力する


まずはなにも考えずに速攻移植さ!

/*---------------------------------------------------------------------------*/
sqlite3 .read hoge.sql
/*---------------------------------------------------------------------------*/

当然のごとく失敗。MySQLとSQLiteだと色々相違点があるので怒られるようだ。
それくらいは許容してくれもいいじゃないかよ、と思うけどそんなことは許さないSQLite。
phpMyAdminも「他のデータベースシステムまたは古い MySQL サーバとの互換性」とかいう
項目があるけど、SQLiteは含まれていない。
それ用のツールもないようなので、自力で変換する。

SQLファイルの変換


参考サイトを記載しておきつつ、なぜかエラー見ながら地道にやったばかたれちゃん。
機能をフルに使っているわけではないので他にもあるかもしれないけど、
大体以下の点に気をつければなんとかなった。
  • コメントアウト?(/*~*/;)されてる行は全て削除
  • 行頭にSETを含む行は全て削除
  • KEY関連の設定は全て削除
  • 少なくともPRIMARY KEYは保持できる。エラーでた気がしたんだけどな…。
  • テーブルのオプション(ENGINE, DEFAULT CHARSETなど)は削除
  • AUTO_INCRIMENTは削除
  • データベースへつけているコメント(COMMENT)は削除
  • ストアドルーチンを設定している箇所を削除
phpMyAdminで吐き出したsqlファイルということ前提。
エラーで怒られてるところを全部消して行けばいずれたどり着く。
正直、参考サイトのほうが良くまとまっているので、そっちを参考にしたほうが絶対いい。

今度こそSQLiteに出力する


コマンドを実行してエラーが出なければ成功。
ちゃんと移植できているか中身を確認しておこう。

C# ディレクトリのファイル一覧を取得する

コンソールツールなんか作ってると、ディレクトリのファイル一覧が取得したくなる。
指定ディレクトリ(または現在のディレクトリ)のファイルに対して特定の処理を行うとか。
そんなわけでやってみた。

ファイル一覧を取得する


/*---------------------------------------------------------------------------*/
string[] files = Directory.GetFiles(directory);
/*---------------------------------------------------------------------------*/

これだけでいいんだから驚き。directoryにはディレクトリのパスが入っている。
なお、特定の拡張子のファイルだけが欲しいときはこうする。

/*---------------------------------------------------------------------------*/
string[] files = Directory.GetFiles(directory, "*.txt");
/*---------------------------------------------------------------------------*/

テキストファイルだけを取ってくる例。
ワイルドカードを使うパターンは多いので、分かる人はわざわざ調べなくても出てきそう。

現在のディレクトリのパスを取得する


GetFilesは引数としてディレクトリ名を要求する。
引数なしなら現在のディレクトリ、なんて気の利いたことはしてくれない。
なので、現在のディレクトリを取得する方法も一緒に調べた。

/*---------------------------------------------------------------------------*/
    string directory = Directory.GetCurrentDirectory();
/*---------------------------------------------------------------------------*/

うーん、まんまだ。インテリセンス見ただけで気づく人も普通にいそう。

C# foreachでDictionaryのキーと値を同時に取得する

C#ではIEnumerableインターフェースを継承してるクラスで、foreachを使用することができる。
コレクションの全ての要素を一回ずつ読み込んでくれる機能。
forと違ってループ回数の指定とか面倒なことしなくてもいいのでなにかと便利。

で、PHPとかにもある機能なんだけども、PHPだと連想配列のキーも一緒に取得できる。
ならC#でもきっとできるさ、と思って調べてみたら、あった。

参考サイト

やり方は簡単。

/*---------------------------------------------------------------------------*/
foreach (KeyValuePair<string, string> pair in dictionary)
{
// なんかする
}
/*---------------------------------------------------------------------------*/

以上。
IDictionaryの要素が<TKey,TValue>のペアで構成されているため、
それを受け取れるようにしたのがKeyValuePairだそうな。

2013年11月22日金曜日

SQLite データをインポートする

C#でSQLiteを使っていて、既存のデータベースと同じデータを扱う必要が出た。
そうなると当然その既存のデータベースからインポートしてしまいたい。
結論から言うと、C#環境下ではできなかった。
もしかしたらできるのかもしれないけど、なんちゃってプログラマにはわからなかった。
SQLiteをダウンロードしてそっちでデータベースを作ってからC#側で使うしかないのかな?

SQLiteをダウンロード



サイトからファイルをダウンロード。
zipファイルを任意のフォルダに解凍すると、sqlite3.exeというファイルがぽつねんとできる。
あとはコマンドプロンプトから叩いてやるだけ。

テーブルにデータをインポートする


参考サイト

今回インポートするのはcsv。
データがダブルクォーテーションで囲まれていると失敗するらしい。
それから、1行目のデータがカラム名じゃなくても失敗する。
全部文字列だったら失敗しないかもしれない。
コマンドプロンプトでexeを展開したフォルダに移動。コマンドを叩いてやろう。

/*---------------------------------------------------------------------------*/
$ sqlite3 -separator , hoge.db ".import hoge.csv hoge"
/*---------------------------------------------------------------------------*/

-separatorオプションでセパレータ(区切り文字)を指定できるので、
カンマ区切りじゃなくても問題はなさそう。

/*---------------------------------------------------------------------------*/
$ sqlite3 hoge.ds
sqlite> .import hoge.csv hoge
/*---------------------------------------------------------------------------*/

この方法でもできるそうだけど、separatorの指定はどうやるんだろうか?
普通にでいいのかな?



/** 同日追記 **/

参考サイト
データをファイルからインポート

区切り文字は「.separator」で変更可能。
それから、カラム名もファイルからインポートするとデータ型が全部TEXTになってしまうようだ。
テーブルそのものは事前に作っておいて、データだけインポートしろってことかな。

jQuery 「jQuery Slider²」を使い、さらに弄ってみた

以前bxsliderを使う記事を上げた。
じゃあもうスライダーはこれでいいな、と思っていたら、
なぜかまったく関係ない要素表示が乱れるというバグが発生。
原因が全然分からんかったので、jQuery Slider²に乗り換えてみた。

参考サイト
とても簡単で軽量なjQueryスライダー「jQuery Slider2」を使ってみる | bl6.jp

まずは実行だ


というわけでサイトからダウンロードしてきてテスト。
特に特別なこともなく、jsファイルとcssファイルを読み込んだら、
htmlに動かしたい要素を追加してjavascriptで要素を指定してやるだけ。

さて、ここでひとつ問題にぶち当たった。
どうにもjQuery Slider²はページナビを右端から順繰り表示がデフォらしい。
オプションやcssを弄ってどうにかならんかと思ったけど、
オプションにはないし、cssはabsoluteが指定されているしでどうしようもない感じ。
仕方ないから、jsファイルを弄る。

ページナビをセンタリングする


参考サイト

使用ツール

まずはcssから余計な要素を削除しする。具体的にはtopとかrightとか。
leftは50%指定に変更。

/*---------------------------------------------------------------------------*/
.jquery-slider-pages {
   overflow: visible;
   position: absolute;
   bottom: 5px;
   left: 50%;
}
/*---------------------------------------------------------------------------*/


そしてjsファイルをツールで整形。
jquery-slider-pagesクラスを追加している部分で

要素数×ページナビの横幅÷2

ピクセル分margin-leftをマイナスしてあげよう。

/*---------------------------------------------------------------------------*/
if (settings.showProgress) {
positionEls.CSS("margin-left", -(count*pixel/2)+"px");
$this.append(positionEls);
}
/*---------------------------------------------------------------------------*/

これでセンタリングが完了。
それっぽい見た目にはなったかな。

2013年11月20日水曜日

C# SQLiteを使ってみた

「SQLite? なにそれ?」状態の自分がSQLiteを使ってみた。

SQLiteってなんぞや?


参考サイト

色々と特徴が書き出されてるけど、要はアプリケーションに組み込む形でデータベースが
使えるとさえ分かっていればいいんだな。いいんだよね?

SQLiteをダウンロード


参考サイト

公式サイトにダウンロードしに行くと、なんかたくさんファイルがあった。
ちゃんと違いがあるみたいなので、上記サイトをよく読んで自分の環境にあったやつを使おう。
すごく丁寧に解説されている。
なぜかインストーラを使うと失敗するので、今回はzip版をダウンロード。

Visual C#で使う


参考サイト

いろんなページで参照に追加する追加する言ってるけど、どうするんだと思っていたら、
本当にプロジェクトに参照を追加するだけでよかったというオチ。
  1. 適当なプロジェクトを作る
  2. 「参照の追加」の「参照」タブから解凍したSystem.Data.SQLite.dllを追加
実行する際はexeと同じフォルダにSQLite.Interop.dllを追加してやろう。
サンプルとして上記サイトに書いてあるコードを実行させてもらいました。
テーブル追加、レコード追加、読み込み、出力の流れ。
動いた。

テーブルを作成すると、
実行ファイルと同じ場所にテーブルのデータファイル(?)が出来上がる。
当然同じテーブルは作れないので連続でテストする時は注意。

コマンドプロンプト ファイルを削除する

コマンドプロンプトでファイルを削除する。

/*---------------------------------------------------------------------------*/
del hoge.fuga
/*---------------------------------------------------------------------------*/

名前が一致したファイルを削除する。
ワイルドカードも使えるので、フォルダ内の特定拡張子のファイルを削除したいときなんかに。

/*---------------------------------------------------------------------------*/
del *.jpg
/*---------------------------------------------------------------------------*/

何気に便利。

2013年11月18日月曜日

コマンドプロンプト ファイルから文字列を検索して行を出力

簡単なファイル操作なり、処理なりは、
コマンドプロンプトないしバッチファイルのほうが楽かもしれないと最近思った。

コマンドプロンプトを使用してファイルから指定文字列を検索。
それを行で出力する。

参考サイト
コマンドプロンプト findstr - [文字列や正規表現を使って文字列を検索する]

/*---------------------------------------------------------------------------*/
findstr /N test test.txt > output.txt
/*---------------------------------------------------------------------------*/

上記の例では、test.txtから、testという文字列を検索。
行番号付きで、output.txtというファイルに書き出している。

色々オプションがあり、正規表現も使えるので、やたらややこしい条件がなければ、
大抵の検索はこれで済むと思われる。

2013年11月15日金曜日

C# アプリケーションを終了する

そもそもアプリを起動するためのデータが取得できなかっただとか、
アプリケーションに必須なものが取得できずアプリを終了せざるをえないこともあるだろう。
あるいは、閉じるボタン以外の場所をクリックしたいときに終了するとか。

そんなわけでどうすればアプリケーションを終了できるのかを調べてみた。

参考サイト
アプリケーション(自分自身)を終了させる: .NET Tips: C#, VB.NET

上記サイトによると、3つの方法で終了できるらしい。

/*---------------------------------------------------------------------------*/
this.Close();
System.Windows.Forms.Application.Exit();
System.Environment.Exit(0);
Environment.FailFast("イベントログに書き込む")
/*---------------------------------------------------------------------------*/

上から順番に、
  • メインフォームを閉じる
  • フォームアプリケーションの終了
  • エントリポイントを抜ける
  • 強制終了
だそうな。

上記2つはフォームアプリケーションでしか使用できないので、コンソールは下の2択。
さらにFailFastはアプリケーションの状態悪化時なんかに呼び出すべきものであるらしいので、
よほどのことがない限り、コンソールはEnvroiment.Exitでよさそう。

フォームアプリケーションは全部選択できるんだけど、上記の理由によりFailFastはなし。
Envroiment.Exitはプロセスを強制的に終了してエントリポイントを抜けるため、
呼び出した場所以降のメソッドが呼ばれない。
Closeは、そもそもメインフォーム以外の場所から呼べんじゃないですか。
参照を持っていれば話は別だけども。
ということでApplication.Exitが一番よさそう。

C# フォームアプリケーションで複数ウィンドウ

フォームアプリケーションをやっていたら、
フォームBで選択されたデータをフォームAに反映したいという状況になった。
フォームBがモーダルダイアログならShowDialogで問題ないんだけど、
フォームAと常に一緒に表示されているウィンドウなので、親子関係を構築する。



親子関係の構築の仕方は簡単。子ウィンドウのShowメソッド呼び出し時に親を渡す。

/*---------------------------------------------------------------------------*/
public FormA() {
        this.Shown += delegate(object sender, EventArgs e) {
        Form formB = new Form();
        formB.Show(this);
        };
}
/*---------------------------------------------------------------------------*/

上記の例では、コンストラクタでShownイベントハンドラを設定し、
イベントハンドラ内でフォームBを生成、親として自分自身を渡している。
コンストラクタ内で直接やると、親のインスタンスが生成されておらず、
期待通りの結果にならないので注意。

表示位置もこちらで自由に指定したいのなら、
StartPositionプロパティをFormStartPosition.Manualに設定して Location を弄る。

常にその配置に固定したいならMoveやResizeにイベントハンドラを設定。

2013年11月14日木曜日

C# FileDialogとカレントディレクトリ

C#のフォームアプリケーションではファイル操作を行うときにファイルダイアログを使うと、
専用のダイアログを開いてファイルを選択できる。

このファイルダイアログ、適当に生成して使うと、
たまげたことにアプリケーションのカレントディレクトリを変更しやがる。
相対アドレスを直接指定して画像ファイルを読み込みとかしていると、
当然のごとく読めなくなった。

こういうときは、RestorDirectoryプロパティをtrueにしてやるといい。

/*---------------------------------------------------------------------------*/
OpenFileDialog dialog = new OpenFileDialog()
{
   RestoreDirectory = true,
};
DialogResult result = dialog.ShowDialog();
/*---------------------------------------------------------------------------*/

上記のコードではOpenFileDialogで行っているが、SaveFileDialogでも同様。

ところで、newしたあとに{}で囲むとプロパティを操作できるのね。
機能名がわからんから詳しく調べられてないんだけど、なんなんだこりゃ?

2013年11月13日水曜日

C# Formあれこれ

ツール作成にはC#が便利だ! というのをどこかで聞いたような聞いていないような。
C#のフォームアプリケーションを試してみたので、メモを残しておく。



まずは単純にフォームを表示するだけ

  1. VisualStudio or VisualC#を立ち上げる。
  2. 「ファイル」→「新しいプロジェクト」→「Windowsフォームアプリケーション」
完成! あらやだ簡単。なにもないフォームを表示するだけだけど。
ここから色々いじくっていくのだ。

フォームデザイナを使う


C#にはフォームデザイナという機能があって、
メニューやテキストボックスなどのコントロールをグラフィカルに追加できる。
試しに使う方法と使わない方法を試してみたけど、使ったほうが圧倒的に楽。
デザインを変更するときもぽちぽちするだけですむのはありがたい。

  1. デザイナを開いた状態で右側の「ツールボックス」へマウスオン
  2. 使いたいコントロールをデザイナ上の好きな場所へドラッグオンドロップ

イベントハンドラを追加する


フォームアプリケーションは
ボタンを押す、指定時間経過などのイベントにしたがって処理を行う「イベント駆動方式」。
ちゃんと意味を理解したのはいまさらだったりする。我ながらひでえ。
そんなわけで、ユーザーのアクションに対して適切な処理を行うためには、
イベントを追加してやらにゃなりません。
デザイナを使用していると、これも簡単に行える。(クリック系の処理に限る)

  1. 追加したコントロールをダブルクリック。
  2. ソースコードにイベントハンドラ定義用の関数が追加され、ついでにそこが開く。
  3. 処理を書き込む。



とりあえず基本中の基本をやってみたのをまとめてみた。
これだけでも簡単なツールは作れると思う。
イベントもほしいイベントは大抵用意されているので、ちょっと調べればすぐ出てくる、はず。

javascript でtrim

ちょくちょくjavascriptを使う機会が出てきたような、そうでもないような。
環境に依存するところもあるけど、いろんな環境でサポートされているので、
覚えておくと後々便利そうだと思った。



意外なことにjavascriptにはtrim関数がないので、
replaceを使ってそれっぽい処理を実装する必要がある。

参考サイト
Javascript で trim するには

上記サイトより
/*---------------------------------------------------------------------------*/
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, "");
}
String.prototype.ltrim = function() {
    return this.replace(/^\s+/, "");
}
String.prototype.rtrim = function() {
    return this.replace(/\s+$/, "");
}
/*---------------------------------------------------------------------------*/

リテラルの最後の/の後にgを入れると条件に該当する全ての要素に対して
処理をしてくれるもの、と思われる。調べた感じ。

正規表現を使って、行頭・行末の文字を検索している。
できればスペース以外のやつもtrimで排除できるといいな、
と思ったんだけども予想以上に面倒そう。
その場合は素直にreplaceを呼んだほうが早いかもしれない。




2013年11月5日火曜日

CakePHP2.x フォルダのファイルを全て削除する

とりあえずwebroot以下にあるhogeフォルダのテキストファイルを削除する。

/*---------------------------------------------------------------------------*/
    App::uses( "Folder", "Utility" ); 
$dir = new Folder( WWW_ROOT."hoge".DS );
$files = $dir->find( '.*\.txt' );
foreach( $files as $file ) {
$file = new File( $dir->pwd().DS.$file );
$file->delete();
}
/*---------------------------------------------------------------------------*/

webroot以下のファイルは基本リソースになるので
プログラムで消す機会はそうそうないとは思うけども。

2013年11月4日月曜日

android-ndk インストールからテストまで

久しぶりにandroidをいじろうと思ってeclipceを立ち上げたら、アプリケーションの実行時に以下のエラーが出て動かなくなった。

 /*---------------------------------------------------------------------------*/
    failed to initialize monitor thread: unable to establish loopback connection
/*---------------------------------------------------------------------------*/

ネットで軽く調べても原因がわからんかったので、いっそのこと最初から入れなおしてやる! と奮起した。
その際に悪戦苦闘したのでメモを残しておく。

AndroidSDKインストール(ついでに日本語化も)


参考サイト
Androidアプリケーション開発環境の構築(ADTバンドル版SDK編)
Android開発をJava 7で行う
  1. AndroidSDKをダウンロードして適当なフォルダに解凍
  2. Java SE Development Kit (JDK)をダウンロード。インストール。
  3. Pleiadesをインストールして解凍
  4. 解凍したフォルダのfeaturesとpluginsのフォルダをeclipce内の同名フォルダに上書き
以上。今のSDKはeclipceが同梱されているバージョンが配布されており、昔に比べて余計な設定の必要がなくてとても楽になった。
JDKは推奨バージョンじゃない場合は「設定」からjreを追加してコンパイラ準拠レベルを推奨バージョンに変更する必要があるらしい。

AndroidNDKインストール



参考サイト
Android NDKを使った開発環境の構築
  1. AndroidNDKをダウンロードして適当なフォルダに解凍。
  2. 「設定」「Android」「NDK」からNDK Locationを解凍したフォルダに設定する
おしまい。

AndroidSDKのサンプルを実行してみる


新しい環境も整えたところで、もうようわからんエラーは出ないだろう、と意気揚々と適当なサンプルを実行。
はい、また同じエラー出ました!

 /*---------------------------------------------------------------------------*/
    failed to initialize monitor thread: unable to establish loopback connection
/*---------------------------------------------------------------------------*/

ええい! なんなのだ貴様は! と本腰入れて調査を開始。
で、仕方ないから全然読めない英語を雰囲気から読み取りつつ見つけた情報を試す。
eclipce.iniの末尾に以下の設定を追加。

/*---------------------------------------------------------------------------*/
    -Djava.net.preferIPv4Stack=true
/*---------------------------------------------------------------------------*/

動いたー! とりあえず原因までは調べてないけど動くようになったので先に進む。
あとで調べようとは思っているけど、誰か理由がわかる人がいたらよければ教えてください。

AndroidNDKサンプルを実行する


SDKも動いたところで、NDKも大丈夫だろうととりあえずGLES使っているサンプルを実行。
この時にエミュレータの「ホストGPUを使用する」の設定にチェックを入れとかないと
動かないので気をつけよう。
それから、Nexus7を使うとなぜかエミュレータが動かなくなる。別のマシンなら問題なし。なぜ?

で、この一連の作業してる時に知ったんだけど、
今のeclipceってcygwinがなくてもNDKのビルドできるのね。
プロジェクトを右クリックして「Androidツール」のサブメニューから「Add Native Support」を選択。
で、表示されたダイアログをOK。名前は変えても変えなくてもいい。
命名規則に従う形にするのが無難かな?
これだけでNDKのビルドができるようになる。

そしてついに実行。そしてさすがというべきかやはりというべきか、エラー。というか落ちた。
こういう時こそデバッガの出番だぜ! と思って起動したらこっちもエラー。なんじゃそりゃ。

/*---------------------------------------------------------------------------*/
   Unable to detect application ABI's
/*---------------------------------------------------------------------------*/

こんな感じのエラーが出てきまして。
他にもずらずら出てる大量のエラーを読み解く。

どうもAndroidManifest.xmlの設定がよろしくないっぽい。
APP_PLATFORMのバージョンとminSdkVersionが違うよ、と怒られているんだと思う。
実際minSdkVersionをAPP_PLATFORMに合わせたらこのエラーは出なくなった。

でも別のエラーで怒られた。
NDK_DEBUG=1がどうこうというメッセージが出ていたので、
プロジェクトのプロパティからビルドオプションにNDK_DEBUG=1を付けたしてやると動いた。
ちなみに後でもう一回試してみたら、オプションを付加しなくても怒られない不思議。


中途半端だけどいろいろ限界なので一回ここでやめる。
続きはまた気が向いたときに追記か新しい記事で。




/** 11/19 追記 **/

結局サンプルは動かせなかったけれど、
適当に作ったndkのプロジェクトが動くところまでは行った。
メモメモ。

参考サイト
Windows で Android NDK を使ってみる

結局デバッグはこれでもうまくいかなかった。
その原因は、なんてこったい。パスの通し忘れだった。
環境変数PATHを設定する。

/*---------------------------------------------------------------------------*/
 C:\android\android-ndk
/*---------------------------------------------------------------------------*/

実際には自分の環境のNDKを解凍したフォルダにパスを通す。
ついでにSDK周りのPATHもチェックしたらこっちは大丈夫だった。
これをやったらデバッグはできるようになった。
でも、相変わらずglesを使ったプロジェクトは落ちるし、サンプルは動かない。

どこのサイトで見たのかは忘れたけど、
エミュレータだとglesのプロジェクトが動かない、というのがあったような気がする。
GPUだかハードウェアだかがどうだか。
実機でテストしようと思ったら、持ってる端末がくそ過ぎてPCにデバイスがダウンロードできない。
glesはまたの機会に持ち越しだ! 諦めたわけじゃないよ!

んで、サンプルのほうは、どうもバージョンによる違いが出てるみたい。
サンプルによってはそもそもビルドすら通らないこともざらにある。
なので、もういっそのこと新規プロジェクトを作ってみたら、普通に動いた。
公式サンプルが信用できないってどうなのよ?

以上。
一応インストールから空のプロジェクトの実行まで。
glesは諦めたわけじゃない。諦めたわけじゃ、ないんだ。

2013年11月1日金曜日

cakephp2.x 他のコントローラのビューを使用する

ひとつのコントローラから別のコントローラのビューを使用したいときはこうする。

/*---------------------------------------------------------------------------*/
    $this->render( "../controller/view" );
/*---------------------------------------------------------------------------*/

コントローラごとに機能を分けるのが理想であって、極力使わないほうがいいんだろうけど。

2013年10月30日水曜日

swf swfmillを使ってみる

swfをxmlに変換してくれるツールがあるということで使ってみた。
主にflashを動的に変換するために使われていたみたい。だよね?

参考サイト
swfmillで動的FlashLite作成!

上記のサイトでバグを修正したバージョンがおみやげとして用意されているのでありがたくいただいておこう。

使い方


なにも難しいことはなく、ダウンロードして展開したら、コマンドプロンプトで展開先へ移動。
exeを叩いてやる。

/*---------------------------------------------------------------------------*/
    swfmill swf2xml hoge.swf hoge.xml
    swfmill xml2swf hoge.xml hoge.swf
/*---------------------------------------------------------------------------*/

文字コードはutf-8を使用しているので、sjisだったりするとエラーで怒られる。
そういう時はオプションを指定してやるといいようだ。
文字コードが合っているときに無駄に使用するとかえって文字化けするみたいなので注意。

/*---------------------------------------------------------------------------*/
    swfmill -e cp932 swf2xml hoge.swf hoge.xml
    swfmill -e cp932 xml2swf hoge.xml hoge.swf
/*---------------------------------------------------------------------------*/

ところで、2ってなんじゃいと思っていたらそのままtoという意味らしい。いや、うん。まあ、うん。
…ええ?


以上、swfmillのかなり適当な使い方。
swfを色々いじくっているので、単純にバイナリデータが可視化されるだけでもうれしい。

2013年10月22日火曜日

Photoshop7スクリプト レイヤーセットをフォルダ別に保存する

前回は単純にレイヤーを保存したので、今回はレイヤーセットに分けられたレイヤーを
セット名と同じ名前のフォルダに保存する。
セットに含まれないレイヤーは考えない。

作業工程

  1. 処理を行うレイヤーセットのみを可視化する
  2. レイヤーセットの名前を取得する
  3. 新しいフォルダを作成する
  4. レイヤーセットの中の処理を行うレイヤーをアクティブにする
  5. レイヤーをフォルダに保存する
前回の処理にレイヤーセットというひとつ上の枠組みが加わっただけ。

処理を行うレイヤーセットを可視化する


レイヤーと同じでvisibleというプロパティがあるので、それを弄る。
処理前に全部を不可視にしてから、処理の際に弄るやつだけを可視化するのがいいと思う。

レイヤーセットの名前を取得する


レイヤーセットの中にnameというプロパティがある。まんま。

新しいフォルダを作成する


すでにフォルダがある場合も考慮してexisitsでチェックする。

/*---------------------------------------------------------------------------*/
var folder = new Folder( folerName );
if( folder.exists || folder.create() ) {
// レイヤーをアクティブにして保存
}
/*---------------------------------------------------------------------------*/

existsメソッドでなかった場合のみ新しくフォルダを保存する。
どっちの結果もだめだった場合は処理しない。

あとはちゃんとフォルダのパスを指定してレイヤーを保存すればオーケー。

2013年10月21日月曜日

Photoshop7スクリプト Re:レイヤーをPNGファイルで書き出す

色々Photoshopのスクリプトを弄っていてなんとなくテクスチャアトラスの仕様が浮かんできたような
気がしないでもないので、作成の前に頭の中の整理も兼ねて必要な機能を試して行く。

今回は単純に現在の画像のレイヤーをPNGファイルで書き出すスクリプト。
すでに1回やっているけど、シンプルにまとめられた気がするのでもう一回やっとく。

作業工程

  1. 処理を行うレイヤーをアクティブにする。
  2. レイヤー名を取得する。
  3. レイヤーの画像をコピー。
  4. 新しいドキュメントを作成する。
  5. 作成したドキュメントに画像を貼り付ける。
  6. 作成したドキュメントの表示部分を結合する。
  7. ドキュメントをPNG形式で保存。
上の処理をレイヤー分繰り返す。

・処理を行うレイヤーをアクティブにする


ちゃんとコピーしたい画像だけ処理しよう。
これはドキュメントもだけど、ちゃんと操作したいやつをアクティブにしておかないと怒られる。
ループの前に全レイヤーを不可視にして、ループの先頭で処理を行う。

/*---------------------------------------------------------------------------*/
doc.activeLayer = doc.layers[i];
doc.layers[i].visible = true;
/*---------------------------------------------------------------------------*/

ループの最後にレイヤーを不可視にするのも忘れずに。

・レイヤー名を取得する


レイヤー名をそのままファイル名に使うので必要な処理。自分で名前をつけるなら必要ない。
レイヤー名は ドキュメント.layers[レイヤーインデックス].name の中に入っている。

・レイヤーの画像をコピー


ドキュメントを全選択してコピーを行う。

/*---------------------------------------------------------------------------*/
doc.selection.selectAll();
doc.selection.copy();
/*---------------------------------------------------------------------------*/

・新しいドキュメントを作成する


documentsのaddという関数を使う。引数には元のドキュメントの値をそのまま渡せばいいと思う。
戻り値として新しいドキュメントが返ってくる。

・作成したドキュメントに画像を貼り付ける


新しいドキュメントを全選択してpasteメソッドを使う。
この時引数にtrueを渡すと選択範囲に貼り付けになる。

・作成したドキュメントの表示部分を結合する


新しいドキュメントでmergeVisibleLayersメソッドを使う。
この処理をしないと保存するときにダイアログが表示されてしまうようだ。

・ドキュメントをPNG形式で保存


/*---------------------------------------------------------------------------*/
var file = new File( "新しいファイル名" );
var pngOpt = new PNGSaveOptions();
dstDoc.saveAs( file , pngOpt, false, Extension.LOWERCASE );
dstDoc.close();
/*---------------------------------------------------------------------------*/

ファイルは保存するときにちゃんとパスを指定しよう。指定しないと保存されないっぽい?
ドキュメントのフルパスからファイル名なり拡張子を抜き取るのが楽。
PNGSaveOptionsの中身で保存するときのオプションを設定できる。
saveAsで最後に指定しているのは拡張子のオプション。今回は小文字で保存する。
このドキュメントはもう使わないので、保存したらcloseで閉じている。

とりあえずタイトルどおりのスクリプトを作ったときの処理と、
処理の簡単な内容及び注意事項をまとめてみた。
かなり長くなってしまったなあ。

2013年10月15日火曜日

MySQL 連番を振る

テーブルに新しいカラムを追加した際に、ユニークな連番を振らなくちゃならなくなった。
どう考えても手作業じゃ面倒だぞ、と思っているときにいい情報を見つけたのでメモ。

参考サイト
MySQL連番を振る ≪ グリニッジ株式会社

/*---------------------------------------------------------------------------*/
    SET @i := 0;
    UPDATE データベース名 SET カラム = (@i := @i +1);
/*---------------------------------------------------------------------------*/

MySQLって変数使えたのね。

2013年10月11日金曜日

Photoshop7 スクリプトでレイヤーをPNGファイルに書き出す

psdファイルからレイヤーを読み取ってpngファイルとして出力できないかな、と
思って調べていたら、そもそもjavascriptでPhotoshopそのものに機能を追加できるらしい。
早速使ってみた。

参考サイト

Photoshop7でスクリプトを使用できるようにする

CS系列にはデフォルトでスクリプト機能が用意されているみたいなんだけど、7にはない。
AdobeさんからPhotoshopScripting102aというexeファイルをダウンロードだ!
実行すると、「ファイル」→「自動処理」の欄にScripts...というメニューが追加される。
最初からサンプルがあるので適当に実行。ばっちり動いた。

レイヤーをPNGファイルに書き出す

そらかぜ工場さんの「スクリプトを使う」のページからPhotoshop7用の
SplitLayersというスクリプトをダウンロード。
実行するとpsdファイルがあるフォルダにレイヤー別にpsdファイルとして出力される。
psdファイルとして、出力される。

今回の目的はPNGファイルとして書き出すこと。しかしネット上には情報がないぞう。
というわけでリファレンスとにらめっこしつつダウンロードしたファイルを弄ってみました。
FileオブジェクトのsaveAsメソッドでデータを保存しているようなので、単純に考えてここかな、と
あたりを付けて調べる。

/*---------------------------------------------------------------------------*/
newFile = new File( baseName + layerName ); // 新規ファイル名
newDoc.saveAs( newFile, saveOpt, false, Extension.LOWERCASE ); // 保存
newDoc.close(); // 作成したファイルを閉じる
/*---------------------------------------------------------------------------*/

最初は拡張子でExtensionじゃない? と思ったんだけどリファレンスを見る限り違うっぽい。

/*---------------------------------------------------------------------------*/
    Extension
    LOWERCASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    NONE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    UPPERCASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/*---------------------------------------------------------------------------*/

それで次に目をつけたのがsaveOpt。保存のオプション。怪しい。
SaveOptionsでリファレンスを検索してみたら、PNGSaveOptionsを発見。
引数saveOptをPNGSaveOptionsに変更してみたら、PNGで書き出しができた。


ネットにあるのが基本的にCSの情報っぽいのがきつい。
今回みたいにもとになるものがあるならなんとかなるけど、0から作るのは厳しいかも。
リファレンスとのにらめっこは必須なり。

2013年10月10日木曜日

Python PIL(pillow)を入れてAtlasGenを動かす

Pythonを入れた目的であるAtlasGenを動かす。

PIL(pillow)をインストールする


AtrasGenを動かすにはPILが必要だというので、インストールする。
PILは開発が停止しているため、pillowをインストールするほうがよさそう。
2.7にはPILも対応しているらしいので、PILでもいいかもしれない。

なにはともあれ早速インストール。
ここで注意するのが、pipでインストールしないこと。easy_installを使う。
pipでインストールすると、インストール時に律儀にビルドしてくれちゃって、
jpegやzlibをちゃんと入れていないと使えないpillowが作られちゃう。


これでかなり詰まった。わざわざ自分でlibjpegをインストールしたり、かなり遠回りした。
eazy_installでさあ、インストール!

/*---------------------------------------------------------------------------*/
    easy_install pillow
/*---------------------------------------------------------------------------*/


AtlasGenを使う



このサイトが分かりやすい。画像ファイルなんかもそのままいただいちゃってテスト。
無事ファイルが生成されたー。
pillowでかなり詰まったのでとても長かった。


今回できたテクスチャを見る限り配置はちゃんと極力無駄なく作成されるようになっているのかな?
アルゴリズムを解析して、photoshopのレイヤーからアトラステクスチャ作る
スクリプトとか作ってみたい。

Python インストール+pipを入れる

AtlasGenというテクスチャ自動配置ツールを見つけたので、
こいつは面白そうだ、と早速使ってみようとしたらば、Pythonで動くツールだった。
というわけでPythonをパイソンと読むことすら知らなかった自分が
Pythonとpipというものをインストールしてみたお話。

Window版Pythonをインストールする


Windows環境でやっているので、まずはサイトからWindows用のインストーラーを入手。
AtlasGenは3.x系では動かないようなので、2.7を入れる。
3.x系は後方互換が無視されているので、文法が変わっていたりするらしい。

インストールしたら環境変数にパスを通す。
マイコンピュータのプロパティ、詳細設定タブから環境変数をぽちっと。
PATHにインストールしたフォルダを追加。

/*---------------------------------------------------------------------------*/
    PATH=C:\path\Python27;
/*---------------------------------------------------------------------------*/

コマンドプロンプトでpythonを実行する。
なんか色々出てきて最後に >>> と出ていれば成功。

distributeをインストールする


easy_installというコマンドを使用するために必要だそうな。
いろんなものをイージーにインストールできるようになる。んだと思う。
古いサイトだとsetuptoolsと表記されていたりするけど、
更新がストップしたsetuptoolsの代わりに配布されているのがdistributeらしい。


distributeのインストールは簡単。こいつをダウンロードしてPythonで実行。

/*---------------------------------------------------------------------------*/
    python distribute_setup.py
/*---------------------------------------------------------------------------*/

pipをインストールする


/*---------------------------------------------------------------------------*/
    easy_install pip
/*---------------------------------------------------------------------------*/

以上です。ほんと、以上です。


これで大抵のサイトで紹介されているPythonの基本環境の構築ができた。はず。

2013年10月4日金曜日

jQuery leanModalを使ってみる

ボタンを押すと新しいウィンドウが出てきて、他の操作ができなくなるやつ。
モーダルダイアログというらしい。だからModalか。
今回はその中でも基本的な機能のみのleanModalを使う。

/*---------------------------------------------------------------------------*/

leanModalをダウンロードする

サイトからjsファイルをダウンロード。cssはセットになっていないので自分で作る。
ダウンロードしたのと同じサイトにサンプルがあるからそのままコピペでも十分。

leanModalを使う

以下のサイトがわかりやすく説明してくれてる。

表示するために追加する要素はきちんとdisplay:noneしてあげよう。
でないと一度実行されるまで堂々と画面に存在してくれちゃう。

/*---------------------------------------------------------------------------*/

基本的な機能のみというものの、これだけで十分な気もする。
closeButtonを指定してあげれば、閉じる用のボタンも作れる。

なにより基本機能しかないということは、カスタマイズ性が高いということ。
自分がほしい機能によっては既存のものを探すより、leanModalをもとにして自分で
作ったほうが早いかもしれない。


2013年10月1日火曜日

CakePHP ページネータの動作をモデルで定義する

正直、ページネータがモデルでなくコントローラにあるのってなんかおかしくない?
あくまでモデルのデータをどうこうしているのであって、コントローラの領分でないような。
と思いつつ使いますが。

通常通りでは普通にモデルからfindを呼んでくるだけのところを、モデルで
以下のメソッドを定義してやれば、自分でデータの取得の動作を定義することができる。

/*---------------------------------------------------------------------------*/

public function paginate( $conditions, $fields, $order, $limit, $page, $recursive, $extra )
public function paginateCount($conditions, $recursive, $extra)

/*---------------------------------------------------------------------------*/

それぞれデータの取得と全体数を取得するときに使うメソッド。
引数の中身はCakePHPを使っているなら名前で大体分かると思う。

2013年9月13日金曜日

CakePHP PageSpeedをChromeで使ってみた

よろしくないなあ、と思いつつサイトの高速化という問題から目を背け続けてきたけど、
いい加減やばいんでない? ということでサイト高速化についてちょこちょこ調べてみた。

参考サイト
表示が速過ぎても、誰も文句は言いません
ついに出た!Chrome版「Page Speed」の使い方

しかし、こうやって情報処理的な調べ物をするたびに、
どれもこれも最低限の専門知識を前提として語ってくるのは困る。
正直、なんちゃってエンジニアな自分にはきついなあ、と思うこともしょっちゅう。

PageSpeed


タイトルにもあるので一番に持ってきた。表示速度を調べた上で問題点も調べてくれるのだとか。
さっそくインストールして実行! なんか色々出てきました。
サイトとは色々違うけどバージョン変わったんかな? それとも別バージョン入れた?
なんにせよなにがなにを示しているのかはわかるのでオーケー。
色で判断で間違ってないよね?

すぐに対応できそうなのとして、色々画像が凝り固まっている部分をエレメントキャッシュ!
...相変わらずそこで怒られるぞい。CakePHP独自のキャッシュには対応してないのかな?
圧縮とかも試してみよう。

JavaScriptを圧縮しよう!


mod_deflateモジュールなるものが必要とな?
うちのxamppには最初から入っていたみたいなのでそのままゴー。
.htcaccessを弄る。以下の一文を追加。

AddOutputFilterByType DEFLATE text/html text/css application/x-javascript

エラー出たー!500エラー。
どうやらCakePHPはヘルパーなりコンポーネントなりを使用してjavascriptを圧縮するのが
正しいよう。この結論に自信はありません。

ちょいと調べて出てきたの。

JSMin Helperが良さそうかな。そのままJavaScript Helperのように使えるとか。
というわけでページからソースをコピペし、jsmin.phpもいただき実行してみた。
オーマイガ。めっさ怒られました。もしかして2.x系には対応していらっしゃらない...?
ソースコードを弄り弄りエラーをひとつずつつぶしていく。
で、なんとか動いた。afterRenderを全部コメントアウトしてみたりしたけど動いた。
PageSpeedにも怒られなくなってちょっとした達成感。
でも大して実行時間が変わっていないような...。
あれ? なんかミスった? それとももっと大きいファイルじゃないと目に見える変化がないのか。
要検証。

2013年9月12日木曜日

CakePHP2.x SmartyViewをいじったメモ

大体アプリケーション部分もできてきたのでぼちぼち負荷テストをはじめたんだけど、
どうしてもスループットが出ない。
どこが原因ぞ? と思い調べてみたらば、RenderringViewが笑える重さを誇っていた。700msて。
で、さらに調べるとSmartyが原因だった。
どこから取ってきたかを忘れたSmartyViewクラスをいじったので、その辺のメモ。

コンパイルを1回こっきりにする

Smartyクラスのcompile_checkにfalseを指定する。
結論から言えばこれだけであっさり早くなったんだけれども、ここにたどり着くまでが大変だった。
最初にこのテストをしたときにソースをさっぱり見ずにやったがためにその後に書いてある
clearCompiledTemplate()の記述に気づかなかった。
こいつのせいでコンパイルチェックを無効にしていても
毎回コンパイルファイルが削除されていたのだ。
そりゃ、そもそもチェックする対象がいなければSmartyもコンパイルせざるをえんでしょう。
こんなくだらないことで1日以上悩んだ。悔しいからメモ。

表示が変わらないページにはページキャッシュを利用しよう

基本的にほとんどのページが動的にデータが入れ替わるので結局見送りになっけんだけども、
せっかく調べたので忘れないうちに。鉄は熱いうちに打て。
ページそのものをキャッシュとしてとっておいてそのページをベーと吐き出してしまう。
ただ、CakePHPを使っていると、ちゃんとキャッシュIDを指定してやらないとどのページも
同じだと判断してくれちゃう。どのコントローラ行っても最初に表示したページのままだぞう。
CakePHPはアドレスでページを判別できるのでキャッシュIDにも同じように指定してやればいい。

$this->cacheid = $this->params->url;

これでオーケー。ただ、クエリが違うだけのページはやっぱり同じページに...。
本格的に利用するつもりならもうちょい調べる必要がありますかも。

2013年9月6日金曜日

アルゴリズム 選択肢

テキストに引き続き、ノベルゲームで使いそうな選択肢を考える。

基本動作

  1. 選択肢を表示する。
  2. 選択肢のどれが押されたかを返す。
  3. 戻り値を受けとってアプリケーション側がなんかする。
戻り値とアプリケーション側の応答の兼ね合いはどういったものを作ろうとしているかで変わる。
選択肢をどのように使うかが決まっていればあっさり決まるかと。

クラス設計

必要なメンバ変数はなんぞや?
  • 選択肢のテクスチャ。文字列とか。
  • 選ばれた選択肢。
  • 選択肢別の戻り値。
必要最低限。選ばれたの判断は選択時に戻り値を返す関数ならいらないけども。
メンバ関数。
  • 選択肢の描画。基本だと背景と文字列はセットになっている。
  • 選択肢ごとの当たり判定を取得する。
  • 選ばれた選択肢を返す。
これだけあれば基本はできそう。
選択肢単品だけど、中央ぞろえで表示とかそういった機能も実装すると別問題なので、
今回は無視。
でもいじりやすいようにひとつのクラスにまとめておくとよさそう。

jMeter 負荷テストわからないよう

jMeterを使って色々やってみたりしてはいるんだけど、未だに正しい使い方がよくわからない。
現時点で「こういうこと?」と思ったことをまとめてみよう。

いろんなサイトを参考にしつつ。資料集めならサイトに飛んだほうがきっと賢い。
A Day In The Boy's Life
 ここの負荷テスト関連がわかりやすい。個人的に他のエントリも面白かった。
TECHSCORE | jMeter
 jMeterの解説が載っている。テストケースの参考もあって大助かり。

webサイトが想定されるアクセス数に対しての負荷に耐えられるか調べる

常に想定数のユーザーがなんらかのリクエストを送っていればいいんだな?
と思って、以下のスレッドグループを作成。
  • スレッド数 : 想定される同時アクセス数
  • Ramp-Up期間 : 1
  • ループ回数 : 無限ループにチェック。
これで単純に実行。無限ループにチェックが入っていると終わらないので、
スケジューラを使ってテスト期間を設定するか手動で終了する。
ただ、これだと本当に一度にリクエスト送られるから初動ですごい負荷かかるんだよね。
Ramp-Up期間を若干広げて少しずつスレッドを送るようにしたほうがいいのかな?

最大でどれだけの負荷に耐えられるか?

ようは上のやつの想定数の値がわからないときの場合...のはず。
どこのページでも何回かテストを繰り返して判断するみたいなことを言っているし。
  • n=テスト回数
  • スレッド数 : 10かけることのn
  • Ramp-up期間 : 1
  • ループ回数 : 無限ループにチェック
  • テスト時間はとりあえず3分
この条件でやってみる。テスト時間は適当に出した値なので当てにしない。
スループットが下がり始めたらそこが限界点!

多分このふたつは考え方は間違っていない、と思う。間違ってないよね。間違ってないといいな。
これをもとにして、色々シナリオ組んだりなんだりすればいいのかなあ?


2013年9月5日木曜日

アルゴリズム ゲームにおけるテキストの表示

どんなゲームでも文字列の表示はあるでしょう。...あるよね?
今回はノベルゲームで使われそうなテキストについて考える。

必要な機能

機能として必要そうなものを列挙する。
  • 文字列を表示する
  • 時間経過による表示の進行
  • ボタンを押されたことによる全表示処理
  • 上記の処理後のテキストの追加
最後の機能はテキストを全画面表示や、表示と表示の間になんらかの演出を挟むための。
分割ボイスを再生とか。

クラス設計

各機能に対して必要な関数やメンバはなにか。
まずはメンバ。
  • 文字列のテクスチャ。これは行ごとに持つ。追加にも対応できるはず。
  • 更新時間を計測するタイマ。
  • 1タイマにつき表示するテキスト量。
  • 全表示を完了しているか。テキストの役目が終了してることをメインフレームに伝える
あれ? こんなもん?
次は関数。というか必要な動作。
  • タイマに合わせて文字列の表示範囲を調整。
  • ボタンの入力を確認。
  • タイマにかかわらず全文字を表示する。あるいはタイマを強制繰上げ。
  • 文字列のテクスチャを追加する。タイマはリセットされない。
文字列の追加は行単位の細かいオブジェクトして追加でもいいかも。

これだけあれば行ける? まあ、開発していればいやでも足りないものは見つかるでしょう。

2013年9月3日火曜日

SWF 構造に対する知識が足りない

SWFを解析して表示できるようにしたい。
そのためにはまず基本知識が必要だ!

わかりやすい解説を見つけたのでメモ。
・How to read SWF

2013年9月2日月曜日

jMeter Proxyサーバを使用してサンプラーを作成する

jMeterで自分でいちいちサンプラーを設定するのは面倒。
Proxyサーバを使えば自分のアクセスをそのまま使用できるということで、
Proxyサーバがなんなのかもわからないけどやってみよう。

今回は以下のサイトを参考にしました。
・JMeter 2.7つかってみた:プロキシー設定
http://sy5.sakura.ne.jp/jmeter/jmeteproxy.html

/*---------------------------------------------------------------------------*/

まずは「HTTPプロキシサーバ」を追加。
ワークベンチから「追加」→「Non-Testエレメント」→「HTTPプロキシサーバ」

Proxyサーバの設定をする。
なんか色々あるけどよくわからんので、対象となるコントローラから、
今回のスレッドグループを選択だけしておく。

開始! なんか警告が出てきたけど、知ったこっちゃねえぜ!

使用しているブラウザのプロキシ設定を変更。
Chromeを使用しているので設定から詳細設定で変更。
使用しているOSのプロキシ設定が立ち上がるので、
アドレスを localhost に、ポートをjMeterで設定されてるやつにする。

ブラウザでアクセス!

なんか色々できた。
不要なものは右クリックで消してしまう。
やってしまえば意外となんとかなった。

/*---------------------------------------------------------------------------*/

2013年8月30日金曜日

CakePHP セッションにデータベースを利用する

複数サーバーを利用するというので、通常のキャッシュを使用すると
お互いに参照先が違うという問題が発生。
CakePHP はデフォルトでデータベースを使ったセッションが提供されている
そうなので使ってみた。

まずは以下のクエリをデータベースで発行。

/*---------------------------------------------------------------------------*/

CREATE TABLE IF NOT EXISTS `cake_sessions` (
    `id` varchar(255) NOT NULL DEFAULT '',
    `data` text NOT NULL,
    `expires` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

/*---------------------------------------------------------------------------*/

次に core.php を編集。Session の設定が書いてあるところ。

/*---------------------------------------------------------------------------*/

Configure::write('Session', array(
    'defaults' => 'database',
));

/*---------------------------------------------------------------------------*/

データベースを使用するための設定はこれだけで十分です。
さっそくテスト。

/*---------------------------------------------------------------------------*/
Error: Table app_models for model AppModel was not found in datasource default.
/*---------------------------------------------------------------------------*/

エラー出たよ。なぜか app_models テーブルがないと怒られている。
試しに useTable を書き換えてみたら別のエラーで怒られた。
なので、使用するモデルを自分で指定する。

core.php に追加。

/*---------------------------------------------------------------------------*/

Configure::write('Session', array(
    'defaults' => 'database',
'handler' => array(
'model' => 'CakeSessions'
)
));

/*---------------------------------------------------------------------------*/

CakeSessions というテーブルを作り、そのモデルを呼び出すように変更。
エラーが出ることはなく、セッションもしっかり機能した。

2013年8月29日木曜日

jMeter はじめての負荷テスト

JMeter を使って負荷テストをすることになった。
ぶっちゃけ触ったことすらないのでまずは基本操作を覚える。

参考
・今から3分で jmeter の使い方を身に付ける  (負荷テスト入門)
http://d.hatena.ne.jp/language_and_engineering/20081014/1223905380

/*---- インストール ---------------------------------------------------------*/

公式サイト(http://jmeter.apache.org/)から
apache-jmeter-x.x.zip をダウンロード。x はバージョンです。
解答して任意の場所に移して bin/jmeter.bat を起動しましょう。
なんかそれっぽい画面が立ち上がったら成功です。

/*---- 動かしてみる ---------------------------------------------------------*/

1.左にある「テスト計画」を右クリック。
    「追加」→「スレッドグループ」で適当にパラメータを登録。
    とりあえず参考にしたサイト通りにスレッド数を50。
    Ramp-up期間を10秒にしてみます。
    Ramp-up期間はスレッド立ち上げ期間のことだそうです。
2.できたスレッドグループからさらに
    「追加」→「サンプラー」→「HTTPリクエスト」。
    サーバ名を使用するサーバに、パスをアクセスする場所に。
3.さらにスレッドグループから
    「追加」→「リスナー」→「結果を表で表示」。
4.適当な名前をつけて保存。
5.実行!

できた。表で表示した結果はそのままエクセルにコピーできるみたい。便利。

/*---- 色々機能を使う -------------------------------------------------------*/

・リスナーを色々使ってみる
  テストの結果を表示するにはリスナーを使う。上で使ったもの以外にも色々ある。
  「統計レポート」や、「結果をツリーで表示」は使えるかと。

・GETパラメータの送信
  クエリ。HTTPリクエストの「リクエストで送るパラメータ」というところに
  値を追加すればいけた。

/*---- 外部ファイルから変数を持ってくる -------------------------------------*/

他にも方法があるのかもしれませんが、今回は CSV を使用。

1.CSVファイルを作成する
    行が1スレッドに割り当てられる変数。
    列が各変数の値。
    わかりづらいけど表にするとこんなん

/*---------------------------------------------------------------------------*/
                   | value_1   | value_2     |
    thread_1    | hoge      | hogehoge  |
    thread_2    | fuga       | fugafuga   |
/*---------------------------------------------------------------------------*/

    作成したファイルは bin 直下に置くのがパスも気にしなくていいので楽。

2.HTTPリクエストから「設定エレメント」→「CSV Data Set Config」を追加。
    FileName にパスを通して、
    Variable Names に変数名を設定。今回は name,pass とでもしておきます。
    この設定により jMeter 上ではこうなる。

/*---------------------------------------------------------------------------*/
                   | name      | pass      |
    thread_1    | hoge      | hogehoge  |
    thread_2    | fuga      | fugafuga  |
/*---------------------------------------------------------------------------*/

3.HTTPリクエストの「送信するリクエストパラメータ」に追加。
    jMeter で設定した変数を使う場合は ${name} ${pass} というふうにする。

一通りやってみたことまとめ。
なんとなく jMeter を使った気分!

2013年8月28日水曜日

php 文字列の長さを調べる

フォームからの入力文字数を制限する必要ができた。

phpで文字列の長さを調べる関数は strlen がぱっと出てくる。
しかし、この関数にはちょいとした問題がある。
たとえば

/*---------------------------------------------------------------------------*/

$str = "文字列mozire";
var_dump( strlen( $str ) );

/*---------------------------------------------------------------------------*/

今回の場合欲しい結果は int(12)。
しかし int(15) と表示されてしまう。
strlen は文字エンコーディングを考慮せず
単純にバイト数を引っ張ってくる関数なのでこういう結果になる。

php には文字列の長さを取る関数だけでも複数あるみたいで、
今回の目的にあっているのは mb_strwidth という関数みたい。
文字列の見た目の長さを引っ張ってくる関数。見た目て。

使ってみた。

/*---------------------------------------------------------------------------*/

$str = "文字列mozire";
var_dump( mb_strwidth( $str ) );

/*---------------------------------------------------------------------------*/

ばっちり。ちゃんと int(12) と表示された。

ついでに、入力された文字列を指定の文字数内に丸めるという処理もしたい。
mb_strimwidth という関数がそれをやってくれるようだ。
名前が似ていて間違いそう。

/*---------------------------------------------------------------------------*/

$str = "文字列mozire//ここから切られる";
var_dump( mb_strimwidth( $str, 0, 12 ) );

/*---------------------------------------------------------------------------*/

/ 以下を切り取る。
    string(15) "文字列mozire"
と表示されるはず。
丸める際に丸めた先にくっつけたい文字列も指定できるので、
まだ続きますよという表示のときに使われる...もこれでくっつけられそう。

2013年8月27日火曜日

php 絵文字を判定する

絵文字をチェックしたい。絵文字を取り除きたい。
そんなことを思った。

いくつか方法があるみたいだけど、簡単かつ高速ということで
HTML_Emojiを使ってみる。
公式(?)サイトにあるのは古いのかiPhone5の絵文字には対応していないので
以下からダウンロード。

http://download.revulo.com/PHP/HTML_Emoji-20111114.zip

iPhoneでテストしていたのでこれに気づかずにしばらくはまった。
自分も適当にネット上から見つけてきたものなので、
このファイルの由来がわからんのがちょっと怖い。
誰か知ってたら教えて。

使い方

/*---------------------------------------------------------------------------*/

// HTML_Emoji
require_once 'HTML/Emoji.php';
$backup = error_reporting(0);
$emoji = HTML_Emoji::getInstance();
error_reporting($backup);

// docomoの絵文字
$text = "晴れ\xEE\x98\xBE";

// 絵文字が存在するか?
if( $emoji->hasEmoji( $text ) ) {
    // 絵文字を取り除くs
    $text = $emoji->removeEmoji( $text )
}

/*---------------------------------------------------------------------------*/

getInstanceを呼び出すときに、
PHP5で使うとE_STRICTレベルのエラーが発生する。
PHP5で推奨されない記法(PHP4由来のもの)などに対する警告らしい。
エラー文を抑制するために、

/*---------------------------------------------------------------------------*/

$backup = error_reporting(0);
$emoji = HTML_Emoji::getInstance();
error_reporting($backup);

/*---------------------------------------------------------------------------*/

で挟む。
あとは文字列を各メソッドに渡してやるだけ。
サンプルでいちいちhasEmojiで調べているのは自分の目的が
どちらかというとそっちにあったからで、
実際に使用するときにはいちいちチェックする必要はないです。

2013年8月23日金曜日

jQuery 画像をスライドさせる

バナー画像をスクロールさせよう。
そんな感じのをいろんなサイトで見かけるぞ。

ということで
そのいろんなサイトでバナーをスクロールさせているjQueryプラグイン bxSlider を使う。

使い方は簡単。
サイト(http://bxslider.com/)からファイルをダウンロードして、
使用しているサーバーの適切なディレクトリに配置。
使用したいページで呼び出す。

/*---------------------------------------------------------------------------*/

<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.bxslider.min.js"></script>
<script type="text/javascript">
$(function() {
  $('.bxslider').bxSlider(
    auto:true,
    responsive:true,
    slideWidth:240 });
});
</script> <div id="title">bx_slider</div> <ul class="bxslider">
    <li><img src="/images/pic1.jpg" /></li>
    <li><img src="/images/pic1.jpg" /></li>
    <li><img src="/images/pic1.jpg" /></li>
</ul>

/*---------------------------------------------------------------------------*/

たったこれだけのコードでできちゃう!
便利便利。
オプションで色々設定もできるみたい。

今回は以下の二つのサイトを参考にしました。
http://wp-and.me/bxslider/
http://cotdeve.com/blog/jquery/jquery-%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC-bxslider/

ところでbxSliderのbxってなんなんだろう? まさかboxじゃないよね。

Objective-C cppファイルを使う

Windows上でVisual Studioを使って開発して、
最後の仕上げ(iphoneへのインストールとか)だけXCodeでできないかと四苦八苦中。

それっぽい資料を求めてさまよっていたときに、有用そうな情報を見つけたのでメモメモ。

情報元

/*---------------------------------------------------------------------------*/

・Objective-Cではcppファイルをそのまま使えるらしい。
・しかし、もとのObjective-Cのファイル(m,mmも?)で使用するとエラー。
・XCodeではファイルタイプによってコンパイル方法が変わっているとか。
・ファイルタイプを変更すると怒られなくなる!

/*---------------------------------------------------------------------------*/

まだ調べている段階なのでテストはしていない。

2013年8月20日火曜日

Smarty PHPの定数を使う

PHPではdefineを使うことで定数を定義できる。

define( "MY_DEFINE", "define_value" );

このPHPで定義した定数をさらにSmartyから使うことができる。

{$smarty.const.MY_DEFINE}

何気に便利なんじゃなかろうか。

CakePHP saveの罠

MySQL側でtinyintかつ長さを1に設定しているとCakePHPが勝手に論理値と判断する?

saveメソッドを呼び出すと0は0でいいんだけど、1以上の値はなにを渡しても必ず1になる。
だいぶ前に気づいていてMySQL側のtinyintを全部長さ3にしといたつもりだったんだけど
漏れがあってしばらく悩んだ。

2013年8月15日木曜日

SDL 日本語フォント

SDLではTTF(TrueTypeFont)を使用することができる。
これを使用して日本語フォントを表示する。
SDL_ttf.dllをプロジェクトと同じフォルダにおいてライブラリとリンクさせておこう。

具体的な使用法はこのサイトがわかりやすい。
http://utsukemononi.gozaru.jp/gc/sdl/page008.html

ただ、サイトにもあるように、読み込む時にSJISからの変換が必要になる。
MultiByteToWideCharとWideCharToMultiByteを使えば変換ができそうだ。

//-----------------------------------------------------------------------------

char* src = "日本語フォント"
char dst[64];

// UTF16のサイズを取得する
int size = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)src, -1, NULL, 0 );

// ShiftJISからUTF-16へ変換
BYTE* buffer16 = new BYTE[ size * 2 + 2 ];
::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)src, -1, (LPWSTR)buffer16, size );

// UTF8のサイズを取得する
size = ::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffer16, -1, NULL, 0, NULL, NULL );

// utf8に変換する
::WideCharToMultiByte( CP_UTF8, 0, (LPCWSTR)buffer16, -1, (LPSTR)dst, size, NULL, NULL );

//-----------------------------------------------------------------------------

大体こんな感じで変換したバッファを渡したらちゃんと日本語で表示された。

2013年8月7日水曜日

php 16進数を扱う

phpで16進数の文字を取り扱うことになった。
変換するための関数があったぞう。

    // number   16進数データ
    // from     変換前の基数
    // to       変換後の基数
    base_convert( $number, $from, $to );

今回は16進数から10進数へ変換する

    $hex = "00000101";
    $dec = base_convert( $hex, 16, 10 );

decの中身が257。
おっけ。

CakePHP2.x 自作クラス(関数)を使用する

CakePHPは一応MVCとなっているのでフォルダ構成もそれに合わせてある。

    app
    -model
    -view
    -controller

というふうになってる。もちろん他にも色々あるけど必要なのだけ抜粋。
で、自分が作ったMVCのどれにも含まれないクラスを作ったとき、
どこに置けばいいんでしょう、と疑問に思った。

appの直下にvendorというフォルダがあるのでそこにやるといいそうな。
phpファイルにまとめて置く。
あとは使用時にインポートするだけ。

    App::import( "Vendor", "Hoge" );
    $hogeClass = new Hoge();        // クラス
    hoge();                         // 関数呼び出し

読み込んだファイルの中身はあとは気にせず使えます。

2013年8月6日火曜日

CakePHP2.x viewを指定する

$this->render('hoge_view');

CakePHP2.x SplFileInfo::openFileエラー

Warning:
SplFileInfo::openFile
(/www/app/tmp/cache/persistent/myapp_cake_core_cake_console_):
failed to open stream:
Permission denied in /www/lib/Cake/Cache/Engine/FileEngine.php on line 314

とかいうエラーが出るようになった。
ファイルの所有者とアクセスユーザーが違うことで起きるエラーらしい。
umaskを設定すればいいですよ、とのことだが、まずumaskってなんですか?

調べた。
ファイル作成時に、利用できるパーミッションを指定するものだそうな。

アクセスユーザーからもファイルを取得できるようにcore.phpを編集する。

    Cache::config('_cake_core_', array(
        'engine' => $engine,
        'prefix' => $prefix . 'cake_core_',
        'path' => CACHE . 'persistent' . DS,
        'serialize' => ($engine === 'File'),
        'duration' => $duration,
        'mask' => 0666,
    ));
    Cache::config('_cake_model_', array(
        'engine' => $engine,
        'prefix' => $prefix . 'cake_model_',
        'path' => CACHE . 'models' . DS,
        'serialize' => ($engine === 'File'),
        'duration' => $duration,
        'mask' => 0666,
    ));

警告文が出なくなった。

2013年8月5日月曜日

php jsonデータ

PHPではjsonと呼ばれるデータ型を扱えるらしい。
JavaScript Object Notation の略だそうな。

    [[2,1],[33,4]]
    {"2":1,"6":1,"9":1}

こんなん。
{} がオブジェクト形式で : で隣接したデータが対になる。
[] が配列形式だとか。
こいつを文字列データから PHP で使えるデータにデコードする。

    $json = json_decode( '[[2,1],[33,4]]' );
    $json = json_decode( '{"2":1,"6":1,"9":1}', true );

第二引数にtrueを指定すると連想配列になって返ってきます。
ちょいと複雑なごちゃごちゃしたデータをデータベースに保存したりとかに
便利そう。

CakePHP2.x findの戻り値

しょっちゅう忘れるのでメモ。

SQL文にエラーがあれば例外を投げてくれるからそのときは気にしなくても
いいんだけど、SQL文がエラーを起こさない場合は配列が返ってくる。
結果が空だろうと何だろうと配列が返ってくる。

findでデータが取得できなければエラーという処理を作りたければ、

    $data = $this->Model->find( "all" );
    if( count( $data ) === 0 ) {}

という風にカウントで配列の個数を取るようにしよう。
findByを使ったときも同じ。

2013年8月1日木曜日

CakePHP2.x Shellを使う(実行編)

せっかくShellを使ってもテストをしないのはよくないということで(当たり前)
コマンドプロンプトなんてほとんど使ったことないけどネットとお友達になりつつ
やってみる。

まずはコマンドプロンプトを開き環境変数のパスを通す。
(xamppはc直下)

    c:\xampp\php>SET PATH=%PATH%;%CD%
    c:\xampp\htcdocs\hoge\app\Console>SET PATH=%PATH%;%CD%

多分現在のディレクトリにパスを通しているんでしょう。きっと。
CDってあるし。
そしてディレクトリをappまで移動して、Shellを実行。

    C:\xampp\htdocs\hoge\app>cake Test

怒られた。細かいメッセージ文は忘れたけど、PHPUnitとかいうのがないとか。
再びネットの海に潜り検索検索。

xamppにPHPUnitをインストールするためにはpearとかいうのを使うらしい。
PEAR(PHP Extension and Application Repository)の略でPHPで利用できる
ライブラリを提供しているサービス。

xampp(というよりもPHP5?)には最初からインストールされているらしいので
アップデートしてからPHPUnitをインストール!

    pear update
    pear install phpunit/PHPUnit

はい怒られましたよ。php_compatがないらしい。これは普通にインストールできそう。

    pear install php_compat

そして再びのインストール!

またしても怒られた。こんどはPHP_Invokerとやらが問題を起こしているらしい。
ご丁寧に警告文に-alldepsオプションを指定しておくれと書いてあったので
オプションを指定してインストール!

    pear install --alldeps phpunit/PHPUnit

今度は成功メッセージが表示されたぞ。ということで早速ちゃんとインストール
されているかの確認もかねてバージョンチェック

    phpunit --version
    Warning: require_once(PHPUnit/Framework/MockObject/Autoload.php)
    fatal error

ほ? PHPUnit/Framework/MockObjectがないとな?
モニターの前で試行錯誤するも答えが見つからず知ってそうな人に泣きつく。
んで、

    pear install --alldeps --force phpunit/phpunit
    pear install --force phpunit/PHPUnit_MockObject

この二つのコマンドを順番に実行したらちゃんとインストールされた。
やったー。ようやくテスト環境が整ったぞ。
 
    C:\xampp\htdocs\hoge\app>cake Test

    Welcome to CakePHP v2.3.5 Console
    ---------------------------------------------------------------
    App : app
    Path: C:\xampp\htdocs\hoge\app\
    ---------------------------------------------------------------
    test message

でけたー!

php 警告文とはいえ放置はよくない

xamppを色々いじってから

    Warning: Module 'pdo_sqlite' already loaded in Unknown on line 0

という警告が出るようになって
何なんだろうと思っていたら、どうやらインストール時に自動的に
読み込んでいるのを再読み込みしていたせいらしい。

PHP Warning: Module '*' already loaded in Unknown on line 0
http://www.omnioo.com/omnioolab/2011/11/php-warning-module-already-loaded-in-unknown-on-line-0.php

2013年7月30日火曜日

jQueryを使ってみた -要素の取得とbindメソッド-

jQueryどころかjavascriptすら良く知らないけど、
webページでスライダーを使うというからやってみた。
jQueryって支援ライブラリだったのね。

とりあえず参考ソースが手元にあったのでそれを参考にする。

...うまくいかねえ!

というわけでネットで調べつつ初歩の初歩からやってみる。

まずはhtml上の要素を取得する

    var element = $("div");     // 要素の名前で直接
    var element = $("#hoge");   // id
    var element = $(".hoge");   // class

あら簡単。
さあやってみよう。

...またしてもうまくいきませんよ?

苦悩にうなり声を上げつつ格闘し続けた結果、原因がわかった。
javascriptの定義のところにべた書きしてたのが問題っぽい。
window.onloadメソッドの中でやったらちゃんと要素を取得できた。
要素がそもそも生成されていなかったってことか?
なんにせよ要素が取得できたので次に進む。

要素を取得したらば次は取得した要素がタッチしてるときに反応するようにする。
bindメソッドを使えばそれができるらしいぞ。

    obj.bind( "click", function(){
        alert( "click event" );
    } );

メソッドのテストをしたいだけなので要素がクリックされたらアラート画面を呼び出す。
今度はつまずくことなくうまくいった。

とりあえず簡単にjQuery。
...まさかたったこれだけのことをやるのに半日以上かかるとは...。

2013年7月29日月曜日

CakePHP2.x モデルのバインドパラメータ

いちいち調べるのも面倒なので
自分がよく使う使い方のものだけまとめておく

$hasOne = array(
"ModelName" => array(
"type" => "inner",
"className" => "ModelName",
"foreignKey" => false,
"conditions" => array(),
),
);
$model->bindModel( array( "hasOne" => $hasOne ) );

こうして毎回動的に生成するのは果たしてどうなのか。
とはいえ、ページごとにテーブルに求めたいデータというのは異なるものになりがちなので
こうしたほうがいい気がする。

foreignKey を false に指定すると conditions で指定した条件でテーブルが結合される。
最後に、モデルにバインドされているアソシエーションを解除する方法。

$model->unbindModel( array( "hasOne" => array_keys( $model->hasOne ) ) );

アソシエーションの種類により hasOne のところは変化する。

CakePHP2.x シェルを使う

CakePHP2.x系でシェルを使うには

/app/Console/Command/TestShell.php

<?
class TestShell extends AppShell
{
        public function main()
  {
                CakeLog::write( "debug", "test" );
  }
}
?>

テストなので適当にログを吐き出すだけ。
ほとんどコントローラっぽく使えるようだ。

<?
// ※未テスト
class TestShell extends AppShell
{
        public $uses = array( "User" );

public function main()
{
                $this->User->find( "all" );
}
}
?>

あとはこいつをシェルスクリプトから呼び出せばいい。
メソッド名がmainの場合は引数で渡さなくても勝手に解決してくれるみたい。

        $ /app/Console/cake Test -app

さて問題は、シェルスクリプトもそもそもあまりコンソールにも触らない自分は
cronどころかそもそもシェルスクリプトがどういったものなのかすら知らないということだ。

なのであくまでCakePHPのシェルクラスの作り方ページ

参考にしたサイト
http://blog.xao.jp/blog/cakephp/cakephp-2-0-%E3%81%A7-cron-%E3%82%92%E4%BD%BF%E3%81%86/

2013年7月26日金曜日

SDLでマウスを使う

SDLでマウスの情報を取得するための関数

    Uint8 SDL_GetMouseState(int *x, int *y)

戻り値が現在押されているボタン
引数が座標

ボタンに関してはとりあえず1が左ボタン、3が右ボタンで十分かな
数値分ビットシフトした値が入ってくる