2012/07/29

Haskellで数あてゲームを書いてみる

言語は実際にプログラムを書いてみないと身に付かない。ということで、昔、ポケコンでよく見かけた数あてゲームをHaskellで書いてみた。
コンピュータが生成した数字をあてる。
コンピュータは、予想した数に対して
 Hit: 数字はあっているが、場所が異なる数字の数
 Blow:数字も場所もあっている数字の数
の2種類のヒントを返す

import System.Random
import Control.Monad(when)

isUsedNum :: Char->String->Int
isUsedNum _ [] = 0
isUsedNum a (x:xs)
             | a == x    = 1 + isUsedNum a xs
             | otherwise = isUsedNum a xs

countUsedNum :: String->String->Int
countUsedNum [] _ = 0
countUsedNum (x:xs) ys = isUsedNum x ys + countUsedNum xs ys

countBlow :: String->String->Int
countBlow [] _ = 0
countBlow _ [] = 0
countBlow (x:xs) (y:ys)
          | x == y    = 1 + countBlow xs ys
          | otherwise = countBlow xs ys

resultString :: String->String->(Bool, String)
resultString xs ys =
             (endFlag, show hit ++ " hit(s) "
                                ++ show blow ++ " blow(s).")
             where blow = countBlow xs ys
                   hit = countUsedNum xs ys - blow
                   endFlag = blow == 4

isSuitableNum :: String->Bool
isSuitableNum [] = True
isSuitableNum (x:xs) = isUsedNum x xs == 0 && isSuitableNum xs

checkNum :: String->IO ()
checkNum compNum = do
         putStr "Number ? "
         guessNum <- getLine
         when (not $ null guessNum) $ do
              let (flag, msg) = resultString compNum guessNum
              putStrLn msg
              when (not flag) $ checkNum compNum
         return ()

targetNum :: [Int]->String
targetNum (x:xs)
          | (isSuitableNum strX) = strX
          | otherwise            = targetNum xs
          where strX = show x

main = do
     r <- getStdRandom $ randomR (0, 99)
     let t = targetNum $ randomRs (0,9999) (mkStdGen r)
     checkNum t
     putStrLn t

乱数はすごいHaskellたのしく学ぼう! の通りにはいかなかった。パッケージングが変更になったんだそうだ。
cabal install random
としてパッケージを追加。また、使い方はRandom モジュールの使い方 : tnomuraのブログが参考になった。



2012/07/27

Mountain LionでPostfixの設定が変わった

OS Xのmail daemonはPostfixなのだが、Mountain Lionになってディレクトリがちょっと変わったようだ。Lionの時の設定のままだと、起動に失敗する。
確認すべき設定は、main.cfの2カ所。queue_directoryとdata_directoryに指定しているディレクトリがなくなっているので、Mountain Lion用の設定に変える。
queue_directory = /var/spool/postfix
data_directory = /var/lib/postfix


2012/07/15

これならすぐに実践投入できる!リーダブルコード

ちょっと話題のリーダブルコード を早速読んだ。いいよ、これ。
人によっては、この程度のことはもう実践しているというだろうけど、実践できていないコードも山のようにある訳で。ちゃんとテストコードを書いてリファクタリングするときに、この本のテクニックを使うようにすれば、次に手を入れるとき、もっとやりやすくなっているはずだ。
Eclipseでは、関数なり変数なりにマウスカーソルをあてればJava Doc形式のコメントを表示するので、コメントを付けることも多いと思う。でも、メソッドの中はどう?
コメントなしで、コードで表現しきるのがbestなんだろうけど、名前が長くなりすぎて処理の流れが追いにくくなるのは本末転倒。どういう方針で付ければよいのか、ヒントというか答えの1つがこの本には書いてある。
そうそう、メソッドというか、関数の出口(return)を1カ所にしろというのは昔むかしの授業で言われた。 流れが見にくくなるし、無駄だなぁと思いながらも、レポートや試験ではフラグを追加して逃げた。 最終的にどういうコードに落ちるかを考えたら、用が済んだらとっととreturnすべきだし、本書でもそれを勧めている。
付録には、おすすめの本がリストされている。その中の1冊、JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス は眺めたことがあるけど、やっぱり、JavaScriptは言語仕様的に大規模なソフトウェアを書くのには向いていないんじゃないかな?


2012/07/08

広告を消す!

広告を表示するために時間がかかったり、セキュリティ的に問題のある中身が表示されたりということがあったりするので、表示しないようにしてみる。
すべてを非表示にするのは難しいけど、MicroAd を無効に!! の巻を参考にして設定変更したDNSを見るように、うちのネットワーク設定を変更。
広告がFlashだとそれだけでパワー喰うから、効果あるはず。


