OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】Dateオブジェクトの使い方

# はじめに
アウトプットが苦手な自分が練習の一環として記事を書いてみる。

第二回目です。

以前Dateオブジェクトを使った日付の加算で少し躓いたところがあったので、
それについて記事を書こうと思ったのですが、
その前にまずは`Dateオブジェクトの簡単な使い方`について書いていきたいと思います。

# 現在の日時を取得する
new Date()を使用することでDateオブジェクトを生成します。
引数を指定しない場合、現在の日時でオブジェクトが生成されます。

```javascript:現在日時を取得
const date = new Date();

console.log(date);
// 実行結果
// 2021-08-02T03:46:44.601Z
```

# 任意の日時を取得する
先ほどのnew Date()に引数を指定して生成します。
指定の仕方は以下の3種類あります。

- 年月日時分秒ミリ秒
- 文字列
- 1970年1月1日(UTC)からの経過ミリ秒数

```javascript:任意の日時を取得
// 年月日時分で指定
const date1 = new Date(2021,7,1,10,00,5,300);

// 文字列で指定
const date2 = new Date('2021-08-01 12:30');

// ミリ秒で指定
const date3 = new Date(1627797600000);

console.log(date1);
console.log(date2);
console.log(date3);
// 実行結果
// 2021-08-01T10:00:05.300Z
// 2021-08-01T12:30:00.000Z
// 2021-08-01T06:00:00.000Z
```
※月を指定する場合、値は0から始まるので注意が必要です。（1月を指定する場合、値は「0」となる）

# 日時の値ををそれぞれ取得する
Dateオブジェクトにはオブジェクトが持つ日時の値をそれぞれ取得するメソッドがあります。

| メソッド | 返値|
|:-:|:-:|
| getFullYear()  | 年の値 |
|  getMonth() |  月の値 |
|  getDate() |  日の値 |
|  getDay() | 曜日の値  |
|  getHours() | 時の値  |
|  getMinutes() | 分の値  |
|  getSeconds() | 秒の値  |
| getMilliseconds()  |  ミリ秒の値 |

```javascript:日時をそれぞれ取得
const date = new Date(2021,7,1,10,20,5,300);

console.log('getFullYear：' + date.getFullYear()); // 年の値を取得
console.log('getMonth：' + date.getMonth()); // 月の値を取得
console.log('getDate：' + date.getDate()); // 日の値を取得
console.log('getDay：' + date.getDay()); // 曜日の値を取得
console.log('getHours：' + date.getHours()); // 時の値を取得
console.log('getMinutes：' + date.getMinutes()); // 分の値を取得
console.log('getSeconds：' + date.getSeconds()); // 秒の値を取得
console.log('getMilliseconds：' + date.getMilliseconds()); // ミリ秒の値を取得
// 実行結果
//getFullYear：2021
//getMonth：7
//getDate：1
//getDay：0
//getHours：10
//getMinutes：20
//getSeconds：5
//getMilliseconds：300
```
※曜日の値も月と同様に値が0から始まります。（日曜日の場合は「0」となる）

# 日時の再設定
先ほどはオブジェクトの値を取得しましたが、オブジェクトの値を再設定するメソッドもそれぞれ用意されてます。

| メソッド | 引数|
|:-:|:-:|
| setFullYear()  | 「年」を表す整数の値 |
|  setMonth() |  「月」を表す整数の値 |
|  setDate() |  「日」を表す整数の値 |
|  setHours() | 0から23までの間の整数値  |
|  setMinutes() | 0から59までの間の整数値  |
|  setSeconds() | 0から59までの間の整数値  |
| setMilliseconds()  |  0から999までの間の整数値 |

```javascript:日時の再設定
const date = new Date(2021,7,1,10,20,5,300);

date.setFullYear(2020);
date.setMonth(9);
date.setDate(20);
date.setHours(11);
date.setMinutes(22);
date.setSeconds(33);
date.setMilliseconds(44);

console.log(date);
// 実行結果
// 2020-10-20T11:22:33.044Z
```

# まとめ
Dateオブジェクトの使い方については以上です。

月と曜日の値が0から始まることに注意すれば簡単な日付の取得と設定はできると思いますので、
参考にしていただければ幸いです。

参考サイト
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date
kubernetes dashboardにIngressを通してアクセスする

kubernetesのリソースをGUIで操作できるdashboardを導入する。

---
環境
クライアント...dashboardを利用する端末(ubuntu)
サーバ...master1台(centos8)、worker2台(centos8)
kubernetes v1.21.3

---
以下のyamlを利用する。そのままだと見られないリソースが多いので適宜カスタマイズ。
https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml

kube proxyコマンドで外部からの通信を受け付けるようにしても、dashboardを利用できず。。
```
kubectl proxy --address 0.0.0.0 --accept-hosts '.*'
```

![Screenshot from 2021-08-02 23-43-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606568/392c6d65-199c-6ebb-3ba4-05da57293e2e.png)

以下のページによるとホストからのアクセス以外はHTTPSでのアクセスが必要なので、IngressでTLS設定をしてアクセスしてみる。
https://github.com/kubernetes/dashboard/blob/master/docs/user/accessing-dashboard/README.md#login-not-available


IngressをLoadBalancerで公開したいので、OpenELBをインストールし、セットアップ詳細は省略する。
設定をしなければNodePortで実施する。
https://porterlb.io/docs/getting-started/installation/install-porter-on-kubernetes/

---
IngressでTLSを終端する設定
①kubectl create secret tlsを実行

```
kubectl create secret tls dashboard-tls --key=dashboard.key --cert=dashboard.crt -n kubernetes-dashboard
```
②以下のようにingressオブジェクトを作成

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8s-dashboard-ing
  namespace: kubernetes-dashboard
spec:
  tls:
  - hosts:
      - k8s-dashboard.local
    secretName: dashboard-tls
  rules:
  - host: k8s-dashboard.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443
```
③serviceリソース「kubernetes-dashboard」をNodePortへ変更

```yaml

...
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: NodePort
  ports:
    - port: 443
      targetPort: 8443
  selector:
...
```
通信の設定が終わったのでデプロイし、実際にアクセス。しかしうまく行っていない。。
・https://k8s-dashboard.local
![Screenshot from 2021-08-06 22-37-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606568/f467c9f0-e35d-5012-fd66-478a03b75d35.png)

以下のページを参考にIngressを修正したらアクセスできた。
https://serverfault.com/questions/1031810/400-error-with-nginx-ingress-to-kubernetes-dashboard

```yaml
annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/configuration-snippet: |-
      proxy_ssl_server_name on;
      proxy_ssl_name $host;
```
結果
![Screenshot from 2021-08-06 22-44-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606568/87b9b872-c693-3101-a678-66f15b620f3b.png)
あとは、トークンを入力してログインするだけ。

---
所感
セキュリティを確保するのであればローカルからkubectl proxy公開したほうがよさそう。
楽天書籍を検索できるLINEBotを作成してみた。

楽天APIを使用して書籍を検索できるLINEBotを作成しました。
ネットショッピングするときに大量のデータを見るだけで、時間がかかってしまったこと、
結局どれを購入すべきかわからなくなったこと、皆さんもありませんか？
なので、売上１位書籍だけを取り出せるLINEBotを作成しました。


##完成したもの




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/88629907-27b7-773a-5b05-ca9225b6bcb8.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/9441c485-b51c-824f-44ae-60126de752c4.png)

　　






##環境
* LINE公式アカウント開設
* LINE Developersアカウント登録
* Herokuの登録
* Node-REDインストール、アカウント登録
* 楽天ブックス書籍検索API



##作り方

**1.http inノードの編集**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/da2c91f1-a948-9756-7a48-aa4b8514b9e2.png)
　　

**2.「function」ノード(左側):受け取ったメッセージ格納**

```csharp

// LINEサーバーからの情報を「msg.line」に移動させる
msg.line = msg.payload;
// msg.payloadにメッセージ本体を入れる

msg.payload = 
    {
        "format": "json",
        "applicationId": "アプリID",
        "booksGenreId": "001004008",
        "hits": 1,
        // 売上順にソートするよう設定
        "sort": "sales",
        // Lineに入力されたタイトルを設定
        "title": msg.payload.events[0].message.text
    };

return msg;

```
　　

**3.「http request」ノードの編集**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/eb544c4c-0269-0d59-4fbf-b9e6c555be0e.png)





**4.switchノードの編集**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/f6e7ef9b-2b37-7058-0019-22ae14275fd8.png)




**5-1.「function」ノード(上側)：検索した結果０件だった場合**


```csharp
const result = '検索結果がありません。';

