vim・viを使ってとりあえず文章を編集する方法

vim使ったことがないけど使う必要があったのでメモ。
 
vimを使ったことがないがターミナルは使えるという人が、利便性・効率性を無視してとにかくテキストファイルを編集することを目的に書いています。
`vimtutor ja`と趣旨は近いです。
少しでもvimの操作に慣れている方はこの記事を見る必要はありません。
 
vimを基準に書かれていますが、以下に書いてある全ての操作がviでも使えます。


最初に知っておくべきこと

  • 動作のわからないキー入力をするとたいてい悲惨なことになるので、してはいけない。
    • 特にバックスペースキーはうっかり押して混乱する危険が高い。
  • 状態が混沌としてvimを強制終了させたくなったら、エスケープキー連打した後に「:q!」と入力し、エンターキー押せば大体終了してくれる。
 
起動
  • 起動時に編集するテキストファイル名を指定する。`vim some_text.txt`のような感じで。

モードについて

  • vimには複数のモードがある。
  • モードが違うとキー操作もがらりと変わるので、今どのモードなのかを常に意識しないといけない。
  • テキスト編集に最低限必要なのは「コマンドモード」と「挿入モード」の2つ。
    • 注:コマンドモードを「ノーマルモード」や「編集モード」、挿入モードを「入力モード」や「編集モード」と呼ぶこともある。
  • vim起動直後はコマンドモードになっている。
  • コマンドモードのときにiキーを押すと、挿入モードに移る。
  • 挿入モードのときにエスケープキーを押すと、コマンドモードに移る。
    • 文字以外のキー(例えばカーソルキー)を入力したときもコマンドモードに移動することがあるので注意。
    • どんなモードのときでもエスケープキーを押するとコマンドモードに移れるので、路頭に迷ったらエスケープキーを押そう。
  • モードごとでできること・できないことは次の通り。
    モード名 コマンドモード 挿入モード
    このモードにするためのキー エスケープキー iキー
    できること カーソルの移動(h, j, k, lキー)
    文字の削除(xキー)
    元に戻す(uキー)
    vimの終了(「:q」コマンド)
    その他色んなコマンド
    文字の入力。
    キーボードの文字を大体普通に打つことができる。
    shiftキー押せば通常通り大文字になる。
    日本語はcygwin bash上ではMSのIMEが使えてるけど、その他環境は知らない。
    できないこと 文字の入力
    範囲選択
    文字入力と、カーソル移動以外全部
     (vimなら、.vimrcをいじくれば文字の削除はできるようになる)

コマンドについて

  • コマンドモードでは、コマンドが使える。
    • 以下の説明は全てコマンドモードで行っていることが前提。
  • カーソルを移動するには、h, j ,k, lキーを押す。
    • カーソルキーも多くの場合使えるが、viでは使えないこともある。
    • カーソルの動き方は以下の表の位置のようになる。
        j(↑)  
      h(←)   l(→)
        k(↓)  
  • 文字を削除するには、x, X, dd, Jコマンドを押す。
    • xキーを押すと、カーソルの右側の1文字を消す。改行を削除しないことを除いて、windowsのメモ帳でデリートキーを押したときと同じ効果。
    • Xキー(shift+x)を押すと、カーソルの左側の1文字を消す。改行を削除しないことを除いて、windowsでバックスペースキーを押したのと同じ効果。
    • 「dd」と押すと、カーソルを含む行全体を削除(切り取り)。
    • Jキー(shift+j)を押すと、カーソルを行の末尾に移動しつつ、行末の改行を削除する。
  • vimを終了するには、コマンドモードで「:q」と押す。このときファイルが更新されていて、かつ保存されていないと、失敗する。
    • ファイルを保存せずに終了…「:q!」
    • ファイルを上書き保存して終了…「:wq」
    • ファイルを上書き保存…「:w」

他のコマンド

  • 「dd」コマンドで、一行切り取り。
  • pキーで、貼り付け。
  • あとは「vim コマンド 一覧」とかでぐぐってください・・・・

