OmniAICreator/Qiita-1.07M huggingface dataset:
40 代おっさんPythonのライブラリついて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 参考資料

<https://www.udemy.com/course/python-kaizen/learn/lecture/26849736#overview>

## ライブラリ

ライブラリとは
便利な関数をまとめたもの

ライブラリでできること
Excelを操れる、グラフが書けるなど

### ライブラリを使う手順

❶ライブラリのインストール

```bash
pip install ライブラリ名
```

❷ライブラリを使う宣言

```python
inport ライブラリ名
```

### 日本の祝日を取るライブラリ

インストール

```bash
pip install jpholiday
```

インポートしてプログラムに書く

```python
import jpholiday

holiday = jpholiday.year_holidays(2022)
print(holiday)
```

出力結果

```bash
[(datetime.date(2022, 1, 1), '元日'), 
(datetime.date(2022, 1, 10), '成人の日'),
(datetime.date(2022, 2, 11), '建国記念の日'), 
(datetime.date(2022, 2, 23), '天皇誕生日'), 
(datetime.date(2022, 3, 21), '春分の日'), 
(datetime.date(2022, 4, 29), '昭和の日'), 
(datetime.date(2022, 5, 3), '憲法記念日'), 
(datetime.date(2022, 5, 4), 'みどりの日'), 
(datetime.date(2022, 5, 5), 'こ どもの日'), 
(datetime.date(2022, 7, 18), '海の日'),
(datetime.date(2022, 8, 11), '山の日'), 
(datetime.date(2022, 9, 19), '敬老の日'),
(datetime.date(2022, 9, 23), '秋分の日'),
(datetime.date(2022, 10, 10), 'スポーツの日'), 
(datetime.date(2022, 11, 3), '文化の日'), 
(datetime.date(2022, 11, 23), '勤労感謝の日')]
```

### クリップ上の情報を扱えるライブラリ

クリップボートとは
コピーした時に一時的に保管できる場所

インストール

```bash
pip install pyperclip
```

インポートしてプログラムに書く

```python
import pyperclip

print(pyperclip.paste())
```

最期にコピーした部分が出てきたと思います。

### グラフを作る関数

インストール

```bash
pip install matplotlib
```

インポートしてプログラムに書く

```python
import matplotlib.pyplot as plt

x = [1,2,3,4,5]
y = [1,5,4,3,7]

plt.plot(x,y)
plt.show()
```

import matplotlib.pyplot as plt
これはas（エイリアス）をつけてます。
別名をつけているという意味

実行結果を出したかったのですが…
Amazon Linux2環境のためGUI環境が整っていないため、やることもできるんですがかなり特殊でめんどくさいため中止しました。（自分の力量ではできないが正しい）

### 標準ライブラリ

osライブラリ
OS （オペレーティングシステム）に依存した機能を使うための標準ライブラリです

自分の今、使っているパスを見る

```python
import os

print(os.getcwd())
```

出力結果

```python
/home/ec2-user/4章
```

自分はCloud9を使っているためこの内容で出ました。

フォルダを作る

```python
import os

os.mkdir("toshiki")
```

実行するとフォルダが出来ていると思います

フォルダの名前を変える

```python
import os

os.rename("toshiki","TOSHIKI")
```

名前が大文字になったと思います

次はフォルダの移動

shutilライブラリを使う

```python
import shutil

shutil.move("TOSHIKI","/home/ec2-user")
```

フォルダを消す

```python
import shutil

shutil.rmtree("/home/ec2-user/TOSHIKI")
```
Amazon NeptuneフォーマットのcsvをGremlinロード形式に変換する

こちらのツールを使います。

https://github.com/awslabs/amazon-neptune-tools/tree/master/csv-gremlin

以下のcsvファイルを入力にしてみます。

```csv:air-routes-latest-edges.csv 
~id,~from,~to,~label,dist:int
3748,1,3,route,809
3749,1,4,route,214
3750,1,5,route,945
3751,1,6,route,576
```

### 実行
```
% python csv-gremlin.py air-routes-latest-edges.csv > air-routes-latest-edges

Processing Summary
------------------
Rows=5, IDs=4, Duplicate IDs=0, Vertices=0, Edges=4, Properties=4, Errors=0
%
```

### 結果
```groovy:air-routes-latest-edges
g
.addE("route").property(id,"3748").from(V("1")).to(V("3")).property("dist",809)
.addE("route").property(id,"3749").from(V("1")).to(V("4")).property("dist",214)
.addE("route").property(id,"3750").from(V("1")).to(V("5")).property("dist",945)
.addE("route").property(id,"3751").from(V("1")).to(V("6")).property("dist",576)
```

### 参考
https://docs.aws.amazon.com/ja_jp/neptune/latest/userguide/bulk-load-tutorial-format-gremlin.html
「スポット~」の差異がわからん

スポットブロック
スポットインスタンス
スポットフリート
（EC2フリート）
↑この辺がよくわからなくなったので説明します

## スポットブロック→廃止
スポットインスタンス利用時にあらかじめ決められた時間の起動を保証するオプション（最大6時間）

## スポットインスタンス
インスタンスの起動時にオプションで付けれる
指定した価格をスポットインスタンスの価格が下回った場合、警告後終了する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/536a1936-5607-e204-5b58-471a5e613a87.png)


## スポットフリート
あらかじめ指定した性能キャパシティを満たすようにスポットインスタンスを構成するオプション
ナビゲーションペインのスポットリクエストから起動できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/6bfced4c-f1e1-78c6-c91a-b4d73d7f0c0c.png)
↑実際のコンソール画面の一部

#### 特徴
①必要なvCPUかインスタンス数かメモリを指定できる

②スポットフリートの一部をオンデマンドインスタンスにする→確実に確保しておきたいインスタンス数を確保することができる。つまりそのオンデマンドインスタンス以外のインスタンスはスポットインスタンス
※起動テンプレートを指定した場合、ターゲット容量の一部をオンデマンドとして割り当てることができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/a9fa12a2-24d7-a349-ea7b-58b20fb5c179.png)

③ターゲット容量を維持する→指定したインスタンス数を下回った場合に新たにスポットインスタンスを起動してくれるオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/b2c85856-454f-4685-978c-016eed2cf714.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/c18c76a9-53ae-6847-b854-30b5286bad7f.png)

## EC2フリート
スポットフリートの上位互換の認識
（おそらくスポットフリートはただ指定された数を維持しようとするだけで、EC2フリーとはcloudwatchのメトリクスを見て調整するみたいに独自の機能があるはず）
https://dev.classmethod.jp/articles/auto-scaling-for-ec2-spot-fleets/

スポットフリート
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/spot-fleet.html
EC2フリート
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ec2-fleet.html


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/f9fb9746-6558-8d67-3976-3f576a8bd61f.png)


参考
https://blog.logical.co.jp/entry/2020/10/16/094330
https://www.youtube.com/watch?v=e-L-1z08j8Q
https://d1.awsstatic.com/webinars/jp/pdf/services/20190306_AWS-Blackbelt-EC2Spot.pdf
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/Fleets.html
CakePHP4でajaxが403になる件

## 問題

CakePHP4でajaxすると403になる。

## 原因

「config/routes.php」に全体のCSRFチェックの処理がデフォルトで入っているため、
フォーム以外からのPOSTはエラーになる。

## 対策1

以下を参照
http://tech.zhu-weichen.com/2020/09/15/164917/6/

## 対策2

最初は対策1をとっていたが、トークンを送信する形にしてみた。

```html:html
<input type="hidden" name="_csrfToken" id="_csrfToken" autocomplete="off" value="<?= $this->request->getAttribute('csrfToken') ?>">
```

```js:javascript
    $.ajax({
      url: "test/ajax_test",
      dataType: "json",
      type: "post",
      data: {"_csrfToken":$("#_csrfToken").val()},
      success: function(data) {}
    });
```

```php:TestController.php
function ajaxTest() {
    // 取得
    $data = $this->request->getData();
    // 返却
    return $this->response->withType('application/json')->withStringBody(json_encode($data))
}
```
Swift のコードをスクリプトから利用する方法

Swift の class や struct をスクリプトから利用する方法について紹介します。

# はじめに

iPhone アプリを開発中に、 iPhone アプリ向けに実装した Swift の class や struct を、 iPhone アプリの中ではなく、 macOS 上で実行するスクリプトから利用する必要性が生じました。
その際に学んだことを紹介します。

# 方法
## ステップ1: `main.swift` の作成
まず、　Swift のスクリプトを `main.swift` という名前で作成します。 Swift では、 `main.swift` という名称のファイルのみが、 top-level code の記述を許されているようです。
実際、他の名称のファイルにおいて top-level code を記述すると、実行時に以下のようなエラーが発生します。

`Expressions are not allowed at the top level`

## ステップ2: cat を利用したソースコードの連結
次に、 `main.swift` から他のソースファイルで実装された class や struct を利用するために、例えば以下の方法で `main.swift` と他のソースファイルを連結し、またそれらをスクリプトとして実行できます。

```
cat Shared/Model/*.swift Shared/Util/*.swift main.swift | swift -
```

# 参考文献

* `main.swift` について
  * https://developer.apple.com/swift/blog/?id=7
  * https://stackoverflow.com/questions/24642372/expressions-are-not-allowed-at-the-top-level-if-the-module-is-not-main-swift