// LINEサーバーからの内容を復元する
msg.payload = msg.line;
// 返信メッセージをhttp requestの結果にする
msg.payload.events[0].message.text = result;

return msg;
```
　　

**5-2.「function」ノード(下側)：検索結果が１件以上の場合**

```csharp
// http requestの結果を取得する
item = msg.payload.Items[0].Item;
const result ='売上No.1書籍\nタイトル:' + item.title + '\n' + '筆者:' + item.author + '\n' + '詳細:' + item.itemCaption + '\n' + 'URL:' + item.itemUrl;

// LINEサーバーからの内容を復元する
msg.payload = msg.line;
// 返信メッセージをhttp requestの結果にする
msg.payload.events[0].message.text = result;

return msg;
```
　　
　　

**6.Reply Messageの設定**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/dabb777c-16f4-a9b6-17d6-41f06d2ae430.png)
　　
##まとめ
時間はすごくかかりましたが、完成できてほっとしています。
最後まで読んでいただきありがとうございました。
Set statementの書き方【GLPK】

[<--目次へ](https://qiita.com/ki073/items/508b3c20eb03078703dd)

マニュアル見てもSetの書き方が分からないことがよくあります。
気が付いた例文を書き留めておきますのでご参考に。

## 不連続な数値型Setの処理
数値型Setの場合には値の並び替えや最大値などの特定の値を取り出すことで、いろいろな処理に使うことができます。

```
set A :=  {10, 1, 2, 8, 3, 9, 5};
```

### 昇順・降順にソート

```
# 昇順
set A1 := setof{k in 1..card(A), i in A : card({j in A: i>=j})=k}(i);
# 降順
set A2 := setof{k in 1..card(A), i in A : card({j in A: i<=j})=k}(i);

# 数値範囲がわかってる場合の昇順
set A3:={1..10} inter A;
# 降順
set A4:=setof{i in 1..10}(11-i) inter A;
```

### 最小値と最大値、小さい方からn番目

```
# 最小値
set A5 := {i in A : card({j in A : i>=j})=1};
# 最大値
set A6 := {i in A : card({j in A : i<=j})=1};
# 小さい方から4番目
set A7 := {i in A : card({j in A : i>=j})=4};
```

### 隣あう数値のペア

```
set A8 := setof{k in 1..card(A)-1, i1 in A, i2 in A : card({j1 in A: i1>=j1})=k and card({j2 in A: i2>=j2})=k+1}(i1,i2);
# 結果 {(1,2), (2,3), (3,5), (5,8), (8,9), (9,10)}
```

### １から連番でインデックスをつける

```
set A9{i in 1..card(A)} := setof{k in A :card({j in A : j<=k})==i}(k);
# 結果 A9[1]:{1}, A9[2]:{2}, A9[3]:{3}, A9[4]:{5}, A9[5]:{8}, A9[6]:{9}, A9[7]:{10}
```

### 添字付きのSet
添字以下の値を含むSet

```
set B := {1, 2, 3, 5, 8, 9, 10};
set B1{i in B} := {j in B : i>=j};
# 結果 B1[1]: {1}, B1[2]: {1, 2}, B1[3]: {1, 2, 3}, B1[5]: {1, 2, 3, 5}
# B1[8]: {1, 2, 3, 5, 8}, B1[9]: {1, 2, 3, 5, 8, 9}, B1[10]: {1, 2, 3, 5, 8, 9, 10}
```

### 添字付きのSet(B1)を使った処理

```
# 最小値
set B2 := setof{i in B: card(B1[i])=1}(i);
# 最大値
set B3 := setof{i in B: card(B1[i])=card(B)}(i);
# 小さい方から4番目
set B4 := setof{i in B : card(B1[i])=4}(i);
# 隣あう数値のペア
set B5 := setof{i in B, j in B1[i]: card(B1[i])=card(B1[j])+1}(j,i);
# １から連番でインデックスをつける
set B6{i in 1..card(B)} := {j in B : card(B1[j])=I};
```

### タプルのn番目の要素を取り出す

```
set C1 := {(1,2), (1,3), (2,3), (2,4)};
set C2 := setof{(i,j) in C1}(i); # 1番目の要素
set C3 := setof{(i,j) in C1}(j); # 2番目の要素
```
CrystalでAtCoder(Log #2)

# Easy_2

https://atcoder.jp/contests/abc156/tasks/abc156_c

$Σ(X_i-P)^2$の最小値を求める。
$P$が実数でもよければ、$P$が$X_i$の平均値のときの値を求めれば終わり。
この問題では$P$は整数値に限定されている。$Σ(X_i-P)^2$は$P$についての２次関数で、放物線は下に凸で軸は$X_i$の平均値。よって近い方（遠くない方）の整数に丸めれば良いのではあるが。
想定解は全探索であろう。$P=1,2,…,100$の全てについて$Σ(X_i-P)^2$を求め、その最小値を取れば良い。

## Range

https://crystal-lang.org/api/0.33.0/Range.html

`a..b`は[a,b]、`a...b`は[a,b)を意味する。Rustだと`a..b`が[a, b)で、[a, b]は`a..=b`なので注意が必要。
1, 2, …, 100という概念は`1..100`で表せる。

## for文がない
```crystal
for i in 1..10
  puts i
end
# syntax error in eval:1
# Error: expecting token 'EOF', not 'in'
```
`for`はマクロの定義には登場するが、通常のループにはないらしい。Wolfram Languageでさえ採用してるのに。`while`文にしても良いが、むしろイテレータで書けということなのだろう。

## 標準入力を受けとる
```crystal:input.cr
n = read_line
x = read_line.split.map(&.to_i)
```

nは文字列になっているが、使わないのでこのままでいい。
2行目の右辺はEasy_1と同じく`Array`型なので、xも`Array`型になる。

## `Range#map`メソッド
Easy_1では`Array`に対して`map`を適用したが、`Range`にも適用できる。

```crystal:Range#map
(1..100).map{|p| 配列xの各要素とpとの差の二乗和}.配列の最小値
```

「xの各要素と、あるpとの差の二乗」は`x.map(|xi| (xi-p)**2)`で`Array`型。

## 配列の和、最小値
配列の和は`Array#sum`で求まる。
`x.map(|xi| (xi-p)**2).sum`で「xの各要素と、あるpとの差の二乗和」が求まる。
`(1..100).map{|p| x.map(|xi| (xi-p)**2).sum}`で、p = 1, 2, …, 100それぞれについての「xの各要素とpとの差の二乗和の配列」が求まる。
配列の最小値は`Array#min`メソッドで求まる。
`(1..100).map{|p| x.map(|xi| (xi-p)**2).sum}.min`で、「xの各要素とpとの差の二乗和」の最小値が求まる。これが答え。

## 標準出力
```crystal:output.cr
puts (1..100).map{|p| x.map(|xi| (xi-p)**2).sum}.min
```

## AC例
```crystal:abc156_c
n = read_line
x = read_line.split.map(&.to_i)
puts (1..100).map{ |p| x.map{ |xi| (xi-p)**2 }.sum }.min
```
【Amazon WorkMail】他のメーラーで送受信する方法【Becky】

##きっかけ
* awsで独自ドメインでアドレス作る際に、流れでAmazon WorkMailで作っちゃった（コスト掛かるの知らず）
* ↑のアドレスを今使ってるメーラーで送受信したい！

きっかけは単純、気軽にできると思っていた。。
設定に手こずったのでログ的に残します。


##Amazon WorkMailとは？
私的にはこんな感じで捉えてます↓

* 独自ドメイン使える（この流れでメアド作っちゃった）
* awsのメールサーバー
* 1アドレス50GBストレージで4ドル/月（お金掛かるの知らなかった:joy:
* 他のメーラーで送受信可能
* IMAPプロトコルのみ対応（POP3じゃないよ）
* リージョンは3つ（バージニア北部、オレゴン、アイルランド）
* 全部英語！

↓awsのこの辺にいます（2021/8/2現在）
![スクリーンショット 2021-08-02 223038.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777576/6719960e-104b-aadc-2fd2-5630c96a62bb.jpeg)

##メーラー側での設定
現在使っている『Becky』でメールの送受信させたかったので、Beckyの画面です。

