2013年1月27日日曜日

LDAP 基礎

dc (domain component) 完全修飾ドメイン名の単一のドメインコンポーネント
c (country name) 2文字の国コード
l (locality name) 地理的な場所名
ou (organizational unit) 該当エントリが所属する部局(局・部・課など)
o (organization name) 組織名
cn (common name) オブジェクトの名前(フルネーム)
sn (surname)
gn (givenName) 名, ファーストネーム
st 州や県などのフルネーム
mail メールアドレス
telephoneNumber 電話番号
mobile 携帯電話
uid 該当アカウントのログイン名
userPassword エントリーのパスワード
serialNumber 装置のシリアルナンバー
description 説明・特徴など

[MySQL]自動バックアップ

データベースの自動バックアップ用バッチファイル (Windows)
以下のバッチファイルを起動時に走らせることでデータベースの自動バックアップができるようになる。
set DBNAME=cake_test
set BACKDATE=%date:~0,4%%date:~5,2%%date:~8,2%
if "%time:~0,1%"==" " (set BACKTIME=0%time:~1,1%%time:~3,2%%time:~6,2%) else (set BACKTIME=%time:~0,2%%time:~3,2%%time:~6,2%)
set BACKUP_FILENAME=%DBNAME%_%BACKDATE%_%BACKTIME%.sql
c:\usr\xampp\mysql\bin\mysqldump.exe -h localhost -u your_account --pass="your_password" %DBNAME% > sql_backup\%BACKUP_FILENAME%
バックアップファイル名は 2009/03/26 8:27:45 に作成すると cake_test_20090326_082745.sql となる。
%date% により 2009/03/26 という文字列を得ることができる。%date:~0,4% で %date% の 0 文字目から 4 文字だけ切り出したものを得られる。同様にして以下の部分で 20090326 という文字列が BACKDATE に代入される。
set BACKDATE=%date:~0,4%%date:~5,2%%date:~8,2%
%time% により 8:27:45.30 という文字列を得ることができる 時間が 1 桁台の時は 0 文字目が空白になっているので if 分により 0 埋めを行うか判断している。以下の部分で 082745 という文字列が BACKTIME に代入される。
if "%time:~0,1%"==" " (set BACKTIME=0%time:~1,1%%time:~3,2%%time:~6,2%) else (set BACKTIME=%time:~0,2%%time:~3,2%%time:~6,2%)

[MySQL]使い方

SQL参考ページ
SQL Tutorial

SQLサーバーに接続する
$ mysql -uユーザー名 -p データベース名
Enter password:

カラムの情報を表示する
mysql> DESCRIBE テーブル名;

SQLサーバーから切断
mysql> quit;

条件に該当するものを検索
SELECT * FROM table WHERE column_name operator value;
SELECT no,name FROM test WHERE name = 'dog';

検索結果を昇順・降順に表示する
SELECT * FROM table WHERE column_name operator value ORDER BY column_name ACS|DESC;
例(昇順: 若い番号が先)
SELECT no,name FROM test WHERE name = 'dog' ORDER BY no ACS;
例(降順: 若い番号が後)
SELECT no,name FROM test WHERE name = 'dog' ORDER BY no DESC;

あいまい検索
SELECT * FROM table WHERE column_name LIKE pattern;
SELECT no,name FROM test WHERE name LIKE "%john%";

条件に該当しないものを検索
SELECT * FROM table WHERE NOT column_name = 'word';
SELECT no,name FROM test WHERE NOT name = 'dog';

条件に該当するレコードの件数を取得する
SELECT COUNT (column_name) FROM table WHERE column_name operator value;
SELECT COUNT(no) FROM test WHERE name = 'dog';

日毎の件数を取得する
SELECT date, COUNT(date) as cnt FROM table WHERE column_name operator value GROUP BY date;
SELECT date, COUNT(date) as cnt FROM test WHERE name = 'dog' GROUP BY date;

[MySQL]文字化け対策

取得したデータが文字化けする場合は /usr/xampp/mysql/bin/my.cnf の[mysqld]セクションに以下を追加する
default-character-set=utf8
skip-character-set-client-handshake
1行目: デフォルトの文字コードを指定
2行目: サーバー・クライアントの文字コードが違っていても内部変換することを抑制する

[MySQL]phpMyAdmin インストール (Fedora13)

  1. インストール
    # yum install phpMyAdmin
    
  2. /usr/share/phpMyAdmin にインストールされるので /var/www/html からスタティックリンクを張る。
    # cd /var/www/html
    # ln -s /usr/share/phpMyAdmin phpMyAdmin
    
  3. httpd.conf を編集して index.php が読み込まれるようにする。
  4. DirectoryIndex に indx.php を追加。
    DirectoryIndex index.html index.html.var index.php
    
  5. アクセス
    localhost/phpMyAdmin にアクセスするとパスワードを聞かれるので MySQL にアクセスできるユーザー/パスワードを入力する。

[MySQL]インストール (Fedora13)

  1. インストール
    # yum install mysql-server
    
  2. 設定
    /etc/my.cnf に以下を追加する。
    [mysqld]
    default-character-set = utf8
    [client]
    default-character-set = utf8
    
  3. 自動起動の設定
    # chkconfig --list mysqld
    mysqld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
    # chkconfig mysqld on
    # chkconfig --list mysqld
    mysqld 0:off 1:off 2:on 3:on 4:on 5:on 6:off
    
  4. 今回は手動で起動
    # /etc/init.d/mysqld start
    MySQL データベースを初期化中: Installing MySQL system tables...
    OK
    Filling help tables...
    OK
    To start mysqld at boot time you have to copy
    support-files/mysql.server to the right place for your system
    PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
    To do so, start the server, then issue the following commands:
    /usr/bin/mysqladmin -u root password 'new-password'
    /usr/bin/mysqladmin -u root -h fedora.local password 'new-password'
    Alternatively you can run:
    /usr/bin/mysql_secure_installation
    which will also give you the option of removing the test
    databases and anonymous user created by default. This is
    strongly recommended for production servers.
    See the manual for more instructions.
    You can start the MySQL daemon with:
    cd /usr ; /usr/bin/mysqld_safe &
    You can test the MySQL daemon with mysql-test-run.pl
    cd /usr/mysql-test ; perl mysql-test-run.pl
    Please report any problems with the /usr/bin/mysqlbug script!
    [ OK ]
    mysqld を起動中: [ OK ]
    
  5. 初期設定
    # mysql_secure_installation
    NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL
    SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
    In order to log into MySQL to secure it, we'll need the current
    password for the root user. If you've just installed MySQL, and
    you haven't set the root password yet, the password will be blank,
    so you should just press enter here.
    Enter current password for root (enter for none): <----- (今は空欄のはず)
    OK, successfully used password, moving on...
    Setting the root password ensures that nobody can log into the MySQL
    root user without the proper authorisation.
    Set root password? [Y/n] Y
    New password: <-------- (MySQL root パスワードを入力)
    Re-enter new password: Password updated successfully!
    Reloading privilege tables..
    ... Success!
    By default, a MySQL installation has an anonymous user, allowing anyone
    to log into MySQL without having to have a user account created for
    them. This is intended only for testing, and to make the installation
    go a bit smoother. You should remove them before moving into a
    production environment.
    Remove anonymous users? [Y/n] Y
    ... Success!
    Normally, root should only be allowed to connect from 'localhost'. This
    ensures that someone cannot guess at the root password from the network.
    Disallow root login remotely? [Y/n] Y
    ... Success!
    By default, MySQL comes with a database named 'test' that anyone can
    access. This is also intended only for testing, and should be removed
    before moving into a production environment.
    Remove test database and access to it? [Y/n] Y
    ... skipping.
    Reloading the privilege tables will ensure that all changes made so far
    will take effect immediately.
    Reload privilege tables now? [Y/n] Y
    ... Success!
    Cleaning up...
    All done! If you've completed all of the above steps, your MySQL
    installation should now be secure.
    Thanks for using MySQL!
    

[SQLite][SQL]データの表示方法を変更する

Default 表示
sqlite> SELECT * FROM tbl1;
hello|10
goodbye|20
column モード
sqlite> .mode column
sqlite> SELECT * FROM tbl1;
hello       10
goodbye     20
Header 追加
sqlite> .header on
sqlite> SELECT * FROM tbl1;
one         two
----------  ----------
hello       10
goodbye     20

[SQLite][SQL]コマンドライン操作

sqlite3.exe の引数はデータベースファイル名
> sqlite3.exe ex0.sqlite
SQLite version 3.7.5
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
テーブルを作成してデータを追加、表示まで
sqlite> CREATE TABLE tbl1(one varchar(10), two smallint);
sqlite> INSERT INTO tbl1 VALUES ('hello', 10);
sqlite> INSERT INTO tbl1 VALUES ('goodbye', 20);
sqlite> SELECT * FROM tbl1;
hello|10
goodbye|20
データを絞って表示
sqlite> SELECT * FROM tbl1 WHERE two >= 15;
goodbye|20
終了
sqlite> .exit
DB ファイル内にあるテーブル一覧表示
sqlite> .tables
tbl1  tbl2
参照: Command Line Shell For SQLite

[SQLite][SQL]Date データの扱い

Date データを扱う時は date() 関数を通す。
sqlite> CREATE TABLE tokyoTemperature (id INTEGER NOT NULL PRIMARY KEY, date DATE NOT NULL, ave FLOAT NOT NULL);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-01'), 6.6);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-02'), 7.0);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-03'), 5.9);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-04'), 6.3);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-05'), 7.3);
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, date('2011-01-06'), 6.5);
sqlite> SELECT * from tokyoTemperature;
id          date        ave
----------  ----------  ----------
1           2011-01-01  6.6
2           2011-01-02  7.0
3           2011-01-03  5.9
4           2011-01-04  6.3
5           2011-01-05  7.3
6           2011-01-06  6.5
sqlite> SELECT * from tokyoTemperature WHERE date >= date('2011-01-05');
id          date        ave
----------  ----------  ----------
5           2011-01-05  7.3
6           2011-01-06  6.5
date() を通さずにデータを登録すると異なる値が入ってしまう。
sqlite> INSERT INTO tokyoTemperature VALUES (NULL, 2011-01-07, 4.0);
sqlite> SELECT * FROM tokyoTemperature WHERE id = 7;
id          date        ave
----------  ----------  ----------
7           2003        4.0
参考: SQLite Query Language: Date And Time Functions

[SQLite][SQL]AUTO INCREMENT

SQLite には AUTO_INCREMENT (AUTOINCREMENT) キーワードが準備されていない。
AUTO INCREMENT を使う場合は "INTEGER NOT NULL PRIMARY KEY" でフィールドを定義して、データ登録の時は NULL を指定する。

実行結果
> a.exe test.db "CREATE TABLE test_tbl(ID INTEGER PRIMARY KEY, NAME TEXT NOT NULL);"
> a.exe test.db "INSERT INTO test_tbl(ID, NAME) VALUES (NULL, '1st');"
> a.exe test.db "INSERT INTO test_tbl(ID, NAME) VALUES (NULL, '2nd');"
> a.exe test.db "INSERT INTO test_tbl(ID, NAME) VALUES (NULL, '3rd');"
> a.exe test.db "SELECT * from test_tbl;"
ID = 1
NAME = 1st

ID = 2
NAME = 2nd

ID = 3
NAME = 3rd

sqlite3.exe の場合
sqlite> CREATE TABLE tbl3 (id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL);
sqlite> INSERT INTO tbl3 VALUES (NULL, 'Tokyo');
sqlite> INSERT INTO tbl3 VALUES (NULL, 'Osaka');
sqlite> INSERT INTO tbl3 VALUES (NULL, 'Nagoya');
sqlite> SELECT * FROM tbl3;
1|Tokyo
2|Osaka
3|Nagoya

[SQLite][SQL]sqlite3_get_table

sqlite3_exec() に callback 関数を登録する以外にテーブルのデータ一覧を取得する方法として sqlite3_get_table() がある
char **azResult;
int row, column;
int i, j;

