OmniAICreator/Qiita-1.07M huggingface dataset:
Power Automate Desktopでフォルダ監視

### やりたいこと
仕事中にこんな指示が来ました。
「このフォルダの中身が更新されたら、フォルダ内にあるファイルの名前を、指定したメモ帳に書き出して！」

RPAについて色々と調べていた所なので、Power Automate Desktop（無料版）を使い、「中身が更新されたら」ではなく「1時間に1回フォルダの中のファイル名を書き出す！」（更新されたらではないですが・・・）と言う方法を試してみました。

### 主なポイント
どうやってやったら良いか迷ったのは下記の2つでした。
・手動でしかフローの実行が出来ないPower Automate Desktop（無料版）でどうやって定期的に（1時間に1回）動かすか。
・フォルダ内のファイル名取得 → メモ帳に書き出しをどうやってやるか。

定期的なフローの実行の参考になったのは下記のページでした。
https://cravelweb.com/rpa/power-automate-desktop/how-to-run-scheduled-flow-on-power-automate-desktop-for-free

また、ファイル名の取得と書き出しは上司からコマンドを教えてもらい、実現できました。

### 実際にやった事
今回はデスクトップに有る「共有フォルダ」の中身を、デスクトップに有る「共有一覧」と言うメモ帳に書き出します。

●新しいフローの作成
　適当な名前を付けて作成開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/f078439a-1fa5-2b2d-f360-4830db5d45c0.png)

●フォルダ内のファイル名取得 → メモ帳に書き出し
　・システムから「DOS コマンドの実行」を選びます。
　・DOSコマンドまたはアプリケーションに dir /b >C:\Users\namae\Desktop\共有一覧.txt を記入
　　dir /b　で、指定した場所にあるファイルの名前を取得し、指定した場所に書き込みます。
　　なので後ろの　>C:\Users\namae\Desktop\共有一覧.txt　で書き込むメモ帳を指定してあげます。
　　
　・作業フォルダーには　C:\Users\namae\Desktop\共有フォルダ　と記入
　　読み込むフォルダを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/bc2878a1-66d9-1abc-dffe-59295345c694.png)

●定期的な動きの作成
　定期的に同じ動きをさせるので「Loop」を使います。
　1時間に1回として今回は24回更新したいと思うので、開始値を0　終了を24　増分を1にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/6ade6c60-dd52-f97b-dda8-c7b10a14cc4e.png)

●「現在の日時を取得」と「次の実行時間の設定」
　では「Loop」の中に「DOS コマンドの実行」を入れてループさせましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/a6c351d0-a1ca-bb62-6ad9-8c79d9fd7a44.png)

　しかし、これでは「DOS コマンドの実行」を24回行ってすぐに終わってしまうので、少し細工を行います。
　まず、現在の時刻を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/0277aded-dae8-a5bb-aa57-4330b7c53161.png)

　そして1回目の実行は今終わったので、次に実行する時間を指定します。
　日時は今取得した時間を使うので関数の %CurrentDateTime% を入れます。
　加算には1を入れます。　（1時間ごとに実行するので）
　時間単位は時間を入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/ea4df472-f7b1-52d6-c434-ccebd1462815.png)

　生成された変数　ResultedDate には次の実行時間（1時間後の時間）が入っています。
　
●次の時間までのループ
　DOSコマンドを実行した時間を取得し、次に実行する時間も設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/c3fe6986-9918-3ae8-00c2-5f618152747a.png)

　しかしこれでは次の時間（1時間後の時間）を設定しただけなのですぐ次のDOSコマンドを実行してしまいます。
　ではどうするかと言うと
　1時間たつまで足止めしましょう。
　と言う事でもう一度ループを持ってきます。

　今回使うループは「ループ条件」です。
　今の時間が、先ほど指定した1時間後の時間より大きくなったら（時間が過ぎたら）ループを抜けるようにします。

　最初のオペランドには1時間後の時間が入った関数　%ResultedDate% を入れます。
　演算子には　より大きい（＞）　を選択します。
　2番目のオペランドには、今の時間　%CurrentDateTime%　を入れていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/beb030f3-8492-86fe-3f0c-f3f8fe2a0466.png)

　そしてそのループの中で今の時間を取得し続け、1時間後の時間になったらループを抜けDOSコマンドを実行してもらいます。ただし、新しく「現在の時刻を取得」を持ってくると時間の入った変数が変わってくるので、上に有る「現在の時刻を取得」をコピー貼り付けするか、新しく「現在の時刻を取得」を持って来て変数名を変えるかしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514815/eb6330c0-ce0f-1b0d-37ec-5c805880c8c4.png)

これで1時間に1回DOSコマンドを実行しフォルダの中の情報をメモ帳に書き出すことが出来ます。
【Cython】AtCoderでnumpyを使う方法

# はじめに
※AtCoderでのCythonについての記事は以下に書きました：

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

AtCoderのCythonでnumpyを使う方法の備忘録です。

# フォーマット

以下の`setup.py`でコンパイルするフォーマットを**Python**で実行することでnumpyを使用できます：

```py
import sys
if sys.argv[-1] == 'ONLINE_JUDGE':
  mycode = r'''
# distutils: language = c++
# cython: language_level = 3
cimport numpy as np # numpyが使える！！
def main():
  pass # ここに書く
if __name__ == 'mycode':
  main()
'''
  with open('mycode.pyx', 'w') as f:
    f.write(mycode)
  setup = r'''
from distutils.core import setup, Extension
from Cython.Build import cythonize
from numpy import get_include
ext = Extension('mycode', sources = ['mycode.pyx'], include_dirs = ['.', get_include()])
setup(name = 'mycode', ext_modules = cythonize([ext]))
'''
  with open('setup.py', 'w') as f:
    f.write(setup)
  import subprocess
  with open('error.txt', 'w') as ef:
    code = subprocess.run('python3.8 setup.py build_ext --inplace'.split(), stderr = ef).returncode
  if code:
    with open('error.txt', 'r') as ef:
      with open('mycode.py', 'w') as f:
        f.write(f'''
import sys
sys.stderr.write("""{ef.read()}""")
exit({code})
''')
  exit()
import mycode
```
MacのターミナルでCPU温度とファン速度を表示する方法


# 概要
iStatやMacs Fan Controlなどのアプリを入れずにCPU温度とファン速度を確認したい。
そこで、ターミナルから確認できるようにしてみたました。

##　試した環境
MacBook Pro 16inch 2019
MacOS Big Sur 11.5.2


# やり方
ターミナルを開き、以下のコマンド打ちます。

```bash
$ sudo powermetrics -n 1 | grep -A8 "SMC sensors"
```

パスワードを求められるので入力するすると、数秒後に情報が表示されます。

```
unable to get backlight node
unable to get backlight node

**** SMC sensors ****

CPU Thermal level: 63
GPU Thermal level: 13
IO Thermal level: 13
Fan: 2705.69 rpm
CPU die temperature: 63.25 C
GPU die temperature: 64.00 C
CPU Plimit: 0.00
```
`Fan`がファン速度です。ファンが2基あっても1つに纏まって表示されます。
`CPU die temperature`がCPUの温度です。


# Aliasに登録する

毎回長いコマンドを打つのめんどくさいので、`temp`と打つことで起動できるようにします。

以下のコマンドを打ち`~/.zshrc`ファイルを開きます。

```bash
$ vim ~/.zshrc
```


開けたら、ファイルの一番最後に以下の行を追加し保存します。

```vim:~/.zshrc
# エイリアス
alias temp='sudo powermetrics -n 1 | grep -A8 "SMC sensors"'
```

これで、`temp`と打つだけで起動できるようになりました。

```bash
$ temp
```


# コマンド解説
今回打ったコマンドはこちら。

```bash
$ sudo powermetrics -n 1 | grep -A8 "SMC sensors"
```

`powermetrics`はMacの色々なステータスを表示するコマンドです。
あまりにも情報が多すぎるので`grep -A8 "SMC sensors"`でCPU温度関係の情報のみに整理しました。
このコマンドは数秒ごとに更新がずっと続いてしまうので、`-n 1`を追加し1回のみ表示としてあります。



# 参考にさせて頂いたサイト
https://qiita.com/watanu/items/5f2234245c2f62a3182a
http://fanblogs.jp/macyarounanoka/archive/473/0
https://tomowarkar.github.io/blog/posts/mac_cpu/
【Salesforce】入力規則のTips

Salesforce入力規則の忘備録（随時更新？？）


#ユニーク
Nameなどの標準項目をユニークにしたいときは入力規則で制御できます。
カスタム項目でもとある条件の時に重複を持たせたくない場合などで使えますね☆

```
AND(
  VLOOKUP($ObjectType.★★★.Fields.●●●, $ObjectType.★★★.Fields.●●●, ●●●) = ●●●,
  OR(ISNEW(), ISCHANGED(●●●))
)
```

★★★はカスタムオブジェクト名、●●●は項目名が入ります。
※標準オブジェクトでは` $ObjectType` が使えないようです。

**例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/01649484-79f3-9729-c125-17a5afb691bc.png)
カスタムオブジェクトに入力規則を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/23c7b351-7959-e6aa-2428-236fed3bda63.png)
カスタムオブジェクト名が「テスト１」のレコードが存在します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/97951b80-35ff-484e-843a-ddee712a82f7.png)
カスタムオブジェクト名が「テスト１」のレコードを新規作成しようとするとエラーメッセージが表示されました！


#項目の変更不可
とある項目について変更をさせたくない場合の入力規則、とてもシンプルです↓

```
PRIORVALUE(●●●)<>●●●
```
●●●は項目名が入ります。

#特定条件のレコード更新不可
クローズ日時が入っている場合は更新不可！など幅広く使えます。

```
AND(
  ✕✕✕✕✕✕✕✕✕✕✕✕,
  !ISNEW()
)
```
✕✕✕✕✕✕✕✕✕✕✕✕は条件が入ります。

#所有者と特定プロファイルのみ項目を変更可能

```
AND(
  ISCHANGED( ●●● ), 
  Owner <> $User.Id, 
  $Profile.Name <>"▲▲▲"
) 
```
●●●は項目名、▲▲▲はプロファイル名が入ります。

#正規表現
使えると便利な正規表現！例と一緒に、、
●●●は項目名が入ります。

**半角英数字（＋アンダーバー）**

```
!REGEX( ●●●, '\\w')
```

**10桁半角英数字（＋アンダーバー）**

```
!REGEX( ●●●, '\\w{10}')
```
**ひらがな**

```
!REGEX( ●●●, '^[ぁ-?]+$')
```
**カタカナ**

```
!REGEX( ●●●, '^[ァ-?]+$')
```
**半角ｶﾀｶﾅ**

```
!REGEX( ●●●, '^[ｦ-ﾟｰ ]+$')
```
**郵便番号**

```
!REGEX( ●●●, '^\\d{3}-\\d{4}$')
```




#参考
Salesforce公式の入力規則ヘルプページ
https://help.salesforce.com/s/articleView?id=sf.fields_useful_field_validation_formulas.htm&type=
AWS Well-Architected Frameworkを学ぶ

