OmniAICreator/Qiita-1.07M huggingface dataset:
Macでpython-igraphを入れる際に、はまってしたこと

# 環境
macOS Mojave 10.14.6
Python 3.6.3 :: Anaconda, Inc.

# やりたいこと/問題
python-igraphをインストールしたい。しかし、```pip install python-igraph```とすると、エラーが出て進まない。

# エラー文
```
    clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
    ld: library not found for -lstdc++
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    error: command 'gcc' failed with exit status 1
```

# やったこと
・gccのアップグレード
・pipのアップグレード
・xcodeのアップグレード
・stdc++のファイル作成
[Xcodeでbits/stdc++.hをインクルードする](https://qiita.com/acchan_ar/items/6a4c4c070dd76a236fdc)
・パスの設定
[brewでインストールしたg++-7およびgcc-7のパスの繋ぎ方](https://teratail.com/questions/113045)

この状態でも、うまくインストールされなかった。。

# 参考になりそうなこと
以下の内容が参考になりそうだったけど、どのように環境変数を変更すればいいか分からなかった。
[MacOS X 10.9 / Xcode 5 で GLUT を使うと警告が出る](http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20140617)

さらに、調べて以下のサイトが参考になった。
[AMBERとAmberToolsのインストール方法](https://qiita.com/Ag_smith/items/d2e86dda17f190a3dd0f)
このサイトに表記されている、以下の部分を実行することでエラーが無くなった。やった！

```
open /Library/Developer/CommandLineTools/Packages

export MACOSX_DEPLOYMENT_TARGET='10.14'
```

# で、python-igraphを入れるのだが...
インストールできたのは良かったけど、動かすと、お決まりのエラーが出るんですよねぇ^^;

```
TypeError: plotting not available
```

そこで、調べたところ。以下のを入れろ、と。
[python + igraph “plotting not available”
](https://stackoverflow.com/questions/12072093/python-igraph-plotting-not-available)

```
pip install cairocffi
```

で、また違うエラーが。
[dlopen() failed to load a library: cairo / cairo-2#84](https://github.com/Kozea/CairoSVG/issues/84)

```
dlopen() failed to load a library: cairo / cairo-2
```

そして、cairoとGtkを入れるらしい。。ただ、```pip```ではなく、Macportsを使うので、それを入れる必要がある。
[教授でもできる、Mac OS XへのMacPortsのインストレーション](http://osksn2.hep.sci.osaka-u.ac.jp/~taku/osx/install_macports.html)

で、carioをインストール。

```
sudo port install cairo
```
[cario](https://www.cairographics.org/download/)

で、GTKをインストール。GTKは```brew install gtk```で、+は無くても良かった。
[MacにGTK+をインストールする](http://yoroheihei.hatenablog.com/entry/2016/01/02/223554)

これで```igraph```を使えるようになった！！えがったえがった。

# 補足
日本語を表示しようと思ったら豆腐問題が。。ということで、以下の記事を参考に。
[pythonでiGraphを使用すると日本語が表示されない問題を解決する[Mac]](https://qiita.com/Tazake/items/af62dfeb27145876990c)

ただ、どこにフォルダがあるのか、という場合は、以下の記事を。
[Python Tips：ライブラリ・モジュールの場所を調べたい](https://www.lifewithpython.com/2014/07/python-get-location-of-libraries-modules-packages.html)

どこに、該当のテキストにあるかのVim命令。
[Vimコマンド : 便利一覧](https://qiita.com/iwaseasahi/items/f536bb3772d2fad5e03c)

いかがでしょう？これでできました。
VBA テキスト化 備忘 4H070Z

他者の投稿から引用したものを自分用に残す。


Public Sub ExportModules()
    '現在のワークブックのモジュールをエクスポートする
    Dim targetModule As VBComponent
    Dim outputPath As String
    Dim fileExt As String
    outputPath = ActiveWorkbook.Path
    For Each targetModule In ActiveWorkbook.VBProject.VBComponents
        fileExt = GetExtFromModuleType(targetModule.Type)
        If fileExt <> "" Then
            ExportModuleWithExt targetModule, outputPath, fileExt
            Debug.Print "Save " & targetModule.Name
        End If
    Next
End Sub

Private Function GetExtFromModuleType(aType As Integer) As String
    '指定されたモジュール・タイプに対応する拡張子を返す
    Select Case aType
    Case vbext_ct_StdModule
        GetExtFromModuleType = "bas"
    Case vbext_ct_ClassModule, vbext_ct_Document
        GetExtFromModuleType = "cls"
    Case vbext_ct_MSForm
        GetExtFromModuleType = "frm"
    End Select
End Function

Private Sub ExportModuleWithExt(aModule As VBComponent, Path As String, Ext As String)
    '指定されたモジュールをエクスポートする
    Dim filePath As String
    Dim fileName As String
    'filePath = Path & "" & aModule.Name & "." & Ext
    fileName = ActiveWorkbook.Name
    filePath = Path & "" & fileName & "-" & aModule.Name & "." & Ext
    aModule.Export filePath
End Sub
応用部分
複数のファイルに対して実行するための部分です。

Sub フォルダ内モジュール一括エクスポート()
    thisfn = ActiveWorkbook.Name
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "フォルダを選択"
        .AllowMultiSelect = False
        If .Show = -1 Then
            targetdir = .SelectedItems(1)
        Else
            Exit Sub
        End If
    End With
    targetfn = Dir(targetdir & "", vbNormal)
    Do Until targetfn = ""
        If thisfn <> targetfn Then
            Call モジュールをエクスポート(thisfn, targetfn)
        End If
        targetfn = Dir
    Loop
    MsgBox "処理が終わりました。"
End Sub

Sub モジュールをエクスポート(thisfilename, targetfilename)
    Workbooks.Open fileName:=targetfilename
    Application.Run thisfilename & "!ExportModules"
    ActiveWorkbook.Close
End Sub


"開発コード:4H070Z"
Slack WebAPIのSpecファイルが修正されたのでOpenAPI GeneratorでPHPのコードを自動生成してみた

## はじめに成果物

https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json

↑これから

https://github.com/halnique/slack-openapi-php

↑これがコマンド一発で生成できました

## 背景

Slackは外部から実行可能なWebAPIの仕様を`OpenAPI(Swagger) Specification`として公開しています

https://github.com/slackapi/slack-api-specs

※ OpenAPIについては[こちら](https://swagger.io/docs/specification/about/)

以前SlackのWebAPIを呼び出すアプリを作っていたとき、[OpenAPI Generator](https://openapi-generator.tech/)を利用してPHPのコードを自動生成しようとしていましたが、当時のSpecファイルに不具合があり生成できませんでした

以下のissueが上がっていたのでウォッチしていたのですが、修正がリリースされたようなので改めてOpenAPI Generatorでコード生成を試してみました

https://github.com/slackapi/slack-api-specs/issues/19

## 準備

* macOS 10.14.5
* docker 18.09.2

OpenAPI Generatorは[Dockerイメージが提供](https://hub.docker.com/r/openapitools/openapi-generator-cli)されているので、Dockerが使える環境ならすぐに利用可能です

## 手順

対象は以下のSlack公式WebAPIのSpecファイルです

https://github.com/slackapi/slack-api-specs/blob/master/web-api/slack_web_openapi_v2.json

コード自体はコマンド一発で生成可能です

```
docker run --rm -v $(pwd)/slack-openapi-php:/out \
  openapitools/openapi-generator-cli generate \
  -i https://raw.githubusercontent.com/slackapi/slack-api-specs/master/web-api/slack_web_openapi_v2.json \
  -g php -o /out
```

`docker run`で`openapitools/openapi-generator-cli`イメージを指定し、対象Specファイルは`-i`オプションでGitHubのURLを直接指定しています

変換する言語を`-g`オプションで指定し、成果物の出力先を`-o`オプションで指定しています

成果物は以下のようになりました

https://github.com/halnique/slack-openapi-php

`README.md`やドキュメントも生成されるので、自前で`guzzle`や`cURL`を使って実装する際の参考としても効果的に使えそうです

## まとめ

SlackのOpenAPI SpecからOpenAPI Generatorを利用してPHPのクライアントコードを生成してみました

OpenAPI GeneratorはSpecファイルさえ適切に定義されていれば、PHPでのクライアント以外にも多様な変換が可能です

Specファイルを参照しても実装のイメージがつかないようなときに、一度実装中の言語で生成できないか試してみるのもいいかもしれません

https://github.com/OpenAPITools/openapi-generator
CSS フレームワーク導入時に気をつけること

※注：個人の経験と主観を多分に含みます

## まえがき

フロントエンドエンジニアと一口に言ってもその出自は様々で、バックエンドから入ってきた人たちは何となく CSS を目の敵にする傾向が強いような気がします。
確かにプログラム視点からみると貧弱過ぎてすぐに壊れる仕様に不満を感じる気持ちは分かりますが…
自分はというと HTMLコーダーから入ってきたクチなので CSS やその設計には全然抵抗ないです。（むしろ大好物）

面倒な CSS の管理を極力遺棄したい気持ちが高まった結果、CSS フレームワークの採用にたどり着くのはもはや必然なのかもしれません。
ただし本当にその選択は正しいんでしょうか…？


## CSS フレームワーク導入による明るい未来の幻想

CSS フレームワーク導入推進派の意見を聞くと開発コストの削減や学習コストの低さ、品質を担保できるなどの利点が挙げられますが、実際に導入をした結果、負の面が噴出するケースに幾度となく遭遇してきました。

フレームワークの利点が実際の成果に反映されなかったケースを幾つか挙げてみます。

### 制作コストを削減できる

確かにイニシャルコストは削減できます。
ただしカスタムが前提の場合、フレームワークの制約がカスタムの足枷になることが多いです。
また事前にカスタムに対するレギュレーションを決めておかないと、直ぐに作業者ごとの「オレオレ CSS」が増えてカオス化、後の運用コストに跳ね返ってきます。
そして大抵の案件はカスタムせずに済むケースである方が少ないです。

作りきりの逃げ切り案件だったらまだしも、運用保守まで見据えると、ちゃんとカスタム部分のレギュレーションを決めておいた方が良いですし、コスト削減はトータルで見る必要があります。

### 学習コストが低い

メジャーな CSS フレームワーク（例えば [Twitter Bootstrap](https://getbootstrap.com/) とか）は制作経験者が多いという1点において学習コストは低いのですが、星の数ほどある様々なフレームワーク、少しでも王道から逸れると大多数の人にとっては初見のケースがほとんどだったりします。
公式の手厚いドキュメントも学習コストを低くできる一因ですが、案件には必要のない多機能なコンポーネントも内包されていたりして、必要最低限にコンポーネント設計したフルスクラッチの CSS に比べて見るべき部分が多かったりします。

### 引き継ぎは公式ドキュメントを案内すれば良い

カスタムしてない状態のフレームワークだったらその通りですが、カスタムしているのであれば追加・修正部分の補足情報はやっぱり必要になるため、公式ドキュメントのみ、という訳には行かなかったりします。
公式＋カスタム差分のドキュメントの合わせ技でフォローする必要はあります。

### クオリティを担保できる

制作に関わる人が CSS フレームワークの仕様と制限、作法を正しく理解していることが前提です。
CSS の工数を減らしたい、手間をかけたくない、というモチベーションが先行してフレームワークの理解が少ないままにコンポーネントを量産すると、本来フレームワークで書くべきレイアウトやコンポーネントをオレオレ CSS で書いてしまい、亜種や派生が生まれてそこから管理が破綻していく、というケースを何度も見てきました。
クオリティを担保するにはフレームワークへの学習とレギュレーションの遵守が必要になります。


## CSS フレームワーク導入検討するときに気をつける点

CSS フレームワークを導入してメリットを享受するには、以下の点をちゃんと事前に検討・対処した方が良いでしょう。

### フレームワークの制約・仕様がプロジェクトの要件に則しているか

よく使われているから、くらいの安易な理由でフレームワークを導入すると痛い目を見ます。

- 採用されている CSS プリプロセッサ
- コンポーネント粒度
- カスタムのし易さ
- コンポーネントの種類やボリューム

プロジェクトの規模や求められる機能・構成・要件によって使い分けられるように CSS フレームワークも複数の選択肢を持っておけると良いでしょう。

### プロジェクト上のレギュレーションを明確にする

カスタムが前提の場合、CSS フレームワークの本来のレギュレーションだけでは不十分です。カスタム可能な範囲や追加の方針、命名規則、管理方法などを決めておかないと運用で担当ごとに重複や亜種が生まれて確実に死んでしまいます。
コンポーネントの修正や追加を行う場合は是非を含めてチームでのレビューが必須になります。

### CSS フレームワーク導入をディレクター、デザイナーが認識している

フレームワークの仕様・制限の前提をある程度理解しないと、ディレクターやデザイナーからそれらを無視したワイヤーフレームやデザインが成果物としてが上がってきて、その内容の差し戻しなどの手間が発生してしまいます。
UI 設計が始まる前のキックオフミーティンなどで、事前にフレームワークの導入とメリット・制限を説明しておく必要があります。


## まとめ

### CSS フレームワーク向きの案件とは

- とにかく工数圧縮、工期短縮が第一命題のプロジェクト
- デザイナーがアサインできないプロジェクト
- マークアップエンジニアがいないプロジェクト（CSS とか極力触らずに済ませたい人向け）

CSS フレームワークは UI 設計や HTML/CSS を他力にすることでショートカットするための仕組みなので、フルスクラッチなデザインが必須だったり、大幅に HTML/CSS を弄る必要がある案件は逆に制作の足枷になるケースが多いです。
逆にカラーパターンの調整など、最低限の変更で済ませてフレームワークの仕様に要件を寄せられる案件の場合は圧倒的コストパフォーマンスを発揮します。

### CSS フレームワーク導入時に気をつけること

CSS フレームワークを導入するのであれば以下の点を考慮すると比較的案件が平和になります。

- CSSフレームワークで規定されている以上のことはしない
- ディレクター、デザイナーにフレームワーク仕様と画面設計の制限を認識・共有する
- 仕様に合わせてカスタムするのではなく、極力 CSS フレームワークの制約に沿って UI 設計・デザインを行う（そういった意味ではフロントエンド側である程度イニチアシブを取れないと色々とつらい）
- カスタムする場合はカスタム部分におけるレギュレーションを明確にして品質を維持する

カスタム部分はフレームワークとは別系管理して切り離しておくことをオススメします。
俯瞰したときにどこまでがフレームワークで、どこからがカスタムなのかが、ファイル単位やレギュレーションレベルで明確にしておくと、理解しやすくなり管理効率も上がります。
別系管理にすることでフレームワークのカスタム汚染を予防してオリジナルの状態を保持でき、不具合発生時の影響範囲の切り分けもやり易くなります。
平均偏差を最小化するのは平均値ではなく中央値

次の平均偏差$\mu$を最小化する$m$の条件を調べます。
計算は初等的な物理数学レベルです。
$$
\mu=\frac{1}{n}\sum_i\big|x_i-m\big|
$$
##方針
方法としては
$$\frac{\partial \mu}{\partial m}=0$$
となる$m$の条件を探索することになります。
その前に下記の準備をしておきます。
##ヘヴィサイドステップ
絶対値が入ると表現するのに使えます。定義は実数$x$に対しヘヴィサイドステップは

```math
\begin{align}
H(x)=
\quad &0 \qquad \text{if} \quad x\leq 0 \\
&1 \qquad \text{if} \quad 0\leq x
\end{align}
```
で定義されます。これを使うと例えば
$$|x|=xH(x)-xH(-x)$$
のように書き換えられます。
##ディラックのデルタ
デルタ関数は

```math
\begin{align}
\delta(x)=
\quad &\infty \qquad \text{if} \quad x=0 \\
&0 \qquad \text{other} \quad x \neq 0
\end{align}
```
のように振る舞います（定義ではない）。
知られた性質として
$$
x\delta(x)=0,\quad \frac{H(x)}{dx}=\delta(x)
$$
があります（今回の計算で使います）。

##計算に戻る
定数$n$を含めて、$n\frac{d\mu}{m}$を計算しましょう。すると、
$$n\frac{d\mu}{dm}
=\sum_i \bigg(
H(m-x_i)-H(x_i-m)
\bigg)
$$
となります。右辺は
（$m-x_i\geq 0$をみたす$x_i$の個数）から（$x_i-m\geq 0$をみたす$x_i$の個数）をひいたものとなります。これが0になるには、それぞれの個数が等しくなること、すなわち$m$が$x_i$の中央値であれば良いことがわかります。■
##これは何の話かというと……
例えば[ここ]
(http://tsujimotter.hatenablog.com/entry/2013/11/17/201051)でやってる計算について、有限個バージョンを作ったようなものです。

##蛇足
今更iPadOSのパブリックベータが出ていたことを思い出し、導入したところ大変軽快だったため、動作環境テストを兼ねてこの記事を書いています。内容はgoodnoteに残っていたメモからそれらしいネタを抜き出してそのまま記事にしてしまいました……
![B0392506-29B0-44C9-A43B-0DD967C2B41E.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64610/4af9bdd9-180a-ff4e-fd62-81929bfc96ac.png)
（iPadのスクショ、上記計算で端折った部分はここの手計算部分で確認できます）
ChromeでCSSが反映されないときの対処

GoogleChromeを使ってwebデザインを行っていると、何回リロードしてもcssが反映されない経験あるのではないでしょうか？
今回は、その際の対処法について記事にしたいと思います。

#原因
まず、cssが反映されなくなる原因は「キャッシュ」にありまあす。
キャッシュにより過去のcssのデータが保存され上手く反映されなくなるため、別のパソコンで開いたり別の人が閲覧すると問題ないこともあります。

#対処方法

###cssがおかしくなっていない時
####➀キャッシュを無効にする機能
開発コンソールを開いている間は、常にキャッシュを無効にする機能がついています。F12を押し、 コンソール画面のnetworkを開きます。その後、Disablecashに☑を付けることでキャッシュを常に無効かできます。


####➁更新するたびに「?」以降の文字列を変化させる
例えばCSSを読み込ませる際のURL（ファイル名）は、以下のように「?」＋「更新日時」の法則で文字列を加えて記述しておきます。

```css

<link type="text/css" rel="stylesheet" href="styles.css?20130420-1100">
```
このCSSを更新したときには、「?」以降の日時の部分を書き換えます。

```css

<link type="text/css" rel="stylesheet" href="styles.css?20130420-1112">
```
このように、更新する度に書き換えれば、キャッシュを読まれる心配はありません。

####➂リロードをshift+F5でおこなう
リロードする際にShift+F5で行うとキャッシュを削除してから最新のcssで反映してくれます。

###cssがおかしくなっている時
この場合は、ブラウザ右上の・が縦に3つ並んでいるところを押し、設定を開きます。
その後、設定画面の一番下の詳細設定を開き閲覧履歴の削除を選択します。
そこで、キャッシュされた画像とファイルを選択し溜まったキャッシュを消すことができます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454254/ddf4738e-e221-be38-d031-0af3cbafd54e.png)

また、デベロッパーツールをF12で開いた状態でリロードマークを右クリックし、「キャッシュの削除とハードの再読み込み」をおすことでも最新のcssを反映させられます。
パーセントエンコーディングをデコードする

# パーセントエンコーディングをデコードする

Python 2 ではサラッとできるのに、Python 3 だと微妙に面倒くささ.

## Python 2 版

```python
>>> s = '%82%A0%82%A2%82%A4%82%A6%82%A8'
>>> import re
>>> pattern = re.compile('%(..)')
>>> t = pattern.sub(lambda m: chr(int(m.group(1), 16)), s)
>>> print t.decode('cp932')
あいうえお
```

## Python 3 版

```python
>>> s = b'%82%A0%82%A2%82%A4%82%A6%82%A8'
>>> import re
>>> pattern = re.compile(b'%(..)')
>>> t = pattern.sub(lambda m: bytes([int(m.group(1), 16)]), s)
>>> print(t.decode('cp932'))
あいうえお
```
Line Things + テルミンでFlappy UFO

# 皆さんはテルミンご存知でしょうか？

手を空中でフワフワ動かすとひゅわ〜んひゅよ〜んと、
人の声のような不思議な音を出す楽器です。
[**こうゆうやつ**](https://youtu.be/VJekCP4I5XY?t=13)ですね。

どうでしょうか？
この音、あるイメージを想起させないでしょうか？なんかこう、ぼーっと夜空を見てて、飛行機だと思ってた光が、ジグザグに飛行しだして…
そうUFOですね。
しかも、この音懐かしさをおびてますよね（Youtubeの映像が古いってのもありますが、、）。人型というよりは、タコ足の宇宙人が乗っていそうです。

UFOとテルミンで何かできないかなーということで、
ちょっとレトロみを感じるFlappy BirdならぬFlappy UFOをLIFFに仕込んで、距離センサをコントローラーにUFOを動かすゲームを作ってみました。

# 構成

<img width="1440" alt="スクリーンショット 2019-07-24 23.20.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415401/b376e443-20a2-58ea-5dea-eee0a63459fc.png">

**デバイス側**

- 距離センサで取得した値をBluetooth経由でLIFFへ送信

**LIFF側**

- 距離をhlzに変換してTone.jsでエフェクトをかけてテルミン風の音をだす
- 距離に合わせてcanvas内のUFOを上下に動かして障害物を避ける

# 実装

[**Liff側**](https://github.com/karukade/liff-theremin/blob/0e721d4cc4f99160a7e47bc4ab58afc418097537/liff/liff.js)
※[line-things-starter](https://github.com/line/line-things-starter/blob/master/liff-app/liff.js)にcanvasの実装をのせた形になっています。

[**デバイス側**](https://github.com/karukade/liff-theremin/blob/0e721d4cc4f99160a7e47bc4ab58afc418097537/theremin.ino)
※こちらも[line-things-starter](https://github.com/line/line-things-starter/blob/master/esp32/arduino/sample/sample.ino)のesp32のサンプルをベースに距離センサの実装を加えています。




# デモ

[![デモ動画サムネイル](http://img.youtube.com/vi/Jh6S_EkHvcM/0.jpg)](https://youtu.be/Jh6S_EkHvcM)

# 一応できたが、、
Bluetoothでリアルタイムでデバイスと通信できるというメリットはいかせたものの、
ゲーム自体は面白くないですね。。
ということで、もう一捻り加えた[ご褒美もらえるバージョン](https://qiita.com/karu/items/b9416d589b6e9e341011)も作ってみました。
OAuth2.0の認可サーバーを理解する〜動作理解編〜

# はじめに
これから何回かに分けてOAuth2.0の認可サーバに対する理解を深めるためのまとめを行います。
まとめの目的は、OAuth2.0の認可サーバー（authorization server）を作ることです。

OAuth2.0についてはこれまで何人もの先人達がまとめてるかと思いますが、RFCを参考にしながら自分流にまとめていきたいと思います。

# 動作理解編の目的
OAuth2.0の認可サーバーはどのような仕事をしているのか言葉ベースでまとめていきたいと思います。
OAuth2.0内で使用する実際のパラメータ名を使用した詳細な動作はフロー編で行なっていきたいと思います。

# そもそもOAuth2.0とは？
OAuth2.0のプロバイダについてまとめる前に、まずはOAuth2.0について簡単にまとめます。
OAuth2.0とはRFC6749で定義されるHTTPプロトコル上で使用する認可フレームワークです。
以下、RFC6749のAbstractの引用

> The OAuth 2.0 authorization framework enables a third-party
> application to obtain limited access to an HTTP service, either on
> behalf of a resource owner by orchestrating an approval interaction
> between the resource owner and the HTTP service, or by allowing the
> third-party application to obtain access on its own behalf.  This
> specification replaces and obsoletes the OAuth 1.0 protocol described
> in RFC 5849.

つまりは、あるアプリケーション内で別サービス内の情報を利用する際に、公開するリソースとそれに対する操作（閲覧・作成・更新・削除など）を双方（**あるアプリケーション**と**別サービス**）が共有するための仕組みです。
例：**私**の**Githubアカウント**の**リポジトリ閲覧権限**を、**あなたが作成するアプリケーション**内で使用させてあげる。

# OAuth2.0の登場人物
OAuth2.0に登場する要素は以下のとおりです。
わかりやすいように上の例と照らし合わせて書いていきます。

|登場する要素|例との照らし合わせ|
|---|---|
|リソースオーナー|私|
|クライアント|あなたが作成するアプリケーション|
|認可サーバー|GitHubの認証・認可機能|
|リソースサーバー|GitHubのAPIサーバー機能|

わかり辛いのは**クライアント**には様々なパターンがあることです。

* Webブラウザベースのアプリケーション
* Webアプリケーションのアプリケーションサーバ
* クライアントにインストールするアプリケーション（PC、スマートフォンアプリ）
* etc...

と、ここまでOAuth2.0に登場する要素まで説明しましたが、
今回は作成したい**OAuth2.0の認可サーバー**に特化してまとめていきたいと思います。

# OAuth2.0の認可サーバーとは？
OAuth2.0の認可サーバーとは、リソースオーナーの本人認証と、リソースに対するアクセス許可（認可）を行い、**リソースオーナー**と**許可したアクセス情報**を一意に特定することができる**アクセストークン**をクライアントに発行するサーバです。 
ここで発行されたアクセストークンをリソースサーバへのリクエスト時に合わせて送出することで、リソースサーバ側でアクセストークンの検証を行い、リクエストが正規のものかを判別することができます。

以下、RFC6749内のauthorization serverを引用

> The server issuing access tokens to the client after successfully
> authenticating the resource owner and obtaining authorization.

# 世の中の認可サーバー
大手のサービスではOAuth2.0の認可サーバーがたくさん稼働しています。
だいたいはOpenID ConnectというOAuth2.0上で実装されるユーザ認証の仕組みに使用されていることが多いですが、それについては後で別でまとめようと思います。

#### よく見るOAuth2.0認可サーバー
* Google
* Microsoft
* GitHub
* Twitter
* etc...

# 認可サーバーの仕事

認可サーバーには以下の仕事があります。
プログラムとして実装する際は、以下の１レコードがそれぞれユースケースになるイメージです。

|アクション|アクセス者|詳細|
|---|---|----|
|ユーザー認証|リソースオーナー|リソースオーナーに対して、認可サーバー上でのユーザー認証。基本的にはログイン画面を表示して認証させることが多い。RFCの中では認証方法については範囲外としている。|
|リソース認可|リソースオーナー|リソースオーナーに対して、リソースサーバー上のリソースへの認可を行うためのインターフェースの提供。|
|アクセストークンの発行|クライアント|クライアントアプリケーションに対してアクセストークンの発行を行う。|
|リフレッシュトークンの発行|クライアント|クライアントアプリケーションに対してリフレッシュトークンの発行を行う。|
|アクセストークンの無効化|リソースオーナー|流出したアクセストークンを即座に無効化するためのユーザーインターフェースを提供する。|
|リフレッシュトークンの無効化|リソースオーナー|流出したリフレッシュトークンを即座に無効化するためのユーザーインターフェースを提供する。|
|アクセストークンの検証|リソースサーバー|クライアントアプリケーションから送られたアクセストークンを検証する。|

# 動作理解編のまとめ
今回はOAuth2.0の認可サーバーを作成するにあたって、どのような動作をしているのか理解するのに重きを置きました。

# 次回：フロー編
RFC6749にて定義されているフローについて、認可サーバーから見た時に具体的にどのようなパラメータに対してどのような処理をするのかを書こうと思います。

#### 今後の予定
* 動作理解編 <- 今回ここ
* フロー編 <- 次ここ
* セキュリティ編
* 設計編
* 実装編

# おまけ：OAuth2.0の認可サーバー実装

自分だけのOAuth2.0認可サーバーを構築したい場合は以下のOSSを使うと楽ちんです。
自分で作るのは理解を深めるため（もとい自己満足）がとても強いです。

* Keycloak
* OpenAM
redux-sagaを利用して良かったこと

## 前書き

今携わってる案件で初めて `redux-saga` を使ってみたんですが
思いのほか良かったので前回に引き続き記事化しました。

redux-sagaという言葉は良く聞くけど、結局どう良かったの？と言う部分が伝われば良いかと思います。

## redux-sagaの利点
redux-sagaは react redux環境での非同期処理をサポートするライブラリの一つです。
テストのしやすさ、アクションをピュアに保つと言った利点があります。

ただ、Noobな私は説明を読んでもあまりピンときませんでした。
なので私の言葉でredux-sagaを使って良かった点を挙げていければと思います。

##### 今回redux-sagaを利用して良いと思った点
- 非同期通信処理をAction部分から切り分けられた
- 非同期通信処理をする際、リクエスト用の値をStoreから簡単に取得できた
- 非同期通信処理の連打回避やローディング処理を簡単に実装できた

せっかくなので、ひとつひとつ見ていきましょう

## 非同期通信処理の切り分け

いままで僕はredux-thunkを使っていましたが
redux-thunkを使うとき、actionCreatorに非同期通信処理を書いていました。

ただ、非同期通信部分って処理が増えがちですよね。
例えば

- リクエスト用に渡す引数の準備
- ローディングの開始処理
- APIコール
- レスポンスの受け取り
- レスポンスをフロント側で使いやすいような形にする変換処理
- ローディングの終了処理
- 失敗時の処理

などなど

非同期通信が少なければまだ良いですが、通信処理が複数になると大変です。
actionCreatorは急速に肥大化し、そこに手を入れる度に微妙な心持ちになるわけです。
非同期通信と同期通信の記述が入り混じり、カオス状態です。

ではredux-sagaを使うとどうなるでしょうか。
今回のファイル構成を軽く見てみましょう。

```
store
  - modules
	  - user
		  - actions.ts
		  - actionCreators.ts
		  - state.ts
		  - index.ts
		  - sagas.ts
		  - reducer.ts
	  - hoge
	  - huga
  index.ts
components
containers
misc
```

userストアの中にsagasが確認できますね。
いままでationCreatorsに書いていた非同期通信は全てこの中に書いています。

結果としてactionCreators及びactionsは非同期通信処理から逃れることができ、とてもスリムになりました。

設計次第ではありますが、これでファットなactionCreatorに会うことはほぼ無くなるでしょう。

sagasもある程度肥大化しますが役割が切り分けられてるので精神的に楽です。
「あああー、あの雑多なactionCreatoreとactionsを触らなきゃいけないのかー」
と思うことが無くなったのは素直に嬉しかったです。

## Storeからの情報取得が簡単

次にこれです。
皆さんmapDispatchToPropsの中でStoreの情報を利用したい時どうしているでしょうか。

- mapStateToPropsで渡してバケツリレー
- mergeProps
- redux-thunkのgetState

などの方法があると思います。

バケツリレーは健全な感じがするんですが
コードを見る時Propsを追って2,3ファイル移動したりすると分かりにくいですよね。
なによりmapDispatchToPropsで利用したい時など、mapStateToPropsからコンポーネント越しに値を渡すのは微妙な感じがします。

mergePropsもコンポーネントで操作があった際、storeの中身が最新状態になっているかどうか気になりますし、propsに渡す物が雑多に放り込まれる感覚がするため個人的に好きではありません。

そこでsagasのselectメソッドが活躍します。
sagasを利用した非同期通信部分限定となりますが
selectメソッドを利用すれば簡単にStoreを取ってくることが可能です。

```
  const { token } = yield select((state: RootState) => state.config)
```

上の例のようにconfigストアに格納したtoken情報を利用する時も簡単です。
RootStateを取ってこれるので複数のStoreから情報を取りたい時もお手の物です。

このメソッドは本当に助かった。。。

## 非同期通信処理の連打回避やローディング処理実装

ここに関しては前回書いたtakeLatest部分なのでこちらお読みください。
非常に簡単に連続したAPIコール回避やローディング処理を実装できました。
記事[こちら](https://qiita.com/EndouT6/items/b09dc59826f063cd7817)です。

## redux-sagaを使ってみて

去年hooks が普及してから redux が無くなっていくと言われていましたが
react redux typescript redux-saga を使った開発をすると
1つのアプリケーションの開発環境として魅力的に思えました。

1年後同じことを言ってるかわからないですが
非同期通信がそれなりにある案件がきたら
また、redux-sagaを利用した環境でやりたいと思っています。

お読みいただきありがとうございました。
TwitterOAuthなど内部的にcurlを使っているライブラリで突然 SSL connect errorが出たとき

2019年7月30日のアップデートでTwitterにhttpsで接続する際にTLS1.2未満では接続できなくなりました。

その影響で、内部的に curlを使っているライブラリでTwitterに接続しようとするとコケます。
具体的にはライブラリ内部で ```SSL connect error``` が発生します。

## 原因
CentOS6.xなどでcurlのバージョンが古い場合に発生します。

```
# cat /etc/redhat-release
CentOS release 6.6 (Final)
```

コマンドラインでもエラーを確認できます。

```
# curl https://twitter.com
SSL connect error
```

## 対処方法
curlが内部的に利用しているNSSをアップデートすることで対応できました。

```
# yum update nss
```

## 結果
```
# curl https://twitter.com
→ HTMLが返ってくる
```
Array.prototype.reduce() 便利

Array.prototype.reduce()便利

たとえば下記の外部APIから配列を受け取る
https://picsum.photos/v2/list?page=1&limit=10

```json
[
  {
    "id": "0",
    "author": "Alejandro Escamilla",
    "width": 5616,
    "height": 3744,
    "url": "https://unsplash.com/photos/yC-Yzbqy7PY",
    "download_url": "https://picsum.photos/id/0/5616/3744"
  },
  /* 中略 */
  {
    "id": "1005",
    "author": "Matthew Wiebe",
    "width": 5760,
    "height": 3840,
    "url": "https://unsplash.com/photos/tBtuxtLvAZs",
    "download_url": "https://picsum.photos/id/1005/5760/3840"
  }
]
```

この配列を下記のような配列に整形したい

```json
[
  {
    id: "0",
    maxWidth: 5616,
    maxHeight: 3744,
    src: "https://unsplash.com/photos/yC-Yzbqy7PY",
  },
  {
    id: "1005",
    maxWidth: 5760,
    maxHeight: 3840,
    src: "https://unsplash.com/photos/tBtuxtLvAZs",
  }
]
```

### Array.prototype.reduce() 便利

```js
const rt = array.reduce((acc,cur,idx)=>{
	const { id, width, height, url } = cur;
	acc[idx] = {
		id,
		maxWidth: width,
		maxHeight: height,
		src: url,
    }

    return acc;
},[])

/// console.log(rt)
[
  {
    "id": "0",
    "maxWidth": 5616,
    "maxHeight": 3744,
    "src": "https://unsplash.com/photos/yC-Yzbqy7PY"
  },
  /* 中略 */
  {
    "id": "1005",
    "maxWidth": 5760,
    "maxHeight": 3840,
    "src": "https://unsplash.com/photos/tBtuxtLvAZs"
  }
]
```

最高、、、

参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
GASでスラックにメッセージを送信する

練習用です
スプレッドシートのC列にimportXMLでスクレイピングしたものを
joinで一つの文字列に格納して、
slackにメッセージを送信する。

```javascript
function myFunction() {
  var POST_URL = '***'; // slack_APPから得る送信用URL
  var USER_NAME = 'patagonia_bot';  // 通知時に表示されるユーザー名
  var ICON = ':hatching_chick:';  // 通知時に表示されるアイコン

  // ▼以下、スプレッドシート用の記述
  // 現在アクティブなスプレッドシート全体の情報を取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // 現在アクティブなシートの情報を取得
  var sheet = spreadsheet.getActiveSheet();
  // 最終行を取得する
  var lastRow = sheet.getLastRow()
  // データ取得範囲をC列に設定、getValuesでデータの配列を取得する
  var range = sheet.getRange(2,3,lastRow-1).getValues();
  // ’,’で配列の値をつなげてメッセージとする
  var message = range.join(',');
  
  // ▼以下、slack送信用の記述
  // 送信用データを json 形式にで整形する
  var jsonData =
  {
     "username" : USER_NAME,
     "icon_emoji": ICON,
     "text" : message
  };  
  // JavaScript の値を JSON 文字列に変換
  var payload = JSON.stringify(jsonData);
  // 送信方法などオプションの設定
  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };
  
  // 送信
  UrlFetchApp.fetch(POST_URL, options);
}
```
WSL2でDockerが動かない

## 問題
WSL上で

```
$ sudo docker run hello-world
```

と打つと、

```
docker: Cannot connect to the Docker daemon at tcp://localhost:2375. Is the docker daemon running?.
See 'docker run --help'.
```

と返されてしまう。

### 情報など
- Windows10 **Pro** Insider Preview 1903 (Build 18945.1001)
- `cat /etc/os-release` -> `Ubuntu 18.04.2 LTS`

## 解決策(原因)
Docker for Windowsを以前使っていて、`Expose daemon on tcp://localhost:2375 without TLS`というオプションにチェックを入れてしまっていたためです。
また、bashもしくはzshなどのrcに記述されているであろう`export DOCKER_HOST='tcp://0.0.0.0:2375'`という記述を消さないと、永遠にそのポートが指定されるので気をつけましょう。
Wordのクイックパーツを使ったＶＢＡコード

#WordのクイックパーツとContentControl
OfficeのWordでクイックパーツを入力した場合、そのパーツをVBA上でContentControlとして扱うことが出来る。実際に書いてみる。
##発行日とタイトルのクイックパーツを用いたファイル保存マクロの作成
###このマクロでやりたいこと

クイックパーツの「タイトル」「発行日」を使っているWord文書に対して以下の処理を行う。

 - 発行日を現在の日付に更新(yyyy/mm/dd)
 - タイトルを取得し、ファイル名を「yyyymmdd_タイトル」として保存するダイアログを開く。

```visualbasic:Wordマクロ_Normal標準モジュール

Public Sub UpdateDate()

    Dim title As String
  
    Dim control As ContentControl

    '繰り返し処理でContentControlのtitleがクイックパーツ名と一致するか調べる。
    '一致した場合、該当したクイックパーツを使って処理を行う。
    For Each control In ActiveDocument.ContentControls
     
    Select Case control.title
    
        Case "発行日"
    
        control.Range.Text = Format(Date, "yyyy/mm/dd")'発行日のクイックパーツの日付を更新
        
        Case "タイトル"
        
        title = control.Range.Text
    
    End Select
    
    Next

    With Application.FileDialog(msoFileDialogSaveAs)'ダイアログの呼び出し

        .InitialFileName = Format(Date, "yyyymmdd") & "_" & title 'ファイル名の設定

        If .Show = False Then
            Exit Sub  'キャンセル
        Else
            .Execute  '保存
        End If

    End With

End Sub

```
#応用可能性について
クイックパークを使っていない場合でも、（組織などで）テンプレートで文書を作っている場合は、その形式からファイル名、日付の位置を選択して同じような処理が出来ると考えられる。
BIG-IP VEの評価版ライセンスを入手し適用する

# はじめに
BIG-IP VEの評価版が必要になったのは人生二度目。
約3年前はSR-IOV方面、今回はIPSec VPN方面。
今回はAzure上で利用するがAzureに限らずKVM、ESXi、AWSなどでも利用できると思われる。

入手方法が変わっていた　＋　ややこしくなったので備忘録も兼ねて。

補足：
 ややこしくなったというのは、
- 「BIG-IP VE 評価版」で検索して出てくる[ここ](https://f5.com/jp/products/trials/big-ip-evaluation-request/popup/true?sbtitle=BIG-IP+Evaluation+Trial+Request&utm_source=f5com&utm_medium=web&utm_campaign=htb-trial-page)に必要事項を入手して送信ボタンを押下してもエラー画面が出るだけで評価ライセンスが入手ができない
- F5の[ログインページ](https://login.f5.com/resource/login.jsp)から辿れる[ここ](https://strongbox.f5.com/strongbox/index.jsp)だと評価ライセンスの入手の仕方がよくわからない
という感じで落とし穴がある。

# 評価版ライセンスを入手する
F5の[ログインページ](https://login.f5.com/resource/login.jsp)でアカウントを作成した後、そのアカウントでログインする。
上記のログインセッションが残っている状態で[ここ](https://www.f5.com/ja_jp/trials)にアクセスして「ログイン」ボタンを押下する。
以下の項目を選択する。

- 検証の目的
- 仕事上の役割について
- 評価対象
    - 「BIG-IP VE and BIG-IQ」  ※今回はこのライセンスを選択
- ライセンス数

登録したメールアドレス宛に評価版ライセンスが届く。

# 評価版ライセンスを適用する
入手したライセンスの適用方法については例えばAzureの場合だとマーケットプレイスの

- F5 BIG-IP Virtual Edition (BYOL) 
    - F5 BIG-IP VE-ALL(BYOL, 1 Boot Location)
 
のイメージを元に作成されたインスタンスに適用できる。

ライセンスのアクチベーションについては[ここ](https://www.infraeye.com/study/bigip2.html)を参考にすること。

1vNIC構成の場合においてWebGUIのhttpsポートは443ではなく8443であるためWebGUIにパブリックIPで直接アクセスする場合はAzureのセキュリティグループの設定変更などが必要になる。

KVMやESXiの場合は、
F5の[ログインページ](https://login.f5.com/resource/login.jsp)でログインし[ダウンロードページ](https://downloads.f5.com/esd/productlines.jsp)で以下のようにリンクを辿ってイメージを入手する。

- BIG-IP v15.x / Virtual Edition with Traffic Management Operating System® (TMOS®) 
    - Virtual-Edition
        - BIGIP-15.0.0-0.0.39.ALL-vmware.ova  ※ESXi
        - BIGIP-15.0.0-0.0.39.ALL.qcow2.zip ※KVM
        - BIGIP-15.0.0-0.0.39.ALL.vhd.zip ※Hyper-V

AWSについてはマーケットプレイスに該当するAMIが存在すると思われるが執筆時点では未確認。
XCode10.3にXVim2をロードした

XCodeにVimのプラグイン（[XVim2](https://github.com/XVimProject/XVim2#branches-and-releases)）を入れようとしたのですが，Eclipseと違ってややこしかったです．

# 想定する読者

XCodeに初めてXVim2を入れようとしている方．

# 環境

- macOS Mojave 10.14.6
- Xcode 10.3

※ XCode 8 かそれ以前のバージョンの方は[XVim](https://github.com/XVimProject/XVim)を使用してください．

# 手順

## 1. XCodeのコード署名を作成する

Githubの公式ページは[こちら](https://github.com/XVimProject/XVim2/blob/master/SIGNING_Xcode.md)です．

1. XCodeを終了する．
2. キーチェーンアクセスのアプリを起動する．
3. メニューバーの「キーチェーンアクセス」>「証明書アシスタント」>「証明書を作成...」を選択．
4. 証明書を作成する．

    4-1. 「名前:」にわかりやすい名前を設定（例: XCodeSigner）．
    4-2. 「固有名のタイプ:」に"自己署名ルート"を選択．
    4-3. 「証明書のタイプ:」に"コード署名"を選択．
    4-4. 右下の「作成」を押す．
5. ターミナルを開いて以下のコマンドを実行する．

```bash
$ sudo codesign -f -s <証明書の名前> <XCodeのパス>
// 例
$ sudo codesign -f -s XcodeSigner /Applications/Xcode.app
```

## 2. XVim2をビルドする

リポジトリをクローンします．

```bash
$ git clone https://github.com/XVimProject/XVim2.git
```

xcode-select でデベロッパディレクトリを指定します．

```bash
// 確認したいだけなら -p
$ xcode-select -s
/Applications/Xcode.app/Contents/Developer
```

正しいタグにチェックアウトします．
インストールされているXCodeのバージョンに合わせます．

```bash
$ git checkout xcode10.3
```

ビルドします．

```bash
$ cd XVim2
$ make
```

## 3. XCodeを起動する

1. 起動済みであれば，完全に終了させて再度起動します．
2. ポップアップが出るので，「Load bundle」を選択します．

メニューバー >「Edit」>「XVim」が表示されれば完了です！

# 参考
[Xcode10.2 で XVimを使う方法](https://qiita.com/KazukiTanaka/items/3b45f1304effe3f25bf3)
Cannot find installed version of python-django or python3-django

#はじめに
Djangoをインストールしてプロジェクトを立ち上げようとしたらつまづいたのでメモします。
※初心者なので、鵜呑みにしないでください。

#プロジェクトを立ち上げる方針
１．python3がインストールされていることを確認
２．Ubuntuにインストールされているパッケージリストをアップデート
３．Pythonのパッケージ管理システムpipをインストール
４．Djangoのインストール
５．フォルダに移動しプロジェクトを立ち上げる

#実行
Python3がインストールされていることを確認

```
$ poython3 --version
Python 3.6.8
```
Ubuntuにインストールされているパッケージマネージャーをアップデート
（最新のものを使うとセキュリティ上いいらしい？）

```
$ sudo apt-get update
```
Djangoをインストールする前にパッケージ管理マネージャーpipをインストール

```
$ sudo apt-get install python3-pip
```
pipを使ってDjangoをインストール

```
$ pip3 install django
```

Djangoがインストールされていることを確認

```
$ python3 -m django --version
2.2.3
```

バージョンが表示されたので、インストールされてた模様…

フォルダを移動し、プロジェクトを立ち上げる

```
$ cd {folder_name}
$ django-admin startproject helloproject
Cannot find installed version of python-django or python3-django
```
このようになりプロジェクトを立ち上げることができなかった。

#解決方法
パッケージからのグローバルインストールを行った(自分でも何をしたか分からない)

```
$ sudo apt-get update
$ sudo apt-get install python-django
```
この後にプロジェクトを立ち上げるとうまくいった。

```
$ django-admin startproject helloproject
```

参考サイト
https://askubuntu.com/questions/643417/message-cannot-find-installed-version-of-python-django-or-python3-django?rq=1

#考察
Djangoをインストールした時に管理者権限で行わなかったことが原因か？
$ pip3 install django ・・・×
↓
$ sudo pip3 install django　・・・〇？


#環境
Windows 10 Home
2019/7/31

ささいな事でもアドバイス頂けると喜びます＾＾
【JavaScript】Blobの中身をJSONに変換する

JavaScriptでBlobの中身をJSONに変換したいことがあったため、方法のメモです。

以下のようなヘルパー関数を作ります。

```/utils/fileReader.js
/**
 * 非同期にBlobをテキストとして読み込みます。
 */
export default blob => {
  const fileReader = new FileReader();

  return new Promise((resolve, reject) => {
    fileReader.onerror = () => {
      fileReader.abort();
      reject();
    };

    fileReader.onload = () => {
      resolve(fileReader.result);
    };

    fileReader.readAsText(blob);
  });
};
```

##使用例
```javascript
import fileReader from "/utils/fileReader";

const blobToJson = async blob => {
    const blobText = await fileReader(blob);
    return JSON.parse(blobText);
};
```
CentOS7上にDockerでMySQL8、Nginxを動かしてRailsを起動するためにしたこと

## deploy用ユーザーの作成

```
# adduser hoge_user
# passwd hoge_user
```

visudoでrootになれるよう設定

## localeの設定

```
# localectl set-locale LANG=ja_JP.utf8
一度ログアウトしてログイン
# locale
LANG=ja_JP.UTF8
```

## ssh設定

rootでのsshはできなくする。
sshのportは2222に変更。

```
# vim /etc/ssh/sshd_config
PermitRootLogin -> no
Port -> 2222
# sshd -t
# sudo service sshd restart
```

## firewalldの設定

httpとsshだけ解放。
sshはportを2222に変更する。

```
# cp -p /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/
portを2222に変更
# firewall-cmd --add-service=http --zone=public --permanent
# firewall-cmd --add-service=ssh --zone=public --permanent
# firewall-cmd --reload
success
```
※さくらVPSの場合混乱するので管理画面から操作できるパケットフィルタをOFFにする。

## Docker

https://docs.docker.com/install/linux/docker-ce/centos/ の手順に従い作業

&

```
$ sudo systemctl enable docker # 自動起動設定
$ sudo systemctl start docker
```


## docker-compose
https://docs.docker.com/compose/install/ の手順に従い作業

## デプロイユーザーがdocker-composeを使えるように

```
# usermod -aG docker hoge_user
hoge_userは一回ログアウトしてログインしなおす。
```

## rbenvでrubyインストール

```
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

ruby-buildインストール
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

$ sudo yum install -y openssl-devel readline-devel zlib-devel
$ rbenv install 2.5.1
$ rbenv global 2.5.1
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
```

## yarnインストール

```
$ curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
$ sudo rpm --import https://dl.yarnpkg.com/rpm/pubkey.gpg
$ sudo yum install yarn
$ yarn install
```

## Webサーバー,DB起動

```
$ docker-compose up --build
```

### docker-compose.yml

```yml
version: '3'
services:
  mysql:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-db:/var/lib/mysql
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD
  nginx:
    build: ./nginx
    ports:
      - "$HOST_HTTP_PORT:80"
    volumes:
      - ../../my_app:/apps/my_app
      - ../log/nginx:/var/log/nginx
      - ../public:/usr/share/nginx/html
volumes:
  mysql-db:
    driver: local
```
Ruby と Rust でアベソートを実装してみた


スターリンソートというソーティングアルゴリズムをさまざまな言語で実装することが流行っているらしい。

* [\[Rust\] スターリンソートと PartialOrd - Qiita](https://qiita.com/osanshouo/items/1d4f56d93ee8ac8bdf55)
* [rubyでスターリンソートをやってみた（ブロック渡しも可能） - Qiita](https://qiita.com/haru_pad/items/1598690e1105f3e33389)
* [計算量O(n)の画期的なソートアルゴリズムであるスターリンソートをHaskell で実装してみた #Haskell - Qiita](https://qiita.com/Tatsuki-I/items/380d6bd06515b872b2b2)
* [計算量O(n)で噂のスターリンソートを実装してみた - Qiita](https://qiita.com/MeilCli/items/721526d716851e92192a)
* [話題の粛清ソートアルゴリズム「スターリンソート」をPythonで実装した - Qiita](https://qiita.com/Sirloin/items/c9e5c74be3366df65bce)

こんなソーティング方法もあるのかと目からうろこだった。

それならば，あまり知られていないアベソートを Ruby と Rust で実装してみよう，と思ったのがこの記事。

# アベソートとは

計算機科学でいうソートとは，言うまでもなく，何らかの観点で大小比較が可能な要素の列が与えられたとき，その大小比較に従って昇順（または降順）に並んだ要素の列を返すことである。

ソーティングアルゴリズムの速さは，要素の数 $n$ に対して計算量がどのように増えるか，という指標で比べられる。
例えば $n$ が十分大きいとき計算量が $n^2$ に比例するなら $O(n^2)$ と書き，「$n^2$ のオーダーだ」などと言う。

アベソートはスターリンソートと同じく $O(n)$ である。これを「線形時間で実行できる」と表現する。ソーティングとしては（特殊なものを除き）最も速い部類である。

アベソートは $O(n)$ のアルゴリズムの中でも，（同じ要素数で比較して）実行時間の短いことで知られている。

そのうえ，原理が極めて単純で理解しやすく，コードが簡潔に書けるため，新しく学んだ言語で Hello, World! の次に挑戦する課題として適している。

# Ruby による実装

シンプルなので，とくに説明は要るまい。

```rb
module Enumerable
  def abe_sort
    max = first
    map{ |v| (v > max) ? (max = v) : max }
  end
end

ary = [2, 6, 4, 5, 7, 10, 13, 12]
p ary, ary.abe_sort
```

# Rust による実装

Rust は完全に素人なので，何か気づいた点があれば教えてほしい。

```rb
fn abe_sort<T: PartialOrd + Copy>(vec: &Vec<T>) -> Vec<T> {
    let mut max = vec[0];
    vec.into_iter()
        .map(|v| {
            if v > &max {
                max = *v;
                *v
            } else {
                max
            }
        })
        .collect()
}

fn main() {
    let ary = vec![2, 6, 4, 5, 7, 10, 13, 12];
    println!("{:?}", ary);
    println!("{:?}", abe_sort(&ary));
}
```

# 名称の由来

アベソートの名称の由来は諸説あってはっきりしない。
しかし，いずれも，政治権力の強引な行使が行われた故事にちなむようだ。
コードを見て分かるとおり，アベソートは，要素が昇順に並んでいない場合に，要素を並べ替えるのではなく，昇順になるよう要素自身を操作する，という考え方に基づいている。そこで，権力者が自らの主張に沿うよう事実をねじ曲げた政治史上の出来事にちなんで名付けられたというのだ。

一説では，ある言葉の意味について宰相が議会で誤った内容の発言をし，のちに内閣がその発言を正当化する内容の閣議決定を行った珍事による，とする。
別の説では，打ち出した経済政策の効果が経済統計上，思わしく出ていないために，統計の手法自体を変更して上向きを演出した事件による，とする[^to]。
アベソートの挙動から言えば後者の説に説得力があるようだが，どうだろう。

[^to]: 国内総生産の算出方法の変更は国際基準に合わせたため，と説明されていたが，実際にはさまざまな変更が同時に行われており，しかも細目が公表されていないため，どのような操作が行われたのか今もって解明されていないという。


いずれにせよアベが何を指しているのかは定かでない。日本人の人名のようだが，アベと発音する姓を持つ政治権力者は奈良時代から現代に至るまで少なくはない（漢字表記もさまざま）。また，米国（あるいは英国）の政治家，<ruby>Abraham<rt>エイブラハム</rt></ruby> の愛称である <ruby>Abe<rt>エイブ</rt></ruby> にちなむ Abe sort を日本人が誤ってアベソートと読んだものが広がった，という説もある。ドイツ人名 Abbe にちなむという説もあるが根拠に乏しいようだ。

参考文献を示したかったが，どうも民明書房の本で読んだような気がする，という程度しか思い出せない。
reveal.jsで他のスライドへのリンクを張るのに苦労した

## きっかけ
社外にデモするにあたってパワポじゃないスライドを作りたくなったので調べてみたら、reveal.jsというOSSがよさそうだったので使ってみた。
試しに使ってみて、すごくよかったのでスライドを作り始めたけど、スライドからスライドへのリンクを張るやり方がよくわからず苦戦した。
備忘を兼ねてメモを残しておく。

## そもそもreveal.jsって
reveal.jsについてはいろんな解説記事があるので割愛。
興味がある方は先人の方の記事をご参照ください。
https://qiita.com/t-kusakabe/items/725e7438892bba395062

## 結論
大した内容でもないので結論だけ。
demoに書いてある内容を見落としていただけだった。
下記で他のスライドへのリンクが張れる。
(横2スライド目の、縦3スライド目みたいな指定になる)

```
<a href="#/2/3">like this</a>
```

## 感想
たったこれだけのことなのに数時間を費やしてしまった。
ずっと組み込み畑でやってきたので、HTMLとかCSS、JavaScriptをあまり触らなかった。
いざ触ってみると勘が働かない。
いろいろ触ってみるのは大事だなと思いました。
jupyter-labでRuby

# はじめに

多分何番煎じどころじゃない

## 環境

ubuntu 18.04 LTS

### 依存関係のあるライブラリを入れる
[ここを参考](https://github.com/SciRuby/iruby)に

```console
$ sudo apt install libtool libffi-dev ruby ruby-dev make
$ sudo apt install libzmq3-dev libczmq-dev
$ gem install cztop
$ gem install iruby --pre
$ iruby register --force
```

## 余談

variable inspectorが使えるととても便利だけどRuby版とかないんですかね
Qiitaトレンド「毎朝15分勉強会」の機会を先輩に提供していただきました

#お伝えすること
Qiitaのトレンド「[毎朝15分の勉強会で若手の行動が驚くほど改善した話](https://qiita.com/kojimadev/items/cd5dd5332e33b3ef46a6)」
をもとに先輩社員さんが
「[Qiitaでバズった「毎朝15分の勉強会」を実際にやってみた！](https://qiita.com/k_yoshikawa/items/66dfc5de2c0e3346e382)」を提供してくれました。
(記事が**バズっていた**ので波に乗って筆を執ることにしました。)

#私のプロフィール
- 平成生まれ令和元年入社(19卒)の新卒。
- 大学ではソフトウェア情報学を専攻(eラーニングの研究をしていました)。
- とあるWebサービスの企業に入社しサーバサイドエンジニアの道を歩み始めました。
- プライベートでは個人ブログ「[Hollect](https://hollect.net/)」を運営。
- 新米ミニマリストでもあります。
- **Qiitaはこの記事が初投稿です。**

#勉強会実施のきっかけ
前提として、4月~6月末まで新卒研修を行い7月からチームに配属。
そこでチームのとある先輩がOJTとしてサポートをしてくれることに。

先輩の手厚いサポートは配属初日から始まり、様々な書籍を用意してくださいました。
技術書はもちろん、社会人としての素養、etc...

そのタイミングで
「[毎朝15分の勉強会で若手の行動が驚くほど改善した話](https://qiita.com/kojimadev/items/cd5dd5332e33b3ef46a6)」の記事を見つけた先輩。

「**せっかく本を読むならこの記事みたいにアウトプットもしていこう**」
というニュアンスの会話から勉強会が始まりました。

#勉強会の概要
こちらの[記事](https://qiita.com/k_yoshikawa/items/66dfc5de2c0e3346e382)にまとめられているので興味がある方はぜひ。

ざっくり言うと
**読んだ本についての自分なりのアウトプットを1日おきに行う** というもの。

今回の読んだ本は「**リーダブルコード**」です。
エンジニアのバイブル的存在。

実業務に入り、レガシーなソースコードと触れ合う初期段階に
読んでおきたいという思いからです。

#ルールの満足度が高い
勉強会を進めるにあたって先輩に設定していただいたルールがとても良かったです。

- **先輩も同じ本を読む**
    - 私の一方的なアウトプットではなく、相互のコミュニケーションにつながる。
- **1日おきのアウトプット**
    - 本を読み、アウトプットをまとめる作業時間としてはとても適切。
- **先輩からの業務知識の説明**
    - 新卒にとっては一般的な知識以上に社内の情報や業務知識は貴重かつ必須。

こういったルール設定のおかげで受動的ではなく**能動的な学習環境**になったと感じています。

#新卒なりに感じたこと
現在進行形で実施中の「毎朝15分勉強会」

本を読むことで得られる知識や
アウトプットに必要なスキルを身につける機会としてはもちろん効果的です。

そしてそれ以上に先輩社員との**コミュニケーション**やお互いを知るきっかけに。
朝の15分を使うことでその日の業務の**モチベーションや気持ちの切り替え**にもつながります。

リーダブルコードを読むことで新人エンジニアが知っておくべき
コーディング・リファクタリング等の知識も効率良く身につけられる環境にもなりました

特にデメリットは感じませんでした。

#おわりに
- 今回の勉強会の実施のきっかけとなった@kojimadevさんとその[記事](https://qiita.com/kojimadev/items/cd5dd5332e33b3ef46a6)
- それを元に実際の現場に最適化して実施していただいた@k_yoshikawaさんとその[記事](https://qiita.com/k_yoshikawa/items/66dfc5de2c0e3346e382)

には非常に感謝しています。

**新卒目線で感じることは今だけ**であり、今後キャリアを積むことで自分がこういった機会を提供する上で非常に**重要な感覚である**ことは間違いないので良い経験となっています。

導入ハードルは低いので気になった方は取り組んでみることをオススメします。
競プロ参戦記 #57 Digits Parade | ABC 135

ABC-only 回です。D 完でした。E は何も分かりませんでした……

## AtCoder Beginner Contest 135

- この連載記事では、着手した問題の考察を自分なりに書いていきます。
    - 前回: [競プロ参戦記 #56 Sequence Decomposing | ABC 134](https://qiita.com/vain0x/items/351703ec8de97b41c78c)
- 問題の詳細は問題一覧を参照してください。
    - 問題一覧: https://atcoder.jp/contests/abc135/tasks

## A - Harmony

問題概要: 整数 A, B (ただし A≠B) が与えられる。|A-K| = |B-K| となる整数 K が存在するか判定し、存在するなら求めよ。

### A: 考察

絶対値 |A-K| は数直線上の AK 間の距離なので、条件は「AK 間と BK 間の距離が等しい」と読めます。つまり K は A と B の中央である (A+B)/2 です。整数にならないケースに注意しましょう。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/abc135/submissions/6567400

## B - 0 or 1 Swap

問題概要: (1, 2, .., N) を並び替えた数列 P が与えられる。1回だけ、2つの要素を交換してもよい。P を昇順にできるか判定せよ。

### B: 考察

実際に交換してみて、昇順になったか確認すればいいです。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/abc135/submissions/6566602

## C - City Savers

問題概要: N+1 個の街があり、N 人の勇者がいる。i 番目の街が A(i) 体のモンスターに襲われている。i 番目の勇者は i, i+1 番目の街を襲っているモンスターを、合計で B(i) 体まで倒せる。勇者たちが倒せるモンスターの数の合計の最大値を求めよ。

### C: 考察

1番目の街のモンスターを倒せるのは1番目の勇者だけなので、1番目の勇者は可能なかぎり1番目の街のモンスターを倒すのがよいです。その後、1番目の勇者は2番目の街のモンスターしか倒せないので、それを可能な限り倒します。

このとき、1番目の勇者が倒せるモンスターはすべて倒したので、2番目の街の残りのモンスターを倒せるのは2番目の勇者だけです。始めと同じ状況になったので、繰り返しで処理すればOKです。

筆者の回答 (Rust, AC): https://atcoder.jp/contests/abc135/submissions/6564259

## D - Digits Parade

問題概要: 数字と '?' からなる長さ N の文字列 S が与えられる。'?' を数字に置き換えて得られる整数のうち、13で割った余りが5に等しいものの個数を求めよ。(mod 10^9+7) (0 で始まる文字列もカウントする。)

### D: 考察

もし「13で割って5余る」ではなく「3で割って0余る」(3の倍数)だったら、よくある桁DPです。「3の倍数は各桁の数字の和も3の倍数」という性質を使って解けるからです。

AtCoder ではコンテスト中のインターネット検索が認められているので、13 の倍数の似たような判定法がないか調べてみました。[1001が13の倍数であることを利用する倍数判定法があるそうです](https://kikyousan.com/mathtalk/hmath/713proof)。

整数の10進展開に3桁ごとにカンマを入れて数列とみなし、交互に足し引きして13の倍数になるか確認する、という方法です。例えば 314158 は -314 +158 = -156 ≡ 0 (mod 13) なので13の倍数です。

数式で書けば $\sum_{i=0}^k 10^{3i} x_i \equiv \sum_{i=0}^k (-1)^i x_i \pmod{13}$ です。$1000 \equiv -1 \pmod{13}$ (☆) を使うと、数学的帰納法により証明できます。(無証明貪欲を反省しつつ。)

k = 0 のケースは自明なので k > 0 とします。

```math
\begin{align}
\sum_{i=0}^k 10^{3i} x_i
  & \equiv 1000 \sum_{i=0}^{k-1} 10^{3i} x_{i+1} + x_0 & \qquad (シグマをずらした) \\
  & \equiv 1000 \sum_{i=0}^{k-1} (-1)^i x_{i+1} + x_0 & \qquad (帰納法の仮定を使った) \\
  & \equiv -\sum_{i=0}^{k-1} (-1)^i x_{i+1} + x_0 & \qquad ((☆) を使った) \\
  & \equiv \sum_{i=0}^k (-1)^i x_i & \qquad (シグマをずらした) \\
  \pmod{13}
\end{align}
```

というわけで、桁DPで解けます。実装は3の倍数を数える桁DPと同様で、「各桁」の代わりに「各3桁」、「各桁の和」に符号がつく、というだけです。

計算量を考えます。最悪のケース `???..???` では3桁ごとに 1000 ステップで遷移するので、全体としては 10^5/3 * 10^3 で 10^8 ステップくらいです。1ケース TLE しましたが、剰余をとる頻度を下げるという最適化をしてなんとか AC。

```rust
    // 抜粋 (遷移部分のみ)

    for d1 in lb(S[bi * 3])..ub(S[bi * 3]) { // 3i 桁目の数字
        let a = d1 * 100;
        for d2 in lb(S[bi * 3 + 1])..ub(S[bi * 3 + 1]) { // 3i+1桁目
            let b = a + d2 * 10;
            for d3 in lb(S[bi * 3 + 2])..ub(S[bi * 3 + 2]) { // 3i+2桁目
                let y = b + d3;
                let z = (13 + y - x) % 13; // (☆) を使う
                dp[bi + 1][z] += dp[bi][x];
                // ここで余りを取ると遅い
                // 10^3×10^9 は溢れないので余りを取らなくてOK
            }
        }
    }

    for z in 0..13 {
        dp[bi + 1][z] %= P; // まとめて余りを取る
    }
```

筆者の回答 (Rust, AC): https://atcoder.jp/contests/abc135/submissions/6575515

解説PDFの解法 (DP) の方が賢いですね。
M5Stack Lora Module(センサー付き）の製作(RAK811,Si7020,LIS3DH,DPS310)

M5StackのLoraモジュールを製作しました。
1年近く前から企画していたもので、実装したけど、動かせていなかったものになります。
なぜか？
Serialがつながらなかったからです・・・
ESP-32のシリアルは、ファーム書き換えのUART0とつながっているとファーム書き換えができません。
この罠にはまり、全く動かない状態が長く続きました。
さらに、UART0のコマンドが違ったり・・・
もう踏んだり蹴ったりです・・・

ということで、完成です・・・
「RAK811 V3.0.0.x firmware でThe Things Networkにつなげるよ」もこのボードで行ったものです。
https://qiita.com/usashirou/items/836826a96e3b5acce4b6

![M5stack-lora-board-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/1df72f38-4338-78c3-9cec-d3cee552b9db.jpeg)

写真に2枚写っているのは、検証用にLoraとセンサーを1枚ずつ実装したためです。

加速度、温湿度、気圧センサーを搭載しています。
センサー3種類は
Lis3DH:0x19
Si7020:0x40
DPS310:0x77
![M5stack-lora-board-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/2a20bd63-4537-81d0-e95e-9a1668fcf86d.jpeg)

フルセットだと4000円を超えてしまうので、売りたくありませんが(外装もつくらないといけないし）
これで、国内Loraを使えるM5stackを用意出来るようになりました。
ComposerでDotenv values containing spaces must be surrounded by quotes.となったときの対応方法

- 環境
    - Windows10 64bit
    - Composer version 1.6.5

# 事象 : composerを動かしたら怒られた

```bash
$ composer install
Loading composer repositories with package information
# 省略
In Loader.php line 228:

  Dotenv values containing spaces must be surrounded by quotes.


Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1
```

# 原因 : `.env`の設定値でダブルクォーテーションに囲まれていないスペースがあるから
[エラー `Dotenv values containing spaces must be surrounded by quotes.` が出た時 - あじちゃんのブログ。備忘録。](http://azix.hatenablog.com/entry/2019/05/22/%E3%82%A8%E3%83%A9%E3%83%BC_%60Dotenv_values_containing_spaces_must_be_surrounded_by_quotes.%60_%E3%81%8C%E5%87%BA%E3%81%9F%E6%99%82)

## 対応方法 : 見つけてダブルクォーテーションで囲む
[grep | 正規表現を利用したテキストのパターン抽出](https://bi.biopapyrus.jp/os/linux/grep.html)

```bash
$ cd {.envのあるディレクトリ}
# コメント以外の行でスペースを含む行を見つける
$ grep -v '^#' .env | grep ' '
# .envを開いてダブルクォーテーションで囲む
$ vi .env
```
AmplifyでAuthしてみるときに詰まったこと

# 概要
基本的には [このサイト](https://www.aruse.net/entry/2019/03/24/175444) を参考にさせていただいてほとんど完結しました。
しかし、詰まるところもあったので、その部分について書きます。

# 詰まったこと
aws-amplify-reactが読み込めない

エラー発生箇所

```js
import { Authenticator } from 'aws-amplify-react'
```

発生したエラー

```
Could not find a declaration file for module 'aws-amplify-react'. '<path>' implicitly has an 'any' type.
  Try `npm install @types/aws-amplify-react` if it exists or add a new declaration (.d.ts) file containing `declare module 'aws-amplify-react';`ts(7016)
```

参考にさせていただいたサイトでも同様のエラーが出たことが報告されていて、その解決法が書かれていたのですが、その解決法では解決しませんでした。

そこで、ググりました。
この [GitHubのページ](https://github.com/aws-amplify/amplify-js/issues/305) によると
aws-amplify-reactの型が定義されていないために起こるエラーであるそうです。

.d.tsファイルに```declare module 'aws-amplify-react'```を追加するとエラーが消えました。

ググってから気づきましたが、解決方法がエラーメッセージに出てましたね。
エラーメッセージをちゃんと読まずにGoogle検索しがちなのは良くない癖ですね。

# まとめ
このエラーは型が定義されていないときに起こるエラーであり、型の定義が見つからない時は、エラーメッセージに出てる通り```npm install @type/hoge```で型の定義を追加できればそれでよく、できない場合は今回のように自分で追加すれば解決できるようです。
WSLでapt installができない

あるときからWSL(Windows Subsystem for Linux)のUbuntu18.04上でsudo apt update,upgradeやinstallをしようとするとエラーが出るようになった。(できるアプリとできないアプリがある)
`環境はwindows10 Pro, Ubuntu-18.04(WSL)`
今回は、scalaをインストールしようとしたときエラーが起きてインストールできなかった。
原因を調べてもあまり事例がないのか、わからなかったので一時的な解決策を載せる。

結論を先に述べると、セキュリティソフトのせいであった。使っているセキュリティソフトはbitDefender製のスーパーセキュリティ。
いろいろ調べて試したがどれも効果がなかったので、スーパーセキュリティをアンインストールしたら、無事scalaをインストール出来た。


BitDefenderは少し前もWSLでブルースクリーン問題を起こしていたので、個人的に評価は高くない。だが、永年無料が財布にやさしくなかなか変えられない（また、それが原因だったわけだが）

おそらくファイアウォールあたりが悪さをしているようだが、異常を通知してくれないのでよくわからない。

カスペルスキーやスーパーセキュリティ等bitdefenderのセキュリティソフトを使っている方は、**「とりあえずセキュリティソフトを疑え」**と言っておく。
~~そろそろノートンあたりに変えたい。おすすめがあったら教えてください（もちろんbitdefender以外で）~~
Redmineのカテゴリをバージョン同様にサブプロジェクトで継承利用する


Redmineの下記課題の対応策を公開しました。必要な方はご利用ください。
Share Issues Categories for sub-projects
http://www.redmine.org/issues/5358

本件については下記でも解説しています。
https://www.slideshare.net/y503unavailable/ss-189711783
https://redmine.tokyo/issues/241

# 課題
Redmineには、カテゴリというチケットを分類する機能がある。
このカテゴリ機能は、プロジェクト単位に項目を設定できるが、サブプロジェクト単位で継承できない。(3.4,4.0現在）
すなわち、親子プロジェクト間で、同じカテゴリを選択できない。そのため、サブプロジェクトを利用している場合、結果的にカテゴリ機能を有効活用できないのが現状である。
サブプロジェクトで同じ名前のカテゴリを作成しても、親プロジェクトのカテゴリ定義とは別物（別ID）として取り扱われる。
結果的にカスタムクエリで同一に利用できない。

カテゴリと類似したバージョン機能では、サブプロジェクト単位に継承して利用できる。
http://blog.redmine.jp/articles/redmine-0_9-version-inheritance/

### 課題の具体例

システムの利用部署単位、および全体で案件管理したい場合、利用部署のサブプロジェクトを作成し、カテゴリで案件を分類するのが自然。
利用部署毎/全体のカテゴリ単位集計も容易に行える。
しかし、カテゴリのサブプロジェクト継承が行えないため、現状では上記運用が行えない。

# 対策

Redmine3.4 ,及び trunkに対して、Redmineのコードを修正し、バージョンと同様にカテゴリもサブプロジェクトで継承利用可能とした。
必要な方はご利用ください。

3.4ベース対応版（本件以外の変更含）
https://github.com/y503unavailable/redmine/tree/3.4-unofficialcooking

trunk対応版(4.1候補に本修正のみ実施）
https://github.com/y503unavailable/redmine/tree/feature-category-trunk20190629

選択画面サンプル
https://twitter.com/y503Unavailable/status/1005658604681158656
# 参考

本件は、Redmine本家に非常に多くの要望が出ている。（現在２位）
2.6までのパッチは公開されていたが、3.X以降が無かったので対応した。
多数の要望が出ており、Redmine本家に取り込まれるべき機能と考える。
賛成の方は、Redmine本家5358に +1 記入し意思表示してください。

Share Issues Categories for sub-projects
http://www.redmine.org/issues/5358 

Redmine.org incomplete tickets vote count list(over 5 cases 2018/12/15)
http://www.redmine.org/boards/1/topics/56452

（日本語の説明は↓参照）
カテゴリをサブプロジェクトで継承利用したい（バージョン同様）
https://redmine.tokyo/issues/241

### 補足

カテゴリではなく、カスタムフィールド（リスト）の選択項目に登録する方法もある。しかし、選択項目の編集はadminのみ可能なため、adminの負荷増大 または admin権限IDの乱発を招き兼ねない問題がある。
Python＋Windowsタスクスケジューラで暑さ指数をLINE通知

こんばんは、@0yanです。
先日、実家に暮らしている妹から**「お母さんが『うちは風通し良くて涼しいからエアコンつけなくて大丈夫』とか言ってエアコンつけないんだけど！熱中症になっちゃうよ！何とか言って！！」**とヘルプ連絡が来たため、環境省の暑さ指数（WBGT）を家族のグループLINEに定期通知するようにしました。

# 前提条件
Windowsのタスクスケジューラ使っていますので自宅でPC起動しっ放しです（知識不足でHerokuやAWSにデプロイできていません）。
申し訳ございませんが、予めご承知おきくださいませ。

# 流れ
1.LINE Notifyからアクセストークンget
2.コーディング
3.LINE Notifyをトークルームに招待
4.batファイル作成＆タスクスケジューラの設定

# LINE Notifyからアクセストークンget
①[LINE Notify](https://notify-bot.line.me/ja/)にログイン後、右上の自分の名前をクリックし、マイページに飛びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373977/acfa93af-7e5d-9eba-6763-743dfb9c7011.png)

②次ページ下部の「トークンを発行する」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373977/cecd4636-408a-d3f7-88c2-19c3a50367ad.png)

③トークン名の記入、通知するトークルームを選択（ご自身向けの場合は「1:1でLINE Notifyから通知を受け取る」を選択）して「発行する」ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373977/1442ff85-a2f6-3bfa-d612-76d1c5aa123f.png)

④発行されたトークンをコピー、メモしておきます。ページ遷移するとトークンは二度と表示されないそうなのでご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373977/6c5fb7ae-02b1-c50f-35f4-44d4765f5d6a.png)

# コーディング
BeautifulSoupで環境省の熱中症予防情報サイトから暑さ指数の情報を取得、LINE Notifyのエンドポイントにポストしております。
詳しくはコメントをご参照くださいませ。

```wbgt.py
# coding:utf-8

import bs4
import urllib
import requests


def main():

    # LINEの通知系API（POST）のエンドポイント（アクセストークンに関連付けられたユーザまたはグループに通知を送信）
    END_POINT_URL = "https://notify-api.line.me/api/notify"

    # LINE Notifyのアクセストークン
    TOKEN = "LINE Notifyのページで発行・コピーしたトークンをここにペースト"

    # リクエストヘッダ（付与してアクセスすることで認証できる）
    header = {
        "Content-Type": "application/x-www-form-urlencoded",
        "Authorization": "Bearer " + TOKEN
    }

    try:

        # 環境省 熱中症予防情報サイト（スマホ版）のページ情報取得
        WBGT_URL = "定期通知したい市区町村のページURLをコピペ"
        html = urllib.request.urlopen(WBGT_URL).read()

        # BeautifulSoupオブジェクトの生成
        soup = bs4.BeautifulSoup(html, 'html5lib')

        # spanタグすべて取得
        spans = soup.find_all('span')

        # メッセージの初期化
        message = ""

        # spanタグの中身（テキスト）を取得し、改行で区切ったうえでメッセージに追加
        for span in spans:
            message += span.text
            message += '\n'

        # メッセージの最後にURLも追加
        message += "→ 変数「WBGT_URL」と同じ文字列をコピペ"

        # リクエストパラメータ（通知オフでないとき、ユーザーに通知する）
        parameter = {
            "message": message,
            "notificationDisabled": False
        }

        # エンドポイントにPOST
        requests.post(END_POINT_URL, headers=header, params=parameter)

    # 例外処理
    except Exception as ex:
        print(ex)


if __name__ == '__main__':
    main()

```

# LINE Notifyをトークルームに招待
トークルームにLINE Notifyを招待しないと通知飛ばないので招待します。

# batファイル作成＆タスクスケジューラの設定
こちら（↓）をご覧ください。
>[【備忘録】WindowsでPythonファイルを自動実行する](https://qiita.com/0yan/items/79a95bb9c9153851bd79)

# さいごに
関東も昨日梅雨明けしたので、これからが夏本番です。
皆様も是非、ご活用くださいませ！