rc = sqlite3_get_table(db, argv[2], &azResult, &row, &column, &zErrMsg);
if (rc != SQLITE_OK) {
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
}
printf("row=%d column=%d\n", row, column);
for (i = 0; i <= row; i++) {
    for (j = 0; j < column; j++) {
        printf("[%d,%d] %s ", i, j, azResult[(i * column + j)]);
    }
    printf("\n");
    if (i == 0) {
        printf("-----------------------------\n");
    }
}
sqlite3_free_table(azResult);
実行結果
row=3 column=2
[0,0] ID [0,1] NAME
-----------------------------
[1,0] 1 [1,1] 1st
[2,0] 2 [2,1] 2nd
[3,0] 3 [3,1] 3rd

[SQLite][SQL]MinGW, MSYS 環境での sqlite のコンパイル・使用方法

  1. sqlite3 の関数を使用するプログラムを準備する。
    main.c
    #include 
    #include "sqlite3.h"
    
    static int callback(void *NotUsed, int argc, char **argv, char **azColName)
    {
        int i;
        for (i = 0; i < argc; i++) {
            printf("%s = %s\n", azColName[i], (argv[i] ? argv[i] : "NULL"));
        }
        printf("\n");
    
        return 0;
    }
    
    // メイン関数
    int main(int argc, char **argv)
    {
        sqlite3 *db;
        int rc;
        char *zErrMsg = 0;
    
        if (argc != 3) {
            fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
            return -1;
        }
    
        rc = sqlite3_open(argv[1], &db);
        if (rc) {
            fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));
            sqlite3_close(db);
            return -1;
        }
    
        rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
        if (rc != SQLITE_OK) {
            fprintf(stderr, "SQL error: %s\n", zErrMsg);
            sqlite3_free(zErrMsg);
        }
        sqlite3_close(db);
    
        return 0;
    }
    
  2. Makafile を準備する。
    Makefile
    CC=gcc
    CFLAGS = -Wall
    LDFLAGS = -lsqlite3
    TARGET = \
         main.exe
    
    .SUFFIXES: .exe .c .o
    
    .c.o:
         $(CC) $(CFLAGS) -c -o $@ $<
    
    .o.exe:
     $(CC) -o $@ $< $(LDFLAGS)
    
    default: $(TARGET)
    
    clean:
     rm -rf *.o *.exe
    
  3. コンパイルをする
  4. 実行して動作確認する。第 1 引数はデータベースファイル名、第 2 引数に SQL 文を渡す。
    > a.exe test.db "CREATE TABLE test_tbl(ID INT PRIMARY KEY, NAME TEXT NOT NULL);"
    > a.exe test.db "INSERT INTO test_tbl(ID, NAME) values (0, 'hoge');"
    > a.exe test.db "SELECT * from test_tbl;"
    ID = 0
    NAME = hoge
    
    > a.exe test.db "INSERT INTO test_tbl(ID, NAME) values (1, 'aaa');"
    > a.exe test.db "SELECT * from test_tbl;"
    ID = 0
    NAME = hoge
    
    ID = 1
    NAME = aaa
    

2013年1月26日土曜日

[SQLite][SQL]インストール

Windows 用コンパイル済みバイナリ
SQLite Download Page から Windows 用コンパイル済みバイナリ (sqlite-shell-win32-x86-3070500.zip, sqlite-dll-win32-x86-3070500.zip) をダウンロードする。

MinGW
  1. SQLite Home Page の DOWNLOAD ページにあるソースコード (sqlite-amalgamation-3_6_18.zip, 2009/10/13 現在) をダウンロードする。
  2. ダウンロードしたファイルを展開する。
  3. configure
    > sh ./configure --prefix=/c/usr/MinGW
    
  4. make
    > make
    
  5. ここで下記のような Warning が頻出するが、コンパイルは完了する。
    Temp/ccfFx7ME.s:184210: Warning: .stabn: description field '10d6b' too big, try a different debug format
    
  6. make install
  7. > make install
    

[SQL]データ集計

サンプルテーブル作成
sqlite> CREATE TABLE tbl2 (id INTEGER NOT NULL PRIMARY KEY, date DATE NOT NULL, name TEXT NOT NULL, math INTEGER, physics INTEGER, chemistry INTEGER);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-02-25'), 'Albert', 69, 42, 74);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-02-25'), 'Emily', 80, 93, 85); sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-02-25'), 'John', 35, 42, 38);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-07-20'), 'Albert', 72, 53, 68);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-07-20'), 'Emily', 75, 85, 87);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-07-20'), 'John', 46, 54, 46);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-12-15'), 'Albert', 63, 54, 65);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-12-15'), 'Emily', 85, 88, 92);
sqlite> INSERT INTO tbl2 VALUES (NULL, date('2010-12-15'), 'John', 43, 53, 41);
sqlite> SELECT * FROM tbl2;
id date name math physics chemistry
---------- ---------- ---------- ---------- ---------- ----------
1 2010-02-25 Albert 69 42 74
2 2010-02-25 Emily 80 93 85
3 2010-02-25 John 35 42 38
4 2010-07-20 Albert 72 53 68
5 2010-07-20 Emily 75 85 87
6 2010-07-20 John 46 54 46
7 2010-12-15 Albert 63 54 65
8 2010-12-15 Emily 85 88 92
9 2010-12-15 John 43 53 41
合計
各テストの合計点を出す
sqlite> SELECT *,math+physics+chemistry AS total FROM tbl2;
id date name math physics chemistry total
---------- ---------- ---------- ---------- ---------- ---------- ----------
1 2010-02-25 Albert 69 42 74 185
2 2010-02-25 Emily 80 93 85 258
3 2010-02-25 John 35 42 38 115
4 2010-07-20 Albert 72 53 68 193
5 2010-07-20 Emily 75 85 87 247
6 2010-07-20 John 46 54 46 146
7 2010-12-15 Albert 63 54 65 182
8 2010-12-15 Emily 85 88 92 265
9 2010-12-15 John 43 53 41 137
平均
math, physics を足して 2 で割った結果を出す
sqlite> SELECT *, (math+physics)/2.0 FROM tbl2;
id date name math physics chemistry (math+physics)/2.0
---------- ---------- ---------- ---------- ---------- ---------- ------------------
1 2010-02-25 Albert 69 42 74 55.5
2 2010-02-25 Emily 80 93 85 86.5
3 2010-02-25 John 35 42 38 38.5
4 2010-07-20 Albert 72 53 68 62.5
5 2010-07-20 Emily 75 85 87 80.0
6 2010-07-20 John 46 54 46 50.0
7 2010-12-15 Albert 63 54 65 58.5
8 2010-12-15 Emily 85 88 92 86.5
9 2010-12-15 John 43 53 41 48.0
GROUP BY
name が同じものを集めて math の平均値を出す
sqlite> SELECT name,AVG(math) FROM tbl2 GROUP BY name;
name AVG(math)
---------- ----------
Albert 68.0
Emily 80.0
John 41.3333333
ORDER BY
2010-12-15 のテスト結果のみ表示してみる
sqlite> SELECT date, name, math FROM tbl2 WHERE date = date('2010-12-15');
date name math
---------- ---------- ----------
2010-12-15 Albert 63
2010-12-15 Emily 85
2010-12-15 John 43
ORDER BY を使って 2010-12-15 のテストで math の点数順に並べる (昇順 (ASCending-order))
sqlite> SELECT date, name, math FROM tbl2 WHERE date = date('2010-12-15') ORDER BY math;
date name math
---------- ---------- ----------
2010-12-15 John 43
2010-12-15 Albert 63
2010-12-15 Emily 85

sqlite> SELECT date, name, math FROM tbl2 WHERE date = date('2010-12-15') ORDER BY math ASC;
date name math
---------- ---------- ----------
2010-12-15 John 43
2010-12-15 Albert 63
2010-12-15 Emily 85
降順に並べる (DESCending-order)
sqlite> SELECT date, name, math FROM tbl2 WHERE date = date('2010-12-15') ORDER BY math DESC;
date name math
---------- ---------- ----------
2010-12-15 Emily 85
2010-12-15 Albert 63
2010-12-15 John 43

[SQL]レコードを全削除

DELETE from テーブル名;
または
TRUNCATE [TABLE] テーブル名;

[SQL]テーブル名の変更

ALTER TABLE 変更前テーブル名 RENAME TO 変更後テーブル名;

[Highcharts]2 つの csv ファイルからデータを読み込んで 1 つのグラフに表示

highcharts1.html
<html>
  <head>
    <title>Highcharts test 1 (2 つの csv ファイルからデータを読み込んで表示)</title>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript" src="../js/highcharts.js"></script>
    <script type="text/javascript" src="../js/modules/exporting.js"></script>
    <script type="text/javascript" src="highcharts1.js"></script>
  </head>
  <body>
    <div id="container0" style="height: 400px; margin: 0;"></div>
  </body>
</html>
highcharts1.js
$(document).ready(function() {
    var options = {
        chart: {
            renderTo: 'container0',
            type: 'line',
            zoomType: 'xy',
        },
        title: {
            text: 'test chart 1',
        },
        xAxis: {
            categories: []
        },
        yAxis: {
        },
        series: []
    }

    $.get('highcharts1_data2011.csv', function(data) {
        // Split the lines
         var lines = data.split('\n');

        // Iterate over the lines and add categories or series
        $.each(lines, function(lineNo, line) {
            var items = line.split(',');

            // header line contains categories
            if (lineNo == 0) {
                $.each(items, function(itemNo, item) {
                    options.xAxis.categories.push(item);
                });
            }
            // the rest of the lines contain data with their name in the first position
            else {
                var series = {
                    name: '2011',
                    data: []
                };
                $.each(items, function(itemNo, item) {
                    series.data.push(parseFloat(item));
                });

                options.series.push(series);
            }
        });
    });

    $.get('highcharts1_data2012.csv', function(data) {
        // Split the lines
         var lines = data.split('\n');

        // Iterate over the lines and add categories or series
        $.each(lines, function(lineNo, line) {
            var items = line.split(',');

            // header line contains categories
            if (lineNo == 0) {
                $.each(items, function(itemNo, item) {
                    options.xAxis.categories.push(item);
                });
            }
            // the rest of the lines contain data with their name in the first position
            else {
                var series = {
                    name: '2012',
                    data: []
                };
                $.each(items, function(itemNo, item) {
                    series.data.push(parseFloat(item));
                });

                options.series.push(series);
            }
        });

        // Create the chart
        var chart = new Highcharts.Chart(options)
    });
});
highcharts1_data2011.csv
Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
5.1,7.0,8.1,14.5,18.5,22.8,27.3,27.5,25.1,19.5,14.9,7.5
highcharts1_data2012.csv
Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
4.8,5.4,8.8,14.5,19.6,21.4,26.4,29.1,26.2,19.4,12.7,7.3
出力結果
sample04 (fc2 に置いてあるテストページに飛びます)

[jQuery]Ajaxでサーバーのプログラム実行

test0.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
    <title>Ajax Test 0</title>
<script language="JavaScript">
<!--
// [実行]ボタンをクリック時の処理
function req(scriptName) {
  // 非同期通信を行うためのXMLHttpRequestオブジェクトを生成
  try {
    xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
  } catch(e) {
    xmlReq = new XMLHttpRequest();
  }

  // サーバーからの応答時の処理を定義(結果のページへの反映)
  xmlReq.onreadystatechange = function() {
    var msg = document.getElementById("result");
    if (xmlReq.readyState == 4) {
      if (xmlReq.status == 200) {
        msg.innerHTML = xmlReq.responseText;
      } else {
        msg.innerHTML = "通信に失敗しました。";
      }
    } else {
      msg.innerHTML = "通信中…";
    }
  }

  // サーバーとの通信を開始
  xmlReq.open("GET", scriptName, true);
  xmlReq.send(null);
}
//-->
</script>
  </head>
<body>
  <form name="test">
    <input type="button" value="実行" onclick='req("test0.pl")'/>
    <input type="button" value="失敗" onclick='req("dummy.pl")'/><br>
    <div id="result"/>
  </form>
</body>
</html>
test0.pl
#!/usr/bin/perl
# -*- coding: utf-8 -*-
use strict;
use utf8;

sleep(3); # 少し待たせる

my $times = time();
my ($sec, $min, $hour, $mday, $month, $year, $wday, $stime) = localtime($times);
$year = $year + 1900;
$month++;
my $currentTime = $year . "/" . $month . "/" . $mday . " " . $hour . ":" . $min . ":" . $sec;