3D空間で回転・向きを表す方法

3Dわからない人によるメモ

行列

4x4正方行列で回転と向きを表す。
 
利点
  • 回転を行列の掛け算で表せるので、計算が速い
  • 行列なので平行移動・拡大縮小・傾きも表現できる
  • OpenGLの回転表現法がこれなので、わざわざ変換する必要がない
欠点
  • 向きを表すのに16個の実数値が必要なので、メモリ効率が悪い
    • 3D物体1つだとなんてことはない差だが、何万個も物体があると大差に。
  • 乗算が多いので、誤差がたまりやすい

オイラー角

軸に対する回転3つで向きを表す。
直観的なので3DCGソフトなどでのクライアントに対する回転表示によく使われるが、内部的に使うとなると特定の状況以外では効率がよくない。
 
利点
  • 向きを直観的な形式で表現することができる
  • 各軸に対する回転処理が単純かつ高速
  • 3つの実数値があればいいので、メモリ効率がいい
欠点
  • 単純でない回転を適用する場合、計算が複雑で時間がかかる
  • 特異点が存在する。つまり、2つの等価でないオイラー角が同じ向きを表すことがある
    • このためオイラー角が一意に定まらないことを考慮しないといけないので、他の向き表現からの変換が多少複雑。
  • ジンバルロックが発生する。つまり、特定の向きのときに回転が急激になったり、ほとんど回転しないことがある。
  • 軸の回転順序に自由度があるうえ、状況によって有効な順番が異なるので、統一感がなく紛らわしい
    • いくつか流儀がある(参考:RfLab.Wiki - 数学)。
    • zxy:航空機の姿勢制御(ロールピッチヨー)。
    • yxz:カメラの向き制御
    • zxz:ロボットの姿勢制御。狭義のオイラー角。
    • xyz:あまり使わないが、順序がわかりやすいので他の向き表現形式からの変換過程で使ったり

クォータニオン

クォータニオン四元数)を使って向きを表す。
四元数複素数を拡張した概念で、1つの実数と3つの虚数からなる数のこと。
回転を表す内部表現にはクォータニオンが使われることが多い。
 
利点
  • 回転を四元数の積で表すことができるので、計算が速い
  • 拡大縮小も表現できる
    • 正規化すると拡大情報が消え、正規化しないと回転の誤差がたまるので、あまり使い勝手がよくないが。
  • 2つの向き間の角度を求めるのが高速
  • 高速な球面線形補間(Slerp)が使える
欠点
  • 表現が直観的でない
  • 複数回の回転を表現できない。つまり、60度の右回転・420度の右回転・300度の左回転…が、全て等価に扱われる
    • 1フレームごとならストロボ効果で気にならぬ
    • Slerpとかするときは処理を細かくわけましょう

Androidで縦向き(Portrait)でカメラを使う方法 (主にAndroid2.x向け)

縦向きカメラを使うのは意外に難しい。

要点

  • Androidのカメラは横向きが基本。
  • Android2.1以前では、縦向きカメラが使用できるかどうかは実装依存Camera.Parameters.set("rotation", 90); とすると、一部端末で縦向き表示になる。
  • Android2.2以降では、Camera.setDisplayOrientation(int)を使うことで縦向きにすることができる。
  • 縦向きカメラを使ってもCamera.takePicture()を使って得られた画像は横向きのままなので、手動で変換する必要がある。

カメラを使う

Androidでカメラを使うには、以下のようなコードを書く。詳しくはAPI DemosCameraPreview.javaとかを見よう。
        mCamera = Camera.open(); //カメラを用意
        mCamera.setPreviewDisplay(holder); //カメラ画像を表示先を設定
        mCamera.startPreview(); // カメラ画像の表示を始める
        mCamera.takePicture(listener, listener, listener, listener); //写真を撮る

カメラを縦向きにする

