OmniAICreator/Qiita-1.07M huggingface dataset:
MacBookでBluetoothスピーカーの音が出なくなった時の対処法メモ

なんか急に外付けスピーカーマイクから音が出なくなり、PC再起動しても接続設定を1からやり直しても改善しなかったんですが、原因が思わぬところだった+ネットに全然乗っていなかったので備忘録として残しておきます。

# 1行まとめ

外付けモニターと繋いでいるUSB-Cを他のポートに挿したら直った

# 環境

## PC
* PC: MacBook Pro (16inc, 2021)
* チップ: Apple M1 Pro
* メモリ: 32GB
* OS: macOS Monterey 12.1

## 接続機器

* 外付けモニター: 2台(USB-Cで接続)
* Bluetooth
    * マウス(純正 Magic Mouce)
    * キーボード(純正 Magic Keyboard)
    * **スピーカーマイク(Anker PowerConf S3)** ← こいつが動かなくなった

## 解決方法図解

![IMG_6441.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984939/4ef0c3e9-0646-e1cf-ce61-39a66ac3086d.jpeg)
![IMG_6440.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984939/c924b12c-e5a3-0fe4-0f69-43df4f22508b.jpeg)

## いつもは②④で挿していた

再起動しても設定し直しても、マイクの入力はあるみたいだけど出力が全然されてないんだよな〜最近環境で変えた部分あったかな〜と思って、ふとtype-Cの刺さっている部分を見たら「これじゃね？」と。

外付けモニターの1つが、たまにPC立ち上げ時に一緒に点いてくれなくて挿し直す時あるんですよね。

そこで適当にいつもと違うところに挿しちゃったんだと思います。

「繋げ直してみるか。。」と③④→②④に変えてみたところ、ビンゴ！

音が出力されるようになりました〜

前に使っていたMacBook Proでは、充電もtype-Cからでしたが、右側と左側でファンの鳴り方が違うーとか聞いてたので、外部接続機器にもポートが影響してるのかなと思ってます。

多分未来の自分はまた同じ過ちを繰り返すと思うので、ググったときにこの記事に引っかかるように備忘録として残しておきます。、、
Laravel コマンド一覧

# よく使うコマンド一覧
よく使うコマンドを一覧にまとめています。