* 他ソースファイルと main.swift の連結方法について
  * https://stackoverflow.com/questions/36265538/how-do-i-import-other-swift-files-into-a-swift-script
【grep】Git の全履歴から検索するコマンドが何をしているか分解してみた 【 $ git grep -w '検索ワード' $(git rev-list --all) 】


はじめに
-
`git grep`便利ですよね。エンジニアなら毎日何回も叩いてるんじゃないかなーと思います。
ただ普通に使うと、今いるブランチの今のソースコードの中からしか検索できません。
そこで、renameされたファイルのrename前や、削除されたファイルも含め全履歴の中から検索する方法を調べた所、このような手段を発見↓
```
$ git grep -w '検索ワード' $(git rev-list --all) 
```

https://suzuken.hatenablog.jp/entry/2018/12/05/155040

`rev-list`など見慣れない部分が結構あったので分解してみた。

分解
-

### `grep`の`-w`オプションとは？

単語で検索する。
したがって、全履歴から検索するという目的においては、あってもなくてもよい。

https://dev.classmethod.jp/articles/useful-git-grep-command/#:~:text=yaml%3A%20%20%20%20Timeout%3A%2010-,%E5%8D%98%E8%AA%9E%E3%81%A7%E6%A4%9C%E7%B4%A2%E3%81%97%E3%81%9F%E3%81%84,%2Dw%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%84%E3%81%BE%E3%81%99%E3%80%82,-%24%20git%20grep%20%2Dw

### `$()`とは？
`$()`内のコマンドを実行して実行結果を出力し展開する。

以下であれば`$(git rev-list --all)`をまず先に評価して、`grep`の引数として渡します。
`$ git grep -w '検索ワード' $(git rev-list --all) `

### `git rev-list`とは？
コミットハッシュを返すコマンド。
`--all`オプションをつけることで、今いるブランチの全コミットハッシュを返す。

### まとめると

```
$ git grep -w '検索ワード' $(git rev-list --all) 
```

まず、`$(git rev-list --all) `が実行され、全コミットハッシュを取得します。
全コミットハッシュは、`git grep -w '検索ワード'`に追加の引数として渡されます。
`git grep`は引数としてコミットハッシュを渡すと、そのコミット内で検索します、したがって全コミットハッシュを渡すことで全履歴からの検索が実現されているわけです。

 
用途
-
使い道としては、ちょっと限定的な状況ではありますが、例えばフロントで使われていないAPIをバックエンドで見つけた時に、フロントの過去のgitの全履歴を検索して、過去に使われていた事を確かめたりとかできます。
（このコマンドを使うと、ファイル名が変更されていたり削除されたファイルからも検索できるので、そういった漏れも起きません）
そうすることで、存在する理由が不明なAPIが、フロントで使用しなくなった時に削除し忘れたものだという事が特定できます。
多分他にもいろいろ使い道はあると思うので、あくまで一例です！


参考
-
https://uxmilk.jp/27666
https://webbibouroku.com/Blog/Article/shell-paren-brace-bracket#outline__6
https://uxmilk.jp/27666
鶏頭図をpythonで書いてみる

## はじめに
鶏頭図という言葉はあんまり馴染みのない言葉だと思いますが、この図を考案したのはかの有名なナイチンゲールであると言われています。
英語ではpolar area diagramとかNightingale rose diagramだとか言われているらしいです。
なるほど確かに鶏の鶏冠のように見えるから「鶏頭」なのかと思いがちですが、wikipediaによるとどうやらナイチンゲールはこの図を鶏頭とは読んでいなかったそう。
（https://ja.wikipedia.org/wiki/%E5%86%86%E3%82%B0%E3%83%A9%E3%83%95）

名前の由来はさておき、ナイチンゲールはこのような可視化の技術を使ってクリミア戦争に参加した兵の衛生状態などを政治家などにわかりやすく伝えていたそうです。確かに極座標的な表現を使うことで、角度だけではなく、面積も用いることができ二次元の情報を視覚的にわかりやすく表現できています。

温故知新ということで私もこのプロットを使おうと思ったのですが、思ったよりも苦戦してしまったので、そのやり方を備忘的に記しておこうかなと思います。


## 準備
今回はmatplotlibを使って実装してみたいと思います。
barplotのwidthをxと対応させて、axのpolarパラメーターをTrueにすることによって綺麗な鶏頭図に仕立て上げるという戦法で行きます。
### import
使うのはこの二種類。
```python
import matplotlib.pyplot as plt
import numpy as np
```
### データの用意
適当に10個用意してみましょう。
```python
x = np.array([np.random.randint(1, 10) for i in range(10)])
y = np.array([np.random.randint(1, 10) for i in range(10)])
```
### まずはbarplot
幅をxに対応させ、高さをyに対応させます。
最後に丸くするので、横軸の幅はそれぞれの合計が2πになるように標準化します。
そうすると今度はxの位置をうまく調整して、さまざまな幅の軸が重ならず上手く隣り合うように調整してあげる必要があります。

```python
width = x * 2 * np.pi / sum(x)
theta = np.insert(width.cumsum(), 0, 0)[:-1]
plt.figure(figsize=(10, 10))
ax = plt.subplot(111)
ax.bar(theta, y, width=width, align='edge')
```
解説します。
widthはxを合計が2πになるように標準化したもので理解できると思います。

thetaに関してですが、累積和を求めてそれぞれのwidthに対応したx軸上の位置を決めてあげます。しかし、最初の一個目は0にしてあげたいので0を先頭にinsertして、最後のx軸の値は要らなくなるのでスライスして消えてもらいます。
![bar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615000/466969f0-6945-c803-f70b-6e797d2ec209.png)

幅の異なるbarたちが肩を寄せ合って並んでくれました。なんと微笑ましい。

### polarにする
こいつを丸めてあげましょう。

```python
plt.figure(figsize=(10, 10))
ax = plt.subplot(111, polar=True)
ax.bar(theta, y, width=width, align='edge')
```

こんな感じです。
![pie1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615000/aa93fdad-0daf-4e25-39d3-2c27e1a7ed86.png)

WAになって踊ろうを彷彿させる図が出来ました。barたちが形を変えながらも、綺麗に犇めきあっているのが気持ちいいです。

### 見やすく整える
なんだかスタートが右からだし、左回りだし見づらいですね。
時間に縛られて生きる現代人の感覚的にはやはり12時スタート、右回りにしたいものです。
おまけに度数表記より％表記にしたいのでやっちゃいます。

```python
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_thetagrids(np.arange(0, 360, 36), labels=["0%", "10%", "20%", "30%","40%","50%", "60%", "70%", "80%", "90%"])
ax.set_rgrids(np.arange(0, y.max()+1, 1), angle=0)
```

おまけに色も変えちゃってます。ここは各々お好きにどうぞ。
![pie2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615000/67257f61-754e-25fe-9f09-93ac15b60bb8.png)


### 全コード
忙しい方はこちらをどうぞ。

```python
import matplotlib.pyplot as plt
import numpy as np

x = np.array([np.random.randint(1, 10) for i in range(10)])
y = np.array([np.random.randint(1, 10) for i in range(10)])

width = x * 2 * np.pi / sum(x)
theta = np.insert(width.cumsum(), 0, 0)[:-1]
plt.figure(figsize=(10, 10))
ax = plt.subplot(111, polar=True)
ax.bar(theta, y, width=width, align='edge', color=plt.cm.Paired(np.arange(10)))
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_thetagrids(np.arange(0, 360, 36), labels=["0%", "10%", "20%", "30%","40%","50%", "60%", "70%", "80%", "90%"])
ax.set_rgrids(np.arange(0, y.max()+1, 1), angle=0)
plt.show()
```

## 終わりに
plotのセンスを磨く前にまずは色々自在に操れるようになりたいです。やりたいplotイメージがあっても実装につまりがちです。このplotめちゃ苦戦した。
リーダーになって見えた景色


エンジニアになってもうすぐ丸3年になろうとしている頃、プロジェクトでリーダーの役割を担う機会をいただきました。今までリーダーからタスクを割り振られて仕事をしていましたが、リーダーになってみると見える景色が違いました。今書いておかないと忘れてしまうので、思ったことを書き残しておこうと思います。

# タスク内容

案件としては2か月で設計からリリースまでを行う改修のプロジェクトです。他案件も掛け持ちしてますが、主なメンバーは4人です。私の主なタスクとしては、①WBSを用いた進捗管理/タスク割り振り、②成果物のレビュー、③上司への報告/相談、④設計や実装など自分のタスク、⑤その他として質問対応/進捗会議運営などでした。お客さんとのやり取りは別の方が担当していました。

進捗管理を誰かが行っているのを見ているのと、自分でやってみるのは全然違いました。思考の幅と量に大きく違いがありました。とにかく先読みが必要でした。「ここまでには～～を完了させて、、」「〇月□日にはこのタスクがあるから、準備をいつ始めればいいか～」など、今日時点の進捗から次のタスクのことを検討していました。正直、タスクを振られる側の時はここまで思案していませんでした。