上記のやり方で得られるカメラ画像は、横向きである。これを画面が縦向きのときに表示させることもできるが、アスペクト比が狂った画像が表示されてしまう。
 
これを縦向きにするには、Camera.setDisplayOrientation(int)でカメラプレビューの角度を設定すればいい。
角度は、リファレンスページにあるコード(下記のもの)をコピペすれば得られる。(ただし要API Level 9。API Level 8向けに修正したコードは後述
 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }
 
Android2.1以前では、setCameraDisplayOrientation()は使えない。パラメーターを取ってきてparameters.set("rotation", 90);とすると一部端末で縦向きになるが、実装依存なので端末によっては動作しない。

撮影した写真を縦向きにする

で、これでカメラのデータを表示する部分は縦向きになったのだが、実際に写真を撮ってみる(Camera.takePicture()を使う)と横長になる。
これを解決するには以下の4つの方法がある。
 
 
下の項目になるほど動作が速いけど、やり方がよくわからないのでここでは上の2つについて説明します。
 
撮った写真を編集する必要がないなら、2番目のイミュータブルなBitmapを作る方法でやる。こちらの方が1番目の方法よりわかりやすい。
     int degrees = getCameraDisplayOrientation(this); // 後述のメソッド
     Matrix m = new Matrix();
     m.postRotate(degrees);
     Bitmap rotatedBitmap = Bitmap.createBitmap(origBitmap, 0, 0, origBitmap.getWidth(), origBitmap.getHeight(), m, false);
 
ここでgetCameraDisplayOrientation()はCameraクラスのリファレンスページにあるsetCameraDisplayOrientation()から抜き出したもの。
以下のようになる。
このコードはAPI level 8向けに修正しているので、インカメラなどを使う場合には間違った数値を返すので注意。
    public static int getCameraDisplayOrientation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
        }
        return (90 + 360 - degrees) % 360;
    }
撮った写真に後から他の図形や画像を書き込む場合は、この方法は不適。
イミュータブルなBitmapを生成後にそれをコピーするという方法もあるが、それはメモリ効率が悪い。
そこで1番目の方法を使う。これは動作原理が微妙にわかりにくいし、コードが長い。
     // dataはonPictureTaken(byte, Camera);で定義
     Bitmap origBitmap = BitmapFactory.decodeByteArray(
             data, 0, data.length);
            
     int degrees = getCameraDisplayOrientation(this); // 前述のメソッド
     int rotatedWidth, rotatedHeight;
     if (degrees % 180 == 0) {
          rotatedWidth = origBitmap.getWidth();
          rotatedHeight = origBitmap.getHeight();
     }
     else {
          rotatedWidth = origBitmap.getHeight();
          rotatedHeight = origBitmap.getWidth();
     }
     Bitmap rotatedBitmap = Bitmap.createBitmap(rotatedWidth, rotatedHeight, Bitmap.Config.ARGB_8888);
     Canvas canvas = new Canvas(rotatedBitmap);
     canvas.save();
    
     canvas.rotate(degrees, rotatedWidth / 2, rotatedHeight / 2);
     int offset = (rotatedHeight - rotatedWidth) / 2 * ((degrees - 180) % 180) / 90;
     canvas.translate(offset, -offset);
     canvas.drawBitmap(origBitmap, 0, 0, null);
     canvas.restore();
     origBitmap.recycle();
    
     // ここからrotatedBitmapに何か描き足したり
 
ndkやExifを使う方法はやったことない。。。
ndkでやるには、AndroidBitmapInfoをいじって転置行列を作る要領でピクセルを書き換えればいいはず。

サンプルコード

上記のようにして作った実際のAndroidプロジェクトを以下においています。

Javaの2重チェックイディオムとhappens-before関係

The "Double-Checked Locking is Broken" Declarationを斜め読みしたところ、Javaで遅延初期化をやるときに2重チェックイディオムが使えるかどうかで悩んだのでメモ。
 
以下のようなクラスがあったとする。
public class AClass {
     private AHugeClass final value; // 状態を持つ巨大なオブジェクト

