2013年1月17日木曜日

財布経過

財布購入から早一年。
購入した GANZO の財布がどうなったかとういことで。


基本、バッグか上着の内ポケットに入れて持ち歩いているが、角のほうが若干へたってきている。
落としたり、水をこぼしたりしてしまったので、内側外側共に細かい傷がいっぱいついている。内側には若干染みになっている部分も。

エイジング的にはありだが、コードバンの場合最初のきれいな状態を保ちたいという感じもしてしまう・・・

手入れは、GANZO のサイトに、「乳化性タイプ無色 成分はろう・油脂の栄養補給を目的としたクリーム」でアフターケアをと書かれてたので、M.モゥブレィシュークリームという靴用のクリーム購入。

これでたまに磨いている。
外側の折る背の部分が若干カサつく。折れる部分なので仕方ないんだろう。念入りクリームを塗っている。

硬さは 1 年前に比べて大分柔らかくなり、360度開くことも可能になった。
小銭部分はマチがないのであまり多いと取り出し難い。
カードも取り出しやすくなった。伸びてガバガバになっているわけでもなくいい感じ。
 さらに使い込んでいこうと思う。

2012年12月27日木曜日

sbt で設定ファイルを本番用に切り替え

Scala の勉強をかなりさぼっていたわけで・・・
構文も大分忘れている状態なんですが、またちょっとはじめることに。
というか実践。

sbt を使ってちょっとしたバッチを開発時に jar に含める設定ファイル(ログレベル設定等)を、開発、ステージング、本番用に切り替えたくなった。そして嵌った・・・約 2 日・・・

とりあえず設定ファイルの構成は、Java の時にやっていた構成で、
+ src
  + main (開発)
    + scala
    + resources
      + logback.xml
      + ...
  + product (本番)
    + resources
      + logback.xml
  + staging (ステージング)
    + resources
      + logback.xml
の構成で、product/resources, staging/resources には上書きするもののみを置くこととする。

始める sbt のスコープ軸を見ると、タスク毎に設定が出来そう。ということで、最初のアプローチは、pack-staging, pack-product のタスクを生成して、タスクのスコープで unmanagedResourceDirectory を追加しようとした。が、そこから呼び出す copy-resources は copy-resources in Compile になってしまい挫折・・・これに 1 日以上費やしたわけだが・・・結局わからなかった・・・

で、maven の profile 的なことができないかと検索してみると参考になるサイトがあった。
ここを参考に、
case class Profile(name: String)

object Profile {
 val staging = Profile("staging")
 val product = Profile("product")

 implicit def toOption(profile: Profile): Option[Profile] = Option(profile)
}
として、
  unmanagedResourceDirectories in Compile <<= (sourceDirectory, selectedProfile, unmanagedResourceDirectories in Compile)
    ((dir, env, res) => env.map((dir / _.name / "resources")).toSeq ++ res),
  unmanagedResources in Compile~= (_.groupBy((_: java.io.File).getName).map(_._2.head).toSeq),
リソースディレクトリの設定時に振り分け。さらに、リソースファイル設定時に一意になるようグループ化しているようなしていないような・・・いまいち何をやっているかわからないが完成・・・ 

記号がさっぱりわからん・・・Perl とまでは言わんが・・・演算子でなくメソッドなので色々できるわけだが、C++ みたいに標準的な演算子のみオーバーライドできればいいのに・・・ ライブラリ毎に覚えるのは大変だ・・・ 標準的な意味合いの記号があるのだろうか。

 とりあえず sbt の API ドキュメントより、Setting[T] の <<= メソッドを見てみると trait DefinableSetting[S] に定義があり、
final def <<=(app: Initialize[T]): Setting[T]
なるほど、Initialize[T] を受け取る。 unmanagedResourceDirectories は SettingKey[Seq[File]] なので、右辺の
(sourceDirectory, selectedProfile, unmanagedResourceDirectories in Compile)
    ((dir, env, res) => env.map((dir / _.name / "resources")).toSeq ++ res)
は、Initialize[Seq[File]] を返すのであろう。

で、右辺部分だが、
(sourceDirectory, selectedProfile, unmanagedResourceDirectories in Compile)(なんかの処理)
つまり、
(タプル).apply(なんかの処理)
のように見えるが、タプルに対してそんなことできるのか・・・おそらくは暗黙の型変換・・・
というわけで、ソースコードを implisit で grep すると、Structure.scala で
implicit def t3ToApp3[A,B,C](t3: (Initialize[A], Initialize[B], Initialize[C]) ): Apply3[A,B,C] = new Apply3(t3)
というのを発見。さらに、Apply3 をみると、
def apply[T](z: (A,B,C) => T) = Project.app( k3(t3) )( hf3(z) )
となっている。さらに、object Project の API ドキュメントに、Init[Scope] に app の定義があり
def app[HL <: HList, T](inputs: KList[Initialize, HL])(f: (HL) ⇒ T): Initialize[T]
なので、Initialize[Seq[File]] が返りそう。なんか予想が多いが・・・

次に、なんかの処理部分は、Apply3 の apply の引き数なので、
(A,B,C) => T
最初のタプルの設定の値がそれぞれ渡り、T つまり、Seq[File] を返す関数を渡せばよさそう。
unmanagedResourceDirectories が SettingKey[Seq[File]] なので、res は Seq[File] とおもわれる。
そして、生成したパスと res を連結したものが返ると。

最終的に返った、Initialize[Seq[File]] で unmanagedResourceDirectories in Compile を設定しているようだ。
とりあえず、今回はここまで。
追うのだけでも大変・・・自分でカスタマイズ出来る気がしない・・・Scala は嫌いじゃないけど慣れないと、読むのも困難だな・・・

2012年10月19日金曜日

Java による画像縮小 lanczos 編

JDK を使った縮小の結果納得行かなかったので、GIMP なんかにもある lanczos による縮小を実装してみることに。
元画像は Jpeg なので、RGB の 3 色のみを扱う。

こちらの Ruby バージョンをとりあえず Java にポーティング。
今回縮小のみなので、拡大部分を削除。実行してみると 6 秒前後かかった・・・

もう少し早くならないかなと、さらにコメントのリンク先を読んでみる。

何をやっているかというと、中心を 1 として距離によって重みを付けるということのようだ。
| 0.3 | 0.5 | 0.3 |
|-----+-----+-----|
| 0.5 | 1.0 | 0.5 |
|-----+-----+-----|
| 0.3 | 0.5 | 0.3 |

といった具合に。
重みを計算するのが lanczos 関数。
lanczos2 や lanczos3 の数字は距離で、縮小画像のあるピクセルを計算するために、対応する元画像ピクセルからどれくらいの範囲を参照するかを決めるものっぽい。

となると、縮小率と距離の数字が決まれば、対象のピクセルがどこであろうと、重みは一緒?
というわけで、先に上記のような重みの表を作成しておき、各ピクセル計算時はそれを使用すれば計算量は減るだろう。

中心からのオフセットと重みを保持するクラス

public class Weight {
  public final int offsetX;
  public final int offsetY;
  public final double weight;

  public Weight(int x, int y, double w) {
    offsetX = x;
    offsetY = y;
    weight = w;
  }
}

重みの一覧と合計を保持するクラス

