OmniAICreator/Qiita-1.07M huggingface dataset:
Swift：NSImageからDataを生成するときのポイント

# 背景

Twitterに画像を投稿するために、画像のファイルURLから`NSImage`を生成して、それを`Data`に変換してPOST APIに投げるというコードを書いていました。一見上手く動いているように見えて、特定のPNG画像だと色がおかしい状態で投稿されることがあることが判明し、原因を究明したところ、`NSImage`から`Data`を生成する時、注意しないとデータの透明度に関するデータが欠損するのか、不完全な`Data`が生成されることがわかりました。

オリジナルのPNG画像↓
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/9fdc2ef9-7e76-b0fb-8658-6dd60c120bac.png)

色がおかしくなったPNG画像↓
![bad_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/e46f7d15-47e0-26e4-c86b-5b48632fb906.png)

# 対処方法

[検索して出てきた記事](https://stackoverflow.com/questions/28171410/how-to-get-png-representation-of-an-nsimage-object-in-swift)によると、いったん`NSImage`を`CGImage`に変換してから`Data`にすると良さそうだと判明したのでそちらを使ったところ上手く行きました。

# 実験に使ったサンプルコード

```swift:Command_Line_Tool_Project
import Foundation
import AppKit

func saveImage(name: String, data: Data) {
    guard let dir = FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first else { exit(3) }
    let url: URL = dir.appendingPathComponent(name)
    do {
        try data.write(to: url)
    } catch {
        Swift.print(error.localizedDescription)
    }
}

// 良い方法
func goodMethod(image: NSImage) -> Data? {
    guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil }
    let rep = NSBitmapImageRep(cgImage: cgImage)
    return rep.representation(using: .png, properties: [:])
}

// 悪い方法
func badMethod(image: NSImage) -> Data? {
    guard let rep = image.representations.first as? NSBitmapImageRep else { return nil }
    return rep.representation(using: .png, properties: [:])
}


guard let image = NSImage(contentsOfFile: "/Users/ユーザ名/Desktop/sample.png") else { exit(0) }

if let data = goodMethod(image: image) {
    saveImage(name: "good_image.png", data: data)
}

if let data = badMethod(image: image) {
    saveImage(name: "bad_image.png", data: data)
}
```
nginx をフォアグラウンドで動かす (Dockerfile用)

# スマートな方法

「シンプルですが、なかなかよい方法では。(自賛)」、と書いた方法が、かなりダサいことが判明したので修正します…

起動用のシェルスクリプトを書いて、`-g` オプションで `"daemon off"` ディレクティブを指定します。

```shell:$PREFIX/sbin/nginx-runner
#!/bin/sh

if [ -f $PREFIX/logs/nginx.pid ]; then
    rm -f $PREFIX/logs/nginx.pid
fi

$PREFIX/sbin/nginx -g "daemon off;"
```

これだと別に設定ファイルを用意しなくていいのでスマートですね……

最後のセミコロンをお忘れ無く！

# 古くてダサい方法…

小さな設定ファイルを作ります。

```nginx:$PREFIX/conf/nginx-foreground.conf
daemon off;
include nginx.conf;
```

起動用のシェルスクリプトを書きます。

```shell:$PREFIX/sbin/nginx-runner
#!/bin/sh

if [ -f $PREFIX/logs/nginx.pid ]; then
    $PREFIX/sbin/nginx -s quit
    rm -f $PREFIX/logs/nginx.pid
fi

$PREFIX/sbin/nginx -c $PREFIX/conf/nginx-foreground.conf
```

`Dockerfile` の `CMD` でこれを使うと `nginx-foreground.conf` を読むので、フォアグラウンドで動きます。

一方、手動で動かすときには、何も指定しなければ `nginx.conf` を読むので、バックグラウンドで動作します。

シンプルですが、なかなかよい方法では。(自賛)
Jupyter 公式の DockerHub に関するメモ

自身の理解のためにある程度調べたことをナレッジになればと思い記載

# リポジトリ毎の関係性

[Jupyter 公式の Read the Docs](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html) に記載がある。

[Image Relationships](https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#image-relationships)

派生関係としては以下の通り。

- base-notebook
    - minimal-notebook
        - scipy-notebook
            - tensorflow-notebook
            - datascience-notebook
            - pyspark-notebook
                - all-spark-notebook
        - r-notebook

イメージ名からは分かりづらいが、`minimal-notebook`の方が`base-notebook`よりもイメージサイズが大きい。

# scipy-notebook、datascience-notebook の違い

よく使われる（であろう）やつ

- `scipy-notebook`
    - データ分析で使われるライブラリセット(pandas, scikit-learn など)を追加したもの
- `datascience-notebook`
    - `scipy-notebook` にさらに R や Julia を追加したもの

したがって、Python しか使わないなら`scipy-notebook`で十分（勘違いしていた）

# イメージ Tag について

各リポジトリ内には多くのイメージ Tag が存在し、どれを利用すれば良いか一見分かりづらい。
イメージ Tag の規則はリポジトリ毎に細かい癖はありそうだが、例えば`base-notebook`は2020/7/29時点で以下のようになっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154711/c36edfd4-93da-49bf-0dc7-7f644f6cffef.png)

- 黄色の強調部分(`b5abe43c6d31`)はコンテナイメージのSHAダイジェスト。同一ダイジェストに対して6つの Tag が存在している。
    - つまり、この6つは全て同一コンテナイメージを指すエイリアス。
- 最後のイメージ Tag (`b90cce83f37b`)もSHAダイジェスト。これは GitHub 側のコミットハッシュ。
    - このイメージ Tag に対応する Git コミットが[こちら](https://github.com/jupyter/docker-stacks/commit/b90cce83f37b0ce0c752f49a9ee5747033c03b36)

これらから分かることは、`base-notebook`のイメージ Tag は Python バージョンや Jupyter コンポーネント（Jupyter Notebook、JupyterLab、JupyterHub）毎にバージョンアップデートしたものが登録されている。

## 分かっていないこと

`base-notebook`は様々なエイリアスが1つのコンテナイメージを指しており、過去の Python バージョンに対応したイメージ Tag を見つけることができる。

ここで、最も実利用する（であろう）`scipy-notebook`のイメージ Tag はコミットハッシュばかりとなっており、目的の Python バージョンに対応するイメージ Tag が見つけづらい。
※逆にいうと、`scipy-notebook`の各イメージ Tag に対してベースイメージとなっている`base-notebook`、`minimal-notebook`のイメージ Tag をどのようにして見つけるのかが分からない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154711/a94ee57b-eee8-fdda-9893-490f7da5414a.png)

いくつかのイメージを試してみたところ、Python のマイナーバージョン（3.6.6, 3.6.7, 3.8.0, ...）毎にイメージ Tag が作成されているっぽい?
【Android/Kotlin】ViewModel・LiveData基本

#ViewModelとは？
　ViewModelとは、UI関連のデータを保存し管理してくれるクラスです。分かりやすい活用方法でいうと、画面のローテーションをしてもUIを保持してくれたりします。ローテーションに対してUIを保存する方法として、`onSaveInstanceState() `メソッドをアクティビティのライフサイクルに組み込むという手がありますが、複雑なデータは保持できない＋ライフサイクルを考えなければならないという点で、リスクがあります。そこで、ViewModelが大活躍します。以下の図を見てください。
![https___qiita-image-store.s3.amazonaws.com_0_88858_68e99b0c-215d-325e-1f75-6875fa580031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658219/7a8f1174-78a6-cbc8-b66a-5b3ea7ab5dec.png)
この図は、ViewModelとActicvityのライフサイクルを表したものです。左がActivity、右がViewModelとなっています。ぱっと見で分かるように、ViewModelにはほぼライフサイクルにおける過程が存在しません。Activityが完全に破棄される（別のアプリに切り替えたり）ときにonClearedが呼ばれるだけです。したがって、いくら画面を回転させてActivityが再生成されようが、ViewModelはそのデータを保持し続けてくれるのです。
　もう一つのViewModelのメリットとして、アクティビティやフラグメントが行っていた非同期呼び出しにおけるメンテナンスを容易にしてくれる事が挙げられます。先述したように、ViewModelのライフサイクルは非常にシンプルなので、`onDestroy`でいちいち通信をキャンセルさせるなどといったリソースの無駄を排除できます。
 以上二つの点がViewModelの主なメリットと役割です。UIに関わるロジックをまとめて管理して複雑さの軽減と効率性の向上を図りましょう。

#LiveDataとは？
　ライフサイクルに応じて、データを監視することが出来るクラスです。ActivityやFragmentがアクティブであるときに更新があったデータに対して、自動的に更新を行ってくれます。LiveDataの説明としては以上の通りですが、これではあまり理解が出来ないと思うのでいくつかあるメリットを紹介していきます。
　まず、先ほど示唆したようにUI をデータの状態と一致させてくれます。これによって、監視対象にしたデータはアプリのデータが変更されるたびに UI を更新するのではなく、変化が生じるたびに UI を更新できます。言い換えると、能動的にUIを更新していたところを、受動的に更新してくれるということです。また、それに伴ってデータを常に最新にしてくれます。
　次に、手動でライフサイクルを処理する必要を省いてくれます。これは、LiveDataが自動的に関連するライフサイクルの状態を認識してくれるためです。ViewModelで例に挙げたように、ローテーションでもデータを保持してくれたりします。それと同時に、メモリリークが発生しません。関連付けているライフサイクルが破壊されたら、それに連動してデータを自動的にクリーンアップしてくれます。
　このように、LiveDataも煩わしい処理を自動でこなしてくれます。

#ViewModelとLiveData
　ViewModelとLiveDataのそれぞれについて、↑のように説明したわけですが、どちらも同じようなメリットを持っていて、いまいち違いが判らないと思います。利点だけを見れば確かに似通うんですが、この二つはそもそも使われ方が異なります。基本的に、この二つはセットで使われますが、ViewModelはUIに関するロジックを入れる箱で、LiveDataはその中のデータ一つ一つの監視を担います。
　この二つを使うのは非常に簡単です。以下にその例を示します。

```
class Hoge : ViewModel() {
    private var fuga: LiveData<String>
}
```
このように、ViewModelクラスを拡張した箱を作って、LiveDataをインスタンス化して各データの監視を行う場所を作ります。今回はHogeクラスにはfugaしか格納されていませんが、ViewModelを拡張するクラスは基本的にUIに関わるロジックしか入れないことになっています。これは、ViewModelでクラスごとに機能の住み分けを徹底するためです。具体的にはMVVMという設計方針が関係します。
　次に、MainActivityでfugaを監視対象にします。

```
private val hoge : Hoge by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
    hoge.fuga.observe(this, Observer { it -> foo = it })
}

```
hogeというViewModelを拡張したHogeクラスのインスタンスを作り、onCreate内でfugaの具体的な内容（foo）を指定してデータをセットします。observeメソッドはその名の通り、引数を監視対象にします。
　これで、fugaは先述したようなViewModelとLiveDataの恩恵を受けれるようなプロパティになりました。これだけで様々な手間が省けるのは非常に楽です。

#ViewModelとLiveDataの実装
　最後に、この二つを使うためにbuild.gradle(app)ファイルで必要な実装をしましょう。ライフサイクル対応コンポートの中から、ViewModelとLiveDataだけを実装します。現在の最新版は2.2.0です。

```
 dependencies {
        def lifecycle_version = "2.2.0"

        // ViewModel
        implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
        // LiveData
        implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
}
```

##おわり
　今回は備忘録的な意味もかねて記事を書きました。まだ不透明な部分もあるので、多少誤りがあると思われますがご了承ください。今回は公式リファレンスのViewModelとLiveDataのページを主に参照しました。
DeepRunning　～Level4.4.1～

#Level４．機械学習講座（理論と実践）
##4-4.主成分分析
###4-4-1.主成分分析とは

　　●予測や分類とは異なるタスクで「次元圧縮」をする。
　　●多変量データの持つ構造をより少数個の指標に圧縮する
　　　要するに高次元のものを、なるべく情報量を減らさずに低次元に圧縮すること。
　　　⇒ 1000次元のものを10次元にする。
　　　　　⇒ 高次元のものを目で見て傾向をつかむことができる。
　　●少数変数を利用した分析や可視化（2・3次元まで）が可能。
　　　4次元以上になると人間が理解できない。


###4-4-2.主成分分析の式
　　【学習データ】
　　　　i番目のデータの1個目の要素、2個目の要素･･･とm次元まである。

```math
x_i=(x_{i1},x_{i2},･･･,x_{im}) \in \mathbb R^m
```

　　【平均（ベクトル）】

```math
\bar x = \frac{1}{n}\sum^{n}_{i=1} x_i
```

　　【データ行列】
　　　　原点まわりで分散するようにしてあげる。

```math
\bar X=(x1 - \bar x,･･･,x_n - \bar x)^T \in \mathbb R^{n×m}
```

　　【分散共分散行列】
　　　　$\bar X$さえ求まれば計算できる。

```math
\sum = Var(\bar X) = \frac{1}{n}\bar X^T \bar X
```

　　【線形変換後のベクトル】
　　　　jは射影軸のインデックスであり、3次元を2次元に圧縮ならj=2
　　　　3次元を1次元に圧縮ならj=1となる。

```math
s_j = (s_{1j},･･･,s_{nj})^T = \bar X a_j　　a_j \in \mathbb R^m
```

###4-4-3.線形変換後の分散
　　●係数ベクトルが変われば**線形変換後の値**が変化する。
　　●情報量を**分散の大きさ**と捉える。
　　●線形変換後の変数の分散が最大となる射影軸を探索すること。

```math
s_j = (s_{1j},･･･,s_{nj})^T = \bar X a_j　　a_j \in \mathbb R^m
```
　　で、元の空間にある分散$\bar X$に対して、$a$で線形結合する。
　　$a$が変われば線も変わる。

　　【線形変換後の分散】
　　　　$s_j$を最大にしたい。

```math
Var(s_j) = \frac{1}{n}s_j^Ts_j = \frac{1}{n}(\bar Xa_j)^T(\bar Xa_j)=\frac{1}{n}a_j^T\bar X^T\bar Xa_j = a_j^TVar(\bar X)a_j
```

###4-4-4.制約付き最適化問題を解く
　　●ノルムが1となる制約を入れる。⇒そうしないと無限に解が出てくる。
　　　例えば、ベクトル(1,1)とベクトル(2,2)は同じ向きなので解が無限に出る。

　　【目的関数】

```math
arg \  max_{a \in \mathbb R^m} \ a_j^T Var(\bar X)a_j
```

　　【制約条件】
　　　　ノルムが1になるもののみを考える。

```math
a_j^Ta_j = 1
```

　　●制約付き最適化問題の解き方
　　　ラグランジュ関数を最大にする係数ベクトルを探索（微分して0になる点）

　　【ラグランジュ関数】
　　　　目的関数　－　制約条件

```math
E(a_j) = a^T_jVar(\bar X)a_j - λ(a^T_ja_j - 1)
```

　　　やることは、ラグランジュ関数が作れたら微分し、=0を解いてあげる。
　　　$a$という式があって、$\hat a$という解が1つ出てくる。
　　　$\hat a$という解は、上記のような制約付き最適化問題の解と同じになっている。

###4-4-5.最適解を求める
　　●ラグランジュ関数を微分して最適解を求める。
　　　⇒　元のデータの分散共分散行列の固有値と固有ベクトルが、制約付き最適化問題の解となる。

　　【ラグランジュ関数の微分】
　　　　計算方は復習しておこう。ベクトル微分をする。

```math
\frac{\partial E(a_j)}{\partial a_j} = 2Var(\bar X)a_j - 2λa_j = 0\\

解は･･･ \  Var(\bar X)a_j = λa_j
```
　　●射影先の分散は固有値と一致する。

```math
Var(s_1) = a^T_1Var(\bar X)a_1 = λ_1a^T_1a_1 = λ_1　　 (a^T_1a_1=1)
```


⇒応用数学の固有値、固有ベクトルと同じ形である。
　$a$は元のデータの分散共分散行列の固有値と固有ベクトルを求めてあげれば、
　分散を最大にする軸になっている。主成分分析の結果である。

###4-4-6.寄与率
　　「分散共分散行列を計算」⇒「固有値問題を解く」
　　　⇒「最大m個の固有値と固有ベクトルのペアが出現」

　　　●圧縮した結果、どれだけ情報がロスしたのかを知りたい！！
　　　●第1～xx次元分の主成分の分散は、元のデータの分散と一致する。
　　　　⇒ 固有値を全て足したものは、元の空間の分散と一致する。
　　　　　　分散を全部足し合せたｍのが全情報量である。

　　　●2次元のデータを2次元の主成分で表示した時、固有値の和と元のデータの分散は一致する。
　　　●第k主成分の分散は、主成分に対応する固有値である。

```math
Var_{(total)} = \sum_{i=1}^m \ λ_i
```

　　【寄与率】
　　　　第k主成分の分散の全分散に対する割合のこと。（第k主成分が持つ情報量の割合）

```math
c_k = \frac{λ_k}{\sum_{i=1}^m \ λ_i}　　「第k主成分の分散 ／ 主成分の総分散」
```

　　【累積寄与率】
　　　　第1～k主成分まで圧縮した際の情報損失量の割合のこと。

```math
r_k = \frac{\sum_{j=1}^kλ_j}{\sum_{i=1}^m \ λ_i}　　「第1～k主成分の分散 ／ 主成分の総分散」
```
【編集中】GitLabで開発してみる

# はじめに

# TODO
- [ ]  書くネタの章立て考える
- [ ]  他ツールとの連携
- [ ]  CD周りを構築

## CI/CD関連

```yml:.gitlab-ci.yml
default:
  image: 'SignalRChat'

variables:
  NUGET_PATH: 'C:\GitLab-Runner\NuGet\nuget.exe'
  VSTEST_PATH:  'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe'

stages:
  - build
  - test
  
build_job:
  stage: build
  script:
    - chcp 65001
    - 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"'
    - '"%NUGET_PATH%" restore SignalRChat.sln'
    - 'MSBuild.exe SignalRChat.sln /p:Configuration=Debug'   # for test
    - 'MSBuild.exe SignalRChat.sln /p:Configuration=Release' # for deploy
  only: 
    - develop
    - master
  artifacts:
    expire_in: 1 day
    paths:
      - 'SignalRChat.Tests\bin\Debug' # for test
      - 'SignalRChat\bin\Release'     # for deploy

test_job:
  stage: test
  script:
    - chcp 65001
    - 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat"'
    - '"%VSTEST_PATH%" "SignalRChat.Tests\bin\Debug\SignalRChat.Tests.dll" /Logger:trx'
  only: 
    - develop
    - master
  dependencies:
    - build_job
```

### 参考サイト
◆GitLab CI/CD pipeline configuration reference
　https://gitlab.com/help/ci/yaml/README
VBAで恋人占いやってみた

```vb
Sub uncode()
'変数宣言
    Dim GF As Boolean   '彼女の有無
    GF = False
    
    Dim Age, year As Integer    '年齢、年号
    Age = 0
    year = 1

Do Until year = Age  '彼女ができる日
    If year = Age Then
        GF = True
    End If
       MsgBox "令和" & year & "年" _
              & vbCrLf & Age & "歳" & "＼(^o^)／"
      Age = Age + 1
      year = year + 1
Loop

MsgBox "おめでとう(ノ゜∇゜)ノ"

End Sub
```
【試行錯誤】はじめてのGBDT

# 基本的な書き方
まず、ネットの偉大な先輩方のソースコードを見ながら学習できる状態にした。
基本的なことであるが、復習も兼ねて説明する。
ちなみに今回はmulti-class loglossを評価指標にしている。
このような状態で学習させたところ過学習してしまったので、特徴量を考える必要がある。

- `pd.read_csv()`    csvの読み込み
- `train_test_split()`    学習用と評価用それぞれの説明変数、目的変数
- `xgb.DMatrix()`    xgboost用の行列に変換する
- `xgb.train()`    xgboostで学習を行う

```python
import pandas as pd 
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss 
from sklearn.preprocessing import LabelEncoder
import category_encoders as ce

df_train = pd.read_csv('/kaggle/input/train_hoge.csv')
df_test = pd.read_csv('/kaggle/input/test_hoge.csv')

y = df_train['hoge']
x = df_train.drop(['hoge','hoge','hoge','hoge'], axis=1)
test = df_test.drop(['hoge','hoge'], axis=1)

list_cols = ['hoge','hoge', 'hoge']
ce_oe = ce.OrdinalEncoder(cols=list_cols,handle_unknown='impute')
x = ce_oe.fit_transform(x)
test = ce_oe.fit_transform(test)

tr_x, va_x, tr_y, va_y = train_test_split(x,y,test_size=0.2, train_size=0.8, shuffle=True)

dtrain = xgb.DMatrix(tr_x, label=tr_y)
dvalid = xgb.DMatrix(va_x, label=va_y)  

param = {'max_depth': 3, 'eta': 1, 'objective': 'multi:softprob', 'num_class': 13, 'eval_metric': 'mlogloss'}

evallist = [(dvalid, 'eval'), (dtrain, 'train')] 

num_round = 1000
bst = xgb.train(param, dtrain, num_round, evallist, early_stopping_rounds=5)  

print('Best Score:{0:.4f}, Iteratin:{1:d}, Ntree_Limit:{2:d}'.format(  
     bst.best_score, bst.best_iteration, bst.best_ntree_limit))

dtest = xgb.DMatrix(test)  
pred = ypred = bst.predict(dtest, ntree_limit=bst.best_ntree_limit)  
print("pred:",pred)
xgb.plot_importance(bst) 

my_solution = pd.DataFrame(pred)
my_solution.head()
```

# 基本的な確認

## 評価指標と目的関数の一致
目的関数とは学習で最適化される関数である。
評価指標とは予測性能を測る指標である。
現在、評価指標は`multi-class logloss`であることは確定している。
そのときの目的関数は`softprob`でいいのだろうか？
基本的には、目的関数＝評価関数とした。
解決はしていないが、[『Kaggleで勝つデータ分析の技術』](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94-ebook/dp/B07YTDBC3Z)のP237に以下のような記述があった。
>マルチクラス分類の場合はmulti:softprobを設定することで、multi-class loglossを最小化するように学習する


## 時系列データの取り扱い

ルールに「特徴量として未来情報を予測アルゴリズムに与えることは禁止」とある場合、例えば以下のような工夫が必要である。

2017年の9月と10月のデータを評価データとする。
2017年の3月から8月までのデータを学習データとする。
ちなみにテストデータは2018年と2019年であるとする。

- 将来の目的変数の傾向が最も直近の年の傾向に近いという仮説から、テストデータにしか存在しない年を学習データに存在する最新の年に置き換える方法(外挿による想定外の挙動は避けられる)

## 問題を理解する

こういうい傾向があるのではないかという仮説を立てて検証する

- 投手の年齢によって、持っている球種に傾向がある
- 持ち球(球種)とコースの関係
- 右打者か左打者か
- アウトサイドかインサイドか
- バッターの打順は


# 宿題
- なぜ、multi-class loglossが評価指標のときにsoftpredを目的関数にするのか？
- softpredとsoftmaxの違いを出力的に、数学的に理解する
- label encodingが決定木でしか使えない(?)理由

# 総括
- 機械学習の基本的な記述方式を復習できてよかった。(sklearnによるデータ分割や評価指標、pandasのDataFrameなど)
- xgboostで学習するという経験を積むことができた。
- 特徴量の作り方についてきっかけをつかむことができた。



# 参考
- [xgboostの使い方：irisデータで多クラス分類](https://qrunch.net/@predora005/entries/qsCd1KKBHvPb9fAg?ref=qrunch)
- [Category Encodersでカテゴリ特徴量をストレスなく変換する](https://qiita.com/Hyperion13fleet/items/afa49a84bd5db65ffc31)
- [カテゴリ変数のエンコーディング](https://qiita.com/ground0state/items/f516b97c7a8641e474c4)
C++のOpen3Dをビルドしてexampleを動作させる

#概要
目標としてはOpen3DのnativePluginをUnityから利用してPointCloudの位置合わせをしたい。その為に必要なOpen3DのC++のビルド環境を整備してサンプルを実行できるところまでやります。

#環境
Windows10
VisualStudio2019
Cmake(cmake-gui)
git

#必要なものをインストール
## VisualStudio2019
2019が必要です。

##git
下記を見ながらインストールしました。
https://qiita.com/taketakekaho/items/75161e1273dca98cb4e1

## Cmake(cmake-gui)
以下を見ながらインストールしました。
https://www.kkaneko.jp/tools/win/cmake.html

## Open3DプロジェクトCloneしてcmakeでビルド
Open3Dの公式ページを見ながら行います。
http://www.open3d.org/docs/release/compilation.html#windows

### Open3DプロジェクトをClone
依存ライブラリも全部ダウンロードします。下記コマンドを適当なディレクトリで行います。

```powershell:
git clone --recursive https://github.com/intel-isl/Open3D
```

## pythonインストール
Open3D C++のpythonバインディングの為に必要らしいです。以下を見ながらインストールします。
http://www.open3d.org/docs/release/compilation.html#id6

## cmake gui設定
cmake-guiを立ち上げて、
[Where is the souce code]にOpen3Dのプロジェクトトップのディレクトリを、
[Where to build the binaries]にビルドした結果を出力させるディレクトリを入力します。ディレクトリは適当に作成したものを利用します。私はとりあえずOpen3Dプロジェクト直下にbuildディレクトリを作成して利用しました。

## Configure -> Generate
Configureボタンを押すと最終的に作成されるVisualStudioプロジェクトの情報を設定するUIが立ち上がります。ここで利用するVisualStudioのバージョンを選択します。私はVisual Studio 16 2019を選択しました。残りの選択項目は空白でOKで、Finishを押すとOpen3Dプロジェクト直下のCMakeLists.txtを実行しようとします。幾つかwainingが出ますが、とりあず無視で大丈夫で、Generateボタンを押すとvisualstudioの環境一式がbuildフォルダ内に生成されます。

## Open Project
Generateが成功するとOpenProjectボタンが押せるようになります。このボタンを押すとOpen3Dプロジェクトが開きます。

## ビルド
ソリューション構成をRelWithDebinfoにし、ソリューションエクスプローラーからALL_BUILDを選択してビルドします。するとC2220コードのエラーが出力されビルドが失敗してしまいます。

これの解決策をネットで探して以下を見つけました。CmakeList中の/WXの記述を削除すれば回避できるみたいです。
https://suzulang.com/cmake-c2220-wx/

なので、プロジェクトTOPにあるCmakeLists.txtの313行目にある/WXを削除します。

```cmake:CmakeLists.txt
        if(MSVC)
            target_compile_definitions(${target} PRIVATE NOMINMAX _USE_MATH_DEFINES _ENABLE_EXTENDED_ALIGNED_STORAGE)
           # target_compile_options(${target} PRIVATE /EHsc /wd4522 /Wv:18 /WX)
            target_compile_options(${target} PRIVATE /EHsc /wd4522 /Wv:18)
```

再びcmake-guiのContigure->Generate->OpenProject->リビルドを繰り返すと無事ビルドが出来ます。

# exampleを動作させる
builds/bin/examples\RelWithDebinfoにexamplesのexeファイルが出力されています。それぞれ使い方はbuild/examples/cppの中にあるcppファイルを見ればわかると思います。一例としてpointCloudのファイルであるplyファイルをみるVisualizer.exeを実行してみます。Visualizer.exeのあるディレクトリまで移動してpowershell等で下記を実行します。

```powershell:
.\Visualizer.exe pointcloud {plyファイル}
```
上記を実行するとpointcloudViewerが立ち上がります。

![plyViewer.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116884/3ce90eff-166b-caa4-1eed-b4869e73c404.png)

利用したplyファイルは下記からダウンロードしました。
https://github.com/keijiro/Pcx/blob/master/Assets/nebulousflynn/anthidium-forcipatum.ply

これだけでも単純にViewerとして機能するので使いどころありそうですね。他にも点群の位置合わせなど色々なサンプルがあるので興味があれば試してみるとよいと思います。

# まとめ
C++のOpen3Dをビルドできる環境を構築し、exampleを実行できるところまでやりました。目的としてはUnityPluginを作る所までやることでしたが、長くなるので別記事に分けます。
コロナはコロナで！Oracle 12c SQL基礎取得！

#Oracle 12c SQL基礎取得
最近はくもり雨ばかりですが、梅雨が明けそうで晴天が楽しみです。
今回は、7月15日にOracle 12c SQL基礎（1Z0-061-JPN）を取得したため報告します。
受験者の参考になれば嬉しいです。

##私について
2018年新卒でIT企業に入社しWebアプリケーションエンジニアとして3年目となります。就職前は農学を学ぶ教育機関にいたためどちらかといえばIT業界には探り探り足を踏み入れました。
今年の春に開発部隊からは距離を置き、別業務でリーダーを担うことになりました。ですので、本来はマネジメント系の学習に時間を割くべきですが、せっかく開発エンジニアを経験しましたのでDB系の知識があることを形として証明したくORACLE MASTER Bronzeの資格取得を目指しました。

開発エンジニアの時にはORACLEのDBを使用しており、簡単なDDL、DMLを扱える程度のベースでした。

入社以来の主な取得資格は下記です。 
2018年 
・**情報処理技術者（ITパスポート試験） **
・**Oracle認定JavaプログラマSE 7/8 Bronze**
2019年 
・**AWS 認定ソリューションアーキテクト – アソシエイト** 
・**Oracle認定JavaプログラマSE 8 Silver**
・**Webクリエイター能力認定試験-エキスパート **
・**情報処理技術者（基本情報技術者） **
2020年 
・**AWS 認定デベロッパー – アソシエイト**
・**Oracle Database 12c Bronze DBA 12c**
・**Oracle 12c SQL基礎**

##1.結果

正答率：70%（**合格ライン：65%**）
![IMG_4128.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403146/0618da43-0955-b62e-fe4c-d88cadbf76e4.jpeg)

##2.勉強

####期間
・2か月（5月中旬〜7月中旬）

####時間
・2時間／日（平日のみ、通勤時）

####書籍
・黒本（[徹底攻略 ORACLE MASTER Bronze 12c SQL基礎問題集［1Z0-061］対応](https://book.impress.co.jp/books/1114101023)）

####方法
練習問題と模擬問題を組み合わせて解く
①練習問題（1〜13章）※間違えた問題番号をメモ
②模擬問題
③練習問題※間違えた問題番号をメモ
④模擬問題
⑤練習問題※①③で間違えた問題のみ、間違えた問題番号をメモ
⑥以降、模擬問題
※練習問題は、スピードは遅くても大丈夫ですので解答の導き方を判断できれば切り上げてしまい模擬問題のみでよいです。練習問題よりむしろ模擬問題の方が本番の出題形式に近いためです。練習問題は一度でも間違えた問題を隙間時間にパラパラと確認する程度で大丈夫です。
※模擬問題は、解答の導き方（選択肢の消去法）がなるべく早くできるように時間をかけましょう。下記にもありますが75問を120分で解くため1問あたりに割ける試験時間が短いためです。



##3.振り返り

####判断軸を定着させること
実のところ、本番試験で残り7問は時間がなく2択まで絞れてもあとはあてずっぽでした。なので、選択肢を消去するための基本的な知識（判断軸）はしっかりと覚えましょう。解答をより短い時間で選べれば、正確に余裕を持って解き終えることが可能です。

####まずはエラーを疑う、次に要件が実現するかを疑う
特に問題で苦手意識を持たれるのが、「問題文の要件を実現するSQLを選択する問題」、「正しく実行できるSQL（長い）を選択する問題」だと思います。私は長いSQLに慣れていないこともあり、全てが正解に見えてしまい苦手でした。この形式の問題には、まずはエラーになる選択肢を弾きましょう。ここで、初めて要件を満たすか考えましょう。選択肢を絞った上で要件を満たすかを考えるので、時間を大きく省くことができます。



##4.おわりに

今回、本試験に合格することでORACLE MASTER Bronze資格を取得しました（Bronze DBA 12cは取得済み）。DB系の資格取得は初めてなので嬉しいですし、DBについて一定水準の理解ができたこと達成感があります。ただ、実務には直接生かせないため満足はできていないです。今はリーダーとしてプロジェクトにいることと、マネジメントが満足にできていないことを鑑みると今の自分に必要なのはエンジニアの技術経験ではなく、マネージャーとしての技術経験であると深く理解しています。ですので、今後はマネジメントの力を伸ばすような方向に勉強を進めていこうと思います。また成長できましたら、皆さまに進捗報告や有用な情報を発信できればと思います。今回の記事が皆さまのお役に立てれば嬉しいです。
children:JSX Element 

<h1>JSX element</h1>

ある時Propsではchildren:JSX element があるのに
その上の階層ではchildren の文字が見当たらなかったので調べてみました。

コンポーネントで事前に子要素が分からない場合に
props.childrenを使って子要素の出力を行います。

つまりページに吐きだす際にスタイル、文字などを設定できるので便利です。

実際に試してみました。

```react
function A(props){
return (<div>props.children</div>)

function wait(){
return(
<A>
<h1>waiting</h1>
</A>
);
}

//呼び出し
function App(){
return (
<div><header>
<wait />
</header></div>
);
}
```

childrenが定義の1か所なので困惑しましたが理解できました。
この場合タグの間にある処理がchildrenに代入されます。

もちろんchildrenを書く書き方もあります。

```react
function A(props){
return (<div>props.children</div>)

function wait(){
props.children = (
<h1>waiting</h1>
);
return(<A></A>);
}

//呼び出し
function App(){
return (
<div><header>
<wait />
</header></div>
);
}
```
[React Native]ReactNativeの開発環境を expoでつくる

# React native 環境構築
最近React Nativeを学習する機会があったのでメモ

## expoを利用して環境を作る
初めてReact Nativeやる人は`expo`でちゃちゃっと作ったほうがいいと思いました。
他にもいろんなやり方があるみたいですが、個人的には`expo`がおすすめ。

### 必要なもの
npmとnode

npmとnodeが自分のPCに入っているか確認する。

- npmの確認

```shell
$ npm --version
6.14.4
```

- nodeの確認

```shell
$ node --version
v14.4.0
```

## 早速インストール

といってもexpoは以下のコマンド一つでOK

```shell
$ npm install expo-cli --global
```

```shell
$ expo --version
3.22.3
```

## expoプロジェクトの作成

```shell
$ expo init アプリ名
```

```shell
$ expo init ReactNativeApp
```

このコマンド一つでReactNativeのプロジェクトを作ってくれる。

## expoの起動

```shell
$ expo start
```

でQRコードが出力されるので、それをスマホのカメラで読み込むと実機確認ができる。（Expoアプリ必要なのでスマホでインストールしておかないといけません）
尚且つホットリロードなのでUIを確認しつつ開発できる。
コミュニケーションの課題を整理して考えてみる

# 概要

現在、社内で勉強会を行っており、そこに人が集まらないという課題があります。その課題に対して「自分のコミュニケーション」に問題があると指摘いただきました。

一度は改善案が出たには出たのですが、若干モヤモヤしている部分があり自分で改めて整理したいなと思いました。こういった課題を考えるプロセスを何か形として残したいと思い、Qiitaの記事として投稿しております。


# コミュニケーションにおける課題

自分は定期的に勉強会を開催しており講師として参加しております。勉強会では出来るだけ気さくに話すようにしており、それが一部の方に評判が悪いとのことです。主に「新しく来た方」には不評で、「これまで参加された方」については特に問題はないとのことでした。「新しく来た方」に対して、`話し方`や`馴れ馴れしく`し過ぎて、あまりよくない印象を持たれているようでした。

# 一旦の解決・改善方法は？

コミュニケーションの取り方を改善することで解決しそうです。自分のコミュニケーションの取り方に問題があり、それを改善すればよいと思われます。具体的な改善方法としては、フォーマルなコミュニケーションを行えば改善しそうです。

ん？本当にそれでいいの？なんか違和感があるような・・・。
気さくに話すような環境がなくフォーマルなコミュニケーションだけになると、それはそれで寂しいモノがあります。


# 改めて原因を考える

まずは改めて課題を考えてみます。課題を２つの要因に分けて考えます。

- 「新しく来た方」には馴れ馴れしい雰囲気が不評
- 「これまで参加された方」には特に問題ではない

「新しく来た方」に対するコミュニケーションが問題であり、
「新しく来た方」と「これまで参加された方」に差があるところに着眼した方がよさそうです。

では、上記の差とは具体的にどのようなモノでしょうか。おそらくそれはコミュニケーションの段階に差があることに原因がありそうです。

以下のチームワークの７つの段階でみるとわかりやすく、以下のように当てはまりそうです。

- 「新しく来た方」　　　　：LEVEL 1 に達していない
- 「これまで参加された方」：LEVEL 3 ~ 4

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/9a6ff06c-3ca1-7d37-0714-1f9c373fbc89.png)


http://www.scholar.co.jp/workcollaboration/level/

つまりこのような差がある方々に対して`同じコミュニケーションの取り方をしていること`に問題があると思われます。

# 改めて改善案を考える

より明確な原因がわかったところで改善案を書いていきます。

## それぞれのコミュニケーションのレベルに応じて対応を気を付ける

当たり前だろいえば当たり前ですが、「新しく来た方」に対しては比較的丁寧にコミュニケーションを取ることにします。

「新しく来た方」と「これまで参加された方」が同じグループで会話することになった場合も、あまり砕けた感じではなくフォーマルなコミュニケーションを取るようにします。これは当初の改善案と同じような内容になります。

## コミュニケーションのレベルの差をなくす

コミュニケーションのレベルの差が原因であり、差をなくすことが重要だと思います。つまりコミュニケーションのレベルを向上するような仕組みが必要になります。

### 雑談できる場所をつくる

気さくに話すこと自体は悪いことではないはずで、「これまで参加された方」には本音でしゃべってもらいやすいなどのメリットもあります。ここはコミュニケーションのレベルを上げる場を別で準備する必要があると思いました。

例えば技術的な勉強会のような場所でなく、雑談ができる場所をつくることでお互いを理解することができそうです。お互いの理解が深まることで上記のチームワークの７つの段階のレベルも上がりそうです。

### 少ない時間でもコミュニケーションを取るようにする

僅かな時間でも直接会話するなどのコミュニケーションを取るようにします。雑談できる場所を作る上で少しずつ回数を重ねていくことが重要そうです。少しずつお互いを知る時間を作ることで意思疎通も取れやすくなると思います。

# 最後に・・・

最初は個人に対する改善方法で、単純にそれだけが原因か悩んでいました。改めて課題を考えて状況を把握することで、個人から行える改善方法と現状の環境に対する改善方法が見つかりました。

当初は自分のモヤモヤを解決するにあたり、いろいろ上記のようなことを悩んで考えたりしました。こういった考えるプロセスもアウトプットすることで誰かの役に立つと思い、Qiitaの記事にまとめた次第です。

技術的な記事ではないですが課題を解決するプロセスもエンジニアの１つの技術だと思っています。
MySQLが起動しないエラー (The server quit without updating PID file)

#mysql起動時に下記エラー発生

```
$ mysql.server start
Starting MySQL
... ERROR! The server quit without updating PID file (/usr/local/var/mysql/XXXX.pid).
```

https://qiita.com/akiko-pusu/items/aef52b723da2cb5dc596
↑記事を参考に一旦アンインストールして再インストールしました。

###一度、5.6をインストールした後、8.0を使いたいと思い、またアンインストール＆再インストールしました。

起動してみると、

```
$ mysql.server start
-bash: /usr/local/opt/mysql@5.6/bin/mysql.server: No such file or directory
```

パスが5.6のままで起動できませんでした。

自分はbashを使用していたので、`.bashrc`ファイルにパスを通しました。
（zshを利用されている方は、`.zshrc`です）

```
$ vi ~/.bashrc
export PATH=/usr/local/opt/mysql@8.0/bin/:$PATH

$ source ~/.bashrc 
```

再度起動してみると、

```
$ mysql.server start
Starting MySQL
... ERROR! The server quit without updating PID file (/usr/local/var/mysql/XXXX.pid).
```
同じエラーが再発しました。

#次に、プロセスを確認

```
$ ps -ef | grep mysql
  501   699     1   0 16 720  ??         0:00.04 /bin/sh /usr/local/opt/mysql@5.6/bin/mysqld_safe --datadir=/usr/local/var/mysql
  501   974   699   0 16 720  ??         1:06.51 /usr/local/opt/mysql@5.6/bin/mysqld --basedir=/usr/local/opt/mysql@5.6 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql@5.6/lib/plugin --log-error=XXXX-Air.local.err --pid-file=XXXX-Air.local.pid
  501  3524 81032   0  1:48AM ttys002    0:00.00 grep mysql
```
5.6が起動してるので、強制終了(-9)する
（974は上記のプロセスID)

```
$ kill -9 974
```

再々チャレンジ!!

```
$ mysql.server start
Starting MySQL
.. SUCCESS!
```
成功！！
コロナウイルス感染者数をBigqueryで見る方法

# きっかけ
コロナウイルス感染症数のdatasetがたくさん見つかったので、Bigqueryに入れて検索してみたりしていた。

# 料金
BigQuery の利用料金が発生します。BigQuery クエリの料金については、毎月 1 TB まで無料です。詳細については、BigQuery の料金ページをご覧ください。

# 条件
1. datasetが公開されていること。
[kaggle.com](https://www.kaggle.com/lisphilar/covid19-dataset-in-japan)にて公開されていたので、こちらからサインアップしてPCにダウンロードします。

2. GCPが有料設定されていること
3. Bigquery APIが有効であること

# Bigqueryにdatasetをする

Bigqueryを開き、自分のプロジェクトを選ぶ。そして **データセットを作成** を選ぶ
![dataset1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/f67ea757-ca01-f1aa-f54f-18485cd831f8.png)

データセットIDはわかりやすければ何でも良いです。今回は **covid** とします。
![dataset2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/fbeb31c6-1ac0-f887-2204-ba07e26efc71.png)

作成した**covid**を選び、「＋」ボタンを押して**テーブルの作成**を行います。

1. **アップロード**を選びます。
2. 入れたいdatasetのcsvファイルを指定してください。今回は**covid_jpn_prefecture.csv**を指定しています。
3. **CSV**形式であることを確認してください。
4. データセット名は、今回は**covid**となります。
5. テーブル名はわかりやすければいいのですが、今回は**prefecture**にします。
6. スキーマと入力パラメータにはチェックをして、自動検出します。

![dataset4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/40f54a3f-3f50-2ca0-e999-689512633391.png)

一応、これで終わりです。後は好きなSQLを叩いて解析してください。
![dataset5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/e7643cf0-fa54-ece2-18db-d0baca86c943.png)

# BIツールで可視化する
SQLだと分かりづらいので、可視化します。
datastudioを開いてくれればいいのですが、**エクスポート**から**データポータルで調べる**を押します。
![dataset5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/82e0912d-3614-d67d-6ee4-4015a0a8a6e1.png)
いきなり表示されるのが**コレジャナイ**感じ満載なので、データソースの編集をします。
![bi1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/6e484d96-cb99-1e5a-eb80-2b55775efd38.png)

最初にある指標の**Record Count**は不要なので消します。**指標を追加**を押します。
![bi3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/58df288d-7729-20b2-d5dc-46c7e64564a5.png)
**フィールドを作成**を選びます。
![bi4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/f8b20b2a-25c1-f368-827d-b586fb9ddb65.png)
新しい指標を作ります。**sum**として、**SUM(Positive)**とします。
![bi5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/87a89d50-0c86-50fc-2009-db8d4f0f230e.png)
後は自分の好みのグラフにしたりします。
![bi6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/a26c2c46-969e-ba80-8739-727be456fe4e.png)

# 課題
ちょっと試してBIツールで可視化できたら面白いな〜と言う発想だけだったのですが、これは毎日データを取得するようにしたり、データ解析して今後を予測するのにも使えますね。
スタックの有無で待つ状態を切り替える

スタックの有無で wait するコマンドを切り替える。

```bash
#!/bin/bash
set -eu

STACK_NAME="foobar"
IS_UPDATE=0

set +e
aws cloudformation describe-stacks --stack-name ${STACK_NAME}  > /dev/null 2>&1
if [ $? -eq 0 ]; then
  IS_UPDATE=1
fi
set -e

aws cloudformation deploy --stack-name ${STACK_NAME} --template-file /path/to/template.yml                                                                                                                                                                          

if [ $IS_UPDATE -eq 1 ]; then
  aws cloudformation wait stack-update-complete --stack-name ${STACK_NAME}
else
  aws cloudformation wait stack-create-complete --stack-name ${STACK_NAME}
fi

echo waited
```

## 参考

* [wait — AWS CLI 2.0.34 Command Reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudformation/wait/index.html)
* [AWS CLIがCloudFormationの状態遷移ポーリング(waiters)に対応しました | Developers.IO](https://dev.classmethod.jp/articles/awscli-now-supports-cloudformation-waiters/)
Dronecode - QGroundControlのカスタマイズ開発

ドローンの自律飛行を実現するには、DronecodeとMAVSDKを試してみます。

# 目次
1. [PX4環境構築](https://qiita.com/k-koh/items/77af5422b3857e68ad9a)
2. [uORB Messaging](https://qiita.com/k-koh/items/c57c02df772785816c14)
3. [QGroundControlの使い方（ユーザーガイド）](https://qiita.com/k-koh/items/eedc303cb0b72d1272ee)
4. [MAVLinkの入門](https://qiita.com/k-koh/items/9e9c1694dbb5a2a4117a)
5. [QGroundControlのカスタマイズ開発](https://qiita.com/k-koh/items/36c34f0e3e18b2e055ac)

## 動作環境
- Ubuntu 18.04
- ROS Melodic

## QGroundControlの開発環境の構築

### QTのインストール
QGroundControlがQTのヘッダファイルをアクセスするため、QTをインストールします。

1. [Qt Online Installer](https://www.qt.io/download-open-source)をダウロードします
2. インストールには、コンポーネント「5.12.5」を指定します
「Desktop gcc 64-bit」、「Qt Charts」、「Android ARMv7 (to build Android)」を選択

3. Packagesをインストール

```
sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/5ea84bc0-1a0b-8375-33e8-bbe7b9240279.png)


### ソースコードの取得
```
git clone https://github.com/mavlink/qgroundcontrol.git --recursive
git submodule update

```

### Qt Creatorでコンパイル
1. Qt Creatorを起動、「qgroundcontrol.pro project」を開く
2. 「Desktop Qt 5.12.5 GCC 64bit」kitを選択
3. ビルド（hammerアイコン）（20分かかる）
4. QGroundControlを実行（playアイコン）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/66efb307-e939-c738-8667-505af4d9e3ce.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/a1fae18b-9b26-be95-b8ba-30c00c5d9fe0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386259/70cc63c2-6373-f94f-045a-b4e40ef734bb.png)
たった14行でiOSアプリ内のリンクをリッチに表示する方法


FacebookやTwitterでURLを投稿すると、リンク先のタイトルや画像を自動で取得してカードのようなUIとして表示されるのを見たことがあるでしょうか。そんな機能を簡単に実装できるApple標準のフレームワークがXcode11以降で使えるようになりました。

# 例えばYoutubeのリンク
Youtube動画の場合、リンクをアプリに埋め込むとそのまま再生できました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LinkPresentationフレームワークを使うと、Youtube動画とかアプリ内でそのまま再生できるのね。<a href="https://t.co/iMYuqb2zaF">https://t.co/iMYuqb2zaF</a> <a href="https://t.co/FxmEF6ygrA">pic.twitter.com/FxmEF6ygrA</a></p>&mdash; Natsui@🏡iOSエンジニア (@MeSummery) <a href="https://twitter.com/MeSummery/status/1288128939089489923?ref_src=twsrc%5Etfw">July 28, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# LinkPresentation framework
URL からメタデータを取得し、アプリ内でリッチなリンクコンテンツをいい感じに表示してくれるAppleのフレームワーク。**iOS 13.0以降から利用可能**。
https://developer.apple.com/documentation/linkpresentation

# 実装ステップ
利用箇所でまずフレームワークをインポートしておきましょう。

```swift
import LinkPresentation
```

## URLからメタデータを取得する
`startFetchingMetadata(for:completionHandler:)`をコールしてメタデータの取得を開始します。

```swift
let metadataProvider = LPMetadataProvider()
let url = URL(string: "https://youtu.be/hMgcaYd2BZM")! // リッチに表示したいURL
metadataProvider.startFetchingMetadata(
    for: url,
    completionHandler: { metadata, error in
    // Make use of fetched metadata.
})
```
`completionHandler`はバックグラウンドキューで実行されます。
**クロージャー内でUIを操作する場合には、メインスレッドで行うように**しましょう。


## メタデータを専用Viewに受け渡す
`LPMetadataProvider`から受け取ったメタデータを`LPLinkView`の初期化時に渡します。

```swift
metadataProvider.startFetchingMetadata(
    for: url,
    completionHandler: { metadata, error in
        if error != nil { return }
        guard let metadata = metadata else { return }
        DispatchQueue.main.async { // メインディスパッチキューで実行
            let linkView = LPLinkView(metadata: metadata) // メタデータを渡す
            self.previewView.addSubview(linkView) // Storyboard上に配置した任意のUIView
            // Sizing
        }
})
```
今回は、生成した`LPLinkView`のインスタンスをStoryboard上に配置した`previewView`に`addSubview `しました。
また、前述のとおり、`completionHandler`内のUIの更新は、`DispatchQueue.main`で実行しましょう。

## サイズを決定する
サイズを指定したら、`sizeToFit()`で任意のサイズにレイアウトを合わせましょう。

```swift
linkView.frame.size = self.previewView.frame.size
linkView.sizeToFit()
```
今回は`linkView`のサイズを`Superview`に揃えましたが、任意の`CGSize`を設定しても◎
これにて完成です。

# ソースコード全体
```swift
let metadataProvider = LPMetadataProvider()
let url = URL(string: "https://youtu.be/hMgcaYd2BZM")!
metadataProvider.startFetchingMetadata(
    for: url,
    completionHandler: { metadata, error in
        if error != nil { return }
        guard let metadata = metadata else { return }
        DispatchQueue.main.async {
            let linkView = LPLinkView(metadata: metadata)
            self.previewView.addSubview(linkView)
            linkView.frame.size = self.previewView.frame.size
            linkView.sizeToFit()
        }
})
```
ぴったり14行✌️😼

# まとめ

iOS14のリリースを（おそらく）9月に控え、最新OSを2,3世代サポートしているアプリは、やっとiOS13以降のフレームワークを本格的に導入していけることと思います。
LinkPresentationは **たった十数行でアプリのUXを向上できる**フレームワークなので、ぜひ活用していきたいですね。

このフレームワークについては、2019年のWWDCビデオもあります。
ビデオの長さは6分前後なので、気軽に見られておすすめです。
今回の記事は触れないローカルキャッシュの取得や共有時の実装のポイントに触れられています。
https://developer.apple.com/videos/play/wwdc2019/262/

以上です :tada:
ありがとうございました。
NuxtをGithub Actions、ECR、ECSでCI/CDさせるまで

# はじめに
WebGL課題が大学であった。そこでNuxtでSSRできたらスマーフォンからでも重い映像を描画できるんじゃないかと思い、見切り発車することにした。その際にCI/CDパイプライン作って、ECS、ECRの自動化チャレンジしたらさらに面白いんじゃないかってことでやってみた。

成果物のgit: https://github.com/yCroma/WebGL.git

# 内容

0. DockerのMultipleCompose
1. Makefileでシェルを叩く
1. ECR、ECS
2. Github ActionsでのCI/CD
3. おまけ(Dockerfile,docker-composeの連携)

## 1. DockerのMultipleCompose

参考は以下の通り。
・[docker-compose.ymlをDRYに書くテクニック2選](https://qiita.com/reireias/items/ecb81e248314253eb156)
・[Share Compose configurations between files and projects](https://docs.docker.com/compose/extends/)

何ができるかって言うと、**複数のcomposeファイルを１つのファイルのようにして処理することができるようになる**。

```
.
├── docker
│   ├── dev
│   │   ├── Dockerfile
│   │   └── docker-compose.dev.yml
│   └── prod
│       ├── Dockerfile
│       └── docker-compose.prod.yml
└── docker-compose.yml
```

こんなファイル群があったときに、開発用の`dev`のcomposeファイルだけ利用したいという場合。

```
$ docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
```

みたいな感じで利用することができる。これにより、**ビルド用のファイルと開発環境用のファイル**を分けて実行することができるからとても便利。
でも実際こんな長ったらしいコマンドを叩くのは面倒くさい。今回の例だと、Makefileと`commands`のなかに用意したshellファイルを実行することによって避けるようにしている。

## 2.Makefile
すごくシンプルなもので、長ったらしくなるコマンドをMakefileとshellのみで完結させた話。
`.env`ファイル内に環境変数を用意して、shellで読み込み実行できるようにする。用意したshellをMakefileから叩く。

## 3. ECR、ECS

これはECRへのpushが詰まった。ログインが必要になるのだが、`AWS Cli v2`を使っていたので`aws ecs login`みたいなコマンドが使えなかった。クラスメソッドさんの記事のおかげで解決することができた。

記事:[[アップデート]AWS CLI v2 で $ aws ecr get-login を使うときの注意点](https://dev.classmethod.jp/articles/aws-cli-v2-ecr-get-login-password/)

```
aws ecr get-login-password | docker login --username AWS --password-stdin https://<< AWSのアカウントID >>.dkr.ecr.<< region >>.amazonaws.com
```

注意点としては、--usernameは**AWS**であること。気を利かせて、自分のユーザー名とか入れると失敗する。

ECSに関しては、以下を参考にした。

構成とやり方
・[【Nuxt.js】AWS ECR/FargateにデプロイするためのDockerイメージ作成方法](https://qiita.com/nakano-shingo/items/e3daad0bfd981f8dd5bf)
・[nuxtプロジェクトを独自ドメインでSSR（CloudFront -> ALB -> Fargate）](https://qiita.com/geerpm/items/a97f0605177b3a18bb5b)

タグ付、push
・[Nuxt.jsでアプリ作成→Dockerfileを使ってイメージ作成→fargateでデプロイ→ドメイン設定・SSL化まで](https://qiita.com/yujiro0102/items/0a4672d7f8ea64fe1d6d)

## 4. Github ActionsでのCI/CD

結論から言うと、一回のCI/CDで約10分かかった。ここは更新点。
基本的に参考にしたのは、以下の記事。
・[GitHub ActionsからサクッとFargateにデプロイしてみた](https://dev.classmethod.jp/articles/github-actions-fargate-deploy/)
・[GitHub ActionsからAmazon ECSにアプリをデプロイ](https://qiita.com/momotaro98/items/a0791969172ac94cfe47)
１つだけこだわったとこがあり、**task-difinition.jsonをローカルで保存しないようにした**。このおかげで、task-difinition.json内にアカウントのIDなど見られたくないものがあった場合でも安心。

task-difinitionの参考:[Amazon ECS "Deploy Task Definition" Action for GitHub Actions](https://github.com/marketplace/actions/amazon-ecs-deploy-task-definition-action-for-github-actions)

## おまけ(Dockerfile,docker-composeの連携)

docker-composeからDockerfile内に環境変数を渡す方法が浮かばなかった。答えとしては、ARGで受け取ってENVで宣言すれば良かったらしい。

・[docker-composeのビルド中に環境変数が認識されない](https://qiita.com/katoosky/items/422c183cf5cabb789030)
・[Dockerfileの"ENV"と"ARG"と"環境変数"について](https://techblog.recochoku.jp/1979)

あとdocker-composeで任意のイメージ名を指定する方法。

・[Docker Composeでビルド時に任意のイメージ名を指定する方法](https://amaya382.hatenablog.jp/entry/2017/04/03/034002)

# おわりに
デプロイに10分かかってしまうのはあれだが、やはり快適だ。いずれは、Terraformを使って完全自動化を目指したい。
Visual Studio でファイルのフォルダ分け(インクルードパスの設定)

# Visual Studioでファイルのフォルダ分け

##はじめに

Visual Studioで c, cpp, h, hppファイルをフォルダ分けしたいと思ったことありませんか？
多分ほとんどの人があると思います。
最初にファイルが作られる場所はプロジェクトファイルなどと同じ場所にあるため
ファイルを取り出す際などに少し面倒に感じたりすることがあるはずです。

今回はそれを解消するための方法を説明していきたいと思います

**説明で使用しているプロジェクトはVisualC++プロジェクトです。**

#説明

![スクショ2_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423473/cd80fc00-802c-4a0a-a53a-a311cfb2611d.jpeg)


[ソリューションエクスプローラ]を開いてください
　　　　　　↓
プロジェクト名を右クリック、[オプション]を開いてください

![スクショ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423473/593a500b-2685-6260-7f19-d8c2efcf5af2.png)

[VC++ディレクトリ]を選択
　　　　　　↓
[インクルードディレクトリ]を選択し、下向き三角のマークをクリック
　　　　　　↓
＜編集...＞をクリックしてください
![スクショ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423473/16296a34-a4c3-c8ef-a358-42cc026b0358.png)

フォルダみたいなマークをクリックしてください
　　　　　　↓
そうすると
[　　　　　　　　　　]...
みたいな感じになります
この状態の...をクリックしてください
　　　　　　↓
そうすると「ディレクトリの選択」というウィンドウが出てきます
この状態でヘッダファイルのまとまっているフォルダなどを選択することで
「#include"folder/header.h"」のように記述せずに
「#include"header.h"」と記述することができます。


##最後に

説明はわかりましたか？
わかってファイル分けができているなら幸いです。
(Express)HTMLからの処理をNode.jsで同期/非同期処理した時に教わった注意点


連投すみません。お引越し中です…。

結論から言うと、
<strong>Expressのミドルウェアには通常のコールバック関数を与えること！</strong>

<p>らしいです…</p>
<p>これだけでは理解できなかったのでまとめます。</p>

#ミドルウェアとは
<p>コンピューターは「ハードウェア」「OS」「ミドルウェア」「アプリケーション」の4要素で構成されています。</p>

<!-- wp:paragraph -->
<p>ミドルウェアは「OS」と「アプリケーション」の間にあるような、「OS」でも「ミドルウェア」でもないもの。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<strong>機械とアプリの橋渡しをするようなものは全て「ミドルウェア」</strong>のようです…。<br>

<p>例えば、windows10が「OS」ブラウザが「アプリケーション」、<br>「Webサーバ」(ブラウザからのリクエストに応じてWebページを送信する)が「ミドルウェア」です。</p>


<!-- wp:paragraph -->
<p>わかりずらい…！</p>
<!-- /wp:paragraph -->

<p><span class="fz-36px"><span class="fz-28px"><span class="fz-22px"><span class="fz-18px">expressとNode.jsでいうと、</span>router.all()関数は、expressからNodeに渡している関数だから、ミドルウェア<span class="fz-18px">らしいです。</span></span></span></span></p>
<p>つまり、<strong>router.all()やrouter.post()のコールバック関数を標準にすればいい</strong>のですね！</p>
#コールバック関数とは

<p>関数の引数として呼び出す関数です。</p>

<p>(例)　<strong>function( 10, timer() )</strong></p>

<!-- wp:paragraph -->
<p>これは、function関数の引数として呼び出されている<span class="bold-red">timer()がコールバック関数。</span></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Express+Node.jsの場合、<strong>router('/', function(){})</strong>のfunction()関数を、通常の関数にしなければならない。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>つまり、asyncはコールバック関数にはつけてはいけません！(つけてた)</p>
<!-- /wp:paragraph -->

#まとめ
だめ↓

```index.js
router.all('/', async function(){
 //中身
})
```

いい↓

```index.js
router.all('/', function(){
 main(){
  //中身
 }

 main()
})
```
composer"Updating dependencies (including require-dev)"で固まり困っている人へ

//駄文を許してください
//筆者はcomposerコマンドを使ってプロジェクトを作成しています

mac ver 10.15.6
composer ver 1.10.9

#ことの発端は...

とある日,laravelを楽しもうとプロジェクトを作成した時であった...

**何分待ってもprojectが作成されないのである。**

Creating a "laravel/laravel" project at "----"　<-ここで固まる

updating dependencies <-composer updateしていた時はここで

# 行動

phpやnodeなど手当たりしだいにアップデート->効果なし

composerのコマンドを打ったときの挙動だけがおかしいことに気づく

composerのアンインストールを考えたができなかった...

#解決への道

参考
> https://iiiso.ti-da.net/e8647248.html
https://stackoverflow.com/questions/17138319/composer-freezing-when-installing-symfony-vendors
https://github.com/composer/composer/issues/4839

公開鍵
> https://composer.github.io/pubkeys.html

言われた通りに、diagnoseをコマンドの尻に付けてみる
->どうやら同じような症状である.

**composer self-update --update-keys**

を打ち,公開鍵をコピペしてみる.

その後、composerコマンドが通常通りに使えるようになった.
実際のところなぜこのような問題が起こったのか不明であり本質的には何が起こったのか不明であるため原因究明に力を注ぐ。

#他の種類の不具合

composerはIPv6で通信できない[要出典]らしいので
-vvvオプションをupdateに付けてみてdownload~~のところで
止まっている人がいたらiphoneへのテザリングを考えてください

##細かなこと

- 初めて記事を制作したので細かなミスがあっても許してください
- 解決？後再度プロジェクトを作成してみると、ターミナル上では余り変化がないので10分程度待ってみましょう.
【同期処理】async/awaitできない(待ってもらえない)問題【Node.js】

<!-- wp:paragraph -->
<p>Node.jsが親切設計すぎて、時間がかかる処理をしている間に勝手にその後の処理に進んでしまって困りました。</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>そこでasync/awaitしたのですがなかなか待ってもらえず…</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>こちらの回答者さんの回答を拝見し、解決しました。→(<a href="https://teratail.com/questions/131373">https://teratail.com/questions/131373</a>)</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>記録します。</p>
<!-- /wp:paragraph -->

#できなかった時のプログラム

```index.js
(略)
async function a(){
  //ちょっと時間がかかる処理

  return '2'
}

async function main(){
  const number = await a()
  console.log(number)
  console.log("numberを表示した後")
}
```

実行結果です↓

```
numberを表示した後
2
```

実行結果がかわってないー(「2→numberを表示した後」、という順番にしたい)

#できた時のプログラム

```index.js
(略)
//--------returnで囲っちゃった！------------
function a(){
  return new Promise((resolve, reject) => {
    //ちょっと時間がかかる処理
    resolve('2')
  }
}

async function main(){
  const number = await a()
  console.log(number)
  console.log("numberを表示した後")
}
main()
```

実行結果です↓

```
2
numberを表示した後
```

やったー！
Eloquentでリレーション先のカラムを条件に並び替える

# 課題
リレーション先のカラムに表示順序が指定されていてそれを元にリレーション元にデータを並び替えたい（ソートしたい）ときがあります。

例えば、次のようなケースを考えてみます。

countires

|id|name|dsp_order
|:---|:---|:--|
|1|日本|1|
|2|アメリカ|5|
|3|中国|3|
|4|韓国|4|
|5|台湾|2|

users

|id|name|country_id
|:---|:---|:--|
|1|張|5|
|2|木村|1|
|3|クレア|2|
|4|金|4|
|5|李|3|

望ましい順序
1. 木村
2. 張
3. 李
4. 金
5. クレア

このとき発行するSQLは次のようになります。

```sql
SELECT users.name
FROM users
LEFT JOIN countries ON countries.id = users.country_id
ORDER BY countries.dsp_order
```

LaravelにはGlobalScopeと言って、そのモデルにアクセスするときに自動で付加するクエリをあらかじめ定義しておくことが可能な機能があります。Userモデルにアクセスしたときに上記のようなSQLを自動で発行させるにはどのようなGlobalScopeを書くといいでしょうか。

# 解決策

```php
protected static function boot()
{
    parent::boot();
    static::addGlobalScope('order', function (Builder $builder) {
        $builder->select('users.*')
            ->join('countries', 'contries.id', '=', 'users.id')
            ->orderBy('countries.dsp_order', 'asc')
        });
}
```

`select('自分のテーブル.*')`を先頭につけておくのがポイントです。さもないと、joinしたcountriesのカラムまで引き連れたデータが取れて、意図した挙動になりません。

# 追記(2021.05.24)
GlobalScopeに他のテーブルを結合するような処理を書いていると、何気なく書いたQueryが他のテーブルのカラム名と衝突したりして(nameとかそれこそdsp_orderとかnoとか)、思わぬバグの原因になるので、このような処理はGlobalScopeではなくLocalScopeに定義してあげて、適宜必要に応じて呼んであげるという運用にしたほうがいいかもしれません。
サーバーに無線LANが使われない理由

有線LANの場合、デバイスの台数分のLANケーブルを用意する必要があるが、無線LANであれば必要最小限のLANケーブルを用意するだけで済む。

それなのに**サーバーの接続に無線LANが利用されるケースはほとんどない。**

その理由を以下にて解説する。

#理由1.障害の理由がわかりづらいから

- 通信障害が起きた時に、何が原因なのかを探るのに手間がかかる

- 有線LANであれば破損していれば一目でわかるが、無線LANではアクセスポイントの通信状況をチェックしたり、無線LANのアダプタが装着されたコンピュータで試行錯誤して調べる必要がある

#理由2.通信の安定性に欠けるから

- 携帯電話の電波やラジオの電波や他のオフィスで利用されている無線LANの電波など、ノイズとなる様々な電波が飛び交っているので影響を受けてしまう


#理由3.有線LANより通信速度が遅いから

- 無線LANの通信はサーバーに要求される通信の水準を満たせないことが多く、有線LANに比べて安定的に必要な速度を出すのが難しい

#理由4.そもそもサーバーを移動させることはないから

- 無線LANのメリットとして「移動に強い」という点があるが、サーバーを移動させるケースはほとんどないのでメリットが活かされない
google colabでイッヌとネッコと戯れる

こんな感じでぬくぬくできる
結構、模様のパターンは多い

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221698/b37f207b-b494-3a03-2be5-a082ac37a4b7.gif)


設定方法は、ツールバーの「ツール」「設定」から「コーギーモード」と「猫モード」にチェックを入れるだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221698/5f462f4a-049e-7156-8daf-a8ac840e3e4c.png)
Rails メールアドレス、パスワード+αでログイン認証する

## 目的
nation_nameプロパティをログインに必要な項目に追加する。
## 使い方
- カラムとして存在しないプロパティを追加するattr_accessorメソッドを使ってnation_nameプロパティをユーザーモデルに追加する

```ruby:user.rb
class User < ApplicationRecord
  #accessor
  attr_accessor :nation_name
```


- registration/new.html.erbとsessions/new.html.erbに以下のコードを追記する。

```ruby
:new.html.erb
<div class="field">
    <%= f.label :国名 %><br />
    <%= f.text_field :nation_name, autofocus: true %>
  </div>
```

- パラメーターとして送られるgroup_nameが許可されるようにする

```ruby
:application.controller
class ApplicationController < ActionController::Base
  before_action :authenticate_user!
  before_action :configure_permitted_parameters, if: :devise_controller?
  
  def configure_permitted_parameters
    #sign_in時にnation_nameも許可する
    devise_parameter_sanitizer.permit(:sign_in, keys:[:nation_name])
    #sign_up時にnation_nameも許可する
    devise_parameter_sanitizer.permit(:sign_up, keys:[:nation_name])
    #account_update時にnation_nameも許可する
    devise_parameter_sanitizer.permit(:account_update, keys:[:nation_name])
  end 
end

```

- ユーザーの新規登録時にネーションIDが保存されるようにする

```ruby:user.rb
class User < ApplicationRecord
  #accessor
  attr_accessor :nation_name
  #association
  belongs_to :nation
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable,
          authentication_keys: [:email, :nation_name]
          
  #validation
  before_validation :nation_name_to_id, if: :has_nation_name?
  
  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    nation_name = conditions.delete(:nation_name)
    nation_id = Nation.where(name: nation_name).first
    email = conditions.delete(:email) || conditions.delete(:unconfirmed_email)

    # devise認証を、複数項目に対応させる
    if nation_id && email
      find_by(nation_id: nation_id, email: email)
    elsif conditions.has_key?(:confirmation_token)
      where(conditions).first
    elsif email
      where(email: email).first
    else
      false
    end
  end

  private
  def has_nation_name?
    nation_name.present?
  end

  def nation_name_to_id
    nation = Nation.where(name: nation_name).first_or_create
    self.nation_id = nation.id
  end

end
```
【GAS初心者】「今日の一ヶ月前」や「初日/末日」の日付を取得する(GAS)


#結論

```javascript:結論
  var date  = new Date(); //現在日時のDateオブジェクトを作る //Tue Jul 28 21:44:30 GMT+09:00 2020
```

#各論


##今日の取得方法

```javascript:今日
  var date  = new Date();  //Tue Jul 28 21:44:30 GMT+09:00 2020
```

正確には「現在日時のDateオブジェクトを作る」ことを行いました。

これを日本人に見やすくするためには、以下の処理を行います。

##今日の表示方法(YYYY/MM/DD)

```javascript:結論
Utilities.formatDate(date, 'JST', 'yyyy/MM/dd')
```
```javascript:今日(YYYY/MM/DD)
  var date  = new Date();  //Tue Jul 28 21:44:30 GMT+09:00 2020
  Utilities.formatDate(date, 'JST', 'yyyy/MM/dd'); //2020/07/28
```

Utilities.formatDate(date, 'JST', 'yyyy/MM/dd')

##今日→先日へ変更する

```javascript:結論
.setMonth(date.getMonth() + (-1 || 0));
```

```javascript:一ヶ月前の日付を取得する
  var date  = new Date();  //Tue Jul 28 21:44:30 GMT+09:00 2020
  date.setMonth(date.getMonth() + (-1 || 0));
  Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');  //	2020/06/28  
```

##年、月、日を抜き出す

```javascript:結論
.slice("ここから","ここまで")
```
```javascript:年、月、日を抜き出す
  //Tue Jul 28 21:44:30 GMT+09:00 2020
  var date  = new Date();  
  //2020/07/28
  Utilities.formatDate(date, 'JST', 'yyyy/MM/dd'); 
  //文字列の最初から4文字目まで切り出す-->2020
  var YYYY = beforemonth.slice(0,4); 
  //文字列の5から7文字目まで切り出す-->07
  var MM = beforemonth.slice(5,7); 
  //文字列の8から10文字目まで切り出す-->28
  var DD = beforemonth.slice(8,10);
```


##先月の初日/末尾を抜き出す

```javascript:一ヶ月前の初日/末尾を抜き出す
  var YYYY = 2020
  var MM = 07
  var startDate = new Date(YYYY, MM-1, 1); //初日
  var endDate = new Date(YYYY, MM, 0);//末尾
  //2020/06/01 
  var _startDate = Utilities.formatDate(startDate, 'JST', 'yyyy/MM/dd'); 
  //2020/06/30
  var _endDate = Utilities.formatDate(endDate, 'JST', 'yyyy/MM/dd'); 
```