OmniAICreator/Qiita-1.07M huggingface dataset:
「WordPressかCGIか、それが問題だ」

####どうでもいい前置き

当記事はプログラミング初心者の学習メモです。
筆者は頭の固いおっさんであり、この記事にはヤマもオチも意味もありません、あしからず。

多分、私自身の無知がゆえにこういう感想になる事は百も承知です。
ただどうしても言いたいので書きます。
異論は認めるので、愚痴としてほおっておいてください。
建設的なご意見なら拝聴しますが、ただの感情論や苦情のたぐいはご遠慮下さい。


####WordPressプラグインに感じる得体のしれなさ
例えばポートフォリオを作る時にでも、手軽にWebsiteを立ち上げる方法として、
多くの人がWordPressを採用しています。
しかし私は、WordPressの構成要素の大半はブラックボックスだと思うのです。
中でもプラグイン。見ず知らずの人が作ったものを、中身も見ずに信用して機能として使い、
ユーザーに提供する薄気味悪さというのが・・・私にはどうも拭えないのです。

もちろん、有志ユーザーによって検証は為されている事でしょうし
わたしのこの感情は多分、勝又健太さんのいうところの「全てわかってから始めたい症候群」なんだろうと思います。
フリーで寄ってたかって集合知を重ねて爆速で開発をするというのは、
UNIX以来、ある種のネットの伝統だと思います。
（「UNIXという考え方」は一通り読んで要約文起こししました、多分ここに出すと著作権的に不味いだろうと思うので出しませんが）

メリットが沢山あることは重々承知していますが、デメリットの部分は忘れ去られてる感があります。
Wikipedia見ても、ちょっとこの辺は詳しく書かれていません。
この辺はもうちょっと、WordPressの「検証の仕組み」を勉強してみたいと思います。

###なぜPerlによるCGIではいけないの？
同時に、「なぜPerlによるCGIではいけないのか？」と思います。
私自身がネットに出会った頃は、掲示板などを動かすというときにはもっぱらPerlで組まれたCGIというのが主流でした。
私がリアルにかまけて眠っていた二十年近くの間に、シェアとしては完全にPHPとWordPressに取って代わられてしまっている。
これはwebに特化したPHPの言語自体の優位性と、オープンに色んな人がよってたかって開発したから、ということなんでしょうが
Perlはオワコンなのか？というと、そうも見えないのです。

ただなんか、Perl５とPerl６（RAKU）に別れてしまうようですが・・・初心者にとってはいささか都合が悪いですねえ。これだけでも混乱の元・・・
しかしPerlの利点というのは数多くあるらしく、そもそもPerlはUNIXの言語処理系言語だそうです。
Perlの学習を通してUNIXに強くなれないかという期待があり、
プログラマーとしてポートフォリオを作る人にもたいがいUNIXの勉強がある程度求められるようですから、やって無駄ということはなく。
とりあえずTwitterでフォローしている村上さん（Kohei Murakami氏　@ryuta69 ）は業務上Perl５系をお使いのようですので
実践的に使われているのであればPerl５を優先してちまちまやっていますが、、、

今やっているもの：https://tutorial.perlzemi.com/blog/20091226126425.html

お金になるかどうかは正直わかりません。
凡百に埋もれてしまっていいとも思えないし、定跡を踏まえずに理解されないのも違うし。
正解なんてわからないので、あとは思いつくままにいいと思ったことをやってみる、それだけなんでしょうかね。
Oracleデータベースが急にオープンできなくなった：ORA-03113

Oracleデータベースに関して、ちょっとしたトラブルシューティングが発生したので、記録がてら書いておくことにする。
バージョンは12c。

###事の起こり
しばらく放置していたOracleデータベースを起動しようとしたら、起動できない。
いろいろ試していると、マウントまではできることがわかった。
マウント状態でオープンしようとすると、以下のエラーメッセージが表示される。

```
SQL> alter database open;
alter database open
             *
行1でエラーが発生しました。:
ORA-03113: 通信チャネルでend-of-fileが検出されました
```

###対処法
検索してみると以下のページにたどり着く。

