OmniAICreator/Qiita-1.07M huggingface dataset:
[mecab] 略語の連語の文脈idを上書きするユーザ辞書を作った

ipadicやNEologdはほとんどの語彙で左文脈idと右文脈idが一致します。そこで「食べちゃう」＝「食べてしまう」のような場合、「ちゃう」の左文脈idは「て」の307ではなく、「動詞,非自立,\*,\*,五段・ワ行促音便」の1252になっています。

```python
import MeCab
text = "食べてしまう。食べちゃう。"
mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd")
node = mecab.parseToNode(text).next

while node:
    print(node.surface, node.lcAttr, node.rcAttr)
    node = node.next
```
の結果はこうです。

```
食べ 625 625
て 307 307
しまう 1253 1253
。 8 8
食べ 625 625
ちゃう 1252 1252
。 8 8
 0 0
```
これが致命的な問題になる場面はそう多くはないと思いますが、運悪くその場面に当たってしまったので、上書き用のユーザ辞書を作りました。

https://github.com/En3-HCl/ryakugo-dict

これを導入すると

```
食べ 625 625
て 307 307
しまう 1253 1253
。 8 8
食べ 625 625
ちゃう 307 1253
。 8 8
 0 0
```

のように、無事に左文脈idと右文脈idが変わります。
導入方法は[mecabのドキュメント](https://taku910.github.io/mecab/dic.html)の通りです。

不足や誤りがあったらPRを送っていただけると嬉しいです。
Font-Awesomeのフォントファイルのフォーマット、及びSVGファイルのWebアクセシビリティチェック


複数フォントファイルあったため、調査しました。
各フォントファイルはFortAwesomeのCSSから参照されます。

https://github.com/FortAwesome/Font-Awesome/tree/master/webfonts

# .eot

Embedded OpenType - フォントファイルのフォーマット、およびファイル拡張子
ie用のフォントファイルっぽい

#### 情報源

Web Embedding Fonts Tool - Wikipedia
https://ja.wikipedia.org/wiki/Web_Embedding_Fonts_Tool

# .woff .woff2

WOFF (Web Open Font Format) 

#### 情報源

WOFF (Web Open Font Format) - 開発者ガイド | MDN
https://developer.mozilla.org/ja/docs/Web/Guide/WOFF
> WOFF (Web Open Font Format) は、Mozilla が Type Supply や LettError、他の組織と提携して開発した新しい Web フォント形式です。

# .svg

Scalable Vector Graphics (SVG)
XMLでグラフィック記述。フォントも作れる。

#### 情報源

SVG: Scalable Vector Graphics | MDN
https://developer.mozilla.org/ja/docs/Web/SVG
> Scalable Vector Graphics (SVG) は、二次元ベースのベクター形式のための XML に基づくマークアップ言語です。
> そのため、どんな大きさでもきれいにレンダリングできる画像を記述するためのテキストベースのオープンなウェブ標準であり、
> 特に他のウェブ標準、例えば CSS, DOM, JavaScript, SMIL などとうまく機能するように設計されています。 
> SVG は本質的に、グラフィックに対するもので、テキストに対する HTML のような位置づけです。

# .ttf

pointTrueTypeフォント

#### 情報源

TTFファイルとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
https://wa3.i-3-i.info/word14137.html
> pointTrueTypeフォントのファイルだよ
> point拡張子が「.ttf」だよ

# その他：SVGファイルのWebアクセシビリティチェック

SVGはXMLのため、Webアクセシビリティ対応（JIS-X 8341-3:2016対応）の参考チェックに以下があります。

H75: ウェブページが well-formed であることを確認する | WCAG 2.0 達成方法集
https://waic.jp/docs/WCAG-TECHS/H75.html

該当するSVGは、全て well-formed で問題なしでした。

* fontawesome/webfonts/fa-brands-400.svg
* fontawesome/webfonts/fa-regular-400.svg
* fontawesome/webfonts/fa-solid-900.svg

 well-formed かどうかは、https://schneegans.de/sv/ でチェックしました。
SOL 文の速攻雛形 

いつも忘れてしまうので、
雛形作成しました！

※苦手なORDER BY文も記載しています。

```sql

CREATE DATABASE test; --データベースを作る

USE test; --デフォルトで使用するデータベースを指定する

CREATE TABLE users (*** VARCHAR(100), *** INT); --カラムを作成

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値); --insert文

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値);

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値);

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値);

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値);

INSERT INTO users (***, ***) VALUES ('任意の値', 任意の値);


SELECT * FROM *** ORDER BY test; --ORDER BY 昇順文

SELECT * FROM *** ORDER BY test DESC;--ORDER BY 降順文

SELECT * FROM *** WHERE *** LIKE '%任意の値%' ORDER BY 任意の値; 
--条件を絞ったORDER BY文 (検索してから、昇順)

SELECT * FROM *** ORDER BY FIELD(***, 'test1', 'test2', 'test3'); 
--FIELD関数＋ORDER BYを使用した文 任意の値に並び替えることが可能。

SELECT * FROM *** ORDER BY test_score >= 30 DESC;
--数字条件付きORDER BY文

SELECT * FROM users ORDER BY BINARY name;
--BINARY付けると 大文字と小文字を区別してソートする文

SELECT * FROM examples ORDER BY 2 ASC;
--ORDER BY文の後に列数を入れると任意列をソートすることが出来る文




```
Apache のアクセスログをマージする

# 複数のログファイルを1つにマージする
日付が4番目の要素の場合のログファイルを、日付順にソートしてマージします

```
$ sort -nmbsk4 log1.log log2.log > marge.log
```

それぞれオプションの詳細は以下の通り。

| オプション | 説明                                                                                                                                                                                                                                                                          |
|------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -n         | 数値順に評価する。行先頭の文字列 (空白が前置されていても良い) を数値文字列として比較する。 数値文字列は、先頭の - 符号 (なくても良い)、 0 桁以上の数字、 そして小数点と 0 桁以上の数字 (なくても良い) からなる。                                                              |
| -m         | 与えられたファイル群をまとめてソートしてマージする。 入力ファイルは事前にそれぞれソートされていなければならない。 マージ動作ではなく、ソート動作を複数ファイルにまとめて行うこともできる。 マージ動作が提供されているのは、 (これでよい場合は) こちらの方が高速だからである。 |
| -b         | 各行の比較の際に、行頭の空白を無視する。                                                                                                                                                                                                                                      |
| -s         | 最終手段比較を無効にし、 全てのフィールドの比較結果が同じだった行の順序を、入力の順序のままにする。                                                                                                                                                                           |
| -k         | -K POS1[,POS2] ソートフィールド指定の POSIX 形式。今後はこちらが推奨される。行の POS1 から POS2 までのフィールドを指定する。 POS2 を含む。 POS2 が省略されたら行末まで。 フィールドと文字位置はそれぞれ 0 から数えはじめる。                                                  |
https://linuxjm.osdn.jp/html/gnumaniak/man1/sort.1.html より引用。
TCP state transition diagram.

高解像度の画像をclassmateが教えてくれたのでメモっておく。 wikipediaのだと情報少なくて。これがいい


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/5330e696-8fb6-570e-1ff7-b92518424b1a.png)

> https://users.cs.northwestern.edu/~agupta/cs340/project2/TCPIP_State_Transition_Diagram.pdf


念の為、僕が見つけた小さい画像もメモっておく

> https://flylib.com/books/en/3.475.1.122/1/
docker-composeのmysqlで起動時に複数DB作るしダンプしたSQLデータも流し込むメモ

## やりたいこと

docker-compose最初の起動時にDB複数作りたいです。

docker-compose.ymlにて、environmentでYSQL_DATABASEにDBを指定するとそのDBを初回起動時に作成してくれますが、複数DBやダンプしたデータの流し込みには対応していません。

MySQL(Docker Official Images)では`/docker-entrypoint-initdb.d`というディレクトリに入っているSQLやシェルスクリプトが初回起動時に実行されるようになっているので、そこに色々入れて実行してもらおうと思います。
MYSQL_DATABASEで作成したDBに対してしか実行出来ないので、作成した別のDBを`USE`します。

**〜やろうとしていることの流れ〜**
1. DB1作る
2. DB1にダンプしたSQL流し込み
3. DB2作る
4. DB2をUSEする
5. DB2ダンプしたSQL流し込み

## docker-entrypoint-initdb.dについて

このディレクトリに入っている`.sh`、`.sql`、`.sql.gz`いずれか拡張子を持つファイルが**アルファベット順**に実行されます。
それ以外の拡張子のファイルは無視されます。


## 構成

### ディレクトリ 

```
├── docker-compose.yml
└── mysql
    ├── Dockerfile
    ├── dbdata
    └── initdb
        ├── 001.ｓｑｌ
        ├── 002.ｓｈ
        └── 003.sql
```

### docker-compose.yml

```yaml:docker-compose.yml
services:
  mysqldata:
    image: busybox
    volumes:
      - ./mysql/dbdata:/var/lib/mysql
  mysql:
    build: ./mysql
    volumes_from:
      - mysqldata
    ports:
      - 4306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=db_1
    volumes:
      - ./mysql/initdb:/docker-entrypoint-initdb.d
```

- MYSQL_DATABASEで`db_1`を作成
- `docker-entrypoint-initdb.d`を`./mysql/initdb`にマウントします

### dockerfile

```dockerfile:dockerfile
FROM mysql:5.7
```
イメージ指定するだけ。

### 001.sql

db_1に流し込むダンプしたSQL。


### 002.sh

```shell:002.sh
#!/bin/sh

echo "CREATE DATABASE IF NOT EXISTS \`db_2\` ;" | "${mysql[@]}"
```

- db_2を作成
- `${mysql[@]}` = 引数付きの`mysql`コマンドを展開しています
    - docker-entrypoint.shで中身が確認出来ます

## 003.sql


```sql:003.sql
USE db_2;
/*以下db_2に流し込むダンプデータ*/
```

`USE`コマンドはファイルをまたぐと無効になるので、ダンプデータの先頭に必要です。

```bash

$ cat header.sql 003.sql > 003_new.sql
// コマンドで合成するなら
```

## おわり
他にもdb_2へのダンプするSQLファイルをtxt形式など(自動で実行されない形式)で設置しシェル上で流し込みを実行するやり方や、csvファイルで設置して流し込みするやり方があるようです。
個人的にはシェル上ででDBの作成だけをするやり方が楽が好きですが、

- DBが増えるとファイルが増えて複雑になる
- .sql.gz形式の時は先頭に`USE`を挿入出来ない

ので使い所は限られるかと思います。
Ruby アンパサンドを用いた安全参照演算子（&.）とは

#はじめに

変数が`nil`の時、メソッドによってはエラーを起こすものがあったりします。

例えば、なんかの処理で値を配列に詰めたものを`each`で回したりするときに、もし`nil`が入ってたりすると、処理が止まってエラーが出る。。なんてことが起こると困りますよね。

そんなときは**ガード節**（関数や繰り返し処理の最初に例外を取り除くように実装する方法）を使って`next if [変数].nil?`とやって、`nil`を回避できたりするんですが、論理演算子を応用した別の方法があるときいて、メモしていきたいと思います。

#アンパサンド（＆）を用いた安全参照演算子
最初に結論から申しますと、`[オブジェクト]&.[メソッド]`というかたちで書きます。

例えば、

~~~ruby
#&を使わないと
ary = [[1,2,3],nil,[5,6]]

ary.each do |element_ary|
  p element_ary.length
end

#=>

#3
#Traceback (most recent call last):
#	2: from test.rb:3:in `<main>'
#	1: from test.rb:3:in `each'
#test.rb:4:in `block in <main>': undefined method `length' for #nil:NilClass (NoMethodError)

#&を使うと
ary = [[1,2,3],nil,[5,6]]

ary.each do |element_ary|
  puts element_ary&.length
end

#=>

#3
#nil
#2
~~~

このように、エラーがおきません。

#原理
実はこれ、論理演算子`&&`が関係しています。

一般的に、論理演算子は以下の特徴を持ってます。

・左から順に評価される
・論理式の真偽が決まると、残りの式は評価されない
・最後に評価された式の値が論理全体の値となる

つまり、`[条件１] && [条件２]`とあったとき、`[条件２]`は`[条件１]`が真のときにのみ、評価されます。`[条件１]`が`nil`~~もしくは`false`~~であった場合、条件２を評価するまでもなく、論理演算子`&&`の結果は`nil`~~もしくは`false`~~になるからです。

[2020/10/27　追記]
コメント欄にて、`条件１`が`false`のときは使えないというご指摘をいただきましたので、修正します。失礼いたしました。。

これを応用して、上記の例を用いて説明すると、以下のように書けます。

~~~ruby
ary = [[1,2,3],nil,[5,6]]

ary.each do |element_ary|
  p element_ary && element_ary.length
end
~~~

`element_ary`に`nil`が入ると`[条件１]`の時点で、論理演算子の処理が終わり、`nil`を返すので、`[条件２]`の`length`メソッドに`nil`が渡ることはありません。

これを省略して以下のように、オブジェクトの後に`&`をつけることでも表現できるのが、安全参照演算子と呼ばれるものだったのです。

~~~ruby
ary = [[1,2,3],nil,[5,6]]

ary.each do |element_ary|
  p element_ary&.length
end
~~~

#おわりに
論理演算子の応用例ということでしたが、あたまいいなあと思いました。
Rails使うときの細かなTips

残しておかないと後で忘れそうな奴を書いておく。随時追記予定。

# putsに色をつける
seedとかrake taskとかで色つけて出したいときに使える小技

```ruby
puts 'aaa'.green
```


# Datadogにエンドポイントでの挙動を細かく出したい (grape使用時)
このリファレンスを参照
https://docs.datadoghq.com/ja/tracing/setup/ruby/#grape

下記の実装例のように、リファレンスのoptionsにある `analytics_enabled` をtrueにするといい感じになる。
grapeとrails両方指定するのがポイント。

実装例

```ruby
  require 'grape'
  require 'ddtrace'

  Datadog.configure do |c|
    c.use :grape, service_name: 'hoge-app', analytics_enabled: true
  end

  Datadog.configure do |c|
    c.use :rails, service_name: 'hoge-app', analytics_enabled: true
  end
```
position争い〜要素が重なった時は？〜

##要素が重なった時に優先順位を決めたい！
###2つの要素にpositionをつけた時、思わぬ形で要素が重なってしまう、、
https://gyazo.com/3c01c80fad0dc299c069baf4a7376225

##原因、2つの要素にpositionをつけた時には、勝手に優先順位ができるので、優先順位を手で書き込むこと

header{
  position: fixed;z-index:10;//z-index:10;を追加
  text-align:center;
}

.tweets-comment{
  width: 30vw;
  background-color: burlywood;
  position: relative;z-index:0; ;//z-index:0;を追加
}
###結論！　z-index:0;の数字が高い　上 z-index:0;の数字が低い　下になります


##直りました。。
https://gyazo.com/61361fe8cfce08d8880a2687e055813a
config内で連想配列を参照,変更する場合


```php:config/○○.php

    'hoge' => [
        'id' => env('KEY'),  
        'secret' => env('SECRET'),  
        'redirect' => env('CALLBACK'),
    ],

````
があった場合

```php:

