「憂鬱な勇者」をErlangで

趣味と勉強を兼ねて「憂鬱な勇者」をErlangで作ってみました。

以下のソースをUTF-8でyy.erlというファイルに保存し、Erlangのコンソールから「c(yy).」「yy:start().」と入力すると実行できます。

Erlangらしく複数プロセスで構成しました。

  • system … ゲームシステム
  • hero … 勇者
  • monster … モンスター
  • rand … 乱数

すべてのモンスターはそれぞれ別のプロセスとして作成されます。乱数はプロセスごとに初期化されるため、一貫した乱数を作成するために別プロセスに独立させました。

以下のようにメッセージを送り合いながら動作します。

Erlang初心者なのでおかしな部分があると思います。アドバイスがありましたらよろしくお願いします。

Play 2からMicrosoft Accessの日本語テーブルに接続する方法

Play 2のScalaコードからMicrosoft Accessの日本語テーブルに接続する方法の説明です。
動作確認環境: Play 2.1.1+WindowsXPMDB(Access 2000形式)

こんなテーブルに接続

以下のようなテーブルに接続します。

接続はODBCデータソースにシステムDSNとして設定しました。


日本語テーブルに接続するコード

play newで新しいアプリケーションを作成し、controllers/Application.scalaとviews/index.scala.htmlを次のような内容にします。

実行すると次のように表示されます。コードを簡単にするため1行だけ表示させています。データベースへのアクセスにはAnormを使用しています。

以下でポイントを説明します。

ポイント1: 標準のデータベース設定は使わない

Playではconfig/application.confに接続情報を書くことでデータベースに自動的に接続してくれます。(JDBCコネクションプールの設定)

しかし文字コードがUTF-8に決め打ちになっているため、Microsoft Accessの日本語テーブルに接続するとエラーが発生します。

そこで、自前でConnectionを作成しています(Application.scala 16〜17行目)。

ポイント2: JDBCドライバの文字コードSJISにする

charSetとしてSJISをセットしたプロパティを用意し(Application.scala 13〜14行目)、それをDriverManager.getConnectionの第2引数に渡しています(17行目)。

以上でMicrosoft AccessのテーブルにSJISで接続することができます。

JavaScriptのMaybeモナド

Maybeモナド

モナドが少し理解できるようになったので、JavaScriptでMaybeモナドを作ってみました。この記事で使われているソースはGitHubにあります。


使ってみる

上記のモナドを使ってみます。サンプルは id:kazu-yamamoto さんのMaybe モナドの秘密 - あどけない話を参考にさせていただきました。

次のように名前と親を格納したデーターがあるとします。Bobの親はDave、その親はSteve、その親はTonyです。Tonyの親は不明 (undefined) です。

// 親子を表すデーター
var tony = { name: "Tony", parent: undefined };
var steve = { name: "Steve", parent: tony };
var dave = { name: "Dave", parent: steve};
var bob = { name: "Bob", parent: dave };

ある人物を与えたときにその人のひいおじいさんを返すような関数は、途中でundefinedに当たることを考慮して、次のように書くことができます。

// ひいおじいさんを返す関数 (Maybeモナドを使っていない)
function findGrandGrandFather(p) {
  if (p.parent) {
    if (p.parent.parent) {
      return p.parent.parent.parent;
    }
  }
  return undefined;
}
findGrandGrandFather(bob);   // --> tony
findGrandGrandFather(steve); // --> undefined

これをMaybeモナドで書き直してみましょう。Maybeモナドを使うと失敗するかも知れない演算を合成することができます。

まず人物を与えると親を返す関数fatherを定義します。親が存在する場合には親を内包するMaybe.Just(親)を、親が存在しない場合にはMaybe.Noneを返します。

// 親を返す関数 (Maybeモナドで返す)
function father(p) {
  return (p.parent) ? new Maybe.Just(p.parent) : new Maybe.None();
}

これを使うとひいおじいさんを返す関数は次のように書くことができます。

// ひいおじいさんを返す関数 (Maybeモナドを使用)
function findGrandGrandFatherM(p) {
  return (new Maybe.Just(p)).bind(father).bind(father).bind(father);
}
findGrandGrandFatherM(bob);   // --> Just(tony)
findGrandGrandFatherM(steve); // --> None

bindで計算を合成しています。関数fatherの値が途中でNoneになった場合、後続の演算はすべてNoneを返します。

Maybeモナドを使わない元のコードでは「ひいひいおじいさんを返す関数」にするにはifのネストを上げる必要がありますが、Maybeモナドを使うと「.bind(father)」を追加するだけで済みます。

なお、私が作ったMaybeモナドでは内包する値を取り出す関数は用意していません。結果のJust(人物)から人物を取り出すにはvalueフィールドを参照します。また、「if (a.value) ...」のように書くとvalueフィールドがあるかどうか判断することができるため、Noneと識別することができます。