2012/07/01

LionでPogoplugネットワークにFirewallを設定する。

WindowsについてはHiroaki's blog: Pogoplugのネットワーク設定を見直す!でFirewallを設定したので、今度はMac OSX Lionで設定する。
LionのFirewallはPF: The OpenBSD Packet Filterなので、/etc/pf.*が設定ファイル。pf.confにルールを追加する。
PogoplugはInterface xcetap0を作成するので、xcetap0に関するルールを作成する。最後に0がついているということは、環境によってはxcetap1だったりxcetap2だったりすることも考えられると。
で、ルール。詳しいことはpfのマニュアルなり設定例なりをみればよいので、省略。
頭の方にpogo_if = "xcetap0"と書いて、一番最後に

#
# PogoPlug
#
block in on $pogo_if all
block out on $pogo_if all
pass out on $pogo_if proto tcp to any port { 80, 443 } keep state
pass out on $pogo_if proto udp to any port { 3333, 4365 } keep state

を追加。3333はkeep stateじゃなくて、inもpassにした方がいいのかな?この修正したルールを読み込み直せばOK。こういったことをやろうとする人はわかっているだろうから、読み込み直す方法とか細かい話は省略。
というか、わからないまま丸写しするようなことをしてはいけない。


2012/06/25

VPN上でIPv6する

これだけIPv6と言われているにも関わらず、公衆無線LANサービスでは、IPv6 addressを配っていない。それどころか、private addressを配布してキャリアグレードNATなんてところもある。global addressが割り当てられないということは、6to4できないということだ。
文句を言っても解決しないので、なんとかする方法を考えてみる。

LionだとOCN IPv6を使おうとしても、PPPが異常終了してしまう。IPv6 addressを持っているServerとVPNを張って、そこでIPv6 over IPv4すればよいのではないか?VPNが割り当てるIPv4のアドレスが固定ではないが、DTCP (Dynamic Tunnel Configuration Protocol)を使ってIPv6トンネルを掘ればよい。
というわけで、まずdtcpcへのLionパッチ。

--- dtcpc.rb-dist 2006-01-09 03:24:01.000000000 +0900
+++ dtcpc.rb 2012-02-26 19:34:35.000000000 +0900
@@ -96,7 +96,8 @@
 TUNIF_CLONING = true
 TUNNEL_CREATE = 'ifconfig %s tunnel %s %s'
 TUNNEL_DELETE = 'ifconfig %s deletetunnel'
-ROUTE_METHOD = ROUTE_IFP
+#ROUTE_METHOD = ROUTE_IFP
+ROUTE_METHOD = ROUTE_INTERFACE
 
 def usage()
   $stderr.print "usage: #{File.basename($0)} [-cdDlnU] [-b udpport] [-i if] [-m mtu] [-p port] [-t tuntype] [-u username] [-A addr] [-R dest] [-P prefix-delegation] server\n"

これを当ててmake installする。
dtcpcは自動で動かすことにして、/usr/local/etc/dtcpc.auth を用意する。これはマニュアル通り。
launchdで自動起動させるため、/Library/LaunchDaemons にdtcpc.plistを作る。中身は
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Label</key>
 <string>dtcpc</string>
 <key>ProgramArguments</key>
 <array>
  <string>/usr/local/sbin/dtcpc</string>
  <string>-t</string>
  <string>host</string>
  <string>-u</string>
  <string>dtcpで使うユーザ名</string>
  <string>dtcpsのアドレスまたはマシン名</string>
 </array>
 <key>RunAtLoad</key>
 <true/>
 <key>ServiceDescription</key>
 <string>Turmpet Dynamic Tunnel Configuration Protocol client</string>
</dict>
</plist>

sudo launchctl load /Library/LaunchDaemons/dtcpc.plist して起動させるが、サーバー側が用意できてからにする。

で、下のようなネットワーク構成で考える。
  • 3つのサーバが同じネットワークに別々に存在している。
  • 割り当てられているIPv6 addressは/64。