public class WeightFilter {
  public final double weightTotal;
  public final Weight[] weightList;


  public WeightFilter(double sumw, Weight[] weights) {
    weightTotal = sumw;
    weightList = weights;
  }
}

lanczos 関数

public static double lanczos(double x, double n) {
  if (x == 0.0) return 1.0;
  if (Math.abs(x) >= n) return 0.0;
  return Math.sin(Math.PI * x) / Math.PI / x * (Math.sin(Math.PI * x / n) / Math.PI / x * n);
}

縮小率と距離で重み一覧作成

縦・横別でなく斜めも距離を計算してみる
public static WeightFilter getReduceFilter(double scale, int distance) {
  double bdx0 = 0 + 0.5, bdy0 = 0 + 0.5;
  int ss = (int)((bdx0 - distance) / scale), se = (int)((bdx0 + distance) / scale);
  double sumw = 0.0;
  List<Weight> weightList = new ArrayList<>((se - ss) * (se - ss));

  for (int sy = ss; sy <= se; ++sy) {
    for (int sx = ss; sx <= se; ++sx) {
      double xl = (sx + 0.5) * scale - bdx0;
      double yl = (sy + 0.5) * scale - bdy0;
      double w = lanczos(Math.sqrt(xl * xl + yl * yl), distance);
      if (w == 0.0) continue;
      weightList.add(new Weight(sx, sy, w));
      sumw += w;
    }
  }
  return new WeightFilter(sumw, weightList.toArray(new Weight[0]));
}


ユーティリティ関数も作成。

指定座標の RGB 値取得

範囲外は鏡像として取得。
public static int getRGB(int[] image, int x, int y, int w, int h) {
  x = Math.abs(x); y = Math.abs(y);
  if (x >= w) x = w + w - x - 1;
  if (y >= h) y = h + h - y - 1;
  return image[y * w + x];
}

0 - 255 の範囲で色値取得

public static int getColor(double val, double sumw)
{
  if (sumw != 0.0) val /= sumw;
  if (val < 0.0) return 0;
  if (val > 255.0) return 255;
  return (int)val;
}

縮小処理

public static BufferedImage reduce3(BufferedImage image, int n, int dw, int dh)
  int sw = image.getWidth(), sh = image.getHeight();

  double scale = (double)dw / sw;
  BufferedImage thumb = new BufferedImage(dw, dh, image.getType());
  WeightFilter filter = getFilter(scale, n);
  double sumw = filter.weightTotal;
  int[] colors = image.getRGB(0, 0, sw, sh, null, 0, sw);

  for (int dy = 0; dy < dh; ++dy) {
    for (int dx = 0; dx < dw; ++dx) {
      double dr = 0.0, db = 0.0, dg = 0.0;
      int bsx = (int)(dx / scale), bsy = (int)(dy / scale);
      for (Weight weight : filter.weightList) {
        int rgb = getRGB(colors, bsx + weight.offsetX, bsy + weight.offsetY, sw, sh);
        dr += ((rgb >> 16) & 0xFF) * weight.weight;
        dg += ((rgb >> 8) & 0xFF) * weight.weight;
        db += (rgb & 0xFF) * weight.weight;
      }
      thumb.setRGB(dx, dy, (getColor(dr, sumw) << 16) | (getColor(dg, sumw) << 8) | getColor(db, sumw));
    }
  }
  return thumb;
}

呼び出し

lanczos2 と lanczos3 で縮小。
long start3_1 = System.currentTimeMillis();
BufferedImage reduce3_1 = reduce3(base, 2, 120, 90);
System.out.println("reduce3_1: " + (System.currentTimeMillis() - start3_1));
outputImage("reduce3_1.jpg", reduce3_1);

long start3_2 = System.currentTimeMillis();
BufferedImage reduce3_2 = reduce3(base, 3, 120, 90);
System.out.println("reduce3_2: " + (System.currentTimeMillis() - start3_2));
outputImage("reduce3_2.jpg", reduce3_2);

結果

lanczos2: 126.3ms
lanczos3: 233.0ms

元画像と左から、パターン1 3段階、パターン2 3段階、lanczos2、lanczos3




大分早くなった。JDK に比べると遅いが画質はいい。
一度作成してた後は、キャッシュするようにすればいいので、満足。

Java による画像縮小 JDK 編

忙しい日々が続いて、色々嵌っているが書けていない・・・
また同じ事で嵌まることになるだろう・・・

半年以上前だが、Java で画像を縮小してサムネイルを作成する際に、なるべく画質を落としたくなかったので色々試したのでその記録を。
結局ブログ書くために再調査したわけだけ・・・

元となる画像(1024 x 768)は、
これから 120 x 90 のサムネイルを作成することとする。


共通処理として、

画像読み込み

public static BufferedImage loadImage(String filename) {
  try (FileInputStream in = new FileInputStream(filename)) {
    return ImageIO.read(in);
  }
}

画像出力

// 品質 95 Jpeg
public static void outputImage(String filename, BufferedImage image) throws IOException {
  JPEGImageWriteParam param = new JPEGImageWriteParam(Locale.getDefault());
  param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
  param.setCompressionQuality(0.95f);

  ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
  writer.setOutput(ImageIO.createImageOutputStream(new File(filename)));
  writer.write(null, new IIOImage(image, null, null), param);
  writer.dispose();
}
の 2 つを用意。

縮小処理は、2 パターン。

パターン1 BufferedImage#getScaledInstance() を使用

public static BufferedImage reduce1(BufferedImage image, int dw, int dh) {
  BufferedImage thumb = new BufferedImage(dw, dh, image.getType());
  thumb.getGraphics().drawImage(image.getScaledInstance(dw, dh, Image.SCALE_AREA_AVERAGING), 0, 0, dw, dh, null);
  return thumb;
}

パターン 2 Graphics2D#drawImage() を使用

public static BufferedImage reduce2(BufferedImage image, int dw, int dh) {
  BufferedImage thumb = new BufferedImage(dw, dh, image.getType());
  Graphics2D g2d = thumb.createGraphics();
  g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
  g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
  g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
  g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
  g2d.drawImage(image, 0, 0, dw, dh, null);
  return thumb;
}

パターン1、パターン2 をそれぞれ呼び出し

try {
  BufferedImage base = loadImage("base.jpg");
  int dw = 120, dh= 90;

  long start1_1 = System.currentTimeMillis();
  BufferedImage reduce1_1 = reduce1(base, dw, dh);
  System.out.println("reduce1_1: " + (System.currentTimeMillis() - start1_1));
  outputImage("reduce1_1.jpg", reduce1_1);

  long start2_1 = System.currentTimeMillis();
  BufferedImage reduce2_1 = reduce2(base, dw, dh);
  System.out.println("reduce2_1: " + (System.currentTimeMillis() - start2_1));
  outputImage("reduce2_1.jpg", reduce2_1);
} catch (Exception e) { e.printStackTrace(); } 

パターン1はぼやけた感じ、パターン2はざらついた感じ。
連続で 4 回実行し、1 回目を除いた 3 回の平均時間を計測。
速度はパターン2が早いが、今回は作成した画像をキャッシュするので速度より画質。

パターン1:  80.3ms


パターン2: 0.7ms