| 項番 | 項目 | コマンド |
|:----:|:-------------|:-------------|
| 1 | [バージョン確認](#バージョン確認) | php artisan --version |
| 2 | [ヘルプ](#ヘルプ) | php artisan help <コマンド> |
| 3 | [起動](#起動) | php artisan serve |
| 4 | [コントローラー作成](#コントローラー作成) | php artisan make:controller <コントローラー名> |
| 5 | [テーブル作成](#テーブル作成) | php artisan make:migration <クラス名> |
| 6 | [マイグレーション実行](#マイグレーション実行) | php artisan migrate |
| 7 | [シーダー作成](#シーダー作成) | php artisan make:seeder <シーダー名> |
| 8 | [シーダー実行](#シーダー実行) | php artisan db:seed |
| 9 | [ファクトリー作成](#ファクトリー作成) | php artisan make:factory <ファクトリー名> |
| 10 | [モデル作成](#モデル作成) | php artisan make:model <モデル名> |

## バージョン確認
```
php artisan --version
```

## ヘルプ

```
php artisan help <コマンド>
// 使用例
php artisan help make:model
``` 

## 起動

```
php artisan serve
// Host、Port指定
php artisan serve　-host=127.0.0.1 -port=8080
```

## コントローラー作成
```
php artisan make:controller <コントローラー名>
// 例
php artisan make:controller TweetController
```

## テーブル作成
```
php artisan make:migration <クラス名>
// 例
php artisan make:migration create_tweets_table
```

## マイグレーション実行
```
php artisan migrate
```

## シーダー作成
```
php artisan make:seeder <シーダー名>
// 例
php artisan make:seeder TweetSeeder
```

## シーダー実行
```
php artisan db:seed
// 個別のシーダーを呼び出す場合
php artisan db:seed —class=TweetSeeder
```

## ファクトリー作成
```
php artisan make:factory <ファクトリー名>
// 例
php artisan make:factory TweetFactory
```

## モデル作成
```
php artisan make:model <モデル名>
// 例
php artisan make:model Tweet
```

### ※マイグレーションファイルも同時に作成
```
php artisan make:model <モデル名> —migration
php artisan make:model <モデル名> —m
```

### ※モデルファクトリーも同時に作成
```
php artisan make:model <モデル名> —factory
php artisan make:model <モデル名> —f
```

### ※シーダーも同時に作成
```
php artisan make:model <モデル名> —seeder
php artisan make:model <モデル名> —s
```

### ※コントローラーも同時に作成
```
php artisan make:model <モデル名> —controller
php artisan make:model <モデル名> —c
```

### ※モデル・モデルファクトリー・シーダー・コントローラーも同時に作成
```
php artisan make:model <モデル名> —mfsc
php artisan make:model <モデル名> —all
```

### ※ピボットモデルも同時に作成
```
php artisan make:model <モデル名> —pivot
```

## 最後に
初めてLaravelを使ったときにメモしていたコマンドの一覧でした。
何かのお役に立てれば幸いです。
【React】Corsエラーの回避　メモ

## 現状
React+Expressの環境でwebアプリを構築していますが、corsエラーが出ています。
エラーの中身↓
```
Access to XMLHttpRequest at 'apiのurl' from origin 'front側のurl' 
has been blocked by CORS policy:
The 'Access-Control-Allow-Origin' header contains the invalid value 'front側のurl'.
```

corsエラーが出ています。

## ひとまずの対応
```typescript
const express = require("express");
const cors = require("cors");
const app = express();

app.use(
  cors({
    origin: "*",
    credentials: true, //レスポンスヘッダーにAccess-Control-Allow-Credentials追加
    optionsSuccessStatus: 200, //レスポンスstatusを200に設定
  })
);
```

urlの指定を*にしているのでセキュリティ的に少しアウトな部分もあるのですが、とりあえずこれで対応します。
なぜかurlを指定するとエラーになってしまうのでそれができたら追記します。
（わかる方いたらコメントお願いします）
インスタンススケジュール機能によるGCE自動停止とterraform

# はじめに
コスト削減のため、踏み台VMや開発・ステージング環境でのVMは、営業時間外は停止しておきたいという要件はよくあると思います。
GCPでは自動停止構成を組む選択肢2つあり、個人的には後述2つ目がシンプルで良いなと思ったので、メリデメとterraformの例をまとめました。

# 構成案

### 案1. Scheduler + Functionsで停止
AWSでも EventBridge + Lambda でEC2やRDSを自動停止させたりする上、[ドキュメント](https://cloud.google.com/scheduler/docs/start-and-stop-compute-engine-instances-on-a-schedule?hl=ja)でも紹介されており真っ先に思いつきそうな構成です。自分も最初はこの構成組んでました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577028/b5703b13-1298-779e-4ba5-5e666d5296c5.png)

terraformで管理する場合は、下記リソースが必要です。

- Cloud Functions + Cloud Scheduler + Pub/Sub
- Functionsのソースコード
- Cloud Storage（ソースコードをアップロードする用）


### 案2. GCEのインスタンススケジュールで停止

なんと、**GCEネイティブの機能で自動停止できます**。（起動も可能）
https://cloud.google.com/compute/docs/instances/schedule-instance-start-stop?hl=ja
cron式も使えるため柔軟に設定可能です。


# インスタンス スケジュールのメリデメ

- **メリット**
    - **構成がめちゃくちゃシンプル**
案1の場合は上記の通り色々リソースが必要で、terraformのコードも長くなる。
一方、インスタンススケジュールはリソースが1つだけなのでめちゃくちゃシンプルに書ける。
また、対象インスタンスへのラベル付与も不要。

- **デメリット**
    - **厳密な時間指定不可**
    ドキュメントに記載があるが、スケジュール時刻から停止が最大15分遅れる。（そもそもビジネスクリティカルなGCEは自動停止させないと思うので、あまり問題にならない？）
    - **スケジュールの変更不可**
    作成したインスタンススケジュールは時刻変更できないので、一旦削除して再作成が必要。
さらに一つのGCEを複数のスケジュールに設定できない関係で、terraform applyで一気にdestroy&createしようとするとエラーが出るため、一旦手動で既存スケジュール削除してからapplyする必要があり地味に手順が煩雑。

デメリットを許容できるようであれば、インスタンススケジュールを使うのが楽で良いかと思います。スケジュールの変更もたまにしかないと思いますし。


# terraformの記述例

```tf
resource "google_compute_resource_policy" "stop_compute_engines" {
  name   = "stop-compute-engines"
  region = var.region
  description = "GCEの夜間自動停止"
  instance_schedule_policy {
    vm_stop_schedule {
      schedule = "0 22 * * *" # 毎日夜10時に停止
    }
    time_zone = "Asia/Tokyo"
  }
}

# 停止対象GCEへのポリシー登録
resource "google_compute_instance" "vm" {
  project      = var.project-name
  # （中略） 
  resource_policies = [
    google_compute_resource_policy.stop_compute_engines.id
  ] 
}
```

GCEへのポリシー登録がterraformのドキュメントに書かれてなかったため、「ここは手動か〜惜しい」と思ってましたが、ちゃんとありました。（terraformいじってたら偶然発見）

# 参考
- [（GCPドキュメント）Cloud Scheduler を使用した Compute インスタンスのスケジュール設定](https://cloud.google.com/scheduler/docs/start-and-stop-compute-engine-instances-on-a-schedule?hl=ja)
- [（GCPドキュメント）VM インスタンスの起動と停止をスケジュールする](https://cloud.google.com/compute/docs/instances/schedule-instance-start-stop?hl=ja)
- [（terraformドキュメント）google_compute_resource_policy](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_resource_policy#example-usage---resource-policy-instance-schedule-policy)
- [Google Compute Engineの起動と停止をGUIでスケジュールする（初心者向け）](https://dev.classmethod.jp/articles/gce-instance-scheduling-gui/)
Python入門 基本操作と数値の計算

## 概要
初学者向けにPythonの基本的な内容をまとめて寄稿します。今回は、基本操作と数値の計算についてまとめました。
※あまりに自明すぎる基礎知識は省いている場合が御座います。

## 基本操作
### コメントアウト
**#でコメントアウト**を行う。

### 文のグルーピングがインデント
**文のグルーピングはインデントで行われます**。
Javaなどの様に{}を使用しません。

### 代入
**イコール(=)演算子を使って変数に値を代入出来ます**。
※以下の例で出てくるprint関数は**文字列や数値を画面に出力**する関数です。

```python:例
print('hogemaru\nhogesuke')
>>hogemaru
>>hogesuke
```
```python:例
a = 1
print(a)
>>1
```

また、多重代入で**変数及び、値をカンマ(,)で区切る事で複数の変数に複数の値を同時に代入出来ます**。
```python:例
a, b = 1, 2
print(a)
>>1
print(b)
>>2
```

## 数値の計算
### 計算のルール
四則演算子は以下になります。
<b>加算: `+`, 減算: `-`, 乗算: `*`, 徐算: `/`</b>
また<b>冪乗の演算子は`**`</b>です。

### 数値の型
Pythonは動的型付け言語の為に、予め数値が何の型になっているのか把握する必要性があります。なので改めてお浚いしましょう。
主な型は**int**と**float**になります。
intは整数にfloatは小数に適用されます。

Pythonの特徴として切っても切り離せない特徴として**徐算は常にfloat**になるという事です。その為、徐算の商が小数点以下が無い場合でも`3.0`の様に浮動小数点数となります。

万が一、<b>整数部分だけが欲しい場合は演算子に`//`</b>を使用しましょう。
また<b>余りだけが欲しい場合は演算子に`%`</b>を使用しましょう。

注意事項として式に`4 * 2.5 / 2`のような**答えが整数になる場合でも式にfloat型の数値が混ざっている場合は`5.0`の様に浮動小数点数で結果が求まります**。

余談ですが、この徐算結果が浮動小数点が故に必要精度が失われた事について私の好きな記事があるので下記に掲載させて頂きます。良ければご一読下さい。

https://linus-mk.hatenablog.com/entry/2019/05/26/234642

そしてPythonでは複素数、１０進数、分数を扱う事ができます。
**複素数の型はcomplex**,**10進数を扱う為のモジュールはdecimal**,**分数の計算を扱う為のモジュールはfraction**になります。
Laravelでbladeファイルを変更した際に変更が反映されない時

# はじめに
Laravelで開発をしていた時に、bladeファイルを変更したものローカルで変更が反映されなかった時の解決策を備忘録として残します。

# 結論「php artisan cache:clear, php artisan view:clear」を行う。
最初ブラウザ側のキャッシュが原因と思い、「ctrl + shift + R」でキャッシュの削除を行いましたが解決せず。

色々と調べたところ、サーバー側のキャッシュもクリアにすると反映されるとの記事があったため、
```php
php artisan cache:clear
```
```php
php artisan view:clear
```

2つのコマンドを実行したところ、無事に変更が反映されるようになりました！
Raspberry Pi 400 に HyperPixel 4 高解像度タッチディスプレイを取り付けてみた。

Raspberry Pi 400 に HyperPixel 4 高解像度タッチディスプレイを取り付けて、使えるようにしてみました。

![PXL_20230203_022233687~2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212972/ac3fd7bf-3ddb-1bad-2375-363b03216618.jpeg)

# 環境
### 作業PC
- Windows11

### Raspberry Pi
- Raspberry Pi 400
- microSD（64GB）

### 拡張パーツ
- HyperPixel 4.0 - Raspberry Pi用高解像度タッチディスプレイ
- Adafruit Raspberry Pi 400用 CYBERDECK HAT

https://www.switch-science.com/products/5985?variant=42382084145350

https://www.switch-science.com/products/7608?_pos=5&_sid=50f8a354e&_ss=r


# Raspberry Pi 400 のセットアップ
Raspberry Pi 400 のセットアップは、下記の記事を参考にしてください。

https://qiita.com/IoriGunji/items/718f8245136af94066eb?0


# HyperPixel 4 高解像度タッチディスプレイ
HyperPixel 4 高解像度タッチディスプレイの設定や取り付けを行っていきます。

## ディスプレイ設定
最新の Raspberry Pi OS の場合は、インストールなどは不要で、設定を変更するだけで利用できます。
設定方法は2種類あります。
都合の良い方で作業してください。


### 方法1：SDカードを直接編集（オススメ）
Raspberry Pi Imager で Raspberry Pi OS の書き込みが終わったら、ファイルエクスプローラーで `config.txt` を探して任意のテキストエディタで開きます。

:::note warn
Raspberry Pi Imager の設定で変わりますが、 Raspberry Pi OS の書き込みが終わると、自動的にSDカードがアンマウントされる場合があります。
その際は、SDカードを PC に刺し直してください。
:::

HyperPixel 4 用の設定を一番下の行に追加し、保存します。
```shell
# HyperPixel 4 touch display
dtoverlay=vc4-kms-dpi-hyperpixel4
dtparam=rotate=270,touchscreen-swapped-x-y,touchscreen-inverted-x
```


### 方法2：ターミナルなどでアクセスして編集
`config.txt` をテキストエディタで開きます。
```bash
sudo nano /boot/config.txt
```

HyperPixel 4 用の設定を一番下の行に追加し、保存します。
```shell
# HyperPixel 4 touch display
dtoverlay=vc4-kms-dpi-hyperpixel4
dtparam=rotate=270,touchscreen-swapped-x-y,touchscreen-inverted-x
```

電源を切ります。
```bash
sudo shutdown -h now
```

## ディスプレイの取り付け
ディスプレイを組み立てて、Raspberry Pi 400 に取り付けます。
![PXL_20230203_022402210_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212972/b026fdfa-602e-9b1f-13d9-36e6f6224398.jpeg)


## 起動
`Fn` と `F10` を同時押しで起動します。
画面が映れば成功です。
事前に議事録を用意し何ならそこで議論を始めてしまう手法を試している

# 定例ミーティングの準備、どうしていますか？

多くのエンジニアがそうであるように、私の所属するチームで毎週定例のミーティングをしています。
この記事は、この定例ミーティングに向けてどのような準備をしているかという話です。

私の所属するチームは私を含め3人に非常に小規模なチームです。そのため、チーム運営のための実験も比較的簡単に行うことができます。

# 以前のやり方

この方法にする前は、各々が今週の進捗や、話したい内容を、手元にテキストで用意しておいて、定例ミーティングでSlackにガッと投稿して、それを見ながら報告をするという手法でした。

この方式には以下の問題点がありました

- ミーティングのその人のターンが来るまで、どのような内容が話されるか不明
  - 即座に意見があれば返す必要がある
  - ミーティングに出席できないと意見を出しそびれる

まぁ重大な意見であれば後日改めて伝えればよいのですが、ちょっとした疑問や、アドバイスのようなものは機会を逃すと「伝えるまでもないか・・」となってしまい、せっかくのチームのシナジーの機会を逃してしまいます。

また、ミーティングで話題になった内容について、即座に自分の意見を練って主張するというのはある種の特殊なスキルが必要な行為であり、そういうものをあえて求める必要はないだろうと考えました。

# 事前に議事録を用意するやり方

以前のやり方を改善するために、まずは社内にHedgeDocを用意しました。
これはHackMDのオープンソース版で、リアルタイムに共同編集できるWikiです。

https://github.com/hedgedoc/hedgedoc

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100375/3d04fba7-3dbd-a77d-6bb8-7fbaa7dc85d5.png)

週の初めに、このHedgeDocにテンプレートを作成し、その週のうちミーティングで話す内容を記載するという方式にしました。

弊社では似たようなツールとしてQiita TeamやGitHubのWikiがあったのですが、今回は「リアルタイム共同編集」を試したかったのでHedgeDocを利用することにしました。

リアルタイム共同編集の無いWikiの一つのページに複数人が編集しようとすると、どうしても編集のコンフリクトが起きます。

まぁ3人のチームでそれがどれだけ起きるのか？という話ではあるのですが、コンフリクトを恐れるあまり、一気に書こうというモチベーションが高まってしまい、結局MTGギリギリにまとめて書き込むことになり、以前と同じく、ミーティングのタイミングで早押しクイズ的に内容を確認し意見するような状況になってしまうのを避けたかったのです。

# この方式により生まれた効果

## ミーティング時に読み上げることが不要となった
議題をみんなでゆっくり読む時間が不要となりました。
もちろん重要な内容や込み入った内容については、立ち止まって読みますが、意見がなさそうな「確認事項」的なものは読んでいる前提でサクサクと進め、本当に議論が必要なトピックに時間を割けるようになりました。

## ミーティングより前に話が進む

疑問形で議題を書いておくと、ミーティングより前にメンバーがそれを見て、その答えや、さらなる問題の深堀りのための質問を書き込むことができるようになりました。
システム的には、そこで何往復もテキストでやり取りすることも可能ですが、多くの場合は1~2往復のやり取りとなっています。

議事録に書くことで解決する問題や、予めその内容について、調べてからMTGに臨むことができるようになり、ミーティングの時間のやり取りが、より実のあるものになったと感じます。

## 雑談コーナーの設置

ミーティングの議題とは別になにか話したいことがあれば書き込める「雑談コーナー」というのも用意したところ、定形のトピックとは違った、チーム運営のための意見や、チームメンバーの関心のネタについての書き込みなども集まるようになりました。

また、時間に余裕がある週などは、業務でよく扱うGo言語のTipsの共有など、ちょっとしたLTのようなものも行う機会となっています。

# 課題
## 機械生成コンテンツと人間のコメントが混ざった文書の更新

ミーティングでの進捗報告は基本的にはGitHubのIssueをベースに行うため、テンプレートは一括で作成します。
その方法については以下の記事で紹介しました。

https://qiita.com/inajob/items/8dcfd91c43b24efa75b5

しかし、チームのメンバーが担当するIssueは時々刻々と変化するため、これを一度生成しただけだと、定例ミーティングの開催時には情報が古くなっており、記載漏れのあるIssueが発生してしまいます。

現状ではそういうIssueで、大事なものは、それぞれが手動で書き足すか、大して重要でないものであれば、なにもせず、翌週に確認するようにしています。

もし、機械生成コンテンツに人間のコメントが混ざった文書に、再度機械生成のコンテンツの差分をパッチする事ができれば、このような問題は起きず、新鮮な進捗状況を文書にできると考えています。

## 結局ギリギリに用意する

この方式も、はじめは目新しく早めに用意したり、雑談コーナーに色々書いたりするのですが、段々とそういうことも減ってきて、結局ギリギリに用意することになったり、雑談コーナーも寂しくなってしまうことがあります。

まぁ、これは別に悪いことではなく、いつでも雑談に書き込める状況を維持すること、早く書くことは強制ではないので、そこのハードルを上げずに、選択肢を増やした状態を維持することが大切なのかなと感じています

# まとめ

まだ、探り探りですが、ミーティングの議事録を事前に用意することで、より効率的なミーティングの実現と、チーム内でのコミュニケーションを促進する方法について紹介しました。
【Expo】ImagePickerで画像を複数枚選択する方法

# はじめに
個人開発中にImagePickerを「Expo ImagePicker 複数枚選択」とググっても「ImagePickerでは複数枚選択できない」とか「MediaLibraryでできる」という記事しかでてこないので記事を書くことにしました。

記事の最後にExpoで個人開発したアプリを紹介しているのでもしよければダウンロードお願いいたします!!🙏

# 前提
* SDK45以上
* expo-image-pickerインストール済み

# 結論
下記のようにするだけでした。
```react
import * as ImagePicker from "expo-image-picker";
~~
~~
const result = await ImagePicker.launchImageLibraryAsync({
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
  allowsMultipleSelection: true, // これをtrueに設定する
  quality: 1,
});
```
これだけでした。そしてしっかり公式ドキュメントに書いてました。。
やっぱり記事をググる前にドキュメント読まないといけないなと痛感しました👶

https://docs.expo.dev/versions/v47.0.0/sdk/imagepicker/

ちなみに`allowsMultipleSelection`と画像をトリミングする`allowsEditing`は共存できません。
例えば以下のような使い方はNG、、というよりできないです。

```react
await ImagePicker.launchImageLibraryAsync({
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
  allowsMultipleSelection: true, //どちらかを..
  allowsEditing: true, //falseにしてｸﾚ....
  quality: 1,
});
```

# 選択枚数の制限をかける
選択できる画像の最大数を設定することもできます。なのですが、現状はIOS14以上でしか対応されていません。。
```react:IOS
await ImagePicker.launchImageLibraryAsync({
  ~~
  selectionLimit: 3, //3枚まで選択可能
});
```
Andoroidで選択最大数を再現したい場合は、選択された枚数を取得してアラートや独自モーダルで警告するのがいいと思います。
```react:Android
const result = await ImagePicker.launchImageLibraryAsync({
  ~~
});
if (!result.canceled && result.assets.length > 3) {
  Alert.alert("3枚以下にしてください。")
}
```
# 最後に
最後まで読んでくださりありがとうございます。少しでもお役に立てていれば幸いです。

もし役に立った、助かったと思って頂けたならこの記事の内容を盛り込んで作成した思い出管理アプリで遊んでいただけると嬉しいです！！

https://play.google.com/store/apps/details?id=com.nojitake.omoidemeisho
NTLM認証を利用したProxy環境下でのSalesforce開発環境構築

# はじめに

Proxy環境下では、何かと開発環境の構築に苦労する事が多いのですが、その中でもNTLM認証を使用したProxy環境下とVSCode×Salesforceの環境構築に苦労したので、忘れないために、まとめておきます。

https://trailhead.salesforce.com/ja/content/learn/projects/quickstart-vscode-salesforce

Salesforce CLIのインストール

https://trailhead.salesforce.com/ja/content/learn/projects/quickstart-vscode-salesforce/vscode-salesforce-ready

Salesforce Extension Pack のインストール

https://trailhead.salesforce.com/ja/content/learn/projects/quickstart-vscode-salesforce/vscode-salesforce-ready

については、深くは触れません。

# NTLM認証Proxyの代理サーバを中継に利用

いわゆるIDE（VSCodeやEclipse）などからは、基本的にNTLM認証に対応している事は、ほとんどありません。

諦めて、自分のローカルに代理サーバを構築するのが早いです。

![Proxy経路.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/f67020bf-dec6-ba00-5e6e-1fbf644c8d4f.jpeg)

# 代理サーバ(NTLM認証)

公式サイト

https://ntlmaps.sourceforge.net/

ダウンロードURL

https://sourceforge.net/projects/ntlmaps/

ZIP版をダウンロードして解凍することで利用可能です。
（pythonを利用しているようで、dllを内包していたり、Pythonインストールが必要だったりバージョンに依存しますが、Pythonで動作しているというあたりを認識しておく）

# 代理サーバ(NTLM認証)の設定

解凍したファイル群の中にある
+ <strong>server.cfg</strong>

に必要事項を設定する。

|項目名|設定内容|
|---|---|
|LISTEN_PORT|ローカルPCの受付ポート番号|
|PARENT_PROXY|NTLM認証のPROXYサーバのホスト名|
|PARENT_PROXY_PORT|NTLM認証のPROXYサーバのポート番号|
|PARENT_PROXY_TIMEOUT|NTLM認証のPROXYサーバとのタイムアウト秒数|
|FRIENDLY_IPS|転送を許可するIPアドレス（ローカルPCのIPアドレス）|
|NT_HOSTNAME|ローカルPCのホスト名|
|NT_DOMAIN|ローカルPCの所属するWindowsドメイン名|
|USER|ユーザ名（Windows環境）|
|PASSWORD|パスワード（Windows環境）|

NTLM認証は、ログインするWindowsドメインの認証を利用する仕組みなので、『FRIENDLY_IPS』で許可するIPアドレスは自分のPCのみを許可するのが望ましい。（なりすまし防止）

# VSCode×Salesforceの環境のProxy

+ settings.json

にProxyの設定が可能ですが、Salesforceプラグインから起動されるCLIは、別の実行端末環境が起動しているようで『settings.json』のProxy設定を引き継がない模様です。

とはいえ、念の為にこちらにも設定
|設定名|値|
|---|---|
|http.proxyAuthorization|http://ユーザ名:@ローカルPCのIPアドレス:受付ポート|
|http.proxy|http://ローカルPCのIPアドレス:受付ポート|
|http.proxyStrictSSL|false|

Windowsのシステム環境変数にProxyの設定を追加すると、『組織の認証』が成功するようになります。

|システム環境変数|値|
|---|---|
|HTTP_PROXY|http://ローカルPCのIPアドレス:受付ポート|
|HTTPS_PROXY|http://ローカルPCのIPアドレス:受付ポート|

※『HTTPS_PROXY』の方も、『<strong>http（sなし）</strong>』であることに注意

# Salesforceの組織『SFDX:組織を認証』には、Javaが必要

+ <strong>settings.json</strong>

|設定値|値|
|---|---|
|salesforcedx-vscode-apex.java.home|javaのJRE環境(C:\\Program Files\\Java\\jdk1.8.0_xxx\\jreなど)|

# お世話になった記事

https://qiita.com/shunkosa/items/e6248520bff90f397158

プラグインの使い方自体などは、こちらを参照させて頂きました。（非常に参考になりました。）

# まとめ

NTLM認証Proxy環境下での開発環境構築は大変なので、ローカルPCに代理サーバを立てて、何でもかんでも代理サーバを通すようにするとイロイロと開発環境構築時のトラブルを回避できる。
GitHub Actionsで何故かIAM Roleの引受ができない

仕事でよくGithub Actionsを使用するのですが、忘れがちな設定なのでメモします。

## やりたきこと
 - GitHub Actions内で、IAMロールをOIDCを使用してActions実行インスタンスに渡したい。
 - 設定値
### IAMロール側信頼ポリシー
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWSアカウントID>:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:<GitHubアカウント名>/<リポジトリ名>:*"
                }
            }
        }
    ]
}
```
### IDプロバイダ
[こちら](https://zenn.dev/kou_pg_0131/articles/gh-actions-oidc-aws)の記事を参考にIDプロバイダの作成も済ませる。

### GitHub Actionsワークフローファイル
```yml
name: Sample

on:
  workflow_dispatch:

env:
  AWS_REGION: ap-northeast-1
  AWS_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/Sample-role

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@master
        with:
          role-to-assume: ${{ env.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}
```
AWSのアカウントIDは一応リポジトリのSecretに追加して運用してます。

## エラー内容
![スクリーンショット 2023-02-03 12.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960876/da87b7c8-fa0e-4d45-4ae7-1d13220bff51.png)
この`Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers`というエラーがなかなか辛かった。

## 修正方法
```yml
jobs:
  deploy:
    runs-on: ubuntu-latest
    # These permissions are needed to interact with GitHub's OIDC Token endpoint.
    permissions:
      id-token: write
      contents: read
```
こんな感じで、`id-token`に書き込むための設定を加えてあげる。
じつはGitHubの[Usage](https://github.com/aws-actions/configure-aws-credentials#usage)にちゃんと書いてある。
やっぱり一次情報を見に行くのが鉄板ですね。
マイクロサービス概論

超久々に記事記載。
最近マイクロサービス案件に携わることが多くなってきたのでちょっとまとめてみます。

# マイクロサービスのすすめ

バグが多くなるプログラムとバグが少ないプログラムの違いを考えるとこんな感じのものがあるのではないでしょうか？

## バグが多くなるプログラム
- ステップ数が多いプログラム
- 複雑怪奇なコード、ロジック、データ構造
- 共通化、再利用ができない(枯れないロジック、毎回テストが必要、同じようなロジックがあちこにに分散してメンテ漏れ)

で、こんな感じの重厚長大なプログラムばかりだと、やれば炎上、デスマーチ…

じゃ、 **逆を行こう！**  ってなりますよね。

## バグが少ないプログラム
- ステップ数の少ないプログラム
- 簡単なコード、単純データ構造
- 共通化、再利用して枯れたロジック

プログラムを極限まで細かく単純なデータ構造にして再利用可能な形で実装しよう！ **それって、マイクロサービス！！！** ってなります。

## イニシエの頃から UNIXという考え方 -その設計思想と哲学
UNIXは、MIT、GE、 AT&T社で共同開発していたMulticsという巨大なOSの開発プロジェクトが複雑すぎ遅々として進まなかったことの反省より、**1969年**にAT&T社のベル研究所が見切りをつけてプロジェクトを抜け、ケントンプソン、デニスリッチー、ブライアンカーニハン、ダグラスマキルロイ、マイクレスク、ジョーオサンナらによって開発が開始された。**1994年**にマイク・ガンカーツは、X-Window System開発チームでの経験を基に以下の哲学を創出しました。

- Small is beautiful(小さいものは美しい)
- Make each program do one thing well (1つのプログラムには1つのことをうまくやらせる)

って、Mike Gancarz (マイク・ガンカーツ) 1994年に言ってるんですね。30年前よ。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255677/61c40cc7-a6c1-c1c6-139e-008e6f395579.png">

UNIXという考え方(オーム社)

AndroidもiOSも、実は中身はUNIX OSです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255677/9a935605-c949-fbe6-fe35-90696c885786.png)
よいプログラムとはハードウエアが大きく変わっても使われ続けられるんですね。

## マイクロサービスとは？

マイクロサービスは、 2014年、ThoughtWorks社のマーチン・ファウラーとジェームス・ルイスが提唱したソフトウェアアーキテクチャ。小さく独立した複数のサービスでソフトウェアを構成する開発技法。下記に述べる特性を挙げている。

- サービスのコンポーネント化 - コンポーネントは独立して交換・更新可能なソフトウェアの単位である。
- ビジネス中心組織 -開発運用チームは技術や開発工程によるチームではなく、ビジネスを中心に機能横断型のチームが編成されている。
- プロジェクトではなくプロダクト - チームは開発完了とともに解散するプロジェクトモデルではなく、製品のライフサイクル全体に責任を持つ。
- スマートエンドポイントとダムパイプ - メッセージ通信は軽量かつシンプルであること。エンドポイントに高い機能を持たせ、通信はダムパイプ（メッセージのルータとしてのみ動作する単純な機構）であること。
- 分散統治 - 各サービスは独立したチーム、開発言語、ツールでアプローチする。
- 分散データ管理 - 概念モデルに関する分散だけでなく、データストレージも分散(サービス間で独立)する。
- インフラストラクチャの自動化 - テスト自動化/継続的デリバリー/継続的インテグレーションの導入
- 障害の設計 - 個々のサービスはいつでも失敗する可能性があるため、互いに障害を迅速に検出し、可能であれば自動的にサービスを復元できることが重要。
- 進化的な設計 - 頻繁に、迅速に、適切に制御されたソフトウェアの変更・廃止・構築を行うことができること。

ただし、これらは定義ではなく、すべての特性をもつ必要はないとしている。
Martin Fowler -Microservices
https://martinfowler.com/articles/microservices.html

## サービスとは？
サービスとは機能を実現するために、単独で動作・デプロイ・リリースできるコンポーネントのこと。

- サービスを利用するためのAPI
- サービスを処理するロジック
- サービスのデータを保持するDB

を持つ。

サービスのサイズ感はアレですけどこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255677/68c0971b-cd5f-9a31-fe46-0009c25aa2b1.png)

ここでいうサービスとはWebサービスですね。

マイクロサービスは修正範囲が限定されるので利点がある。と説明されることが多いけど、限定されるようにサービスを分割する『設計力』が必要ということ。
オブジェクト指向プログラミングであっても構造化プログラムであっても、太古の頃から設計力の重要性については言われていますね。

すべてのシステムをマイクロサービス化してリプレイスすることは莫大なコストがかかるため一部の機能のみマイクロサービス化した場合のアーキテクチャを次は考えていきます。

以上
VSCodeでJavaの引数名（パラメータ名）のヒントを非表示にする メモ

# はじめに

- VSCodeでJavaの引数名（パラメータ名）のヒントが表示されると、Vimプラグインなどで操作しずらい。。。
- そうだ非表示にしよう

# 設定

- VSCodeの設定からparameterで検索する
- `Java > Inlay Hints > Parameter Names` を `none` に設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/bd87083c-e980-9386-a397-d43cde6de356.png)

# さいごに

- すぐに忘れる
Z80アセンブラで書いたインベーダー

CHATGPTでインベーダーゲームを書かせてみた。
イメージ的には、インベーダーが体当たりで降りてくるイメージだが、ソース的には十分な内容だった。
玉を発射したりするルーチンは無いけど、たぶんココからちょっと指示しただけで、追加してくれると思う。
なんか妙に懐かしく、PC8001のゲームが作りたくなってきた。

```z80
; インベーダーゲーム
; Z80アセンブラで書いたサンプルプログラム

org	100h

; スタートアップルーチン
startup:
	ld	a,#0
	ld	(score),a	; スコアをゼロに設定
	ld	(lives),a	; 残機をゼロに設定
	call	init		; 初期化
	call	play		; ゲーム開始
	jp	finish		; 終了

; 初期化ルーチン
init:
	ld	a,#20		; 画面の幅を20文字に設定
	ld	(width),a
	ld	a,#16		; 画面の高さを16行に設定
	ld	(height),a
	call	clear_screen	; 画面を消去
	call	create_ship	; 自機を作成
	call	create_invader	; インベーダーを作成
	jp	startup		; スタートアップに戻る

; 画面を消去するルーチン
clear_screen:
	ld	hl,#0000h	; 画面の先頭アドレスを設定
	ld	bc,#4000h	; 画面サイズを設定
	ld	a,#20h		; 画面を消去するためのデータ
	ldir			; 全てを20hで埋め尽くす
	jp	startup		; スタートアップに戻る

; 自機を作成するルーチン
create_ship:
	ld	hl,#4000h	; 画面の底端をHLに設定
	ld	(ship_pos),hl	; 自機の座標を記憶
	ld	a,#0fh		; 自機を作成するためのデータ
	ld	(hl),a		; 自機を画面に描画
	jp	startup		; スタートアップに戻る

; インベーダーを作成するルーチン
create_invader:
	ld	hl,#0000h	; 画面の先頭アドレスをHLに設定
	ld	a,#0eh		; インベーダーを作成するためのデータ
	ld	(hl),a		; インベーダーを画面に描画
	jp	startup		; スタートアップに戻る

; ゲームを開始するルーチン
play:
	call	draw_screen	; 画面を描画
	call	control		; 操作を受け付ける
	call	move_ship	; 自機を動かす
	call	move_invader	; インベーダーを動かす
	call	check_collision	; 衝突をチェックする
	call	check_end	; ゲーム終了をチェックする
	jp	play		; 繰り返す

; 画面を描画するルーチン
draw_screen:
	ld	hl,#0000h	; 画面の先頭アドレスをHLに設定
	ld	bc,#4000h	; 画面サイズを設定
	ldir			; 画面を描画
	jp	startup		; スタートアップに戻る

; 操作を受け付けるルーチン
control:
	in	a,(#00h)	; キー入力を受け取る
	cp	#01h		; 左キーが押されたかチェック
	jp	z,move_left	; 押されていたら左に移動
	cp	#02h		; 右キーが押されたかチェック
	jp	z,move_right	; 押されていたら右に移動
	jp	startup		; スタートアップに戻る

; 左に移動するルーチン
move_left:
	ld	a,#0fh		; 自機を消去するためのデータ
	ld	(ship_pos),a	; 自機を消去
	dec	hl		; 左に1文字移動
	ld	(ship_pos),hl	; 自機の座標を記憶
	ld	a,#0fh		; 自機を作成するためのデータ
	ld	(hl),a		; 自機を描画
	jp	startup		; スタートアップに戻る

; 右に移動するルーチン
move_right:
	ld	a,#0fh		; 自機を消去するためのデータ
	ld	(ship_pos),a	; 自機を消去
	inc	hl		; 右に1文字移動
	ld	(ship_pos),hl	; 自機の座標を記憶
	ld	a,#0fh		; 自機を作成するためのデータ
	ld	(hl),a		; 自機を描画
	jp	startup		; スタートアップに戻る

; インベーダーを動かすルーチン
move_invader:
	ld	a,(inv_pos)	; インベーダーの座標を取得
	ld	hl,a		; HLに設定
	ld	a,#0eh		; インベーダーを消去するためのデータ
	ld	(hl),a		; インベーダーを消去
	inc	hl		; インベーダーを1文字右へ移動
	ld	(inv_pos),hl	; インベーダーの座標を記憶
	ld	a,#0eh		; インベーダーを作成するためのデータ
	ld	(hl),a		; インベーダーを描画
	jp	startup		; スタートアップに戻る

; 衝突をチェックするルーチン
check_collision:
	ld	a,(ship_pos)	; 自機の座標を取得
	cp	(inv_pos)	; インベーダーの座標をチェック
	jp	z,game_over	; 衝突したらゲームオーバー
	jp	startup		; スタートアップに戻る

; ゲームオーバー時の処理
game_over:
	dec	(lives)		; 残機を減らす
	ld	a,(lives)	; 残機を取得
	or	a		; 残機がゼロかチェック
	jp	z,finish	; ゼロなら終了
	call	create_invader	; インベーダーを再作成
	jp	startup		; スタートアップに戻る

; ゲーム終了をチェックするルーチン
check_end:
	ld	hl,#4000h	; 画面の底端をHLに設定
	ld	a,(inv_pos)	; インベーダーの座標を取得
	cp	hl		; 画面の底端と比較
	jp	nc,startup	; 画面の底端以外ならスタートアップに戻る
	inc	(score)		; スコアを1増やす
	call	create_invader	; インベーダーを再作成
	jp	startup		; スタートアップに戻る

; 終了ルーチン
finish:
	halt			; プログラムを終了

; 変数定義
score	defb	00h	; スコア
lives	defb	00h	; 残機
width	defb	20h	; 画面の幅
height	defb	16h	; 画面の高さ
ship_pos	defw	0000h	; 自機の座標
inv_pos	defw	0000h	; インベーダーの座標

end
```
Glue Data Quality(プレビュー版)について①

## はじめに
こんにちは。株式会社ジールの@Shin-Nakamura224です。
先日、Glue Data Quality(プレビュー版)が発表されたので、
概要と簡単な検証を紹介したいと思います。
今回の記事はGlue Data Qualityの概要について紹介いたします。

検証 ↓
[Glue Data Quality(プレビュー版)について②](https://qiita.com/Shin-Nakamura224/private/2bf8fdf5cea311811b03)
***
## 概要
### Glue Data Qualityとは
AWS Glueでデータの品質検査（問題の検出）を簡単に実施できる機能になります。
（2022年11月30日​発表）
ユーザは品質評価のルール（DQDL）を設定して、データの品質検査を実施することが可能​です。
Amazonが開発したOSSのDeequを使用してルールを評価します。
<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120637/f60f0be1-2fc4-fa46-cfa2-89374ad2e5cd.png">
引用元：https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-glue-data-quality-preview/
***
### データの品質検査とは
データレイクには様々なデータが保存されますが、データソースに変更が加わったり、
処理が変更されると、データソースに保存されるデータが意図しない形に変更される可能性があります。
よってデータ分析の際には正確なデータを使用するための検査が必要​になります。
###### 品質検査の例​
・特定カラムが含まれているか​
・カラムに含まれる値の範囲​
・値がプライマリーキーとして利用できるか​
・ユニークな値の判定​

今までは、品質検査を行うために手作業で品質検査を実装するコードを書く必要がありました。
そこで今回発表された​ **AWS Glue Data Quality** を利用することによって、
簡単に品質検査を行うことができるようになりました。
***
### DQDL(Data Quality Definition Language)
DQDLはデータ品質のルールを定義するための言語です。
Glue Data Qualityでは、DQDLを使用して「ルールセット」(データのチェック内容)を作成し、
Glueのテーブルに対してタスクを実行することで、データレイクに保存されているデータの品質を検査します。
#### DQDLルール定義の方法
DQDLの定義方法は以下の例の通りになります。
※大文字、小文字は区別されます。

```:例：「order-id」列の値がすべて非NULLであるか, 「order-id」列の値がすべて一意であるか
Rules = [ IsComplete "order-id", 
          IsUnique "order-id" ] 
※ルールが複数ある場合はカンマで区切って定義。
```
***
#### DQDLで定義可能なルールの例
DQDLは定義可能なルールタイプが約20種類あります。
詳細：https://docs.aws.amazon.com/glue/latest/dg/dqdl.html

一部の例が以下の通りになります。


```:ColumnExists：カラムが存在するかチェック
Rules = [ColumnExists “列名" ] 
```
```:ColumnLength：値の長さが指定した数値と合致するかをチェック
Rules = [ColumnLength “列名" = 5] 
```
```:IsPrimaryKey：対象カラムが主キーを含むか（カラムの値がすべて一意であるか）をチェック
Rules = [IsPrimaryKey “列名" ]
```
***
### Deequ
Deequとは、Amazonで開発・利用されているオープンソースツールのことです。
大規模なデータの品質をテストすることができます。
主な機能としては、以下の3点が挙げられます。
・メトリクスの計算
⇒Amazon S3 などのソースから読み取り、完全性・最大値・相関などの統計を計算する
・制約の検証
⇒指定した制約の検証を実施し、結果を生成する
・制約の提案
⇒データ品質制約の提案、有用な制約を推測するなど、制約作成のサポートを行う。
<img width="700" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120637/2758068f-0588-aa7a-d70f-b62e189fdc26.png">

引用元：https://aws.amazon.com/jp/blogs/news/test-data-quality-at-scale-with-deequ/
***
### Glue Data Quality(プレビュー版)の仕様について
・**Glue3.0** のみ対応
・データソースは **S3** のみ利用可能
・利用可能なリージョン
　- バージニア北部（us-east-1）​
　- オハイオ（us-east-2）​
　- オレゴン（us-west-1）​
　- 東京（ap-northeast-1）​
　- アイルランド（eu-west-1）
・料金はETLジョブの実行に費やした時間に対して課金​（Glue jobと同様）
※リソースの管理費用や初期費用は不要。​
 　スタートアップ時間やシャットダウン時間も課金されない。​
***
## まとめ
今回の記事では、AWS Glue Data Quality(プレビュー版)の概要について紹介いたしました。
Glue Data Qualityはデータの品質を検査する機能となります。
今までDeequをインストール・セットアップしたり、
コードを手作業で作成してデータを検査していましたが、
Glue Data Qualityを利用することでその手間を省くことができます。
現在のところ色々と制限（Glue3.0のみ対応、S3のみ対応等）はありますが、
今後のGAに期待しつつ、使い倒していこうと思います。
***
## 次回の記事について
次回の記事は下記の2点の検証について紹介いたします。
① ELTジョブ内でData Qualityの品質検査の実施と
　Data Qualityのルール違反をAWS CloudWatchで通知
② Python処理との実行時間の比較

[Glue Data Quality(プレビュー版)について②](https://qiita.com/Shin-Nakamura224/private/2bf8fdf5cea311811b03)
Laravel ファイルアップロードでname属性を配列で扱う処理例

### Laravel ファイルアップロードでname属性を配列で扱う処理例を紹介します

ファイルアップロードでname属性を配列で扱うのは、不確定の数をファイルアップロードを受け取りたい場合に使うケースがあります。
それでは順番に確認していきます。

#### HTML
HTML側のFILE INPUTを以下の通りにname属性を配列にした場合。
```view/upload.blade.php
<div class="row">
    <div class="col-sm-3 col-form-label-sm mb-1">添付ファイル</div>
    <div class="col-sm-9 mb-1">
        <input id="file-multiple-input" type="file" name="file[]" multiple="">
    </div>
</div>
```

#### アップロード先の定義
ファイルCONFIGで定義を作っておくと、メンテナンスや再利用の管理がしやすいので、
使うストレージ設定の配列にroot、filepathを付け足しておく。
今回は、documentsに入れています。

```config/filesystems.php
<?php
return [
    /*間省略*/
    'disks' => [
        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],
        'documents' => [
            'driver' => 'local',
            'root' => storage_path('app/documents'),
            'url' => env('APP_URL').'/documents',
            'filepath' => '/documents',
        ]
    ],

];
```

#### アップロード処理
POSTで受け取ったら、foreachループで１つ１つファイルを保存して、dbに記録する処理を行っています。

```Controller/FileUploadController.php
if ($request->has('file')) {//ファイル送信の有無
    foreach ($request->file as $key){{//配列をループする
        //ファイルの保存先などのパスをCONFIGで定義を取っくる
        $storagePath = Config::get('filesystems.disks.documents.root');
        $folderpath = Config::get('filesystems.disks.documents.filepath');
        $OriginalName = $key->getClientOriginalName();//POSTされてくるファイル名
        $extension = $key->getClientOriginalExtension();//POSTされてくるファイルの拡張子
        $pathInfo = pathinfo($OriginalName);

        //ファイル名をユニークにしたいので、
        //ファイル名が日本語だったり、保存先に同じファイル名があったりするなら、
        //新しいファイル名を命名する。
        if (preg_match("/^[\x21-\x7e]{1,50}+$/", $pathInfo['filename'])) {
            $UploadFileName =$this->unique_filename($storagePath.DIRECTORY_SEPARATOR.$pathInfo['filename'].'.'.$extension);
        } else {
            $newfileName = md5(date('YmdHis').$pathInfo['filename']).'.'.$extension;
            $UploadFileName =$this->unique_filename($storagePath.DIRECTORY_SEPARATOR.$newfileName);
        }
        //指定のパスに指定のファイル名でファイルを保存
        $filepath = $key->storeAs(DIRECTORY_SEPARATOR, $UploadFileName, ['disk'=>'documents']);
        //DBに相対パスで保管
        $doc = new Documents;
        $doc->filepath = $folderpath.DIRECTORY_SEPARATOR.$filepath;
        $doc->save();
    }
}


    /**
     * ユニークファイル名の生成
     *
     * @param  string  $org_path
     * @param  int  $num
     * @return string
     */
    protected function unique_filename($org_path, $num=0){
        if( $num > 0){
            $info = pathinfo($org_path);
            $path = $info['dirname'].'/'.$info['filename']."_".$num.'.'.$info['extension'];
        } else {
            $info = pathinfo($org_path);
            $path = $info['dirname'].'/'.$info['filename'] .'.'. $info['extension'];
        }
        if(file_exists($path)){
            $num++;
            return $this->unique_filename($org_path, $num);
        } else {
            $info = pathinfo($path);
            $fileName = $info['filename'] .'.'. $info['extension'];
            return $fileName;
        }
    }
```

こんな所です。ユースケースにより、バリデーションを加えたりします。
簡単な紹介ですが、ご参考ください。
[Python]collection.dequeを使ってマージソートをする

# 実現したいもの
Pythonを用いたマージソートを実装する。

# まずは普通に
両端キューを使わずに実装してみる。

```py
def merge_sort(a):
    # 空配列の場合は返す
    if len(a) <= 1:
        return a

    n = len(a)
    x = n / 2
    l, r = [], []

    # 分割
    for i in range(n):
        if i < x:
            l.append(a[i])
        else:
            r.append(a[i])

    # 再帰関数の呼び出し
    l = merge_sort(l)
    r = merge_sort(r)

    # 結合
    merged = []
    merged.extend(l)
    r.reverse()
    merged.extend(r)

    b = []
    while len(merged) != 0:
        first = merged[0]
        last = merged[len(merged)-1]
        if first <= last:
            b.append(first)
            del merged[0]
        else:
            b.append(last)
            del merged[len(merged)-1]

    return b

n = int(input())
a = list(map(int, input().split()))
sorted_a = merge_sort(a)
print(*sorted_a)
```

`l, r`の結合処理に注目してほしい。

```py
# 結合
    merged = []
    merged.extend(l)
    r.reverse()
    merged.extend(r)

    b = []
    while len(merged) != 0:
        first = merged[0]
        last = merged[len(merged)-1]
        if first <= last:
            b.append(first)
            del merged[0]
        else:
            b.append(last)
            del merged[len(merged)-1]
```

`merged`という空配列を準備し、両端の値を比較、小さいほうを別の配列`b`に移動している。

## 問題点
Pythonのlistにおける先頭の要素の削除は、後続の要素をすべて前にずらす関係上 **計算量が $O(N) $ になる**という弱点がある。
そのため、`(first <= last) == True`が続くような入力パターンに弱い。

# 改善案
`collections.deque`を利用する。

> Deque はどちらの側からも append と pop が可能で、スレッドセーフでメモリ効率がよく、どちらの方向からもおよそ O(1) のパフォーマンスで実行できます。

# 実装例
```py
from collections import deque

def merge_sort(a):
    # 空配列の場合は返す
    if len(a) <= 1:
        return a

    n = len(a)
    x = n / 2
    l, r = [], []

    # 分割
    for i in range(n):
        if i < x:
            l.append(a[i])
        else:
            r.append(a[i])

    # 再帰関数の呼び出し
    l = merge_sort(l)
    r = merge_sort(r)

    # 結合
    dq = deque()
    dq.extend(l)
    r.reverse()
    dq.extend(r)

    b = []
    while len(dq) != 0:
        first = dq[0]
        last = dq[-1]
        if first <= last:
            b.append(dq.popleft())
        else:
            b.append(dq.pop())

    return b

n = int(input())
a = list(map(int, input().split()))
sorted_a = merge_sort(a)
print(*sorted_a)
```


# 参考
https://note.nkmk.me/python-collections-deque/

https://qiita.com/Hironsan/items/68161ee16b1c9d7b25fb
Keian wizbook KZG14X128BK 買ってみた。

# 概要
keian KZG14X128BK 買ってみた。

# 写真

http://www.keian.co.jp/img/2011/08/KZG14X128BK_hpbanner07v2.jpg

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b298f80f-4092-db05-10ca-8ab20153b19b.png)

# 良いところ
- ssd が余裕
- コアが4つ

# 駄目なところ
- wifiのon,offが不明
- キーが、ぺなぺな


# 一番駄目なところ
- windowsが、認証エラーしてる。
エラーコードは、0xc004c008
どうする、俺。


以上。
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「AzureロールとAzure ADロール」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「AzureロールとAzure ADロール」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[Azure ロールと Azure Active Directory ロールを比較する](https://learn.microsoft.com/ja-jp/training/modules/configure-role-based-access-control/5-compare-azure-roles-to-azure-ad-roles)
[ロールベースのアクセス制御を適用する](https://learn.microsoft.com/ja-jp/training/modules/configure-role-based-access-control/6-apply-authentication)
[ロールベースのアクセス制御ロールを決定する](https://learn.microsoft.com/ja-jp/training/modules/configure-role-based-access-control/7-determine-roles)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「ロールの割り当て」](https://qiita.com/fsd-jume/items/1c6bee555c85d57d1e51)

## AzureロールとAzure ADロール
### Azureにおけるロール
・従来のサブスクリプション管理者ロール
・Azureロール(Azure RBACロール)
・Azure ADロール

### 従来のサブスクリプション管理者ロール
・Azureリリース段階から実装されていた管理者ロール
・Azureサブスクリプションへのフルアクセス権がある
・Azureへのサインアップに使用されたアカウントが自動的に管理者になる
⇒自動的にアカウント管理者とサービス管理者の両方に設定される
・サービス管理者/共同管理者は所有者ロールと同等のアクセス権
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/cab0abaf-bedc-035c-f3f9-ebe1473e53ae.png)

### Azureロール(Azure RBACロール)
・従来のサブスクリプション管理者ロールの後に追加されたロール
・Azureリソースに対するきめ細かいアクセス管理を提供
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/89296c34-4a54-c702-1aaa-d4eb076caf0a.png)
**◆Azureロールの注意点**
・上記以外にも組み込みのロールがある
　-例：仮想マシン共同作成者 → VMの作成/管理をユーザに許可
・組み込みロールでニーズを満たせない場合、カスタムロールを作成可能
・ロールでオブジェクト内のデータへのアクセス権を付与可能

### Azure ADロール
・Azure ADリソース(ユーザ/グループ/ドメインなど)を管理するロール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/c2b4b8c1-029f-9595-058e-a55e6b2dc2dc.png)

### AzureロールとAzure ADロールの比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/5dddec08-e9ce-d27b-2008-c53ce258e162.png)

## 次の学習内容
**◆Azure ADユーザアカウントの追加/削除**

https://qiita.com/fsd-jume/items/1fba86e7f873f3e56400

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
mesonを使用してのビルドでライブラリが見つからないときの対策

#### 【きっかけ】
Linuxのターミナルってどんな仕組みになってるんだろう？
よし、gnome-terminalのソースコードをgit cloneして、まずビルドしてみるか！と、思ったのですが、gnome-terminalってビルドがmesonを使うようになってるんですね。
gnome-terminalは基本的なソフトウェアだしビルドもそんなに苦労せずにできるかな？と思ったのが間違いで、約半日の時間を溶かした原因になったのでした。

#### 【環境】

|   |   |
|:- |:-:|
| Ubuntu | 22.04 |
| meson | 1.0.0 |
| ninja | 1.11.1 |
| pkg-config | 0.29.2 |


#### 【環境構築】

meson + ninja は、pip3を使用してインストールしました。(あちこちのサイトでインストール手順は紹介されているので省略します)
他の方法を使ってインストールしても、基本的にバージョンが一緒であれば問題ないはずです。


#### 【エラーに至る手順】

まず、ソースコードのダウンロードを。

```bash:bash
$ git clone https://github.com/GNOME/gnome-terminal.git
$ cd gnome-terminal
```

いよいよビルドなのですが、最初、ライブラリのvte-2.91が見つからず、そうか、パス指定しないといけないのかなと思い、HomeBrewで **pkg-config** をインストールしました。
先に結論を言ってしまうと、このHomeBrewの **pkg-config** が原因でmesonが混乱して、ライブラリが見つかんねー！！って言ってたのです。

話をもとに戻して、一応 meson でのビルド手順も書いておきます。

``` bash:bash
$ meson setup <ビルドしたファイルを格納するディレクトリ名> ← build や builddirとすることが多いようです
```

これで、mesonが成果物を格納するディレクトリを作って、その中にファイルを格納してくれるはずなんですが、ログや中間ファイルは生成されているものの、ライブラリの ***vte-2.91*** が見つからず、ninjaを使ってコンパイルするためのファイルが生成されていませんでした。

ここで、上で書いた ***pkg-config*** をHomeBrewでインストールしたのですが、いろいろ試したりバージョンも確認していた中で気づいたのが、HomeBrewの　***pkg-config*** とaptでインストールした ***pkg-config*** は同じバージョンの0.29.2であるにも関わらず、mesonから呼ばれた場合の挙動に差異があるということでした。

そして、厄介なことに、mesonはライブラリを探しに行く際にHomeBrewでインストールしていた ***pkg-config*** をまず見つけて、そいつを使って共有ライブラリを探しに行こうとするのです。

これは多分なのですが、aptでインストールした　Ubuntuの公式リポジトリの ***pkg-config***は 、どうもバグフィックスされているような感じなのです。 " ***pkg-config --version*** "では 0.29.2 としか表示されないので、リビジョンまではわからなかったのですが、おそらくそういうことなんだと思います。

ちなみに、mesonが先にHomeBrewの ***pkg-config*** を見つけに行くのは、exportしたPATHの順番なのかなぁと想像しています。ただ、マイPCの環境では、PATH自体に特殊な設定はしておらず(HomeBrew以外のパスは幾つか追加していますがまるっきり関係ないパスなので、これによる影響はありません)、HomeBrew自体をインストールした際に ***$HOME/.profile*** に追加してね！と指定された設定しか適用していません。HomeBrewで ***pkg-config*** をインストールしてしまうと、mesonでのビルドで十中八九、この共有ライブラリが見つからないというエラーに出くわす可能性が高いです。

もうすこし補足しておくと、HomeBrewの ***pkg-config*** がmesonから呼ばれるときには、/etc/ld.so.conf.d/ に共有ライブラリのパスを追記して ***ldconfig*** でそれを反映させても、やっぱり共有ライブラリは見つからずじまいです。

#### 【結論】
mesonを使うときは ***HomeBrew*** の ***pkg-config*** は ***$ brew remove pkg-config*** でサクッとリムーブしちゃいましょう。でないと、無駄に時間が溶けるばかりです。

長くなってしまいましたが、さいごまでお付き合いいただきありがとうございました！
基本的なPython其の物についてお浚い

## 概要
改めてPythonがどういったプログラミング言語なのか、初学者向けに、なるべくわかりやすくまとめるように努め記述させて頂きます。

## Pythonの特徴
### 高水準言語
高水準言語とは、**人間が理解しやすい言語**を指します。C/C++, Perl, Javaなども高水準言語の一例です。もちろん、高水準言語の反対である低水準言語もあり、これには機械語やアセンブリ言語が含まれます。

:::note info
**人間が理解しやすい言語**
:::

### 動的型付け言語
動的型付け言語とは、**変数の型を事前に宣言しない言語**を指します。Pythonは実行時に型を判断しています。他の動的型付け言語としては、RubyやJavaScriptがあります。反対に、変数の型を事前に宣言する必要がある静的型付け言語としてはC/C++, C#, Java, Goなどがあります。

:::note info
**変数の型を事前に宣言しない言語**
:::

### インデントによる文のグルーピング
Pythonでは**文のグルーピングはインデント（字下げ）で行われます**。これは、例えばJavaのように{}を使用しないということを意味します。

:::note info
**文のグルーピングはインデントで行われる**
:::

### モジュールとパッケージによる再利用
Pythonでは、よく使う処理やクラスを整理、管理したいときに、モジュールとパッケージを利用することで**汎用性のあるコードを再利用することが可能**です。

:::note info
**汎用性のあるコードを再利用できる**
:::

### インタープリタ型言語
インタープリタ型言語とは、**プログラムの命令を一つずつ、機械語に解釈しながら実行する方式**のことを指します。コンパイルとリンクが不要であり、またPythonには<b>対話モード(インタラクティブモード)</b>という機能もあり、これによりインタープリタ上で、そのままPythonプログラムを入力・実行することが可能です。

なお、コンパイラ型言語として知られるC/C++, Javaなどは、ソースコードを一旦機械語に翻訳し、その機械語になったプログラムを実行します。ただし、Javaの場合は少し特殊で、JavaコードはまずJava Virtual Machine (JVM)が理解できるバイトコードにコンパイルされ、このバイトコードは実行時に機械語に変換されます。

インタープリタ型言語の欠点としては、実行される度にプログラム中の各ステートメントを分析しなければならないため、**プログラムの処理性能がコンパイラ型言語に比べて低くなりやすい**という点が挙げられます。

:::note info
- **コンパイルとリンクが不要**
- **対話的に使うことが可能**
- **コンパイラ型言語に比べると処理が遅い**
:::

## この記事のシリーズ
- [基本的なGo其の物についてお浚い](https://qiita.com/kimascript/items/965518539df2a54731eb)
LC(ライトニングチャレンジ)をしています！

運動通信社では開発チーム独自の取り組みとしてLC （ライトニングチャレンジ） をというものを行なっています！

## LC （ライトニングチャレンジ） とは 

「**5分程度の短い時間（やる分にはいくら長くなっても大丈夫です！！）でも良いので、新規で何かをチャレンジすること**」です。

ヒントはLT （ライトニングトーク）から
>カンファレンスやフォーラムなどのプレゼンテーションで、3～5分程度の短い時間で発表する手法

参考
https://www.brain-gate.net/content/column/engineer-tips-lt/
https://www.wantedly.com/companies/tobila/post_articles/104468#_=_
https://qiita.com/turmericN/items/6f13667fc34269acd88c

## 背景
この度ウェブ開発チームのGL（グループリーダー）の役割を担うことになりました。その中で「チームをどうしたいか？」「どういうチームを目指すのか？」ということを考えました。そこでまず第一に考えたこととして

「技術者グループである以上。テクノロジーを1人1人が楽しんでほしい。」

というのがありました。

IT業界にダイブして活躍しているみなさんであれば、新しい知識を得たり、そのアウトプットで何か変化が起きたことで面白さを感じたりモチベーションが上がった経験があると思います。それは私たちの武器だし、大切なことだと思うのですが、タスクに追われる昨今で忘れてしまいがちなのではないでしょうか？

LCのような取り組みをしていくことによってコードを書く機会であったり、知見を増やしたり...最終的にその活動が各メンバー自身の市場価値を高めて、チームや仕事への貢献に繋がるはずだと思ったのがきっかけです！

## 目的
技術者グループである以上。テクノロジーを1人1人が楽しもう！！

## ルール
特にルールを決める必要はないと思いますが、ある程度枠組みがあった方がわかりやすいので、弊社では以下のようなルールで運用しています。

- 新規で何かをチャレンジしてもらう。
- 新規の定義は今まで自分になかったものでスキルに関してはお任せする。（別にレベルが高いものをやってもらう必要はない）

    ex)
    vscodeのライブラリを追加してみた。
    〇〇さんの使ってるツールが便利そうだったので自分も使ってみた
    typescriptを触ったことがなかったのでチュートリアルをやってみた

- 5分でいいから必ず手を動かしてほしい
    気になったサービスとかのアカウントを作成してポチポチしてみる
    ツール入れてコマンド叩いてみる...etc
    ↑このレベルから始めても問題ないです。

- 共有はslackの専用チャンネルへ。必ず一言コメント（自分なりの感想）を記載する


## 実施フローの例

前提としてアンテナを張っておく。興味のあるものをどこかにストックしておく

1. テーマを決める
2. どこまでやるかいつまでにやるか決める
3. 手を動かす
4. まとめる（自信の感じた体験を教えてください。DXっていうの？）
5. slackで共有

※ やってて最初に決めた範囲、期限まで終わらなさそうであれば再調整。終わってなくても終わってないなりに区切りをつける。次回に回すとか

ex)
![スクリーンショット 2023-02-24 16.36.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254217/33eec203-7648-8b04-00d8-2be23a3bab64.png)


## 表彰
振り返りとして毎週LCの表彰を行なっています。表彰する項目は以下です（運用していくうちに変えてく予定）

- 今週もっともチャレンジ（共有数）が多かった人
- 今週もっともいいねが多かった人（累計）
- 今週もっとも良かったテーマ（弊社ではランダムで決めるメンバーを選出して、その人の独断と偏見で決めてもらってます笑）

## あとがき
開発だけじゃなくて会社全体を巻き込みたい。あとは上手く定着したらLTに昇華してイベントとかできたら良いね...

## 最後に運動通信社について
運動通信社は「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、一緒に働く仲間を募集しています！
PMやアプリエンジニア、Webエンジニアなど色んな職種を募集しておりカジュアル面談大歓迎なので是非採用フォームよりご連絡ください！
ぜひ一緒に、自分たちも世の中もワクワクするサービスを作りましょう！

https://sportsbull.jp/about/#recruit
GitHub用のSSH keys作成と設定

久しぶりにログインしたら鍵が爆発してたのでメモ

# ENV
- OS: Mac
- Date: 2023/02

# 1. 鍵の生成
FYI: [新しい SSH キーを生成して ssh\-agent に追加する \- GitHub Docs](https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)

- デフォルトの鍵にして使いまわしたくないので鍵名はgithub.id_rsaに
```bash:step1
# 生成
$ ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/github.id_rsa

# 生成を確認
$ ls -l ~/.ssh/github.id_rsa*
-rw-------  **** ~/.ssh/github.id_rsa
-rw-r--r--  **** ~/.ssh/github.id_rsa.pub
```

## 補足
- ex. ディレクトリ作成(必要なら)
    - `$ mkdir -m 700 ~/.ssh`
- `github.id_rsa`
    - 秘密鍵、流出させてはならない
- `github.id_rsa.pub`
    - 公開鍵
- `-t ed25519`
    - 鍵生成アルゴリズム([エドワーズ曲線デジタル署名アルゴリズム \- Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%89%E3%83%AF%E3%83%BC%E3%82%BA%E6%9B%B2%E7%B7%9A%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E7%BD%B2%E5%90%8D%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0#Ed25519))
    -  OpenSSHが古いと使えない、アップデート推奨、できないなら`-t rsa -b 4096`を

# 2. 鍵をgithubに登録
[SSH and GPG keys](https://github.com/settings/keys) ->  [New SSH key]をクリック

- title
    - `$ hostname`の実行結果でも入れておく、他に適切な名前があればそれで
- Key type
    - Authentication Key
        - 通常はこっちでOK、最初から選択(default)
    - Signing Key
        - FYI: [SSH 署名キー \- GitHub Docs](https://docs.github.com/ja/rest/users/ssh-signing-keys?apiVersion=2022-11-28)
- Key
    - 公開鍵をコピーして貼り付け
```bash:step2
$ cat ~/.ssh/github.id_rsa.pub | pbcopy
```

[Add SSH Key]をクリック

# 3. SSH configの設定
1で作成した公開鍵をgithubで利用するよう設定
```bash:step3
$ cat << EOT >> .ssh/config
Host github.com
  HostName github.com
  IdentityFile ~/.ssh/github.id_rsa
EOT

# 追記を確認
$ tail -3 .ssh/config
Host github.com
  HostName github.com
  IdentityFile ~/.ssh/github.id_rsa
```

## 補足
- うまく設定できていない時
```bash
$ git clone git@github.com:****.git
Cloning into '****'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
【UiPath モダン】エクスプローラを検索した状態で開く

あまりシチュエーションは無いかもしれないですが、UiPathで「アプリケーション/ブラウザーを使用」アクティビティを使用してエクスプローラを検索した状態で開く。というのが現場で需要があったので備忘として。

エクスプローラを検索した状態で開くためには「search-msプロトコル」というものを使用することで可能となるらしいです。

https://learn.microsoft.com/en-us/windows/win32/search/-search-3x-wds-qryidx-searchms

いろいろ見てたんですが、奥が深かったのでとりあえずUiPathで開くときにどのようにしたかだけ記載していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/8082e66e-19fc-5173-d0a5-1313490b65e6.png)
アクティビティとしては、「アプリケーション/ブラウザーを使用」のみです。
アプリケーションパスには、explorer.exeのパスを設定
アプリケーション引数には、検索する文字列とどのフォルダで検索をするのかを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/773fa4c2-04da-d2d8-c8a2-8fc000d5ed10.png)
```csharp:式エディター
String.Format("search-ms:""query={0}&crumb=location:{1}""", 検索する文言, 検索するディレクトリ)
```


queryやcrumbについてはちゃんと調べて勉強できていないので記載は避けておきます。
AWS Lambdaに固定IPを付与する時の考慮事項(NAT Gatewayは0.062ドル/時､月約45ドル）

AWSの請求書を見たら想定外に高かったので調べたらNAT Gatewayでした｡
t4g.xlarge（vCPU:4､メモリ:16GB)を借りられる(3年予約)料金じゃないか･･･｡

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

これは､ある外部システムとの連携機能をAWS Lambdaで実装したのですが､IP制限に対応するために固定IPを持たせる必要があったため｡

不覚にも発生する料金はElastic IPだけだと思いこんでました｡涙
反省｡
SAPインストール後にUID/GIDを変える

設計の際、忘れがちなのがUID･GIDです。
最初にちゃんと設計をしないと、あとでファイル連携した際にパーミッションでうまくいかないことがあります。
ただ、導入後でも変更は可能です。

・OSユーザのUID変更
　usermod -u <新UID> sidadm

・OSユーザのGID変更
　groupmod -g <新GID> sapsys

これでOSユーザのIDは変更完了です。
しかし、ファイルのパーミッションは上記では変更されないので別途変更が必要です。
findで旧UID/GIDを見つけて一括で変えていきます。

・ファイルのパーミッションのUID変更
　find / -uid <旧UID> -print0 | xargs -0 chown <新UID/ユーザ名>

・ファイルのパーミッションのGID変更
　find / -gid <旧GID> -print0 | xargs -0 chgrp <新GID/グループ名>

変換が終わったら、再度findで確認します。
そうすると以下のようなシンボリックリンクが未変換で見つかると思います。
　/usr/sap/SID/SYS/exe/uc
　/usr/sap/SID/SYS/exe/nuc
　/usr/sap/SID/SYS/exe/dbg
　/usr/sap/SID/SYS/exe/run
　/usr/sap/SID/SYS/profile
　/usr/sap/SID/SYS/global

シンボリックリンクの場合"-h"オプションが必要なので、これらは個別に変更してください。
　chown -h <ユーザ名>:<グループ名> <シンボリックリンク>
re.error: nothing to repeat at position … ってなんだ？

Pythonなどでコーディングしていると、以下のようなエラーに遭遇することがあります。

::: note alert
**re.error: nothing to repeat at position**
:::

あとは0とか13とかいろんな数値が検索時の質問例に出てきますが、これに対してあまり有効な回答がなかったので、ズバリ答えを書いておきます。

# 回答
正規表現の繰り返し記号の部分を見直しましょう。また、**positionは正規表現内Regex（reはRegexのこと）記述部分の文字列位置**で、0だと0文字目、13だと13文字目です。

※マッチング対象の文字列ではなくて、Regexでの文字列位置なので注意。

## 実例１
例を見ていきます。例では加算の式から序数を抽出しています。

```py:test1err.py
 val = re.sub(r'(+?)(\d+)(.*)',r'序数:\2',val)
```

`?`は後で詳しく説明しますが、0回か1回の繰り返しを判定するマッチング記号なので、値（グループ）の存在有無を判定する場合によく用いられます。これを確認すると+記号が0文字か1文字で判定しているようですが、+という記号はマッチング記号（1文字以上の繰り返し）とも被ってしまうので、その結果**存在しない文字の繰り返し**を指定することになり、以下の警告が出ます。

**nothing to repeat**

つまり、**繰り返したい文字が存在しない**という意味です。繰り返し記号と重なる記号をマッチングさせたりする場合は必ずエスケープしておきましょう。

```py:test1.py
 val = re.sub(r'(\+?)(\d+)(.*)',r'序数:\2',val)
```

## 実例２
次のようにパスを認証したい場合でも出現します。一見?no=9999（9999は任意の番号）に紐づくパスクエリを確認しているようですが…

```py:test2err.py
re.match(r'(.+)(?no=)(\d+)',path)
```

説明した通り、`?`はエスケープが必要なので、以下のように修正します。

```py:test2.py
re.match(r'(.+)(\?no=)(\d+)',path)
```

## エラー出現の条件
繰り返し記号なので、以下のマッチング記号と重なる記号をマッチングさせた場合に、エスケープ処理を怠ると出現します。
- `?` 0回か1回
- `+` 1回以上
- `*` 0回以上
- `{n} {n,} {n,m}` 繰り返し回数の指定


# 類似のエラーメッセージ
**re.error**と書いているのがヒントで、これはRegex上のエラーを意味します。positionは文字列の順番です。また、Regexにおいて、グループ化記号`(`、`)`は最初に評価されます。なので、このグループ化が不適切な場合は直下に例示するエラー（unbalanced…）が出現し、このグループ化が適切でマッチング記号パターンが不適切の場合は他のエラーが出現することになります。

### **unbalanced parenthesis at position**
parenthesisとは括弧のことで、()のグループ化が不適切だった場合に出現します。( )のグループ化がきちんとできているか確認しましょう。

### **unterminated character set at position**
終了をしていない文字列という意味なので、エスケープせずにRegex上で意味を持っている左括弧（例でいえば`(`、`[`、`{`など）を繰り返し回数にかけたりすると出現します。ただし、右括弧（`)`、`]`、`}`）だけの場合は、記述の位置によって普通に処理できたりもします。

### **invalid group reference 3 at position**
不正なグループという意味で、エスケープしていない文字列（&、\など）に対して、繰り返し記号などを指定した場合に出現します。ちなみにシングルクォートやダブルクォートでエスケープ処理を怠ると、Syntax error（Syntaxとは構文のこと）が発生し、サーバー自体止まってしまいます。