     public AClass() {
          value = new AHugeClass(); // かなり膨大で副作用のある計算
          /* 他の処理 */
     }

     public AHugeClass getValue() {
          return value;
     }
}
 
基本的にはこのコードに何も問題はないが、value変数の初期化に非常に多くの計算が必要で、かつ場合によってはvalue変数を一切使わないようなとき(計算が無駄になるとき)には、あまり良いコードとは言えない。
 
そこで、遅延初期化を行う。
遅延初期化は、初期化の計算が膨大で、初期化を遅らし、必要なければ初期化を行わないための手法のこと。
 
これをそのまま実装すると、以下のようになる。
public class AClass {
     private AHugeClass value;

     public AClass() {
          /* 他の処理 */
     }
     public AHugeClass getValue() {
          if(value == null) value = new AHugeClass(); // かなり膨大で副作用のある計算
          return value;
     }
}
 
こうするとスレッドが1つのときは正しく遅延初期化されるが、マルチスレッド環境ではdoAHugeCalculation()が複数回呼ばれてしまう。副作用がなければ何度よばれても別に問題ないが、副作用がある場合は以下のような排他制御が必要になる。
public class AClass {
     private AHugeClass value;

     public AClass() {
          /* 他の処理 */
     }
     public synchronized AHugeClass getValue() {
          if(value == null) value = new AHugeClass(); // かなり膨大で副作用のある計算
          return value;
     }
}
 
しかしsynchronizedを使うと、多くのスレッドがアクセスする場合にはメソッドへのアクセス速度が激しく低下してしまう。
そこで、volatile変数で原子性を確保しつつ、2回の判定でなるべく排他しないようにしたものが2重チェックイディオム。
public class AClass {
     private AHugeClass value;

     public AClass() {
          /* 他の処理 */
     }
     public AHugeClass getValue() {
          if(value == null) {
               synchronized(this) {
                    if(value == null) {
                         value = new AHugeClass(); // かなり膨大で副作用のある計算
                    }
               }
          }
          return value;
     }
}
 
これで晴れて遅延初期化を実装できた。
 
しかし、このコードが正しく動作するのはJDK5以降のみ。
JDK1.4以前では、volatile変数にhappens-before関係が存在しないため、2重チェックイディオムをすり抜けてしまう。
※JDK1.4以前のvolatileは、変数がスレッドごとのキャッシュを読まないということのみ保証している。
 
具体的にどう抜けるのかはThe "Double-Checked Locking is Broken" Declarationが詳しいが、根本的な原因はプログラムが書いた順番通りには動かない(逐次一貫性が保証されない)ことである。
上の例では、value = new AHugeClass();でvalueにAHugeClassのインスタンスを代入したにAHugeClassのコンストラクタが呼ばれている。
 
happens-before関係(happened-before、C++流にはsequenced-beforeともいう。日本語では「前に発生」)は、ある命令がプログラムに書かれた順序で実行されるという関係。
普段プログラミングをしているときにはこれは当然のもののように感じるが、内部的には徹底的な最適化が行われているので、プログラムが書いた順に実行されるということはまずない。
happens-before関係を保証するのがC++やJDK5以降のJavaのvolatile修飾子。
 
詳しいことはC++0x Memory Model 第1回 - 1.9 Program execution - Cry’s Diaryを読むとわかるかもしれない。C++の話だし難解だけど。

メモ:The CERT Oracle Secure Coding Standard for Java

The CERT Oracle Secure Coding Standard for Java - java - CERT Secure Coding Standards
Javaでセキュアなプログラムを書くための基準。とても詳しく書かれている。
 
重大度が大きいものを流し読みしていて気になった部分をメモ。
 
 
SQLインジェクション対策には準備された文を使う
 
文字列比較のときにはUnicode文字を正規化する
 