段階的に縮小

近傍縮小法だと、大きな画像から一気に縮小すると色情報の欠落が大きくなるので、段階的に縮小してみる。
  • 1024x768 -> 640x480 -> 120x90 の 2 段階
  • 1024x768 -> 800x600 -> 480x360 -> 120x90 の 3 段階
の 2 つそれぞれのパターンで実行。
int dw2_1 = 640, dh2_1 = 480;
int dw3_1 = 800, dh3_1 = 600, dw3_2 = 480, dh3_2 = 360;

long start1_2 = System.currentTimeMillis();
outputImage("reduce1_2.jpg", reduce1(reduce1(base, dw2_1, dh2_1), dw, dh));
System.out.println("reduce1_2: " + (System.currentTimeMillis() - start1_2));

long start2_2 = System.currentTimeMillis();
outputImage("reduce2_2.jpg", reduce2(reduce2(base, dw2_1, dh2_1), dw, dh));
System.out.println("reduce2_2: " + (System.currentTimeMillis() - start2_2));

long start1_3 = System.currentTimeMillis();
outputImage("reduce1_3.jpg", reduce1(reduce1(reduce1(base, dw3_1, dh3_1), dw3_2, dh3_2), dw, dh));
System.out.println("reduce1_3: " + (System.currentTimeMillis() - start1_3));

long start2_3 = System.currentTimeMillis();
outputImage("reduce2_3.jpg", reduce2(reduce2(reduce2(base, dw3_1, dh3_1), dw3_2, dh3_2), dw, dh));
System.out.println("reduce2_3: " + (System.currentTimeMillis() - start2_3));
パターン1 2段階: 141.7ms


パターン1 3段階: 215ms


パターン2 2段階: 7.3ms


パターン2 3段階: 16.3ms


多少マシになったが、ちょっと納得いかないレベル・・・
続く

2012年4月22日日曜日

Apache + Tomcat のレスポンス

ここのところ忙しく、全然更新していなかったが、実際には色々嵌りまくりな日々・・・

その中でも最近一番大きかったのが、Apache + Tomcat の構成でレスポンスがおかしい現象が発生。
しばらく使っていると、別のリクエストのレスポンスが返ってくるようになる。
別のユーザのユーザ情報が見えたり・・・セッションがおかしくなったり・・・

Apache または、Tomcat のいずれかを再起動すると普通に戻るがしばらくするとまた発生し始める
プログラムのせいではないことを祈り調査。

接続は mod_proxy_ajpを使用して mod_proxy_balancer で分散していた。
分散していないテスト環境でも発生していたため、mod_proxy_balancer は調査から除外。
mod_proxy_ajp を mod_proxy_http に変更したところ発生しなくなった。
過去に何度も Apache + Tomcat, mod_proxy_ajp 構成をやったことはあるが初めての現象。

次に、Apache 2.4 を使っていたため、2.2 にダウングレード。
mod_proxy_ajp で接続して問題は発生しなかった。

つまり、Apache 2.4 の mod_proxy_ajp が問題だったと思われる。
Apache 2.4 は今回初めて使用したが、まだ早かったんだろうか・・・

2012年2月12日日曜日

Pacemaker で仮想 IP の切り替え

Pacemaker でまず仮想 IP の切り替えを行う時に嵌まったこと。

OS は CentOS 5.7 でやってみる。インストールは、LINUX-HA JAPAN より、ローカルリポジトリ + yum を使用。

クラスタ制御部には、Corosync を使用することにする。
/etc/corosync/corosync.conf を作成。
# Please read the corosync.conf.5 manual page
compatibility: whitetank

aisexec {
        user: root
        group: root
}

service {
    name: pacemaker
    ver: 0
    use_mgmtd: yes
}

totem {
    version: 2
    secauth: off
    threads: 0
    rrp_mode: active
    clear_node_high_bit: yes
    token: 4000
    consensus: 10000
    rrp_problem_count_timeout: 3000
    interface {
        ringnumber: 0
        bindnetaddr: 192.168.234.0
        mcastaddr: 226.94.1.1
        mcastport: 5405
        ttl: 1
    }
}

logging {
    fileline: on
    to_stderr: no
    to_logfile: yes
    to_syslog: no
    logfile: /var/log/cluster/corosync.log
    debug: off
    timestamp: on
}
bindnetaddr にはインターフェースの IP でなくネットワークアドレスを指定する。
ログをファイルに出力するように指定。

/etc/init.d/corosync start で起動して、crm_mon を実行して確認する。
Attempting connection to the cluster.........................
帰ってこない・・・

一般ユーザで実行したからっぽい。グループに、haclient を追加したら帰ってきた。
============
Last updated: Sun Feb 12 00:54:09 2012
Stack: openais
Current DC: localhost.localdomain - partition WITHOUT quorum
Version: 1.0.11-1554a83db0d3c3e546cfd3aaff6af1184f79ee87
1 Nodes configured, 2 expected votes
0 Resources configured.
============

Online: [ localhost.localdomain ]

次に、 crm configure help でコマンドを確認しようとするも、
cibadmin not available, check your installation
となる、sudo でやってもダメだった。仕方ないので root になって行う。
# crm configure property no-quorum-policy="ignore" stonith-enabled="false"
# crm configure rsc_defaults resource-stickiness="INFINITY" migration-threshold="1"
# crm configure primitive vip ocf:heartbeat:IPaddr2 \
params ip="192.168.234.51" nic="eth0" cidr_netmask="24" op monitor interval="10s"
eth0 に 192.168.234.51 の仮想 IP を作成する設定。

ifconfig で確認するも設定したアドレスが見当たらない。
eth0 にはそもそも実インターフェースの IP が割当たっているからだ。
ip addr show eth0 で確認できる。
inet 192.168.234.51/24 brd 192.168.234.255 scope global secondary eth0

最初、CentOS 6 を使用して普通に yum でインストールして開始したわけだが、こっちのほうが嵌まった。
Pacemaker が 1.1 になっており、クラスタ部に heartbeat が使えなかったり、corosync.conf の service の ver を 1 にしないとだったり、vip 指定時に nic に eth0:1 などを指定すると警告が出たりとかなり面倒だった。

結局、CentOS5.7 を使うことになり、落としたわけだが・・・

2012年1月11日水曜日

SAStruts + Maven

久々、Java での Web アプリケーションを作成をすることに。
最近のフレームワークが分からないため、今更 SAStruts を選択。最近は何がメジャーなんだろうか・・・

とりあえず開発環境を最新版でそろえていく。
  • JDK 1.7.0_02
  • Maven 3.0.3
  • Eclipse 3.7 64bit(Pleiades のプラグイン + Maven プラグイン)
  • Tomcat 7.0.23 -> 6.0.35
Maven で SAStruts のプロジェクトを作成。
# mvn archetype:generate -DarchetypeRepository=https://www.seasar.org/maven/maven2/ \
  -DarchetypeGroupId=org.seasar.sastruts \
  -DarchetypeArtifactId=sa-struts-archetype -DarchetypeVersion=1.0.4-sp9.0 \
  -DgroupId=com.example.sample.sas -DartifactId=sas -Dversion=1.0.0 