$id = config('○○.php.hoge.id');//configの値や文字列を$idに代入
config(['○○.php.hoge.id','△△']);//configに代入したい値や文字列を'△△'に記述
```
これでできます

配列のネストした要素をドット記法で取得できるらしいです


以下laravel非公式日本語ドキュメント引用
config関数は設定変数の値を取得します。設定値はファイル名とアクセスしたいオプションを「ドット」記法で指定します。デフォルト値が指定でき、設定オプションが存在しない時に返されます。

https://readouble.com/laravel/6.x/ja/helpers.html
Package manager 一覧整理


# Package managerの一覧整理
パッケージマネージャとは、コンピュータに何のソフトウェアがインストールされたかを記録し、新しいソフトウェアのインストール・新しいバージョンへのソフトウェアの更新・以前インストールしたソフトウェアの削除を容易に行えるようにするプログラムです。

パッケージとは、ファイル群を一つにし、インストールや削除をまとめてできるようにしたものです。

## 各言語

|  Language  |  Type  |  File  |  Package manager  |
| ---- | ---- | ---- | ---- |
|  Python  |  FS  |  requirements.txt  |  pip  |
|  Ruby  |  FS  |  Gemfile  |  Bundler  |
|  JavaScript  |  F  |  package.json  |  npm, yarn  |
|  Node.js  |  S  |  package.json  |  npm, yarn  |
|  Rust  |  -  |  Cargo.toml  |  cargo  |



#### npmとYarnの違い

|    |  npm  |  Yarn  |
| ---- | ---- | ---- |
|  Package-install速度  |  遅い傾向  |  速い傾向  |
|  安全性  |  パッケージの整合性チェックなどはない	 |  パッケージの整合性チェックがあり、安全性が高い  |    |
|  バージョン管理  |  バージョン違いの依存パッケージをインストールしてしまう可能性がある  |  yarn.lockファイルによってバージョン管理が強固になり、バージョン違いの依存パッケージのインストールの心配がな  |    |

Yarnの特徴としては、次のものが挙げられます。

>npmと互換性がある
インストールが速い
セキュリティが高い
強固なバージョン管理が可能

そして、Yarnはインストールの速度がnpmと比べて非常に速い。
npmでは直列でインストールし、Yarnでは並列でインストールできるためです。

さらにセキュリティもYarnは強固で、インストール時にパッケージが不正に変更されていないかなどをチェックサムを用いて検証することができます。

最後にバージョン管理についても優れています。
・yarn.lock
インストールしたパッケージが使用している別のパッケージ（依存パッケージ）のバージョンが明確に書き込まれます。
依存パッケージバージョンの整合性が保たれるので、バージョン不一致でプロジェクトが動かなくなる危険性が無くなります。

## Linux

|  Distibution  |    |  パッケージ形式  |    |
| ---- | ---- | ---- | ---- |
|  RedHat系  |    |  RPM  |  RPM、yum  |
|  Debian系  |    |  deb  |  dpkg、apt  |

#### パッケージ管理システムでできること
・パッケージのインストール、アンインストール、更新

・パッケージ同士の依存関係の解決
パッケージ管理システムでは依存関係を把握し、依存関係が損なわれてしまうようなインストール(あるいはアンインストール)に警告を出します。

・パッケージをリポジトリから持ってきます。
「公式リポジトリ」おかげで、パッケージ名を指定することでシステム側でリポジトリを探して、パッケージを探してくれます。
非公式のリポジトリもありますが、それらはパッケージ管理システムに登録することで使えるようになります。
XcodeのBuild Phasesでmintを実行する時の注意点

XcodeのBuild Phasesにて、SwiftGen のような自動生成ツールや、SwiftLint のような静的解析をかけることがよくあると思います。

最近、それらのツールを Swift CLI 用パッケージマネージャー Mint で管理するようにしました。その時に少しつまづきポイントがあったので記録します。

### Mintfile のあるディレクトリで実行しよう！
Mintfile でパッケージを指定している場合、Mintfile の存在するディレクトリで mint を実行する必要があります。そうしないと次のように mint の実行が失敗します。

```sh
mint run SwiftLint
# 👉  🌱  "swiftlint" package not found
```

Build Phases スクリプト実行時のカレントディレクトリに Mintfile がないような場合は、Mintfile のディレクトリに移動してから実行するようにしましょう。 

### 環境変数SDKROOTを解除しよう！
`mint run` で実行するツールがまだインストールされていない場合は、インストールするところから始まります。この時、次のようなエラーが発生する場合があります。

```sh:SwiftLintインストール時の例
🌱 Cloning SwiftLint 0.40.3
🌱 Resolving package
/private/var/folders/m7/c2p5rh6d73g56sqnz33wrzsw0000gn/T/mint/github.com_realm_SwiftLint: error: manifest parse error(s):
<unknown>:0: warning: using sysroot for 'iPhoneSimulator' but targeting 'MacOSX'
<unknown>:0: error: unable to load standard library for target 'x86_64-apple-macosx10.15'
```

これは、SwiftLint を macOS 向けにビルドしようとしているのに、利用するSDKがiOSシミュレーター用になっているためです。具体的には、XcodeでiOSのアプリをビルドする場合、Build Phasesでは環境変数 `SDKROOT` がiOSシミュレーター用のSDKパスが指定されています。例えばこんな感じです。

> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.1.sdk

スクリプト実行の間だけ、環境変数 `SDKROOT` を解除することで回避することができます（が、後述のxcrunを使う方法がベターです）。

```sh
unset SDKROOT
mint run swiftlint
```

(2020/11/24追記)
@uhooi さんに、より安全な方法として、xcrunコマンドで使用するSDKを指定する方法を教えていただきました。こちらをオススメします。

```sh
xcrun --sdk macosx mint run swiftlint
```
CognitoにGoogleでサインインしたときメアド以外のGoogleの情報を取得したい

ほぼ自分用メモ。

# 前提

CognitoにGoogleでサインインするとこまではできる。
GoogleのトークンをCognitoのカスタム属性に入れるなりして参照可能な形にできる。

# やりたいこと

https://www.googleapis.com/admin/directory/v1/users/
このAPIを叩いてログインユーザーのGoogleアカウントの情報を引っ張りたい。
（他のGoogle APIでも大体やり方は同じじゃないかと思います）

# やりかた

### APIの仕様を調べる

#### 目的のAPIを探す。

今回使うのはAdminSDKのAPIなのでここから探します。
[Google API Reference](https://developers.google.com/admin-sdk/directory/v1/reference)

使いたいAPIはこちら。
[Users: get](https://developers.google.com/admin-sdk/directory/v1/reference/users/get)
![スクリーンショット 2020-10-22 112007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116428/c472f22b-ecc2-d5f2-231e-998dc8fd4707.png)
※右側の「Try this API」で欲しい情報を取得できるか試しておくとよい。

#### このAPIを使用するために必要なスコープを確認する

ちょっと下にスクロールするとこれがあるので、ScopeのURLをメモる。
今回は情報を取得するだけなので__readonly__だけでよい。
![スクリーンショット 2020-10-22 112304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116428/24b6134a-6570-38c7-89fb-a1d00926819f.png)

### GCPでAPIを使えるように設定する

#### ライブラリからAPIを有効にする

[AdminSDK](https://console.cloud.google.com/apis/library/admin.googleapis.com)を使うので有効にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116428/e18f4d5b-6562-ef2e-b80c-f17c850e6aed.png)

#### OAuth同意画面にスコープを追加する

必要なスコープのみチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116428/4e89d704-8a10-ea19-1d46-6c352e10a185.png)




### Cognito IDプロバイダーの承認スコープに追記する

API仕様書からメモったスコープのURLをそのままぺたっと貼るだけ。
複数指定する場合は半角スペース区切りで貼っていく。
![スクリーンショット 2020-10-22 112602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116428/65855b82-32c1-364c-81fb-d4dfc4ba9e3d.png)


# おわり

あとはトークンを使ってLambdaなり何なりでAPIを叩いて情報を引っ張ってよしなに使うとよい。
Microsoft Ignite 2020 Power Platform アップデート日本語版を観てみた

# TL;DR

- 2020/9/24にYouTubeライブ配信された[Microsoft Ignite 2020 Power Platform アップデート日本語版](https://www.youtube.com/watch?v=dpkJIM602SY)について概要を記載します。録画が公開されています。

# 概要

## Power Apps + Teams連携

https://www.youtube.com/watch?v=dpkJIM602SY&t=0h07m42s

- 経費精算のデモ、質疑など

## Power Appsの思想

https://www.youtube.com/watch?v=dpkJIM602SY&t=0h48m44s

- 連携させるのではなく一緒に作っていく世界にしていこう
- 市民開発者がローコード、プロの開発者が難しいところを設定コードを書いていき市民開発者が書いたものも理解していく

    つまり**市民開発者とプロの開発者が手を取り合っていく**ことが大事！

    **TOYOTAの例**
    アプリケーションが可視化されることで管理されるようになる！
    1. 最初は市民開発者でアプリを作成する
    2. 自動で作成されたアプリを登録するようにIT側（プロの開発者）がメールする（もちろんPowerAppsで自動で！）
    3. もし登録しなかったら？申請して登録しないと削除されるようになっている
    4. ちゃんと登録したら、IT側で管理できるようになるし、類似アプリについて提案できる
    5. このことで相乗効果でアプリの作成と共用化が進んでいく
    6. アプリが小さいうちは作成した市民開発者が管理しなければいけない
    7. IT側としてはトレーニングと質疑に乗る責任がある
    8. 最終的には利用者も増えてくるアプリもある。そうなったアプリについてはIT側が巻き取って全体での共用アプリとして管理していく！

        💡 作成の敷居をさげ市民開発者とIT開発者（プロの開発者）が手を取り合って開発するよい事例！

## Power Appsの求人

https://www.youtube.com/watch?v=dpkJIM602SY&t=0h56m40s
## Power Platform + GitHub

https://www.youtube.com/watch?v=dpkJIM602SY&t=0h58m17s
## Power Platform + AzureDevOps

https://www.youtube.com/watch?v=dpkJIM602SY&t=1h01m58s

## Power Platform + AzureAPI

https://www.youtube.com/watch?v=dpkJIM602SY&t=1h05m38s

## Power AutoMate DeskTop

https://www.youtube.com/watch?v=dpkJIM602SY&t=1h09m08s

- デスクトップを自動化（15年ほど実績がある欧州で有名な会社の製品が元になっている）
- 公開プレビューでリリース

    手順：https://qiita.com/nakaamino/items/7460ea11601f880d8a90
    　　　
- ローコードな開発環境（マウス操作メインで構築できる）　※要素認識している模様
- いろんなシステムへアクセスできる様々なコネクタを用意。　※Excelなどは専用のアクション
- SAP、ターミナルアプリ、JAVA、Citrixにも対応
- 同一PCで並列処理やマルチタスクに対応。複雑なケースにも対応する例外処理
- Power Automateクラウドサービスとの連携による完結したシナリオへの対応

## Power AppsとPower Automateの内部統制機能

https://www.youtube.com/watch?v=dpkJIM602SY&t=1h31m32s

- データの保護（暗号化）など

## Power Virtual Agents

https://www.youtube.com/watch?v=dpkJIM602SY&t=1h42m59s

- チャットボットをUI操作で簡単に作成できるサービス

## 作成した経理ちゃんのデモ

https://www.youtube.com/watch?v=dpkJIM602SY&t=2h04m42s

## Bot Frameworkの更新

https://www.youtube.com/watch?v=dpkJIM602SY&t=2h06m18s

- Bot Framework Composer
- アダプティブダイアログを使うと会話への割り込みができる
- 返答を柔軟にできるように
- API連携、自然言語処理
秀丸エディタ を見やすい（ダークカラー＆文字は目に優しく）表示にする方法（他ブログ様を自分用にメモ） 

#背景の変更
「その他」>「ファイルタイプ別の設定」
「設定の対象」>「デザイン」をクリック
「リセット／統一」ボタン>「黒い背景の配色にリセットする」をクリック

#文字色の変更
「プロパティ」枠の「文字の色」の領域を選択
「色の指定」のウィンドウで白（＋黄色っぽい色）を選択
背景も同様に調整

結果：黒／白のコントラストを弱めた設定にできた。

この設定は、
[秀丸エディタをコンソール風黒い背景色に設定変更する](https://ameblo.jp/hal7pi/entry-12350676249.html "はるなぴ日記")を参考にした。
fastlaneでiOSアプリがアップロードできなくなった(2020/10,version 2.150.0)

fastlaneでiOSアプリがアップロードできなくなりました。
結論からいうと、`2.160.0`以上のバージョンにアップデートすると解消されました。

## 現象
fastlaneでiOSアプリをアップロードしようとすると、途中で処理が止まってタイムアウトになる。

```console
[11:06:42]: Loading './fastlane/metadata/zh-Hans/release_notes.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/support_url.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/marketing_url.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/promotional_text.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/name.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/subtitle.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hans/privacy_url.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/description.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/keywords.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/release_notes.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/support_url.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/marketing_url.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/promotional_text.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/name.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/subtitle.txt'...
[11:06:42]: Loading './fastlane/metadata/zh-Hant/privacy_url.txt'...
[11:06:42]: Loading './fastlane/metadata/copyright.txt'...
[11:06:42]: Loading './fastlane/metadata/primary_category.txt'...
[11:06:42]: Loading './fastlane/metadata/secondary_category.txt'...
[11:06:42]: Loading './fastlane/metadata/primary_first_sub_category.txt'...
[11:06:42]: Loading './fastlane/metadata/primary_second_sub_category.txt'...
[11:06:42]: Loading './fastlane/metadata/secondary_first_sub_category.txt'...
[11:06:42]: Loading './fastlane/metadata/secondary_second_sub_category.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/first_name.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/last_name.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/phone_number.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/email_address.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/demo_user.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/demo_password.txt'...
[11:06:42]: Loading './fastlane/metadata/review_information/notes.txt'...
```
必ずここで処理が止まりタイムアウトになります。

## 解決
fastlaneのバージョンを2.160.0以上にあげることで解決します。
[修正PRはこちらになります](https://github.com/fastlane/fastlane/pull/17235)
外部キーを持つデータの削除方法

#環境
この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

#前提
３つのモデルを作成し、以下の状況となっています。

User / ユーザー
Report / レポート
Comment / ユーザーとレポートの関連付けテーブル

コメントがついているレポートの削除を行う際に、以下のエラーが発生しました。

##エラー発生
ActiveRecord::InvalidForeignKey in ReportsController#destroy
外部キーエラー
![スクリーンショット 2020-10-22 10.00.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693227/cb3a90ff-1395-db25-d4a6-748a0d2e8b20.png)

何が原因なのか、その解決策を考えます。

##原因
レポートの削除を行う際に、コメントテーブルのユーザーとレポートのidの値がなくなることが原因と判断。（外部キー制約のため）
ユーザーとレポートのidの関連付けがなくなったものは、コメントも削除できるようにしたい。

##解決策
```dependent: :destroy```を```Userモデル```と```Reportモデル```に記述する。
この記述により、親モデル（Report)を削除する際に、その親モデルに紐づく「子モデル(Comment)」も一緒に削除できる」ようになります。

##検証

```ruby:app/models/user.rb
class User < ApplicationRecord
  has_many :reports
  has_many :comments, dependent: :destroy