print "Content-Type: text/xml\n\n";
print '' . $currentTime . '';

# print $currentTime . "\n";

DokuWiki

インストール
  1. dokuwiki からダウンロード
  2. ダウンロードしたファイル (dokuwiki-xxxx-xx-xx.tgz) を解凍する
  3. 解凍したファイルを Web サーバーの cgi が動作するディレクトリに置く
  4. dokuwiki/conf と dokuwiki/data に書き込み権限を与える
    $ chmod -R o+w conf/
    $ chmod -R o+w data/
    
  5. dokuwiki/install.php にアクセスする
  6. Superuser の情報を入力してインストールを完了する
  7. dokuwiki/doku.php にアクセスする
言語変更
  • Sueperuser でログインし Admin メニューの Configuration Settings → Interface language で変更する
新規ページ作成
  1. 検索窓で作成するページのタイトルを入力
  2. 検索結果なしと表示されたら右の Create this page アイコンをクリックして内容を記載する
ページの削除
  • ページの内容を全て削除する
アンダースコア 2 つの表示方法
  • __test__ という表記は test の下線表示になってしまう
  • __ を表示したい時は %%__%% と記述する
BBCode Plugin (文字装飾)
  1. BBCode Plugin からダウンロードする
  2. ダウンロードしたファイル (plugin-bbcode.tgz) を解凍する
  3. dokuwiki/lib/ の下に bbcode ディレクトリを作成し、解凍したファイルの中身をコピーする
  4. Admin メニューの Manage Plugins を開くと bbcode がインストールされている
  5. 赤字を表示する時は以下のように記述する
    [color=red]赤字[/color]
    
テンプレート
ページのデザインはテンプレートにより定義される
  1. Templates にある Search Templates から好みのテンプレートを探す
  2. ダウンロードしたファイルを解凍し、dokuwiki/lib/tpl にコピーする
  3. Admin メニュー → Configuration Settings にある template でデザインを変更する
サイドバー
  1. sidebar というページを作成すると各ページの左側にバーが表示される
  2. サイドバーに全ページリストと更新履歴を表示する
    1. indexmenu plugin をダウンロード、インストール
    2. Changes plugin をダウンロード、インストール
    3. sidebar ページに以下を記載
      ==== Pages ====
      {{indexmenu> | tsort}}
      
      ==== Change log ====
      {{changes>}}
      

[Perl]csvファイルの行列を入れ替え

# -*- coding: utf-8 -*-
use strict;
use utf8;

# csv ファイルの行列を入れ替える
my $inputFileName = 'input.csv';
my $outputFileName = 'output.csv';

open(IN, $inputFileName);
open(OUT, '> ' . $outputFileName);

my %b;
my $i = 0;
while () {
    chomp;
    my @r = split(/,/, $_);
    $i = 0;
    foreach $a (@r) {
        $b{$i} .= ($a . ",");
        $i++;
    }
}
for (my $j = 0; $j < $i; $j++) {
    # 末尾の , は削除する
    $b{$j} = substr($b{$j}, 0, -1);
    print(OUT $b{$j} . "\n");
}
close(IN);
close(OUT);
input.csv
2013-1-1,6.5
2013-1-2,10.0
2013-1-3,5.6
2013-1-4,3.2
2012-1-5,2.8
実行結果
output.csv
2013-1-1,2013-1-2,2013-1-3,2013-1-4,2012-1-5
6.5,10.0,5.6,3.2,2.8

[PHP]SQL で COUNT() を使って取得した件数を表示する

<?php
 /*
  * 条件に該当するレコードの件数を取得する
  */
function getRecordCount($connId, $query)
{
    $result = mysql_query($query, $connId);
    if ($result == false) {
        print "Error: " . $query . "<br>(" . mysql_error() . ")";
        exit;
    }

    list($num) = mysql_fetch_row($result);
    switch ($num) {
    case "":
        print "Not found<br>\n";
        $cnt = 0;
        break;
    default:
        $cnt = $num;
        break;
    }

    /* メモリの開放 */
    mysql_free_result($result);

    return $cnt;
}
?>

<?php
    $cnt = getRecordCount($connection_id, $query);
    print "結果: " . $cnt . "件<br>\n";
?>

hMailServer

インストール手順
  1. http://www.hmailserver.com/ からダウンロードする
  2. ダウンロードした hMailServer-5.3.3-B1879.exe (2012/12/21 現在) を実行する
    • Use built-in database engine (Microsoft SQL Compact) を選択
  3. Welcome 画面の [Add domain] でドメイン追加 (local.local)
  4. Domains - local.local にある Accounts でアカウント追加
  5. Settings - Logging で Enabled を ON にする, 各プロトコルも ON にする
クライアント設定
  • Account: test@local.local
  • Account を test として使っても認証エラーになる。 @local.local を忘れないように
Windows Firewall (Windows 7) 設定
  1. コントロールパネル - Windows ファイアウォール - 詳細設定で「セキュリティが強化された Windows ファイアウォール」ダイアログを開く
  2. 「受信の規則」で「新しい規則」を選択
  3. TCP ポート 25, 110 を許可する
LAN 内のクライアントから SMTP Auth なしで接続する
  1. Settings - Advanced- IP Ranges に Internet で "Require SMTP authentication" の "Local to local e-mail addresses" がチェックされている。
  2. 接続を許可する IP address の範囲を指定する
  3. 指定した IP address range の "Require SMTP authentication" の "Local to local e-mail addresses" のチェックを外す
  4. Priority を Internet より高くする (数字を大きくする), これが Internet と以下になっていると Internet 設定の SMTP auth 必要が優先されてしまう
注意
  • パスワード認証でNGになると Settings - Advanced - IP Ranges で ban list に追加される

2013年1月19日土曜日

[Highcharts]棒グラフと線グラフ同時に表示

sample03.js
$(document).ready(function() {
    var options = {
        chart: {
            renderTo: 'container0',
            zoomType: 'xy',
        },
        title: {
            text: 'test chart 0',
        },
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
        },
        yAxis: {
        },
        series: [
            {
                type: 'column',
                name: 'sample0',
                data: [3, 5, 8, 2, 6, 9],
            },
            {
                type: 'line',
                name: 'total',
                data: [3, 8, 16, 18, 24, 33],
            }
        ]
    }

    // Create the chart
    var chart = new Highcharts.Chart(options)
});
sample03.html
<html>
  <head>
    <title>Highcharts test</title>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript" src="js/modules/exporting.js"></script>
    <script type="text/javascript" src="js/sample03.js">>/script>
  </head>
  <body>
    <div id="container0" style="height: 1200px; margin: 0;"></div>
  </body>
</html>
出力結果
sample03 (fc2 に置いてあるテストページに飛びます)

[Emacs]メイリオ改フォント