DTCP Serverはマニュアル通りにセットアップする。dtcpc.plist にあるように、dtcpcはhostモードで動かすので、prefixに/64のアドレスを設定する。
dtcpcのアドレスはdtcpsが自動で割り当てる。このとき、IPv6 Gatewayから見ると、dtcpcにはDTCP Server経由となるのだが、割り当てているのは同一の/64のアドレスなので、proxy arpのように、DTCP Serverが代理で応答してくれないと、通信できない。
/64よりも大きいaddress blockが割り当てられているのであれば、別の/64アドレスを使うこともできるのだが、その手は使えない。
そこで、dtcpsが割り当てるaddressが/64の頭の方であることに注目し、IPv6 GatewayにDTCP Server経由の/96(/80でも可)のルートを追加して逃げる。routeはlongest matchなので、これでOK。DTCP ServerでRIP NGか何かを動かすのが正攻法なのだろうけど。3つがバラバラでなければもっと簡単になるんだろう。

まだまだ、IPv6で生活するには手間がかかるな。



2012/06/24

MuninでUPSを監視する

もともと電源の配線がおかしい家なので、サーバーを動かしておくためにはUPSが必須。
長らくUPSのバッテリーが切れていたのだが、さすがに今年の夏は使うことになるかと思い、交換バッテリーを購入した。 当然、監視が必要な訳で、Apcupsd, a daemon for controlling APC UPSesを使ってUSB経由でデータを取得できるようにした上で、hirose31/munin-apcupsd · GitHubMunin でグラフ化。

Muninってついに2.xが出たんだ。


2012/06/18

inline patchでLion上でのEmacsを快適にする