end
```
```ruby:app/models/report.rb
class Report < ApplicationRecord
  belongs_to :user
  has_many :comments, dependent: :destroy
end
```
無事解決しました！
以上です。
同じような悩みや壁にぶつかっている方のお役に立てれば幸いです！

#参考
下記を参考にしたので、より深く内容を理解したい方は、見てみてください！
https://qiita.com/Ushinji/items/650fa295a3054d2fe582
https://qiita.com/ITmanbow/items/2170ccaceafd5d401df8
https://qiita.com/Tsh-43879562/items/fbc968453a7063776637
Nuxtjsでgenerate時に、公開しているページのtitleとurlのリストを作成する

**※力技での解決法です。絶対もっと良い方法があるはず。**

発端としては、
>フロントのNuxt側でデータを受け取るだけでなく、
>外部に渡せる形で書き出せないか？

と思ったこと。

ググったけど、あまり情報が見当たらず、
「そもそもこの発想自体がズレてるのでは？」と思えてきたが、
とりあえず作ってみた。

内容としてはシンプルに、
``nuxt generate``で生成された
distの中のhtmlファイル群をスクレイピングすること。

まずはささっとモジュール作成。

```generate-pages-info.js
const {resolve} = require('path')
const {readFileSync, writeFileSync} = require('fs')
const requireContext = require('require-context');

module.exports = async function () {
  const {rootDir, generate: {dir: generateDir}} = this.options
  const fileName = 'pages.json'

  this.nuxt.hook('generate:done', async () => {
    const dir_path = resolve(rootDir, generateDir);
    const html_files = {};
    const page_paths = requireContext(dir_path, true, /\.html$/).keys();
    for (const page_path of page_paths) {
      const name = page_path
        .split("./")
        .pop()
        .split(".")
        .shift();

      html_files[name] = await getPageInfo(dir_path, page_path);
    }

    const pages_json = JSON.stringify(html_files);
    const generate_file_path = resolve(rootDir, generateDir, fileName);
    writeFileSync(generate_file_path, pages_json);
  })
}

async function getPageInfo(dir_path, page_path) {
  const file_path = resolve(dir_path, page_path);
  const content = await readFileSync(file_path, "utf-8");
  const page_title = content.match(/<title>(.*?)<\/title>/)[1];
  const page_metas = await pageMetas(content);

  return {
    "title": page_title,
    "metas": page_metas,
    "url": page_path
  }
}

async function pageMetas(content) {
  const regex_text = /<meta[^<>]*?name=\"(.*?)\"[^<>]*?content=\"(.*?)\"/;
  const metas = content.match(new RegExp(regex_text, 'g'));
  let result = [];
  for (const meta of metas) {
    const match = meta.match(new RegExp(regex_text));
    result.push({
      "name": match[1],
      "content": match[2]
    })
  }
  return result;
}
```

nuxt.config.jsにモジュール登録。

```nuxt.config.js
  modules: [
    '~modules/generate-pages-info.js'
  ]
