2016年1月3日日曜日

WindowsでVagrantのインストールから起動までのメモ

まずはVagrantをインストール

Vagrantのダウンロードページからmsiファイルを選択してインストール

以下のように動作確認できればOK.

 
> vagrant --version
Vagrant 1.8.1

BOXのダウンロード

vagrantboxのサンプル配布サイトからboxファイルを探す。今回はCentOS6.3 の64bit版を使用する。

 
> vagrant box add Centosh63_x64 https://s3.amazonaws.com/itmat-public/centos-6.3-chef-1
0.14.2.box
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'Centos63_x64' (v0) for provider:
    box: Downloading: https://s3.amazonaws.com/itmat-public/centos-6.3-chef-10.14.2.box
    box:
==> box: Successfully added box 'Centos63_x64' (v0) for 'virtualbox'!

> vagrant box list
Centos63_x64 (virtualbox, 0)
 
> rvagrant init Centos63_x64
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

Vagrantfileを編集して、以下の内容をコメントアウト
config.vm.network :private_network, ip: "192.168.33.10"


vagrant up を実行すればVMが立ち上がる。
 
> vagrant up


ちなみに、Virtual Boxのバージョンが4.2.0のときは、以下のエラーが出て起動できなかった。
Virtual Boxのバージョンを上げて解決。
 
Stderr: VBoxManage.exe: error: Shared folder named 'vagrant' already exists
VBoxManage.exe: error: Details: code VBOX_E_OBJECT_IN_USE (0x80bb000c), component SessionMachine, interface IMachine, callee IUnknown
VBoxManage.exe: error: Context: "CreateSharedFolder(Bstr(name).raw(), Bstr(hostpath).raw(), fWritable, fAutoMount)" at line 978 of file VBoxManageMisc.cpp

2015年12月30日水曜日

サラリーマンのための確定申告ガイドライン

 確定申告のシーズンなので、サラリーマンのための確定申告したほうが良いかどうかの基準を整理することにする。

1.前提

以下のような人を対象とする。
  • サラリーマンで会社で年末調整を行っている。
  • 株式の売買を行っており、数万~数十万程度売買益(損)や配当収入がある。

2. そもそも何故確定申告をやるのか

 サラリーマンは会社側で税金の調整をしてくれており、株式の売買も特定口座源泉徴収ありにしておけば確定申告は行わなくても良い。確定申告する理由は、払いすぎた税金を取り戻す(来年以降に取り戻す)から。税金の計算方法は、後述のように何通りか選べる場合がある。デフォルトの源泉徴収よりほかの計算で税額が小さくなるのであれば、小さいほうを申告して、差額の税金を還付してもらう、ということができる。

3. 国内株式の売買損益について

 特定口座源泉徴収なしを選択している場合・・・ 売買益20万以上の場合は確定申告が必要。但し、売買益含む給与以外の所得が20万以下の場合、確定申告が免除されるので、この場合確定申告しないほうが良い。

特定口座源泉徴収ありを選択している場合・・・ 確定申告したほうがよい場合を以下に挙げる。

  • 複数の口座があり、かつ売却損が出ている口座がある・・・口座間の損益を通算することで、税額を減らせる。
  • トータルで売却損になっている・・・損失を申告することで、翌3年間に出た利益と損益通算することができる。(その際にはまた確定申告が必要)

4. 国内株式の配当金について

 配当金は売買損益と異なり以下の課税パターンを選択できる。
  • 源泉徴収(デフォルト) ・・・ 最初から20%引かれている。
  • 申告分離課税 ・・・ 株式の売買損益の枠と合わせて計算する。
  • 総合課税 ・・・ 給与所得含む所得と合算して計算する。またこの場合配当控除が受けられる。
確定申告することで税金を減らせるのは以下のパターンが考えられる。

  • 株式の売却損が出ていた場合 ・・・ 配当金を申告分離課税で損益通算することで、配当金の課税を減らす。
  • 年間所得が695万以下の場合 ・・・ 給与所得と配当所得を合算して課税額を計算し、源泉徴収で引かれた税金の一部を戻す。

5.外国株式の配当金について

外国株式の配当金の扱いも原則として国内株式と同じだが、アメリカ株など二重で税金を徴収されている場合がある。外国税額控除を行えば、二重で課税された一部を減額することが可能。

参考 


2015年10月20日火曜日

EWS(Exchange Web Service)接続仕様解説

はじめに

本ドキュメントはEWS(Exchange Web Service)を使用して、
スケジュールの取得、更新、削除の方法を解説する。
また、スケジュールのカスタムフィールドを埋め込んで予定を作成する方法も解説する。
EWSではスケジュールの他に連絡先、メールなどの取得機能がありますが、スケジュールに関するに機能にのみに絞って説明する。
Exchange Server 2010以降を対象とする。

基本的な方針