不要な文字を削除するときは、削除前に検証を行う
XSSを起こすものがないかチェック→アスキー文字以外を削除…という順序だと、"<scrあipt>"という文字列が検証を通ってしまう、という当然なお話。
 
適切にオートボクシングされているかに注意
Set<Short>.remove(short) のようにすると、shortがShortにボクシングされると見せかけてIntegerにボクシングされ、適切に消去ができない。
 
不正なサブクラスは叩き潰す
イミュータブルであることが期待されるクラスorメソッドを継承orオーバーライドして可変にすると、いろいろ悪いことができたり。
不変でないクラスはサニタイズするしかないか。
 
不変を期待するためには防御的コピーせよ
 
重要なクラスはclone()でコピーされてはいけない
clone()を持っていないクラスでも継承されてコピーできてしまうので、clone()をfinalにする。
 
コンストラクタで例外を投げるのは注意して行う
コンストラクタで例外が発生すると、そのオブジェクトは部分的に初期化された状態で生成される。
このオブジェクトはどこからも参照されていないのですぐガベージコレクトされるが、そのオブジェクトのクラスを継承してファイナライザーをオーバーライドするとそのオブジェクトを捕捉することができる。そうなると困る。
 
clone()内でオーバーライドできるメソッドを呼ばない
 
ぬるぽをキャッチしてはいけない
 
多スレッドで共有される値は可視性(値がスレッド間で整合性を保つこと)を保証する
 
多スレッドで共有される値を読んで書くなら可視性だけでなく原子性も保証する
 
排他制御に使うオブジェクトはちゃんとnewで初期化する
intのボクシングの実態はInteger.valueOf()で、これはキャッシュを使いまわすので駄目。
 
static領域を排他するなら排他用オブジェクトもstaticに
 
部分的に初期化されたオブジェクトを見せない
例えば'SomeObj obj = new Someobj();'というコードがあったとき、SomeObjクラスのコンストラクタが実行される前に変数objへの変数割り当てが起こることがある。
このとき複数スレッドが存在するとobjの過度状態を見ることができ、バグのもととなる。

配列のラッパーとしてのBufferで使用する配列は外部に渡さない
Buffer.wrap()とBuffer.put()は全然違うよ。
 
シリアライズメソッドを可視(非private)にしてはならない
readResolve()とwriteReplace()はprotectedなメンバーメソッドに。
 
staticでない内部クラスをシリアライズ可能にしてはならない
staticな内部クラスはシリアライズしてもいいよ。
 
汚染された変数を権限付きで実行してはならない
 
アクセス可視領域を広げてしまうリフレクションを使ってはいけない
publicメソッドで不用意にリフレクションを使うと、privateメンバーにアクセスできてしまう。
Field.setAccessible(true) は基本的にセキュリティマネージャーがはじいてくれるので、そこまで怖くはないはず。
 
決定的な乱数は使ってはいけない
 
パスワードなどを直書きしてはいけない
 
 
重要そうだけどよく意味が分からなかったもの:
SEC2~7

CC-BY-SAのメディアをCCでないWebページで使用してもいいのか

もっと法律的に:第三者の作成した著作物を別のWebページに含めた場合、そのWebページは編集著作物であるか?

もし編集著作物であれば、そのWebページはCC-BY-SAと互換性のあるライセンスを適用しなければならない。

CC-BY-SA を適用できないけどCC-BY-SAの画像を含めたいという状況になったので、いくらか事例がないか調べてみた。