# 変わったこと
役割が変わったからか、発言や時間の使い方などタスクの進め方に変化がありました。まず、メンバーに対して「いつ頃終わりそうか？」という質問が増えました。こまめなリスケやタスクの入れ替えを行うためです。違う立場を経験したこともあって、自分がタスクを振られる側（作業側）になったら、おおよそな見込みを聞かれる前に答えれるようになりたいところですね。

また、ミーティングやミーティング準備の時間が増えて、自分の作業時間が減りました。上司への進捗報告や他チームとの調整のためにミーティングに参加していましたが、予想以上に時間を持っていかれました。タスクを行う自分だけの時間が減り、誰かとコミュニケーションをとって円滑にプロジェクトを進める動きが増えました。スケジュールとにらめっこして、いつまでに〇〇タスクをやりきるぞ！と気合を入れていました。思った通りに進められない方が多かったですが。

さらに、自分から情報をチェックする回数が増えました。チャットやチケット、メールなど担当プロジェクトにかかわりそうな情報は全て内容を確認しました。振り返るとかなり重要な習慣でした。連絡のチェックは後回しにすると、痛い目に遭います。責任感とタスク進捗の間で揺れ動く部分ですが、忙しくても必要なことだと感じました。「あれってどうなりました？」みたいなセリフがチームを救う瞬間もありますね。

# 気を付けていたこと
進捗会議の運営も板につき始めた頃から気を付けていたことがあります。まず、即レスです。質問やレビュー依頼が頻繁に私のもとにきます。これにすぐリアクションをつけることには注意を払っていたつもりです。会議中ですぐ返答できなさそうなときは、「会議中なので、終わってから返します！」「少々お待ちを！」と一報入れるようにしました。リモートワークなので、連絡が届いているという意思表示は連絡した側の気持ちを楽にしてくれると思います。

また、気になったことは積極的に発言することです。慣れない会議で、慣れない役割でもとりあえず声に出してみることです。けっこう勇気いります。「疑問を持ち、非難せずに質問すること」はリーダシップ/フォロアーシップ両方で必要な行動です。今まであまりできていない部分でしたが、役割が私を強くした部分でした。

# 改善したいこと
改善点はたくさんあります。たくさんです。今回は3つだけ紹介します。一番直したいのは「自信のなさ」です。進捗確認のミーティングなどで対応に困ることや解決策が思い浮かばないとき、声が弱々しかったように思います。雰囲気を台無しにしている気がして反省点として最初に思い浮かびました。「できていません」ではなく「対応します」、「わかりません」ではなく「確認します」といえるようになることが第一歩でしょうか。また、どこまで自分で判断していいのか迷う場面もたくさんありました。「迷い」が「自信のなさ」に直結していると自己分析しました。経験を積むしかないですかね。

次に改善したいのは、「技術力の向上」です。リーダーになると小さいタスクの数が圧倒的に増えます。量をこなすには1つ1つにかける時間を短くする必要があります。そのためには技術力を磨くことが最優先かと思いました。当然ですが、技術力はミーティング内容の理解度、レビューの精度やシステムの品質に大きな影響を与えます。問題が起きた時の原因調査や解決策の提示にスピード感をもってあたるには必ず必要な要素です。どこを確認すればよいか、見当を素早くつけれるようになりたいですね。

3つ目は「質問の仕方」です。「～は大丈夫ですか？」というような質問ばかりしていました。「～は大丈夫ですか？」の質問に対する答えはだいたい「大丈夫です」になります。実は「大丈夫」以外の答えを知りたい時もあるのですが、この聞き方だと正確に聞き出せない気がしています。質問する側になって気づきました。他の人はどのような聞き方をしているのか意識して聞いて、取り入れたいですね。

# 今時点で思ういいチームの条件
ポジティブ思考で進められているなどたくさんあると思いますが、この2か月の経験で考えたいいチームの条件があります。その条件とは「情報がよいタイミングで必要な人にわたること」です。質問しやすい環境をつくるだとか、ミーティングで必要な人を呼べている、変更部分はちゃんとメンバーに伝わっているなど、タスクの進みに影響します。そして、情報をちゃんと流す、いきわたらせるのは主にリーダーの役割です。ちょっとした気遣いが進捗を加速させると思います。

誰が何をどこまで知っているか。この視点は今まで持っていない視点でした。タスクの管理も大事ですが、情報伝達管理も大事なタスクです。次またリーダーになったら、意識する部分です。

***

新しいことに挑戦したときの気持ちやギャップはすぐに忘れてしまいます。慣れが出てくと、思い出せません。だから、書き残しておこうと思いました。今までもたくさん失敗がありましたし、これからもたくさん失敗するでしょう。忘れない仕組みをつくって積み重ねると、きっと、どこまでもいけると信じてます。

最後まで読んでいただいた方、ありがとうございました。
WordPressのWP Mail SMTPでエラーが出た時の対処法

AWS上でWordPressを構築していて、メール設定をしていたところ、設定自体は上手くいったのですが、しばらくすると次のようなエラーが出るようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/679eb304-4a9c-daad-59b5-340aeb4da419.png)

```
SMTP Error: data not accepted.SMTP server error: 
DATA END command failed Detail: Message rejected: Email address is not verified. 
The following identities failed the check in [送信先メールアドレス].
SMTP code: 554
```

エラー内容を見る限り、正しいメールアドレスとして認識されずに送信に失敗しているようです。
メールソースを見ると、SiteGuardプラグインから送出されているようで、恐らくログイン失敗時にメールを飛ばそうとしたみたいです。ただ、そもそもメールが送れないことが問題なので、このソースは関係なさそう。

# 結論
今回はメール配信サービスにAWS SESを利用しました。
そこで設定したメールアドレスと上記エラー内の[送信先メールアドレス]が異なっていました。

WP Mail SMTPの設定内には「このメールを強制使用」というチェックボックスがあり、ここにチェックを入れると指定されたメールアドレスに強制的にメールが送られるようです。

こちらのチェックを入れた後、メールテストを行ったらエラーは出なくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/0011e703-4258-c448-8510-764c4a79a62e.png)

ただ、SiteGuardが違うメールアドレスに送信しようとしたなら、どこかにその設定があると思うんですが、SiteGuardの設定内にメールアドレスの設定は見つかりませんでした。対象のメールアドレスは以前、WordPressの一般設定に書いていたものなので、そこのキャッシュなどが残っていたのかもしれないですね。

# 追記
SiteGuardはWordPressユーザーに設定しているメールアドレス宛に通知を送るようです。
そのため、下記ユーザー編集画面でメールアドレスを変更すれば、エラーは出なくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520632/47d1abcf-b056-06b2-c210-21ac00ccb84e.png)
GitHub Actions で .node-version の中身を actions/setup-node@v2 に渡したい

GitHub Actions 上で Node.js をインストールする場合、バージョンを指定しますよね。
そこでバージョン番号をベタ書きしてしまうと、プロジェクトで使う Node.js のバージョンが上がった際にいちいち書き換えないといけないので、ちょっと面倒です。