EWSはSOAP通信によってリクエストをPOSTで送ることで、Exchangeに持つ情報を操作可能。
また、httpsを使用するためSSL証明書をインストールする必要がある。
今回は通信時にBasic認証を行って認証するものとする。
EWSで使用できる命令一覧は以下を参照

スケジュール取得(FindItem, GetItem)

入力例1(時間を指定してスケジュールを取得)

FindItemによるスケジュール取得方法を示す。



  
    
      
        Default
      
      
      
        
      
    
  


BaseShape, CalendarView の値を変えることで、以下のように結果を指定できる。
BaseShape 意味
IdOnly IDのみを返す
Default デフォルトで規定されているプロパティを返す
AllProperties Exchange Business Logic レイヤで規定されているすべてのプロパティを返す
CalendarView 意味
MaxEntriesReturned 取得するスケジュールの最大件数を指定する。
StartDate 開始日時を指定する。表記はタイムゾーン(YYYY-MM-DDThh:mm:ss+09:00)
EndDate 終了日時を指定する。表記はタイムゾーン(YYYY-MM-DDThh:mm:ss+09:00)

応答例1

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : 2414b9a2-3098-4a78-afea-13ca70b8d541
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=e1c788bc304a4876a75a8ceb9a15818e; expires=Mon, 07-Mar-2016 19:27:29 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M/I387GxczIxc3G; expires=Sat, 07-Mar-2015 19:37:29 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Sat, 07 Mar 2015 19:27:28 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
                
              
            
          
        
      
    
  

入力例2(GetItemによる取得)

スケジュールの固有ID, ChangeKeyが分かっていれば、GetItemでIDを指定して取得することが可能。
IDはオブジェクトに一意に付与される。ChangeKeyはオブジェクトのある特定の状態を表すもので、オブジェクトが更新されると、ChangeKeyも変化する。



  
    
      
        IdOnly
        
          
        
      
      
        
      
    
  

応答例2

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : e04c54a3-d851-4a91-aa57-4ff707bf57cb
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=ada4db7f7ca448458f78c9a5cefb8b0e; expires=Mon, 07-Mar-2016 22:42:49 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M/I383NxcrNxcvG; expires=Sat, 07-Mar-2015 22:52:49 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Sat, 07 Mar 2015 22:42:49 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
              4月の予定
            
          
        
      
    
  

スケジュール新規作成(CreateItem)

CreateItemを使用してスケジュールが新規作成できる。

入力例3




  
    
      
        
      
      
        
          テスト予定(Powered by EWS)
          This is test meeting
          2015-04-04T14:00:00
          2015-04-04T15:00:00
          false
          Busy
        
      
    
  


応答例3

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : 809f50a6-f346-4d80-9695-6af66379c8d1
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=573595eeeb4d498bb0102f09e8ef26a1; expires=Mon, 07-Mar-2016 22:51:22 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M/I383Mxc/Oxc3M; expires=Sat, 07-Mar-2015 23:01:23 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Sat, 07 Mar 2015 22:51:22 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
            
          
        
      
    
  

DeleteItemでIDを指定することで、削除可能。

入力例4




  
    
      
        
      
    
  

DeleteTypeを指定することで以下のように削除方法を指定できる。
DeleteType 意味
MaxEntriesReturned 物理的に消去する。
SoftDelete 回復可能な削除領域に移動させる(削除済みアイテムの保持が有効な場合)
MoveToDeletedItems アイテムを削除済みフォルダに移動させる。

応答例4

--------------HEADER SECTION-------------------
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : e08d3acf-3ee2-4a9b-b39e-28ac0229527b
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=7070dbf7a6ef43938b076150169c3d3b; expires=Mon, 07-Mar-2016 17:57:21 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M/I387Hxc/Ixc3O; expires=Sat, 07-Mar-2015 18:07:21 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Sat, 07 Mar 2015 17:57:20 GMT
connection : close
--------------BODY SECTION-------------------


  
    
  
  
    
      
        
          NoError
        
      
    
  

スケジュール更新(UpdateItem)

UpdateItemを使用することで、既存のスケジュールを更新可能。
IDとChangeKeyの両方を指定する必要がある。

入力例5




  
    
      
        
          
          
            
              
              
                Modified
              
            
          
        
      
    
  

更新内容が競合した場合、ConflictResolutionの指定により以下のような挙動となる。
ConflictResolution 意味
NeverOverwrite 競合が発生したら上書きしない。
AutoResolve 競合が発生したら自動的に解決を試みる。
AlwaysOverwrite 競合が発生しても常に上書きする。

応答例5

--------------HEADER SECTION-------------------
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : 0b9bccc5-c440-468a-8b40-cd2b186a583a
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=f5fd2b1f008d45d3a0668b5c5dffebc3; expires=Mon, 07-Mar-2016 20:04:12 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M/I383Pxc7Lxc7N; expires=Sat, 07-Mar-2015 20:14:12 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Sat, 07 Mar 2015 20:04:12 GMT
connection : close
--------------BODY SECTION-------------------


  
    
  
  
    
      
        
          NoError
          
            
              
            
          
        
      
    
  


