paiza.IO から paiza.IO API を使って再帰呼び出しを書こうとして動かなかった話

タイトルの通りだけど paiza.IO API を見つけた時にふと思い浮かんだので試してみた。

まぁ、これ動いちゃったら paiza.IO のリソースを使い潰せるので、ちゃんと対策してるんだろうなー。

コード 1

FizzBuzz です。途中にある pデバッグ目的のやつ。

require 'json'
require 'net/http'

PAIZA_API_URL = 'http://api.paiza.io/runners/create'
SLACK_API_URL = '<Slack Incoming WebHook URL>'
MAX_SIZE = 10
SOURCE = File.read(__FILE__)

def fizzbuzz(n)
  [].tap do |arr|
    arr << 'Fizz' if (n % 3).zero?
    arr << 'Buzz' if (n % 5).zero?
    arr << n.to_s if arr.empty?
  end.join(" ")
end

def post_runners(input)
  uri = URI.parse(PAIZA_API_URL)
  options = { language: :ruby, source_code: SOURCE, api_key: :guest }
  res = Net::HTTP.post_form(uri, options.merge(input: input))
  p input
  p options
  p res
  p res.body
end

def post_slack(text)
  uri = URI.parse(SLACK_API_URL)
  res = Net::HTTP.post_form(uri, payload: JSON.dump(text: text))
  p res
  p res.body
end

def main(accumulator, n)
  result = [].tap do |arr|
    arr << accumulator unless accumulator.empty?
    arr << fizzbuzz(n)
  end.join(', ')

  input = "#{result}\n#{n.next}"
  if n < MAX_SIZE
    post_runners(input)
  else
    post_slack(result)
  end
end

args = $stdin.read.split("\n")
p args
if args.size > 1
  main(args[0], args[1].to_i)
else
  p 'args are required'
end

このコードは実行できたけど、API で実行したコードではエラーが発生して止まっていた。