ところで [nodenv](https://github.com/nodenv/nodenv) などを使っているメンバーがいるプロジェクトでは、 `.node-version` というファイルが存在すると思います。
GitHub Actions が実行される際に `.node-version` ファイルの中身を読んで、それに従って Node.js をインストールしてくれたら、後々楽ができそうです。

一番最初に試してみたのは以下の実装です。
`xargs` を使うのがミソですね。
（アドバイスをくださったチームメンバーの H さんに感謝します。）

```yaml
steps:
  - uses: actions/checkout@v2
  - name: Set NODE_VERSION
    run: cat .node-version | xargs -I {value} echo "NODE_VERSION={value}" >> $GITHUB_ENV
  - uses: actions/setup-node@v2
    with:
      node-version: ${{ env.NODE_VERSION }}
      cache: 'yarn'
  - run: yarn install
  - run: yarn test
```

次に試したのは、 `$()` を使った実装です。
こっちの方が記述量が少ないですね。
（コメントをくださった @ushjp さんに感謝します。）

```yaml
steps:
  - uses: actions/checkout@v2
  - name: Set NODE_VERSION
    run: echo "NODE_VERSION=$(cat .node-version)" >> $GITHUB_ENV
  - uses: actions/setup-node@v2
    with:
      node-version: ${{ env.NODE_VERSION }}
      cache: 'yarn'
  - run: yarn install
  - run: yarn test
```

ここまで試したところで、そもそも `actions/setup-node@v2` 自体にその機能があることが判明しました。
実は `node-version-file` を指定するだけで良かったんですね。
（コメントをくださった @kmkm さんに感謝します。）

```yaml
steps:
  - uses: actions/checkout@v2
  - uses: actions/setup-node@v2
    with:
      node-version-file: '.node-version'
      cache: 'yarn'
  - run: yarn install
  - run: yarn test
```

https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#node-version-file

というわけで、一番下のやり方がベストだと思われます。
皆様のご参考になれば幸いです。

#### 蛇足

`ruby/setup-ruby@v1` は `.ruby-version` ファイルを勝手に読んでくれるし、 `bundler-cache: true` を指定すれば `bundle install` もやってくれるらしいです。
便利ですね。

https://github.com/ruby/setup-ruby
[Vue.js] v-ifを複数要素まとめて一括で適用したい

Vue.jsの理解がまだまだ浅いので備忘録。

# v-if の基本
`v-if`はディレクティブと呼ばれるものの1つで、基本的には1つの要素に対して記述します。
ディレクティブとはなんぞや？という人は、公式ドキュメントをどうぞ。 ⇒ [Vue.js ディレクティブ](https://012-jp.vuejs.org/guide/directives.html)

例えば以下の例では、ボタン要素に対して`v-if`を使用しています。
（`color="primary"`はボタンの色を指定しています）
```html:vue
<template>
    <v-btn v-if="true" color="primary">ボタンだよ</v-btn>
</template>
```
`v-if="true"`なので、こんなボタンが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1337870/ea218ddf-04ff-9fcc-b2e6-00cd784daa5d.png)
これを`v-if="false"`にすると、ボタンが消えます。
他にも、`v-if="変数 === 値 "`や`v-if="変数 !== '文字列' "`などのように記述することもでき、ディレクティブの式が真を返す場合のみ表示されます。

# v-if を複数要素に適用したい
表やグラフなど、複数の要素を1つのまとまりとして`v-if`で制御したい場面はよくあると思います。
例えばこんな感じの長ったらしいコードについて、`v-card-text`の内容を、セレクトタグで選択した値など何らかの条件によって表示が変わるようにしたいとします。（内容は適当ですが例なのでご勘弁を）
```html:vue
<template>
    <v-card>
        <v-card-text>
            <v-card-subtitle>タイトル</v-card-subtitle>
            <v-card>
                <v-row>
                    <v-col>あれとか</v-col>
                    <v-col>これとか</v-col>
                </v-row>
            </v-card>
        </v-card-text>
    </v-card>
</template>
```
さてここで、`v-if`の何たるかを全然わかっていない僕はこんなことをします。
##### 間違った書き方
```html
<template>
    <v-card>
        <v-card-text v-if="true">  <!-- ← ここにv-if置いて見事にエラー -->
            <v-card-subtitle>タイトル</v-card-subtitle>
            <v-card>
                <v-row>
                    <v-col>あれとか</v-col>
                    <v-col>これとか</v-col>
                </v-row>
            </v-card>
        </v-card-text>
    </v-card>
</template>
```
初心者の直観的にはまさにやりたいことはこんなイメージなんですが…これではエラー。
`v-if`は基本的には単一の要素に対して有効だからです。

正しくは以下のように、**条件で表示を変えたい要素を新たにtemplateタグで囲み、このtemplateタグにv-ifを付加する**と思い通りの描画ができます。
##### 正しい書き方

```html
<template>
    <v-card>
        <v-card-text>   <!-- ← ここにv-ifを置くのではなく -->
            <template v-if="true">   <!-- ← ここにtemplateタグを作ってv-ifを置く -->
                <v-card-subtitle>タイトル</v-card-subtitle>
                <v-card>
                    <v-row>
                        <v-col>あれとか</v-col>
                        <v-col>これとか</v-col>
                    </v-row>
                </v-card>
            </template>
        </v-card-text>
    </v-card>
</template>
```
これで`v-card-text`の中身を`v-if`で一括して制御できるようになりました。


# まとめ
`v-if`で一括して制御したい複数要素は、新たに作った`template`タグに`v-if`を付加して、この中に入れる。

公式ドキュメントの説明はこちら。 ⇒ [< template >での v-if による条件グループ](https://v3.ja.vuejs.org/guide/conditional.html#template-%E3%81%A6%E3%82%99%E3%81%AE-v-if-%E3%81%AB%E3%82%88%E3%82%8B%E6%9D%A1%E4%BB%B6%E3%82%AF%E3%82%99%E3%83%AB%E3%83%BC%E3%83%95%E3%82%9A)
駆け出しエンジニアの初開発と環境構築

### 環境構築（CodeIgniterのインポート）

エンジニアとしてスタートを切ったばかりの駆け出しが、初開発を終えての備忘録と、今後駆け出すエンジニアの役に立てたらなと思い、記事を投稿します。
まだまだ知識が少ないので、間違いも沢山あると思います。
この記事を読んでくださる方からアドバイス等たくさん頂けると嬉しいです。

### 開発環境

・Eclipse
・CodeIgniter3
・MySQL
・GitHub
・Bootstrap4

初開発ではECサイトを作成しました。
CodeIgniterはPHPの、Bootstrapはフロントサイドのフレームワークです。
DBはMySQLを使用し、Eclipseで開発を行いました。

今回はCodeIgniterのインポート方法です。
以前はJavaとSpringを使用して学習していました。SpringはJava用のフレームワークで、Eclipseに元々入っていたので、画面左上のファイルからSpringのプロジェクトを作成できました。しかし、CodeIgniterはEclipseに入っていません。どうすればいいのか迷ったので、その記事を残せればと思います。既に情報はあるかもしれませんが、この記事は備忘録も兼ねてますので改めて書かせていただきます。


それでは、本題に入ります。

初めに、PHP用のEclipseとCodeIgniterをインストール。
※インストール方法は割愛します。

Eclipseを起動後、左上のファイルを開き、新規、PHPプロジェクトを選択。
任意の名前を付けプロジェクトを作成します。
次に、作成したプロジェクトを右クリックし、インポートを選択。
![スクリーンショット (370).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/a7fea967-5e9f-1fb6-2767-c1f22604effb.png)
下記のような画面が出てくるので一般、ファイルシステムを選択し次へを押します。
![スクリーンショット (371).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/27f60454-0d33-dc97-1ce3-ab2f08bc54cc.png)
下記ウィンドウが開かれるので、参照を押します。
ファイルの選択を行うことができるので、インストールしたCodeIgniterを選択し開くを押します。
最後に、すべてを選択するを押して、完了。
![スクリーンショット (374).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/59c2ccb1-4e6f-032e-46ee-bd9c5078445a.png)
これで、EclipseにCodeIgniterをインポートできました。
インポート完了後、このようにエラーや警告が大量に出ているかと思います。
![スクリーンショット (375).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/e0246285-be49-09cc-774a-ed7b01e36168.png)
エラーや警告は、型に解決できない、CIのついているクラス名を変更しなさいみたいな感じでしょうか。
ただ、CodeIgniterの仕様なので動作に問題ないです。
気になる方は、画面上部のメニューのウィンドウ->設定->PHP->検証->エラー/警告を開きます。
![スクリーンショット (377).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/7f0982bc-38d1-2e7b-9688-48dd05f99108.png)
下から5つを無視に設定すると、エラーと警告はほぼ消えて、エラーが一件残ります。
![スクリーンショット (378).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539853/c5b19ab0-9dde-ea3b-8b48-ca79a305b353.png)
こちらも動作に問題ないので、CodeIgniterの仕様だと思います。
これで、CodeIgniterのインポートは完了です。

お疲れ様でした！
Wordleが高速で解けるアプリ「WordFinder.」を開発しました

![WCTLEN.003.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540507/d53ca981-f6d0-ec1e-59cf-f2c9b695211d.jpeg)
アプリのダウンロードはこちら -> https://apps.apple.com/us/app/wctl/id1612200762


このアプリでは、入力した内容をもとにWordleの解答を高精度で推測することができます。

紹介動画↓

<iframe width="560" height="315" src="https://www.youtube.com/watch?v=teowmbi7GGI&t=304s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


入力をもっと速くするとか、ある程度定石を決めておくなどすれば10秒以内も可能かと思います。
また、次はARの画像認識技術を使って、カメラを設置してWordleの画面をリアルタイムで読み取り、自動で答えを導出できるようにしたいと思います。
確か今、１０周の世界記録が１分程度だったのでAR技術を導入すれば世界記録の短縮も可能と思われます。


アルゴリズムを作るのにはかなり苦労しました。 




そもそもこれ、表面上は「Wordleを解くためのアプリ」ではないのですよね。
仮に、Wordleというゲーム単体のためのみに作られたコンセプトだとしたら、おそらくAppleStoreの審査で弾かれてしまうのです。
実際に公式の[Apple Store Review ガイドライン](https://developer.apple.com/jp/app-store/review/guidelines/)4.1条「模倣」ではこのように定義されています。

>4.1 模倣
独自のアイデアを生み出してください。自分だけのアイデアがあるはずです。それを形にしましょう。App Storeで人気のある最新Appを単にコピーしたり、別のAppの名前やUIを少し変更して自分のAppとして提出したりすることは避けてください。知的財産侵害の申し立てをされるリスクがあるだけでなく、App Storeの運営が困難になり、また、他のデベロッパにとってもフェアではありません。

どこまでが模倣と定義されるかは分からないのですが、以前フリーランスで個人でアプリ開発を承った際に、クライアントの要望でLINEのようなやりとりを自分で作れるアプリを開発したのですが、なんとこの4.1条「模倣」で審査に引っかかってしまい、時間と労力を無駄にしてしまうという致命的な死活問題を起こしてしまったことがありました。


そのようなトラウマがあったため、私はWCTLを開発する際に「３〜８文字でもできる」「行数制限なし」「頻度レベルで分類する」「GIFを多用してとにかくデザインを凝る」といった独自の要素を取り入れてリジェクト（審査落ち）を回避しようとしました。　


そのような甲斐あってか、今回は審査に時間はかかったものの一発で審査に合格することができました。

![WCTLEN.002.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540507/4f3f6877-395b-a19e-558e-679d2da37be4.jpeg)
AttributeError: module 'optuna' has no attribute 'create_study'にはまった話

# はじめに
XGBRegressorのハイパーパラメータをチューニングしようとoptunaを使おうとしたときに、あまり見たことがないエラーを吐いたので、今後同じミスをしないように、記事を残しておきます。

# エラーの詳細
AttributeError: module 'optuna' has no attribute 'create_study'

モジュールにはxxxという機能がありませんよ！って怒られてます...
どういうこっちゃ？

# 解決方法
ドキュメント見直しても、create_studyあるよなぁって思いながら、似た質問している人いないか探していたら、下記の記事を見つけました。

[Visualization not working #308](https://github.com/optuna/optuna/issues/308)

ファイルの名前とモジュールの名前をうっかり一緒にしていました。モジュールとファイル名を同じにすると、今開いているファイルを優先してしまうみたい。
uninitialized constant FactoryBotのエラーが出た時の話

出たエラーは下記

```
1) User ユーザー新規登録 内容に問題ない場合 すべての値が正しく入力されていれば保存できること
     Failure/Error: @user = FactoryBot.build(:user)
     
     NameError:
       uninitialized constant FactoryBot
     # ./spec/models/user_spec.rb:6:in `block (3 levels) in <top (required)>'
```


# 確認箇所
・FactoryBotの記述内容
・user_spec.rbの記述内容

上記確認しても誤字は見当たらない

uninitialized constant
⇨翻訳すると”未初期化の定数”
ということは、、、

Gemfileを見ると下記のように記述していました。。。
```Ruby:Gemfile
group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
```


正しくはこう
```Ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
```
bundle installコマンドを実行後、再度テストコード実行コマンドを叩き解決しました。
めちゃくちゃ凡ミスでしたが、いい勉強になりました。。。
Laravel+Nuxt.jsでCORSエラー

またCORSエラーに何時間も悩まされました。

Laravel8でconfig/cors.php を最大限に緩めた設定にしても、毎度おなじみのエラーが出て困り果てていました。
 
結局、原因はCORSそのものの設定ではなく、その手前の処理でいくつかミスっていたため、レスポンスが正しく返されていないせいでした。

# 今回のミス。

## Basic認証対策漏れ
Basic認証がかかっている試験環境サーバへのデプロイだったが、レスポンスが正しく返せていなかった。この場合でもブラウザにはCORSエラーが表示される。

APIリクエストのパスにBasic認証のIDとパスワードを付与していなかったためと思ったが、URLを

```
https://basicid:basicpath@sample.com/api/test
```

みたいにして埋め込んでもダメでした。

そのため、APIサーバになるLaravel側のドメイン部分はApacheの設定を上書きしてBasic認証から除外しました。
とりあえず全部許可しましたが、今後管理画面とかをこのドメインに配置する場合はURLパターンで制限かけ直す必要はあります。

```public/.htaccess
# 以下を追記
Satisfy Any
Order allow,deny
Allow from all
Deny from none
```

## モデルのSeedが正しくできていなかった。
ログインページでCORSエラー発生。
API連携でLaravel側で認証していたが、単純にUserの初期データを投入できていなかった。
DatabaseSeederに必要なSeederクラスを登録していないのに、
php artisan db:seed を実行してやった気になっていた。
php artisan db:seed --class=UserTableSeeder でやりなおしたら治った。

## Allow-Origin-Headerを２箇所に書いていた
ググっていろいろ試しているうちに余計なことをしていた。
laravel内のcors.phpで記述しているのに、同じことをpublic/.htaccessにも書いていた。
２箇所に allow-origin-header = "*" を書くと、重複エラーが起きる。
ブラックボックステスト技法 境界値分析

# 概要
基本情報や応用情報でも出てくるテスト技法です。
プログラミングの事ばかり勉強していると疎かになりがちな知識なので
復習をするためのアウトプットです。

前回：[同値分析法](https://qiita.com/RINYU_DRVO/items/597d8ffdf1f0c99527e1)

# 境界値分析
>　同値分割法の拡張で、パーティションが数値または順序付け可能な値で構成される場合だけ使用できる。パーティションの最小値及び最大値が境界値である。

最大値と最小値を選んでテストする

例)
1桁の正の整数2個を足し算

```javascript
function add(num1, num2) {
  if (num1 < 1 || num1 > 9 || num2 < 1 || num2 > 9) {
    // バリデーション
    throw new Error('valid');
  }
  return num1 + num2;
}
```

無効同値パーティション
`9 < x`
最小値：`10`

```javascript
add(1, 10); // Error: valid
add(10, 1); // Error: valid
```

`x < 1`
最大値：`0`

```javascript
add(1, 0); // Error: valid
add(0, 1); // Error: valid
```

有効同値パーティション
`1 < x < 9`
最小値：`1`
最大値：`9`

```javascript
add(1, 1); // 2
add(9, 9); //18
```

# ポイント
境界に対する記述ミスや解釈ミスに起因する欠陥を狙う

例）
不等号`<`等の記述ミス

# 参考
[JSTQB FLシラバス](http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018V31.J03.pdf)
AWS CDKでセキュリティグループを制限したFargateの起動

# 概要

AWS CDKの`ApplicationLoadBalancedFargateService`でFargateを作った際、ALBのセキュリティグループでIP制限をしましたが、セキュリティグループが全開放されてしまいました。なので今回はセキュリティグループを設定したFargateを起動する方法を紹介します。
`ApplicationLoadBalancedFargateService`については以下を参考にしてください。

https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs-patterns.ApplicationLoadBalancedFargateService.html

# 環境

- windows10
- aws-cdk: `2.8.0`

# 手順

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

`SecurityGroup`クラスを使用し、セキュリティグループを作成します。

```typescript
    const alb_securityGroup = new SecurityGroup(this, "SecurityGroup", {
      vpc: vpc, //VPCを指定
      allowAllOutbound: true,
    });
```

### インバウンドルール追加

セキュリティグループにインバウンドルールを追加します。

```typescript
alb_securityGroup.addIngressRule(
      ec2.Peer.ipv4('IPアドレス'),
      ec2.Port.tcp(ポート番号),
      "任意" //インバウンドルールの説明を記載
    );

```

`SecurityGroup`クラスの詳細については以下を参考にしてください。

https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ec2.SecurityGroup.html

## ALB作成

作成したセキュリティグループを割り当てたALBを作成します。


```typescript
    const alb = new ApplicationLoadBalancer(this,'alb',{
      internetFacing: true, //インターネットからのアクセスを許可するかどうか指定
      loadBalancerName: 'alb',
      securityGroup: alb_securityGroup, //作成したセキュリティグループを割り当てる
      vpc   
    })
```

` ApplicationLoadBalancer`クラスの詳細については以下を参考にしてください。

https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-elasticloadbalancingv2.ApplicationLoadBalancer.html

## Fargateを作成

`ApplicationLoadBalancedFargateService`を使用し、先ほど作成したALBを指定しFargateを作成します。



```typescript
    const loadBalancedFargateService = new ecsp.ApplicationLoadBalancedFargateService(this, 'SampleWebService', {
      cluster,
      memoryLimitMiB:512,//任意の値を指定
      desiredCount:1,//任意の値を指定
      cpu:256,//任意の値を指定
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
      loadBalancer:alb, //先ほど作成したALBを指定
      openListener:false,
    });
```

`ApplicationLoadBalancedFargateService`はデフォルトでは、ALBのリスナーに全開放されたセキュリティグループが割り当てられてしまうため、最後の行の`openListener:false`に指定することで作成したALBのセキュリティグループが反映されるようにします。
これでALBのセキュリティグループで制限したFargateを起動することが可能です。
` ApplicationLoadBalancedFargateService`クラスの詳細については以下を参考にしてください。

https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-ecs-patterns.ApplicationLoadBalancedFargateService.html
夏時間を考慮した日付のフォーマット変換

[Answersで回答する時に使う情報のまとめに戻る](https://qiita.com/Keiji_otsubo/items/9e6e0e946826133eddc7)


military timeとなっているので24時間表示かと思ったらAM、PM表示の12間表示なんですよね。
私の感覚とは違う。

```
IF( OR(
SchedStartTime< DATETIMEVALUE(DATE(YEAR(DATEVALUE(SchedStartTime)),3,14)
-(WEEKDAY(DATE(YEAR(DATEVALUE(SchedStartTime)),3,14))-1))+11/24,
SchedStartTime> DATETIMEVALUE(DATE(YEAR(DATEVALUE(SchedStartTime)),11,7)
-(WEEKDAY(DATE(YEAR(DATEVALUE(SchedStartTime)),11,7))-1))+11/24
),
TEXT(
HOUR(TIMEVALUE(SchedStartTime-5/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-5/24))>23,24,0)-
IF(HOUR(TIMEVALUE(SchedStartTime-5/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-5/24))>23,24,0)>12, 12,0))+":"+
LPAD(TEXT(MINUTE( TIMEVALUE(SchedStartTime  ))),2, "0")+
IF(HOUR(TIMEVALUE(SchedStartTime-5/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-5/24))>23,24,0)>11, " P"," A")
,
TEXT(
HOUR(TIMEVALUE(SchedStartTime-4/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-4/24))>23,24,0)-
IF(HOUR(TIMEVALUE(SchedStartTime-4/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-4/24))>23,24,0)>12,12,0))