Emacs で IPA フォントを使用していたが、~(チルダ), ^(アクサンシルコンフレックス), `(ア クサングラーブ) が正しく表示できないのでメイリオフォントに変更した。
メイリオフォントでは英数日本語の幅が合わないのでメイリオ改 (meiryoKe) を使用することにした。meiryoKe についてはこちらのサイトを参照

メイリオ改フォント作成
meiryoKe ジェネレータを使用してメイリオフォントからメイリオ改を生成する
  1. 作業フォルダにメイリオフォント (meiryo.ttc, meiryob.ttc) をコピー
  2. meiryoKe_gen_6.02rev1.exe を実行
  3. meiryoKe_602r1.ttc, meiryoKeB_602r1.ttc が生成される

.emacsにメイリオ改用のフォント設定をする
;;;;; メイリオ改
(if use-meiryoKe
  (progn
  ; メイリオ改フォント用設定追加
    (ntemacs-font-create-fontset
      "meiryoKe_Gothic" "MeiryoKe_Gothic" "Lucida Console*" "メイリオ改*" "GB2312" ntemacs-font-defined-sizes)      ; メイリオ改 (meiryoKe10) をデフォルトフォントに設定
      (add-to-list 'default-frame-alist
    '(font . "fontset-meiryoKe_Gothic12"))
  )
  (progn
    (message "No operation for MeiryoKe")
  )
)

Windows XPでの対応
Windows XP の場合、ClearType のメイリオフォントを入れてもフォント表示が汚くなる。
[画面のプロパティ] - [デザイン] - [効果] にある「次の方法でスクリーン フォントの縁を滑らかにする」を「ClearType」にすることでフォント表示が綺麗になる。












変更前



















変更後



















注意
Windows XP のクラッシックモード + ClearType 設定にすると Chrome でチェックボックス・ラジオボタンが表示されないことが発生する。Windows XP の標準スタイルに戻すことで回避はできている。

[Emacs]フォント設定を確認する

.emacs に以下を追加して Shift + 左クリックで Windows のフォント設定ダイアログが表示できるようにする。
(setq w32-use-w32-font-dialog 1) 
好みのフォントを選択し、M-x describe-font を実行することで -outline-....-iso8859-1 が表示される。 各表示によるフォントの確認は M-x list-faces-display でできる

[Emacs]IPA モナーフォントを追加

.emacs に以下を追加する
;; IPA モナーフォント用設定追加
(defvar ntemacs-font-defined-sizes '(7 8 9 10 12 14 16 18 20 24))
(defun ntemacs-font-create-fontset
 (fontset ascii-font latin1-font japanese-font size-list)
 (let (size)
 (while size-list
 (setq size (car size-list))
 (setq size-list (cdr size-list))
 (create-fontset-from-ascii-font
 (format "-outline-%s-normal-r-normal-normal-%d-*-*-*-*-*-iso8859-1"
        ascii-font size)
 nil
 (format "%s%02d" fontset size))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'latin-iso8859-1
 (cons latin1-font "iso8859*"))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'japanese-jisx0208
 (cons japanese-font "jisx0208-sjis"))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'katakana-jisx0201
 (cons japanese-font "jisx0201-katakana"))
        )))

(ntemacs-font-create-fontset
 "IPAmona" "IPA モナー ゴシック" "Lucida Console*" "IPA モナー ゴシック*" ntemacs-font-defined-sizes)
;; ここまで IPA モナー

;; IPAモナー (ipamona12)
(add-to-list 'default-frame-alist
 '(font . "fontset-ipamona12")) 

[Emacs]各言語のフォント表示確認

日本語 (JISX0208, JIS 基本漢字)
M-x list-charset-chars
Character set: japanese-jisx0208
韓国語 (KSC5601)
M-x list-charset-chars
Character set: korean-ksc5601 
中国語 (BIG5, 繁体字)
M-x list-charset-chars
Character set: chinese-big5-1 
中国語 (GB2312, 繁体字)
M-x list-charset-chars
Character set: chinese-gb2312 

[Emacs]n + ~ を表示する

Emacs ではさざなみフォントを使う設定にしているのだが、これでは Espan~ol などで使用される n + ~ (n~) が表示できない
M-x view-hello-file を表示するとこのようになっている。
















OpenOffice でいろいろなフォントで表示してみるとさざなみフォントでは n + ~ が表示できないことが判明した。










そこでフォントの設定を ASCII 文字は DejaVu Sans Mono にし、日本語はさざなみで表示されるように設定した。
(defvar ntemacs-font-defined-sizes '(7 8 9 10 12 13 14 16 18 20 24))

(defun ntemacs-font-create-fontset
 (fontset ascii-font latin1-font japanese-font size-list)
 (let (size)
 (while size-list
 (setq size (car size-list))
 (setq size-list (cdr size-list))
 (create-fontset-from-ascii-font
 (format "-outline-%s-normal-r-normal-normal-%d-*-*-*-*-*-iso8859-1"
 ascii-font size)
 nil
 (format "%s%02d" fontset size))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'latin-iso8859-1
 (cons latin1-font "iso8859*"))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'japanese-jisx0208
 (cons japanese-font "jisx0208-sjis"))
 (set-fontset-font (format "fontset-%s%02d" fontset size)
 'katakana-jisx0201
 (cons japanese-font "jisx0201-katakana"))
)))

; DejaVu Sans Mono フォント用追加設定
(ntemacs-font-create-fontset
 "DejaVu" "DejaVu Sans Mono" "DejaVu Sans Mono" "さざなみゴシック" ntemacs-font-defined-sizes)

; DejaVu Sans Mono + さざなみ (DejaVu13) をデフォルトフォントに設定
(add-to-list 'default-frame-alist
 '(font . "fontset-dejavu13"))


;;; ===== 行間の調整 =====
; 整数で指定するとピクセル数で、少数で指定すると行の高さに対しての相対値で設定
; 例えば 1.0 を設定すると 1 文字分行間が空く
(setq-default line-spacing -1)

;;; ===== フレーム位置設定 =====
; 好みのフレームサイズ縦横を決めた後に *scrach* buffer で
; eval(frame-height), eval(frame-width) を実行して幅、高さの値を調べる
(setq initial-frame-alist
 (append
 '((top . 0) ; フレームの Y 位置 (ピクセル数)
 (left . 0) ; フレームの X 位置 (ピクセル数)
 (width . 80) ; フレーム幅 (文字数)
 (height . 74) ; フレーム高 (文字数)
 ) initial-frame-alist))
この設定で表示した結果が

[Emacs]スペイン語入力

  1. C-x RET k または M-x set-keyboard-coding-system で utf-8-dos を指定する。 これを指定しておかないと特殊文字を入力した場合に Invalid code とでて文字入力ができない
  2. C-x RET l または M-x set-language-environment で言語環境 Spanish に設定する
  3. C-x RET C-\ で入力メソッドを spanish-postfix に設定する
  4. 特殊文字は日本語フォントでは表示されないのでフォントを "Ariel Unicode MS" に設定する
  5. M-x quail-help で特殊文字の入力方法が表示される

下図の入力をするには





E s p a n~ o l
?/ Q u e' ?
とキーボードを叩く。
Emacs で複数言語が表示できるかを確認するには C-h h で多言語 hello 表示をする

[Emacs]フォントセット確認

使用中のフォントセットを表示する
*scratch* buffer にて
(frame-parameter nil 'font) [Ctrl + j]
"-outline-さざなみゴシック-normal-normal-normal-*-12-*-*-*-c-*-iso8859-1"

フォントセット詳細表示
M-x describe-fontset 

フォントセット一覧表示
M-x list-fontsets 

default-frame-alist で設定している値を表示
M-x describe-variable
Describe variable: default-frame-alist 

フォント切り替え
M-x set-frame-font
Font name: fontset-sazanami12

[Emacs][Elisp]Hook

hook で定義されたアクションが実行される時に紐付けされた hook funcsion が実行される。例えば suspend-hook は Emacs が suspend される直前に実行される hook となる。
add-hook
add-hook 関数を使うことで定義済み hook 変数に関数を追加できる
(add-hook 'text-mode-hook 'turn-on-auto-fill)
text-mode の場合は disable truncate にする
(add-hook 'text-mode-hook
 (lambda() (setq truncate-lines nil)))

[Emacs][Elisp]HTTP 通信

scratch バッファで Elisp による HTTP 通信をしてみた
各命令の最後で Ctrl + j により実行
; TCP コネクション (localhost:80) をはる
; open-network-stream は返値に process 名を返してくるので、それを proc に格納する
(setq proc (open-network-stream "http-proc" "*test-http-buffer*" "localhost" 80))
#
; proc の状態を確認
(process-status proc)
open
; proc に対して送る coding を指定する
(set-process-coding-system proc 'binary 'binary)
nil
; proc に文字列を送る
(process-send-string
proc
(format(concat
"GET / HTTP/1.0\r\n"
"\r\n")))
nil
指定した *test-http-buffer* に結果が表示される
Process http-proc connection broken by remote peer
HTTP/1.1 200 OK
Date: Thu, 06 Aug 2009 13:59:44 GMT
Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8i mod_autoindex_color mod_python/3.3.1 Python/2.5.2 PHP/5.2.6
Last-Modified: Fri, 06 Mar 2009 23:42:57 GMT
ETag: "6000000000669-1bc-4647bd829e8db"
Accept-Ranges: bytes
Content-Length: 444
Connection: close
Content-Type: text/html
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8">
<title>Test page</title>
</head>
<body>
Hello, world
</body>
</html>
Process http-proc connection broken by remote peer

open-network-stream
open-network-stream NAME BUFFER-OR-NAME HOST SERVICE
TCP 接続を確立する
Table: open-network-stream の引数
引数内容
NAMEprocess 名を指定する
BUFFER-OR-NAMEこの TCP コネクションに割り付けられるバッファ名
HOST接続先ホスト
SERVICEネットワークサービス名 または ポート番号
process-status
process-status PROCESS-NAME
PROCESS-NAME で指定したプロセスの状態を返す
Table: process-status の引数
引数内容
PROCESS-NAMEプロセス名
Table: process-status の返値
返値意味
runプロセスは running 状態
stopプロセスは停止している、再開可能
exitプロセスは終了している
signalプロセスは fatal signal を受けた
openネットワークコネクションが open している
closedネットワークコネクションは close した
connectnon-blocking コネクション、完了待ち
failednon-blocking コネクション、失敗
listenネットワークサーバが listen 中
nil指定したプロセス名のプロセスは存在しない
set-process-coding-system
set-process-coding-system PROCESS &optional DECODING-SYSTEM ENCODING-SYSTEM
PROCESS で指定したプロセスとの output/input 用コーディングを指定する
Table: set-process-coding-system の引数
引数内容
PROCESSプロセス名
DECODING-SYSTEMプロセスからの output コーディング
ENCODING-SYSTEMプロセスへの input コーディング
process-send-string
process-send-string PROCESS STRING
プロセスに対して文字列を送る
Table: process-send-string の引数
引数内容
PROCESSプロセス名
STRING文字列

[Emacs][Elisp]入力された文字列の長さを表示する

length 関数を使用して入力された文字列を表示する関数
(defun string-length (str)
  (interactive "sInput a string:")
  (setq len (length str))
  (message "String: %s (%d)" str len))
M-x string-length を実行すると mini-buffer に文字列の入力を求めるメッセージが表示される。文字列を入力すると入力した文字列とその文字数を表示する
String: hello (5)

[Emacs][Elisp]interactive 関数

コマンド実行時に質問してきてくれる interactive な関数の定義
(interactive "sWhat is your name: ")
これを実行すると mini-buffer に What is your name: と表示される。そこで文字列を入力すると結果が表示される
(interactive "sWhat your name: ")
("hoge")
数字を入力させる場合は下記のように n を先頭につける
(interactive "nInput your favorite number: ")
(5)
関数を定義して M-x 関数名 で実行すると mini-buffer に interactive で値を入力して渡すことができる
(defun add (a b)
  (interactive "nFirst argument:\nnSecond argument:")
  (setq ans (+ a b))
  (message "Ans: %d" ans))

add
M-x add を実行すると First argument:, Second argument: と mini-buffer に表示され、数値を入力する。計算結果は mini-buffer に出力される

[Emacs][Elisp]関数定義

defun を使って関数を定義する
(defun hello (a b)
  (setq ans (+ a b))
  (message "Ans: %d" ans))

hello
(hello 1 3)
"Ans: 4"
フォーマット
defun NAME ARGUMENT-LIST BODY-FORMS
Table: defun の引数
引数意味
NAME関数名
ARGUMENT-LIST引数リスト
BODY-FORMS関数の中身

HTTP Post する elisp を関数で定義すると下記のようになる
(defun http-post (server)
  (setq proc (open-network-stream "http-proc" "*http-buffer*" server 80))
  (set-process-coding-system proc 'binary 'binary)
  (process-send-string
    proc
    (format (concat
      "POST /test.php HTTP/1.0\r\n"
      "Content-Type: application/x-www-form-urlencoded\r\n"
      "Content-Length: 23\r\n"
      "\r\n"
      "fname=hello&lname=world"))))

http-post
(http-post "localhost")
nil

[Emacs][Elisp]文字列出力

message
message 関数を使用して *Message* バッファに出力する
(message "Hello, world")
*Message* バッファには次のように出力される
Hello, world

princ
文字列出力
*scratch* バッファでテスト
(princ "hello, world")
hello, world"hello, world"

2013年1月18日金曜日

[Emacs][Elisp]HTTP Post の elisp を interactive 対応

POST 先のサーバ、渡すパラメータ (First name, Last name) を入力することができるようになる
(defun http-post (server fname lname)
  (interactive "sServer:\nsFirst name:\nsLast name:")
  (setq proc (open-network-stream "http-proc" "*http-buffer*" server 80))
  (set-process-coding-system proc 'binary 'binary)
  (setq content-len
    (+ (+ (+ (length "fname=") (length fname)) (length "&lname=")) (length lname)))
  (process-send-string
    proc
    (format (concat
    "POST /test.php HTTP/1.0\r\n"
    "Content-Type: application/x-www-form-urlencoded\r\n"
    "Content-Length: "
    (number-to-string content-len)
    "\r\n"
    "\r\n"
    "fname="
    fname
    "&lname="
    lname))))

2013年1月17日木曜日

[Emacs][Elisp]region 指定

(defun dosomething-region (pmin pmax)
  (interactive "r")
  (message "pmin:%d pmax:%d" pmin pmax)
)
region を選択して M-x dosomething-region を実行すると *Messages* バッファに以下のように表示される
pmin:405 pmax:423
interactive に "r" を渡すと選択した region の開始位置、終了位置が引数に格納される。

2013年1月16日水曜日

[Emacs][Elisp]プロセス

プロセス実行
start-process

プロセスの状態を監視
フォーマット
set-process-sentinel process sentinel
process が Finished, exited abnormally など特定のイベント状態になった場合に sentinel で渡した命令を実行する
(defun ls-test ()
  (interactive)
  (defun msg-me (process event)
  (princ
    (format "Process: %s had the event [%s]" process event)))
    (set-process-sentinel
    (start-process "ls" "*ls*" "ls" "-a")
    'msg-me)
  )

(defun ls-test2 ()
  (interactive)
  (set-process-sentinel
    (start-process "ls" "*ls*" "ls" "-a")
    (lambda (process event)
    (princ
      (format "Process: %s had the event [%s]" process event)))
    )
  )

*ls*
.
..
COPYING
addpm.exe
cmdproxy.exe
ctags.exe
ddeclient.exe
digest-doc.exe
ebrowse.exe
emacs.exe
emacsclient.exe
emacsclientw.exe
etags.exe
hexl.exe
movemail.exe
runemacs.exe
sorted-doc.exe
*Messages*
Process: ls<1> had the event [finished
]

[Emacs][Elisp]バイトコンパイル

M-x byte-compile-file で el ファイルを指定すると elc ファイルを生成してくれる

[Emacs][Elisp]基礎

演算
演算, 評価, evaluation と表現する時もある
(operand arg1 arg2)
例)
(+ 1 2) は 1 + 2 を表す

代入
(variable value)
例)
(auto-fill-mode 1) は auto-fill-mode という変数に 1 を代入する
Auto fill mode: 最大幅までで文字が到達したら自動的に改行を入れる

Labmda
フォーマット
(lambda (arg-variables...)
 [documentation-string]
 [interactive-declaration]
 body-forms ...)
  • 先頭は lambda シンボルを使用する
  • labmda により以下のリストが関数であることを表している。これにより他のリストとはっきり区別をつけている。
  • documentation-string は function 定義を記述する
  • interactive-declaration は interactive code-string を記述する。すなわち M-x で使用する時のコマンド名になる
  • body-form には Lisp コードを記載する
例)
((lambda (a b c) (+ a b c))
 1 2 3)
6
(a b c) という新しい関数を登録する。内容は (+ a b c) となる。その (a b c) という関数に (1 2 3) という引数を渡した結果は 1 + 2 + 3 となるので結果は 6 となる。

2013年1月14日月曜日

[Highcharts]csvファイルからデータを取り込んで表示するグラフ

ソースコード
<!DOCTYPE HTML>
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>Highcharts example 02</title>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
 <script type="text/javascript" src="js/highcharts.js"></script>
 <script type="text/javascript" src="js/modules/exporting.js"></script>
 <script type="text/javascript">
 $(document).ready(function() {
 var options = {
   chart: {
     renderTo: 'container',
     defaultSeriesType: 'line',
   },
   title: {
     text: '月平均気温'
   },
   xAxis: {
     categories: []
   },
   yAxis: {
     title: {
       text: '気温 (℃)'
     },
     plotLines: [
       {
         value: 0,
         width: 2,
         color: 'red'
       }
     ]
   },
   series: []
 }

 $.get('sample02.csv', function(data) {
   // Split the lines
   var lines = data.split('\n');

   // Iterate over the lines and add categories or series
   $.each(lines, function(lineNo, line) {
   var items = line.split(',');

   // header line contains categories
   if (lineNo == 0) {
     $.each(items, function(itemNo, item) {
     if (itemNo > 0) options.xAxis.categories.push(item);
   });
 }
 // the rest of the lines contain data with their name in the first position
 else {
   var series = {
   data: []
 };
 $.each(items, function(itemNo, item) {
   if (itemNo == 0) {
     series.name = item;
   }
   else {
     series.data.push(parseFloat(item));
   }
 });
 
 options.series.push(series);
 }
 });
 
 // Create the chart
 var chart = new Highcharts.Chart(options);
 });
 });
 </script>
 </head>
 <body>
 <div id="container" style="width: 600px; height: 400px; margin: 0 auto"></div>
 </body>
</html>
データファイル
Categories,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
Tokyo,5.1,7.0,8.1,14.5,18.5,22.8,27.3,27.5,25.1,19.5,14.9,7.5
Osaka,4.4,7.4,8.1,13.8,19.6,24.2,27.8,28.9,25.2,19.5,15.2,8.1
Sapporo,-3.8,-1.1,0.7,6.9,11.1,17.3,21.8,26.6,19.2,12.1,6,-2
Naha,14.9,17.6,17.1,20.4,23.9,27.9,28.9,28.3,27.9,25.2,23.7,18.6
出力結果
sample02 (fc2 に置いてあるテストページに飛びます)

[Highcharts]範囲を指定すると拡大するグラフ

chartでzoomTypeを指定する。
ソースコード
<!DOCTYPE HTML>
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>Highcharts example 01</title>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
 <script type="text/javascript">
 var chart;
 $(document).ready(function() {
 chart = new Highcharts.Chart({
 chart: {
   renderTo: 'container',
   zoomType: 'x',
 },
 title: {
   text: '月平均気温',
 },
 xAxis: {
   categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
 },
 yAxis: {
   title: {
     text: '気温 (℃)'
   },
   plotLines: [
     {
       value: 0,
       width: 2,
       color: 'red'
     }
   ]
 },
 series: [
   {
     name: 'Tokyo',
     data: [5.1,7.0,8.1,14.5,18.5,22.8,27.3,27.5,25.1,19.5,14.9,7.5],
   },
   {
     name: 'Osaka',
     data: [4.4,7.4,8.1,13.8,19.6,24.2,27.8,28.9,25.2,19.5,15.2,8.1]
   },
   {
     name: 'Sapporo',
     data: [-3.8,-1.1,0.7,6.9,11.1,17.3,21.8,26.6,19.2,12.1,6,-2]
   },
   {
     name: 'Naha',
     data: [14.9,17.6,17.1,20.4,23.9,27.9,28.9,28.3,27.9,25.2,23.7,18.6],
   }
 ]
 });
 });
 </script>
 </head>
 <body>
 <script type="text/javascript" src="js/highcharts.js"></script>
 <script type="text/javascript" src="js/modules/exporting.js"></script>
 <div id="container" style="width: 600px; height: 400px; margin: 0 auto"></div>
 </body>
</html>
出力結果
sample01 (fc2 に置いてあるテストページに飛びます)

[Highcharts]基本の折れ線グラフ

ソースコード
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Highcharts example 00</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript">
      var chart;
      $(document).ready(function() {
        chart = new Highcharts.Chart({
          chart: {
       renderTo: 'container',
           defaultSeriesType: 'line',
          },
          title: {
           text: '月平均気温',
          },
          xAxis: {
           categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
        'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
          },
          yAxis: {
         title: {
             text: '気温 (℃)'
            },
         plotLines: [
            {
             value: 0,
               width: 2,
               color: 'red'
             }
            ]
         },
          series: [
            {
               name: 'Tokyo',
               data: [5.1,7.0,8.1,14.5,18.5,22.8,27.3,27.5,25.1,19.5,14.9,7.5],
            },
            {
               name: 'Osaka',
               data: [4.4,7.4,8.1,13.8,19.6,24.2,27.8,28.9,25.2,19.5,15.2,8.1]
            },
            {
               name: 'Sapporo',
               data: [-3.8,-1.1,0.7,6.9,11.1,17.3,21.8,26.6,19.2,12.1,6,-2]
            },
            {
               name: 'Naha',
               data: [14.9,17.6,17.1,20.4,23.9,27.9,28.9,28.3,27.9,25.2,23.7,18.6],
            }
          ]
        });
      });
    </script>
  </head>
  <body>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript" src="js/modules/exporting.js"></script>
    <div id="container" style="width: 600px; height: 400px; margin: 0 auto"></div>
  </body>
</html>
出力結果
sample00 (fc2 に置いてあるテストページに飛びます)

[Highcharts]インストール

Highcharts から ダウンロードする。

2013年1月11日金曜日

[JpGraph]CakePHP + JpGraph

データベースに以下のテーブルを追加する
Table: テーブル例
iduser_idmathenglishphysics
11493656
22454842
33728091
Model の user.php を修正
<?php

class User extends AppModel
{
 var $name = 'User';
 // var $hasOne = 'Profile';
 var $hasOne = 'Exam';
 var $hasMany = 'Diary';
}

?>
Model に exam.php を追加
<?php

class Exam extends AppModel
{
 var $name = 'Exam';
 var $belongsTo = 'User';
}

?>
Controller にある users_controller.php に以下を追加
function exam($param = null) {
 if (!$param) {
  /* デフォルトは math を表示 */
  $param = 'math';
  $this->set('graph_path', 'exam_graph/' . $param);
 }
 else {
  $this->set('graph_path', '../exam_graph/' . $param);
 }
 $this->set('param', $param);
}

function exam_graph($param = null) {
 /* JpGraph を使用する */
 App::import('Vendor', 'jpgraph/jpgraph');
 App::import('Vendor', 'jpgraph/jpgraph_bar');

 /* DB から値を取得 */
 $users = $this->User->find('all');

 $ydata = array();
 $a = array();

 /* 値を取り込む */
 foreach ($users as $user) {
  array_push($ydata, $user['Exam'][$param]);
  array_push($a, $user['User']['username']);
 }

 /* グラフ作成 */
 $graph = new Graph(350, 250, "auto");
 $graph->SetScale("textlin");

 /* X軸項目追加 */
 $graph->xaxis->SetTickLabels($a);

 /* plot作成 */
 $bplot = new BarPlot($ydata);

 /* グラフ上に描画 */
 $graph->Add($bplot);

 /* グラフ表示 */
 $graph->Stroke();
}
exam.ctp を作成
<html> <head>
<title></title>
</head>

<body>
<h1><?php echo $param; ?></h1>
<?php echo '<img src="' . $graph_path . '" />'; ?>

<hr>
</body> </html>
結果
  • cake/users/exam にアクセスすると数学の結果が表示される
  • cake/users/exam/math にアクセスすると数学の結果が表示される
  • cake/users/exam/english にアクセスすると英語の結果が表示される
  • cake/users/exam/physics にアクセスすると物理の結果が表示される

[CakePHP]インストール

  1. http://cakephp.org/からダウンロードしてhtdocs以下に展開
  2. http://localhost/php/cake/にアクセスするとCakePHPのインストール完了が確認できる
  3. app/config/にあるdatabase.php.defaultをコピーしてdatabase.phpにする
  4. app/config/database.phpにDatabaseへアクセスするための設定を書き込む
        var $default = array(
          'driver' => 'mysql',
          'persistent' => false,
          'host' => 'localhost',
          'login' => 'データベースにアクセスするユーザ名',
          'password' => 'パスワード',
          'database' => 'データベース名',
          'prefix' => '',
        );
    
  5. cake/でDatabaseにアクセスできることを確認。アクセスできると以下のメッセージが表示される。
    Your database configuration file is present.
    Cake is able to connect to the database.
    
  6. mod_rewriteの設定
    httpd.confにあるディレクトリ設定セクションが以下のようになっていることを確認する。
    AllowOverride All
    
  7. httpd.confで以下のようになっていることを確認する。
    LoadModule rewrite_module modules/mod_rewrite.so
    

[JpGraph]グラフに値を表示する

plot 作成時に value->Show() を呼び出すことで値が表示されるようになる
/* plot作成 */
$bplot = new BarPlot($ydata);
$bplot->value->Show();
value->SetFormat() で数値のフォーマットを指定できる。フォーマットの指定方法は printf での指定方法と同様。
$bplot->value->Show();
$bplot->value->SetFormat('%d');

[JpGraph]棒グラフで表示する最大値・最小値を指定する

function Graph::SetScale($aAxisType, $aYMin, $aYMax, $aXMin, $aXMax)
Table: SetScale 引数
引数Default値説明
$aAxitType軸の種類
$aYMin1Y 軸最小値
$aYMax1Y 軸最大値
$aXMin1X 軸最小値
$aXMax1X 軸最大値
Y 軸を 0 〜 100 の範囲でグラフを表示する場合は
$graph->SetScale("textlin", 0, 100);

[JpGraph]2 つの Y 軸で棒グラフを表示

左右の Y 軸で別々の尺度を持たせる場合には Graph::SetY2Scale を使用する。折れ線グラフの場合はそのままでもグラフを見ることができるのだが、棒グラフの場合は同じ場所に棒グラフが表示されてしまうためにグラフが重なり見えなくなってしまう。
/* グラフ作成 */
$graph = new Graph(350, 250, "auto");
$graph->SetScale("textlin", 0, 100);
$graph->SetY2Scale("lin", 0, 300);

/* X軸項目追加 */
$graph->xaxis->SetTickLabels($a);

/* plot作成 */
$bplot1 = new BarPlot($y1data);
$bplot1->value->Show();
$bplot1->value->SetFormat('%d');

$bplot2 = new BarPlot($y2data);
$bplot2->value->Show();
$bplot2->value->SetFormat('%d');

/* グラフ上に描画 */
$graph->Add($bplot1);
$graph->AddY2($bplot2);

/* グラフ表示 */
$graph->Stroke();














そこで 2 つのグラフを値 0 の dummy グラフとグループ化しておき、その GroupBarPlot を表示することで 2 つの棒グラフが並んで表示されるようにすることができる。
/* グラフ作成 */
$graph = new Graph(350, 250, "auto");
$graph->SetScale("textlin", 0, 100);
$graph->SetY2Scale("lin", 0, 300);
/* 右側の Y 軸で値が全部表示できないのでグラフを表示する場所の
 * margin を指定する
 */
$graph->img->SetMargin(50, 70, 30, 40);

/* X軸項目追加 */
$graph->xaxis->SetTickLabels($a);

/* plot作成 */
$bplot1 = new BarPlot($y1data);
$bplot1->value->Show();
$bplot1->value->SetFormat('%d');

$bplot2 = new BarPlot($y2data);
$bplot2->value->Show();
$bplot2->value->SetFormat('%d');

/* 単純に bplot1, bplot2 を表示するとグラフが重なってしまうので
 * $zerodata のダミーを間に挟んでグループ化して
 * bplot1, bplot2 が並んでいるように表示する
 */
$bplotzero = new BarPlot($zerodata);
$bgplot1 = new GroupBarPlot(array($bplot1, $bplotzero));
$bgplot2 = new GroupBarPlot(array($bplotzero, $bplot2));

/* グラフ上に描画 */
$graph->Add($bgplot1);
$graph->AddY2($bgplot2);

/* グラフ表示 */
$graph->Stroke();

[JpGraph]グラフの表示位置を調整

グラフのプロット領域のマージン (margin) を指定する
function Image::SetMargin($lm, $rm, $tm, $bm);
Table: SetMargin 引数
引数Default値説明
$lm左マージン (Left margin)
$rm右マージン (Right margin)
$tm上マージン (Top margin)
$bm下マージン (Bottom margin)
SetMargin で調整していない場合は右 Y 軸の数値が表示しきれていない。














$graph->img->SetMargin(30, 30, 30, 30); で調整した場合。

[JpGraph]データベースから JpGraph でグラフを作成する

PHP + MySQL については こちら を参照
examsテーブルに以下のデータが入っているとする。
Table: テーブル例
idnamescore
1student149
2student230
3student386
examsテーブルから点数(score)を取得して表を書く
Example: exams_table.php
<?php
/* SQLサーバに接続 */
$conn_id = mysql_connect("localhost", "ユーザ名", "パスワード") or die ('Error connecting to mysql');

/* DBを選択 */
mysql_select_db('データベース名', $conn_id);

/* examsテーブルからname, scoreを取得する */
$query = "SELECT name, score FROM exams";
$result = mysql_query($query, $conn_id) or die ($query . ' failed (' . mysql_error() . ')');

echo "<table border=1>\n";
echo "<tr><th>Name</th><th>Score</th></tr>\n";
while ($row = mysql_fetch_object($result)) {
 echo "<tr>";
 echo "<td>" . $row->name . "</td>\n";
 echo "<td>" . $row->score . "</td>\n";
 echo "</tr>\n";
}
echo "</table>\n";
mysql_free_result($result);

/* SQLサーバから切断 */
mysql_close($conn_id);
?>
グラフを作成し画像として出力する。
Example: exams_graph.php
<?php
include ("jpgraph/jpgraph.php");
include ("jpgraph/jpgraph_bar.php");

$ydata = array();
$a = array();

/* SQLサーバに接続 */
$conn_id = mysql_connect("localhost", "ユーザ名", "パスワード") or die ('Error connecting to mySQL server');

/* DBを選択 */
mysql_select_db("データベース名", $conn_id);
 
/* examsテーブルから使用量を取得する */
$query = "SELECT name, score FROM exams";
$result = mysql_query($query, $conn_id) or die ($query . ' failed (' . mysql_error() . ')');

/* データを配列に格納する */
while ($row = mysql_fetch_object($result)) {
 array_push($ydata, $row->score);
 array_push($a, $row->name);
}
mysql_free_result($result);

/* SQLサーバから切断 */
mysql_close($conn_id);

/* グラフ作成 */
$graph = new Graph(350, 250, "auto");
$graph->SetScale("textlin");

/* X軸項目追加 */
$graph->xaxis->SetTickLabels($a);

/* plot作成 */
$bplot = new BarPlot($ydata);

/* グラフ上に描画 */
$graph->Add($bplot);

/* グラフ表示 */
$graph->Stroke();
?>
表とグラフを表示するページ
Example: exams.php
<!DOCTYPE HTML PUBLIC "-//IETF/DTD HTML//EN">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Exam</title>
</head>
<body>
<?php
  require('exams_table.php');
?>
<br><br>

<img src="exams_graph.php">

</body></html>
グラフはこのようなものが表示される。

[JpGraph]インストール

  1. JpGraph - Most powerful PHP-driven charts からダウンロードする
  2. php.iniに定義してあるinclude_pathディレクトリの下に展開したディレクトリを置く
  3. jpgraph下のsrcにphpファイル群があるが、phpソースからはjpgraph/hoge.phpで参照されるのでsrcファイル群をjpgraph直下に移動する
  4. TrueTypeフォントの設定をする
  5. jpgraph/jpg-config.inc.phpの42行目に以下を追加
        DEFINE("TTF_DIR","c:/windows/fonts/");
        DEFINE("MBTTF_DIR","c:/windows/fonts/");
    
  6. 日本語フォントの確認をする
  7. jpg-config.inc.phpの110行目のフォント指定がIPAになっているか確認
        // Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
        DEFINE('MINCHO_TTF_FONT','ipam.ttf');
        DEFINE('PMINCHO_TTF_FONT','ipamp.ttf');
        DEFINE('GOTHIC_TTF_FONT','ipag.ttf');
        DEFINE('PGOTHIC_TTF_FONT','ipagp.ttf');
    

[PHP]MySQL へアクセス (まとめ)

php_test という Database に species というテーブルがあるとする。
species は以下の構成とする。
Table: テーブル例
idint(10)Primary Key, auto_increment
namevarchar(30)
speciesテーブルの中身は以下の通りとする
Table: Species テーブル例
idname
1Bird
2Fish
3Dog
<html>
  <body>
    <?php
$dbhost = 'localhost';
$dbuser = 'ユーザ名';
$dbpass = 'パスワード';

/* MySQL server に接続 */
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error connecting to mysql');

/* Database 選択 */
$dbname = 'php_test';
mysql_select_db($dbname);

/* SQL query */
$query = "SELECT * FROM species WHERE 1";
$result = mysql_query($query);
if ($result == false) {
 print "Error: " . $query . "<br>(" . mysql_error() . ")";
 exit;
}

print("<table border=1>\n");
print("<tr><td>ID</td><td>Name</td></tr>\n");

while ($row = mysql_fetch_object($result)) {
 print("<tr><td>");
 echo $row->id;
 print("</td><td>");
 echo $row->name;
 print("</td></tr>\n");
}
print("</table>\n");

/* メモリの開放 */
mysql_free_result($result);

/* MySQL server から切断 */
mysql_close($conn);
    ?>
  </body>
</html>
結果
<html>
  <body>
    <table border="1">
      <tr><td>ID</td><td>Name</td></tr>
      <tr><td>1</td><td>Bird</td></tr>
      <tr><td>2</td><td>Fish</td></tr>
      <tr><td>3</td><td>Dog</td></tr>
    </table>
  </body>
</html>

[PHP]MySQL へアクセス

MySQLサーバへの接続
mysql_connect() で connection_id (接続ID) を取得し、その ID を使用してデータベースにアクセスする。
$connection_id = mysql_connect("MySQLサーバのアドレス:ポート番号","ユーザー名","パスワード");
MySQLサーバから切断
mysql_close($connection_id);
MySQLサーバへの永続的接続
  • mysql_connect() はスクリプト完了と共に切断される
  • mysql_pconnect() を使用するとスクリプト終了後もコネクションが張られたままになる
  • 既に接続済みの場合は既存の接続 ID を返してくれる
$connection_id = mysql_pconnect("MySQLサーバのアドレス:ポート番号","ユーザー名","パスワード");
データベース選択
mysql_select_db("データベース名",$接続ID);
SQL query
mysql_query("SQL文",$接続ID);
Query 結果表示
  • SQL 文が SELECT の場合 mysql_query() は戻り値に結果 ID を返す
  • 検索結果を取得する場合は結果 ID に対して mysql_fetch_object() を使用する
$result = mysql_query("SELECT分で始まるSQL文",$接続ID);
$row = mysql_fetch_object($result);
オブジェクト取得後は -> で結果を表示
$row = mysql_fetch_object($result);
echo $row->テーブルのカラム名;
または連想配列で結果を取得する
$row = mysql_fetch_array($result);
echo $row["テーブルのカラム名"];
最後は mysql_free_result() で結果を保持しているメモリを開放する
mysql_free_result($result);

[PHP]ファイル操作

ファイルを開く/閉じる
<html>
  <body>
    <?php
    $fp = @fopen("hoge.txt", "w"); // @ を付けることでエラーが表示されない
    fclose($fp);

    $fp = fopen("hoge2.txt", "r");
    fclose($fp);
    ?>
  </html>
</body>

[PHP]現在時刻を取得する

<html>
  <body>
    <?php
    print(date("Y/m/d"));
    ?>
  </html>
</body>
実行結果
<html>
  <body>
  2009/02/19
  </body>
</html>

[PHP]引数付き関数

<html>
<body>
<?php
$a = "hoge";
hoge($a);
print($a . "<br>");

function hoge(&$arg) {
 $arg = "fuge";
}
?>
</body>
</html>
出力結果
<html>
<body>
fuge<br></body>
</html>

[PHP]関数

<html>
<body>
<?php
function greeting() {
 print("Hello, world<br>\n");
 print("Good morning<br>\n");
 print("Good bye<br>\n");
}
greeting();
greeting();

function disp_count($count) {
 print($count . " time<br>\n");
}
disp_count("1st");
disp_count("2nd");
disp_count("3rd");
?>
</body>
</html>
出力結果
<html>
<body>
Hello, world<br>
Good morning<br>
Good bye<br>
Hello, world<br>
Good morning<br>
Good bye<br>
1st time<br>
2nd time<br>
3rd time<br>

</body>
</html>

[PHP]配列

<html>
<body>
<?php
 $a = array();
 array_push($a, "item 1");
 array_push($a, "item 2");
 echo "<pre>\n";
 print_r($a);
 echo "</pre>\n";

 $b = array(34, 65, 1256, 12356, 12, 523);
 $sum = 0;
 for ($i = 0; $i < count($b); $i++) {
  $sum += $b[$i];
 }

 echo "<pre>\n";
 print_r($sum);
 echo "</pre>\n";
?>
</body>
</html>
出力結果
<html>
<body>
<pre>
Array
(
    [0] => item 1
    [1] => item 2
)
</pre>
<pre>
14246</pre>
</body>
</html>

配列のクリア
$raw = array(); // 配列を準備

// 配列の先頭から順番にデータを入れていく
$raw[] = 1;
$raw[] = 2;
$raw[] = 3;
unset($raw); // 配列のクリア

[PHP]文字を表示

<html>
  <body>
    <?php
    echo 'Hello, world!';
    ?>
  </body>
</html>
実行結果
<html>
  <body>
  Hello, world!
  </body>
</html>

[jQuery]アニメーション

Example: ソースコード
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <title>sample02</title>
    <script type="text/javascript">
  $(function() {
    $("button#001").click(function() {
      $("div#a").show("slow");
    });
    $("button#002").click(function() {
      $("div#a").show(3000);
    });
    $("button#010").click(function() {
      $("div#a").hide();
    });
  })
    </script>
    <style type="text/css">
  div {
    width: 200px;
    height: 200px;
    background: red;
    display: none;
  }
    </style>
  </head>
  <body>
    <button id="001" type="button">表示 (slow)</button><br>
    <button id="002" type="button">表示 (3000msec)</button><br>
    <button id="010" type="button">非表示</button><br>
    <div id="a">a</div>
    <br>
  </body>
</html>
結果
sample02 (fc2 にあるテストページに飛びます)

[jQuery]イベント

ボタン押下
Example: ソースコード
<html>
<head>
 <meta content="text/html; charset=UTF-8" http-equiv="content-type">
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
 <title>sample01</title>
 <script type="text/javascript">
$(function() {
 $("button").click(function() {
 $("li").css("color", "red");
 })
})
 </script>
</head>
<body>
 <ul>
 <li>Test Test Test</li>
 <li>テスト テスト テスト</li>
 </ul>
 <button type="button">変更</button><br>
</body>
</html>
結果
sample01 (fc2 にあるテストページに飛びます)
$("button").click(function() {}
はbutton要素がクリックされたイベント時に実行される。

[jQuery]Selector

要素セレクター
$("li").css("color", "red");
<li>要素を選択している。
ID セレクター
$("#001").css("color", "red");
特定のIDを持つ要素を選択している。
要素とIDを使う場合は次のように指定する。
$("li#001").css("color", "red");
クラスセレクター
$(".001").css("color", "red");
特定のクラスを持つ要素を選択している。
要素とクラスを使う場合は次のように指定する。
$("li.001").css("color", "red");

[jQuery]基本形

jQueryの基本形は次のようになる。
$("Selector").Event
Example
<html>
 <head>
 <meta content="text/html; charset=UTF-8" http-equiv="content-type">
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
 <title>sample00</title>
 <script type="text/javascript">
 $(function() {
 $("li").css("color", "red");
 })
 </script>
 </head>
 <body>
 <ul>
 <li>Test Test Test</li>
 <li>テスト テスト テスト</li>
 </ul>
 </body>
</html>
上のコードでは最初の
$(function() {}
$(document).ready(function() {}
の省略形でHTMLが読み込まれてreadyになったタイミングで実行される。
$("li").css("color", "red");
は<li>要素のCSSのcolorプロパティを変更している

[jQuery]導入

HTMLファイルのhead領域に以下を追加する
<script type="text/javascript src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
動作確認
<html>
 <head>
 <meta content="text/html; charset=UTF-8" http-equiv="content-type">
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
 <title>sample00</title>
 <script type="text/javascript">
 $(function() {
 $("li").css("color", "red");
 })
 </script>
 </head>
 <body>
 <ul>
 <li>Test Test Test</li>
 <li>テスト テスト テスト</li>
 </ul>
 </body>
</html>
結果
sample00 (fc2 にあるテストファイルへ飛びます

[script.aculo.us]変更可能な選択リスト

ソース中の ajax.php は上記のものと同様。
<div class="collection_tag">
<span id="collection_tag">dog</span>
<script type="text/javascript">
<!--
new Ajax.InPlaceCollectionEditor('collection_tag', 'ajax.php', {
        collection:["dog", "cat", "elephant"]
});
-->
</script>
</div>
div.collection_tag {
        position: absolute;
        top: 400px;
}

[script.aculo.us]クリックで編集

<div class="edit_tag">
<span id="edit_tag">クリックすると編集可能</span>
<script type="text/javascript">
<!--
new Ajax.InPlaceEditor('edit_tag', 'ajax.php'); // 第 2 引数でフォームの送信先を指定
-->
</script>
</div>
div.edit_tag {
        position: absolute;
        top: 300px;
        left: 300px;
}
Example: ajax.php
<?php
  $str = $_POST['value'];
  echo htmlspecialchars($str);
?>

[script.aculo.us]スライダーバー

<div id="slider_back" class="slider_back">
<div id="slider_top" class="slider_top">0</div>
</div>
<script type="text/javascript">
<!--
new Control.Slider('slider_top', 'slider_back', {
        axis: 'Horizontal', // スライダーの配置方向
        values: $R(0, 100), // 取ることのできる値の範囲
        onChange: function(value) { // 値を変更した時にコールバック
        document.getElementById('slider_top').innerHTML = value;
        },
        onSlide: function(value) { // バーをドラッグしている時にコールバック
        document.getElementById('slider_top').innerHTML = value;
        }
});
-->
</script>
div.slider_top {
        position: relative;
        top: -10px;
        width: 20px;
        height: 25px;
        background-color: #aaaaff;
        text-align: center;
        vertical-align: baseline;
}

div.slider_back {
        position: absolute;
        top: 250px;
        width: 200px;
        height: 5px;
        background-color: #6666aa;
}

[script.aculo.us]項目をドロップする

<div id="drag3" class="drag3_div">Drag3</div>
<div id="drag4" class="drag4_div">Drag4</div>
<div id="drop1" class="drop_div">Drop ゾーン</div>
<script type="text/javascript">
<!--
new Draggable('drag3', { revert: true });
new Draggable('drag4', { revert: true });
Droppables.add('drop1', {
        accept: 'drag3_div', // drop を受け付ける "クラス" を指定
        onDrop: function(element) { // ドロップが発生した時のコールバック
        document.getElementById('drop1').innerHTML = element.innerHTML;
        }
});
-->
</script>
{revert: true}
オプションをつけることでドラッグ後に元の位置に戻るようになる。
div.drag3_div {
        position: absolute;
        left: 200px;
        top: 50px;
        width: 120px;
        height: 60px;
        background-color: #ccffcc;
}

div.drag4_div {
        position: absolute;
        left: 200px;
        top: 150px;
        width: 120px;
        height: 60px;
        background-color: #ffffcc;
}

div.drop_div {
        position: absolute;
        left: 200px;
        top: 200px;
        width: 200px;
        height: 100px;
        background-color: #aaaaaa;
}

[script.aculo.us]Drag とコールバック

drag2 で囲まれた div 領域をドラッグし、その時にコールバック関数を呼び出して処理する。
Example: index.html
<script type="text/javascript">
<!--
new Draggable('drag2', {
        onDrag: function(element, event) {
        var x = element.handle.style.left;
        var y = element.handle.style.top;
        element.handle.innerHTML = 'location:<br /> [' + x + ', ' + y + ']';
        },
        onEnd: function(element, event) {
        element.handle.innerHTML = 'ドラッグ完了';
        }
});
-->
</script>
Example: style.css
div.drag2_div {
 position: absolute;
 left: 20px;
 top: 150px;
 width: 120px;
 height: 60px;
 background-color: #ccffff;
}

[script.aculo.us]Drag

drag1 で囲まれた div 領域をドラッグできるようにする。
Example: index.html
<div id="drag1" class="drag_div">Drag できるlt;/div>
<script type="text/javascript">
<!--
new Draggable('drag1');
-->
</script>
Example: style.css
div.drag_div {
 position: absolute;
 left: 20pxl
 top: 50px;
 width: 120px;
 height: 60px;
 background-color: #ccccff;
}

[script.aculo.us]HTML への記述

<head> タグで scriptaculous.js, prototype.js を読み込ませる。
同様に style.css も読み込ませる。
<link rel="stylesheet" type="text/css" href="./css/style.css" />
<script type="text/javascript" src="./js/prototype.js"></script>
<script type="text/javascript" src="./js/scriptaculous.js"></script>

[script.aculo.us]導入方法

  1. script.aculo.us - downloads からダウン ロードする。
  2. css.jsというディレクトリを作成し js 以下に Script.aculo.us のファイル類を置き、css 以下に style.cssを作成する。

[astyle]padding (--pad-xxx, --unpad-xxx)

制御文, 計算式の padding について整形する。
Example: 整形前
int main(void)
{
int i;
if(i==0) {
i=(i*2)*(3+5);
func(i);
}
return 0;
}
--pad-oper
Operator (=, +, -, *, / など) の周囲を padding を入れる。
Example: --pad-oper
int main(void)
{
    int i;
    if(i == 0) {
        i = (i * 2) * (3 + 5);
        func(i);
    }
    return 0;
}
--pad-paren
括弧 () の周囲に padding を入れる。
Example: --pad-paren
int main ( void )
{
    int i;
    if ( i==0 ) {
        i= ( i*2 ) * ( 3+5 );
        func ( i );
    }
    return 0;
}
--pad-paren-out
括弧 () の外側にのみ padding を入れる。
Example: --pad-paren-out
int main (void)
{
    int i;
    if (i==0) {
        i= (i*2) * (3+5);
        func (i);
    }
    return 0;
}
--pad-paren-in
括弧 () の内側にのみ padding を入れる。
Example: --pad-paren-in
int main( void )
{
    int i;
    if( i==0 ) {
        i=( i*2 )*( 3+5 );
        func( i );
    }
    return 0;
}
--pad-header
if, for, while 等に続く括弧 (条件文) の前後にのみ padding を入れる。
Example: --pad-header
int main(void)
{
    int i;
    if (i==0) {
        i=(i*2)*(3+5);
        func(i);
    }
    return 0;
}
--unpad-paren
Example: 整形前
int main(void)
{
int i;
if ( i == 0 ) {
i = ( i * 2 ) * ( 3 + 5 );
func ( i );
}
return 0;
}
余分な padding を削除する。
Example: --unpad-paren
int main(void)
{
    int i;
    if(i == 0) {
        i = (i * 2) * (3 + 5);
        func(i);
    }
    return 0;
}

[astyle]括弧 (--break-closing-brackets)

前のブロックを閉じる括弧に続いて else 等が来た場合に改行してから else 文を始める。
Example: 整形前
int main(void)
{
int i;
if (i == 0) {
printf("i = 0\n");
}
else if (i == 1) {
printf("i = 1\n");
}
else {
printf("others\n");
}
return 0;
}
Example: --break-closing-brackets
int main(void)
{
    int i;
    if (i == 0) {
        printf("i = 0\n");
    }
    else if (i == 1) {
        printf("i = 1\n");
    }
    else {
        printf("others\n");
    }
    return 0;
}

[astyle]括弧 (blackets オプション)

関数宣言の括弧, ブロックの括弧の付け方。
Example: 整形前
int main(void)
{
int i;
if (i == 0) {
printf("i = 0\n");
}
else if (i == 1) {
printf("i = 1\n");
}
else {
printf("others\n");
}
return 0;
}
--brackets=break
--brackets=break は括弧によるブロックを前の文と分ける。
Example: --brackets=break
int main(void)
{
    int i;
    if (i == 0)
    {
        printf("i = 0\n");
    }
    else if (i == 1)
    {
        printf("i = 1\n");
    }
    else
    {
        printf("others\n");
    }
    return 0;
}
--brackets=attach
--brackets=attach は括弧によるブロックを前の文と同じ行にする。
Example: --brackets=attach
int main(void) {
    int i;
    if (i == 0) {
        printf("i = 0\n");
    } else if (i == 1) {
        printf("i = 1\n");
    } else {
        printf("others\n");
    }
    return 0;
}
--brackets=linux
--brackets=linux は namespace, class, 関数定義の括弧は新規の行に付けるが、関数内の条件分岐などに使う括弧は前の文と同じ行にする。
Example: --brackets=linux
int main(void)
{
    int i;
    if (i == 0) {
        printf("i = 0\n");
    } else if (i == 1) {
        printf("i = 1\n");
    } else {
        printf("others\n");
    }
    return 0;
}

[astyle]switch 文に関わるオプション

switch 文に関わる indent 整形
Example: 整形前
int main(void)
{
int i;
switch (i) {
case 0:
printf("case 0\n");
break;
default:
{
printf("default\n");
break;
}
}
return 0;
}
--indent-cases
--indent-cases は case/default 内の処理が括弧で囲まれている場合は括弧を indent する
Example: --indent-cases
int main(void)
{
    int i;
    switch (i) {
    case 0:
        printf("case 0\n");
        break;
    default:
        {
            printf("default\n");
            break;
        }
    }
    return 0;
}
--indent-switches
--indent-switches は switch 以下の case/default を indent する
Example: --indent-switches
int main(void)
{
    int i;
    switch (i) {
        case 0:
            printf("case 0\n");
            break;
        default:
        {
            printf("default\n");
            break;
        }
    }
    return 0;
}

[astyle]indent オプション

Example: 整形前
int main(void)
{
int i;
printf("hello, world ");
for (i = 0; i < 10; i++) {
printf("%d \n", i);
}
return 0;
}
オプションなし
オプションなしは indent はスペースで埋められる
Example: オプションなし
int main(void)
{
    int i;
    printf("hello, world ");
    for (i = 0; i < 10; i++) {
        printf("%d \n", i);
    }
    return 0;
}
--indent=tab
--indent=tab は indent は TAB で埋められる
Example: --indent=tab
int main(void)
{
 int i;
 printf("hello, world ");
 for (i = 0; i < 10; i++) {
  printf("%d \n", i);
 }
 return 0;
}

[astyle]ソースコード整形 (indent)

インストール
Artistic Style からダウンロードする
使い方
> AStyle.exe --mode=c sample.c
sample.c は sample.c.orig に rename されて、結果が sample.c に出力される
--mode=c
C/C++ のキーワードに従って動作する。c または cpp ファイル以外で C/C++ のルールに従って整形したい場合はこのオプションを指定する。

2013年1月10日木曜日

[Python]標準出力の文字コードを指定

Example: test02.py
# -*- coding: utf-8 -*-
import sys
import codecs

# コマンドプロンプトの文字コードを cp65001 (UTF-8) にしておくと
# LookupError: unknown encoding: cp65001
# と表示されるので cp65001 が utf-8 であると登録しておく

def cp65001(name):
    if name.lower() == 'cp65001':
        return codecs.lookup('utf-8')

codecs.register(cp65001)
print sys.stdout.encoding

# そのままでは文字化けで表示される
# stdout の文字コードを UTF-8 に変更する
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

print "あ"
print u"あ"
実行結果
> python test02.py
cp65001
Traceback (most recent call last):
  File "test02.py", line 20, in 
    print "(文字化け)"
  File "C:\usr\Python27\lib\codecs.py", line 351, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
str 型は表示できないとエラーが出る

2013年1月9日水曜日

[Python]LookupError: unknown encoding: cp65001 対策

Example: test01.py
# -*- coding: utf-8 -*-
import sys
import codecs

# コマンドプロンプトの文字コードを cp65001 (UTF-8) にしておくと
# LookupError: unknown encoding: cp65001
# と表示されるので cp65001 が utf-8 であると登録しておく

def cp65001(name):
    if name.lower() == 'cp65001':
        return codecs.lookup('utf-8')

codecs.register(cp65001)
print sys.stdout.encoding

print "あ"
print u"あ"
実行結果 (UTF-8 のコマンドプロンプト)
> python test01.py
cp65001
(文字化け)
(文字化け)
LookupError は表示されなくなる。

2013年1月8日火曜日

[Perl]Gnuplot

Chart::Graph で Gnuplot を操作
Chart::Graph モジュールをインストール
ppm> install Chart-Graph
Windows で実行すると temporary directory `/tmp/Graph_Gnuplot_xxxx' を作成できないとエラー表示されるので、環境変数に TMPDIR を設定すればよいと考えたのだが、
> set TMPDIR=%USERPROFILE%\Local Settings\Temp
このようにすると出力先指定でディレクトリ記号が
set output "C:\Documents and Settings\xxxxxxx\Local Settings\
            Temp/Graph_Gnuplot_7672/plot.2.png"
