OmniAICreator/Qiita-1.07M huggingface dataset:
generics覚書

structでgenericsを使う際にどういう定義をしたらよいか
迷ってChatGPT先生に教えていただいたので覚書。
また、得られた自由な型をFromトレイトを使ってどう定義すれば
よいかもChatGPT先生にお伺いした。

```rust
#[derive(Debug)]
struct MyStruct<T> {
    my_val: T,
}

impl<T> MyStruct<T> {
    fn new(val: T) -> Self {
        Self {
            my_val: val,
        }
    }
}

impl<T> From<&'static str> for MyStruct<T>
where
    T: From<&'static str>,
{
    fn from(s: &'static str) -> Self {
        Self::new(T::from(s))
    }
}

impl<T> From<String> for MyStruct<T>
where
    T: From<String>,
{
    fn from(s: String) -> Self {
        Self::new(T::from(s))
    }
}

fn main() {
    let struct1: MyStruct<&str> = MyStruct::from("string: &str");
    let struct2: MyStruct<String> = MyStruct::from(String::from("string: String"));

    println!("{struct1:?}");
    println!("{struct2:?}");
}
```
Fundamentals of Data Engineering 輪読会資料 第3回分 20230427開催

# 本記事の位置付け
こちらの勉強会　[英語で技術書を読もう：Fundamentals of Data Engineering 第3回](https://gaisaba.connpass.com/event/281425/)　に参加する際にまとめたもの。

- 今回の対象は以下
    - Chapter3「User Access: Single Versus Multitenant」
    - Chapter3「EventDriven Architecture」






# Chapter3「User Access: Single Versus Multitenant」

- アクセスの設定について
    - 複数のチーム、組織、顧客からのアクセスについての考慮点
- クラウドサービスは多かれ少なかれマルチテナント
    - サーバは共有された状態
    - 正しい設定により隔離される
- エンジニアが考慮すべき点
    - 大企業の複数部署はDWHを共有するのか？
    - 企業は大口顧客に対して同じテーブルを共有するのか？
- 考えるべき点は以下2点
    - パフォーマンス
        - クラウド内に複数テナントがある場合
            - 安定したパフォーマンスは担保されるのか
            - 隣のテナントが活発だとパフォーマンスが悪化するのか
    - セキュリティ
        - クラウド内に複数テナントがある場合
            - 顧客に別な顧客がいることを知られてはならない
            - データ漏えいを防がなければならない。
- データ隔離の戦略はシステム毎に異なる。
    - マルチテナントのテーブルを作って、（閲覧時は）ビューで隔離するなら、ビューからデータ漏えいがでないようにしなければならない
- ベンダーのドキュメントを精読し、リスクを見極めるべきである。


# Chapter3「Event-Driven Architecture」

- ビジネスではイベント（何らかの状態を変更させるもの）が発生する。
    - 新規顧客獲得
    - 顧客からの新規注文
    - 製品やサービスについての注文
- ワークフローは3つの部分に要約できる（boiled　down）
    - 生成（データ元）
    - 経路付け（データの行き先を決定する）
    - 消費（データの終着駅）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/2f16f0e4-08c9-edec-212a-9ce5ec904d99.png)
- イベントは、イベントを消費する対象に向けて経路を決定付けられる
    - 生成と経路と消費の緩やかな繋がりの中で、それは実行される。
    - 複数のサービス間で移動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295123/b9334b8f-7ddd-0ea5-4c7c-755080010bfb.png)
【Mantine】LayoutのFlex系の使い分けについてまとめてみた🍙

## はじめに
Mantineでレイアウトを組むときに、Layoutのためのコンポーネントがいくつか用意されていますが、種類がいくつかあり似た様なものがあって、どれを使うのが最適なのか迷いがちなので、今後の自分のためにもまとめてみました。

:::note warn
この記事はFlex系のCSSを理解していることを前提としています。
:::

