OmniAICreator/Qiita-1.07M huggingface dataset:
ActiveRecord で時間の長さを保存する

`1.year` や `2.weeks` などで生成される ActiveSupport::Duration をデータベースに保存してロードできるようにしたい。

# どうシリアライズする?
ActiveSupport::Duration をそのまま DB に保存はできないので、シリアライズの方法を考える必要がある。

## 秒数

ActiveSupport::Duration には `to_i` メソッドがあり、秒数を返す。これは必ずしも実際の秒数ではない (たとえば月によって日数がかわるため) が、`ActiveSupport::Duration.build` に渡せば**だいたい**復元することができる。

値をみてもどれくらいの期間なのかはわかりにくいが、たんなる整数なので、DB に不正な値が入る危険が少なく、比較やソートもしやすい。

しかし、たとえば `1.month.to_i` は `2629746` と定義されており `2629746.seconds.to_i` と区別できない。`ActiveSupport::Duration.build(2629746)` は `1.month` と解釈されるので、だいたいの場合は問題ないだろうが、やや厳密さにかける。

※ 年の秒数はグレゴリオ年の秒数、月の秒数はその 1/12 と定義されている

## ISO8601

もう一つの方法として、`iso8601` メソッドで得られる [ISO8601 の継続時間を表す文字列](https://ja.wikipedia.org/wiki/ISO_8601#%E7%B6%99%E7%B6%9A%E6%99%82%E9%96%93)が使える。たとえば `2.years.iso8601` は `P2Y`、`10.minutes.iso8601` は `PT10M` のようになる。これは `ActiveSupport::Duration.parse` で復元できる。

読み方さえわかれば秒数よりも理解しやすいが、比較やソートは難しい。

この方法だと `1.month.iso8601` は `P1M`、`2629746.seconds.iso8601` は `PT2629746S` のように区別され、`ActiveSupport::Duration.parse` に渡すとそれぞれもとの形に復元される。

※ただし `0.year.iso8601` `0.day.iso8601` `0.hour.iso8601` などは区別されず `PT0S` になるようだ

なお、ISO8601 には `14.days` を`P0000-00-14T00:00:00` のように表現する形式もあるが、この形式では `30 時間` のような値を表現できないため、これ以上検討しない。

# ActiveRecord::Type::Value
上記の ISO8601 による文字列表現を使って、[ActiveRecord::Attributes::ClassMethods#attribute](http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute) で使える型を定義する。

```ruby
# DB での型に対応するクラスを継承
class DurationType < ActiveRecord::Type::String
  # attribute_name= で assign された値の変換
  def cast(value)
    case value
    when ActiveSupport::Duration
      value
    when NilClass
      nil
    else
      begin
        ActiveSupport::Duration.parse(value.to_s)
      rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
        nil
      end
    end
  end

  # DB から読んだ値の変換
  def deserialize(value)
    return nil if value.nil?
    ActiveSupport::Duration.parse(value)
  end

  # DB に書き込む値
  def serialize(value)
    return nil if value.nil?
    value.iso8601
  end
end

ActiveRecord::Type.register(:duration, DurationType)
# attribute :attribute_name, :duration
```

これで下記のように使える。

```ruby
class Plan < ActiveRecord::Base
  attribute :term, :duration
end

Plan.create!(term: 2.years).reload.term == 2.years # true
Plan.create!(term: "PT3H").reload.term == 3.hours # true
```
[Keras] Callback History


#LSTM 
CALLBACK 

```python:callback.py

class CustomHistory(keras.callbacks.Callback):
    def init(self):
        self.losses = []
        self.vol_losses = []
        self.accs = []
        self.vol_accs = []        
        
    def on_epoch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        self.vol_losses.append(logs.get('vol_loss'))
        self.accs.append(logs.get('acc'))
        self.vol_accs.append(logs.get('acc_loss'))

```

#init

```python:usage.py

custom_hist = CustomHistory()
custom_hist.init()
```

#使用

```python:train.py
model.fit(X_train, Y_train, epochs=1, batch_size=10, validation_data=(X_val, Y_val), callbacks=[custom_hist])
```
DNS CAA レコードを設定してみる

## DNS CAAとは
ドメイン管理者があるドメインに対して、DNSレコードで「CAA」を指定することでSSL/TLSサーバー証明書を発行できる認証局(CA)を指定できる仕組みです。

### DNSレコードの形式
DNSのレコードの形式はCAA \<flags> \<tag> \<value>になります。
#### flags
クリティカルフラグのみが定義されています。クリティカルフラグは、認証局が対応するCAAリソースレコードのtagの種類を理解できない場合、証明書を発行してはならないことを示します。クリティカルフラグを設定する場合は値に128を指定します。それ以外の場合は値に0(ゼロ)を指定します。
#### tag/value
| tag | 説明  | value |
|:-:|:--|:--|
| issue   | サーバー証明書全般の発行を許可する認証局を指定  | "letsencrypt.org"などの認証局が指定している値等 |
| issuewild  | ワイルドカード証明書の発行を許可する認証局を指定  | "letsencrypt.org"などの認証局が指定している値等 |
| iodef  | CAA レコードの確認結果、証明書を発行できない場合に申請があった事実を連絡する連絡先  | mailto:example@example.com |

### レコードを作成してみる
https://sslmate.com/caa/ でドメイン等を入力することで、作成してくれます。

### 作成したレコードをDNSに登録する
私はお名前.comでドメインを取得していたので、お名前.comのDNS設定でCAAレコードを追加しました。
＊お名前.comの場合はCAAレコードの対応を2018/06/06あたりから始めたようです（https://www.onamae.com/news/domain/180606_1.html）。
### 確認
こちらでhttps://www.ssllabs.com/ssltest/ 確認できます。
「DNS CAA」の値が「No」 から「Yes」に変わりました。

## 参考
[DNS CAAとは](https://rms-digicert.ne.jp/howto/basis/caa.html)
[DNS CAAレコードに Let's Encrypt 認証局を設定する](https://blog.apar.jp/web/7334/)
[CAA レコードについて](https://www.cybertrust.ne.jp/sureserver/productinfo/caa.html)
[DNS CAA レコード設定について](https://help.sakura.ad.jp/hc/ja/articles/115000139062-DNS-CAA-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
CentOS7でPDO使ってpostgresにつないでたら、"Ident authentication failed for user"ってエラーログが出た

CentOS7でPDOを使ってpostgresqlにつないでたら、

```
[Sun Jul 01 18:28:19.399178 2018] [:error] [pid 2883] [client xxx.xxx.xxx.xxx] PHP Fatal error:  Uncaught exception 'PDOException' with message 'SQLSTATE[08006] [7] FATAL:  Ident authentication failed for user "hogeuser"' in ...
```

っていう内容がエラーログに吐かれていました。

読んでの通り、「hogeuserってユーザ（postgresqlのユーザ）の認証が失敗しましたってことなんですが、

```php
$db = new PDO("pgsql:dbname=hogedb;host=localhost;", "hogeuser", "hogepassword");
```

その時のコードはこの通り。
PHP公式ページの接続例とほとんど相違ありません
接続例url->
[http://php.net/manual/ja/pdo.connections.php](http://php.net/manual/ja/pdo.connections.php)

こんな時はググってみようということで、エラーメッセージでググる。

Qiitaにこんな記事↓
[https://qiita.com/pugiemonn/items/7ec47bc82bd56b0458b9](https://qiita.com/pugiemonn/items/7ec47bc82bd56b0458b9)

このブログで一つの解決策が
`/var/lib/pgsql/9.5/data/pg_hba.conf`っていうファイルを書き換えればいいらしい。
でもこれは、`hogeuser`のパスワード認証を無効にするということ。
公開を目的としていないプログラムならいいが、公開を目的とするプログラムには適さない。

ベストソリューションはこちら。
https://blog.fkoji.com/2015/02260627.html

内容としては、
<b>`host=localhost`の指定を外す</b>
それだけ。

PDOからインスタンスを生成するときに渡すdsnにおいて、hostを指定しない場合はデフォルトでlocalhostが指定されるので、外しても問題なし。

というわけで、さっきのコードからhost=localhostを消してみる。


```php
$db = new PDO("pgsql:dbname=hogedb;", "hogeuser", "hogepassword");
```

無事エラーを吐かず接続。select文とinsert文が実行できたことを確認。

パスワード認証をしたのはこれで初めてだったが、これにて一件落着！

同じようなエラーが出た場合は、ぜひ試してみてください。
Next.jsの_appと_document

バイト先でNext.jsを使っていて、v6から入った`_app`と、以前からある`_document`の違いがよくわかっていなかったので調べてまとめました。基本的には[これ](https://zeit.co/blog/next6)の一部を和訳しているので、よくわからなかったらそちらを参照してください。

## `_document`
これが定義されている場合には、`<html>`要素をレンダリングするトップレベルのドキュメントをオーバーライドすることができます。しかし、これにはいくつかの重大な制限が存在します。例えば、Reactは`<html>`や`<body>`をクライアント側で直接レンダリングすることはできません。そのため、`_document`の呼び出しはレンダリング前に限定されます。

## `_app`
`_app`はそのほかのユースケースに対しても使うことができます。

|  |Prerender phase| Runtime lifecycle | Data fetching |
|:--|:---------------|:-------------------|:---------------|
|`_document`|YES|NO|NO|
|`_app`|YES|YES|YES|

### 例1)ページトランジション
- [ページトランジションのサンプルのソースコード](https://github.com/xavczen/nextjs-page-transitions)

この例では、ページごとに独立してアクセスし、プリレンダリングをし、遅延ロードをしていますが、クライアント側に移行するとなめらかなアニメーションを行います。

### 例2)良質なApolloやReduxとの統合
Nextではすでに、ApolloやReduxのような状態管理フレームワークと統合した例が数多くありましたが、`_app`を使えばそれらを含めるのが容易になります。

- [Apolloのサンプルのソースコード](https://github.com/zeit/next.js/tree/canary/examples/with-apollo)
- [Reduxのサンプルのソースコード](https://github.com/zeit/next.js/tree/canary/examples/with-redux)

### 例3)良質なエラーハンドリング
Reactは`componentDidCatch`というコンポーネントメソッドを用意しています。このメソッドを使用すると、クライアント側のネストされたコンポーネントの例外をキャッチして処理できます。
これらの予期しない例外は、トップレベルでキャッチして均等に処理しておきたいというケースが多くあります。`_app`は、その`componentDidCatch`ロジックを定義するのに適しています。

- [エラーハンドリングのサンプルのソースコード](https://github.com/zeit/next.js/tree/canary/examples/with-componentdidcatch)

## 感想
以前までは各ページをHOCに食わせるなどして共通の事前処理を行っていたので、その必要がなくなったということで、HOC地獄から少し開放されたような気がしています。
Azure Logic AppsでノンプログラミングREST API

## Logic Appsとは
Logic Apps は、Microsoft Azure の PaaS サービスでアプリケーションをホストする App Service のサブ機能の位置づけのサービスです。
特徴としては、プログラミングなしで手軽に複数のサービスを相互にコネクションすることができます。
すでに、接続用に準備されたコネクタは現時点で約160種類以上あります。

## 実際の構築
今回はクライアントからHTTPの要求を受けて指定の画像ファイルをAzureBlobStrageから取得し、クライアントにbase64でエンコードした文字列を返却するAPIを作成します。

1. HTTP要求をトリガーに設定
    ![0702_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/2312dfbd-b128-6461-645a-3e38bae61015.png)
    （URLはロジックの保存後に発行されます）

    ここで要求本文（Body）のJSONスキーマを設定しておくと、のちのアクションでパラメータごとに使用が可能となります。
    ここでは

    ```json
    {
        "fileName": "hogehoge"
    }
    ```
    という形のJSONで本文が送られてくると設定します。

    【サンプルのペイロードを使用してスキーマを生成する】を選択し、上記のJSONをそのまま貼り付けます。

    ![0702_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/2448a766-5b4e-9ece-5a64-791f0857f41e.png)

    スキーマが自動的に設定されていれば完了です。

    ![0702_3.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/ca1e0250-2e56-2b56-15ae-a13562fd36d4.png)

1. Blobからpdfを取得するアクションを追加

    ※Blobストレージと接続するには接続文字列が必要なのでBlob側の【アクセスキー】から接続文字列を取得しておく必要があります。

    今回はパスによるBLOBコンテンツの取得アクションを選択します。

    以下、画像のようにBLOBパスの文字列の中にスキーマで設定したfileNameを動的なコンテンツとして使用することができます。

    ![0702_4.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/612013b7-dcad-90cd-2a05-1de94b2f51db.png)


1. クライアントへ画像ファイルを返却する

    トリガーをHTTPの要求に設定した場合、応答アクションとしてHTTPのレスポンスを返却することができます。（応答を設定しなかった場合は処理の結果を待たずに202を返す）

    応答本文のJSONも自身で定義でき、Blobから取得したファイルコンテンツを動的なコンテンツとして指定できます。
    この際、【式】タブから様々な関数を実行することができ、今回は取得した画像ファイルをbase64でエンコードする関数を追加します。

    ![0702_5.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/b7205ede-8126-60d4-7a89-2295916cc3e0.png)

1. 実行確認

    ではロジックを保存して確認してみましょう。
    RESTのクライアントから要求を投げると、、、

    ![0702_6.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/4ccc3614-58ab-8d0e-41b2-e11bb5957926.png)

    実行は成功して想定通りのJSONが返却されました。

## 最後に

今回作成したロジックの全体像

![0702_7.PNG](https://qiita-image-store.s3.amazonaws.com/0/206219/77d10a9d-30a9-950e-3330-1312036f7108.png)

このようにLogicAppsを使えば簡単にサーバーサイドをノンプログラミングで構築できます。
他にも、処理を分岐させて非同期で実行したり、配列ループさせたりと様々なことができます。
さらに複雑な処理をしたい場合はAzure Functionsと組み合わせることもできます。

課金はロジックの実行時間に応じてなので、皆さんもまずはデザイナーで何ができるか試してみるのはいかがでしょうか。
[音声認識入門]WebSpeech APIは https を使う

#WebSpeechAPIとは
Chromeブラウザで動く音声認識APIです。
ライブラリなど読み込む必要もなくJavaScriptで動かすことが出来ます。
WebSpeechAPIには音声認識・音声発話機能があります。

###参考URL
https://qiita.com/m-shimao/items/e340efac71f709c43a4e
https://qiita.com/advent-calendar/2015/jsrobotics

##使用する上での注意点
**まずhttp://～だとマイク認識しない!!**
ここでハマりました...http://～だとChromeのマイクがブロックされます。
<img width="73" alt="スクリーンショット 2018-07-04 11.58.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/259333/63ea0e3a-3b0e-ae0e-4f23-1f37b41e8e39.png">

httpsであればchromeのマイクが認識します。
###**WebSpeechAPIはhttps://～を使いましょう!**
コピーして、ファイル名を書き換えるコマンド


コピーして、ファイル名を書き換えるコマンド

```
for f in `ls`; do cp $f ${f/<1>/<2>}; done
```

#  検証

```sh

$ ls
hoge2017-1hoge.pdf	hoge2017-3hoge.pdf	hoge2017-5hoge.pdf
hoge2017-2hoge.pdf	hoge2017-4hoge.pdf	hoge2017hoge.pdf

# hogeのつく、下から5件のみコピーして、2017の部分のみを2018に変更
$ for f in `ls hoge* | tail -n5`; do cp $f ${f/2017/2018}; done
$ ls
hoge2017-1hoge.pdf	hoge2017-4hoge.pdf	hoge2018-2hoge.pdf	hoge2018-5hoge.pdf
hoge2017-2hoge.pdf	hoge2017-5hoge.pdf	hoge2018-3hoge.pdf	hoge2018hoge.pdf
hoge2017-3hoge.pdf	hoge2017hoge.pdf	hoge2018-4hoge.pdf
```
AndroidX対応を人力で頑張ってみたまとめ

AndroidX対応を人力でやってみて出てきた警告とかメモ

普通であればASで自動でリファクタできるはずなのでやる必要のないことが多いハズ

# やったこと
- dependenciesの修正
- classのimportを修正
    - View
    - Activity/Fragment
- layoutで使ってるViewを修正
    - RecyclerViewとか
- gradle.propertiesの修正

# dependenciesの修正
https://developer.android.com/topic/libraries/support-library/refactor
ライブラリの対応表を参考にしながらbuild.gradleを修正する

# classのimportを修正
Viewとかのimportを修正する。
ActivityやFragmentもサポートライブラリのを使ってれば切り替える。
`ViewModelProviders` もActivityやFragmentを変えるとAndroidX用のに変える必要あるので、忘れずにdependenciesを直しておく。
`DataBindingUtil` もAndroidX版に変わってるので忘れないで直す。

# layoutで使ってるViewを修正
修正を忘れるとkaptのコンパイルで失敗する

# gradle.propertiesの修正
`gradle.properties` に以下を追加

```
android.useAndroidX=true
android.enableJetifier=true
```
ちょっと便利な小技【Unity】

はじめまして、ますみです！

[![自己紹介.png](https://www.umi-mori.jp/wp-content/uploads/2023/02/introduction_banner_2-2048x533.png)](https://bit.ly/banner_intro_masumi_creator_qiita)


# 小技①：Align With View
- 機能：`Sceneの画面をカメラの画面にする`
- 方法：カメラのオブジェクトを選択 → `GameObject`を選択 → `Align With View`を選択
- ショートカット：`Cmd/Ctrl + Shift + F`

![AlignWithView.gif](https://qiita-image-store.s3.amazonaws.com/0/240280/32316094-274f-d09d-7e27-844df89d9aec.gif)

# 小技②：Lock View to Selected
- 機能：`選択したオブジェクトが中心に来るようにする`
- 方法：オブジェクトを選択 → `Edit` → `Lock View to Selected`を選択
- ショートカット：`Shift + F`
（以下の例ではショートカットを使用。）

![LockView.gif](https://qiita-image-store.s3.amazonaws.com/0/240280/a4222e01-175d-2ef9-11cc-c9c779af3b9c.gif)

# 小技③：平面の移動
- 機能：`オブジェクトを平面方向に移動する`
- 方法：オブジェクトの軸の矢印の代わりに軸からなる平面をマウスで掴む

![PlaneMove.gif](https://qiita-image-store.s3.amazonaws.com/0/240280/6a3eda1e-21c9-ff98-e7a0-52dc1d29198c.gif)

# 小技④：Freeze Position / Freeze Rotation
- 機能：`オブジェクトの位置・回転を固定する`
- 方法：`Rigidbody`を追加 → その中の`Constraints`を選択 → 固定したい位置・回転の軸にチェックを入れる

![Freeze.gif](https://qiita-image-store.s3.amazonaws.com/0/240280/c5240dab-a107-8088-89a5-9c74fcc84de5.gif)

# 小技⑤：再生と停止のショートカット
- ショートカット：`Cmd/Ctrl + P`
- 備考：再生と停止は、数えきれないほど繰り返す操作なため、ショートカットの使用を推奨します。

# 小技⑥：Audio Low Pass Filter
- 機能：低音域の音を通し、高音域をカットする / `水に潜ったような音にする`
- 方法：Add Componentから、`Audio Low Pass Filter`を追加

<img width="300" alt="スクリーンショット 2018-08-18 21.45.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/240280/7786bfb5-bbdf-dd46-f25e-a910fa2739a5.png">

# 最後に
最後まで読んでくださり、ありがとうございました！
いかがだったでしょうか？

この記事を通して、少しでもあなたの学びに役立てば幸いです！

:::note info
【仕事の相談はこちら】
お仕事の相談のある方は、下記のフォームよりお気軽にご相談ください。

[問い合わせフォームはこちら](https://forms.gle/G5g1SJ7BBZw7oXYA7)

もしもメールでの問い合わせの方がよろしければ、下記のメールアドレスへご連絡ください。

info*galirage.com（*を@に変えてご送付ください）

🎁 「生成AI活用の無料相談券」もしくは「生成AIの社内ガイドライン（無料PDF）」を『公式LINE』で配布中 🎁
『生成AIを業務に活用したいけど、どうしたらいいかわからない』といった声を多くいただきます。

Galirageでは公式LINEにて、チャットやオンライン会議で「完全個別の生成AI活用無料相談会」を実施しております！
（期間限定で実施しているため、ご興味ある方はお早めに以下のLINE公式アカウントをご登録ください^^）
https://lin.ee/rvz6lMN

※ 予告なく、キャンペーンを終了する可能性がございますが、ご了承ください。

【業務内容】
具体的には、以下のお仕事を中心に受け付けております！（[詳しくはこちら](https://galirage.notion.site/Galirage-AI-c2f3945fafb0433d8d2fd03e56927fd8)）
1. 受託開発（例：生成AIを使った社内システムの開発）
2. コンサルティング（例：技術戦略のアドバイス）
3. 講演（例：社内研修、イベント登壇）

※ 特に「生成AIを使ったシステム開発のご依頼」が多く、ご好評いただいております。

【これまでの相談事例】
以下のようなご相談が多くあります。

🔑 機密情報を漏洩させないための、生成AIのシステム構築をお願いしたい。
🤖 自社データを用いたFAQチャットボットの作り方を知りたい。
💡 ChatGPTを、自分たちの事業にどのように活かせるか、アドバイスやアイデアが欲しい。
:::
# おまけ
エンジニアの仲間（データサイエンティストも含む）を増やしたいため、公式LINEを始めました🎉

「**一緒に仕事をしてくれる方**」「**友だちとして仲良くしてくれる方**」は、友だち追加をしていただけますと嬉しいです！（仲良くなった人たちを集めて、「ボードゲーム会」や「ハッカソン」や「もくもく会」もやりたいなと考えています😆）

とはいえ、みなさんにもメリットがないと申し訳ないので、特典を用意しました！

友だち追加後に、アンケートに回答してくれた方へ「**エンジニア図鑑（職種20選）**」のPDFをお送りします◎

https://lin.ee/hFUN4TL

[![](https://www.umi-mori.jp/wp-content/uploads/2023/10/line_banner_v2.png)](https://lin.ee/hFUN4TL)
今日の日付を表示するプログラム

#はじめに
今日の日付を表示するプログラムを書いてみました。

#ソースコード
```
namespace ConsoleApplication9
{
    class Program
    {
        static void Main()
        {
            // 今の日付、時刻を取得する

            DateTime dt = DateTime.Now;
            Console.WriteLine(dt);



            Console.ReadKey();
        }
    }
}

```
#実行結果
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/249273/7cbd7041-7565-0e8d-db8c-b2e2fe875ac3.png)
Apigee でプロダクト環境へのデプロイしてみるの巻

#目的
テスト環境で試験をクリアしたAPI proxy をプロダクト環境へ展開する

#目標
Apigee で、プロダクト環境へAPI proxy を展開する

#利用方法
[営業向け]Apigee は、手間のかかる環境移行（検証＞プロダクト）を回避し、プロダクト環境移行後の試験を最小化できる。
　　　　　※オンプレだと、プロダクト環境移行後、機器の動作確認や環境差分があるため再試験が走る。
　　　　　　　apigee なら、機能をそのまま移行するので、簡単な動作確認のみ
　　　　　　！ここは、真偽を確認していく必要があるが、問題はなさそう
　　　　　ブルーグリーンデプロイのように多面展開が簡単にできることをデモする
[サーバエンジニア向け]検証と試験が完了したAPI proxy を本番環境へ展開する

#作業
作業は、前回記事の続き
　https://qiita.com/hatakkkk/items/eefa7e98603db3f75c18

API Proxies > 作成したAPI Proxie(図では、"yahoonewstest")を選択
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/2d4a8658-0978-2ab6-e462-71015670e810.jpeg)

Deployment
![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/8aad03c4-dbd4-24d1-4e79-bee826d4eb3d.jpeg)

Prod へ展開する
![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/f99a36a2-12f4-7fb1-afae-043464ad8f92.jpeg)

確認がでるので、Deploy
![WS000003.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/4fea62ae-a2bd-3825-9c9f-2ed0ad31a09d.jpeg)

30秒程度で プロダクト環境が展開される
![WS000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/6506b4c9-11e6-0382-405a-b0515ca62d9a.jpeg)


動作確認のため、リンクをクリック
yahoo new が開くことを確認
![WS000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/184724/00403913-1ad6-747d-7d8d-05adbd5bfa7d.jpeg)


今回は以上です。
プロダクト環境でのURL を周知するようにして下さい。


お疲れ様でした。
EC2 インスタンス (EBS) の AMI (Snapshot) 作成失敗時 (Failed) について

# ０．はじめに

Python スクリプトから CreateImage で AMI を作成し、EC2 インスタンスのバックアップを日時で取っていたんですが、AMI の作成に失敗することがあったので、サポートに確認したところ、ご回答を頂いたのでシェア。

# １．経緯

Python スクリプトは、CloudWatchEvent から Lambda で定期実行していたんですが、ある日２つのインスタンスが AMI の作成に失敗し、Failed 状態になっていました。
それ以降は問題なくスクリプトが実行され AMI が作成されたのですが、Failed になっていた AMI が次の日消えていたので、サポートに確認しました。

# ２．原因

結論からいうと、

* Failed となった原因については、内部的な要因による一時的なエラーが発生し、EBS ボリュームのスナップショット作成に失敗していたとのこと。

<br>
また、

* Failed になった AMI が一定時間マネジメントコンソール上に表示され、その後見えなくなる挙動については、現時点での動作仕様とのこと。
<br><br>
   * マネジメントコンソール上に表示されている間は、その AMI の「詳細」のタブから「AMI ID」や「状態の理由」を参照することができ、それらの情報からトラブルシューティング等が可能。
   * ただし、FailedとなったAMIはご使用できないので、一定時間経過後に一覧から削除される。
   * なお、これらの挙動については現時点での動作仕様であり、将来的には変更される可能性がある。

<br>
ということでした。

## ※ 参考



## ※ 補足

補足として、以下のご説明も頂きました。

* 今回の事象のように、AMIの作成を含めたあらゆるリクエストの実行は、ネットワーク上のさまざまなコンポーネントが原因でエラーが発生する可能性がある。
<br><br>
* AWSでは冗長化を含めて耐障害性には十分配慮し、日々改善しているものの、一時的なエラーの発生は避けられない場合がある。
<br><br>
* 重要なインスタンスのAMIを作成される場合などには、リトライ処理の実施も検討するのが良いかも。
    * create-image のレスポンスとして作成した AMI の ID が取得できるので、その ID を引数に describe-images で AMI の状態 (available | pending | failed) が取得し、リトライの処理を行う。
    * [create\-image — AWS CLI 1\.15\.51 Command Reference](https://docs.aws.amazon.com/zh_cn/cli/latest/reference/ec2/create-image.html)
    * [describe\-import\-image\-tasks — AWS CLI 1\.15\.51 Command Reference](https://docs.aws.amazon.com/zh_cn/cli/latest/reference/ec2/describe-import-image-tasks.html)

# ３．解決策

使っているスクリプトは数年動かしていて初めての失敗だったので、AMI の作成に失敗する確率は非常に低いかと思います。

ただ、
一つの失敗も許されないというのであれば、

* リトライの処理を組み込むか、
* そもそも実行する間隔を短くする

のが良いのかもしれません。

# ＸＸ．まとめ

やはり何事もやってみないとわからないことが多いですね。
AWS もとにかくどんどん試してみることが大切かと。


* ※参考：
    * [EC2 インスタンス \(EBS\) の AMI \(Snapshot\) 作成に関する制限について \- Qiita](https://qiita.com/kusokamayarou/items/f762c87b71e671f415e3)
個人学習メモ#3　Javascript基礎編１  曖昧な所、理解できていない所を書いてみました

自分で何か作ってみようと思いましたが、途中で何をしたらいいかわからなくなります...。プログラムはやっぱり難しいですね...；；

暗記というより理解が大事なので、曖昧な所やもう一度復習しておこうと思ったことをズラズラっと書いてみました。

１.bodyの中にscriptを書く意味
-
Javascriptを読み込んでいる際はHTMLの読み込みが行われないので、先にページの読み込みをしてからJavascriptを読み込ませることにより、表示速度を向上させるため。

※ＨＴＭＬの前に読み込みが必要な場合はhead内に記述。


-head内とbodyの一番下にscriptを書きました-


head内
![スクリーンショット 2018-07-04 11.03.56.png](https://qiita-image-store.s3.amazonaws.com/0/263583/2de926f9-dcbd-1df7-b3c0-001efdd5cdae.png)

bodyの一番下
![スクリーンショット 2018-07-04 11.04.04.png](https://qiita-image-store.s3.amazonaws.com/0/263583/0977f3ba-a51c-4d87-20c7-ff4d15cf14b1.png)

`getElmentById()`などもhead内に書いてしまうとページを読み込む前に実行されてしまい、ページに何も無い状態なのでnullが返ってきます。


２．documentについて
-
Webページを構成する全てのHTML要素

指定したidを持つＨＴＭＬを取得するdocument.getElementById();
指定したname属性を持つＨＴＭＬを取得するdocument.getElementsByName();
HTML要素を作成するdocument.createElement();
※createElementは"生成"しただけなのでWebページには反映されないことに注意！

要素を挿入するにはappendChildを使う
`document.body.appendChild(変数);`

文字列を書き出す`document.write();`
などなど...他にもあります。
Nuxt.jsでgenerate時に特定の処理を実行する（hook）

## 概要
Nuxt.jsで、`nuxt generate` の途中にアプリケーション固有の処理を差し込みたい。

公式ドキュメントを見ると、hookの概念があることがわかった。

https://ja.nuxtjs.org/guide/modules/
> 特定のフックでタスクを実行する
> 
> 単に Nuxt の初期化処理時だけではなく、特定の条件下でのみ、モジュールにある処理を実行させたいこともあるでしょう。特定のイベント時にタスクを行うため、パワフルな Tapable プラグインシステムを使うことができます。フックが Promise を返すか async として定義されている場合は Nuxt は待機します。

## generate時に呼ばれているhook
`pages/index.vue` を作成した状態で `nuxt generate` するとログ後半に以下のようにhookの呼び出しログが出る。
`hooks (1)` となっているのはそのタイミングで呼ばれたhook数の模様。

```
  nuxt: Call generate:distRemoved hooks (1) +0ms
  nuxt:generate Destination folder cleaned +34s
  nuxt: Call generate:distCopied hooks (1) +141ms
  nuxt:generate Static & build files copied +140ms
  nuxt:render Rendering url / +0ms
  nuxt: Call generate:page hooks (1) +3s
  nuxt: Call generate:page hooks (1) +18ms
  nuxt:generate Generate file: /index.html +3s
  nuxt:render Rendering url / +86ms
  nuxt: Call generate:done hooks (1) +3ms
  nuxt:generate HTML Files generated in 37.4s +3ms
  nuxt:generate Generate done +0ms
✨  Done in 40.45s.
```

他にもありそうなので、generateのscriptを見に行くと
https://github.com/nuxt/nuxt.js/blob/0ca99426c93e4f5b7579c12675efb4f8fbef3f8b/lib/builder/generator.js

現時点では8個のhookが呼び出されている。

| hook | comment |
|:-:|:-:|
| generate:before | Call before hook |
| generate:extendRoutes | extendRoutes hook |
| generate:distRemoved |  |
| generate:distCopied |  |
| generate:routeFailed |  |
| generate:page | Call hook to let user update the path & html |
| generate:routeCreated | Make sure the sub folders are created |
| generate:done | Done hook |

探した限りhook一覧のようなものはなかったので、
scriptを見てhookが呼びされるタイミングを把握するのが現時点では一番確実そう。

## hookを設定してみる

今回は `dist` に各pageのファイルが作られたタイミングで処理を差し込みたいと思っていたので、
`generate:routeCreated` のhookを試してみる。

moduleファイルを設置し、

```js:modules/hook/generate.js
module.exports = function () {
  this.nuxt.hook('generate:routeCreated', async generator => {
    console.log('pageのファイル作成が終わったよ')
  })
}
```

`nuxt.config.js` にモジュール設定を追加。

```
  modules: [
    '@/modules/hook/generate'
  ]
```

この状態で `nuxt generate` すると…

```
  nuxt: Call generate:distRemoved hooks (1) +0ms
  nuxt:generate Destination folder cleaned +31s
  nuxt: Call generate:distCopied hooks (1) +20ms
  nuxt:generate Static & build files copied +19ms
  nuxt:render Rendering url / +0ms
  nuxt: Call generate:page hooks (1) +261ms
  nuxt:generate Generate file: /index.html +261ms
  nuxt: Call generate:routeCreated hooks (1) +1ms
pageのファイル作成が終わったよ
  nuxt:render Rendering url / +80ms
  nuxt: Call generate:done hooks (1) +1ms
  nuxt:generate HTML Files generated in 31.7s +2ms
  nuxt:generate Generate done +0ms
✨  Done in 34.32s.
```

ちゃんと出力されてました。

```
  nuxt: Call generate:routeCreated hooks (1) +1ms
pageのファイル作成が終わったよ
```

あとは個別の処理をここに書いていけば良さそうですね！
javaScriptでWEBカメラの映像をブラウザで表示する(PC/iPhone)

WEBカメラから映像をブラウザに表示するには、ノートPCだったら搭載のインカメラ、デスクトップだったらUSB型のWEBカメラ、スマホならインカメラ・背面カメラといろいろありるので取得してみます。

※2018年7月現在：実験段階の機能です。
※セキュリティの問題でlocalhostかHTTPSのみかな？


```html:index.html
<video id="video" width="640" height="480" autoplay></video>
```

* ビデオ属性のサイズ初期値は640*480の4:3です。
* ビデオ属性はautoplayで取得したそばから再生させます。
* PCの場合はautoplayのみでOK。
* iphoneの場合、初期値がフル画面のため、枠内に収める場合はplaysinlineを入れる
* iphoneの場合、はじめに停止ボタン出るけど止める方法あるのだろうか。
* インカメラの場合は左右反転するので、反転したい場合はCSSで対応します。
* (CSSを指定してもiphoneの場合、フル画面の場合は反転しません。)

```js
//動画流す準備
var video = document.getElementById("video");
// getUserMedia によるカメラ映像の取得
var media = navigator.mediaDevices.getUserMedia({
    video: true,//ビデオを取得する
    //使うカメラをインカメラか背面カメラかを指定する場合には
    //video: { facingMode: "environment" },//背面カメラ
    //video: { facingMode: "user" },//インカメラ
    audio: false,//音声が必要な場合はture
});
//リアルタイムに再生（ストリーミング）させるためにビデオタグに流し込む
media.then((stream) => {
    video.srcObject = stream;
});
```
https://developer.mozilla.org/ja/docs/Web/API/MediaDevices
Pytorchで３次元以上の配列の掛け算

Pytorchで３次元以上の配列の掛け算を行う必要に迫られたので、そのやり方をメモします。

# [torch.matmul(tensor1,tensor2)](https://pytorch.org/docs/stable/torch.html?highlight=torch%20matmul#torch.matmul)
上記の関数を使います。
一見して行列同士の掛け算を行う関数に思いますが、３次元以上の配列でも演算を行ってくれるようです。
３次元以上の配列の積といっても、テンソル積のようなものではなく、ミニバッチの行列演算を行ってくれるものです。

# 使用例(3次元配列と2次元配列)
$M$個の行列をまとめたミニバッチt1 $(M,p,q)$と$M$個のベクトルをまとめたミニバッチt2$(M,p)$がそれぞれあるとします。
このときミニバッチ中の各サンプルに対して次のように計算したいとします。
$y_i = x_iW_i\ \ \ \ \cdots (1)$
where $i = 1,\dots,M$
$x_i$はt1に含まれる、shape$(1,p)$の行ベクトル,$W_i$はt2に含まれるshape$(p,q)$の行列です。
もしW_iが一つだけで、t1がshape$(p,q)$の二次元配列なら上記の計算のためには行列演算として、t2*t1を計算しておけばよいのですが、いまshapeは$(M,p,q)$なので、行列演算できません。

そこでtorch.matmul()を使います。
torch.matmul()では引数の配列のうち、下二つの次元を行列とし、残りをサンプルとして計算を行います。
(1)式においてすべての$i$についての掛け算をやってくれます。

コード例です。

```python
import torch

t1 = torch.FloatTensor(3,2,2)
for i in range(3):
     t1[i,:,:] = torch.eye(2)*2**i
print('t1:\n',t1)
'''
t1:
 tensor([[[ 1.,  0.],
         [ 0.,  1.]],
        [[ 2.,  0.],
         [ 0.,  2.]],
        [[ 4.,  0.],
         [ 0.,  4.]]])
'''

t2 = torch.FloatTensor(3,2)
for i in range(3):
    t2[i,:] = 2**(2-i)

print('t2:\n',t2)

'''
t2:
 tensor([[ 4.,  4.],
        [ 2.,  2.],
        [ 1.,  1.]])
'''

t2 = t2.unsqueeze(1)
t2t1 = torch.matmul(t2,t1)

print('t2t1:\n',t1t2)
print('t2t1.shape:\n',t1t2.shape)

'''
t1t2:
 tensor([[[ 4.,  4.]],

        [[ 4.,  4.]],

        [[ 4.,  4.]]])
t1t2.shape:
 torch.Size([3, 1, 2])

'''
```
t1は(3,2,2)のテンソル、t2は(3,2)のテンソルです。
コード中の計算としては、[4,4],[2,2],[1,1]のベクトルを1,2,4倍しているだけです。
1次元目はサンプルとして、各サンプルにおける(1)式を計算したいとします。
まず、テンソルの次元はあっていないといけないので、t2を３次元にします。
行ベクトルにしたいので、unsqueezeで間に(3,2)の真ん中に１次元追加して(3,1,2)にします。
そのつぎにtorch.matmul(t2,t1)とすると、下2次元を使って(1,2),(2,2)の行列の掛け算とみなして、ミニバッチt2,t1に含まれる各サンプルに対してその行列計算をしてくれます。
帰ってくる配列のshapeは(3,1,2)です。

# 4次元以上
下2次元を行列とみて、残りの次元をサンプルと見てミニバッチ計算する点は同じです。
と言い切っておきますが、各サンプルに対してどう計算されているか少しよくわかりませんでした。必要に迫られなかったので今回はここまでとしました。
詳しくはテキストを読んでいただきたいです。

# なんでやった？
重みやバイアス自体にノイズを加えて計算したかったためです。
AWS Certificate Manager(ACM)をメール認証からDNS認証に切り替える

# 概要
AWS Certificate Manager(ACM)をメール認証からDNS認証に切り替えたい。
そうすることで証明書の自動更新が可能になる。

# 手順
既存証明書の認証方式をメール認証からDNS認証に切り替えることはできない。
なので、同じドメインで証明書をDNS認証で新規作成し、切り替えることになる。

# その他
ALBに証明書を適用している際、証明書の切り替え時に瞬断等は発生しない。
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-update-certificates.html
Raspberry Pi > MODBUS > MinimalModbus > Linkと動作確認(失敗)

```
Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
pySerial 2.6-1.1
Python 2.7.9
```

RPiでMODBUS通信を行う場合、どういうライブラリが必要か?

下記を見つけた。
[HOW TO USE MODBUS WITH RASPBERRY PI](http://www.instructables.com/id/How-to-Use-Modbus-With-Raspberry-Pi/)

上記で紹介されているのがMinimalModbus
http://minimalmodbus.readthedocs.io/en/master/index.html

pipでのインストール
http://minimalmodbus.readthedocs.io/en/master/installation.html

API
http://minimalmodbus.readthedocs.io/en/master/apiminimalmodbus.html

Manual testing of Modbus equipment
http://minimalmodbus.readthedocs.io/en/master/modbusdetails.html#manual-testing-of-modbus-equipment

### setup

上記ドキュメントに基づきインストールできた。

```shell
$ sudo pip install minimalmodbus
```

## MODBUS製品との通信

MODBUS製品と通信をしてみたが応答がない。

一方で、Windows 10で[RS232Cテストツール(NonSoft様)](http://nonsoft.la.coocan.jp/Download/Rs232cTool/index.html)で通信をするとデータシート通りの応答がある。

RPi + MinimalModbus + USBシリアル + pySerial 
の組合せの問題だろうか。

MinimalModbus を使わない通信でも失敗した。

別途、とある組込み基板での実装を試したところ、応答を確認できた。
使用ラインはTX, RX, GNDのみ。

(調査は保留)。
【Ubuntu Server 16.04 LTS】PHP7.0 + Apache2.4 + MySQL5.7環境を構築する

普段はCentOSを使ってWebサーバを構築するんですが、訳あってUbuntuで構築したときのメモになります。

## インストールされているパッケージを更新
```bash
$ sudo apt-get update
```

## Apache2.4をインストール
```bash
$ sudo apt-get install apache2
$ apaches -v
Server version: Apache/2.4.18 (Ubuntu)
Server built:   2018-04-18T14:53:04
```

### CentOSに慣れている人は注意
設定ファイルと実行ユーザがCentOSと異なるので注意してください。

* 設定ファイル（サイト公開用）：/etc/apache2/sites-available/000-default.conf
* 実行ユーザ・グループ：www-data

## PHP7.0をインストール
```bash
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get install php7.0 php7.0-mysql libapache2-mod-php7.0 php7.0-mcrypt php7.0-mbstring php7.0-xml
$ php -v
PHP 7.0.30-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: May  2 2018 12:43:14) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.30-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2017, by Zend Technologies
```

### Composerをインストール
Composerが必要な場合はこちらも行います。

> Composerは、PHPプログラミング言語向けのソフトウェアおよび必要なライブラリの依存関係を管理する標準形式を提供するアプリケーションレベルのパッケージ管理システムである。
> 引用元：https://ja.wikipedia.org/wiki/Composer

```bash
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ sudo mv composer.phar /usr/local/bin/composer
$ composer -V
Composer version 1.6.5 2018-05-04 11:44:59
```

## MySQL5.7をインストール
```bash
$ sudo apt-get install mysql-server
# rootユーザのパスワード設定を行う

$ mysql -V
mysql  Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using  EditLine wrapper
```
pythonセッティングメモ（virtualbox+vagrant+centos7.5）

pythonをセッティングした時の記録です。

バージョンに関しては違うものを複数入れて切り替えて使うことが一般的とのこと。
バージョンの管理にはpyenvを使うのが多そう。
（pipはパッケージ管理ツールでpyenvはpythonのバージョン管理ツール）

【参考ページ】
https://qiita.com/glostuan/items/6030e309542615470e0d
参考にさせていただきました。
ありがとうございます。

#概要
pythonの複数バージョンをインストールして切り替え（pyenvというツールを使う）が
できるようにセッティング。
以下はvirtualbox+vagrant+centos7にセッティングした時のメモ

#下準備として関連ツールインストール

```install.shell

yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel git

```

#pyenvインストール

```install.shell

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

```


#/home/user/.bash_profileを編集、以下追記

```install.shell

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

```

#.bash_profileの編集を反映させる

```source.shell

source .bash_profile

```

#pyenvでインストール可能なバージョンを確認

```list.shell

pyenv install --list

```

#pyenvにてpython本体（最新安定板）をインストール

```install.shell

pyenv install 3.6.6

```

#使用中バージョン確認

```version.shell

python --version

```


#pythonのバージョンをpyenvで切り替える

```changev.shell

pyenv global 3.6.6
pyenv rehash
python --version

```

ここまででpythonのバージョン管理ツールpyenvのインストール＆セッティング
pythonの最新版インストール＆デフォルト化セッティング


#pipセッティング
pipとはpython関連のパッケージを管理するツール。
パッケージマネージャーとも呼ばれ、
パッケージのインストール、アンインストール、
バージョンアップなどを実行するときに便利。

#ファイルをダウンロード

```download.shell
　　wget https://bootstrap.pypa.io/get-pip.py

```

#pythonのバージョンを指定してインストール

```install.shell

　　sudo python3.6 get-pip.py

```

#pipのバージョン確認

```version.shell

　　pip -V

```
RxJS v5からv6

# 今までのimport形式で使うなら
応急処置になりますが、`npm`でインストールできる`rxjs-compat`というライブラリで保管できるようです。

また`TypeScript`を使用している場合には`rxjs-tslint`というライブラリを使用するとリファクタリングしやすい模様

# 主な変化
1. import文のパス変更
1. 演算子の構文でpipeを使用
1. `Observable`で動作するクラスが関数に
1. result selector(etc. `resultScheduler`)は今後廃止されていく

# 詳細
## 1. import文
[import文例](https://rxjs-dev.firebaseapp.com/guide/v6/migration#import-paths)

## 2. pipe
v5.5からpipeが導入
tslintとrxjs-tslintを使用して互換性のあるものに置き換える前にpipeで書き換えるのが良い
[書き方](https://rxjs-dev.firebaseapp.com/guide/v6/migration#howto-convert-to-pipe-syntax)

## 3. Observableクラス
v6から全てのObservableクラスがなくなり同じ機能を持つオペレータが追加
`ArrayObservable.create(Array1)`が`from(Array1)`に変更もできるし新しく`fromArray()`というオペレータも追加
Observableにこんなに種類があったとは...[廃止予定Observable](https://rxjs-dev.firebaseapp.com/guide/v6/migration#observable-classes)

## 4. result selector
`resultSchedoler`の`first()`と`last()`は`rxjs-compat`でも保管されないよう
その他のmapping関数はv7リリース前まではほかのもの置き換えられる予定

## v7までに
1. `Observable.if` ->  `iif()`,  `Observable.throw`  ->  `throwError()`
1. "Creation"オペレータはすべて`rxjs/operators`  ->  `rxjs`
1. `merge`, `concat`, `combineLatest`, `race`, `zip`がなくなる
1.  その他... [v7までに変更するべきこと](https://rxjs-dev.firebaseapp.com/guide/v6/migration#howto-convert-deprecated-methods)

...`mergeMap`無くなるの！？
って思ったけどresultSelectorがなくなって書き方が変わるだけみたい
Gitlabでremote unpack failed: unpack-objects abnormal exitが出た時

自前で運用しているgitlabにpushしようとしたら

```
remote: error: unable to create temporary file: No space left on device
```

とか

```
error: remote unpack failed: unpack-objects abnormal exit
```

のエラーが出た。

調べるとinodeの枯渇ってことらしく、下記の状況。

```
$ df -i
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/xvda1      983040 982949      91  100% /
```

ファイル数を多く使っているディレクトリを計算。

```
find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
```

結果、linux-header関係が多いってことがわかったので、
どうやって消すか調べると未使用のバージョン指定して個別に消すという記事を発見。

面倒だし、ほんとに消していいかこのあたり不安しかない。

というわけでいい方法ないのかってことで、調べると

```
apt-get autoremove
```

これで解決する模様。

コレ自体の実行が失敗もありうる可能性はあるが。

実行して少し待つと解消。

```
# df -i
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/xvda1      983040 228724  754316   24% /
```

ファイルサイズも激減。
以前は数百MBしか残ってなかった。

```
# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       15G  8.0G  6.1G  57% /
```

環境はこちら。

```
Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-104-generic x86_64)
```
[Review]Neural Language Models

## Foreword
This a literature review-ish article to allow me to summarise my understanding on the domain of NLM.

## Papers

## 1. Factored Neural Language Models
### Profile:
Authors : Andrei Alexandrescu, Kartin Krinchhoff
Link: http://melodi.ee.washington.edu/people/katrin/Papers/alexand-kirchhoff-hlt06.pdf
Published Year: 2006

### Issue: ?? they have just investigated the further improvement in NLM.
### Approach:
They viewed a word as a vector of word features or “factors” : $w = $<$f_1, f_2, . . . , f_k$> and predict a word jointly from previous words and their factors.
Based on the original neural language model introduced by Bengio et al. in 2000, they have combined the factorisation and NLM, then this technique called Factored Neural Language Model.

*Bengio's NLM
<img width="702" alt="Screen Shot 2018-07-04 at 9.54.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/d96d4a41-ae3d-1afc-6b5e-2811260b3e41.png">
*Factored NLM
<img width="658" alt="Screen Shot 2018-07-04 at 9.55.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/be511e58-cf49-6a96-0698-d735e12f017f.png">
Ruby on Rails の ActiveRecord で結合先のテーブルを COUNT する場合は joins/left_joins が良い

Ruby on Rails の Active Record って便利ですよね。
SQL から解放されたかのようにデータアクセスできるので、心穏やかに DB と向き合えます。

でも、以下のような SQL をイメージしてデータを取得したい場合はどうでしょうか。

```sql
SELECT
  users.*,
  COUNT(thanks.id) AS thanks_count
FROM
  users
  LEFT OUTER JOIN
    thanks
  ON  users.id = thanks.user_id
GROUP BY
  users.id
;
```

`users` と `thanks` は親子関係のテーブルで、 1:n の関係性を持っているケースです。

`users` に紐づく `thanks` の件数を取得したいと考え、例えば以下のようなコードを書いてしまうと、よく聞く n+1 問題が発生してしまいます。

```ruby
User.all.thanks.each { |thank| thank.count }
```

この対処法としてよく聞くのが `eager_load` や `joins` などです。

`eager_load` とか `joins` とか `includes` とか、いろいろあって何がどうだったかよく分からなくなっちゃいますよね。
それぞれの特徴に関して、私はよく以下の記事を参考にしております。お世話になっております。

[ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い](https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58)

結論としては、結合先のテーブルで COUNT をしたい場合は `joins` が有効です。
`eager_load` では、結合先テーブルの全カラムを select に入れてしまい、集計関数が使えなくなってしまうためです。

なので、上記の SQL 的なデータアクセスをする場合は、以下のように書きます。

```ruby
User.all.left_joins(:thanks).group(:id).select('users.*, COUNT(`thanks`.`id`) AS thanks_count')
```

もし、これを複数箇所で使う場合、さらに他のテーブルなどにも汎用性をもたせたい場合、以下のように Model にメソッド化しておきたいですね。

```ruby
class User < ActiveRecord::Base
  scope :add_count_column, -> (join_table_name) do
    scope = current_scope || relation
    scope = scope.select("`#{table_name}`.#{Arel.star}") if scope.select_values.blank?
    scope.left_joins(join_table_name).group(:id).select('COUNT(`#{join_table_name}`.`id`) AS #{join_table_name}_count')
  end
end
```

上記の書き方は、以下の記事を参考にさせていただきました。ありがとうございます。

[Rails: SELECTするカラムを追加するscopeを定義する](http://www.techscore.com/blog/2013/08/30/rails-select%E3%81%99%E3%82%8B%E3%82%AB%E3%83%A9%E3%83%A0%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8Bscope%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B/)

## おわりに

Ruby on Rails の Active Record は良いツールではあるのですが、それだけで完結できないこともあります。
どこかで SQL を考え、パフォーマンスを意識しておかないといけないのかもしれません。

今回紹介した `joins` や、`eager_load`、`includes` を使いこなせると、こうした問題に立ち向かえる力が増すと思いますよ。
Amazon Sumerianで簡単な全天球画像ビューワーを作ってみる

Amazon Sumerianで簡単な全天球画像ビューワーを作ってみたので手順をメモしておく。
ビューワーは画像ファイルを選択すると周りを取り囲む球面に表示してマウスでグリグリと視点変更できるだけのもの。

# 作成手順

* シーンを作成する
* Spot Light Entityを追加する
* Default CameraのCamera ComponentのFollow Editor Cameraのチェックを外す
* Default CameraのScript ComponentでOrbitNPanControllScriptを削除してMouseLookScriptを追加する
* Default CameraのTransform Componentを以下のように設定する

||x|y|z|
|:--|:--|:--|:--|
|Translation|0|0|0|
|Rotation|0|0|0|
|Scale|1|1|1|

* 以下からSphere100.fbxを入手しドラドラする
 * [No hack, no work • UnityとOculusで360度パノラマ全天周動画を見る方法【無料編】](http://warapuri.com/post/131599525953/unity%E3%81%A8oculus%E3%81%A7360%E5%BA%A6%E3%83%91%E3%83%8E%E3%83%A9%E3%83%9E%E5%85%A8%E5%A4%A9%E5%91%A8%E5%8B%95%E7%94%BB%E3%82%92%E8%A6%8B%E3%82%8B%E6%96%B9%E6%B3%95%E7%84%A1%E6%96%99%E7%B7%A8)
* Assetsに追加されたSphere100.fbxのEntityをEntitiesにドラドラして追加する
* Sphere100.fbxのTransform Componentを以下のように設定する
 * Rotationを設定しているのは全天球画像の中心をカメラの中心にするため
 * RotationのYが-90でないのはSphere100の中心が微妙にずれているから(ただし正確な数字かはちゃんと検証していない) 

||x|y|z|
|:--|:--|:--|:--|
|Translation|0|0|0|
|Rotation|0|-93.60165|0|
|Scale|100|100|100|


* HTML Entityを追加する。
* HTML EntityのHTML ComponentのMove with Transformのチェックを外す
* HTML EntityのHTMLを以下のように編集する

```html
<input type="file" id="inputfile">
```

* HTML EntityにScript Componentを追加して以下のようなCustom Scriptを設定する

```javascript

'use strict';

function setup(args, ctx) {
    let input = document.getElementById("inputfile");
    input.addEventListener('change', (e) => {
        let file = e.target.files[0];
        let image = new Image();
        image.onload = () => {
             let material = args.target.meshRendererComponent.materials[0];
             material.setTexture('DIFFUSE_MAP' , new sumerian.Texture(image, {repeat: [-1, 1]}));
        } 

        image.src = URL.createObjectURL(file);
    });
}

var parameters = [
    {
        name: "Target",
        key: "target",
        type: "entity"
    }
];
```

* HTML Entityで追加したCustom Scriptのtarget parameterにSphere100.fbx配下のpSphere1_phong1を設定する(Sphere100.fbxではないことに注意)

# ハマったところ

## imageのロードタイミング

image.srcを設定した後すぐにsetTextureするとテクスチャが表示されずにグレイアウトしていた。
image.onload中でsetTextureするといけた。

あまりにハマったのでSumerianのSlackで質問したら解析してもらえた（自力解決したけど)。

![05d1ef02-96cc-472e-9a2a-b590535b8e8a.jpg](https://qiita-image-store.s3.amazonaws.com/0/16768/6839eabf-484c-40a6-5896-043670af42a1.jpeg)

## テクスチャの左右の反転

そのままテクスチャを作成すると全天球画像の左右が反転するのでテクスチャ生成時に[repeatオプション](https://content.sumerian.amazonaws.com/engine/latest/docs/Texture.html)をつけるとうまくいった。
これで本当に良いのかはわからないけどとりあえずこれでいってみる。

```
new sumerian.Texture(image, {repeat: [-1, 1]})
```
メモ: RDS PostgreSQL から Aurora PostgreSQL に移行したらシーケンスが巻戻る事があった件

一部のシーケンスが巻戻り、プライマリキーが重複してユニークキー制約違反となった。

数ヶ月前にフォーラムにて報告されていたらしく、現在鋭意修正中、だとか。

- [AWS Developer Forums: Aurora PostgreSQL breaking sequences ...](https://forums.aws.amazon.com/thread.jspa?threadID=274763)

現在および将来的な問題を回避するためには `setval` 関数を使って `is_called` を `false` にすればよい、とか。

> To avoid the issue, please follow these steps:
> 
> After migrating to Aurora PostgreSQL, before you begin using the database, for each sequence in your database follow these steps:
> Get the current state of the sequence by executing “\d ”. For example:
> ...
> Note the current last_value. To ensure the sequence doesn't regress in the future, we want to clear the is_called flag by executing “select setval(, , false)”. For example:
> select setval('id_seq', 115149, false);
> ...
> Notice the last value hasn't changed, but is_called is false and log_cnt is 0. On the next call to nextval() with these changes, Aurora PostgreSQL will write a fresh log record that guarantees the sequence number will not regress.
> 
> If you have already run a workload on your migrated snapshot and have encountered duplicate sequence numbers, you can repair the sequence using similar steps. Run a SELECT query on the table using the sequence to find the maximum value used, say maxval. Follow the steps above using maxval+1 as last_value. This will both set the next sequence value to something unique and clear the is_called flag to ensure the change is logged.

また、RDS/Aurora の修正がリリースされても、既存インスタンスについては作業が必要だとか。

> > Planning to run a sequence fix script tomorrow setting the maxval + 1 and the is_called flag to false on every sequence that I have.
> > 
> > Is that correct ?
>
> Yes, that is the correct remedy for instances that have already encountered this problem.
>
> Note, when we deploy a fix, the change will only affect new migrations from RDS Postgres to Aurora PostgreSQL-compatible Edition. Any migration that occurs before the fix is in place will still require the specified steps to correct the issue, even if the problem is not detected until after the fix is in place.
>
> We are working hard to test and deploy the fix. I'll update this thread when it is available.
AmazonDashボタンを使ってMastodonへにゃーんって呟いてみる

この記事は下記の記事の転載になります
[AmazonDashボタンを使ってMastodonへにゃーんって呟いてみる](http://gamelinks007.hatenablog.com/entry/2018/07/03/225223)

#はじめに
先日の松江Ruby会議09でのセッション時に話してた「にゃーんボタン」をさっそく作ってみた

ちなみに、その時のスライドは[これ](https://speakerdeck.com/gamelinks007/pu-tomastodon)
 
#必要なもの
- AmazonDashボタン(お好きなものを）
- Linuxマシン(amazon-dashを使うため)
- Wifi環境
 

##AmazonDashボタンの購入
AmazonDashボタンはプライム会員であれば簡単に購入できます。ちなみに、[こちら](https://www.amazon.co.jp/Amazon-Dash-Button-%E3%83%80%E3%83%83%E3%82%B7%E3%83%A5-%E3%83%9C%E3%82%BF%E3%83%B3/b?ie=UTF8&node=4752863051)から購入可能

購入後は[この記事](https://qiita.com/nardtree/items/23c36fa3b989d329a1f3)にあるようにスマホからセットアップを行う。

肝は、LinuxマシンとAmazonDashボタンの接続するWifiは同一のものを選ぶことと、商品選択は無視して設定を終了すること

##Linuxマシンでの設定
仮想マシンでもいいので、Linuxマシンを用意する。

用意出来たら、Python3とpipをインストール。

ちなみに僕が使ったのはLubuntu18.04で、Python3は既にインストール済みだったので、以下のコマンドを使ってpipだけをインストール

```sh
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
```
 
pipをインストールした後は、amazon-dashをインストールする

```sh
pip install amazon-dash
```
 
次に、AmazonDashボタンのMACアドレスを調べる。

```sh
sudo amazon-dash discovery
```

このコマンドを実行後、AmazonDashボタンを押すとMACアドレスが表示される。

 
そして、`amazon-dash.yml`を作成し、以下のように記述していく

```amazon-dash.yml
settings:
  delay: 0
devices:
  AA:AA:AA:AA:AA:AA:
    name: meow
    user: SH
    cmd ruby /home/SH/Desktop/nyaaan/meow.rb
```
 

で、実際にMastodonへ呟く`meow.rb`を作成

```meow.rb
require 'mastodon'

client = Mastodon::REST::Client.new(base_url:"呟きたいMastodonのURL", bearer_token: "アクセストークン")

response = client.create_status("にゃーん！")
```
 
最後に、rootで叩けるように変更

```sh
touch amazon-dash.yml
sudo chown root:root amazon-dash.yml
```
 

あとは、以下のコマンドを実行してAmazonDashボタンを連打するだけ

```sh
sudo amazon-dash run
```

#おわりに
とりあえず、これでAmazonDashボタンを使ってのMastodonへ「にゃーん！」って呟けるようになった！

皆さんも、ストレスがたまった時に押してみてはどうでしょうか？

#追記

凡そのことをよしなにしてくれるリポジトリを作ってあるので、そっちを使うと楽かも
[NyaaanDashButton](https://github.com/S-H-GAMELINKS/NyaaanDashButton)

 

以下、参考資料

[Amazon Dash Buttonを(正しくない方向で)使ってみた](https://qiita.com/takustaqu/items/8539b33780c9675c8657)

[Amazon Dashボタンで「今日は休みます」メールや、HDDを消したりします
](https://qiita.com/nardtree/items/23c36fa3b989d329a1f3)
今こそ語ろう、電子帳簿保存法の秘奥

#電子帳簿保存法という法令がある

法人の請求書や領収書の電子保存を認める法令だ。
経理業界ではちょっと最近、流行った。
今もまだ下火が燻っている。
##なんだか良さげだけど、うちでもできるの？
という会社さんはまだまだいるようだ。

本稿では電子帳簿保存法について言及を行う。
導入を考えている経理の方、
よく聞くけど何ソレ？という方にオススメだ。

#平成28年度電子帳簿保存法要件緩和
~~諸悪の根源~~
**電帳法が持て囃されるきっかけ**となった法令だ。
###えっ？！ スマホで請求書撮って、それを電子保存していいの？
##いいんです

ただし、簡単な手続きを踏む必要があります。
軽くご説明しましょう！


#1.電帳法について正しく理解する

###書類の電子保存ができる。###
###従って営業部門などの利用者、経理部門といった管理者双方がメリットを享受できる。###


**間違いじゃない。**
**確かにそれは電帳法対応の持つ効能の一側面だ。**
**でもそれが全てじゃない。**

まず、原本となる紙は即廃棄していいわけじゃない。「定期的な検査」を経たうえで廃棄するべし、と[神](https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/index.htm)によって定められている。

また、スマホで原本を撮影する際はその日付から3日以内。**原本を受け取った本人の署名を記載する必要がある。**下手な字でもいいから安心してくれ。[^1]

例として06月10日21時に接待でオネエちゃんの店に行った領収書は06月13日23:59分迄にタイムスタンプ押す必要があるってこった。
電帳法対応しているシステムのスマホ版を使えばこれは問題ない。[るろ剣](https://ja.m.wikipedia.org/wiki/るろうに剣心_-明治剣客浪漫譚-)風に言えば[**撮・即・押**](https://dic.pixiv.net/a/斎藤一%28るろうに剣心%29)だ。[^2]

[^1]…**読める字にしろよ！**
[^2]…撮影(画像)データをPDFに埋め込み、PDFに対してタイムスタンプを
押下するという動きになる。
  もしくは画像ファイルと紐づくタイムスタンプトークンを保管する。



#2.使用するシステムの選定

言わずもがな。
本稿のおまけとして、最下部に主だった製品を掲載しているぞ。参考にせい！

[電帳法対応システムを認定する第三者機関](https://www.jiima.or.jp/activity/certification/denchouhou/)も存在する。
ここに認定されているシステムを使うといいことがあるかもしれんな！ ガハハハ



#3. 所轄税務署への届け出

電帳法を適用するナウでヤングな法人はすべからく所定の書類を提出する義務がある。
下記項目を記載して、電子保存を開始する3ヶ月前までに提出するんだ。

- [x] 電子保存対象の国税関係書類種別
請求書とか領収書とか、書類の種類を選ぶ。

- [x] 使用する電子機器
プリンタやスマホ、デジカメについて記載する。**型番までキッチリ**とな！
届け出していない機器を使用した瞬間、**ジ・エンド！** 覚えておきな。

- [x] 使用するシステム

- [x] 使用するシステムで電子帳簿・関連取引を検索する際の検索条件
法令では「取引日、金額など複数条件の組み合わせで迅速に検索できること」と規定されているからな。

もっと詳しく知りたい？
そんな欲しがりさんは[こっち](https://goo.gl/VaEexF)を見てくれ！



#4. 電子帳簿保存法対応製品一覧
[らくらく旅費経費.net](https://rk2.mugen-corp.jp/ryohi/)
[楽楽精算](https://www.rakurakuseisan.jp/lp/denshichobo.html?gclid=EAIaIQobChMI7eevjJSE3AIVTIaPCh2V7QdEEAAYASAAEgJ9ifD_BwE)
[MFクラウド経費](https://form.biz.moneyforward.com/form/expense/110/?mfd_cam=gsn_ex&mfd_type=05_denshichoubo_DGBThinkhard&mfd_cre=text&mfd_word=電子帳簿保存法&mfd_others=gsn_ex_110)
[Concur](https://www.concur.co.jp/resources/ryoshusho-denshika-perfect-guide?gclid=EAIaIQobChMI7eevjJSE3AIVTIaPCh2V7QdEEAAYAyAAEgLBefD_BwE&pid=ppc&cid=jp_goo_web_c_search_-_erm_br_電子帳簿_保存法とは&s_kwcid=AL!5232!3!259821844445!b!!g!!電子帳簿%20保存法とは&ef_id=WzwQ7gAAAK34y-fR:20180704001230:s)
[TKC](https://www.tkc.jp/consolidate/tds?gclid=EAIaIQobChMI7eevjJSE3AIVTIaPCh2V7QdEEAAYBCAAEgIV2vD_BwE&gclid=EAIaIQobChMI7eevjJSE3AIVTIaPCh2V7QdEEAAYBCAAEgIV2vD_BwE)
まだまだあるぞ！



##以上です
JavaScriptで扱える整数の最大値は？

# オーバーフローとラップアラウンド
Go言語を勉強しているのですが、Go言語にはオーバーフローが起きた時に、その演算結果をラップアラウンドさせるという仕様があります。

```go
b := byte(255)
b = b + 1 // b ==0
```

# javascriptはどうなっているのか
そこで、javascriptはどうなっているのか気になりました。

一応、言語仕様的には**安全**に計算できる範囲は`9007199254740991`のようです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

では、64bitの最大値`18446744073709551615`を扱うとどうなるのか？？
以下はchromeのconsoleで試した結果です。
勘違いして**18446744073709551616**で計算してしまっていますが、結果は変わらなかったのでスルーしてください:poop:

<img width="338" alt="スクリーンショット 2018-07-04 7.28.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/140178/33ae24c1-8ce3-5f61-e4c5-1638b8839656.png">

![スクリーンショット 2018-07-04 9.04.48.png](https://qiita-image-store.s3.amazonaws.com/0/140178/28f0d50c-f5a5-e0f7-3d0f-5cf90ab42016.png)

上記を見る限り、ラップアラウンドはされてないっぽい。

---

ここまでやって気づいたのですが、JSは符号ありだから最大値は`9223372036854775807`かも？？
以下、結果です。

![スクリーンショット 2018-07-04 9.12.42.png](https://qiita-image-store.s3.amazonaws.com/0/140178/3c25635f-f2d0-e1b6-723c-34619b721105.png)

全然関係なく、計算できなかった・・・:raised_hand:

最初に書いた通り、MAXは`9007199254740991`と思った方が良さそう・・・？？:ear:
UMLをソースコードで書く　PlantUML

excelでユースケース図を作成していたのですが、時間がかかりすぎるので、
別の方法を探していたところ、PlantUMLなるものを発見。
ソースコードでUMLが書けるようなので、早速導入する。

PlantUMLをAtomで使えるようにする。

～追記～
Atomを導入する理由は、リアルタイムプレビューが便利だからなのですが、
私の環境では、動作が安定しませんでした。
なくても、問題ないので、下記『追記：Atomなしでリアルタイムプレビューを実現』をご確認ください。

# PlantUMLをインストールする
下記からplantuml.jarをダウンロードする
[PlantUML](http://plantuml.com/download "PlantUML")
![UML000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/14c7c249-2b1b-bea8-524e-96b70de11f86.jpeg)

jarの保存場所は、好きなところでよい

# Graphvizをインストールする
Graphvizは、グラフデータ構造の可視化のツール

1.下記からダウンロードする
[Graphviz](https://graphviz.gitlab.io/download/ "Graphviz")

2.「Windows」のところにある 「Stable」版を選ぶ
![UML000003_.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/6817f3d5-dd0a-19dd-f819-0d0f21943ae5.jpeg)

3.「＊.msi」を選択する
![UML000004_.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/e97c5c6b-e6fd-232f-408a-59d43914e212.jpeg)

4.「＊.msi」を実行する

5.「Next」をクリック
![UML000003.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/1fc3de9f-96d5-a212-0beb-91700f83e945.jpeg)
6.「Everyone」を選択し、「Next」をクリック（インストール先はお好きなところへ）
![UML000004.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/cdb92a1b-e765-04f6-4e47-8958ff4297a5.jpeg)
7.「Next」をクリック
![UML000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/8ff59a4c-fce2-df22-046f-ee87b5d8483c.jpeg)

8.「Next」をクリック
![UML000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/70c53bc3-89ba-ded4-ee5b-2345267d87d8.jpeg)

9.「Close」にて完了
![UML000007.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/a9650614-fa6d-693b-16e4-c3606d0ea076.jpeg)

10.ちゃんと使えるようになっているかどうかを確認
下記コマンドを実行する。
結果が表示されたら、OK
```
>java -jar "plantuml.jarのパス" -testdot

The environment variable GRAPHVIZ_DOT has not been set
Dot executable is c:\Program Files\Graphviz2.38\bin\dot.exe
Dot version: dot - graphviz version 2.38.0 (20140413.2041)
Installation seems OK. File generation OK
```

# Atomプラグインのインストール

下記をインストールする。

- language-plantuml
- plantuml-viewer

### plantuml-viewerの設定
 - Settings で「charset」 を「UTF-8」にしておく。 
 - 「GraphViz Dot Executable」にパスを設定しておく。(スクショの通り、GraphVizフォルダのbinの下にあります）


![UML000009.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/2656711e-d26e-1737-746f-8818d524af60.jpeg)

# 追記：Atomなしでリアルタイムプレビューを実現
plantuml.jarには、GUI機能があり、これを活用します。

下記を実行します。
 - オプションguiは、GUI機能の実行
 - オプションcharsetは、文字コードの選択


```

> java -jar "plantuml.jarのパス" -gui -charset utf-8

```

GUIが起動します。

![atom000010.JPG](https://qiita-image-store.s3.amazonaws.com/0/10966/974064d7-d5da-97b1-4010-4d9998840c39.jpeg)

「Change Directory」ボタンにて、PlantUMLのソースがあるディレクトリを選択してください。
今回は、以下を準備

```:sample.puml

@startuml{sample.png}

title sample

actor ユーザ as user
left to right direction
user -d-> (物を買う)
@enduml

```

ディレクトリを選択すると、自動でsample.pngを出力してくれますので、sample.pngを開きます。
ファイルを変更し、上書き保存すると、自動でsample.pngも書き換わります。


# 参考

ありがとうございます。

[PlantUMLをAtomで使う in Windows7](https://qiita.com/utsumin/items/bc34b74ed529f566d912 "PlantUMLをAtomで使う in Windows7")






以上!