[ORA-03113：通信チャネルでend-of-fileが検出されました - PROJECT GROUP](https://www.projectgroup.info/tips/Oracle/errorcode/ORA-03113.html)

これによると、ディスク容量がいっぱいの時に発生し、アーカイブログを削除すれば解決するらしい。
記事内にさらにリンクがあり、要するにRMANでアーカイブログを日付指定して削除すればよいとのこと。
ディスク容量には余裕があったが、とりあえず試してみることに。

```
SQL> host rman

RMAN> connect target /

RMAN> delete archivelog until time 'sysdate - 1';

RMAN> exit
```

上記コマンド実行後、再度データベースオープンを試みる。

```
SQL> alter database open;

データベースが変更されました。
```

無事データベースがオープンできた。

###原因は……
原因はもしかすると、高速リカバリ領域が食い尽くされてたことだろうか？
アーカイブログは既に削除してしまったので、残念ながら確認できず。
この曲の曲名が分からない…という時の対処法


### 前提

- YouTubeのアカウントを持っている
- その 曲名の分からない音源を持っている

<br>

### 方法

1. 曲名の分からない音源を動画編集ソフトの音声トラックに入れて、動画を作る
    - Windows ムービーメーカーやAviUtlなど、MacならiMovieなど
2. 作った動画をYouTubeに非公開でアップロードする
3. 数時間ぐらい放置
4. アップロードした動画の視聴ページの動画説明欄を見る

<br>

### 結果

![Screen Shot 2019-10-28 at 13.45.24.png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515024/46e56383-dcf2-2ff3-deb6-42d70baf9c24.png)
YouTubeが曲名発見器になっちゃった！
【SQLite3】 〜データベースの操作

## データベースの作成・接続
```shell:ターミナル上で実行
sqlite3 sample.sqlite3
```

上記のコマンドは、SQLite3のコマンドライン起動コマンドと同じです。
このコマンドを実行した際、指定したデータベースが存在すればそのデータベースに接続し、指定したデータベースが存在しなかった場合はそのデータベース名で新規ファイルが作成されコマンドラインツールが起動します。

なお、データベース名についてですが、拡張子をつけなくてもデータベースとして使うことは可能です。
ですが、ひとつのプロジェクト内には、多数のプログラムファイルが存在していることやデータベースの種類も多数あることから、それを明示するために例として下記のような拡張子をつけることが通例となっているようです。

- sample.sqlite3
- sample.sqlite
- sample.db

この記事では、拡張子を「.sqlite3」に統一します。

---

## データベースのバックアップ
SQLite3は、データベースごとにひとつのファイルとして管理しているので、エクスプローラー(Windows),ノーチラス(Ubuntu)を開いて、名前を変えてコピーするだけで、データベースのバックアップを取ることができます。

---

## データベースの削除

バックアップの項目と同様の理由で、データベースを格納してあるファイルを削除することで、データベースを削除することが可能です。

---

### 本記事目次ページ
[【データベース】SQLite3・JDBCまとめ](https://qiita.com/tsweblabo/items/8fa21f3e9e30885be034)


### 参考サイト
- [DBOnline 初心者でもわかりやすいサイトSQLite入門](https://www.dbonline.jp/sqlite/)
【第１回】Ruby + Seleniumを使ってスクレイピングしてみる

#@cosmeの商品レビューをスクレイピングしてみる
###ゴール
@cosmeの各商品のレビューを自動収集し.xlsxに書き出す。
（余力があれば各レビューの品詞解析＆ポジネガ判別もできればよいかも）


###条件
Ruby 2.4.6
Ruby on Rails 5.2.6
Windows環境

###なぜSeleniumを使うのか
これは@cosmeのページ構成が大きな理由です。他のECサイト(Amazon)と@cosmeのHTMLを比較してみます。
#####Amazon

Amazonでは1ページに最大10レビューが表示される仕組みになっています。
各レビューは全文が`<span class>`に入っているので、スクレイピングの際はこのクラスを指定すれば、レビュー本文だけをを丸ごと抜き出すことができます。(LOHACOも同様の仕組みです。)

#####@cosme
@cosmeの商品レビューは、**同一URLに全文が表示されません。**
各レビューの最後にある「続きを読む」リンクを踏むと、そのレビュー全文ページに遷移します。（言うまでもなく、URLも変わります。）
なので、@cosmeの商品レビューのスクレイピングをする時には、
①スクレイピングする商品レビューページの「続きを読む」のリンク先に遷移
②レビュー全文をスクレイピングする
のフローを経る必要があります。

まとめますと、もし100件のレビューを取得するとしたら、
・Amazon
　1ページ(1URL)10レビュー × **10**ページ分
・@cosme
　1ページ(1URL)1レビュー × **100**ページ分　　　のスクレイピングが必要になるわけです。大変ですねこれは・・・。



加えて、AmazonであればレビューページのURLに規則性があるので、
例：１ページ目　amazon.co.jp/商品名/商品IDとか/review/page=**1**
　　２ページ目　amazon.co.jp/商品名/商品IDとか/review/page=**2**
とまあこんな感じに規則性があるので、もし8ページ分取りたければ1ページごとに最後のページ数に+1してやるだけで済みます。(page=8になったら終了する)

しかし@cosmeの全文レビューページURLには規則性が何もありません。レビューごとに固有のreview_idなるものが割り当てられているので、これを直接指定しないことにはどうにもこうにもならないってことらしいです。
例：全文レビューページのURL　
　　cosme.net/product/product_id/商品ID/review/**レビューID**(アットランダムな整数９桁)

はいこれは困りますね・・・100件分のレビューIDなんて知らんし打ち込むのめんどくさいしなんかいい方法ないかなーと困っていたところ思いついたのが「**Selenium**」ってわけです。(前置き長くてすみません笑笑)

###Seleniumでできること　
ひとことで言えば「**自動でブラウジング**」ができます。今回のケースだと、ブラウザ起動して、ECサイトに飛んで、商品名入力して、検索一覧から商品選択して、レビューページ飛んで、「続きを読む」クリックして、、、、、、、とかいうのをぜーんぶ自動でやってくれます。賢いですね。(×100回)
他にも、テキストボックスに自動入力したり、スクショとったり、けっこう色々できちゃいます。
https://www.seleniumqref.com/index.html　
（↑↑有志による？？リファレンスがあったのでこちらに載せさせて頂きます。）

###想定仕様
・任意の商品URL＆取得レビュー件数を指定
・xlsxのフォーマットをあらかじめ用意し、取得したレビューを上書きする

長くなったので、第二回に続けます。
https://qiita.com/sasaken33/items/9f07b8ff677bf49fa2ba
【データベース】SQLite3・JDBCまとめ

## SQLite3操作コマンドまとめ

SQLite3を操作する際に必要なコマンドを記録していきます。
私自身SQLite3初心者なので、基本的なところから少しずつですが、まとめていこと思います。

ひとつの記事では長くなるので項目ごとに分けた記事のリンクを貼っていきます。

なお、使っているOSがUbuntu18.04なので、WindowsOSの方と表示等に若干の差異があるかと思いますが、ご了承ください。

1. [SQLite3のインストールとコマンドラインツールの使い方](https://qiita.com/tsweblabo/items/37a92bff177ef72f2db2)
2. [データベースの操作](https://qiita.com/tsweblabo/items/6fabc9570aec5478024a)
3. [テーブルの操作](https://qiita.com/tsweblabo/items/c427aeef0e976ada6eab)
4. [SQLite3のデータ型](https://qiita.com/tsweblabo/items/0a0c14d236d896b7f4a7)
5. [データの追加 (INSERT文)](https://qiita.com/tsweblabo/items/76d00b2944c946425d8f)
6. [データの更新 (UPDATE文)](https://qiita.com/tsweblabo/items/a4b45cfc4d73b5b453fa)
7. [データの削除 (DELETE文)](https://qiita.com/tsweblabo/items/14612dca2bf7222f48c5)
8. [データの取得 (SELECT文)](https://qiita.com/tsweblabo/items/ddcfa878f64824793428)
9. [テーブルの結合（JOIN句）](https://qiita.com/tsweblabo/items/f12deddd4ba18ece04ef)

---
## JDBCを用いたJavaからのSQLiteデータベースアクセス

1. [【JDBC ①】JavaからSQLite3のデータベースにアクセスしてみた。](https://qiita.com/tsweblabo/items/39bdd73a910417a9a8df)
2. [【JDBC ②】JavaからSQLite3のデータベースアクセスをSQL文ごとにメソッド化してみた。](https://qiita.com/tsweblabo/items/a3e37bc439bacfe6c5c5)
3. [【JDBC ③】プレースホルダと引数を使ってmainメソッドから入力してみた。](https://qiita.com/tsweblabo/items/eccad6d4c7d10987974d)

---
### SQL文の書き方
SQL文については、大文字 小文字かかわらず同じように使えます。
ただ、SQL文の中には、データベース名・テーブル名・カラム名などの単語が入ってきて、パッと見でどこが名前で、どこがSQL文なのかがわかりにくくなる気がしました。
プログラムコード内にSQL文を埋め込むとなれば、尚更ですよね。

小文字で書いた場合と大文字で書いた場合と比較したものを下に示してみました。
個人的には大文字のほうが見やすいかと思うので、SQL文に関しては大文字で統一しようと思います。

```sql:小文字で書いた場合
create table personal002(id integer primary key autoincrement, name text not null);
```
```sql:大文字で書いた場合
CREATE TABLE personal002(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL);
```

---
### 参考サイト
- [DBOnline 初心者でもわかりやすいサイトSQLite入門](https://www.dbonline.jp/sqlite/)
Pyramid Scene Parsing Network

# Pyramid Scene Parsing Network 要約
## 読んだ論文
Pyramid Scene Parsing Network
Hengshuang Zhao, Jianping Shi, Xiaojuan Qi, Xiaogang Wang, Jiaya Jia
https://arxiv.org/abs/1612.01105v2

上記の論文を読んだので簡単にまとめます．ADE20Kデータセットで現在SOTA取っている（らしい），SemanticSegmentationの研究．CVPR2017の論文で，現在1600引用程．

## 3行でまとめる
- ピラミッド構造のPoolingを挿入する手法を提案した．
- これにより局所的情報だけでなく大域的情報を獲得することに成功した．
- ADE20Kデータセットで評価した．それを使うときに気をつけることもまとめた．


## ADE20Kで気をつけること
### Mismatched Relationship
モノとモノの間の関係（Context-relationship）が重要なので，それを意識すればより高度な予測ができる．例えば，湖の上にボートがある状況で，FCN（従来手法）だと車と予測されているが，これは湖の上という位置関係が見えれば改善できるはずである．

### Confusion Categories
（意味的にも）似ているけれども，違うラベルが与えられているモノが存在することが，精度を悪くしている．例えば，山と丘，壁と家と建物と超高層ビル等など．カテゴリ間の関係を利用することで改善できるはず．

### Inconspicuous Classes
適切なグローバルシーンレベルの分布がわかると，シーンレベルのパフォーマンスが向上できるはず．すなわち，大きすぎるものと小さすぎるものが混在している場合，分類が難しくなるケースが有るので注意を払って見る必要がある．

- 上記3つの問題点より，ネットワークはより広域な特徴を意識してセグメンテーションを行う必要がある．

## 提案手法
- 既存手法は，各sub-regionから有益な情報を抽出してはいるものの，その後平坦化及び連結されているため，それぞれ独立た情報として取り扱われている．
- 一方，各sub-regionのみでなく，周囲のsub-regionから情報を抽出できれば，より高度な表現を獲得することができるであろう．
- 従って，Fig.3のピラミッドPooling構造の導入を提案する．

![20191028_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376859/25d50d8b-a3bc-ce33-c895-6b8f5dec96ad.png)

### Pyramid Pooling Module
図のPyramid Pooling Moduleの手順は以下の通りである．
1. 与えられた特徴マップを，1*1，2*2，3*3，6*6で4種類のPoolingを行う．
2. それぞれに，1*1Convでチャネル数を1/Nに揃える．
3. それぞれにBilinear補完でUPSAMPLEし，同じサイズに整えた上で，Concatenateする．

なお，上記のPoolingサイズは可変で，かつN（ピラミッドの段数：Poolingの種類数）も可変である．

### 全体のモデル構造
図のモデル構造全体を説明する．
1. 入力をCNN（今回はResNet50）に通し，1/8のサイズの特徴マップが得られる．
2. 特徴マップをPyramid Pooling Module（PPM）に通す．
3. 元の特徴マップと，PPMを通した結果と結合する．
4. 残りのConvolutionの説明は無いが，従来のEncoder-Decoderモデルと同じ？と思われる．


## 評価実験
いろんなデータセットで，いろんな手法と比較評価を行った結果，一番良かったよ．

## 所管
勉強会として数名で1時間半くらいで読了＋記事作成．1時間半という制限内で読み解く練習？
java.lang.Mathのメソッドを使ってみる

#はじめに
　本記事は、筆者のアウトプット練習の一環として、数学的計算で用いられるAPIであるjava.lang.Mathのメソッドをメモしようと思います。説明等おかしいところがありましたら指摘してもらえると助かります。
参考：[公式 java.lang.Math](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Math.html)

#abs
　引数にとった整数の絶対値を求める。

```java
  int num1 = Math.abs(-1); //num1 = 1
```

#max, min
　二つの引数のうち大きい方(小さい方)を返す。

```java
  int num2 = Math.max(1,2); //num2 = 2
  int num3 = Math.min(1,2); //num3 = 1
```

#random
　0.0以上で1.0より小さい、正の符号の付いたdouble値を返す。整数値にしたい場合は任意の倍数をかけてからキャストする。
※キャストした後乗算した場合、キャスト時に小数点以下が切り捨てられるため 0 のみ返却されてしまう。

```java
  //0~1000の範囲でランダムな値をとる
  int num4 = (int)(Math.random()*1000); 
```

#log, log10
　`log`は自然対数、`log10`は常用対数の値を返す。
※ `Math.E` : 自然対数の底$e$。定数として定義されている。`Math.PI`(円周率$π$)も定義されている。


```java
  double num5 = Math.log(Math.E); //num5 = 1.0
  double num6 = Math.log10(100);  //num6 = 2.0
```

#sin, cos, tan
　三角関数のメソッド。引数にはラジアンを入力する。~~弧度法の引数を入力したい場合は$\frac{π}{180}$を掛けることで変換できる。~~
※逆三角関数(asinなど)・双曲線関数(sinhなど)も用意されている。
(追記 10/29)弧度法で入力したい場合、`Math.toRadians(double angdeg)` メソッドを用いればラジアンに変換してくれる。

```java
  double num7 = Math.sin(Math.PI/4); //1/√2 の近似値
  double num8 = Math.cos(Math.PI/4); //1/√2 の近似値
  double num9 = Math.tan(Math.toRadians(45));//1(0.9999999999999999)
```

#pow
　第一引数を第二引数で累乗したdouble値を返す。整数値として扱う場合はキャストする。

```java
  double num10 = Math.pow(10, 4); //num10 = 10000.0
```

#exp, expm1
 前者は自然対数の底$e$の累乗値を返し、後者は前者から1引いた数を返す。物理系や統計学で使いそう...?

```java
  double num11 = Math.exp(2);  // e^2
  double num12 = Math.expm1(2);// e^2 -1
```

#sqrt, cbrt
　平方根・立方根を返す。

```java
  double num13 = Math.sqrt(9);  //num13 = 3.0
  double num14 = Math.cbrt(64); //num14 = 4.0
```

#あとがき
...使いそうなものがまた発見出来たら更新します。
Linux ディレクトリをまるごと削除(完全削除)

# ディレクトリを中のファイルもまるごと削除する

Linuxでファイルが入っているディレクトリをファイルまるごと削除する場合のコマンド。

**ディレクトリを再帰的にまるごと削除するので、削除対象に気を付けて！**

```
$ rm -rf directoryname
```

# オプション

|オプション|説明|
|---|---|
|-r, -R|ディレクトリ内を再帰的に削除する|
|-f|警告メッセージを表示しない|

# エラーが出た時はこちらを参照

## rmで-rオプションを付けていない場合

```
$ rm directoryname
rm: cannot remove 'directoryname': Is a directory
```

## rmdirでディレクトリ内にファイルが入っている場合

```
$ rmdir directoryname
mdir: failed to remove 'directoryname': Directory not empty
```
Boostnoteユーザは今すぐアップデートすべき（２０１９年１０月２８日）

# Boostnoteユーザは今すぐアップデートすべき
（２０１９年１０月２８日　現在）

## 環境
Ubuntu 18.04
boostnote 0.12.1

## バグ
boostnoteの使い勝手が良すぎて、あまりQiitaに戻ってこなかったのですが
最近１文字タイプする度に一番上まで戻ってしまうバグに遭いました。

なのでググってみると

https://github.com/BoostIO/Boostnote/issues/3023

boostnote 0.11.15ぐらいからのバグらしく、
boostnote 0.13.0のバージョンから、そのバグを改善したみたいです
１０日前発表なので最近です

## boostnoteのサイト

https://boostnote.io/

## アップデートしたら解決

boostnote 0.13.0にアップデートしたら上記のバグが起こらなくなりました。

なので、このバグに困っている方は、最新のバージョンにした方がいいですよ。
テストクラスの作成時の注意点

isTest(SeeAllData=true)
　　　　　　　⇊
　　　　既存のデータの検索を使えます。

テストデータが作成する時に、もし既存のデータを探してからデータがない場合、新しいデータを作るときに、検索のSoql文がSeeAllDataから既存のデータの有無の判断として使います。
【Rails】検索機能を実装しよう

#はじめに
検索機能を実装しましょう！
今回は**完全一致、部分一致、前方一致、後方一致**を実装します。
それぞれ簡単に実装できるのでこの記事を理解して実装してみてください！！
今回はPostテーブルのtextカラムを検索する機能を実装します

#実装方法
機能の大まかな内容は以下の通りです。
1. 検索方法を選択し、検索フォームに単語を入力する
2. 検索ボタンをクリックするとsearchアクションに繋がる
3. searchアクションでテーブルから検索をかける
4. 検索結果をビューで表示する

実装方法をビュー、モデル、コントローラーの順に説明していきます

##ビュー
以下、検索フォームのソースです。

```html:app/views/posts/search.html.erb
<%= form_tag(posts_search_path , method: :get) do %>
	<%= select(@search_content, :search_method, [["前方一致","forward_match"], ["後方一致","backward_match"], ["完全一致","perfect_match"], ["部分一致","partial_match"]])%>
	<%= text_field(@search_content, :search_word)%>
	<%= submit_tag "検索" %>
<% end %>
```

`@search_content`に`search_method`、`search_word`が含まれています。
`search_method`が検索方法です。ドロップダウンリストで選択します。
`search_word`が入力フォームに入力した単語を代入します。


##モデル
以下がモデルに検索のメソッドを定義する部分です。

```Ruby:app/models/post.rb
	def self.search(method,word)
                if method == "forward_match"
                        @posts = Post.where("text LIKE?","#{word}%")
                elsif method == "backward_match"
                        @posts = Post.where("text LIKE?","%#{word}")
                elsif method == "perfect_match"
                        @posts = Post.where("#{word}")
                elsif method == "partial_match"
                        @posts = Post.where("text LIKE?","%#{word}%")
                else
                        @posts = Post.all
                end
 	end
```

引数の`method`によって検索方法を選択し、`word`で検索します。

##コントローラー
以下、コントローラーの内容です

```ruby:app/controllers/posts_controller.rb
def search
	method = params[:search_method]
	word = params[:search_word]
	@posts = Post.search(method,word)
end
```
検索方法と単語を引数に渡し検索をします


#終わりに
以上が検索機能の実装方法になります。

**疑問、気になるところがございましたら、質問、コメントよろしくお願いします！！！**
macOSでWebサーバーを立ち上げる

#macOS 10.13.6のMacにWebサーバーを立ち上げるためのメモ。
元々MAMPでサーバーを立ち上げていたのですが勉強にならないので。
標準のApacheとPHPを使わず、Homebrewでインストールしたものを使っています。
色々なところから引用させていただいています。

##macOS標準のApacheの場所
`usr/sbin/apachectl`
Apache/2.2.29(Unix)

###HomebrewでインストールしたApacheの場所
`usr/local/bin/apachectl`
Apache/2.4.41(Unix)


##macOS標準のphpの場所
`usr/bin/php`
PHP 7.1.23 (cli)

###Homebrewでインストールしたphpの場所
`/usr/local/bin/php`
PHP 7.3.9 (cli)


##usr/local/binを優先で読み込むようにPATHを通す
`vi ~./bash_profle`
`export PATH=/usr/local/bin:$PATH`
`export PATH=/usr/local/sbin:$PATH`


以下、[MacでPATHを通す]
(https://qiita.com/nbkn/items/01a11392921119fa0153) より引用
.bash_profileの更新
`source ~/.bash_profile`

###PATHの確認
`printenv PATH`
もしくは
`echo $PATH`


実行すると次のような文字列が帰ってくる。（『:』はPATHの区切り）
`/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/test/`
目的のPATHがここに記載されていれば成功。


##usr/local/etc/httpd/httpd.conf を編集
```httpd.conf

デフォルトから編集したところ
Listen 8080
↓
Listen 80

User _www
Group _www
↓
User administrator
Group staff

DirectoryIndex index.html
↓
DirectoryIndex index.php index.html

#AddHandler cgi-script .cgi
↓
AddHandler cgi-script .cgi
AddType application/x-httpd-php .php


#AddType text/html .shtml
#AddOutputFilter INCLUDES .shtml
↓
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml .html .htm .php

Include /usr/local/etc/httpd/extra/php73.conf
を追加

AddHandler application/x-httpd-php .php .html
を追加
（htmlファイル内でphpが動作するように）
```


あとはこちらの記事を参照
[Apacheのhttpd.confにPHPを設定する方法]
(https://qiita.com/ponsuke0531/items/e27c3dafcc9741ef3e73)より引用


これでMacのサーバー上でphpが動くようになりました。

Macだと何かうまく動かない時、標準から入っているApacheとphpと、後からHomebrewで入れたApacheとphpのどちらかが読み込まれているのか確認しないといけないのでそれが面倒と言えば面倒ですね。
最近のmacOSだとApacheもphpも最初から高いバージョンが入っているので無理にHomebrewでインストールし直さなくてもいいかもしれないです。
SNMPv3 の Trap受信設定をしてみる（CentOS7）

#1. はじめに

Centos7のサーバー上でLBからのSNMPv3 Trap受信設定をした際の備忘録です。
SNMPv3関連の情報があまり見当たらなかったので記事にします。

#2. サーバーへのTrap受信設定方法

1.まずはfirewalldをオフにする
```systemctl stop firewalld```
or
```systemctl disable firewalld```

2.「/etc/snmp/snmptrapd.conf」に設定を追加

```
# Example configuration file for snmptrapd
#
# No traps are handled by default, you must edit this file!
#
# authCommunity   log,execute,net public
# traphandle SNMPv2-MIB::coldStart    /usr/bin/bin/my_great_script cold

createUser -e <EngineID> <UserName> SHA <Password> AES
authuser log <UserName>
```

3.SNMP Trapの動作確認

```

[daikon@CentOS7 ~]$ sudo snmptrapd -f -C -c /etc/snmp/snmptrapd.conf -Le
NET-SNMP version 5.7.2
~Trap受信時にログが出力される~
```

#4. trapが出力されない時。。。

1.「No access configuration」が出力される場合
「/etc/snmp/snmptrapd.conf」の設定内容が不足しています。

```
[root@CentOS7-149 snmp]#  snmptrapd -f -C -c /etc/snmp/snmptrapd.conf -Le
Warning: no access control information configured.
  (Config search path: /etc/snmp:/usr/share/snmp:/usr/lib64/snmp:/root/.snmp)
This receiver will *NOT* accept any incoming notifications.
NET-SNMP version 5.7.2
No access configuration - dropping trap.
No access configuration - dropping trap.
```

2.「Authentication failed」が出力される場合
設定するパスワードが間違っています。

```
[disaito@CentOS7-149 ~]$ sudo snmptrapd -f -C -c /etc/snmp/snmptrapd.conf -Le
NET-SNMP version 5.7.2
Authentication failed for SNMPv3userMD5
```

3.何も出力されない場合
ユーザーID,Engine IDを間違えています。

```
[disaito@CentOS7-149 ~]$ sudo snmptrapd -f -C -c /etc/snmp/snmptrapd.conf -Le
NET-SNMP version 5.7.2



```

#5. 参考

[公式ドキュメント]
http://www.net-snmp.org/wiki/index.php/TUT:Configuring_snmptrapd_to_receive_SNMPv3_notifications#Configuring_a_SNMPv3_TRAP_User

#4. 終わりに
参考になれば幸いです。
WRF > Version 3.XのGeographicsl Static Dataの場所

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2 
32GB RAM 
CentOS Linux release 7.7.1908 (Core)
```

WRF (Weather Research and Forecasting Model)関連。

WRF v3.9.1など、古いVersion 3.Xで処理する時に必要となるデータ。

WRF v4.Xが利用可能になってから公式サイトから見つかりにくくなったとのこと。
下記にあるようです。
http://www2.mmm.ucar.edu/wrf/users/download/get_sources_wps_geog_V3.html
FBX SDK の pScene と lScene の違い

# FBX SDKの pScene と lScene の違い

FBX SDK のサンプルコードを見ていると、C++版でもPython版でも、 `pScene` と `lScene` という変数をよく見かけます。
どちらも、 `FbxScene` クラスのインスタンスなのですが、この `p` と `l` の違いが気になったので、調べてみました。



# `pScene` は引数で `lScene` はローカル変数だった

公式ドキュメントの以下のページに説明がありました。
[Autodesk FBX / Information and technical support](https://help.autodesk.com/view/FBX/2019/ENU/?guid=FBX_Developer_Help_welcome_to_the_fbx_sdk_technical_support_html)

なんと、`pScene` は引数で `lScene` はローカル変数でしたｗ

まとめると、以下のようになります。

|接頭辞|意味|例|
|----|----|----|
|`Fbx`|FBX SDKが用意したクラスの接頭辞|`FbxScene`|
|`p`|クラスのメンバー関数（メソッド）の引数の接頭辞|`pScene`|
|`l`|ローカル変数の接頭辞|`lScene`|
|`g`|グローバル変数の接頭辞|`gScene`|
|`m`|クラスのメンバー変数の接頭辞|`mScene`|

ここまで命名を細かく分けるのは、 C++ っぽいなぁと思いました。



# さいごに

意味がわかってスッキリしました！

ちなみに、上記を調べるまでは、勝手にシステムハンガリアン記法だと思い込んでいました。
システムハンガリアンだと、

- `p` はポインタ型
- `l` は `long` 型

です。

ちゃんと調べてよかったですｗ
spring boot security + DB認証のテストコード

# はじめに
 - 作成したテストコードは【[spring boot security + DB認証を試した時のポイント](https://qiita.com/teradatk/items/1e09f0ed4a29d2699504)】用です

## コード
 - 下記のコードはDBへの接続を行わなずにモックを使用した場合のテストコード

```java:DemoControllerTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ContextConfiguration
@WebAppConfiguration
public class DemoControllerTest {
	private MockMvc mockMvc;

	@Autowired
    private WebApplicationContext context;

	@Autowired
    private FilterChainProxy springSecurityFilterChain;

	@InjectMocks
	private DemoController demoController;

	@MockBean
	private UserRepository userRepository;

	@Before
	public void setUp() {
		mockMvc = MockMvcBuilders
					.webAppContextSetup(context)
					.apply(springSecurity(springSecurityFilterChain))
					.build();
	}

	@Test
	public void testLoginOk() throws Exception {
		// 正常系
		String user = "user01";
		UserModel userModel = new UserModel("user01", "ゆーざ０１", "pass1", true);
		doReturn(userModel).when(userRepository).selectByUser(user);

		mockMvc.perform(formLogin("/login").user(user).password("pass1"))
			.andExpect(status().isOk());
	}

	@Test
	public void testLoginNg1() throws Exception {
		// DBにユーザが存在しない場合テスト
		String user = "user01";
		UserModel userModel = null;
		doReturn(userModel).when(userRepository).selectByUser(user);

		mockMvc.perform(formLogin("/login").user(user).password("pass1"))
			.andExpect(status().is3xxRedirection());
	}

	@Test
	public void testLoginNg2() throws Exception {
		// 有効フラグが無効になっている場合のテスト
		String user = "user01";
		UserModel userModel = new UserModel("user01", "ゆーざ０１", "pass1", false);

		doReturn(userModel).when(userRepository).selectByUser(user);

		mockMvc.perform(formLogin("/login").user(user).password("pass1"))
			.andExpect(status().is3xxRedirection());
	}

}

```

- 下記のコードはDBへの接続を行い一連の動作確認する場合のテストコード

```java:DemoControllerITTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ContextConfiguration
@WebAppConfiguration
public class DemoControllerITTest {
	private MockMvc mockMvc;

	@Autowired
    private WebApplicationContext context;

	@Autowired
    private FilterChainProxy springSecurityFilterChain;

	@Before
	public void setUp() {
		mockMvc = MockMvcBuilders
					.webAppContextSetup(context)
					.apply(springSecurity(springSecurityFilterChain))
					.build();
	}

	@Test
	public void test1() throws Exception {
		// ルートへのアクセス時のテスト
		mockMvc.perform(get("/"))
			.andExpect(status().isOk())
			.andExpect(view().name("home"));
	}

	@Test
	public void testLoginOk1() throws Exception {
		// ログイン画面の正常系テスト
		mockMvc.perform(formLogin("/login").user("user01").password("pass"))
			.andExpect(status().isOk());
	}

	@Test
	public void testLoginNg1() throws Exception {
		// ログイン画面の異常系テスト
		mockMvc.perform(formLogin("/login").user("user01").password("pass1"))
			.andExpect(status().is3xxRedirection());
	}

}

```
JavaScriptでURLからOGP取得する

JavaScriptでURLからOGP取得します。

# 結論

```js
const url = "https://qiita.com/ksyunnnn/items/bfe2b9c568e97bb6b494";

fetch(url).then(res => res.text()).then(text => {
    const el = new DOMParser().parseFromString(text, "text/html")
    const headEls = (el.head.children)
    Array.from(headEls).map(v => {
        const prop = v.getAttribute('property')
        if (!prop) return;
        console.log(prop, v.getAttribute("content"))
    })
})
```

#### 結果

```
og:title JavaScriptでURLからOGP取得する - Qiita
og:type article
og:url https://qiita.com/ksyunnnn/items/bfe2b9c568e97bb6b494
og:image https://cdn.qiita.com/assets/qiita-fb-2887e7b4aad86fd8c25cea84846f2236.png
# 以下略
```

デベロッパーコンソールとかで適当に試してみてください

# 追記

### リスト表示

```js
fetch(url).then(res => res.text()).then(text => {
    const el = new DOMParser().parseFromString(text, "text/html")
    const headEls = (el.head.children)

    return Array.from(headEls).map(v => {
        const prop = v.getAttribute('property')
        if (!prop) return;
        return { prop: prop.replace("og:",""),content: v.getAttribute("content")}
    })
}).then(list=>{
    return list.filter(v=>v)
}).then(result=>console.log({result}))
```

### SNS共有用に整形

```js
const url = "https://qiita.com/ksyunnnn/items/bfe2b9c568e97bb6b494"

fetch(url).then(res => res.text()).then(text => {
    const el = new DOMParser().parseFromString(text, "text/html")
    const headEls = (el.head.children)

    return Array.from(headEls).map(v => {
        const prop = v.getAttribute('property')
        if (!prop) return;
        return { prop: prop.replace("og:",""),content: v.getAttribute("content")}
    })
}).then(list=>{
    return list.filter(v=>v)
}).then(result=>{
    const title = result.filter(v=>v.prop==="title")[0].content;
    const url = result.filter(v=>v.prop==="url")[0].content;
    console.log(`${title} | ${url}`)
})

// 結果
// JavaScriptでURLからOGP取得する - Qiita | https://qiita.com/ksyunnnn/items/bfe2b9c568e97bb6b494
```

いまみてるサイトから取得する

```js
const url = location.href

fetch(url).then(res => res.text()).then(text => {
    const el = new DOMParser().parseFromString(text, "text/html")
    const headEls = (el.head.children)

    return Array.from(headEls).map(v => {
        const prop = v.getAttribute('property')
        if (!prop) return;
        return { prop: prop.replace("og:",""),content: v.getAttribute("content")}
    })
}).then(list=>{
    return list.filter(v=>v)
}).then(result=>{
    const title = result.filter(v=>v.prop==="title")[0].content;
    const url = result.filter(v=>v.prop==="url")[0].content;
    console.log(`${title} | ${url}`)
})

// 結果
// JavaScriptでURLからOGP取得する - Qiita | https://qiita.com/ksyunnnn/items/bfe2b9c568e97bb6b494
```
CloudFormationでCloudWatchAlermを作成する

# はじめに
ぐぐってもサンプルがでてこなくて、公式ページ見ながら作成したのでメモ。
いくつもLambda関数を作成しており、マネジメントコンソールで手動で作成するのが面倒なため、CloudFormationでコピペでできるように作成。

# テンプレート(yaml)
Lambdaで実行時間が3秒を超えたときのアラーム。
1分の間に実行時間の最大値が3秒以上の回数が1回を超えたときにアラームをだす。
SNSにアラーム情報を送っている。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  sample:
    Type: 'AWS::CloudWatch::Alarm'
    Properties:
      Namespace : AWS/Lambda
      AlarmName : lambda-duration-alarm-sample # アラーム名(自由に設定する)
      AlarmActions :
        - arn:aws:sns:ap-northeast-1:123456789012:sns-alerm # アラーム時に実行するSNSのarn(必須ではない)
      MetricName : Duration # 実行時間なのでDurationを指定
      ComparisonOperator : GreaterThanOrEqualToThreshold # 以上を表す
      EvaluationPeriods : 1 # 閾値を何回超えたときにアラーム状態にするか
      Period : 60 # 60秒
      Statistic : Maximum # 最大値
      Threshold : 3000 # 3秒(ミリ秒指定)
      Dimensions :
        - Name : FunctionName
          Value : sample-lambda
```

## 指定できる値

### MetricName
メトリクス名を指定する。
AWSリソースにより指定する値が異なる。
メトリクスの作成画面のメトリクス名から指定できる値が見れる。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478113/14221873-1e39-2ea8-1071-6c884e3f448f.png)

呼び出し回数でアラームを設定したい場合は、「Invocations」を指定する。

### ComparisonOperator
| 指定する値   |  意味 |
|:-------------|----:|
| GreaterThanOrEqualToThreshold|  以上 |
| GreaterThanThreshold|  より大きい |
| LessThanOrEqualToThreshold|  以下 |
| LessThanThreshold|  より低い |

### Statistic
| 指定する値   |  意味 |
|:-------------|----:|
| Average|  平均 |
| Maximum|  最大値 |
| Minimum|  最小値 |
| SampleCount|  サンプル数 |
| Sum|  合計 |

### Dimensions
公式ページ見ても指定の仕方がわかりませんでした。
マネジメントコンソールで作成画面を表示して設定しました。
サンプルの例だと下記の箇所を見ました。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478113/40f34006-14ff-e4e6-0d1d-ebd74012f134.png)

複数設定する必要なときもある。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478113/fa6f069d-e20b-f926-292c-9928c3287aa5.png)

上記のようなときは、Dimensionsは下記のように複数設定する。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:

・・・(省略)

      Dimensions :
        - Name : TableName
          Value : sampletable
        - Name : Operation
          Value : Query
```

# 最後に
CloudFormationをバリバリコーディングできる人がいるとしたらすごいなぁと思います。
1行定義するにも調べながら書いていて苦労しています。
[iOS13] 既存アプリのiOS13対応でハマったこと（現在進行形）

# 既存アプリのiOS13対応。楽勝かと思ったらアンドキュメントな罠が。。。
現在進行形な既存アプリのiOS13対応で、アンドキュメントな変更によりはまったところを、同じ状況な人のために残しておきます。

## CoreBluetooth Peripheralの取れるタイミング
今までは、

```objective_c:objective-c
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
```
の後に、

```objective_c:objective-c
[_centralManager retrievePeripheralsWithIdentifiers:identifiers];
```
で取れたんですが、（いや、実際には、取れるとは限らないんですが）
iOS13になってからは、**ちゃんと** 

```
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;
```
のイベントが通ってからでないと、ペリフェラル一覧が取得できなくなりました。
いや、そもそも前からそう書くのが正解のはずなんですが、僕のところに回されてきたプロジェクトの元のコードが、、、げふん

参考 [https://www.jenx.si/2019/10/02/changed-bluetooth-initialization-on-ios13/](https://www.jenx.si/2019/10/02/changed-bluetooth-initialization-on-ios13/)

## Settings.bundle 同名グループはダメ
これも暗黙のルールだったんでしょうが、、、
[[iOS13] Settings.bundleのグループ名が重複すると設定アプリの内容が正しく設定されない](https://qiita.com/bird_tomita/items/a2fcbdc215247ad0c71c)

## 画面横向き（Landscape）の時はステータスバーを表示できない。
当然、prefersStatusBarHidden をセットしたり、info.plistで設定したり、古い書き方のAppDelegateで設定したり、回転時に表示させようとしたり、色々やってるんですが、横向き時にステータスバーを表示させることができません。Appleのdeveloper forumなんかでも同様の報告がありますが、現状最新ベータ版でも直ってません。うーむ、、、

## モーダル表示画面の親。viewWillApearが呼ばれない。
モーダルビューの表示方法のデフォルトが変更された件で、みなさん「フルスクリーンに設定して表示の変更を回避」ってやってると思うので気がついてないと思いますが、裏に画面が見えてるということは、モーダル画面を閉じた時に親の「ViewWillApear」が呼ばれないのです。フルスクリーンにしない人は気を付けましょう。

以上、後半は昼休み終わりかけてダレたので、スクショもコードもありませんが！
C# 整数型

自分用です

| 型名| 記憶領域サイズ|扱える値の範囲|
|:-----------------|------------------:|:------------------:|
|byte|1バイト|0 ~ 255|
|sbyte|1バイト|-128 ~ 127|
|short|2バイト|-32,768 ~ 32,767|
|ushort|2バイト|0 ~ 65,535|
|int|4バイト|-2,147,483,648 ~ 2,147,483,647|
|uint|4バイト|0 ~ 4,294,967,295|
|long|8バイト|-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807|
|ulong|8バイト|0 ~ 18,446,744,073,709,551,615|
tfenvを使ってTerraform0.12のバージョンアップに必要な環境を用意する

### terraformを0.12にバージョンアップしたい
terraformは0.11と0.12に大きな変更がある。
[Upgrading to Terraform 0\.12 \- Terraform by HashiCorp](https://www.terraform.io/upgrade-guides/0-12.html)
その差分を埋めるためにサポートツールが公式から用意されている。

- terraform 0.11.4
    - `terraform 0.12checklist`
- terraform 0.12.x
    - `terraform 0.12upgrade`

このとき、0.12に上げるために使うのが `0.12checklist`で必要な環境がそろえば一気に変数名などを解決してくれる `0.12upgrade` を使いたいとなる。
実際は、その両方を逐一チェックしたい状態または一時的に両方を確認したい状況がうまれる。
そこで、両方のバージョンを行ったり来たりして使うことができる `tfenv` を使うとよいというお話です。

### [tfutils/tfenv: Terraform version manager](https://github.com/tfutils/tfenv)
rbenv等をご存じのかたは定番のhoge_env。
導入はいたって簡単でマニュアルのとおり。

#### 今回使いたいセット
Macで導入する場合はHomebrewを使えばいい。
必要なセットをあわせると以下。

```
brew install tfenv
tfenv install 0.11.14
tfenv install 0.12.x #最新を確認する
```
0.12は `tfenv list-remote | grep 0.12` でもしつつ最新を導入するとよい。
最新バージョンはreleaseを確認するのもあり。
[Releases · hashicorp/terraform](https://github.com/hashicorp/terraform/releases)

以下、terraformのバージョンが二つ入った状態になった例。

```
% tfenv list
  0.12.9
* 0.11.14 (set by /usr/local/Cellar/tfenv/0.6.0/version)
```

`0.12checklist` を使いたいときは　`0.11.14` に切り替えて、
`0.12upgrade` で出力を確認したい場合は `0.12.x` を使えばいい。

```
% tfenv use 0.11.14
[INFO] Switching to v0.11.14
[INFO] Switching completed
% tfenv list
  0.12.9
* 0.11.14 (set by /usr/local/Cellar/tfenv/0.6.0/version)
```


そうして両方で確認しながら実際に0.12.xでterraform plan/applyまでたどり着けば無事にアップデート完了までたどり着くことができる。
最小構成のreact-nativeをとりあえず動かす　

まずはreact-nativeを最小構成で動かすまでをメモ

```
$ npm i -g react-native-cli
$ react-native init hello # helloはプロジェクト名
. . . 
Done in 33.80s.

  Run instructions for iOS:
    • cd /home/oreore/dev/test/hello && react-native run-ios
    - or -
    • Open hello/ios/hello.xcodeproj in Xcode or run "xed -b ios"
    • Hit the Run button

  Run instructions for Android:
    • Have an Android emulator running (quickest way to get started), or a device connected.
    • cd /home/oreore/dev/test/hello && react-native run-android
```
react-native run-androidを実行しろとのこと

```
$ react-native run-android
. . .
ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.
```
JAVA_HOMEとjavaコマンドがないらしい。AndroidStudioインストール時にopenjdkが入っていたはずなので、せっかくなのでそれを利用する。
javaのpathはAndroidStudioの、File > Project Structureから確認可能。

![コメント 2019-10-28 110614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194356/e5f79ce3-e02b-e87f-8fdf-2b2d32ad86af.png)

パスとか入れる。

```
$ vim .bashrc

JAVA_HOME=/usr/local/android-studio/jre
export PATH="$PATH:/usr/local/android-studio/jre/bin"

$ source .bashrc
```

java確認

```
$ java -version
openjdk version "1.8.0_202-release"
```

いい感じなので、再度run-android実行

```
$ react-native run-android
. . .
error Failed to launch emulator. Reason: No emulators found as an output of `emulator -list-avds`.


FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project's local properties file at '/home/oreore/dev/test/hi/android/local.properties'.
```

ANDROID_SDK_ROOTを入れてる

```
$ vim .bashrc

export ANDROID_SDK_ROOT=/home/oreore/Android/Sdk

$ source .bashrc
```

run-android再実行

```
$ react-native run-android
. . .
BUILD SUCCESSFUL in 33s
28 actionable tasks: 28 executed
info Connecting to the development server..
```

成功してエミュレーターが立ち上がった。

![コメント 2019-10-28 122630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194356/f7e07a35-88e4-6e0f-a002-65526d594c32.png)


画面は黒いが初期状態なのでこれで成功しているはず。次はreduxとか入れてhello worldしよう。

追記：
黒い画面は正しく起動できていなかった。
理由は不明だが```android/app/src/main/assets```ディレクトリがなく、indexファイル的なのもなかった。ので、作成する

```
$ mkdir android/app/src/main/assets
$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res 
$ react-native start
```

welcome画面きた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194356/8b911f1e-7db9-9bf7-36e9-a87a9746d9a1.png)

追記2:
start&run-androidしてもエミュレータが動かなかったので、ANDROID_HOME環境変数を入れた。再度initから新規アプリを作成した場合、assetsがなくても起動したので、追記1はなくてもいいのかも。。
android開発環境作りでは、環境変数がすごい大事なことがわかった。

```
$vim .bashrc

export ANDROID_HOME=/home/oreore/Android/Sdk
```

メモ：
```error SHA-1 for file```は```npm i -g react-native-cli```で直った
Flutter style設定(カラー、フォントサイズ、フォントスタイル等)

部分的スタイリング変更は下記のように書けると思います。下記の例だとTestという文字をスタイリングしています。


```test.dart
child: Text(
  'Test',
   style: TextStyle(
     fontWeight: FontWeight.bold,
     fontSize: 20,
     color: Theme.of(context).primaryColor,
     ),
  ),
```

変更する箇所をglobalに設定したい場合は、下記のthemeの`textTheme`の記述のように書けます。
`textTheme > text`ということになります。

```main.dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Test App',
      theme: ThemeData(
          primarySwatch: Colors.grey,
          accentColor: Colors.amber,
          fontFamily: 'Quicksand',
          textTheme: ThemeData.light().textTheme.copyWith(
                title: TextStyle(
                  fontFamily: 'OpenSans',
                  fontWeight: FontWeight.bold,
                  fontSize: 18,
                ),
              ),
          appBarTheme: AppBarTheme(
            textTheme: ThemeData.light().textTheme.copyWith(
                  title: TextStyle(
                    fontFamily: 'OpenSans',
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                  ),
                ),
          )),
```
Array.prototype.fill()にオブジェクトをそのまま渡してハマった

知らなくてハマったのでこれから知らなくてハマる人のために書きます。

# 顛末
最初は単純な二次元配列でやっていたところを状態持たせようとオブジェクトに変更してハマりました。お馬鹿さんですね。

[maze-text-generator | m19e](https://github.com/m19e/maze-text-generator)

```javascript
const fillArray = arr => {
  // before
  // fillにそのままオブジェクトを渡してはダメです
  return arr.map(x => new Array(x.length).fill({char: 'ほ', blacklist: []}))
}

const maze = fillArray(generateEmptyArray([5,10]))
/*
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ

charだけ抜き出すとこう
*/

maze[0][0]['char'] = '黒'

/*
黒黒黒黒黒
ほほほほほ
ーー略ーー
ほほほほほ
ほほほほほ

え？
*/
```
わけがわからない。

# 解決

```javascript
const fillArray = arr => {
  // after
  // fillしたあとにmapで埋めてあげるといい感じ
  return arr.map(x => new Array(x.length).fill().map( x => { return {char: 'ほ', blacklist: []} }))
}

const maze = fillArray(generateEmptyArray([5,10]))

maze[0][0]['char'] = '黒'

/*
黒ほほほほ
ほほほほほ
ーー略ーー
ほほほほほ
ほほほほほ

ヨシ!
*/
```

解決したのでテキストを埋め込む再帰関数に投げます。

```javascript

fillGrid(maze, [...'黒猫列車はお客様第一'])

/*
黒ほほほほ
猫ほほほほ
列ほほほほ
車客様ほほ
はお第一ほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ
ほほほほほ

にゃあん!
*/
```

ありがとうございました。

# 補遺

よく考えたらArray.prototype.fill()自体使わなくていいのでは？

```javascript
const generateFilledArray = (x, y) => {
  return [...Array(y)].map(_=>[...Array(x)].map(_=>({char: 'ほ', blacklist: []})))
}

fillGrid(generateFilledArray(10,10), [...'銀河を繋ぐ黒猫列車、本日ひとりめのお客様がご乗車ですっ'])

/*
銀河ぐ黒猫列車ほほほ
ほを繋ほ日本、ほほほ
ほほほほひとりめのほ
ほほほほ車乗ほ客おほ
ほほほほでごが様ほほ
ほほほっすほほほほほ
ほほほほほほほほほほ
ほほほほほほほほほほ
ほほほほほほほほほほ
ほほほほほほほほほほ

いいでしょう!
*/
```

# 参考

[Array.prototype.fill() with object passes reference and not new instance - Stack Overflow](https://stackoverflow.com/questions/35578478/array-prototype-fill-with-object-passes-reference-and-not-new-instance)
[エンジニアのハマり時間とその技術的難易度の相関関係] (https://qiita.com/jabba/items/b0a0f8c310e164b4db2b)
Rails6 のちょい足しな新機能を試す100（不正なURLパラメータのリクエスト編）

# はじめに

Rails 6 に追加された新機能を試す第100段。 今回は、 不正なURLパラメータのリクエスト編です。
Rails 6 では、 不正なパラメータのリクエストの場合でもエラーにならずに、Railsのエラー画面を表示するようになりました。

Ruby 2.6.5, Rails 6.0.0 で確認しました。

```shell
$ rails --version
Rails 6.0.0
```

今回は、Userの CRUD を作って確認します。

# Rails プロジェクトを作る

```
$ rails new rails_sandbox
cd rails_sandbox
```

# User の CRUD を作る

```shell
$ bin/rails g scaffold User name
```

# データベースのマイグレーションを実行する

```shell
$ bin/rails db:create db:migrate
```

# 不正なパラメータのURLにアクセスする

ここで、 rails server を実行して、不正なパラメータつきの存在しないURLにブラウザからアクセスしてみます。
今回は、 http://localhost:3000/foo?x=1&x[y]=2 にアクセスしてみます

エラー画面が表示されます。

![error1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/6dd21505-47dc-8b3f-4d6f-313f527c5674.png)


このときパラメータの情報は画面には表示されません。

試しに不正ではないパラメータを使い http://localhost:3000/foo?x=1 にアクセスしてみます。

このときは、パラメータの情報が画面に表示されます。

![error2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/6786fd80-19d4-14a4-4551-72e100467209.png)

# Rails 5 では

Rails 5.2.3 では、 http://localhost:3000/foo?x=1&x[y]=2 にアクセスしたときに Rails のエラー画面は表示されません。
![error3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/df7a3a77-2723-8221-99f3-ac0b2347f868.png)


# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try100_malformed_url

# 参考情報

* [Fix a bug where DebugExceptions errors out when malformed query parameters are provided (COMMIT) ](https://github.com/rails/rails/commit/7b00308161241ac93df707f7ec84bfe6ed46cf80)
* [Fix a bug where DebugExceptions errors out when malformed query parameters are provided (PR) ](https://github.com/rails/rails/pull/32209)
* [Hide malformed parameters from error page](https://github.com/rails/rails/pull/36196)
docker の空き容量が足りないなら docker system prune すれば良いじゃない ( #docker )

35GBぐらい空きました。

```
$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              45                  35                  13.53GB             6.234GB (46%)
Containers          327                 7                   3.855GB             3.854GB (99%)
Local Volumes       425                 136                 30.98GB             30.45GB (98%)
Build Cache         0                   0                   0B                  0B
```


```

$ docker system prune --volumes
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all volumes not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y

Deleted Containers:
528096fb9948df25b4fa6396384d13d70981af032cb3cb012b4c9d16887231d2
a8fec1d907172c994b75d43bcab536ea4efa7efa88d83dc096d95b7b061162c7
6350e53bc429e04aa996c2e7356c13db7f3618294b28f1b45ecd18a233da4742


Deleted Networks:
project2_default
tmp_default

Deleted Volumes:
3ecff240d1d40bc44dc4bb0f6e099ae0c16d9f1bd5ffeea7a0274235209220eb
7b694aed1803d983e4fd475a6693d406d3c654f6c3c96429bc18bd0575541b60
9179d1174ec9a39d3fc4639e83a7190e8c794f5151ac14e7272648f8ec1c24fe


Deleted Images:
deleted: sha256:f2f39fb9f14f724101ee9dd9bb7995b61919b41ea6a69926aa897732928b7783
deleted: sha256:bf0e02c7377e2165c89e13f13aae8e83f139d57601942c12dbf7823b2930750f
deleted: sha256:16032a7be6cfa3acbebc6097a76bce72f44ef8954df3de4a3d2aef2424ef3ad3
...

Deleted Containers:

deleted: sha256:d35ef5a3a04121f3604511342f3170869e10223568d16dca1643f8badf3bba12
deleted: sha256:fdcdc09ea99cc713c4eaf52de7bfb0c6f98b6436b6e7307359b5ce28101f2bf4
...

Total reclaimed space: 35.08GB
```

```
$ docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              38                  9                   13.09GB             9.632GB (73%)
Containers          10                  7                   906kB               327.9kB (36%)
Local Volumes       5                   4                   504.9MB             96.35MB (19%)
Build Cache         0                   0                   0B                  0B
```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2630








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
今更ながらSwift5の変更点について調べました（パッケージマネージャ編）

#前置き
最後にパッケージマネージャについての変更点です。
パッケージマネージャなので開発リーダーや案件管理者の方は知っておいて損はなさそうです。
ここまで長いこと調査（理解）に時間をかけましたが、今回は少ないのでサクッといけそうwww

#パッケージ構成ファイルの追加
[[ SE-0219]](https://github.com/apple/swift-evolution/blob/master/proposals/0219-package-manager-dependency-mirroring.md)

SwiftPMが追加入力として使用できる依存関係ごとのミラーリング情報を保存するために、「パッケージ構成」ファイルが導入されたとのこと。このファイルはjson形式ですがSwiftPMが操作することを前提としているそうです。
なので勝手に編集することはしない方が良さそうです。

#パッケージマネージャープラットフォームの展開設定
[[SE-0236]](https://github.com/apple/swift-evolution/blob/master/proposals/0236-package-manager-platform-deployment-settings.md)

SwiftPMは現在、macOSデプロイメントターゲットにハードコードされた値を使用してプラットフォーム展開しています。これにより、プラットフォームがハードコーディングされていたりしているそうで変えたいとのこと。
そこでapiを新たに導入してターゲットを明確化させようと言うことらしいです。

```swift
/// Represents a supported platform.
struct SupportedPlatform {
    static func macOS(_ version: MacOSVersion) -> SupportedPlatform
    static func macOS(_ versionString: String) -> SupportedPlatform

    static func tvOS(_ version: TVOSVersion) -> SupportedPlatform
    static func tvOS(_ versionString: String) -> SupportedPlatform

    static func iOS(_ version: IOSVersion) -> SupportedPlatform
    static func iOS(_ versionString: String) -> SupportedPlatform

    static func watchOS(_ version: WatchOSVersion) -> SupportedPlatform
    static func watchOS(_ versionString: String) -> SupportedPlatform
}

/// List of known versions.
extension SupportedPlatform.MacOSVersion {
    static let v10_10: MacOSVersion
    static let v10_11: MacOSVersion
    static let v10_12: MacOSVersion
    ...
}

final class Package {
    init(
        name: String,
        platforms: [SupportedPlatform]? = nil,
        ...
    )
}
```

#パッケージマネージャーターゲット固有のビルド設定
[[ SE-0238]](https://github.com/apple/swift-evolution/blob/master/proposals/0238-package-manager-build-settings.md)

SwiftPMは現在、ビルドツール（コンパイラ、リンカ、等）は、ビルド時に呼び出される方法をカスタマイズするための機能でやっていて、ターゲットを構築するためにいくつかの基本的なカスタマイズを行いたいパッケージ作成者にとって色々と面倒なようです。
そこでターゲット・ファクトリメソッドって奴に引数を追加してあげてプロジェクトとライブラリのコンパイルのバージョンを区別しようと言うことらしいです。

これによって**プロジェクトのバージョンとライブラリのswiftバージョンが異なってもビルドできるようになるのか？**これは実際に検証実験が必要なので後日加筆したいと思います。

#終わりに
一つづつ調べて行きましたが、途中からswiftを始めた身としてはかなり勉強になりました。
経験が浅くとも調べることによって過去の経緯・今後の展開等把握できるいい機会となると思うので、じっくり調べてみるのも悪くないと思いました。
今後も新しいのが出たら自分なりに解釈して行こうと思います。
#Mac の絵文字入力コンソールでクラッカー ( tada cracker party popper ) を入力するには party で検索すべし

tada ヒットしない
popper ヒットしない
cracker ヒットしない
party <- なにこれ

![image](https://user-images.githubusercontent.com/13635059/67644981-58e81d80-f969-11e9-950e-216b139982fd.png)
![image](https://user-images.githubusercontent.com/13635059/67644982-5a194a80-f969-11e9-892e-ae270e683660.png)
![image](https://user-images.githubusercontent.com/13635059/67644985-5b4a7780-f969-11e9-9a52-2b896018073e.png)

絵文字のエイリアスの世界にも標準規格を！


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2629








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
AWSのrootアカウントでMFA設定時に「アクセス権限が必要です」と出た時の話


前提条件
--------------------
認証アプリ：Google Authenticator (Google 認証アプリ)


結論
--------------------

認証アプリへ登録したアカウントを、認証アプリ内から一回消して、QRコードをすぐ読み直しましょう。

当初
--------------------

AWSのrootアカウントへ、MFA(Multi Factor Authentication)を有効化しようとしたんです。
しかし、`アクセス権限が必要です`と出てきて進みませんでした。
説明文章にある`認証コード１`、`認証コード２`、`連続`の意味を思い出せず、ちょっと四苦八苦してた時に、
「ああ、順次表示されたコードを2回連続で入力するのね」
と理解したのですが、それでもダメでした。後にググって、同じ様に若干ハマってた人がいたので、手順はOKと判断しました。
しかし、何故か`アクセス権限が必要です`がまだ出ます。
`root`なんだから、`アクセス権限が必要です≠IAMのアクセス権限が必要です`だよなぁ・・・と思いつつ、IAMユーザにアクセス権限を付加したりなんだりと無駄な事をやり・・・

解決
--------------------

もう一度、rootアカウントのMFA有効化を試し、
「一回認証アプリへ登録したアカウントに異常があるかもしれない」
と判断し、認証アプリへ登録したアカウントを認証アプリから削除、登録し直しました。
→この行動を取った理由は、以前MFA有効化をした時用に別のモバイルデバイスがあって、
新旧の認証アプリで表示されていた認証コードが不一致だったので、
時間なのかsaltなのかは分からないけども、認証コードの仕組みで違いが出たのだろうなぁ・・・と想像したためです。

で、結論は先に書きましたが、MFA有効化は成功し、ログアウトしてサインイン、認証コードが通る事を確認出来ました。
認証コードをフワっとした理解のまま使っていたので、小一時間無駄にしてしまいました。
これを機会に、認証コードについての理解を少しだけでも仕入れてみました。


認証コードについてのザックリした理解
--------------------

↓ググって掴みに良さそうな記事を見つけたのでリンク貼っておきます。
[Google 認証システムの仕組み(sekika.github.io)](https://sekika.github.io/2016/03/26/GoogleAuthenticator/)

### 元仕様

RFCなんですねー、6238です。

### 仕組み

**ほぼ**ワンタイムパスワードを作って認証する仕組みです。
準備や手順は非常に単純で、

- QRコードを読み込むと、サーバが生成した秘密鍵を受け取れる
  - なので、QRコードを読み込んだ時点でサーバとクライアントで秘密鍵を共有した状態になります。
- **30秒間だけ有効になるワンタイムパスワード**を作っている
  - クライアント側では30秒ずつ別のパスワードが表示されるのは、これが理由

#### ザックリ図解

```
<<準備: 秘密鍵を盗まれたらOut>>
[      ケータイ電話   ]          [     サーバ     ]
秘密鍵 <- Google認証アプリ   <-   QRコード <- 秘密鍵

<<認証: 確認コードを盗まれたらOut(ただし約30秒間)>>
[      ケータイ電話   ]          [     サーバ     ]
           秘密鍵   ->           <- 秘密鍵
現在時刻 -> カウンタ -> 認証コード <- カウンタ <- 現在時刻
```

#### 補足

- QRコード以外にもBase32文字列でも認証アプリへ登録可能だそうです。
- 参考リンクにもある通り、中間者攻撃を防ぐ仕様は無いらしいので、
**30秒間はずっと有効なパスワード**という扱いなので、**One-Period Password**と呼んだ方が適切に思えます。
(サーバ側で、「一回認証OKになったら、次の認証コード発行までは同じ認証コードは無効化」としておけば、本当にワンタイムなパスワードになりますね)


結局、手順をどう誤ったのか
--------------------

おそらくは以下の通りでしょう。

1. 「MFAの有効化」で認証アプリへQRコードを読み込み → 秘密鍵を認証アプリへ保存した
2. 「認証コード１」、「認証コード２」と「連続」の意味が分からず、MFA有効化に失敗したので一旦「キャンセル」した → **おそらく、この時点でサーバ内の秘密鍵は無効化されたのでしょう**
3. ヘルプを調べたりググったりして情報を得てから再度MFA有効化のためにQRコードを読み込み、しかしMFA有効化に失敗した
→**QRコードの再読み込みでは、認証アプリ内に既に作成した秘密鍵は上書きされなかった、しかもサーバ内には新しい秘密鍵が作成されたので、認証アプリとサーバとの間で秘密鍵の不一致が発生**と推論します。(秘密鍵を照合したいですが、公開してもらえないでしょうから。。)
4. 小一時間経過後、認証アプリ内のアカウントを削除し、QRコードを再読み込みする事で、MFA有効化に成功
AndroidのWebView復帰処理について

### Android WebView を利用したときの、復帰処理まとめ
- アプリ内でブラウザを表示する際に利用する`WebView`コンポーネントを利用した際の、画面復帰処理まとめです。

### WebViewの復帰をさせよう

#### 状態の保持をするときは

- `WebView`には、表示状態を保持するための`saveState`が用意されているので、これを使って復帰処理をします。
- 使用している`Activity`や`Fragment`の`onSaveInstanceState`の引数を利用してデータの保持を行います。
 
```kotlin:WebviewFragmentSample.kt

override fun onSaveInstanceState(outState: Bundle) {
        webView?.saveState(outState)
        super.onSaveInstanceState(outState)
    }

```

#### 状態の復帰をするときは

- `Activity`であれば`onCreate`、`Fragment`であれば`onCreateView`の引数`savedInstanceState :Bundle?`を利用しましょう。
- この`savedInstanceState`にすでに保持されたデータがあれば何らかのデータが引き渡されます。（なにもデータがなければ`null`です）
- `savedInstanceState`を`WebView`の`restoreState`に渡してあげることで復帰処理が行われます。

##### 注意点
- `WebView`の`loadUrl`処理は同期処理では無いです。なので復帰したからといってURLが引き継がれているという保証が無いことに注意しましょう
- [コード](https://github.com/aosp-mirror/platform_frameworks_base/blob/882f63b2f204a5890cf428505146191c94a751ff/core/java/android/webkit/WebView.java#L2015)はこのあたりから見れます。
- urlのデータをHandlerMessageを利用して、WebViewCoreに送信して処理を実施しているので、必ずしも同期的に処理が完了する保証がなさそうです。
    - なので、`restoreState`後に正しくURLが入っているかを確認し、入っていなければ再度セットするようにしておくのが良いと思います。

```kotlin:WebviewFragmentSample.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    if (savedInstanceState != null) {
        webView?.restoreState(savedInstanceState)
    }
    if (webView?.url == null) {
        webView?.loadUrl(url)
    }
    ・・・省略・・・
}

```

### 最後に
- 対応を見逃しそうな`onSaveInstanceState`の話でした、画面の復帰処理は忘れがちな部分だったりしますので、しっかり入れておきましょうって話でした

これからも、良いアプリ開発を目指して:dancers: