OmniAICreator/Qiita-1.07M huggingface dataset:
メモ〜jenkinsを用いたpython unittestの定期実行

今回のお題
-
今回は、jenkinsを用いてpythonのunittestを自動化していきます。

前回の続きです。

https://qiita.com/keishi04hrikzira/items/180611da1858a83aff4f

目次
-

- workspaceの追加
- ビルド内容の指定
- 実行タイミングの指定

workspaceの追加
-
まずは最初にworkspaceの追加を行います。

テストを手動で実行する場合、まずはターミナル上でテストファイルのディレクトリで移動すると思います。

jenkinsに作業を任せる場合もそれと同じで、まずは実行対象のテストのありかを教えてあげる必要があります。

まずはいつものようにジョブの新規作成を選択し、適当な名前をつけてください。

区分は`フリースタイルプロジェクト`で大丈夫です。

次に以下の画面で高度な設定を押してください。

[![Image from Gyazo](https://i.gyazo.com/1af58516a74995f7c35d0c47b9210995.png)](https://gyazo.com/1af58516a74995f7c35d0c47b9210995)

カスタムワークスペースを使用にチェックをつけて、テストコードの存在するディレクトリの絶対パスを入力します。

[![Image from Gyazo](https://i.gyazo.com/f85cee486b32bc305951a736039eb58b.png)](https://gyazo.com/f85cee486b32bc305951a736039eb58b)

これでworkspaceの追加が完了しました。

ビルド内容の指定
-

次にビルド内容の指定を行います。

今回やってほしい作業はシェル上で

```shell
% python3 xxxx.py
```
と入力することなので、そのように指示します。

`ビルド手順の追加` > `シェルの実行`と進み、テスト実行のためのコマンドを入力します。

[![Image from Gyazo](https://i.gyazo.com/14ecade8b6df2952d4bdc89347328fd7.png)](https://gyazo.com/14ecade8b6df2952d4bdc89347328fd7)

これでビルド手順の追加はOKです。

実行タイミングの指定
-
前回と全く同じなので省略します。

終わりに
-
これテストの自動化が行えるようになりました。

テスト以外にも色々と使えるそうなので、うまく使って楽をしたいですね。
【Azure Kinect】C#でBody Tracking SDK v1.1.0を使うための手順と隠されたトラップ

後程Markdownを習得したら、Qiitaへ移植予定

元記事
https://umehashi.hatenablog.com/entry/2021/10/25/154810?_ga=2.104253832.94080739.1636333188-1125909395.1595051620
vscodeでPHP開発環境作ってみた(日本語化・Git・PHP Intelephense)

久しぶりにPHP案件に復帰するので、せっかくなら新しいエディタで始めてみようと思い、vscodeでPHP開発環境を準備してみた。

## vscodeのインストール
https://code.visualstudio.com/
ここからダウンロード。ダウンロード完了したらファイルを開き、成り行きでインストール。

## 日本語化
へぼへぼエンジニアなので、英語が怖い。日本語化する。
### 日本語拡張機能の追加
左のメニューの一番下をクリックし、拡張機能の画面を開く。
「japanese」まで入力すると、日本語の拡張機能が一番上に表示されるので、Installをクリックする。
![日本語インストール.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/35cc0983-1e06-16db-c7dd-64c7c106f58a.png)
### 言語の切り替え
インストールが完了しただけだとまだ英語のままだ。
`ctrl`+`sift`+`P`を押すと上に入力欄が出るので、「display」と入力する。
「Configure Display Language」と表示されるので、`Enter`を押す。
![言語切り替え.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/d8651bde-6659-20f7-58a5-eb18be54e60c.png)
`en`と`ja`が表示されているので、`ja`を選択して`Enter`
![言語切り替え2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/17616af6-0793-d50f-76bf-263a0dc54662.png)
「設定を有効化するには再起動が必要」といったメッセージが表示されるので、「Restart」を選択する。
![許可メッセージ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/03844c68-5156-95aa-c022-b61cd209f9a0.png)
再起動完了、やっと読めるようになった。ありがてぇ。
![日本語化完了.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/d0f8786e-5440-e083-e39c-3be67236b11f.png)
## Gitを使う
何はともあれ、Gitを使う時代なのでGitでソース管理できるようにする。
### Gitのインストール
https://git-scm.com/
を開き、「Download for Windows」をクリック。
あとは成り行きでインストールする。
### Gitのパスを通す
gitのインストール先を確認する。デフォルトだと
`C:\Program Files\Git`
にインストールされる。
`C:\Program Files\Git\bin`
に`git.exe`があるので、ここにパスを通す。

Windowsマークの右側「ここに入力して検索」に「path」と入力。
「システム環境変数の変更」を選択する。
![システム環境変数の設定.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/62fc55dc-66f9-13c3-9e68-6a498069d6bb.png)
下の「環境変数」をクリックする。
![環境変数.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/b0999e19-74d8-0575-d217-200094b15042.png)
下の「システム環境変数」から「path」を選択し「編集」をクリックする。
![環境変数の編集.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/03105e45-a168-fbc5-3bd8-712523d7f691.png)
「新規」をクリックし、新規項目に`git.exe`が存在するパスを入力する
![環境変数の新規登録.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/eb00c303-4a84-90a0-4718-f3a1318b422b.png)
ここまで完了したら、「OK」を押していままで開いたウィンドウをすべて閉じる。
一旦vscodeを終了して、再度起動する。
### Gitのリポジトリを複製する
vscodeが再起動されると、「リポジトリの複製」が選択可能になる。
「リポジトリの複製」をクリックすると、リポジトリのURLが入力可能になるので、リポジトリのURLを入力する。
![githubから落とす.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/9b5803dc-805b-fe3a-1663-ca1ee95e7779.png)
ディレクトリの選択画面が表示されるので、保存先を選択する。
![保存先を指定.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/60069198-1b74-c3c8-e6d4-1fd3d691e625.png)
リポジトリからコードをclone後、「フォルダーを開く」でソースを開くことができる。
## PHPを使う準備をする
コード補完やコードジャンプは、PHP Intelephenseがよいらしい。
ので、インストール。例のごとく、左メニューの一番下から。
![php.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109315/aa1be18e-3623-4e3b-90b7-dc7ac7cf61c8.png)
さくっとインストールしておしまいなので、特記事項はなし。
ADFS からのアプリ認証移行が必要な理由

# はじめに
本記事では、企業や組織において業務で利用されている Active Directory Federation Service（以降、ADFS）を移行しなければならない背景のおさらいと、将来テクノロジーがさらに発展していく想定での提言をしていきます。
ADFS 移行のきっかけは、大きく分けて下記の 6 つがあります。

> ・データセンターの契約満了
> ・事業継続性
> ・キャッシュフローの問題
> ・サイバーセキュリティの脅威
> ・IT 予算、リソースの不足
> ・急増するアプリケーション需要への対応

この中でも、「急増するアプリケーション需要への対応」について取り上げます。

# 急増するアプリケーション需要への対応の背景

アプリケーション需要が急増した背景は、アプリケーションのオンライン化が進み、SaaS と呼ばれるクラウドアプリケーションの利用が多くなってきたことが挙げられます。そして、オンライン会議や電子化されたデータを扱う業務のため、毎日 2 つ 3 つのツールを従業員の方が使うことが当たり前になりました。さらに、昨今の状況から、自宅や遠隔地からリモートワークを行う必要性があります。この時、モバイルデバイスから社外ネットワークを通じてアプリケーション利用するシーンが確実に増えています。このような背景から、従来の利用シーンと比較して想定を超えるニーズが出てくるようになってきました。

![Blog20211108.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879870/4af7e1de-5f4e-3e20-6681-7694db21efca.jpeg)

# 利便性の確保

急増するアプリケーション需要への対応として、利便性が求めらるようになるのは言うまでもありません。従業員の方は、アプリケーションごとにバラバラの ID を使うことを望んでおらず、１つの ID でアプリケーションを使いたいと思うはずです。多くの企業において、Identity as a Service（以降、IDaaS）とよばれるクラウドサービスの導入によって、クラウド環境の ID の一元化が進んできました。IDaaS の例の 1 つに Azure Active Directory（以降、Azure AD） があります。Azure AD は Office 365 に組み込まれているため、既にご利用いただいているお客様が多くいらっしゃいます。すでに利用中の IDaaS が存在していれば、投資を抑えながら、アプリケーション認証基盤としての展開が可能です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879870/ded12ff1-96c3-0f4d-ce99-e5569db249c6.png)

# よくある課題と目指すべきゴール
ADFS からの移行を検討する段階で、よくある課題があります。プロジェクトを進める時に立ちはだかる 2 つの壁について紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879870/43a8dfa9-f341-3097-7fb2-062327f1b806.png)

* 1 つ目の壁: アプリケーションの認証をイントラネット内で完結させることが必要となっているため、Azure AD のようなクラウドサービス上で認証を行うことがポリシー上で許可されない

* 2 つ目の壁: アプリケーションへのアクセスを社給デバイスのみに制限したい。ADFS の証明書認証を使って実現しているため、容易に移行できない

上記は社内と社外にネットワーク境界を設けた防御設計に沿った、非常に強固な考え方です。しかし、最近では、様々な場所から多様なデバイスを利用できることが、従業員の生産性向上に寄与しています。そのため、既存の ADFS を含むオンプレミスのインフラ基盤では、技術・運用の両面で対応が難しくなってきました。

例えば、下記のようなニーズが挙げられます。
> ・社給デバイスではない個人所有の端末（BYOD）を使いたい。
> ・証明書が入った端末のみに制限するだけでなく、より動的な適用型アクセス制御を行いたい。
> ・クラウドのエンドポイント セキュリティ ソリューションと連携して、ID や端末が保護されている状態を条件にアプリケーションへのアクセスを許可したい。

このような新しいニーズに対しては、クラウドで予め実装されたソリューションを持っている Azure AD で素早く対応することが出来ます。
強調しておきたいのは、ADFS を使ったアクセス制御の考え方と本質は同じであるということです。安全なネットワーク、デバイスからアクセスされるべきというセキュリティの考え方に基づいて、実装をアップデートしていくことが ADFS 移行の目指すべきゴールであると言えるでしょう。

# まとめ
アプリケーションの観点から、ADFS からの移行が必要な理由を紹介しました。IDaaS によるアプリケーション認証の統合を推進していただけそうでしょうか。
これからアプリケーション認証を ADFS から移行しようとしている方の参考になれば幸いです。

次回の記事では、ADFS からアプリケーション認証移行を設計する前に知っておきたい事について掲載する予定です。
＊本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。
App Links の Android 12 うんぬん関連メモ

軽くドキュメントを読んだ際のメモです。

# ドキュメントに関して
- おいらが読んだ時点での[ドキュメント](https://developer.android.com/training/app-links)に関して言えば、和文と英文で文章がまったく異なり、リンクのタイプ分類のような基本的なレベルで異なることが書かれているなど、結構微妙な感じだった、、、。英語側のほうがまともだとは思うのだが、web links の scheme が HTTP, App Links 側が HTTP and HTTPS であると書かれているけど、実際は両方とも https を含む動作をするので、何を信じでいいのかわからない、、、。

# たぶんこういうことなんだろーなということ
- Android 12 から云々という話は、端末OSの話であり、ビルド時の compileSdk や targetSdk とは無関係だと思われ。
- http, https 以外は、今まで通りの deep link.
- http, https は、
  - 端末OSが Android 12 未満の場合はダイアログで選択。
  - 端末OSが Android 12 以降の場合は verified であればアプリ、そうでなければブラウザに問答無用で飛ぶ。
- つまり、端末OSが Android 12 以降の端末上では、verified でない http/https のリンクからのアプリ起動は絶対にできない。

# Deep links を用いていた既存のアプリをどうすべきか？
- App links に対応しないと Andorid 12 以降の端末上で deep link を踏んでもアプリに飛べないので困る。
- ユーザーに、端末のOS設定で登録してもらえば対応できるが、UX的に最悪である。
- 結論 → App links に対応する以外の道はない。

# その他
- adb から `adb shell am start -W -a android.intent.action.VIEW -d "https://example.com/foo" com.example.debug` 的にやる場合は、無条件で verified 扱いになるっぽい。
NEMのノードをアップグレードする方法をまとめてみました。

The English text of this article is below.
https://qiita.com/Solve/items/e190e7c7b530a87392d0

NEMのノードを最新バージョン（v0.6.98 Harlock）にアップグレードしましたので、その方法をまとめてみました。
rootにUPしている場合を記しますので、sudoを付けるなど、適宜変更してください。

##1．ノードを停止します

```
systemctl stop nem-nis.service
systemctl stop nem-servant.service
```

:::note info
上記はsystemdに登録している場合です。始動や停止の方法はどのような方法でも構いません。なお、自動起動の方法を追記しました。
:::

##2．バックアップします

フォルダnemServerの名前を変更します（バックアップしたことになる）。
フォルダnemServerは後で新しく作成されます。

```
mv nemServer nemServer_backup
```

nemフォルダのバックアップを取ります（数分かかる）。

```
cp -rpi nem/ nem_backup/
```

##3．新バージョンのダウンロード

```
wget https://github.com/NemProject/nis/releases/download/v0.6.98/nis-0.6.98.tgz

必要なら、servantもダウンロードします。
wget http://bob.nem.ninja/servant_0_0_4.zip
```

##4．解凍します

```
tar xzf nis-0.6.98.tgz
unzip -q servant_0_0_4.zip
```

##5．それらをnemServerという1つのフォルダにまとめます

```
mv servant package
mv package nemServer
chmod -R g-w nemServer
```

##6．下記の4つのファイルをバックアップからnemServerへコピーします

```
cp -i nemServer_backup/nis/config.properties nemServer/nis
cp -i nemServer_backup/servant/config.properties nemServer/servant

cp -i nemServer_backup/nix.runNis.sh nemServer
cp -i nemServer_backup/servant/startservant.sh nemServer/servant
```

##7．実行権限を付けておきます

```
chmod u+x nemServer/nix.runNis.sh
chmod u+x nemServer/servant/startservant.sh
```

##8．起動します

```
systemctl daemon-reload

systemctl enable nem-nis.service
systemctl enable nem-servant.service

systemctl start nem-nis.service
systemctl start nem-servant.service
```

##9．2重起動していないか確認します

```
pgrep -fa org.nem
```

##10．最新バージョンになっているか、起動の最終確認をします

下記リンクで、heightが増えているなら起動に成功しています！
http://(IPアドレス):7890/chain/height

5，6時間後に同期が完了します。
下記リンクで、バージョンが"version":"0.6.98"となっていればUpgrade成功です。
http://(IPアドレス):7890/node/info

その後、しばらくして、NEMのノードリストが更新されます。
https://nemnodes.org/nodes/

以上です。

この方法でアップグレードできましたので、まとめておきました。

##追記：自動起動の設定は次の通りです

《viの使い方》
esc・・・コマンドモード
i・・・挿入モード
:wq・・・書き込み終了

（１）NISサーバーの自動起動の設定

```
vi /etc/systemd/system/nem-nis.service
```
下記をi（挿入モード）で張り付け、:wqで書き込みします。

↓↓↓↓↓↓↓↓↓↓
[Unit]
Description = NEM NIS Server
After = network.target

[Service]
WorkingDirectory = /root/nemServer
ExecStart = /root/nemServer/nix.runNis.sh
Restart = always

[Install]
WantedBy = multi-user.target
↑↑↑↑↑↑↑↑↑↑



:wq

（２）Servantサーバーの自動起動の設定

```
vi /etc/systemd/system/nem-servant.service
```

下記をi（挿入モード）で張り付け、:wqで書き込みします。

↓↓↓↓↓↓↓↓↓↓
[Unit]
Description = NEM Servant program
After = network.target nem-nis.target

[Service]
WorkingDirectory = /root/nemServer/servant
ExecStart = /root/nemServer/servant/startservant.sh
Restart = always

[Install]
WantedBy = multi-user.target
↑↑↑↑↑↑↑↑↑↑

:wq

（３）それから、NISサーバーとServantサーバーをsystemdに登録します

```
systemctl daemon-reload
systemctl enable nem-nis.service
systemctl enable nem-servant.service
```
MacのローカルディレクトリをS3にcronでバックアップ

# 概要

ふと、MacのローカルファイルをS3にバックアップしようと思ったので。

TimeMachineも併用しているけど、S3にバックアップする利点として以下がある

- インターネット経由でバックアップできる
    - TimeMachineに接続できない環境の時にもバックアップできる
- 作成されてから期間が経過したファイルを低価格のストレージに移行したり、アーカイブできる
- `aws s3 sync` を使うことで簡単にローカル・リモートが同期できる

aws-cliが使える環境であればすごく簡単にできる。

# 今回やるもの

- MacにあるローカルディレクトリをS3にバックアップする
- `aws-cli` を使ってS3と同期する
- `cron` を使って定期的に同期を行う
- S3のライフサイクル設定などファイル同期後の諸々は書きません

# 前提

- Macでの動作だけ確認
- `aws-cli` が実行可能な状況にしておく
- S3にバケットを作成しておく
- S3にアクセスするIAMユーザまたはロールが `aws-cli` にセットされている状態にしておく　

# 手順

## shellの作成

s3にバックアップする処理をシェルを作成

```
vim ~/backup-to-s3.sh
```

```zsh
#!/bin/zsh -l

// ~/Downloadsフォルダを同期する例
// 配下のディレクトリも再帰的にすべて同期してくれる
aws s3 sync ~/Downloads s3://[バケット名]/Downloads --profile=[aws-cliに設定したprofile名]

```

```
chmod 755 ~/backup-to-s3.sh
```

## cronの設定

```
crontab -e
```


```
// 毎時30分に実行する例
30 * * * * /bin/zsh -l -c '/Users/xxxxxxxxx/backup-to-s3.sh > /Users/xxxxxxxx/backup-to-s3.log 2>&1'
```


## cronでディレクトリアクセスできるようにする

Macの場合、デフォルトだとcron実行時にディレクトリアクセスが制限され、ファイル読み込みができない。

以下の手順でcron実行時のファイルアクセスを許可する必要がある


システム環境設定 -> セキュリティとプライバシー -> プライバシー -> フルディスクアクセス を開く

左下の鍵マークをクリックし、鍵を解除

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60056/869c54bb-64ca-b0c8-a563-1fea3549e9c5.png)

`+` ボタンを押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60056/a031d6c4-d289-c9ab-5ab0-54c4d34c721e.png)

Finderが開くので、ここで `Command + Shift + G` を押す
フォルダの場所を入力　で `/usr/sbin/cron` を入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60056/68aca4da-8b96-f2b7-9509-b39c0ed851db.png)

`移動` を選択 -> `cron` を選択 -> `開く` を選択

`cron` が出てくるのでチェック状態にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60056/e8c02581-1592-19ae-bfb4-6fa2f5ebea56.png)

左下の鍵をクリックして鍵をかけた状態にする

これでOK。


# 試す

これで毎時30分になったタイミングでcronが実行され、指定したディレクトリ（今回の例だと `~/Downloads`） をS3に同期してくれる。
初回実行時は存在するすべてのファイルがアップロードされ、２回目以降は差分更新される。
メモ〜jenkinsの使い方

今回のお題
-
今回はjenkinsという自動化ツールを取り上げます。

現在pythonのunittestを学習中なのですが、そこでjenkinsを用いたテスト自動化の話になっているので、自分用のメモとして、という意図です。

なお、本記事ではjenkins自体の導入やアカウントの作成については扱いませんのでご了承ください。

管理画面の見方
-

[![Image from Gyazo](https://i.gyazo.com/ef6a17cf2ea2db2861fab3a1e415d7aa.png)](https://gyazo.com/ef6a17cf2ea2db2861fab3a1e415d7aa)

上記が管理画面です。

`ジョブ`というのが作成したタスクであり、`ビルド履歴`が実際に実行されたタスクになります。

また、タスクは実行タイミングを指定して定期実行するのが基本になりますが、手動で実行することも可能です。

まずは一旦練習がてらに手動で実行してみようと思います（定期実行も後半に扱います）。

ジョブの作成
-
上記の管理画面で`新規ジョブの作成`をクリック（以下の画面に遷移します）。

[![Image from Gyazo](https://i.gyazo.com/f8f55ff7a9c113b23855a448cb5dd4fc.png)](https://gyazo.com/f8f55ff7a9c113b23855a448cb5dd4fc)

ジョブ名を適当に入力し（今回はテスト１とします）、`フリースタイル・プロジェクトのビルドをクリック`（以下の画面に進みます）。

[![Image from Gyazo](https://i.gyazo.com/84c1edfc25a4ccd840116562d71e540a.png)](https://gyazo.com/84c1edfc25a4ccd840116562d71e540a)

[![Image from Gyazo](https://i.gyazo.com/6f14af6af4435e31e79f38d2b0dc17cf.png)](https://gyazo.com/6f14af6af4435e31e79f38d2b0dc17cf)

写真２枚目の`ビルド手順の追加`の部分が実行させたい内容になります。

クリックすると以下の画面になるので、適宜項目を選択します。

[![Image from Gyazo](https://i.gyazo.com/caf86456cd23772d091aa19748f717de.png)](https://gyazo.com/caf86456cd23772d091aa19748f717de)

今回はテストとしてプロジェクト実行時の現在時刻を入力させるので、一旦は`シェルの実行`を選択します。

[![Image from Gyazo](https://i.gyazo.com/7d078e32dee88c152b93c15dc4f17a4e.png)](https://gyazo.com/7d078e32dee88c152b93c15dc4f17a4e)

実行内容として`date >> datelog_jenkins`と入力し保存します。

[![Image from Gyazo](https://i.gyazo.com/d4817a90324f8f5f52cf186430c11a5a.png)](https://gyazo.com/d4817a90324f8f5f52cf186430c11a5a)

作成したプロジェクトの個別ページに遷移します。

今回は実行タイミングを指定していないので、手動で実行してテストします。

ページの半ばにある`ビルド実行`をクリックしてください。

`ビルド履歴`をクリックすると上記の画面が表示されます（今回は2回実行しました）。

[![Image from Gyazo](https://i.gyazo.com/972ed3655b920aa3ab1b9fee6eee0390.png)](https://gyazo.com/972ed3655b920aa3ab1b9fee6eee0390)

履歴をクリックすると以下の画面になります。

[![Image from Gyazo](https://i.gyazo.com/62d014ad23f33ebba8e71fcaf4d60ebb.png)](https://gyazo.com/62d014ad23f33ebba8e71fcaf4d60ebb)

コンソール出力をクリックしてください。

[![Image from Gyazo](https://i.gyazo.com/5c0786b82922734af8048439b0102d39.png)](https://gyazo.com/5c0786b82922734af8048439b0102d39)

上記のように実行日時、出力先、出力内容（＋以下）が表示されます。

`date`の中身もターミナルで確認できました。

[![Image from Gyazo](https://i.gyazo.com/3e9578a94fa5bd9d0c0e32348fc2588d.png)](https://gyazo.com/3e9578a94fa5bd9d0c0e32348fc2588d)

定期実行の設定
-
手動で動いていることが確認できたので、いよいよ定期実行の設定を行います。

プロジェクトの管理画面から`設定`を選択します。

以下のようにプロジェクト作成の時と同じ画面に移るので、`ビルドトリガ`の`定期的に実行`を選択します。

[![Image from Gyazo](https://i.gyazo.com/16c7d1cb94241bc220f2d5b88fd1d950.png)](https://gyazo.com/16c7d1cb94241bc220f2d5b88fd1d950)

スケジュール入力欄が表示されます。

ここにはプロジェクトの実行タイミングを`分 時 日 月 曜日`のフォーマットで入力します(ワイルドカードは`*`曜日は`日曜日=0`~`土曜日=6`)。

```shell:実行スケジュールの入力例
# 毎年11月7日の午前6時15分に実行
15 6 7 11 *
# 毎分実行
* * * * *
```

終わりに
-
以上でjenkinsの使い方を終わります。

次回はテストを自動化できるようにしていきます。
Juliaでのabstract typeの使い方

Juliaでは抽象型(Abstract type)というものがあり、これを使うとオブジェクト指向プログラミングでのクラスに似た感じのコーディングができます。具体的にはc++の抽象クラスでの純粋仮想関数みたいになります。

# バージョン
Julia 1.6.2

# Abstract type
抽象型(Abstract type)を使うには例えば、

```julia
module Mysupermodule
    export Mysuperstruct
    abstract type Mysuperstruct end

    function add(A::T,B::T) where T <: Mysuperstruct
        error("add is not implemented for $(typeof(A))")
        return
    end
end
```
のようなmoduleを作成します。ここで、```Mysuperstruct```には```add```という関数が定義されていますが、これが呼び出されるとerrorで落ちるようにしておきます。

次に、このtypeをsuper typeにもつtypeを

```julia
module Mymodule
    import ..Mysupermodule:Mysuperstruct,add

    struct Mystruct <: Mysuperstruct
        a::Float64
    end

    function add(A::T,B::T) where T <: Mystruct 
        return Mystruct(A.a+B.a)
    end
end
```
と定義します。このようにしておくと、


```julia

module Testmodule
    import ..Mysupermodule:Mysuperstruct,add
    import ..Mymodule:Mystruct
    export test

    function test()
        A = Mystruct(2.0)
        B = Mystruct(10.0)

        C = add(A,B)
        println(C.a)

    end

end

using .Testmodule
test()
```
とした時に、```Mystruct```で定義されている```add```が呼び出されます。ここで、```import```しているのが```Mysupermodule```の```add```であることに注意してください。```Mystruct```で動作する```add```は```Testmodule```から呼び出していません。つまり、```Mysupermodule```の中に```add```が追加されています。```Mysupermodule```でできることが増えているわけですね。

もし、```add```が定義されていないモジュールがあったとすると、

```julia
module Hismodule
    import ..Mysupermodule:Mysuperstruct,add

    struct Hisstruct <: Mysuperstruct
        a::Float64
    end

end
```

```julia
module Testmodule
    import ..Mysupermodule:Mysuperstruct,add
    import ..Mymodule:Mystruct
    import ..Hismodule:Hisstruct
    export test

    function test()
        A = Mystruct(2.0)
        B = Mystruct(10.0)

        C = add(A,B)
        println(C.a)

        A = Hisstruct(2.0)
        B = Hisstruct(10.0)

        C = add(A,B)
        println(C.a)
    end

end
```
を実行した結果は

```
12.0
ERROR: LoadError: add is not implemented for Main.Hismodule.Hisstruct
```
となり、addが実装されていない方はエラーで落ちます。

これは、C++での抽象クラスにvirtualを使って定義する「純粋仮想関数」と似た感じです。もう少し似せるならば、

```julia
module Mymodule
    import ..Mysupermodule:Mysuperstruct,add

    struct Mystruct <: Mysuperstruct
        a::Float64
    end

    add() = nothing

end
```
とすると、

```
ERROR: LoadError: MethodError: no method matching add(::Main.Hismodule.Hisstruct, ::Main.Hismodule.Hisstruct)
```
となります。どちらがいいかはお好みです。
ここではimportを使って書いていますが、usingを使っても同様の結果になるようです。
PHPで /tmp のファイルが見つからない

PHPでデプロイ時にも削除されないように `/tmp` にキャッシュファイルを作成したが、ファイルが存在するのに`file_exists()` が `false` になったり、PHPからプロセス起動しての `ls` コマンド実行でも "No such file or directory" になり、ドハマリした。
ファイルの存在はもちろんファイル権限や状態など確認しまくっても、既存のファイルとPHP内で取得してきたファイルに全く違いがない。謎すぎた。

PHPのプロセスごとにバーチャル `/tmp` が使用されているのが原因だった。。。

https://stackoverflow.com/questions/21615786/content-of-tmp-is-not-visible-from-php-fpm-when-using-systemd

知っていればなんてこと無かったことだが、数時間を無駄にしてしまった。

追記：
そもそも、`/tmp`ではなく、キャッシュならば`/var/cache`を使用すべきか。
Linuxディストリビューションによっても異なるが、例えばCentOS7では`/tmp`の内容はシステム再起動時や一定期間後に削除されるので、一時的な作業中・処理中にしか使用しないものをちょっと置いておくだけの場所としてのみ使うべきということか。
APIや機能を50あるクライアントに正しく伝えるコツ

こんにちは～。

50もあるクライアントと日々向き合い、鬼のように多いプラットフォーム機能に関して毎日えっさほいさとFAQしたり、どうやったら要望を満たせる機能を提案できるか、日々研究を重ねております。
DMMPF（[たこちー](https://qiita.com/aoichan/items/9dec33060d0a6e8cc237)）のhayashiです。

今回は、私たちのチームの重要ミッションである、DMMの全クライアントに正しくPFの機能を伝えるための工夫としてやっている日々の施策をご紹介します:sunny:

## 前提
* DMMはすごい事業数がある（50くらい）
* プラットフォームのチームも20くらいある。#大変
* そのチームごとに機能もたくさんある。（数えたことはありません…）

各クライアントが作りたい機能やサービスに対して、PFのAPIや機能やインフラ環境を正しく選定して、伝達する仕事を行っています。

そのために、 **どの機能やAPIが最適で、どうやったら使えるか、を正しく手ほどきする必要** がある。
今回の記事では、それを実現するために日々私たちがやっている施策をご紹介したいと思います。

## 大小の問い合わせに対応し、そこから学ぶ
* 問い合わせの解決はチームメンバーに偏りなくやる
* 問い合わせの大小で解決までの手段を変更する
* 質問に対しては事業のナレッジをとにかく漁る
* 理解できたことは、チームにFBする（学習）

PFでは私たちのチームだけでも月間60件ほどの質問や相談があります。
中には秒で解決できることも、会議を何度も重ねて解決に促すものも様々です。
その対応にはチーム5名のメンバーを、バランスよく問い合わせに対応する工夫をしてます。
誰かに偏ると、結果回答できるスキルや知見が偏ってしまうので、苦手な分野でもできるだけ偏りなくアサインをすることを心掛けてます。
また、分かったことはチームにFBするようにして、自分だけの知識にせずそれを与える環境にしています。
結果、誰に相談がきても正確かつスピードをもって伝達できるようにしています。

## 問い合わせのボリュームからナレッジ化する。
* ナレッジ化すべきもの質問にはフラグをつける
* 似たような質問はFAQ式ですぐにナレッジ化する

これは当たり前ではありますが、常設運用にするととても価値がでます。
ナレッジを作るのはかなり時間がかかりますが、FAQ式（一問一答式）でアーカイブする程度であれば、10分程度で終わりかつ量産されるので、困ったときに引き出せるようにしています。

## PFの機能やAPIを正しく覚える
* 正しさとは仕様の理解だけではなく、変更の時系列も理解する
    * 過去のパラメータの仕様が変わったこと
    * 新しくできたパラメータの背景や用途を知る
* APIの用途以外に制約を知る
* APIの最適な利用ユースケースを知る
* API仕様書をチームで読む

これも当たり前ではありますが、重要なのは小さい変化でもキャッチアップしておくこと。
またユースケースを知ることで、利用できても最適性がない使い方を提案しないように、提供側の背景を知っておくことを大切にしています。
さらに新しく参画したメンバーには、API仕様書を読み合わせることを行い、用途やデータの形やAPIごとのつながりをイメージできる学習施策を行っています。

## APIナレッジは最新化する
* プロダクト（専門）チーム以外でも必要に応じて更新をかける
    * 補足資料とのつながりが必要であれば補記する
    * 言い回しによって読み手が混乱しそうであれば表現を変える
* 管掌が変わるものはすぐに新しい管理元に移管をする


## （最後に）機能やAPIに対して不足があると気づけば改修の提案を行う
どれだけAPIや機能があっても、多数を組み合わせないと使えなかったり、クライアントの要求に対する再現性がないものを提供し続ければそれは意味のないものになります。
汎用性を意識することも重要ですが、結果的に利用シーンにミスマッチな構成になっている場合には、カラムの追加を希望したり、API利用の複雑性を避けるためにアプリケーション化して提供するなどの解決方法を提案して、改修まで進めるようにしています。

## 今後やりたい施策
* ナレッジの可読性を高める
* ナレッジを1つのツールに集約する　など

そもそもクライアントが自己解決できるリファレンス環境にできないかな～と試行錯誤中です。

## ご拝読ありがとうございました！
クライアントに対して正しく機能を伝達するには、こういった施策をルーティーン化し長期的かつ形骸化をしないように続けていくことが大切だと感じています。

施策の中には、コストを下げるための自動化の工夫も実践しているので、
興味がある方は以下もご参考くださいませ。

## Appendix

* [Slack Workflow Builderを用いた社内アンケートのとり方](https://qiita.com/toru-kadowaki-dmm/items/8b87a4b0c375d5c44e81
)
* [業務効率化のためのSlack活用術 ～他事業部コンサル編～](https://inside.dmm.com/entry/2020/01/06/tako-operational-efficiency)
pytestのmock

# フォルダ構成

```:tree
.
├── config.yml
├── main.py
├── src
│   ├── __init__.py
│   └── my_module.py
└── tests
    ├── __init__.py
    └── unit
        ├── __init__.py
        └── test_handler.py
```

# サンプルコード

```Python:main.py
import os
import src.my_module as my_module

def get_config() -> dict:
    cd = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(cd, 'config.yml')
    with open(path, encoding="utf-8") as f:
        config = yaml.safe_load(f)
    return config

def main():
    # *1
    if os.path.isfile('./config.yml'):
        print('ファイルが存在します')
    else:
        print('ファイルが存在しません')

    # *2
    config = get_config()

    # *3
    return my_module.get_sample(config)

if __name__ == '__main__':
    main()
```

```Python:tests/unit/test_handler.py
import pytest
import main

def test_response_ok(mocker):
    # *1) os.path.isfile をモック化する(常にFalse)
    mocker.patch('main.os.path.isfile', return_value=False)

    # *2) 自作関数のモック化
    mocker.patch('main.get_config', return_value={})

    # *3) 自作ライブラリのモック化
    mocker.patch('main.my_module.get_sample', return_value={'status': '200'})

    response = main.main()
    assert response['status'] == '200'

```

*1 はmain.pyでの`os.path.isfile()`の結果を固定
*2 はmain.pyでの`get_config()`の結果を固定
*3 はmain.pyでの`my_module.get_sample()`の結果を固定

# 参考
[pytest でモックを使う方法](https://webbibouroku.com/Blog/Article/pytest-mock)
[pytest で単体テストの方法まとめ](https://qiita.com/waterada/items/6143d80896eb9d89bf2f)
良く使うWebサービスをまとめみた

※タイトルを修正しました

# 初投稿、ということで。。。
Qiitaに初投稿、ということで
最近良く使うWebサービスをまとめた記事を書いてた


## Qiita
* 概要
    * 当サイト

## Airtable
* サイトURL：[Airtable](https://airtable.com/)
* 概要
    * UIがエクセルベースの簡易DBサービス
    * REST形式のWebAPIが用意されているのでアプリ連携も容易


## STUDIO
* サイトURL：[STUDIO Design](https://studio.design/ja)
* 概要
    * ウェブサイトをノーコードでデザイン可能なウェブサービス
    * モックアップ、静的サイトの制作なら無料版で十分
        * CMS機能を利用したい、などの場合は要有料化
C# ソースジェネレータで生成したコードを含むアセンブリに対するcoverletの挙動

- ソースジェネレータで作成した、ソースコードを含むアセンブリをcoverletでカバレッジを取ろうとするとカバレッジが取れなく、ログを確認すると下記エラーが発生する。

```
[アセンブリ名], pdb without local source files [ソースコードのパス]
```
- 暫定的だが、ソースジェネレータでソースコード追加時に拡張子を.g.csとすることでこの問題を回避できる。

```
 Context.AddSource("hoge.g.cs","");
```
- 参照　https://github.com/coverlet-coverage/coverlet/issues/1084
【JavaScript】反復処理①　ループ文


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/b4e9b0432850000a3a2c

#目的

* 反復処理についての理解を深める

#本題
###1.ループ文

####for文

````基本構文.
for (初期化式; 条件式; 変化式){
  実行する文1;
  実行する文2;
  ...
}
`````

Javaと一緒？？

参照

https://www.javadrive.jp/javascript/for/index2.html

````js
// ①初期値を設定
// ②条件式　→　どうなったらループ抜ける？
// ③変化式 →　1ループごとにどうやって値が変化するか
for(let i = 0; i < 10; i = i + 1){
  // 0から9まで出力される
  console.log(i);
}
`````


####while文

```基本構文.
while (条件式){
  実行する文1;
  実行する文2;
  ...
}
`````

参照

https://www.javadrive.jp/javascript/for/index6.html

```js
// （）内にループを継続する条件を書く
// 例1
while(false){
  // 出力されない
  console.log("Hi!")
}
// 例②
// 初期化
let i = 0;
// 条件式
while(i < 10){
  console.log(i);
  // 変化式(省略形)
  i++;
}
````

###2.ループ文とブロックスコープ

####例1

基本構造

````js
// ループ分を定義
for(let i = 0; i < 5; i++) {
  const j = i * 2
  // 2,4,6,8と出力される
  console.log(j)
}
// constは再代入も再宣言もブロックスコープが1ループ毎に切り替わっていないと何度も呼び出されてエラーになるはず
// しかし、そうならないのは1ループ毎にブロックスコープが切り替わっているから
`````

####例2

setTimeoutを用いた場合

````js
// ループ分を定義
for(let i = 0; i < 5; i++) {
  const j = i * 2
  // ２秒後に出力される
  setTimeout(function(){
    console.log(j)
  }, 2000)
}
````

上記例の変数定義をvarを用いたらどうなるのか

````js
// ループ分を定義
for(let i = 0; i < 5; i++) {
  var j = i * 2
  setTimeout(function(){
    console.log(j)
  }, 2000)
}
// 8が5回出力される
// varはブロックスコープを透過するのでループの外で定義しているのと変わりないから
// 下記でも同じ結果

var b;
for(let a = 0; a < 5; a++) {
　 b = a * 2
  setTimeout(function(){
    console.log(j)
  }, 2000)
}
`````

###3.ループ文と配列

####例1

for文で配列を1つずつ出力するには

```js
// 配列を定義
const arry = [1, 2, 3, 4, 5];

// for文を使用
// arry.lengthで配列の要素数を表す => 5こ
for(i = 0; i < arry.length; i++){
  // arryの[i]番目を出力する(1,2,....)
  console.log(arry[i]);
}
````

####例2

while文だとどのように記述するか

```js
// 配列を定義
const arry = [1, 2, 3, 4, 5];

// while文を使用
// 自分の回答
// let i = 0;

while(i < arry.length){
  console.log(arry[i]);
  i++;
}

// vもiも初期値0
let v, i = 0;
// 後方インクリメントなのでiに値が渡ってきたら+1する
// 0番目の値は1 v = 1で1が出力される
// 値がtrueであればループ継続
while(v = arry[i++]){
  // arry[5]は6だが配列表記にないので、undefined = falseとなるのでループから抜け出せる
  console.log(v);
}
`````



今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
* [Let'sプログラミング JavaScript入門](https://www.javadrive.jp/javascript/)
C#：繰り返し処理

## while文

- ifと同じように真偽値の条件を使って繰り返しを行う。
   - while(条件となる物){繰り返す処理}
   - 繰り返す処理の中ではfalseになるようにする。インクリメント、デクリメントなど

    ```csharp
    //[while文]
    
    int max = 2;
    int total = 0;
    int count = 0;
    
    while ( count <= max)
    {
    	  total += count++; //totalに足した後、countに1を足す。
    		//total += ++count; //countに1を足した後、totalに足す。 //6になる
    }
    
    Message("合計は、" + total); //3
```

## for文
- while文をまとめたもの
    - for( 初期処理; 条件となるもの; 繰り返し後の処理){処理内容}
    - 条件となるものがfalseなら処理を抜ける。        
    
    ```csharp
    //[for文]
    int max = 100;
    int total = 0;
    for(int i = 1; i <= max; i++)
    {
        total += i;
    }
    Debug.Log(max + "までの合計：" + total);
    ```
【Project Euler】Problem 70: アナグラムのファイ関数

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題：アナグラムになるファイ関数の最小値

原文 [Problem 70:Totient permutation](https://projecteuler.net/problem=70)

**問題の要約：　$1<n<10^7$、$φ(n)$が$n$のアナグラムになるもので $n/φ(n)$が最小になる$n$を求めよ**

ここでいうアナグラムとは元の数字を並べ替えて同じになるもので、例として$φ(87109)=79180$があげられています。

これを素直にインプリすると、以下のようになりますがPythonでは約20分かかってしまいました。

```python
from sympy.ntheory import totient

def isPermSame(n1,n2):
  return sorted(str(n1)) == sorted(str(n2))

npmin, npminN = 99999, 0
for n in range(2,10**7):
  phi = totient(n)
  if isPermSame(n, phi):
    np = n/phi
    if np < npmin:
      npmin, npminN = np, n
print(f"n = {npminN}, n/phi = {npmin}")
```
そこで[前回](https://qiita.com/masa0599/items/0fd96fadf1dc5c09abf2)のように ファイ関数の定義に戻ると$n/φ(n)$は、

$\displaystyle n/φ(n) = \frac{p_1}{p_1-1}\*\frac{p_2}{p_2-1}\*...\*\frac{p_k}{p_k-1}$</br>

なのでなるべく小さくするには前回と逆で、

* なるべく大きな素因数を選ぶ
* 素因数の数は少ないほど良い。ただし素数のように素因数が１つの時は$φ(n)=n-1$となりアナグラムにならないので、素因数の数が2つの物がが候補となる。

従ってアルゴリズムは以下のようになります。

* $\sqrt 10^7$の前後ある幅の素数をリストする。
* そこから2つの組み合わせを選んで$φ(n)$がアナグラムかチェックして$n/φ(n)$が最小となる$n$を探す

これをインプリしたコードです。2つの素数は$\sqrt 10^7$が約3162なので[2000,4000]で選びました。実行時間は1秒未満です。

```python
import itertools
from sympy import primerange

N = 10**7
pl = list(primerange(2000,4000))
npmin, npminN = 99999, 0
for (p1,p2) in itertools.combinations(pl,2):
  if p1*p2 > N: continue
  n, phi = p1*p2, (p1-1)*(p2-1)
  if isPermSame(n, phi):
    np = n/phi
    #print(p1, p2, n, phi, n/phi)
    if np < npmin:
      npmin, npminN = np, n
print(f"n = {npminN}, n/phi = {npmin}")
```
NoMethodError: undefined method `host' for #<Rails::Application::Configuration の対処法

docker-compose run app rails db:create　を実行したら以下のエラーが発生しました。

```
$ docker-compose run app rails db:create

Starting ecs_db_1 ... done
Creating ecs_app_run ... done
rails aborted!
NoMethodError: undefined method `host' for #<Rails::Application::Configuration
Did you mean?  hosts
```


#原因
config/environments/development.rb にて編集した箇所が原因でした。

```config/environments/development.rb
config.host.clear 
```


エラー文の通り hosts と書かないといけないところが host となっております。


#対処策
config/environments/development.rb を以下のように修正します。

```config/environments/development.rb 
config.hosts.clear
```

解決です。

#雑感
ただ、最初どのファイルのhost を指しているのかわからなかったのですが、自分が直近で編集したファイルを疑ったら該当箇所がわかりました。
自戒なのですが、常にどのディレクトリのどのファイルを編集しているのかは把握しておきたいものです（まあ当たり前のことなのですが、、自分は時々抜けておりまして反省せねばと痛感しております）
pythonのparameterizedについてまとめる

今回のお題
-
今回はpythonのunittestで用いられる`parameterized`というパッケージを取り上げます。

parameterizedはパラメータを用いたテストを可能にするものです。

例えば以下のような関数を定義し、それをテストするとしましょう。

```python:関数定義
def add(a, b):
  return (a + b)
```

```python:テスト
class MyTestCase(unittest.TestCase):
  def test_add(self):
    assertEqual(add(3, 5), 8)

if __name__ == "__main__":
    unittest.main()
```

add関数は引数aとbがどんな数字であっても成り立ってほしいですが、上記の例では`3 + 5 = 8`しか確認できていないので厳密性が担保できているとは言い難いです。

そのような場合にパラメータを用いることで複数のケースでのテストを容易にするのが、今回のテーマである`parameterized`です。

目次
-

- 導入方法
- コード例

導入方法
-
parameterizedはpipからインストールします。

```shell
% pip3 install parameterized
```

コード例
-
parameterizedを用いたコードの例は以下の通りです。

```python
import unittest
from parameterized import parameterized

class MyTestCase(unittest.TestCase):
  @parameterized.expand([
    (3, 8, 11),
    (7, 1, 8),
    (9, 12, 21),
  ])
  def test_add(self, input_a, input_b, expected_result):
    print(f"input_a: {input_a}")
    print(f"input_b: {input_b}")
    print(f"expected_result: {expected_result}")
    unittest.assertEqual(input_a, input_b, expcted_result)

if __name__ == "__main__":
  unittest.main()
```
テスト関数の前に`@parameterized.expand`を付けると、その引数をテスト関数が受け取ってくれるという仕組みです。

テスト関数に設定する仮引数の名前はなんでも構いません。
【裏技】AtCoderでコンパイラコマンドを変更する

# はじめに

AtCoderでコンパイラコマンドを変更できたらなあ，ということはありませんか？
そんなときのための裏技です．

# フォーマット

以下を**Python**で実行することで，自由なコンパイラコマンドでコードをコンパイルできます．

```py
import sys
import os

def run():
  # 実行前であることを判定
  if sys.argv[-1] == 'ONLINE_JUDGE':
    import subprocess

    # ファイルの名前
    filename = 'mycode.cpp'
    # コンパイラコマンド
    command = 'g++ -std=gnu++17 mycode.cpp'
    # コード
    mycode = r'''
#include <bits/stdc++.h>
using namespace std;
int main() {
  cout << "Hello world!" << endl;
}
  '''

    # ファイルを作成し，コードを記述
    with open(filename, 'w') as f:
      f.write(mycode)

    # コンパイルエラーがerror.txtに出力されるようにコンパイルする
    with open('error.txt', 'w') as f:
      exit_code = subprocess.run(command.split(), stderr = f).returncode

    # exit codeが0以外ならfailed.txtを作成
    if exit_code:
      with open('failed.txt', 'w') as f:
        pass
    exit()

  # failed.txtが存在したら標準エラー出力にerror.txtを記述
  if os.path.exists('failed.txt'):
    with open('error.txt') as f:
      sys.stderr.write(f.read())
      exit(1)

  # 実行コマンド
  os.system('./a.out')

run()
```

### 使い方

変更する必要のある場所は4つです．

- `filename`：ファイルの名前
- `command`：コンパイラコマンド
- `mycode`：コードの本体
- 最後の`os.system`の引数：実行コマンド

これさえ用意すればあとはコンパイルしてくれます．

# 仕組み

[Language Test 202001](https://atcoder.jp/contests/language-test-202001) によれば，AtCoderのPythonではテストケース実行前に次のようなコマンドでコードが実行されます．

```bash
python3.8 {dirname}/{basename} ONLINE_JUDGE 2>/dev/null
```

そして，この `ONLINE_JUDGE` コマンドライン引数は，テストケース実行時には無くなります．

これを利用すれば，`ONLINE_JUDGE`の有無で**テストケース実行前かを判定**できます！！(おそらくこれはPython限定です)

フォーマットでは，`if sys.argv[-1] == 'ONLINE_JUDGE':`として実行前にコンパイルしています．

また，コンパイルエラーが出た場合も`error.txt`に保存しておいてちゃんと出力されるようになっています．

# 応用例

## Clangで `bits/stdc++.h` を使ったり最適化したりする

AtCoderでGCCよりClangが劣っていると言われやすい点を解消できます．

AtCoderのClangは `libc++` という標準ライブラリを使っているので，`bits/stdc++.h` がありません．

そこで，AtCoderのコンパイラコマンド([Language Test 202001](https://atcoder.jp/contests/language-test-202001))から `stdlib=libc++` を取り除けば，GCCと同じ `libstdc++` となり，`bits/stdc++.h` を使えるようになります．

同様に，Clangではコードからは `#pragma clang optimize on` という最適化しかできませんでしたが，コンパイラコマンドをいじることで詳細まで最適化できるようになります．

## スタックサイズを変更

稀にスタックオーバーフローを起こす場合は，先に次のコードを実行してからコンパイルさせれば通るかもしれません．

```py
os.system('ulimit -s unlimited')
```

ただし，AtCoderではスタックサイズが既にギリギリなので，[colun法](http://www.colun.net/archives/547) の方が無難です．

## Cythonのコンパイル

AtCoderのCythonは，Cにコンパイルされるので，C++のSTLが使えなくなってしまいます．

そこで，自分でコンパイルします．

Cythonのコンパイルやその他については以下にまとめました：

https://qiita.com/Chippppp/items/d20303f79342cb9c2423

## NumbaAOT

Numbaは、通常ではコンパイルに400msほどかかり，メモリ消費もそこそこ多いため，JuliaやPyPyと比較して見劣りします．

そこでNumbaAOT(事前コンパイル)を使うと，メモリ消費がPyPyより少なく，起動時間もNumpyのimportの100msだけとなり魅力的になります．

以下の記事に使い方が載っています．

https://qiita.com/yniji/items/d012bb9f938e0445a3ff

## その他

- C++で`-fconstexpr-loop-limit=10000000000`などのオプションの追加
- Python/PyPyの事前コンパイル(`py_compile`)
- Pythonのコンパイル時計算(ファイルの読み込みが重いので実用的でない)．

# おわりに

実行前に処理を行えることは色々と応用が効くので，新しいアイディアがあるかもしれません．

最後まで読んでいただきありがとうございました．

# 参考

[AtCoderでCythonの力を開放する魔術詠唱](https://aotamasaki.hatenablog.com/entry/2020/09/09/Cython_in_AtCoder) を参考に作成しました．
STM32L010のMbedでのHT16K33でLチカ (I2C)(STM32L010F4P6)(Mbed2リビジョン変更)


目的
I2Cの練習
単純にライト(書き込み)だけでうまくいくとLEDが光る。
ICも約100円ぐらいで安い
とりあえず、I2Cのテストの時に一番最初に動かす。
あいてんどうと秋月で売っているよ。
いちお書いておくと24ピンと28ピンの違いは、
24ピンが12ビットモードで28ピンが16ビットモード

1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり

![i2c_HT16K33_010_1_r.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3f4337d3-8d97-86b1-b7ae-609b3908dd56.jpeg)


![i2c_HT16K33_031_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d149041e-d46f-2aef-3e55-2f2eb4269454.jpeg)



![中華link_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/fe1729c0-9a56-48ea-a7f4-e331608e3b12.jpeg)




注意
mbed2のリビジョンは、125

リビジョンの変更

1.mbedを選択
2.リビジョンを選択

![o_con83.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e54a7949-dba7-77c7-f702-4c9e29728335.jpeg)

3.リビジョン125を選択(スライドを使う)
4.切り替えを選択

![o_con84.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7a962140-ba5c-fab8-263c-01a3ee2b2149.jpeg)



写真のは、約100円であいてんどうで買った
単に28ピンより20円安いから

![o_con85.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ce30be55-d2af-c3af-e3a8-3daf39bf05f8.jpeg)



```c++


#include "mbed.h"

#define ADDR (0xe0)  //address

I2C i2c(PA_10, PA_9); //010

char data_read[8];  //i2cバッファー
int ii;             //ループカウンター

//メインプログラム
int main() {
    
///*INIT start *********  
    
    data_read[0]=0x21;
    i2c.write(ADDR, data_read, 1);wait_ms(1);

    data_read[0]=0x81;
    i2c.write(ADDR, data_read, 1);wait_ms(1);

    data_read[0]=0xef;
    i2c.write(ADDR, data_read, 1);wait_ms(1);

    for(ii=0;ii<16;ii++){
        data_read[0]=ii;
        data_read[1]=0x00;
        i2c.write(ADDR, data_read, 2);wait_ms(1);
    }//for

//*/  //INIT end *********    

    //無限ループ
    while(1){
         
         //LEDをオン
        data_read[0]=0;
        data_read[1]=1;
        i2c.write(ADDR, data_read, 2);       
        wait_ms(200);

        //LEDをオフ
        data_read[0]=0;
        data_read[1]=0;
        i2c.write(ADDR, data_read, 2);
        wait_ms(200);

    }//while

} // main

//容量削減 約-3kバイト
void error(const char* format, ...){}





```
【SQL】INNER JOINとOUTER JOIN

#はじめに#
　SQLでテーブル結合する際にはJOIN句を使いますが、それにはINNER JOINとOUTER JOINの２種類があります。OUTER JOINの方はあまり使ったことがなかったので、改めて勉強しなおしました。

#INNER JOINとOUTER JOIN#
　まずはじめに、テーブル結合について説明していきます。テーブル結合とは、データベースにある複数のテーブルを合体させて１つのテーブルとして扱うことです。例えば、このような2つのテーブルがあったとします。
とあるSNSのデータベースを想像してください。左がユーザー情報を保管するusersテーブル、右が投稿内容を保存するpostsテーブルです。
![スクリーンショット 2021-11-08 6.50.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/6e433b78-7829-d8b6-de5f-a9845dbab6d2.png)

↓これを合体させるとこのようになります。

![スクリーンショット 2021-11-08 6.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/82b22e45-c204-cec9-1871-0cb9dcc34770.png)

usersテーブルのidとpostsテーブルのuser_idが紐づいて、テーブルを合体させることができます。SQLではこのように書きます。

```
SELECT * 
FROM 
  users
  INNER JOIN posts
  ON users.id = posts.user_id;
```

こうするとユーザーの情報と投稿内容情報を一気にとってくることができます。この手法を、**INNER JOIN**と言います。注意しなければならないのは、佐藤さんはまだ投稿をしていないので、postsテーブルにデータがありません。結合するテーブルにデータがない場合、結合後のテーブルではそのレコードがまるまる削除されてしまいます。postsにデータはないけれども佐藤さんのデータも取ってきたい場合はこのように書きます。

```
SELECT * 
FROM 
  users
  LEFT OUTER JOIN posts
  ON users.id = posts.user_id;
```


結果はこちらになります。

![スクリーンショット 2021-11-08 7.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/d1c12643-17c5-2a58-a9c2-5fe7d3aab92e.png)

**LEFT OUTER JOIN**を使うことで佐藤さんのデータも取ってくることができます。ただし、postsテーブルにはまだデータが存在していないため、値はnullとなります。


これらをベン図で表すとこのようになります。

![スクリーンショット 2021-11-08 7.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558223/b039de74-678d-44a7-5858-7c58a01dd316.png)

INNER JOINのことを内部結合、OUTER JOINのことを外部結合と言います。LEFTが付くと左外部結合になります。ベン図を想像するとどっちがどっちか覚えやすいですね。


#終わりに#
　テーブル結合は必須の知識ですので、しっかり覚えておくようにしましょう！
enumとvalidationの用い方（初学者向け、コード説明あり）


Swift初学者であり、間違っていることも、
記載している可能性もありますので、ご注意ください。

##まずはじめに用語の説明

バリデーションとは、
__入力内容や記述内容が要件を満たしているか、妥当性を確認すること__
URL：https://wa3.i-3-i.info/word11610.html
かんたんに言うと　入力チェックです。

enumとは、
__列挙型（enum）とは関連性のある事柄、データを一つにまとめた定数のようなものです。__
URL：https://www.sejuku.net/blog/35711

##行いたいこと
テキストフィードが２つあり、
一つに税抜金額、
もう一つに税率を入力し、
数値が入力されているか、されていないかを確認する。
チェック後に、行いたい処理を行う。

というプログラムを作成します

##enumでValidationを定義
![スクリーンショット 2021-11-08 5.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799713/5425c737-48bd-5c15-3880-fa79119433c5.png)
enumを用いて、ValidationResult型を用意する。

バリデーションの要素として、

invalidExcludingTax：無効な税抜金額
invalidTaxRate・・無効な税率
valid(TaxRelatedValues)・・有効（TaxRelatedValues型を引数に持つ）

TaxRelatedValues型は、構造体として作成したものです。
この中には、税抜金額、税率、税込金額のプロパティが用意されています。

##メソッドを定義
![スクリーンショット 2021-11-08 5.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799713/59604739-1eda-7fa7-441b-cbc713d2869f.png)
ValidationResult型を返り値として持つメソッドを定義する。その中で、if文、guard文　を用いて、どの条件のときに、ValidationResult型のどの要素を返すかを考える。

ここでは、Validationの要素別の処理を入力しない。次のコードで入力する。

チェックに引っかかった場合は、invalid〇〇
チェックに引っかからなかった場合は、valid〇〇
の要素が返って来たら、良いという認識でよいかもです。


##アクションの中で、メソッドを実装
![スクリーンショット 2021-11-08 5.23.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799713/4d4aee0d-208d-597c-47e6-8a2526075278.png)
ボタンアクションのメソッドの中で、さきほど定義したvalidateTextFieldsメソッドの返り値（ValidationResult型の要素）によって、行う処理を変更したい。
そのために、switch文で、返り値別に、行う処理を実装している。

case .valid(let values)は、有効な場合の処理である。
validationが有効だった場合は、TaxRelatedValues型を用いて、行いたい処理を行いたい。
そのために、TaxRelatedValues型（税抜金額、税率などのプロパティがある構造体）を引数の型として設定している。

validの処理の中身は、無視して頂いて構いません。

##まとめ
流れとしては

①enumで、型を設定することが可能であり、enumの中の要素を増やすことによって、Validationの種類を増やすことが可能である。（入力値の字数オーバーなど）

②enumで作成した型を返り値として、実際の処理とは別で、メソッドを作成し、どの条件のときに、どの処理をおこなうかを、まとめたメソッドを作成する。

③実際の処理（ボタンをタップ時、テキストフィードへの入力時など）の中で、②で設定したメソッドを実装する。


以上です。

Swift初学者であり、間違っていることも、
記載していますので、ご注意ください。
皆さんの学習の一助になることができれば、幸いです！
Railsのテンプレートエンジンをslimからerbに戻した理由

#はじめに
Railsで開発をする際にslimを使っていましたが、元のerbに戻すことにしました。本記事ではslimのメリットとデメリットを比較し、slimからerbに戻した理由について説明します。
#slimとは？
slimはRailsで使うテンプレートエンジンの１つです。slimを導入することで、通常のhtmlよりも記述量を減らすことができます。
例えば、次のように< >と閉じタグは省略されます。

``` html:html
<div>
  <h1>メニュー</h1>
  <ul>
    <li>Ruby</li>
    <li>on</li>
    <li>Rails</li>
  </ul>
</div>
```

```slim:slim
div
  h1 メニュー
  ul
    li Ruby
    li on
    li Rails
```

詳細な文法は↓にリンクを貼っておきます。

https://github.com/slim-template/slim/blob/master/README.jp.md

https://qiita.com/ngron/items/c03e68642c2ab77e7283

https://qiita.com/wann/items/2b8151fc39c201cfa889

#slimのメリット
slimを導入すると以下のメリットがあります。

・書きやすく読みやすい最小限のテンプレート
・デフォルトでHTMLエスケープを行い、セキュア

要するにコードを短く書けるようになるということです。
#slimのデメリット
上ではslimのメリットについて記述しましたが、一方で以下のデメリットがあります。

・デフォルトでない
・細かいところは都度調べる必要がある

簡単に書けて記述量を減らせるのがslimのメリットでしたが、基本的な文法から外れるなどの細かい書き方をする場合、その度に調べる必要がありました。その調べる時間を考慮すると、記述量を減らせることによる時間短縮を上回りました。また、時間だけでなく、何度も詰まり調べなくてはならないことにより、大きく開発体験が損なわれることも体感しました。

リーダブルコードの1.2「読みやすさの基本定理」には以下のように書かれています。

>コードは他の人が最短時間で理解できるように書かなければいけない。

ここでいう「他人」には自分も含まれています。書いているときにはslimの文法を覚えていても少し時間が経てば、完全に覚えているということはないでしょう。少なくとも僕はその自信がありません。そうなると、長期的な目線ではデフォルトのhtmlで書くほうが可読性が高いでしょう。自分だけでなく他人も開発に参加する場合、その都度slimの文法を学んでもらう必要があります。この点においても、可読性が下がっていることがわかります。

また、1.3「小さなことは絶対にいいこと？」では、コードはただ短ければ良いことなのかということに疑問提起をしています。ただ短いだけのコードより、長くなったとしても読みやすいコードのほうが良いとしています。重要なのは「理解するまでにかかる時間」を短くすると結論づけています。これは先程の議論と同様にslimの場合に対してもあてはまります。

#おわりに
以上の理由により、slimからerbに戻しました。slimのメリット、デメリットを比較するにあたり、コードの読みやすさ、開発体験などを改めて考えることができました。

#参考

https://tech.ga-tech.co.jp/entry/replace-slim-haml-to-erb

https://higelog.brassworks.jp/3232
M5Stamp C3で時計

　7セグメントLEDを使った時計を作ります。M5Stamp C3はWi-Fi経由でインターネットにアクセスできるのでntpサーバから時間を持ってきます。

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/b2e531d9-8e86-a16b-01ae-9171486bef91.png">


###表示器はHT16K33ドライバ
　アマゾンでも入手可能な、4桁の7セグメントLEDを使います。インターフェースはI2Cです。コントローラはいろいろありますが、ここではHT16K33を選びました。
　ライブラリを入れます。一番上に見えているHT16K33です。14セグメントには対応していないようです。
![2021-11-07 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/e7ce7635-de87-703c-79e6-4e3b461f99c9.png)

###ntpライブラリを入れる
　NTPClientライブラリを入れます。

![2021-11-07 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/aa9f23dc-db4a-44e3-0159-91aba736b522.png)


###スケッチ
　``WiFiMulti.addAP("Buffalo-G-20EA", "＊＊＊＊＊＊＊＊");``は、Wi-Fiルータへのアクセスです。

```C
//  AUTHOR: Rob Tillaart
//     URL: https://github.com/RobTillaart/HT16K33

#include "HT16K33.h"
HT16K33 seg(0x70);

#include <WiFi.h>
#include <WiFiMulti.h>
#include <NTPClient.h>

WiFiMulti WiFiMulti;
//const char* ntpServer = "ntp.nict.jp";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

void setup(){
  Serial.begin(115200);
    WiFiMulti.addAP("Buffalo-G-20EA", "＊＊＊＊＊＊＊＊");
    //Serial.print("\nWaiting for WiFi... ");

    while(WiFiMulti.run() != WL_CONNECTED) {
    //    Serial.print(".");
        delay(500);
    }

 /*   Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
*/
  timeClient.begin(); 
  delay(500); 
    
  seg.begin();
  Wire.setClock(100000);
  seg.displayOn();
  seg.setDigits(4);
}


void loop(){
  delay(1000);
  timeClient.update();
  String TIME = timeClient.getFormattedTime();
  String Hr = TIME.substring(0, 2);
  String Mini  = TIME.substring(3, 5);
  //Serial.println(TIME);
  //Serial.print(Hr);Serial.print(":");Serial.println(Mini);
    
  seg.displayTime(Hr.toInt()+9, Mini.toInt(), true, false);  // do not display leading zero.
  seg.displayColon(1);
}
```

　Windows10は、デフォルトで１週間「604800秒」でNTPサーバにアクセスしに行っているようです。上記のように毎秒アクセスするのはあくまでも実験運用いうことで。長期運用時には、アクセス頻度を下げるべきでしょう。しかし、ローカルに時計を持っていない場合は、面倒です。下記記事に具体的な手法が掲載されています。
　　　[ESP32 の 時刻取得のオフライン時の挙動](https://qiita.com/yomori/items/0d72ab3d9556a0b7ef70)

　JSTに修正するのに、``Hr.toInt()+9``とインチキをやっています。朝4時に見ると、28時という表示でした。プログラムは暴走していたわけではないようです。

###修正

``NTPClient timeClient(ntpUDP);``　を　``NTPClient timeClient(ntpUDP, "ntp.nict.jp", 3600*9, 60000);``に

``seg.displayTime(Hr.toInt()+9, Mini.toInt(), true, false);`` を  ``seg.displayTime(Hr.toInt(), Mini.toInt(), true, false);``に変更します。
　``3600*9``はオフセットで、秒単位です。``60000``は更新のインターバルです。[GitHub](https://github.com/arduino-libraries/NTPClient)にアクセスして、使い方がわかりました。
golangで『hello world』ならぬ『Merry Christmas』を出すまで。(初めてのAdvent Calendarです！)

# はじめに

[毎日誰かのプルリクをマージしてクリスマスを彩るアドベントカレンダー（Golang）](https://qiita.com/advent-calendar/2021/go-advent)2日目のアドベントカレンダーです！

初めての『Advent Calendar』でとてもドキドキしています！(>ω<)！！！！

今回行ったことは以下です！凝ったことはしていません！:sunglasses:ドヤっ！
・『Merry Christmas』を出す！
・ 実行手順を書く
・ 他にもIssueを書いておく


#『Merry Christmas』を出す！

```
$ cd app
$ go build main.go
$ ./main
```

chromなどで、http://localhost:8080/sachiko
でアクセス。

以下表示されるようにしました。

| ![スクリーンショット 2021-11-08 2.14.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/2e53a653-95c4-2952-a2aa-1ed19f45565f.png)| 
|:-:|



# 実行手順を書く
READMEに以下を追記させていただきました！

|![スクリーンショット 2021-11-08 3.32.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/95034542-47b6-d2cc-8840-4b02e3b26252.png)| 
|:-:|



# 他にもIssueを書いておく
『Issue』を書くのも出来るとのことだったので沢山『Issue』を書いてみました！
実現してくれる方いたら凄くテンション上がるんだろうなと感じています！(>ω<)


- 『Merry Christmas』をオシャレにする。
- サンタクロースからの素敵な言葉を追加。
- 面白いパッケージを作成する。

# 行った全体の流れ

- githubのフォーク(好みかもです、)

|![スクリーンショット 2021-11-08 3.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/c9f66b35-3a91-ab5c-2be8-01d337a3bd77.png)| 
|:-:|

- フォークをクローンしてゴニョゴニョしてプッシュ

```
$ git clone https://github.com/sachiko-kame/advent.git

$ cd advent

$ git checkout -b merry_christmas

ゴニョゴニョする。

$ git push --set-upstream origin merry_christmas
```
- 作者のリポジトリに行きプルリクボタンを押してプルリクメッセージ等書く。その際メッセージにIssuesのリンク記述する。

|![スクリーンショット 2021-11-08 3.41.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/f5f95912-c427-21c0-ab0f-fed828472ded.png)| 
|:-:|


3日目は @codehex さんです！
よろしくお願いします！

@rhymof さんマージお願いします！
twitterでメンション飛ばしたのですが念の為こちらでも！

# 少しの雑談
githubトークン作らないといけなくなりましたね、、

https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token


# 参考

golang参考

https://golang.org/doc/

プルリク参考

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork
[aws,alb]Health checks failed with these codes: [500] の解決例

## 何があった？

ecs(fargate)をalbで負荷分散させるようなアーキテクチャ設計での環境構築をした際、何度ECSをたててもALBがタイトルのエラー文でunhealthyになってしまう現象が起きていました。


## 原因
albの設定ではなく、laravelのAPP_KEYの登録ミスでした。

具体的には`base64:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=`と登録しなければいけないのに`XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=`と登録しておりました。

結果phpのコンテナが立ち上がってすぐもエラーで削除されてしまい、結果としてロードバランサーの方でエラーとなって現れておりました。

## 解決策
環境変数の部分を修正することで解決しました。（筆者はSystemManagerのParameteStoreに保存していたのでその中の値を修正しました。)

## 類似エラー解決の考察
エラー文が500やTarget.FailedHealthChecksのように具体的な原因が出ていない場合は、ロードバランサーではなく、nginxかlaravel（アプリ側）の設定ミスを疑うと解決できるかもしれません。
ExcelをPDF化したときにタイトルが文字化けするのを解消する方法

# 概要

Excelで記載したドキュメントを`Microsoft Print to PDF`でPDF化したとき、ブラウザでPDFを見るとタイトルが文字化けすることがあった。
直し方をネットで調べたものの、PDFビューワーが必要だったりで上手くいかないものが多かった。
根気よく調べたところ最終的にエクセルとChoromeだけで解消ができたので、その方法を記載する。

# タイトルが文字化けするのを解消する方法
## ExcelをPDF化する

`メニュー` > `印刷`からプリンタを`Microsoft Print to PDF`に設定してOKを選択

## タイトルが文字化けしたPDFをChoromeで開く

1. 先程出力したPDFをChoromeで開き、右上の印刷ボタンを選択する。
2. 送信先を`PDFで保存`にして、保存を選択する。
3. 保存する際のファイル名が文字化けしているはずなので、ファイル名を任意の文字に修正して保存する。
4. 出力されたPDFをブラウザで開いてみると文字化けが解消しているのが確認できる。

# 補足

後々で気づいたが、ExcelのファイルをPDF化したいだけであれば`Microsoft Print to PDF`を使わずに、`名前を付けて保存`から形式をpdfで選択して保存すれば文字化けもせずにPDF化することができた。
Homebrew の bottle は直近三世代の macOS に対応

こんにちは。
Homebrew（の formula）の bottle は、直近三世代の macOS に対応のようです。

##### 対応 OS の例
最新の macOS Monterey リリースから約二週間後[^1]、対応 OS を見ますと下記のようです。したがって以前の mojave は非対応扱いになったようです。

1. 最近更新された formula は： __monterey__, __big_sur__, __catalina__
2. そうでない formula は： __big_sur__, __catalina__, mojave

[^1]: 2021年11月上旬

##### Macintosh 機種（Homebrew 対応）
現時点で、上記を勘案しますと、big_sur へ対応する機種が対応状況が良いと考えることもできそうです[^2]。また今後二年間は Homebrew 対応してくれそうです。

[^2]: 例えば、MacBook Pro Late 2013（この機種のサポートはすでに終了）

##### Macintosh 機種（Homebrew 非対応）
Homebrew 対応しない macOS バージョン下では、bottle 利用不可となります。したがって新規インストールもしくはアップグレード時には source からのビルドが不可欠となります。

しかし失敗したり、時間がかかりすぎてお手上げになりそうです。対応策は下記が考えられます。

* 通常手順で macOS アップグレードする（Appleサポートされている機種）
* OpenCore Legacy Patcher[^3] を使って macOS アップグレードする
* 機種を買い替える


[^3]:参考：「[Appleサポートが終了したMacに新バージョンのMacOSをインストールする方法](https://qiita.com/almas/items/96da1cdfddd7aac6a027)」