+":"+
LPAD(TEXT(MINUTE( TIMEVALUE(SchedStartTime ))),2, "0")+
IF(HOUR(TIMEVALUE(SchedStartTime-4/24))
-IF(HOUR(TIMEVALUE(SchedStartTime-4/24))>23,24,0)>11, " P"," A")

)
+"M"
```

[Time Formula is showing military time](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000FXcDzSAL)
現役エンジニアがプログラミング学習サービス「Progate」のおすすめコンテンツを5つ+α厳選してみた

# 読んで欲しい方
- プログラミングでも始めてみようかな、と思っている方
- できれば無料で勉強したいと思っている方
- 何から始めたら良いかワカンネ状態の方

# Progateとは？
> Progateはオンラインプログラミング学習サービスです。「初心者から、創れる人を生み出す」ことが、私たちの理念です。

[公式サイト](https://prog-8.com/)より



# なぜProgateなのか？
イラストを使った説明がわかりやすく、迷わない！
文系出身の自分でも挫折することなく、おかげさまで「創れる人」になりました！
Progateさん、ありがとう！！謝謝！！

# おすすめコンテンツ一覧 （言語別コース編から厳選）
では、さっそく！
おすすめコンテンツは以下になります。


* JavaScript
* Python
* Command Line
* SQL
* Git

５つ上げていますが、**プログラミング言語** と **その他**に分けられます。
## プログラミング言語
* JavaScript
* Python

## その他
* Command Line
* SQL
* Git 
 
# おすすめの理由
## JavaScript
* GitHub人気プログラミング言語ランキング１位
* 汎用性が高い
    * フロントエンドでもサーバーサイドでも使える
    * ランキング４位のTypeScriptの先祖
## Python
* GitHub人気プログラミング言語ランキング２位
* クセが少なく、書きやすい
* 機械学習系の案件で使われることが多く、将来はAIに関わりたいと思っている方にもおすすめ

### どちらにしようか迷った方へ
どちらでも良いです。直感でオーケーです。
とりあえず始めることが大事です！

## その他
その他の3つは、職業エンジニアになったら必須になるスキルです。
できないと「えっ」となってしまいます。
JavaScriptかPythonを勉強した後に職業エンジニアに興味がでてきたらやってみることをオススメします！

### Command Line
* あれです、エンジニアが使う「謎の黒い画面」のやつです
* キーボードから文字を入力することで命令を出し、コンピューターと直接対話するようにファイルを見たり、変更したりするもの
![スクリーンショット 2022-03-01 19.29.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186503/42b0281f-e01b-4618-9d40-99f969ebfb6e.png)



### SQL
* データベースを取り扱う時に使う言語
* テーブル定義を設定したり、データを取得したりする時に使います

### Git 
* ソースコードのバージョン管理システム
* 実務では絶対に避けて通れないスキルです
Gitについては、実戦向きの記事があるので、良かったら読んでみて下さい。
（[未経験エンジニアが1年半で使ったgitコマンド一覧](https://qiita.com/ken1041/items/6dff35ad08c409c09685)）


# おすすめ+α
１人で勉強するにはProgateがおすすですが、実践に勝るものはないと思っています。
Progateさん、ごめんなさい。。陳謝。

現在、当社では一緒に働く仲間を募集しております！
未経験で入社し、活躍している社員がたくさんいる環境です。

ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
高速超解像　Fast-SRGANをモバイルで使う

# 高速超解像機械学習モデルをiOSで使う方法です
256 → 1024
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/aaf51131-9c93-6d22-780a-274cf9cd9d59.png" width=500> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/b20435b7-1e4d-6b43-1087-74d80a63cedd.png" width=500>
![スクリーンショット 2022-03-02 11.04.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/a9e7754c-6293-b43a-e3ac-2ff046deb0c8.png)


# 超解像を高速に使いたい
モバイルアプリでのユーザーエクスペリエンスの向上や、動画の超解像には、超解像モデルの実行時間が長すぎる場合があります。

# Fast-SRGAN
高速実行できる超解像モデルです。
これをiOS用に変換して実行します。

#変換

チェックポイントからモデルをロードし、CoreML形式に変換します。

```python
from tensorflow import keras

model = keras.models.load_model('models/generator.h5')
inputs = keras.Input((None, None, 3))
output = model(inputs)
model = keras.models.Model(inputs, output)

import coremltools as ct
mlmodel = ct.convert(model,inputs=[ct.ImageType(shape=(1,256,256,3),scale=1/255)])
```

出力形状を画像用に変形し、非正規化します。

```python
from coremltools.proto import FeatureTypes_pb2 as ft
from coremltools.models.utils import save_spec

spec = mlmodel.get_spec()
builder = ct.models.neural_network.NeuralNetworkBuilder(spec=spec)
builder.add_permute(name="permute", dim=[0,3,1,2], input_name="Identity", output_name="permute_out")
# builder.add_squeeze(name="squeeze", input_name="permute_out", output_name="squeeze_out", axes = None, squeeze_all = True)
builder.add_activation(name="activation",non_linearity="LINEAR",input_name="permute_out",output_name="activation_out",params=[127.5,127.5])

builder.spec.description.output.pop()
builder.spec.description.output.add()
output = builder.spec.description.output[0]
output.name = "activation_out"

output.type.imageType.colorSpace = ft.ImageFeatureType.ColorSpace.Value('RGB')
output.type.imageType.width = 1024 
output.type.imageType.height = 1024

save_spec(builder.spec, 'fast-SRGAN.mlmodel')
```

0.42秒で実行できました。

変換スクリプト：

https://colab.research.google.com/drive/1wRCegYOIFdyshVG0moZWXcxARO3FbRk1?usp=sharing

変換済みモデル：

https://github.com/john-rocky/CoreML-Models#fast-srgan

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
ゼロパディングでsliceとpadStart使ってみた

過去に投稿した記事のコメントを元にコードをブラッシュアップしたい。
今回は時計機能で使うゼロパディングをif文以外のやり方である
・slice
・padStart
について自分なりに整理する

ブラッシュアップ対象である僕の記事がこちら↓


https://qiita.com/KK1989/items/c5060a09f9986c86d983


<h2>コメント内容</h2>

コメント
「ゼロパディング処理は、sliceを使う方法やpadStartを使う方法が簡潔に記述できて良いかと思います。
」
→if文以外にも便利そうな方法があるのか、やってみよう

<h3>ゼロパディングとは</h3>

例えば、「5時30分」の表記を「5:30」から「05:30」と表記すること
 そんな定数をtwoDigitalと言う名前で宣言して使おう

<h3>if文の場合</h3>

```js:if-padding.js

