読者です 読者をやめる 読者になる 読者になる

『遠回りして学ぶ Yesod 入門(上)』の電子版(PDF)のインターネット販売を開始しました

BOOTH にて『遠回りして学ぶ Yesod 入門(上)』の電子版(PDF)のインターネット販売を開始しました!

1000円となります。

kakkun61.booth.pm

結構さっくり開設できてびっくりしてる。

店舗候補

どこでダウンロード販売すべきなんかなと思ってちょっと調べたんでまとめときます。

候補としては、メロンブックス・BOOTH・DLsite がありました。それぞれの店舗での販売価格に対する受取価格はざっくり次の通りでした。

店舗 受取価格
メロンブックス*1 販売価格 × 0.7 -(振込手数料)
BOOTH*2 販売価格 × 0.966 - 10 -(振込手数料 300 or 200)
DLsite*3 販売価格 ×(販売価格により変動 0.5~0.8)

BOOTH が圧倒的じゃないか、というわけで、BOOTH にしました。後出だけあってサイトがナウいのもポイント。

ちなみに月の受取価格が1000円未満の場合は次の月に繰り越されるので振込手数料でほぼ消えたなんてことにはならないようです。

疑問

公開してから思ったんですが、誤謬を修正してバージョンアップした場合は、ファイルを登録しなおせば、すでに購入した人は新しいのをダウンロードできるんだろうか?

先人のみなさんはどうしてるんですかね?

BOOTH のその他の技術書典作品

技術書典タグがあるのでそれで検索すれば他サークルの作品ももう販売されているようですね。

技術書典に関する人気の同人グッズ18点を通販できる! - BOOTH

技術書典 ふりかえり

技術書典お疲れさまでしたー。

閉場30分前まで整理券制で、だいたいの方が1時間半待ちだったそうですね。びっくりするような盛況で何よりです。運営さんの手際もよく大変ありがとうございました。

最終的に1200人は超えたそうですね。

弊サークルも14時前には印刷して来た分が完売しまして、送料が250円追加でかかるにもかかわらず3名の方が後日発送で購入いただきました。ありがとうございます!

それでは初めてのサークル参加をふりかえっていきたいと思います。

スケジュール

3月

技術書典の開催が発表されたのは、このころだっと思います。もしかしたら2月だったかも。

3月26日~4月25日

サークル参加応募期間

正直最後の方まで参加するか悩んでました。興味はあったけどちゃんと作れるかなと。最終的には抽選に決断を委ねることに。最後まで悩んでて時間がなかったんで、サークルカットは文字とパブリックドメイン素材を使って GIMP で作りました。

f:id:kakkun61:20160626035220p:plain:w300

4月3日

techbookfest.connpass.com

雰囲気を知りに行く。

4月30日

当籤通知

覚悟を決める。

5月7日

リポジトリーを作る。

5月24日

一通り書き上げて、レビューをお願いする。ちなみに本文28ページ。

6月4日

レビュー対応も終わって、入稿用に編集しだす。

6月8日

入稿。

6月10日

印刷所から指摘があったので修正して再入稿。

6月13日

告知ブログを書く。

kakkun61.hatenablog.com

6月19日

当日使う小物を買う。イーゼルとかカルトンとか。

6月20日

名刺を入稿。3日プランで契約したのでちょっと割高だったけど、初回クーポンでちょっとお得に。22日夕方に出荷されたものの到着がイベント前日でギリギリだった。

6月25日

イベント当日

作成環境

基本的に TechBooster の『技術書をかこう!』にのっとりました。買っておいてよかった。原稿リポジトリーをそのまま取ってきて書き換えていきました。sty ファイルがいくつか足りなかったんでちょっと修正しました。

techbooster.booth.pm

github.com

エディターも書籍の通り Atom に language-review で。

atom.io

ただでプライベートリポジトリー使いたかったんで GitHub ではなく Bitbucket を使いました。

ページ番号付き空白ページを作りたかったんでそこだけは Re:VIEW を拡張しました。

# encoding: utf-8
# review-ext.rb

module ReVIEW
    Compiler.defsingle :emptypage, 0
    class LATEXBuilder
        def emptypage
            puts '\newpage\null'
        end
    end
end

印刷

『技術書をかこう!』が日光企画向けだったので、そのまま日光企画に依頼しました。

本文 PDF はよかったんですけど、表紙の PSD に不備があって再入稿しました。

