OmniAICreator/Qiita-1.07M huggingface dataset:
Powershellとcygwinでデータ連携するときは文字コード変換必須ですか？

Windowsでもsedやgrep,awkなどUNIX由来のツールが手放せず、もうずっとcygwinを使っています。
WindowsでPowerShellのスクリプトを使うようになって、困ったことが文字コードです。
当面の結論としては、PowerShellとcygwinでデータをやりとりするときはiconvやnkfなどでの文字コード変換必須です。
その時に使うのは、Shift-JISかUTF-16で。

####2021/01/13追記
コメントいただきました、ありがとうございます。
バージョンを明記するのは大事ですね。そうでした。
Windows10標準のものは 5.1ですが、最新は7なのですね。

以下は実験。

まず、お話の前提、バージョンです。OSバンドルのものです。

```
PS C:\> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.18362.1171
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.18362.1171
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

PS C:\> uname -a
CYGWIN_NT-10.0 MyPC4 3.1.7(0.340/5/3) 2020-08-22 17:48 x86_64 Cygwin
```

時刻を表示させるスクリプトで試して見ます。

```python:print_now.py
from datetime import datetime
print(datetime.now())
```

これをコマンドプロンプト、powershell、cygwin(mintty)でそれぞれ実行して、ファイルへリダイレクトします。すると

```
T:\>c:\work\date_now.py > now_cmd.txt
```

```
PS T:\> C:\work\date_now.py > now_ps.txt
```

```
$ python c:\\work\\date_now.py > now_cygwin.txt
```

```
$ file now*
now_cmd.txt:    ASCII text, with CRLF line terminators
now_cygwin.txt: ASCII text, with CRLF line terminators
now_ps.txt:     Little-endian UTF-16 Unicode text, with CRLF line terminators
```

PowerShellでは、リダイレクトするとUTF-16へ変換保存してくれるようです。
サイズを見てもたしかに

```
PS T:\> dir now*
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2021/01/10     11:47             28 now_cmd.txt
-a----       2021/01/10     11:55             28 now_cygwin.txt
-a----       2021/01/10     11:46             58 now_ps.txt
```

ちなみに、標準出力に出力しつつファイル保存してくれるコマンドを使っても、

```
PS T:\> C:\work\date_now.py |tee now_ps_tee.txt
2021-01-10 12:09:09.078514
PS T:\> file now*
now_cmd.txt:    ASCII text, with CRLF line terminators
now_cygwin.txt: ASCII text, with CRLF line terminators
now_ps.txt:     Little-endian UTF-16 Unicode text, with CRLF line terminators
now_ps_tee.txt: Little-endian UTF-16 Unicode text, with CRLF line terminators
```

パイプを通した時点でUTF-16に変換されるようです。
cygwinで処理したデータをPowerShellへ渡すときはShift-JISがよさげです

時代の流れに従って、cygwinでもUTF-8が使えますので、デフォルトをUTF-8にしています。
ところが、Windows10でPowerShellを使ってみるとUTF-8は特殊設定が必要なようです。
ポーティングやリプレースを考えると、デフォルトからの設定変更は少ない方が良いです。

#まとめ
PowerShellからCygwin(bash)を呼び出したときは、ja_JP.SJISにする。
そのために、~/.bashrc末尾に以下を追記

```~/.bashrc
# PowerShellから呼び出し時だけShift-JISにする
if [ $PPID -eq 1 ]
then
        export LANG=ja_JP.SJIS
fi
```
[Excel VBA]要注意なExcel VBAコード