モナド

モナドと名乗るにはモナド則を満たす必要があります。QUnitによるテストは次の通りです。

モナド則の3つの規則すべてを満たしています。

MyDefragで自動実行されるデフラグの優先度を下げる方法

MyDefragをインストールするとWindowsのタスクスケジューラに自動実行タスクが登録されます。このタスクが開始されるとパソコンの反応速度が下がります。そこで優先度を下げることにしました。

MyDefragの優先度を変更するには、実行されるスクリプトファイルの中で次のように優先度を指定します。

ProcessPriority(引数)

引数には次のうちの一つを指定します (MyDefragのヘルプより)。

High CPU優先度高。ほとんどすべてのCPU時間を使用するため、MyDefragではお勧めしません。
AboveNormal CPU優先度はNormalとHighの間です。
Normal すべてのWindowsプログラムの標準のCPU優先度です。これはMyDefragのデフォルト値です。
BelowNormal CPU優先度はNormalとLowの間です。
Low CPU優先度低。この設定ではMyDefragはシステムがアイドルの時だけ実行されます。これはMyDefragスクリーンセーバーのデフォルト値です (Windowsはすべてのスクリーンセーバーをこの優先度クラスで実行します)。
Background バックグラウンド優先度です。これはリソース(I/O)スケジューリングとCPU優先度を低にします。この設定によって他のプログラムはより高速にディスクにアクセスできるようになります。この設定はWindows 2000/2003/XPではサポートされていません。

というわけで、MyDefragの優先度を下げるには、Windows 2000/2003/XPでは「ProcessPriority(Low)」、Vista以上では「ProcessPriority(Background)」を指定します。指定する場所はMyDefragのスクリプトの先頭付近の適当な場所です。

たとえば自動的にインストールされるタスク「MyDefrag vX.X.X Daily」ではMyDefragをインストールしたディレクトリのScriptsフォルダにあるAutomaticDaily.MyDファイルが実行されるため、そのファイルに以下のように記述します。

...

/* Automatically exit when the script has finished. This script is designed to
   be run via the task scheduler, so it must exit automatically. */
WhenFinished(exit)

/* If another instance of MyDefrag is already running then exit. */
OtherInstances(exit)

/* Write the header to the logfile. See the "Settings.MyD" file for the
   definition of the "LogHeader" string. */
WriteLogfile("MyDefrag.log","LogHeader")

/* Use low priority I/O (Windows Vista and above only) */
ProcessPriority(Background)

...

これでスケジュールされたMyDefragタスクの実行時にバックグラウンド優先度で実行されます。

Gmailで指定したタイトルのメールを表示するブックマークレット

受信トレイにある、指定したタイトルのメールを表示するブックマークレットです。

Google Chrome 22.0.1229.92 m、Firefox 15.0.1で動作確認しています。今後のGmailの仕様変更によって動作しなくなる可能性があります。

使い方

1. 準備:下記のコードをブラウザのブックマークに登録します。

2. ブックマークレットを実行します。

3. ダイアログが表示されますので、タイトルの一部を入力します。

4. タイトルに指定した文字列を含む、受信トレイにあるメールが一覧表示されます。

もし受信トレイではなくすべてのメールの中から表示したい場合には、コード中の "in:inbox%20subject:" を "subject:" に変更してください。

Gmailで同じ送信者のメールを表示するブックマークレット

受信トレイにある、現在表示しているメールと同じ送信者からのメールを表示するブックマークレットです。

Google Chrome 21.0.1180.89 m、Firefox 15.0.1で動作確認しています。今後のGmailの仕様変更によって動作しなくなる可能性があります。

使い方

1. 準備:下記のコードをブラウザのブックマークに登録します。

2. Gmailでメールを開いた状態にします。

3. ブックマークレットを実行します。

4. 開いていたメールと同じ送信者で受信トレイにあるメールが一覧表示されます。

もし受信トレイではなくすべてのメールの中から表示したい場合には、コード中の"in:inbox%20from:"を"from:"に変更してください。

play! 1.2.4でSQL ServerのIDENTITYフィールド付きテーブルのモデルを作成する方法

play! 1.2.4でSQL ServerのIDENTITYフィールド付きテーブルのモデルを作成する方法です。自分用のメモです。

下記コードは d:id:scalar:20120224:1330071564 さんを参考にさせていただきました。

SQL Serverにこんな構成のTABLE1テーブルがあったとします。

IDはIDENTITYで自動採番になっています。

このテーブルのモデルを作成するには次のように記述します。

package models;

import javax.persistence.*;
import play.db.jpa.GenericModel;

@Entity
@Table(name="TABLE1")
public class Table1 extends GenericModel {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="ID", unique=true, updatable=false)
    public long id;
    
    @Column(name="NAME")
    public String name;
    
    public Table1(String name) {
        this.name = name;
    }
    
}