本の厚さを考慮して表紙・裏表紙の位置が変わるんですけどその計算をまちがってました。

平綴じと中綴じを自分が逆に覚えてしまっていて、当日印刷したものを見て気付きました。中綴じが平に重ねた紙の真ん中にステープラー打つやつですね。次回移行は平綴じもしくは無線綴じになると思います。

2週間ほどの余裕をもっての入稿だったので2割引でした。

f:id:kakkun61:20160626151324p:plain

ちなみに、H のキャラクターは D 言語くんのパロディーの Haskell くん(@tanakh さん作)で、指指しているところにあるのはヘブライ語で יסוד = Yesod と書いてあります。基礎 foundation って意味らしいです。英語アルファベットに当てはめると右から、ysvd だそうです。ヘブライ語は子音しか表記しません。v があるのは謎。読まない文字なのかな。

togetter.com

裏表紙の絵はユダヤ教における生命の樹で、赤い部分が Yesod だそうです。エヴァのオープニングで見たことあるあれです。

Yesod の発音はイェソッドというよりイソッド(イはや行のい)のようです。

ja.forvo.com

当日準備

当日に必要になるものは Circles' Square の『はじめてのサークル参加』を見て勉強しました。準備しておくものや、申し込みから当日まで全体の流れなどが分かるのでおすすめ(画像は Circles' Square より引用)

csqr.org

f:id:kakkun61:20160626160610j:plain:w500

とりあえず近所の百均で、小銭入れ・カルトン(受け取ったお金を入れる青いトレー)・ホワイトボード・白紙カード・付箋・イーゼルを買ってきました。

百均のイーゼルの木の表面が何も処理してなかったんで、ホームセンター行って砥の粉やらニスやら買ってたら1200円ぐらいして、ちゃんとした小さいイーゼル買えばよかったのでは感が強い。

前日の夜になってダウンロード用 URI の書かれた紙の原稿を作ってコンビニへ。ネットワークプリントサービスを使ったんですけどめっちゃ圧縮されるんですね。なんのために 700 ppi で作ったんだか。ネットプリントは圧縮かかるって直前で聞いたんで USB メモリーにも画像入れて持っていったんですけど、ファイルを認識してくれなかった。

当日

寝坊!事前入場できる10:50までに会場に到着できるように起きれたのは奇跡。売り子の友人、準備ありがとうございます。

10:40に到着して、イーゼル立てて見本誌シール・値札貼って名刺も並べてコンビニおにぎり食べて、後は開場待ち。

用意してた本は17冊だったんですけど2時間40分ぐらいで完売。

その後のこと何も考えてなかったんですけど、多めに印刷してたダウンロードカードだけ売ればいいじゃんって友人に言われて、確かにーと思って売ることに。最初から売ってればダウンロードカードだけ欲しいって人ももしかしたらいたんだろうか。

入場が整理券制になってて閉場30分前までずっと新規の一般参加者が来てたんで最後までわりと売れるスピードは維持されたままでした。

途中でダウンロードカードが尽きて手書きカードにしたんですけどさすがに URI が辛くて、追加で印刷しに近所のコンビニまで。ネットプリントにしておいてよかったですね。追加印刷したのが閉場30分前だったんですけど、それから3枚売れたんで印刷してよかったです。

そんなわけでなんとか当日を乗り切れました。

後日

帰ってきてから初めて紙の本読んだら誤字が見つかったので、後で正誤表を公開します。印刷するとなぜか見付かりやすいですよね。

数字

ここからは数字の面で振り返っていきましょう。

売上

まず売れた冊数と売上から。

項目 単価 部数 合計
紙版(事前印刷) 1000 17 17000
紙版(後日発送) 1250 3 3750
電子版 800 14 11200
合計 34 31950

売上部数の勘定は最初はちゃんとしてたんですが途中で書き忘れたことに気付いたので最終的なダウンロードカードの残りなどから算出。

支出

今回のイベントのためだけの費用は次の通り。

項目 金額
紙版(事前印刷) 9760
紙版(後日発送) 2850
ダウンロードカード 40
参加費 5000
合計 17650

次回移行も使えるものへの初期投資は次の通り。

項目 金額
小銭入れ 108
カルトン 108
ホワイトボード 108
白紙カード 108
付箋 108
イーゼル 108
木工道具 1248
フォント(墨東ルイカ細めセット) 11232
名刺 100枚 529
合計 13657

その他年間契約として Adobe Creative Cloud の費用。

