OmniAICreator/Qiita-1.07M huggingface dataset:
【新人orトレーナー向け】Gitの基本操作を学習できるデスクトップアプリ


<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-116132394-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-116132394-1');
</script>
# はじめに
現場に新卒の子(IT未経験)が入ってきてトレーナーをすることになり、開発環境やツールを（GitやDocker）を体系的に教えられないかなと、色々探していたところGitやGitHubを学習できるデスクトップアプリ「[Git-it](https://github.com/jlord/git-it-electron)」というものがありました。

Electron製でソースコードが公開されているため、自社のプロジェクト用にカスタマイズもできそうだったため、こちらを利用してみることにしました。

### 環境
- 端末：MackbookPro13インチ メモリ16GB 
- OS：MacOSMojave ver10.14.1
- Node.js(npm)インストール済み

# Git-itのインストール
1. [https://github.com/jlord/git-it-electron](https://github.com/jlord/git-it-electron)からクローンしてきます
2. `npm install`でパッケージインストール
3. `npm run prestart`でビルド
4. `npm run start`でアプリ実行

以下の通り、アプリ画面が起動される。
Git-itチャレンジが1~11用意されており、それぞれチュートリアルのようになっているなっているため、アプリにしたがって学習させるのみ。
![スクリーンショット 2019-01-14 19.44.33-min.png](https://qiita-image-store.s3.amazonaws.com/0/56388/ddb4a596-1006-a850-7502-a1f00efad0d7.png)

※また、各チャレンジの終わりにチュートリアルを正しく実施できたかVerifyボタンでチェックができるので、答え合わせもできるのは新人にとっては嬉しいところではないかと思う。
![Git-it.gif](https://qiita-image-store.s3.amazonaws.com/0/56388/92d6dae3-8afd-3fe2-cd84-8f396429ab0a.gif)

※なお、内容がデフォルトのままでよければ[git-it-electron/releases](https://github.com/jlord/git-it-electron/releases)から各PC用にアプリケーションとしてもダウンロードできるので、Node.jsのインストールが出来ない方も利用することはできます。

# 良いと思ったところ
- デフォルトのGitチャレンジだけでも、分散開発を意識したGitの操作をチュートリアルできる。
- ページの編集が出来るため(Node.jsで実装する必要あり)、自社プロジェクトにカスタマイズしたチュートリアルを追加できる。(プロジェクトのリポジトリに差し替えたりね)
- アプリとして配布出来るため準備が簡単。
- 多言語対応してる。(日本語、英語、中国語、韓国語、フランス語、スペイン語、ポルトガル語など)。
- 新人から次の新人へと教育用アプリとして改善しながら引き継いでもらえそう。

### Git-itチャレンジの詳細
チャレンジの詳細は[@exabugsさんの記事](https://qiita.com/exabugs/items/8d989def21b912afa109)がよく解説されていましたので、紹介します。
Ada言語 16日目 キャスト

#はじめに
いままでソースの上で`with`と`use`を両方書いていましたが、やっと`use`の意味が分かったので今回から`with`だけにします。

#ソースと結果
```main.adb
with Ada.Integer_Text_IO;
with Ada.Float_Text_IO;
with Ada.Text_IO;

procedure main is

   hennsuu1 : Integer := 5;
   hennsuu2 : Integer := 2;
   hennsuu3 : Float;

begin

   hennsuu3 := Float (hennsuu1) / Float (hennsuu2);

   Ada.Float_Text_IO.Put(hennsuu3, 0);

end main;
```

`実行結果 : 2.50000E+00`

#おわりに
今回はキャストでした。C言語とは違い、変数のほうを括弧でくくるようです。

#日記一覧へ
[Ada言語を習得する日記一覧](https://qiita.com/C_Assembly/items/50a0f9d8542679d92ea8)
[python]文字列を回転する

文字列を順番に入れ替えする。


```python:rolling.py
word = "abcde"

def rolling(str , n):
    return str[n:len(str)] + str[:n]

for i in range(len(word)):
    print(rolling(word,i))

# abcde
# bcdea
# cdeab
# deabc
# eabcd
```
PyInstallerで実行ファイルにリソースを埋め込み

## リソースを埋め込んだ実行ファイルを生成する手順
PyInstallerを使うとPythonスクリプトを実行ファイル（.exe）にできます。
ただ、画像などリソースファイルを埋め込んだ単体の実行ファイルにするには一手間かかるため
その手順について説明します。Windows 10環境で説明しますが、MacやLinuxでも変わらないはずです。

### リソースファイルの参照方法を変更
実行に埋め込んだリソースは実行時に別フォルダに展開されます。
（例：%USERPROFILE%/AppData/Local/Temp/_MEIxxxxxx）
これを参照できるよう関数を追加し、リソース参照時はこれを使用するようにします。

```Python:リソースを参照するresource_path関数を使った例
import tkinter as tk
import sys
import os


def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)


root = tk.Tk()
photo = tk.PhotoImage(file=resource_path("image.png"))
label = tk.Label(root, image=photo)
label.pack()
root.mainloop()
```

### specファイルを作成
pyinstallerが未インストールならpipでインストールします。
スクリプトファイルに対してpyinstallerを実行するとspecファイルが作成されます。
`./dist/test/test.exe`も作成されますが、まだ単一の実行ファイルではありません。
ここではリソース(image.png)がスクリプトと同じ階層にあるとします。

```sh:実行ファイルを仮作成
> pip install pyinstaller
> pyinstaller test.py
```

### specファイルを書き換え
外部ファイルはdatasに記述する仕様なので
`a.datas += [('image.png', '.\\image.png', 'DATA')]`を加えます。
複数のリソースを追加する場合は、その分だけ加えます。

またEXE()の引数の`exclude_binaries=False,`を削除し
`a.binaries,`と`a.datas,`を追加します。
（console=Falseはお好みで。余計なコンソールが開かなくなります）

```py:書き換え後のspecファイル

# -*- mode: python -*-

block_cipher = None


a = Analysis(['test.py'],
             pathex=['D:\\Desktop'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
a.datas += [('image.png', '.\\image.png', 'DATA')]
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.datas,
          name='test',
          debug=False,
          strip=None,
          upx=True,
          console=False)
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='test')

```

### specファイルを使ってexeを作成
コンソールにspecファイルを指定してexeを作成します。

```sh:specファイルを使って単一の実行ファイルを作成
> pyinstaller test.spec
```

### distフォルダのexeを確認
`./dist/test.exe`を実行すると、単体の実行ファイルでリソースを使用できることを確認できます。
ARKitで「ARで見る」を真似る その壱

## きっかけ

<blockquote class="twitter-tweet" lang="ja"><a href="https://twitter.com/kenkawakenkenke/status/1084256927935152128">ARで見る</a></blockquote>

これを見て、アイデアって無限の可能性を秘めていると感じた。

ちなみにこのアプリはARCoreに対応したAndroid端末でしか動かないとことなのでiOSでも同じようなことをやってみた。
とは言っても、私はフロントエンドエンジニアでも何でもないのでまずはちょろっとARKitを動かすところまでやってみた。

## 開発環境の準備

- Mac
- iPhone
- XCode

たまたま趣味で買ったMacとiPhoneがあったのでXCode入れて開発スタート！

## 開発

XCodeを起動し、`Create a new XCode project`から`Augmented Reality App`テンプレートを使用する。

この時点で飛行機の飛ぶサンプルが出来ているから非常にありがたい。しかしそんなものは使わない。以下のように置き換える。

``` swift:ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // Create a new scene
        sceneView.scene = SCNScene() // ビューのsceneプロパティに空のシーンを生成する
        
        let node = SCNNode() // ノードを生成
        node.geometry = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)// ノードの形状を一辺が20cmの立方体とする
        let material = SCNMaterial() // マテリアル（表面）を生成する
        node.geometry?.materials = [material] // 表面の情報をノードに適用
        node.position = SCNVector3(0, 0, -0.5) // ノードの位置は、カメラを原点として左右：0m 上下：0m　奥に50cm
        
        sceneView.scene.rootNode.addChildNode(node) // 生成したノードをシーンに追加する
    }
```

おー！Swiftは素晴らしい！キレイな言語な気がする。

## できたもの

<img width="375" alt="IMG_3405.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/84493/8bd4a368-c392-d710-24b3-0938876b2f6d.png">

無事に四角いオブジェクトが宙に浮いてる。
次回はサイズを変えたり、テクスチャ貼ったりしてみたい。
OSSセキュリティ脆弱性テストツールの紹介

## 経緯
https://hogespace.hatenablog.jp/entry/2019/01/12/184200

脆弱性調査が可能なOSS等をまとめました。

## Nmap
- ポートスキャニングを実行
    - 特定のポートに絞って調査することも可能
    - 出力内容
        - ポート
        - プロトコル
        - アプリケーション名
        - OS名
        - サービスの状態
            - ポートが開いているかどうか
            - ポートにパケットが届くかどうか
- 出力方式
    - 標準出力(.nmap)
    - インタラクティブ出力(.nmap)
        - 標準出力だが実行時間情報や警告が表示される回数が標準より多い
    - grep可能な方式(.gnmap)
        - ターゲットホストに関するほとんどの情報が1行で表示される
    - xml
- GPLv2ライセンス
- 参考
    - https://nmap.org/book/man.html

## OpenVAS
- いくつかのサービスからなるフレームワークで、高度な脆弱性スキャニングと脆弱性管理ソリューションを提供
- ネットワーク脆弱性テスト(Network　Vulnerability　Tests)を行う
    - ソフトウェアのバージョンや設定、構成などを確認してそれらに脆弱性がないかどうかをチェック
    - テスト項目が日々更新されており、現在は5万以上のテスト項目がある
    - 具体的なテストは不明
- 様々なインタフェースで診断対象にするシステム、診断する項目や定期実行などを設定可能
    - CLI
    - OS上のGUI
    - WebUI
- 出力方式
    - CLI
    - WebUI
    - html
    - csv
    - xml
    - pdf
    - メール
- GPLv2ライセンス
- **(注意)クラウド上で使用する際は申請が必要**
- (参考)
    - http://www.openvas.org/
    - http://www.nvtgroup.co.uk/services/security/

## Vuls
- Go言語製のソフトウェア脆弱性スキャナ
    - Go言語のインストールが必要
    - システムに関係ある脆弱性と、脆弱性のあるサーバを検知
    - 自動スキャンにより、脆弱性検知の漏れを防ぐことが可能
    - cronで定期実行も可能
- 主要なLinux/FreeBSDでのみ使用可能
- スキャン実行のトリガー
    - ローカル上で実行
    - SSH接続時
        - スキャンしたいサーバにSSH接続可能なホストにVulsをセットアップすると自動で実行
    - Dockerコンテナ
        - docker execコマンドを使用するとコンテナ内に対してスキャン実行
        - 稼働中のコンテナでも可能
- 出力方式
    - CLI
    - TUI(Text User Interface)
    - WebUI(VulsRepo)
    - json
    - csv
    - メール
    - slack通知
- GPLv3ライセンス
- (参考)
    - https://vuls.io/
    - https://qiita.com/sadayuki-matsuno/items/0bb8bb1689425bb9a21c

#### コメント
紹介しきれていないので、いずれ追記すると思います...
例えばアプリケーションの脆弱性テストツールとか。
(余裕があるといいなあ...
Visual Studio Code Extension を作る

# 作ったもの

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84493/fcccad26-3071-3867-9f1c-b83be32b7d0b.png)
ソースコード：https://gitlab.com/transnano/markdown-jira-preview

## 機能

マークダウンのコード機能に`jira`を指定し、jiraの記法でコードを挿入するとプレビュー機能で出力を確認できる。

## 開発

公式に拡張機能の作り方があるので、そちらをとりあえずやってみる。
- [Your First Extension](https://code.visualstudio.com/api/get-started/your-first-extension)
他にもgithubに多くのサンプルがあるのでいろいろと見てみる。
- [Microsoft/vscode-extension-samples](https://github.com/Microsoft/vscode-extension-samples)

この辺を見て実際に作ってみたがうまく動かず。。。最新版のサンプルはTypeScriptで作成されていて私にはちょっと早すぎた模様。

旧サンプルのJavaScript版を参考に今回はやってみた。

今回プレビュー表示するために重要なものは以下の関数。

``` javascript:extension.js
extendMarkdownIt(md) {
...
}
```

あとはコードを[jira2md](https://github.com/kylefarris/J2M)でHTML形式に変換するだけ。（今回最も重要だったJIRAの記法を変換する処理は本ライブラリに委譲したので側だけを頑張った）

ちょっとだけ見た目を整えるため拡張機能でCSSを読み込ませる。

``` javascript:package.json

  "contributes": {
    "markdown.previewStyles": [
      "./markdown-jira.css"
    ],
...
```

## 公開

公開する場合も公式を参考にする。
- [Publishing Extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)

重要なのは[Azure DevOps](https://azure.microsoft.com/ja-jp/services/devops/)を取ること！クレジットの登録とかもないのでちゃちゃっと取れる。
新規に作成する場合は以下の3種類のドメインを選ぶことが可能。
1. `outlook.jp`
2. `outlook.com`
3. `hotmail.com`

あとはコマンドをちょこっと打つだけで数分後には[Visual Studio Code - Marketplace](https://marketplace.visualstudio.com/vscode)に上がる素晴らしさ！

- [Markdown JIRA Preview](https://marketplace.visualstudio.com/items?itemName=transnano.markdown-jira-preview)

## 終わりに

元々はマークダウンのコード機能にJIRAの記法ではシンタックスハイライトが付かないことが許せなくて始めた拡張機能開発だったが、jira2mdとう素晴らしいライブラリを知って方向転換。結果的には無事にはじめての開発から公開が出来た。
次は本来作りたかったシンタックスハイライトにチャレンジしようと思う。
[Unity]Udemyの無料講座を受講してみた

# はじめに

とある日。
仕事の昼休み中にTwitterを見ていた時、

![cap.png](https://qiita-image-store.s3.amazonaws.com/0/335844/6cdde5a0-b46b-79f9-20e7-87212f4fa1fc.png)

Unityの無料講座の情報がRTで流れてきました。
前々からUnity気にはなっていたものの、
手を出せてなかったので良い機会ですしやってみます！

![cap2.png](https://qiita-image-store.s3.amazonaws.com/0/335844/d13e1242-f170-45e0-4f42-94c6d00a3de9.png)

講座内容はこんな感じ。
Unityの最初の最初から解説してくれるようです。

![cap3.png](https://qiita-image-store.s3.amazonaws.com/0/335844/e846eca2-4210-f426-afef-59ab53fbca9c.png)

ではUdemyのアカウント登録もサクッと完了したので、
早速開始！

## 実施環境

とその前に、補足として実施環境です。
以下の環境で実施しました。

```
・Windows 10 Home(17134.523)
```

ご参考までに。

# 内容

![cap4.png](https://qiita-image-store.s3.amazonaws.com/0/335844/e03d8339-9cd2-8258-beef-21d50ae0de24.png)

動画でいろいろユニティちゃんが解説してくれます。

・そもそもUnityって何？
・どういう使い道があるの？

というところから丁寧に教えてくれました。

続いて

・Unity IDの登録
・Unityインストール
・Unityの使い方

等々。

で、動画に沿って進んでいき

![cap5.png](https://qiita-image-store.s3.amazonaws.com/0/335844/65c315f2-acee-11b6-9857-e4bffaaa3d3e.png)

新規プロジェクト作成すると
いよいよ開発画面っぽくなりました。
ワクワクしますね！

![cap6.png](https://qiita-image-store.s3.amazonaws.com/0/335844/7109effc-724d-e3a8-1385-69573af3540d.png)

ビューのレイアウトを変えて、
3Dオブジェクトを配置しただけでもワクワクしちゃう。

そしてシーンビューの操作方法の説明。
操作方法の説明後はベーシック・チュートリアル。

![cap7.png](https://qiita-image-store.s3.amazonaws.com/0/335844/b9c6c821-2443-deba-5ff5-c1624463159b.png)

Learnにあるものを動画を見ながら黙々と進めました。

![cap8.png](https://qiita-image-store.s3.amazonaws.com/0/335844/42495147-de2a-2018-78ba-eda037bb0a66.png)

ベーシック・チュートリアルは全部英語ですが、
動画見ながらやれば特に躓くことなく進められました。

※チュートリアル自体も親切なので、英語が分からなくても、
　１つ１つ進めていけば何をどうすれば良いのかは分かるレベルでした。

ベーシック・チュートリアル後は、
動画講座用のサンプルプロジェクトをGitから取得します。

![cap9.png](https://qiita-image-store.s3.amazonaws.com/0/335844/1c7a92aa-3084-c046-5d94-26325f06ee28.png)

ZIPを解凍して、Unityプロジェクトのフォルダに設置。
Unityを起動して該当のプロジェクトで進めていきます。

![cap10.png](https://qiita-image-store.s3.amazonaws.com/0/335844/d9a1b3c4-8319-cb6d-ed94-6a26c7e10e9b.png)

動画に倣っていきなり遊んだりもします。
ユニティちゃん可愛いぜ・・・。

![cap11.png](https://qiita-image-store.s3.amazonaws.com/0/335844/002f5eb3-25bd-2801-3147-0ed238389b78.png)

ユニティちゃん可愛いぜ！！

そしてマテリアルの使い方などを習い、
いよいよプログラミングです。とりあえずやってみよう。

![cap12.png](https://qiita-image-store.s3.amazonaws.com/0/335844/52024ea2-0aa7-bbc7-efdc-b43d70695dc5.png)

迫真のVisual Studio起動。
C#やったことないけど、初級レベルのものであれば
全然読めるし書けますね。

ちなみに動画では、

・クラスとは？
・メソッドとは？
・変数、宣言とは？

みたいなプログラミングの初歩の初歩な部分も、
丁寧に解説されてました。
プログラミング初心者にも配慮されていて素晴らしい。

そして動画を見ながら紆余曲折ありまして・・・
最終的にWebGLでビルドして、ゲーム完成＆講座終了。
(どういう成果物が出来上がるかは、是非受講してみてください！)

# 所感

一気に受講しましたが、
インストールからビルドまで４～５時間ぐらい？でした。
(途中、休憩も挟みつつ。)

講座のタイトル通り、
Unityを全くやったことない人でも、
動画を見ながらやれば簡単にゲームが出来てしまいました。
また合間合間に、プログラミング自体の解説などをしてくれるので、
プログラミング自体初心者の人でも進めることが出来そうです。

ただし、動画講座あるあるですが、
基本的に都度一時停止必須でした。
(特にコーディングする部分の表示時間が短いので。)

まだまだ覚えることが多くて、
Unityは大変そうですが、ゲームを作ること自体は
すごく面白いので、気になっている人は
無料なので試しに受けてみるのはいかがですか？

# 受講URL

[初心者向けUnity講座](https://www.udemy.com/unity-chan-tutorial-01/)
hexdocs のトップページを README.md にする

[最近作っているライブラリ](https://github.com/ishikawa/ex_fake_http)を [Hex.pm](https://hex.pm) で公開するときに少しハマったので書き残しておく。

## ドキュメントのトップページを README.md にする

ドキュメントをほとんど書いていないので、とりあえずトップページを README にするために、[ExDoc の README](https://github.com/elixir-lang/ex_doc) を参考に以下のようにした。

```elixir
def project do
  [
    ...
    docs: [
      main: "README",
      extras: ["README.md"]
    ]
  ]
end
```

## しかし、PAGE NOT FOUND

ローカルで問題なく動いていることを確認して、 `mix hex.publish` で公開。しかし、公開自体はうまくいったが、Page Not Found になる...😰

<img width="1011" alt="スクリーンショット_2019-01-14_18_54_00.png" src="https://qiita-image-store.s3.amazonaws.com/0/18990/0f63630f-d5ed-9f2f-0c70-8ee9015968fa.png">


Works on my machine なのに何故...

## [解決] ファイル名は小文字

[Hex.pm の FAQ](https://hex.pm/docs/faq) に書いてあった。

>also verify that there are no differences in letter casing since Hexdocs is case-sensitive but your machine may be case-insensitive.

Mac のファイルシステムは大文字・小文字を無視するが、Hexdoc で使われてるファイルシステムでは区別するので、以下のように変更する必要がある。

```elixir
def project do
  [
    ...
    docs: [
      main: "readme",
      extras: ["README.md"]
    ]
  ]
end
```

## ブラウザのキャッシュも更新が必要

公開されたドキュメントはブラウザにキャッシュされているので、キャッシュもクリアする必要がある。
ROSのノードグラフ作図のためのDot言語のサンプル

ROSの[rqt_graph](http://wiki.ros.org/rqt_graph)で出力されるノードグラフっぽいものを、dot言語で作成するときのサンプル。

## dot言語で書く理由
「rqt_graphでノードグラフを自動で作成できるのに、なぜわざわざ手書きをするのか」という当然の疑問に対する答えとして、以下のケースを挙げておきます。

* 実装前の設計時に、どうしても綺麗なノードグラフを書く羽目になってしまった。
* 実装はし終わったが[nodelet](http://wiki.ros.org/nodelet)を使っていたため、`rqt_graph`で出力されるノードグラフの可読性が低くなってしまった。
    * (2019/1/27追記) nodelet managerを使わずに，各ノードレットをstand aloneで起動させれば，rqt_graph内で通常のノードと同じように描画されることに気づきました。なので，後者の場合はノードグラフ描画のためにlaunchファイルを別途作ったほうが早そうです。

また、dot言語はテキストで作図できるため、gitなどで差分管理がしやすく、設計変更時に必要な労力を下げることができます（plant-UMLと同じ哲学です）。dot言語を知らないという方は[ここ](https://qiita.com/rubytomato@github/items/51779135bc4b77c8c20d)などを見てください。

ちなみに，rqt_graphの画面の右上あたりのボタンから，図をdotファイルとして出力できます。

## 環境構築のメモ書き
- 環境構築とか面倒という私みたいな方は、[GraphvizOnline](https://dreampuf.github.io/GraphvizOnline/)を使ってブラウザで作業できます。本記事の図もGraphvizOnlineで作成しました。
- Visual Studio Codeだと、[VSCodeとGraphvizでテキストからグラフ生成
](https://qiita.com/lilacs/items/fe8b3223f2a193c0fa2e)が参考になりそうです。
- DotEditorというGUIアプリでDot言語を扱えるソフトもあります。[DotEditorで分散ソフトのノードグラフを書く
](https://qiita.com/hyt126/items/8164caf08d40326f0499)が参考になります。

## ノードグラフのサンプル
ここではhttp://wiki.ros.org/rqt_graph に出てくる以下の図に相当するグラフをdot言語で書いてみます。
![rqt_output](http://wiki.ros.org/rqt_graph?action=AttachFile&do=get&target=snap_rqt_graph_moveit_demo.png)

```dot
digraph graph_name {
 // graph setting
 graph [
     rankdir=LR; // left to right (default is TB)
 ]

 // nodes (楕円の枠を作る)
 "/joint_state_publisher";
 "/move_group";
 "/virtual_joint_broadcaster_0";

 // topics (長方形の枠を作る)
 "/joint_states"[shape=box];
 "/move_group/display_planned_path"[shape=box];
 "/tf"[shape=box];
 "/planning_scene_world"[shape=box];
 "/planning_scene"[shape=box];

 // link (矢印を作る)
 "/joint_state_publisher" -> "/joint_states";
 "/joint_states" -> "/robot_state_publisher";
 "/joint_states" -> "/move_group";
 "/virtual_joint_broadcaster_0" -> "/tf"
 "/robot_state_publisher" -> "/tf";
 "/tf" -> "/move_group";
 "/planning_scene" -> "/move_group";
 "/planning_scene_world" -> "/move_group";
 // 名前空間（長方形で囲む）
  subgraph cluster_name {
    label = "move_group";
    "/move_group" -> "/move_group/display_planned_path";
  }
}
```

出力すると、以下のような図ができます。
![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/260124/b463ad72-fe47-a800-9da4-359d9a1dfebf.png)

楕円がノード名を、長方形がトピック名をそれぞれ表しています。名前空間の長方形は`subgraph`を使って実現しています。rqt_graphの出力結果と少し異なるようですが、本質ではないので気にしません。

ROSのノードグラフっぽくするポイントとして、`rankdir=LR`を指定しておくことです。これがないと、下図のように、上から下に矢印が描画されます。これでもいいのですが、今回の場合だと、名前空間のmove_groupの表示が矢印と重なっており、締りが悪いです。
![sample1a.png](https://qiita-image-store.s3.amazonaws.com/0/260124/04de6976-d491-fe8f-bd64-1ddbd9be8451.png)

なお、トピック名は矢印のラベルとして次のように描画することもできます。

```dot

"/joint_state_publisher" -> "/robot_state_publisher"[label="joint_states"];
```

![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/260124/9b8bda0a-7335-620c-01cd-ff660eb737d7.png)

## 参考
- [DotEditorで分散ソフトのノードグラフを書く
](https://qiita.com/hyt126/items/8164caf08d40326f0499)
git push したら error: pack-objects died of signal 13

# 症状
git push したら、下記の通り
error: pack-objects died of signal 13
というエラーが発生してpushが完了しない。

```
$ git push -u origin master
Counting objects: 147, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (133/133), done.
fatal: The remote end hung up unexpectedly
packet_write_wait: Connection to xxx.xxx.xxx.xxx port 22: Broken pipe
error: pack-objects died of signal 13
error: failed to push some refs to 'git@github.com:xxxxxx/yyyyyyyy.git'
```

# 結論
ネットワークを某喫茶店のWi-Fiから携帯を使ってのデザリングに変更してpush 
したら、ちゃんとpushできた！

# 経過
1. 某喫茶店にて作業
2. 作業終わってそろそろ帰るかな〜とおもむろに `git push` する
3. `error: pack-objects died of signal 13` エラー発生
4. とりあえずググる
5. この辺がヒットして、怪しいな  
https://www.d-wood.com/blog/2014/09/17_6824.html
6. 容量調べてみる

```
$ git count-objects -Hv
count: 147
size: 3.34 MiB
in-pack: 0
packs: 0
size-pack: 0 bytes
prune-packable: 0
garbage: 0
size-garbage: 0 bytes
```
めっちゃ軽いやんけ！
7. 某喫茶店のWi-Fi使ってるんだけどちょっと回線遅いな〜
8. 携帯のデザリングに変更する
9. `git push`する
10. 完了
11. 帰宅

ネットワークの問題もあるってことなのかな〜
細かいことは調べてません！
Intent更新時の再審査回避方法について

Actions on GoogleでDialogflowを利用しているとき、
intent内の更新を公開版に適応するには必ず**再度審査**を通さなければなりません。
けど、緊急な変更等が必要な場合に一々審査結果を待つというのも、見方によってはナンセンスです。

> _For edits to go live, you’ll need to submit your draft for alpha, beta, or **production release** in the Actions Console._
>引用 [Dialogflow versioning - Actions on Google](https://developers.google.com/actions/dialogflow/submit#dialogflow_versioning)

この点、**DialogflowのバージョニングはFirebase Functionsまでに及ばない**ので、
こちらの方にTraining phraseの処理を移してしまえば、一々審査を通す必要はなくなるでしょう。

> _Actions on Google: Dialogflow's inline code editor **does not have versioning for Cloud Functions.**_
> 引用　[Create a webhook with the inline editor - Dialogflow](https://dialogflow.com/docs/fulfillment/configure#create_a_webhook_with_the_inline_editor)



連想遊戯では、IntentのTraining phraseに@sys.anyを指定して、
その後の処理をFirebase functions側で処理しています。

そのため、急な変更とかは、一々Intentを編集して審査に再申請するのではなく、
例えば以下のように受け取ったフレーズに任意の言葉が含まれていないかチェックする機能をサーバ側で処理しています。

```Javascript
app.intent('theIntent', (conv) => {
    // ユーザの発した言葉を受け取る
    let userComment = conv.arguments.raw.input.text.textValue;

    //クエリを関数に引き渡し、「反応させたいフレーズ集」に引っかかったら1を返す
    if(receivedPhrase(userComment) === 1){
        // 任意のフレーズに該当
        app.close("ばいばい")
    }
    app.ask("どうしたの？")
}

function receivedPhrase( query ){
    //反応させたいフレーズ集
    var thePhrases = [
        "AAA", "BBB", "CCC", "DDD" 
    ],
    query = query,
    i = thePhrases.length;

    while (i--) {
        if (query.indexOf(thePhrases[i]) !== -1) {
            console.log("Found user said : " + query ); 
            return 1
            break;
        }
    }
    return 0
}
```

もちろん、この解決策を使うことに批判があります。
そもそも、sys.any自体を濫用することがDialogflowが想定していた使い方であるかと言われたら、そうではないからです。
つまり、クエリのやり取りだけならばActions SDKだけでもでき、
この解決策では、GUIで形態素解析をしてくれるというDialogflow良い点まで破棄するということになります。
（私の場合はActions SDKのActions Packageを準備するのが面倒なだけですが...）

あと、Actions on Googleを利用するにあたって、ポリシーや利用規約があるので、
悪用厳禁と自己責任で諸々お願いします。現場からは以上です。即出なら失礼(｀･ω･´)ゞ

ところで、いつも自分のブログで書いているのですが、
今回はGutenbergを使ったときのソースコードの見せ方がわからないため、Qiitaに投稿しました。
【Prometheus】remote  writeの設定項目について調べてみた

remote writeの設定項について詳しい説明が見当たらなかったので、
ソースコードを読んだりデバッグしてわかったことをまとめてみた。
※バージョンは2.6.0を使用
# remote writeのデフォルト設定

```yaml:prometheus.yml
remote_write:
- url: http://HOST:PORT/xxxxx
  remote_timeout: 30s
  queue_config:
    capacity: 10000
    max_shards: 1000
    min_shards: 1
    max_samples_per_send: 100
    batch_send_deadline: 5s
    max_retries: 3
    min_backoff: 30ms
    max_backoff: 100ms
```

urlから下は書かなくても自動で設定が追加される。

# remote_writeの設定項目
## url
**外部ストレージへ書き込みを行うAdapterのURL。**

```yaml
remote_write:
- url: http://HOST01:PORT/receive
- url: http://HOST02:PORT/api/v1/prom/write?db=prometheus

```
↑のように複数指定できる。

## remote_timeout
**Adapterとの接続をタイムアウトさせる時間。**


## queue_config
Prometheusがスクレイプしたサンプルはキューに一旦格納され、順番に外部ストレージに書き込まれるようになっている。
queue_configではそのキューについて設定ができる。
またキューはurlで指定した書き込み先ごとに割り当てられる。

## capacity
**サンプルを格納できる最大容量。**
スクレイピングで取得したサンプル数がcapacityを超えた場合、超えた分のサンプルは破棄されるので注意。
100のcapacityに対してスクレイピングしたサンプル数が130個だったとすると、30個のサンプルが送信されず消失することになる。
その際以下のようなエラーが出力される。

```
Remote storage queue full, discarding sample. Multiple subsequent messages of this kind may be suppressed.
```

## max_shards/min_shards
**remote writeの並列実行数の上限・下限。** 
remote writeはShardという単位で並列に実行することができ、max/min_shardsではその並列実行数の下限と上限を決めることができる。（起動時のShard数はmin_shards）
Prometheusは10秒置きに負荷を計算し、負荷に合わせてShardの数を増減させている。

詳細は省くが必要なShard数は以下の計算式で計算されていた。

```go
desiredShards = (timePerSample * (samplesIn + samplesPending + t.integralAccumulator)) / float64(time.Second)
```

timePerSample: サンプル1つあたりの送信時間
samplesIn: 1秒あたりの取り込みサンプル数
samplesPending: samplesInから1秒あたりの送信サンプル数を引いた数（ = 1秒あたりの送信待ちサンプル数）
t.integralAccumulator: t.integralAccumulator + (samplesPending * 0.1)

> 参考：https://github.com/prometheus/prometheus/blob/master/storage/remote/queue_manager.go
func (t *QueueManager) calculateDesiredShards() 

![remote_storage_integrations_01.png](https://qiita-image-store.s3.amazonaws.com/0/237938/f42fde11-1434-5689-2f10-e03eaec8233f.png)



## max_samples_per_send
**一度にまとめて送信するサンプルの数。**データをPOSTする回数を調節することができる。
例えばキュー内に100個のサンプルがあり、max_samples_per_sendを20に設定している場合、サンプルを20個ずつ5回に分けて送信する。
（この場合実際にはサンプルが20個溜まった時点で外部ストレージに送信される。）

## batch_send_deadline
**キュー内に残ったサンプルを外部ストレージにフラッシュするまでの待ち時間。**
外部ストレージへのサンプルの送信はmax_samples_per_send単位で送信されるため、キュー内のサンプル数が単位未満の場合は送信されず残ることになる。
サンプルがキューに残り続けないようbatch_send_deadlineに設定した時間が送信待ちサンプルの待機時間となり、設定した時間経過すると外部ストレージに書き込まれる。

![remote_storage_integrations.png](https://qiita-image-store.s3.amazonaws.com/0/237938/ec9d4254-5316-c563-f177-e68c12aeb47d.png)


## max_retries
**サンプルの送信が失敗した時にリトライする回数。**

## min_backoff/max_backoff
**送信リトライの待ち時間の上限・下限。**
送信が失敗した時すぐにはリトライせず、min_backoffに設定した時間待ってから行われる。
２回目は前回のbackoff時間を2倍した値が待ち時間になり、以降２倍ずつ待ち時間が増えていく。
ただし最大はmax_backoffまで。

# 参考
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write
https://prometheus.io/docs/prometheus/latest/storage/#remote-storage-integrations
https://prometheus.io/docs/operating/integrations/#remote-endpoints-and-storage
https://github.com/prometheus/prometheus/tree/master/storage/remote
バージョン3のdocker-compose.ymlでvolumes_fromを使う

バージョン3のdocker-compose.ymlで `volumes_from` が使えないので代わる方法。

例
----

```yaml:docker-compose.yml
---
version: '3'

services:
  nginx:
    image: nginx:1.15.8-alpine
    :（省略）
    volumes:
      - document_root:/usr/share/nginx/html
    :（省略）

  wordpress:
    image: wordpress:5.0.3-php7.2-fpm-alpine
    :（省略）
    volumes:
      - document_root:/var/www/html
    :（省略）

volumes:
  document_root:
    driver_opts:
      type: none
      device: /path/to/host
      o: bind
```

解説
----

トップレベルで `volumes` を書いてそれを各サービスで共有する。こうすると`volumes_from`と同じように使える。

`driver_opts` はマウントするときのオプションを指定できる。例えば `nfs` の場合は `type` に `nfs` を指定すると良い。
Keynoteでスライド番号を表示させる方法

今回利用するKeynoteのバージョンは8.3となっています。

まずは、マスタースライドを開きます。

マスタースライドは『表示→マスタースライドを編集』をクリックすることで表示できます。
![img_5c3af2d092424.png](https://qiita-image-store.s3.amazonaws.com/0/140792/d2bee5e3-15ab-c8d3-5b8c-dd767a85ff32.png)

もしくは、『フォーマット→マスタースライドを編集』で開くことができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/ad916c8b-91ec-1457-2009-6d6351255f83.png)


『フォーマット』をクリックすると『アンビバレンス』という項目があります。
アンビバレンスにある『スライド番号』のチェックをONにするとスライド番号が表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/f4172a96-a57f-0680-d428-d5af6c81b10d.png)



編集したマスタースライドをテーマとして保存すればスライド番号が表示されたスライドを使い回しできます。

Keynoteのテーマの作り方については以下の記事を参考にしてください。
<a href="https://nishinatoshiharu.com/create-keynote-theme/" target="_blank">既存テーマはイケてない!?Keynoteでテーマを自作してみよう!</a>
Keynoteで箇条書きの行頭記号を変更する方法

今回利用するKeynoteのバージョンは8.3となっています。

まずは、箇条書きされたテキストをクリックします。すると、右側に『テキスト』という項目が表示されるので、それをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/b63f51be-c626-27e6-c2fb-8a136b848dcd.png)

『テキスト』をクリックすると『箇条書きとリスト』という項目があります。
ここの部分で行頭の記号、サイズ、インデントなどが変更できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/4e969820-30ad-9867-1b8f-a5513b6368bb.png)


なお、マスタースライドを編集し、テーマとして保存すれば変更した行頭記号を使い回しできます。

Keynoteのテーマの作り方については以下の記事を参考にしてください。
<a href="https://nishinatoshiharu.com/create-keynote-theme/" target="_blank">既存テーマはイケてない!?Keynoteでテーマを自作してみよう!</a>
ゼロから作るDeep Learning② ２章 自分用まとめ

#### （単語の）分散表現
単語をベクトルで表現すること。

#### 分布仮説
「単語の意味は、周囲の単語によって形成される」という考え。

#### Co-occurence Matrix 共起行列
ある単語に着目した場合、その周囲にどのような単語がどれだけ現れる化をカウントし、集計した行列。
分布仮説に基づいて単語をベクトル化する方法の一つ。

       |you|say|goodbye|and|i|hello|.
    ---|---|---|---|---|---|---|---
you    |0|1|0|0|0|0|0
say    |1|0|1|0|1|1|0
goodbye|0|1|0|1|0|0|0
and    |0|0|1|0|1|0|0
i      |0|1|0|1|0|0|0
hello  |0|1|0|0|0|0|1
.      |0|0|0|0|0|1|0

#### Cosine Similarity コサイン類似度

「2つのベクトルがどれだけ同じ方向を向いているか」を示す。完全に同じ方向を向いているときは1、逆向きだと-1となる。


```math
similarity(x, y) = \frac{x\cdot y}{\|x\|\|y\|} = \frac{x_1y_1+...+x_ny_n}{\sqrt{x^2_1+...+x^2_n}\sqrt{y^2_1+...+y^2_n}}
```

```python
eps=1e-8
nx = x / (np.sqrt(np.sum(x**2)) + eps)
ny = y / (np.sqrt(np.sum(y**2)) + eps)
return np.dot(nx, ny)
```

#### PMI - Pointwise mutual Information 相互情報量

単純な共起行列では「the」などの頻出単語が、色々な単語と強い関連性を示してしまうという問題がある。PMIは単語単独の出現回数を考慮することで、より良い指標にするための式。

```math
PMI(x, y) = \log_2 \frac{P(x, y)}{P(x)P(y)} = \log_2 \frac{\frac{C(x, y)}{N}}{\frac{C(x)}{N}\frac{C(y)}{N}} = \log_2 \frac{C(x, y)\cdot{N}}{C(x)C(y)}
```
P(x) : 単語xが文章の中に登場する確率
P(y) : 単語yが文章の中に登場する確率
P(x, y) : 単語xとyが文章の中で共起する確率
C(__) : 文章の中に登場する回数
N : コーパスに含まれる単語数

#### Positive PMI 正の相互情報量

PMIが持つ、2つの単語で共起する回数が0の場合、$$log_2 0=-∞$$となってしまう問題を補う手法。

```math
PPMI(x, y) = max(x, PMI(x, y))
```

#### Dimensionality Reduction 次元削減

ベクトルの次元を、重要な情報をできるだけ残した上で、削減する手法のこと。


#### SVD - Singular Value Decomposition 特異値分解

次元削減の手法のひとつ。
Xcode Signing CertificateでThe 'Apple Developer Program License Agreement' has been updated. In order to access certain membership resources, you must accept the latest license agreement.の対処法

# 前置き
小ネタになります:pushpin:
私事ですが今年の目標は個人開発でiOS/Andorid、RailsでWEBサービスをリリースすることです。iOSの開発していたらTargetのSigningに「The 'Apple Developer Program License Agreement' has been updated. In order to access certain membership resources, you must accept the latest license agreement.」という警告が出ていました。

# 現象
XcodeのSigningに以下の警告が表示されていました。「Try Again」を押下しても改善されません。
![00.png](https://qiita-image-store.s3.amazonaws.com/0/240974/31c84ee1-d524-e67c-cdd1-d1f56597eb4a.png)

# 対処法
エラーメッセージのとおり「Apple Developer Programのライセンスが変わったので同意して」という意味です。[Apple Developer](https://developer.apple.com/jp/)でログインします。
![40.png](https://qiita-image-store.s3.amazonaws.com/0/240974/3fd7dc8c-9621-c26b-a752-f5a389b0144d.png)

Apple Developer Programでもお知らせがありました。「Review Agreement」を押下します。
![50.png](https://qiita-image-store.s3.amazonaws.com/0/240974/0c9f8d01-f90e-1eb8-24ba-07facac81a11.png)

ライセンスを確認して合意します。
![60.png](https://qiita-image-store.s3.amazonaws.com/0/240974/62276078-5623-35a2-9a4c-ef82cb2da24c.png)

ページが戻るとお知らせが消えて元どおりになっています。
![80.png](https://qiita-image-store.s3.amazonaws.com/0/240974/cc1d6b00-2dfd-50db-30e1-c39fa5969cea.png)

改めてXcodeの「Try Again」を押下すると警告が解消されます。
![100.png](https://qiita-image-store.s3.amazonaws.com/0/240974/d473dc2e-5526-ec9c-2df9-200787babfcf.png)

# 参考
https://stackoverflow.com/questions/50531453/the-apple-developer-program-license-agreement-has-been-updated

# 終わりに
日本語かつスクリーンショット付きの情報は少ないようですね。ご参考になれば幸いです。まぁ、stackoverflowの情報で十分かもしれませんが。。。
昨年10月にライセンスが変更されたようなのですが、なんで今年になって警告されるのでしょう:thinking:
Keynoteでグリッド線を表示させる方法

PowerPointを使っている人であればグリッド線(背景に表示される格子状の補助線)にはなじみがあると思います。

PowerPointではチェックボックスのON・OFFでグリッド線の表示を制御できます。
ところが、**KeynoteではPowerPointのようにグリッド線を簡単に表示させる機能が用意されておりません。**

グリッド線はスライド作りをする上で役に立つものなのでKeynoteでも表示をさせたいと思う人も多いでしょう。

そこで今回は個人的におこなっている、Keynoteでグリッド線を表示させる方法について紹介をしたいと思います。

なお、今回利用するKeynoteのバージョンは8.3となっています。


## マスタースライドを編集する

まずは、マスタースライドを開きます。

マスタースライドは『表示→マスタースライドを編集』をクリックすることで表示できます。
![img_5c3af2d092424.png](https://qiita-image-store.s3.amazonaws.com/0/140792/d2bee5e3-15ab-c8d3-5b8c-dd767a85ff32.png)

もしくは、『フォーマット→マスタースライドを編集』で開くことができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/ad916c8b-91ec-1457-2009-6d6351255f83.png)



## マスタースライドに補助線を引く
補助線を引くにあたり、まずはルーラを表示させます。
ルーラの表示は『表示 → ルーラを表示 (Command + r)』で行います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/e34fb77a-218e-46e8-49b9-69448dd98cd7.png)


ルーラをドラッグすると補助線が引けます。
![create-grid-line.gif](https://qiita-image-store.s3.amazonaws.com/0/140792/e4c9386b-ae3b-1379-ac4d-ad7d791632f4.gif)


等間隔で引くことでPowerPointのようなグリッド線用意することができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/a72c4669-c1e4-cce5-d658-bbe5328391c0.png)


## マスタースライドを呼び出す
マスタースライドを呼び出すと先ほど利用したグリッド線を利用することができます。
![low-open-master-grid-1.gif](https://qiita-image-store.s3.amazonaws.com/0/140792/bbdc19e8-6e57-5450-0dd5-bda6d60072da.gif)


マスタースライドで設定されたグリッド線の表示・非表示は『表示 → ガイド → マスターガイドを表示』で制御します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140792/0fd44616-fec4-87db-e182-554582a43c14.png)


## テーマとして保存すればいつでも再利用可能
グリッド線を引いたマスタースライドをテーマとして保存すればいつでもグリッド線を利用することができます。
Keynoteのテーマの作り方については以下の記事を参考にしてください。
<a href="https://nishinatoshiharu.com/create-keynote-theme/" target="_blank">既存テーマはイケてない!?Keynoteでテーマを自作してみよう!</a>


## まとめ
以上でKeynoteでグリッド線を引く方法について紹介を終わります。

個人的に利用している方法なので、もっといい方法があれば教えていただければ幸いです。

なお、今回の内容の詳細は以下の記事で紹介しているので、興味のある方はご覧ください。
<a href="https://nishinatoshiharu.com/gridline-in-keynote/" target="_blank">図形をキレイに配置する!Keynoteの背景にグリッド線を引く方法</a>
Google Cloud Functions の HTTP トリガーで matplotlib を使って生成した画像を返す

## はじめに

BigQuery に溜まったデータに対して Python のロジックをかまして、画像を返したいというケースがあったので、 Google Cloud Functions で実現できるか検証しました。自分の欲しいところまではできたので、記事としてまとめておきます。

GitHub でソースコード公開してますので、そちらも合わせてご参照ください。 
https://github.com/tanabee/functions-matplotlib

![screenshot20190113.png](https://qiita-image-store.s3.amazonaws.com/0/19698/eadb9cf7-7c63-ffed-1f4e-0224c245fea9.png)
完成物

## 最小限の実装

以下のコードで動作する。 Cloud Functions の動作環境にはデフォルトで Flask がインストールされているので、 Flask の記法で HTTP リクエストを処理できる。 matplotlib は別でインストールする必要があるので、 requirements.txt に記載。

Cloud Functions のローカル環境での開発〜デプロイは以下を参照。
[Google Cloud Functions のプログラムを Mac のローカル環境で開発〜デプロイする](https://qiita.com/tanabee/items/7eb2c46296bb9ac026a7)

```python:main.py
from flask import make_response
import matplotlib.pyplot
from matplotlib.backends.backend_agg import FigureCanvasAgg
from io import BytesIO
import random

def graph(request):

    # グラフ生成部分
    fig, ax = matplotlib.pyplot.subplots()
    ax.set_title(u'GRAPH')
    x_ax = range(1, 200)
    y_ax = [x * random.randint(100, 200) for x in x_ax]
    ax.plot(x_ax, y_ax)

    canvas = FigureCanvasAgg(fig)
    buf = BytesIO()
    canvas.print_png(buf)
    data = buf.getvalue()

    response = make_response(data)
    response.headers['Content-Type'] = 'image/png'
    response.headers['Content-Length'] = len(data)
    return response
```

```text:requirements.txt
matplotlib
```

ソースコード: https://github.com/tanabee/functions-matplotlib/tree/f27e307e5044d0a236b47c44576e82fa1f9be05d

## トークンで簡易認証

![スクリーンショット 2019-01-14 0.06.44.png](https://qiita-image-store.s3.amazonaws.com/0/19698/2f0a89a1-4b32-2b80-9d55-02f5a3172898.png)

トークンを使って認証をしてみる。 Cloud Functions の環境変数を使って認証している。これにより `[URL]?token=[環境変数で設定したトークン]` のようにリクエストしないと 403 エラーを返すようになる。

```python:main.py
- from flask import make_response
+ from flask import make_response, abort
  import matplotlib.pyplot
  from matplotlib.backends.backend_agg import FigureCanvasAgg
  from io import BytesIO
  import random
+ import os

  def graph(request):

+     if request.args.get('token') != os.environ.get('TOKEN', 'token123'):
+        return abort(403)
+        
      fig, ax = matplotlib.pyplot.subplots()
```

![スクリーンショット 2019-01-14 0.09.54.png](https://qiita-image-store.s3.amazonaws.com/0/19698/bf40c492-d0c7-0ff0-95c8-fb3c7ea5cd48.png)
TOKEN はオレンジ枠で囲った部分で設定できる。デプロイコマンド時に設定することも可能。

## まとめ

matplotlib で生成した画像を Cloud Functions を使って、 HTTP リクエストで返せるようにできました。公開範囲を絞りたい場合には、簡易なトークンも実装できます。 Cloud Functions は無料枠も多くて、簡単に実装できるので良いですね。

以上！
ディープラーニングのパラメーター数ってどうやって数えるんだっけという人へ

新しい記事として更新しましたので下記をご覧ください
https://qiita.com/Phoeboooo/items/b92c35f6739a9e765a80
# パラメータの数の計算まとめ
<b>NN , CNN , Embedding , SimpleRNN, LSTM, GRU</b>

#CNN, NN(Dense)
```python

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
```

＊ MaxPooling2Dは　2*2の範囲ごとの最大値, GlobalAveragePooling2Dは各チャンネルの平均を取るだけのため重みはなし


#Conv2D(１つ目）
<b>3 * 3 * 3 * 32 + 32 = 896</b>

フィルターの縦 * フィルターの横 * 入力のチャンネル数 * 出力のチャンネル数 + バイアス(1チャンネルごとに1つ)

#Conv2D(２つ目）
<b>3 * 3 * 32 * 64 + 64 = 18496 </b>

フィルターの縦 * フィルターの横 * 入力のチャンネル数 * 出力のチャンネル数 + バイアス(1チャンネルごとに1つ)

#Dense
<b>128 * 32 + 32 = 4128</b>

シンプルなニューラルネットワーク,   バイアスを忘れずに



#Embedding , SimpleRNN, LSTM, GRU
```python
model = Sequential()
model.add(Embedding(4000,32,input_length=20))
model.add(LSTM(64))
#model.add(SimpleRNN(64))
#model.add(GRU(64))
model.add(Dense(3))
model.add(Activation("softmax"))
```

#Embedding
<b>4000 * 32 = 128000</b>

・バイアスはない 
・Embedding層は仕組みはニューラルネットワークだが、ワンホットベクトルを小さな（密な）ベクトルに変換するための層

#SimpleRNN
<b>32 * 64 + 64 * 64 + 64 = 6208</b>

・入力に対しての重み
入力の次元数ｘ隠れ状態の次元数　
→　32*64

・隠れ状態に対しての重み
隠れ状態の次元数 x 隠れ状態の次元数 
→　64*64

・バイアス
隠れ状態の次元数
→　64

#LSTM
<b>32 * 64 * 4 + 64 * 64 * 4 + 64 * 4 = 24832</b>

・入力に対しての重み
入力の次元数 * 隠れ状態の次元数 * 4 　　　(forgetに１つ、inputに2つ、outputに1つ)
→　32 * 64 * 4 

・隠れ状態に対しての重み
　隠れ状態（記憶セル）の次元数 * 隠れ状態の次元数 * 4　　　(上記のように4つ必要)
→　64 * 64 * 4

・バイアス
隠れ状態の次元数 * 4 　　　　　(上記のように4つ必要)
→　64 * 4

#GRU
<b>32*64*3 + 64*64*3 + 64*3 = 18624</b>

・入力に対しての重み
入力の次元数 * 隠れ状態の次元数 * 3 　　　(リセットゲートで1つ、更新ゲートで2つ) 
→　32 * 64 * 3

・隠れ状態に対しての重み　
隠れ状態の次元数 * 隠れ状態の次元数 * 3　　(上記のように3つ必要) 
→　64 * 64 * 3

・バイアス 
 隠れ状態の次元数 * 3　　(上記のように3つ必要) 
→　64 * 3
Google Cloud Functions の Python コードを Mac のローカル環境で開発〜デプロイする

## はじめに

[Google Cloud Functions](https://cloud.google.com/functions/?hl=ja) は GCP コンソールにもエディタが用意されていますが、ローカルで開発したほうがはかどるので、 Mac で開発してデプロイする方法を備忘録としてまとめておきます。

[公式の日本語ドキュメント](https://cloud.google.com/functions/docs/quickstart?hl=ja) は記事公開時点では Python のサンプルがないので、 Python ユーザーは [英語ドキュメント](https://cloud.google.com/functions/docs/quickstart?hl=en) 推奨。

## gcloud コマンドのインストール

以下のコマンドを実行。 gcloud コマンドをインストールすると Cloud Functions に限らず、 Google Cloud Platform のデプロイなどが可能になる。

```bash
$ brew cask install google-cloud-sdk
$ gcloud init
$ gcloud components update && gcloud components install beta
```

## デプロイ

言語が Python で HTTP トリガーを利用する場合は、以下のコマンドを実行するとデプロイできる。

```bash
$ gcloud functions deploy graph --runtime python37 --trigger-http
```

以上。

## 関連記事
- [Google Cloud Functions の http トリガーで matplotlib を使って生成した画像を返す](https://qiita.com/tanabee/items/2bfee85f9659be097750)
keycloakのセットアップ手順

#概要
keycloakのセットアップは非常に簡単。
っていうかインストールして起動するだけなんで。
というわけでこのページは以下の内容で書いていきます。

１．keycloakを動かすのに必要なものをインストール
２．keycloakをインストール
３．起動、動作確認

#必要なもの(システム要件)
・Java 8 JDK
・RAM512MB以上
・今回はCentOS7.5

#keycloakのセットアップ
##keycloakのインストール
keycloakは公式の[こちら](https://www.keycloak.org/downloads.html)からインストールします。

インストールしたら、対象サーバの任意の場所に置きます。



##サーバの起動
ダウンロードしたら、適当なフォルダに解凍して、binディレクトリにあるstandalone.shまたはstandalone.batを実行すると、Keycloakサーバーが起動します。
※デフォルトではリモートホストからの通信を許可していないため、-bオプションを入れてあげる必要があります。

~~~
./bin/standalone.sh -b 0.0.0.0
~~~

なんか色々起動して、最終的にこんなメッセージが出てきていれば大丈夫です

~~~
Keycloak 4.8.2.Final (WildFly Core 6.0.2.Final) started in 25739ms - Started 577 of 834 services (557 services are lazy, passive or on-demand)
~~~

で、これこの状態で切断を切るか、もしくはバックグラウンドで実行するとかが必要そうです。

##管理者ユーザの作成
ブラウザから以下URLへアクセスします。
http://<keycloakサーバーのIP>:8080/auth
するとこんな画面が出てきます。
※4.8だとこんなオシャンティーな画面なんですねー
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167126/f46c373d-9691-f8b5-ebed-2db68a27623f.png)

keycloakにはデフォルトの管理ユーザがなくて、まずはそれを作成しないことには何も始まらない！ので以下手順で作ります。

で、以前のバージョンだとこの画面から管理者ユーザ作成できたんですけど、今はローカルホストに接続するか、add-user-keycloak.shを使ってユーザを作るかのいずれかになっているみたいです。

今回のようにサーバーを別で用意してkeycloakを入れる場合は後者の方法しかありません。
以下のコマンドで管理者ユーザを作成しましょう。

~~~
./bin/add-user-keycloak.sh -u　<管理者ユーザ名>
~~~

一度keycloakを再起動して、再度URLにアクセスすると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167126/e8d0753b-b43f-c884-f16d-3cd47638d108.png)

Administratiron Console なるものが表示されるようになりました！！！

こいつをポチっと押すとログイン画面が出てくるので、先ほど設定した管理者ユーザとパスを入力してログインします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167126/79f495a5-1210-0f4c-4c0d-600b6e7b116d.png)

デフォルトだと英語表示になっているので、日本語に直します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167126/79ab2d55-f6c8-562e-5d8b-a932387d3750.png)

「Themes」タブを選択し、「Internationalization Enabled」をONにして、SAVEします。
一度サインアウトすると日本語化されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167126/5cb5ff33-2016-c05d-3b12-7ab362620364.png)
Linux 64bitアセンブラでhello, world

#環境
Windows Subsystem for Linux

- Windows 10 Home 64bit
- Ubuntu

参考：[Windows Subsystem for Linuxをインストールしてみよう！](https://qiita.com/Aruneko/items/c79810b0b015bebf30bb)

#ソース等

- ソース

```nasm:hello.s
msg:	.ascii "hello, world\n"

	.globl _start

_start:
	mov $1,%rax     # write
	mov $1,%rdi	# stdout
	mov $msg,%rsi	# addr
	mov $13,%rdx	# len
	syscall

	mov $60,%rax	# exit
	mov $0,%rdi	# status
	syscall
```

- アセンブル&リンク

```
as hello.s -o hello.o
ld hello.o -o hello -s
```

#実行結果
![hello.png](https://qiita-image-store.s3.amazonaws.com/0/257554/7163f9d4-63de-09ba-b8eb-def3729c65de.png)

#参考
- [アセンブラでQuine](https://qiita.com/fujitanozomu/items/1108c16a4712c14c58db)
Google Hangoutchat に GASから定期的に投稿する


# はじめに

* Google Hangoutchat の Webhook機能 と GASのトリガー(定期実行)機能 を使って、定期的に投稿できるようにします

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/e31b6791-d455-a821-0327-9ecfbf23ef74.png)

↑ は 1分おきに定型文を投稿しています

# Webhookを設定

* 定期的に投稿したいチャットルーム or グループ のWebhookを設定します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/08422340-0534-d457-29ef-b72e9d289809.png)

* 以下を設定
    * 名前 ( チャットで表示される名前 )
    * アバタ ( チャットで表示されるアバター )

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/5f273da5-c41b-fd0b-e5d1-6ecf052ff860.png)

* Webhook用のURLが発行されるのでコピーしておく

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/71a73bbd-32b5-0d3a-ebbe-5677758d6d42.png)


# GASを設定

## スクリプトを作成

* > GAS 新規プロジェクト でソースコードを作成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/cf23083a-7a20-3e67-5415-1bd3c8f985dc.png)


* `webhookUrl` に先ほど取得した URL を設定してください

```js
function myFunction() {
  var webhookUrl = 'https://[取得したWebhookURL]';
  var botMessage = { 'text' : 'Cron Post from GoogleAppsScript!'}

  var options = {
    'method': 'POST',
    'headers' : {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    'payload':JSON.stringify(botMessage)
  };

  var result = UrlFetchApp.fetch(webhookUrl, options);
  Logger.log(result);
}
```

## トリガーの設定

* トリガーの設定をします。 `> プロジェクト一覧 > メニュー > トリガー`

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/f5ab99c6-0a93-1037-9439-df0102f6bf2b.png)

* `新しいトリガーの作成` からトリガーを作成します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/04097861-fc94-de1a-5f31-24a30b99dec5.png)

* ためしに、1分おきに実行してみます。以下のように設定ができるようです。
    * 時間主導型
        * 特定の日時
        * 分ベース
        * 時間ベース
        * 日付ベース
        * 週ベース
        * 月ベース
    * カレンダー主導型


![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/1b3f3036-c01e-a686-faea-8fbcc87bf925.png)

* トリガーで設定できました。これで設定は終わりです！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/b44c9906-77a2-2a35-bda3-6f3d2e2a5c3a.png)


# チャットルーム確認

* ちゃんと設定した通り 1分 おきに投稿されていますね

![image.png](https://qiita-image-store.s3.amazonaws.com/0/108052/db8c7a8d-ac55-1ae6-d5a6-774b65d25f7c.png)


# 参考

* [GASからhangout chatにPostする](https://qiita.com/mistolteen/items/a67b131b31d5c5246a6c)
CSSだけで、角が丸いグラデーションのGoogle風ボタンを描く

画像を使わずにこんなボタンがつくれます。
![serch.png](https://qiita-image-store.s3.amazonaws.com/0/262601/e9528e56-0c03-1659-a0d4-b93541ea84df.png)

```css
.btn {
  box-shadow:inset 0px 1px 0px 0px #ffffff;
  background:color-stop(0.05, #f9f9f9), color-stop(1, #e9e9e9));
  background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%);
  filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#e9e9e9',GradientType=0);
  background-color:#f9f9f9;
  border-radius:6px;
  border:1px solid #dcdcdc;
  display:inline-block;
  cursor:pointer;
  color:#666666;
  font-family:Arial;
  font-size:1em;
  padding:3px 24px; /* ボタンの上下と左右の中の余白 */
  text-decoration:none;
}

.btn:hover {
  background:color-stop(0.05, #e9e9e9), color-stop(1, #f9f9f9));
  background:linear-gradient(to bottom, #e9e9e9 5%, #f9f9f9 100%);
  filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e9e9e9', endColorstr='#f9f9f9',GradientType=0);
  background-color:#e9e9e9;
}

.btn:active {
  position:relative;
  top:1px;
}

.btn {
  margin-top: 1em;
}
```
Chart.js で0位置のグリッド線の位置を変える

<p data-height="265" data-theme-id="0" data-slug-hash="qLLKYZ" data-default-tab="js,result" data-user="boushi-bird" data-pen-title="Chartjs example - change the zero line position." class="codepen">See the Pen <a href="https://codepen.io/boushi-bird/pen/qLLKYZ/">Chartjs example - change the zero line position.</a> by boushi-bird (<a href="https://codepen.io/boushi-bird">@boushi-bird</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
文字列を一文字ずつ分割して反復（Array.from 利用）

こんにちは。
文字列を一文字ずつ分割して反復させ、オブジェクトを作ってみました。```Array.from()``` を利用しました。

```js
var abc = {};
Array.from('abc', (v, i) => {abc[v]=i;});
  // Array.from('abc').forEach((v, i) => {abc[v]=i;});
console.log(abc); // => {a: 0, b: 1, c: 2}
```
【自分用メモ】シェルスクリプト実行時に/bin/bash^M: bad interpreter: No such file or directoryが出力される

Qiita初投稿です。

自分用のメモだけでなく、ググってもなかなかヒットせずなんとか自己解決に導いたものなどをどんどんアウトプットできれば嬉しいな、と考えています。

## 事象
Visual Studio Codeで作成したシェルスクリプトをubuntuで実行しようとしたところ、以下のエラーが出力された。

```
-bash: ./hoge.sh: /bin/bash^M: bad interpreter: No such file or directory
```

## 原因と対策
Visual Studio Codeで作成したシェルスクリプトの改行コードが`CRLF`になっていたため。
改行コードを`LF`に修正することで問題なく実行できた。
Qiitaのスパムに対処する方法を考える

#　なんかスパム投稿がいっぱい

　タグ・ランキングを見たら「vs」というのが一番に来ていた。一瞬、もしやVisualStudioCodeがPythonを上回ったのかと思ったら、単なるスパム投稿の塊だった。まあ、連休が明けたらなんとかしてもらえるだろう。もしかしたら、対処されないであろう連休を狙ってきたということだろうか？スパムが多すぎてあまりに酸っぱい、酸っぱいよ。

　まあ、それは置いておくとして、こういったスパムに対抗する方法を考えてみたい。

##　相手がボットだったら

　キーワードや画像を人間に識別させ入力させるCAPTCHAを行うのが一般的である。しかしこれは正規利用のユーザに負荷をかける方式だ。あまりに面倒なので入力を代行するサービスが商売となってしまうほどである。さらに画像認識技術の発達により、難易度の高いCAPTCHAを人間よりも優秀に解いてしまうこともある。逆に早すぎたり、正確すぎると自動入力だと判断されるというカオスな世界となっている。いつまでイタチごっこが続くのか、先が見えない。ボットの対処のために人間がボーッとしてられないのだ。

##　相手が人間だったら

　まずは登録ユーザをBANすることである。しかしたとえ一人BANしようとも、第二第三のスパマーが現れるのだ。もはや何番目のBANだという状態である。そうなると該当IPからの登録を弾くしか無い。だがIPをごまかしてきたら？

　本人確認の手段の一つとしてクレジットカードを登録させるというのがある。しかし無料サービスには馴染まない。クレジットカードのデータをクレと言ってジッとしていても稼働はしない。では打つ手無しだろうか？


##　一見さんお断り

　一つの対処法として、既存ユーザの紹介が必要とする方式がある。SNSの草分け的存在だったmixiは招待制から始まった。ただそうなると、最初のハードルが高くなりすぎてサービスの普及を阻む要因にもなりかねない。非常にリスクの高い諸刃の剣だ。　


##　キーワードによる検閲

　スパム投稿に含まれる何らかのキーワードをNGワードとして、投稿させないようにする手段もある。単純なNGワードだと正規利用者の投稿の妨げになる可能性があるので、キーワードのスコア付けが必要だろう。ただし問題がある。スパマーが投稿内容を修正して、検閲に引っかからないキーワードや文章に変えてきたら、再びロジックを再考しなければならない。ぶっちゃけ、やってられない。

##　人間による承認

　投稿内容を管理者が確認し承認する方式だ。しかしこれは管理者の負荷がかかりすぎる。無料サービスではやっていられないだろう。他の方法としては利用者に対しスパムの判定を委ねる方法がある。一定基準を超えたら非表示とするのだ。ただし自分の気に入らない投稿をスパム扱いしたりというケースも考えられるので、運用がうまくいかない可能性もある。

##　AIによるスパムの学習

　メールフィルタリングではすでに実現されている。スパムメールを学習し自動的にフィルタリングする方式だ。すり抜けてしまったものを学習させれば、精度を向上させることが出来る。しかし世の中には重要なメールなのにスパムみたいな形式で送られてくるメールがあり、必要なのにスパムとして振り分けられていたりと予断を許さない。

　投稿のフィルタリングにAIを活用するとして、致命的な問題がある。とても開発コストがかかることだ。無料サービスでの実施はあまりに厳しい。いつか「Pythonでスパム投稿を99%判別するプログラムを作ってみた」とかいう投稿を待つしか無いだろう。


#　まとめ

　「Pythonでスパム投稿を99%判別するプログラムを作ってみた」はいずれ~~暇~~優秀な人が記事を投稿してくれると思う。
Cognitoユーザープール認証をALBに適用した際に500エラーとなる件

## はじめに

Elastic Beanstalkで構成したALBにCognitoユーザープールの認証を適用しようとした際に、500エラーでハマったので共有しておきます。やろうとしたことは、ほぼ下記の記事と同じです。
[インフラエンジニアが一切コードを書かずにWebサーバーに認証機能を実装した話](https://dev.classmethod.jp/cloud/alb-cognito-user-pool/)

この記事通りに設定をしたはずなのに、認証が成功するとなぜかALBが500 Internal Service Errorを返してきます。

## 結論

ALBに設定されているセキュリティグループのアウトバウンド設定が問題でした。下記がElastic Beanstalkが自動で作成したALBに設定されているセキュリティーグループのアウトバウンド設定です。

![EC2 Management Console (1).png](https://qiita-image-store.s3.amazonaws.com/0/7519/c68b72d7-116b-f10a-a3c2-ba3ceb18e304.png)

ALBがIdPエンドポイントにトークンの検証をしに行く際に、httpsでコネクションに行くために、この設定ではつながらないという落ちでした。下記のようにHTTPSも通してあげれば、ちゃんと通りました。IdPのエンドポイントはデュアルスタックで動いているようなので、一応IPv6も入れときましょう。

![EC2 Management Console (2).png](https://qiita-image-store.s3.amazonaws.com/0/7519/2e10a6f5-c279-8e7b-8469-86756c521721.png)

普段、アウトバウンド側の設定はほとんどいじることがないので、全然気づかずだいぶハマりました。しかし、セキュリティグループを新規作成する時のアウトバウンド側のデフォルトは全開放なのに、なぜElastic Beanstalkさんはこんな中途半端な設定にしてくれちゃっているのでしょうか？
Haskell触る際の備忘録

# Haskell触ったことのない自分の備忘録です

個人的に引っかかったり詰まった部分を
「あれ、どうすればいいんだっけ」となったときに見返すための記事です。
他の方の記事のまとめになってしまうかもしれません。


# 環境

OS : Windows10, ArchLinux, Cabal, VSCode

# cabalプロジェクトの作り方

```
$ mkdir project_cabal
$ cd project_cabal
$
$ cabal init
$ cabal configure
$ cabal build
$
```
【Processing3.0対応】クラッシュなどで壊れたデータの復元方法

#データの場所
**この方法がわかるまで数十回プロジェクトを作りなおしました**
Processingに自動保存機能はないのですが、
C:\Users\ユーザー名\AppData\Local\Tempの中にプロジェクトが一時保存されているようです！
保存されているフォルダ名ですが。
Nameという名前で保存していた場合、Name"文字列"tempというフォルダーに入っています。
保存していなかった場合どんな名前なのかはこちらが参考になります
http://monge.tec.fukuoka-u.ac.jp/cg_processing/01_basic-2a_v2.html
#開き方
フォルダーを開くと、XXXX.javaというファイルがあるので、（他のものが入っていたら似た名前のフォルダーから探してください）
XXXX.java から XXXX.pdeというファイル名に変換します。（拡張子表示モードで変換してください）
後は変換後のファイルをProcessingで開いてください。
初めての時は何か表示されますが**OK**を押してください
#開いた後
import文とプロジェクト全体を囲っているclassを削除してください。（関数の前にPublicが付いていますが消して大丈夫だと思います）
これでうまく動くはずです！
Vagrant環境を他のPCに受け渡す方法

Vagrantで構築した環境を、別PCにコピーする機会があったのでその作業メモです。
# 移動元

1. Vagrant管理しているディレクトリ(Vagrantfileがあるところ)で`vagrant halt`コマンドで停止
2. `vagrant package`コマンドを実行する。package.boxファイルが作成される。これが配布用のファイル
3. package.boxファイルを移行先PCへ移動させる。1GBくらいあったのでAirDropで移動した。


# 移動先
VagrantとVirtualBoxはインストールしておく

1. `vagrant box add 任意のボックス名 package.boxへのパス`でpackage.boxを登録する。
例：`vagrant box add My_BOX ./package.box`
2. `vagrant box list`で登録したBoxを一覧表示で確認
3. `vagrant init 登録したBox名`で初期化する。Vagrantfileが生成される。
 例：`vagrant init My_BOX`
5. `vagrant up `で起動
6. `vagrant ssh`で接続

# 留意事項
* Vagrantfileはコピーされないので、移動元で変更している場合は、移行先でも合わせて変更する
* もちろんVagrantで管理しているOSのユーザーパスワードも移行先に引き継がれるので、共有してもOKなパスワードに変更の上で`vagrant package`する
swift4で"子クラスに"プロトコルを準拠させる方法

特定のクラスにプロトコルを準拠させるのではなく、その`子クラスに`プロトコルを準拠させたいことがあったのでメモまでに！

# コード例
例えばUITableViewCellクラスを継承する独自cellのクラスに、`identifier`というstaticプロパティを持たせたいとします。

```swift
// 対象の独自cellクラス(子クラス)
class ShopListViewCell: UITableViewCell {}

// Protocolを用意
protocol IdentifiedCell {}

// まずUITableViewCell(親クラス)を準拠させる
extension UITableViewCell: IdentifiedCell {}

// 子クラスに準拠させたいProtocol内容を記述
extension IdentifiedCell where Self: UITableViewCell {

    // `Self`が使えるのがいいですね！
    static var identifier: String {
        return String(describing: Self.self) // => "ShopListViewCell" など子クラスの名前取得できる
    }
}
```
※Protocolエクステンションであるため、ストアドプロパティを定義できないのは仕方ないですね😅

## まとめ
簡単にいうと、親クラスに準拠させたプロトコルに、extensionで`where Self: 親クラス`という形で子クラスにのみ対応させたい内容を追加していけばいいんですね🙌
よければ使ってみてください！
他にもいい方法があればコメントお待ちしてます〜〜