\ (円マーク)と / (スラッシュ) の混在となってしまう。これでは gnuplot が解釈できないのでスクリプト内で
$ENV{TMPDIR}=".";
と指定して出力先を current directory 以下にしてもらう。
set output "./Graph_Gnuplot_7980/plot.2.png"
スクリプトから gnuplot を実行しようとするところで
program not found in search path: gnuplot
とエラー表示される。これは Chart::Graph::Utils 内で使用される _get_path が Linux 形式の PATH しか対応していないためである。
sub _get_path {
    my ($exe) = @_;
    my @path = split (/:/, $ENV{PATH});
    my $program;

    foreach my $i(@path){
   $program = "$i/$exe";
   if (-x $program) {
  return $program;
   }
    }

    carp "program not found in search path: $exe";
    return 0;
}
また gnuplot というコマンドを実行しようとするので Perl/site/lib/Chart/Graph/Gnuplot.pm にある gnuplot コマンドを設定する _set_gnupaths を見てみると
sub _set_gnupaths {

    if (not defined($gnuplot)) {
 if (not $gnuplot = _get_path("gnuplot")) {
     return 0;
 }
    }

    if (not defined($ppmtogif)) {
 if (not $ppmtogif = _get_path("ppmtogif")) {
     return 0;
 }
    }
    return 1;
}
となっているので $gnuplot に直接実行プログラムを記述してやればこの問題は回避できる。
使い方
Windows 用 Gnuplot では pgnuplot.exe なので下記のように指定する。
$Chart::Graph::Gnuplot::gnuplot = "c:/usr/gnuplot/bin/pgnuplot.exe";
Example: テストスクリプト
use utf8;
use Chart::Graph::Gnuplot qw(gnuplot);
$Chart::Graph::save_tmpfiles = 0;
$Chart::Graph::Gnuplot::gnuplot = "c:/usr/gnuplot/bin/pgnuplot.exe";