項目 金額
Adobe CC 年間 51576

利益

変動費だけ見ると 14300(= 31950 - 17650)。

初期投資も含めた全体として見ると -50933(= 31950 - 17650 - 13657 - 51576)ですね。

Adobe 税を除いた初期投資の元は取れてるんで、後はこの1年で何冊出して元を取るかという感じですかね。元を取りたいって話なら。

総括

(下)を書かないといけない!

売り子してくれた友人・レビュワーのみなさん・運営さん・印刷会社さん・一般参加のみなさんありがとうございました!

技術書典、後日配送で購入してくださったけどダウンロードカードを受け取っていない方へ

お詫び

お詫びです。技術書典で『遠回りして学ぶ Yesod 入門(上)』を後日配送で購入してくださった方のうち1名の方に PDF のダウンロードができる URI の書いたカードをお渡しするのを忘れてしまいました。

申込用紙の連絡先を記入していただいた部分は技術書典運営および印刷所に提出してしまったため、こちらから連絡することができません。

申し訳ありませんが、自分だという方は後日発送申込用紙の控えの「運営受注№」を明記して kazuki.okamoto@kakkun61.com までお願いします。

よろしくお願いします。

技術書典にて人生初の同人誌を頒布します!

技術書典にて人生初の同人誌を頒布します!うおぉぉ!!ドコドコドコ!プワプワー!

『遠回りして学ぶ Yesod 入門(上)』

f:id:kakkun61:20160613123319p:plain:w300

内容は、入門書程度の内容の Haskell を理解した人がウェブアプリケーションフレームワーク Yesod を使うときに手助けになるような内容です。具体的には次の通り。

  • ビルドツール Stack
  • 効率のよい文字列の扱い
  • Web Application Interface とは
  • Scotty を使ったウェブアプリ

ただ書いてたら最後まで間に合わない気がしてきたので今回は「上巻」ってことで逃げました!これから下巻書かなきゃ。

ペンタブレットを買って表紙も自分で書きました!絵がうまい人ってすごい!

いろいろ初めてのことだらけで至らないところもあると思いますが会場にいらしていただければ幸いです。

  • 技術書典
  • 2016年6月25日 土曜日
  • 秋葉原通運会館
  • A-34 卓

PDF で見本誌も用意したのでぜひご覧ください。

まだ確定してませんが、紙の書籍には電子版のダウンロード権も付けようと思います。早くに売り切れたりしたら後日電子版のオンライン販売もするかも?皮算用かしら。

それでは会場で!待ってます!!

PC 環境

ディスプレー買い足そうかって思ったときに「端子空いてたっけ?そもそもグラボ何だっけ?」ってなったので書き残しておこうと思った。

CPU

Intel Core i5 4440

ark.intel.com

  • 3.1GHz
  • 4コア
  • 6MB キャッシュ

マザーボード

ASRock Fatal1ty H87 Performance

www.asrock.com

  • LGA 1150
  • PCIe
    • PCIe 3.0 x16 1つ
    • PCIe 2.0 x16 1つ
    • PCIe 2.0 x1 2つ
  • 映像出力
    • DVI-D 1つ
    • D-Sub 1つ
    • HDMI 1つ
  • 映像入力(出力へのリダイレクト)
  • Ethernet
    • 8P8C (RJ-45)
  • SATA
    • SATA3 6つ
  • USB
    • USB 3.0 6つ
    • USB 2.0 8つ(内1つ Fatal1ty マウス ポート)

メモリー

16GB

メーカー忘れた。

ストレージ

Seagate Barracuda 2TB (ST2000DM001)

http://www.seagate.com/jp/ja/internal-hard-drives/desktop-hard-drives/desktop-hdd/#specswww.seagate.com

WD GREEN 3TB (WD30EZRX-1TBP) 2つ

www.wdc.com

光学ドライブ

LG BD ライター (BH14NS48)

www.lg.com

グラフィックスボード

ASUS STRIX-GTX750TI-OC-2GD5

www.asus.com

  • NVIDIA GeForce GTX 750 Ti
  • PCI Express 3.0
  • ビデオメモリ 2GB
  • インターフェース
    • DisplayPort 1つ
    • HDMI 1つ
    • DVI-I 1つ
  • HDCP 対応
  • 消費電力最大75W
  • 2スロット分のスペース

テレビチューナー

アースソフト PT3

http://earthsoft.jp/PT3/index.htmlearthsoft.jp