[本記事は、自分サイトのこの記事と同一内容です。](https://hagiayato.github.io/my-site/jekyll/update/2021/01/10/ExcelVBA.html)

Excel VBAはマクロの書き方に自由度があり、簡単にマクロを実装できます。
それゆえに実装を間違えると、意図しない動作のマクロややけに遅いマクロになってしまいます…
ここで紹介するのはその一例と対処法です。

# 1.画面更新有効のままマクロ実行

Application.ScreenUpdatingをFalseにすることで、マクロ実行中の画面更新を無効にできます。

```vb
'画面更新無効化
Application.ScreenUpdating = False
'ここに処理を入れる

'画面更新有効化
Application.ScreenUpdating = True
```

もしこれがないと、マクロを1処理実行する度にExcelの画面表示が更新されます。
そのため、

 - 画面が見ずらくなる
 - マクロを実行する処理が遅くなる

ということが発生します。
逆に処理の最後でApplication.ScreenUpdatingをTrueに戻し忘れることにも注意。

# 2.いきなりセル指定、いきなりシート指定

"Test.xlsm"というファイル(ブック)のVBAで"Sheet1"で起動するプマクロで以下の機能を実装します。

 - "Test.xlsm"の"Sheet1"A1セルの文字を"テスト"にする

これを一番簡単に書くと、以下の短い一文になります。

```vb
'"Test.xlsm"の"Sheet1"A1セルの文字を"テスト"にする
Range("A1").Value = "テスト"
```

シート1枚、開くブックが1つなら問題ないのですが、
シートが2枚、開くブックが2つ以上になると厄介なことになります。
このマクロを"Sheet1"以外のシート、もしくは"Test.xlsm"以外のブックを表示中に実行すると…
表示中のブックの、表示中のシートのA1セルの文字が"テスト"になります。
そして、"Test.xlsm"の"Sheet1"A1セルの文字は"テスト"になりません。
### 対策
対策としては、ブック、ワークの指定を追加することをおすすめします。

 - ThisWorkBook…このマクロが書かれているブックを指定
 - Sheets("Sheet1")…"Sheet1"を指定

```vb
'"Test.xlsm"の"Sheet1"A1セルの文字を"テスト"にする
ThisWorkBook.Sheets("Sheet1").Range("A1").Value = "テスト"
'もしも他のブックから指定する場合
Workbooks("Test.xlsm").Sheets("Sheet1").Range("A1").Value = "テスト"
```

# 3.Select,Selection,ActiveCell
Excelでマクロを記録すると出てくるのがSelect,Selection,ActiveCell。

```vb
Sub Macro1()
    Range("A1").Select
    ActiveCell.FormulaR1C1 = "テスト"
    Range("A1").Select
    With Selection.Font
        .Color = -16776961
        .TintAndShade = 0
    End With
End Sub
```

このコードを編集したりデバッグしたりしなければいいのですが、もしするとなると要注意です。
3つの文それぞれの意味は

 - Select…セルを選択
 - Selection…選択中のセル
 - ActiveCell…現在カーソルがあるセル

です。コードを編集したりデバッグしたりして、SelectをしてからSelection、ActiveCellを使用すると
意図しないセルに処理がされます。
### 対策
対策としては、Select,Selection,ActiveCellを使わないことをおすすめします。

```vb
Sub Macro1()
    Range("A1").FormulaR1C1 = "テスト"
    With Range("A1").Font
        .Color = -16776961
        .TintAndShade = 0
    End With
End Sub
```

上記のようにSelection、ActiveCellをRange("A1")に置き換えることで、意図しない処理を回避できます。
ついでに、2章で取り上げたブック、シート指定を加えるとこうなります。

```vb
Sub Macro1()
    Dim range As range
    Set range = ThisWorkbook.Sheets("Sheet1").range("A1")
    range.FormulaR1C1 = "TEST"
    With range.Font
        .Color = -16776961
        .TintAndShade = 0
    End With
End Sub
```
少しコードが長くなりますが、意図しない動作はこれで回避できます。

# おわりに
Excel VBAは要注意な部分がありますが、そこさえ気を付ければExcelでの作業を効率よく実行できます。
「これをマクロで自動化すれば時間をかけずに作業ができる!」
ということがあれば使ってみるのはいかがでしょうか。
[フォームオブジェクト]1つのフォームをPOSTでもPATCH(PUT)でも使えるようにする方法

1つのフォームを複数のHTTPメソッドで使い分ける方法です。
フォームオブジェクトで実装すると難しかったのでメモ。

他にもっと良い方法がある場合は遠慮なく教えていただけると嬉しいです:innocent:

# こんな方にオススメ
・フォームオブジェクトでフォームを実装している方。
・フォームで情報を送信する際に、新規作成と編集で同じフォームを使いたい方。

# やることは２つだけ
(1) フォームを呼び出す側(render)に method: :〇〇を追加。(〇〇はpostやpatchなど)
(2) フォーム側に method: methodを追加。

###(1) フォームを呼び出す側

```ruby:example.html.erb
<%= render "フォームテンプレートのパス", url: 呼び出したいアクションのpath, method: :〇〇 %>
```
新規作成の場合は〇〇をpostに、編集の場合はpatch(put)にすればOKです。

###(2) フォーム側

```ruby:_example_form.html.erb
<%= form_with model: モデルのインスタンス, url: url, method: method do |f| %>
```
普通はここでurlやmethodを直接指定すると思うのですが、あえて変数にしています。
そうすることで、新規作成でも編集でも使えるようにしています。

# 背景
renderでPATCHのパス(url)を定義したはずなのに、実際にはPOSTで送信されていることがありました。原因は下記の記事にあるように、フォームのmodel: に記述したインスタンスが既存であればPATCH, 既存でなければPOSTとなるからだと思われます。フォームオブジェクトを使うとフォーム送信のたびにインスタンスを生成するので、常にPOSTとなり期待した動きをしてくれません。そこで、methodも定義してこの問題を回避しています。


# 参考にした記事はこちら
https://qiita.com/snskOgata/items/44d32a06045e6a52d11c#2-form_with%E3%81%AE%E5%8B%95%E4%BD%9C%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

# 環境
ruby: 2.7.1
rails: 6.0.3.3
【AWS】RDS

＃概要
・フルマネージドなリレーショナルデータベース
　Aurora、MySQL、MariaDB、Oracle、MicrosoftSQL、PostgreSQL
・シンプルかつ迅速にスケール
・高速。安定したパフォーマンス
・低コスト、従量課金

#特徴
・シンプルな構築
　オプション
　　・マルチAZデプロイメント　←高可用性
　　・リードレプリカ　←パフォーマンス確保
　　・バックアップ（スナップショット）　←復旧　
　　　S3上に保存
　　・RDS プロビジョンドIOPS　←パフォーマンス確保
　　・監視（Cloudwatch）
　　・拡張モニタリング
・高い可用性
　マルチAZデプロイメント
　　・同期レプリケーション　＋　自動フェイルオーバー
　　　→アプリ側での対処は必要なし
　　　→スタンバイ状態のDBはアクセス負荷
・パフォーマンスの向上
　リードレプリカ
　　→レプリカDBで読み取り処理をスケールアウト
　　→MySQL、MariaDB、PostgreSQL、Auroraに対応
・スケールアップ
・運用負荷の軽減
　バックアップ
　　→スナップショットとリストア
　
・セキュリティ
各DBインスタンスに対してSSL／TLS証明書を生成する
暗号化された接続が確立されたらDBインスタンスとお客様のアプリケーション間で転送されるデータは、転送中に暗号化されるようになる

#負荷軽減
・DBインスタンスのサイズを増やしてプロビジョンドIOPSを設定
・ElastiCacheを用いることでメモリ内キャッシュにより読み取りがヘビーなアプリケーションの作業負荷（ソーシャルネットワーキング、ゲーム、メディア共有、Q&Aポータル）や莫大な計算処理を必要とする作業負荷における待ち時間やスループットを改善


#マルチAZの障害時の動作
AZ機能はデータベースの更新を異なるAZに配置されたプライマリーとホットスタンバイを同時に行うことで、耐久性と可用性を高める

#メモ
・マルチAZ配置のスタンバイは読み取りトラフィック処理不可
　→リードレプリカ使用により可能
・パフォーマンス向上（トラフィック処理）
　→クロスリージョンレプリカ作成しリードレプリカから読み取りする
　→別のAZにマスターのDBのロードレプリカを作成、リードレプリカから読み取りする
　→ElastiCacheクラスタ作成し、頻繁にアクセスされるデータやクエリをキャッシュから取得する設定
HerokuのRedisをflushallする

# はじめに
HerokuにWordPress入れてブログ書いているものです。
DBに直接接続してデータ一括更新する機会があったのですが、トップページがどうも更新されない... :thinking: 
DBへそもそも取りに行ってないな... :thinking: 
コード追いかけてたら、DBから取得したデータをRedisにキャッシュしてました。

あ、じゃあRedisをflushallすればいいか！

heroku-redis使っているんだが、接続してflushallしたい！

# 作戦
1. heroku-redisに繋ぐ
2. flushallする

## redisに繋ぐ
```shell
$ heroku redis:cli
```

## flushallする
```
$ flushall
```

# おわりに
無事にトップページが更新されて安堵です :smile: 
herokuのredisへの接続ってどうするんだろうと思ったのですが、上記で行けることに少し感動しました。

自分もマシンにredis-cli入ってないけど、このために入れる？
クライアントアプリは入っているけど、このために設定する？

上記をせずにできたのが個人的にはうれしかったです。

参考になりましたら幸いです :pray:
RasPi＋PythonでDHT22を動かす

アマゾンで販売している「DSD TECH DHT22 温湿度センサーモジュール AM2302チップ付き Arduino Raspberry Pi用 DHT11の進化版」というモジュールをラズベリーパイに接続して温度計測を行ってみました。

# モジュールのインストール

MyPyDHTを下のWebに従ってインストールする。

https://github.com/freedom27/MyPyDHT

# Pythonのコード

下の例外が発生していましたが、「use_cache=True」を「MyPyDHT.sensor_read」へ設定することで回避できるようです。

```bash
MyPyDHT.DHTException: A timeout occurred while attempting to read the sensor!
```

Pythonのバージョン：

```bash
$ python3 -V
Python 3.7.3
```

下の例ではGPIO４番にDAT端子を接続して、VCCには５Vを与えています。
また、センサーの監視を１秒毎に行いターミナルへ出力しています。

```python
import time
import RPi.GPIO as GPIO
import MyPyDHT


DHT_PIN = 4 

GPIO.setmode(GPIO.BCM)
GPIO.setup(DHT_PIN, GPIO.OUT)
try:
    while True:
        try:
            humidity, temperature = MyPyDHT.sensor_read(MyPyDHT.Sensor.DHT22, DHT_PIN, use_cache=True)
            if humidity is not None and temperature is not None:
                print(f"temperature={temperature} / humidity={humidity}")
        except MyPyDHT.DHTException as e:
            print(f"err: {str(e)}")
        time.sleep(1)
except KeyboardInterrupt:
        GPIO.cleanup()
        print("finish")
```

# 結果

エアコンを１６度設定にした室内で測定したので、結果は合っているはずです。

```terminal
temperature=16.7 / humidity=44.1
temperature=16.8 / humidity=44.8
temperature=16.8 / humidity=44.8
```
Go言語でCircleCIの環境変数の登録を自動化する

CircleCIで環境変数の登録を自動化するプログラムを書いたので、作成した内容を書いていきます。

# 課題
CircleCIの環境変数の設定の際にブラウザからポチポチして登録していたのですが、単純作業で登録が面倒なのと、誤操作により設定ミスが発生することがありました。

# CircleCIの環境変数について
まず環境変数の設定方法のバリエーションについてです。
大きくは、以下の６つのレベルで環境変数を設定することができます。今回の対象は、Project Environment Variablesの設定に関しての記事になります。
登録方法は、Build > Project > Settings で設定します。（もしこれ以外の登録方法をご存知の方がいらっしゃいましたら教えていただきたいです。）

- Global Environment Variables
- Project Environment Variables
- Job Environment Variables
- Container Environment Variables
- Step Environment Variables
- Bash Environment Variables

https://medium.com/veltra-engineering/circleci-2-0-a0549c65bc3b

# 解決策
今回はGo言語のagoutiというライブラリとChromeDriverを使用して、ブラウザ操作を自動化します。
https://agouti.org/
https://chromedriver.chromium.org/downloads

## 全体の処理のフロー
① CircleCIのGithubログイン認証を行う
https://circleci.com/login/

② 環境変数設定ページに遷移

③ Add Environment Variableをクリックし、入力フォームを開く

④ 入力フォームにNameとValueを入力する。

⑤ 登録完了

## 必要な設定
①ChromeDriverをインストールする。

```
$ brew install chromedriver
```

②constに設定されている各変数に任意の値を入力してください。

- GithubUserName ... あなたのGithubのユーザー名を入力してください。
- GithubPassWord ... あなたのGithubのパスワードをを入力してください。
- Organization ... 個人開発の場合はGithubのユーザー名、組織開発の場合は組織名を入力してください。
- Repository ... 対象のリポジトリ名を入力してください。

```go
const (
   CircleCIURL    = "https://circleci.com/login/"
   GithubUserName = "あなたのGithubのユーザー名"
   GithubPassWord = "あなたのGithubのパスワード"
   Organization   = "組織名"
   Repository     = "リポジトリ名"
)
```

③登録する環境変数の準備
下記のmapでkeyに環境変数名、valueに登録する値を設定してください。

```go
func setVariables(page *agouti.Page) error {
	vars := map[string]string{
		"HOGE": "hoge",
		"PUGE": "puge",
		"FUGA": "fuga",
	}
...
}
```

全体のソースコードはGithubに上げてありますので、下記のURLからご確認ください。
https://github.com/kozy0810/agouti-circleci

## ローカルで実行
上記の設定が完了しましたら、ローカルで下記のコマンドを実行してください。

```shell
$ go run main.go
```

処理が完了すると下記のように環境変数の登録が完了します。
![スクリーンショット 2021-01-10 12.09.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228026/25a4007b-6958-c267-ca7a-53b3a612a249.png)


# まとめ
Go言語でCircleCIの環境変数の登録を自動化する方法について記述しました。
ブラウザでポチポチして登録するより、時間やストレスを大きく削減できるかと思います。
使用する際には、機密情報になると思いますのでセキュリティには十分ご注意ください。
今回初めてQiitaの記事を書いてみました。
もし参考になりましたらLGTMをいただけると嬉しいです。
VPC内にElasticsearchを配置する際の注意点

VPC内のプライベートサブネットにElasticsearchを置いたはいいけど、LambdaからAPI叩けないしKibanaにもアクセスできなくて困ったときのメモです。

# 解決策

- BastionServerとして同VPC内にEC2(パブリックサブネット)を置く
    - EC2にSSH接続してダイナミックフォワードを行う(ダイナミックフォワードあまりわかっていない...)
- Lambdaを同じVPC内に置く
    - 仕様によってプライベートかパブリックかを選択する
- それぞれのリソースに適切なセキュリティグループ（後述）を設定する

# セキュリティグループ設定

## EC2

- アクセス元IPアドレス(ローカルマシン)から`22ポート`へのトラフィック許可

- アクセス元IPアドレス(ローカルマシン)から`8157ポート`へのトラフィック許可

## Lambda

- 今回は特に設定は不要(仕様による)

## Elasticsearch

- Lambdaにアタッチしたセキュリティグループから443ポートへのトラフィック許可

- EC2のプライベートIPアドレスから443ポートへのトラフィック許可

# ハマりポイント

ElasticsearchのアクセスコントロールでEC2のプライベートIPを許可しようとしたが以下のエラーが出ました。

`UpdateElasticsearchDomainConfig: {"message":"You can’t attach an IP-based policy to a domain that has a VPC endpoint. Instead, use a security group to control IP-based access."}`

解決策が見つからず２時間くらいはまりましたが、ちゃんと公式に書いてありました。

>VPCs ではセキュリティグループを通じてドメインへのアクセスを管理できます。多くのユースケースでは、このセキュリティ機能の組み合わせで十分となり、ドメインにオープンなアクセスポリシーを安心して適用できます。

[Amazon Elasticsearch Service ドメインの VPC サポート - Amazon Elasticsearch Service](https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-vpc.html#es-vpc-security)

どうやらセキュリティグループでの制限で十分のようです。<br>

つまりVPC内にElasticsearchを置くケースだとオープンアクセスを選択しておいて、アタッチしているセキュリティグループのみでアクセスの制限を行う形になります。

 

# 参考

https://github.com/awsdocs/amazon-elasticsearch-service-developer-guide/commit/a033da866dff1251a42aa1637b89e7ebcc5fc779#diff-861cbf8ba5a0dc5589e8ef3d5cf74a1e:embed:cite

https://aws.amazon.com/jp/premiumsupport/knowledge-center/kibana-outside-vpc-ssh-elasticsearch/:embed:cite

https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-kibana.html#es-kibana-access:embed:cite
pipenv installするディレクトリを間違えた時

# 概要
`pipenv install`を行うディレクトリを、子ディレクトリで間違えて実行してしまいました。

すると、本来環境構築したかった親デイレクトリで再度実行して`pipenv shell`をしても、
間違えた子ディレクトリに勝手に移動してその環境下で実行されてしまい困ったのでメモです。

# Q. そもそも、どこに仮想環境が作られるのか

A.　答え、初期設定では `~/.local/share/virtualenvs/`の下に仮想環境が作られるそう。

`pipenv install`をしたら、どこに仮想環境がおかれるのかと思って調べてみました。

勝手なイメージは`pipenv install`を実行した配下に設定ファイルがおかれるのだと思っていたら違ったようです。

あくまでも`Pipfile`や`Pipfile.lock`は環境構築の設定内容で、それを使用して構築された環境は別の場所におかれるようです。

# 解決方法

なので、 上記を踏まえて、

1. `~/.local/share/virtualenvs/`に移動

2. `ls`で間違えて構築してしまった仮想環境のディレクトリを確認、`rm -r <dir>`コマンドで丸ごと削除

3. 本来環境構築したかったディレクトリに移動して再度`pipenv install`

# 参考
https://qiita.com/tonluqclml/items/cd0d2a2cb0197cbaee42
https://qiita.com/propella/items/ea29d6a62fdf75f1b421
Bootstrap4ではheaderを固定するnavber-fixed-topが使えない

学習メモ用です。
##解決したい問題

Bootstrap4においてheaderを固定したいが、navber-fixed-topでは適応されなかったので、いかにheaderを固定するか？

##開発環境

Rails　6.0.3
bootstrap　4.5.3
OS macOS Catalina



##bootstrap4からnavber-fixed-topじゃなく、fixed-topだけでいけるとのこと


![スクリーンショット 2021-01-10 10.55.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294460/34c93792-2ccb-e38a-01b0-8c42e52d47ed.png)


見てみるとheaderの下部が詰まっている。

bootstrap公式では

>固定トップ
>端から端まで、ビューポートの上部に要素を配置します。プロジェクト内の固定位置の影響を必ず理解してください。CSSを追加する必要があるかもしれません。

<!---->

とのこと。

bootstrap3を使っているrailsチュートリアルでは下記になっている。
>>body {
>>  padding-top: 60px;
>>}
>ページ上部に60ピクセルの余白を追加します。headerタグにnavbar-fixed-topクラスが与えられているので、これに従ってBootstrapはナビゲーションバーをページ上部に固定し、ナビゲーションバーの下に余白を置いて主要部分から分離します



しかし、うまく適応されない。。。

```app/views/layouts/application.html.erb

     <!DOCTYPE html>
<html>
  <head>
    <title><%=full_title(yield(:title))%></title>

    <%= render 'layouts/head' %>

    <%= render 'layouts/shim' %>
  </head>

  <body>

    <%= render 'layouts/header' %>

    <div class="container-fluid">

      <%= render 'layouts/flash' %>

      <%= yield %>

    </div>

  </body>
</html>
```

このビューも"<%= render 'layouts/flash' %>"がある以外はほとんどrailsチュートリアルと同じ。

やはり、bootstrap4で仕様が変わったと思われ。

```app/views/layouts/_flash.html.erb

<div class="text-center lead", style="padding-top: 100px">
  <% flash.each do |key, value| %>
  <p class="alert alert-<%= key %>">
    <%= value %>
・・・
```

flashのpartialに'padding-top: 100px'を追加してみる。


![スクリーンショット 2021-01-10 11.21.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294460/70620ba5-a0b5-d2f7-9865-8dfc2509ca64.png)


いけた！

以前はflash自体も重なって表示されなかったけど、今回はこの通り！

![スクリーンショット 2021-01-10 11.25.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294460/aa89db5d-9350-a8b8-9387-0f4765bb8bee.png)

##まとめ
Bootstrapを使っていると、要素の関係性がよく分からなくなるからひとつずつ潰していきたいもんです。

##追記

###fixed-topの問題点
- スクロールしたときにheaderが上部に表示されなくなる
- 下記画像のようにheaderが被ってしまう

![スクリーンショット 2021-01-10 15.48.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294460/76670f36-4f84-4089-efd5-fc28bedfbdc5.png)

###sticky-topであれば解決！

リンクを表示するとその分だけ画面が下方に！
スクロールしても常にheaderは上部に！
![スクリーンショット 2021-01-10 15.53.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294460/f5447f25-5862-12a4-3ef6-780efa53deb6.png)
Unity2020 WebGL 9割まで読み込めるがアプリが起動しない不具合の解決方法

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [不具合の内容](#不具合の内容)
1. [解決方法](#解決方法)
1. [参考文献](#参考文献)
1. [その他](#その他)

# 不具合の内容
<!-- 発端や概要を記載 -->
Unity2020のWebGLビルドで作成したアプリを起動しようとしたものの、9割までデータを読み込めるがアプリが起動しない不具合の解決方法です。
Unity -> File -> Build Settings -> Build and Run でアプリを起動できるのですが、GitHub Pagesなどにアップロードした場合に起動しなくなります。

この画面のままで固まってしまう現象です。
![スクリーンショット 2021-01-10 11.30.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/a021e81d-f3ef-6835-63ee-ae0531709d43.png)

Chromeの右上の「︙」ボタン -> その他のツール -> ディベロッパーツールの中にあるConsoleのウィンドウに以下のエラーが表示されていました。

![スクリーンショット 2021-01-10 11.26.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/f5c376a0-bda4-c2e0-97e6-0a3901f8e9c7.png)

>:8887/Build/アプリ名.framework.js.gz:1Uncaught SyntaxError: Invalid or unexpected token

>アプリ名.loader.js:1 Uncaught ReferenceError: unityFramework is not defined at HTMLScriptElement.r.onload (アプリ名.loader.js:1)

# 解決方法
Unity -> File -> Build Settings -> Player Settings -> Publish Settings -> Decompression Fallbackにチェックを付けましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/1481f9bb-8bab-1d21-a822-e2827f3e027d.png)

# 参考文献
- [UnityTechnologies Jukka_jさんからのご回答](https://forum.unity.com/threads/solved-unity-2020-webgl-doesnt-work-uncaught-syntaxerror-invalid-or-unexpected-token.872581/#post-6480523)

# その他
この不具合に対する回答に、「Player Settings -> Publish Settings -> Compression FormatをGzipやBrotliからDisableに変更する。」といったものがありました。この方法だとアプリのサイズが例えば37MBから96MBに膨れ上がってしまうため、あまり推奨はしないです…。もし本記事の方法でも解決しなかった場合に試していただくと良いかもしれません。
Unityのバージョン：2020.2.1
パソコン： Mac OS Catalina 10.15.7
何か質問などありましたらコメントしていただけると助かります。m(_ _)m
PHP8・Laravel8にバージョンアップしたらartisanが”Required parameter $message follows optional parameter $level ”で実行できなくなったので対処した

# 出来事

ある日久々に`php artisan serve`をしてみたら以下のエラーが出て実行できなかった。

```Log.php　line　24
  Required parameter $message follows optional parameter $level 
```

# 遠因

PHP8になって、メソッドにおいて必須でないパラメータが必須のパラメータより前に定義されているとエラーを吐くようになったらしい。
そういえばLaravelはVersion7系にはあげたけれど、途中だったかもしれないと思って調査を開始。

# 原因

* Composerで入れたパッケージのアップグレードを途中で放り出していた。
* 何らかのミスでPHP8が入ってしまった。

どちらかだと思う。お粗末な話なので対処を開始。

# 解決手順

## アップグレードガイドに従ってComposerパッケージをアップグレード
https://readouble.com/laravel/8.x/ja/upgrade.html

上記だけでは解決しなかった。

## Log.phpという名前のファイルを検索
`vendor/laravel/framework/src/Illuminate/Support/Facades/Log.php` 
が真っ先に見つかるがL24にはコメントしかない。

さらに探すと、
`vendor/itsgoingd/clockwork/Clockwork/Request/Log.php`
において、怒られている記述を発見できた。（v4.1.8）

## `itsgoingd/clockwork`をアップグレード

2021/1時点での最新版は5.0.6らしいので、`composer.json`を以下のように修正。

```composer.json
 "itsgoingd/clockwork": "^5.0"
```

アップデートを実行。

```
$ composer update
```

解決した。

```
% php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
[Sun Jan 10 11:46:10 2021] PHP 8.0.1 Development Server (http://127.0.0.1:8000) started
```

# 反省

PHP・Laravelのメジャーバージョンアップがどれほど面倒か身にしみてわかったので、今後の業務に活かしたい。
24歳大手SIerのSES勤務の自分がWeb業界への転職を考えだした話

<h1>はじめに</h1>
<p>はじめまして、新卒で大手SIerに入社し現在キャリア2年目の者(@takamoto822)です。</p>

<h2>スキルセット・開発経験</h2>
<p>・Java<br>
 →入社時に会社の研修で2か月ほど学習しました。<br>
  変数の設定やコンソール画面への出力などの基本的な操作～クラス実装位までを実装した記憶があります。<br>
研修で学習したのみで実務で使用した経験はないのでスキルセットとして書くのも微妙なレベルです。</p>

<p>・C#<br>
→1年目の時に設計書に基づいてコーディング、単体テストの実装まで担当しました。(開発期間半年程)<br>
   簡単な機能と単体テストの実装レベルなら一人でもできる位のスキルレベルです。<br></p>

<p>・HTML&CSS<br>
　→Progateで学習中(2021/1現在)
   業務で使用した事はないけど、SEなら多少は触れたほうがいいかなと思い勉強を始めました。</p>

<h2>なんでSIerからWeb業界へ？</h2>
結論から話すと、下記の理由がSIerからWeb業界に転職を決めた理由です<br>
①SIerでは若いうちから開発経験を積むことが難しい
②圧倒的エンジニア不足の現在、会社員でいることで会社にマージンを取られるのが損な気がする
③SIer業界で自分のプログラミングスキルを伸ばした所で、開発に関われるとは限らない。<br>

1つずつ解説していきます。<br>
まず①についてですが、僕の場合は新卒で入社して現場入りしてすぐに
運良くC#での開発業務に携わることができました。
しかし1年目の秋～2年目冬の1年半の間、プロジェクトを移動したこともありますが
一切開発に携わることが無くなってしまいました。
1年目の時はとにかく現場での仕事やシステム仕様を覚えることで精一杯でしたが、
2年目に入りある程度仕事を自分のペースで進めることができるようになったときに<br>

<strong>「俺、開発ほぼしてないけど大丈夫か・・・？」</strong>

と、漠然と不安になりました<br>
そもそもSESではほぼほぼ年功序列で上流工程を担当することになることがほとんどなので
経験の浅いエンジニアは必然的に保守を担当することが多いです。(ウォーターフォール開発の場合)
そこで、アジャイル開発がメインで人数も比較的少ないWeb開発なら
自分のスキルを伸ばしつつプロジェクトに貢献することもできると考えたためです。

②ですが、日本は現在も今後もエンジニアが圧倒的に不足すると言われています。
私は会社に所属する大きなメリットは<br>
・とりあえず手抜いても給料を安定的にくれる
・大手なら会社のネームバリューの恩恵を受けられる<br>
これくらいかなと思ってます。
給料が安定しているのは一見良いことのように聞こえがちですが、
言い方を変えると、どんだけスキルを上げて努力しても給料はほぼ同じなんですよね。
楽してお金を稼ぎたい人は会社にいればいいですが、お金を稼ぐための努力なら
苦労を惜しまないタイプの私からすると、会社にいながら開発スキルの勉強で土日を使うのは
効率が悪い気がします(言語を習得しても仕事で使えるか分らんし、、、)<br>

僕の所属している会社は規模こそは大きいですが、メーカー系ではないので
会社名を伝えたところでほぼ聞いたことがないって人が大半なところです。<br>

③は上記でも書きましたが、例えばJavaのスキルを付けたところで
自分のプロジェクトでJavaを使用していなければ有効活用できませんし、
仮に異動先でJavaを使用していても開発担当にならなければそれまでです。
SIer、SES業界あるあるの「案件ガチャ」で運良く当たりを引かない限り報われません。


<h2>だからWeb業界に行こうと思いました。</h2>
上記を踏まえて、
・自己スキルを伸ばせばそれだけプロジェクト貢献度が上がる。
・Web業界なら高確率で若いうちから開発に携われる。
・将来的にフリーランスを目指し、会社員時代より給与が上がる。

これらの結論に自分の中で至りました。
ただ、Web言語の開発経験無しでいきなり自社開発に潜りこむのは難易度が高い気がするので
まずは派遣エンジニアとしてWeb業界に忍び込むのが良いのかなと思っています。

将来的にはフリーランスを目指しているので、SIer→Web開発フリーランスになりたいと思っていますが
Web業界の右左も分からない奴がいきなりフリーランスになるのは厳しいと思うので
まずはWeb開発の実務経験を積むことを最優先に転職活動をしていこうと考えています(今年の夏までには、、、)


長くなりましたがここまで読んでいただきありがとうございました。
SIerからWeb業界への転職の過程を今後も書いていけたらと思っています。
.NET Standard 2.0 でSystem.Numerics.BitOperationsを使う

.NET Core 3.0から、`System.Numerics.BitOperations`クラスが追加されています。
このクラスには、下記のようなビット操作を行うメソッドがあります。

- `LeadingZeroCount`
- `Log2`
- `PopCount`
- `RotateLeft`
- `TrailingZeroCount`

これらのメソッドはIntrinsicsを使って実装している(依存している)ため、.NET Frameworkなどの環境で使用できるバックポートNugetパッケージがありません。

しかし、これらのメソッドにはIntrinsicsが使えない環境用にフォールバック実装があります。

従って、常にフォールバック実装を使用すれば、.NET Standard 2.0でも使用できるようになります。

というわけで、MITライセンスの[BitOperations.cs](https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs)をコピペ&細工しましょう。(ライセンスに従って取り扱う必要はがあります。)
`#if` ディレクティブで無効にするだけです。

したものが[こちら](https://github.com/udaken/Shim.System.Numerics/blob/master/src/BitOperations.cs)です。

一応[Nugetパッケージ](https://www.nuget.org/packages/Shim.System.Numerics/)も用意してみましたが、使用するアセンブリに組み込んでしまったほうがいいでしょう。

なお、Unityで動作するかはわかりません。
検証用仮想サーバのIPアドレスラクラク管理方法

# 問題点

Viatualboxの仮想サーバで開発環境を作って使ってます。
SSHログインなどの時にIPアドレスが可変なので使いずらい。
VMは、デフォルトではDHCPで動作するようになっていて、StaticIPアドレスを設定するのが面倒。

# 解決策

仮想サーバとの接続はHostPCのInternet接続しているNICとBridgeで接続する。
HostPCのInternet接続のDHCPサーバ（私の場合は、ブロードバンドルータのDHCPサーバ）でDHCPの固定アドレス設定でMACアドレスと対応するIPアドレスを設定。

以下の表の様に、規則的にしておくと便利！

|MAC|IP|
|---|---|
|0000000003|192.168.0.3|
|0000000004|192.168.0.4|
|0000000005|192.168.0.5|
|0000000005|192.168.0.6|

VirtualBoxのネットワーク設定で、MACアドレスを登録した値に設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/cc87cec4-ff88-9704-b0c0-15304cf40e12.png)

指定したMACアドレス、IPアドレスになっています。

```
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:00:00:00:00:05 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.5/24 brd 192.168.0.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet6 240f:68:4c37:1:a12c:4689:1e2f:a40a/64 scope global noprefixroute dynamic
       valid_lft 291sec preferred_lft 291sec
    inet6 fe80::9262:6b42:ec4f:b506/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
```


# MACアドレスについて

Wikiによると

> 先頭オクテットのビット0x02がグローバルアドレスとローカルアドレスを識別するビットで、GLビットと呼ばれる。OFFであればグローバルアドレス、ONであればローカルアドレスであることを示している。また、先頭オクテットのビット0x01がユニキャストとマルチキャストを識別するビットで、IGビットと呼ばれる。

ローカルでしか使われない値なので、自己責任で、入力しやすい00000000+IPアドレスの末尾
としました。
VercelにNext.jsで構築したサイトを公開したときに行うSEO対策

Next.jsは、Vercel社が開発しているReactフレームワークであり、同じくVercel社が提供するデプロイプラットフォームでNext.js製のサイトあるいはアプリケーションをデプロイすることによって、効率よい開発が可能になります。

本記事では、Next.js製のサイトをVercelのプラットフォーム上に公開したときに行うSEO対策について整理してみました。

## Trailing Slashの有無を統一する

Trailing Slashとは、URL末尾に付けるスラッシュのことです。例えば、`/about/`の末尾のスラッシュのことを指します。 

Next.jsでつくったサイトを何も考えずにアップロードすると、Trailing SlashありのURLでもなしのURLでもページを表示できてしまいます。このような挙動になる理由は、VercelのTrailing Slashの扱いがデフォルトでは未定義となっているからです。

内容が全く同じコンテンツがごくわずかな違いではありつつも複数のURLで表示できてしまうのはサイト設計上望ましくないので、Trailing SlashありかなしかのどちらかにURLは揃えます。

設定には、まず`vercel.json`という名前の設定ファイルをプロジェクトのルートに置きます。

そして、Trailing Slashを付けないURLにそろえる場合は、

    {
        "trailingSlash": false
    }

のようにファイル内に記述します。これを設定するとTrailing SlashありのURLでアクセスしたときはTrailing SlashなしのURLにリダイレクトされます。

Trailing Slashを付ける場合は、

    {
        "trailingSlash": true
    }

のように記述します。これを設定するとTrailing SlashなしのURLでアクセスしたときはTrailing SlashありのURLにリダイレクトされます。

これを設定するときに注意しなければいけないことが1つあります。一度Trailing Slashをどちらかにそろえたら設定を反転させないようにする必要があります。というのも、リダイレクトのHTTPステータスコードが[308](https://developer.mozilla.org/ja/docs/Web/HTTP/Status/308)のため、そろえた方にページ評価が永続的に渡されることになるからです。

## Development URLから独自ドメインにリダイレクトを設定する

Vercelにデプロイすると、複数の`[project name].vercel.app`というDevelopment URLがプロジェクト内に生成されます。

どのURLも表示されるコンテンツは独自ドメインと同じソースからデプロイしているものなので、異なるURLで同じコンテンツが表示されてしまいます。

独自ドメインをVercelの管理画面上で割り当てた場合は、この`[project name].vercel.app`というドメインから独自ドメインにリダイレクトを設定してコンテンツの重複を防ぎます。

管理画面でのリダイレクト設定はプロジェクトのドメイン設定から行えます。ただし、プロジェクトを更新するたびにランダムに文字列が割り当てられるDeployment URLのみリダイレクトの設定はできないようになっています。

ちなみに、Development URLには`x-robots-tag: noindex`が設定されているので、そもそも検索エンジンにインデックスされることはありません。ただ、ダイレクトにURLを入力すればコンテンツが表示されます。よって、何らかのきっかけでDeployment URLが良質な被リンクを大量に獲得したときの機会損失を防ぐためにリダイレクトは適切に設定しておいた方が良いと思います。
Apache spark RDD を Join した後の Partition 数

##### 背景
異なるパーティション数のRDDをJoin した後、Join後のRDDのパーティション数が少ない方に合わせられてしまうという現象を確認。
後続の処理のパフォーマンスに影響を与えるので、Join後のRDDのパーティション数は多い方に合わせられる方が望ましい。

##### 検証
取りあえず、spark-shell でその動作を検証してみました。
spark version:2.3.2

1.パーティション数1000のRDDを作る

```bash:size1000
scala> val rdd1 = sc.parallelize(1 to 10000, 1000)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:24

scala> val pairRdd1 = rdd1.map(r => (r, r))
pairRdd1: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[1] at map at <console>:25

scala> pairRdd1.partitions.size
res0: Int = 100
```

2.パーティション数10のRDDを作る

```bash:size10
scala> val rdd2 = sc.parallelize(1 to 100, 10)
rdd2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at <console>:24

scala> val pairRdd2 = rdd2.map(r => (r, r))
pairRdd2: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[3] at map at <console>:25

scala> pairRdd2.partitions.size
res1: Int = 10
```

3.Join する

```bash:join
scala> val joined = pairRdd1.join(pairRdd2)
joined: org.apache.spark.rdd.RDD[(Int, (Int, Int))] = MapPartitionsRDD[6] at join at <console>:27

scala> joined.partitions.size
res2: Int = 1000
```

Join後のRDDは多い方のパーティション数（1000）の方に合わせられた結果になりました。
想定していた結果は少ない方のパーティション数（10）になることでしたが、基本的な仕様としては多い方に合わせられるようです。

```bash
scala> joined.toDebugString
res3: String =
(1000) MapPartitionsRDD[6] at join at <console>:27 []
  |    MapPartitionsRDD[5] at join at <console>:27 []
  |    CoGroupedRDD[4] at join at <console>:27 []
  +-(1000) MapPartitionsRDD[1] at map at <console>:25 []
  |   |    ParallelCollectionRDD[0] at parallelize at <console>:24 []
  +-(10) MapPartitionsRDD[3] at map at <console>:25 []
     |   ParallelCollectionRDD[2] at parallelize at <console>:24 []
```

##### 少ない方のパーティション数になるケースも存在するのか
詳細は省きますが、（暗黙的な）パーティション数の決定については、複数の要因が影響するようです。
基本的に spark のパラメータの一つである "spark.default.parallelism" が設定されていない場合、大きい方のパーティション数が採用されるように思われます。
もし、"spark.default.parallelism" が設定されている場合は、"spark.default.parallelism" に設定されている値とパーティション数を比較しますが、単純に大きい方が採用されるわけではなく、小さい方の値が採用されるケースもあるようです。
また、このパーティション数の決定ロジックについては、RDDとDataFrameでも異なるようです。

##### Join 時にパーティション数を明示する

暗黙的なパーティション数の決定には、理解しないといけないロジックがあり、意図しない結果が発生する可能性があるので、明示した方が安全そうです。
※別途、シャッフルの回数が増えることもないはず

```bash:joinwithnumber
scala> val joined2 = pairRdd1.join(pairRdd2, 200)
joined2: org.apache.spark.rdd.RDD[(Int, (Int, Int))] = MapPartitionsRDD[9] at join at <console>:27

scala> joined2.partitions.size
res5: Int = 200

scala> joined2.toDebugString
res6: String =
(200) MapPartitionsRDD[9] at join at <console>:27 []
  |   MapPartitionsRDD[8] at join at <console>:27 []
  |   CoGroupedRDD[7] at join at <console>:27 []
  +-(1000) MapPartitionsRDD[1] at map at <console>:25 []
  |   |    ParallelCollectionRDD[0] at parallelize at <console>:24 []
  +-(10) MapPartitionsRDD[3] at map at <console>:25 []
     |   ParallelCollectionRDD[2] at parallelize at <console>:24 []
```

##### 結論
暗黙的なパーティション数の決定は、Spark自身が最適なロジックを元に行っているはずですが、（個人的な経験として）それがアプリケーション的に最適にならないケースも存在すると考えていた方が良いかもしれません。
暗黙的にParition数が決定されるロジックを理解していない場合、明示した方が安全そうです。
【SQL】PostgreSQLで全文検索をする

# 全文検索とは
>全文検索(または単にテキスト検索)は、
問い合わせを満たす自然言語の文書を識別し、更には問い合わせとの関連性の順に並び替えることができます。
[公式より](https://www.postgresql.jp/document/12/html/textsearch-intro.html#TEXTSEARCH-DOCUMENT)

...意味わからんすね😊



>もっとも一般的な検索は、与えられた検索語を含む文書を探し、問い合わせとの類似性の順に返す、というものです。
[公式より](https://www.postgresql.jp/document/12/html/textsearch-intro.html#TEXTSEARCH-DOCUMENT)

要するに、全文検索とは**文字列を検索できる**ことだと認識しています。

# SQLの実行方法

導入version: PostgreSQL 8.3〜

```
db=# select * from article;
 title  |     tag
--------+-------------
 title1 | 001 002 003
 title2 | 002 003 004
 title3 | 003 004 005
 title4 | 004 005 006
 title5 | 005 006 007
```


tagに'002'を持っているレコードのみを取得したい場合...

```
db=# select * from article where tag::tsvector @@ '002'::tsquery = 't';
 title  |     tag
--------+-------------
 title1 | 001 002 003
 title2 | 002 003 004
```

tagに'001'かつ'002'を持っているレコードのみを取得したい場合...

```
db=# select * from article where tag::tsvector @@ '001 & 002' ::tsquery = 't';
 title  |     tag
--------+-------------
 title1 | 001 002 003
```

## 解説
tsvector（文書）とtsquery（問い合わせ）を照合演算子@@で比較して、一致した場合、't'つまりtrueが返ってくるという仕組みです。

つまり...

```
'001 002 003'::tsvector @@ '002'::tsquery = 't'
```
となり、'002'というテキスト（文書）が問い合わせと一致するため、trueとなります。

>※1 文書 ･･･ 全文検索システムにおける検索の単位です。

## ちなみに

もちろん、マルチバイト文字を検索することもできます。

```
db=# select * from book where tag::tsvector @@ '猫'::tsquery = 't';
     title      |            tag
----------------+----------------------------
 吾輩は猫である   | 夏目漱石 日本 小説 猫 明治
```
masterにコミットしてしまった修正をブランチに移動したい

## 目的
ブランチを切って作業すべきところを、間違えてmaster上で作業してコミットしてしまった。

```
 $ git branch
* master
 $ git log --oneline 
9491e2d add Z
877a87e add Y
5301865 add X
0846a50 initial commit
```

このままだと pull requestも出せないし、自部署の gitリポジトリは masterへの pushを禁じているのでどうにかしたい、という話

## 手順

masterからブランチ branchXYZを作成。

```
 $ git checkout -b branchXYZ
 $ git log --oneline 
9491e2d add Z
877a87e add Y
5301865 add X
0846a50 initial commit
```

次にmasterのコミットを巻き戻す

```
 $ git checkout master
 $ git reset --hard HEAD~3
HEAD is now at 0846a50 initial commit
 $ git log --oneline    
0846a50 initial commit
```

あとは branchXYZを pushして pull requestを出せば解決
Dartはコンストラクタを継承しない

# 発生している問題
スーパークラスでコンストラクタを定義してあるのに、そのクラスのサブクラスをインスタンス化しようとすると、`The named parameter 'xxx' isn't defined`というエラーが発生する。

```super_class.dart
import 'package:flutter/material.dart';

class SuperClass {
  const SuperClass({this.argument});

  @protected
  final String argument;
}
```

```child_class.dart
import 'super_class.dart';

class ChildClass extends SuperClass {
  void method() {
    print(argument);
  }
}

```

```main.dart
import 'child_class.dart';

final myClass = ChildClass(argument: 'hoge');
```

![スクリーンショット 2021-01-10 10.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534248/d90943bb-79eb-5ca9-46e4-5fdff0d931d4.png)

# 原因
[Dartの公式ドキュメント](https://dart.dev/guides/language/language-tour#constructors-arent-inherited)によると、コンストラクタは継承されないらしい。

以下抜粋。
>Constructors aren’t inherited
> Subclasses don’t inherit constructors from their superclass. A subclass that declares no constructors has only the default (no argument, no name) constructor.

日本語訳
> コンストラクタは継承されない。
> サブクラスはそのスーパークラスのコンストラクタを継承しない。コンストラクタを定義していないサブクラスは、デフォルト（引数なし、名前なし）のコンストラクタしか持たない。

だそうです。
つまりサブクラスでもコンストラクタを定義すればOK。

```child_class.dart
import 'super_class.dart';

class ChildClass extends SuperClass {
  const ChildClass({String argument}) : super(argument: argument);

  void method() {
    print(argument);
  }
}
```

うーん。サブクラスでいちいち定義するの面倒くさくないか？
google driveのファイル一覧をtreeで作成する

## 動機
google drive上にある議事録などのファイルを階層構造付で一覧化したい時があった。
ネットで検索するとgoogle app scriptを使用してgoogleスプレッドシートに吐き出すというやり方の記事が多いが、treeコマンドの結果のような形式でファイル一覧が作成したかったため、やってみた。

## 手順
### 1.ファイル一覧を作成したいgoogle driveにログインし、Google Colaboraroryのファイルを作る。

google drive→新規→その他→Google Colaborarory

### 2.以下の4セルの内容を貼り付ける

```python
# google　driveをGoogle Colaboraroryからアクセスできる場所にマウントする
from google.colab import drive
drive.mount('/content/drive')
```

```python
# Google Colaborarory環境にはtreeが入っていないので入れる
!sudo apt-get install tree
```

```python
# /path/to/dirはtreeを発行したいディレクトリに変更
%cd drive/MyDrive/path/to/dir
```

```python
!tree -N
```

### 3.セルを順番に実行していく

以下のセルの実行をすると、google driveへの認証を求められる。指示に沿って認証を行う。

```python
from google.colab import drive
drive.mount('/content/drive')
```

順番に実行していくと以下のような結果が得られる。

```python
!tree -N

.
├── dir1
│   ├── 基本設計
│   │   ├── file1
│   │   ├── file2
│   │   ├── file3
│   │   ├── dir2
│   │   │   ├── file4
│   │   │   └── file5
│   │   ├── file6
.
.
.
```

## なぜGoogle Colaboraroryを使うのか
treeコマンドを発行するだけであればgoogle APIを使用すればできそうではあるものの、会社で使用しているgoogle driveの場合は外部API認証が出来ない場合があるため、Google Colaboraroryを使用した。

外部API認証が出来ない場合とは、google関連のサービスに二段階認証を設定している場合。
二段階認証をONにしていなければ、設定の［安全性の低いアプリの許可］から許可を行うことで外部APIからdriveにアクセスできるようになるが、会社全体で二段階認証をONにしている場合、treeコマンドを発行したいというだけで二段階認証をOFFにするわけにもいかない。そういう場合はGoogle Colaboraroryからdriveにアクセスすることで、認証で弾かれる事態を防ぐことができる。
[参考](https://support.justsystems.com/faq/1032/app/servlet/qadoc?QID=054933#:~:text=%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7Google%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9,%E7%84%A1%E5%8A%B9%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

他の方法として、OAuth2.0に対応させた形でgoogle driveにアクセスできるようにすればそれでもtreeコマンドは実行可能である。(が、treeを発行するためだけにそこまでやるのは面倒な気もする。)
[参考2](https://support.google.com/a/answer/6260879?hl=ja#zippy=%2C%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E5%AE%89%E5%85%A8%E6%80%A7%E3%81%AE%E9%AB%98%E3%81%84%E3%82%82%E3%81%AE%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
Docker 用語とコマンド


#用語
###Docker
必要な環境(OS,ライブラリ,アプリケーション)をパッケージ化した仮想環境(コンテナ)を作り出すことで、アプリ開発からデプロイまで簡単にできる仕組みのこと。


###コンテナ
Dockerイメージをもとに作成される仮想環境の実行部分
###Dockerイメージ
コンテナを作成するために必要な物を記載した雛形
###Dockerレジストリ
Dockerイメージをオンライン上で保管
###Dockerfile
コマンドやライブラリなど環境構築を記述
###Docker Compose
複数のアプリケーションを連携し一括で管理
###docler-compose.yml
一括で管理するコンテナを記述

#コマンド
##Dockerイメージ
###イメージ作成
```terminal.
% docker image build
% docker image build -t <名前空間>/<名前>:<名前> 
```
###イメージ一覧
```terminal.
% docker image　ls -a 
```

##Dockerコンテナ
###コンテナ作成・起動
```terminal.
% docker container run
% docker container run -p <ポート番号>:<ポート番号> --name <名前空間>/<名前>:<名前>
```
###コンテナ一覧
```terminal.
% docker container ls -a
```
###コンテナ停止
```terminal.
% docker container stop <名前>
```
###コンテナ削除
```terminal.
% docker container rm <名前>
```
###コンテナのログを確認
```terminal.
% docker container logs <名前>
```

##Docker Compose
###イメージの作成
```terminal.
% docker-compose build
```
###コンテナ作成・起動
```terminal.
% docker-compose up
```
###コンテナ停止・削除
```terminal.
% docker-compose down
```
###コンテナ一覧
```terminal.
% docker-compose ps
```
###ログを表示
```terminal.
% docker-compose logs
```
###コマンドを実行
```terminal.
% docker-compose run <サービス><コマンド>
```
###起動中のコンテナにコマンドを実行
```terminal.
% docker-compose exec <サービス><コマンド>
```
##Dockerコマンド一覧
```terminal.
% docker --help
```
MuZeroを使って強化学習で遊ぶ

はじめに
========
DeepMind が発表した MuZero という AlphaZero をより一般化した手法があります。ルールが明確な対人ゲームだけでなく、 Atariゲームのような一人用ゲームにも同じように適用できるというのが非常に強力で、性能もかなり高いようです。
（個人的に育休とか取っていたのもあって）1年くらいその存在すらしらず(...)、最近になってまたニュースになっていてやっと知ることができて、最近色々遊んでみているのでその共有をします。

すでに [muzero-general](https://github.com/werner-duvaud/muzero-general) という PyTorchベースの非常に素晴らしい実装のリポジトリが公開されているので、主にその紹介です。


[muzero-general](https://github.com/werner-duvaud/muzero-general)
===========

良いところ
--------

- 色々なゲームが最初から付いていて、自分で追加するのも非常に簡単にできる（1ファイル追加するだけ）
- Hyperparameterの調整も簡単
- GPUが使えるなら使ってくれる
- TensorBoardで Rewardの獲得状況やLossの推移、学習&SelfPlayの消化速度 がリアルタイムで見られる
- 使い始めるのが簡単
- ソースコードも読みやすい

導入＆試しかた
--------

[Getting started](https://github.com/werner-duvaud/muzero-general#getting-started) を見ると良いですが、こんな感じで始められます。

```
git clone https://github.com/werner-duvaud/muzero-general.git
cd muzero-general

pip install -r requirements.txt

python muzero.py  
# -> Menu が表示される 
# -> Gameの種類選択 
# -> 何をするか: Training, LoadModel, TestPlay(MuZero vs Human), ViewPlay(MuZero Vs MuZero),  etc
```

最初は `tictactoe` という日本語で言うなら「マルバツゲーム」 くらいを眺めるのが良いんじゃないかと思います。

Gameの追加方法
-------------

`games/` ディレクトリにファイルを追加するだけです。
`Game` というクラスに `reset`, `step`, `to_play`, `legal_actions` のようなメソッドを実装していきます。同ディレクトリに参考になるGame実装がいくつもあるので、何をすべきかは理解しやすいかと思います。

2人対戦ゲーム用のPatch
-------------

たぶん2人対戦ゲームの実装にはバグがあって、うまくいかない場合はこの[PullRequest](https://github.com/werner-duvaud/muzero-general/pull/108)を適用してみてください。
最初 tictactoe を半日かけても弱いままだったのが、このPRを適用すると２~3時間で納得のいく強さになりました。

ちょっと作ったゲーム
----------
スマホのゲームアプリによくあるゲームを追加したので、興味があればどうぞ。

### [2048](https://play2048.co/)


- ファイル: [make2048.py](https://github.com/mokemokechicken/muzero-general/blob/mine/games/make2048.py)


### [X2 Blocks](https://apps.apple.com/us/app/x2-blocks-merge-puzzle-2048/id1480338372)

- ファイル: [x2blocks.py](https://github.com/mokemokechicken/muzero-general/blob/mine/games/x2blocks.py)


さいごに
======

とても楽しいおもちゃを手に入れた気分です。
connect4 とか １〜２日くらい学習させるとかなり強くなります。適当にやっていると嫌なTrapでやられます...
HTML/CSSに関するメモ

#はじめに
HTML/CSSについて、調べる度毎回内容を忘れてしまうので内容を備忘録としてまとめておく。

##HTMLタグについて
色々なタグがあって覚えきれないが、分からなくなったら以下のページを参照する。
[HTMLクリックリファレンス](http://www.htmq.com/html/)

##class/idについて
参考記事：

- [classって何？CSSと組み合わせて使う方法を徹底解説](https://www.sejuku.net/blog/56996)
- [CSSとidの関係とは？要素に名前をつけて細かくデザイン指定しよう](https://www.sejuku.net/blog/56934)

classはHTMLタグに対して付与できる「グループ分けのための名前」みたいなもの。
CSSでスタイルを指定する時に、class名を指定して適用させる。

idもHTMLタグに付与できる名前であるが、classとidの違いとしては

- id：同一ページ内で１回しか使えない
- class：同一ページ内で何回でも使える

である。

また、CSS適用の優先順位は

- id > class >HTMLタグ

となる。

##`<form>`について
- [参考リファレンス](http://www.htmq.com/html/form.shtml)

入力/送信フォームを作る時に利用するタグ。
タグには色々な属性を付けることが出来る。

- action属性：フォームの送信先を指定する
    - 値を空にした場合や、この属性自体を省略した場合（HTML5から）は、自身にデータを送信するらしい　[参考](https://creatorquest.jp/reference/html/element/form/#action-attribute)
- method属性：フォームの送信方法を指定する
    - getとpostがある

###`<input>`タグについて
`<form>`タグの中に記述し、テキスト入力欄や実行ボタン等、`<form>`を構成する部品を作成する。
データが送信される際には、 `<INPUT>`タグのname属性で付けたデータ名とその値を一組にしてサーバーに送信される。

###`<select>`タグについて
`<form>`タグの中に記述し、セレクトボックスを作成する。
セレクトボックス内の選択肢は`<OPTION>`タグで指定する。
データが送信される際には、 `<SELECT>`タグのname属性で付けたデータ名と、 選択された`<OPTION>`のvalue属性の値を一組にして送信される。

##`<p>`タグについて
<P>タグはParagraphの略で、`<P>～</P>`で囲まれた部分がひとつの段落であることを表す。
BIG-IP Virtual Editionを使ってみる。（その１：BIG-IP VEと評価ライセンスの入手）

# はじめに
私の記事では何度か登場しているF5社の`BIG-IP`ですが、仕事で久しぶりに使うことになったので、思い出しがてら、`VMware Workstation Player`を使って`BIG-IP Virtual Edition`を動かしてみようと思います。

- 【次】[BIG-IP Virtual Editionを使ってみる。（その２：BIG-IP VEの起動とライセンス登録）](https://qiita.com/sakai00kou/items/e7e458709e9771b85181)

以前の記事
- [BIG-IPのAuto Last Hop機能には気をつけろ！！](https://qiita.com/sakai00kou/items/da50f5aade1cdc930b3c)
- [現行機器の仕様を取り込み切れなかった話](https://qiita.com/sakai00kou/items/67218c20541da687c9de)

# BIG-IP Virtual Editionの入手
`BIG-IP`には`ESXi`や`VMware Workstation Player`で動かせる`Virtual Edition`があり、購入前に事前に試せる**トライアル用ライセンス**もあるため、こちらを使ってみようと思います。

## ダウンロードページへのログイン
[F5社のページ（日本語）](https://www.f5.com/ja_jp)から「**製品**」→「**トライアル版**」を選択します。

![trial1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/3759a5ab-fa08-9e39-3dfd-672c445633c7.jpeg)

遷移後の画面で「**無料トライアル版を利用**」を選択。

![trial2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/86441ec6-75a8-905f-762a-b0bd973545d2.jpeg)

画面下部に`AWS`や`Azure`など様々な環境用のイメージの記載がありますが、今回は`VMware`の欄にある「**Download BIG-IP VE image**」を選択。

![trial3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d573c534-2fe0-e779-55e4-bcc01633e52f.jpeg)

ログイン画面が表示されるので、**Email**、**Password**を入力して**Login**します。
まだアカウント作成していないようであれば、画面下の「**Create one.**」よりアカウントを作成して下さい。

![trial4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/cbfbdd9d-fcaf-c547-f435-ae8310eaf028.jpeg)

# イメージのダウンロード
ログインするとダウンロードするプロダクト選択画面が表示されるため、今回は「**BIG-IP v16.x / Virtual Edition with Traffic Management Operating System (TMOS)**」を選択します。

![trial5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f6599882-ac0a-45e3-94be-a0149081a55a.jpeg)

**BIG-IP v16.x**の各種イメージが表示されるため、今回は「**16.0.1_Virtual-Edition**」を選択します。

![trial6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/d821ceb0-0b8a-de70-214d-0c70f85efcdf.jpeg)

使用許諾のページから進むと、いよいよイメージのダウンロード画面が表示されるため、ダウンロードするイメージを選択します。
ダウンロードロケーションの選択はそれぞれのロケーションに合わせて選択して下さい。

![trial7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/056f137c-7c19-acd8-0ebb-e5ab47456cfe.jpeg)

# 評価ライセンスの入手
`BIG-IP`はイメージを入手しても、ライセンスが無ければ何もできません。
とはいえテストのために正規ライセンスを購入するのはハードルが高いので、今回は**評価用のライセンス**を取得します。

## 評価ライセンスの発行
先ほどイメージダウンロードで表示した、[ここ](https://www.f5.com/ja_jp/trials/big-ip-virtual-edition)の画面の「**Login or Register**」を選択します。

![trial12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/491259c7-1b1d-595c-191f-afa386607c71.jpeg)

各種情報を選択し、「**Request license keys**」をクリックします。
評価ライセンス数は冗長化の確認等行うようなら複数発行しておきましょう。

![trial13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/f9be3846-309f-beeb-d3e2-6026715a9d10.jpeg)

少しすると登録しているメールアドレスに評価ライセンスが送られてきます。

# おわりに
今回は`BIG-IP Virtual Edition`のダウンロードと評価ライセンスの発行まで実施しました。

次回は入手したイメージを使って、ライセンス登録まで行ってみようと思います。
シェルスクリプトで呼び出し元プロセスの情報を表示する (take2)

# シェルスクリプトで呼び出し元プロセスの情報を表示する (take2)

[シェルスクリプトで呼び出し元プロセスの情報を表示する](https://qiita.com/m-tmatma/items/2a48e608b38eb5aad645) で書いた記事の拡張版です。「呼び出し元プロセスの情報を表示する」という観点では追加はありません。子スクリプトがどのように呼ばれたか、デバッグするときに便利な情報を追加しました。

## スクリプト定義

### parent.sh (親プロセス側)

```
#!/bin/bash

./child.sh test1 test2 test3
./child.sh test11333 test2 test3
```

### child.sh (子プロセス側)

```
#!/bin/sh

TIMESTAMP=$(date "+%Y/%m/%d-%H:%M:%S")
CALLER=$(ps $PPID | tail -n 1 | awk '{c="";for(i=5;i<=NF;i++) c=c $i" "; print c}')
echo -n "["
echo -n "$TIMESTAMP"
echo -n "]: "
echo -n "("
echo -n $CALLER
echo -n ") "
echo $*
```

## 実行例


```
$ ./parent.sh 1 2 3
[2021/01/10-09:57:24]: (/bin/sh ./parent.sh 1 2 3) test1 test2 test3
[2021/01/10-09:57:24]: (/bin/sh ./parent.sh 1 2 3) test11333 test2 test3
```

```

$ ./parent.sh 1 12 123 | column -t
[2021/01/10-09:58:37]:  (/bin/sh  ./parent.sh  1  12  123)  test1      test2  test3
[2021/01/10-09:58:37]:  (/bin/sh  ./parent.sh  1  12  123)  test11333  test2  test3
```


## 参考リンク

`column -t` は以下を参考にしました。

https://stackoverflow.com/questions/6345429/how-do-i-print-some-text-in-bash-and-pad-it-with-spaces-to-a-certain-width
【selenium/Python】裁判例pdfを一括表示してみる

##自己紹介
初めまして。今回初めて記事を書いてみることにしました。
現在情報系の修士2年生で、今年の4月よりIT企業へ入社する予定です。
今まで外部発信はしてきませんでしたが、これから少しずつ発信していく所存ですのでよろしくお願いします！

##背景
記念すべき初投稿は、「スクレイピング」の超入門です。
私はかねてより自然言語処理に興味をもっており、その対象として「法律」を扱えないかと考えていました。
そしたら[とある研究報告](https://ci.nii.ac.jp/naid/120006652159/)を見つけ、私にもできるかも！と思い、とりあえず[裁判所のページ](https://www.courts.go.jp/index.html)から判決文を引っ張ってこよう！と思った次第です。

##環境
・Python 3.7.7
・Windows 10 Pro
・PyCharm 2019.3.3(IDE)

##中身
＊注意＊
今回は単にページ内のpdfをブラウザ表示させるだけの内容です。
これから改良を重ねて、法分野をより身近にしていきたいと考えております。

```law.py
from selenium import webdriver

driver = webdriver.Chrome('C:\chromedriver_win32\chromedriver')
driver.get('https://www.courts.go.jp/app/hanrei_jp/search1')
search_bar = driver.find_element_by_name("filter[text1]")
search_bar.send_keys("GPS")
search_bar.submit()

#Xpathで要素を抽出し、formatでtr[]の値を変更する
#それをクリックしてページ表示
for i in range(1,11):
    x_path = "//*[@id='main-contents']/div[2]/div/div[3]/div[5]/table/tbody/tr[{0}]/td[2]/a".format(i)
    driver.find_element_by_xpath(x_path).click()
```

＊今回seleniumやChromedriverのインストール方法は割愛させていただきます。

**➀裁判所の裁判例検索ページにアクセスさせます。**
**②検索窓のhtmlタグを抽出し、「GPS」というキーワードで検索させます。**
＊なぜ「GPS」を選んだかというと、学部生の頃法学部に所属しており、当時のゼミ活動でGPS捜査の合憲性について調査したことがあったからです。
**➂pdfファイルが埋め込まれているhtmlタグを抽出し、for文でループします。**


##学び
今回初めてseleniumを使用しましたが、これだけの内容で1時間くらいかかってしまいましたね。（効率が悪かったかな）
特に最後の部分ですが、html構造が複雑すぎてPDFファイルのタグをどう抽出させるかにだいぶ悩まされました。

今後は、
➀ページ遷移させて全てのPDFを表示
②PDFのダウンロード
➂検索ワードをユーザーが自由に設定できる
などの機能ができれば、自然言語処理の応用もできそうなので引き続き挑戦していきたいと思います。

拙い初投稿を読んでくださりありがとうございました！


##参考
・https://stackoverrun.com/ja/q/11884507
・https://ai-inter1.com/python-selenium/
・https://www.seleniumqref.com/api/python/element_get/Python_find_element_by_xpath.html
【rails6】webpackを使って手動でjsをコンパイルしながら行う開発が非常にスムーズで感動した件

# webpackを使って手動でコンパイルする際の開発の進め方

componentを編集したとき

```
% cd frontend #webpack.config.jsが置かれているディレクトリ
% webpack #webpack.config.jsを使ってアプリで読み込むjsをbuild
```

とコマンドを入力することでcomponentの変更が反映される。このとき別タブでrailsのサーバーを起動しっぱなしでも問題ない。よって開発するときは

| タブ1                           | タブ2                                             |
| ------------------------------- | ------------------------------------------------- |
| railsのサーバーが動いているタブ | webpack.config.jsが入っているディレクトリ<br />componentの編集→webpackコマンドでbuildを行う |

といった形でタブを分けると開発がスムーズである。

componentも事前にwebpackでコンパイルしているのでrailsアプリでは出力されたjs一つを読み込むだけで済む。
ビューをrailsのviews以下のビューファイルで読み込むのと処理速度がかなり違う印象。
RubyでGmailを送信する基礎

出涸らし情報だけどRuby教えるときに便利なので手順メモ

##Gmailのアプリパスワードを取得する
要は以下のような16桁が欲しい
![スクリーンショット 2021-01-10 9.03.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239796/14799bf3-232b-1d83-98c1-c0dd7f15e59f.png)

以下作業は[こちら](https://myaccount.google.com/security?utm_source=OGB)の画面で行います。

1. Google 二段階認証を有効にする (これやらないとパスワードが取れない！)
    - [パスワードとログイン方法] -> [2段階認証プロセス]
    - SMSで認証して有効化させる
1. アプリパスワードを取得する
    - [パスワードとログイン方法] -> [アプリパスワード]
    - [アプリを選択]と[デバイスを選択]をそれぞれ入力 (本人が管理できればなんでもいい。。はず)
    - アプリパスワードが生成されるので控えておく

# gem mail をインストール

```zsh
$ gem mail install
```

#サンプルコードを書く

```ruby:send_gmail.rb
require 'mail'

from   = 'my_gmail_address@gmail.com'
password = '16_digit_app_password'
to = 'to_address@gmail.com'

Mail.defaults do
  delivery_method :smtp, {
    address: 'smtp.gmail.com',
    port: 587,
    domain: 'example.com',
    user_name: from,
    password: password,
    authentication: :login,
    enable_starttls_auto: true
  }
end

m = Mail.new do
  from "#{from}"
  to "#{to}"
  subject "Great Mail Title"
  body "Fantastic body blar blar"
end

m.charset = "UTF-8"
m.content_transfer_encoding = "8bit"
m.deliver
```

取り敢えずこれで動くはず。

#参考情報
Ruby を使って Gmail 経由でメール送信
http://1bed.allright.life/?p=2004
Lambda layer（python）で5分くらい遊ぶ

## まとめ

- ディレクトリ構成: `python/layer/function.py`
- インポート: `from layer import layer1`

## Layer化したいファイルの用意

```function.py
def sum(x:int, y:int) -> int:
    return x + y
```

## Layerを利用する関数の用意

```python:lambda_function.py
import json
from layer import function

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': function.sum(1,2)
    }
```

## さいごに

- `python/` ディレクトリ以下に配置して、その先をimportする
  - Zip化する際に共通系がそこに入るようにコーディネートしなければならないのめんどくさい
  - そんなモジュールないぜ、ってPython的に言われるだけで、ちょっとデバッグしづらい
  - Lambda視点からのエラーメッセージを出力してくれたらもう少し親切なのに