もともとEmacs+Wnn(Egg)という環境で育ってきたので、Lion上でもその使い勝手を再現したい。 FreeWnnという手もあるのだが、できることなら他のアプリと同じかな漢字変換を使いたい。
inline patchを使うと、ことえりやATOKを使って同じようなことができるようなので、Emacs 24でやってみた。
Emacs 24のインストールについては、 Emacs24 のインストール と新機能 : 紹介マニアを参考にした。autoconfなどの周辺ツールのバージョンで怒られたので、 Build Emacs 24.1 on Mac OS X Lion | Re: no subjectを見て、brew link autoconfとかbrew link automakeとかしてからconfigureする。
ATOKの新しい体験版がでていたので、Cocoa Emacs(Emacs23)をOS X Lion向けにフルスクリーン、インライン入力対応のパッチを当ててビルドする方法 | Oreradio.memoをまねて、
(setq default-input-method "MacOSX")
(mac-set-input-method-parameter "com.justsystems.inputmethod.atok25.Japanese" `title "漢")
を~/.emacs.d/init.elに加えてみたところ、ばっちりC−\で切り替えられるようになった。ことえりとかGoogle日本語入力でも大丈夫っぽい。


2012/06/16

Synergy復活

Windows PC(32bit Vista)とMac(Snow Leopard)を並べて使っている。マウス、キーボードを1つにするため、Synergyを使っていた。Windows PC側に繋いだマウス、キーボードでMacも操作する形。UACのダイアログは直接繋がったキーボードでしか操作できないので、WindowsをSynergy Serverにする必要があるのだ。
何となくMac側のSynergyをアップグレードしたところ、マウスは繋がるものの、キー入力は反映されないという状態になった。パケットキャプチャしてみたところ、データは流れている様子。ググってみると、このキーボードが効かないというトラブルは割とあるらしい。
で、PC側、Mac側とも、いろいろな派生バージョンを試して、なんとか動く組み合わせ発見。
PC側。素直に公式サイトの1.3.8を使用。デスクトップにショートカットを作り、ログオンしたときに自分でダブルクリックして起動させる運用にする。
Mac側。定番ソフト Synergy(SynergyKM for Leopard)、設定まとめ: メモノメモにあるように、SourceForge.net: SynergyKM - Project Web Hosting - Open Source Softwareの1.0b7を、「すべてのユーザ向け」にインストール。設定画面を開いて設定している間に、Dockのアイコンを右クリックして、ログイン時に開くように設定。Macは自動でログインするようにしてある(家だから許される)ので、これでOK。
お気に入りのキーボードで元通りどちらも操作できるようになったので、満足、満足。


bloggerをカスタムドメインで使う

Bloggerが国別ドメインへリダイレクトするようになったので、使用しているブログパーツの再設定を行う必要が出てきた。どうせ再設定するならと、bloggerを自前のドメインで使うことにした。今までのURLでアクセスしても、独自ドメインにリダイレクトされるということなので、アクセスする分には影響ないはず。

設定方法については、Bloggerでカスタムドメインを設定する方法|Nomad Worker Styleを参考に。既に持っているドメインのサブドメインとするので、zoneファイルにCNAMEレコードを追加、ghs.google.comを指すようにする。Blogger側の設定も行なって、移行完了。

ZenbackBloggerにzenbackを美しく導入する方法-swordsmithを参考にして、個別の記事のみに表示するようにする。

URL見てカウントしているブログパーツはすべてリセットになってしまったけど、アクセス元によって動作したりしなかったりということはなくなるはずだから、よしとしよう。


2012/06/11

VPNを便利にするアプリ

Hiroaki's blog: RTX1100でL2TP Serverを立てるで外からVPN経由でアクセスできるようにしたのだが、中古のせいか、接続しても1分経たずに切断されることが度々ある。切れたら自動で再接続してほしいので、scriptを書いてアプリに仕立てた。

KeepVPN by hiroaki0404はVPNの再接続を自動で行うアプリケーション。cronで処理しようとすると、VPNの設定情報にアクセスできないので、ログイン時に実行するようDockから指定する。VPNの設定自体は"ネットワーク"環境設定で行ったものを利用する。

公衆無線LANに繋がれば、勝手にVPN接続してくれるので、なかなか便利。



2012/05/06

アジャイル、アジャイル

アジャイルと騒がれている。けど、これ、あたりまえのことを言っていいることが多い。逆に言うと、今まで、あたりまえのことが通らなかった業界だったということ。
アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~は、何らかの形でソフトウェア開発にかかわる人なら、発注側、受注側関係なく、読んでおくべき1冊。
  • 仕様が全部出ているとはとても思えないんだから、どれだけ時間がかかるかなんて、わかるわけないじゃん。
  • すべての時間をこのプロジェクトに割り当てられるわけではないんだから、工数から単純に期日を決められたって…。
  • これ、そういう意図がある機能なら、あっちの機能と同じような動きにしたほうがスマートだけど、そういう仕様じゃないなぁ。
なんてことはしょっちゅうあるわけで、そういった不確定要素があるにも関わらず、「えいや」で期日やらコストやらを無理やり決めてしまうから、トラブルが発生する。 一度に全部なんて決められるわけないんだから、本当に必要なものから順番に、確実に作っていきましょう、ということだろう。
順番に、確実に作っていくということは、発注側(要望決定者側)も付き合う必要があるわけで、適当に丸投げしておしまい、なんて手抜きはできないということ。

今まで作った部分についても、これから作る部分の影響で手を入れなければいけないということは、当然、起こるわけで、だからテスト自動化やCIが重要な技法になってくる。

コンピュータリソースが劇的に安くなったんだから、プロジェクトの進め方もそれに合わせて変えていくのが当然だし、うまくいったやりかたをこうやってまとめているのだから、目を通しておくべき1冊。


2012/05/05

UIに関する本購入

UI, UXが流行り。流行りものは追いかけないと乗り遅れてしまうわけで。
iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザインは、iPhoneアプリを作る人は必読。Androidでも参考になることは多い。
About Face 3 インタラクションデザインの極意 は結構前に購入しながら、全然進んでいない一冊。ちょっと読みにくいけど、いいUI、というか、使いやすさというものには理由があるわけで。

3冊目。毛色が違うけど。


2012/04/28

テストコードはjmockitでかなり楽に書けるのでは?

既存のシステムの改修という仕事がほとんどなわけで、残念ながらテストコードのない、レガシーコードだったりすることがほとんど。
なので、レガシーコード改善ガイド (Object Oriented SELECTION)を読みなおしているのだが、ここにあるテクニック、jmockit - A developer testing toolkit for Java - Google Project Hostingを使うと、結構すんなり解決できるのでは?
jmockitの使用例って、ググってもそれほど見かけないような印象だけど、テスト対象のクラスの一部のメソッドをモックにできるので、 リファクタリングして多くのprivateなメソッドを呼び出しているような公開メソッドでも、変に悩まずに漏れのないテストパターンを用意できる。
テストコードの作成を嫌がる人は未だに多いため、テストコードの作成に手間取ると、変にバッシングされたり、コーディング能力を低く見られたりすることもある。だから、すんなりテストを書けるフレームワークを使いたいし、いろいろな使用例があれば、尚良い。
まぁ、そもそも未だにテストコードを否定するような職場にいるようであれば、レガシーなエンジニアになってしまわないよう、次の手を考える必要があるよね。


2012/03/31

Androidでhttp通信するアプリをJunitでテストする

テストプログラムが流行り。というか、複雑になったソフトをexcelシートにまとめた条件入れてポチポチこなしていくのは限界なので、当然の流れ。 なので、AndroidのアプリもJUnitでテストしてみる。

android.jarがclasspathに含まれていると動かない、というのはあちこちで見かける通りなのだが、android.jarを除いたら、通信で使っているhttpclientのライブラリが見つからないとのエラー。 2010-08-24 - にゃんだふる日記によると、android SDKで使用しているのはApache HttpClient 4.0beta1相当らしい。ので、Index of /dist/httpcomponents/httpclient/binaryからhttpcomponents-client-4.0-beta1-bin-with-dependenciesをダウンロード、libディレクトリを丸ごとTestプロジェクトにコピー。srcディレクトリとlibディレクトリが同じ階層に並ぶようにする。
これらのライブラリは、JUnitでテストするときだけ必要なので、テストプロジェクトのライブラリには加えないでおく。 Eclipseから実行するときの設定で、クラスパスにこれらのライブラリを外部Jarとして加えればよい。


2012/03/11

RTX1100でL2TP Serverを立てる

RT107e/RTX1100/RTX1500 ファームウェア公開-Rev.8.03.92 | ヤマハの音とネットワーク製品を語るで、 RTX1100でもL2TP Serverがサポートされるようになった。古い機種でもちゃんとメンテナンスされるどころか、機能追加も行われるから、Yamaha Routerはいいよね。
設定については、ドキュメント L2TP/IPsec を見ればOK!なのだが、注意点。IPsecのpolicyで暗号アルゴリズムと認証アルゴリズムを選ぶ時、何でもいいというわけではないようだ。まぁ、接続してくるクライアント側と同じにしないと通信できないのだが。あと、コマンドラインのヘルプだとアルゴリズムが1個しか表示されないが、暗号と認証の2つを指定する必要がある。1個しか指定していなくてもエラーにならなかったけど、接続時のpolicyの調整が失敗する。


2012/03/10

バックアップのタイミングを調整する

便利なTime Machineではあるものの、バックアップ中はやっぱりCPUやネットワークのリソースを使うので、実施タイミングを調整したい。
ということで、
の2つが見つかった。
平日は帰宅してから寝るまで、土日は朝から寝るまで、バックアップはしないようにすると、逆に、バックアップする時間は
  • 平日は昼間と深夜
  • 土日は深夜
ということになる。
どちらを使っても設定パターンは多くなる。また、バックアップ開始時間を調整するだけなので、夕方にスタートしたバックアップが夜になっても終わっていない、ということが起こる。
ま、しばらく使ってみてから判断しよう。


2012/03/06

Windows8を入れてみた

Consumer Preview版ということで、まだしろーとさんお断り、検証用途のみという状態だけど、仮想環境を作って入れてみた。
HostはMacBook Air上のVirtualBox。設定は




画面は、[Windows 8] VirtualBox(Windows 8のVM)に解像度追加に従うと、幸せになれる。


2012/03/03

CloudCoreでIPv6を使う

CloudCore(クラウドコア)|KDDIウェブコミュニケーションズ。 破格の値段なので、申し込んだ。64bit版CentOS 5.7。監視はいつものようにMunin。IPv6は必要なので、6to4で。
下記のページを参考に。
そして、muninのpluginの1つであるmultipingで各サイトまでの時間を定期的に測定する。6to4のgatewayが混んでいるのか、munin nodeへのアクセスの度にエラーメールがポロポロ飛んできて鬱陶しいので、パラメータを調整。/etc/munin/plugin-conf.d/munin-nodeに
[multiping]
env.ping /bin/ping6
env.ping_args -c 1 -W 1
env.host ipv6.google.co.jp aaa bbb
env.names Google aaa bbb
と記述することで、タイムアウト待ちで他のpluginも道連れ、という事態を防止。もうIPv6のアドレスはデフォルトで割り当ててもいいと思うけどなぁ。わざわざサーバーを借りようとする人を相手にしているんだから。



2012/02/25

Time Machineが止まるのはSpotlightのせい?

Time MachineでNetwork上のサーバにバックアップをとるよう設定していると、時々、ネットワークをデータが全然流れていないことがある。
アプリケーション→ユーティリティ→コンソール.app を開いて、system.log を確認。すると、
Waiting for Spotlight to finish indexing ... とあった。Spotlightのインデックスを作るので、バックアップが止まっていると。
ググってみると、OS X Lion: Disable Spotlight Indexingというページ。mdutilコマンドでコントロールできるらしいので、ターミナルでmanして確認。

mdutil -saで現在の設定状況を確認すると、Time Machineのディスクだけではなく、そこのBackups.backupdbに対しても設定されている。インデックスの対象外にするには、これも指定する必要があると。
sudo mdutil -i off バックアップディスク/Backups.backupdbとして、しばらく様子見。当然のことながら、バックアップディスクの名前にスペースが入っていたら、'バックアップディスク/Backups.backupdb'とすること。