日本語版Wikipediaでは、記事は編集著作物ではなく、テキストとメディアファイルの著作関係は完全に分離できる、という見解を示している。(参考:Wikipedia‐ノート:著作権 - Wikipedia

しかし、記事によってはメディアファイルと本文の結びつきが強く、その2つを分離できるという考えは正しくないのではないか、という意見もある。(参考:Wikipedia‐ノート:アップロードされたファイルのライセンス/GFDLとCCの衝突の可能性 - Wikipedia

つまり、CC-BY-SAのメディアをCCでないWebページで使用できるかどうかは、そのWebページとCCのメディアとの結びつきの度合に依存する。その2つがどのくらい結びついていたら駄目なのか、という指標は今のところない、ということらしい。

でも…分離できた方がメディア利用者にとってはいろいろと嬉しいよね。個人的には、Wikipedia程度の画像と記事の結合度なら分離できるという方針でいこう。

TopCoderの各コンテストについて適当な紹介

自分はSRMしか参加したことがないけど、TopCoderのコンテストにはいろいろと部門がある。
アルゴリズム部門以外のTopCoderのコンテストが全然わからなかったので簡単に調べてみた。
とても読みにくいので注意。

Copilot Opportunities(共同開発機会)

TopCoderのコンテストを利用してあるプロジェクトを遂行したい顧客のために、企業と共同で一連の開発工程を運営する、というお仕事。
顧客との対話や他のコンテストの実施、成果物の納入など、TopCoderのソフトウェアコンテスト運営の重要な役割を担っている。
 
最初にプロジェクトの基本戦略や、コンテストの開催ロードマップなどを最初にWord・Excelで提出し、選別のためのコンテストを行う。
その後、コンテストをパスした人たち(コパイロットと呼ばれる)によって他のソフトウェア開発コンテストが実施される。

上記のようにこのコンテストはとても重要なものなので、参加するには以下の条件を満たしている必要がある。

  • 過去1年間に3種目以上のコンテスト(SRMとMarathon Matchesは除く)に参加し、スクリーニングレビューをパスしている
  • 少なくとも1つの部門で緑色コーダー以上である
  • 過去1年間にレビュアーになったことがあり、レビュアー権限を剥奪されていない
  • 過去6か月間にコパイロット権限を剥奪されたことがない

Design(設計)

  • Studio(スタジオ)
    • デザイナー向けのコンテスト。
    • ワイヤーフレーム作成やアイコン作成などいろいろな部門があるけど、ここでは詳しく解説しない。
  • Conceptualization(概念化)
    • 出資者と共同してプロジェクトの設計を行うコンテスト。多くの場合、コパイロットが決定したすぐ後に行われる。
    • デザイン(ストーリーボードやワイヤーフレーム)の原型を作ったり、ビジネス要件を定義・記述した文書を作ったりする。
    • Conceptualizationコンテストは1つのプロジェクトに対して複数回行われることが多い。
    • 最終的な成果物の例がWikiページの下のほうにあるですよ。
  • Specification(仕様化)
    • 要件を基に、具体的なプロジェクトの仕様(要求仕様)を書くコンテスト。
    • 仕様はUMLによる図(主にユースケース図とアクティビティ図)を含めた文書で書く。
  • Architectureアーキテクチャ
  • Component Designコンポーネント設計)
    • 与えられた仕様やアーキテクチャのもとで、ユースケース図・クラス図・シーケンス図とコンポーネント仕様文書を書くコンテスト。
    • 内部設計に相当する? Architectureコンテストとの違いがよくわかってない。
    • ここで具体的なライブラリを決めたり、テストケースも作ることもあるみたい。

Development(開発)

  • Component Developmentコンポーネント開発)
  • Assembly(組立)
    • よくわからない。部品から実際に動くアプリを作るコンテスト? 試作版が完成されているアプリケーションに機能追加するコンテスト?
    • とりあえずアセンブリ言語は関係ない。
    • 英語の解説でも"Assembly competitions are hard to define."と言ってる…。
  • Test Suites(テストスイート)
    • 自動化されたテストケースを作るコンテスト。
    • 見つかったバグは、前段階のコンテストの勝利者に修正を依頼される。
    • テストケースは、JUnitとか、NUnitとか、Seleniumとかで作っているようだ。
  • Reporting
    • 謎。説明がないし今まで一度もコンテストが開かれてない。

UI Development(UI開発)

QA and Maintenance(品質保証と保守)

  • Test Scenarios(テストシナリオ)
    • テストケースを作るコンテスト。
    • DevelopmentのTest Suitesとほぼ同じコンテストで、開催されるときのプロジェクトの工程が異なる。
  • Bug Race

