Golf on Slack

Slackでゴルフ場を作ったよ
遊んでくれると嬉しいよ

![codegolf_view.png](https://qiita-image-store.s3.amazonaws.com/0/100881/c262cac0-5e85-f769-95d0-fae97ef62e45.png)

# 背景・動機

- 元々は@fmy が社内のコミュニケーションツール上で開催してたよ
  - エンジニア数百人で黙々とランキング更新戦が行われ、1byteを巡る攻防に皆業務を忘れ必死だったとか
- 簡単にSlack APIに置き換えられたので公開してみたよ
  - [Node学園 25時限目](https://nodejs.connpass.com/event/54749/presentation/)でも宣伝してみたよ

# 参加方法

[Google form](https://goo.gl/forms/OONuFtwtESP2kI5G2)で（Slackで使う）メアドだけ入力すれば数分後にSlackからinviが届くよ

※GAS(Google Addon Script)で自動化したよ: [公開Slack用 自動招待フォーム by GAS](http://qiita.com/atusi/items/c2669add8038c43efff3)

# 遊び方

- slackにloginしたらgeneral channelに入るけど、generalはランキングを公開する目的の場所だから、まずは**x-codegolf**ってbotをクリックしてDIRECT MESSAGE(以下DM)を繋ごう
  - general部屋でコードを投げないよう注意してね！皆から丸見えになるよ！
  - general部屋での質問や雑談も歓迎だよ！
- DMを繋ぐと自動的にHELPが表示されるよ
  - HELPは`help`とかbotに打てば何度でも見れるよ。色んな文字列で反応するから試してみてね。
  - [node-slack-sdk](https://github.com/slackapi/node-slack-sdk)を使っているなら`RTM_EVENTS.IM_CREATED`で実現できたよ

![codegolf_help.png](https://qiita-image-store.s3.amazonaws.com/0/100881/393b80db-ed33-5b4f-772d-90c06dc8e622.png)

- `v`とか`version`って打てば使える言語とそのバージョンの一覧が見れるよ

![codegolf_version.png](https://qiita-image-store.s3.amazonaws.com/0/100881/a28624ba-a535-c97a-8660-d6076da7a593.png)

- `q 1`って打てば問１の問題文が、`q 2`って打てば問2の問題文が見れるよ

![codegolf_q.png](https://qiita-image-store.s3.amazonaws.com/0/100881/b78d75ac-d4f5-2ab1-4175-f9b828cf6837.png)

- 問１をpythonで解く時は`1 python`って問題番号+言語を書いて改行して、解答の初めと終わりをシングルクォート3つで括って投稿してね。
  - シングルクォート3つで括るとSlackが引用ぽく表記するよ（syntax highlightはないよ）
  - botの正規表現でシングルクォート3つを引っかけてるよ。改行は無視するよ（解答中の改行は1byteで数えるよ）
    - https://github.com/slack-codegolf/platform/blob/master/index.js#L171
  - ちなみに入力欄での改行はCtrl+Enterでできるよ
- サーバーサイドでテストされて、成功か失敗かバイト数と一緒に通知が来るよ

![codegolf_answer.png](https://qiita-image-store.s3.amazonaws.com/0/100881/bcd56161-65ba-440d-cec0-e08e6efdfda7.png)

- Byte数を縮めて上位5位以内になれば、general部屋でランキングが更新されて(∗´꒳`)ﾄﾞﾔｧできるよ
  - 問題を全部解いていればその言語の総合ランキングの対象にもなるよ
- ランキングは問題別・言語別でいつでも確認できるよ。botのHELPを見てね。

# 特徴

- 投稿するcodeは公開されないし保持してない
  - general channelにランキングとバイト数だけが表示
  - サイエンスチックな解き方とか、どんな解き方をしてもバレないし問題ないよ
  - 圧倒的な結果を見せつけてからの(∗´꒳`)ﾄﾞﾔｧはクセになるよ
  - 運営が勝手に「ランキング上位の人のコードを発表〜」とかできないよ
      - 正確には現状はherokuのlogにstraceの結果が残ってるけど、無料プラン・無料アドオンだから保持期間は7日間だけだよ

# 禁止事項

- 答えをcatする行為
  - 権限で制御
- ネットワーク経由で答えを送信する行為
  - ネットワーク遮断
```
ifconfig $(ifconfig | fgrep encap:Ethernet | awk '{print $1}') down
```
- bash以外のすべての言語で外部コマンド禁止
  - straceを用いて子ps監視
```
strace -f -e execve $COMMAND < ${INPUT}/$file
```
- しかし現状は......
  - [システム構成](https://github.com/darai0512/talks/blob/master/node_school_20170424/system.png)
  - herokuのsudo不可とか「docker使える！」と言いつつapp内でdockerコマンドが使えるわけじゃない制限のせいで(ry
  - 人が増えたらサーバー借りてちゃんとやるよ。Mastodon化もしたいよ

# Codegolf Tips
## Nodejs
### ex ascii

次の文字列を出力してください。

```
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
```

### JavaScriptなら

63 Byte

```js
j=''
for(i=33;i<127;)j+=String.fromCharCode(i++)
console.log(j)
```

### Node Core API

Buffer便利だよ

51 Byte (43 Byteまで縮められるよ)

```js
console.log(Buffer.alloc(94,33).map((v,i)=>v+i)+"")
```

### stdin

下記のように書けるよ

```js
// 文字コードを指定すればstring
s=require('fs').readFileSync('/dev/stdin','UTF8');

// 文字コードを指定しなければBuffer
b=require('fs').readFileSync('/dev/stdin');

// 引数はfdも可能、bufferはmap処理できる
require('fs').readFileSync(0).map(v=>{});

// eventで受けてもいい(bはBuffer)
process.stdin.on('data',b=>{});
```

## Python

下記の記事を参考にしたよ。
他にもたくさん有効な方法があるから、公式DOCとかも読んでね。

- [Python golfテクニック集 (Stack Exchangeの翻訳より) - Qiita](http://qiita.com/shibacho/items/37413a5d479d8bb57764)
- [Python - Code Golfing Tips](https://sites.google.com/site/codegolfingtips/python)
- [[python] スライスでリバース！！ - Qiita](http://qiita.com/kakk_a/items/54e81346d8f35733ab5e)