電源

COUGAR GX-S 600W

http://www.milestone-net.co.jp/product/cougar/power_supply/gx-s.htmlwww.milestone-net.co.jp

筐体

Fractal Design CORE 3000

http://www.fractal-design.jp/home/products/cases/discontinued-products/core-3000www.fractal-design.jp

ディスプレー

Amark EB2126DA

www.giga-zone.com

  • Model number EB2126DA
  • 型番 TAB2126WAD-G13R
  • 21.5型
  • TN 液晶
  • インターフェース
    • D-Sub 15ピン
    • DVI-D
  • 1920×1080画素
  • 壁掛け VESA 100×100mm
  • HDCP 非対応

ディスプレーアーム

Green House GH-AMCA03

www.green-house.co.jp

  • 4軸
  • 2アーム
  • 27型 9kg まで

カードリーダー

NTT Communications SCR3310-NTTCom

www.ntt.com

Gulp でビルドスクリプトを書く(PureScript で Hello, World!)

これらに続く第4話。前回では NPM の scripts を使ってコマンドを書いてビルドをしていたんだが、sh と cmd と2つ管理しないといけなかったり、ワンライナーなんで保守がしづらかったりと問題があるので、今回はビルドツールである Gulp を使って PureScript のコードをビルドするようにする。

おさらい

前回使ったワンライナーはこんなんだった。

bower install && psc --ffi bower_components\purescript-*\src\**\*.js bower_components\purescript-*\src\**\*.purs src\Main.purs && psc-bundle output\*\*.js --module Main --main Main -o output\main.js && copy src\index.html output\

4つのステップがあるのでそれぞれ見ていく。

bower install

bower.json に記載した依存をインストールする。

psc --ffi bower_components\purescript-*\src\**\*.js bower_components\purescript-*\src\**\*.purs src\Main.purs

PureScript ソースコードコンパイルして JavaScript に。

psc-bundle output\*\*.js --module Main --main Main -o output\main.js

CommonJS 仕様の JS コードをブラウザーで実行できるように変換する。

copy src\index.html output\

JS を読み込む HTML を成果物フォルダーにコピーする。

bower install は初回にこれをそのまま実行してもらうとして、それ以外を Gulp スクリプトに変換していく。

gulpfile.js

Gulp スクリプトは単なる JS のコードで require('gulp') すると使える内部 DSL である。今のワンライナーでは psc コマンドで生成される途中成果物と psc-bundle した後の最終成果物が同じフォルダー下にあって管理の問題上分けたいので、最終成果物は dest フォルダー下に置かれるようにする。そうすると、所望の Gulp スクリプトは下記のようになる。これを gulpfile.js として保存する。

'use strict';

var gulp = require('gulp');
var purescript = require('gulp-purescript');

var sources = [
  'src/**/*.purs',
  'bower_components/purescript-*/src/**/*.purs',
];

var foreigns = [
  'src/**/*.js',
  'bower_components/purescript-*/src/**/*.js'
];

var destination = 'dest';

gulp.task('make', function () {
  return purescript.psc({ src: sources, ffi: foreigns });
});

gulp.task('bundle', ['make'], function () {
  return purescript.pscBundle({
      src: 'output/**/*.js',
      output: destination + '/main.js',
      module: 'Main',
      main: 'Main'
  });
});

gulp.task('copy', function () {
  return gulp.src(['src/**/*.html'])
             .pipe(gulp.dest(destination));
});

gulp.task('default', ['bundle', 'copy']);

雰囲気でだいたい分かると思うが簡単に説明すると、require('gulp-purescript') で Gupl スクリプト内で PureScript 固有の記述ができるようになる。gulp.task 関数は第1引数にタスク名、第2引数に依存するタスクの配列、第3引数にタスクの内容のクロージャーを渡すようになっている。第2・第3引数は省略することができる。

このようにタスクを記述すると下記のようにタスクを実行することができるようになる。

> gulp make

引数なしで gulp とだけ実行すると default タスクが実行される。

依存の追加

新たに、Gulp を使用するようになったので package.jsondevDependenciesgulpgulp-purescript を追加する。

  "devDependencies": {
    "purescript": "0.7.2",
    "bower": "^1.4.1",
    "gulp": "^3.9.0",
    "gulp-purescript": "^0.7.0"
  }

NPM でインストールした Bower と Gulp を呼べるように package.jsonscripts を下記のようにする。当然既存のワンライナーのビルドコマンドはもう要らない。

  "scripts": {
    "bower": "bower",
    "gulp": "gulp"
  }