Algorithm(アルゴリズム)

  • Single Round Matches(SRM)
    • アルゴリズムに関する短時間の定期コンテスト。
    • TopCoderのコンテストの中で最も参加者が多い。
  • Marathon Match
    • アルゴリズムに関する長時間の定期コンテスト。

High School

高校生向けのコンテスト。アルゴリズム問題。

The Digital Run

その月で部門別で一番DRポイントを稼いだ人に賞金をあげますよという話。
DRポイントはソフトウェア開発コンテストで参加してスクリーニングをパスすると、成績に応じてもらえる。
 



ソフトウェア開発コンテストの大まかな流れ

個々のコンテストによっては違う部分も多いけど、ほぼ次のような流れで共通している。
  1. 登録(Registeration)
    • 自分が参加したいコンテストのページへ行き、参加登録をする。
    • 参加登録をすると、そのコンテスト専用のフォーラムにアクセスできるようになる。そこで、登録前では得られない追加情報を入手できる。
  2. 投稿(Submission)
    • 作るべきものを作って、投稿する。
    • 必要があれば、専用フォーラムで質問をすることもできる。コンテストによっては、専用フォーラムでの対話が作業の中核になるものもある。
  3. 評価(Review)
    • 投稿期間が終わったら、自分の作成物をコンテストのレビュアーに評価・採点してもらう。
    • もし自分の評価点が不当に低いと感じたら、専用フォーラムでスコアの修正を要求することができる。最終的なスコアは修正要求を吟味した後に決まる。
  4. サポート(Support)
    • もしコンテストで勝利したら(最も高いスコアを得たら)、このフェーズに入る。
    • 一定期間(多くの場合30日間)、自分の制作物で見つかった不具合を修正したり、続く開発工程でのコンテスト参加者からの質問に答えたりする。
    • 期限後はバグが見つかっても修正する必要はないが、修正したら追加の報酬金を得られることもある。



その他まとまりのないこと

  • ものすごい勢いで色々な作業がマニュアル化されている。すげー
  • そのせいか、ソフトウェア開発コンテストがガチガチのウォーターフォールモデルになっていて、LL言語によるプロジェクトがPHP除いて圧倒的に少ない。
    • 過去2年間くらいのコンテストを流し見てみたけど、その中にRuby案件とPerl案件は一つも見つからなかった。これは意外。
    • Pythonを使っている案件は一つだけ見つけたけど…すごく…Jythonです…。
  • ソフトウェア開発コンテストは、SRMに比べて1コンテスト当たりのサブミッター(コンテスト参加者のうち制作物を投稿した人)が少ない。
    • 開発工程のコンテストでは、サブミッターが1人しかいないことも割と頻繁にある。これとかこれとかこれとか。
      • Assemblyは半数近くがサブミッター1人な印象
      • サブミッター0人も、あるよ。(ただしそのようなコンテストは履歴からは見えない)
    • なので、「コンテスト」というよりは「コンテストを利用したアウトソーシング」といった方が正確だと感じた
  • フォーラムやサポートでの対話が発生するので、ある程度の英語力は必須だと思う。
    • 設計部門のコンテストだとガシガシ文章書かないといけないから、ある程度では済まないだろうけど。
    • 開発部門なら、英文書くのはコードのドキュメンテーションと、成果物の変更リスト、フォーラム上の会話くらい。
    • 成果物に書くことは部門ごとにテンプレがあるから、それに倣えば深く考えなくてもよさそう。もちろん、テンプレはきっちり読まないといけない。
    • フォーラムでの会話は、他のフォーラムの書き込みを参考にすれば大丈夫…か? 参加したことがないので自信がない。
  • SRMと比べてとても敷居が高いけど、その分野の知識があるのなら気軽に参加していいと思う。参加費は無料ですし。


 

主に参考にしたページ(英語)