2011年5月31日火曜日

ボーカロイドをTTSとして活用するには?

ニコニコ動画にて、
ボーカロイドの読み上げはゆっくりの1000倍大変だという話を聞きました。

つまりボーカロイドの読み上げ難度がゆっくり並になると、
ニコニコ動画はもっと面白くなりそうです。

では具体的にはどうすれば実現できるでしょうか?

google先生から色々ご指導を受けた結果、

「SofTalk → SAPI → *自作の*SAPIエンジン → ボーカロイド」

という構成が一番近道じゃないでしょうか?
という結論が出ました。

つまりSofTalkの音声にボーカロイドが追加されるイメージです。
これは流行る!(*´ω`*)

突破しないといけない点は主に2点、

  • SofTalkが自作のSAPIエンジンを認識してくれるか?
  • ボーカロイドがコマンドやAPIで実行できるのか?
あたりかな?

とりあえずダミーのSAPIエンジンを作ってSofTalkを起動させてみるのと、
初音ミクを購入するのが次のアクションか~

帰りにヨドバシに行くか~の

追記:次回へ続く

思えば遠くに…でもないか

アクセスカウンタが500を突破しました。
何の宣伝もしてないこのブログとしては健闘しているような気がします。

リアル世界の人にも一切紹介してないですしね。
(いや、する予定だけどすっかり忘れていた…)

次の目標は1000ですが、
せめて半分くらいの期間で達成したいものです。

2011年5月30日月曜日

Wiresharkで自端末へのパケットをキャプチャする為のスクリプト

前からの続きです。

Wiresharkは自分自身へのパケットはキャプチャーできないわけですが、
方法はあります。

ふりっつさんのブログにて分かりやすく解説されています。
【ネットワーク】Wiresharkで自端末へのパケットをキャプチャする方法

ということなので、スクリプト化してみましょう。
ちなみにHey, Scripting Guy!の助力を得て作成しています。

あ、動かすにはMACアドレス入れないとダメなんでよろしく。

' 変数宣言の強制
Option Explicit

'--- 定数一覧 ---

' MACアドレス(“ipconfig /all”でコピー&ペーストしてください。)
Dim strMACAddress
strMACAddress = "XX-XX-XX-XX-XX-XX"

' コンピューター名
Dim strComputer
strComputer = "."



'--- 処理の開始 ---

' WMIサービスからネットワーク接続設定を検索します
' このとき、MACアドレスはコロン区切りに置換して検索する必要があります
Dim colItems
Set colItems = GetObject("winmgmts:\\" & strComputer & "\root\cimv2").ExecQuery( _
 "SELECT * " & _ 
 "FROM Win32_NetworkAdapterConfiguration " & _
 "WHERE IPEnabled = True " & _
 "AND MACAddress = '" & UCase(Replace(strMACAddress, "-", ":")) + "'")

' コマンドを実行するためのオブジェクトを取得
Dim objShell
Set objShell = CreateObject("Wscript.Shell")

' 多分0~1ですが、検索結果分ループします
Dim objItem
For Each objItem In colItems

 ' IPアドレス分ループします
 Dim objAddress
 For Each objAddress In objItem.IPAddress

  ' ARPテーブルに対象のIPアドレスが存在するかチェックします
  ' このときDOS窓がちらっと開きます
  Dim objExec
  Set objExec = objShell.Exec("arp -a")
  Dim flgAlreadyRegist
  flgAlreadyRegist = False
  Do Until objExec.StdOut.AtEndOfStream 
   Dim strLine
   strLine = objExec.StdOut.ReadLine
   If InStr(strLine, LCase(strMACAddress)) <> 0 Then
    flgAlreadyRegist = True
   End If
  Loop

  ' ARPテーブルにIPアドレスが未存在なら登録、存在していたら削除を行います
  ' 同時にルーティングテーブルも操作しておきます
  If Not flgAlreadyRegist Then
   If msgbox("[" _
      & objAddress _
      & "]をルーティングテーブルに登録しますか?", _
     vbOKCancel, _
     "確認") = vbOK Then
    objShell.Run "arp -s " _
     & objAddress _
     & " " _
     & strMACAddress, 0, False
    objShell.Run "route ADD " _
     & objAddress _
     & " mask 255.255.255.255 " _
     & objAddress, 0, False
    Wscript.Echo "[" _
     & objAddress _
     & "]をルーティングテーブルに登録しました。"
   End If
  Else
   If msgbox("[" _
      & objAddress _
      & "]をルーティングテーブルから削除しますか?", _
     vbOKCancel, _
     "確認") = vbOK Then
    objShell.Run "route DELETE " & objAddress, 0, False
    objShell.Run "arp -d " & objAddress, 0, False
    Wscript.Echo "[" _
     & objAddress _
     & "]をルーティングテーブルから削除しました。"
   End If
  End If

 Next

Next
う~ん、google-code-pretifyには辛かったか~、
まあしゃあない。

2014/11/06 追記:
ARPテーブルをこねこねするのは、たぶん管理者権限が必要です。
このスクリプトではARPでエラーが発生しても無視しますのでご注意ください。
エラーチェックするように修正するのは君だ!

2011年5月27日金曜日

Wiresharkを使う

WiresharkでSIPの動きを見ようと思ったら、
(当たり前だけど)ローカル内の通信が見れなかった。


というわけでローカルのルーティングテーブルをいじったんだけど、
今度はプロキシ絡みで何か上手く動作しないっぽい…

ICMPが通ってHTTPが通らないから…そうだよなぁ?

まあそれでも有用なので、
MACアドレスから切り替えが可能なスクリプトでも組むかね?

追記:スクリプト化しました

2011年5月26日木曜日

ハンドルネームの由来

自分は“Bladean Mericle”というハンドルネームを使っています。
まあこれはアナグラムでして、“enabled miracle”という意味を込めています。

直訳すると“奇跡を可能にした”です。

過去形なのにあまり深い意味はなく、
単純に“d”が欲しかったからというくだらなさ。
まあ本当に奇跡を可能にする意気込みを感じられていいでしょうか?

ちなみに奇跡=魔法ということでこのブログのサブタイトルを付けています。

つまりですね、

  • すごい人たちと仲良くなる
  • すごい人たちとすごいモノを創る
  • すごいモノを広める
という指針を持とうというわけです。

すごいモノはソフトウェアである必要はないですが…
職業的にはソフトウェアになるんでしょう。

まだな~んにもできていませんが、
日進月歩、少しずつ頑張っていきたいです。

2011年5月25日水曜日

Twitterをやるか否か

自分はTwitterに参加していません。

つぶやきはそこら辺の雑談と変わらないからです。
通りすがりにちょっと小耳に挟むような感じでしょうか。

即時性の高い情報には有効なんですが、
論文的な情報には不向きっていうのがあります。

そして欲しい情報の9割以上が論文側にある身としては、
どうしても優先度が下がってしまうわけです。

友人の近況が知りたいって?
いや、そこまで頻繁に知りたくないっす…

これが聞き取る側の理由です。



次はつぶやく側の理由です。

そりゃ世の中に言いたいことはたくさんありますが、
やっぱり論文形式なので却下です。

おっと、日常的なことを聞いて欲しい趣味はないですよ。

次に宣伝的な使い方ですが…
RSSの方がいいじゃないんですかねぇ?

ボットのつぶやきを聞くって言っても…すぐに飽きません?

あるとしたら1時間単位で更新があるような場合ですが…
今のところそんなサービスはありません。

つまり今はつぶやくことがないっと。



何だかんだと変なこと書いてますが、
ようするに過度なつながりはいらないのです。

つながるタイミングは、
自分で決めたいんです。

そうしないと疲れますから。

2011年5月24日火曜日

新人プログラマー研修の範囲

新入社員の方と(自分だけノンアルコールで)飲む機会があったので、
新人研修について思いを馳せることにしました。

最近のIT系新人研修なら、
プログラミング入門(おおよそJava)とネットワーク入門、
後は汎用的なビジネスマナーってところでしょうか?

絵描きに例えると、
筆とパレットの使い方を教わるレベルと言えます。
(例えるとひどいな…)

当たり前ですがこんなレベルなら大体の人が通過します。
でも絵の描き方は知りません。
これがヤシガニ作画を大量に生み出す人たちなわけなんです。
(意味が分からない人はgoogle先生に聞いてください。)

数年後…まだ大半がヤシガニ作画です。
(だってOJTしてもその人達がヤシガニ作画ですから。)

10年後…それでも多くがヤシガニ作画です。
(さすがに絵を教える人なんてもういないですから。)


え?絵が上手くなった人はどうしたかって?
仕事が集中して病院送りになりましたけど?
もしくは他の会社に転職しましたね。

つまりは、そんなにこの研修は役に立つ?って言いたいわけです。



…もっとコミュニケーションを養えばいいって声が聞こえてきました。
しかしコミュニケーション能力は、
(プログラマーでは)複数人開発にて伝達ロスを無くすための技能です。

100技術 × コミュニケーション30% = 30成果
1技術 × コミュニケーション90% = 0.9成果
(100倍差は言い過ぎ?
いやいや、参照も分からないJavaプログラマーはそれくらいでは?
それでも気に入らない方は10倍差でどうぞ♪)

確かにコミュニケーション能力はある程度必要ですけど、
技術を上げないと本末転倒ですね…

あ、マネージャークラスはちゃんと必要ですよ?
それだけじゃ雇いませんわれないと思いますけど。



さてさて、新人研修で何の範囲を教えたら良いものでしょうか。
自分ならチーム開発のスキルを研修に入れたいものです。
個人開発だと身につかないことが多い要素ですし。

レベルが高すぎる?
ご安心を、コーディング規約とソース管理とバグ管理についてちょっと実践するだけです。
あ、デイリービルドも入れないといけませんね。

基礎は最初の一週間で教えて、
後は小さな仮想プロジェクトで実践させましょう。
(自分なら本当のプロジェクトにするでしょうけど。)
これなら簡単でしょ?



…ま さ か うちでヤシガニ作画を描く新人を雇ったわけではないですよね?

2011年5月23日月曜日

インターネット日付フォーマット

JavaがRFC3339に対応していないらしいので、
適当に作ってみました。

よくよく考えるとSimpleDateFormatに大部分をまかせてもよかった気がしますが、
頭のエクササイズだと思ってスルーすることにしました。

今回のはま~ったく自信がないので、
流用される方はよくテストしてください。

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * RFC3339に準拠した日付フォーマットです.
 * 例:"1937-01-01T12:00:27.87+00:20"
 * 速度はあまり重視していません.
 * @version 1.14
 * @author Bladean Mericle
 */
public class InternetDateFormat extends DateFormat {

 /** 自動生成されたserialVersionUID. */
 private static final long serialVersionUID = -3948472717995863848L;

 /** タイムゾーンオフセット. */
 protected boolean zoneOffsetFlagField = true;

 /** 秒数の小数点以下桁. */
 protected int fractionalSecondsLengthField = 0;

 /**
  * デフォルトコンストラクタ.
  * タイムゾーンオフセットは出力し、秒数の小数点以下は出力しません.
  */
 public InternetDateFormat() {
     super();
     setCalendar(Calendar.getInstance());
     setNumberFormat(NumberFormat.getInstance());
 }

 /**
  * コンストラクタ.
  * @param zone タイムゾーン
  * @param aLocale ロケール
  */
 public InternetDateFormat(TimeZone zone, Locale aLocale)  {
     super();
     setCalendar(Calendar.getInstance(zone, aLocale));
     setNumberFormat(NumberFormat.getInstance(aLocale));
 }

 /**
  * コンストラクタ.
  * @param zoneOffsetFlag タイムゾーンオフセット出力フラグ
  * @param fractionalSecondsLength 秒数の小数点以下の桁(0~3)
  */
 public InternetDateFormat(
         boolean zoneOffsetFlag,
         int fractionalSecondsLength)  {
     this();
     setZoneOffset(zoneOffsetFlag);
     setFractionalSecondsLength(fractionalSecondsLength);
 }

 /**
  * コンストラクタ.
  * @param zone タイムゾーン
  * @param aLocale ロケール
  * @param zoneOffsetFlag タイムゾーンオフセット出力フラグ
  * @param fractionalSecondsLength 秒数の小数点以下の桁(0~3)
  */
 public InternetDateFormat(
         TimeZone zone,
         Locale aLocale,
         boolean zoneOffsetFlag,
         int fractionalSecondsLength)  {
     this(zone, aLocale);
     setZoneOffset(zoneOffsetFlag);
     setFractionalSecondsLength(fractionalSecondsLength);
 }

 /**
  * タイムゾーンオフセットを詳細に出力するかを取得します.
  * この値はフォーマット時にのみ適用されます.
  * 解析時には適用されません.
  * @return trueの場合、詳細に出力する
  */
 public boolean hasZoneOffset() {
     return zoneOffsetFlagField;
 }

 /**
  * タイムゾーンオフセットを詳細に出力するかを設定します.
  * この値はフォーマット時にのみ適用されます.
  * 解析時には適用されません.
  * @param zoneOffsetFlag trueの場合、詳細に出力する
  */
 public void setZoneOffset(boolean zoneOffsetFlag) {
     zoneOffsetFlagField = zoneOffsetFlag;
 }

 /**
  * 秒数を小数点以下第何位まで出力するかを取得します.
  * この値はフォーマット時にのみ適用されます.
  * 解析時には適用されません.
  * @return 秒数の小数点以下の桁(0~3)
  */
 public int getFractionalSecondsLength() {
     return fractionalSecondsLengthField;
 }

 /**
  * 秒数を小数点以下第何位まで出力するかを設定します.
  * この値は0~3までしか設定できません.
  * その範囲を超えた場合は、IllegalArgumentExceptionが発生します.
  * この値はフォーマット時にのみ適用されます.
  * 解析時には適用されません.
  * @param fractionalSecondsLength 秒数の小数点以下の桁(0~3)
  */
 public void setFractionalSecondsLength(int fractionalSecondsLength) {
     if (fractionalSecondsLength < 0 || 3 < fractionalSecondsLength) {
         throw new IllegalArgumentException(
                 "Invalid fractional seconds length(" + fractionalSecondsLength + ")");
     }
     fractionalSecondsLengthField = fractionalSecondsLength;
 }

 /**
  * 日付からフォーマット文字列を取得します.
  * @param date 日付
  * @param toAppendTo 文字列を追記するバッファ
  * @param fieldPosition 使用していません
  */
 @Override
 public StringBuffer format(
         Date date,
         StringBuffer toAppendTo,
         FieldPosition fieldPosition) {
     Calendar calendar = (Calendar) getCalendar().clone();
     calendar.setTime(date);
     if (hasZoneOffset()) {
         int offset = calendar.get(Calendar.ZONE_OFFSET);
         toAppendTo.append(String.format(
                 "%1$tFT%1$tH:%1$tM:%1$tS", calendar.getTime()));
         toAppendTo.append(getFractionalSeconds(calendar));
         toAppendTo.append((offset >= 0) ? "+" : "-");
         toAppendTo.append(String.format(
                 "%1$02d:%2$02d",
                 offset / 3600000,
                 offset % 3600000 / 1000));
     } else {
         // タイムゾーンオフセットの補正
         calendar.add(Calendar.MILLISECOND, -calendar.get(Calendar.ZONE_OFFSET));
         toAppendTo.append(String.format(
                 "%1$tFT%1$tH:%1$tM:%1$tS", calendar.getTime()));
         toAppendTo.append(getFractionalSeconds(calendar));
         toAppendTo.append("Z");
     }
     return toAppendTo;
 }

 /**
  * 秒数の小数点以下をドット付き文字列で取得します.
  * 例えば10.527秒であれば、".527"や".5"のような結果となります.
  * 桁数を0に設定していた場合は、空文字列を返します.
  * @param calendar 日時
  * @return 秒数の小数点以下
  */
 protected String getFractionalSeconds(Calendar calendar) {
     if (getFractionalSecondsLength() == 0) { return ""; }
     return "." + String.format(
             "%03d",
             calendar.get(Calendar.MILLISECOND)).substring(
                     0,
                     getFractionalSecondsLength());
 }

 /**
  * 文字列を解析し、日付を取得します.
  * @param source 解析する文字列
  * @param pos 解析位置情報
  */
 @Override
 public Date parse(String source, ParsePosition pos) {
     try {
         Calendar calendar = (Calendar) getCalendar().clone();
         calendar.set(Calendar.YEAR, parseNumber(source, pos, 4));
         checkSeparator(source, pos, "-");
         calendar.set(Calendar.MONTH, parseNumber(source, pos, 2) - 1);
         checkSeparator(source, pos, "-");
         calendar.set(Calendar.DAY_OF_MONTH, parseNumber(source, pos, 2));
         checkSeparator(source, pos, "T");
         calendar.set(Calendar.HOUR_OF_DAY, parseNumber(source, pos, 2));
         checkSeparator(source, pos, ":");
         calendar.set(Calendar.MINUTE, parseNumber(source, pos, 2));
         checkSeparator(source, pos, ":");
         calendar.set(Calendar.SECOND, parseNumber(source, pos, 2));
         if (source.substring(pos.getIndex()).startsWith(".")) {
             pos.setIndex(pos.getIndex() + 1);
             calendar.set(Calendar.MILLISECOND, parseFractionalSeconds(source, pos));
         } else {
             parseCalendar.set(Calendar.MILLISECOND, 0);
         }
         String next = source.substring(pos.getIndex());
         if (next.equals("Z")) {
             pos.setIndex(pos.getIndex() + 1);
             calendar.set(Calendar.ZONE_OFFSET, 0); // 省略時は00:00と等価
             return calendar.getTime();
         } else if (next.startsWith("+")) {
             pos.setIndex(pos.getIndex() + 1);
             calendar.set(Calendar.ZONE_OFFSET, parseZoneOffset(source, pos));
             return calendar.getTime();
         } else if (next.startsWith("-")) {
             pos.setIndex(pos.getIndex() + 1);
             calendar.set(Calendar.ZONE_OFFSET, -parseZoneOffset(source, pos));
             return calendar.getTime();
         }
         pos.setErrorIndex(pos.getIndex());
         return null;
     } catch (IndexOutOfBoundsException e) {
         pos.setErrorIndex(pos.getIndex());
         return null;
     }
 }

 /**
  * 文字列を解析し、数値を取得します.
  * @param source 解析する文字列
  * @param pos 解析位置情報
  * @param length 解析する長さ
  * @return 解析した数値
  */
 protected int parseNumber(
         String source,
         ParsePosition pos,
         int length) {
     int index = pos.getIndex();
     int number = Integer.parseInt(source.substring(index, index + length));
     pos.setIndex(index + length);
     return number;
 }

 /**
  * 文字列を解析し、セパレーターが正しいかチェックします.
  * セパレーターが不正な場合、IndexOutOfBoundsExceptionがスローされます.
  * @param source 解析する文字列
  * @param pos 解析位置情報
  * @param separator セパレーター
  */
 protected void checkSeparator(
         String source,
         ParsePosition pos,
         String separator) {
     int index = pos.getIndex();
     int length = separator.length();
     if (!source.substring(index, index + length).equals(separator)) {
         throw new IndexOutOfBoundsException();
     }
     pos.setIndex(index + length);
 }

 /**
  * 文字列を解析し、秒数の小数点以下を取得します.
  * @param source 解析する文字列
  * @param pos 解析位置情報
  * @return 秒数の小数点以下
  */
 protected int parseFractionalSeconds(String source, ParsePosition pos) {
     String milliSecond = source.substring(pos.getIndex()).split("\\D")[0];
     int number = Integer.parseInt((milliSecond + "000").substring(0, 3));
     pos.setIndex(pos.getIndex() + milliSecond.length());
     return number;
 }

 /**
  * 文字列を解析し、タイムゾーンオフセットを取得します.
  * 書式は"HH:mm"で、正負は既に解析されたものとしています.
  * @param source 解析する文字列
  * @param pos 解析位置情報
  * @return タイムゾーンオフセット(絶対値)
  */
 protected int parseZoneOffset(
         String source,
         ParsePosition pos) {
     int hour = parseNumber(source, pos, 2);
     checkSeparator(source, pos, ":");
     int minute = parseNumber(source, pos, 2);
     return (hour * 60 + minute) * 60000;
 }
}

2011/11/24追記:バグを見つけたので修正しました。タイムゾーン省略時はローカル時じゃなく標準時なのね…
2013/06/26追記:一箇所セペレーターだったので慌てて修正
2013/07/17追記:英語版にしてみました。
2013/12/16追記:ミリ秒のパースに問題があったので慌てて修正。英語版との名前の差異は…もうめどいからいいや。
2017/09/18追記:パースのバグを直しました。コメントくれた方ありがとう!

2011年5月20日金曜日

歩数計の精度

スマートフォンに歩数計が入っていたので有効にしてみました。

ここ3日での測定結果は、
いずれも8000歩オーバーという結果でした。

こんなに歩いているか~?と疑問になり、
腕を固定してモニターを見ながら歩いてみましたが、
おおよそ正しいように…見えました。

かといって電車とかで誤反応しているような履歴でもないですし…
これは信じていいのでしょうかねぇ?

2011年5月19日木曜日

リトライ回数という罠

プログラムを組んでいると、
リトライ回数という値を設定することが良くあります。

しかしこのリトライ回数というものは、
意外と認識がずれる厄介ものなのです。

例えば必ず処理が失敗するようにした場合、
リトライ回数によって何回処理が実行されるのかを考えてみます。


  • 自分の場合
    リトライ回数=0 … 1回 意味:リトライしないで終了する
    リトライ回数=1 … 2回
    リトライ回数=5 … 6回
  • ある人の場合
    リトライ回数=0 … 考えていない
    リトライ回数=1 … 1回
    リトライ回数=5 … 5回 意味:リトライ回数分処理する?


これ…どっちが多数派なんだろう…
うぅ、自分が正しいと信じたいよ…(泣)

2011年5月18日水曜日

ゴールデンウィークという名の敗戦

今年のゴールデンウィークは、
完全に体調不良のみで潰してしまいました…

ひどい頭痛で何か行動すると痛みが増すというひどいものでした。

ゴールデンウィーク終了直前に治り、
正直ブルーとしか言いようがありません。

風邪というには何か違うような…
一体なんだったんでしょうかね?

まあ、調べたりはしないですけど。

…何が言いたいかというと、
休日に体調が悪くなるタイプの人間って本当に損ですよね。

2011年5月17日火曜日

“プログラマの権利宣言”を考える

たまには真面目な話題にするか~ということで、
プログラマの権利宣言について考えてみることにしました。

Jeff Atwoodさんが提唱したもので、
青木靖さんが日本語訳を行って公開されています。
プログラマの権利宣言

  1. すべてのプログラマは2つのモニタを持つ権利を有する
    自分はよくプリンタホルダーをモニターの横に配置しています。
    まあこれがあると、設計書を見ながらコーディングしやすいわけです。
    しかし所詮は紙なので、ページをめくるのが面倒でしょうがないです。
    きっとデュアルモニターならさらに効率が上がるのかもしれません。

  2. すべてのプログラマは高性能なPCを持つべきである
    一昔前、カーネルコンパイルに1日かかったという話をよく聞きました。
    自分の適当なプログラムでも、分単位でかかることがしばしばありました。
    今はどうでしょう?
    行変更ごとにコンパイルが走るのすら一般的になっています。
    エラーのフィードバックは瞬時に行われ、
    後からまとめてコンパイルするよりもはるかに修正しやすいです。
    これは単純な時間短縮以上の効果を持っています。
    筐体がパーテーションに見えるようなサイズを買っても、
    決して損ではないと信じています。

  3. すべてのプログラマはマウスとキーボードの選択の権利を有する
    まずはマウスの話から、
    マウスはあまり高いのは買いませんが、
    最低でも光学式でホイールが付いているものは買っています。
    特にホイールが無いのは今となっては致命的です。
    中クリックでできることを知ってしまうともう戻れません。
    ただし、5ボタンマウスは誤操作が増えるのでやめました。
    おそらく5ボタン好きもいるでしょうし、選択できるのはいいことです。

    次はキーボードです。
    こちらはちょっと高いのでお気に入りのがあります。
    Filcoブランドのキーボードで、5000円前後するモデルです。
    何軸かは忘れましたが、“カチッ”という確かな手応えが大好きです。
    初めてキーボードショップで触れたときは、その感触に感動を覚えました。
    ただし壊れるのが早く、すぐに1000円の予備に切り替わります。
    そのときのモチベーションは言うまでもありません。

  4. すべてのプログラマは快適な椅子を持つべきである
    冗談抜きで、安い椅子はおしりが痛くてしょうがないです。
    手頃の値段のものは、ひと月くらいで身体の節々が疲れてきます。
    ちょっと値段の張ったものは、デスノートのL座りして使っています。
    アーロンチェアについては、座ってみたい憧れです。
    (そのうち中古でも買おうかな?)

  5. すべてのプログラマは高速なインターネット接続を持つべきである
    ええ、なきゃ困りますとも!
    普段触り慣れないものであればなおのこと。
    本の方が良くまとまっているのは事実です。
    しかし世の中には、本を買うまでもない調べごとが塵のように存在します。
    インターネットはダイソンの掃除機のようなものです。
    集まった塵の中から、プログラマは宝石を探し出してデコレーションします。
    そんな便利な掃除機があるのに、今さらちりとりやほうきを使うのですか?

  6. すべてのプログラマは静かなる仕事環境を持つべきである
    自分は自宅であっても静かな環境ではありません。
    自作PCのファンの音は、サーバールームと間違えられるほどだからです。
    きっと仕事場よりも作業ができないのは、この騒音ではないでしょうか。
    次に買い換えるときは、自作水冷式にチャレンジするとしましょう。

  7. (個人的な追加)すべてのプログラマは私服で出勤しても構わない
    別にスーツが良い人を止めはしませんが、
    せめて私服を選ぶ権利は与えられてほしいものです。
    今の仕事場は休日出勤時は私服が許されているのですが、
    明らかに生産性が違うのはここだけの秘密です。
    なんで高い服を買ってまで生産性を下げたいのか…永遠の謎です。
    (いや、ピープルウェア読んで知ってますけどね。)
…本当、プログラマを雇う経営者って無駄遣いが好きなんでしょうね。

2011年5月16日月曜日

Stack Overflowのミラーサイト

で日本語の場所を見つけたので登録しました。
そのうちユーザーリンクを貼る予定です。
(ただユーザーリンク画像が無いのでちょっと考える必要があります。)

Python寄りなんであんまり利用することはないですが、
今後に期待ってことでちらちら見ていきます。

あとはニコニコ動画とpixivあたりをリンク付けておきたいね~
pixivは登録すらしてないですけど。

絵を…描かないと。

追記:消えてしまったのでユーザーリンクも外しました。

2011年5月14日土曜日

メンテが終わってる~

たまには週末に書きこむぞ~
昨日はメンテナンスだったので書き込みができませんでした。

代わりにJTAPIとかJSAPIの仕様を眺めていました。
しかし最新版のJSAPIェ…
javadocだけでソースが無いのはどういうことディスか?

インターフェースは逆算できるけど、
実装は中身が分からないじゃないですか~!?

2011年5月12日木曜日

カルマを重ねて

Stack Overflowのカルマ値が100を超えました。
いや、別に珍しいことじゃないですけど、
やっぱり感慨深いものがあるわけです。

けれど気になるのはカルマ値の“上昇”でしょうか?
ザナドゥをやりこんだ身としては、
「カルマ値=上げてはいけないもの」
という図式が頭から離れません。

でも他の引用を見ると“上昇”の方がむしろ自然なようです。(例えばelonaとかね。)
“業”と訳すよりも、“徳”と訳せば近いのかな~?


すごく…どうでもいいです。

追記:なんか昔の記事が上に来てしまいました…なぜこの記事だけ?
追記2:これで元に戻った?

2011年5月10日火曜日

キャートラングサーン!!

前回からの続きです。

trangは無実だった!
問題はJAXBっぽいZOY!

というか変換成功したやつも悲惨やな…
しばらくはDOMが天下ですね、
空気で分かります。

2011年5月9日月曜日

ギャートラングサーン!!

ゴールデンウィークも終わり、
ブログも再開です。
PCでの書き込みができなかったのでスマートフォンからの投稿です。
trangでDTDからXMLスキーマに変換し、
それをJAXBでオブジェクトにしようとしました。
そしたらエラーが…ナンダコレ?
変換後のXMLスキーマを見たら、
何か違う…これは変換バグ!?
手作業の修正が必要なり…
エイリアスがらみは気をつけて!

追記:trangは無実だった!