ビルド手順

以上をまとめるとビルド手順は下記となる。

> npm install
> npm bower install
> npm gulp

ビルドを少し速くする

今の copy タスクでは前回ビルドから変更点がなくてもコピーしてしまっているので、最終変更日時を確認して必要のあるときだけコピーするようにする。変更点は下記である。

package.json

  "devDependencies": {"gulp-newer": "^0.5.1"
  }

gulpfile.js

var newer = require('gulp-newer')
…
gulp.task('copy', function () {
  return gulp.src(['src/**/*.html'])
             .pipe(newer(destination))
             .pipe(gulp.dest(destination));
});

実行するコマンドに変更はない。

NPM と Bower に依存を管理させる(PureScript で Hello, World!)

前々回の記事「PureScript ver. 0.7.0 以上での Hello, World!」、前回の記事「PureScript ver. 0.7.0 以上で “ブラウザーで” Hello, World!」に次ぐ記事。

NPM の package.json とか Bower の bower.json とかに依存を書いてビルドを簡単にするのが今回の目的。

おさらいと前提

ファイル一覧。

> dir /b
src
> dir /b src
index.html
Main.purs

ファイルの中身。src\index.html は下記。

<html><head><script type="text/javascript" src="main.js" ></script>

src\Main.purs は下記。

module Main where

import Control.Monad.Eff.Console (log)

main = log "Hello, World!"

NPM と Bower と依存するパッケージはすでにインストールしてある前提。

package.json

NPM の設定ファイルは package.jsonnpm init コマンドでいくつか質問に答えれば下記のような package.json ができるはず。

{
  "name": "purescript-hello-console",
  "version": "1.0.0",
  "main": "index.html",
  "dependencies": {},
  "devDependencies": {
    "bower": "^1.4.1",
    "purescript": "^0.7.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/kakkun61/purescript-playground.git"
  },
  "author": "Kazuki Okamoto",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/kakkun61/purescript-playground/issues"
  },
  "homepage": "https://github.com/kakkun61/purescript-playground",
  "description": ""
}

dependencies のバージョン番号のところの ^ はセマンティックバージョンを考慮して互換性のあるバージョンを表す NPM の文法らしい。

bower.json

Bower の設定ファイルは bower.json。NPM と同じように bower init コマンドで質問に答えていけば下記のような bower.json ができるはず。

{
  "name": "purescript-hello-console",
  "version": "1.0.0",
  "main": "index.html",
  "authors": [
    "Kazuki Okamoto"
  ],
  "license": "MIT",
  "homepage": "https://github.com/kakkun61/purescript-playground",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "purescript-console": "~0.1.0"
  }
}

~^ みたいなものっぽいけどいまいち分かってないので「node.js - What is the bower version syntax? - Stack Overflow」読んどいて。(丸投げ

ここまでで npm installbower install で依存をインストールすることはできるようにはなるけどビルドは手打ちなんでスクリプトにしておく。

NPM のスクリプト機能

package.jsonscripts の項目に下記を追記する。

    "build": "bower install && psc --ffi 'bower_components/purescript-*/src/**/*.js' 'bower_components/purescript-*/src/**/*.purs' src/Main.purs && psc-bundle output/*/*.js --module Main --main Main -o output/main.js && cp src/index.html output/",
    "build-cmd": "bower install && psc --ffi bower_components\\purescript-*\\src\\**\\*.js bower_components\\purescript-*\\src\\**\\*.purs src\\Main.purs && psc-bundle output\\*\\*.js --module Main --main Main -o output\\main.js && copy src\\index.html output\\",

ユーザーが NPM で Bower をインストールしたことを考えると bower コマンドにパスが通ってない可能性があるので $(npm bin)/bower ってしておくべきなんだけど、package.json の中に書く場合は npm bin がパスに追加されている。($(npm bin)/bower だけ cmd じゃない…… cmd で同じことしようとすると for /f "usebackq" %p in (`npm bin`) do %p\bower とかになるはず。)

ここまで準備するとユーザーは NPM をインストールした後、下記コマンドでビルドしできた output\index.html をブラウザーで開けばよい。

> npm install
> npm run build-cmd

編集

2015.10.18

package.jsondependencies に記述していた bowerpurescriptdevDependencies に移した。これらは成果物が依存しているわけではなく開発時にのみ依存するため。