①メールボックス＞新規作成＞基本設定
![スクリーンショット 2021-08-02 215026.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777576/d5c728c4-a384-b1f3-cbd9-40e9343e9fa5.jpeg)
受信プロトコルはIMAPを選択。
※IMAPサーバーとSMTPサーバーは、リージョンにより違うので詳細は [aws公式](https://docs.aws.amazon.com/ja_jp/workmail/latest/userguide/using_IMAP_client.html) をご覧ください。

OP25Bにチェック入れると送信エラーが出たので外してます（原因追跡中


②メールボックス＞新規作成＞詳細
![スクリーンショット 2021-08-02 214953.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/777576/7375ce91-0b2f-503a-cbed-589c6dc25a76.jpeg)
SMTPは465、IMAPを993に設定。
SSL/TLS関連は「証明書を検証しない」にチェック入れる（入れないとエラーでたry）

これだけ！！
最初、

* OP25Bにチェック入れる
* 「証明書を検証しない」にチェックなし

この2点に引っかかり送受信エラーハマって時間かかってしまい、悔しいので記事書きました。
この記事を参考に、少しでも救われる方がいたらいいなーと。


##おわり
※Amazon SESのサンドボックスから外に出しておきましょうね！
[Amazon SES サンドボックス外への移動](https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/request-production-access.html)
arduinoを用いた家庭菜園用センサー群の構築(1)_構想

#arduinoを用いた家庭菜園用センサーの構築
#目次
1. 目的
1. 達成手段
1. 課題

#目的
arduinoを用いて以下の目的を達成する
1. 適切な水やり等のタイミングを知らせることで、枯れや病気などの家庭菜園における失敗を防ぐ
1. データを収集し、気候や土壌環境の傾向を可視化する
1. カメラ等で撮影し、作物の現状を知らせる

#達成手段
##目的 1の達成手段
###適切な水やり等のタイミングを知らせる
- 外気温センサー
- 外湿度センサー
- 土壌温度センサー
- 土壌湿度センサー
- 日照度センサー

これらセンサーの情報を収集し、注意域・警戒域に達した場合にアラーム

##目的 2
###気候や土壌環境の傾向の可視化
- 収集した情報を処理しグラフ化
- 付属モニター、または通信を介して別の端末上に表示させる

##目的 3
###作物の現状を知らせる
- 一定時間ごとに撮影した画像を、別の端末に転送、またはSMS等に投稿する

#課題
##目的1の課題
- 各種センサーの選定
- アラームの出し方(音、光、etc)
- 注意域、警報域の設定

##目的2の課題
- データ収集方法
- 表示はどうやって？
- 別端末の場合、通信方法は？
- arduinoで出来る？

##目的3の課題
- 撮影したデータをどうやって転送する？
- 画像データの通信はarduinoで可能？
指定した時間後に処理をする

#今回の内容
* 指定した秒時間後に処理をさせる

# コード
* 今回は、3秒後に`3秒経過`とデバックエリアに表示させます。

```Swift
        print("通信などの処理開始")

        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            
            //tableView.reloadData()など
            print("3秒経過")
            
        }
```

```:デバックエリア
通信などの処理開始処理開始
3秒経過
```
#終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
どの記事を見ても（主観）OS X El Capitanをインストールできなかった話

#はじめに
覚書も兼ねて投稿します。
どのサイトを見ても（自分の調べ方と知識が残念なだけ）ターミナル上で日付変更もしくはインストーラの作成しか書いておらず、どちらを試してもできなかったので自分なりに成功した方法をまとめました。

**前提としてOSをインストールするMac（子Mac）と普段使用しているMac（親Mac）の２台を持っている方むけの記事になります。**

これが誰か一人でも役に立ってくれればうれしいです。
稚拙な文章ですがご容赦ください。
#結論
1.親Macで日付を変更
2.インストーラ作成
3.子Macにインストール
となります。
以降詳しく説明していきます。
#親Macで日付を変更
まず、なぜ日付を変更する必要があるかというと
>This certificate expired on 14 February 2016, causing error dialogs and preventing some apps from launching.
>https://tidbits.com/2016/03/02/previously-downloaded-os-x-installers-no-longer-work/

そう、Apple Worldwide Developer Relations Intermediate Certificateが2016年2月14日に期限切れとなったことでそのままインストールしようとするとエラーになるようです。

そこで、子Macのターミナルで日付を変更してインストールしよう！という記事が多く見られました。
しかし私の場合はエラーでした、、

そこでまず親MacのSafariを使ってOSをダウンロードします。

>https://support.apple.com/ja-jp/HT211683

OS X El Capitan 10.11を選びダウンロードします。
次に親Macの日付を変更します。（ダウンロード前に日付を変更してしまうとネットに接続できないでの注意）
左上のリンゴマーク→システム環境設定→日付と時刻→鍵を外す→2016年1月1日0時0分に設定

#インストーラ作成
ダウンロードしたdmgファイルを開き、「InstallMacOSX.pkg」を起動します。
手順に沿ってダウンロードを行います。
完了するとアプリケーション内に「OS X El Capitanインストール」というアイコンができます。
![無題19_20210802232346.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624994/3f341199-a388-1245-0356-de49e3364ce0.png)


次にインストーラを作成するUSBの設定を行います。（USBは初期化されるのでご注意ください）
上のメニューバーの「移動」→ユーティリティ→ディスクユーティリティ→今回使うUSBを選択し「消去」→写真のように名前を「macosx」、フォーマットを「Mac OS 拡張（ジャーナル）」で消去をクリックします。

![スクリーンショット 2021-08-02 22.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624994/1ec5875c-4fea-0152-6950-d7ea705d4a3f.png)

完了すると✅が出てUSBの名前が「macosx」になります。
いよいよインストーラの作成を行います。ターミナルを開き

```
/Applications/Install\ OS\ X\ El\ Capitan.app/Contents/Resources/createinstallmedia --volume /Volumes/macosx --applicationpath /Applications/Install\ OS\ X\ El\ Capitan.app
```

を打ち込んでください。最後のApplications/Install\ OS\ X\ El\ Capitan.appの部分はアプリケーションからOS X El Capitanインストールのフルパスを確認して各自変更してください。
あとは実行し、案内に従い「Y + enterキー」を押し10分程度待ちます。

完了すると「macosx」と名付けたUSBの名前が変更されています。
#子Macにインストール
親MacからUSBを安全に取り出し子Macに差し替えます。
子Macの電源をoptionキーを押しながら付けます。
すると「Install OS X El Capitan」が出てくるので、選択をしてインストールを進めます。

**ここでエラーがでた方はターミナルを開き以下のコードを打ち日付を変更してみてください。**
>date 0101000016

これで子Macの方も証明書の有効期限前の環境になります。

以上でインストール完了です！お疲れ様でした。

#終わりに
最後まで読んでいただきありがとうございます。
これでエルキャピタンのインストールに困る方が一人でも救われることを願います、、。

また最後まで読んでいただいたのに解決に至らなかった方、貴重な時間を奪ってしまい申し訳ありません。
【初心者向け】頻出のCSS

<h1>文字を装飾するCSS</h1>
<strong>【font-size】</strong>
用途：フォントの大きさを変更する
使用例：font-size: 2.5px;　font-size: 2.5em;
px：端末の設定が変わっても大きさが一定
em：端末の設定によって大きさが変わってくる

<strong>【font-family】</strong>
用途：フォントの種類を変更する
使用例：font-family: serif;

<strong>【font-weight】</strong>
用途：フォントの太さを変更する
使用例：font-weight: 100;(数字が大きいほど太くなる)

<strong>【color】</strong>
用途：フォントの色を変更する
使用例：color: #1b1b1b;(色はカラーコードで指定)

<strong>【text-align】</strong>
用途：文字の左寄せ・右寄せ・中央寄せを変更する
使用例：text-align: center; text-align: right; text-align: left;


<h1>画像や要素の縦幅、横幅調整</h1>
<strong>【width】</strong>
用途：横幅を変更する
使用例：width: 100%; width: 150px;

<strong>【height】</strong>
用途：縦幅を変更する
使用例：height: 100%; height: 150px;

<h1>画像や文章の位置調整</h1>
<strong>【margin-top】</strong>
用途：上との間隔を変更する
使用例：margin-top: 10px; margin-top: 15%;

<strong>【margin-left】</strong>
用途：右との間隔を調節する
使用例：margin-left: 10px; margin-left: 15%;

<strong>【margin-right】</strong>
用途：左との間隔を調節する
使用例：margin-right: 10px; margin-right: 15%;

<strong>【margin-bottom】</strong>
用途：下との間隔を調節する
使用例：margin-bottom: 10px; margin-bottom: 15%;

<strong>【margin】</strong>
用途：上下左右との間隔を一括で調節する
使用例：margin: 1px; margin: 10% 0% 10% 0%;

値が1つ指定された場合、上下左右に同じ値が適用される。
値が2つ指定された場合、1つ目の値は上下、2つ目の値は左右の辺に適用される。
値が3つ指定された場合、1つ目の値は上、2つ目の値は左右、3つ目の値は下に適用される。
値が4つ指定された場合、値はそれぞれ上、右、下、左の順 (時計回り) に適用される。


<strong>【padding-top】</strong>
用途：上部の余白を調節する
使用例：padding-top: 10px; padding-top: 15%;

<strong>【padding-left】</strong>
用途：左部の余白を調節する
使用例：padding-left: 10px; padding-left: 15%;

<strong>【padding-right】</strong>
用途：右部の余白を調節する
使用例：padding-right: 10px; padding-right: 15%;

<strong>【padding-bottom】</strong>
用途：下部の余白を調節する
使用例：padding-bottom: 10px; padding-bottom: 15%;

<strong>【padding】</strong>
用途：上下左右の余白を一括で調節する
使用例：padding: 1px; padding: 10% 0% 10% 0%;

値が1つ指定された場合、上下左右に同じ値が適用される。
値が2つ指定された場合、1つ目の値は上下、2つ目の値は左右の辺に適用される。
値が3つ指定された場合、1つ目の値は上、2つ目の値は左右、3つ目の値は下に適用される。
値が4つ指定された場合、値はそれぞれ上、右、下、左の順 (時計回り) に適用される。

<strong>【top】</strong>
用途：ページの最上部からの位置を調節する
使用例：top: 10px; top: 15%;

<strong>【left】</strong>
用途：ページの最左部からの位置を調節する
使用例：left: 10px; left: 15%;

<strong>【right】</strong>
用途：ベーシの最右部からの位置を調節する
使用例：right: 10px; right: 15%;

<strong>【bottom】</strong>
用途：ページの最下部からの位置を調節する
使用例：bottom: 10px; bottom: 15%;


<strong>※margin-topとtopの違い</strong>
margin-top：<strong>上にある要素との間隔</strong>を調節する
→縦に2つ並んだ画像の間隔を開けたい場合に使用する

top：<strong>ページ全体での上からの位置</strong>を調節する
Codeforces Round #736 (Div. 2) B. Gregor and the Pawn Game 二部グラフの最大マッチング/最大流解法

https://codeforces.com/contest/1549/problem/B

二部グラフの最大マッチングで解きます。公式のTutorialにも記載があるし、面白味はないです。

# 題意
- チェスのポーンがあり、黒(1列目にある)、白(2列目にあるとしてよい)の順に0=駒がない,1駒があるで与えられる
- 黒は動かない。白は何もない駒に対してまっすぐ進むことができる。黒がまっすぐある場合進めない。白は１つ斜めにある駒はとれる。
- さて、最大で何個の駒が1列目に行けるか？なお、白は１列目に行っても消滅しない

# こう考えた
最大流で解きます。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/2e551e61-c0b1-deca-5487-3b0c79bae88a.png width=50%>

- sから白(下)にはすべて辺を張ります(1にだけ張っても良いです) cap=1です。
- 黒(上)からtにはすべて辺を張ります。cap=1です。これは駒がある場合(1)もない場合(0)も白が到達する可能性があるのですべて辺を張らないといけません。
- 白から黒に辺を張ります。白のインデックスを$i$とすると、
    - 黒_$i$が0の時、辺をcap=1で張ります。何もないマスにはまっすぐ進めます
    - 黒i-1、あるいは、黒i+1が1の場合、それぞれ独立にcap=1で辺を張ります。白_$i$からcap=1で張ります。これは斜めの駒をとれることを意味します

以上の辺を張って最大流を流すと、このグラフにおける、tに到達できる最大のフロー = 1列目に到達できる最大の白のコマ数が求められます。

# 実装
$\pm 1$の処理が面倒なので、sを読み込む際に左右に$0$を付けて読み込みます。今回の制約ではこれは結果に影響しません。その際、$n$は$+2$して考える必要があることに注意です。

```C++
/* ACLをぺたり */
void solve() {
    int n; cin >> n;
    string s;
    vector<int> dat1(n+2);
    vector<int> dat2(n+2);
    cin >> s; REP(i, n) dat1.at(i+1) = s[i] - 0x30;
    cin >> s; REP(i, n) dat2.at(i+1) = s[i] - 0x30;

    mf_graph<int> mf((n + 2) * 2 + 2);
    int ss, tt;
    int node = n + 2;
    ss = node*2;
    tt = node*2 + 1;

    FOR(i, 1, n+1){
        mf.add_edge(ss, i, 1);
        mf.add_edge(node+i, tt, 1);
        if(dat2.at(i) == 0) continue;
        if(dat1.at(i) == 0) mf.add_edge(i, node + i, 1);
        if(dat1.at(i-1) == 1) mf.add_edge(i, node + i-1, 1);
        if(dat1.at(i+1) == 1) mf.add_edge(i, node + i +1, 1);
    }
    cout << mf.flow(ss, tt) << "\n";
    return;
    // debug
    vector<mf_graph<int>::edge> edges = mf.edges();
    for (auto &e : edges) {
        //cout << e.from <<","<<e.to << "," << e.flow << e.cap<< endl;
    }
}
int main(int argc, char *argv[]) {
    int q; cin >> q;
    REP(qq, q) solve();
}
```
https://codeforces.com/contest/1549/submission/124697616
APIとは何か？

##APIとはなに？
結論、プログラム同士を繋ぐインターフェースのことです。
「アプリケーション　プログラム　インターフェース」（Application Programming Interface）

インターフェイスとは、USBのように異なる二つの間を繋ぐ意味を持つみたいです。

過去音楽活動を行なっていた際、インターフェイスとゆう単語はよく聞き慣れていました。
個人的につなぐものって認識で間違ってなかったみたいですね（笑）

APIは主にソフトウェアやプログラム同士をつないでいるインターフェイスです。

要はシステムをみんなで使えるようにってことかなと思っています。


##APIの基本的なプロセス
基本的なプロセスとしては
1.「リクエスト（要求）API利用者側」
2.「レスポンス（応答）API提供者側」

##超ざっくりと
ようは、他で存在するプログラムを使うこと
メリットは開発のコストが抑えられること
セキュリティ面で強くなること
常に最新の情報を取得することができることです。

すでにできているプログラムを使えば、開発のコストは抑えられるし、APIを利用すれば要求を送るだけで高度な処理は提供者側が処理してデータを返してくれる。
また、リクエスト側でユーザーの情報を保持していないくていいので情報が漏洩するリスクが減る。

##参考サイト
言葉足らずになりましたが、APIがどういったものなのか。
全容を掴むことはできると思います。

https://www.sbbit.jp/article/cont1/62752

https://tcd-theme.com/2019/07/beginner-api.html?gclid=CjwKCAjwr56IBhAvEiwA1fuqGuREK88quiQHXqThTlnU7Oqi6I9AlmVrmZ0M4rQZy5sywu1mVAmiJBoCwMcQAvD_BwE

https://data.wingarc.com/what-is-api-16084
チーム開発には欠かせないgitgubの機能、プルリクエストについて。

###この記事を作成したきっかけ...
MENTAのあだちんさんに環境構築を見てもらう機会があり、知らないコマンドや手順が多くいくらコードが書けるようになってもグループ開発ではgitが使えないと感じたので備忘録として残します。

####プルリクエストとは

プルリクエストとは、開発者のローカルリポジトリでの変更を他の開発者に通知する機能です。プルリクエストは次のような機能があります。

・機能追加や改修など、作業内容をレビュー担当者や
　に通知される。
・ソースコードの変更箇所をわかりやすく表示


######自分-->pull request-->レビュー担当-->Merge-->main

####1.mainブランチに移動
ブランチを作る時は基本的にmainブランチからにする

```
$ git checkout main
```

####2.現在のブランチを確認

```
$ git branch
```
*マークがついているのが参照中のカレントブランチ
main *
  module1
  module2
  
####3.現在のブランチを元に新しいブランチを作成

```
$ git checkout -b module3

$ git branch
```
main 
  module1
  module2
module3*

####4.ファイルを変更してコミット

```
$ git add file-name
$ git commit -m "メッセージ"
```

####5. GitHub上にPush

```
$ git push origin module3
```

####参考記事
https://teratail.com/questions/280631
クロージャによるイベント通知パターン（備忘録）

##クロージャによるイベント通知
Swiftにおけるイベント通知パターンには3種類あり、その1つがクロージャによるイベント通知である。
クロージャを用いると、呼び出し元と同じ場所にコールバック処理を記述できるため、処理の流れを追いやすくなる。

しかし、複数のコールバック関数が必要な場合やコールバックの処理が複雑な場合はネストが深くなり可読性が下がる。

```swift
final class SomeClosure {
    
    private var num: Int = 0
    
    func plus(completion: (Int) -> (Void)) {
        num = 100
//処理の完了時の結果をクロージャに渡す
        completion(num)
    }
}

let someClosure = SomeClosure()

//処理の結果がnumに入る
someClosure.plus { (num) in
    print("Number is \(num)")
}

```

##どんなときに利用するべきか？
処理の完了イベントだけを受け取れればいいようなシンプルなケースの場合はクロージャを選択するべきであるが、コールバックの種類がいくつもある場合はデリゲートの利用も検討すべき

#参考
・Swift実践入門
「この住所なんて読むの？」郵便番号から地名の読み方を確認したい！プログラム知識ゼロ初心者のNode-RED×LINEbot奮闘記録

##「地名」って読むの難しい！
私が住んでいるのは　北海道　アイヌ語が地名の語源になっており
「読むのが難しい地名ランキング」なんてまとめサイトがあるくらい難解な地名が多いです。

今回は習いたてのNode-RED×LINEbotを使って、
「郵便番号を入力すると地名の読み方が検索」できるbotの作成にチャレンジしました。
社内で電報などの作成を依頼される場合があり、日本郵便の郵便番号検索ページを
使わなくても手元でさっと住所とヨミガナを検索する場面を想定しています。


##【使用ツール】
・[Heroku](https://jp.heroku.com/home/)
・[Node-RED](https://nodered.jp/)
・[LINE Developers](https://developers.line.biz/ja/)
・[zipcloud](http://zipcloud.ibsnet.co.jp/doc/api)(郵便番号検索API）
##◆実装されたもの
LINEで郵便番号を入力すると一致した住所とヨミガナを教えてくれます。
（「足寄」って読めますか？松山千春さんの出身地です）
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/992c0328-41b9-4359-3ccb-c65dec744bd5.png)
Node-REDのフローはこうなっています。
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/89004faa-b3c2-5891-36f5-b252d6e7a192.png)

##◆苦労したポイント
最初は何を入力しても固定の住所を返してくる困ったbotが出来上がりました。
↓↓ 「http requestノード」で固定の郵便番号をしているのが原因でした。
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/6468b568-0ff3-6f00-46bf-f120ee3ff6d2.png)
##◆解決できた方法
入力した郵便番号に応じた住所を返すための必要なステップは２つでした
①チェンジノードを挟む
この動作で、LINEから入力された郵便番号をzipcodeとして「郵便番号検索API」へ送ります
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/2144712f-18b2-d39d-54bd-5cb8484c5078.png)




②httprequestノードの指定URLに変数を入れる
先ほど固定の郵便番号を記入していた部分に「{{{zipcode}}}」を代入します
参考サイト：https://cookbook.nodered.jp/http/set-query-string
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1792185/ce334d9a-ab41-a41b-c452-d211f7d7c27f.png)
##作成を終えて
以上が、人生で初めて自分で作ったbotとなりました。
目的に対してどんな手段があるのかを考え、調べて作っていくこと。
やり方は一つではないことを実感しました。
我が子１号の「郵便番号検索bot１号」は今後「住所から郵便番号を検索できるbot」にレベルアップできるよう改良していきたいと思います。