const twoDigital = function(num) { 
        let digit  /
           if (num < 10) {digit = "0"+ num; }  //if文 "0"+は文字列として0を足すため
           else {digit = num; }         
           return digit ;  //返り値（結果）としてdigitを返す

```
これを時間取得するメソッド使って
```js:clock-easy.js
  const now =new Date();
  const hour = twoDigital(now.getHours());
  const minute = twoDigital(now.getMinutes());
  console.log(hour + minute);
```
でclock関数宣言とインターバルで表示させるって感じ

<h3>slice()の場合</h3>

sliceの使い方はこちらを参照

https://rfs.jp/sb/javascript/js-lab/zeropadding.html

こんな感じで書ける

```js:clock-slice.js
   const twoDigital = function(num) {
    let digit = String("00" + num).slice(-2);
    return digit;
   }
```

<h3>padStart()の場合</h3>

padStartの使い方はこちらを参照

https://itsakura.com/js-padstart


https://qiita.com/y-u-t-a/items/66db68a1f089ab8748bc

こんな感じで書ける

```js.clock-pad.js
   const twoDigital = function(num) {
     let digit = String(num).padStart(2,0);
     return digit;
   }
```

<h2>感想</h2>
ゼロパディングするだけでも、３つもやり方があるのですね〜　奥が深い〜
個人的にはイメージしやすいくて、（参考URLに注意書きがあるけど、）ブラウザ環境によって使えなかったりするらしいけど、とりあえず一番新しいpadStartを同じ局面出てきたら使ってみよう。
ブラックボックステスト技法 同値分析法

# 概要
基本情報や応用情報でも出てくるテスト技法です。
プログラミングの事ばかり勉強していると疎かになりがちな知識なので
復習をするためのアウトプットです。

# 同値分割法
> 同等に処理されると想定したデータ全てを同じパーティションに振り分ける技法

各パーティションから少なくとも1個の値を選んでテストする

メリット：テスト回数の大幅な削減

例)
1桁の正の整数2個を足し算

```javascript
function add(num1, num2) {
  if (num1 < 1 || num1 > 9 || num2 < 1 || num2 > 9) {
    // バリデーション
    throw new Error('valid');
  }
  return num1 + num2;
}
```

## 同値パーティションに振り分け
同等に処理されると想定したデータ全てを同じパーティションに振り分ける

### 無効同値パーティション
システムに拒否される値
`x < 1`

### 有効同値パーティション
システムに受け入れられる値
`1 < x < 9`

### 無効同値パーティション
システムに拒否される値
`9 < x`

## 各パーティションから最初1つの値を選んでテスト
例）
無効同値パーティション：`-3`・`13`
有効同値パーティション：`3`

```javascript
// 無効同値パーティション
add(3, -3); // Error: valid
add(-3, 3); // Error: valid
add(3, 13); // Error: valid
add(13, 3); // Error: valid

// 有効同値パーティション
add(3, 3); // 6
```

# 補足
パーティションが識別できるのは入力だけではない

例）
`5 + 5 = 10`
答えが2桁になった時は表示位置がずれるかも？
と考えると別パーティションにしてもいい

# 参考
[JSTQB FLシラバス](http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018V31.J03.pdf)
[Next.js]初心者なりにnext.jsの推しポイントをまとめてみた

# 前書き
どうも！絶賛就活中のグッピーです！

なんと僕の尊敬する師匠が会社をクビになってしまいました・・・

理由が価値観の相違などと聞き、価値観の一致がどれほど重要なのかを思い知らされましたね。

ってなことは置いておき、今回はnext.jsの主な機能と、なぜnext.jsが人気急上昇中なのかを書いていきたいと思います！！

## next.jsとは？

Reactをベースに作られたwebフレームワークです。これを使うことで、reactを使ったweb開発が、より便利にできるようになります！

また、next.jsはvercelという米国の企業が開発しており、完全にオープンソースなライブラリとしてGitHubに公開されています。

## なぜNext.jsが使われるか

そして、なぜnext.jsが選ばれるのか。ということについてなのですが、それは

・　サイトの初期表示が遅い

・　SEOにめっぽう弱い

・そのため、サービスによって向き不向きがある


などのデメリットが挙げられます。これらについて最初知らなかったので結構驚きですね。というかReactってSEOに弱かったんですね・・・

ではなぜnext.jsが使われるのかということなのですが、それは以下のメリットが挙げられます。

・サイトの初期表示が早い

・SEOが強い

・Node.jsなどサーバーJSも使える

・デプロイが簡単

が挙げられます！もちろん他のも色々と挙げられるのですが、主なものはこんな感じです。

## 個人的な推しポイント

次にnext.jsの主な機能と推しポイントを紹介していきます。

・　SSR/SSGが使える
やはり、next.jsを使う人はこの機能目当ての人も多いのではないでしょうか。SSRとはサーバーサイドレンダリングの略で、クライアント側で処理していたHTMLなどの処理をサーバー側でやろう！っていう話ですね。SSGはサーバーサイドジェネレーターの略で、サーバー側で先にHTMLファイルとして処理しておこう！とする機能です。この機能のおかげで、超高速でページ遷移ができます。もちろんデメリットはありますが、それは大規模開発などの時に気をつけるべきことなので、今は気にしなくて良いです。

・　ルーティングの自動生成
なんとpagesファイルの下にjsファイルを配置するだけでページを作れちゃうんです。もう感動ですね。reactだけでやっていた時はreact-router-domというライブラリを導入して、ちまちまとルーティングをしていたのですが、それからもう解放されます。

・CSSファイルの適用
Reactではcssを描くのにライブラリーを導入する必要があるのですが(知らなかった・・)、next.jsでは最初からサポートされています。環境構築という最初の鬼門を取り払ってくれることには感謝しかありませんね。

・APIルート
APIルートとはnext.jsでAPIを構築できる機能です。このおかげでバックエンドの処理をここで行ったり、APIと連携できたりします。また、apiルート以下でもJSで書くことができるので、JavaScriptだけで書かれたアプリケーションを作ることができるのです。JSファンにとっては鬼に金棒ですね

・デプロイとデータベースの連携が簡単
vercel社が出しているvercelを使えばデプロイが簡単にできます。また、データベースも簡単に作成できたりするので、データベースの管理も楽々です。

僕の推しポイントはこんな感じです。一言で言うと神ですね。


## 終わりに
はい。こんな感じでNext.jsについてまとめてみました。reactでwebアプリを作ってみるつもりだったのですが、next.jsで作ろうと決意するぐらいには恵まれた機能群です。これからもはやっていくと思うので、興味がある方は触ってみては？！

にしても就活を色々とやっているのですが、競技プログラミングを課題に課す企業が多いですね。プログラミングスクールはその指導もちゃんと行ったほうがいいと思うのは僕だけでしょうか・・・

ではまた別の記事で！！グッピーでした！
【Shopifyアプリ】ページを「nosh-ナッシュ」みたいな感じにする、日本製のShopifyアプリを見つけた話

# はじめに
Shopifyのコレクションページを「nosh-ナッシュ」みたいな感じにするShopifyアプリを見つけました。

使いやすくて結構凄いアプリだったので、今回の記事でご紹介します。

# nosh-ナッシュみたいな感じって何？
ナッシュは、ヘルシーな冷凍弁当を毎週お届けするミールキットみたいなものです。

https://nosh.jp/

このサービスの凄いところは、毎週のミールキットを選択する画面のUXです。

![6822f2b745e362ea9036ddcbb651c4d2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/2e6cca54-94a5-b573-7c8b-142b0ced6462.gif)


次々と「カートに追加」を行うことができるため、ユーザーはストレス無く次々と商品をカートに追加してしまいます。

売上の上昇が見込めるため、こちらの機能を実装したいという事業主さんは結構多いです。


![340e777e2f1e610df33736b772828605.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/50f9f6cd-1e00-3e2f-be6d-59590c0b1ced.gif)


上の方にあるタブから、商品の絞り込みが行えます。そのため、全ての商品をこちらの画面に表示しておき、ユーザーが商品を探す場合は、自分でタグの切り替えを行う形になります。

このような実装を行うと、カテゴリー画面や商品詳細画面が必要無くなります。

そうすると、画面遷移の数が減り、カートに追加の心理的障壁が下がるので、売上の向上が見込めます。




# アプリのインストール
ページを「nosh-ナッシュ」みたいにするアプリは、こちらのアプリです。

https://apps.shopify.com/ponpon-cart?from=qiita

コレクションページカート追加アプリ｜リテリア ぽんぽんカートというアプリで、コレクションページから商品をぽんぽんと追加できるようにする、という機能を実現できます。正直、機能が分かりにくいですね。

アプリをインストールすると、以下の管理画面に飛びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/80ae7d65-da10-b06f-6178-a808e3715908.png)

アプリの有効化を押すと、自動的にアプリが有効化されます。

こちらのアプリは、あくまでコレクションページに追加が行われるアプリなので、テーマの編集画面からコレクションページに移動しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/6724fb39-ce24-6cc2-58c9-ced4e026a966.png)

「アプリ」というセクションに、PonPonCartが追加されていれば、設定は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/63b6ea1d-ae05-53f0-5557-db90df0d193d.png)

実際に、サンプルストアから、アプリの動きを見てみましょう。

![3488bf0dd5da728cdbcc981332a3fc11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/878733/60bc70bc-240b-a966-a4fd-824f2568083c.gif)

このように、「nosh-ナッシュ」のような「カートに追加」を行うことができます。

また、上のタブから商品の絞り込みも行うことができるため、「nosh-ナッシュ」のようなUXを実現することが可能になっています。

カスタマイズ性の高く、カートの種類や商品カラムの列数等を変更することが可能になっている、非常に強力なアプリだと思います。

コレクションページを「nosh-ナッシュ」のようにしたいという要望があれば（あるかどうかは分かりませんが）導入してみるのもありでしょう。

# 終わりに
今回は、コレクションページを「nosh-ナッシュ」みたいな感じにする、日本製のShopifyアプリを見つけたのでご紹介しました。

その他にも良さげな記事があれば、記事を書いていこうと思います。
[py2rb] zip

# はじめに
移植やってます。
( from python 3.7 to ruby 2.7 )
# zip (Python)
```python
import numpy as np

x = np.array([1, 2, 3])
y = np.array([4, 5, 6])

for a, b in zip(x, y):
    print(a, b)

# output
1 4
2 5
3 6
```
何の変哲もないように思われますが、pythonとnumpyの親密さが伺い知れます。
# 失敗(Ruby)
```ruby
require 'numpy'

x = Numpy.array([1, 2, 3])
y = Numpy.array([4, 5, 6])

x.zip(y).each do |a, b|
  p [a, b]
end

# output
undefined method `zip' for array([1, 2, 3]):Numpy::NDArray (NoMethodError)
```
`PyCall`経由とはいえエラーになります。
# 成功(Ruby)
```ruby
require 'numpy'

x = Numpy.array([1, 2, 3])
y = Numpy.array([4, 5, 6])

x.to_a.zip(y.to_a).each do |a, b|
  p [a, b]
end
```
`to_a`を使用して、一旦rubyの配列に変換する必要がありました。
# 成功(numpy.column_stack)
```ruby
require 'numpy'

x = Numpy.array([1, 2, 3])
y = Numpy.array([4, 5, 6])

p Numpy.column_stack([x, y])

# output
array([[1, 4],
       [2, 5],       
       [3, 6]])
```
`numpy`の`stack関数`を使用して結合することも可能です。
# おまけ(Numo-NArray)
```ruby:numo-narray
require 'numo/narray'

x = Numo::NArray.cast([1, 2, 3])
y = Numo::NArray.cast([4, 5, 6])

x.to_a.zip(y.to_a).each do |a, b|
  p [a, b]
end
```
`numo-narray`でも変換が必要の様です。
# メモ
+ Python の zip を学習した
+ 百里を行く者は九十里を半ばとす
google home PCペアリング　ハマったところ　対処法

# google home PCペアリング　はまったところと対処法

基本的な話かもしれませんが、
ググっても見つからなかったので自分へのメモも兼ねて残します。

ペアリングまでは比較的簡単なのですが、
ペアリングの仕方でうまくいかない時がありました。

## １．やりたい事

PC（lets note)のスピーカーが酷くて、
外部スピーカーが欲しかった。