```

あとは``nuxt generate``して、
公開フォルダ（デフォルトではdist）にpages.jsonが出来ていればOK。

パーサー使えばもっと上品にできるかも。

- - -

非同期処理関連が結構躓いた。
当たり前だけど、同じサイトだろうが別ファイルの読み込みは時間かかるのね。
Elastic File Systemをざっくり知る。

#この記事について
Elastic File Syestemについてざっくり説明する営業資料記事的な感じ。
まだEFSを触ったこと無い人、調べてる途中の人、良さがわからんって人向けです。

「今からNFSインスタンスを構築するって？ならElastic File Systemを試してみない？」

#Elastic File Systemってなぁに
Amazon Web Services社が提供する**フルマネージド型のファイルシステム。**

・容量の心配無し(サイジング不要の従量課金)。
・メンテナンスの心配無し。
・EFSへのファイル伝送時は暗号化されてて高セキュア。

という、**最強のファイルシステム。**

EBSと比べると費用が3倍だったり、IOPS速度は汎用SSDと比べてちょっと遅かったり、
バックアップにはAmazon Backupの設定が必要だったりするけど、
そんなデメリット消し飛ばすくらいメリットや構成案の幅が増えるサービスである。

長年の課題だった**Autoscaling時の先祖返り対策がこれ一発で解決した。**
(今までは別途NFSインスタンス立てて、それのマネージドどうするねんとかサイジングどうするねんとかやらないといけなくて辛かった)

#そもそもファイルシステムってなによ
調べた中で一番分かりやすかったのは以下記事。

[【ざっくり概要】Linuxファイルシステムの種類や作成方法まとめ！](https://eng-entrance.com/linux-make-filesystem)

その上で、さらに自分でまとめた図解が以下。
このファイルシステムは通常サーバー起動時に自動でマウントされているので、
普段は意識することが無い。
このファイルシステムが無いと、「ディレクトリどこ？」「ファイルどこ？」って状態になっちゃう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536700/d235f773-ed9c-f975-2297-c29af82f719d.png)

その上で、Autoscalingの先祖返りっていうのがどういう状態かっていうと以下。
折角負荷分散でELBをかましているのに、その下のコンテンツが古いっていう状態。
それぞれのファイルシステムは各々のローカルホストEBSを見にいってる状態なので、
見る人によってコンテンツが新しかったり古かったりするのはとてもマズイ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536700/eebc2072-17f1-a028-e125-16cfc67c7ed0.png)

###そんな時の救世主がElastic File System

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536700/acde6ac0-d5d8-bf11-116e-8c13efab5145.png)
これであれば、見にいくディレクトリは1つだけになり、左右どちらのインスタンスでコンテンツを更新したとしても左右のインスタンスは同じものを返す。
**インスタンスがいくつ増えようとも、いつ増えようともEFSにマウントさえしていれば先祖返りは発生しない。**
勿論、fstabとかで起動時にマウントする設定とかが必要になってくるんだけど、そこは誰かの記事見て実際に作ってみて欲しい。

#まとめ
Elastic File Systemは可能性の塊のようなサービスなので、まだ触ったこと無い人、提案したことが無い人は是非とも触れてみて欲しいな。
ownCloudとかオンラインストレージをこれで構築できないか検討中。
bxsliderの使い方

#bxslider
[bxsliderのダウンロードはこちら](https://github.com/stevenwanderski/bxslider-4)
GithubからZIPファイルをダウンロードして、スライドが使えます。

![スクリーンショット 2020-10-22 11.04.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633943/61db01f2-ca19-8cda-1adb-3dda0e0d6b88.png)

```html:HTML
<div class="bxslider">
  <div><img src="img/01.jpg"></div>
  <div><img src="img/02.jpg"></div>
  <div><img src="img/03.jpg"></div>
  <div><img src="img/04.jpg"></div>
  <div><img src="img/05.jpg"></div>
</div>
```

```js:JavaScript
$('.bxslider').bxSlider({
  auto: true,
  autoControls: true,
  stopAutoOnClick: true,
  pager: true,
  slideWidth: 600
});
```
jQueryを使ってテキストボックスにフォーカスを当てる方法

###jQueryを使ってテキストボックスにフォーカスを当てる方法を見ていきましょう

以前に私が書いた要素の表示、非表示のコードをそのまま使っていきます。
まだ見ていない方はこちらからご覧ください。
https://qiita.com/pikarunn/items/ce8dc83d5baa4ce5fd60

###完成形はこちらです
要素を表示した時にフォーカスが当たり、カーソルを当てなくても文字を打てるようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726659/3949df1e-387d-2d4b-42f0-188cd5214436.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726659/b4449db1-0a98-ff7c-1d29-83d196e5e8d6.png)


以前に使ったコードはこちらです

```javascript:header.script

$("#input").toggle();

$("#button").click(function() {
    $("#input").toggle();
});
```

```html:header.html
<button id="button">表示 非表示ボタン</button>
<input id="input" placeholder="表示させたい要素">
```

このコードに一行足すだけでテキストボックスにフォーカスを当てることができます

```javascript

$("#input").focus();
```

`.focus`を`("#input")`につけることで、テキストボックスが表示されたと同時にフォーカスも当たるようになり、カーソルを当てなくても、文字を打てるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726659/b4449db1-0a98-ff7c-1d29-83d196e5e8d6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726659/e1826cfa-a0fb-9301-fc5f-2ba160b24027.png)


#まとめ
以上で実装完了です。
このようなフォーカスを当てる機能は項目を入力する際などに使うと便利です。
また、フォーカスを当てることでユーザーの手間を省くことができます。
このような時に便利なので是非実装してみてください！
パス中の\使用に気をつけよう。

### エラーコード

```python:selenium.py
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome("C:\Users\Hoge\chromedriver_win32\chromedriver")
driver.get("https://www.google.com/")
```

こんな感じでセレニウムしようとしたら、以下のエラー発生。

```
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape
```

初心者のわたしは、googleさん検索でなんとか解決策を見出した。

単純な話だった。

webdriverを指定した文字列中の、`\`が問題で、`\`は文字列中でエスケープに使われるため、きちんとしたパスが通ってなかった。
いくつか解決策はあり、`\\`を使う。もしくは、Windows系でもXP頃からは`/`もパス区切り文字として使用可能。
~~もしくは、Win系でもpythonなら`/`を使って、よしなに処理してくれる様子。~~（コメント頂き修正しました）
なので、後者を使用した。

### 解決コード

```python:selenium.py
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome("C:/Users/Hoge/chromedriver_win32/chromedriver")
driver.get("https://www.google.com/")
```

無事、chromeドライバが立ち上がりました。良かった。
【AWS CLI】ロールを切り替えて別のアカウントにあるDockerイメージを取得する

#背景
AWSを使用して別のアカウントのECRにあるDockerイメージを取得したかったため
AWS CLIによるロール切り替えについていろいろ調べた結果をまとめました。


#前提条件
#####1.アカウントAに欲しいDockerイメージがある
#####2.アカウントBに存在するEC2にアカウントAのDockerイメージをPULLする


#作業の流れ
####1.アカウントAのIAMからアカウントBで使えるロールを作る
#####1-1.信頼されたエンティティの選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195655/e2dee093-98e9-3221-b268-ae27aa4f6073.png)

※アカウントIDは__アカウントBのID12桁__を入力する

#####1-2.Attachアクセス制限ポリシー
　下記を付与する
　・AmazonEC2ContainerRegistryFullAccess
　・AmazonEC2FullAccess
　・AmazonEC2RoleforSSM(EC2にセッションマネージャーで接続するために使用)

#####1-3.ロールの作成
　・タグ名は入力しなくてもよい
　・ロール名はswitch-roleなどわかりやすい名前が良いかと。
　・作成後、作成されるロールのARNをコピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195655/6c7ee6fb-8cfc-8cfe-389e-90d19a72d63b.png)

####2.アカウントBで実際にロールを切り替えるための準備をする
#####2-1.アカウントBでログインしてEC2のIAMロールを設定する
EC2に付けているIAMロールを開いて信頼関係タブから信頼関係編集ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195655/e5c471eb-26c4-c28e-cb90-c6758e042ba3.png)

青枠に作成したロールのARNを貼り付ける

#####2-2.EC2にログインして、awscliの設定をする
EC2にログイン（今回はセッションマネージャーを利用）
ログイン後、管理者権限（su）に切り替え

######2-2-1.切替後のプロファイルを登録する

```
[root@ip-10-10-10-131 ~]# aws configure --profile dev
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-1
Default output format [None]: json
```
ここでは、切替後の名前を__dev__と定義する
設定後、configureファイルを直接開く

```
[root@ip-10-10-10-131 ~]# vi .aws/config
```
「role_arn」と「source_profile」を追記する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195655/efd91376-c9a5-64cc-e489-1ad7a3f40c8f.png)

######2-2-2.認証情報を登録する

```
[root@ip-10-10-10-131 ~]# vi .aws/credentials
```
credentialsファイルを新規作成する

```
[default]
aws_access_key_id = xxxxxxxx
aws_secret_access_key = xxxxxx
```

アクセスキーとシークレットアクセスキーはアカウントBで使用できるユーザーのものを登録する

####3.実際に試してみる
#####3-1.ロールを切り替えない場合

ECR（Amazon Elastic Container Registry）にログイン

```
[root@ip-10-10-10-185 ~]aws ecr get-login --region ap-northeast-1 --no-include-email > dlogin.sh
[root@ip-10-10-10-185 ~]chmod +x dlogin.sh
[root@ip-10-10-10-185 ~]./dlogin.sh
```
リポジトリの取得

```
[root@ip-10-10-10-185 ~]docker pull 'リポジトリのURI'
Error response from daemon: Get 'リポジトリのURI' no basic auth credentials
```
という風に認証関係でエラーとなる


#####3-2.ロールを切り替えた場合
ECR（Amazon Elastic Container Registry）にログイン

```
[root@ip-10-10-10-185 ~]aws ecr get-login --region ap-northeast-1 --no-include-email --profile dev > dlogin_dev.sh
[root@ip-10-10-10-185 ~]chmod +x dlogin_dev.sh
[root@ip-10-10-10-185 ~]./dlogin_dev.sh
```
リポジトリの取得

```
[root@ip-10-10-10-185 ~]docker pull 'リポジトリのURI'
ダウンロード中..
・
・
・
・
Digest: sha256:0xx
Status: Downloaded newer image for 'リポジトリのURI'
```

取得したイメージの確認

```
[root@ip-10-10-10-185 ~]# docker images
REPOSITORY     TAG                 IMAGE ID            CREATED             SIZE
リポジトリ名    latest              xxxxxxxxxxxx        13 months ago       5.37GB
```

#最後に
今回はDockerイメージの取得に特化したが、ロールの切り替えはCodeCommitからドキュメントの取得などにも使えるので
備忘録としてaws cliの切り替えの手順をまとめました。

#参考
[AWS CLI のprofileを簡単に切り替える](http://uorat.hatenablog.com/entry/2015/10/16/023008)

[AWS CLI でロールを切り替えて作業する]
(https://nasrinjp1.hatenablog.com/entry/2018/04/06/215737)
next.jsでurl pathを取得したい

共通のコンポーネント使っててpath別で処理したいときあるよね。
必要な度にググってるのでメモ。

## だめな例
SSRされたときはdocumentがないので下記ではだめ。

```js:pages/my-component.js
import React from 'react';