最後まで読んでいただきありがとうございました。
（北海道の地名の読み方にご興味があればどうぞ：https://hokkaidofan.com/placename-base/
AWSのEC2にDockerをインストールする方法

# はじめに
昨日はローカルの開発環境（Windows）でDockerを使う記事を書いたので、本日はクラウド上（EC2）にDockerを導入する方法について記事にしたいと思います。

https://qiita.com/nagareboshi/items/2042755619f978394efd

# Amazon Linux2へのDockerのインストール

```bash
# yumを最新にする
sudo yum update -y

# dockerのインストールする
sudo yum install -y docker
docker -v
sudo systemctl start docker
sudo usermod -aG docker ec2-user

# 自動起動を有効化する
sudo systemctl enable docker

# 自動起動の設定確認する
sudo systemctl is-enabled docker

# インストールが終わったらEC2を再起動するために終了する
exit
```

# UbuntuへのDockerEngineのインストール

```bash
# 古いバージョンをアンインストールする
sudo apt-get remove docker docker-engine [docker.io](http://docker.io/) containerd runc

# 最新にする
sudo apt-get update

# リポジトリを利用してインストールするための準備をする
sudo -y apt-get install apt-transport-https ca-certificates curl gnupg lsb-release

# GPGキーを追加する（ファイルが改ざんされていないことを確認するために使われる鍵ファイル）
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# リポジトリ追加する
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Engineをインストールする
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# ubuntuユーザーでdockerを使えるようにする
sudo gpasswd -a ubuntu docker

# インストールが終わったらEC2を再起動するために終了する
exit

# 導入確認する
docker --version
```