そこで「**google home**」さんいたじゃん！
ってなったので、これにbluetoothで繋げたい！


## ２．はまったところ
とりあえずbluetoothのペアリングまでは簡単でした。
こちら参照ください。

https://kogaranozakki.net/2019/04/03/google-home-skype-microphone-speaker/

これでペアリングは出来るんですが、なぜか私の場合は
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2095609/36caedb1-5b38-1e51-fe5b-4499af5600a2.png)

ここのその他のデバイスになっちゃったんですよね。（↑これは改善後のイメージ）

## ３．対処法
上記の絵のように**オーディオデバイス**として認識させる必要があります。
これにはスマホからgoogle homeへの設定が必要でした。

【スマホ】
**追記　スマホはGoogle Homeと同じWifiにいる必要あり**

①Google Homeアプリを起動（なければInstall）
②お使いのGoogle Homeを選択
③右上の「歯車」マークを選択
④デバイスの機能→音声
⑤ペア設定されたBluetoothデバイス
⑥ペア設定モードを有効にする

【PC】
⑥Bluetoothまたはその他のデバイス追加

## ４．トラベルシュート
どうしても「**その他のデバイス**」のままになる事がありました。
その時の対処法です。
少し面倒ですが簡単に言うとデバイス削除と再接続です。

【スマホ】
④まで進む
⑤ペア設定されたBluetoothデバイス
⑥接続済みのPCを削除

【PC】
・Bluetoothまたはその他のデバイス
・接続済みのgoogle homeを削除

３．の手順で再接続


以上となります！
UberEats風SPAチュートリアルの復習メモ：1章

https://www.techpit.jp/courses/138
Reactの基礎になれるためにこちらの教材をやってみました。
以下、要点確認用のメモです。

---
# 1章　要件定義

# 1-1　構成

- 店舗一覧（/restaurants)
    - レストランを一覧表示
    - レストラン1をクリックするとレストラン1の商品一覧ページ（/restaurant/1/foods）に遷移
- 商品一覧（/restaurants/{id}/foods
    - 販売してる商品を一覧表示
    - 商品をクリックすると仮注文のモーダルが表示される
- 仮注文モーダル
    - 数量の+-ボタン
    - 数量に応じて金額を計算して表示
    - 最初から購入数を選べるようにする（+-何回も押さなくて良いように）
- 注文確認画面
    - 仮注文した複数商品の合計金額+配送料を計算、表示
    - 注文確定のボタン

例外パターン

複数の店舗で仮注文しようとする可能性


解決策⇨別店舗で注文するかどうか確認するモーダルを表示する

- 店舗Aの仮注文がある状態でB店舗の商品を仮注文⇨モーダル表示
- 新規注文を承諾すると、店舗Aの仮注文した商品はキャンセルされる

---

前提

1. サーバーサイド処理は簡潔なものだけ
2. モデルの定義は最低限の動きにのみ対応
3. ページ遷移：React Router
4. ビュー：React（Rails側では作らない）
5. 例外処理：最低限

（実装しないもの）

- サーバーサイド
    - データを投入するAdmin画面(システム管理者用画面)
    - データごとのユニークな画像
    - テスト
    - ユーザー登録/ログインの処理
    - 本番デプロイ
- フロントエンド
    - エラーの場合の例外処理（エラーメッセージの表示）
    - テスト
    - HTML/CSS

必要なもの

- サーバーサイド（データを用意⇨返す）
    - [ ]  必要なデータのMigrationとModelの定義（Restaurant、Food）
    - [ ]  APIコントローラー（データ取得のため）
    - [ ]  API内で例外パターンと一致したらエラーを返す
- フロントエンド
    - [ ]  React Routerで画面遷移
    - [ ]  最低限のレイアウト
    

---

# 1-3　データ・モデル設計

基本データ

- Restaurant
    - [ ]  店舗名　name
    - [ ]  配送料　shipping_fee
    - [ ]  配送時間　shipping_time
- Food
    - [ ]  店舗ID　restaurant_id
    - [ ]  商品名　name
    - [ ]  価格　price
    - [ ]  説明　description
    

注文に関するデータ

- Order
    - [ ]  店舗ID　restaurant_id
    - [ ]  商品ID　food_id
    - [ ]  商品数　count
    - [ ]  状態　active
    - [ ]  注文ID　id
- NewOrder
    - [ ]  店舗ID　restaurant_id
    - [ ]  合計金額　total_price

---

# 1-4　フロントエンド設計

### Reactでよく推奨されるコンポーネントの種類分け

- Container Component
    - データをもつ
    - 親コンポーネントとして子コンポーネントにデータを渡す
    - ページごとのコンポーネント
- Presentational Component
    - 単に受け取ったデータを表示する
    - ボタン、モーダルなど子コンポーネント

子コンポーネントにデータを持たせてしまうと、複数ページで同じようなUIなのにデータが異なる場合でもデータが再利用出来なくて、結局コピペする羽目になる

子コンポーネントを再利用しやすくするためにも、データを持つのは親コンポーネントだけにする

### コンポーネント設計

- Parent (Container)
    - `containers/Restaurants.jsx`
    - `containers/Foods.jsx`
    - `containers/Orders.jsx`
- Child (Presentational)
    - `components/Buttons/HogeButton.jsx`
    - `components/Modals/FugaModal.jsx`
    - `components/Wrapper.jsx`
    
    複数種類ありうる子コンポーネントはcomponentsの１階層下に掘って配置するとわかりやすい
    

### API叩く関数

- `apis/restaurants.js`
- `apis/foods.js`
- `apis/orders.js`

＊関心はファイルごとに分散するのが一般的

API呼ぶやつもcomponentsとは別のファイルで管理する

### カプセル化（useReducer）

- `reducers/restaurants.js`
- `reducers/foods.js`
- `reducers/orders.js`

### APIのURL

- `urls/index.js`

urlを定数に格納してここで一元管理
【Git】.gitkeepで空ディレクトリのみGit管理したい

# はじめに

[こちら](https://qiita.com/ndxbn/items/f124d2b183b60cb074e2)の記事によると

>.gitkeepは、「デフォルトではファイルが存在しないけれど、ファイルが追加されたら、そのファイルを Git での管理対象にしたい」場合 に使います。
>.gitignore は、「デフォルトではファイルが存在しないし、そこに作られたファイルもバージョン管理したくない」場合 に使います。

とのことなので、空ディレクトリのみの管理であれば`.gitignore`でしたほうが良さそうですが、諸事事情によりメモ。


# 書き方

ex. `output/sample`をディレクトリのみ管理したい場合

```:ディレクトリ構成
.
├── .gitignore
└── output/
        └── sample/
                └── .gitkeep
```

```:.gitignore
!output/                    # outputディレクトリ配下は除かない!!
output/*                    # でもoutput階層のファイルは除く..
!output/sample/             # output/sampleディレクトリ配下は除かない!!
output/sample/*             # でもoutput/sample階層のファイルは除く..
!output/sample/.gitkeep     # でもoutput/sample階層の.gitkeepは除かない!!
```

冗長だけど仕方ないっぽい。
画面の向きを固定する方法

# 開発環境
Swift version 5.5.2
Xcode Version 13.2.1
Interface SwiftUI

# 問題
SwiftUIを使用しアプリを開発しているが、
画面を横向きに固定できず回転してしまう。

# 結論
<b>xcodeprojで修正する</b>
Xcode13だと効かないことがあるようですが、以下の手順全てを試したところ横向きのみに固定できました。
　
# 手順
1, Navigator areaのプロジェクト名をクリックし、.xcodeprojを開く。
2, TARGETS>`General`の`Device Orientation`で固定したい項目にチェックを入れる。

 |項目|内容|
 |-|-|
 |.portrait|通常|
 |.portraitUpsideDown|逆さ|
 |.landscapeLeft|左向き|
 |.landscapeRight|右向き|

 上記だけだと解決できなかったため以下の手順も試しました。

3, 手順2の`General`ではなく`Info`を開く。
4, `Supported interface orientations (iPhone)`という項目の不要なitemを削除する。
　どれが不要かはitemのvalueを確認してください。

<b>※`Supported interface orientations (iPhone)`以外にも`Supported interface orientations (iPad)`や`Supported interface orientations`などがあるため注意してください</b>

上記の内容で横向きのみの固定できました。
自分の場合はチェックする項目が足りていなかったため固定できませんでした。。。
少しでも皆様の参考になれば幸いです。

## 参考
[【Xcode/Swift】画面の回転を固定する方法を2パターン紹介〜Xcode13からDevice Orientationが効かなくなった?〜](https://ios-docs.dev/rotate/)