$ENV{TMPDIR}=".";

gnuplot({'title' => 'Test graph',
   'xrange' => '[0:3]',
   'yrange' => '[0:50]',
   'output type' => 'png',
   'output file' => 'test.png',
   'size' => [0.625, 0.625],
   'extra_opts' => join("\n", 'set grid'),
},
  [{'title' => 'data1',
    'type' => 'matrix'}, [[0,5],
        [1,10],
        [2,20],
        [3,30]]],
  [{'title' => 'data2',
    'style' => 'lines',
    'type' => 'matrix'}, [[0,20],
        [1,5],
        [2,15],
        [3,12]]],
  [{'title' => 'y=10x+10',
    'style' => 'lines',
    'type' => 'function'}, '10+10*x'],
 );
size を指定しているのは、出力データの画像サイズを調整するため。デフォルト (size 指定なし) では 640x480 pixel となるので 400x300 pixel を作りたければ縦横 0.625 倍と指定すればよい。
出力結果

[Python]web.py - Apache + mod_wsgi で web.py を動作させる

  1. /etc/httpd/conf/httpd.conf を編集
    # web.py
    WSGIScriptAlias /webpy /var/www/cgi-bin/python/webpy/code.py/
    Alias /webpy/static /var/www/cgi-bin/python/webpy/static/
    AddType text/html .py
    <Directory "/var/www/cgi-bin/python/webpy/">
    Order allow,deny
    Allow from all
    </Directory>
    
  2. ディレクトリ作成
    /var/www/cgi-bin/python/webpy ディレクトリを作成
  3. Test script 作成
    /var/www/cgi-bin/python/webpy/code.py を作成
    Example 8. code.py
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    import web
    urls = (
        '/', 'index'
    )
    
    class index:
        def GET(self):
            return "Hello, world!"
    
    app = web.application(urls, globals())
    application = app.wsgifunc()
    
  4. Apache 再起動
    # /etc/init.d/httpd restart
    
  5. http://localhost/webpy/ にアクセスし Hello, world! が表示されることを確認する
