OmniAICreator/Qiita-1.07M huggingface dataset:
Ransackの検索フォーム入力をクリアする（javascriptバージョン)

# 検索フォームに入力した内容をクリアにする
今回はgem ransackで実装した検索フォームの入力をクリアしてみます。

### やりたいこと
javascriptを使用する際には　適用するclass またはid　をしっかり記述しておきましょう。

クリアボタンをクリック
∟ → id:"serach-clear"発火
　 ∟ → class side-search_sort のselectは空に
　 ∟ → class side-search__group__labelのinputは空に
　 ∟ → class side-search__group__formsのinputは空に

こちらが　Hamlファイルの記述

```ruby:/views/products/searches/index
.side-search
      = search_form_for(@q,url: products_searches_path) do |f|
        .side-search_sort
          = f.select( :sorts, { '並び替え': 'id desc', '価格の安い順': 'price asc', '価格の高い順': 'price desc', '出品の古い順': 'updated_at asc', '出品の新しい順': 'updated_at desc' } , { onchange: 'this.form.submit()'} ,class:"side-search__sort")
        .side-search_form
          .side-search__title
          %h3 詳細検索
          .side-search__group
          .side-search__group__label
            %p キーワードを追加する
            = f.search_field :name_cont, placeholder: "例）値下げ",class:"side-search__textarea"
          .side-search__group
            .side-search__group__label
            %p 価格 
          .side-search__group__forms
            = f.search_field :price_gteq, placeholder: "¥ Min",class:"side-search__pricerange"
            %p 〜
            = f.search_field :price_lteq, placeholder: "¥ Max",class:"side-search__pricerange"
          .input-form-box
            %label 商品の状態を指定する
            = f.select :status_eq, Product.statuses.keys,{prompt:"---"},class:"side-search__status"
          .input-form-box
            %label 配送料の負担　　　　　
            = f.select :postage_eq,Product.postages.keys,{prompt: "---"},class:"side-search__postage"
          .input-form-box
            %label 発送元の地域　　　　　　　　　
            = f.select :prefecture_eq,Product.prefectures.keys,{prompt:"---"},class:"side-search__postage"
          
          .side_search__btn
            .side_search__btn--grey{ id:"search-clear",class:"side_search__btn--grey"}
              クリア　
            = f.submit "完了",class:"side_search__btn--red",id:'search_submit'
```

表示はこんな感じ