カスタム項目を追加する場合

以下のようにExtendedPropertyを指定することで、カスタム項目を追加して
予定を新規作成できる。
PropertyNameに任意の名前を記述でき、PropertyTypeはデータの型を表す。
(以下の例ではAccountNoというカスタム項目を追加している)

入力例6




  
    
      
        
      
      
        
          CUSTOMテスト予定2(Powered by EWS)
          This is test meeting
          
            
            320
          
          2015-04-06T14:00:00+09:00
          2015-04-06T15:00:00+09:00
          false
          Busy
        
      
    
  

応答例6

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : c40b2b35-4aa8-4940-8548-3ea19ccede2a
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=141d265651ac42aeab68137b65067650; expires=Sat, 12-Mar-2016 23:14:20 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M7N383Mxc3Lxc3I; expires=Thu, 12-Mar-2015 23:24:27 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Thu, 12 Mar 2015 23:14:26 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
            
          
        
      
    
  


カスタム項目が付与されたレコードを取得するには、カスタム項目で指定したPropertyNameを以下のように指定する必要がある。

入力例7





  
    
      
        IdOnly
        

            

        
      
      
        
      
    
  

応答例7

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : c98ce9a5-70d6-42bc-acfb-28f809617b43
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=c2e612b25a6a495491dbb61db49a7e25; expires=Sat, 12-Mar-2016 23:19:35 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M7N383Mxc3GxczJ; expires=Thu, 12-Mar-2015 23:29:36 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Thu, 12 Mar 2015 23:19:36 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
              
                
                320
              
            
          
        
      
    
  

"--------------HEADER SECTION-------------------"
cache-control : private
transfer-encoding : chunked
content-type : text/xml; charset=utf-8
vary : Accept-Encoding
server : Microsoft-IIS/8.5
request-id : c40b2b35-4aa8-4940-8548-3ea19ccede2a
x-targetbeserver : win-t79tuft08l9.hogehogenet.com
x-diaginfo : WIN-T79TUFT08L9
x-aspnet-version : 4.0.30319
set-cookie : exchangecookie=141d265651ac42aeab68137b65067650; expires=Sat, 12-Mar-2016 23:14:20 GMT; path=/; HttpOnly, X-BackEndCookie=S-1-5-21-2274913595-3117749821-1060021795-1135=u56Lnp2ejJqBx82bysedms7SxsfJmtLLms7I0sfLmsnSy87Im5rJms6dxs7OgYHNz87K0M/M0M7N383Mxc3Lxc3I; expires=Thu, 12-Mar-2015 23:24:27 GMT; path=/EWS; secure; HttpOnly
x-powered-by : ASP.NET
x-feserver : WIN-T79TUFT08L9
date : Thu, 12 Mar 2015 23:14:26 GMT
connection : close
"--------------BODY SECTION-------------------"


  
    
  
  
    
      
        
          NoError
          
            
              
            
          
        
      
    
  

参考資料

参考文献
ひと目でわかる Exchange Server 2013

変更履歴

  • 1.0 初版作成

間違いなどありましたら指摘いただけると幸いです。

Written with StackEdit.

2015年10月14日水曜日

ISUCON5のベンチを動かすメモ


ISUCON5の予選問題を動かしてみたいけどどうやったらいいのかよくわからん人用のメモ。

GCPアカウント作成~イメージ作成まではレギュレーションに書いてあるので省略。

$ sudo su - isucon
$ vi .bashrc

 //以下を追記
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
alias ll="ls -la"
alias vi="vim"
 //.bashrc反映
$ . .bashrc
 // リポジトリをクローン
$ git clone https://github.com/isucon/isucon5-qualify.git

$ cd isucon5-qualify/bench

 //ビルド
$ gradle compileJava

 //jq入れる
$ sudo apt-get install jq

 //ベンチ実行
$  ( curl localhost/initialize;cd ~/isucon5-qualify/bench; cat ~/isucon5-qualify/webapp/script/testsets/testsets.json  | jq .[0] | gradle run )

自分の環境ではなぜかベンチがJSTの時刻を取得できなくてうまく動いてなかったので、
以下の修正を入れた。

$vi ./bench/src/main/java/net/isucon/isucon5q/bench/scenario/BootstrapChecker.java
LocalDateTime beforeUpdates = LocalDateTime.now().withNano(0);
LocalDateTime afterUpdates = LocalDateTime.now().withNano(0);

 => 以下のようにZoneIdを指定
//ZoneIdをインポート
import java.time.ZoneId;