参照: Webpy + Apache with mod_scgi

2013年1月7日月曜日

[Perl]Test

Test::Simple
Test::Simple モジュールを使って Perl のテストを書いてみる
use Test::Simple tests => 2; # テスト数の設定 (計画しているテスト数を記述)

ok(1+1==2);                  # テスト No.1 (OK)
ok(1+1==0);                  # テスト No.2 (NG)
実行結果は以下のようになる。
>perl test-simple.pl
1..2
ok 1
not ok 2
#     Failed test (test-simple.pl at line 4)
# Looks like you failed 1 tests of 2.
上記のテスト用 perl ソースで 1 行目の想定テスト数を実際のテスト数と異なる数にしておくと
use Test::Simple tests => 3; # テスト数の設定 (計画しているテスト数を記述)

ok(1+1==2);                  # テスト No.1 (OK)
ok(1+1==0);                  # テスト No.2 (NG)
実行結果
>perl test-simple.pl
1..3
ok 1
not ok 2
#     Failed test (test-simple.pl at line 4)
# Looks like you planned 3 tests but only ran 2.
計画していたテスト数と実施されたテスト数が異なると注意が出る
Test::More
Test::More モジュールを使用すると Test::Simple よりも幅広いテストができる
use Test::More tests => 7; # テスト数の設定