[zenn](https://zenn.dev/mo_ri_regen/articles/aws-well-architected-framework)にも同様の記事を書いています。更新頻度はzennのほうが多めです👋

## AWS Well-ArchitectedFramework について

2015 年の AWS re:Invent で発表され、毎年アップデートされています。
AWS についてクラウド上でワークロード[^1]を設計および実行するための主要な概念や設計概念、ベストプラクティスについて説明したものです。
AWS のソリューションアーキテクトとユーザの実際の経験から作成されました。

[^1]:
    作業負荷、業務量と訳します。
    [AWS](https://docs.aws.amazon.com/ja_jp/wellarchitected/latest/userguide/workloads.html)ではリソースと、ビジネス価値をもたらすコード (顧客向けアプリケーションやバックエンドプロセスなど) の集まりと定義されています。

:::note warn
ベストプラクティスは理解する必要はありますが、すべてを守る必要はありません。
ビジネス的な判断をして、守らなかった理由が「なんとなく」ではなく、きちんと説明できるようにすることが重要です。
:::

## ホワイトペーパー

設計原則が書かれています。"原則"なので、実装の詳細やアーキテクチャパターンは扱っていません。5 つの柱(~~柱って言い方、鬼滅の刃 👹 みたいですね~~)について Q&A 形式のベストプラクティス集が書かれています。
中身について AWS に関するものもありますが、AWS に特化していないものもあります。

### クラウドでの一般設計原則

- 必要なキャパシティを勘に頼らない
- 本番規模でのシステムテストを行う
- 自動化を取り入れる(アーキテクチャ試行の回数を増やすため)
- 発展的なアーキテクチャを受け入れる
- データ計測に基づいてアーキテクチャを決定する
- 本番で想定されるトラブルをあらかじめテストし、対策する

### 5 つの柱

- オペレーショナルエクセレンス(運用の優秀性)の柱
  システムの実行とモニタリング、プロセスと手順の継続的な改善に焦点を当てています。
  トピックとして、変更の自動化やイベントへの対応などです。

- セキュリティの柱
  情報とシステムの保護に焦点を当てています。
  トピックとして、データの機密性や権限管理における権限の特定などです。

- 信頼性の柱
  ワークロードが意図された機能を期待通りに正しく一貫して実行することを保証することに重点を置いています。
  トピックとして、復旧計画や変更の処理方法などです。

- パフォーマンス効率の柱
  IT およびコンピューティングリソースの効率的な使用に焦点を当てます。
  トピックとして、パフォーマンスのモニタリングや要件に応じた適切なリソースタイプの選択などです。

- コストの最適化の柱
  不要なコストを回避することについて焦点を当てています。
  トピックとして、最適なリソースの選択や費用が発生する箇所の把握、管理などです。

## AWS Well-Architected Tool について

[AWS Well-Architected Tool](https://aws.amazon.com/jp/well-architected-tool/)を使うことで、最新の AWS のアーキテクチャのベストプラクティスと比較することができます。
使い方は、AWS のマネジメントコンソールでワークロードを定義したあとに 5 つの柱についての一連の質問に答えるだけです。
そのあとにベストプラクティスを使った アーキテクチャの設計方法に関する計画が提示されます。

## 参考

※大枠は変わっていないと思いますが、動画は 2018 年と古いので注意が必要です。

https://www.youtube.com/watch?v=jMJFFo1Oybo

https://aws.amazon.com/jp/architecture/well-architected/

https://aws.amazon.com/jp/blogs/news/aws-well-architected-whitepaper/

https://aws.amazon.com/jp/well-architected-tool/
【忘備録】Unityプロジェクトを作成後、最初にやること

#Gitに対応させる
**・Github for Unityをアセットストアからインポート**
>Asset Store Link : https://assetstore.unity.com/#!/content/118069
>公式サイト Link : https://unity.github.com/

Unityエディター上で**Window>Github**を開く
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/f843b88c-0ff4-6afd-1c8f-f5b93205cc3e.png">
上記画面で**[Initialize...]**をクリック
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/059c1b87-6aec-8dda-dd2c-846737340be7.jpeg">
Settingタブを開き、名前とメールアドレスを設定する
Githubに公開する予定が無いので適当でも可
Githubと連携させたい場合は適宜**[Sign in]**等を行うべきだが、VRChatでは再配布不可のデータを扱うことが多いので連携しないと想定
使用PC上で一度Gitを使ったことがある人は自動で入力されているはず

これでデータのバックアップ管理ができるようになる
Github for Unityの詳しい使い方は他サイト様に丸投げする

#シーンビューにアンチエイリアシングを適用する
デフォルトのままだとシーンビューのジャギー(画像のギザギザ)が気になって仕方ないのでアンチエイリアシングを適用する

**・Post Processingをアセットストアからインポート**
Unityエディター上で**Window>Package Manager**を開く
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/45f05802-3421-c50a-be92-073130d1c017.jpeg">
右上の検索欄に「**Post Processing**」と入力して検索
右下の**[Install]**をクリック
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/ab28f448-f4ab-77a4-6951-2d75ca005e8a.jpeg">
Hierarchy ウインドウで**Main Camera**を選択(無い場合は**Game Object>Camera**から追加)
Inspector ウインドウでMain Cameraが選択されていることを確認し**Add Component**をクリック
検索欄に「**Post-process Layer**」を入力し、出てきたPost-process Layerを追加する
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/44eca8bd-8419-cb0d-5b16-82bd916cf8a4.jpeg">
コンポーネントが追加されたことを確認
この時点でアンチエイリアシングは効いているが、**Anti-aliasing>Mode**から任意のアルゴリズムに変更できる

<img width=50% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/2d446fe4-cfbf-fe32-01e2-b33edac4f590.png"><img width=50% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/c98eeb0f-f078-7a58-0fcf-b1c617831302.png">

適用前(左)と適用後(右)の比較
閲覧時の環境によっては差異が分かりづらいかもしれないが、実際に適用してみると一目で違いが分かるほど効果がある

#キャッシュサーバーを有効にする
VRChatではQuest対応の際にビルドプラットフォームを頻繁に変更する場合がある
その際、変更毎にテクスチャなどのデータのコンパイルが走ると時間がかかりすぎる
キャッシュサーバーを設定することでコンパイル前後のファイルがキャッシュされ、ビルドプラットフォームの変更を高速化することができる

**・キャッシュサーバーをローカルに設定**

Unityエディター上で**Edit>Performances**を開く
<img width=70% alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238453/c3433995-da94-6c64-2624-66dfa96e7d64.jpeg">
**Cache Server (global)**項目内の**Cache Server Mode**を**Disable**から**Local**に変更
キャッシュ容量が足りないようなら**Maximum Cache Size (GB)**を適宜変更
STM32F103C8と温度,S-5851でOLED温度計 (Arduino)(AL12832AWWB)


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


x プログラムは、unoと同じ
x ハードは、BluePill 設定は、BluePillF103C8

b6 swd-clk
b7 swd-io


![h_con13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5c7299a2-e325-3ca4-5d39-5a2150505ab7.jpeg)

stm32のボードを選択している

![h_con14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/0384b19c-1290-fece-91c1-a42793fb8f9b.jpeg)



```c++


#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h> //I2C library

// I2C temperature sensor - see table 1 of data sheet.  Resistor selects address. 
#define S5851A  0x48

//#ifdef U8X8_HAVE_HW_SPI
//#include <SPI.h>
//#endif

U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);   // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED

int     cursor1;      //カーソルの位置
char    data_read[8]; //i2cバッファー

void i2c_oled_w(char *s)
{
            //文字の表示
            u8x8.drawString(
            ((cursor1-0) & 0x07  )*2, // x
            (cursor1>>3)*2,           // y
            s);
            
            while(s[0] != 0) {
              s++;
              cursor1++;
            }
            
            //cursor1=cursor1 + 3; 
} //i2c_oled_w

//初期化
void setup(void) {

  delay(2000); //oledのリセット時間

  u8x8.begin();

  u8x8.setFont(u8x8_font_px437wyse700a_2x2_r);

  //スタートロゴ
  cursor1 = 0;
  i2c_oled_w("START");
  delay(500);

  //画面の初期化
  u8x8.drawString( 0,0,"        ");
  u8x8.drawString( 0,2,"        ");
  cursor1 = 0;

  //Wire.begin(sdaPin,sclPin); //f103
  Wire.begin(); //uno

} //setup

int tempval;          //温度
int n0;               //温度　小数点以上
int nt[] = {0,2,5,7}; //温度

void loop(void) {

//  //画面の初期化
//  u8x8.drawString( 0,0,"        ");
//  u8x8.drawString( 0,2,"        ");
  //カーソルのクリア
  cursor1 = 0;

  //0番目のレジスター
  Wire.beginTransmission(S5851A);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);

  //温度の読み込み
  tempval = 99;
  Wire.requestFrom(S5851A, 1);
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    tempval = (int)Wire.read(); // 1バイトを受信
  }//while

  //温度をセット
  int n0 = tempval;

  //n0=20; //debug
  
  //画面に表示
  i2c_oled_w("TMP=");
  data_read[0] = '0' + n0/10;;
  data_read[1] = '0' + (  n0-(  (n0/10)  *10)  );
  data_read[2] = '.';
  data_read[3] = '0' + 0;
  data_read[4] = 0; 
  i2c_oled_w(data_read);

  //1秒待つ
  delay(1000);
} //loop




```
ArcticFox(AGP7.0)マイグレーション時にCircleCIで発生する java.lang.NoSuchMethodError: 'void org.apache.commons.compress.archivers.zip.ZipFile.<init>(java.nio.channels.SeekableByteChannel)' について

CircleCIから提供されているAndroidのDockerイメージを使用している場合、使われるbuildToolsVersionの一覧が`dockerfiles`に書かれているみたいです。

例えば api-30を使う場合、👇

https://github.com/CircleCI-Public/circleci-dockerfiles/blob/master/android/images/api-30/Dockerfile#L183

```yml
RUN sdkmanager \
  "build-tools;27.0.0" \
  "build-tools;27.0.1" \
  "build-tools;27.0.2" \
  "build-tools;27.0.3" \
  # 28.0.0 is failing to download from Google for some reason
  #"build-tools;28.0.0" \
  "build-tools;28.0.1" \
  "build-tools;28.0.2" \
  "build-tools;28.0.3" \
  "build-tools;29.0.0" \
  "build-tools;29.0.1" \
  "build-tools;29.0.2" \
  "build-tools;29.0.3" \
  "build-tools;30.0.0" \
  "build-tools;30.0.1" \
  "build-tools;30.0.2"
```

`30.0.2`までしかないみたいです👀

ただ、ローカル環境で`compileSdk`を`30`に設定していて、**`buildToolsVersion`を指定していない、もしくは最新である`30.0.3`を指定している場合**は、今回のタイトルにもあるようなエラーが出てしまいそうです。

```
What went wrong: Could not determine the dependencies of task ':app:mergeDebugAssets'. > Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'.
> Could not create task ':app:minifyReleaseWithR8'.
> 'void org.apache.commons.compress.archivers.zip.ZipFile.(java.nio.channels.SeekableByteChannel)'
```
https://stackoverflow.com/a/68683944

一見`buildToolsVersion`周りとは関連がなさそうなエラー内容なのでハマりました。。

対応としては、下記の方の`Dockerfile`から作られるDockerイメージを参照していくのがいいかもです

https://github.com/circleci/circleci-images/blob/staging/android/Dockerfile.m4

`30.0.3`が追加されたコミット

https://github.com/circleci/circleci-images/commit/2f46fd4ef6165a77246da7804ee06324ec7dbe9d#diff-f60ed56a9c8275894022fe5a7a1625c33bdb55b729bb4e38962af4d1613eda25

とりあえずこちらのdigestの最新版を入れたら動きました！
https://hub.docker.com/r/circleci/android/tags?page=2&ordering=last_updated

`circleci/android@sha256:9810ea004180253c2bc75e67c9c8bff85e3da2da3bcf45d976e4906ad99c7d05`


これでJetpack Composeが進められる！🎉 
Happy Composing!
Forkからgithubの認証が通らなくなったのでOAuth認証に切り替えた

Forkインストール時にどういう設定を行ったのか覚えてないのですが、[8月13日のアップデート](https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/)で、Forkからpushできなくなりました。どうやらユーザ/パスワード認証にしてたみたいですね。

OAuth認証が一番手っ取り早く解決できると思うので、以下に手順を買いておきます。
Fork > Accounts... > GitHub
にて、GitHubのアカウント名とパスワードを入力します。

そうすると、以下のように認証が通るのでプッシュができるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561891/c581155c-385c-1bd1-01c6-7b8317792b1f.png)
【youtube_dl】 ERROR: requested format not availableの解消方法

# はじめに
* 授業で使えそうな動画を一括ダウンロードしたい。(著作権に関しては、記事後半で述べました。)
* youtube_dlで動画をダウンロードするpythonスクリプトを書いているときに、ちょっとしたことでハマった。
* 調べても日本語の記事が見つけられなかったから、備忘録も兼ねて書いておく。

## エラーが出たコード(該当部分のみ、全体はページ下部で)
```python
import youtube_dl

path = "動画のURL"

ydl = youtube_dl.YoutubeDL({'outtmpl': '%(id)s%(ext)s','format':'137+140'})

with ydl:
  result = ydl.extract_info(
    path,
    download=True
   )
```

## 出てきたエラー
```
ERROR: requested format not available
(中略)
youtube_dl.utils.DownloadError: ERROR: requested format not available
```


## いつエラーが起こるか
* このスクリプトで、うまく行く時もあればうまくいかない時もあった。
* 新しい動画だとうまくいく、2〜3年前の動画だとエラーになる。

## 原因と解決方法
### 原因
* エラー的に、`format`がだめなんだろうなあとあたりをつけて調べた。
* formatについては、[このサイト](https://enctools.com/youtube-dl-format/)で調べた。
* 投稿元の動画の画質(サイズ)によって、使えるフォーマットに縛りがある(考えれば当たり前か)。
  * ネット上の色々なサイトをもとになんとなく`'format':'137+140'`としていたのが良くなかった。

### 解決方法
* [公式リファレンスのフォーマットに関する部分](https://github.com/ytdl-org/youtube-dl#format-selection)に書いてあるとおり、とりあえずその動画でできる最高画質でダウンロードしたいときは、`'format':'best'`とすれば良いみたい。


## 修正を加えた完成品

[こちら(Githubへ飛びます)](https://github.com/phys-ken/mov_controller_apps/blob/master/dl.py)

**注意** 違法ダウンロードを勧めているわけではありません、授業でネット上のコンテンツを授業で利用するときは、教員が正しく理解してからにしましょう。
> Q2−3インターネット上（教材用動画サイト、あるいは動画共有サイト（ユーチューブ等））に、教材として使えそうな動画がありました。授業で使用し、可能であれば他の学級とも共有していきたいと思うのですが、授業で視聴することや、ダウンロードすることに問題はないでしょうか？
>>A2−3
公表された著作物は授業等に供することを目的とする場合は、第35条の権利制限で著作権者の許可なく利用することができます。教材用動画サイトはその用法を守れば問題ありませんが、動画共有サイトは、注意が必要です。違法動画が含まれているかもしれません。
(中略)
＜動画共有サイトの場合＞
ユーチューブやニコニコ動画等の誰もが投稿出来る動画サイトは、著作権侵害の温床となっています。令和2年に「著作権法の一部を改正する法律」が成立し、違法なインターネット配信による音楽・映像を違法と知りながら複製することを私的使用目的でも権利侵害とする改正が行われました（第30条第2項〜第4項）。こうしたサイトに公開されている映像が、確実に合法なものか違法なものか見分ける方法がありませんので、利用には十分ご注意ください。

[【参考】日本著作権教育研究会のQ &A](https://www.jcea.info/Q&A.html)

### できること
* 初回実行時にcsvファイルを作成、２回目実行時にcsvの内容に基づいて動画をダウンロード
* その後、csvの内容に基づいて動画の名前を変更してフォルダに保存
git-bashをVisual Studio 2019 のTerminalに追加する手順

## 前書き

Visual studio 2019の最終版(Version 16.11.1)が出たので久しぶりにアップデートしたところ、右クリックのコンテキストメニューに「ターミナルで開く」という機能が（いつからか？）追加されていました。

![open-terminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/16273a4d-8c47-2e2f-12be-b808c3444a4e.png)

デフォルトのシェルはPower-Shellでした。。VSCodeで使い慣れているgit-bashにするための設定手順を記載します。

![powershell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/9a77ba57-cd5c-fe2a-a550-348f4b6ee30e.png)


## 設定画面を開く

* 歯車マークをクリックして設定画面を開きます。
下図は**「追加」**ボタンを押した直後の画面です。
![add-shell1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/dccc10e1-497d-5ad8-664a-2ba42317ff64.png)

* **「シェルの場所」**を変更します。
テキストボックスから直接入力しても適用ボタンが有効にならないので、大人しく**「...」**ボタンをクリックしてファイル選択ダイアログを表示します。
指定するパスは「`"C:\Program Files\Git\git-bash.exe"`」ではなく「`"C:\Program Files\Git\bin\sh.exe"`」です。間違えると別ウィンドウで開いてしまいます。

![select-bash.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/20de9d50-4e9f-6e3c-1463-b474e4a41cf4.png)

* 引数に「`-l -i`」をセットします。
「.bash_profile、.bashrc」が読み込まれるので、エイリアスなど使えるようになります。

![add-shell2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/8f9c748b-ca0f-7c8d-c833-a70603b09c19.png)


| 項目名 | 設定値 | 備考 |
|:-----------|------------|:------------|
| 名前| git-bash| |
| シェルの場所| "C:\Program Files\Git\bin\sh.exe"| 要：ボタンでダイアログを開いて選択|
| 引数| -l -i|          |
ActiveRecordのhook(after_create / after_create_commit)とtransaction

## 気になったこと
ActiveRecordのhookはかなり便利で、レコードのCRUDに合わせてさまざまな処理を入れることができます。
hookした処理内でエラーが発生した時のレコード操作はrollbackされるのかちょっと気になったので確認しました。

## 結論
after_create
=> hook内でエラーが発生した時にはレコード操作がrollbackされる

after_create_commit
=> hook内でエラーが発生してもレコード操作はcommitされている(それはそうですよね)

## 前提
ActiveRecordをテストするので何もないテーブルを作成。

```rb
create_table :tests do |t|
  t.string :hoge
end
```

## after_create

```rb
class Test < ActiveRecord::Base
  after_create :raise_error

  def raise_error
    raise 'after create error'
  end
end
Test.create!
```

after_createでraiseしつつレコードを作成してみます

#### 実行結果
```bash
[1] pry(main)> class Test < ActiveRecord::Base
[1] pry(main)*   after_create :raise_error
[1] pry(main)*
[1] pry(main)*   def raise_error
[1] pry(main)*     raise 'after create error'
[1] pry(main)*   end
[1] pry(main)* end
:raise_error
[2] pry(main)> Test.create!
   (7.9ms)  SET NAMES utf8mb4 COLLATE utf8mb4_bin,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.6ms)  BEGIN
  Test Create (0.7ms)  INSERT INTO `tests` VALUES ()
   (2.0ms)  ROLLBACK
RuntimeError: after create error
from (pry):5:in `raise_error'
```

transaction内でROLLBACKが発生しているのがわかります。

## after_create_commit

```rb
class Test < ActiveRecord::Base
  after_create_commit :raise_error

  def raise_error
    raise 'after create commit error'
  end
end
Test.create!
```

#### 実行ログ

```bash
[1] pry(main)> class Test < ActiveRecord::Base
[1] pry(main)*   after_create_commit :raise_error
[1] pry(main)*
[1] pry(main)*   def raise_error
[1] pry(main)*     raise 'after create commit error'
[1] pry(main)*   end
[1] pry(main)* end
:raise_error
[2] pry(main)> Test.create!
   (17.7ms)  SET NAMES utf8mb4 COLLATE utf8mb4_bin,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.8ms)  BEGIN
  Test Create (0.4ms)  INSERT INTO `tests` VALUES ()
   (2.9ms)  COMMIT
RuntimeError: after create commit error
from (pry):5:in `raise_error'
```

SQLのCOMMITが入った後にエラーがraiseされているのがわかります。
Cloud Firestoreにraspberry piからデータを追加する

# はじめに
FirebaseにRaspberry Piからデータを突っ込む方法を記載します。


# 環境
* macOS Big Sur 11.5
* Raspberry Pi Zero WH(Raspberry Pi OS)
* Firestore
* macOS(Python):3.8.5
* RaspBerryPi(Python):3.7.5

Firebase環境の構築等は今回は説明を省略します。Firebaseの状態は以下の通りです。
![firebaseImg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423321/2d479209-1a7e-7de5-6462-b9f7e6ffcebe.jpeg)


# 手順
1. macでFirebaseにデータを追加する
1. RaspBerryPiでFirebaseにデータを追加する

# 1.　macでFirebaseにデータを追加する
1-1.　ドキュメントのフィールド値を決める
定期的に温度をFirebaseに上げる仕組みとするため、具体的に以下のようにFirebaseの値を決める

* Collection: Environment
* Document: 自動
* Field: temperatura,time

1-2. Firebaseへアクセスする環境を整える

* @yusukeito58 さんの[Cloud FirestoreのデータをPythonで取得する]
(https://qiita.com/yusukeito58/items/c77feaa25fbbe37e9953)を参考に環境を整える
* 以下のコードで更新を行えることを確認する

~~~python:reportTemperature
import time
import datetime
import os
import csv

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
from firebase_admin import storage

cred = credentials.Certificate("Firebase秘密鍵")

app = firebase_admin.initialize_app(cred)

db = firestore.client()

today = datetime.datetime.fromtimestamp(time.time())
date  = today.strftime('%Y%m%d%H%M%S')

data = {
     u'time':date,
     u'temparature':35.5 #この値はデバイスから取得するよう変更が必要
}

db.collection(u'environment').add(data)
~~~

# 2.　RaspBerryPiでFirebaseにデータを追加する
2-1.　[macでFirebaseにデータを追加する](# 1.　macでFirebaseにデータを追加する)にデータを追加するで作成したreportTemperatureをraspberry piにアップロードする

今回は、「reportTemperature.py」と「Firebase秘密鍵」の２種類

~~~bash
scp -P 22 reportTemperature.py pi@raspberrypi.local:/home/pi
scp -P 22 Firebase秘密鍵 pi@raspberrypi.local:/home/pi
~~~

2-2. Raspberry Pi でも1-2の初期設定を行う
2-3. Raspberry Pi をテザリングまたはWirelessLANで繋ぐ
テザリングまたはWirelessLANの設定は、@hishi さんの[Raspberry Pi Zero(W, WH)のセットアップ]
(https://qiita.com/hishi/items/8bdfd9d72fa8fe2e7573)を参照
2-4. 動作確認を行う

# まとめ
先人の情報を使用して、ほとんど困らずに温度を更新する仕組みができた。Firebaseのデータベース定義について、定石がわからないが、今回のデータではドキュメント名を自動でふり、そのフィールドに時間と温度を持たせることでコレクションとして扱うことにした。
セル上に配置したUISwicth rxで管理

## セルに配置したUISwitchの管理メモ

セル内でDisposeBagを定義

```swift
class SwitchCell: UITableViewCell {
    @IBOutlet weak var `switch`: UISwitch!
　　　　　　　　var disposeBag = DisposeBag()

    override func prepareForReuse() {
        super.prepareForReuse()
        self.disposeBag = DisposeBag() // ここで毎回生成
    }
}
```

セル表示時に処理を設定

```swift
    // セル
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        guard let cell = tableView.dequeueReusableCell(withIdentifier: R.reuseIdentifier.switchCell, for: indexPath) else { return UITableViewCell() }
        
        // 初期値はここで設定
        cell.switch.setOn(false, animated: false)
        
        // スイッチ ON/OFF 処理
        cell.switch.rx.controlEvent(.valueChanged)
            .withLatestFrom(cell.switch.rx.value)
            .subscribe(onNext : { bool in
                print(bool)
            }).disposed(by: cell.disposeBag)
        
        return cell
    }
```
[Apex] 文字列の比較における「==」と「equals」の違い

## TL;DR
英数字以外の文字が含まれる文字列の比較にはStringクラスのequalsを使いましょう。

「==」はロケールによって結果が違います。
ロケールが日本語でも、結果が感覚とは異なる場合があります。
(例えば、「あいうえお」と「ぁぃぅぇぉ」は等価なのに対し、「アイウエオ」と「ｱｲｳｴｵ」は等価でない。)

## 「==」と「equals」の違い
#### 大文字小文字の区別
「==」は大文字小文字などの区別がありません。
「equals」は完全におなじ文字かどうかで判定されます。
大文字小文字の違いだけを無視したい場合は「equalsIgnoreCase」を使うことができます。

#### nullのあつかい
「==」は文字列がnullであっても使用できます。
「equals」はインスタンスメソッドであるため、インスタンスがnullだとNullPointerExceptionとなります。

#### ロケールによる違い
「==」はロケールによって結果が変わります。
「equals」は変わりません。
このため、英数字以外の文字列を含む可能性がある場合、equalsを使うべきです。

### 実際の比較
「==」を使用した場合、英字の大文字小文字以外にも、区別されない文字種があることがわかります。

```apex:日本語のロケール下での実行結果
System.debug('ABC' == 'abc'); // true ←注意！！
System.debug('ABC' == 'ＡＢＣ'); // 半角と全角 true ←注意！！
System.debug('ABC' == 'ａｂｃ'); // 半角と全角 true ←注意！！
System.debug('あいうえお' == 'アイウエオ'); // true ←注意！！
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // true ←注意！！
System.debug('アイウエオ' == 'ｱｲｳｴｵ'); // false

System.debug('ABC'.equals('abc')); // false
System.debug('ABC'.equals('ＡＢＣ')); // 半角と全角 false
System.debug('ABC'.equals('ａｂｃ')); // 半角と全角 false
System.debug('あいうえお'.equals('アイウエオ')); // false
System.debug('あいうえお'.equals('ぁぃぅぇぉ')); // false
System.debug('アイウエオ'.equals('ｱｲｳｴｵ')); // false

System.debug('ABC'.equalsIgnoreCase('abc')); // true
System.debug('A'.equalsIgnoreCase('Å')); // false
System.debug('ABC'.equalsIgnoreCase('ＡＢＣ')); // 半角と全角 false
System.debug('ABC'.equalsIgnoreCase('ａｂｃ')); // 半角と全角 false
System.debug('あいうえお'.equalsIgnoreCase('アイウエオ')); // false
System.debug('あいうえお'.equalsIgnoreCase('ぁぃぅぇぉ')); // false
System.debug('アイウエオ'.equalsIgnoreCase('ｱｲｳｴｵ')); // false
```

## 「==」のロケールによる違い
「==」の結果はコンテキストユーザのロケールの設定によって異なります。

```apex
// ロケールが日本語の場合
System.debug('ABC' == 'abc'); // true
System.debug('ABC' == 'ＡＢＣ'); // 半角と全角 ★true
System.debug('ABC' == 'ａｂｃ'); // 半角と全角 ★true
System.debug('あいうえお' == 'アイウエオ'); // ★true
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // ★true
System.debug('アイウエオ' == 'ｱｲｳｴｵ'); // false

// ロケールが英語(アメリカ合衆国)の場合
System.debug('ABC' == 'abc'); // true
System.debug('ABC' == 'ＡＢＣ'); // 半角と全角 ★false
System.debug('ABC' == 'ａｂｃ'); // 半角と全角 ★false
System.debug('あいうえお' == 'アイウエオ'); // ★false
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // ★false
System.debug('アイウエオ' == 'ｱｲｳｴｵ'); // false
```

ロケールはユーザの設定画面から変更が可能です。
![ロケール設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/6f91b731-32d8-c445-0696-00c729768537.png)

## 参考
* 「Java とは異なり、Apex の == はユーザ定義の型を除き、参照が同等であるかではなく、オブジェクト値が同等であるかを比較します。」「Apex は SOQL 比較セマンティックを使用するため、String の結果はコンテキストユーザのロケールに従って照合され、大文字と小文字は区別されません。」([式の演算 | Apex開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.232.0.apexcode.meta/apexcode/langCon_apex_expressions_operators_understanding.htm))
* 「渡された文字列が null ではなく、現在の文字列と同じバイナリ文字シーケンスを表す場合、true を返します。」([Stringクラス | Apex開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_string.htm#apex_System_String_equals))
IBM Semeru Runtimes 無償で利用できる新しいJava実行環境

OpenでFreeなJava実行環境を提供してきたOpenJDKのディストリビューション[AdoptOpenJDK](https://adoptopenjdk.net/)は，2021年7月末で更新を終了しました。8月以降は[Eclipse Adoptiumプロジェクト](https://adoptium.net/)および[IBM Developerサイト](https://developer.ibm.com/languages/java/semeru-runtimes/)から配布が継続されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60041/791317d7-34c2-51cd-24c7-9caf2e0f90f4.png)

AdoptOpenJDKでは，OpenJDKの標準のJVMであるHotSpot VMを含んだものの他に，もう一つのJVMであるOpenJ9を含んだディストリビューションも配布していました。HotSpot VMは，もともとSun Microsystemsが実装していたものに[JRockit](https://en.wikipedia.org/wiki/JRockit)のコードなどが組み込まれたJVMです。また[OpenJ9](https://www.eclipse.org/openj9/)は，IBMが開発を続けてきた独自JVMです。いまは，どちらのJVMもOSS化され，オープンなコミュニティで開発が継続されています。

AdoptOpenJDKがプロジェクトの独立性をたもちながら安定的に活動していくためには，[文化的そして法律的な基盤が必要](https://blog.adoptopenjdk.net/2020/06/adoptopenjdk-to-join-the-eclipse-foundation/)とされていました。そのため，プロジェクトはEclipse Foundationの傘下に入り[Adoptiumプロジェクトとして再スタート](https://blog.adoptopenjdk.net/2020/12/eclipse-adoptium-projects-ready-for-community-review/)することになります。ですが，[その過程](https://www.eclipse.org/lists/openj9-dev/msg00084.html)で[様々な事情](https://www.reddit.com/r/java/comments/l5m3p6/eclipse_to_host_only_tck_compliant_java_se/)があり，AdoptiumプロジェクトではOpenJ9を含んだディストリビューションを配布することができなくなってしまいました。

そこで，2021年8月のAdoptium移行に合わせ，OpenJDK＋OpenJ9はIBM Developerサイトで[公開されるように](https://developer.ibm.com/blogs/semeru-runtime-quality-you-can-depend-on/)なりました。ランタイムの名前も，AdoptOpenJDKからIBM Semeru Runtimesに変更になります。ちなみにSemeruというのは，[インドネシアJava島の最高峰](https://en.wikipedia.org/wiki/Semeru)の名前から取られています。なお，Adoptiumで配布されるランタイムはEclipse Temurinという名前になります。こちらは”Runtime"のアナグラムが由来です。

IBM Semeru Runtimesでは二つのランタイムが[提供されて](https://developer.ibm.com/blogs/introducing-the-ibm-semeru-runtimes/)います。

- IBM Semeru Runtime Open Edition
  - OSSライセンス（[クラスパス例外付きGPLv2](https://openjdk.java.net/legal/gplv2+ce.html)）で提供
  - [Eclipse AQAvit](https://projects.eclipse.org/projects/adoptium.aqavit)品質保証テストを通過
- IBM Semeru Runtime Certified Edition
  - IBMのライセンスで提供
  - Eclipse AQAvit品質保証テストを通過
  - [TCK](https://en.wikipedia.org/wiki/Technology_Compatibility_Kit)を通過

Open Editionは，OSSライセンスで提供されますので，これまでのAdoptOpenJDKで配布されていたランタイムと同様に，どなたでも無償でご利用いただくことができます。Certified Editionも無料で使用できますが，こちらはJavaの商標と共に提供するにあたって必要となるTCKによるテストをパスしたエディションで，IBM独自ライセンスで提供されます。両方エディションに機能的な差はありません。

両エディションとも，サポートが必要な場合には，[IBM Runtime for Business](https://www.ibm.com/jp-ja/cloud/support-for-runtimes)を契約いただければ，IBMから商用サポートが提供されるようになります。

サポート期間は，2021年8月現在，[以下のように](https://www.ibm.com/support/pages/semeru-runtimes-support/)なっています。

|IBM Semeru Runtimesバージョン|リリースタイプ|サポート終了予定|
|:---|:---|:---|
|16|Feature|2021年9月|
|11|LTS|2024年10月|
|8|LTS|2026年5月|

2023年3月現在は以下のようになっています。

|IBM Semeru Runtimesバージョン|リリースタイプ|サポート終了予定|
|:---|:---|:---|
|17|LTS|2027年10月|
|11|LTS|2024年10月|
|8|LTS|2026年9月|

2024年3月現在は以下のようになっています。

|IBM Semeru Runtimesバージョン|リリースタイプ|提供終了予定|
|:---|:---|:---|
|21|LTS|未定|
|17|LTS|未定|
|11|LTS|2026年9月|
|8|LTS|2026年9月|

IBM Semeru Runtimesは，[こちらからダウンロード](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/)することができます。
ip ruleコマンドでのポート指定のメモ

ip ruleでは以下のような方法でポートの指定ができる

```bash
sudo ip rule add ipproto tcp dport 80 blackhole
```
確認

```
$ wget -O - http://www.google.com
--2021-08-21 11:30:24--  http://www.google.com/
www.google.com (www.google.com) をDNSに問いあわせています... 172.217.25.68, 2404:6800:4004:818::2004
www.google.com (www.google.com)|172.217.25.68|:80 に接続しています... 失敗しました: 無効な引数です.
www.google.com (www.google.com)|2404:6800:4004:818::2004|:80 に接続しています... 失敗しました: ネットワークに届きません.
```

ポートを指定するときに使うもの
- ipproto
プロトコル
- sport
送信元ポート 
- dport
送信先ポート

ポートを指定する際は 80-81のように範囲で指定することもできる
数理計画（MATLAB①）

MATLABで数理計画（最適化）を行う場合、”Optimize　ToolBox”必要になる。
MATLABで”EXCEL①”で記載したモデルで求解してみる。

``` 
【問題：条件】
　　一週間の製造計画について考えます。（土曜日から金曜日）
　　出荷は翌日朝から実施するため、前日に必要量を製造する。
　　翌週のために金曜日の貯蔵量を守る。

　　目的：製造量を最小化
　　説明変数：製造量
　　制約条件：
　　　・製造量　≦　一日の最大製造量
　　　・製造量　≧　一日の最小製造量
　　　・貯蔵量　≦　貯蔵できる最大量
　　　・貯蔵量　≧　翌日の出荷量
　　　・最終貯蔵量　≧　翌週のための貯蔵量

　　貯蔵量　＝　前日の貯蓄量＋製造量-出荷量
```

```
まずは、説明変数を定義しますが、EXCELの時のように自動計算（貯蔵量）はしてくれないので、貯蔵量も説明変数として考えます。
　①貯蔵量　　　　　　　　　　　　Xhld　　
　②製造量　　　　　　　　　　　　Xgen

MatLABでは、連続した配列で定義するため上記は”Xという名前の配列”として考える。
　Xhld →　X[1:7]
　Xgen →  X[8:14]

下記はパラメータ（固定値）として考えます。
　①出荷量　　　　　　　　　　　　Output
　②前週金曜日の貯蔵量　　　　　　Before　　　　　　
　③来週の金曜日の貯蔵予定量　　　After　　　　　　　　　
　④最大製造量　　　　　　　　　　MaxGen　　
　⑤最小製造量　　　　　　　　　　MinGen　　
　⑥最大貯蔵量　　　　　　　　　　MaxHld　　
本来であれば、引数などで汎用性を持たせるのが普通だが、ここでは固定とする。
```
Mファイル（スプリプ）として作成します。
我流のため、良い書き方ではないかもしれません。

``` sample.m
%  Xhld   1-7
%  Xgen   8-14

%%　固定データの定義
Output = [100, 150, 0, 300, 0, 400, 200];
Before = 200;
After = 100;
MaxGen = 300;
MinGen = 0;
MAXHld = 500;

%% 上下限範囲設定
MAX(1:14,1) = zeros(14,1);
MAX(1:7,1) = MAXHld;
MAX(8:14,1) = MaxGen;
MIN(1:14,1) = zeros(14,1);
MIN(1:6,1) = 0;
MIN(7,1) = After;
MIN(8:14,1) = 0;

%% 目的関数
F=zeros(14,1);
F(8:14,1) = 1

%% 整数制約
INT=1:14;

%% 等式制約
eqA=zeros(7,14);
eqB=zeros(7,1);

% 貯蔵量制約
eqA(1,1) = -1;
eqA(1,8) = 1;
eqB(1)=Output(1) - Before;

for c=2:7
    eqA(c,c) = -1;
    eqA(c,7+c) = 1;
    eqA(c,6+c) = 1;
    eqB(c)=Output(c);
end

%% 不等式制約
A=zeros(6,14);
B=zeros(6,1);

% 翌日の出荷量制約
for c=1:6
    A(c,c) = -1;
    B(c) = -Output(c+1); 
end

x = intlinprog(F,INT,A,B,eqA,eqB,MIN,MAX);

```

実行すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314982/38e988ee-b88e-bf81-94e3-bc1b17f821d4.png)


解
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314982/af26c8bc-9523-16e6-2232-ff40cccf7bed.png)

上側が貯蔵量、下側が製造量

EXCELの場合と最小値は同じですが、説明変数の値が異なることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314982/4bbe7282-79a1-c2a9-5dcd-ad3af5953fc0.png)
記憶域スペースでのPowerShellコマンドメモ

前回のエントリから研究が進んだので個人的メモです。

ProxmoxにてHDDパススルー

```
qm set 801 -virtio1 /dev/disk/by-id/ata-HP_SSD_S700_500GB_HBSA30130300484,serial=A1,backup=no
qm set 801 -virtio2 /dev/disk/by-id/ata-HP_SSD_S700_500GB_HBSA30130300485,serial=B2,backup=no
qm set 801 -virtio3 /dev/disk/by-id/ata-TOSHIBA_DT01ACA100_11HEU1VNS,serial=C3,backup=no
qm set 801 -virtio4 /dev/disk/by-id/ata-TOSHIBA_DT01ACA100_11HHM35NS,serial=D4,backup=no
qm set 801 -virtio5 /dev/disk/by-id/ata-TOSHIBA_DT01ACA100_11HMDZLNS,serial=E5,backup=no
```

記憶域プール作成

```
$Disks = Get-PhysicalDisk -CanPool $true | Sort-Object Size
$StoragePoolName = 'tank'
$StorageSubSystem = Get-StorageSubSystem
New-StoragePool -PhysicalDisks $Disks -FriendlyName $StoragePoolName -StorageSubSystemFriendlyName $StorageSubSystem.FriendlyName
```

シリアル番号でSSD/HDDタイプ付与

```
Set-PhysicalDisk -UniqueId A1 -MediaType SSD
Set-PhysicalDisk -UniqueId B2 -MediaType SSD
Set-PhysicalDisk -UniqueId C3 -MediaType HDD
Set-PhysicalDisk -UniqueId D4 -MediaType HDD
Set-PhysicalDisk -UniqueId E5 -MediaType HDD
```

SSD/HDD層を作成

```
$PerformanceTier = New-StorageTier -FriendlyName Performance -MediaType SSD -StoragePoolFriendlyName $StoragePoolName -ResiliencySettingName Mirror
$CapacityTier    = New-StorageTier -FriendlyName Capacity -MediaType HDD -StoragePoolFriendlyName $StoragePoolName -ResiliencySettingName Parity
```

最大割り当て可能領域を確認

```
Get-StorageTierSupportedSize Performance | FT @{E={$_.TierSizeMin/1GB};L="TierSizeMin(GB)"}, @{E={$_.TierSizeMax/1GB};L="TierSizeMax(GB)"}, @{E={$_.TierSizeDivisor/1GB};L="TierSizeDivisor(GB)"} -AutoSize
Get-StorageTierSupportedSize Capacity    | FT @{E={$_.TierSizeMin/1GB};L="TierSizeMin(GB)"}, @{E={$_.TierSizeMax/1GB};L="TierSizeMax(GB)"}, @{E={$_.TierSizeDivisor/1GB};L="TierSizeDivisor(GB)"} -AutoSize
```

ボリュームの作成

```
$VolumeName = 'testdisk'
New-Volume -StoragePoolFriendlyName $StoragePoolName -FriendlyName $VolumeName -StorageTierFriendlyNames $PerformanceTier.FriendlyName, $CapacityTier.FriendlyName -StorageTierSizes xxxGB, xxxxGB -FileSystem ReFS -AccessPath "E:" -ProvisioningType Fixed -AllocationUnitSize 4KB
```
iOSの実機でビルド実行するとProvisioning profileが証明書に含まれていないとのエラーが出る場合の解決方法

こんにちは。[もぐめっと](https://mogmet.com)です。

本日の投稿は問題解決tips系の投稿です。

## 結論

iOS実機をビルドしてデバッグしようとするとprovisioning profileがうまくあたらなくてビルドできないので、端末の証明書を再発行するとうまくいく

## エラー内容

最近Flutterをやっているのですが、別端末でiosを実行しようとすると下記のようなエラーがでました。

```
  error: Provisioning profile "iOS Team Provisioning Profile: com.mogmet" doesn't include signing certificate "Apple Development: Mog Met (XXXXXXXX)". (in target 'Runner' from project 'Runner')
```

ちゃんとAutomatically manage signingにチェックが入って組織も問題なさそうなのにこのエラーが出ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/a836d232-04b9-d395-f1b1-606bef92339b.png)


原因としては証明書をfastlane matchで管理しているのですが、match nukeとかで他の証明書などの環境を掃討したのでこの現象に陥ったっぽいです。

## 解決方法

解決方法は至って簡単です。
端末の証明書を再発行するだけです。

preferencesを開き、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/17e1f67d-0f00-0b6b-e5d8-a1044696689e.png)

対象の組織を選んで、「Manage Certificates」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/0b3d697e-639f-744c-eb4c-51643fbdcb8a.png)

左下の+ボタンから「Apple Development」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/1fe8e1ee-e1b5-254a-9965-69844be95b53.png)

その後再度ビルドすると実機で実行できるようになります。


## まとめ

match nukeを実行した後は端末側の証明書も再発行してあげましょう。
MacOSを更新した時に 場所が変更された項目としてgroupファイルが提示された

# MaCOSを更新した時に出て来る　場所が変更された項目　の一例

MaCOSを更新した際、場所が変更されて項目として、group ファイルが提示されました。
自分で編集した覚えはありませんが、、、system_default　と差異がある。とのことなので確認してみます。

```最終的には groupファイルを group.system_default で上書きしてます。```

## 差分の確認

### diff で確認

```_trustd:*:282:_trustd``` が足りないっぽい。

```diff
kichise@imac /etc % diff /Users/Shared/Relocated\ Items/Configuration/private/etc/group.system_default /etc/group
141d140
< _trustd:*:282:_trustd
kichise@imac /etc %
```

### 念の為　VSCodeでも確認

やっぱり　```_trustd:*:282:_trustd``` が足りない。

![スクリーンショット 2021-08-21 11.25.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560759/b5328c60-323c-56d7-b37d-0caff23233de.png)

## このIDが必要なのかを確認

gid ***282*** で検索したら、**/private/var/protected/trustd/** で使われてるっぽい事がわかった。
ただ、グループファイルにエントリはないのに、グループ名も解決できてるんだよな〜
そういうものなのか？？？

```shell
kichise@imac /etc % ls -ln /private/var/protected
total 0
drwxrwxrwx  7 0    0    224  4 27 14:46 sfanalytics
drwxr-xr-x  8 282  282  256  8 21 10:41 trustd
kichise@imac /etc % ls -l /private/var/protected
total 0
drwxrwxrwx  7 root     wheel    224  4 27 14:46 sfanalytics
drwxr-xr-x  8 _trustd  _trustd  256  8 21 10:41 trustd
kichise@imac /etc %
```

## 対処

system.default の値を採用した方が良さそうなので、gropu.system_default を　/etc/group に上書きすることにしました。

```shell
kichise@imac /etc % ls -l group
-rw-r--r--  1 root  wheel  3168  1  1  2020 group
kichise@imac /etc % ls -l /Users/Shared/Relocated\ Items/Configuration/private/etc/group.system_default
-rw-r--r--  1 root  wheel  3190  1  1  2020 /Users/Shared/Relocated Items/Configuration/private/etc/group.system_default
kichise@imac /etc % sudo cp /Users/Shared/Relocated\ Items/Configuration/private/etc/group.system_default /etc/group
Password:
kichise@imac /etc %
```

終わり
【Docker】全部小文字なのに "repository name must be lowercase" エラー

> ローカルにクローンしたリポジトリを Docker にマウントして実行しようとすると、「リポジトリは小文字で」エラーがでます。
>
> ```shell-session
> $ docker run --rm -it -v $(pwd):/app golang:alpine /bin/sh
> docker: invalid reference format: repository name must be lowercase.
> See 'docker run --help'.
> ```

でも、**リポジトリのディレクトリ名は小文字**なんです。

[「docker: invalid reference format: repository name must be lowercase」でググって](https://www.google.com/search?q=docker%3A+invalid+reference+format%3A+repository+name+must+be+lowercase)も、リポジトリを別箇所に移動したり、Windows 情報ばかりだったので Linux/macOS の情報として自分のググラビリティとして。

## TL; DR <sub><sup>（今北産業）</sup></sub>

1. 理由： リポジトリの「パス」に半角スペースが含まれています
1. 原因： <br>Docker のボリューム（ディレクトリ）のマウントは、**<font color=darkorange>絶対パスである必要があります</font>**。しかし、パスが相対パスだったり、スペースが入っていると、引数を展開する際に複数の引数があると判断されてしまい構文（`format`）エラーになります
1. <font color=darkorange>対処： パスを**ダブルクォート**して 1 つの引数として扱います。</font>

    ```diff:ダブルクォートで囲う
    - $ docker run --rm -it -v $(pwd):/app golang:alpine /bin/sh
    + $ docker run --rm -it -v "$(pwd)":/app golang:alpine /bin/sh
    ```

:::note info
<code>pwd</code> は Linux/macOS の UNIX 系コマンドで、["Print Working Directory" の略](https://www.gnu.org/software/coreutils/manual/html_node/pwd-invocation.html#pwd_003a-Print-working-directory) です。

その名の通り「現在の作業ディレクトリのパスを返す」コマンドで、"password" の略ではありません。カレント・ディレクトリの絶対パスを表示する際によく使われます。

また、<code>$(...)</code> は <code>...</code> を実行した結果を返すコマンドです。`...` が `ls` の場合は `$(ls)` とすることで、`ls` コマンドの結果を得られます。<code>()</code> でサブシェル（別プロセス）として実行し、<code>$</code> で内容を出力します。

シェルの構文であるため、<code>bash</code> でも使えるコマンドなので、Windows でも WSL2 がインストールされていれば <code>Bash on Windows</code> でも使える tips になります。
:::
ActiveRecord::ConnectionNotEstablishedの解決方法

下記のようなエラー文が出たので、一つづつ紐解いて対処していく。

```
ActiveRecord::ConnectionNotEstablished (could not connect to server: No such file or directory

Is the server running locally and accepting

connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
```

> ActiveRecord::ConnectionNotEstablished

dbとの接続がうまくいっていないという意味らしい。

> Is the server running locally

local環境でサーバーは動いているか

> and accepting connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

もしくはUnixドメインソケットの.s.PGSQL.5432に繋がっているか？

## **環境**

- macOS Big Sur 11.5.2
- MacBook Pro (Retina, 13-inch, Early 2015)
- postgres (PostgreSQL) 13.3
- rails 6.1.4

## 問題の場所と対処

---

データベースが正常に起動しているのかを確認するために、postgresqlの状態を確認してみる

```
$ postgres -D /usr/local/var/postgres
2021-08-21 10:57:07.740 JST [41676] FATAL:  lock file "postmaster.pid" already exists
2021-08-21 10:57:07.740 JST [41676] HINT:  Is another postmaster (PID 1188) running in data directory "/usr/local/var/postgres"?
```

FATALを紐解いてみる。どうやら起動時に作成されるロックファイルがすでに存在していて、エラーになっている模様。

前回の起動情報をkillしないと新しく起動できなくなるみたいだ。

postmaster.pidを削除＆postgresの再起動をかけると治ると[記事](https://stackoverflow.com/questions/19828385/pgconnectionbad-could-not-connect-to-server-connection-refused)に書いてあるので、下記コマンドを入力する。

```jsx
$ rm /usr/local/var/postgres/postmaster.pid
$ brew services restart postgresql
Stopping `postgresql`... (might take a while)
==> Successfully stopped `postgresql` (label: homebrew.mxcl.postgre
==> Successfully started `postgresql` (label: homebrew.mxcl.postgre
```

すると、無事再起動できました！！

[Postgresで発生したエラー「PG::ConnectionBad: 〜"/tmp/.s.PGSQL.5432"?」に対処した - Qiita](https://qiita.com/great084/items/98c83364f246473249c4)

[PG::ConnectionBad - could not connect to server: Connection refused](https://stackoverflow.com/questions/19828385/pgconnectionbad-could-not-connect-to-server-connection-refused)
ITメモ

### 環境変数の設定方法

```terminal
sample@MacBook-Pro ~ % X
zsh: command not found: X
sample@MacBook-Pro ~ % echo $X
100
sample@MacBook-Pro ~ % 
```

echo ＄変数名　で変数を呼び出すことができる。

```terminal
sample@MacBook-Pro ~ % echo $SHELL
/bin/zsh
```

/bin/zsh <= シェル
 .zshrcというシェルファイルに
`TEST=”12345″`と記述して環境変数を作成することができる。

ターミナルから直接シェルファイルに環境変数を書き込む方法

```terminal
echo 'export TEST= "12345"' >> ./.zshrc
```
(git) 現在のブランチの取得方法

# (git) 現在のブランチの取得方法

## Git 2.22 または以降

```
git branch --show-current
```

## Git 2.22 以前

```
git rev-parse --abbrev-ref HEAD
```

または

```
git symbolic-ref --short HEAD
```

## 参考サイト

https://stackoverflow.com/questions/6245570/how-to-get-the-current-branch-name-in-git
SQLAlchemyで動的にテーブルクラスを作る方法

SQLAlchemyでテーブルクラスを作るときに、既存のテーブル情報を使って動的に作り出したいニーズがあって、ややハマったので方法をメモしておきます。

# 普通の作り方

公式ドキュメントなどでは、既存の`user`テーブルにマッピングする`User`クラスはこのような作り方が紹介されています。`declaratibe_base`という機能を使うことで、`__tablename__`で指定したテーブルと自動的にマッピングが作られるというわけです。

```python
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base

# declarative base class
Base = declarative_base()

# an example mapping using the base
class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    nickname = Column(String)
```

# 今回やりたかったこと

- `__tablename__`の部分を可変にしたい
- 属性として持つ`Column`を既存のテーブルに合わせて可変にしたい

対象のテーブル名を切り替えながらいろいろ処理する機能が作りたかったということです

```python
# create_engineのところは省略
bind = create_engine(...)

Base = declarative_base(bind)

name = ここに既存のテーブル名を指定

namespace = {
    '__tablename__': name,
    '__table_args__': {'autoload': True},
}
class_ = type('TableClass', (Base,), namespace)
```

これで最初の例と同様のテーブルクラスが作成できます
`type`の第一引数の`'TableClass'`という名前は適当です

型を確認すると`Base`を継承して作った場合と同じです

```python
print(type(class_))
```

```xml
<class 'sqlalchemy.orm.decl_api.DeclarativeMeta'>
```

varsで内容を見るとテーブルに存在する列情報のほか、`__mapper__`属性もあります

## 補足

指定したテーブルが存在しないと`sqlalchemy.exc.NoSuchTableError`が出ます

## 参考

https://try2explore.com/questions/jp/10696747

https://qiita.com/takada-at/items/9f008e8f394235b72c6e
【Vuex】getterに引数を渡す【TypeScript】

## 最初に
表題の通りですが、getterに引数を渡す実装方法のご紹介です。
TypeScriptで型定義も行なっております。

## 結論（実装方法）

```getters.ts
import { Getters } from 'vuex';
import { GettersInterface, StateInterface } from './type';

export const getters: Getters<StateInterface, GettersInterface> = {
    sampleGetter:(state) => (arg) => {
        // 何かしらreturnする
    },
};
```

```type.ts

// Sampleは任意のstateの型です
// 記事の本筋からは逸れてしまうので省略します
export type StateInterface = Sample;

export interface GettersInterface {
    sampleGetter: (arg: number) => string;
}
```

Vueコンポーネントからは、```this.$store.getters.sampleGetter(1)```のような形で呼び出すことができます。

## 解説

#### getter

```getters.ts
sampleGetter:(state) => (arg) => {
  // 何かしらreturnする
}
```

getterの返り値を関数にすることで、引数を渡すことができます。

参考:[メソッドアクセススタイル](https://vuex.vuejs.org/ja/guide/getters.html#%E3%83%A1%E3%82%BD%E3%83%83%E3%83%88%E3%82%99%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9)

##### type

```type.ts
sampleGetter: (arg: number) => string;
```

実装そのままですが、関数を返り値にする型を定義すればOKです。
上記だとnumber型の引数を受け取って、stringを返す関数になります。

## 最後に
VueはVueで楽しい。
[子育てIoT][環境構築]Raspberry PIでNode.jsなど

## 背景
私事ですが、そろそろ第一子が生まれます。
そんな子供に私ができることはと考えたときに思いついたのが、
IoTです。

子供の成長の記録を撮ったり、健康状態を確認したり、子供のおもちゃを作ったりなど。
まだ、何も作ってませんが何かできるのではと思ったのです。

本記事はタンスに封印していた、「Raspberry Pi 3 Model B」のホコリを払って、Node.jsをセットアップするまでの手順書（ただのメモになります）。
vim,zshは私のメインPCのMacと同じ構成にしたかったのでインストールしただけです。
まったくもって必須ではありません。

ちなみに、Raspberry Piの開発は一般的にはPythonの方が参考文献も多いと思いますので、
参考までに御覧ください。

間違ってたらぜひご一報ください。

## OSセットアップからSSH接続までの作業
他に沢山わかりやすいサイトがありますので、ぜひそちらを御覧ください。

## vim
* インストール<br>

```
apt-get install vim
```
* vimの設定<br>
とりあえず jj -> ESCの設定
~/.vimrcを編集

```
inoremap <silent> jj <ESC>
```

## zsh
* インストール<br>
mac環境に合わせるためにzshをインストール。
といっても、既にインストールされてるみたいなのでアップデートとshellの切り替え

```
//　　　　インストール＆アップデート
sudo apt-get install zsh
//  ｓｈのパスを /bin/bash -> /bin/zsh　に変更
chsh
```
## nodebrew
* インストール<br>
macとなるべく同じ環境に揃えたく、nodebewをインストール
公式サイトより以下のコマンドを実行(https://github.com/hokaccha/nodebrew)

```
// DL+Install
curl -L git.io/nodebrew | perl - setup
//　　環境変数にパスを登録
export PATH=$HOME/.nodebrew/current/bin:$PATH
//　　　環境変数のPATHに登録されていればOK
printenv
```

## Node.js
* 既にインストールされてないかの確認<br>

```
node -v
```

どうやら入ってそう

* アンインストール<br>

```
sudo apt remove --purge nodejs
```

* インストール<br>

```
//　安定版をインストール
nodebrew install stable
// 利用バージョンとして設定
nodebrew use <version>
```

## yarn
既にインストールされているかもしれませんが念のため、ちなみにこれもMac環境に合わせたいだけで必須ではありません。

```
npm install -g yarn
```

## 参考URL
[aptコマンドチートシート](https://qiita.com/SUZUKI_Masaya/items/1fd9489e631c78e5b007)
[Debianにzshを導入する](http://www.atelier-nodoka.net/2013/10/install-zsh-to-debian/)