OmniAICreator/Qiita-1.07M huggingface dataset:
これだけは覚えておきたいMackerelの基礎概念

チュートリアルを経てない同僚へMackerelの説明をするために、個人的に必要最低限と思う概念だけまとめました。

#Mackerelとは

Mackerelはサーバリソースの可視化(グラフ化)および監視サービスです。
mackerel-agentを監視したいホストにインストールすれば、Mackerel上でリソースの確認を行うことができます。

zabbixサーバの管理をMackerelがやってくれているイメージです。

#Mackrelの概念図

覚えておいたほうが良い概念は以下の通りです。
赤字がMackerelが定義している部分です。
![mackerel1.png](https://qiita-image-store.s3.amazonaws.com/0/143313/82e968e8-9f39-b7cc-75ed-ab76a6ad84fc.png)

赤字だけ抜き出した部分が下記の通りになります。

* Hosts
* Role
* Services
* HostMetrics
* ServiceMetrics
* Monitors
* Alerts

#Hosts

mackerel-agentをインストールし、起動すると、Mackerel上でHostとして認識されます。
そのため、実際の監視対象と1対1の関係にあります。
![mackerel2.png](https://qiita-image-store.s3.amazonaws.com/0/143313/0f729dda-5d07-44c0-d0e9-6e8d8ef7e70e.png)



#Services

監視するシステムのサービスを表します。
例えば、ストアサービスを展開しているシステムはStoreサービスなど命名することになります。
サービスを作成してから、ロールを作成します。

![mackerel3.png](https://qiita-image-store.s3.amazonaws.com/0/143313/9abd72c7-b48d-9785-d4c1-406bb2658928.png)



上記の画像の例では、AWSのEC2なのか、RDSなのか、区別するためにAWS_SERVICEというサービスを作成しています。

#Role

監視するホストの役割を表します。
例えばWebサーバが10台あったとしたら、10台のホストそれぞれにWebロールをつけて役割をまとめます。
ロールはServicesに紐づくため、ロールを割り当てる前にServicesを作成する必要があります。

![mackerel4.png](https://qiita-image-store.s3.amazonaws.com/0/143313/638bd8f5-c96d-a0fd-7d48-ed149e851881.png)


上記の画像の例では、AWSのサービスの中のRDSであることを示すために、AWS_SERVICEに紐づけてRDSロールを作成しています。

#HostMetrics

ホストに紐づくメトリクスをグラフにします。
例えば、CPU使用率やファイルシステムなどがホストに紐づきます。

![mackerel5.png](https://qiita-image-store.s3.amazonaws.com/0/143313/ff1750ad-c758-17d5-3362-a858da7f3dd6.png)


確認したいホストを選択すると、可視化しているグラフが現れます。

#ServiceMetrics

サービスに紐づくメトリクスをグラフにします。
例えば、ストアのレスポンスタイムなどがサービスに紐づきます。

![mackerel6.png](https://qiita-image-store.s3.amazonaws.com/0/143313/771aba73-7148-3298-a885-0c8e56c44d75.png)

サービスを選択し、サービスメトリクスのタブを選択するとグラフが現れます。

#Monitors

メトリクスに対して、閾値による監視を設定することができます。
例えば、ロードアベレージが10以上であればslackに通知するなどです。
通知先は、slack/webhook/email ... など様々なものが設定できます。

![mackerel7.png](https://qiita-image-store.s3.amazonaws.com/0/143313/db168da9-f406-e8c7-c8f2-2e4c17522dfb.png)
モニターを選択し、メトリクスに対して閾値を設定して監視を行います。

#Alerts

Monitorsで監視しているリソースが閾値を超えるとアラートが発生します。
いつ、何に対するアラートなのか、それが継続中なのか終了した状態なのか、などを見ることができます。

#まとめ

他にもアノテーションやダッシュボードなど機能がありますが、最低限必要な要素はこの辺りかと思います。
めでたく、これらの概念を覚えてもらったら、基本的な話は理解してもらえるようになりました。
MySQLのデータの結果を監視してメールを送信するバッチ（cron設定する）

###作ろうと思ったきっかけ
データベース上でデータ不整合が発生する現象が発生した。
AというテーブルのBカラムの集計値はCというテーブルのDカラムと一致しなければならないのに、何故か一致しない。
どこかで不整合が発生する仕組みになってしまったのだろうが、原因が特定できない。
発生した日のログを見ようと思ったが、発生した日すらわからない。
このシステム稼働してもう何年だっけ？という手詰まりなので、
「今までの事はさておき、これから発生したとして、発生した日がわかればログも追いやすいだろう。チェックバッチを作って毎日チェックしよう」という悲しいモチベーションで作る事になった。


###check.shをとりあえず作ってみる
ネーミングセンスの悪さは否めない。

先に言っておくと、下の記述は良くない。

```check_ng.sh
#!/bin/bash

# 集計値と異なる場合にメールを送信するsh

# メール送信時に送信時刻を記載するためだけのもの
NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`
# 送信先メールアドレス
ADMIN="hoge@hogehoge.com"

# SQLファイルの指定
# 簡単ならば直接記述しても良いけれども、ボチボチ修正も入りそうなので
# 外からファイルを読み込む事にする。
SQL_FILE_NAME=diff_check.sql
# このSQLは「count (*)」とかにしておいて、差分が発生した時だけ0以外の
# 値が取得できるものとする。

# MYSQLの設定
DB_USER=hoge
DB_PASSWORD=fuga
DB_NAME=example

COUNT=`cat "$SQL_FILE_NAME" | mysql -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -N 2>&1`
# ほとんどの場合は何かしらワーニングがついてくると思うのですが…
echo $COUNT

if [ $COUNT -ne 0 ] ; then
echo "$NOW_TIME error" |mail -s "error" $ADMIN
echo "NG"
else
echo "OK"
fi
```

`check_ng.sh: 25 行: [: 引数が多すぎます`とか言われます。
echo $COUNT の中身が「mysql: [Warning] Using a password on the command line interface can be insecure. 0」とかなってるからしょうがないです。

最初は「mysql: [Warning] Using a password on the command line interface can be insecure. 」を削れば良いかと思いました。
`COUNT=${COUNT#"mysql: [Warning] Using a password on the command line interface can be insecure. "}`とか。
でもこのワーニング文言、実は環境ごとに微妙に違うようで、この実装だと他の案件で流用できない。それもどうかと思うけれど、何もかもがあまりよくない。

そもそもの話なのだけれども、DB_PASSWORDという変数がもはやおかしい。
https://dev.mysql.com/doc/refman/5.6/ja/environment-variables.html
を見ると
MYSQL_PWDという環境変数がある。これを使えばいい。

※やっぱりセキュアではないんだけれども。
「mysqld に接続する際のデフォルトのパスワード。これを使用することはセキュアではありません。」と書いてある。
本番稼働しているMYSQLに対して、クリティカルな異常でも何でもない監視用バッチの為にcnfを弄って対応する事も難しい。許可が降りない。

どうせ上の例でもパスワードをハードコーディングしていてセキュアでもなんでもないので、今更セキュアを気にしてもしょうがないと割り切る。


```check.sh
#!/bin/bash

# 集計値と異なる場合にメールを送信するsh

# メール送信時に送信時刻を記載するためだけのもの
NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`
# 送信先メールアドレス
ADMIN="hoge@hogehoge.com"

# SQLファイルの指定
# 簡単ならば直接記述しても良いけれども、ボチボチ修正も入りそうなので
# 外からファイルを読み込む事にする。
SQL_FILE_NAME=diff_check.sql

# MYSQLの設定
DB_USER=hoge
DB_NAME=example

# -pの部分はごっそり消していい。
COUNT=`cat "$SQL_FILE_NAME" | MYSQL_PWD=fuga mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
# これで件数だけ取得できる
echo $COUNT

if [ $COUNT -ne 0 ] ; then
echo "$NOW_TIME error" |mail -s "error" $ADMIN
echo "NG"
else
echo "OK"
fi
```

ちなみに、

```
MYSQL_PWD=fuga
COUNT=`cat "$SQL_FILE_NAME" | mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
```
ではダメです。

```
COUNT=`cat "$SQL_FILE_NAME" | MYSQL_PWD=fuga mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
```
こうでないと、うごかない。

###cronの設定
あとは、cronで設定するだけ。

```
00 6 * * * sh /home/hoge/batch/check.sh > /home/hoge/batchlog/check_`date +\%Y-\%m-\%d`.log
```
Omron 環境センサ(2jcie-bl01)の設定をBroadcasterに変更してアドバタイズパケットから情報を取得してみるテストまで

##背景
タイトル通りです。あまり細かいことは書きません。単純に温度・湿度・気圧などの環境値をBroadcastしてくれるBLEビーコンが必要だったので、探してみたらこれ見つかりWeather news のOEM品（WxBeacon2）を購入しました。しかし初期設定では（１）デバイスにConnectして（２） Latest data (Characteristics UUID: 0x3001)を見にいく、ことをしないとデータが取れません。つまり複数台のビーコンが見つかる環境で動かそうとすると全てのビーコンに一回接続してデータを取りに行かなくててはいけなく辛い。とはいえその設定変更機能はOMRONさんのオフィシャルアプリにはないので面倒くさいなーとオフィシャルドキュメントを読み解きながらAdv settingsをなんとかいじって、値の取得までできるようにしました。

##必要なもの
- BLE Scanner ～ BLEデバイス開発者必携の神アプリです。iOS/Android両方あります。
- Omron 環境センサ
 - [商品ページ](http://www.omron.co.jp/ecb/product-info/sensor/iot-sensor/environmental-sensor)
 - [通信仕様マニュアル Environment Sensor 2JCIE-BL01 Communication Interface Manual v1.3](https://omronmicrodevices.github.io/products/2jcie-bl01/communication_if_manual.html)

##設定変更してみよう
- Env(EnvSensor-BL01)というBLEデバイスを探してConnect
- CUSTOM SERVICEの5文字目から8文字目が3040のものを開く(2.4. Parameter Service に該当します)
- CUSTOM CHERACTERISTICの5文字目から8文字目が3042のものを探す(2.4.2 ADV setting に該当します)
![Screenshot_20171211-110301.png](https://qiita-image-store.s3.amazonaws.com/0/103775/d0a55fc9-55fb-7b15-4181-cb28af12a7a8.png)

- W(Write)をタップしADV設定をByteArrayで書き込む。今回はGeneral Broadcaster 2の0x04に設定したかったので以下の文字列を書き込みました。
 0808A000000A0032 **04** 00
![Screenshot_20171211-110309.png](https://qiita-image-store.s3.amazonaws.com/0/103775/627e44ef-c1cc-cf0e-8888-3f85550aae0c.png)

- R(Read)をタップし設定が書き込めているか確認
- 念のため接続を切り、再接続します。機器の名前がEP(EP-BL01)に変わります
- アドバタイズパケットを見てみる。OSによって微妙にアドバタイズパケットの表示の範囲が異なるので注意してください。アドバタイズパケットの中身は **3.5. (E) Sensor ADV 2 (ADV_IND)** が仕様になります。
 - Androidの場合
19，20文字目がTemp High, 17，18文字目がTemp Lowです。
![Screenshot_20171211-112144.png](https://qiita-image-store.s3.amazonaws.com/0/103775/bfadaee9-cfd7-131a-2224-3e49da68ba12.png)

 - iOSの場合
9,10文字目がTemp High,7,8文字目がTemp Lowです。
<img width="375" alt="IMG_4636.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/103775/8becee29-1c22-c8a8-b58c-b7870975e5e9.jpeg">

拾っている桁数が異なるのはよくわかりませんが、いずれの場合もこの場合f40b(Little endianなのでバイトをひっくり返す必要があるので注意！)を10進に戻した3060→30.6℃が測定値になります。

さああとはこれをCordovaで拾ってどれかmBaaSに投げるだけ。 **Enjoy!**

ちなみに同じような感じで測定パラメターをいじることも可能です。自分は据え置きではなくカバンに付けっ放しな用途で使う予定ですが、どうも急激なデータ変化をしないように初期設定されているっぽかったので多少調整しました。
ポリモーフィック関連で実装し運用してみて

## はじめに
私が現在、保守運用・追加開発をしているシステムにて、ポリモーフィック関連を利用して実装し本番リリースした後、追加開発などでその機能に更新が入ったりして、ポリモーフィック関連の便利さや注意すべき点などを感じたのでその内容を書いていきます。

そもそもポリモーフィック関連とは何なのか、具体的にどうやって実装するのかは本記事では説明しません。「ポリモーフィック関連」で検索すれば、分かり易く書かれている記事が多数見つかりますので、そちらを参照されるのが良いかと思います。

ちなみに今回のシステムはRailsで作っています。

## アプリ要件
まず、今回のシステムはSNSのようなサイトで、サイト内でユーザはEventとCommunityを作成することができ、他の人が作成したEventとCommunityに参加することができます。そして、EventとCommunityの管理者は参加者に対してメッセージを送ることができ、メッセージ履歴は各EventとCommunity内で管理されます。EventとCommunityにMessageが紐づくという構造になりますね。実際にはUserモデルも絡んでますが、本記事では触れません。

## ポリモーフィック関連を利用しない場合
この実装に着手した当初、私はポリモーフィック関連のことを知らなかったため以下のように別々のテーブルを作って共通するロジックはconcernsに切り出そうかなーと思ってました。

```ruby:event.rb
class Event < ActiveRecord::Base
  has_many :event_messages
end
```
```ruby:event_message.rb
class EventMessage < ActiveRecord::Base
  belongs_to :event
end
```
```ruby:community.rb
class Community < ActiveRecord::Base
  has_many :community_messages
end
```
```ruby:community_message.rb
class CommunityMessage < ActiveRecord::Base
  belongs_to :community
end
```

しかし、この状況はそんなに珍しいものでもなく他の人もけっこう同じ問題にぶち当たってるだろう、みんなはどうやって解決しているのかなーと思い、調べてみたらポリモーフィック関連のことを知りました。ポリモーフィック関連について書かれた記事をいくつか読んで、やや批判的な意見の方が多かった気がしましたが、Railsでもサポートしている仕組みだし、アンチパターンを回避して実装すれば良さそうに思えたので、ポリモーフィック関連を利用して実装することを決めました。

## 実装した内容
ポリモーフィック関連を利用して以下のように実装しました。
※実際にはメソッドがいくつかありますが省略してます

```ruby:event.rb
class Event < ActiveRecord::Base
  include Messageable
end
```
```ruby:community.rb
class Community < ActiveRecord::Base
  include Messageable
end
```
```ruby:messageable.rb
module Messageable
  extend ActiveSupport::Concern
  included do
    has_many :messages, as: :messageable, dependent: :destroy
  end
end
```
```ruby:message.rb
class Message < ActiveRecord::Base
  belongs_to :messageable, polymorphic: true
end
```

## メリットに感じたこと
まず最初にメリットと思ったことは、コーディング量が少なくすんだことですね。必要なバリデーションやメソッドはmessage.rbに書けばよいし、変更があったときもmessage.rbを修正すればよく、上記のポリモーフィック関連を利用しない場合のようにevent_message.rbとcommunity_message.rbの２つに対して実装する必要がありません。

そして、EventとCommunityという関連先を意識しながら実装する必要がなかったというのも思ったより実装が楽でした。これは作業量が減って楽になったというよりも気が楽になったという感じです。MessageからEventもしくはCommunityのidを取得したいときは、message.messageable.idと書け、頭の中でEventの場合とCommunityの場合を思考しなくても良いという安心感がありました。

私のようにまだまだオブジェクト指向できちんと実装できない人間にとっては、Railsが用意してくれたポリモーフィック関連の仕組みに乗っかることで、このロジックはどこに書くべきかを考えたときに実装場所を誘導してくれて、結果、整理された実装になりました。この経験でオブジェクト指向についての理解が一つ深まった気がします。

## デメリットに感じたこと
他のポリモーフィック関連について書かれている記事の中でも指摘されてますが、外部キー制約を張ることができないのはデメリットに感じました。例えば、Messageに格納されているEventのidがeventsテーブルに存在しなかった場合、RailsではそのEventを取得しにいった時にnot foundで404ページに遷移してしまいます。そうなるとメッセージ一覧を表示できないといった状況に陥る場合もあります。そうならないように`dependent: :destroy`で依存関係を作っていますが完全に防げるわけではないので、やはりDBで確実に防いで安心しておきたいと思いました。ちなみに、本番リリース後に上記のようなエラーはまだ起きていません。

保守運用という観点では、メンバーのポリモーフィック関連に対する理解が重要だと思いました。ポリモーフィック関連を理解していない人がソースコードを更新すると、そもそも意味がない実装になってしまったり、かえって複雑な実装になってしまったりする危険性があります。ポリモーフィック関連を利用していることをチームメンバーに共有したり、ソースコード上にコメントで記載しておいたり、ポリモーフィック関連という言葉をまず伝え、それを理解してからソースコードを更新しなければならないということを伝える必要があります。私のようにポリモーフィック関連を知らなかった人は実装前にまず「理解する」ということに時間を使うことになりますが、これを機に勉強すれば成長になるのでそれはそれで良いかと思います。

## まとめ
私がまだ遭遇していないデメリットも沢山あると思いますが、ポリモーフィック関連について注意点も理解した上で利用すれば、コードが整理されるし変更に強くなるため有用かなと思います。
ユーザの行動分析用ログを組み込む上で注意すべきこと

![eyecatch_1712AdventCalendar_header.png](https://qiita-image-store.s3.amazonaws.com/0/192832/31c24b14-4273-9412-d1f7-f72100b57ed1.png)


これは [ドリコム Advent Calendar 2017](https://adventar.org/calendars/2575) の19日目です。
18日目は ohr486 さんによる、 [escript how to](https://qiita.com/ohr486/items/ab8c69fdc5358e649fd8) です。
　
　
　

こんにちは。
2017年4月から新卒で入社した秦と申します。
普段の仕事は、サーバーサイドエンジニアとして機能開発を行ったり、
施策の分析業務を行ったりしています。

本記事では、新卒の私が感じたソーシャルゲームの新機能開発時における、
ユーザの行動分析用ログを組み込む際の考え方とその際の注意点について記していきます。

ごくごく当たり前のことかもしれませんが、
分析用ログの実装を考えている方、新人エンジニア、新人分析者の
お役に立つことができれば幸いです。
　
#はじめに
はじめにサマリーと注意点について記します。
##サマリー
```
1.新機能における達成したいことを把握する
2.達成したいことに必要なデータをログに落とし込む
3.定点観測も大事
4.分析者の方と相談、認識合わせをしよう
```
##注意点
もっと良いやり方はあるかもしれませんが、
新卒１年目の私が感じたことベースで書いていますのでお手柔らかに。
　　
　
　
　
では、本題に入っていこうと思います。
実際に組み込む際の流れと共に書いていこうと思います。


#新機能における達成したいことを把握する
まずは新機能における、達成したいことを把握します。
そうしなければ、何を見ればその新機能における
やりたいことを達成できたか確認できないからです。

例えば、キャラクターの強化機能が新機能として実装されたとします。
この時、

- どのキャラクターが多く強化されているのか
- 1日どのくらい強化機能が使われているのか
- 強化画面に遷移した人数は何人か

など、たくさん見たい項目が出てくるかと思います。
しかしこれらはひとつの指標に過ぎず、「新機能における達成したいこと」が
達成されているか判定できる指標かもしれませんし、そうでないかもしれません。
　

では関係ありそうな指標を全部出しておけば良いのではないか？
私も初めはこのように考えていたことがありましたが、これには以下のような問題点があります。

1. ログサーバーの容量圧迫
2. 本当に必要な情報が取れない場合がある

1については言わずもがなですが、
2については、ログの詳細に関わる部分です。

実際にログを組み込む際は、紐づけておかなければならないデータがあります。
代表的な例だとユーザidですね（ユーザの行動分析用ログなので当たり前ですが）。
このような紐づくデータが、必要なタイミングで必要なデータと共に
取得できていない場合があります。
　

例えば、強化画面に遷移した人数をカウントするためのログを作ろうとします。
その場合、遷移したタイミングにユーザidを取得すれば人数をカウントすることができます。

しかし分析時、ユーザのレベルごとの強化画面に遷移した人数が必要になったとします。
この場合、ログを組み込む段階でレベル情報も付け加えておかなければなりません。

このように一見、「強化画面に遷移した人数」が見たい項目だと思っていたが、
実際は「強化画面に遷移したレベルごとの人数」が見たかったということになってしまいます。
　

以上のように、見たい項目だけでなく、
それを詳細に分解した上で考えなければ必要な情報の抜け落ちにつながります。
結局は達成したいことを把握しようということにつながりますね。

ログを作る際は機能を考えた方と会話をし、
何を目的としこの機能を実装したのかを把握するようにしましょう。


#ログの状態へ落とし込む
達成したいことを把握できたら、それに必要な見るべき指標は何かを考えましょう。
また、見るべき指標が決まったら、それを取得するべきタイミングと必要なデータを考えます。

例えば、上述と同じようにキャラクターの強化機能が新機能として実装されたとします。
ここで達成したいことが、
「既存ユーザがよりゲームに定着し、高難度なステージを楽しめるようになる」
だとします。
この場合、以下の二つに分解できます。

- 既存ユーザがよりゲームに定着
- 高難度なステージを楽しめる

そしてこれらは、このような指標で判断できると思われます。

- 既存ユーザがよりゲームに定着　→　継続率
- 高難度なステージを楽しめる　　→　高難度ステージの参加率

このように、達成したいことを見るべき指標に落とし込みます。

また、これらを取得するタイミングと必要なデータを考えます。
強化機能により、継続率が上がったかどうかを判定するためには、
強化を行ったユーザを調べる必要があります。

ですので、この場合は強化処理時にユーザidが入ったログを
出力する必要があるということになります。

また、これらをレベルごとに分けて分析したい場合はレベル情報も必要になってきます。
このように、見たい分析項目とそれに必要なデータは何かを考えながら、
ログの状態に落とし込みます。


#定点観測したい値について考える
散々達成したいことを考えようという話をしてきましたが、
とはいえゲームバランスのためや、お問い合わせ対応のためにログを残したい場合もあります。

そこで、達成したいこととは別に、定点観測したい値については別途取る必要があります。
ここでも注意すべきはログサーバーの容量を考えつつ、
必要最低限に収まるよう考えるようにしましょう。

#ログのフォーマット、スケジュールを分析者と相談する
これには２つの理由があります。

１つ目は分析しやすいログにするためです。
ログサーバーの容量を気にするあまり、ログで出すデータを絞り、
後からたくさん結合しようとすると分析作業面でのコストがかかりすぎます。

かといって先ほどから述べている通り、必要そうなデータを全て取得してしまうと
ログサーバーの容量圧迫につながってしまいます。

必要なのはバランスです。
分析者の方に意見をもらいながら一緒に作っていきましょう。
　

２つ目は分析用スクリプト作成のためです。
事前にフォーマットを決めておかなければ、分析用スクリプトを作成することができず、
後回しにするとリリース後すぐに分析結果を見ることができません。

当たり前ですが分析者の方にもスケジュールがあるので、
いつ頃、どういったフォーマットで、ログが出力するのかを相談しましょう。

#さいごに
いろいろ書きましたが、これは私が新卒で働き始めてから感じた個人の意見です。
正しいかどうかはわかりませんが、１つだけは絶対に自信があります。
それは

「分析者の方との相談は必須」

ということです。

みなさん協力し合って良いものを作っていきましょう！！
postgresql：ログインせずに中身を削除してインポートするコマンド備忘録

たまに使うけど絶妙な頻度なので忘れてる


# コマンド
```
psql -U ユーザー名 -d DB名 -c "drop schema public cascade" # 中身削除
psql -U ユーザー名 -d DB名 -c "create schema public" # schema作成
psql -U ユーザー名 -d DB名 < ./tmp/dump_20170101.sql # sqlファイルインポート
```

# オプション
|オプション名|説明|
|---|---|
|-U|ユーザー名を引数で指定する|
|-d|DB名を引数で指定する|
|-c|実行したいsqlを引数で指定する。ダブルクォーテーションで囲む。セミコロンは入れておいた方が無難かも。今回の肝。|

# sql
|sql|説明|
|---|---|
|drop schema public cascade|publicという名前のschemaを削除し、その際にcascadeオプションを指定することでpublic schemaに含まれるオブジェクト（テーブル、関数など）も削除する|
|create schema public|publicという名前のschemaを作成する|

# 用語
|用語|説明|
|---|---|
|schema|dbを格納する場所。一つのschema内に複数のdbを作成することが可能。階層みたいなもの。|
|public|schema名。publicと名付けられたschemaはどのユーザーからでも操作できるschemaになる。多分予約されていてそういう機能を実現できているんだろうけど自信無い。。|
|cascade|dropコマンドのオプション。schemaに含まれるオブジェクト（テーブル、関数など）も削除する|


# まとめ
普段はpublic schemaしか触らないため気にする機会が無かったので調べてみました。

* -c オプションでログインせずに操作できる
LTSVフォーマットから該当の項目のみを抽出

# 概要
アクセスログをLTSVフォーマットに変更した。
既存のログと大きな違いは以下の２点

* タブ区切り
* ラベルが付けられる

今までgrepやawkを駆使して該当項目を抽出していたが、
lltsvコマンドをインストールすることにより、作業がグッと楽になった。

# 使い方

例えば以下のようなアクセスログがあるとする。

``` log
time_local:11/Dec/2017:12:09:25 +0900	request:"GET /admin/widget/ HTTP/1.1"	http_x_forwarded_for:"-"	uid_got:"-"	req_body_start:""	
time_local:11/Dec/2017:12:09:25 +0900	request:"GET /admin/widget/ HTTP/1.0"	http_x_forwarded_for:"192.168.120.120"	uid_got:"app_uid=060012AC5A99275A050070A502030303"	req_body_start:""	
time_local:11/Dec/2017:12:09:26 +0900	request:"GET /admin/event/ HTTP/1.1"	http_x_forwarded_for:"-"	uid_got:"-"	req_body_start:""	
time_local:11/Dec/2017:12:09:26 +0900	request:"GET /admin/event/ HTTP/1.0"	http_x_forwarded_for:"192.168.120.120"	uid_got:"app_uid=060012AC5A99275A050070A502030303"	req_body_start:""
```

このログから

* time_local
* http_x_forwarded_for

のみを抽出したい場合、以下のようなコマンドで簡単に抽出できる

```
# tail access.log | lltsv -k time_local,http_x_forwarded_for

time_local:11/Dec/2017:12:09:22 +0900	http_x_forwarded_for:"-"
time_local:11/Dec/2017:12:09:22 +0900	http_x_forwarded_for:"192.168.120.120"
time_local:11/Dec/2017:12:09:22 +0900	http_x_forwarded_for:"-"
time_local:11/Dec/2017:12:09:22 +0900	http_x_forwarded_for:"192.168.120.120"
time_local:11/Dec/2017:12:09:24 +0900	http_x_forwarded_for:"-"
time_local:11/Dec/2017:12:09:24 +0900	http_x_forwarded_for:"192.168.120.120"
time_local:11/Dec/2017:12:09:25 +0900	http_x_forwarded_for:"-"
time_local:11/Dec/2017:12:09:25 +0900	http_x_forwarded_for:"192.168.120.120"
time_local:11/Dec/2017:12:09:26 +0900	http_x_forwarded_for:"-"
time_local:11/Dec/2017:12:09:26 +0900	http_x_forwarded_for:"192.168.120.120"

# 
```


#インストール方法

```
yum install wget -y
wget https://github.com/sonots/lltsv/releases/download/v0.3.0/lltsv_linux_amd64 -O lltsv
chmod a+x lltsv
mv lltsv /usr/sbin/.

```

# 参考情報
http://blog.livedoor.jp/sonots/archives/39628163.html
http://tech.mercari.com/entry/2017/05/09/152428
GovHackに参加して、Code forを知っておもったこと。

大学生のしげるです。ただの大学生です。地域活性化活動についての考えをまとめます。
CODE forとの出会いは、インターン先の社長にCODE for Kusatsuに誘われたのがきっかけです。

CODE forとは別に、2016年度は、大阪の茨木市民の方に大学の図書館を利用してもらうプロジェクトや、2017年度では、草津青年会議所のビジネスコンテスト・滋賀の交通を考えるワークショップにも参加しました。

もともとハッカソンが好きで、[GovHack](http://hackcamp.jp/govhack/)に興味を引かれに神戸・生駒の二箇所に参加ました。
GovHackは、神戸・千葉・生駒・大阪の4箇所で開催されました。
GovHackの作品について、それぞれのCODE forのイメージとGovHackの感想を書きたいと思います。

最終的な結果として、GovHack生駒で作成した郷ろうくんがMA 2ndステージ進出&LINE GovHack賞（LINE）をいただきました。[記事](https://hacklog.jp/events/115)

# CODE forについて
## CODE for Kusatsu
[ホームページ](http://codeforkusatsu.org/)
地域のいろんな人が参加してアットホーム感じです。
ミーティングに市議さんなども参加しており、大学生エンジニアが参加していくとより面白いコミュニティーになると思います。
この記事を読んでいるあなた！チャンスですよ！！

## CODE for Kobe
[Facebook](https://www.facebook.com/codeforkobe/)
CODE for Japan 2017が開催された聖地！
阪神淡路大震災から地域を良くしていこう！みんなで街を変えよう！という意識がすごい高い！
ルミナリエを筆頭に市民活動が活発！

## CODE for Ikoma
[ホームページ](https://www.code4ikoma.org/)
市が率先して[オープンデータ](https://data.city.ikoma.lg.jp/)を進めている
[竜田揚げプロジェクト](https://data.city.ikoma.lg.jp/data/dataset/1487394023)のデータもオープン化されている。市長自らがオープンデータがが必要であると提言している。
他の自治体もこういうデータが欲しいなぁーと思う。
NAISTがあり、田舎だけど先端を行っているいけているCODE for。

## CODE for Yourth
[Facebook](https://www.facebook.com/codeforyouth/)
CODE for Japan2017で発表されたCode for Yourthについても知人が運営をしているので(ﾒﾓﾒﾓ
CODE for Xで活躍する若者を応援する組織みたいです。
設立されてまもないですが、東京・大阪で、オープンデータの活用のセミナーをしているみたいです。
一つのCODE forだとマンネリ化してしまうので、このような横断する組織は非常に良いと思います。

## 思ったこと
- 自治体の協力なしに、市民だけで行なっていくのは難しい。
- 一つの地域じゃなく複数の地域で連携できたら新たな面白いアイディアが出てきてきそう
- 大学の地域活性化を題材にしている教授と連携することができれば、学問の方向から新たな地域に対するIT活用が見えそう
- オープンデータについても、量(人口・生産量等)のデータではなく場所(GPS)が絡んだデータがあれば、活用はしやすい

# GovHackとは
LINE@を活用し、地域活性化を目指すサービスを提供する。市町村の問題も各地少しずつ違ったので面白かったです。


## 作った作品
- モンスター返し
神戸のGovHackで作りました。モンスター市民のクレームを大喜利形式で面白い回答にできると面白いね！というアイディアです。
生活の中で実際にどのように返したらいいかわからない場合もあるので、その時にも対応できるようにしよう！としていました。
実装系で、実装をする形でbotをかけるエンジニアが自分しかいなかったので開発時間が足りず思うようにできませんでした。

- 郷ろう君
郷土史を歩いて巡り、学生への郷土学習・親子参加型のイベント開催・海外から人をターゲットに置いたアプリです。
機能は大きく、目的地を決める・ヒントを出す・ギブアップする・ゴールしたら図鑑に写真を投稿する・図鑑を見るの5つの機能です。
2daysのハッカソンだったのですが、4つの機能が実装完了し、ゲームとしての機能を完了し、GovHack生駒で最優秀賞・GovHack賞をいただきました。
一応全員普段からプログラミングを触っているメンバーが集まっていたので、タスクを分担・終わらせることができました。
[github](https://github.com/4geru/ikoma-hack)


## 面白かった作品
- ゴミなしbot
5374アプリをline botにしてみた！というアプリでした。従来のアプリの機能に加えて、写真で分別の判定をすることができます。

## 参加してみて
それぞれの地域性・課題が見えてきて面白かったです。また、その中で参加しているメンバーの構成どうなのか、実際に何を活動しているのか、という点がCODE for Xが活動していく上で必要だな。
短期的なイベントではなく、長期的なスパンで考えていくこと。一つの地域に固まるのではなく、他の地域とも交流するべきだと感じました。
linux：tar.gzファイルを扱うコマンド備忘録

たまに使うけど絶妙な頻度なので忘れてる

# 圧縮
```
tar zvfc 既存のディレクトリ名 新規作成するファイル名.tar.gz
```

# 解凍
```
tar zvfx ファイル名.tar.gz
```

# オプション
|オプション|説明|必須かどうか|
|---|---|---|
|z|gzipを使用する|gzipにしたい場合○|
|v|プログレスを表示する||
|f|ファイル名を指定するかどうか|○|
|x|解凍|解凍したい場合○|
|c|圧縮|圧縮したい場合○|  

# 覚え方
* オプションにはハイフンを付けない
* 圧縮はcオプション（createの頭文字？）
* 解凍はxオプション（何の頭文字か不明）
* zvfオプションは圧縮と解凍で共通と覚える
* tar zvf+cもしくはxで覚える
[WordPress] マルチサイト設定で JSON REST API へのリクエストがリダイレクトループしてしまう

発端は、長らくバージョンアップを放置されていたサブディレクトリ型マルチサイト設定の WordPress をバージョンアップして、[Contact Form 7](https://ja.wordpress.org/plugins/contact-form-7/) もバージョンアップしたら動かなくなったという問い合わせから。
Contact Form 7 Ver.4.8 からは、Ajax フォーム送信時に [WordPress REST API](https://developer.wordpress.org/rest-api/) を使用するようになったので、それが原因で動作しなくなっていたのでした。
[私のサイトでは REST API が無効化されています。Contact Form 7 を使うことはできますか](https://contactform7.com/ja/faq/rest-api-is-deactivated-on-my-site-can-i-use-contact-form-7/)

ただ、このサイトでは JSON REST API を無効にするようなプラグインとか入れていたわけではないのですが、`/wp-json/contact-form-7/v1/contact-forms/4/feedback` へのリクエストが `500 (internal server error)` を返してしまい、送信できないような状態。
Apache のログ見ると、どうやらリダイレクトループが発生しているようです。

```
[Fri Dec 08 21:05:41 2017] [error] [client xxx.xxx.xxx.xxx] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace., referer: http://example.com/hoge/contact/
```

ってことで、[codex](https://codex.wordpress.org) を確認。[htaccess](https://codex.wordpress.org/htaccess)
はい、もう答えが書いてありましたね。
WordPress マルチサイト版では、JSON REST API 導入前後で .htaccess の記述方法が変わります。

```text:3.5_and_up
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
```

肝は `RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]`
以前は、これ `RewriteRule  ^([_0-9a-zA-Z-]+/)?(wp-.*) $2 [L]` だったはず。
古いバージョン用の .htaccess だと、`/{子サイト}/wp-json/*` へのリクエストがリダイレクトループしちゃうんです。

怪しげな2次情報とか調べずにまずは codex やプラグインのサポートサイトを調べましょうというお話でした。
zshでvimVim+Tabでエラーになる場合の対処法(zplug編)


zsh + zplug 環境で vimでファイル名補完をしようとして突然できなくなったときの対処法です。

ここ数週間で2回ハマったのでメモ :sob: 

# 事象

```shell-session
vim ~/dotf # ここでTab補完しようとする

_arguments:451: _vim_files: function definition file not found
```

# 解決方法

zplugのホームディレクトリにある`zcompdump`ファイルを削除する。

```
rm -fr $ZPLUG_HOME/zcompdump
exec $SHELL -l
```

## ※ハマった内容
- HOMEディレクトリにも`.zcompdump`があったので、消しても解決せず。
- find / --name ".zcompdump"でも `.`がついているので、 `~/.zcompdump` しか見つからず。
- `ZPLUG_HOME`のデフォルトは[~/.zplug](https://github.com/zplug/zplug/blob/master/doc/guide/ja/README.md#4-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)
  - 自分の場合は、[dotfile](https://github.com/bob1983/dotfiles/blob/master/zsh/zplug.zsh)でHOMEを変更していたので `rm -fr ~/.zplug/zcompdump` で解決せず。


# 参考

- zplugを使用していない場合は、[こちら](https://qiita.com/Asuforce/items/28b287fdb933d1985e15)が参考になります。

# 備考
そもそもこの事象が発生する要因って何ででしょうね :thinking:
Phalcon VoltテンプレートでVue.jsを使う

[ソニックムーブ](https://www.sonicmoov.com/)で、マークアップしたりJavascriptをかじったりしてるココエです。
弊社では、サイト構築の際、高確率で[Phalcon](https://phalconphp.com/ja/)フレームワークが採用されるわけですが、その際Phalcon　フロントエンドで利用されるテンプレートエンジンVoltと[Vue.js](https://jp.vuejs.org/)と一緒に利用して困った点をあげます。

・・・まあ、困った点といっても、1点だけなんですけどねｗ

# Phalcon VoltとVue.jsは、式展開が二重中括弧

[Phalcon](https://phalconphp.com/ja/)のテンプレートエンジン[Volt](https://docs.phalconphp.com/ja/3.2/volt)。
「基本的な使用法」の章を引用。

> Basic Usage
> A view consists of Volt code, PHP and HTML. A set of special delimiters is available to enter into Volt mode. {% ... %} is used to execute statements such as for-loops or assign values and {{ ... }}, prints the result of an expression to the template.

Google翻訳
> 基本的な使用法
> ビューは、ボルトコード、PHPとHTMLで構成されています。特別なデリミタのセットは、ボルトモードに入るために利用可能です。{% ... %}for-loopsや値の代入などの文を実行し{{ ... }}、式の結果をテンプレートに出力します。

つまり、二重中括弧（Mustache）で式の結果だしますよーって書いてあります。

そして、[Vue.js](https://jp.vuejs.org/)。
[テンプレート構文・展開の章](https://jp.vuejs.org/v2/guide/syntax.html)を引用

> データバインディングのもっとも基本的な形は、”Mustache” 構文(二重中括弧)を利用したテキスト展開です:

というわけで、**VoltもVue.jsも、式展開が二重中括弧(Mustache)になる**ので、VoltかVue.jsが二重中括弧以外の式展開をさせる必要があるわけです。

# Vue.js delimitersオプション

回避方法として、Vue.jsのdelimitersオプションを利用するのが良いと思います。

https://jp.vuejs.org/v2/api/#delimiters

```html

<div id="app">
  <%- hoge %>
</div>

<script>
new Vue({
  delimiters: ['<%-', '%>'],
  el: '#app',
  data: {
    hoge: 'ほげほげ'
  },
});
</script>
```
delimitersオプション`Array<string>`に指定する配列値、
index　0 には、`{{`に該当する記号を、index　1　には、`}}`に該当する記号を指定します。

## delimitersオプションはコンポーネントレベル

delimitersオプションは、コンポーネントレベルのオプションなので、new Vueしているrootに設定しただけでは、すべてのコンポーネントのdelimitersを変換してくれません。

※うまくいかない例：
https://jsfiddle.net/kokoe/5ezx7Low/
`<%- fuga %>`って文字列として出力されてますね。

## グローバルMixinにdelimitersオプションを指定しちゃう

こういうケースは、もう[グローバルMixin](https://jp.vuejs.org/v2/guide/mixins.html#グローバルミックスイン)でelimitersを指定しちゃっていいんじゃないかと思います。

```
Vue.mixin({
  delimiters: ['<%-', '%>'],
});
```
公式の説明にも記載されていますが、
上記の例だと`<%- %>`で展開される構文を使うサードパーティと併用できないので、
本当にグローバルMixinを使っていいのかは、ちゃんと全体設計を考えた上で指定したほうがいいかもしれませんね。
（まあ、こんなケース自体あんまりないと思いますが。。あとdelimitersで指定する記号を再考するとか。）

# まとめ

```
Vue.mixin({
  delimiters: ['<%-', '%>'], //配列値は、開発環境に合わせて変えてくださいね
});
```
で、おおよそ解決。
[初心者向け] 実務開始の前に知っておきたいAWSのこと


この投稿は、チュートリアルを終えて実務に入る前の人に知っておいて欲しいことをまとめています。
チュートリアルは終えている前提なので、AWSのサービスに関する説明は省略しています。
ベンチャー企業の複数あるうちの1サービスくらいの規模感のアプリケーションを構築すること（移行ではない）を前提としています。
社内メンバー宛なので偏りがあるかもしれないですが、みなさまの役にも経てば幸いです。

## 設計に役立つツール
AWSを実務で利用する際は、構成図を書くかと思います。その際に利用できるのが [Cloudcraft](https://cloudcraft.co/) です。
構成図とともに料金もざっくりわかります。
![cloudcraft例.png](https://qiita-image-store.s3.amazonaws.com/0/68146/4e139b81-c610-d380-c445-bcccf6e91b31.png "cloudcraft例.png")

もっと詳細に料金を出す必要があるならば、AWSが提供している料金計算ツールを使うと良いかもしれません。
[SIMPLE MONTHLY CALCULATOR](http://calculator.s3.amazonaws.com/index.html?lng=ja_JP)

また、サーバーレス構成を検討している方は、re:Invent2017で発表された「[AWS Serverless Application Repository](https://aws.amazon.com/jp/serverless/serverlessrepo/)」を利用すると構成案が公開されていますので、参考になると思います（2017年12/11時点ではまだpreview版）

## リザーブドインスタンス
リザーブドインスタンスはEC2やRDSのようなサービスで、前払いをすると料金を節約)できる制度です。 (参考: [AWSリザーブドインスタンスについて](https://qiita.com/katsukii/items/ae2e88d36be1253f3cfa))
インスタンスタイプや期間によりますが、「半年以上使うことが決まってるなら、1年分はリザーブドインスタンス買っちゃった方がお得」ということも少なくありません
ただし、リザーブドインスタンスはリージョン（もしくはアバイラビリティーゾーン）ごとで、インスタンスタイプも指定するので、インスタンスを立て直したり、何も知らずにインスタンスタイプを変更してしまうと「リザーブドインスタンスを買っているのに使えてない」状態になりえます。
リザーブドインスタンスは売買もできますし、t2.small2つをt2.medium1つに変更などもできるので、一度買ったらできるだけ今の構成を追随するようにしましょう。

## IAM
IAMはAWS内の権限をつかさどるサービスです。各種サービスへの参照・書き込み・実行などを細かく設定できます。
権限を操作できてしまうので、一度作るとなかなか変更するのが怖いところです。
ここでのtipsはポリシーはできるだけ細かく設定することです。めんどくさいですが、サービスAのs3参照ポリシーとサービスBのs3参照ポリシーは分けた方が良いと思います。たとえ1つしかサービスをローンチしてなくても、サービスAに限定するようなポリシーを設定しておきましょう。
最小単位であるポリシーが細かければその組み合わせで柔軟に設定が可能です。

## awsを操作するためのツール
- [aws-cli](https://aws.amazon.com/jp/cli/) ... コマンドラインからawsを操作できる
- [ansibleのec2.py](http://docs.ansible.com/ansible/latest/intro_dynamic_inventory.html) ... ansibleでipを指定するのではなく、ec2についているタグ名で絞ってec2をプロビジョニングするためのツール（というかpython script）


## 最後に
クラウドになるとlinuxではないもの(IAMやセキュリティグループなど)の設定をたくさんしなければならず、(aws-cliもありますが）guiでの設定も増えてしまいます。
面倒な部分はありますが、慣れてしまえば早いですし、コスパもよいのでどんどん利用していきたいですね
では、よいaws lifeを

## [初心者向け] 実務開始の前に知っておきたいシリーズ
[[初心者向け] 実務開始の前に知っておきたいSpreadSheetのこと](https://qiita.com/vankobe/items/5bcd2ca38f289bb9b98f)
[[初心者向け] 実務開始の前に知っておきたいAnsibleのこと](
https://qiita.com/vankobe/items/5dc71bc0ab52114b34d6)
[[初心者向け] 実務開始の前に知っておきたいGoogleAnalyticsのこと](https://qiita.com/vankobe/items/2ef45365c190d154103b)
[[初心者向け] 実務開始の前に知っておきたいWordPressのこと](https://qiita.com/vankobe/items/bc16ec597cf7cf37c348)
[[初心者向け] 実務開始の前に知っておきたいRailsのこと](https://qiita.com/vankobe/items/f7e7b2592fcb3c51988f)
Qiitaの通知画面のリンクをすべて開くブックマークレット

```javascript
javascript:%20document.querySelectorAll('.notification_link').forEach(a%20=>%20window.open(a.href));
```

https://qiita.com/notifications
でお使いください。
アドベントカレンダーを開くだけでも大変だぜ。

Firefox57になり、グリモンが4になり…新規UserScriptの作り方がわからないのでブックマークレットです。

スクラッチパッドからの実行ではポップアップブロック。
ブックマークレットだとセーフのもよう。
`getElementsByClassName`では`HTMLCollection`なので`forEach`できない。
Djangoでユーザー作成フォームをクラスベースで作る方法

Djangoでユーザー作成フォームを作成するための資料が少なく、個人的に納得する記事がなかったためまとめた。
メソッドとして実装している例は複数あったのだが、クラスとして実装したほうがスマートだと思ったため、できるだけ無駄な実装を省くように記述した。

**Django1.11**でテストした内容だが、ある程度の上下は問題ない。

# djangoでデフォルト設定のユーザーを作成する方法  

```myapp/view.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.views.generic import CreateView
from django.urls import reverse_lazy

class UserCreateView(CreateView):
  model = User
  form_class = UserCreationForm
  success_url = reverse_lazy('login') # urls.pyのnameを指定
  # template_nameのデフォルトはtemplates/auth/user_form.html

  def get_success_url(self):
    return reverse('login') 
```

```myapp/urls.py
urlpatterns = [
  url(r'user_creation$', views.UserCreateView.as_view(), name = "user_creation"),
]
```

```templates/auth/user_form.html
{% extends "base.html" %}

{% block contents %}
  <h1>Create User</h1>

  <form method="POST" action="">
    {% csrf_token %}

    {{ form.as_p }}

    <input type="submit" id="save" value="Save">
  </form>

{% endblock %}
```

これで、デフォルトのユーザー作成フォームができる。  

# カスタマイズしたユーザー作成フォームを作る方法(今後追加予定)  

1. 使用するフォームを変えたい場合
  [UserCreationForm][]を継承し、新しいフォームを`form_class`に設定する
2. 使用するモデルを変更したい場合
  `User`を継承し、新しいモデルを`model`に設定する


[UserCreationForm]:https://github.com/django/django/blob/16411b8400ad08f90c236bb2e18f65c655f903f8/django/contrib/auth/forms.py#L63
cesiumでskybox

#概要

#写真
![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/cc8bcc80-409a-58ba-9c84-0c4fea29903c.png)

#サンプルコード

```
var urls = [
    'http://jsrun.it/assets/Q/A/A/R/QAARR.jpg',   
    'http://jsrun.it/assets/I/H/N/E/IHNEH.jpg',
    'http://jsrun.it/assets/0/T/e/l/0TelF.jpg',
    'http://jsrun.it/assets/A/E/O/S/AEOSa.jpg',
    'http://jsrun.it/assets/O/g/r/5/Ogr5i.jpg',    
    'http://jsrun.it/assets/6/s/G/E/6sGEA.jpg'];

var widget = new Cesium.CesiumWidget('cesiumContainer', {
    skyBox : new Cesium.SkyBox({
        sources : {
          positiveX : urls[1],
          negativeX : urls[3],
          positiveY : urls[4],
          negativeY : urls[2],
          positiveZ : urls[0],
          negativeZ : urls[5]
        }
    })
});

```

#成果物
http://jsdo.it/ohisama1/MvN6

以上。
glslで疑似ディスプレイメントマップをプロシージャルにやってみる

# はじめに 
[GLSL シェーダスクール 2017](https://webgl.souhonzan.org/entry/?v=1068) の講義内容の復習を兼ねて、複数の講義内容を組み合わせてやってみます。

# まず、背景となる市松模様のパターンを作ります。

![ichimatsu.png](https://qiita-image-store.s3.amazonaws.com/0/135381/49580a6a-db8f-6dc4-a3ca-c6139d40459d.png)

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	p*=4.;
	float l = mod(floor(p.x)+floor(p.y),2.0);
	gl_FragColor = vec4(vec3(l), 1.0);
}
```
https://goo.gl/EQ8tPy

# 次にハイトマップを作りましょう
今回は水面の波紋をイメージして作っています。
![ripple.png](https://qiita-image-store.s3.amazonaws.com/0/135381/2a6c8709-d092-3b72-fda3-f8bffea5545c.png)
https://goo.gl/hC2MHH

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float d=sin(length(p)*30.-t*10.);
	gl_FragColor = vec4(vec3(d), 1.0);
}
```

注意点としては、プロシージャルにヘイトマップを作る場合は、テクスチャーで用意する場合と違って-0.5してマイナスの値を作る必要がないというところです。

# 合成しましょう。
![ripplewater.png](https://qiita-image-store.s3.amazonaws.com/0/135381/1f03a164-6f21-903c-5e51-d974d2b69143.png)
https://goo.gl/1XmQ6Q

```glsl
precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

void main(void){
	vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
	float d=sin(length(p)*30.-t*10.);
	p+=d*.1;
	p*=4.;
	float l = mod(floor(p.x)+floor(p.y),2.0);
	gl_FragColor = vec4(vec3(l), 1.0);
}

```

このままだと、ずっと波紋の高さが一緒のままですので、距離に応じて減衰するようにしてもいいでしょう。

# 最後に
疑似ディスプレイスメントマップめっちゃ簡単ですね。

応用して、ノイズ関数で雲模様を作ってヘイトマップとして適用すると水面の揺れを再現できたり
ヘイトマップをパーティクルにすると、水滴の表現や、炎の陽炎の表現が出来たりするので色々ためしてみましょう！

# 参考
* [GLSL 音に反応する波紋エフェクト](http://puarts.com/?pid=1226)
* [床井研究室 第１２回 模様を付ける](http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090920)
GoogleHomeとGoogleHomeMini

GoogleHomeを購入し色々やっていましたが、先日の半額セールでついうっかりGoogleHomeMiniを購入してしまい、2台環境になりました。
使ってて感じたGoogleHomeとGoogleHomeMiniの違いをメモりました。

## おうち環境

- 2DKです
- GoogleHomeは寝室ベッド付近
- GoogleHomeMiniはダイニングのテーブル
- 寝室にNatureRemo
    - テレビ、照明、エアコンをIFTTT経由で操作可
- 寝室テレビにchromecast刺してる

## セットアップ

セットアップは寝室で行ったため、一時的に2台が同じ部屋にある状態
この時「OKグーグル」と話しかけると両方が反応した
が、その後のレスポンスは片方からのみ返ってきた

例
「OKグーグル」 → 両方反応
「今日の天気は？」 → GoogleHomeMiniが天気を教えてくれた

この時の物理的な距離はGoogleHomeMiniのほうが近かった
単純に距離かは不明
それぞれ別アカウントに紐付いた状態でやったときは両方が返すのかな？

## 違い

### ウェイクワードへの反応
    
- GoogleHome：光る、音がなる
- GoogleHomeMini：光る

~~この違いが微妙にストレス。
GoogleHomeMiniの場合、ちゃんと反応したか見ないとわからないので別のことをしながら話しかけづらい。
GoogleHomeの場合、音がなるので 認識した/認識しなかった わかるのでやり直しもスムーズ。~~

デバイス → GoogleHomeMiniの設定 → ユーザー補助機能 → 「リクエストの開始時」「リクエストの終了時」をオン

### マイクの性能

今のところこれが一番大きいかもしれない
寝室のドアを開けたままダイニング側で「OKグーグル」と言うと、Miniも反応するのだが寝室のGoogeHomeから「ピコ」と音がなる
かといって小声で話しかけるとMiniすら反応しないなど

## 良かったこと

### ニュースの続きが聞ける

朝起きて「OKグーグル、おはよう」と言うと天気、予定、ニュースを読み上げてくれる。
ニュースが再生されている頃にベッドから抜け出してダイニングで朝食を摂るので一旦「OKグーグル、停止」で止める。
ダイニングで「OKグーグル、ニュース」と言うと先程再生されていた続きが再生される。

### 寝室の照明をダイニングから操作できる

NatureRemoが寝室にしかないので「OKグーグル、電気消して(つけて)」は寝室の照明
出かける直前だったり帰宅時に寝室の照明を切り替えられるのが地味に便利。エアコンも同様に

## 気にならないこと

### スピーカー

音質に拘る人ではないのでGoogleHomeとGoogleHomeMiniの音質はそんなに気にならない。どちらでも音楽聴ける。
chromecastでテレビに飛ばして音楽聞くと流石に音質圧倒的に良いが。


## まとめ

やはり~~ウェイクワード反応で音鳴らしたいのと、~~マイク性能が気になる
半額の3000円＋税だった前提であれば十分良し
GoogleHomeかGoogleHomeMiniだったらGoogleHomeをおすすめすると思う
Project Euler Q43 【部分文字列被整除性】

Project Eulerをワンライナーで解いてみる。
間違っていたらコメントください。


## 問題
数$1406357289$は$0$から$9$のパンデジタル数である ($0$から$9$が$1$度ずつ現れるので). この数は部分文字列が面白い性質を持っている.

$d_1$を上位$1$桁目, $d_2$を上位$2$桁目の数とし, 以下順に$d_n$を定義する. この記法を用いると次のことが分かる.

$d_2d_3d_4=406$ は $2$ で割り切れる
$d_3d_4d_5=063$ は $3$ で割り切れる
$d_4d_5d_6=635$ は $5$ で割り切れる
$d_5d_6d_7=357$ は $7$ で割り切れる
$d_6d_7d_8=572$ は $11$ で割り切れる
$d_7d_8d_9=728$ は $13$ で割り切れる
$d_8d_9d_{10}=289$ は $17$ で割り切れる

このような性質をもつ$0$から$9$のパンデジタル数の総和を求めよ.

## 解答

```bash
seq -w 17 17 987 |
awk '{for(i=1;i<=int(987/7);i++){printf("%03d%03d\n",7*i,$1)}}' |
awk '{for(i=1;i<=int(987/2);i++){printf("%03d%06d\n",2*i,$1)}}' |
awk 'substr($1,6,3)%13==0' |
awk 'substr($1,5,3)%11==0' |
awk 'substr($1,3,3)%5==0' |
awk 'substr($1,2,3)%3==0' |
awk -v FS= '{delete a;for(i=1;i<=NF;i++){a[$i]+=1;b[NR]+=$i};print $0,length(a),b[NR]}' |
awk '$2==9{print (45-$3)$1}' |
awk '{s+=$1}END{print s}'
16695334890
```

`seq 9876543210`とかやればスッキリするだろうけど、時間かかってしまうからさすがに難しい。。

## 答え合わせ
こちらのサイト様と一致していればOKとした。
http://kingyojima.net/pje/043.html
2017年のAdventCalendarで面白そうなのをピックアップ

[テコテックAdventCalendar2017](https://qiita.com/advent-calendar/2017/tecotec)の17日目の記事です。

個人的に面白そうだと思ったカレンダーをピックアップしてみます！
タイトルだけみて面白そうだと思ったのも入っているので、内容は保証しません！
Adventarのほうが制約ないぶん面白そうなのが多いですねー

# Qiita
Kotlin
https://qiita.com/advent-calendar/2017/kotlin

Go
https://qiita.com/advent-calendar/2017/go

D言語くん
https://qiita.com/advent-calendar/2017/d-man

BlockChain
https://qiita.com/advent-calendar/2017/blockchain2017

暗号通貨
https://qiita.com/advent-calendar/2017/cryptocurrencies

技術系同人誌
https://qiita.com/advent-calendar/2017/tech-fanbook

体育会系エンジニア
https://qiita.com/advent-calendar/2017/athlete

初老丸
https://qiita.com/advent-calendar/2017/syoroumaru

ひとりでCPUとエミュレータとコンパイラを作る
https://qiita.com/advent-calendar/2017/lowlayer

クソアプリ
https://qiita.com/advent-calendar/2017/kuso-app2017

eeic （東京大学工学部電気電子・電子情報工学科）
https://qiita.com/advent-calendar/2017/eeic

Yahoo! JAPAN Tech
https://qiita.com/advent-calendar/2017/yahoojapan-tech

# Adventar
Raspberry Pi
https://adventar.org/calendars/2075

Sansan
https://adventar.org/calendars/2530

登壇者
https://adventar.org/calendars/2198

心
https://adventar.org/calendars/2750

経理関係ネタでも
https://adventar.org/calendars/2745

脳みそ溶かされた音楽
https://adventar.org/calendars/2086

ウイスキー
https://adventar.org/calendars/2219

今年行ってよかったところ
https://adventar.org/calendars/2241

今年買ってよかったもの
https://adventar.org/calendars/2240

はの飯
https://adventar.org/calendars/2477

ドイツのトリ
https://adventar.org/calendars/2074

---
他にも面白そうなのがいっぱいあると思います。
みなさんもお気に入りを探して、AdventCalendarを楽しみましょう！
flexの縦レイアウト


## 上下左右中央寄せ

Demo : https://codepen.io/mo4_9/pen/pdXBmR

![スクリーンショット 2017-12-11 10.25.28.png](https://qiita-image-store.s3.amazonaws.com/0/136286/43a4361f-b88b-1f20-57cd-14c9a3077784.png "スクリーンショット 2017-12-11 10.25.28.png")


```css
.item__inner{
  // 縦に積む
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  // 中央寄せ
  justify-content: center;
  align-items: center;
}
```

## 縦の比率を維持して伸縮

Demo : https://codepen.io/mo4_9/pen/oorVoY

![flex.gif](https://qiita-image-store.s3.amazonaws.com/0/136286/54d0f7b0-5f30-d14e-e8d9-a706122b9250.gif "flex.gif")


```css
.wrapper {
  // 1画面に収める
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  // 縦並べ
  display: flex;
  flex-direction: column;
}

.content-1 {
  background: green;
  flex: 3; // 75%
}

.content-2 {
  background: blue;
  flex: 1; // 25%
}
```
cesiumとgooglemap

#概要
cesiumとgooglemapを連動してみた。

#写真

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/244a3a3a-79c0-ecd1-8ab4-b6728c5ec234.png)

#サンプルコード

```
var gmap;
var widget;
var prev = {
    lat: 0, 
    lon: 0, 
    zoom: 0
};
function czoom(lat, lon, zoom) {
    var alt = 2000000;
    switch (zoom) 
    {
	case 0:
	    alt = 8000000;
    break;
    case 1:
	    alt = 4000000;
    break;            
    case 2:
	    alt = 2000000;
    break;            
    case 3:
	    alt = 1000000;
    break;            
    case 4:
	    alt = 500000;
    break;            
    case 5:
	    alt = 250000;
    break;            
    case 6:
	    alt = 125000;
    break;          
    case 7:
	    alt = 62500;
    break;    
    case 8:
	    alt = 31250;
    break;      
    case 9:
	    alt = 15625;
    break;    
    case 10:
	    alt = 7812;
    break;     
    case 11:
	    alt = 3906;
    break;     
    case 12:
	    alt = 1953;
    break;     
    case 13:
	    alt = 976;
    break;     
    case 14:
	    alt = 488;
    break;     
    case 15:
	    alt = 488;
    break;
    case 16:
	    alt = 488;
    break;
    case 17:
	    alt = 488;
    break;  
    case 18:
	    alt = 488;
    break;   
    case 19:
	    alt = 488;      
    break;
    }
    widget.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(lon, lat, alt)
    });
}
function setCenter(lat, lon, zoom, mode) {
    if (mode != 'gmap') 
    {
        gmap.setCenter(new google.maps.LatLng(lat, lon));
        gmap.setZoom(zoom);
    }
    if (mode != 'cmap')
    {
        czoom(lat, lon, zoom);
    }
}
function fmt(x) {
    x = Math.round(x * 100000000) / 100000000 + '';
    if (x.match(/\.\d{1,7}/)) 
    {
        x += '00000000';
        x = x.replace(/(\.\d{8})\d*$/,'$1');
    }
    return x;
}
function init() {
    gmap = new google.maps.Map($('#gmap')[0], {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    widget = new Cesium.CesiumWidget('cmap');
}
$(function() {
    init();
    setCenter(38.0, 140.0, 0);
    setInterval(function() {
        var center,
            lat,
            lon,
            zoom;
        center = gmap.getCenter();
        lat = center.lat(); 
        lon = center.lng();
        zoom = gmap.getZoom();
        if (lat != prev.lat || lon != prev.lon || zoom != prev.zoom) 
        {
            prev = {
                lat: lat, 
                lon: lon, 
                zoom: zoom
            };  
            czoom(lat, lon, zoom);
        }
    }, 800);
});



```

#成果物
http://jsdo.it/ohisama1/8VaS

以上。
SymfonyにPull Requestしてみました

先日、たまたまSymfonyにPull Requestする機会がありました。無事にマージしていただき、みつけた不具合も修正されたようなので、そのときの体験談をまとめようと思います。

## 不具合をみつけたきっかけ

EC-CUBEで利用しているSymfony Componentを、2.7.37から2.7.38に更新しようとしていたところ、EC-CUBEのTravis-CIのテストが通らなくなりました。

Formに対してテストデータをsubmitしている箇所で、こんなエラーが発生していました。

```
ContextErrorException in FileType.php line 43:
Warning: Invalid argument supplied for foreach()
```

EC-CUBEのテストコードが間違っているのか？と思い、最小限のコードを試してみたところ、やはり同じエラーが発生します。

```php
$builder = $app['form.factory']->createBuilder();
$builder->add('file', FileType::class, [
   'multiple' => true,
]);

$form->submit([]);
```

[FileTypeのコード](https://github.com/symfony/symfony/blob/v2.8.31/src/Symfony/Component/Form/Extension/Core/Type/FileType.php#L38
)を確認してみると、`$event->getData()`をそのままforeachループで回していて、getDataがnullを返した時にこのエラーが発生することがわかりました。

```php
foreach ($event->getData() as $file) {
    if ($requestHandler->isFileUpload($file)) {
        $data[] = $file;
    }
}
```

## Issueの投稿

とりあえずIssueに投稿しようと、[Contributing to Symfony](http://symfony.com/doc/current/contributing/index.html)に目を通しました。ちゃんとガイドラインが整備されているのはありがたいですね。

不具合報告の場合は、[Reporting a Bug](https://symfony.com/doc/current/contributing/code/bugs.html)に説明があります。
書かれているのは基本的なことで、

- ライブラリの使い方間違ってない再度ドキュメントを確認する
- 不具合かどうか判断できないときは、SlackやStackOrverFlowで聞いてみる

といった、Issueを立てる前の注意事項であったり、

- 再現手順や再現コードを載せる
- 環境や利用しているバージョンなど、できるだけ詳しく説明する

といった、不具合報告についての注意事項が書いてあります。

実際にIssueを立てるときには、テンプレートが表示されるので、それに従って埋めていくだけです。他の人のIssueを参考に書いてみたのが以下です。

https://github.com/symfony/symfony/issues/25063

さきほど調べた、発生している事象と、再現コード、原因箇所を記載しています。

ちなみに英語はGoogle翻訳です！

## Pull Requestを送ってみる

Issueを立てたらすぐに反応をいただきました。

```
Hi @chihiro-adachi I think this should be handle whenever getData() is null.
Do you want to provide a PR to fix the behaviour ?
```

```
getData()がnullのときは制御する必要があると思う。Pull Requestできる？(難しかったらこっちでやるよ)
```

くらいの意味でしょうか。せっかくなのでPull Requestしてみることにしました。

Pull Requestのガイドラインは、[Submitting a Patch](https://symfony.com/doc/current/contributing/code/patches.html)に説明があります。

ここでちょっと迷ったのが、Symfonyはバージョンごとにブランチが用意されているので、
どのブランチを修正すればよいか、ということです。

Symfonyのコミットログや他の人のPull Requestを確認してみると、該当機能が実装された一番下位のバージョンを修正しているようでした。下位バージョンにPull Requestしておけば、マージする際に、上位バージョンのブランチにも反映してくれるようです。

ということで、送ったPull Requestがこちらです。
https://github.com/symfony/symfony/pull/25102

Pull RequestもIssueと同様にテンプレートがあるので埋めていくだけです。

余談ですが、Pull Requestを投げるとほぼ同時に`Bug`ラベルや`Status:NeedReview`ラベルが付けられます。Symfonyのレポジトリには[carsonbot](https://github.com/carsonbot)というbotが動いていて、レビューやマージがスムーズに進むよう自動化されているようです。

http://symfony.com/blog/calling-for-issue-triagers-a-new-workflow-and-the-carson-butler

Pull Requestもすぐに反応いただき、指摘事項を修正したらマージしてくれました。

マージされると、リリースノートにも名前が載ったりするようです。テンション上りますね！
https://github.com/symfony/symfony/releases/tag/v4.0.0-RC2

## まとめ

SymfonyにPull Requestをするのは初めてだったのですが、全般的にとても反応が速く、コミュニティがうまく運営されているなあと感じました。

また、ドキュメントや自動化の仕組みなど、巨大なOSSだけあって、全体がスムーズにまわるようにとても工夫されています(とても勉強になりました)

もし不具合を見つけたりしたら、ぜひIssueの投稿やPull Requestにチャレンジしてみてください。一緒にSymfonyを良くしていければなあと思います！
cesiumで一枚タイル

#概要
cesiumで、一枚タイルやってみた。

#写真
![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/cabac37c-f69a-e3af-4385-aea48d04cbde.png)


#サンプルコード

```
var widget = new Cesium.CesiumWidget('cesiumContainer', {
    imageryProvider : new Cesium.SingleTileImageryProvider({
	    url: '/assets/w/h/9/k/wh9kS', 
    })
});

```

#成果物
http://jsdo.it/ohisama1/uCPk

以上。
Numpy のよく使うスニペット集

当記事は、[SENSY Advent Calendar 2017](https://qiita.com/advent-calendar/2017/sensy)の6日目の記事です。

当記事は、[Pandas のよく使うスニペット集](https://qiita.com/tokuda109/items/3b5cdaef7fd1aaeff366)のスニペットシリーズの[Numpy](http://www.numpy.org/)版です。（アドベントカレンダーを埋めるために2017/12/14に記事を追加公開しました。）

SENSY Inc.の業務では、`Pandas` とともに `Numpy` がよく使われます。
まだ、Numpyを上手く使いこなせていないので、よく使っている書き方をスニペットとして記載していきます。

## インポート

Numpy をインポートするには以下を実行します。

`np` としてインポートすることが多いみたいです。

```py
import numpy as np
```

## Numpy行列の作成

```py
np_array_1 = np.array([1, 2, 3])

np_array_1

# array([1, 2, 3])

np_array_2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

np_array_2

# array([[1, 2, 3],
#        [4, 5, 6],
#        [7, 8, 9]])
```

## DType の取得

```py
np_array_1.dtype

# dtype('int64')
```

## 配列形状の取得

```py
np_array_1.shape

# (3,)

np_array_2.shape

# (3, 3)
```

## 算術演算

```py
np_array_1 + 1

# array([2, 3, 4])

np_array_1 - 1

# array([0, 1, 2])

np_array_1 * 3

# array([3, 6, 9])

np_array_1 / 2

# array([ 0.5,  1. ,  1.5])
```

## 乱数を含む配列の生成

```py
np.random.rand(3)

# array([ 0.97677458,  0.19336271,  0.66828087])
```

```py
np.random.rand(3, 3)

# array([[ 0.00420696,  0.9480934 ,  0.79849675],
#       [ 0.1099369 ,  0.55860276,  0.71633783],
#       [ 0.00835927,  0.80184971,  0.62207637]])
```

## 特定のインデックス以降を取得

```py
np_array_1[1:]

# array([2, 3])
```

## 順番を反転

```py
np_array_1[::-1]

# array([3, 2, 1])
```

## 1次元に変換

```py
np_array_2.ravel()

# array([1, 2, 3, 4, 5, 6, 7, 8, 9])
```

`flatten` はコピーしたものを返却する。

```py
np_array_2.flatten()

# array([1, 2, 3, 4, 5, 6, 7, 8, 9])
```

## 形状の変更

```py
np_array_2.reshape((9, 1))

# array([[1],
#        [2],
#        [3],
#        [4],
#        [5],
#        [6],
#        [7],
#        [8],
#        [9]])
```

## 軸(axis)反転

```py
np_array_2.transpose()

# array([[1, 4, 7],
#        [2, 5, 8],
#        [3, 6, 9]])
```

## 垂直方向に連結

```py
np.vstack((np_array_1, np_array_2))

# array([[1, 2, 3],
#        [1, 2, 3],
#        [4, 5, 6],
#        [7, 8, 9]])
```

## 水平方向に連結

```py
np_array_3 = np_array_2 * 3

np.hstack((np_array_2, np_array_3))

# array([[ 1,  2,  3,  3,  6,  9],
#        [ 4,  5,  6, 12, 15, 18],
#        [ 7,  8,  9, 21, 24, 27]])
```

## NaNが含まれているかチェック

```py
np_array_4 = np.array([np.nan, 2, 3])

np.any(np.isnan(np_array_1))

# False

np.any(np.isnan(np_array_4))

# True
```

## 配列内のNaNのインデックスを取得

```py
np.where(np.isnan(np_array_4))

# (array([0]),)
```

## 0要素の配列を生成

```py
np.zeros((3, 3))

# array([[ 0.,  0.,  0.],
#        [ 0.,  0.,  0.],
#        [ 0.,  0.,  0.]])
```

## 1要素の配列を生成

```py
np.ones((3, 3))

# array([[ 1.,  1.,  1.],
#        [ 1.,  1.,  1.],
#        [ 1.,  1.,  1.]])
```

## 初期化されていない配列を生成

```py
np.empty((3, 3))

# array([[  1.48219694e-323,   2.96439388e-323,   4.44659081e-323],
#        [  5.92878775e-323,   7.41098469e-323,   8.89318163e-323],
#        [  1.03753786e-322,   1.18575755e-322,   1.33397724e-322]])
```

## 同形状で0要素の配列を生成

```py
np.zeros_like(np_array_2)

# array([[0, 0, 0],
#        [0, 0, 0],
#        [0, 0, 0]])
```

## 内積を求めた配列を生成

```py
np.dot(np_array_2, np_array_3)

# array([[ 90, 108, 126],
#        [198, 243, 288],
#        [306, 378, 450]])
```
窓に落書きするWebアプリみたいなのを、HTML+CSS+Jqueryやらで作った

冬っぽいものをしゃにむに作りたくなったのでやりました。
（本当は、AdventCalendarをやることになったので作成しました。）  

題して「子供の頃によくやった、結露した窓に落書きするやつ」
です。  

こんな感じ
![2017-12-06_095944.png](https://qiita-image-store.s3.amazonaws.com/0/132904/02912cee-0054-cb0f-3aef-de173ee10f03.png)  
  
ここで遊べます。
※PCのChromeとiOSのsafariのみ動作を保証します。なお、重くなりがちです。
Androidの方は・・・すみません。
リンク：http://ahlover.html.xdomain.jp/flosted_window/resource/view/advent_flame.html  
  

# 仕組み
スマートな実装方法が思いつかなかったので、所謂ゴリ押し実装です。  
  
重要な要素を掻い摘んで説明すると  
  
##### 1.  背景画像を用意 スタイルは以下の通り
```html
background-repeat: no-repeat;
background-attachment : fixed;
position: relative;
```

##### 2.  曇り（レイヤー）を被せる
```html
background-color:rgba(255,255,255,0.5);
```
##### 3.  クリックした箇所に「穴をあける・・・風に見せかけたdiv要素」を配置する。
そのdivは背景画像の子要素として配置

```
background:inherit;
position: absolute;
top:YYY px;
left:XXX px;
```

この3つです。
なぜコレで穴が開くのかをさらに詳しく解説します。  
  
「穴をあける・・・風に見せかけたdiv要素」（以下、穴とします）は親要素を完全に引き継いでおり、
そこに自身の宣言しているスタイルが合わさり、このようになります。  

```html
background-repeat: no-repeat;
background-attachment : fixed;
position: absolute;
top:YYY px;
left:XXX px;  
```

background-attachment : fixed;（かつ、背景位置無指定）により、
本来なら「自身の要素の左上から描画される」背景が「親要素の左上から描画される」ようになります。

イメージ
各図形の役割
![2017-12-05_113251.png](https://qiita-image-store.s3.amazonaws.com/0/132904/75158760-da46-d331-1b45-d6ff7da097f2.png)

各要素は、このように重なっています。
![2017-12-05_113352.png](https://qiita-image-store.s3.amazonaws.com/0/132904/94d1df39-e4c1-3035-5f9a-5ddf8c5421ba.png)

これが、「要素の左上から描画される」状態です。
![2017-12-05_113614.png](https://qiita-image-store.s3.amazonaws.com/0/132904/5437de87-9969-4fb3-e743-507f3c7235ad.png)

一方こちらは、「親要素の左上から描画される」状態になります。
![2017-12-05_113931.png](https://qiita-image-store.s3.amazonaws.com/0/132904/724cb5d6-3bd4-55aa-f724-8bada942016e.png)

このようにして、あたかも背景が浮きあがっているような演出ができるわけです。
![2017-12-05_114143.png](https://qiita-image-store.s3.amazonaws.com/0/132904/bd228e87-58e5-5b34-b665-8ce213d1fe57.png)

なお、fixedの弊害により「スクロール時についてきてしまう」問題や「レイヤーとズレが起きてしまう」問題などがありましたが・・・
iframeで埋め込むことでクリアーしました。

2017年も暮れなのに、まさかここで使うことになるとは。
SSIでもよかったかもしれないけど。

残課題として
android対応、IE対応：
└ 言わずもがな。時間が無いから切り捨てたけど、やっぱそこから使える方が色々な人に見てもらえますしね。
なんちゃって線形補完のブラッシュアップ：
└ マウスイベントは高速移動すると飛び飛びになってしまうので、素早く線を引く行為に対応できない。
軽くする：
└ 大量のdivを設置してお絵かきのように見せかけているので、描けば描くほど重くなる状態です。
　特に、なんちゃって線形補完では「飛んだ部分を追従するようにdivを鬼設置」しているだけなので、
　指を小さくすればするほど重くなる速度も上がっている状態。

この辺を上手く解決して、さらに使いやすいモノにしたいですね。
以上、自分用まとめみたいなものでした。
F2とEnterを連打するその前に

# 導入
執筆者がいなかったのでエクセルのことを書いてやろうとPCを開いたのですが

エクセルをインストールしていないことに気付きちょっと狼狽しています。

このブログが公開するのは月曜に会社で画面ショットを取り終わった頃でしょう。

# こんな経験ありませんか？

エクセル等で「文字列」として書き込まれた項目を「数値」として扱いたく、

セルの書式を「数値」に変更して依然として「文字列」…

![a.png](https://qiita-image-store.s3.amazonaws.com/0/71261/bbe19976-5741-c4d4-dd80-9cb432fde91a.png)
![b.png](https://qiita-image-store.s3.amazonaws.com/0/71261/0a191d73-5693-a0bd-4307-ebf13af1aa96.png)


セルの編集をしようとすると「数値」になる事に気づき、`F2`と`Enter`を連打する

…こんな経験

# 解決方法

1. 適当に**「数値の1」**のセルを作りコピーする
![d.png](https://qiita-image-store.s3.amazonaws.com/0/71261/e8635e98-4278-5dcd-6dd7-995ac53adaf7.png)

2. 変換したいセルを選択する
3. 「形式を選択して貼り付け 」を選び**「乗算」**で貼り付けを行う
![e.png](https://qiita-image-store.s3.amazonaws.com/0/71261/2efc24ed-d58a-3f84-8b95-e33cba56f85c.png)

4. 「数値」になってる！
![f.png](https://qiita-image-store.s3.amazonaws.com/0/71261/c323c983-e65c-c655-a081-653e388422ee.png)


# ちなみに
* `open office`の`calc`ではできませんでした。
* `google`の`spreadsheets`では書式を変更するだけでできました。
* 新しい`MS-Office`ならできそうな気がする。