ok(1+1==2);                  # Test No.1 (OK)
ok(1+1==0);                  # Test No.2 (NG)

# 等差チェック (is)
is(1+1, 2);                   # Test No.3 (OK) (等しいか?)

# 正規表現チェック (like)
like("abcde", qr/^a/);       # Test No.4 (OK) (正規表現にマッチしているか?)
like("abcde", qr/^b/);       # Test No.5 (NG)

# 比較 (cmp_ok)
cmp_ok(1+1, '<', 3); # Test No.6 (OK)
cmp_ok(1+1, '=', 2); # Test No.7 (OK)
実行結果は以下のようになる
>perl test-more.pl
1..7
ok 1
not ok 2
#     Failed test (test-more.pl at line 4)
ok 3
ok 4
not ok 5
#     Failed test (test-more.pl at line 11)
#                   'abcde'
#     doesn't match '(?-xism:^b)'
ok 6
ok 7
# Looks like you failed 2 tests of 7.
Test::Base
Test::Base モジュールはテストデータとテスト手段を分けて記述することができる
use Test::Base;

plan tests => 1 * blocks;

filters {
    input    => [qw/chomp/],
    expected => [qw/chomp/],
};

run {
    my $block = shift;
    is(increment($block->input), $block->expected);
};


# テスト対象関数
sub increment {
    my ($arg1) = @_;
    my $ret;

    $ret = $arg1 + 1;

    return $ret;
}

__END__

# 以下がテスト対象と期待される結果を記述するブロック
=== test 1 (OK)
--- input
1
--- expected
2

=== test 2 (NG)
--- input
1
--- expected
0
実行結果は以下のようになる
> perl test-base.pl
1..2
ok 1
not ok 2
#     Failed test (test-base.pl at line 12)
#          got: '2'
#     expected: '0'
# Looks like you failed 1 tests of 2.

[Python]web.py - 動的なページの作成

URL で指定
上記の index.html を再度使用する
Example 4. test02.py
# -*- coding:utf-8 -*-
# http://localhost:8080/?name=hoge とすると name が指定される
import web
urls = (
    '/', 'index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class index:
    def GET(self):
        i = web.input(name=None)
        return render.index(i.name)

if __name__ == "__main__": app.run()
実行
> python test02.py
http://localhost:8080/ にアクセスすると Hello, world! と表示される
http://localhost:8080/?name=hoge としてアクセスすると I just wanted to say hello to hoge. と表示される

URL の別階層として表示
index.html を再び使用する
Example 5. test03.py
# -*- coding:utf-8 -*-
# http://localhost:8080/hoge とすると name が指定される
import web
urls = (
    '/(.*)', 'index'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class index:
    def GET(self, name):
        return render.index(name)

if __name__ == "__main__": app.run()
実行
> python test03.py
http://localhost:8080/ にアクセスすると Hello, world! と表示される
http://localhost:8080/hoge としてアクセスすると I just wanted to say hello to hoge. と表示される

2013年1月6日日曜日

[Perl]ImageMagick

インストール
  1. ImageMagick の Windows binary ファイルダウンロード へ行き、ImageMagick の DLL 版 (ImageMagick-6.8.5-9-Q16-x86-dll.exe) をダウンロードする
  2. インストール時に PerlMagick for ActiveState Perl を選択する


画像ファイルの長辺・短辺を判断
フォルダ内の全画像ファイルに対して、画像の縦横長を調べる
use Image::Magick;
use strict;
use utf8;

# ディレクトリ内のファイルを探索
my $dir = "."; # カレントディレクトリ
my @fileList;
my $file;
opendir(DH, $dir) or die "$dir:$!";
while ($file = readdir DH) {
 next if $file =~ /^\.{1,2}$/; # ., .. を除く
 if ($file =~ /\.jpg$/) {
  # 末尾が jpg のファイルのみ選択する
  print "$file\n";
  push(@fileList, $file);
 }
}
print "\n". "@fileList" . "\n";

my $width, my $height;
foreach $file (@fileList) {
 # インスタンス作成
 my $imgMagick = Image::Magick->new;

 # 画像読み込み
 $imgMagick->Read($file);

 # 縦横幅取得
 ($width, $height) = $imgMagick->Get("width", "height");
 print "$file - Width: $width, Height: $height\n";
}
実行結果
> perl image.pl
a.jpg
b.jpg

a.jpg b.jpg
a.jpg - Width: 2592, Height: 3872
b.jpg - Width: 3872, Height: 2592
画像の長辺を固定幅にそろえる
Perl の Image::Magick モジュールを使ってフォルダ内にある全画像の長辺をすべて 1024 に統一する。
use Image::Magick;
use strict;
use utf8;

# ディレクトリ内のファイルを探索
my $dir = "."; # カレントディレクトリ
my @fileList;
my $file;
opendir(DH, $dir) or die "$dir:$!";
while ($file = readdir DH) {
 next if $file =~ /^\.{1,2}$/; # ., .. を除く
 if ($file =~ /\.jpg$/) {
  # 末尾が jpg のファイルのみ選択する
  print "$file\n";
  push(@fileList, $file);
 }
}
print "\n". "@fileList" . "\n";

my $width, my $height;
foreach $file (@fileList) {
 # インスタンス作成
 my $imgMagick = Image::Magick->new;

 # 画像読み込み
 $imgMagick->Read($file);

 # 縦横幅取得
 ($width, $height) = $imgMagick->Get("width", "height");
 print "$file - Width: $width, Height: $height\n";

 if ($width > $height) {
  $imgMagick->Resize(geometry=>"1024x");
 }
 else {
  $imgMagick->Resize(geometry=>"x1024");
 }
 $imgMagick->Write("f" . $file);
}
実行結果
> perl image.pl
a.jpg
b.jpg

a.jpg b.jpg
a.jpg - Width: 2592, Height: 3872
b.jpg - Width: 3872, Height: 2592
実行後、fa.jpg, fb.jpg というファイルが生成され、それぞれ以下のファイルサイズに変換されている
fa.jpg - Width: 685, Height: 1024
fb.jpg - Width: 1024, Height: 685