[![Image from Gyazo](https://i.gyazo.com/01baf50791fa735493d7a6b9bc76f382.png)](https://gyazo.com/01baf50791fa735493d7a6b9bc76f382)

# js ファイル作成

```javascript
$(function () {
  $('#search-clear').click(function (e) {

    $('.side-search_sort').find('select').val("");
    $('.side-search__group__label').find('input').val("");
    $('.side-search__group__forms').find('input').val("");
    $('#search_submit').val("完了");
    e.preventDefault();
    return false;
  });
});
```
検索フォームだけ　クリアします
[![Image from Gyazo](https://i.gyazo.com/444f4b00fa673d896602d8da2b5f48e7.gif)](https://gyazo.com/444f4b00fa673d896602d8da2b5f48e7)

gem ransackはかなり高機能なgemで　様々な検索ができます。その機能紹介はまた別の機会に。
【Rails】既存のモデルに timestamp を追加したい

# 問題点
既存モデルに timestamp を追加したい時、下記の様にマイグレーションファイルを作成し実行するとエラーになってしまいます。

```rb
def change
  add_timestamps :products, null: false
end
```

これは、過去のレコードの timestamp が、 NULL になってしまうのが原因です。


# 解決方法
1. 一旦`null: true`とし一時的に NULL を許容する。
2. 過去のレコードに適当な古い日付を追加し、timestamp の NULL 状態を回避する。
3. 最後に再び`null: false`とする。


```rb
def change
  add_timestamps :products, null: true 

  long_ago = DateTime.new(2000, 1, 1)
  Product.update_all(created_at: long_ago, updated_at: long_ago)

  change_column_null :products, :created_at, false
  change_column_null :products, :updated_at, false
end
```
AWS Lambda で Javaを使う ーEclipse準備編

##やりたいこと
AWS Lambdaで実行するJavaを実装する

##AWS Lambda で Javaを使う　目次
・[Eclipse準備編](https://qiita.com/t_ookubo/items/a71a9bd05282bf20e023)
・登録実行編（いつか）
・[実装編 - EC2を止める/立ち上げる](https://qiita.com/t_ookubo/items/3b12bd985a65a73b4c59)
・[実装編 - CloudWatchの引数を確認する](https://qiita.com/t_ookubo/items/18d47265d39bba4364b8)
・[実装編Tips - ReagionとInstanceIDからInstance名を取得する](https://qiita.com/t_ookubo/items/619d8029546447e61391)

## Eclipse準備編
まずは、開発環境を整える。
AWS Toolkit for Eclipseというのが準備されているので、それを利用する。
https://docs.aws.amazon.com/ja_jp/toolkit-for-eclipse/v1/user-guide/setup-install.html

↑に従うと
Eclipse→[Help] →[Install New Software] からインストールできるはずなのだけど、
ネットワークの問題なのかなんなのかうんともすんとも言わなかった。

ので、↓の「Drag and Drop Install」からインストールした。
https://marketplace.eclipse.org/marketplace-client-intro?mpc_install=907


とりあえず、全フィーチャーを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/594c4883-1dd6-ef13-998b-b4736db8d4b2.png)

条件に同意して、完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/10824c16-30ac-4fdd-8f06-0c10b54ed62b.png)

そして、再起動すると、AWSアカウントの構成を求められる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/0ad73d50-b5d1-f904-fc43-96d6e2cceb9f.png)


↓の「アクセスキー ID とシークレットアクセスキーを取得するには」を参考にして、アクセスキーを作成。
https://docs.aws.amazon.com/ja_jp/toolkit-for-eclipse/v1/user-guide/setup-credentials.html


作成した内容を入力すると、↓が出てくるので、完了を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/d3206ab9-1faa-7cda-bda1-5f4d73dd476f.png)

そうするとAWS Explore Viewがでているので、完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/dcfe46aa-26bb-93d7-2417-3c4888d23ade.png)


## サンプルソースを見てみる

AWS Exploreマークのボタンから、いろいろAWSのプロジェクトが見れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/8075d5f4-eea1-8ac7-0c53-c1da6db69188.png)

ここで、Lambdaを選ぶとサンプルパッケージが作らるので、これを参考にしながら実装できる、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/9a17ddc3-0619-bbc6-6ac0-b84a6a5174bb.png)
【Udemy Python3入門+応用】　31. コメント

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**



##■コメント
```python:comment
print('XXXXX')
# 見せられないよ！
# 見せられないよ！
# 見せられないよ！
print('XXXXX')
"""
見せられないよ！
見せられないよ！
見せられないよ！
"""
print('XXXXX')
```
```:result
XXXXX
XXXXX
XXXXX
```
`#`を行の先頭に入れるか、
複数行にわたる場合は`"""`で挟む。
RaspberryPi 3+ に簡単にOpenCVをインストール

# 1)OpenCVのインストール
昔はめんどくさかったopencvのインストールも下記のコマンドで一発でインストール


```python
sudo pip3 install opencv_python
```

(OpenCVの後はアンダーバーです。ずっとハイフンでやって困ってました。)

たったこれだけで、OpenCVは入るはず。
COTOHA APIで Pen Pineapple Apple Pen

# COTOHA API
[COTOHA API](https://api.ce-cotoha.com/contents/index.html)を使えば、簡単に日本語解析ができる。

COTOHA APIの構文解析のページには「日本語テキストの構造と意味を解析するRESTful APIです」という説明がある。

僕はこの説明に騙されていた。
日本語しか解析できないのだと。
いや、騙されていたのではなく、勝手な思い込みだった。

# COTOHA APIでの英語まじり文の解析
COTOHA APIで「新装open」を解析すると、"open" の解析結果の kana には「オープン」が入っている。
※以下は解析結果の一部の要素のみ

```javascript

[{
      "form" : "新装",
      "kana" : "シンソウ",
      "lemma" : "新装",
      "pos" : "名詞"
}, {
      "form" : "open",
      "kana" : "オープン",
      "lemma" : "open",
      "pos" : "名詞"
}]
```

COTOHA API は日本語だけでなく、英単語も解析できたのだ。

# 英文を解析してみる
英単語まじりの日本語文ではなく、英文を解析してみよう。
"I have two computers" を解析すると、以下のような結果が得られる。
（主要な要素のみを抜粋）

```javascript
[ {
      "form" : "i",
      "kana" : "アイ",
      "lemma" : "i",
      "pos" : "名詞"
    }, {
      "form" : " ",
      "kana" : "",
      "lemma" : " ",
      "pos" : "空白"
    }, {
      "form" : "have",
      "kana" : "ハブ",
      "lemma" : "have",
      "pos" : "名詞"
    }, {
      "form" : " ",
      "kana" : "",
      "lemma" : " ",
      "pos" : "空白"
    }, {
      "form" : "two",
      "kana" : "ツー",
      "lemma" : "two",
      "pos" : "名詞"
    }, {
      "form" : " ",
      "kana" : "",
      "lemma" : " ",
      "pos" : "空白"
    }, {
      "form" : "computer",
      "kana" : "コンピューター",
      "lemma" : "computer",
      "pos" : "名詞"
    }, {
      "form" : "s",
      "kana" : "ズ",
      "lemma" : "s",
      "pos" : "英語接尾辞",
}]
```

各 token の kana には英単語のカタカナでの読みが入っている。
しかも、computers は computer と s に分解されている。
日本語だけじゃなく、英文も解析できているじゃないか。
何で教えてくれなかったんだ。

# オレ チュウガクセイ ナル
はじめて英語を勉強した中学生になったつもりで、英文をカタカナ読みに変換してみよう。
COTOHA API を使えば、kana を使うだけで十分だ。

[1] 英文を COTOHA API で解析する。
[2] 各 token のカナを出力する。
　　ただし、読みやすさのため、kana が ""（空文字）の場合には、" "（空白） を出力する。

各 token の kana を出力するのは、@Harusugi さんの[ゲンシジン](https://qiita.com/Harusugi/items/f499e8707b36d0f570c4)と同じだ。
（もしよろしければ[前の記事](https://qiita.com/dakikd/items/08b5b239d98f955e5565)もご覧ください）

実際に英文を解析してみよう。

I want something just like this
⇒　アイ ウォント サムシング ジャスト ライク ディス
うん、うまくいっている。

He was excited
⇒　ヒィー ワズ エキサイテッド
「ヒー」ではなく、「ヒィー」だ。
カタカナ翻訳へのこだわりが感じられる。

Thank you
⇒　サンク ユー
「サンキュー」ではなく、逐語訳の「サンク ユー」。
丁寧な翻訳だ。

# Pen Pineapple Apple Pen
ここまでで COTOHA API が英語にも対応できていることが十分にわかった。
ここで、この記事のタイトルにもある "Pen Pineapple Apple Pen" を解析してみよう。

Pen Pineapple Apple Pen
⇒　ペンパイナップルアップルペン

ちゃんとカタカナに翻訳できている。
いや、何か違うぞ。
token 間には空白が入るはずなのに、空白がはいっていない。
解析結果をみてみよう。

```javascript
{
      "form" : "pen pineapple apple pen",
      "kana" : "ペンパイナップルアップルペン",
      "lemma" : "pen pineapple apple pen",
      "pos" : "名詞"
}
```
何と、"pen pineapple apple pen" は、ひとつの token として解析されていた。
解析用の辞書に登録されているに違いない。
恐るべし、COTOHA API。

# その他の解析結果
他にもいろいろな英文を試してみたが、うまくいかない場合もあった。

I have a book
⇒　アイ ハブ エー ブック
"a" が「エー」になる。

We will rock you
⇒　ウィ ウィル ロカビリー ユー
辞書が充実しているせいか、"rock" の kana が「ロカビリー」になる。

最後に。

COTOHA
⇒　シーオーティーオーエッチエー
辞書に登録されていない単語はアルファベットの読みを連結しているようだ。
要件定義品質向上への突破口～RDRA2.0の提案～

昨年のことになりますが、アプリケーション開発におけるモデルベースの要件定義手法である「リレーションシップ駆動要件分析 RDRA2.0」の作者である神崎善司さん（[@zenzengood](https://twitter.com/zenzengood)）をお招きし、社内で勉強会を開催しました。

![EEG5Q2BUEAIZBQO (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131112/54622a3b-57af-acc7-bd6d-d8ad8aa7111c.jpeg)
[当日の様子](https://twitter.com/yasuoyasuo/status/1171421091702562816)

RDRA2.0についてはこちらを記事を是非ご覧ください。

[リレーションシップ駆動要件分析(RDRA)](https://qiita.com/tatane616/items/f7f4e5ad818fe8b125d6)
[RDRA２.０についてまとめみた（前編）](https://qiita.com/neoti0_tech/items/dab2f035221f9cdb6cd1)
[RDRA２.０についてまとめみた（後編）](https://qiita.com/neoti0_tech/items/b4606e8ede34368f49cd)

#参加者の声
参加者からのアンケートは以下のようなものでした。

>相手（顧客）のレイヤーによっても、プロジェクトのフェーズによっても変わってくると思いますが、いかに相手に伝わる、相手に伝えるために考えられたフレームワークかということを感じられました。ぜひ今後この考え方を参考にさせてください。ありがとうございました。

*
>少しお話もさせていただきましたが、私はUIデザインを担当する立場から今回のお話を聞かせていただき、大変勉強になりました。数え切れない数のシステムと要件定義が存在する中で、今回のような新しい手法が生み出されているということはそれだけ要件定義というもの自体に課題があるのだろうと実感しました。

*
>「要件定義の段階でHOWを考えるとすべてにおいて手がとまる」と話されていたのが、個人的にとても印象に残りました。私もHOWまで考えていて、とても苦労しました。今回受講させて頂き、要件定義で何を可視化して、顧客に説明すればよいのかとても参考になりました。
ありがとうございました。

*
>「決める」要件定義をするために、システムの機能自体だけを見て議論をするのでなく、依存関係を持つ外側のレイヤーから議論を進めていくという考えが勉強になった。現在、コードの修正をする際に他への影響調査に苦労することがあるので、今回の話の中にあった影響度分析がしやすくなるという点も良いと思った。1時間半の中で盛りだくさんの話を聞かせていただいたので、まだ内容を整理しきれていない面はあるが、学びが多く楽しい勉強会だった。

#要件定義で一番大切にするべきこと
結局RDRAでやりたいことは何なのか？書籍を読んだり何度かお話を聞ききつつ、実際に自分でも書いてみながら考えました。多分ポイントだと思うことを表現しているスライドを抜粋しました。

![picture_pc_1c032902027a071c9e9e67552e0bea54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131112/a203fdf5-c5f8-bdca-5dac-a247af23e6d3.png)

「一覧」→「詳細」型でタスクを割り振り、各担当者が相互連携して全体整合を維持しながらそれぞれの要件を深堀りしていくというのは、私の経験上理想でしかありません。
ほっておくとタコツボ化しがちなPJ作業において、常に全体像をわかりやすく表現し、かつそのつながりを検証できる価値は非常に大きいと思います。

「伝え方が９割」という本もありましたが、まさにシステム開発の要件もその典型です。利用ユーザーとベンダーとの境界がなくなり、全員で整合性と網羅性の担保を意識し続けられれば、大きな手戻りを要する要件不備は防げるはずです。「誰か一人の優秀なPMやSEに頼るのではなく、全員で要件の抜け漏れや不整合を防ぐー」全体をわかりやすく表現できる手段を持つことは、上流工程においてチームで品質を創り込む上で不可欠なツールと言えるでしょう。

#実際書いてみた
ある内製の社内システムの要件定義をRDRAで書いてみました。
<img width="833" alt="0e48b8ef2669b9b46db7d910a548456b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131112/f3527ab7-1c1d-09d8-8842-850602a55c31.png">

書いてみた印象としては、業務階層を順次ブレイクダウンさせながらDFD的業務フローを書いている印象でした。慣れると結構サクサク進みますし、まったくRDRAの記述様式を知らない他のメンバーの可読性も高かったのが印象的でした。書式にのっとり書くのは多少ハードルはあるが、書いてあるものを理解することはさほど大変ではないことがわかりました。

また標準書式にはありませんでしたが、ビジネスユースケースに要件定義時に並行して作成したワイヤーフレームを添付させました。（図中のP6,P7,P10）弊社では要件定義時にデザイナーチームが参画しデザインテイストを加えながらワイヤーを書くことが多く、今回もそのアプローチをとりましたが、各画面がどういったシーンで利用されるかが俯瞰でき非常にわかりやすくなりました。

また継続して実践事例を重ねながら、ノウハウを共有していければと思います。
pipをアップデートした後pipコマンドを実行しようとすると「No such file or directory」って言われた

#  問題「sudo pip install --upgrade pip」後にpipコマンドが使えない
`sudo pip install --upgrade pip`でpipをアップデートしたら、色んなpipコマンドを試したが、`bash: /usr/bin/pip: No such file or directory`って言われた。

# 解決法 `hash -r`
`hash -r`をターミナルで実行したら直った。

# 自分なりの解釈
[参考サイト](https://www.atmarkit.co.jp/ait/articles/1703/23/news017.html)によると、
>シェルがビルトインコマンドではないコマンドを実行する場合、環境変数PATHから該当する実行ファイルを探す必要がありますが、頻繁に使うコマンドは「ハッシュテーブル」と呼ばれる場所に記憶しています。「hash」はこのハッシュテーブルの表示や削除、追加を行うコマンドになります。

要するに、**OSは、「内蔵されていない、頻繫に使うコマンド」をハッシュテーブルに記憶している**ということだ。
つまり、

1. pipをインストールしたとき、前バージョンのpipはアンインストールされた
2. だが、ハッシュテーブルには前バージョンのpipのPASSが記憶されままだった
3. ターミナルでpipコマンドを実行しても、OSはハッシュテーブルを見て、前バージョンのpipを探した
4. 前バージョンのpipはアンインストールされていたから見つからない

といった具合だろうか。

# 次起こった時は？
[参考サイト](https://www.atmarkit.co.jp/ait/articles/1703/23/news017.html)によると、
>`hash -r`はハッシュテーブルに記憶しているパス情報を消去する

らしい。これでは前バージョンの情報以外の削除してほしくない記憶まで消されそうだ。そこで、
> `hash -d コマンド名`はコマンド名に対応する記憶を削除する。

また、
> `hash`だけを実行すると、ハッシュテーブルに記憶されているパス名と、そのパスでコマンドを実行した回数が表示されます。

とあるので次回は、まず`hash`でハッシュテーブル内を確認し、`hash -d コマンド名`で不要な記憶だけを削除しようと思う。
#PowerAutomate で動的なプロパティ名を持つ JSON を扱う方法 (別の方法) 

@shibatea さんのまとめてくれた投稿: [#PowerAutomate #LogicApp で動的なプロパティ名を持つ JSON を扱う方法](https://qiita.com/shibatea/items/a391936f0e712f6f769b) では、Microsoft Graph API で取得した Planner のタスクに含まれるチェックリストの情報のうち、チェックリストID自体がKeyであるということをいかに克服するかが書かれています。

ここでは、その方法とは少し違う手段で、チェックリストIDの一覧を作るところまでを紹介します。

以下のTweetがヒントでした。アドバイスをくれたJohnに感謝！
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Hack <a href="https://twitter.com/hashtag/FlowNinja?src=hash&amp;ref_src=twsrc%5Etfw">#FlowNinja</a> 86 while playing with Create CSV in <a href="https://twitter.com/MicrosoftFlow?ref_src=twsrc%5Etfw">@MicrosoftFlow</a> I thought hmm 💡<br>well well, another hack.<br><br>1. Create CSV: automatic header - automatically selects every property name of the first item.<br>2. So this can be used to perform keys(object) <a href="https://t.co/pAXW1r5cv3">pic.twitter.com/pAXW1r5cv3</a></p>&mdash; John Liu 劉 (@johnnliu) <a href="https://twitter.com/johnnliu/status/1110180968285921280?ref_src=twsrc%5Etfw">March 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# Create CSVを使った方法
設定を同一にするために、@shibatea さんの記事からjsonを拝借してきて、Composeします。
その後のステップは
1. Composeアクション で、Planner task detailのchecklistを取得して、1"行"の配列にする。
2. 1行の配列から、Create CSVアクションでCSVを作成する。その際にAdvanced OptionはAutomaticのまま。
3. 生成されたCSVの1行目を取り出すために、CR+LFの改行コードでSplitして、0番目をとる
4. 得られた結果を","(カンマ)でsplitして配列にする
これだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/75559572-99db-6463-b64e-1928c9572576.png)

##各ステップの実行結果
### 1.の結果

```
outputs('PlannerTaskDetail')?['checklist']
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/abf4b2cc-d6fe-4338-90db-558275bc73bc.png)
1行の、チェックリストIDをKeyとする配列ができている。OK

### 2.の結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/0897d0ab-adb8-d6f6-b2c6-01cccc4a96f5.png)
うまく同じ階層のプロパティを引っ張ってこれている！

### 3.の結果
```
first(split(body('Create_CSV_table'),decodeUriComponent('%0D%0A')))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/89f08ea0-1b6d-20b3-2f40-3bec19316308.png)
ここの段階ではまだ"37396,60542,66123"という文字列

### 4.の結果
```
split(outputs('Get_Header_Row'), ',')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/7a76d2ff-5479-8c9c-dbf5-548f3f85cc29.png)

# おわり
素晴らしいチャレンジのきっかけをくださった @shibatea さんに感謝をするとともに、だいぶ間があいたのに覚えていてアドバイスをくれた[John](https://twitter.com/johnnliu)にも感謝を申し上げます。

# Acknowledge
To write this blog post, John Liu kindly provided me a helpful advice.
I really appreciated his support!!
Ref: http://johnliu.net/
損失関数とは？？〜機械学習の用語まとめ〜

#損失関数の役割
ニューラルネットワークを学習するときには、正解ラベルのあるデータをニューラルネットワークに入力し、その出力と正解ラベルを比較して、ニューラルネットワークの重みを更新していく。この時出力と正解ラベルから、ある指標となる値出力させるものが**損失関数**である。
**損失関数**は主に、ニューラルネットワークの悪さを表す値であるので、できるだけ値が小さくなるようにニューラルネットワークの重みを更新していくことになる。

#損失関数の種類
今回は、代表的な損失関数として
(分類)２乗和誤差、交差エントロピー誤差
(回帰)平均２乗誤差、平均絶対誤差
を紹介する。

###２乗和誤差
２乗和誤差は以下のような式によって計算される。
$$
E = \frac{1}{2}\sum_{k} (y_k - t_k )^{2}
$$
$y_k$はニューラルネットワークの出力、$t_k$は教師データを表している。
例えば5分類のニューラルネットワークの活性化関数としてソフトマックス関数を用いた時には、各ラベルに対して0~1が与えられる。(例)[0.1 , 0,7 , 0.05 , 0 , 0.05]
一方、正解ラベルが2の時は、[0 , 1 , 0 , 0 , 0]という教師データとなる。(**one-hot表現**)
これに対して２乗和誤差は
$$
(0.1)^{2} + (0.3)^{2} + (0.05)^{2} + (0)^{2} + (0.05)^{2} = 0.105
$$
となる。
この場合出力の２つ目が１に近づき、それ以外が０に近づくと、２乗和誤差が小さくなる。
ソフトマックス関数の出力は各ラベルの確率も捉えられるので、２乗和誤差が小さくなればなるほど、良いニューラルネットワークとなっていることが納得できる。

###交差エントロピー誤差
交差エントロピー誤差は以下のような式によって計算される。
$$
E = -\sum_{k}  t_k \ log \ y_k
$$
先ほど同様、$y_k$はニューラルネットワークの出力、$t_k$は教師データを表している。
教師データは正解ラベルが１で、それ以外は０なので、正解ラベルに対応する出力のみが影響する。
活性化関数としてソフトマックス関数を用いた時には、出力が0~1となる。対数は以下のグラフのように0~1において、-∞〜0の値をとる。
<img width="253" alt="スクリーンショット 2020-03-03 23.33.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470838/757cdd0e-1eda-79fa-2594-e26cfba0b93e.png">
交差エントロピー誤差にはマイナスが付いているので、２乗和誤差同様、出力が１に近づくと小さくなり、出力が０に近づくとかなり大きな値となる。
２乗和誤差と比較すると、他のラベルの値は影響を受けないが、正解ラベルに対応する出力が0に近いと無限に大きくなってしまう。

###平均２乗誤差(MSE)
ここからは主に回帰問題で用いられる損失関数だ。
平均２乗誤差は以下のような式によって計算される。
$$
 MSE(y_i , \hat{y_i} )= \frac{1}{n}\sum_{i=1}^{n} (y_i - \hat{y_i} )^{2}
$$
$y_i$は実測値、$\hat{y_i}$は予測値である。
回帰問題においては一番基本的な関数である。このあと紹介する平均絶対誤差よりも外れ値の影響が大きくなる損失関数である。

###平均絶対誤差(MAE)
平均２乗誤差は以下のような式によって計算される。
$$
 MAE(y_i , \hat{y_i} )= \frac{1}{n} \sum_{i=1}^{n} | y_i - \hat{y_i} |
$$
先ほどの平均２乗誤差よりも外れ値に強い。

なお、ここで紹介したのは一部であり他にも様々な損失関数を存在する。

#損失関数を使う理由
分類問題の精度だけを測りたいのであれば、損失関数を使わなくても正解率だけを考えれば良い。ではなぜ損失関数を用いるのか。それはパラメータの更新において重要だからである。
正解率を指標にしていると、パラメータを微妙に変化させた時には基本的に正解率が変化しない。つまり、パラメータを大きくするべきか、小さくするべきかがわからない。
ここで損失関数を用いてみると、パラメータを変化させると、出力も変化し、損失関数も変化する。損失関数の増減によって、パラメータを動かす方向を見つけることができる。
（詳しくは(勾配編)にて解説)

#まとめ
損失関数はニューラルネットワークにおいて用いられる評価関数で、ニューラルネットワークの良し悪しを表し、パラメータの更新に用いられる。
代表的な損失関数には２乗和誤差、交差エントロピー誤差、平均２乗誤差、平均絶対誤差などがある。
railsの「resources」と「resource」の違いについて

#はじめに「resources」メソッドとは何か
railsアプリで登場する７つのアクションを自動で設定してくれる便利なメソッドです。
「routes.rb」で１行記述するだけでアプリケーションに必要なルーティングが自動生成されます。

「resources」メソッドには単数形の「resource」も存在します。
この違いについて以下解説していきます。

#複数形の 「resources」
複数形の 「resources」は、複数のリソースに対する処理を行うためのルーティングを生成してくれます。
簡単に説明すると、urlに「/:id」が含まれた状態で生成されます。

例えば以下のように「resources」で「users」コントローラーのアクションを生成したとします。



```ruby:routes.rb
resources :users, only: [:show, :index, :new, :edit, :update]
                  #onlyでアクションを絞っています
```
ターミナルにて「rails routes」を実行してみます。



```terminal
$ rails routes
                          〜 省略 〜

          users GET    /users(.:format)             users#index                                          
       new_user GET    /users/new(.:format)         users#new                                                                 
      edit_user GET    /users/:id/edit(.:format)    users#edit                                                             
           user GET    /users/:id(.:format)         users#show                                                                   
                PATCH  /users/:id(.:format)         users#update                                                                  
                PUT    /users/:id(.:format)         users#update                                                                 

                          〜 省略 〜
```
urlに「/:id」が含まれています。
urlに「/:id」を含むことで、それぞれのリソース（user）ごとに処理を行うことができます。

#単数形の「resource」
単数形の「resource」は１つのリソースに対する処理を行うためのルーティングを生成してくれます。
こちらも以下の通り「resource」で「users」コントローラーのアクションを生成したとします。
（単数形の「resource」を使用する場合はコントローラー名も単数形で記載します。）

```ruby:routes.rb
resource :user, only: [:show, :index, :new, :edit, :update]
                  #onlyでアクションを絞っています
```

ターミナルにて「rails routes」を実行してみます。

```terminal
$ rails routes
                            〜 省略 〜

         new_user GET    /user/new(.:format)     users#new                                                            
        edit_user GET    /user/edit(.:format)    users#edit                                                                
             user GET    /user(.:format)         users#show                                                                    
                  PATCH  /user(.:format)    　　　users#update                                                                      
                  PUT    /user(.:format)         users#update

                            〜 省略 〜                                                                      
```

urlに「/:id」が含まれてないですね。
また、「/:id」が無いので「:index」アクションも生成されません。
iOSの各種ログ収集方法におけるOSLog等のログ出力関数によるログの可視性調査

iOS 10から「Unified logging system」というログシステムが導入されていて、ログレベルや変数のプライバシー設定など様々な機能があるため、実際に活用するにあたり詳しい挙動を確認したかったため、その調査結果をメモしておく

# 調査環境
- Xcode 11.3.1
- iOS 13.3

# 調査内容
## ログの種類
`OSLog`に関しては5つのログレベルがあるため、従来のログ出力関数である`print`・`NSLog`と合わせて7種類を比較・調査する

```swift
import os.log

func outputVariousLogs() {
    os_log("Log test: OSLog / Info", type: .info)
    os_log("Log test: OSLog / Debug", type: .debug)
    os_log("Log test: OSLog / Default", type: .default)
    os_log("Log test: OSLog / Error", type: .error)
    os_log("Log test: OSLog / Fault", type: .fault)
    print("Log test: print")
    NSLog("Log test: NSLog")
}
```

さらに`OSLog`では、ログとして変数の中身を表示する場合、単純な型（Intなど）はデフォルトでそのまま見えるが、それ以外の複雑な型（Stringなど）はデフォルトでは見えない
そのため、複雑な型の中身を表示することを明示的に指定する書式`%{Public}`があり、その書式の付与による可視性も比較・調査する

```swift
func outputSomeArgs(simpleArg: Int, complexArg: String) {
    os_log("Log test: OSLog, embedded=%d", simpleArg)
    os_log("Log test: OSLog, object=%s", complexArg)
    os_log("Log test: OSLog, object(Public)=%{Public}s", complexArg)
}
```

## ログの収集方法
以下の3つを比較・調査する
1. Xcodeで「Run」した際に、画面下部に表示されるログ
2. Console.appで表示されるログ（macにデフォルトで入っているログ収集アプリ）
3. sysdiagnoseでアーカイブした時の、アーカイブ中に含まれる`*.logarchive`ファイルに保存されたログ

3のsysdiagnoseは、Appleへのバグレポートを提出する際に求められる場合がある、端末のログ収集方法である
詳しいやり方は、以下のページの「sysdiagnose for iOS」>「Instruction」に記載されている
https://developer.apple.com/bug-reporting/profiles-and-logs/

# 調査結果
## ログ収集方法と収集できるログの種類
- XcodeによるRunは全てのログが見え、`print`はこの場合にしか見えない
- `OSLog`の`Info`と`Debug`のレベルはメモリ上に保持されるため、リアルタイムにログを表示するツール（XcodeとConsole.app）でしか見れない

| ログの種類 | Xcode(Run) | Console.app | sysdiagnose |
|:--|:--:|:--:|:--:|
| OSLog / Info | ○ | ○ | × |
| OSLog / Debug | ○ | ○ | × |
| OSLog / Default | ○ | ○ | ○ |
| OSLog / Error | ○ | ○ | ○ |
| OSLog / Fault | ○ | ○ | ○ |
| print | ○ | × | × |
| NSLog | ○ | ○ | ○ |

**補足**

- アプリのビルドに使う証明書の種類（Development/Distribution）で特に結果に違いはない
- Console.app で`Info`と`Debug`のログをみる場合は、メニューの「アクション」から「情報メッセージを含める」と「デバッグメッセージを含める」をONにしておく必要がある
![Console_ログレベル設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/258ae1bf-d88e-0b34-4b6b-c44304be2e6a.png)

## ログ収集方法と変数の閲覧可否
- XcodeによるRunは全ての変数が見える
- その他は、ドキュメントに記されている通り、複雑な型であれば明示的に`%{Public}`を指定しなければ見えない

| 引数の種別 | Xcode(Run) | Console.app | sysdiagnose |
|:--|:--:|:--:|:--:|
| 単純な型(Intなど) | ○ | ○ | ○ |
| 複雑な型(Stringなど)・Publicなし | ○ | × | × |
| 複雑な型(Stringなど)・Publicあり | ○ | ○ | ○ |

"×"の場合、`<private>`と表示される

# その他
- `OSLog`のログレベル`Info`の説明に「基本はメモリ上に格納されるが、障害やエラー発生時にはデータストアに保存される」という記述があったため、`fatalError()`を意図的に発生させると静的なログ収集方法であるsysdiagnoseでも見えるのではと考えて試したが、特に変化はなかった
- XcodeのRunは、一度プロセスが終了するなどして接続が切れると、再度メニューの「Debug」>「Attach to Process」で再接続してもログは見えないため、再度Runしなければならない

# 参考
- https://developer.apple.com/documentation/os/logging
- https://developer.apple.com/videos/play/wwdc2016/721/
『効果検証入門』のすごいところベスト５

安井翔太著[『効果検証入門』](https://www.hanmoto.com/bd/isbn/9784297111175)を読了しました。

因果推論や統計の基礎を学ぶ上でとても良い本でしたが、同時に作者のRコードもかなり洗練されていてRの勉強にもなりました。そこで今回は書籍で紹介されているコードの中からとくにエレガントだと思った箇所を５か所ピックアップしました。

コード全文は[ここ](https://github.com/ghmagazine/cibook)にあります

## 第５位：エラーバーのプロット
ggplot2でエラーバーをプロットするのは地味に面倒だが、お手本のようなコードなので、このままコピペして使える

```r
using_voucher_results %>%
  ggplot(aes(y = estimate, x = model_index)) +
  geom_point() +
  geom_errorbar(aes(ymax = estimate + std.error*1.96,
                    ymin = estimate - std.error*1.96,
                    width = 0.1)) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        plot.title = element_text(hjust = 0.5),
        legend.position = "bottom",
        plot.margin = margin(0.5,1,0.5,1, "cm"))
```

## 第４位：回帰分析への神パイプライン
data → 回帰モデル → broom:tidy() という華麗なるパス

```r
ong_coef <- biased_data %>%
  lm(data = .,
     formula = spend ~ treatment + recency + channel + history) %>%
  tidy()
```

summary ではなく tidy() を使うことで結果をデータフレーム化することができ、パラメータの取り出しが容易になる

```r
## aの結果から介入効果に関するパラメーターのみを取り出す
alpha_1 <- short_coef %>%
  filter(term == "treatment") %>%
  pull(estimate)
```

## 第３位: pull の利用
`pull`関数はデータフレームの特定のカラムをベクトルとして取り出す関数

`select`と似ているが、`pull`の場合はベクトルなので検定モデルに入れやすい

```r
# (6) t検定を行う
## (a)男性向けメールが配信されたグループの購買データを得る
mens_mail <- male_df %>%
  filter(treatment == 1) %>%
  pull(spend)

## (b)メールが配信されなかったグループの購買データを得る
no_mail <- male_df %>%
  filter(treatment == 0) %>%
  pull(spend)

## (a)(b)の平均の差に対して有意差検定を実行する
rct_ttest <- t.test(mens_mail, no_mail, var.equal = T)
```

## 第２位：回帰分析の自動化
複数のモデルを`broom`パッケージを使って効率的に回す

```r
## モデル式のベクトルを用意
formula_vec <- c(spend ~ treatment + recency + channel, # モデルA
               spend ~ treatment + recency + channel + history, # モデルB
               history ~ treatment + channel + recency) # モデルC

## formulaに名前を付ける
names(formula_vec) <- paste("reg", LETTERS[1:3], sep ="_")

## モデル式のデータフレーム化
models = formula_vec %>%
  enframe(name = "model_index", value = "formula")

## まとめて回帰分析を実行
df_models <- models %>%
  mutate(model = map(.x = formula, .f = lm, data = biased_data)) %>%
  mutate(lm_result = map(.x = model, .f = tidy))

```
`enframe` 関数が良い味出してます


## 第１位：バイアスのあるデータの作成
こんな方法があるなんて…

```r
obs_rate_c <- 0.5
obs_rate_t <- 0.5
## バイアスのあるデータを作成
biased_data <- male_df %>%
  mutate(obs_rate_c =
           ifelse( (history > 300) | (recency < 6) |
                     (channel == "Multichannel"), obs_rate_c, 1),
         obs_rate_t =
           ifelse( (history > 300) | (recency < 6) |
                     (channel == "Multichannel"), 1, obs_rate_t),
         random_number = runif(n = NROW(male_df))) %>%
  filter( (treatment == 0 & random_number < obs_rate_c ) |
            (treatment == 1 & random_number < obs_rate_t) )
```
サンプルの値に基づいて、閾値をルールベースで決める→一様乱数を`mutate`で作成→閾値とrandom_number を比べてfilteringという方法

どうやって思いつくんだろう
Rustのデータ型

#データには型がある
型とはデータの分類です。Rustでは以下のような型があります。

|型|データの例|説明|
|:-:|:-:|:-:|
|bool|true,false|真偽を表すデータ|
|char|'A', '4', 'Ψ'|一文字のユニコード|
|str|"UTF-8の文字列"|UTF-8の文字列|

以下は数値を表す型です。末尾の数字はデータを表すのに必要なbit数です。

|型|最小値|最大値|
|:--|:--|:--|
|i8|-128|127|
|i16|-32768|32767|
|i32|-2147483648|2147483647|
|i64|-9223372036854775808|9223372036854775807|
|u8|0|255|
|u16|0|65535|
|u32|0|4294967295|
|u64|0|18446744073709551615|
|isize|-9223372036854775808|9223372036854775807|
|usize|0|18446744073709551615|
|f32|-3.4028235e38|3.4028235e38|
|f64|-1.7976931348623157e308|1.7976931348623157e308|

####余談
最大値、最小値は以下のように知ることが出来ます。
`std` `::` `型` `::` `MAX`　→最大値
`std` `::` `型` `::` `MIN`　→最小値
以下はこの記事のテーブルを作成したコード。
マクロで簡単にできると思ったのですがうまくいかず・・・
結局置換機能を使って12行分書きました。

~~~rust
fn main() {
    println!("|型|最小値|最大値|");
    println!("|:--|:--|:--|");
    println!("|i8|{min}|{max}|", min = std::i8::MIN, max = std::i8::MAX);
    println!("|i16|{min}|{max}|", min = std::i16::MIN, max = std::i16::MAX);
    println!("|i32|{min}|{max}|", min = std::i32::MIN, max = std::i32::MAX);
    println!("|i64|{min}|{max}|", min = std::i64::MIN, max = std::i64::MAX);
    println!("|u8|{min}|{max}|", min = std::u8::MIN, max = std::u8::MAX);
    println!("|u16|{min}|{max}|", min = std::u16::MIN, max = std::u16::MAX);
    println!("|u32|{min}|{max}|", min = std::u32::MIN, max = std::u32::MAX);
    println!("|u64|{min}|{max}|", min = std::u64::MIN, max = std::u64::MAX);
    println!("|isize|{min}|{max}|", min = std::isize::MIN, max = std::isize::MAX);
    println!("|usize|{min}|{max}|", min = std::usize::MIN, max = std::usize::MAX);
    println!("|f32|{min:e}|{max:e}|", min = std::f32::MIN, max = std::f32::MAX);
    println!("|f64|{min:e}|{max:e}|", min = std::f64::MIN, max = std::f64::MAX);
}
~~~

[目次](https://qiita.com/tonesuke/items/52e469f18e747c794376)
基本情報技術者　テクノロジ系　第1章　浮動小数点表示、論理演算と論理回路

[基本情報技術者試験](https://qiita.com/savaniased/items/d3f94da4f087e178cb69)
こちらより

今日から
午後の部についての勉強を初めて行きます。


# 浮動小数点表示
基本、10進数と2進数との変換が肝となります。
そこを意識してといて行きます。

## 符号部
プラスかマイナスかを表すところ
まずここから判断する

## 指数部
何乗かを表す部分
ビットで表してる場合、２進数として
2の何乗なのかを表している

## 仮数部
整数部分、つまり小数点を超えた値が
省略されていることがあります。
指数部で調整するので。

# 論理演算と論理回路

## 論理和
どちらか成立で真

## 論理積
どちらも成立で真

## 否定
真と偽の反転

## 排他的論理和
どちらか成立で真
両方一緒だ偽

## ド・モルガンの法則
否定論理積と
それぞれ否定された論理和は等しいという法則

又は

否定論理和と
それぞれ否定された論理積は等しいという法則

要は否定論理積和は
積和が反転し、それぞれ否定されたのと等しい法則です。

間の否定をぶった切ると積和は反転すると考えた方がいいかも
[Heroku] ReactのアプリのBASIC認証の設定方法

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#create-react-app-buildpackを利用する

- 必要なもの
- static.json

 `環境変数`の設定

- BASIC_AUTH_USERNAME
- BASIC_AUTH_PASSWORD

#static.jsonの設定

こちらを参考に`static.json`を追加します。
ビルドパックが内部的に使用しているheroku/static用の設定ファイルです。
https://github.com/mars/create-react-app-buildpack#user-content-create-the-heroku-app

`"basic_auth": true`をtrueにする。
BASIC認証の設定が実態として動いているnginxに追加される

```static.json
{
  "root": "build/",
  "routes": {
    "/**": "index.html"
  },
  "basic_auth": true
}
```

#buildpackをセット

heroku/staticは`create-react-app-buildpack`が内部的に呼び出しているもの

```
$ heroku buildpacks:set https://github.com/mars/create-react-app-buildpack
```

![Screen Shot 0002-03-03 at 11.44.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394657/d6fef0ed-aa95-383d-3bba-0bf4b33349be.png)

#環境変数の設定
`BASIC_AUTH_USERNAME`  ユーザー名を設定する
`BASIC_AUTH_PASSWORD` 設定したいパスワードをhtpasswd形式に変換したものを設定する
[変換用のサイト](https://www.luft.co.jp/cgi/htpasswd.php/)

```
$ heroku config:set BASIC_AUTH_USERNAME="basciAuthUsername"
$ heroku config:set BASIC_AUTH_PASSWORD="basicAuthPasswrd"
```

これでBasic認証を設定できました！
<img width="463" alt="Screen Shot 0002-03-03 at 21.13.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394657/e9718fd0-72ed-66db-613b-44b5f11c7749.png">


#参考記事
・[heroku-buildpack-static](https://github.com/heroku/heroku-buildpack-static#configuration/)
・[heroku-buildpack-static by Heroku](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static/)
【CSS】CSSだけでおしゃれな表現　小技集（備忘録）

# CSSだけでおしゃれな表現　小技集（備忘録）<br>※どんどん追加していく所存

## 1.テキストの背景をグラデーションにする方法

```HTML:html
<p>This is dummy sentence</p>
```

```css:css
p {
display: inline-block;
background: linear-gradient(100deg, #008000, #000080 48%, #fcbbbb 90%);
 -webkit-background-clip: text;
background-clip: text;
 -webkit-text-fill-color: transparent;
font-size: 36px;
}
```

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="kazuhito-nakayama" data-slug-hash="qBdXXrg" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Text gradation">
  <span>See the Pen <a href="https://codepen.io/kazuhito-nakayama/pen/qBdXXrg">
  Text gradation</a> by Kazuhito Nakayama (<a href="https://codepen.io/kazuhito-nakayama">@kazuhito-nakayama</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
インクルメンタルサーチ

$(document).on("click", ".chat-group-user__btn--add", function

documentでHTML要素取得
clickアクション

const ＃ = $(this).attr

const 値書き換えを禁止した変数を宣言する方法
attr() HTML要素の属性を取得したり設定する

$(this)
  .parent()
  .remove();

this データ取得専用の変数,JavaScriptの実行内容によって自動的に変化

parent 親要素を取得する

remove 要素を削除


addDeleteUser(userName, userId);
削除ボタンの書いてあるhtmlを呼び出す処理に飛ばす


addMember(userId);
ユーザーをグループに登録するための処理
unity 1週間ゲームジャムチャレンジをして。

※完全なる感想なので、unityについては触れません

# ひとまずUnityを触りたい。
Javaとjavscriptばかりを業務で触っていてふとUnityとかを始めようと思った時、ググったら出てきたのが[unity1weekjam](https://unityroom.com/unity1weeks)。
ほぼ一回ボールを動かすチュートリアルをやっただけだったの状態だったのだけれど、unityで何ができるのかもわかっていない状態だったから、一週間とりあえず走ってみることにしたのだったが...

# ほぼ最終日に作ることに。。
あれしたいこれしたい、けども壁をボールは突き抜けるしunity chanはエラー出してくるし何も進まねぇ...って荒ながら最終日を迎えまして。
ひとまずゲームスタート、クリア条件、ゲームオーバー条件だけ作ってリリースを目標にしよう...orzと心に決めて走ってまさかのbuildで死亡して20:14にようやく公開にこぎつけました。

# そこから他の人のを見て振り返り。
振り返るべき内容が多々あり過ぎてもうあれなのですが。。。できるようになりたい項目を列挙しておこう
。。

## あった方がよかったなぁと思うもの。
そもそもその考え方がなかったというものばかりですが。
ゲームとはやはり楽しくなくては。

1. ランキング。確かにあった方が楽しい！！
2. 操作性、使い勝手の良さというか、まさに自分が操作をしているのだと感じられること（レーシング系は特に。）
3. 音楽。有るとなしとではやっている感もワクワク感も全く異なる。
4. アイデア。人それぞれでアイデア自体も面白いので、他人は一旦置いておいてそれに自信を持って表現すること。
5. あいこん。大事ですね。。。そんなものがあったと知らず無地にしてしまった。。。考えよう。

## やってみたいこと
1. 重力やら引力やら使いたい。物理演算的な。有る程度の操作性と、有る程度のコントロールできなさとがないまぜになってくれそうなものが欲しい。「えっあっそっち行っちゃうの！？」みたいな。操作性は大事だと思うし、操作しきれるという感覚は大事だと思うので、微妙らないんで。
2. ~~ランキングが出せるっぽいので出せるようにしてみたい。~~
3. 水面を走る的な画面を出したい。奥行き感。
4. ゲームアニメとかで有る、地面から物体がニョッキリ生えてくるやつやってみたい。
5. ~~タイマー機能~~
6. UIとかレイヤー周り
7. キラキラし異世界を作ってみたい。

と、他の人のゲームで遊んでみて思ったことでした。

それ以外として、ゲームとは何か。面白いとはなんなのか考える時間は必要かなと。
他の人のやってみて、ちゃんと「ゲームだ！！」って感じて楽しかったんですよ。とても。
これからも大事にしていきたい。

時間があったらいくつか改善してみようかな。
https://unityroom.com/games/paa_block

---

やりたい内容のうち
2020/03/07
2. ランキング機能追加しました。
    -  ncmbを初めて使ったんですが、とても使いやすくナイスって感じ。
5. タイマー機能追加しました。
Powershellを使って ` du -sh | head -n 20`をする

# コマンド
```PowerShell
(Get-ChildItem -Path C:\ -Recurse | Select-Object FullName,  Length | Sort-Object Length -Descending)[0..20]
```
- 上記コマンドはCドライブ直下のファイル全てを探すので、powershellは管理者として発行する

# 参考
[https://nasrinjp1.hatenablog.com/entry/2017/01/15/232620](https://nasrinjp1.hatenablog.com/entry/2017/01/15/232620)
[https://orebibou.com/2015/01/PowerShellでhead,tail相当の処理を行う/](https://orebibou.com/2015/01/PowerShellでhead,tail相当の処理を行う/)
GCSへデータをアップロードする時「フォルダが見えない」状態を回避する方法

### 注意
時間がないため、基本的には書き殴りになっており、表現にブレがあります。
検証できていない部分も多いため、不確実な記事となっておりますので、こんな操作方法もあるんだ程度にお読みください。
また、省略している部分や書き落としている部分もあるので、適宜調べていただく or コメント頂けますと幸いです。

## この記事でやりたいこと

GCSにローカルのデータ(ディレクトリ)を簡単にアップロードし、インスタンスから操作できる状態にする。

## 現時点での問題点

※2020/3/3 時点

```
$ gsutil cp [コピーしたいファイル or ディレクトリ] [gs://ストレージ名/パス]
```
でディレクトリをコピーした場合、上記ストレージをマウントしたインスタンスなどから、
コピーしたディレクトリが見れないというバグ?が発生している。

すでに上記コマンドでコピーした場合は、ストレージのマウントを

```
 $ gcsfuse --implicit-dirs [ストレージ名] [パス]
```
で行うと、ディレクトリが見れるようになっているが、データの読み込み等が遅くなるらしい。(未検証)

## 解決策

以下3通りの操作でストレージにデータディレクトリをアップロードした場合に、
対象のストレージをマウントしたGCPインスタンスから問題なくアクセスできることを確認。
ただし、データ数が多い場合や、インスタンスとストレージが同じリージョンにないと遅いかもしれない。

#### 前提 : 
・ローカルPCに gcloud, gcsfuseをインストール済み
・ローカルPCはmacOS(catalina)で検証。要検討だが、ubuntuでも多分できると思われる。
・今回の検証に使用したインスタンスは Deep Larning VMを使用。
・[GCLOUD_WIDE_FLAG](https://cloud.google.com/sdk/gcloud/reference/compute/instances/stop?hl=ja#GCLOUD-WIDE-FLAGS)に関しては割愛


### ❶ストレージをマウントしてcp (mv)で直接データをアップロード

操作がローカルのPCだけで完結するので操作が楽。
また、ストレージに直接コピーするので時間的にも早い。

i) ローカルのPCでの操作

```
# ストレージのマウント
$ gcsfuse [ストレージ名] [パス]

# データのコピー
$ cp -r [コピーしたいディレクトリ] [gcsをマウントしたディレクトリ]

# アンマウント
$ umount [gcsをマウントしたディレクトリ]
```

・MacBook(catalina)へGCSをマウントする時に、最初の一回はセキュリティ的に弾かれるが、許可して再度実行するとマウントできる。

・マウントしたディレクトリに対象のデータをコピー時にpermission errorが起きることがあるが
「システム環境設定→セキュリティと〜→プライバシータブ→フルディスクアクセス→追加でterminal.app」
をするとできるようになる。

・could not copy extended attributes, unable to copy ACL などのエラーが出る場合もあるが、ファイル自体はコピーされるのでシカトでOK
->
extended attributesはファイルに付けられた属性 (画像であれば撮影地や撮影時間など)
ACLはファイルへのアクセス権限を持つユーザーなどの情報

### ❷インスタンスを介してアップロード

ローカルからインスタンスへのアップロードをして、インスタンスからGCPにアップロードする方法。

何かしらの理由で、ストレージをローカルのPCにマウントできない場合に有効だと思われる。

i) ローカルPCでの操作

```
# ローカルのディレクトリをインスタンスにアップロード 
$ gcloud compute copy-files [ローカルのコピー元ディレクトリ] [インスタンス名]:[インスタンスのコピー先のディレクトリ]
```

ii) インスタンスでの操作

```
# インスタンスにストレージをマウント
$ gcsfuse [ストレージ名] [パス]

# インスタンスからストレージへコピー
$ cp -r [コピーしたいディレクトリ] [gcsをマウントしたディレクトリ]
```

### ❸アップロードしたいディレクトリをzip化してアップロード

面倒・時間と手間がかかる

i) ローカルPCでの操作

```
# 対象のディレクトリをzip化
$ zip [zip化した時の名前] [対象のディレクトリ] 

# zipファイルのアップロード
$ gsutil cp [コピーしたいファイル or ディレクトリ] [gs://ストレージ名/パス]
```

ii) インスタンスでの操作

```
# ストレージのマウント
$ gcsfuse [ストレージ名] [パス]

# データのunzip (一度インスタンス内のディレクトリにコピーする必要があるかも、、？)
### 直接ストレージ内で解凍しようとすると処理がスタックするので、解凍先はインスタンスのディレクトリへ
$ unzip [対象のzipファイル] [解凍した画像を置くインスタンスのディレクトリ]

# 解凍したデータをストレージにコピー
$ cp [解凍したデータ] [ストレージ]
```

## 結論

アップロードしたいデータがあるPCにストレージをマウントして、データをコピーするのが一番早くて楽。
コードヘルス - 丁寧なレビュー == 役に立つレビュー

*この文書は[Code Health: Respectful Reviews == Useful Reviews](https://testing.googleblog.com/2019/11/code-health-respectful-reviews-useful.html)の翻訳です。*

コードレビューはソフトウェアプロジェクトの品質改善のための[役立つツール](https://dl.acm.org/citation.cfm?id=3183525)として知られているが、一方、**あいまいで、きつすぎると解釈されるコードレビューは好ましくない結果となりうる**: 遅いレビュー、ブロッカーとなるレビュー、ネガティブな感情、他のコントリビューターや同僚に対するネガティブな認識など。

**これらのティップスを用いてコードレビューを丁寧に解決することを考えてほしい。**

## レビューアーあるいはコードオーサーとして

- ○ **能力を仮定する。** コードオーサーの実装やレビューアーの推奨は君のとは異なるコンテクストを持つ立場から来ているのかもしれない。理解するために質問することから始めよう。

- ○ **根拠やコンテキストを提供しよう。** ベストプラクティスの文書や、スタイルガイド、デザインドキュメントなど。そうすることで、相手になぜそう考えるのかを理解するのを助け、メンターシップを与える。

- ○ **どのようにコメントが解釈されるうるかを考慮しよう。** 誇張やジョークや絵文字などが違ったふうに捉えられることに気をつけよう。

悪いコードオーサー:

```
僕は短い名前の方が好きなんだ。
ここを変えようとは思わない。
君が強制しない限りね。:)
```

いいコードオーサー:

```
ベストプラクティスは自明だったり一般的な語を除くように推奨している[^1]。
そのアドバイスとこのリクエストをどう調和をとるべきだろうか。
```

- ✗ **個人を批判する。** 代わりに、*コード*を議論しよう。たとえ、コメントが人に関して書かれていたとしても（例、「君」といった語が使われている）、コードを改善するというゴールに集中しよう。

悪いレビューアー:

```
どうしてこのアプローチを使ったのか。
君は不要な複雑さを追加している。
```

いいレビューアー:

```
この並行モデルによって、はっきりとしたパフォーマンスの改善はないが、
システムの複雑性は増しているようにみえる。
```

- ✗ **不快な言葉を使う。** ネガティブな調子のコードレビューのコメントは役に立ちにくくなる。例えば、[先行研究](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/bosu2015useful.pdf)で、とてもネガティブなコメントはコードオーサーにとって57%で有益だと捉えられたが、より中立なコメントは79%も有益だと捉えられた。

## レビューアーとして

- ○ **はっきりとして行動を起こせるフィードバックを提供する。** もし、具体的なアドバイスができないのであれば、コードオーサーにどうしてその判断をしたのかを明らかにしてくれるようお願いするのもいい。

悪いレビューアー:

```
ここ分からない。
```

いいレビューアー:

```
これは最適化なのかな。もしそうなら、コメントを加えてくれる？
```

- ○ **小さなことであるということやオプショナルなコメントだということを明示的に表明する。** `Nit`や`Optional`から始めることで、コードオーサーはレビューアーの期待することを推し量ることができる。

## コードオーサーとして

- ○ **コードを明確にするか、**フィードバックに対して**レビューアーのコメントに答える。** それに失敗するとコードの改善を実装する能力が足りていないとみなされかねない。

悪いコードオーサー:

```
そういう場合もあるけど、ここでは違う。
```

いいコードオーサー:

```
なぜ実装がこうなっているかのコメントを追加した。
```

- ○ **フィードバックに同意できないとき、君のアプローチの利点を説明しよう。** 意見の一致をみないとき、Googleガイダンスの「コードレビューに関する[コンフリクトの解消](https://google.github.io/eng-practices/review/reviewer/standard.html#conflicts)」に従ってほしい。

[^1]: [コードヘルス - ワールドワイドウェブブログポスト識別名](https://qiita.com/akrisn/items/0cb93165cc44f409dbda)
[Rust] println!とprint! 実行順序が逆になる → flushを使う

# 課題
練習として以下のプログラムを作った。
文字列を入力して、挨拶文を出力するだけ。

```Rust
use std::io::stdin;

fn main() {
    let mut name = String::new();
    println!("名前を入力してください> ");
    stdin().read_line(&mut name).unwrap();
    // read_lineは改行コード（\r\n）を含むので.trim()してから出力。
    println!("こんにちは、{}さん。", name.trim());
}
```

```:実行結果
名前を入力してください> 
beginner
こんにちは、beginnerさん。
```
「名前を入力してください> 」と名前の入力行が分かれている。
同じ行にそのまま入力できるほうが自然なので改良したいが、println! を print! に変えるだけではうまくいかなかった。
以下のように read_line と print! の処理順が逆になってしまう。

```
beginner
名前を入力してください> こんにちは、beginnerさん。
```
# 解決策

flush()を使えばよい。

```Rust
use std::io::stdin;
use std::io::{stdout, Write};

fn main() {
    let mut name = String::new();
    print!("名前を入力してください> ");
    stdout().flush().unwrap();
    stdin().read_line(&mut name).unwrap();

    println!("こんにちは、{}さん。", name.trim());
}
```

```:実行結果
名前を入力してください> begginer
こんにちは、begginerさん。
```
# 参考
https://doc.rust-lang.org/std/io/struct.Stdin.html
https://doc.rust-lang.org/std/macro.print.html
実践Rust入門 6章
【Nuxt.js】変数を他のコンポーネントへ受け渡す/ 他のコンポーネントから変数を受け取る

##### `export default`に受け渡したい変数を記載

```vuejs:index.vue
<script>
export default {
  data() {
    return {
      // 省略
    }
  },
  send_data: send_data  // 他のコンポーネントに渡したい値
}
</script>
```
##### `import`で受け取りたい変数を受け取る

```vuejs:他のコンポーネント.vue
<template>
  <p>{{ send_data }}</p>
</template>

<script>
import send_data from "~/pages/index.vue"

export default {
  data() {
    return {
      send_data: send_data.send_data
    }
  },
  // 省略
</script>
```
Svelte3 音声ファイルの再生・停止をする

Svelte3でボタンを押した時などに音声ファイルの再生・停止を行いたい場合の書き方。

`audio`タグに`bind:this`を記述するだけですが使うことがあったのでメモ

```html
<button on:click="{start}">start</button>
<button on:click="{pause}">pause</button>

<audio src="/sample.mp3" loop bind:this={audio}></audio>

<script>
    let audio;

    const start = () => {
        audio.play();
    };
    const pause = () => {
        audio.pause();
        audio.currentTime = 0;
    }
</script>

```
IT Service Management Foundation 受験記

EXINが実施している [IT Service Management Foundation based on ISO/IEC 20000:2011](https://embed.exin.totalservices.io/certifications/exin-it-service-management-foundation-based-isoiec-200002011-exam?language=ja)を受験しました。

#試験について
試験時間：60分
問題数：40問 (選択式)
合格ライン：65% (26問) 以上
受験料：¥26,264 (EXIN Anywhere) or ¥27,540 (プロメトリック)
受験形式：[EXIN Anywhere](https://embed.exin.totalservices.io/certifications/information-security-foundation-based-iso-iec-27001-exam?language=ja) (在宅オンラインビデオ録画) 又は [プロメトリック](http://it.prometric-jp.com/testlist/exin/)各試験会場
※オンライン受験の場合、試験内容以外は全て英語。申し込みから約1ヶ月後くらいまでの自分の好きなタイミングで24時間いつでも受験できる。結果はその場でわかり、後日ビデオ録画の判定を含めた正式な結果が届く。

#筆者の経歴
IT実務経験：無し

日常的にPCを弄る、大体のことはググれば対処できるくらいには扱えるレベル。

また、EXINの情報セキュリティ関連試験の [Information Security Foundationは合格済み](https://qiita.com/dfnotu/items/e4a75d529af23d84baff)。内容が被る部分が多少あり、試験の出題形式や傾向もある程度把握していた。 

#勉強方法
① [EXIN公式準備ガイド](https://embed.exin.totalservices.io/certifications/exin-it-service-management-foundation-based-isoiec-200002011-exam?language=ja)の用語を一通り確認して定義などを書き出す。

② [EXIN公式サンプル問題](https://embed.exin.totalservices.io/certifications/exin-it-service-management-foundation-based-isoiec-200002011-exam?language=ja)を解く。間違った問題は解説を確認し、満点が取れるようになるまで複数回解く。

③ [JPNSHIKEN ITSM模擬試験PDF版Demo](https://www.jpnshiken.com/shiken/EXIN.EX0-115.v2019-03-12.q81.html)でも同じことをして満点が取れるまで繰り返す。

#勉強時間
10時間強。勉強時間が確保できれば数日で受かる。

#結果
32/40点 (80%) 合格

#感想
本番では模擬試験と同じ問題が大半だったので、模擬試験を完璧にしておけば合格は難しくない。参考書等なしの独学では理解仕切れない部分も多かったが、試験に合格するという意味では問題と答えの丸暗記でもある程度は対処できる。

用語の確認の段階では一部ITILの参考書を使用したが、手元にあったからという理由で使っただけ、ググれば用語の定義は出てくるのでわざわざ購入する必要はない。

試験時間は60分あるが既知の問題が多かったので15分程度で解き終わった。
【Udemy Python3入門+応用】　30. 集合の使い所

**※この記事はUdemyの
「[現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル](https://www.udemy.com/course/python-beginner/ "現役シリコンバレーエンジニアが教えるPython3入門+応用+アメリカのシリコンバレー流コードスタイル")」
の講座を受講した上での、自分用の授業ノートです。
講師の[酒井潤](https://twitter.com/sakaijun "酒井潤")さんから許可をいただいた上で公開しています。**


##■集合の使い所
#####◆例1
```python:mutual_friend
my_friends = {'A', 'C', 'D'}
your_friends = {'B', 'D', 'E', 'F'}

# Who is our mutual friend?
print(my_friends & your_friends)
```
```:result
{'D'}
```
`my_friends`かつ`your_friends`を表示させることで、
共通の友人を割り出すことができた。


#####◆例2
```python:fruits_basket
basket = ['apple', 'lemon', 'banana', 'apple', 'apple', 'banana']

# change list to set
kind = set(basket)

print(kind)
```
```:result
{'apple', 'banana', 'lemon'}
```
適当にバスケットの中に果物を入れた後、なんの種類の果物が入っているのか確認したい。
`basket`はリスト型で定義してあるが、
それを集合型に変換すると、重複しているものは1つにまとまる。
iOS アプリのテストカバレッジ周りでクラッシュしたメモ

特に役に立たない気もするが、自分がハマったところのメモ。

# 起こったこと

シミュレータ上で実行するようにして iOS アプリのユニットテストを実行すると 「EXC_BAD_ACCESS (code=EXC_I386_GPFLT)」 ってエラーでクラッシュが発生した。

![スクリーンショット 2019-12-18 21.31.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5721/f87b133c-0b8f-9612-711d-3750ba51e271.png)

# 調査メモ

* スタックトレースによると `__llvm_gcov_writeout` ってあるので、カバレッジに関係してそう
* 似たような現象として同僚が見つけてくれたページ : 
    * [Crash when running unit test target using XCode 7 - Stack Overflow](https://stackoverflow.com/questions/32803264/crash-when-running-unit-test-target-using-xcode-7)
    * [Xcode 7.0 and 7.1, code coverage turned ON, unit test crash “cannot merge previous GCDA file: corrupt arc tag” - Stack Overflow](https://stackoverflow.com/questions/33289254/xcode-7-0-and-7-1-code-coverage-turned-on-unit-test-crash-cannot-merge-previo)
* プロジェクト設定で `GCC_GENERATE_TEST_COVERAGE_FILES = YES` となっていたので、これを消して試してみた → クラッシュしなくなった
* コードカバレッジを吐こうとして、そこで何かがおかしくてクラッシュする、みたいな状況になってたっぽい
    * 同僚によると、問題が発生している .gcda のあるディレクトリ (DerivedData 以下) から .gcda を一掃したら直ったとのこと
* `GCC_GENERATE_TEST_COVERAGE_FILES` オプションは、gcov 形式 ([llvm-cov](https://llvm.org/docs/CommandGuide/llvm-cov.html) gcov とかで確認できるカバレッジ情報) のカバレッジ情報を出力するためのものっぽい？
【Nuxt.js】ページを読み込む必要がある場合のリンク設定

- APIを呼び出してページを表示する場合、ページを読み込む必要があるので、`nuxt-link`を使用できない
- 今回、完了画面（complete）でAPIを呼び出す必要があったので、`href`を使用して対応

```vuejs
<template>
  <section>
    <!-- 省略 -->
    <div class="btn">
      <a href="complete">
        <button @click="submit">送信</button>
      </a>
    </div>
  </section>
</template>

<script>
export default {
  // 省略
  methods: {
    submit() {
      axios
        .post(url, data)
        .then(res => {
          // 処理
        })
        .catch(e => {
          // 処理
        })
    },
  // 省略
}
</script>
```
View Binding入門

Android Studio3.6がリリースされてView Bindingが使えるようになりました。
使ってみましたが、めちゃくちゃ簡単です。
DataBindingのときのように<layout></layout>で囲う必要なく、xmlが生成されたらBindingのクラスが生成されます。
では、使い方を見ていきましょう。
# 使い方
使い方は全て[Android DevelopersのView Binding](https://developer.android.com/topic/libraries/view-binding)のページに書いてあります。
ここ見れば十分です。
解説記事なんて必要ないです。
リファレンス読みましょう
# まとめ
View Bindingすごい簡単ですね！
これからは基本的にView Binding経由でViewの操作はしようと思います。
知っててよかった スプレッドシートでのQuery関数の使い方[非エンジニア向け]

「知っててよかったスプレッドシート」のお時間がやってまいりました。

### 本頁要約
- スプレッドシートにはQUERY関数というものがあるよ
- あるタブ(シート)に元データがあって、そこから必要な情報を集約したり分析したりして別のシートにまとめるのに使えるよ
- 便利だけど、元データのシートをいじると参照エラーを起こす可能性があるので注意してね


### 想定読者
- Googleスプレッドシート(またはExcel)で業務に関わっていて、少し高度な分析をしてみたいという人
- SQL初心者 / 書いたことがない人
- 2ヶ月前のわし


### 本題：Query関数の使い方

#### 前準備
- スプレッドシートのファイルがあり、そのシートに分析をしたいデータがある状態をつくりましょう。例として、以下の「ジュースの注文データ一覧」が「シート1」のA~D列/1~7行にあるとします。
- 真っ白のシート2がある状態。

||A列|B列|C列|D列|
|:--|:--|:--|:--|:--|
|1|id|company|juice_provided|time|
|2|100|あいうえお社|オレンジジュース|2020-03-11|
|3|100|あいうえお社|ももジュース|2020-02-20|
|4|200|ABC社|オレンジジュース|2020-02-21|
|5|200|ABC社|バナナジュース|2020-02-28|
|6|100|あいうえお社|オレンジジュース|2020-03-01|
|7|300|かきくけこ社|オレンジジュース|2020-03-01|

#### 使ってみよう
- シート2の好きなセルに、以下を打ってみましょう。

```
=QUERY('シート1!'A2:D, "SELECT A, B, C, D WHERE C='オレンジジュース' ORDER BY A DESC",)
```
すると、↓のようなデータが自動で出力されたのではないでしょうか。

|id|company|juice_provided|time|
|:--|:--|:--|:--|
|300|かきくけこ社|オレンジジュース|2020-03-01|
|200|ABC社|オレンジジュース|2020-02-21|
|100|あいうえお社|オレンジジュース|2020-03-11|
|100|あいうえお社|オレンジジュース|2020-03-01|

#### 関数の解説

基本形：
> QUERY(分析対象のシート名!セル範囲, "クエリ",)
(最後の,は誤植ではありません)

- 第一変数：分析対象のシート名!セル範囲
    - ここでいう'シート1!'A2:Dのこと。分析結果を出力する際に見出し(シート1の1行目)も合わせてほしい場合は、今回の場合A2ではなくA1と指定すれば良い。
    - セル範囲(A2:D)は、後述の第二変数に合うように指定してください。
- 第二変数：クエリ。
    - クエリとは、データベースに対して『こんな条件にあったデータがほしいの、お願い！』という***お願い***のことです。
    - SELECT(すべて大文字です)の後に、シート1から持ってきたいデータの存在する列をカンマ区切りで指定しましょう。
        - 第一変数にて、この指定する列がすべて含まれている必要があるので注意してください。
        - A,B,Cと選ぶ以外にも、A,C,Gなどと飛び飛びで指定することもできます。
    - WHEREの後には、「データを出してほしい条件」を入れます。後述します
    - ORDER BYの後には、「データを出してほしい順番」を入れます。後述します
- 第三変数：見出しの処理の指定
    - 今回のように見出しを省いてA2:Dと指定している場合は、省略してもんだいないです
    - 第一変数でA1:Dのように見出しを含めた場合、「1」と入力しておくと、A1行を見出しとして捉えてくれるので、後述するWHERE句での集計等から除外されます。


#### WHERE句の条件の例
- 特定の文字列に一致させる
    - WHERE B = 'オレンジジュース'
- 特定の文字列と一致しない
    - WHERE B <> 'オレンジジュース'
- 数の大小を比べる
    - WHERE A >= 200
- 複数の条件を組み合わせる
    - WHERE B = 'あいうえお社' AND C = 'オレンジジュース'
    - WHERE C = 'ももジュース' OR C = 'オレンジジュース'
    - (WHEREと何回も入力する必要はなく、ANDやORで結びつけます)
  
#### ORDER BY句の条件
- ORDER BY X列 ASCで、X列の値が昇順(小→大、1,2,3)になるように並び替えます」
- ORDER BY X列 DESCで、X列の値が降順(大→小、3,2,1)になるように並び替えます」
- 今回の場合は、 ORDER BY A DESCなので、「idが大きい順に並び替えて出力してね」という意味です。

### 応用例
- 上司から「◯◯に該当する企業についてXXのレポートつくって」と言われた時に、さくっとアウトプットを出すことが出来る
    - 特に元シートを直接いじるとまずい場合。
- Salesforce等のSFAツールにて作成したレポートについて、スプレッドシートに出力し、分析をする
    - 私が実際にこれを行っていました。Salesforce内のレポート検索機能はかなり限定的で使いづらいので、一旦スプレッドシートに落としてから分析を行っていました。

### 注意
- 元シート(シート1)でデータが記述されている列が変更された時、分析テーブル(シート2)のQUERY関数がエラーを出してしまったり、予想できない値を出してしまったりする。
    - 通常の関数と異なり、QUERY関数(の第二変数)では文字列で指定してセルの操作をするため。


### まとめ
- QUERY関数が使えるようになると一気にスプレッドシートの活用の幅が広がります
- クエリとはもともとエンジニアがSQLという仕組みの元でデータを編集・確認するために使うものですが、非エンジニアにも有用な仕組みです。
- ご紹介した例以外にも、WHERE句内に入れられる条件などは多々ありますので、ぜひ調べてみてくださいませ！
AppStoreをスクレイピングしてレーティングをSlackへ定期通知する

## 前述
公開しているアプリのレーティングの変化に気づけないため、AppStoreのWebサイトをスクレイピングしてレーティングを取り出しSlackへ通知することにしました

## 実装
### Google スプレッドシートを作成し、ツール > スクリプト エディタを選択

<img width="1235" alt="スクリーンショット 2020-03-03 22.15.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149856/4bed8d0e-c832-ab9a-9572-ecbbdacfc9dd.png">

### スクリプト エディタでコーディング

<img width="1124" alt="スクリーンショット 2020-03-03 22.17.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149856/ee193272-b444-11c3-c3dc-2602338577c2.png">

### トリガーを追加
スクリプト エディタ上の時計アイコンをクリック
以下のようにトリガーを作成して完了

<img width="1609" alt="スクリーンショット 2020-03-03 22.19.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149856/b65c9ab8-021f-0db0-c67a-268f7ad49fc7.png">

### 実際のソース

```javascript
function sendRatingCount() {
  var ratingCount = fetchRatingCount();
  if (ratingCount == null) {
    return;
  }
  
  var now = new Date();  
  var date = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyy年MM月dd日');
  
  sendSlack(date +  "\n" + ratingCount);    
}

function fetchRatingCount() {
  var response = UrlFetchApp.fetch("https://apps.apple.com/jp/app/stockey/id1407877357");
  var responseCode = response.getResponseCode();
  if (responseCode != 200) {
    return null;
  }
  
  var contentText = response.getContentText("utf-8");
  var regexp = /<figcaption class="we-rating-count star-rating__count">(.*?)<\/figcaption>/;
  try {
    var ratingCount = contentText.match(regexp);
    return ratingCount[1];   
  } catch (e) {
    return null;
  }
}

function sendSlack(text) {
   var payload = {
     "text" : text
   };
  
   var options = {
     "method" : "post",
     "muteHttpExceptions": true,
     "payload" : JSON.stringify(payload)
   };
  
   UrlFetchApp.fetch("https://hooks.slack.com/services/.....", options);
}
```

## 参考
- [Google Apps Script でスクレイピングがうまく出来ない場合にチェックするポイント](https://qiita.com/DriftwoodJP/items/7f26a625a31845e1665c)