ZoneId zoneId = ZoneId.of("Asia/Tokyo");
LocalDateTime beforeUpdates = LocalDateTime.now(zoneId).withNano(0);
LocalDateTime afterUpdates = LocalDateTime.now(zoneId).withNano(0);


以上。

2015年9月27日日曜日

Excel系SEがISUCON5に参加してみた



ISUCONなる面白そうなコンテストがあったので、同僚を誘って計三人で参加してみた。
やったこと、感想などを残しておく。

1.ISUCONとは

お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル。 詳しくはこちら

2.準備編

今年6月ぐらいからISUCONが開催されることを知ったので、三週間に1回ぐらいみんなで過去門をやるぐらいのまったりペースで練習開始。普段こういうチューニングはやらいので、みんな手探りの状態からとりあえずスタート。最終的に5回ぐらい集まって練習会を実施し、行ったのは大体以下の内容。

  • 1回目・・・ とりあえずISUCON4予選過去問をやってみる。AWSの設定やら試行錯誤でみんな好き勝手にいじる。模範解答を参考にnginxやRedisを入れてスコアをあげてみる。
  • 2回目,3回目・・・ ISUCON4予選問題を各自でいじってみて、結果を持ち寄る。node + Redis構成にしてMySQLを完全に取っ払うことで、当時の予選通過スコアぐらいまで出せて満足。
  • 4回目・・・ ISUCON3予選問題をみんなでやる。そろそろ本番はどういう構成で望むのかを議論。みんなそれほど得意な言語はなかったので、最大公約数的にRubyを選択し、DBは部分的にRedisかもしくはSQLite(インメモリ)で行こうという方針で検討。
  • 5回目・・・ ISUCON4予選問題をRuby+Redis+nginx で構成するように模擬本番形式で実施。Google Cloud Platformで動くISUCON4予選イメージが配布されていたので、そちらを使用する。スコア送信用本番サーバ1台と、各自の開発用サーバ1台*3の構成で実施。ファイルの受け渡しはGithub上のリポジトリでやり取りするように取り決め。SSH鍵の作成やRuby, Redis, nginx の設定ファイルテンプレをリポジトリに登録。
# レギュレーションを見て、予選終了までリポジトリ公開は禁止だったので、慌ててgithubアカウントをプライベートに変更(合わせてGithubアカウントをアップグレード)

また、予選をチーム名"本業:Excel職人" で登録。

3.本番当日編

10開始予定だったので、9時に集合して買出しなど済ませ、準備に入る。
その後アナウンスがあり11時開始に変更となったので、それまで待機。ISUCON4のイメージを上げて復習。

11時からポータルサイトにアクセスが解禁され、VMイメージが公開されたので、早速展開して接続。その際に"uname -a" を打ったときに衝撃が走る。