/usr/local/rbenv/versions/2.3.3/lib/ruby/2.3.0/net/http.rb:882:in `rescue in block in connect': Failed to open TCP connection to api.paiza.io:80 (getaddrinfo: Temporary failure in name resolution) (SocketError)

コード 2

API 実行により、Slack へ投稿するコード。

require 'net/http'
PAIZA_API_URL = 'http://api.paiza.io/runners/create'

def post_runners(source_code)
  uri = URI.parse(PAIZA_API_URL)
  options = { language: :ruby, source_code: source_code, api_key: :guest }
  res = Net::HTTP.post_form(uri, options)
  p res
  p res.body
end

source_code = <<-EOF
require 'json'
require 'net/http'
SLACK_API_URL = '<Slack Incoming WebHook URL>'

def post_slack(text)
  uri = URI.parse(SLACK_API_URL)
  res = Net::HTTP.post_form(uri, payload: JSON.dump(text: text))
end

post_slack('hello')
EOF

puts '---'
puts source_code
puts '---'

post_runners(source_code)

これも同じエラーが出ました。

まとめ

paiza.IO API を使って実行したコード内からは外部ネットワーク接続は無理っぽい。

Docker Remote API を使ってコンテナを起動させてみた

Docker Remote API を触って、簡単なコマンドを実行してみた。

実行環境

$ docker --version
Docker version 1.12.1, build 6f9534c

API ドキュメント

docs.docker.com

コンテナの作成

$ curl -v -X POST \
  --unix-socket /var/run/docker.sock \
  -H "Content-Type: application/json" \
  -d '{"Image": "elixir", "Cmd": ["elixir", "--version"]}' \
  http:/containers/create
*   Trying /var/run/docker.sock...
* Connected to http (/Users/sinsoku/Library/Containers/com.docker.) port 80 (#0)
> POST /containers/create HTTP/1.1
> Host: http
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 51
> 
* upload completely sent off: 51 out of 51 bytes
< HTTP/1.1 201 Created
< Content-Length: 90
< Content-Type: application/json
< Date: Tue, 29 Nov 2016 17:31:03 GMT
< Server: Docker/1.12.1 (linux)
< 
{"Id":"c8542f8b6965ea049a0ea4214b3bcb171345d50f032d8960366fb3db1d28e647","Warnings":null}
* Connection #0 to host http left intact

コンテナの起動

$ curl -v -X POST \
  --unix-socket /var/run/docker.sock \
  http:/containers/c8542f8b6965ea049a0ea4214b3bcb171345d50f032d8960366fb3db1d28e647/start
*   Trying /var/run/docker.sock...
* Connected to http (/Users/sinsoku/Library/Containers/com.docker.) port 80 (#0)
> POST /containers/c8542f8b6965ea049a0ea4214b3bcb171345d50f032d8960366fb3db1d28e647/start HTTP/1.1
> Host: http
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 204 No Content
< Date: Tue, 29 Nov 2016 17:31:14 GMT
< Server: Docker/1.12.1 (linux)
< 
* Connection #0 to host http left intact

コンテナの実行結果

$ curl -v --unix-socket /var/run/docker.sock \
  /containers/c8542f8b6965ea049a0ea4214b3bcb171345d50f032d8960366fb3db1d28e647/logs?stdout=1
*   Trying /var/run/docker.sock...
* Connected to http (/Users/sinsoku/Library/Containers/com.docker.) port 80 (#0)
> GET /containers/c8542f8b6965ea049a0ea4214b3bcb171345d50f032d8960366fb3db1d28e647/logs?stdout=1 HTTP/1.1
> Host: http
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Tue, 29 Nov 2016 17:32:40 GMT
< Server: Docker/1.12.1 (linux)
< Transfer-Encoding: chunked
< 
cErlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.3.4
* Connection #0 to host http left intact

2年ぶりに dotfiles を更新した

sinsoku/dotfiles を2年ぶりくらいに更新した。

更新した理由

先日、MacBook 2016 を買ってしまったからです。

設定の自動化

そんな頻繁にPCを買い換えるわけでもないし、してない。

dotfiles のために Ansible Best Practices に則ってディレクトリ作るの面倒だし、そもそも2年後とかに Ansible 使っているか微妙...。
3年前とか「Boxenで環境構築を自動化しよう」とか言われていたのに、今はあまり聞かないですよね...。

zsh

今まであまり plugin などを使っていなかったので、 zplug を入れてみた。

git commit の時に絵文字を使うので、この2つは便利。

vim

軽そうなので NeoVundle から vim-plug に変えた。

vim はあまりカスタマイズしていないので、plugin管理を変えたくらいかも。

ruby

結構前から使っているけど、rbenv-default-gemsgem-src について追加した。

あと .gemrc が古かったので、新しいオプションに直した。

-gem: --no-ri --no-rdoc
+gem: --no-document

git

大して変わっていなくて、たぶん古い指定の push.default を直したくらいかも。

-[push]
-  default = tracking
+[push]
+  default = current

これから

あまりメンテしてなかったので、 dotfiles を変更したらちゃんと GitHub に push していきたい気持ち。気持ちだけはある。

速習プログラミングElixir勉強会を主催してました #quick_elixir

10月末くらいから Elixir の勉強会を主催していて、今日で一通り終わりました。

connpass.com

資料

今日のLT資料は Qiita に上げた。 Elixir のマクロとプロセスの関係

この勉強会を開催したきっかけ

10月にプログラミングElixir を買ったけど、積み本になりそうな予感がしたのでちゃんと読了するために勉強会を開催しました。

あと、社内Slackで聞いたら意外と興味ある人がいたので、勢いのまま勉強会のページを作成した。

f:id:sinsoku:20161115234331p:plain

開催して良かった

毎週大変だったけど、なんとか当初の目的であるプログラミングElixirの読了を達成できた。

読んだ感想などはLTでも話したけど、やっぱり普段使いの Ruby と考え方が違うところは楽しいですね。新しい発見とかがある。

プログラミングElixir は良い本

読んでいて面白いし、分かりやすいので興味をもった人は買ってみたら良いと思いますよ。

プログラミングElixir

プログラミングElixir

Elixir で Sleep Sort を実装する

タイトルの通り、 Sleep Sort を実装してみました。

Elixir の並行プログラミングを生かしているけど、全く実用的じゃないソートですね!

defmodule SleepSort do
  def sort(collection) do
    me = self
    collection
    |> Enum.map(fn (n) ->
        spawn_link fn -> (send me, { :timer.sleep(n * 10) && n }) end
      end)
    |> Enum.map(fn (_pid) ->
        receive do { result } -> result end
      end)
  end
end

range = 1..20
collection = Enum.shuffle(range)
IO.inspect collection
#=> [6, 13, 17, 10, 1, 16, 15, 14, 12, 11, 18, 8, 3, 5, 4, 20, 9, 7, 2, 19]
sorted = SleepSort.sort(collection)
IO.inspect sorted
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
IO.inspect Enum.to_list(range) == sorted
#=> true

factory girl で特定のメソッドを rspec-mock の stub で潰す

備忘録。

外部APIを呼ぶメソッド、処理に時間のかかるメソッドなど、普段のテストでは不要であるメソッドは factory 側で潰すと楽。

FactoryGirl.define do
  factory :user do
    transient do
      stubs [:call_external_api]
    end

    after :build do |user, evaluator|
      evaluator.stubs.each do |m|
        r = RSpec::Mocks::Matchers::Receive.new(m, -> {})
        RSpec::Mocks::AllowanceTarget.new(user).to r
      end
    end

もし User#call_external_api のテストをしたい場合は stubs を空にすれば良い。

user = build :user, stubs: []
user.call_external_api
#=> call_external_api が呼べる。

8月に購入したバルドハート、テイルズオブベルセリアをクリアした

8月末に発売された「BALDR HEART バルドハート (PC 18禁ゲーム)」と「テイルズオブベルセリア(PS3)」を最近やっとクリアできたので、たまにはゲームの感想でもブログに書いてみる。

Qiita と違ってこういう記事書いても非公開にならないので、はてなブログは良い。

BALDR HEART

戯画のバルドシリーズの最新作。今までのシリーズが好きなら、買って後悔しない出来だと思う。

プレイ時間は全ヒロイン、サバイバル Stage 260 クリアまでで50時間くらい。

あらすじ

電脳化が一般化し、仮想世界(ネット)はもう一つの現実となった。 仮想世界に没入(ダイブ)して活動する電子体が怪我を負えば現実の肉体にフィードバックされ、リミッターがかかってない場所での死は脳死(フラットライン)に至ってしまうほどリアルな手触りを得ていた。

とある事情で戦闘能力と職を失った瀧沢蒼は、養父を頼り故郷である『海神』という島に帰ってきたが、傭兵時代の相棒である三納岸ユーリがなぜか島にまでついて来た上に、ついて早々、記憶喪失の少女月詠を助けたことで自宅に居候させることになってしまう。

過疎化が進みろくな仕事も無い島だったが、謎の人物から仕事の依頼が舞い込む。 その内容は、海神唯一の学園である『甲華学園』に編入し、学園生が島で発生しているテロに関わっていないか調査することだった。

学園に潜入しようとした蒼の前にシュミクラムで立ちはだかる生徒会長の天ケ瀬茉緒。

その時、蒼の前に自らを妖精と名乗る少女が現れ、戦闘能力を失った蒼のシュミクラムに同化しはじめた

引用: http://dic.nicovideo.jp/a/baldr%20heart

世界観

前作のバルドスカイから未来の話なので、

  • 電子体幽霊の話
  • AI
  • 無意識の海

など、過去作をやっている人にとっては懐かしい単語が出てくる。

シナリオ

今までのバルドシリーズと同様、ヒロインの攻略順は完全固定で 月詠 → 茉緒 → ユーリ → 凪 の順になる。

シナリオを進めると伏線が少しずつ分かるようになっていて、過去の事件と現在の事件がつながり始める。凪シナリオ後半の世界がカオスな感じになるのはバルドっぽくて良かった。

ラスボス戦

主題歌が流れてラスボス戦に突入する演出が熱い!!

武装のレベルが低いと、だいぶ厳しい。

master 武装でコンボすれば、結構簡単に倒せた。

武装(兵装少女)

今作では武装が擬人化され、武装を使うごとに兵装少女との信頼関係が高まって新しい武装が使えるようになる。 また、装備する武装の組み合わせで兵装少女同士が戦友になって、更に武装が強くなる。

やっぱり武装が強くなってコンボ組み立てるのは楽しい。「バルトハンマー → I・A・I → 彗星脚 → DDミサイル」みたいに、最後は重火器で〆るのが威力高くてよく使ってた。

巨弾のイリヤのグラルパトン「こいつをふっ飛ばして、更地にしてやろうぞ〜」の台詞が好き。

アペンドディスク

アペンドディスク出るらしいので、全兵装の武装を master にして、全兵装少女を戦友にしておかないといけない。

テイルズオブベルセリア

テイルズシリーズの最新作。前作ゼスティリアと同じ世界観で、過去の話。

プレイ時間は隠しダンジョン、真ラスボスを倒すの含めて70時間くらい。

あらすじ

ウェイストランドと呼ばれる世界。ミッドガンド聖導王国の辺境の村にベルベット・クラウという少女が住んでいた。彼女は明るく飾り気のない性格で家族と平和に暮らしていた。 しかし、赤い月が上ったある夜、この村に異変が起きた。この事件がきっかけでベルベットは肉親を失い、左腕が魔の手になってしまう。 それから3年、ベルベットは復讐のため、旅に出る。

引用: https://ja.wikipedia.org/wiki/テイルズオブベルセリア

シナリオ

復讐から始まる旅だけど、話が進むにつれて謎が少しずつ分かっていき、そして世界の危機を救うことに・・・というテイルズらしい話。

前作のような変な矛盾も無いし、良いシナリオだったと思う。ただ、ベルセリアの未来がゼスティリアだと思うと複雑な気持ちになるが・・・。

戦闘システム

戦闘システムはSG(ソウルゲージ)で特技を結構自由に出せるし、慣れるとスイッチブラストでキャラ交換しながらコンボを繋げられるようになって楽しい。

前作のようにカメラワークが酷かったり、戦闘キャラが2人固定みたいな事もないのでストレスなく遊べると思う。

キャラクター

ライフィセット の存在が癒やし。一番可愛い。

おわり

バルドハートの感想に時間かけすぎて、テイルズは短くなってしまった。