Eclipse 用プロジェクト作成。
# cd sas
# mvn eclipse:eclipse -Dwtpversion=1.5
Eclise で「インポート」->「一般」->「既存プロジェクトをワークスペースへ」でインポート。が、ここで問題発生。
プロジェクトを右クリックしても Maven のメニューが出てこない・・・ Maven プラグインは入れたはずなのに。 昔はこれでいけてた気がしたが、バージョンが上がって変わったのだろうか。

色々検索したり、Maven のバージョン変えたりプラグインを再インストールしたりしてみたがうまくいかない。で、かなりして Eclipse のインポートメニューに Maven の項目を発見。
 mvn archietype:generate でプロジェクト作成後、mvn eclipse:eclipse は行わずに、Eclipse の「インポート」->「Maven」->「Existing Maven Project」でインポート。途中、「maven-antrun-plugin:1.3:run (1 errors)」 とエラーが出るがかまわず完了。これで、プロジェクトの右クリックメニューに Maven の項目が出た。

取り込み後、pom.xml に警告とエラーが出ているので潰していく。
まず、<project> タグで警告がでるため、クイック・フィックスで修正。

次に、maven-antrun-plugin の「Plugin execution not covered by lifecycle configuration: org.apache.maven.plugins:maven-antrun-plugin:1.3:run (execution: delete-lib-dir, phase: initialize)」もクイック・フィックスの「Permanently mark goal run in pom.xml as ignored in Eclipse build」で修正する。

最後の、maven-dependency-plugin の「maven-dependency-plugin (goals "copyff-dependencies", "unpack") is not supported by m2e.」は、上記修正で追加された、pluginManagement/plugins/plugin/configuration/lifecycleMappingMetadata/pluginExecutions に設定を追加する。
<pluginExecution>
  <pluginExecutionFilter>
    <groupId>
      org.apache.maven.plugins
    </groupId>
    <artifactId>
      maven-dependency-plugin
    </artifactId>
    <versionRange>[1.3,)</versionRange>
    <goals>
      <goal>copy-dependencies</goal>
    </goals>
  </pluginExecutionFilter>
  <action>
    <ignore></ignore>
  </action>
</pluginExecution>
ついでに、build/plugins/plugin/artifactId が maven-compiler-plugin の source と target を 1.7 に変更。

プロジェクトを右クリックして 「Maven」 -> 「プロジェクト構成の更新」を実行して反映すればエラーと警告が消えた。

次に、WTP の設定。
プロジェクトを右クリックしてプロパティを開き、プロジェクト・ファセットを選択。
Convert to faceted from... をクリック。動的 Web モジュールにチェックを入れて、バージョンを確認すると、3.0 になっている。SAStruts は 3.0 で動くのだろうか・・・調べてみるとどうもダメっぽいので、2.5 に変更。よって Tomcat も 6 に落とす。
プロジェクト・ファセットの設定がなぜだか、1 回目だと失敗する。2 回やると通ったのでそのまま続けることにする・・・
次に、プロパティダイアログの Deployment Assembly を選択。/WebContent の行を削除。追加をクリックして、 「フォルダー」より src/main/webapp を追加。/WebConent のディレクトリは物理的に削除して大丈夫だと思われる。さらに、追加をクリックして、「Java Build Path Entries」より Maven 依存関係を追加。

src/main/webapp/WEB-INF/web.xml のバージョンが 2.4 になっているので 2.5 に変更。
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  id="WebApp_ID" version="2.5">
dependencies/dependency の geronimo-jsp_2.0_spec を geronimo-jsp_2.1_spec に、バージョンを 1.0 から 1.0.1 に変更。
同じく、geronimo-servlet_2.4_spec を geronimo-servlet_2.5_spec に、バージョンを 1.0 から 1.2 に変更。

プロジェクトを右クリックして、「実行」->「サーバで実行」でサーバを起動すると特にエラーもなく無事起動。
だが、ブラウザで http://localhost:8080/sas/ にアクセスすると、「org.apache.jasper.JasperException: /WEB-INF/view/index.jsp(1,1) /WEB-INF/view/common/common.jsp(1,61) JARファイル "file:/ワークスペースのパス/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sas/WEB-INF/lib/standard-1.1.2.jar" からTLD "META-INF/c.tld" を読み込めません: org.apache.jasper.JasperException: TagLibraryValidatorクラスのロード又はインスタンス化に失敗しました: org.apache.taglibs.standard.tlv.JstlCoreTLV 」と 500 エラーになる。 

これも結構嵌まったが、どうも pom.xml の provided の jar を読み込んでいる模様。
WTP 実行時に、pom.xml の povided を認識しないらしい。

検索してみると m2e-wtp なるものを発見。インストールしてみる。
「ヘルプ」->「Eclipse マーケットプレース」検索してインストール。
プロジェクトを右クリックして 「Maven」 -> 「プロジェクト構成の更新」を実行後、起動すると無事「Hello!」が表示された。

プラグインをインストールしたことでかなり飛ばせる手順がありそうだが、次回もこの手順でやれば同じ結果になるだろう・・・

2012年1月3日火曜日

財布購入

革の財布が欲しかったので、財布を買うなら正月かなということで商品券もあったことだし百貨店に行って来た。

近所の、伊勢丹、日本橋の三越本店へ。さらに、銀座の松坂屋と三越に行ってみた。 長財布で小銭入れ付かラウンドファスナーのタイプが欲しくて、気になったものはいくつがあったが、これ!というものがなかったので転々と。
最後の銀座三越で気に入ったものがあったが、予算より若干オーバー。しかも、コードバンとブライドルレザーの 2 種類あって悩むことに。店員さんの説明を聞いたりして長々と考えたが、悩んでる時点で買うことはほぼ確定していたんだろう。結局コードバンを買ってしまった。

GANZO のコードバンの長財布、小銭入れ付。影が写り込んでるが・・・
色はダークブラウン。38,850円だった。

 コードバンなので硬いのは当然だけが、カードを入れるのが結構大変。カード入れ全てにカードを入れるとパンパン。完全開くにも硬いので小銭や札を出すだけでも結構厄介。 ブライドルレザーのほうが少し軟らかく、完全に開いた上にさらに反対側に開いたので扱いやすいだろうなといったところでも迷ったわけだが。
まぁなじむだろうと期待してコードバンにしてみた。使い込んでいかないと。

2011年12月21日水曜日

is_writable の実装探しの旅

pgpoolAdmin のインストール時のエラーの続き。

selinux が原因だったので、 is_writable の実装探しの旅に出ても結局分からなかったと思われる。
が、気になったので、実装探しの旅に出てみることにした。

emacs + cscope で読むことにする。
php のソースコードを展開して、cscope のファイルを作成。
$ cd php-5.3.8
$ find ./ -name "*.h" -or -name "*.c" > cscope.files
$ cscope -b -q -k
emacs で展開したディレクトリあたりを開いて、 M-x cscope-find-global-definition is_writable を実行。
まぁそう簡単には見つからない。M-x cscope-find-this-symbol is_writable でいくつか候補が。
その中でそれっぽいのが、
*** ext/standard/php_filestat.h:
<global>[39]                   PHP_FUNCTION(is_writable);
...
*** ext/standard/basic_functions.c:
ZEND_END_ARG_INFO[3194]        PHP_FE(is_writable, arginfo_is_writable)
宣言と定義っぽいのが見つかったが、マクロのようだ・・・