const MyComponent = props => {
  console.log(document.location);
...
```

```
Server Error
ReferenceError: document is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.
```

## だめな例２
client sideで使えって怒られた

```js:pages/my-component.js
import React from 'react';
import Router from 'next/router';

const MyComponent = props => {
  console.log(Router.pathname);
...
```

```
Server Error
Error: No router instance found.
You should only use "next/router" inside the client side of your app.
```

## いい例
hookが提供されてるからこれ使おう

```js:pages/my-component.js
import React from 'react';
import { useRouter } from 'next/router';

const MyComponent = props => {
  const router = useRouter();
  console.log(router.pathname); // '/example/mycomponent'
...
```


## 参考
next/router | Next.js - https://nextjs.org/docs/api-reference/next/router
アジャイルソフトウェア開発

# 迅速かつ適応的にソフトウェア開発を行う軽量な開発手法群の総称[^1]

[^1]: https://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA

---

## アジャイルソフトウェア開発宣言

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/a0744569-a442-a57b-c2a4-36eddc7a20bc.png)


https://agilemanifesto.org/iso/ja/manifesto.html

---

## アジャイル

- 個人と対話
- 動くソフトウェア
- 顧客との協調
- 変化への対応

---

## デイリー
- 昨日やったこと
- 今日やったこと
- 困っていること
DBコネクションプールをgolangで実現

#初めに
GCPをつかっていてコネクションプールの話に行き着きました。
「最大コネクション数が100を超えました」というエラーが発生。
なぜコネクション数が多くなってしまうのかを調べ、見つけた対処方法となります。

#環境
クラウド：GCP
WEBサーバーをVue/CloudRun
APIサーバーをGolang/CloudRun
DBサーバーをMySQL/CloudSQL

#原因

```
APIを叩くたびにAPIサーバーとDBサーバー間で新しいコネクションができているから
```

と判明した。

つまり、コネクションの使い回しができていなかった。

#対策

database.sqlの以下のメソッドを使用し、コネクションプールの設定を行う。
また、ORMでもコネクションプールできるらしい。

| メソッド名| 説明 | 
|:-:|:-:|
|func (db *DB) SetMaxOpenConns(n int)   |接続の最大数を設定。 nに0以下の値を設定で、接続数無制限。   | 
|func (db *DB) SetMaxIdleConns(n int)   |コネクションプールの最大接続数を設定。   |   
|func (db *DB) SetConnMaxLifetime(d time.Duration)   |接続の再利用が可能な時間を設定。dに0以下の値を設定で、ずっと再利用可能。   |   

以下のようにして実装。

```go:DBconnection
func NewLocalDBConnection() error {
	/* ===== connect datebase ===== */
	// user
	user := os.Getenv("MYSQL_USER") 
	// password
	password := os.Getenv("MYSQL_PASSWORD") 
	// connection database
	database := os.Getenv("MYSQL_DATABASE") 
	// connection host
	host := "localhost" 
	// connection port
	port := "3306" 

	var err error
	DB, err = setupDB("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, password, host, port, database))
	if err != nil {
		return fmt.Errorf("sql.Open: %v", err)
	}

	return err
}

//this function is a function for connection pooling
func setupDB(Driver string, dsn string) (*sql.DB, error) {
	db, err := sql.Open(Driver, dsn)
	if err != nil {
		return nil, err
	}
	//コネクションプールの最大接続数を設定。
	db.SetMaxIdleConns(100)
	//接続の最大数を設定。 nに0以下の値を設定で、接続数は無制限。
	db.SetMaxOpenConns(100)
	//接続の再利用が可能な時間を設定。dに0以下の値を設定で、ずっと再利用可能。
	db.SetConnMaxLifetime(100 * time.Second)

	return db, err
}
```
【TypeScript】Reactでちゃんと型を指定したい

コールバックなどの型を`any`にしないために。

Reactの範囲だけでなく一般のtsの記述もあります。

Reactは名前`React`でimportしていることとします。

# `props`, `state`
コンポーネント作成時にpropsで受け取る型とstateの型を指定する。

```tsx:
// ジェネリクスで<propsの型, stateの型>を指定する
class Hello extends React.Component<{user: string}, {greeting: string}> {
  constructor(props: {user: string}) {
    super(props);
    this.state = {greeting: 'Good morning'};
  }

  render() {
    return (<p>{this.state.greeting} {this.props.user}!</p>)
  }
}

// 使う側
class TestComponent extends React.Component {
  render() {
    const elem: React.ReactNode = <p>Hello React</p>
    return (
      <Hello user="kide"/>
    )
  }
}
```

事前に`type`を宣言しておくこともできる。

```tsx:
type userInputPropsType = {
  name: string,
  onNameChanged: (arg0: React.ChangeEvent<HTMLInputElement>)=>void
}
class UserInput extends React.Component<userInputPropsType, {}> {
  render() {
    return (
      <input value={this.props.name} onChange={this.props.onNameChanged} />
    )
  }
}
```

# コールバック
イベントは`React.ChangeEvent`, `React.MouseEvent`などで引数を受け取る。
ジェネリクスで要素を指定するが、ちゃんと指定しないと`target.value`などを参照できなくなる。

受け取れるイベントの確認は[公式ドキュメント](https://reactjs.org/docs/events.html)で。

```tsx:
class UserButton extends React.Component<{}, {userName: string}> {
  nameChanged = (event: React.ChangeEvent<HTMLInputElement>)=>{
    this.setState({userName: event.target.value});
  }

  buttonPressed = (event: React.MouseEvent<HTMLButtonElement>)=>{
    alert(this.state.userName);
  }

  render() {
    return (
      <div>
        <input onChange={this.nameChanged} />
        <button onClick={this.buttonPressed}>Click!</button>
      </div>
    )
  }
}
```


# 要素の受け取り
`children`で描画する時は`React.ReactNode`型で受け取る。

```tsx
// propsでchildrenを受け取るようにする。
// 他のプロパティも受け取れる(color)
class ColorPane extends React.Component<{children: React.ReactNode, color: string}, {}> {
  render() {
    return (
      <div style={{background: this.props.color}}>
        {this.props.children}
      </div>
    )
  }
}

// 使う側
class TestComponent extends React.Component {
  render() {
    const elem: React.ReactNode = <p>Hello React</p>
    return (
      <div>
        <ColorPane color="blue">
          <h1>Blue Pane</h1>
          <p>This is blue pane text</p>
        </ColorPane>

        <ColorPane color="red">
          <h1>Red Pane</h1>
          <p>This is red pane text</p>
        </ColorPane>
      </div>
    )
  }
}
```
Navigation 2.3.1でonNavDestinationSelectedを使ってActivityに遷移できない

- 2020/11/10 更新  
この問題について修正されており次のバージョンである 2.3.2 で修正されるようです  
https://android-review.googlesource.com/c/platform/frameworks/support/+/1489583/

AndroidX の [Navigation 2.3.1](https://developer.android.com/jetpack/androidx/releases/navigation#2.3.1) で `MenuItem#onNavDestinationSelected` を使用して Activity へ遷移させると遷移が正しくできない問題に遭遇しました。
Fragment への遷移ではこの現象は発生しません。


## Workaround

Issue Tracker に報告したところ、バグ扱いになったのでライブラリ側で対応してくれるのを待ってもいいかもしれません。
https://issuetracker.google.com/issues/171364502

Activity への遷移の時は `navigate` を使用するようにすれば回避することができます。

```
override fun onOptionsItemSelected(item: MenuItem): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    if (navController.currentDestination?.parent?.findNode(item.itemId) is ActivityNavigator.Destination) {
        navController.navigate(item.itemId)
        return true
    }
    return item.onNavDestinationSelected(navController) ||
            super.onOptionsItemSelected(item)
}
```
Atomでの"No kernel of grammar Python found"エラーの解決方法

# はじめに
正常に動いていたatom, Hydrogenが，突然`No kernel of grammar Python found`と真っ赤なエラーメッセージを吐き出したときの対処方法です。


# 解決方法

```bash
jupyter kernelspec list --json
```

上記コマンドでkernlspecを表示させます。以下のような回答が得られます。

```bash:出力例
{
  "kernelspecs": {
    "python3": {
      "resource_dir": "/Users/taka/Library/Jupyter/kernels/python3",
      "spec": {
        "argv": [
          "/opt/anaconda3/bin/python",
          "-m",
          "ipykernel_launcher",
          "-f",
          "{connection_file}"
        ],
        "env": {},
        "display_name": "Python 3",
        "language": "python",
        "interrupt_mode": "signal",
        "metadata": {}
      }
    }
  }
}
```

これをコピーし，**atom > Settings > packages > Hydrogen** の下にある`Startup Code`の欄にこれを貼り付けます。

以上でエラーは解決されます。

# 最後に
atomからjupyter kernelに正しくアクセスできなかったのが問題だったようです。上記の設定で正しくkernelにアクセスできるようにすれば解決されると思います。

個人的な感想になりますが，atomはちょくちょくこういったエラーが発生するなぁ，と。未だ見ぬ大地・vscodeに移民したほうが良いのかな・・・。
matlabでラズパイにつないだ温度センサからデータをもってくる。確度は±0.1℃


　テレビの天気予報では、0.1℃単位で温度が表示されます。温度計は、とうぜん気象庁の校正を受けていなければ、うそっこのデータになります。校正といえば、費用と時間がかかります。ここでは、±0.1℃がメーカによって保証？されているTMP117を使います。
　データシートに書かれている特徴です。

> ASTME1112およびISO 80601の電子医療体温計の要件を満
> たすように設計されています。較正不要で、-20°C～50℃
> の温度範囲にわたって0.0078℃の分解能、最大±0.1℃
> の精度で16ビットの温度結果を提供します。

###TMP117のおもなスペック

- 動作電圧　1.8～5.5V
- 分解能　16ビット、LSBは0.007812℃ 
- 動作温度範囲　 -55～150℃
- 確度
 - -20～+50℃ の範囲で±0.1℃ （最大値）
 - -40～+100℃ の範囲で±0.2℃ （最大値）
 - -55～+150℃ の範囲で±0.3℃ （最大値）
- 消費電流　1Hzの変換サイクルで3.5uA
- インターフェース　I2C（1～400kHz）
- データ長　2の補数形式の16ビット
- 平均化出力が可能
- 温度設定のアラートあり

###評価ボードを加工
　とても小さいパッケージなので、手はんだは困難です。評価ボード[TMP117EVM](https://www.ti.com/jp/lit/ug/snou161/snou161.pdf)を入手しました。使用例は、こちらを[参照](https://www.denshi.club/pc/measure/tmp117.html)してください。
![IMG_3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/fe35cfdc-d578-5b97-182e-8a5d199fdae4.png)

　先端を切り離して使います。
![IMG_3989.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/66641c4a-70c6-a790-7299-7e8c15a6400f.png)

　ケーブルをはんだ付けし、先端にコネクタを圧着し、ラズパイとの接続に使います。
![IMG_3999 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/79dc409a-7778-23c6-72f1-6c1631eab2d4.png)
###接続
　SDAをラズパイの3番（GPIO2）、SCLを5番（GPIO4）に接続します。GNDはGNDへ、V+は3.3Vへ接続します。アラート出力のALRTは、今回使いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/85b14af5-c212-c961-faec-dc249deeb64e.png)

###スレーブ・アドレス
　切り離したセンサ部分の基板上にはR16が取り付けられている（ADD0がGNDに接続）ので、スレーブ・アドレスは0x48です。
　プログラムで確認します。ラズパイのセットアップは、前回の[記事](https://qiita.com/jamjam/items/02101b2d177e10d210a6)を参照してください。

```matlab
clear all
rpi = raspi('192.168.111.114', 'pi', 'raspberry');
for i = 1:length(rpi.AvailableI2CBuses)
   scanI2CBus(rpi, rpi.AvailableI2CBuses{i})
end
```
　0x48が返りました。

###プログラム
　ConfigurationRegister に各種設定を書き込みます。データシートには、factory default reset = 0220hと書かれています。
　Conversion cycle bitが'100'です。変更する必要はなかったのですが、'000'にしました。
　Conversion averaging modesは'01': 8 Averaged conversionsです。'11': 64 averaged conversionsに変更しました。この時、変換時間は1秒になります。

　10回繰り返して温度を読み出します。分解能を見たいがために小数点第5位まで表示していますが、確度はそこまで取れません。
　パッケージが小さいので、レスポンスはよいです。

　読み出したデータは、16ビット長 2の補数形式なので、一度dec2bin()でバイナリの文字列に変換します。この文字列の前に接頭語'0b'をくっつけ、後ろに接尾辞's16'をつなげます。その文字列をbin2dec()で10進数に変換すると、先頭が'1'であればマイナスの符号の処理が行われます（R2020a以降）。

```matlab
clear all
rpi = raspi('192.168.111.114', 'pi', 'raspberry'); % host name raspberrypi-uMchsTIvew
% for i = 1:length(rpi.AvailableI2CBuses)
%    scanI2CBus(rpi, rpi.AvailableI2CBuses{i})
% end

tmp117 = i2cdev(rpi, 'i2c-1', '0x48');

TemperatureRegister   = 0x00;
ConfigurationRegister = 0x01;

Ctrl_OUT = [0x00, 0x60]; % Continuous conversion,Conversion cycle=000,averaging=11 is 64...1sec
writeRegister(tmp117, ConfigurationRegister, Ctrl_OUT, 'uint8');

for i=1:10
    RegisterData = readRegister(tmp117, TemperatureRegister, 2);
    temperature =  double(bitshift(uint16(RegisterData(1)), 8)) + double(RegisterData(2));
    temperature = bin2dec(append('0b',dec2bin(temperature),'s16'))* 0.0078125;  % 2's complement R2020a
    fprintf(' temperature is %.5f \n', temperature);
    pause(2);
end
```
【Windows】俺的におすすめなソフト一覧

パソコンを初期化したときに入れるアプリ
Reboot、PC

Chrome
https://www.google.co.jp/chrome/?brand=CHBD&gclid=CjwKCAjwyo36BRAXEiwA24CwGV9hQxJuMqocK_jesWtbBO0hmK5QBes0zJ8MmgdN-hGURz9gTPUgmhoCv0wQAvD_BwE&gclsrc=aw.ds

Office系
https://www.office.com/?auth=2

VSCode+Java+ReactNative(Node.js)
https://code.visualstudio.com/download
https://code.visualstudio.com/docs/languages/java
https://nodejs.org/ja/

PyCharm+Anaconda
https://www.jetbrains.com/ja-jp/pycharm/download/#section=windows
https://www.anaconda.com/products/individual

Git
https://git-scm.com/

DeepL
https://www.deepl.com/ja/translator

Atok
https://mypassport.atok.com/install/install_win.html

Mcafee
https://home.mcafee.com/downloads/keycard.aspx?affid=1274&culture=JA-JP&tk=4lpKpKzn3CxQMgk5ESzD9ucRRy-xkSc5h7OUMq96KLFeDENrnu00KJQGFBCu7tgO0&tp=44

7zip
https://sevenzip.osdn.jp/

Gyazo
https://gyazo.com/ja

Slack
https://slack.com/intl/ja-jp/downloads/windows

iVcam
https://www.e2esoft.com/ivcam/
開発でハマりそうな時のヒント

- 実装方針でいくつか選択肢があっていくら考えても決められない時が有る。そんな時はどちらかの実装を始めてみる。すると頭の中だけで考えていた時は思いつかなかった
メリットやデメリットが見えてきて選択できるようになるかも。
- 開発環境構築やインフラ構築などで期待通りに動かないことが有る。最初はミュータブルに一部の設定などをいじって直るならそれが一番速い。しかしどうにも動かない時はイミュータブルにゼロから再構築すると直るということはよく有る。
- 一つのことを頭の中で考えていると堂々巡りみたいになって結論がいつまでも出ないことが有る。そんな時は疑問点を紙に書き出す。そしてその疑問に対して思いついた考えを全て書き出してみる。アウトプットすることで頭の中が整理されるということは有る。
[Swift, ARKit]非推奨になったhitTestからraycastQueryに移行する

iOS14が正式にリリースされました。
これに伴いARKitも3.5から4.0に移行しましたが、その中でARSCNViewに存在していた

```swift
open func hitTest(_ point: CGPoint, types: ARHitTestResult.ResultType) -> [ARHitTestResult]
```

という関数が非推奨(deprecated)となりました。

この関数の使いどころとしては、ARSCNView内に設置した3Dオブジェクトを移動させる時に、指先でなぞった場所の位置を取得することだと思います。
例えば以下のようなコードです。

```swift
@IBOutlet var scnView: ARSCNView!

override func viewDidLoad() {
    super.viewDidLoad()

    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(pan))
    self.scnView.addGestureRecognizer(panGesture)
}

@objc
func pan(_ sender: UIPanGestureRecognizer) {
    //こちらのhitTestは[SCNHitTestResult]を返すもので非推奨となった関数とは別もの
    guard let node = scnView.hitTest(sender.location(in: scnView), options: nil).first?.node else {
        return
    }
    //こちらが非推奨となった関数
    guard let transform = scnView.hitTest(sender.location(in: scnView), types: .existingPlaneUsingExtent).first?.worldTransform else {
        return
    }
    node.setWorldTransform(SCNMatrix4(transform))
}
```

コードによってはsenderのstateによってswitchしたり、guardではなくif letを使っていたりと多少の違いはあるかと思います。

これをraycastQueryに書き直すと以下のような形になります。

```swift
//変数宣言とviewDidLoad()は省略

@objc
func pan(_ sender: UIPanGestureRecognizer) {
    guard let node = scnView.hitTest(sender.location(in: scnView), options: nil).first?.node else {
        return
    }
    //変更したところ
    guard let raycast = scnView.raycastQuery(from: sender.location(in: scnView),
                                                  allowing: .estimatedPlane,
                                                  alignment: .any),
          let result = scnView.session.raycast(raycast).first? else {
        return
    }
    node.setWorldTransform(SCNMatrix4(result.transform))
}
```

ARSCNView本体から取得したARRaycastQueryを、今度はARSCNViewのsessionに送って、そこから[ARRaycastResult]を改めて取得しています。
ARSCNViewのタップ箇所をそのまま使うのではなく、間にsessionを挟んでいますね。

ARRaycastResult自体は変更は無いので、hitTestで取得した時と同じ使い方で問題ありません。

次にraycastQueryの中身を確認していきます。

```swift
open func raycastQuery(from point: CGPoint, allowing target: ARRaycastQuery.Target, alignment: ARRaycastQuery.TargetAlignment) -> ARRaycastQuery?
```

第一引数はそのままですね。
第二引数と第三引数はどちらもARRaycastQueryにあるenumです。

第二引数のenumはこちら。

```swift
public enum Target : Int {
    case existingPlaneGeometry = 0
    case existingPlaneInfinite = 1
    case estimatedPlane = 2
}
```

ポイントに存在するものが何なのかを判断するためのものです。
大きさの確定したPlaneが欲しい場合はexistingPlaneInfiniteを、大雑把でいいのならestimatedPlaneを選択します。

次は第三引数のenumについて。

```swift
public enum TargetAlignment : Int {
    case horizontal = 0
    case vertical = 1
    case any = 2
}
```

こちらは該当箇所が垂直なのか、水平なのか、どちらでも構わないのかという3つの選択肢を列挙しているものです。

第二引数と第三引数はどちらも新しく登場したものですが、hitTestで使っていたARHitTestResult.ResultTypeを分解し、組み合わせを自由にできるようになったと考えていいのではと思います。

hitTestは非推奨というだけなので使えるには使えるのですが、折を見て変更していきたいところです。
【StereoDepth】EdgeStereo : EdgeでDisparityの精度があがるらしい

<h1>EdgeStereo: A Context Integrated Residual Pyramid Network for Stereo Matching</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d0f5bbfa-933f-f7f1-8a87-27b1c0503e85.png)

従来のStereo Depth EstimationにEdgeの情報を加える事でより精度があがったという研究である。


<h1>Context Pyramid</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d07edd4d-1f38-4e49-fe22-feece3ae1614.png)
以下の3つを比較しpooling context pyramidを採用
・convolution context pyramid
・pooling context pyramid
・dilation context pyramid

<h1>Residual Pyramid</h1>
2-stageのDisparityをrefinementするネットワークでは初期Disparityの差を学習するが、この差がとても小さい事から学習が困難である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/efa3e020-606c-2ce5-f626-9e404d00e101.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/03625064-1646-1817-d2a4-ebb4ac6c301a.png)
ds => disparity map dS ( 1/2^(S−1) of the full resolution)
u(·) => 2倍にupsample
rs => refineする為のDisparityの差のblock

グレーのAggregated Featureの入力は左の画像とwarpした左の画像の差分をError Mapとする。

<h1>Cooperation of Edge Cues</h1>
Fle(左のedge)、Flr(左の特徴量Map)、Fc(cost volume)を結合することで、エッジの情報とlocalの情報を学習出来ると期待している。

Edge MapはFlのそれぞれのScaleの情報から推定される。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/4e385b4a-52a4-140c-47c9-af1696729444.png)

Edge MapはSmoothness LossのEdgeの重みを小さくするのに役立つ。



<h1>結論</h1>
EdgeDetectionをする事でかなり複雑なネットワークになっている気がする。
Edgeを今までと同じように入力画像の1次微分または2次微分にしたらかなりスッキリすると思う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/247f1b02-8e49-17d9-73f9-f3c967497f3d.png)

たしかにEdgeまで綺麗にDisparityが推定されている事が分かる。
Edgeの所まで綺麗に推定したい人は論文を読んで見ると良いかも。


<h1>EdgeStereo: A Context Integrated Residual Pyramid Network for Stereo Matching</h1>
EdgeStereo: A Context Integrated Residual Pyramid Network for Stereo Matching
https://arxiv.org/pdf/1803.05196.pdf