## Flex系のコンポーネント
Mantineドキュメントのサイドバーの`Layout`でFlex系のコンポーネントは以下のものになります。  
それぞれについて簡単な解説をしていきます。
- [Center](https://mantine.dev/core/center/)
- [Stack](https://mantine.dev/core/stack/)
- [Group](https://mantine.dev/core/group/)
- [SimpleGrid](https://mantine.dev/core/simple-grid/)
- [Grid](https://mantine.dev/core/grid/)
- [Flex](https://mantine.dev/core/flex/)

※下に行くほど自由度は増えますが、極力上の方からに最適なコンポーネントを選ぶことで、無駄のないコードが書けると思います。
※スクショ背景黄色の部分がコンポーネントを利用している箇所になります。

### Center
内包するコンテンツを縦横中央寄せにしたい時に使用します。  
propsも無いため、かなりシンプルです。

#### 利用例
![center.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/4c751fed-69b6-bb8c-d021-b8d5fafb6bb6.png)

https://mantine.dev/core/center/

### Stack
内包するコンテンツを縦積みにしたい時に使用します。  
`flex-direction: column`を指定したい場合に使えばよいです。

#### 利用例
![stack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/f1a899ab-9bd2-5b87-c93d-166ff53229a9.png)

https://mantine.dev/core/stack/

### Group
内包するコンテンツを横並びにしたい時に使用します。  
Flexのwrapの設定が必要ない時に使うものと思っておけばよさそうです。  
何気に`align-items: center`がデフォルトで設定されてるのがミソ👍

#### 利用例
![group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/f1fb40fd-115f-3640-cd83-e57ead485b70.png)

https://mantine.dev/core/group/

### SimpleGrid
これは厳密にはFlex系ではない（※）ですが、次で紹介するGridをよりシンプルにしたものです。  
グリッドシステムは子要素でカラムの値を指定して、レイアウトを組むことが多いかと思いますが、親要素でカラム数を決めて子要素を同サイズにすることができます。  
カラム数5とかGridでやろうと思うとめんどくさいので、そういった場合にサクッと使えばいいかと思っています。

:::note warn
Flexではなくgridが使われています
:::

#### 利用例
![simplegrid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/7e7ed8d7-956a-d22f-d776-911a08a39234.png)

https://mantine.dev/core/simple-grid/

### Grid
グリッドシステムを利用したい時に使用します。  
propsでFlex系のプロパティが指定でき、自由度の高いレイアウトが組めそうです。

#### 利用例
![grid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359978/86e1961b-d4ac-b702-69e3-10e2fba04d90.png)
※背景黄色にしてもわかりづらいので、devtoolで該当箇所を選択しています。

https://mantine.dev/core/grid/

### Flex
cssで書くFlexと同じことができます。  
Flexを理解してるなら、とりあえずこれ使っておけば大概のレイアウトは組むことができるでしょう。

言わずもがなため利用例は割愛します。

https://mantine.dev/core/flex/

## まとめ
自分用にまとめたものですが、誰かのお役に立てば幸いです。

## 最後に
### GoQSystemでは一緒に働いてくれる仲間を募集中です！
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site/?qiita=3979d609f3a4721c6453
go getでinvalid pseudo-version: preceding tag not foundのエラーが出た時の対処法

```shell
$ go get -u github.com/githubアカウント名/レポジトリ名@ブランチ名
```
をすると
```shell
go: downloading github.com/githubアカウント名/レポジトリ名 v0.1.2-0.20230424071711-f3c4a2f5ed55
go: github.com/githubアカウント名/レポジトリ名@ブランチ名: github.com/githubアカウント名/レポジトリ名@v0.1.2-0.20230424071711-f3c4a2f5ed55: invalid pseudo-version: preceding tag (v0.1.1) not found
```
のようなエラーが出て、その対処法についてメモとして記します

上記例の場合は、リモートリポジトリのタグはv0.1.0が最新のタグです

```shell
$ go get -u github.com/githubアカウント名/レポジトリ名@v0.1.1-0.20230424071711-f3c4a2f5ed55
```
のようにエラー文で出たtagのバージョンから1つ下げたバージョンで指定してgo getするとうまくいきました

これでいけた詳しい理由はわかってないので、分かる方はぜひコメントください。
find_elementsは遅い。

# 要素の存在判定にfind_elementsを使ってはいけない

find_elementの実行時間: 0.993401 秒
find_elementsの実行時間: 6.281310 秒

```python:test.py
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://jp.mercari.com/item/m98015773873")

# find_elementを使った場合
start_time_find_element = time.time()
try:
    element = driver.find_element(By.XPATH, "//mer-item-thumbnail")
except NoSuchElementException:
    element = None
end_time_find_element = time.time()

# find_elementsを使った場合
start_time_find_elements = time.time()
elements = driver.find_elements(By.XPATH, "//mer-item-thumbnail")
element = elements[0] if elements else None
end_time_find_elements = time.time()

# 実行時間を比較
find_element_time = end_time_find_element - start_time_find_element
find_elements_time = end_time_find_elements - start_time_find_elements

print(f"find_elementの実行時間: {find_element_time:.6f} 秒")
print(f"find_elementsの実行時間: {find_elements_time:.6f} 秒")

driver.quit()
```
【Laravel】PHPSpreadSheetを使ってExcelファイルを作り、アップロードテストする

久々の投稿です。よろしくお願いします。

# 課題
- 元々Excelファイルをアップロードする処理はあったが、テストが無かった
- テストデータは手作成でExcelを作ってアップロードし、目視で確認していたため効率が悪かった。

# TL;DR
- テストデータ作成用Factoryクラスを作る（LaravelのデータベースFactoryとは別）
- テストデータはFactoryクラスで作成
- テストデータのアップロードはUploadedFileクラスを使う

# xlsxファイルFactoryクラスの作成
今回は「XlsxFileFactory」とでもしましょうか。

```php
class XlsxFileFactory
{
    public array $importFileHeaders;
    public SpreadSheet $workBook;

    public function __construct(array $headers)
    {
        $this->workBook = new SpreadSheet();
        $this->importFileHeaders = $headers;
    }

    public function createDummyFile(int $createCount): void
    {
        $this->write($createCount);
        $writer = new Xlsx($this->workBook);
        $writer->save(base_path('storage/app/public/') . 'test.xlsx');
    }

    private function write(int $createCount): void
    {
        $workSheet = $this->workBook->getActiveSheet();
        $faker = Factory::create('ja_JP');

        // ヘッダの書き込み(ヘッダは配列をそのまま出力)
        $workSheet->fromArray($this->importFileHeaders, 'エラー', 'A1');

        // データ部の書き込み(データ部は書式を設定したりするのでループで処理)
        for ($i = 2; $i < $createCount+2; $i++) {
            // 数値5文字を標準書式で作成
            $workSheet->setCellValue('A'.$i, $faker->numerify('######'));

            // 日付を書式設定して入力
            $workSheet->getStyle('B'.$i)->getNumberFormat()->setFormatCode('yyyy/m/d h:mm');
            $workSheet->setCellValue('B'.$i, Date::PHPToExcel($faker->dateTime())); // DateTime型を渡すと書式設定通りに値が入る

            // 数値を文字として入力
            $workSheet->setCellValueExplicit('C'.$i, $faker->numberBetWeen(1,10), DataType::TYPE_STRING);
        }
    }
}
```

# テストコードの作成

```php
class ExampleTest extends TestCase
{
    public function setUp(): void
    {
        // ケースごとにセットアップしたいものをここに書く
        // hogehoge...

        parent::__construct();
    }

    /**
     * @test
     */
    public function Excelのアップロードテスト()
    {
        $count = 10;
        $headers = ['標準書式', '日付', '数値を文字で'];
        $fileFactory = new XlsxFileFactory($headers);

        // この処理を行うと「storage/app/public/test.xlsx」が出来上がる
        $fileFactory->createDummyFile($count);

        // アップロードのテスト
        $file = new UploadedFile(
            base_path('storage/app/public/') . 'test.xlsx',
            'test.xlsx',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // MS ExcelのMimeType
            0,
            true // テストフラグをtrueにする
        );

        // POSTのボディ部(フォームデータ)にfileを渡す
        $this->post(route('import'), [
            'import_file' => $file,
        ]);
    }

    public function tearDown(): void
    {
        if (Storage::disk('public')->exists('test.xlsx')) {
            Storage::disk('public')->delete('test.xlsx');
        }
    }
}
```

tearDownでファイルを消しているので、テストした跡も残らず
GitHubActionsやCircleCI等のテストランナーで活用できるかと思います。
テスト中は、ファイルの中身を見たいシーンもあるでしょうから、コメントアウトしとくと良いですね。

本当はStorageファサードで全部解決できれば良かったのですが
`Storage::get()`や`new File()`等で取得しようとすると中身のコンテンツがStringで拾われることとなり
テキストデータをPOSTする羽目になってしまったので、今回こういう形になりました。
もっと他に良い方法をご存じの方がいらっしゃれば、ご意見頂きたいと思います。
シグモイド関数のオーバーフロー対策

# 指数関数のオーバーフロー対策

最近見た実装で賢いなぁと思った実装があったのでご紹介します。

それが，タイトルにもある通りシグモイド関数のオーバーフロー対策です。

pythonは割と数値型（int, float,...）に関しては優秀で，あまり意識せずとも大きな数値を取ることが可能です。
しかし，流石に限度があるようで。
指数関数ぐらい発散速度が大きいものは簡単にオーバーフローします。

例）

```python3
>>> import numpy as np
>>> np.exp(100) #100くらいなら平気
2.6881171418161356e+43 #ただしかなり大きい桁数
>>> np.exp(709)
8.218407461554972e+307
>>> np.exp(710)
<stdin>:1: RuntimeWarning: overflow encountered in exp
inf
>>> np.exp(-1000)
0.0 #マイナス方向なら大丈夫
```

というわけで，$e^{710}$ という数値になるとオーバーフローしました。

肩の数字がマイナス方向に大きければ問題ないのですが，そうでなければ気をつけなければなりません。
これが効いてくるのが，シグモイド関数の実装時です。

## シグモイド関数とは

$$
f(x) = \frac{1}{1+e^{-x}}
$$
で表される関数で，ロジスティック回帰とかニューラルネットワークの活性化関数とかでよく見られるやつです。

これ，一応定義域が実数全体をとるのですが，xがマイナス方向に大きい場合はどうなるでしょうか。

例えば，

$$
f(-1000) = \frac{1}{1+e^{-(-1000)}} = \frac{1}{1+e^{1000}}
$$

なので，$e^{1000}$がオーバーフローすることを考えると計算できないことになります。

そこで，実装上この関数を次のように場合分けをします。

```math
f(x) = \left\{
\begin{array}{ll}
\frac{1}{1+e^{-x}} & (x \geq 0) \\
\frac{e^x}{1+e^{x}} & (x \lt 0) 
\end{array}
\right.
```

このようにすると，$x\geq0$の時は$e^{-x}$を計算して，$x\lt0$の場合は$e^x$を計算してくれるため，指数関数の肩の数字がマイナスの値になります。

よって，オーバーフロー対策になるわけです。

なお、`if文`で書いてもいいですが次のようにやると一行で書けます。

```python3
import numpy as np
def sigmoid(x):
    return np.exp(np.minimum(x, 0)) / (1 + np.exp(- np.abs(x)))
```
JavaScript Promiseとは？（備忘録）

## Promiseとは

JavaScriptにて
実行に時間がかかるコードがあった時
次のコードに処理が終わる前に処理がされてしまう。
そんなときに時間のかかる処理があった場合でも、すべて処理が終わった後で次のコードと処理してほしい時に使う

Promiseには3つの状態があり、
pending　処理が終わるのを待機状態
resolved 処理が成功した状態
rejected 処理が失敗した状態

最初は、pending状態でそこから
処理が成功したとき、resolved(その後thenに書かれた処理が実行される)
処理が失敗したとき、rejected(その後catchに書かれた処理が実行される)


## async/await とは？
(追記)
promiseによる非同期処理においてthenを使ってコードを書いていくと複雑になればなるほど見にくくなっていくが、それをasync/awaitを使うことでより見やすく、簡潔に記述することが出来る。
Linuxディレクトリ構造を理解する（備忘録）

## Linuxディレクトリ構造
Linuxのディレクトリ構造について把握したと思っていたので自分用にまとめておこうと思います。

### / ルートディレクトリ
- ツリー構造の頂点にあたるディレクトリ

### /bin
- 一般ユーザー向けの基本コマンドがあるディレクトリ
- cdなど基本的なコマンドがある
- Binary Folderの略
- ルートユーザー、一般ユーザーともにアクセス可能

### /boot
- システム起動に必要なファイルが配置
- Linuxカーネル[^1]やGRUB[^2]の設定ファイルなどがある。

[^1]:Linuxカーネルとは
ハードウェアとソフトウェアの間をもつ、OSの根幹
オペレーティングシステム（OS）の基本機能の役割を担うソフトウェア
OS内部に存在し、ハードウェアの主な機能のすべてを制御する

[^2]:GRUBとは
GNU GRand Unified Boot loaderの略

### /dev
- デバイスファイルが配置されているディレクトリ
- deviceの略字でハードウェア機器を表すファイルが保存される場所

### /etc
- 設定ファイルが配置されているディレクトリ
- Linux設定のための各種ファイルを持っている
- システムのほぼすべての設定ファイルが存在する

### /home
- ユーザーのホームディレクトリ
- /home/ユーザ名でユーザごとのホームディレクトリが作成される

### /lib
- カーネルモジュールや共有ライブラリ、プログラムに必要な各種ライブラリファイルが配置されるディレクトリ
- 32bit 版のライブラリー（基本コマンドの実行に必要なライブラリ群）

### /media
- 外部デバイスやリムーバブルメディアがマウント[^3]される場所

[^3]:マウント (mount)とは
ファイルシステムを特定のディレクトリに結びつけることを指す
具体的には、外部のストレージやネットワーク上のリソースを、ローカルのファイルシステムに接続して使用する場合に用いられる
例えば、外付けのハードディスクをPCに接続した場合、そのハードディスクはPCのファイルシステムにマウントする必要があり、その結果、外付けハードディスクの中身をローカルのファイルと同じように扱うことができるといったような感じか。

### /tmp
- ファイルなどを一時的に保管するディレクトリ
- システムを使用する全てのユーザーが共同で使用するディレクトリ

### /mnt
- 一時的にマウントするためのディレクトリ
- 取り外し可能な装置に対してファイルシステムを臨時に接続するディレクトリ

### /opt
-　ソフトウェアパッケージのインストール先となるディレクトリ
-　特定のアプリケーションに関連するすべてのファイルを/opt以下に配置する必要はなく、通常は/opt/[アプリケーション名]のようにサブディレクトリを作成し、その下に必要なファイルを格納する

### /proc
- プロセスを操作したり、システム情報を処理するための手段を提供している仮想ファイルシステム
- プロセスを監視・デバッグする際に利用される。

### /root
- rootユーザのホームディレクトリ
- 機密性の高いファイルなどを保存するために使用される


### /sys
- デバイスやドライバーの設定ファイル
- Linuxカーネルに関する情報がある
- システム全般についての内容を提供

### /usr
- ユーザで共有するデータを保持するディレクトリ
- 全てのユーザーが使えるアプリがインストールされるディレクトリ
- ユーザーが使用する各種プログラム

### /var
- Variableの略
- システム運用中に生成されて削除されるデータを保存するためのディレクトリ
- 内容が常に変化するファイル群が格納される
- ログファイルやデータベース、メール、プリンタのキューなどが格納される
- 定期的にバックアップすることが推奨される
model-viewer使ってみた

# 3Dモデルと写真を撮ろう！

社内プロジェクトの一環で、ARを自作することに。
ARと一緒に写真撮れたりしたらいいなーということで、調査してたらこんなツイートが…。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Windows10 の標準アプリだけを使って、文字の3Dデータを作ってそれをAR的に確認する30秒デモ。Paint 3D で3Dテキストを作成したら、Mixed Reality Viewer ボタンをおせば、PCのカメラでMR表示テスト。あとは3DデータとしてObjやfbxで保存ができます。標準環境だけで今すぐ誰でも試せます♪ <a href="https://t.co/VAIoTiHyf5">pic.twitter.com/VAIoTiHyf5</a></p>&mdash; しのぶ (@shinoblogavi) <a href="https://twitter.com/shinoblogavi/status/1025306200601112577?ref_src=twsrc%5Etfw">August 3, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>
<p>

**Windowsに搭載されてたのかよ！！！**
ということで、この技術は使うしかないよね。

# model-viewerを使おう！
調べてみたら、githubでコードも公開されていたのでトライしてみることに。
私ごときが考えることなんて、だいたい先人が確立してくれてますよね・・・。
googleさんありがとう！

https://github.com/google/model-viewer


大変ありがたいことに、すでに実践されてる方もおられました。
初心者に英文githubは難易度高すぎたので、こちらの記事の通りにやってみました。

https://qiita.com/matsu666/items/fd69a57cee4f131f70cd

# 完成！

ほぼ@matsu666さん完コピですが、完成したのがこちら。

https://padhinton.github.io/view_AR/

3Dモデルを表示することには成功。
なぜだか、cubeマークをタップしてもARになりませんでした。
私の環境だけなのかしら・・・。

# 終わりに
とりあえず３Dモデルは表示できたので、ファーストミッションクリア？笑
「３Dモデルと一緒に写真を撮る」という課題は持ち越しかなー。

three.jsとか、A-frameでもトライ中。

初心者の趣味プログラマでもこんなに簡単に実装できたのは、先人のみなさまのおかげ。
本当にありがたい限りです。

まだまだやりたいことがたくさんなので、精進します！
CKA試験、Service（命令語のみ）

# Create deployment
```sh
kubectl create deployment (deployment name) --image=nginx
```

# ClusterIP
```sh
kubectl expose deployment -n (namespace name) (deployments name) --type=ClusterIP --port=80 --target-port=80 --name=(service name)  
```

# NodePort
```sh
kubectl expose deployment -n (namespace name) (deployments name) --type=NodePort --port80 --target-port=80 --name=(service name) --dry-run=client -o yaml > testNodePort.yaml
```

```(修正前) testNodePort.yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: front-end
  name: front-end-nodesvc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: front-end
  type: NodePort
status:
  loadBalancer: {}
```

```(修正後)　testNodePort.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: front-end
  name: front-end-nodesvc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 32000
  selector:
    app: front-end
  type: NodePort
```

```(修正後 複数のポートを指定する場合)　testNodePort.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: front-end
  name: front-end-nodesvc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 32000
  - port: 443
    protocol: TCP
    targetPort: 443
    nodePort: 30300
  selector:
    app: front-end
  type: NodePort
```


```sh
kubectl apply -f ./testNodePort.yaml
kubectl get svc

# NAME                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
# front-end-nodesvc   NodePort    10.104.26.176    <none>        80:30200/TCP   5s
```
mtoa 2018にて透かし (from 2024 update)

Autodesk Account 内の Network License ManagerよりArnold Renderのネットワークライセンスを生成した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634498/6f948f64-99cc-815d-0c05-dfeb80312c2a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634498/dc61d191-6699-11e6-7626-91c01d65d241.png)
発行された .lic を開くと、中には Arnold 2020-2024までのProduct Infomation のみが記述されていた
2018のプロダクトコードは記載されていないので、透かしが発生する

Autodeskが遡って過去4バージョンのProductまでしかサポートしなくなったのでこのような現象が発生した
現在は代理店に .lic を再発行してもらい、透かしなくレンダリングが可能になった
Djangoで新規プロジェクト立ち上げからrunserverまで

## はじめに
Djangoとは、Pythonで書かれたウェブアプリケーションフレームワークです。
ここでは、自分のPC上で開発環境を構築するという前提のもと、仮想環境の設定、Djangoのインストール、プロジェクト作成、サーバーの起動 **(runserver)** までを行います。

## 環境
・Windows 10 64bit
・Python 3.10.6
・Django 4.2
・VS code

## 仮想環境の設置
Djangoをインストールする前に、他のプロジェクトとのライブラリの混同や、システム環境の汚染を防ぐために仮想環境を設定します。
今回は、**venv**を用います。

``` python:Console
python -m venv (環境の名前)
```
上記のコマンドを実行すると、仮想環境が設置されます。
しかし、それだけでは機能しないため、仮想環境の有効化 **(Activate)** を行います。

## 仮想環境の有効化
仮想環境を有効化するには、先に設置した仮想環境のフォルダへ移動します。
移動したフォルダ上で以下のコマンドを実行します。
```python:Console
(環境の名前)\Lib\Script\Activate.ps1
```
正しく実行され、仮想環境が有効化されると、コマンドプロンプト上に表示されているパスの先頭に、仮想環境の名前が表示されます。
![SnapCrab_NoName_2023-5-4_11-54-39_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336814/f8c2cc7f-f45a-462a-50fd-a35e813d4c8f.png)

## Djangoのインストール
いよいよDjangoのインストールに入ります。

```python:Console
pip install Django ==4.2
```
上記のコマンドを実行すると、先ほど設置した仮想環境内((仮想環境の名前)\Lib\site-packages)にDjangoがインストールされます。

pip install Django 以降の"**==**"を省略してコマンドを実行すると、最新版のDjangoがインストールされます。

## プロジェクトの作成
Djangoがインストールされたら、**django-admin**という管理コマンドが使用できるようになります。
主にプロジェクトやアプリの作成、スーパーユーザーのデータをデータベースに保存する際に使用します。

```python:Console
Django-admin startprject (プロジェクトの名前)
```
上記のコマンドを入力すると、現在のフォルダにプロジェクトフォルダが作成されます。

## サーバーの実行
プロジェクトフォルダが作成されると、その中にいくつかのファイルと共に、**manage.py**というファイルが作成されます。
manage.pyはDjango上でサーバーを実行させたり、データベースの操作を実行したりする際に使用します。
```python:Console
python manage.py runserver
```
上記のコードを実行すると、サーバーが起動します。
![SnapCrab_NoName_2023-5-4_14-28-36_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336814/1c236fa6-cb78-6009-a105-328b4c0880e9.png)
帰ってきたメッセージ内のアドレス（ここではhttp://127.0.0.1:8000）
をクリックするとwebブラウザが起動しDjangoのwelcomeページが起動します。

:::note info
文中に赤色の文字で警告文が書かれていますが、これはマイグレーション（モデルの変更をデータベースに反映されていないため、正しく実行できない可能性があるというものなので、今の段階では無視して大丈夫です）
:::

![SnapCrab_NoName_2023-5-4_14-28-11_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336814/7e2ab8a1-5f41-fded-8c76-855bc5a17478.png)

ロケットが発射されていたらサーバーの実行が成功しています！


## 最後に

今回はプログラミング初学者である自分への備忘録的な意味合いで本記事を作成しました。
間違いや訂正箇所等ありましたらご連絡頂けますと幸いです。
Autodesk 2018の起動エラー (from 2024 update)

【発生】
2024年リリースの各種アップデートを掛けたタイミングで、Maya 2018が立ち上がらなくなった
LGS.dataを削除したところ認証用のポップアップまでは出るが、アカウントへサインインしようとするとプロセスが落ちる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2634498/857494f7-9f93-0e4e-25d1-2fef0c61dbab.png)

----

【対処】
Autodesk アカウントでログインしているWindows Userで、以下のbatを作成して実行する。配置場所は任意に決めてよい。

```bat
@echo off

if _%1_==_payload_  goto :payload

:getadmin
    echo %~nx0: elevating self
    set vbs=%temp%\getadmin.vbs
    echo Set UAC = CreateObject^("Shell.Application"^)                >> "%vbs%"
    echo UAC.ShellExecute "%~s0", "payload %~sdp0 %*", "", "runas", 1 >> "%vbs%"
    "%temp%\getadmin.vbs"
    del "%temp%\getadmin.vbs"
goto :eof

:payload
taskkill /f /im "AdSSO.exe"
taskkill /f /im "AdAppMgrSvc.exe"
taskkill /f /im "AutodeskDesktopApp.exe"
taskkill /f /im "AdskLicensingAgent.exe"
taskkill /f /im "ADPClientService.exe"

del "C:\ProgramData\Autodesk\ADUT\ProdInd_UserInd.cur"
del "C:\Users\%USERNAME%\AppData\Roaming\Autodesk\ADUT\ProdInd_UserInd.cur"
del "%localappdata%\Autodesk\Web Services\LoginState.xml"

echo.
echo done

pause
```

----

カレントの認証情報が削除されるので、Mayaを起動して再度ログインする
docker build時にapt-get updateでPackages Not Found

## 事象
`ruby:2.4.1-slim-stretch` のDockerイメージビルド時に以下のエラーが発生。
エラーは先頭でビルドに必要なパッケージ群をインストールする箇所で発生していた。

```Dockerfile:Dockerfile
RUN apt-get update && apt-get install XXXXX
```

```shell
$ docker build XXXX
:
E: Failed to fetch http://security.debian.org/dists/stretch/updates/main/binary-arm64/Packages  404  Not Found
E: Failed to fetch http://deb.debian.org/debian/dists/stretch/main/binary-arm64/Packages  404  Not Found
E: Failed to fetch http://deb.debian.org/debian/dists/stretch-updates/main/binary-arm64/Packages  404  Not Found
E: Some index files failed to download. They have been ignored, or old ones used instead.
ERROR: executor failed running [/bin/sh -c apt-get update && apt-get install XXXXX]: exit code: 100
```

## 原因
`ruby:2.4.1-slim-stretch` のLinux OSディストリビューションであるDebianのバージョンが古く、パッケージのインデックスファイルの置き場所が変更されてしまっているため。

```shell:/etc/apt/sources.list
deb http://deb.debian.org/debian stretch main
deb http://deb.debian.org/debian stretch-updates main
deb http://security.debian.org stretch/updates main
```

## 対処方法（暫定）
デッドリンクになっているライブラリ一覧の向き先をアーカイブのホストに変更すればOK。
`/etc/apt/sources.list` の記述を上書きする。


```shell:/etc/apt/sources.list
deb http://deb.debian.org/debian stretch main
deb http://deb.debian.org/debian stretch-updates main
deb http://security.debian.org stretch/updates main
```
↓↓↓↓↓
```shell:/etc/apt/sources.list
deb http://archive.debian.org/debian/ stretch main
deb http://archive.debian.org/debian-security stretch/updates main
```

つまり、以下のようにDockerfileのRUNを書き換えれば良い。


```Dockerfile:Dockerfile
RUN apt-get update && apt-get install XXXXX
```
↓↓↓↓↓
```Dockerfile:Dockerfile
RUN echo "deb http://archive.debian.org/debian/ stretch main" > /etc/apt/sources.list \
    && echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list \
    && apt-get update \
    && apt-get install XXXX
```

* 参考：アーカイブのURL（バージョン：stretch、アーキテクチャ：amd64）
  * http://archive.debian.org/debian/dists/stretch/main/binary-amd64/ 


## 対処方法（恒久）
利用しているDocker ImageのDebianバージョンが古いことが根本原因のため、Rubyのパッチバージョンを上げてDebianバージョンも安定版に上げる。
これにより、アーカイブ参照は（当面は）不要となる。

### Debian：bullseye / Ruby:2.7.7
https://hub.docker.com/layers/library/ruby/2.7.7-slim-bullseye/images/sha256-28ee3b6cbfe566ab1052d4cabe990fd96ab66fd041234b30f26cd2fddef9d577?context=explore


※動作確認は必要
Unity 内の箱庭ロボットを動かすPython API仕様書

本記事は、パソコン上で Unity 内の箱庭ロボットをPythonプログラムで動かすためのAPIについて解説する記事です。

ベースとなるアーキテクチャの解説はこちらを参照ください。

https://qiita.com/kanetugu2018/items/ee9b2bf0596a35e42b03

# アーキテクチャ

本記事で解説する範囲は、下図のPythonプログラム（赤枠内）のところです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/ec661c30-d12e-81e7-8786-61165b9afed4.png)


そして、上図をより細かくレイヤ分けするとこんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/f4776576-7bb4-03ff-d40a-dd21b5502dcb.png)


ロボット制御アプリが利用できる API は、以下の３モジュールになります。

* hako_env
* hako_robomodel_any
* hako



# hako_env

本モジュールは、箱庭のシミュレーション実行制御を行う機能を提供します。

## make(model_name, robo_type, model_filepath = None)

* 機能
  * 箱庭環境を作成します。
* 引数
  * model_name
    * Unity上で作成した箱庭ロボットの名前を指定してください
  * robo_type
    * 常に `any` を指定してください
  * model_filepath
    * 常に、`dev/ai/custom.json`を指定してください
    * このファイルは、Unity上の箱庭コンフィギュレーションの `Generate` で自動生成されます。
    * `custom.json` は、箱庭ロボットの I/O 用のインタフェース仕様が定義されたファイルです。
* 戻り値：HakoEnvオブジェクト


## HakoEnv.robo()
* 機能
  * `make()` の第一引数　`model_name` で作成した箱庭ロボット制御用のオブジェクトを返します。
* 引数 : なし
* 戻り値 : `HakoRoboModelAny`オブジェクト

## HakoEnv.reset()

* 機能：
  * 箱庭シミュレーションをリセットします。
* 引数 : なし
* 戻り値 : なし


# hako_robomodel_any

本モジュールは、Unity内の箱庭ロボットに対して I/O を行う機能を提供します。

## HakoRoboModelAny.get_state(name, obserbation)

* 機能
  * 当該箱庭ロボットのセンシングデータ一式を取得します。
* 引数
  * name
    * センシングデータ名
    * `custom.json`の`org_name`を設定してください。
  * obserbation
    * `hako`モジュールの `execute()` メソッドの戻り値を指定してください。
      * execute()実行結果として、センシングデータ一式が返ってきます。
* 戻り値 :　当該センシングデータ

## HakoRoboModelAny.get_action(name, obserbation)

* 機能
  * 当該箱庭ロボットのセンシングデータ一式を取得します。
* 引数
  * name
    * アクチュエータ名
    * `custom.json`の`org_name`を設定してください。
* 戻り値 :　当該アクチュエータ指示データ


# hako

本モジュールは、C++版箱庭コア機能のAPIを提供します（Python用に使いやすくしています）。

補足：libshako.so は、hakoc というモジュールでアクセスします。

## Hako.execute()

* 機能
  * 箱庭ロボットのシミュレーションを１ステップ進めます。
* 引数：なし
* 戻り値 :　当該ロボットのセンサデータ

## Hako.wait_event(ev)
* 機能
  * 箱庭のシミュレーションイベントが発生するのを待ちます。
* 引数
  * ev
    * 待ち合わせしたいイベント
      * HakoEvent['START']
      * HakoEvent['STOP']
      * HakoEvent['RESET']
* 戻り値 :　なし

## Hako.wait_state(expect_state)
* 機能
  * 箱庭のシミュレーションイ状態が期待する状態になるのを待ちます。
* 引数
  * expect_state
    * 期待する状態
      * HakoState['STOPPED']
      * HakoState['RUNNABLE']
      * HakoState['RUNNING']
      * HakoState['STOPPING']
      * HakoState['RESTTING']
* 戻り値 :　なし

## Hako.write_pdu(channel_id, pdu_json)
* 機能
  * 当該ロボットのアクチュエータ指示値(pdu_json)を書き込みします。アクチュエータは channel_id で指定します。
* 引数
  * channel_id
    * アクチュエータのID
    * 具体的なID値は、custom.jsonで定義されています。
  * pdu_json
    * アクチュエータ指示値
* 戻り値 :　なし



以下、工事中・・・
WLS2 on UbuntuにArduinoIDEをインストールする方法

Ubuntuのドキュメントに従ってやってみても上手くいかなかった。

上手くインストールできた方法は単に、

```bash
sudo apt update
sudo apt install arduino
```

で終わり。びっくり。


起動は
```bash
arduino
```
AWS Summit 2023 参加レポート【1/3】

# はじめに
AWS Summit 2023に参加してきました。

https://aws.amazon.com/jp/summits/tokyo/

# まずは会場の様子など
会場は幕張メッセでして、とにかくでかい！！

![awssummit_04.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521220/2be97f99-880f-639e-2ea4-129513ce7442.jpeg)

人が多い！！

![awssummit_10.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521220/4fd4db0b-7e35-2b72-16ae-56dc958b1e7d.jpeg)

楽しい！！
![awssummit_08.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521220/700a8ad0-d861-e7d3-e31d-1e5130756a7d.jpeg)

4年ぶりのオフライン開催だったとのこともあり、盛り上がりまくっておりました。
![awssummit_14.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521220/e01f10c0-7515-3c47-23af-fbb47f284489.jpeg)

わたしは初参加で、色々と刺激的な2日間でした。
自分の振り返りと一緒に、何回かにわけ、受けたセッションの内容を紹介したいなと思います。

# 事例セッション①- リコー
* 題名: リコーの大規模言語AIモデルを活用した顧客価値創造 ～デジタルサービスの会社への変革を目指すリコーのデジタル戦略～
* 概要: 大規模言語AIモデルを活用した様々な取り組みについて、これまでの軌跡、現状の課題や解決方針、今後のゴールなど、紹介されていた

## 生成AI開発のはじまり
* OA機器のデジタル化にAIは欠かせず、1990年代から様々なオフィス業務効率化にかかわる音声系、自然言語系、画像・映像系のAI開発・サービス提供を行ってきた
* 2015年から、いわゆるディープラーニングの分野で、RNN(自然言語系)や時系列系のモデル開発をはじめる

## 「仕事のAI」の開発
* 2020年から、リコーのクラウド基盤(RSI)上でBERTを使った会話データなどのドキュメントの分類・分析サービスの開発がはじまり、2021年に「[仕事のAI](https://www.ricoh.co.jp/service/ai-for-work)」としてローンチ、コールセンターなどで導入され業務効率化を実現
    * BERT: 自然言語処理の事前学習用のTransformerベースの機械学習手法、2018年に公開
* [Amazon SageMaker Serverless Inference](https://aws.amazon.com/jp/blogs/news/amazon-sagemaker-serverless-inference-machine-learning-inference-without-worrying-about-servers/)で、低ランニングコスト・高可用性を実現

## 「仕事のAI」の課題であるPOC疲れ、その解決策
* 効果への懸念のためユーザの導入検討に時間がかかる
* 導入前検証用のユーザ側のデータ準備に時間がかかる
* 総じてPOCに数か月～半年かかってしまう「POC疲れ」解決のために、AI開発プラットフォーム自体の提供を進める
    * データ作成、モデル作成、推論ができる (SageMakerの簡素版のようなイメージぽかった)
## GPT-3の登場と今後の取り組み
* 業務改善の分野において、2020年に発表された[GPT-3](https://www.nri.com/jp/knowledge/glossary/lst/alphabet/gpt_3)のインパクトは大きく、開発を強化
* 幅広い業種の企業が自社内で自由にAI開発を実現するサービスを提供していく
    * ①GPT-3を使った、より簡単な業務向けのリコー独自のGPTモデルの開発を行う
        * データ処理部分: GPUが高速すぎて、S3では学習データ転送が追いつかず。Amazon FSx for Lustre で転送遅れを解消
        * 学習部分: Amazon SageMakerによる分散学習環境の構築
        * アーキテクチャ: S3→ Endpoint→ Fsx→ Sagemaker
    * ②バーチャルヒューマンの開発
        * 聞き、考え、音声発話し、動画化することで、自動接客をするAIアバターがブラウザベースで使えるサービス(chatGPTみたいに)
        * ↓ リコーのブースにデモもありました
![バーチャルヒューマン.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521220/dcc9fc87-fe0d-2c52-4208-ea54eec1883c.jpeg)

## 今後の課題
* AI運用・デジタルバディは今後、ほとんどの業種業界の企業での取り扱いが普通になっていく
* 現実的にユーザの予算もあるので、ハードをいかに小さくし、導入ハードルを下げられるか(承認レベル的に)が課題
* そのため、AWSの深層学習専用の高性能チップであるAWS TrainiumやAWS Inferentiaの導入を進めている
* 特に、AWS inferentia2 inf2インスタンスは学習コストが半減するため、期待大
 
# 感想
* BtoBのAIのビジネス活用についてのドメイン知識を増やせた
* 特に、各フェーズの課題やその解決方法などを具体的に紹介されていて、かなり有意義だった
* AI運用を当たり前にしていくために、規模も領域も、ユーザに合わせてしぼっていく、小さくしていくというところが、とても興味深かった
* MLはこれからの時代の象徴をつくっていくという、ゼロから生み出す面白さを感じる分野なんだなと強く思った、専門外だからとか思わずどんどんキャッチアップしていきたいなと、モチベーションが上がった
* スピーカーの方(梅津さん)のインタビュー記事「[『人間が作った文化に、身体や脳が追い付いていない』人間拡張の第一人者から見た、AIの進化と人間の未来](https://www.businessinsider.jp/post-263010)」が面白かったのでぜひ。
週一でPython勉強会やってみる③

前回の続き

https://qiita.com/Waddy675/items/815c68863005caab3165

AWSSummitに行ってみたりしていたら記事を書く時間がなく・・・
言い訳にせず続けていくことが重要なので頑張ります。
**継続は力なり**

## 文字列リテラル
シングルクォートかダブルクォートを1つか3つで囲う。
```py
str1 = 'hoge'
str2 = "hoge"
str3 = '''hoge'''
str4 = """hoge"""
```
複数行のコメントもシングルクォートかダブルクォート3つで書けましたね。


**生徒「2つじゃダメなんですか？4つは、5つは？」**

足し蟹！！

ということで試してみました。

```py
str = ''hoge''
```
```py
str = ''''hoge''''
```
```py
str = '''''hoge'''''
```
5つ以外**エラー**になりました。
5つは思ってたのと違う結果になりました。

なぜでしょうか。

まず2つの場合は、最初「''」で文字リテラルと認識してしまっているんですね。なので以降の「hoge''」はゴミとして認識されてエラーになりました。


続いて4つの場合「SyntaxError: EOL while scanning string literal」とエラーになります。文字列リテラルと認識しようとしてるのが分かりますが、普通にダメみたいです。

2つの場合から考えると「'' + '' + hoge + '' + ''」となり、hogeのタイミングで怒られる気がします。

もしくは「''' + 'hoge' + '''」になるが、シングルクォートで囲う中にシングルクォートは書けません。書くなら「''' + **"** hoge **"**  + '''」ですが、結果は「**"hoge"**」で期待している「hoge」にならないので要注意です。
以上を考えると1つより3つの書き方の方を優先した実行結果になっているようですね。


最後に5つの場合を3つの書き方を優先するルールに従うと「''' + ''hoge + ''' + ''」になります。そして表示結果は「**''hoge**」でエラーにはなりません。（正確には「''hoge」の後に空文字がいます）


法則性が見えたのでこれ以上はやりませんでしたが、勉強会らしいことができました。


# if文（条件分岐）
もし～なら①の処理、以外は②の処理的なやつです。
書き方は下記の通りです。
```py
i = 1
if i < 0:
    print('hoge')
else:
    print('fuga')
print('apple')
```
JSなどで使う{}に慣れている人からすると違和感しかないですが、スコープ定義は**インデント**によって使い分けられます。
else ifは「elif ~:」で書けます。

個人的にif ~の後の「:」をよく忘れるので注意しないとと思いました。Switch文のcaseぐらいにしか使ったことないイメージです。

それ以外は特に気になることがなかったのでif文に関しては以上です（笑）


# まとめ
今回は文字列リテラルについて色々試していたら時間が来てしましました。「フーンなるほど」ではなく「え、それなんで？」という子供のような「なんで？」を追求できるのは勉強会のいいところだと思います。
いよいよ制御文になってきたのでコーディングっぽくなってきた気がします。
次回はfor文からです。
各ステータスコードの番号と意味ってなんぞや？

# はじめに

APIなどを叩いてると「200 OK」だの「404 Not found」だのってよく目にしますよね。
あれってなんぞや？って思う方もいると思うので簡単にまとめてみました。

# ステータスコードってなんぞや？
***ステータスコードとは***
処理結果の概要を把握するもの。
番号によって何に起因するエラーなのか？ということを分類できるよってやつ

# ステータスコードの分類
|ステータスコード|意味|
|---|---|
|100番台|情報|
|200番台|成功|
|300番台|リダイレクト|
|400番台|クライアントサイドに起因するエラー|
|500番台|サーバーサイドに起因するエラー|

# 主要なステータスコードの意味
## 1xx:情報
|種類|説明|
|---|---|
|100 Continue|サーバーがリクエストの最初の部分を受け取り、またサーバーから拒否されていないことを示す|
|101 Switching Protocol|プロトコルの切り替え要求を示す|

## 2xx:成功
|種類|説明|
|---|---|
|200 OK|リクエストが成功したことを示す。本文にデータが含まれる|
|201 Created|リクエストが成功し、新しいリソースが作成されたことを示す。ヘッダーのLocationに新しいリソースへのURLを含める。|
|202 Accepted|非同期ジョブを受け付けたことを示す。実際の処理結果は別途受け取る|
|204 No Content|リクエストは成功したが、レスポンスデータがないことを示す。クライアント側のビューを変更することがないことを意味する|

## 3xx:リダイレクト
|種類|説明|
|---|---|
|301 Moved Permanently|リクエストされたリソースが永久に変更されたことを示す。レスポンスヘッダーにLocationを設定する|
|302 Found|リクエストされたリソースが一時的に変更されたことを示す。レスポンスヘッダーにLocationを設定する|
|303 See Other|リクエストされたリソースを取得するために、別のURLにGETリクエストでアクセスすることを示す|
|304 Not Modified|前回リクエスト時から変更がないことを示す。レスポンスボディは空になる|
|307 Temporary Redirect|リクエストされたリソースが一時的に変更されたことを示す。リダイレクト時はリクエストと同じメソッドを利用する|
|308 Permanent Redirect|リクエストされたリソースが永久に変更されたことを示す。リダイレクト時はリクエストと同じメソッドを利用する|

## 4xx:クライアントサイドエラー
|種類|説明|
|---|---|
|400 Bad Request|その他のエラー|
|401 Unauthorized|認証されていないことを示す|
|403 Forbidden|リソースに対するアクセスが許可されていない(認可されていない)ことを示す|
|404 Not Found|リクエストされたリソースが存在しないことを示す|
|409 Conflict|リソースが競合して処理が完了できなかったことを示す|
|429 Too Many Requests|アクセス制限が制限回数を超えたため処理できなかったことを示す|

## 5xx:サーバーサイドエラー
|種類|説明|
|---|---|
|500 Internal Server Error|サーバーサイドのアプリケーションエラーが発生したことを示す|
|503 Service Unavailable|サービスが一時的に利用できないことを示す。メンテナンス期間や過負荷で応答できないようなケース|

# まとめ
なんとなくは理解していたけど、細かく復習する良い機会だった。
備忘録としてまとめときます。

# 参考文献
https://www.udemy.com/course/rest-webapi-development/
Let's Encrypt certificate expiration notice for domain が届いた時の対処法

▼　背景
専門技術コースでAWSと簡単なプログラミングを学んだが、学習が終了したら、AWSのhttpsの更新がきて困っていた。

▼　はじめに
メールでLet’s Encryptからhttpsの更新依頼が英語で届いたが、色々いじったらうまくいかなかず、途方にくれていた

▼　環境
・Amazon Linux 2
・Certbot 
・Ruby on Rails

▼　うまくいった対応
# certbot certonly --apache -d サイト名 -d サイト名

上記をEC2上のサイト名のフォルダ上で、入力すると更新してくれました。

学んでから時間が経って、さらによく分からない泥沼に入り込みましたが、色々と参考になるサイトを参考にしてなんとかhttpsの更新ができました。

▼　参考にしたサイト
https://qiita.com/s-katsumata/items/2286052aa8d375c26a39

https://www.karakaram.com/letsencrypt-usage/

https://qiita.com/ENDoDo/items/17c59665fe64fa5ede76

https://zenn.dev/d0ne1s/scraps/303a400331ba4b
tWAS 9.0 と MQ 9.2 でJMSを動かす

# 目的

tWAS 9.0 と MQ 9.2 環境を構築してJMSをテストします。

# Gitレポジトリ
用意したGitレポジトリをクローンします。

```
git clone https://github.com/pdprof/jms
cd jms/jms-docker/
```

# MQイメージのビルド, tWASイメージのビルド

MQ, tWASのイメージをビルドします。localhost 以外の docker を動かしているホストのIPアドレスをACCESS_HOSTに指定します。Libertyの環境を流用しているのでLibertyもビルドされます。

```
export ACCESS_HOST=127.17.0.1
# export ACCESS_HOST=`hostname` # hostnameコマンドで返す値でアクセスできる場合
./setup-docker.sh
./setup-was90.sh
```

# MQの起動

MQ以外にも docker images の用意はありますが、ここではMQを起動します。

```
./mq-start.sh
```
tWASは、MQ用にしか構成していないので、SIBusやActiveMQとは動作できません。


# MQにアクセスするtWASの起動

JMSアプリケーションを実行するtWASを起動します。

```
./was90-start.sh
```


# アプリケーションにアクセスして動作確認

http://localhost:9080/jms/
にアクセスすると以下画面が確認できます。localhost部分はACCESS_HOSTに指定したものと置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262366/5f23dbd5-91b7-b16a-81c6-79d6df68533b.png)

Action, Queue, Message を指定してメッセージの送受信をします。
Q3はMDBが動作しているので、receiveAllの必要はありません。MDBが動いたタイミングでlibertyのログに受信したメッセージが出力されています。

```
[4/24/23 6:31:21:070 UTC] 0000008c SystemOut     O > PdprofJMSServlet.send
[4/24/23 6:31:21:103 UTC] 0000008c SystemOut     O = PdprofJMSServlet.send to queue:Q3
[4/24/23 6:31:21:107 UTC] 0000008c SystemOut     O < PdprofJMSServlet.send
[4/24/23 6:31:21:210 UTC] 0000008d SystemOut     O PdprofMdb.onMessage() - Message Received : 
  JMSMessage class: jms_text
  JMSType:          null
  JMSDeliveryMode:  2
  JMSDeliveryDelay: 0
  JMSDeliveryTime:  0
  JMSExpiration:    0
  JMSPriority:      4
  JMSMessageID:     ID:414d5120514d31202020202020202020ce1c4664022b0040
  JMSTimestamp:     1682317881097
  JMSCorrelationID: null
  JMSDestination:   queue://QM1/DEV.QUEUE.3
  JMSReplyTo:       null
  JMSRedelivered:   false
    JMSXAppID: bootstrap.WSPreLauncher     
    JMSXDeliveryCount: 1
    JMSXUserID: app         
    JMS_IBM_Character_Set: UTF-8
    JMS_IBM_Encoding: 273
    JMS_IBM_Format: MQSTR   
    JMS_IBM_MsgType: 8
    JMS_IBM_PutApplType: 28
    JMS_IBM_PutDate: 20230424
    JMS_IBM_PutTime: 06312109
test test test
```

# まとめ

JMSの環境を構築して、テストをすることができました。これまでのテスト環境構築手順とあまり変わり映えしませんが、それだけ手軽に環境が構築できるのだと思ってもらえるとありがたいです。
Swift　for文　配列の反復処理

Swiftでは、for-inループを使用して配列を反復処理することができます。for-inループは、配列の要素を1つずつ取り出し、指定した処理を繰り返し実行します。

以下は、for-inループを使用して配列 `numbers` 内の各要素を順番に処理する例です。

```swift
let numbers = [1, 2, 3, 4, 5]

for number in numbers {
    print(number)
}
```

上記の例では、 `numbers` 配列内の要素を順番に処理して、各要素を `number` という定数に代入しています。ループ本体では、 `number` の値を出力しています。

上記のコードを実行すると、以下のように出力されます。

```
1
2
3
4
5
```



また、配列のインデックスを使用して各要素を取り出すこともできます。以下は、配列 `fruits` 内の各要素を順番に処理し、インデックスと一緒に出力する例です。

```swift
let fruits = ["apple", "banana", "cherry"]

for (index, fruit) in fruits.enumerated() {
    print("Index \(index): \(fruit)")
}
```

上記の例では、 `enumerated()` メソッドを使用して、 `fruits` 配列の各要素に対して、その要素のインデックスと値のタプルを生成しています。for-inループの本体では、それぞれのインデックスと値を出力しています。

上記のコードを実行すると、以下のように出力されます。

```
Index 0: apple
Index 1: banana
Index 2: cherry
```

このプログラムでは、`fruits`という配列が定義され、`for-in`ループを使用して、配列の各要素を順番に処理しています。`for-in`ループ内のタプル`(index, fruit)`は、`enumerated()`メソッドによって生成されたもので、`index`変数には現在の要素のインデックスが、`fruit`変数には現在の要素の値が代入されます。その後、`print`文を使用して、現在の要素のインデックスと値を出力しています。

したがって、上記のプログラムは、配列`fruits`内の要素を順番に処理し、各要素のインデックスと値を表示します。

配列を反復処理する方法は、ほかにも多数ありますが、基本的にはfor-inループを使用して、配列の各要素を順番に処理することが一般的です。
Salesforce Scratch Org 作業のデイリー・コマンドライン

Salesforce Scratch Org 作業のデイリー・コマンドラインをメモ。

# 前提

- `Dev　Hub` 環境がすでに存在
- `Scratch Org` 作業のための `sfdx` プロジェクトおよび `git` リポジトリがすでに存在
- `tiga0424a` のような、日付とリビジョンをあらわす文字列を使用
    - git のブランチ名や Scratch Org 接続名に使用
- `Scratch Org` は少なくとも日次で作成＋廃棄
- 記載のルールの多くは私の独自ルールであり、一般的なものではない

# デイリー Dev Hub 作業

## Scratch Org 作成から初回プッシュまで

まず Dev Hub にログインします。

```
sfdx org:login:web -d -a DevHub
```

（少なくとも1日に1回） `Scratch Org` を作成します。

```
sfdx force:org:create -f config/project-scratch-def.json -s -a tiga0424a
```

できたての `Scratch Org` に手元ソースを配備します。

```
sfdx force:source:push -u tiga0424a
```

`Scratch Org` の Web画面を開きます。

```
sfdx org:open -o tiga0424a
```

※さあ、どんどん開発しよう
※私の場合は、初回に権限セットへのユーザ割り当てを実施

## 開発成果をゲット

`Scratch Org` での開発作業が進んだら、良きタイミングにて開発成果ソースを取得します。

```
sfdx force:source:pull -u tiga0424a
```

※適宜 git に開発成果を反映

## 日々の作業終了時

日々の作業終了時には接続をすべて閉じます。

```
sfdx org:logout --all
```

※本当にすべての接続を切断してよいかどうかは都度判断すること。

# フルセット

フルセットの手順は以下参照。

- [Salesforce Scratch Org をもちいたコマンド一巡メモ](https://qiita.com/igapyon/items/611093d8d9eee93f87a9)
windows版nvmでnodejs version20がインストールできない不具合

# 問題のバグ

https://github.com/nvm-sh/nvm/issues/3097

windows上でnvmを使ってnodejs ver.20をインストールしようとするとエラーになるっぽいです。

エラーになるコマンド

```
nvm install 20.0.0
```
## 原因(?)
エラーを見てみると引数が原因っぽいです。

```
panic: runtime error: index out of range [3] with length 3

goroutine 1 [running]:
main.checkVersionExceedsLatest({0x124140b0, 0x6})

...[以下略]
```


# 仮の対処法

上記のissueがまだ2日前に開始されたばかりなので、現状はWinの設定で旧バージョンのnodejsをアンインストールしてから、新しいバージョンをインストーラー経由でインストールするのがよさそうです。

https://nodejs.org/en/blog/announcements/v20-release-announce
リードが変換された後で、リードの客の所有者を変更できますか?

+ [Can you change the lead owner after the lead has been converted?](https://trailhead.salesforce.com//trailblazer-community/feed/0D54S00000A7cOdSAJ)


正直なところ、回避策は理解できないですね。Apex トリガーかな？

+ [レコードの所有者は、リードを変換したユーザーに変更されます](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A7cOdSAJ)

リードが変換されると、トリガーとワークフロールールが実行されると、リードを変換したユーザーが「リード所有者」として認識されます。


+ [Ownership of objects created in Lead Conversion](https://salesforce.stackexchange.com/questions/9753/ownership-of-objects-created-in-lead-conversion)

見込み客を新しいアカウント、連絡先、商談に変換すると、3 つのレコードすべてが同じ所有者で作成されます。これは、変換を開始したときの見込み客と同じ所有者にデフォルト設定されます。変換後も、所有者を他の人に変更する可能性があります。検索ダイアログで別のユーザーを選択する。覚えておくべきことの 1 つは、見込み客がキューによって所有されている場合、レコードの所有者を定義する必要があるということです。これは、アカウントと連絡先をキューによって所有することはできないためです。

リードを既存のアカウントに統合する

見込み客を変換する際に、既存の取引先に見込み客を結合することを選択した場合、[取引先名] リストで既存の取引先を選択するか、[ルックアップ] ダイアログを使用して、既存の取引先データを変更しないため、既存の取引先所有者は変更しません。変わりません。ただし、アカウントに新しい連絡先 (および場合によっては新しい商談) を作成しているため、その所有者は、前に説明したように、リードを変換するときに同じルックアップ ダイアログによって決定されます。

Apex からのリードの変換 これは他のものとは少し異なりますが、ある意味ではまったく同じです。唯一の違いは、ownerId を提供しないことを選択した場合、関数を使用して apex から所有者を設定できることですsetOwnerId()。同じ所有者がリードとして使用されます (リードの所有者がキューでない限り、所有者を定義する必要があります)。 、変換は失敗します)、既存の取引先の apex からの変換についても同じことが言えます。取引先所有者は変わりませんが、リード/商談は変わります。

+ [リードから取引の開始後の所有者の変更について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000PeQ5ASAV)
Golangを使ってローカル環境からGmailを送信する

こんにちは。
Golang では"net/smtp"パッケージを使用して、
簡単にローカル環境からメール送信できる機能が実装できます。
掲題の通り、Golangを使ってローカル環境からGmailを送信する方法を記載します。


---
### ■やること
1. GooogleテストアカウントのGmail設定
1. 実装


---
### GooogleテストアカウントのGmail設定

##### A. テストアカウントの作成
まずは頑張ってGoogleのテストアカウントを作成します。

##### B. 2段階認証プロセスを有効にする
アカウント作成後、アカウントのセキュリティーから、2段階認証プロセスを有効にします。

##### C. アプリパスワードを生成する
アプリ：メール
デバイス：その他　　で生成します。（名前はなんでもよいです）

※ **"お使いのデバイスのアプリパスワード"** が表示されるので、忘れずにコピっておきます。


### ■実装

今回は、yamlファイルにSMTPサーバ情報を記載し、
そのyamlファイルを読み込みメール送信する方法を実装しました。

#### 開発環境

```
go 1.20
github.com/labstack/echo/v4 v4.10.2
```

#### ファイル構成

```
test/
├── config/
│   └── smtpserver.yaml             -- SMTP接続情報が記載
├── functions/
│   └── functions.go                
├── handler/
│   └── handler.go
├── models/
│   └── models.go                   -- yamlから取得した接続情報を入れる
├── util/
│   └── util.go
└── main.go
```

#### SMTP接続情報
##### config/smtpserver.yaml
```
smtpserver: smtp.gmail.com
smtpport: 587
authaddress: <テストアカウントのメールアドレス>
authpassword: <生成したアプリパスワード>
```
#### データ構造
##### models/models.go
```
package models

type SmtpServerConfig struct {
	SmtpServer   string `yaml:"smtpserver"`
	SmtpPort     string `yaml:"smtpport"`
	AuthAddress  string `yaml:"authaddress"`
	AuthPassword string `yaml:"authpassword"`
}
```

#### メール送信機能
##### util/util.go
```
package util

import (
	"io/ioutil"
	"net/smtp"
	"strings"

	"test/models"

	"gopkg.in/yaml.v2"
)

// ---------------------------------------
// SMTPサーバ情報取得
// ---------------------------------------
func SmtpServerConfig() (models.SmtpServerConfig, error) {

	var smtpServerInfo []byte
	var err error

	smtpServerInfo, err = ioutil.ReadFile("config/smtpserver.yaml")
	if err != nil {
		return models.SmtpServerConfig{}, err
	}

	var smtpConfig models.SmtpServerConfig
	err = yaml.Unmarshal([]byte(smtpServerInfo), &smtpConfig)
	if err != nil {
		return models.SmtpServerConfig{}, err
	}

	return smtpConfig, nil
}

// ---------------------------------------
// メール送信
// param1. 送信するメールアドレス  string
// param2. 送信するメールの件名   string
// param3. 送信するメールの本文   string
// return: error
// ---------------------------------------

func SmtpSendMail(mailAddress string, mailSubject string, mailBody string) error {

	var smtpConn models.SmtpServerConfig
	var err error

	smtpConn, err = SmtpServerConfig()
	if err != nil {
		return err
	}

	// メールの内容を定義
	toMailAddress := []string{mailAddress}

	// 本文を設定する
	var mailBody string

	mailMessage := []byte("To: " + mailAddress + "\r\n" +
		"Subject: " + mailSubject + "\r\n" +
		"\r\n" +
		mailBody + "\r\n")

	// SMTPサーバ接続
	var auth smtp.Auth
	auth = smtp.PlainAuth("", smtpConn.AuthAddress, smtpConn.AuthPassword, smtpConn.SmtpServer)

	// メール送信
	err = smtp.SendMail(smtpConn.SmtpServer+":"+smtpConn.SmtpPort, auth, smtpConn.AuthAddress, toMailAddress, mailMessage)
	if err != nil {
		return err
	}

	return nil
}

```

-----

yaml 記載のSMTP設定ファイルを読み込み、Gmailでメールを送信するやり方でした。
テストなどで、ローカルからメールを飛ばす際に役に立つと思います。
Golang初心者でも簡単に実装できたので、Goが好きになりました。
レコード トリガー フロー: 保存前と保存後


+ [Trigger a Flow to Run After a Record Is Saved](https://help.salesforce.com/s/articleView?id=release-notes.rn_forcecom_flow_fbuilder_after-save_trigger.htm&release=226&type=5)

このhelpの画像を見ると After the record is savedって更新後の処理がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/83bf04f6-8945-244e-5d8e-8b11e28cd844.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e673ff30-c1e2-4752-0897-960a3c03c200.png)


しかし、私のフローではないんですよね。日本語だからないのかと思って英語にしたけど、オプションは表示されません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ec122929-24a9-95d6-c281-95e37d4a6eec.png)


# 私の疑問に答えてくれたいい解説をみつけました。

+ [Record-Triggered Flow: Before Save vs After Save](https://salesforcetime.com/2022/02/04/record-triggered-flow-before-save-vs-after-save/)

Winter '22 リリースより前は、開始要素の設定は次のように使用されていました。ご覧のとおり、「レコードを保存する前」と「レコードを保存した後」のオプションがありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d36b0780-1b4b-9722-b7ce-c91ad2c5ecf2.png)

ただし、Winter '22 リリースでは、Salesforce はこの設定の UI を変更しました。彼らはもはや前後にそれらを呼びません。保存する前に用語に慣れていない人にとってより明確にするために、ラベルを変更しました。「Fast Field Updates」オプションは保存前を意味し、「Actions and Related Records」オプションは保存後を意味します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9832dab6-91f3-b9cc-52c9-7b0d569b0668.png)

いやいや、ややこしいことしないで欲しかったなぁ。余計に分からん。
Apex Triggerと同じようにbefore とafterでいいだろう。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d0cee694-cb50-1da0-3e87-7e4b44dc1c11.png)

# 保存前 (高速フィールド更新)
フローをトリガーするレコードのフィールドを更新するだけでよい場合は、これが適切なオプションです。レコードが作成、作成または更新、更新、または削除されたときにトリガーできます。保存前のフローは、保存後のフローよりもはるかに高速 (10 倍) に実行されます。ただし、このタイプのフローで何ができるかを理解することが重要です。

まず、実行できることは、フローをトリガーするレコードを更新することだけです。ご覧のとおり、レコードを作成または削除するオプションや、サブフローの呼び出しやアクションの実行 (電子メールの送信など) などの対話要素はありません。ただし、システムからレコードを取得して、必要なロジックを実行することはできます。

Apex トリガに精通している場合は、update をコールしてレコードを変更する必要がないことをご存知でしょう。レコードがデータベースに入る前に作業しているので、必要なフィールド値を設定するだけで済みます。ロジックは、保存前フローでも同じです。レコードを更新するには、Update Records がなくても割り当て要素を使用できます。ただし、より明確にするために、Salesforce はレコードを更新するための別のオプションを追加しました: Update Records 要素です。

ああ、高速って意味が分からんかったので使ったことは全くない。なんだ、beforeのことかよ。

# 保存後 (アクションと関連レコード)
他のレコードを更新したり、電子メールの送信やサブフローの呼び出しなどのアクションを実行したりする必要がある場合は、これが適切なオプションです。レコードが作成されたとき、作成または更新されたとき、または更新されたときにトリガーできます。以前の保存フローとは異なり、削除イベントでトリガーすることはできません。ただし、保存後のレコードによってトリガーされるフローを使用して達成できることは他にもたくさんあります。

# 結論
要約すると、レコードによってトリガーされるフローは、ワークフロー ルールとプロセス ビルダーを置き換えます。トリガー レコードのフィールドを更新する必要があるだけの場合は、10 倍高速であるため、保存前フローを使用する必要があります。ただし、他のレコードを更新したり、他の多くのアクションを実行したりするには、保存後のフローを使用する必要があります。新しい Migrate to Flow ツールを使用して既存のワークフロー ルールをフローに変換すると、ワークフロー ルールごとに新しいフローが作成されることがわかります。フローを減らし、ステップとアクションをよりよく理解できるように、それらをマージしてみてください。

以下は、保存前と保存後のレコード トリガー フローの比較チャートです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1a99c71e-2cd5-1c1a-d0ae-c9d722f7d2df.png)
オブジェクト指向の考え方（その４：クラスとインスタンス）

# クラスとは
クラスを直訳すると、
> 部類、種類、学級、組、などの意味を持つ英単語

オブジェクト指向言語の参考書では、**「クラスとは設計図のこと」** のように表現することが多いが。何となくピンとこない人が多いと感じている。
クラスは、とあるモノの **＂種類＂** の、**「情報の項目」（フィールド）と、「動作」（メソッド）** を定義しているもので、あくまで実態を持たないモノと考えておくと良い。

--- 
プログラミングした時に、一番混しやすいと感じているのが、最初に出てきそうなサンプルで、

```java:catクラス（”猫とは” を定義している。）
public class Cat{
    private String name;

    Cat() {
    }

    Cat(String name) {
        This.name = name    
    }

    void nyaaa() {
        if (name == null) {
            System.out.print("にゃー");
        } else {
            System.out.print(name + "だにゃー");
        }
    }
}
```
```java:sample（猫に鳴いてもらう。）
class sample {
    public static void main() {
        Cat cat = new　Cat("モイ");
        cat.nyaa();
    }
}
```

上記ソースコードのように、Catクラスを使って、catオブジェクトを生成（インスタンス化）することが多く、猫を猫として利用するのでクラスの存在意義が分からなくなっている。

---
「クラスは設計図のこと」はその通りで、上記のソースコードだと、Catクラスは、猫という **＂種類＂** を定義しているので、猫が持つべき **「情報の項目」と「動作」** が定義されている。

情報の項目　→　name：名前
```java
    private String name;
```
動作　→　nyaa：鳴く
```java
    void nyaaa() {}
```
猫という種類のモノは、「名前」という情報の項目と、「鳴く」という動作 を持っていると考える。

---
そのクラスを利用する時には、オブジェクト指向の考え方の根本にある **「現実世界を表現する」** に基づいて、一匹一匹の猫をソースコード上に登場させないといけないので、
```java
        Cat cat = new　Cat("モイ");
```
の **new演算子** が存在する。

ちなみに、ウチの猫たちの名前は、
- ミケトラの「モイ」
- ハチワレの「マレ」
- 白猫の「ムー」

なので、ソースコード上に登場させてみると、
```java
        Cat moi = new　Cat("モイ");
        Cat mare = new　Cat("マレ");
        Cat muu = new　Cat("ムー");
```
となる。

最初のsampleクラスでは、猫（Catクラス）を、猫（catオブジェクト）として登場させていたので混乱を招いてしまう。
実際のプログラミングでは、現実で世界を表現するために、複数の猫（上の例だと、モイ・マレ・ムー）をそれぞれ１つずつの個体としてプログラム上に登場させる必要がある。
それぞれの個体は別であっても、猫という種類の設計図（クラス）は同じなので、取り扱い方法は統一されることとになる。

# インスタンスとは
インスタンスを直訳すると、
> インスタンスとは、事実、事例、例、場合などの意味を持つ英単語

ソフトウェアの世界では **実態** として表現されることが多い。
**１つの個体としてプログラム上に登場** したもののことをインスタンスという。

インスタンスを作ることを、インスタンス化と言い、
ソースコードで言うところの **new演算子** でそれを実装できる。（プログラマはインスタンス化のことを「newする」ということが多い。）
```java
        Cat cat = new　Cat("モイ");
```

ちなみにnew演算子が実行されると、素となるクラス（設計図の方では、 **コンストラクタ** という動作が行われインスタンスの初期状態を作り上げてくれる。
```java:catクラスだとこの部分（コメント追記）
    // {}の中に何も書かれていないので特に何もしていない。
    Cat() {
    }
    // 名前を付けてもらえたら名前を覚えておく。
    Cat(String name) {
        This.name = name    
    }
}
```

---
とあるサイトでのアカウント作成（サインアップ）で例に出すと、
![オブジェクト指向-7 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580819/d1a87642-baf7-aa2a-1807-4a1437380288.jpeg)
のように、
- Aさんのアカウント情報を登録　（New しているイメージ）
- Aさんのアカウントでログイン　（コンストラクタが実行されているイメージ）
- Aさん用の画面を表示　　　　　（個体としてプログラム上に登場したイメージ）

がインスタンスが生成されるまでの流れになる。
（若干、異なる様な気がしてきたが、、）

---
前の回はこちら → [オブジェクト指向の考え方（その３：カプセル化）](https://qiita.com/TkyI/items/732078cd3ceb5ad0e306)
Xcode Command Line Tools の再インストール

## はじめに

Homebrewのアップグレードの結果、1件のエラーがありました

「Command line tools」のバージョンが古い、とのことだったので、
最新バージョンにアップデートしました。
その記録です。


## Homebrewとは

Homebrewとは、さまざまなパッケージをインストールしたり、
バージョン管理を行うための、パッケージ管理システムです。

インストールするメリット
- 手動でパッケージをダウンロードしたりアップデートすることに比べ、格段に作業がしやすい
- インストールするとbrewというコマンドが使えるようになり、このコマンドを使ってさまざまな操作を行うことができるようになる

## Command line toolsとは

HomebrewをMacでインストールするためには、事前にあるもののインストールが必要です。
それが「Command line tools」です。
これは、Mac上での開発に必要となるツール群をインストールものになります。

##### インストールの手順

1、 コマンドを実行します。
```zsh
$ xcode-select --install
```
2、 ポップアップが表示されるので、「インストール」
3、 使用許諾契約に関する説明が表示されるので、「同意する」をクリックします。

すると、Command line toolsのインストールが開始されます。
（時間がかかるのでお気をつけて！）

## アップグレードしたらエラー発見

Homebrewをアップグレードしました。
```
$ brew upgrade
```
すると、一部エラーを発見。

```zsh
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Settings.

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/all/.
You should download the Command Line Tools for Xcode 14.3.
```

＜内容＞
エラーです： コマンドラインツールが古すぎます。
システム設定のソフトウェアアップデートから更新してください。

それで更新が表示されない場合は、実行してください：
  sudo rm -rf /Library/Developer/CommandLineTools を実行してください。
  sudo xcode-select --install

または、手動で以下からダウンロードしてください：
  https://developer.apple.com/download/all/。
Xcode 14.3用のコマンドラインツールをダウンロードする必要があります。


## 言われた通りに

表示された通りに、コマンドを入力しました。

```zsh
$ sudo rm -rf /Library/Developer/CommandLineTools
$ sudo xcode-select --install
```
待つこと10分ほど…無事完了しました。

## おわりに
完全に私の備忘録です。(笑)
何か大事なものが消えたりとんでもないエラーが起きるのではないかと、
ターミナルコマンドに入力する際は、いつもびびりちらかしているので、
自信持って操作ができるように、引き続き勉強を頑張ります🔥
SAP会計仕訳

■　MM

①入庫時点(MIGO)

原材料＊             / 入庫請求仮勘定
差異勘定(仕入価格差異）

　→原材料の金額 = 品目.標準原価 x 購入数量
　→入庫請求仮勘定 = 実際の購買金額

②請求書照合ESR(MIRO)
入庫請求仮勘定 / 買掛金
仮払消費税