宣言っぽいほうを追っていくと
#define ZEND_FN(name) zif_##name
とか出てくる。zif_iswritable とか作られているのだろうか。

次に定義っぽい方を追っていくと、
const zend_function_entry basic_functions[] = { /* {{{ */
  [snip]
    PHP_FE(is_writable,       arginfo_is_writable)
となっている。
関数ポインタを持った構造体の配列?これを追うのは大変そうだ・・・そもそもの仕組み知らないし・・・呼び出し元が探せない・・・
という訳で、GDB でステップ実行してみることに。

http://d.hatena.ne.jp/anatoo/20111117/1321463886
を参考にまず、まずコンパイル。
$ ./configure --disable-all --enable-debug
$ make
でテスト用のスクリプト(~/test_is_writable.php)を作成。(前回通らないと思ってたが Web 経由だとユーザが異なっていてパーミッションの問題だったかも・・・パーミッション確認後、再度実行したらこのスクリプトは true となった)
<?php
echo is_writable('/usr/local/etc/pgpool.conf');
次に、GDB で実行。
$ gdb sapi/cli/php
(gdb) break zif_is_writable
Breakpoint 1 at 0x509b30: file /usr/local/src/php-5.3.8/ext/standard/filestat.c, line 1092.
(gdb) run ~/test_is_writable.php
後は、s と n で辿っていく。
ext/standard/filestat.c:782 の php_stat が実装のようだ。
さらに入っていくと、
eck_open_basedir_ex (path=0xb03350 "/usr/local/etc/pgpool.conf", warn=1)
    at /usr/local/src/php-5.3.8/main/fopen_wrappers.c:297

 if (PG(open_basedir) && *PG(open_basedir)) {
あたりだろうか。
PG の定義は、
# define PG(v) (core_globals.v)
extern ZEND_API struct _php_core_globals core_globals;
_php_core_globals の open_basedir が設定されているかどうかを見ているっぽい。
が、open_basedir が分からない。
ググッて見ると、php.ini にそういう項目があるようだ。
このあたりをいじればいけるかと思ったがそうでもなかった。

テストスクリプトだと true となるのでこのあたりで断念。
結局追えなかった・・・

2011年12月12日月曜日

pgpoolAdmin のインストール時のエラー

今回は、pgpoolAdmin を検証するためにインストールしていた時に嵌まったことを。

pgpoolAdmin を展開後、http://www.example.com/pgpoolAdmin/install/index.html にアクセスしてインストール作業を続けるわけだが、/usr/local/etc 以下の pgpool.conf や pcp.conf が "Write access denied" となっていて先に進めない。

ファイルのパーミッションや所有者を確認してみるが特に問題はなさそうだ。
PHP で作られているようなので中身を見てみることにした。

install/checkParameter.php 60
if (!is_writable($pgpool2_config_file)) {
  $msgPgpoolConfigFile = 'Write access denied';
  $error = TRUE;
}
となっている。

実行ユーザを調べるために
echo `id`;
を埋め込んでみるも、想定通りのユーザで動いてそうだ。

スクリプトからパーミッションを取得するために
var_dump(stat($pgpool2_config_file));
を埋め込んでみるも、
["mode"]=> int(33188)
となっており、8 進数で 100644 となり、これも問題なさそう。

is_writable のみを記述したテストプログラムを作成してみるが、この時点で false が帰る。後日、動かしてみたら true だった。おそらくこれはパーミッションだったかな・・・
これは困った。is_writable の実装を探す旅にでるしかないのかと思ったが、ふと英語が出来ないなりに「is_writable always false」でググったら一番上に出てきた。
selinux... すっかり忘れていた・・・コネクション周りなら思い出せたかもしれなかったが。

# setenforce 0
ついでに、/etc/selinux/config の SELINUX を disabled に変更。
で無事にインストールを続けることができた。

続く...

2011年12月7日水曜日

複数 FLV ファイルから DVD 作成

今回は開発以外で嵌まったことを。
知人に複数 FLV から DVD を作成したいと言われたので調査することに。これが思いのほか嵌まった・・・

そもそも、動画を変換、編集することがかなり久しぶりだった。昔は、DVD-RAM で TV 番組を録画して CM カットして DVD-R に保存なんてこともやっていたが、何年も前であまり覚えていない。
前は、DVD ドライブを買うと、動画編集ソフトやオーサリングソフトがバンドルされていたが、現在手元に何もない・・・なのでフリーソフトでやるしかない。

まず、昔の手順的なものを思い出すことに。たしか、
  1. DVD-RAM(vob たしか中身は mpeg2)に録画
  2. GOP 単位でざっくり CM カット
  3. AVI(huffyuv 可逆圧縮)変換
  4. フレーム単位で細かくカット
  5. mpeg2 に変換
  6. オーサリング
  7. DVD 焼き
みたいなことをやってたはず。途中どっかの手順で音を分離して最後に結合してたような記憶もあるが。
とりあえず、今回は編集が入らないので、
  1. FLV
  2. AVI(huffyuv)に変換
  3. オーサリング(mpeg2 に変換含む)
  4. DVD 焼き
でいけそうだ。

まず、FLV の変換だが、Any Video Converter というソフトでいけそうだ。これで AVI に変換。オーサリングは、Windows7 についてるWindows DVD メーカーを使用した。Windows DVD メーカーは ISO ファイルは作れずに一気に DVD に焼くようだ。
簡単にできたと思い、中身を確認してみると、出た!音ずれだ・・・
そういえば昔も嵌まった・・・だから音を分離して結合してなんて記憶が残ってたわけだ。ちゃんと確認してみると、AVI の時点でずれている・・・先に確認すれば 1 枚無駄にならなかったのに・・・

とりあえず Any Video Converter で変換時に音を分離することにする。で、VirtualDub で結合して AVI の時点で音があってる状態にしてみることに。
ここでさらに問題が。Any Video Converter で作成した AVI(huffyuv) が VirtualDub で開けない。VirtualDub の圧縮の選択肢の中に huffyuv があるというのに。つまりコーデックは入っているということだが。調べてみたら動画再生、作成等の API が 2 種類あるらしい。
  • Video for Windows(コーデックを使用)
  • DirectShow(フィルターを使用)
知っているのは前者のみだったわけで、そういえば ffdshow なるものも入れた気がする。Any Video Converter は両方(?)対応、VirtualDub は前者対応のようだ。
VirtualDub のプラグインで DirectShow を使用するものがあったので入れてみるがうまく認識しなかった。直接 FLV を読み込むプラグインもあるようだったがこれも読み込んでくれない。そもそも、64bit 版の VirtualDub を使っているがプラグインは 32bit 版な気がする。ソース付のもあったのでコンパイルしなおす等もしてみたが、あっているかも分からずやはり認識せず。
仕方ないので、ほかに可逆圧縮はないものかと探したところ、ffv1 とういものが共通で扱えたのでこれでやることに。
で、Any Video Converter で ffv1 を出力後、VirtualDub で読み込み、分離した音を結合した AVI を作成。作成された AVI を見てみると、音がずれている・・・
さらに確認してみると、そもそも、分離した、ffv1 の動画と wav の音の時間がずれている・・・あうわけがない・・・

VirtualDub でどうにかならないかと「オプション」->「音声に同期させる」や「遅れる場合はフレームを落とす」を選択してみたがダメだった。 「音声」->「インターリーブ」あたりを触ってもダメ。
前はどうやっていたか思い出せないが、有料のソフトがいい塩梅でやってくれてたんだろうか。とりあえずさらに調べてみることに。
すると、「映像」->「フレームレート」の「ソースレート調整」->「映像と音声の再生時間が一致するように変更する」という設定があり、これでいけた。

これで映像と音があった AVI ができたので、次は、mpeg2 変換とオーサリングだ。前回みたく失敗するたびに DVD-R が消費されると辛いので、VIDEO_TS 形式なり ISO イメージなりで出力できるアプリケーションを探すことに。mpeg2 に変換できるもの自体が少ないため、選択肢はあまりなく、その中では、メニュー等も作れる DVD forger がよさそうだったのでこれにすることに。

で、またまた問題が。DVD forger は ffv1 形式が読み込めない。かなり振り出しに戻った気分だ。だがここまできてやめるわけにもいかない。すでにかなりの時間を使っている。
Any Video Converter は他の可逆圧縮を選べない。となると、VirtualDub で音の結合をする時点で別形式に変換することに。
可逆圧縮もさほど選択肢がないわけだが、Ut Video Codec YUV が使えたのでこれにする。正直よくわかってないので、ここでも VfW と DirectShow が入り混じっているのかもしれない。

やっと、DVD forger でオーサリングすることに。とりあえずメニューは作らず。DVD forger には音ずれの設定等設定項目があまりないので mpeg2 に変換時に音がずれないでくれと願いつつ、変換 & オーサリングを実行。
確認しみると、おぉ音があってる!後は焼くだけかと、さらっと見てたら動画が途中で終わっている・・・

実は、FLV ファイルは 4 つあって、その 1 つが再生された時点で終わっていた。
ファイルは個々に変換しているので、Ut Video Codec 形式の AVI も 4 つある。それを、DVD forger に追加すると、タイトルが 4 つできる。メニューを作成して、4 つボタンをつけてみると、ボタンクリックからは再生できる。が 1 タイトル終了後メニューに戻ってしまう。次のタイトルが再生できない。見れないことはないのでいいのかも知れないが、美しくない。俺的にアウトだ。
ということで、Ifo Editor なるものを入れて、ifo ファイルを編集することに。
VIDEO_TS.IFO の「VMGM_PGCI_UT」->「LU_1 PGC-Menu_1」の Pre Command や VTS_01_0.IFO の 「VTS_PGCITI」->「VTS_PGC_1」の Pre Command や Post Command をいじってみることに。
(Jump_TT)Jump to Title や(CallSS_VMGM)Call VideoManager PGC など適当にさわってみるが再生されない。メニューにすら飛ばなくなる。PgcEdit のほうがいいという情報も見かけたので入れてみるが変わらない・・・
まったく知識なくいじっているので仕方がないといえば仕方がないが。かと言って IFO の構造を学ぶのも大変そうだ・・・が、もはや意地でやってるので、さらに調べることに。
  • http://www.geocities.jp/montty_jp/backup/index.htm
  • http://dvd.sourceforge.net/dvdinfo/vmi-jmp.html
が、詳しくて参考になった。見てるとどうも、タイトルからタイトルつまり、VTS から VTS には飛べない感じがする。できた VOB ファイルをみると、VTS_01_0.VOB, VTS_02_0.VOB となっていて、VTS_0* の時点で違いがある。これはもしや、VTS_01_0, VTS_01_1 になればいいのかと、DVD forger の設定を見直してみることに。

「Edit videos, audio tracks and subtitles...」から入ったダイアログに「Merge」なるボタンがあるのに気付く。だが押せない。動画を複数選択しても Disable のまま・・・なんのためのボタンだと思いつつ。View のラジオボタンを適当に押していると、「Outline(for re-orderring, merging and deleting titles)」を選択したときに、Enable になった。なんて使いづらいインターフェースだ。View なんて書くと見た目だけ変わるのかと思うじゃね~かと思ったが、よくみりと、ちゃんと書かれている・・・「Outline(for re-orderring, merging and deleting titles)」
英語は苦手だ・・・

とりあえず、4 つ全ての動画を選択して、Merge をクリック。
メニューのボタンが 1 つになったが問題なし。チャプタは?とも思ったが拘りだしてはキリがないし、俺的に拘るところでもないのでスルーすることに。

確認してみるとちゃんと再生された。音が短くそれにあわせた分一番最後が若干さくっと終わる感じはあるが、ご愛嬌ということで。
後は、DeepBurner で DVD に焼いて終了。焼くのはすんなりいった。

久しぶりに動画の編集をやったがやはり大変。昔に比べてマシンスペックはあがっているので、エンコード時間は短いが、それでも数十分、数時間の待ちがあるので、待ったあとダメだった場合が辛い。
まぁ昔は 30 分の動画をエンコードするのに一晩中動かしても終わってなかったりしてたわけだが。

ちなみに著作権が絡む動画は注意が必要。個人的にダウンロードして複製する分には問題なさそうだが、YouTube などはダウンロードの時点で規約違反となる。違法でなければやっていいというわけでもない。モラルの問題もある。
了承を得られている等、著作権的に問題がない動画ならいいが。
本の自炊屋が消えていったりしているので、著作権が絡む動画を今回のように人に頼まれて変換して渡すとなるとアウトな気がする。

長々と書いてて読みにくいことに気付いた。キャプチャ等を貼るべきかと思うがそれもメンドイ。無理やり文字を大きくしたりでなんとかならんかとやってみたが・・・

2011年11月30日水曜日

三角関数と微分積分

前に読んだ OpenCL のサンプルでフーリエ変換が出てきたのでもう少し詳しく知ろうと、
Excelで学ぶフーリエ変換−Excel 2010対応版−
を最近読み始めたのだが、基本知識がなさすぎて最初の時点でつまづいた。
当然、全てが理解できるとは思っていないが、フリーエ変換のの字も出る前の基本知識の説明の時点でつまづいたら先に進みようがないため調べることに。

でてきた式が

ふむふむ、なるほど、なんで?って感じ。

三角関数は、
  • しんこうこうしん
  • ここマイナスしんしん
  • しんたすしんはにしんこう
  • こうたすこうはにこしん
なんて覚えた記憶がある。でどうやって使うの?
公式の導き方も知ってたような記憶があったが、知ってたかもという記憶だけ・・・

まずは三角関数からかと、ググッて勉強。先は長い。Wikipedia に色々公式が載っていた。
まずは、ピタゴラスの定理より

この時点で悩むことになるが・・・
半径 1 の単円で角度 X の場合、x = cosX, y = sinX となり、直角三角形の斜辺の 2 乗は各辺の 2 乗の和になることから上記、式になるようだ。

次は、加法定理。
しんこうこうしん、ここマイナスしんしんは加法定理のようだ。
左辺を覚えてないと意味がなかった。
加法定理の導き方は Wikipedia に載っていた。
A(cos(-α), sin(-α)) B(cosβ, sinβ) の線分の長さから求めるものしか分からなかったが。
線分 AB の長さの 2 乗は、

途中が省かれてて、最初見たときは?だったが、
上記ピタゴラスの定理により、2 に変換されている。
また、sin(-X) = -sinX, cos(-X) = conX による変換も行われる。

次に、+α分回転させた、A'(cos(-α + α), sin(-α + α)) = (1, 0), B'(cos(β + α), sin(β + α)) を考える。
線分 A'B' の長さの 2 乗は、回転させるまえの線分 AB の長さの 2 乗に一致することにより求めるようだ。

さらに、加法定理より積和公式を求める。
  • しんたすしんはにしんこう
  • こうたすこうはにこしん
は、積和公式の変形の和積公式のようだ。
 cos の加法定理、

の2つの式を足して、

が積和公式の一つ。

ここで、α = x, β = x とすると、

となりようやく本題の式に代入可能な形になった。


1/2 は外に出せるはず。で積分だが、+1 の積分は、+x となるのはいいが、問題は cos2x の部分。
cos x であれば、sin x なわけだが・・・
で調べてみると、合成関数の積分なるものを使うっぽい。
t = 2x として、cos t とする。これを t で積分すると sin t。ただこれは t の積分なので
x でやるためには、 t を微分したものを用意して、

で割ってやると

となり、

やっと繋がった・・・
すごい遠回りをしてる気もする。意外とあっさり変換できたりして・・・

2011年11月22日火曜日

ASUS UX31E-RY128 の感想

しばらく使用してみて、(というかほとんど使用していないが・・・)気づいたこと。

タッチパッド
タッチパッドの反応が悪い時がある。いくら触っても反応しない。 いきなり不具合!?または微妙な仕様!?
かとあせったがとりあえずマニュアルを見たところ、キーボード操作中はタッチパッドの反応領域が狭くなるらしい。
つまり、キーボード操作直後は、反応領域が狭いため、一定の部分からタッチしないと反応しない。
 
「コントロールパネル」の「マウス」より設定をみたところ、範囲のサイズと中心点を設定できるようだ。
キーボード入力中にパッドに触るとクリック扱いとなって、別ウィンドウがアクティブになったりしていたので範囲を小さくした。これは便利だ!
ノートパソコンに慣れていないので最近では当然の機能なのかもしれないが・・・

また、タッチパッドの下に、左クリック、右クリック用のボタンが 2 つあるが、これを使わずともタッチパッドのジェスチャーで右クリックやドラッグ、スクロール、ズーム等の処理ができる。タッチパネルの影響なんだろうか。

キーボード
キーボードの操作感だが、普段メカニカルな感じが好きなため、ノートのキーボードはあまり好きではないが、ノートにしては結構クリック感があるほうだと思う。悪くないかと。

重量
持ち歩いた感じ、やはり本などと一緒に持ち運ぶと重い・・・クッション入りのバッグも欲しいが、それだけで 1kg とかするので迷い中。壊れては意味がないがデフォルトのケースはあるので。
電車で座れずに立ったままブラウジング等もやってみたが、立ちながらやるには大きい。腕も疲れる。
さすがにタブレットのようにはいかなかった。座れる場合は問題ないが。

解像度
解像度は結構満足できるレベル。ブラウジングやちょっとした入力なら何の問題もない。
この記事もノートでやっているがいい感じ。


現時点では、こんなもんか。もうちょっと使ってみれば色々でるかもしれないが。


ノートより通勤途中の地下鉄で WiMax が繋がらないのが痛い。駅停車時ぐらい繋がるのかと思ってたのが甘かった・・・

2011年11月14日月曜日

Jericho HTML で一部サイトが文字化け

前回のソースで一部サイトが文字化けを起こした。

Souce のコンストラクタに URLを渡した場合は、ヘッダー情報の Content-Type の charset からエンコードが取得できるかもだが(Jericho が取得しているかは未調査)、BODY 部分のストリームを渡す場合、取得出来ないため内容から自動判別すようで、そこがおかしくなっているようだった。
なので指定してやることに、
HttpClient http = new DefaultHttpClient();
HttpResponse res = http.execute(new HttpGet(URI.create("http://www.example.com")));
if (res.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
{
  LOG.error("Failed to load uri.");
  return false;
}    

InputStream in = res.getEntity().getContent();
if (res.getHeaders("Content-Encoding").length > 0 &&
  "gzip".equals(res.getHeaders("Content-Encoding")[0].getValue()))
  in = new GZIPInputStream(in);

String charset = EntityUtils.getContentCharSet(res.getEntity());

Source source = null;
if (charset != null) source = new Source(new InputStreamReader(in, charset));
else source = new Source(in);
14 行目で Content-Type の charset からエンコードを取得して、指定があれば、17 行明で明示的に指定してやることに。直接渡しているので、Shift_JIS 等で部分的に文字化けがおきそうだがとりあえず。

Source(final Reader reader) の実装が、
this(reader,(reader instanceof InputStreamReader) ? ((InputStreamReader)reader).getEncoding() : null);
となっていて、instanceof が気に入らない。Source(final Reader reader, final String encoding) が public だといいのだが。

Content-Type の charset がなければ今まで通り自動判別。

もっとスマートにいかないものか・・・

2011年11月11日金曜日

Shell から rsync

しょうもないことで嵌まったこと。

rsync を実行してバックアップする Shell ファイルを作成中のこと。exlude で除外ファイルを指定したかったわけだが・・・
CMD="rsync -avz"
echo CMD "--exclude='*.pid'" src1 dest1
echo CMD"--exclude='*.lock" src2 dest2
上記の様に普段は、まずコマンドの前に echo をつけてコマンド、引数の確認後、出力されたコマンドをコピペして実行し動作確認を取った後 echo を外して Shell の確認って手順で作成することが多い。
今回、コピペでやると --exclude で指定しているファイルが除外されるが、Shell ファイルを実行すると除外されなかった。

原因は、--exclude オプションがクウォートで囲まれてコマンドに渡されているためで、当然なわけだが、echo で出力されると文字列が展開されてクウォートが表示されない。

実際は他にもオプションや変数を渡してたりして、気づくのに結構かかってしまった。

2011年11月9日水曜日

Scala の勉強(インストール)

前にちょっと調べた程度で終わっていた Scala を勉強しなおそうかと思う今日この頃。
はっきり言って全然覚えてないので初歩からスタートすることに。

まずは環境を作るところからか。(いつものように Cygwin 上でやってみる)
  1. http://www.scala-lang.org/ の Download Scala より Windows の最新版 scala-2.9.1.final.zip をダウンロード。
  2. インストール場所へ展開。
  3. 環境変数 SCALA_HOME と PATH を設定。
とりあえずこんな感じか。

emacs 用に scala-mode も付属している。さらに ENSIME なるものもあるようなので入れてみる。
  1. ${SCALA_HOME}/misc/scala-tool-support/emacs へ移動。
  2. make ELISP_COMMAND=emacs のパス
  3. https://github.com/aemoncannon/ensime/downloads より ENSIME をダウンロード。
  4. インストール場所へ展開。
  5. .emacs あたりに設定。(yasnippet も使用)
    (when (require 'scala-mode-auto nil t)
      (add-hook 'scala-mode-hook
                '(lambda ()
                   (yas/minor-mode-on)))
      (when (require 'ensime nil t)
     (add-hook 'scala-mode-hook 'ensime-scala-mode-hook))
      )
    
eclipse プラグインも入れておきたいがこれはそのうち。

参考にするサイトとして、
あたりを調べつつやっていこうかと。
は初心者向けらしい。英語なんで少しずつだがここからやってみるか。

2011年11月3日木曜日

ノート PC 購入

やっぱりノート PC を購入。
ネットブックを買うならタブレットでもいいかと思ったが、もう少しディスプレイ等のスペックも欲しかったので、ウルトラブックなるレベルのものにしたいと。
Mac Book Air で Mac デビューするのもありかと思ったけど、結局調べてた ASUS UX31E-RY128 を買ってしまった。
とりあえず触ってみてから決めようと、発売日の今日秋葉原に行ってきた。Sofmap で展示されているのを見つけとりあえず触って見ることに。韓国版(?)が展示されていて、キーボードが違っていた。英語キーボードが良かったが、発売されているのは日本語キーボードだけだということ。
タブレットに比べるとさすがに重さは感じるが、持ち運びは楽そうな感じだった。SSD256GB 版は発売がまだだった。まぁ 128GB もあれば十分かなと。

Sofmap ヨドバシ と見て、最終的にヤマダ電機で購入。
他の店より 3000円ほど安く、WiMAX の 1 年契約でさらに 5000円引きと。WiMAX の割引はヨドバシもやってそうだったが。
カード払いだとポイント 8% になるということで、悩んでたら 10% にしてくれるということで購入することにした。

 ケースがデフォルトで付いてるのが良い。

こちらは WiMAX ルータ。
部屋での電波は怪しいかなと思ったが、電波 は 2 本立った。
家には無線ルータもスイッチもないので直接ネットに繋がるのはいいかも。

2011年11月2日水曜日

Jericho HTML で Content-Encoding が gzip なサイトのパース

Jericho HTML でパースできないサイトがあるようで、調べてみると、Content-Encoding が gzip になっていた。
元ソース。
Source source = new Source(new URL("http://www.example.com"));

Accept-Encoding からはずせばいいのかもしれないが、HttpClient も使用しているため、そちらで対応することに。
HttpClient http = new DefaultHttpClient();
HttpResponse res = http.execute(new HttpGet(URI.create("http://www.example.com")));
if (res.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
{
  LOG.error("Failed to load uri.");
  return false;
}    

InputStream in = res.getEntity().getContent();
if (res.getHeaders("Content-Encoding").length > 0 &&
  "gzip".equals(res.getHeaders("Content-Encoding")[0].getValue()))
  in = new GZIPInputStream(in);
Source source = new Source(in);
Jericho HTML だけで対処出来る方法があればいいのだが。
compress, deflate は未対応・・・

文字化けしたので、続き

2011年10月31日月曜日

ノートPC || タブレット

ノート PC またはタブレットを買おうか迷い中。
携帯はガラケーで、モバイル系一切持ってないので、何かしら欲しいかなと。
携帯で Web を見ることもなく、まったく不便を感じてないんでいらないっちゃいらないんだが・・・

勉強会とか参加したことないので、ちょっと参加してみたいなと。
で参加するならタブレットかノート PC かなと。
開発環境入れれるノート PC のほうが良さげだが。
通信に、WiMAX なりイーモバイルなりが必要になるけど。

ノートならMac Book Air サイズのやつがいい。持ち運びは軽いほうがいい。
ただ、慣れないだけかもしれないがあまり Mac が好きになれない。

11/3 に発売する、ASUS ZENBOOK が結構よさげ。
ディスプレイは、13.3 型がいいかな。ディスクは 128GB で十分な気がする。
なので UX31E-RY128

キーボードが日本語なのが問題だが・・・
売ることがあるとすれば日本語キーボードのほうがいいな。
まぁのどかとかでキーバインド変えちゃうのもありか。
のどかのライセンスも持ってないわけだが。

とりあえず実物触ってから考えよう。

ここまで迷ってると何かしら買うんだろうな・・・

2011年10月28日金曜日

オーバーライド時のアクセス修飾子変更 C++ 編

PHP 編Java 編C# 編に続き、 C++ でも検証。C++ は好きだがこれも慣れていないため、怪しいかも・・・

まず、親クラス。
class ParentClass
{
private:
  virtual void func1() { std::cout << "Parent private func1" << std::endl; }
protected:
  virtual void func2() { std::cout << "Parent protected func2" << std::endl; }
public:
  virtual void func3() { std::cout << "Parent public func3" << std::endl; }
 
public:
  virtual ~ParentClass() {}
  virtual void call()
  {
    func1();
    func2();
    func3();
  }
};
private, protected, public の 3 種類のメソッドと、それらを呼び出すメソッドを作成。

子クラス1 は public に変更。
class Child1Class : public ParentClass
{
public:
  virtual void func1() { std::cout << "Child1 private -> public func1" << std::endl; }
  virtual void func2() { std::cout << "Child1 protected -> public func2" << std::endl; }
  virtual void func3() { std::cout << "Child1 public func3" << std::endl; }
  virtual ~Child1Class() {}
};
シンタックスエラーは起きない。

子クラス2 は protected に変更。
class Child2Class : public ParentClass
{
protected:
  virtual void func1() { std::cout << "Child2 private -> protected func1" << std::endl; }
  virtual void func2() { std::cout << "Child2 protected func2" << std::endl; }
  virtual void func3() { std::cout << "Child2 protected -> protected func3" << std::endl; }
public:
  virtual ~Child2Class() {}
};
これもシンタックスエラーは起きない。

子クラス3 は private に変更。
class Child3Class : public ParentClass
{
private:
  virtual void func1() { std::cout << "Child3 private func1" << std::endl; }
  virtual void func2() { std::cout << "Child3 protected -> private func2" << std::endl; }
  virtual void func3() { std::cout << "Child3 public -> private func3" << std::endl; }
public:
  virtual ~Child3Class() {}
};
これもシンタックスエラーは起きない。

実行してみると、
ParentClass* p = new ParentClass();
p->call();
std::cout << "----------" << std::endl;
delete p;

Child1Class* c1 = new Child1Class();
c1->call();
std::cout << "----------" << std::endl;
delete c1;

Child2Class* c2 = new Child2Class();
c2->call();
std::cout << "----------" << std::endl;
delete c2;

Child3Class* c3 = new Child3Class();
c3->call();
delete c3;
結果は、
Parent private func1
Parent protected func2
Parent public func3
----------
Child1 private -> public func1
Child1 protected -> public func2
Child1 public func3
----------
Child2 private -> protected func1
Child2 protected func2
Child2 protected -> protected func3
----------
Child3 private func1
Child3 protected -> private func2
Child3 public -> private func3

全てのパターンで特に制限なく変更出来ている。
Java とかと逆の制限があったような気がするが、気のせいだったか。

何か間違っている可能性も・・・

Cygwin g++ (GCC) 4.5.3
Visual C++ 2010
でコンパイル。 いくつかの言語で試してみたものの、結果まぁ言語仕様書を読めよということで。