# 関連サイト
https://docs.docker.com/engine/install/ubuntu/

https://www.trifields.jp/how-to-install-docker-on-ubuntu-2004-4436

https://www.atmarkit.co.jp/ait/articles/1612/14/news022.html

https://kazmax.zpp.jp/linux_beginner/etc_group.html#ah_1
SwiftのログフレームワークXCGLoggerを使ってみた(macOS)


    
# ログの保存先
- ログファイルの保存場所は`~/Library/Logs`以下が標準なので、下記の通り宣言します
    - [Adding custom log locations to the OS X console application](https://stackoverflow.com/questions/145354/adding-custom-log-locations-to-the-os-x-console-application)
    - [url\(for: in: appropriateFor: create:\)](https://developer.apple.com/documentation/foundation/filemanager/1407693-url)
    - [SwiftでNSDocumentDirectoryを見つける方法は？](https://www.it-swarm-ja.com/ja/ios/swift%E3%81%A7nsdocumentdirectory%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F/1047182722/)

```swift
private var logFile: URL {
    let library = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
    return library
        .appendingPathComponent("Logs")
        .appendingPathComponent("XCGLoggerDemo.log")
}
```

- 非サンドボックス環境では以下の通り

```sh
/Users/<UserName>/Library/Logs/XCGLoggerDemo.log
```

- サンドボックス環境では以下の通り
- `Containers`以下は何ぞやというのは次を参照
    - [Container Directories and File System Access](https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW6)

```sh
/Users/<UserName>/Library/Containers/jp.co.gmail.xxx.XCGLoggerDemo/Data/Library/Logs/XCGLoggerDemo.log
```    

    
# 実装例

- CocoaPodsでインストール

```
pod 'XCGLogger'
```

- [DaveWoodCom/XCGLogger](https://github.com/DaveWoodCom/XCGLogger)の`Basic Usage (Quick Start)`の通り進める
- `AppDelegate.swift`に`XCGLogger`のグローバル変数を定義する

```swift
import Cocoa
import XCGLogger

let log = XCGLogger.default

@main
class AppDelegate: NSObject, NSApplicationDelegate {
```

- `applicationDidFinishLaunching`で初期設定を行う

```swift
func applicationDidFinishLaunching(_ aNotification: Notification) {
    log.setup(level: .debug, showThreadName: true, showLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: logFile, fileLevel: .debug)
}
```

- あとは任意の場所で以下のように呼び出せば、コンソールおよびログファイルに出力されます

```swift
log.info("Hello, XCGLoggerDemo!")
```

- コンソールへの出力例

```sh
2021-08-02 22:07:21.190 [Info] > XCGLogger writing log to: file:///Users/<UserName>/Library/Logs/XCGLoggerDemo.log
2021-08-02 22:07:21.190 [Info] > XCGLoggerDemo Version: 1.0 Build: 1 PID: 57277
2021-08-02 22:07:21.190 [Info] > XCGLogger Version: 7.0.1 - Level: Debug
2021-08-02 22:07:22.438 [Info] [main] [ViewController.swift:33] saveLogFile(message:) > Hello, XCGLoggerDemo!
```

- ログファイルへの出力例

<img width="512" alt="image" src="https://i.imgur.com/6qQZI0M.jpg">

<img width="512" alt="image" src="https://i.imgur.com/WkbOnlB.jpg">
OSS-DB Silver合格までの勉強方法　

<h1>前提</h1>
sql初級者（簡単なselect文、insert文であれば書ける）
簡単なSQLでも必要なときに調べながら書いていたレベル。

<h1>勉強期間</h1>
合計2ヶ月間（1回目→1ヶ月で不合格）
平日は通勤時間(1h)。土日は2〜3h程度。

<h1>使用した教材</h1>
・ping-t
・OSS教科書 OSS DB Silver

<h1>結果</h1>
2回目で合格。1回目はトータル60％

　一般知識　87％
　運用管理　84％
　開発 SQL 68％
　トータル　80％

<h1>学習方法</h1>
ping-tを問いて、不明点をノートに書いて、覚えることを何度も繰り返した。
運用管理が馴染みがなく覚えにくかったので、実機に触って、理解することで理解を深めることができた。
合格することが目的であれば、ping-tだけで十分であるが、理解を深めたいという目的があれば参考書も購入することをおすすめします。

<h1>取得するメリット</h1>
「なんとなくやったことがある」という分野は、体型的に学ぶことで理解が深まると感じました。
また、自分自身のレベルを可視化する意味も持っていると思います。
資格不要論を唱える人もいますが、受験してみようと思った人は迷わず受験してみて下さい。
【Teratermマクロ】　if文で文字列が一致しているか判定


Teratermマクロでinputboxの入力値に応じて、条件分岐をする仕組みを作ろうとしたところ、
比較演算子で判定できないという想定外。自分なりに考えた方法を残しておく。

<h4>strcompareを使う</h4>

```
;●インプット
inputbox '対象を入力してください。(3文字以上)' 'Input'
msg = inputstr
;●入力文字列のチェック
messagebox msg 'Input'

;●頭3文字の切り出し
strcopy msg 1 3 Re
;●頭3文字のチェック
messagebox Re 'test'

;●'abc'と同値か比較、結果をresultへ
strcompare Re 'abc'

;●判定、比較の繰り返し
if result = 0 then
	VALUE = 'ABC'
	goto output
else
	strcompare Re 'def'
	if result = 0 then
		VALUE = 'DEF'
		goto output
	else
		strcompare Re 'ghi'

		if result = 0 then
			VALUE = 'GHI'
			goto output			
		else
			VALUE = 'XXX'
		
		endif
	endif
endif

;結果----------------------------
:output
messagebox VALUE 'Message'
end

```

→比較結果がシステム変数resultに格納される為、
入れ子構造になってしまいコードが見づらくなった。
書き方を工夫すればもう少し見やすくはなりそう。


<h4>別案</h4>
str2codeを使って文字列をASCIIコードに数値変換。

```
inputbox '対象を入力してください。(3文字以上)' 'Input'
msg = inputstr
messagebox msg 'Input'

strcopy msg 1 3 Re
messagebox Re 'test'

str2code returncode Re

;●ASCIIコードの確認
;messagebox returncode 'test'

if returncode = 6382179（ASCIIコード） then
	VALUE = 'ABC'
	goto output
elseif returncode = (ASCIIコード) then
	VALUE = 'DEF'
	goto output
elseif returncode = (ASCIIコード) then
	VALUE = 'GHI'
	goto output			
else
	VALUE = 'XXX'
endif

:output
messagebox VALUE 'Message'
end
```

→if文の入れ子にする必要がないので、比較的シンプルに書ける。
問題はASCIIコードを確認する手間がかかる事
lazy swift

map,filterのパフォーマンスを最適化するために使用される。
指定したコレクション型や要素が使われるまで評価しないようにしてくれる（遅延評価）

通常であればmap,filterは新しいシーケンスを生成するため余計にシーケンスを作成してしまう可能性がある。
パフォーマンスの低下に繋がる恐れがある。

そこでlazyの出番になる

```swift
 let lazySequence = array.lazy.map｛$0 + 1｝

 let mapSequence = Array(lazySequence)//この時に発火する
```
mapの後に記述して、,クロージャーの中の処理をキャッシュしてくれる。それをすることによって、
mapの処理が遅延し、必要なときだけ発火するようになる

lazyStoredProperties
--
lazyキーワードをストアドプロパティを宣言する前に記述してあげる
同様に必要なときだけしか呼ばれない。
インスタンス化したときに評価はされず、実際にプロパティにアクセスされた時に評価される。

```swift
struct Animal {
  lazy var name: String = {
    print("初期化が実行されました！")
    return "Cat"
  }()
}

// インスタンス化しても評価されない
var animal = Animal()
print("インスタンス化")

// プロパティにアクセスして（遅れて）評価される。
let name = animal.name
```
RESAS APIからちょっと知りたい数値をLINE Botで見るためにNode-REDを活用してつくる

エリアマーケティングで、対象のエリアのちょっとした数値をレポートに反映したいため、元のデータ(RESAS API)から探し出すのはちょっと面倒なので、LINE Botで指定の数値を教えてくれる仕組みをNode-REDも活用し制作。

#結論

![GIF.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/db8b4d1f-b3ce-35c1-63ef-b890021bb8f5.jpeg)

[RESAS API](https://opendata.resas-portal.go.jp/docs/api/v1/index.html)から指定のエリアの「将来人口推計」を教えてくれるものです。RESASAPIで登録された市区町村を入力すると、登録された将来人口推計を返します。(登録されている市区町村がない場合は「わかりません」を返す）

#使ったもの

###サービス

[Heroku](https://www.heroku.com/home)
[Node-RED](https://nodered.jp/)
[LINE Developers](https://developers.line.biz/ja/)
[RESAS API](https://opendata.resas-portal.go.jp/docs/api/v1/index.html)
※RESAS APIを利用の際にはAPIキーの取得（無料）が必要

#１．取得したデータ
![スクショ⑦.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/26c6c662-b1ec-e4fb-35f7-630c20efa72f.jpeg)

ここの「cityname」を入力すると、「value」(将来人口推計)を返すようにします。


#２．フロー構成

![スクショ①.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/eb151efe-1e3b-3978-d059-400ae94accce.jpeg)

先頭（左端）はhttp inノード、末尾（右端）は、インストールした ReplyMessageノードです。

###１つめ：http in
![スクショ②.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/484b1320-5abd-78da-e644-75f56b267464.jpeg)



LINEサーバーからのWebhookを受け付けるノードです。


###２つめ：function(検索ワードを保持）
![スクショ③.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/6bcda45a-c7ec-c691-10fa-b59815c15419.jpeg)

次以降のノードでmsg.payloadに入っているLINEメッセージが失われてしまうので、一時的にmsg.lineに退避させています。


###３つめ：function(RESAS APIキーで鍵開け)
![スクショ④.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/664466bf-0575-3438-ab43-56bb9151b544.jpeg)

RESAS API指定のリクエストヘッダー（X-API-KEY）と取得したAPIキー（画像は一部マスキング）を反映


###４つめ：http request(RESAS APIにアクセス）
![スクショ⑤.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/a7f72ea9-01b9-e945-ded4-a34366659594.jpeg)

メソッド：GET
出力形式：JSONオブジェクト


###５つめ：function(検索ワードがあったら将来人口を返す)
![スクショ⑥.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/7a933a79-24f8-c7da-030f-ae3ccd690516.jpeg)


都市名は配列になっているので、その配列の中身を検索する[findIndex](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)という関数を使って、LINEのメッセージと配列内の都市名が一致するか確認し、一致すればその配列位置（インデックス）を取り出します。そのインデックスを用いて、推定人口が示されているvalueをとってきます。該当の都市名がない場合は、「わかりません」を返します。

※ちなみに、将来人口推計(value)ではなく、人口増減率(ratio)を取り出したい！場合は15行目の「value」を「ratio」に変更することで取り出せます。

###６つめ：ReplyMessage(LINEで返信)
![スクショ⑧.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/a1358633-b086-9010-f6c6-bd5d5acdc072.jpeg)

LINE DevelopersでMessaging APIチャネルを作成し、「チャネルアクセストークン」と「チャネルシークレット」をそれぞれ取得してきてここに入れます。


#３．LINE DevelopersでWebhook URLを作成
![スクショ⑨.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/a62527dd-dda6-999b-8dfe-4ed6d02020b9.jpeg)

HerokuのURLに/webhookというパスを追加したものがエンドポイントとなります。
LINEとの連携において必要な情報はこのWebhook URLのほかにはシークレットとアクセストークンであり、あとはLINE公式アカウントマネージャーで、「応答設定」が以下のようになっているか確認するだけです。

![スクショ➉.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803233/8b3d6a99-8f9c-674f-225b-f682950f2ecb.jpeg)
公開鍵認証の設定覚え書き

# 公開鍵認証の設定手順

覚え書きですが、設定手順をまとめます。

* ssh-keygenで秘密鍵、公開鍵の作成

オプションは「man ssh-keygen」参照。
パスフレーズは空にすればssh-addを実行しなくてもSSH接続可能ですが、セキュリティが低下するため設定します。

```
% ssh-keygen -t [鍵の種類] -C [コメント] -N [パスフレーズ] -f [出力先 identity ファイル]
```
パスフレーズを指定するとhistoryコマンドの履歴に残るため、OpenSSHのコマンドは履歴に残らないようにzshaddhistoryで条件式が真の場合に内部の履歴リストに保存します。

参考記事：
zshaddhistory：[ZshManual/9.3.1 Hook Functions](https://zsh.sourceforge.io/Doc/Release/Functions.html#Functions)
条件式：[zshで特定のコマンドをヒストリに追加しない条件を柔軟に設定する](https://mollifier.hatenablog.com/entry/20090728/p1)

```~/.zshrc
zshaddhistory() {
　　　　　　　　# コマンドライン全体から改行を除去したもの
    local line=${1%%$'\n'}
　　　　　　　　# １つ目のコマンド
    local cmd=${line%% *}
    # 以下の条件をすべて満たすものだけをヒストリに追加する
    [[ ${cmd} != (ssh) &&
       ${cmd} != (ssh-keygen) &&
       ${cmd} != (ssh-add) &&
       ${cmd} != (ssh-agent) &&
       ${cmd} != (scp)
    ]]
}
```

* 公開鍵とSSHの接続設定は[ssh パスワードなしで Raspberry Pi にログインする](https://skylab.hateblo.jp/entry/2018/03/11/004603)を参考に実施

* SSHコマンドでパスフレーズを入力しないようにするため秘密鍵を登録

```
// 秘密鍵の登録する場合
% ssh-add [秘密鍵のパス]

// 登録されている鍵のFingerprints一覧を表示する場合
% ssh-add -l 

// 登録されている鍵を削除する場合
% ssh-add -d [秘密鍵のパス]
Identity removed: [秘密鍵]

// 登録されている鍵のFingerprints一覧を表示(削除後)する場合
% ssh-add -l             
The agent has no identities.
```

* ユーザ設定ファイル(~/.ssh/config)を作成

```~/.ssh/config
Host [接続するsshのエイリアス名]
  HostName [ローカルホスト名]
  User [ユーザー名]
  IdentityFile [秘密鍵のパス]
  Port [ボート番号(デフォルトは22)]
```

* sshdの設定変更(パスワード認証)

```
/etc/ssh/sshd_config
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
```

以上で「SSH [接続するsshのエイリアス名]」で公開鍵認証が可能になります。
DJITelloPyをMacbookに入れて、動かしてみる（成功）


Macbookへのインストールと動作確認で、成功しました。

###インストール対象

- [damiafuentes / DJITelloPy](https://github.com/damiafuentes/DJITelloPy)

###環境構築

```bash:Terminal
electron@diynoMacBook-Pro Desktop % pip3 install djitellopy
```

###動作確認（成功）

```bash:Terminal
electron@diynoMacBook-Pro Desktop % python3
Python 3.9.6 (default, Jun 29 2021, 06:20:32) 
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from djitellopy import Tello
>>> tello = Tello()
[INFO] tello.py - 107 - Tello instance was initialized. Host: '192.168.10.1'. Port: '8889'.
>>> 
>>> tello.connect()
[INFO] tello.py - 422 - Send command: 'command'
[ERROR] tello.py - 442 - 'utf-8' codec can't decode byte 0xcc in position 0: invalid continuation byte
[INFO] tello.py - 422 - Send command: 'command'
[INFO] tello.py - 446 - Response command: 'ok'
>>> 
>>> tello.takeoff()
[INFO] tello.py - 422 - Send command: 'takeoff'
[INFO] tello.py - 446 - Response takeoff: 'ok'
>>> tello.move_left(10)
[INFO] tello.py - 422 - Send command: 'left 10'
[INFO] tello.py - 446 - Response left 10: 'ok'
>>> 
>>> tello.move_left(20)
[INFO] tello.py - 422 - Send command: 'left 20'
[INFO] tello.py - 446 - Response left 20: 'out of range'
[INFO] tello.py - 422 - Send command: 'left 20'
[INFO] tello.py - 446 - Response left 20: 'ok'
>>> 
>>> tello.rotate_counter_clockwise(90)
[INFO] tello.py - 422 - Send command: 'ccw 90'
[INFO] tello.py - 446 - Response ccw 90: 'ok'
>>>
>>> tello.move_forward(20)
[INFO] tello.py - 422 - Send command: 'forward 20'
[INFO] tello.py - 446 - Response forward 20: 'ok'
>>> 
>>> 
>>> tello.land()
[INFO] tello.py - 422 - Send command: 'land'
[INFO] tello.py - 446 - Response land: 'ok'
>>> quit()
electrom@diyinoMacBook-Pro Desktop % 
```
プログラミング初心者が書いたマイグレーションのやり方について

はじめに
----

現在Laravelを学習しているプログラミング初心者の僕が
今回はマイグレーションのやり方について記載していきたいと思います。

マイグレーションとは？
----

マイグレーションとはデータベースのバージョン管理機能のことを指します。
PHPのスクリプトを使うことによりテーブルの作成処理などを用意することが出来るのです。

マイグレーションの手順としては以下のようになります。

+ マイグレーションファイルの作成
+ スクリプトの記述
+ マイグレーションの実行

マイグレーションファイルの作成~実行まで
-----

現在作成しているプロジェクトに移動してから以下のコマンドを実行します。
(僕は今回peopleというファイルを作ります)

```
$ php artisan make:migration cretate_people_table
```

するとdatabaseフォルダのmigrationsフォルダの中に
xxxxx_create_people_table.phpというファイルが新たに作られていると思います。
(xxxxxには作成した日時が書いてある)

```PHP:xxxxx_create_people_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePeopleTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('people', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('people');
    }
}
```

続いては上記のコードにテーブル生成と削除の処理を記載していきます。

```php
    public function up()
    {
        Schema::create('people', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name'); //追記
            $table->string('mail'); //追記
            $table->integer('age'); //追記
            $table->timestamps();
        });
    }
```

これでテーブルの生成は完了です。
テーブルの生成方法は下記の通りです。

```php
    public function up()
    {
        Schema::create('テーブル名', function (Blueprint $table) {
            $table->型('フィールド名');
        });
    }
```
続いてテーブルの削除処理となります。
削除処理のメソッドはすでにデフォルトで下記のコードが記述されています。

```php
    public function down()
    {
        Schema::dropIfExists('people'); //テーブルがあれば削除
    }
```

ここは特に変更するポイントは御座いません。
そして最後にこの作成したファイルを基にマイグレーションを実行します

```php
$ php artisan migrate
```

うまく成功すると画像のようになります
![マイグレーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1478204/9b681ec3-3495-6551-c6d0-fabb1211102d.png)
個人的な感想ですが、マイグレーションがうまく決まった時の気持ち良さは結構好きです笑
ちなみにmigrateして上手くいかなかった場合はまとめて巻き戻すことも出来ます。

```
$ php artisan migrate:rollback
```
以上がマイグレーションの作成〜実行となります。
問題なく進めばあっという間に完成できるので良ければやってみてください！

参考記事
https://qiita.com/shosho/items/a5a5839735dfef9214b1
https://readouble.com/laravel/5.6/ja/migrations.html
plotly で日付が密になる場合の回避方法

# plotlyを使っていて日付が密になってしまう例

英語でplotlyの日付が密になる現象の説明は下記にある。

https://community.plotly.com/t/how-to-make-the-messy-date-ticks-organized/7477

理由としては、plotly は、

- 文字列 YYYY-MM-DD のフォーマット(例 '2015-01-01') しか受け付けない。
- Datetime オブジェクト

の２つの型しか日付として受け付けてくれないのである。
その説明は明快なのですが、回避方法はこの記事を読んでもパッとわからない(私だけかもしれませんが..特にpandasでデータを保持した場合)。

## 回避方法 pandas 編

例えば、2021/08/02-10:43:33、という文字列でデータがpandasの df['time'] 保存されている場合、

``` python:
df['time'] = df['time'].str.replace("-"," ").str.replace("/","-") # b/c plotly only accepts YYYY-MM-DD
``` 

のように、str.replace で、適当に文字列を変換すればよい。この例だと、2021-08-02 10:43:33 のように変換されて、plotlyが解読可能な文字列になる。


このようにplotlyが受け付ける日付フォーマットに変換すれば、書式は特に指定しなくても、変な密な表示にはならない。

pandas 以外の場合は、実直に for loop 回して、replace で変換するなど、１発変換を入れるとOK。

``` python:
# date is a list such as ["2021/08/02-10:43:33", "2021/08/02-10:53:33", ...]
newdate = []
for onedate in date:
    newdate.append(onedate.replace("-"," ").replace("/","-")) 
```
binding.pryを使えるようになりたい！２

# はじめに
本記事は、昨日投稿した続きで、
「binding.pry」の使い方をまとめたものになります。
前回の投稿もご参照ください。

https://qiita.com/mkato1013/items/e7cbc21a4a03c9acf22c

# 「binding.pry」の目的
たとえ、「binding.pry」が万能だとしても、
確認できることは限られています。

```
目的（私が思いつくものです。他にもあると思います。）

①paramsの中身の確認
②「binding.pry」の後に、if文があれば、true　or falseの指示が出せているかどうか
③エラー内容の確認
④インスタンス変数の中身の確認
```
結論としては、
`何かの中身や結果が期待するものかどうかを調べたい時`
`エラーの原因はどこにあるのかを探したい時`
が目的となります。

# 何ができる？

```
ここのコードが間違えているため、このように修正しなさい！！
```
という`直接的にエラーを解決できるものではありません`。

```
ここではないかという目星をつけ、
「ここは間違えていない！ここも間違えていない！ここは間違っている！」
という風に、選択肢を潰していく
```
このようなことができます。
`指定した場所でエラーが起きるかどうかを確認するもの`です。

# どこで使用できる？
`コントローラー`でも`ビュー`でも`モデル`でも使用できます。
特にモデルでは、自作のメソッドが役割を果たせているかを確認する際に、
「binding.pry」は多く使用されます。

また、試したいコードの部分の手前に「binding.pry」を置きましょう。

# エラー内容の確認

```ruby
class OrdersController < ApplicationController

  def index
    @order = Order.new
  end

  def create
    @order = Order.new(order_params)
    binding.pry
    if @order.valid?
      @order.save
      return redirect_to root_path
    else
      render 'index'
    end
  end

  private

  def order_params
    params.require(:order).permit(:price)
  end

end
```

前回投稿したものを引用しますと、

```ruby
if @order.valid?
```
から「binding.pry」はエラーを調べることができます。
エラーがあれば「false」、なければ「true」ということは、前回に投稿しました。

「false」だった場合で、エラーの内容を確認したい時は、
`errors.full_messages`を記述しましょう。

```
[1] pry(#<OrdersController>)> @order.valid?
=> false

[2] pry(#<OrdersController>)> errors.full_messages
=> Price can't be blank
```

エラーが実際に画面に表示されたときも、
「Price can't be blank」のような文章が現れるはずです。

`errors.full_messages`
についてはよく使用するので、ここは暗記でも良いのでは？
と思い、私は暗記しました。

# 終わり
昨日に引き続き「binding.pry」の深堀を行いました。
何一つわからなかった昨日とは大きく成長したように思えます。

今回のように理解していなく、不安な要素は、
理解した上で、深堀することで、
`苦手から得意`になると私はそう思います。

どんどん得意を増やします。
引き続きがんばりましょう！！
【Laravel】package不足でcomposer installができない

既存のLaravelプロジェクトをインストールする工程で、composer installをしますが、

```
[ec2-user@ip-172-31-39-229 laravel]$ composer install
PHP Warning:  PHP Startup: Unable to load dynamic library 'pdo' (tried: /opt/remi/php74/root/usr/lib64/php/modules/pdo (/opt/remi/php74/root/usr/lib64/php/modules/pdo: cannot open shared object file: No such file or directory), /opt/remi/php74/root/usr/lib64/php/modules/pdo.so (/opt/remi/php74/root/usr/lib64/php/modules/pdo.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - doctrine/dbal[v2.10.0, ..., 2.13.x-dev] require ext-pdo * -> it is missing from your system. Install or enable PHP's pdo extension.
    - Root composer.json requires doctrine/dbal ^2.10 -> satisfiable by doctrine/dbal[v2.10.0, ..., 2.13.x-dev].
...
```

と出て、うまく動かなかった。

###エラー文：パッケージが不足している
ので、パッケージをインストールしていけばいいんですが、EC2だとインストールしたphpのバージョン毎に合わせて入れてあげる必要があります。

私の環境のphpのverionは7.4.22なので、

```
[ec2-user@ip-172-31-39-229 laravel]$ php -v
PHP 7.4.22 (cli) (built: Jul 27 2021 18:08:31) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

php74-php-pdoをインストールすればいいのです。

```
[ec2-user@ip-172-31-39-229 laravel]$ sudo yum install -y php74-php-pdo
```

以上です。
シフト情報を通知してくれるLINEbotが欲しい


コロナの流行により、
テレワーク勤務が職場で導入された方も多いのではないでしょうか。
その変化に伴い感じた課題を改善すべく、プログラミング初心者が取り組んでみました。

#【私が感じた課題】
出社時に、他部署で誰が不在または、テレワークかが把握できておらず、
シフト把握に時間がかかりお客さまをお待たせしてしまうということがありました。

・誰が
・何時までの勤務なのか
→毎日LINEbotでの通知で、シフト情報を教えてくれると少し楽になるのではないかと考えました。


#【完成イメージ】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/fe9742b2-d39a-5365-37e0-4ad6b6b5eb00.png)
↑上記のシフト内容に合わせて、
日付を入力するとLINEbotが勤務内容を教えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/80a70748-c98a-764b-e7da-559f193d2104.png)

この仕組みを作りたいと思いました。

#【使用したもの】
・[Node-red](https://nodered.jp/"Node-red")
・[LINE Developers](https://developers.line.biz/ja/"LINE Developers")
・[Google スプレッドシート](https://www.google.com/intl/ja_jp/sheets/about/"Google スプレッドシート")

#【プログラミング初心者がやってみた】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/8d020e3a-0af8-03e2-d855-74dd6d6731e3.png)
↑上記の形で、試行錯誤を行いましたが、なかなかGSheetノードがうまく動作せず、Google スプレッドシートからデータを取得できませんでした。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/bbcff6c1-e28d-1987-ebbe-3f1898b42119.png)
データが取れなくなっていることを相談させていただいたところ、Google スプレッドシートの「ファイル」→「ウェブ公開」で取得したURLでの方法を教えていただきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/5cf33e88-f4ad-6319-f136-060824b55fcb.png)
〇1つ目のfunctionノード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/768b85e1-8a0e-9eef-5e05-63301f19c57a.png)

〇2つ目のfunctionノード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802156/56ef6064-1f77-07b3-ab0f-b5b1211a06f6.png)

なんとか、8/1と8/2限定でデータ取得が可能となり、
完成イメージ図のLINEのメッセージが届くようになりました。


#【もっと知りたい】
Google スプレッドシートのデータを出し分ける方法を今も模索中です。
Google スプレッドシート内容に合わせて、データの出し分けをし返信ができるようになるとさまざまな業務の効率化にもつなげられると思っています。

最後までご覧いただきありがとうございました。
git stashでコンフリクトが起きたときの対処

## 【Git】git stashでコンフリクトが起きたときの対処

https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning

`git stash`は現在のブランチで変更をコミットせずに退避・一時保存できるコマンド

### たまに遭遇するケース

結構前に退避したものを`git stash pop`や`git stash apply`で元に戻そうとした時、色々なコミットを取り込んでしまっていると、場合によっては以下のような感じでコンフリクトが起きることがある

```bash
# 1 退避
git stash

# 2 別の人のコミットなどを取り込んだ後に元に戻そうとする
git stash apply stash@{0}

# 3 コンフリクトが起きる
error: Your local changes to the following files would be overwritten by merge:
        ~/ファイル名
Please commit your changes or stash them before you merge.
Aborting
```

そんな時に使うコマンドが`git stash branch <newbranch>`コマンド

### `git stash branch <newbranch>`の使い方

これは**新しいブランチを作成し、作業スタックに退避した時点のコミットを再現して、スタックにある作業を再適用**してくれる

つまり**stashコマンドを実行した時点のブランチの状態に戻せるようなイメージ**

```bash
# new-branchブランチを作成し、そっちのブランチに適用
git stash branch new_branch stash@{0}
```
Laravelでどの項目がバリデーションにかかっているかわからなくなった時

LaravelのBladeで、入力項目が多すぎて、どの項目がバリデーションに引っかかっているかわからなくなった。
以下のコードをbladeに埋め込むと該当の入力箇所が判別する、


```php
@foreach ($errors->all() as $error)
    {{$error}}
@endforeach
```