Linux isucon5-production 3.19.0-21-generic #21-Ubuntu SMP
Ubuntuだと・・・(´゚д゚`)


ISUCON4予選も3予選もCentOSだったので、Ubuntuはノーマークだった。しかも普段CentOSしか触っていなく、Ubuntuをサーバ用途でいじったのは何年ぶりかわからない。
しかもサービスはsystemdで管理されているし。。これログどうやってみるんだっけ。。
※(追記) レギュレーションにUbuntuって追記されてましたね。。恥ずかしい。。

学生のころの期末テスト開始直後で問題用紙を裏返して見た直後に"ここ出すんかい"
と試験勉強範囲を外されたときと似た思いだった。

お題はSNS系のサイトだった。過去の予選に比べかなり複雑な印象を受けた。
DBのテーブルも今まで2~3個だったけど、今回は7つ。

とりあえず1時間半程度かけてみんなでコードリーディングしながら、改善点を洗い出していく。
最終的に変更できたのは以下の内容。

  • nginxでの静的ファイルのキャッシュ。nginxやunicornの稼動プロセス数の変更。通信のgzip化
  • tcp接続からunixドメインソケットを使用するよう変更
  • 足跡の処理をMySQL -> Redisに変更
  • 日記のentryテーブルのbodyカラムにタイトルと本文が入っているために、分離
  • usersとsaltsテーブルの統合
  • いけてないMySQLクエリを粛々と改善。インデックスの検討
  • 不要なサービスの停止
上記のことをやっていたらいつの間にか8時間たってしまった。
スコアは上位陣とは程遠いもので、初期スコアよりはまあ改善は見られるものの、もう少し出せればよかった。。上位陣の模範解答が気になる。

練習でやろうとしていたことは最低限できたような気がしたが、修正スピードが遅かった。
もう少し多くの部分をRedisに置き換えたかったが、ベンチに怒られて最終的にコミットできず。
また練習ではベンチマークがまわし放題だったが、本番ではベンチの実行リクエストがキューに
たまるので好き放題まわせなくて、修正に戸惑う場面もあった。

今回の練習でsinatoraとかnodeとかRedisとかnginxとか普段触らないものを勉強できたのでいい機会だった。
前回よりお題が複雑で、運営さんも大変そうだった。

似たようなイベントがあればまた参加したい。


※上記ロゴ画像は本家より拝借しております。問題ありましたら削除しますのでご連絡下さい



2014年6月9日月曜日

AndEngineの使い方(インストールメモ)

Andoridの2Dゲームエンジン"AndEngine"が面白そうなので、使い方をメモ




当方の実行環境は以下の通り。

  • IntelliJ IDEA Community Edition 13.1.2
    • Android開発用のプラグインを入れておくこと
  • 以下のバージョンのAndEngine
    • commit: 720897f99d2c56ba357e8fe361454bd8d88c37ed
  • AneEngineExample
    • commit: 75b657b2cd7e1153e005a917753b6d0390e034d5
  • その他GitHubに公開されているExtension全て

1.ソースコードの入手

Githubにソースコードが公開されているので、AndEngine本体に加えて、サンプルコードをExtensionをすべてcloneする。
同一のディレクトリにまとめてcloneしておくと便利。

2.プロジェクトの作成

IntelliJの"import project"でAndEngineExampleのプロジェクトをインポートする。
参照するライブラリはInnteliJが自動で解決してくれるみたい。便利。

3.サンプルプログラムの実行

ExampleLauncherを実行すればさまざまサンプルが実行できる。

そのままビルドすると、いくつかエラーが発生したので、以下のように修正





  • java: シンボルを見つけられません[シンボル:   クラス DrawMode




  • インポートするディレクトリを変更 

  • import org.andengine.entity.primitive.vbo.DrawMode; 
    → import org.andengine.entity.primitive.DrawMode;





  • TextBreakExampleのTextOptionの引数が逆になっているので修正



  • BoundCameraExampleのAnimatedSprite作成時に、animateの実行を別の文に分ける。
  • final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion, this.getVertexBufferObjectManager()).animate(100);



    これでビルドできるようになり、
    これらのサンプルを参考にすればすぐにある程度ゲームが作れそう。


    2013年12月21日土曜日

    ブラックジャックのシミュレータをjavascriptで書いてみた

    ブラックジャックのシミュレータは以前も作ったことがあるけど、今回はブラウザでも実行できるようjavascriptで作ってみた。 途中で力尽きしまったので、ディーラーのシミュレーション部分のみ作成。 概要は以下のとおり

    • ディーラーのアップカードを2~10, Aceのいずれかを選択する
    • 17以上になるまでカードを引く
    • 最終的なディーラーハンドの出現回数と割合を計算する


    結果の見方

    たとえば、ディーラーのアップカードが10のとき、バーストする確率は約22~23%というが分かる。 ということは、プレイヤーカードが16であったとしてもスタンドすればほぼ8割方負けしまうので、引いた方がまだましという判断になる。

    シミュレータの場所

    シミュレータのページはこちら

    2013年8月31日土曜日

    BlackJackシミュレータ作ってみた

    ブラックジャックのそれぞれの手の場合にどれくらいの期待値で
    勝てるのかを調べるために、Scalaでモンテカルロシミュレーションプログラムを作ってみた。


    • プレイヤーの手札が8~20の時に対して、ディーラーのアップカードが2~Aのそれぞれに対して、HIT/STAND/DOUBLEDOWNを500000回繰り返したときの期待値を求める。
    • カードは無限にあるものとする(カウンティングの要素は含まない)
    • 乱数は擬似乱数を使用する
    • サレンダーは考慮しない(アーリーサレンダーとレイトサレンダーを分けるのがしんどいので)
    • ディーラーはソフト17スタンドとする

    結果



     こんな感じになった。表の各数値はHIT / STAND / DOUBLE DOWN をずっと繰り返したときの期待値です。各セル内の最大値となるものが、最適戦略となる。


    他のサイトとの比較

     このあたりに掲載されているベーシックストラテジーと比較すると、一部微妙に違いがあるが、このあたりは乱数の性能の限界なのかもしれない。




    作成したプログラム


    GitHubに置いています。

    2013年4月13日土曜日

    家に帰ってブログ書くまでがシェル芸



    春爛漫シェル芸人撩乱勉強会に参加してきた。
    本日はwget, curl, sedさんたちが活躍する内容。 curlなんて入ってたっけ?と思うぐらい何もしない状態での参加をしてしまった。
     前回と同じく以下、自分の知らなかったことの(断片的な)まとめ。

    curl, wget で画像URL収集

    curl, wgetでhtmlファイルを持ってきて、そこからは必要なデータを切り出すという作業。
    以下はimgタグにある画像データを取ってくる場合。

    $ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&/g' | grep "img src" | grep http | sed -e 's/^[^"]*"//' | sed -e 's/".*$//'
    
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    http://k.yimg.jp/images/clear.gif
    ・・・以下略
    

    上のコマンドを見て気持ち悪いと持った人は正常な感性を持ってると思う。オレならこう書けるとか思った人は変態やと思う。

    ひたすらsedでテキストをいじってるけど、このURL抜き出しに必要なsedイディオムは以下のようだった。
    • img srcタグ1つにつき1行にするように抜き出したいタグ(この場合img)の前に改行をぶちこむ
    • 先頭からURLの直前の'"'までと、URL以降を削除する。
    正規表現は普通に書くと最長一致となり意図しない部分まで削られてしまうので、 ^[^"]*"のような気持ち悪い書き方になる。これは何とかならない物なのか。

    grep -oオプションを使えばもう少し簡単にかけて、以下のような感じになった。
    $ curl http://www.yahoo.co.jp | sed -e 's/<img src/\n&amp//g' | grep "img src" | grep -o 'http://[^"]*"' | tr -d \"
    
    
    
    -oオプションは行単位ではなく、マッチした部分のみ出力する。これは一番明日から使える内容かもしれない。 

    いずれにしろ、こういう書き方はワンライナーだから許されるものであってこんなのがスクリプトとして残っていたら見るほうが発狂しそう。

    あと便利なgrepオプションついでに-A -B -C (NUM)オプションも素晴らしい。これはマッチした行の前後もあわせて表示すると言うもの。

    % seq 1 10 | sort -R
    % seq 100 110                                           
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    
    # マッチした次の行も表示
    % seq 100 110 | grep -A 1 105
    105
    106
    # マッチした前の行も表示
    % seq 100 110 | grep -B 1 105  
    104
    105
    # マッチした前後の行も表示
    % seq 100 110 | grep -C 1 105 
    104
    105
    106
    
    


    curl, wgetでPOSTリクエスト

    以下のようにすれば、wget, curlでもPOSTリクエストが送れる。 cronで定期的にリクエスト投げたいときに使えるかもしれない。
    $ wget -O - --post-data=test http://www.usptomo.com/XXXXXXX
    $ curl -d test  http://www.usptomo.com/XXXXXX
    
    

    他にもいろいろあったけど、とりあえず酒が入ってものすごい眠いので今日はここまで!

    2013年1月27日日曜日

    Windows環境へPython, easy_installインストール手順


    Linux環境ならすぐできたけど、Windows環境では環境変数の
    設定などが多少必要だったのでメモ

    環境:Windows 7
    入れるもの: python2.7, easy_install

    1. Python公式サイトからpython2.7インストーラをダウンロード・実行
    2. すべてデフォルトでインストールすると、C:\Python27以下にディレクトリ・ファイルが生成される。
    3. 環境変数PATHに"C:\Python27"と"C:\Python27\Scripts"を追加。
    4. 環境変数PYTHON_HOMEにも"C:\Python27"追加。
    5. コマンドプロンプトからpythonと実行すると反応があることを確認。
    以上でpythonインストール完了。
    ついでにeasy_installも入れる。
    1. このWebサイトからez_setup.pyをダウンロード
    2. python ez_setup.py でインストール
    3. コマンドプロンプトからeasy_installと実行すると反応があることを確認。
    以上




    2013年1月2日水曜日

    cmdおみくじ

    正月で暇だからコマンドプロンプトで貼り付けたらおみくじの結果を表示するワンライナー書いてみた。 シェルだとすぐにできるけどDOSのコマンドだとどうやっていいのかなかなか分からなかったので、メモ代わりに残しておく。
    SET /A R=%RANDOM% % 6+1 >null & for /f "tokens=%R%" %i in ("大吉 中吉 小吉 末吉 凶 大凶") do echo おみくじの結果は"%i"です。
    
    おみくじの結果は"中吉"です。
    

    2012年12月8日土曜日

    シェル芸人への道


    第2回シェル芸人養成勉強会に参加してきた。
    hbsstudyハンズオンにも参加していたので、なんとなく雰囲気が掴めていて前回よりついていけたような気がする。 前回と同じく以下、自分の知らなかったことの(断片的な)まとめ。

    パイプステータス

    パイプを何個もつなげると、最後の終了ステータスしか分からないと思っていたが、
    実はPIPESTATUSに最後のステータス以外も配列として格納されている。
    % echo hoge | cat
    hoge
    % echo hoge | cat | cat | cat | cat
    hoge
    % echo ${PIPESTATUS[@]}
    0 0 0 0 0
    % echo hoge | cat | cat error | cat | cat
    cat: error: No such file or directory
    % echo ${PIPESTATUS[@]}
    0 0 1 0 0

    フィールドを指定したソート

    -kn,m (nは開始フィールド、mは終了フィールド)オプションでソートに使用する基準を指定できる。
    -kオプションを使うことは知っていたけど、このあたりの理解が曖昧になっていた。
    % cat hoge
    a 12
    a 13
    b 13
    a 432
    b 111
    b 43
    # フィールド1番目、2番目の順でそれらをキーとしてソート
    % sort hoge | sort -k1,1 -k2,2nr
    a 432
    a 13
    a 12
    b 111
    b 43
    b 13
    

    ランダムソート

    要素をランダム(ハッシュに応じて)ソートする。
    これはソートと言っていいのか?という疑問はある。
    % seq 1 10 | sort -R
    5
    9
    1
    2
    6
    3
    10
    8
    4
    7
    

    grep検索パターンをファイルから指定

    -fオプションを使うことにより、検索するパターンをファイルから取得できる。これは便利。
    % cat fuga
    hoge
    fuga
    piyo
    % cat fuga2
    fuga
    piyo
    piyopiyo
    # fuga2の内容をパターンとしてfugaからgrep
    % grep -f fuga2 fuga
    fuga
    piyo
    

    プロセス置換

    これを一般的になんて表現したらいいのか分からないけど、以下のようにするとファイルに出力を意識することなく、ファイル出力されたものとして他のコマンドに結果を渡せる。
    # 裏側ではファイル出力してるのやろうけど、使用者からは意識しなくて言いと言う意味
    (ご指摘を受けたので修正)

    以下のようにすると、プロセスの入出力をファイルのように取り扱うことができる(ファイルは出力していない)。
    % cat hoge
    a 12
    a 13
    b 13
    a 432
    b 111
    b 43
    % wc <(cat hoge)
          6      12      32 /dev/fd/63
    

    どれも明日使える内容ばかりですね!!

    しかしこれくらいで感心しているようでは、シェル芸人の道のりはまだまだ遠い。。

    2012年11月20日火曜日

    [Android] AVDの作成時に"Error: null"と表示されて作成失敗する。


     Androidのエミュレータを作成するときに作成ボタンを押しても反応せずに、 "Error:null"とだけログに表示される。


     困ったときのStackOverFlowがやはり役に立って、このあたりの回答と参考にすると、 結局のところ環境変数ANDROID_SKD_HOMEに.androidの上のディレクトリ(\Users\toyuserなど)を指定してやればこのエラーは出なくなった。


     問題はなんで今まで作成できたものが出来なくなったのかは分からないけど、とりあえず解決したらかクローズ。

    2012年11月9日金曜日

    [Android]スライドで大きさを変えられる可変ビュー作ってみた


    Androidっていわゆるスライドバーみたいな感じでビューの大きさを変えることって
    標準のウィジェットでは用意されていない。

    やからスライド(ドラッグ)で大きさを可変にできるビューを作ってみた。

    なまえは適当にSlideBarDrugViewControllerとしてみた。
    ソースはコチラ(Github)。以下は使い方の簡単なメモ。

    レイアウト

    スライドバー用のビューと、その上下にビューを用意する。
    今回は例なのでビューの種類は何でもいい。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello"
            android:id="@+id/view0"
            android:gravity="center" />
    
        <TextView
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="SlideBar"
            android:background="#6090ef"
            android:gravity="center" />
        
        <Button
            android:id="@+id/view2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="BottomView" />
    
    
    </LinearLayout>
    


    MainActivity

    Mainのアクティビティにレイアウトを読み込ませる。
    以下の2点を使用する。
    • (1)で書かれている4つの引数を与える
    • (2)のようにonTouchイベントをcontrollerに渡す

    public class SlideBarWidgetActivity extends Activity {
        
     Context context;
     SlideBarDrugViewController controller;
     View upperView;
     View slidebarView;
     View bottomView;
     
     
     /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            upperView = (View)this.findViewById(R.id.view0);
            slidebarView = (View)this.findViewById(R.id.view1);
            bottomView = (View)this.findViewById(R.id.view2);
            context = this;
            
        }
        
     public void onWindowFocusChanged(boolean hasFocus) {
      WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
      Display display = wm.getDefaultDisplay();
      final int screenHeight = display.getHeight();
      
            Rect r = new Rect();
            this.upperView.getGlobalVisibleRect(r);
      if(controller == null){
          /**
      * (1)以下の4つの引数を与える
      * drugView 可変ビュー(スライドバーの上部ビュー)
      * slideBarView スライドバーとなるビュー
      * minpx 可変ビューの上部(top)の絶対座標
      * maxHeight スライドバーが下に動く最大サイズ。画面全体の大きさを入れると最下端まで移動させられる
      */
       controller = new SlideBarDrugViewController(upperView, slidebarView, r.top, screenHeight);
      } 
     }
      
     @Override
     public boolean onTouchEvent(MotionEvent event){
               // (2) onTouchイベントをcontrollerに委譲
       return controller.onTouchEvent(event);   
     }
        
    }
    

    実行結果

    画像では分かりにくいけど、ScrollBarをスライドさせるとそれにあわせて上下のビューの大きさが変化する。

    2012年10月28日日曜日

    #hbstudyハンズオン


    10問お題が出されてそれをbashワンライナーで解けという内容でした。
    普段からのコマンド習熟度が問われるわけですね。
    ・・・と思ったらawk習熟度が思いっきり問われました。

    以下は自分が知らなかったことの(断片的な)まとめ。

    標準入力をcatで受け取るには


    ハイフンを引数に取ればいける。知らなかった。
    もちろん複数の引数をとればcatの出力は連結される。

    $ echo "hoge" | cat -
    


    bashでデータをランダムにシャッフルするには

    慣れている人がやればawkでもうこれは慣用句らしい。

    以下は1~10の数字をランダムにシャッフルする例


    $ seq 1 10 | awk '{print rand()" "$1}' | sort | awk '{print $2}'
    10
    4
    8
    6
    1
    2
    9
    5
    7
    3
    
    awkでの切った貼ったはお手のものですね。

    欠けているデータを探すには

    お題では1~10までのどれか一つの数字が欠けていてさらにシャッフルされたデータがあるとき、その欠けている数字のみを表示するというもの。
    diffはそれ以外のものも表示されてしまうので禁止。


    $ cat num
    10
    8
    6
    1
    2
    9
    5
    7
    3
    $ seq 1 10 | cat - num | sort -n | uniq -u
    4
    

    ここの問題のミソは比較したいデータをまとめてソートしてuniqで一行しかないものをとってくると言うこと。-uオプションとかこういう風に使えるのね。

    FizzBuzz問題

    できるだけエレガント?に

    $ seq 1 100 | awk '$1%15==0{printf "FizzBuzz "} $1%5==0{printf "Buzz "} $1%3==0{printf "Fizz "} {print $1" "}' | awk '{print $1}' | tr "\n" " "
    
    1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buz
    

    まあこれはいろんな方法がありそう。自分は最初bashのtestコマンドで頑張っていたがawkの方が短くなるね。


    所感?

    印象深かったことは、玄人(バイニン)の人たちは息をするかの如くawkを書きなぐっていたこと。
    自分はawkほとんど慣れていなかったので、後半はついていけなかった。。

    あの時間から3時間シェルと遊ぶのはなかなかエネルギーが必要やったけど、いい勉強になった。

    2012年10月14日日曜日

    MongoDBメモ

    MongoDBのインポートコマンドのメモ
    mongoimport -v -d Document名 -c Collection名 --file JSONファイル
    
    上記のコマンドで、JSONファイルで書かれたデータをMongoDBにインポートできる。

    2012年10月2日火曜日

    Scala体験記_2

    Scalaのifは文(statement)じゃ無くて式(expression)なんだぜ。だから以下のように書けたりする。

        val a = if (1 < 2 ) {10} else {20}
        println(a)
    
    まぁこれだけやと三項演算子と何が違うの?っていわれそうやけども。

    if式でハマってしまったのは、if式の評価順が予想よりも低いこと。
    以下の例の出力結果はどうなるやろうか。


        val a = if (1 < 2 ) {
           10
        } else {
           20
        } 
           + 5
        println(a)
    

    意味もなくネストして書いてみたけど、こいつの出力結果は10となる。 これはifよりも{20} + 5が先に評価されたせい。 これに気づかずに1時間ぐらい悩んでたら良くある誤解として取り上げられていたのでメモ。

    2012年10月1日月曜日

    Scala体験記


    Scalaを使って何か書いてみようと思ったけど、基本的なループの書き方すらよく分かってなかったので復習がてら内容をメモ

    以下Int型リストの総和を求めるというものすごく簡単な例

    関数型っぽく書いたとき


    def calcsum(list:List[Int]) : Int = {
        if (list.isEmpty)
          0
        else
          list.head + calcsum(list.tail)
      }
    

    Java(手続き型)っぽく書いたとき


      def calcsum2(list:List[Int]) : Int = {
        var sum = 0
        for( value <- list) sum += value
        sum
      }
    

    こういう風に関数型と手続き型の両方で書けるのがScalaのいいところ。 その気になれば全部Javaっぽく書くのも可能。

    2012年9月20日木曜日

    1つのプロジェクトにJavaとScalaを混在させてビルドする方法

    もうすでに詳細なやり方が他の記事で書かれていたので、メモ代わりにリンクを張っておく

     Scala Eclipseプラグインの導入からビルドまでの手順

     JavaプロジェクトでScalaコードを含めてビルドする手順

     思ったより簡単にJavaプロジェクトにScalaコードを書いて実行することができた。
     Scalaで定義したメソッドの定義をJava側のコードで補完とかもできるので一部だけScalaを混ぜても 違和感無く使用できそうな感じがした。



     Androidコードもこの調子でさくっとビルドできればいいんやけど。。