OmniAICreator/Qiita-1.07M huggingface dataset:
唐突だけど、absoluteStringとrelativeStringの違い調べてみた

# 前談
URLをstringとして扱いたいケースでよく出てくる `absoluteString`　と　`relatieveString`
なんとなく、使っていたので今回を機に調べてみることにしました🐣

## absoluteString
> The absolute string for the URL.

URLの絶対文字列

## relativeString
> The relative portion of a URL.
If baseURL is nil, or if the URL is itself absolute, this is the same as absoluteString.

URLの相対部分
baseURLがnilの場合、またはURL自体が絶対の場合、absoluteStringと同じになる

なるほど？

## 比較パート

```swift
let sampleURL = URL(string: "https://hogehoge.com/path/to/resource/sample.mp3")!

print("absoluteString: ", sampleURL.absoluteString)
print("relativeString: ", sampleURL.relativeString)
```

結果
```terminal
absoluteString: https://hogehoge.com/path/to/resource/sample.mp3
relativeString: https://hogehoge.com/path/to/resource/sample.mp3
```

これは、baseURLが nilなので　absoluteString と relativeStringで変化が見られませんでしたね。

ではbaseURLを指定するパターンを見てみることにしましょう。

```swift
let baseURL = URL(string: "https://hogehoge.com")
let relativeURL = URL(string: "/path/to/resource/sample.mp3", relativeTo: baseURL)!

print("absoluteString: ", relativeURL.absoluteString)
print("relativeString: ", relativeURL.relativeString)
```

結果
```terminal
absoluteString: https://hogehoge.com/path/to/resource/sample.mp3
relativeString: /path/to/resource/sample.mp3
```

結果に変化が見られました！

## まとめ
relativeStringを使うには、URLを作る際に relativeToを通してbaseURLを設定する必要があるということがわかりました。
ということで、普通に使う分には `absoluteString`で問題なさそうですね。

おわり

## Links
- https://developer.apple.com/documentation/foundation/url/1779984-absolutestring
- https://developer.apple.com/documentation/foundation/url/1780171-relativestring
【BE用語】開発環境の種類と用語


Webアプリケーションを開発するための環境は、それぞれ使用されているソフトウェアの頭文字をとった用語（サーバースタック用語）で表現されます。

- XAMP
- MAMP
- LEMP
- LAMP

Webアプリケーションを開発するための開発環境は一般に、
**OS・WEBサーバー・データベース・プログラミング言語**が必要になります。

それぞれ以下のようなソフトウェアで構成されています。

## XAMP
- X : クロスプラットフォーム
- A : Appach（WEBサーバー）
- M : MariaDB（データベース）
- P : PHP（プログラミング言語）
- P : Perl（プログラミング言語）

## MAMP
- M : MacOS（OS）
- A : Appach（WEBサーバー）
- M : MySQL（データベース）
- P : PHP（プログラミング言語）

## LEMP環境
- L : Linux（OS）
- E : Nginx（WEBサーバー）
- M : MySQL（データベース）
- P : PHP（プログラミング言語）

## LAMP環境
- L : Linux（OS）
- A : Apache（WEBサーバー）
- M : MySQL（データベース）
- P : PHP（プログラミング言語）

## 各ソフトウェアの説明
### Linux（OS）
Linuxは**オープンソースのOS**で、コストが低く自由にカスタマイズできる点に加えて安定性とセキュリティの高さで知られています。
代表的なOSはWindowsやMac OSですが、上記の利点でLinuxが使われいます。

### Nginx（WEBサーバー）
Nginx（エンジンエックス）はWebサーバーで、パソコンやスマートフォンなどの端末からHTTP/HTTPSで送られたリクエストに対してHTML、CSS、JavaScriptなどの情報を返す役割を持っています。

### Apache（WEBサーバー）
Apacheも、Nginxと同じWebサーバーで、Nginxよりも歴史が長く、昔から多くの開発現場で利用されています。

（NginxとApacheの違いもそのうちまとめます）

### MySQL（データベース）
MySQLは、データベースのことです。

### PHP（プログラミング言語）
PHPは、サーバーサイドのプログラミング言語です。
サーバーサイドのプログラミング言語はJavaやPythonなど他にもたくさんありますが人気の言語です。

* * *

このまとめは随時更新予定です
:point_up_tone2: 続く
【Node.js】OpenAI Vision APIを使ってみた


11月7日早朝のOpenAI DevDayで、たくさんのアップデートがあり、とりあえずOpenAI Vision APIを使ってみました。


ターミナル画面で以下のコマンドを入力
```
$ mkdir visionAPI
$ cd visionAPI
$ npm init -y
```

環境変数を使うため dotenvをインストール
```
$ npm install --save dotenv
```

同じフォルダに .envを作る
```
$ touch .env
```

.env に環境変数を入力
```.env
OPENAI_API_KEY="OpenAIのAPI"
```

パッケージをインストール
```
$ npm install openai
```

実行プログラム app.js を作成
```
$ touch app.js
```

app.js に以下のコードを入力

```app.js
require("dotenv").config();

const OpenAI = require('openai');

const openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY,
  });

async function main() {

    const response =  await openai.chat.completions.create({
        model: "gpt-4-vision-preview",
        messages: [
            {
                role: "user",
                content: [
                    {type: "text", text: "この画像には何が写っていますか？"},
                    {
                     type: "image_url",
                     image_url: "画像ファイルのURL",
                    },
                ],
            }    
        ],
        max_tokens:300,
    });
     
    console.log(response.choices[0]);

}

main();


```

<br><br>


試しに、自分のブログから
この画像のURLをいれてみます。
<IMG SRC="http://tatsuya1970.com/wp-content/uploads/2023/03/331549262_222259286877196_3009845257450085464_n.jpg" width=50%>



実行すると、

```
node app.js
{
  message: {
    role: 'assistant',
    content: 'この画像には、三本の異なる種類の日本酒がテーブルの上に置かれています。左から、黒いラベルに赤い文字がありますね、「勝駒（かちぐら）」と書かれているようです。真ん中のボトルは「大七」とラベルにあり、右の緑のボトルは「国稀 CLASSIC」の文字が見えます。また、日本酒を飲むための三つの小さなおちょこも並んでいます。このような設定は日本の居酒屋やレストランにてよく見られます。背景には和風のインテリアが見て取れ、日本の飲食文化が感じられる場面です。'
  },
  finish_details: { type: 'stop', stop: '
' },
  index: 0
}
```

<br>
さすがにラベルまでは読めなかったですが、すごい精度ですね。
Dockerをアップデートしたら永続化したMySQLデータベースを読み込めなくなった

Dockerを最新バージョンにアップデートしたら、永続化したMySQLデータベースを読み込めなくなり、本番環境に持ち込もうと思っていたMovable Typeの環境にアクセスできなくなりました。アクセスできないので、当然ダンプも取れません。
なんとか解決したので、取り急ぎ記事にします。

## Dockerの環境設定を変更する

私が解決した方法から記載します。

環境設定の「General」にある「Choose file sharing implementation for your containers」へ移動し、「VirtioFS」が選択されていたのを「gRPC FUSE」に変更したところ直りました。

![スクリーンショット 2023-11-08 17.53.59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21117/7cfde2de-d6d2-ca79-d157-cb356e9f95a5.jpeg)

## 現象

私はMacOS版のDockerを利用しており、docker-composeで、データベースの永続化をしていました。つまり、プロジェクト内の`db-data`ディレクトリ内にデータベースを保存して、Dockerを終了してもデータが消えないようにしていました。

```
services:
  mysql: 

・・・

    volumes:
      - ./db-data:/var/lib/mysql

```

これが、Docker Desktopを 4.25.0 (126437) にアップデートしたところ、MySQLが起動しない状態となりました。
コンテナ内を詳しく見てみると、何度も起動と停止を繰り返しており、以下のようなエラーを出していました。

```
chown: changing ownership of '/var/lib/mysql/mysql.sock
```

## 既知の不具合らしい

エラーでひたすら検索したところ、以下のissueにたどり着きました。

https://github.com/docker-library/mysql/issues/939

どうもmysqlコンテナの立ち上げの際に chown コマンドが入るようになり、それがMacOSではエラーとなってしまうようでした。

さらにこのissueには、「私はここのURLのトップコメントで解決しました！」というコメントがありました。

## 解決

https://stackoverflow.com/questions/64146845/mysql-not-starting-in-a-docker-container-on-macos-after-docker-update

トップコメントは以下のように書かれています。

> With the latest docker you can disable the gRPC Fuse for file sharing. (the gRPC Fuse setting is causing this problem, it's incompatible with the data dictionary of 0)
> 最新の Docker を使用すると、ファイル共有の gRPC Fuse を無効にすることができます。(gRPC Fuse 設定がこの問題の原因です。0 のデータ ディクショナリと互換性がありません)

Docker Desktopでは複数のファイルシステムを選択できるようで、私の環境では「VirtioFS」が選択されていました。もしかすると、今回のバージョンから初期状態がVirtioFSになって、gRPC FUSEから強制変更されたことにより、不具合が出たのかもしれません。

気が狂うかと思ったので、これからはこまめにバックアップを取ろうと思いました…
AWS SAMを用いたAPI GatewayとStep Functionsの統合

## 概要
AWS Serverless Application Model (SAM) を使用して、API Gateway 経由で AWS Step Functions ステートマシンを起動するアーキテクチャを構築するプロセスについて学んだ内容を共有します。特に、swagger.yaml を S3 にアップロードし、CloudFormation スタックの中で参照する方法に焦点を当てます。

## 課題と解決方法
### 課題 1: API Gateway と Step Functions の統合
SAM テンプレートで API Gateway から Step Functions ステートマシンを起動する設定が必要でした。

#### 解決方法:
SAM テンプレートの Resources セクションで、AWS::Serverless::Function と AWS::Serverless::StateMachine リソースを定義し、API Gateway の AWS::Serverless::Api リソースの DefinitionBody で Fn::Transform と AWS::Include を使用しました。

### 課題 2: Swagger 定義の管理
API の定義を外部 swagger.yaml ファイルで管理したかったが、S3 を使わずにどうやって CloudFormation に組み込むかに悩みました。

#### 解決方法:
S3 は使わないと無理そう？
ローカルでswagger.yaml ファイルを記述し、その後S3にアップロードする方法で措置。
S3 バケットへの swagger.yaml ファイルのアップロードとその後のデプロイをスクリプトで自動化しました。詳細は後述「デプロイスクリプトの例」にて。

### 課題 3: Fn::Sub の使用法
swagger.yaml ファイル内で !GetAtt や !Ref のような CloudFormation の関数を使う正しい方法を理解する必要がありました。

#### 解決方法:
CloudFormation の Fn::Sub 関数を使用して、リソース属性値の動的な置き換えを行いました。これにより、API Gateway の統合設定でステートマシンの ARN を正確に参照することができました。

## 完成した template.yaml の例
以下、実際に作成した SAM テンプレートの抜粋です。
Fn::Transform と AWS::Include を使えば別ファイルで管理することができます。
また、動的な変数は !Ref か !GetAtt で参照することができますが、それぞれの違いは
- !Ref
    - オブジェクトそのものを参照
    - 例）`!Ref ReportOutputStateMachine`
- !GetAtt
    - オブジェクトが持つ値を参照
    - 例）`!GetAtt ReportOutputStateMachine.Arn`

```yaml: template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
# (中略)

Resources:
  SampleStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      # ステートマシンの中身はstatemachine/state_machine.asl.jsonで定義
      DefinitionUri: statemachine/state_machine.asl.json
      DefinitionSubstitutions:
        SampleFunctionArn: !GetAtt SampleFunction.Arn
      Role: !GetAtt StepFunctionsExecutionRole.Arn

  SampleApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      DefinitionBody:
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: s3://sample-bucket/swagger.yaml
```

## swagger.yaml の例
以下、API Gateway のエンドポイント定義の抜粋です。

```yaml: swagger.yaml
swagger: "2.0"
info:
  title: "SampleApi"
basePath: "/prod"
# (中略)

paths:
  /execution:
    post:
      x-amazon-apigateway-integration:
        credentials:
          Fn::Sub: "${StepFunctionsExecutionRole.Arn}"
        uri:
          Fn::Sub: "arn:aws:apigateway:${AWS::Region}:states:action/StartExecution"
        # (以下略)
```
## デプロイスクリプトの例
```bash: sam-deploy.sh
#!/bin/bash
aws s3 cp swagger.yaml s3://scp-report-output/swagger.yaml

sam build

sam deploy -guided
```

## 教訓
Fn::Transform と AWS::Include を活用することで、外部ファイルの管理が簡単になります。
Fn::Sub の正しい使用法を学び、SAM テンプレート内での動的な値の置き換えが可能になります。
ただ、スタック管理サービスにはCDKもあり、複数環境を管理するなど複雑なリソース管理を行うのであればCDKの方がいい気が…。公式もCDK推しっぽいですし（偏見）。
Roblox にて、アバター画像をURLで取得する


Robloxでアバター画像をURLで取得する方法を説明します。ゲーム内での使用とAPIを介した外部の使用の2つの方法があります。

**ゲーム内での使用:**

```lua
rbxthumb://type=AvatarHeadShot&id=USER_ID&w=420&h=420
```

このURLを使用すると、指定したユーザーのアバターのヘッドショット画像を取得できます。USER_IDの部分に実際のユーザーのIDを入れて使用します。画像の幅（w）と高さ（h）も指定できます。

**APIなど外部での使用:**

```lua
https://api.newstargeted.com/roblox/users/v1/avatar-headshot?userid=USER_ID&size=150x150&format=Png&isCircular=false
```

このURLを使用すると、指定したユーザーのアバターのヘッドショット画像を取得できます。USER_IDの部分に実際のユーザーのIDを入れて使用します。また、画像のサイズ、フォーマット、および形状（isCircular）も指定できます。

以上の方法を使用して、Robloxのアバター画像をURLで取得できます。どちらの方法も、アバター画像をゲーム内で使用するか、外部のアプリケーションやウェブサイトで使用するかに応じて選択できます。

おしまい。
OpsRamp Logs エクスプローラについて

本記事では、OpsRamp Logsの見方について説明します。

# 概要
OpsRamp Logsには、取り込んだログを見ることができるログエクスプローラがあります。ログエクスプローラでは、ログの絞り込みや検索、詳細を確認することができます。
[Log Explorer](https://docs.opsramp.com/platform-features/feature-guides/log-management/use-logs-explorer/)

# ログエクスプローラの説明
ログエクスプローラは、Infrastructure > Logsからアクセスすることができます。

## ログビューア
ログビューアの画面について説明します。
[View Logs](https://docs.opsramp.com/platform-features/feature-guides/log-management/use-logs-explorer/view-logs/)

以下にそれぞれの説明を記載します。

|番号|説明|
|:-:|:------------|
|①  |日時範囲によるログの絞り込み (デフォルトでは直近30分)|
|②  |日時単位によるログレベルごとのログ数 (ログレベルごとでログを絞り込むことも可能です。)|
|③  |①、②で絞り込まれたログの一覧|

![viewer1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/600a7ee1-b5a9-96ae-a8cf-b9f29ad43d1b.png)

::: note
指定した日時範囲にログがない場合、ログの設定画面が表示されます。
:::

③の各ログを選択することにより、ログの詳細を参照することが可能です。
また、ログ詳細の「Host」項目ではOpsRampで管理されているリソースに紐づけられている場合には、そのリソースの詳細画面にアクセスすることが可能です。
![viewer2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/6f9a1969-264f-2a26-c6ae-97ac6ba9e05c.png)

## ログフィルター
ログフィルターについて説明します。
[Filter Logs](https://docs.opsramp.com/platform-features/feature-guides/log-management/use-logs-explorer/filter-logs/)

ログのフィルターは「ADD FILTER」から設定することが可能です。
フィルター項目は、取り込んでいるログの情報により異なります。

|オペレーター    |説明|
|:-------------:|:------------|
|= Equals       |完全一致した場合に抽出|
|!= Not Contains|文字列を含まない場合に抽出|
|=~ Regex       |正規表現により一致した場合に抽出|
|!~             |正規表現により一致しない場合に抽出|

![filter.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/c8c0fbd6-69e1-8b12-10e1-216fcce3ff4f.png)


---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
組織全体でのEVMによるプロジェクト進捗管理(3/3) 　：　組織全体でEVM管理をやってみた

# ■SPIとCPIの収集を開始
すべてプロジェクトで週報にSPI, CPIの計算結果を記載するようにし、閾値を超えた場合は異常と判断し、管理層に詳細な報告を行うというルールを設けました。
SPI, CPIは1.00が正常値で、今回は0.80を閾値としました。これは、残業を最大20%程度までと想定した閾値です。
現場の負荷を軽減するために、進捗管理表のデータからSPI, CPIを計算するツールを提供しました。

最初は計測を行わないプロジェクトもありましたが、管理層からの強い要請や個別のフォローにより、最終的にほぼすべてのプロジェクトのSPI, CPIが毎週報告されるようになりました。

# ■収集してわかったこと①
SPI, CPIはプロジェクトの規模や期間に関係なく、すべてのプロジェクトの状況を共通の指標／閾値で確認できることが明らかになりました。
これは100以上のプロジェクトを確認する経営層にとって、非常に大きなメリットとなりました。すべてのプロジェクトのSPI, CPIを一覧で見ることができます。
以下の図は実際のプロジェクトのEVMデータ一覧の抜粋です。
![EVM7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/c6069c8c-1451-b728-d20b-b026a0c65d76.png)
成熟度が上がり、閾値以下となっていたプロジェクトが減少していることが確認できます。これは閾値を超える前に対策が取られるようになったためです。

# ■収集してわかったこと②
SPI, CPIのデータから、ある程度、要因が推測できるようになりました。
以下の図は、SPIとCPIの値から推測される要因を示したものです。
![EVM6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/9785b981-6c17-30c4-25e1-20992c3eb050.png)

横軸はSPIで中心の1.00が計画通りで、右がスケジュール前倒し、左がスケジュール遅れを表します。
縦軸はCPIで中心の1.00が計画通りで、上が開発効率高、下が開発効率低を表します。
斜めの軸はコスト(消費工数)を表し、軸の上側がコスト余り、下側がコスト超過(残業)を表します。

閾値が0.80なので、それ以下の部分は危険であることは明らかですが、右下の部分も危険となっています。これはSPIが高くCPIが低いため、前倒しに見えますが、開発効率が低いのを工数を投入して対処しているだけなので、健全な状態ではありません。最終的にコスト超過で終わるリスクがあります。SPIが低い場合は残業してコストをかければ1.00に戻せますが、CPIが低い場合は残業しても改善しません。開発効率を向上させるか、再計画するしか対応策はありません。

左上の部分も不思議な状況です。開発効率が高く、コストも余っているのに、スケジュールが遅れている状態です。これは、複数のプロジェクトを兼務している場合によく見られます。片方のプロジェクトが忙しくて、もう片方のプロジェクトに工数を割けていないようなケースです。また、新型コロナで1週間休んだというようなケースもありました。

右上の順調すぎるのも、実は注意が必要です。順調ではあるけれども、見積もり精度が低いという課題があると考えられます。また、想定していたものより品質が低い可能性もあるかもしれません。

SPI, CPIが1.00付近にずっといるのも、少し異常です。見積りの精度が100%ということは、少し考えにくいですよね。一見正常に見えるこのケースは、調査すると、リーダー自身の工数や計画外の不具合対応の工数を計上していなかったり、与えられた時間をすべて使い切ろうとしていたりといった事例がありました。

このように、SPI, CPIは単に閾値以下であれば危険というだけでなく、SPIとCPIの値から何が起こっている可能性があるのかを推測でき、それを基に現場のリーダーにヒアリングすることで問題の有無を判断しやすくなります。

# ■収集してわかったこと③
驚くべきことに、管理層やリーダーだけでなく、メンバもEVMについて意識するようになりました。

SPI, CPIの乖離の要因を問われるため、それに対して説明できる必要があります。このため、毎回、「ふりかえり」を行うのと同じ状態になり、閾値を超える前に改善しようという意識が生まれました。また、SPI, CPIの値は進捗管理表に連動して計算できるため、メンバもそれを確認し、意識するようになりました。

リスクマージンを意識するようになり、残業がコスト増につながるという認識が伝わり、当初の課題の一つが解決しました。
特に、CPIの低下は残業では解決しないということが理解され、管理手法や開発手法を学びたい(学びなおしたい)という人も増えました。

# ■まとめ
改善したかった以下の二点は、全プロジェクトに対してEVMのSPI, CPIを導入することで解決しました。
・管理層が必要とする、定量的で客観的な指標を用いて、各プロジェクトの状況を見える化したい。
・現場のリーダーに、残業がコスト増につながることを認識させたい。

自分たちが達成したい目標を明確にし、EVMをその目標達成のツールとして活用したことで、良い成果が得られました。
# 
もしこの記事が参考になったのであれば幸いです。ぜひ、あなたの組織でも試してみてください。

[組織全体でのEVMによるプロジェクト進捗管理(1/3)　：　進捗管理の課題](https://qiita.com/Masahiro_Kawasaki/items/d52c985e13f6cc3ef33a)
[組織全体でのEVMによるプロジェクト進捗管理(2/3) 　：　EVMの運用可能性を考える](https://qiita.com/Masahiro_Kawasaki/items/60a373a44d637a24b1f7)
組織全体でのEVMによるプロジェクト進捗管理(3/3) 　：　組織全体でEVM管理をやってみた
Git初心者がGitを頑張って解説してみる


## ＊今回のテーマ
新入社員の方からGitについての質問をよく受けるので
ざっくりとした解説を作ってみました。
自分自身も歴が浅くGitに慣れていないので勉強も兼ねています。


------

## ＊目次
[Gitとは](#＊Gitとは)
[ローカル/リモート](#＊ローカル/リモート)
[クローン](#＊クローン)
[コミット・プッシュ・プルなど](#＊コミット・プッシュ・プルなど)
[作業の流れ](#＊作業の流れ)
[最後に](#＊最後に)

------


## ＊Gitとは
Gitとはソースコードなどのバージョンを管理するための
分散型バージョン管理システムの一つです

※分散型バージョンシステムの他に集中型バージョンシステムがあります
集中型：中央サーバーにリポジトリが配置され、そこに変更が反映される
（サーバーがダウンすると作業ができなくなる可能性がある）
分散型：リポジトリをクローンして、リモートリポジトリにプッシュして変更を反映する
（リモートリポジトリがダウンしても影響を受けない）

バージョンの管理をしないと開発中にバグが起こってしまった時
「あのタイミングに戻したい...」
となっても戻す事が難しいです

Gitで管理していると、何かあった時も
簡単にバージョンを戻す事ができるので安心して作業ができます

Git=Githubでは？とよく聞かれますがこれは別物です
GithubはGitというツールを使ったwebサービスです

GithubでもBacklogでもGitの管理をすることはできるので
各プロジェクトに合わせて使ってみてください



## ＊ローカル/リモート

自分も含めて初心者が躓く点は **ローカル/リモート** の混同ではないでしょうか

ローカルで変更したのに他の人の環境に反映されていない！　など

たまに混乱している姿を目にします


    
### ローカル
自分のPC、個人の開発環境

### リモート
複数人がアクセスできる環境
　　


私が教えられた身近なものを使った例は

テレビの向こう側がリモート（誰でも見る事ができる）
テレビを見ている自分がローカル

と教えられた記憶がうっすらとあります

ソースコードだと、見るだけでは作業ができないですよね。

そこで次の項目、クローンに入ります。

## ＊クローン

リモートのソースコードをローカルに持ってきて作業をしていきます。

そのためにはまずリモートリポジトリのクローンが必要になります

クローンをする方法はいくつもあります

＊コマンドでクローンをする（git clone URL）
＊SourceTreeでURLを入力してクローンする

私はよくSourceTreeを使います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507621/eef96cfe-abef-20c0-fb86-3ffbb7057451.png" width=70%>



## ＊コミット・プッシュ・プルなど
クローンする事ができたらローカルで作業を始めます。

作業をする → コミット & プッシュ → プル　→ 作業　→ 。。。
の繰り返しです。

コミットのタイミングをよく聞かれますが、
何回コミットしてもデメリットは特にないと思うので、

**その日の業務終了時、小さいタスクが完了した時、**

などのタイミングでいいのではないでしょうか？


プッシュは他の人にコードを共有したいときや

プルリクエストを送るタイミングでいいと思います

初心者にとって大切なことは

**とにかくコードを書く・コードレビューをいただく**

だと思います。

フェッチ、プルについては、

フェッチは見るだけ
プルは持ってくる

といつもざっくり伝えています。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507621/1a816bc1-e6cf-8432-e884-d0a4ca1bb069.png" width=70%>



## ＊作業の流れ

初心者や慣れていない方はおそらく

Developブランチのまま開発することはないと思います。

基本的には、作業ブランチを作って作業する(赤線部分)

レビュー担当者にプルリクエストを送る
　　

**NG =>　修正を再度コミット&プッシュ**
**OK => レビュー担当者がリモートにマージしてくださる**
　　

初めのうちはプルリクはすんなり通らないと思いますが

挫けずにコードを書いていきましょう


  　　
レビュー担当者がマージしてくださったら

ローカルのTask-01ブランチからdevelopブランチに戻ります。

そこでリモートのdevelopブランチをプルすれば

ローカルのdevelopが最新の状態になります


　　

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507621/ab7fab4f-0fea-cfb0-47d0-d600b0fede77.png" width=70%>


その他Gitの運用フローやブランチの命名規則などはプロジェクトによって違うので

各プロジェクトに合わせてGitに慣れていきましょう。



## ＊最後に

Gitに自身がない方はコマンドだけで管理するのではなく

GitGraphやSourceTreeなどの便利な機能もあるので

そちらを利用してみるといいかもしれません。

　　
以上、最後までお読みいただきありがとうございました。
組織全体でのEVMによるプロジェクト進捗管理(2/3) 　：　EVMの運用可能性を考える


# ■EVMとは?
EVMとは「プロジェクトの進捗や作業のパフォーマンスを、出来高の価値によって定量化し、プロジェクトの現在および今後の状況を評価する手法」です。
進捗の進行や遅れのような指標（スケジュール差異）も、日数や時間という単位ではなく、コストを単位として求められることが特徴です。

EVMでは、PV, EV, AC, BACという4つの入力情報から、SV, CV, SPI, CPI, EAC, ETC, VACという7つの指標を生成します。
![EVM1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/b8729133-61e4-cb93-12d9-8192da2d1731.png)
この中で、SPIは日程的に順調か、CPIはコスト的に順調かを示す指標であるため、プロジェクトの現在の状況を知るのに使えそうです。
また、EACは最終的にマージンに収まるか、ETCはあとどれくらいで終わりそうかを示す指標であるため、プロジェクトの今後の状況を知るのに使えそうです。


ただし、EVMはコストを単位とするということは、「計画や進捗をすべてお金に換算して管理しよう」という意味になります。おそらく、EVMは大きなプロジェクトで、資材の調達や人員の調達など、お金を扱う人の進捗管理に適しているのでしょう。

だとすると、ソフトウェア開発の進捗管理にも使えるのでしょうか? 不安がよぎります。

# ■事例を調べてみた
EVMは良く知られた手法なので、その考え方や方法について述べている資料は多いのですが、適用による成功事例や具体例は意外と見つけられません。
海外の会社と仕事をした際に、EVMでの進捗報告が求められ、それが大変だったという話を見つけました。しかし、具体的に何が大変だったのかは明らかにされていませんでした。
実際にEVMを使おうとすると、管理が重くなるのかもしれません。また、お金で管理するたるめ、現場には向いてないかもしれません。

# ■運用可能性を考えてみた
EVMでは、PV, EV, AC, BACという4つの入力情報から、SV, CV, SPI, CPI, EAC, ETC, VACという7つの指標を生成します。これらの入力値はすべてお金です。
しかし、ソフト開発の現場の進捗管理にお金を使うのは現実的ではありません。そこで、人件費に見合った「時間(h)」を単位とすることを考えました。
そうすると、BACは総見積り工数、PVは現時点までに使う予定の工数、ACは実際に使った工数、EVは現時点までに完了した出来高となります。

出来高についても、「計画時に見積もった作業成果物の開発見積工数をその作業成果物の(工数的な)価値とする」と定義しました。
例えば、100H の工数で作成すると見積もった成果物は、実際には 120H かかったとしても、価値は 100H と考えます。

具体例で説明します。下の表は進捗管理表の一部だと考えてください。例として、週報で7/17までの状況を集計する場合を考えてみます。
![EVM2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/78a6673b-764b-df01-3c58-b2a1b8bb1314.png)
PVは、集計日の7/17までの見積工数の合計で70h、ACは集計日までの消費工数で75h、EVは集計日までの出来高の価値です。価値は見積りで表すと定義したため、集計日までに作成できた見積工数となります。集計日までには作業成果物Dが50%しか作成できていないので、その部分は少なくなり、60hとなります。

この考え方であれば、EVMをソフトウェア開発の進捗管理に適用することが可能になるかもしれません。実現性が見えてきました。

# ■試行してみた結果
実際に、あるプロジェクトの計画と実績のデータを EVM の指標を使ってグラフ化してみました。

計画と実績のグラフではPV, AC, EVが示されています。
![EVM3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/a444e90d-266d-ac22-dd51-4a1b7094c9dc.png)
典型的な進捗率のグラフと似ており、進捗率が徐々に上がっていく様子は良いのですが、縦軸のスケールの問題で乖離が分かりにくいという問題があります。

効率指数のグラフではSPIとCPIが示されています。
![EVM4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/f3f86b12-9972-0ad8-b33f-0ff32f869f37.png)
計画通りであれば、SPIもCPIも両方とも1.00となりますが、実際には上下に変動しています。開始直後は冬休みと重なっているため、データが不正確な可能性があります。
その後は1.00より小さい値が続きますが、急激に変化した部分の理由を調査したところ、再計画をしていたことが判明しました。
これらの指標を見ることで、プロジェクトが順調に進行しているかを判断できそうです。

残工数予測のグラフではEACとETCが示されています。
![EVM5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/e4bf9e0c-f0a4-f21d-3534-df39e177181a.png)
計画通りであれば、赤色のETCは左上から右下への斜めの線となり、最終的に0になります。しかし、実際には最終的に0にはなっているものの、前半は不確定な動きを見せています。
また、緑色のEACは計画通りであれば、総見積り工数の水色のBACの値と一致しますが、途中から常にそれを超えており、残業で対応していることがわかります。
予測なので前半はデータ量が少なく、精度はあまり高くないようですが、後半は比較的実態に近い値になっているように感じます。


結論として、SPI, CPIを用いることで今回の課題が解決できそうだという結果が得られました。

# 
次回は実践編です。実際にプロジェクトの見える化ができたのかを説明します。

[組織全体でのEVMによるプロジェクト進捗管理(1/3)　：　進捗管理の課題](https://qiita.com/Masahiro_Kawasaki/items/d52c985e13f6cc3ef33a)
組織全体でのEVMによるプロジェクト進捗管理(2/3) 　：　EVMの運用可能性を考える
[組織全体でのEVMによるプロジェクト進捗管理(3/3) 　：　組織全体でEVM管理をやってみた](https://qiita.com/Masahiro_Kawasaki/items/9b670f6f9b62f847e959)
【AWS初心者】アソシエイト(SAA-C03)合格体験記

# はじめに


初めましてこんにちは、開発部の一筒です。
まずわたしのスペック
- 業界未経験から入社1年半
- 業務でAWSに携わったことない


AWS初心者どころか、まだまだIT初心者なのですが
AWSアソシエイト(SAA-C03)を取得できましたので、合格までの流れをご紹介します！


# とりあえずクラウドプラクティショナー受験

EC2ってなに？レベルから勉強を始めたので
まずはクラウドプラクティショナーを受験しました。
教材はUdemyのこちらを使用。

https://www.udemy.com/course/aws-4260/

AWS Well-Architected Frameworkも参考にしました。

https://wa.aws.amazon.com/index.ja.html

クラウドプラクティショナーの勉強を経て、
**まんべんなくサービスを理解することができました。**
おかげで、アソシエイト試験の勉強時に
「なんのサービスか全くわからない」ということがなかったです。

「クラウドプラクティショナーは意味がない」と言われがちですが、
勉強してよかったと思います。

勉強を始めて2週間ほどで合格できました。


# 使用教材
アソシエイトも教材はUdemyを使用しました。

https://www.udemy.com/course/aws-knan/


こちらの動画も購入しましたが、
1度流し見する程度しか使わなかったので個人的にはあまり必要なかったです...

https://www.udemy.com/course/aws-uoyc/

# 勉強方法
**とにかく解きまくる**
どれだけ参考書をしっかり読んでも問題を解けなければ合格できません。

**解く　→　見直し　→　また解く**　を繰り返します。

見直しは理解できるまで解説を読んだり、調べたりで3時間くらいかけてました。
また、勉強中は以下のようなことを意識してしました。
***
**1. 解きながらメモ**

解いている途中で`迷ってしまったり、自信のない部分はその理由をメモ`しておいて
解き終わった後に振り返るようにしていました。
あとで見返すと勘違いして覚えている箇所など矯正できます。

**2. 不正解の理由も考える**

同じ問題集を繰り返していくうちに慣れて、答えを覚えてしまうと意味がないので
`「他の選択肢が不正解の理由」を考えながら解く`ようにすると理解もより深まるかと思います。

**3. サービスの違いを覚える**

似たようなサービスが多いので
- サービスの組み合わせ方
- サービスの特徴(DBだったらNoSQLなのか、サーバレスなのか、など)
- どのような機能を持っているのか、何ができないのか

などしっかり覚えましょう。


自信のないサービスはこちらを解いて情報補完したりしていました。
(※情報が古かったりするようなのでこれだけで完結はお勧めしないです...)

https://aws-exam.net/saa/


# 試験本番
上記の勉強方法で1ヶ月ほど勉強して試験に挑戦。
問題の運が良かったのか実際の試験はUdemyの難易度より簡単に感じました。

結果は合格ラインより100点以上余裕を持って合格できました。:raised_hands:

受験後のアドバイスとしては翻訳独特の言い回しで問題文を理解するのに
時間がかかったので色んな問題に触れて、慣れておくのが良いかなと思います...

# まとめ
学習のコツとかはあまりないですが、サービスを一つ一つ理解すれば
IT初心者でも十分狙える資格だと思いました。

とはいえ実務でAWSを使いこなせることにならないので、まだまだ勉強は必要ですが…
少しでもご参考にしていただければ幸いです:fish_cake:


はつかぜ株式会社では、IT学習や業務に役立つ情報を定期的にお届けしていきたいと思っています。 
システム開発のお問い合わせ・ご相談はこちら
https://www.hatsukaze.co.jp/inquire/
【Postfix】指定回数バウンスしたメールアドレスを抽出して送信しないように自動更新する

## 概要
- 送れないメールアドレスに送り続けてdnsbl登録されるのを避けたい
- メールログからバウンス情報を抽出し、指定回数以上バウンスしたアドレスを抽出
- 特定のディレクトリに指定日数保存
- 保存されたディレクトリ内のアドレスをまとめて送信拒否リストを作成
- postfix をリロードし送信拒否リストを読み込む
- cron 等で一日一回実行することを想定

## 環境
- postfix 2.6

## Postfix設定準備
- main.cf 送信拒否リストをチェックするように設定 (check_recipient_access)
```main.cf
...
smtpd_recipient_restrictions =
        check_recipient_access hash:/etc/postfix/bounce/recipient_access,
        permit_mynetworks,
        permit_sasl_authenticated,
        reject_unauth_destination,
...
```

## シェルプログラム
```bash:manage-bounce.sh
#!/bin/bash
#
# Postfix bounce management shell
#

# メールログファイルのパス
BOUNCE_LOG="/var/log/maillog"
# バウンスログの保存ディレクトリ
SAVE_DIR="/etc/postfix/bounce"
# バウンスの閾値
BOUNCE_THRESHOLD=10
# 保存期間（日数）
SAVE_DAYS=14
# 除外文字列
EXCLUDE_WORD='@mycompany.com'

# バウンス情報を抽出し、回数が多い順にソートして出力する関数
extract_and_save_bounces() {
    local datestamp=$(date +%Y%m%d)
    local output_file="${SAVE_DIR}/${datestamp}_bounces.txt"
    awk -v threshold="${BOUNCE_THRESHOLD}" -v word="${EXCLUDE_WORD}" '
        BEGIN { FS = "[<>]" }
        /status=bounced/  {
            email = $2
            reason = $0
            gsub("^.*said: +", "", reason)
            bounces[email]++
            bounce_reasons[email] = reason
        }
        END {
            for (email in bounces) {
                if (!index(email, word) && bounces[email] >= threshold) {
                    #print bounces[email], email, bounce_reasons[email]
                    print email
                }
            }
        }
    ' "${BOUNCE_LOG}" | sort > "${output_file}"

    echo "Bounce list saved to ${output_file}"
}

# 古いバウンスログファイルを削除する関数
cleanup_old_bounces() {
    find "${SAVE_DIR}" -type f -name "*_bounces.txt" -mtime +${SAVE_DAYS} -delete
    echo "Old bounce files removed"
}

# 重複を排除した宛先メールアドレスリストを作成する関数
create_recipient_access() {
    local recipient_access="${SAVE_DIR}/recipient_access"
    awk '!a[$0]++ {print $0, "REJECT"}' ${SAVE_DIR}/*_bounces.txt > "${recipient_access}"
    /usr/sbin/postmap ${recipient_access}
    if [[ $? != 0 ]]; then
        echo "postmap command failed, proccess quit!"
        exit 1
    fi
    echo "Recipient access list created at ${recipient_access}"
}

# Postfixをリロードする関数
reload_postfix() {
    /etc/init.d/postfix reload
    echo "Postfix reloaded"
}

# メインの処理
main() {
    mkdir -p "${SAVE_DIR}"

    extract_and_save_bounces
    cleanup_old_bounces
    create_recipient_access
    reload_postfix
}

main

```

以上、お疲れさまでした！

## こちらもどうぞ

https://qiita.com/a__i__r/items/9f040e8fc35625bf6569
タスク管理って難しいよね。ちょっと楽しませんか。

こんにちは！
株式会社OGIXのプロジェクトマネージャ H.Yです！
（弊社については最後に紹介があるのでぜひ見てください）

今日はエンジニアリングというより、自己管理に寄ったお話をしたいと思います。

みなさん、タスク管理好きですか？私は好きではありません。

- 優先順位がつけづらい
- なんやかんやで納期に追われてしまう
- 漠然としていてふんわりとした管理になってしまっている

ありがちだと思います。これはプロジェクト単位であろうが、個人のタスク管理単位であろうが変わらないと思います。
マネジメントの手法は様々あると思いますが、ここでは基本の思想だけお話ししたいと思います。

:::note info
ポイント
これはあくまでもベースとなる考え方です。タスク管理ツールにRedmineやTrello等様々あると思いますが、それ以前の思想の話をしたいと思います。
:::

:::note warn
ポイント
個人の考えですので、多種多様な意見は尊重しています。
:::

## "CAN"をまず考える
- CAN（できる）
- CANNOT（できない）

をまず考えてみてください。

- 能力
- 状況

によって、それらのタスクが達成できない可能性があります。
評価するときはCANなのかCANNOTなのかの評価だけで大丈夫です。
諸々考慮をし始めると、終わらなくなるので単純にできる/できないの判断だけしましょう。

## まずタスクの粒度は3段階で考える
CANを出した後に、それぞれのタスクを以下の観点で再評価してみましょう。

- MUST（必ずやらなければいけない）
- SHOULD（やるべき）
- WANT（やりたい）

の3段階で考えるとよいと思います。このタスクの評価は毎日行ってもいいですし、週に1回行うでもいいと思います。そこはルールの問題なので、自分なりのルールを引いてみてください。

私が取っている手法は**セルフ朝会とリファインメント**です。
朝会はスクラムのデイリースクラムのようなもので、業務の始まりにタスク一覧をざっと見て、再評価を素早く行っています。
リファインメントでは、CANNOTタスクの分解等、時間を取って業務の整理をしています。（週1回、最大30分）

## タスクのマトリクス
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565804/5c18bc1e-ed98-0c1c-f8eb-80571a4a39f1.png)
評価したタスクは上記のような考えで業務に取り組みます。
MUSTの量と納期を比較して、自らのキャパシティを超える場合にはタスクの相談をするべきです。
※時間の見積もりは別記事に分離して書きたいと思います。

## よくある勘違い

1. WANT（やりたいこと）をMUST（やらなくてはいけないこと）と勘違いをする。
1. WANT（やりたいこと）をSHOULD（やるべきこと）と勘違いをする。
1. MUST（やらなくてはいけないこと）はCAN（できる）と勘違いをする。

特にゲームを作っているとやりたいことを「やらなくてはいけないこと・やるべきこと」にしてしまうことが多いです。
作り込みは大切だと思いますし、ゲームクリエイターであればWANTをできる限り詰め込むことは大切だと思います。しかし、MUSTが達成されていないのにも関わらずWANTを優先させてしまうと要件を満たさなくなり、最悪のパターンだとリリースができなくなります。評価するときに「これってWANTではない？」を再確認するようにしてください。

MUSTだから必ずCANだとも限りません。MUSTは「やらなくてはいけないこと」であって「誰でもできる」ではありません。

## まとめ
以上、基本思想を書いてみました。
学生の頃私が考えていた思想を、仕事を通じてアップデートをしたものになります。
似たような考えはもうすでに世の中にはでているのかなと思いますが、この基本思想があるだけで

- 助けを請う人
- 助ける人
- 仕事をマネジメントする人

全員が幸せになります。
チームの仕組みとして落とすのもいいですが、個人の習慣からはじめてみませんか？
個人が基本思想を持ち合わせることで、チームの習慣になります。

煩雑なタスク管理をしていませんか？
優先度つけていればいいと思ってませんか？
ツールで満足していませんか？

タスク管理は「やること」の管理です。
「やること」を具体的にどのラインに落とし込むかがタスク管理の肝です。
最初から複雑なことをしても達成は難しいと考えています。
「こんなの誰でもできる」と思ったそこなあなた！
誰でもできるが大切です。
みんなができてから次のステップに進むことができます。

## 一緒に働く仲間を募集しています！
株式会社OGIXでは一緒に働いてくれる仲間を募集しています！
エンタメ制作集団としてゲームのみならず、未来を見据えたエンタメコンテンツの開発を行っています。

事業拡大に伴い、エンジニアさんを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/company_6473754/about
▼代表インタビュー
https://www.wantedly.com/companies/company_6473754/post_articles/443064
▼東京オフィスの応募はこちら
https://www.wantedly.com/projects/1468324
▼新潟オフィスの応募はこちら
https://www.wantedly.com/projects/1468155
組織全体でのEVMによるプロジェクト進捗管理(1/3)　：　進捗管理の課題

# ■はじめに
今回紹介するのは、[SPI Japan 2020](https://www.jaspic.org/events/sj/spi_japan_2020/), [SPI Japan 2023](https://www.jaspic.org/events/sj/spi_japan_2023/)で私が報告した事例です。
ポイントが伝わりやすいように、改めて書き直したものです。

# ■背景
弊社はシステムおよびソフトウェアの委託開発を行っています。弊社はパナソニックグループの会社ですが、約半分の業務はグループ外のお客様からの委託を受けています。
委託の単位でプロジェクトを立ち上げるため、常時100以上のプロジェクトが稼働しています。プロジェクト規模も様々で、数十人規模のものから1人規模のものまで存在し、プロジェクトの期間も様々です。
各プロジェクトは進捗状況を週報として課長に報告し、課長がそれらをまとめて経営層に伝えるという形の運用が行われています。

# ■週報での報告内容
週報には計画に対する進捗状況やトピックが記載されます。しかし、「進捗率 30%」と記載されても、それが順調なのかどうかは判断できません。
そのため、「進捗率：計画 [30% → 36%] / 実績 [30% → 35%] (1日遅れ)」のように、計画と実績が先週と比べてどう変わったのかを明示するようにしています。

# ■週報での報告の課題
課長や部長は週報を見てプロジェクトの状況を把握します。
しかし、週報では遅れがないように記載されているにもかかわらず、残業が多いプロジェクトが存在します。また、「○日遅れ」が続いており、一向に改善しないプロジェクトも存在します。
しかし、週報を読んでも、その週に何を行ったのかが書かれているだけで、遅れの原因や残業が多い理由については明記されていません。
これは、管理層が必要とする情報が提供されていないという問題を示しています。

# ■なぜ週報と齟齬があるのか
現場のリーダーたちは強い責任感を持っており、顧客と合意した日程を守るために力を尽くしています。大丈夫です。それはちゃんと知っています。

しかし、少なくともその時点では、問題は自分たちで対処可能であり、大きな問題ではないと考えています。遅れが発生すると、自分たちで解決しようと、残業をしてでも遅れを取り戻そうとします。それでも遅れが残った場合は、翌週も引き続き頑張ります。

これは一面では素晴らしいことですが、一方で、残業がコスト増につながることに注意しなければなりません。委託開発の場合、「○○万円で○○を開発して」という契約のため、残業が多いと人件費が増え、結果的に赤字になるリスクがあります。
管理層が早めにその情報を得られれば、顧客側との調整や一時的な人員の追加などの対策を考えることができます。しかし、その情報がなければ対策も打てません。

現場のリーダーと管理層との間には、この点に関する意識の差があるようです。

# ■この状況を改善したい
上記を踏まえ、以下の点を改善したいと考えています。
　・管理層が必要とする、定量的で客観的な指標を用いて、各プロジェクトの状況を見える化したい。
　・現場のリーダーに、残業がコスト増につながることを認識させたい。

これらの課題を解決するために、EVM (Earned Value Management)の導入が有効ではないかと考えました。

EVMはプロジェクトの管理の一手法であり、経済産業省やIPAでも推奨されています。プロジェクトの状況をコストに換算して予兆管理が可能なため、これらの課題を解決できると考えたのです。

# 
次回は、このEVMについて検討した内容を説明します。

組織全体でのEVMによるプロジェクト進捗管理(1/3)　：　進捗管理の課題
[組織全体でのEVMによるプロジェクト進捗管理(2/3) 　：　EVMの運用可能性を考える](https://qiita.com/Masahiro_Kawasaki/items/60a373a44d637a24b1f7)
[組織全体でのEVMによるプロジェクト進捗管理(3/3) 　：　組織全体でEVM管理をやってみた](https://qiita.com/Masahiro_Kawasaki/items/9b670f6f9b62f847e959)
ddlの作り方

★ddlの仕組み
alwaysにすると、
アプリケーション・プロパティズの# DataSource配下のclasspathって書いてあるやつが読み込まれる。

作り方
アプリケーション・プロパティズの# DataSource配下のclasspathにクラスパスを書く
（マスタ系は、0020に入っている）![スクリーンショット 2023-11-07 14.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112450/7f6bcdb2-c62a-c106-41fb-cb88fed15b91.png)
VsCode のコマンドで現在開いているファイル名を変更する

# 問題

VsCodeでは直接ファイル名変更ができないので大変だ

# 解決

git 管理しているプロジェクトなら `Git Rename` で変更できるようだ
ただしディレクトリが存在しない場所には rename できないようなので注意

たぶん拡張機能じゃなくてデフォルト機能のはず

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/436c137c-efe0-4726-8cf0-ef1bd63dba10)

# 次善の策

現在ファイルのパスをクリップボードニコピしておいてから


<img width="439" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/fc9dc1fc-9c33-4d25-9c9a-1a1fbd618082">

コンソールで名前変更する場合が多い

`mv path/to/file path/to/renamed_file`


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
匿名ウィンドウを使ってレコードを更新する

私自身の備忘録を兼ねて匿名ウィンドウを使ってレコードを更新するサンプルを公開します。

ハンドで修正するには件数が多くて面倒だけど、データローダ用にcsvファイルを作るのも面倒なときに使っています。始めは怖いので１件処理して機能したら複数件更新するのですが、あまりたくさん指定するとエラーになってしまいます。何でだろう。



以下は、得意先ｺコードで指定した取引先のレコードタイプを強制的に変える例

````
Set<String> accSet = new Set<String>();

//ここに変更したい得意先コードを追加する
accSet.add('60027');
accSet.add('60028');
accSet.add('60029');

// レコードタイプ取得
Map<String, Id> recordTypeMap = new Map<String, Id>(); // keyは[sObjectType]-[developerName]
for (RecordType rt: [SELECT Id, sObjectType, developerName FROM RecordType]) {
    recordTypeMap.put(rt.SobjectType + '-' + rt.DeveloperName, rt.Id);
}

List<Account> updateAccList = new List<Account> ();

List<Account> accList = [select Id from Account where customer_code__c =:accSet];

for (Account acc : accList) {
    Account a = new Account();
    a.Id = acc.Id;
    a.RecordTypeId = recordTypeMap.get('Account-customerDeleted');
    updateAccList.add(a);
}
system.debug('処理件数 ==>>> '+ updateAccList.size() );  

if (updateAccList.size() > 0) update updateAccList;
```


# 関連

+ [本番環境で2000件以上のレコードを削除する](https://qiita.com/Keiji_otsubo/items/1bd9c9eeea3e68b9a940)
Github Actions のメール通知を止める

ここから設定

https://github.com/settings/notifications


<img width="1440" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/9aeaf03b-7944-4bd3-8ea2-ad5cfc9cdf62">


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
plunkerでlzma

# 概要
plunkerでlzmaやってみた。
plunkerで圧縮してダウンロードして、アップロードして解凍してみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a25e9e73-6c80-6b86-7ae5-bb12e77a7b73.png)


# サンプルコード

```

var compression_mode = 7,
    my_lzma = LZMA;
var file = document.getElementById('file');
var out = document.getElementById('out');
function loadLocalFile(e) {
	var fileData = e.target.files[0];
	var reader = new FileReader();    
	reader.onload = function() {
        var asArray = new Uint8Array(reader.result);
		alert(asArray);
		my_lzma.decompress(asArray, function on_decompress_complete(result) {
            //alert("Decompressed: " + result);
            out.value = result;
        }, function on_decompress_progress_update(percent) {            
        });
	}
    reader.readAsArrayBuffer(fileData);
}
file.addEventListener('change', loadLocalFile, false);

document.getElementById("go").onclick = function() {
    my_lzma.compress(document.getElementById("compression_el").value, compression_mode, function on_compress_complete(result) {
        alert("Compressed: " + result);
        my_lzma.decompress(result, function on_decompress_complete(result) {
            alert("Decompressed: " + result);
        }, function on_decompress_progress_update(percent) {
            document.title = "Decompressing: " + (percent * 100) + "%";
        });
    }, function on_compress_progress_update(percent) {
        document.title = "Compressing: " + (percent * 100) + "%";
    });
}

document.getElementById("go2").onclick = function() {
    my_lzma.compress(document.getElementById("compression_el").value, compression_mode, function on_compress_complete(result) {
        alert(result);
        var asArray = new Uint8Array(result);	
	    var blob = new Blob([asArray], {
		    type: "application/zip"
	    });	            
	    var linkText = document.createTextNode("down load link");
	    var a = document.createElement('a');
	    a.appendChild(linkText);
        a.download = "hello2.txt.lzma";
	    a.href = URL.createObjectURL(blob);
	    document.body.appendChild(a);
    }, function on_compress_progress_update(percent) {
    });
}


```

# 成果物

https://embed.plnkr.co/plunk/jZzTPPK812ryJWq4

以上。
Firebase Authentication Googleサインイン時に出たエラー:PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 16: , null, null)

# 問題の状況
flutterでFirebaseのAuthenticationを使ってGoogleサインインできる機能を実装しようとしたら
`PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 16: , null, null)`
というエラーが表示される。
設定したSHA1に間違いがないか確認している。
エミュレータ上のデバイスでは動かないのに実機だとなぜか動作する。

# 対処法
恐らく、デバイスのGoogle Play servicesのバージョンが問題でした。
エミュレータにPlay Storeがインストールされているデバイスを選択することで解決。
私の場合Pixel 4を選択したところ無事エミュレータでも動作しました。


![device_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616979/00def91b-284d-7190-c1de-8dda67ba400f.png)

# 終わりに
エラーの対処法は、Play Storeのあるデバイスに切り替えるだけったのに三日も対処に時間がかかりました。
同じエラーで悩んでいる方の助けになれば幸いです！
コマンドuvicorn app.main:app --reloadの意味とは？（FastAPI）

`uvicorn app.main:app --reload`は、Uvicornを使用してFastAPIアプリケーションを実行するためのコマンドです。ここで、各部分の意味は以下の通りです



- `uvicorn`: Uvicornの実行可能ファイルです。Uvicornは、ASGI (Asynchronous Server Gateway Interface) 仕様をサポートする軽量で高速なASGIサーバーです。FastAPIはASGIを使用するので、非同期Python Webアプリケーションを実行するためにUvicornを使用します。

- `app.main:app`: Uvicornに、アプリケーションをロードするモジュールと変数名を指定しています。ここでは、`app.main`は`app`ディレクトリの`main.py`というPythonファイルを指し、`app`はそのファイル内でFastAPIのインスタンスとして作成された変数の名前です。

- `--reload`: このオプションを付けると、開発中にソースコードが変更されたときにサーバーが自動的にリロードされます。つまり、コードを編集して保存すると、自動的にアプリケーションが再起動して変更が反映されます。これは開発環境で非常に便利ですが、本番環境で使用するのは推奨されません。

このコマンドを実行すると、Uvicornは指定されたFastAPIアプリケーションをホストし、デフォルトのポートである`8000`でリッスンします。ブラウザで`http://127.0.0.1:8000`にアクセスすることにより、開発中のWebアプリケーションを表示できます。
Android開発者オプションの最小幅をいじってたら戻せなくなった

# はじめに
Androidの開発者オプションの最小幅をいじっていたら値を大きくしすぎて戻せなくなりました．
同じようなことをしてしまった少数のうっかりさんのため，記事を書く練習を兼ねて解決策を紹介します．

# 環境
Android 9

# やらかすまでの流れ
最小幅いじる(すんごい大きい値にする) 
⇨ なぜか開発者オプションをオフにする 
⇨ 再度オンにして値を戻そうとするも，キーボードが立ち上がらずロックを解除できず詰む

# 解決した方法
最大の課題は，以下にしてキーボードが使えない状態を解決して開発者オプションを再度有効にするかでした．
デフォルトで入っているキーボードからGboardというGoogleが提供しているキーボードアプリをインストールしたら解決できました！

## 詳細手順
 1. パソコンからSlack（テキストがコピーできる任意のSNS）に`Gboard`というテキストを送信する
 2. スマホから先ほど送信したテキストをコピーし，Google Playストアから`Gboard`アプリをインストールする
 3. スマホの設定 -> システム -> 言語と入力 と移動し画面上のキーボードでGboardを有効にする
 4. キーボードが復活したので，開発者オプションをオンにして最小幅をデフォルトに戻す（筆者の場合360dp）

 ## 補足
 　物理キーボードが使える方は最初からそちらでやった方が早いかもしれません．
  ユーザーアシスト機能をオンにすると最小幅が大きい世界で画面遷移などをしやすくなります．

# まとめ
 　最小幅大きくしすぎた人は，その最小幅に対応してくれるキーボードがあれば元の値に戻せます．
（そもそも開発者オプションオフにしなければもっと楽）

そもそもスマホが起動しなくなってしまった方は，[こちらの方](https://qiita.com/Tarooo000/items/1515f2eb8669a2524a0c "Androidの開発者オプションの最小幅を上げすぎたら起動しなくなった話")の記事を参考にすると良いと思います．

# 参考文献
[Androidの開発者オプションの最小幅を上げすぎたら起動しなくなった話](https://qiita.com/Tarooo000/items/1515f2eb8669a2524a0c)
PHP について

# はじめに
はじめまして。 **佐藤** です。現在、私はPHP の学び直しをしている身です。勉強するにしても、単純に知識をインプットするだけに終始するのはもったいない。そこでこの度、PHP をテーマにQiita を始めることにしました。Qiita を始めた動機としては、
* **学んだ知識を共有するため**
* **学び直しの内容を忘れないようにするため、アウトプット**

**詳しく書かない** をコンセプトに **テクめも** を書いていきたいと思います。よろしくお願いいたします。

# 対象読者
**詳しく書かない** をコンセプトにしているため、**サクっとPHP の要点を見直したい人**。

# PHP とは
PHP: Hypertext Preprocessor とは、主にサーバサイドのWeb ページを作成するためのプログラミング言語。HTML に埋め込むことができ、動的なページを生成することができる。

# PHP 記述のルール
* PHP ファイルの拡張子は「**.php**」
例．sample.php
* PHP コードは、 `<?php ～ ?>` の中に記述する
* **命令文** の大文字、小文字は区別しない
* 文と文の区切りは **セミコロン** (`;`)
* インデント、改行、コメントを適宜付与し、読みやすさを心がける
* コメントの種類には、単一行 (`//`、`#`) 、複数行 (`/* ～ */`) がある
```php:PHP 記述のルール
<?php
// PHP タグ開始

/*
    PHP コードは <?php ～ ?> の中に書く
    命令文の大文字、小文字は区別しない
    文と文の間は、セミコロン (;) で区切る
    インデント、改行、コメントを適宜入れ、読みやすさを心がける
    以下、PHP コードの例
*/

$flg = true;
if ($flg) {
    print 'スイッチON';    // 文末はセミコロン (;)
} else {
    print 'スイッチOFF';
}

/* コメントの種類 */
// 単一行コメント
#  単一行コメント
/*
    複数行
    コメント
*/

// PHP タグ終了
?>
```
:::note info
`<?php ～ ?>` は、 **スクリプティングデリミター** or **PHP タグ** と呼ぶ。
ファイル末尾の `?>` は **省略可**
:::

# PHP コードの埋め込み
PHP ファイル (.php) には、PHP コードはもちろんのこと、HTML を記述することもできる。つまり、HTML にPHP コードを埋め込むことができるということ。以下の「sample.php」は、HTML にPHP コードを埋め込んだ例。`print` で文字列を出力している。
```php:sample.php
<!DOCTYPE html>
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <?php
            print 'Hello world!<br>';
            print 'My name is PHP.';

            /*
                実行結果：
                Hello world!
                My name is PHP.
            */
        ?>

    </body>
</html>
```
Pythonで「リストなどに要素として格納されている文字列を指定した区切り文字で連結する(join)」の動作を確認してみた

# 概要

Pythonで「リストなどに要素として格納されている文字列を指定した区切り文字で連結する(join)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/string/index22.html

# 実装

以下のファイルを作成しました。
```sample.py
print("".join(["Apple", "Orange", "Lemon"]))
print(",".join(("Blue", "Red", "Green")))

print("".join(["Apple", 12, "Lemon"]))
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
AppleOrangeLemon
Blue,Red,Green
Traceback (most recent call last):
  File "/.../sample.py", line 4, in <module>
    print("".join(["Apple", 12, "Lemon"]))
TypeError: sequence item 1: expected str instance, int found
```

# まとめ

何かの役に立てばと。
# pythonを任意のディレクトリ上のコマンドラインで動かす。

## 目的

自作したpythonファイルを以下のようにコマンドラインツールとして実行できるようにする。
以下は成果物のイメージ（画像を回転させるプログラム。~~ffmpegを使えば...~~）
```bash
user:~$ rotate.py
start rotate...
...
user:~$ cd HOGE
user:~/HOGE$ rotate.py
start rotate...
...
```

## 環境
- Ubuntu 20.04 LTS
- python 3.8

## pythonを実行できるようにする

プログラムを作成する(詳細は省略)
```python:rotate.py
# import cv2 #　とりあえずコメントアウト

print("start rotate...")
```

### 実行可能にする

shebang(シバン)を追加する
```diff:rotate.py
+ #!/usr/bin/python3
```
```bash
chmod +x rotate.py
```
参考:

https://qiita.com/Nick_paper/items/b9655e02721a583f29b5

### PATHを通す

ファイルがあるディレクトリをPATHに追加する。
今回は `~/.local/bin`というディレクトリに`rotate.py`をコピーして、そこにPATHを通す。
```bash
# 実行ファイルのコピー
user:~$ mkdir ~/.local/bin
user:~$ cp rotate.py ~/.local/bin

# PATHを通す
user:~$ export PATH=~/.local/bin:$PATH
# 毎回通すのが面倒臭い場合は以下
user:~$ echo "export PATH=~/.local/bin:$PATH" >> ~/.bashrc
user:~$ source ~/.bashrc
```
参考：

https://qiita.com/takanemu/items/6027291be8a2a6af9adc

### 実行確認

以下のようにいろんな場所で実行できるようになればOK。

```bash
user:~$ rotate.py
start rotate...
...
user:~$ cd HOGE
user:~/HOGE$ rotate.py
start rotate...
...
```

## 仮想環境毎の実行ファイルをコマンドラインで使えるようにする。

### 問題
実際には python を使う場合は `venv` や`anaconda`等を使用して、それぞれ独立した仮想環境上で実行することが多い。それらの実行ファイルを前述した方法でコマンドラインで用いることはできない。
例えば`rotate.py`でコメントアウトしていたところを修正する。

```diff:rotate.py
- # import cv2 #　とりあえずコメントアウト
+ import cv2 #　とりあえずコメントアウト
```
そして実行するとエラーが発生する。これは素のpythonにopencvがインストールされていないからである。

```bash
user:~$ rotate.py
Traceback (most recent call last):
  File "/home/user/.local/bin/rotate.py", line 2, in <module>
    import cv2
ModuleNotFoundError: No module named 'cv2'
```
### 対策

上述の問題はそれぞれの仮想環境の python を用いることで対処できる。
とりあえず、opencv　がインストールされた仮想環境を作成する。

```bash
cd ~
user:~$ mkdir imgtools
user:~$ cd imgtools
user:~/imgtools$ python -m venv .venv
user:~/imgtools$ source .venv/bin/activate
user:~/imgtools$ pip install opencv-python
```

インストールが終わったら、rotate.pyのshebangを以下のように仮想環境の python の PATH　に変更する。

```diff:~/.local/bin/rotate.py
- #!/usr/bin/python3
+ #!/home/user/imgtools/.venv/bin/python
```
そして実行する。すると `import cv2` が問題なくインストールできているためエラーを吐かずに実行することができる。

```bash
user:~$ rotate.py
start rotate...
...
```

### その他の仮想環境

`anaconda`などの場合でも、以下のように shebang を編集することで、それぞれの仮想環境のライブラリをimport することができるようになる。
```diff:~/.local/bin/rotate.py
- #!/usr/bin/python3
+ #!/opt/conda/envs/imgenv/bin/python
```
【AWS】DB インスタンスクラスでサポートされている DB エンジンについて

## はじめに
今年7月上旬にAWSから旧世代のDBインスタンスが廃止になるという旨のメールが届いていました。

廃止予定DBインスタンスクラス
>db.m4、db.m4、db.r4、db.t2 インスタンスクラス

廃止予定日
>2024年4月1日

RDSメジャーバージョンアップと同じタイミングで実施しようと
調査していましたら、DBインスタンスクラスでサポートされているDBエンジンのバージョンに違いがあることを知りました。

## DBインスタンスクラスでサポートされている DB エンジンバージョン一覧

例.MySQLエンジンバージョン一覧
| インスタンスクラス | MySQL|
| ---- | ---- |
| db.m6i.large | MySQL バージョン 8.0.28 以降 |
| db.m5.large | インスタンスクラスは DB エンジンのすべての<br>バージョンでサポートされています。 |

※詳細な一覧は以下をご確認ください。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html#Concepts.DBInstanceClass.Support

上記の一覧を確認しますと、新しい世代(db.m6i.large)のインスタンスクラスでは、
MySQL5.7とMySQL8.0.27以前のバージョンがサポートされていない状況となっています。

## 所感
MySQL5.7→MySQL8.0へのメジャーバージョンアップを考えたときに、
新世代のDBインスタンスクラスを利用する場合は、先にメジャーバージョンアップを
実施する必要がありそうです。

余談ですが、DBエンジンがMySQL5.7のRDSでインスタンスクラスを変更しようとしても
新世代のDBインスタンスクラスは表示されないようです。
Docker Desktopが使えなくて困った話

# はじめに

レンタルしたMacで環境構築をしていたところ、悲劇に出会ったのでここで小さくまとめておきます！


# 問題
Docker Desktopをインストールできたものの
DockerEngineが起動せず、ずっと詰まっていました泣

![スクリーンショット 2023-11-08 15.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627753/3a3e9655-bc5a-08b7-0f49-70c371c6de74.png)








# 解決方法
1. MacのOSのバージョンをあげること

2. Docker Desktopのバージョンを下げること

この2点です。

# 自分がなぜこんなに詰まったか

"MacのOSのバージョンを更新せずにひたすら作業をしていた"

です。

Dockerの公式から
Docker Desktop for Macをインストールすると、最新のDocker Desktopを取り入れることができます。

2023/11/08現在
Docker DesktopをインストールするとDocker Desktop4.25のバージョンを入手できます。

このバージョンが許容するMacのOSは

> macOS 13.0以降で使用可能。macOS 14.1以降ではデフォルトで有効になっている

そうです。

https://www.publickey1.jp/blog/23/docker_desktopapplex86-64rosetta_for_linux.html



# おわりに
ちゃんと公式の要件を読まずに、Dockerをインストールしていたのが間違いでした笑
Docker Desktopにも、対応できるバージョンが絞られているのですね。

バージョン全てに対応していると思って行動してました💧
どのバージョンのOSに対応しているかは要チェックですね
Juliaでニューラルネットワーク: Flux.jlのMinimal reproducible example

Flux.jlはv0.15以降、これまでの標準であったImplicit-styleを用いた記述がサポートされなくなるようです([公式ドキュメント](https://fluxml.ai/Flux.jl/stable/models/quickstart/))。新しい記述スタイルに対応したサンプルコードはいまだに多くないため、とりあえず動く、汎用性の高いminimum exampleを参考として載せておきます。

# モデル設定
よくあるパーセプトロンのteacher-student model. $\boldsymbol{x} \in \mathbb{R}^d$に対して、

```math
y = W_{teacher} \boldsymbol{x}
```
によって出力$y\in \mathbb{R}$が定まる。生徒パーセプトロンは教師データを用いて$W_{teacher}$を推論する。

# コード
```Julia
#! teacher-student modelを解く1層パーセプトロン
using Flux, Distributions, LinearAlgebra, Plots, ProgressMeter

mu = 0.0f0
sigma = 1.0f0

d = 100 # dim
N = 1000 # train_num
M = 1000 # test_num

# teacher
W_teacher = rand(Normal(mu, sigma), d) 

# train
x_train = rand(Normal(mu, sigma), d, N) 
y_train = Float32.(W_teacher' * x_train)
train_data = [(x_train[:, i], y_train[i]) for i in 1:N] 
train_loader = Flux.DataLoader((x_train, y_train) |> gpu, batchsize=5, shuffle=true)

# test
x_test = rand(Normal(mu, sigma), d, M) 
y_test = Float32.(W_teacher' * x_test)
test_data = [(x_test[:, i], y_test[i]) for i in 1:M] 


# model and loss
model = Chain(Dense(d, 1, bias=false))  |> gpu
loss(y_hat, y) =  sum((y_hat .- y).^2)   # 全バッチでのlossのsumをとってgradを出す
opt = Flux.setup(Adam(), model) 

# training
n_epoch = 1000
train_loss = zeros(n_epoch)
test_loss = zeros(n_epoch)

function loss_total(x_batch::AbstractMatrix, y_batch::AbstractArray, model, loss)
    y_preds = model(x_batch) 
    return sum(loss.(y_preds, y_batch))
end 

@time @showprogress for i in 1:n_epoch
    for data in train_loader
        input, output = data

        grads = Flux.gradient(model) do m
            y_hat = m(input)
            
            return loss(y_hat, output) 
        end
        Flux.update!(opt, model, grads[1])
    end

    train_loss[i] = loss_total(x_train, y_train, model |> cpu, loss)
    test_loss[i] = loss_total(x_test, y_test, model |> cpu, loss)
end

# 結果の表示
plt = plot(train_loss, label="train")
plot!(plt, test_loss, label="test", title="Loss")
display(plt)
```

# Remark
- データは自分でFloat32に変更する必要があります。
- モデルが小規模なためかGPUを使うと逆に遅くなります。
cakePHP でうまくアソシエーションが読み込めない

cakePHP3 ではまったので共有。
## 今回はまったポイント
アソシエーションを別名で定義していた場合、孫要素のcontainがうまくいかなかった。

例)

:::note
（）内はテーブル名です
:::

①「記事（documents）」には「評価（evaluations）」が紐づいている。
②「評価（evaluations）」には「高評価（good_evaluations）」と「低評価（bad_evaluations）」がある。
③「評価（evaluations）」には「ユーザー（users）」が紐づいている。

・・・・・
上記の条件で**低評価を下したユーザー名を取得したい**場合、
いつものように書くと孫要素である「ユーザー（users）」が読み込めない。
```documentsTable.php
$this->hasMany('bad_evaluations', [
    'className' => 'evaluations',
    'conditions' => ['value' => -1],
    ...
    'propertyName' => 'bad_evaluations'
]);
```
```evaluationsTable.php
$this->belongsTo('users', [
    ...
]);
```
```documentsController.php
$this->documents->find()->contain(['bad_evaluations' => ['users']);
// ↑ ここでエラーが起こる
```

原因は、classNameの定義が小文字だったから。
classNameを大文字で指定したらアソシエーションが読み込まれた。
```diff_php
//  documentsTable.php
$this->hasMany('bad_evaluations', [
-   'className' => 'evaluations',
+   'className' => 'Evaluations',
    'conditions' => ['value' => -1],
    ...
    'propertyName' => 'bad_evaluations'
]);
```
## 教訓
小文字でも子要素である「評価（evaluations）」レコードの取得は可能。

cakePHPは自動補完してくれるため開発効率がいいが、
定めている通りに書かないと、どこかでボロが出るとわかった。
https://book.cakephp.org/3/ja/orm/associations.html
venvのクイックスタート【Linux, Mac】

venvでサクッと環境構築したいときの備忘録

今回はenvという名前でプロジェクト直下に環境を作成する。envは任意の名前に変更可能。

# 仮想環境の作成

```sh
python3 -m venv env
```

`python -m venv`の後ろにディレクトリ名を指定することで、そのディレクトリに仮想環境が作成。

# 仮想環境の有効化

```sh
source env/bin/activate
```

仮想環境を有効化すると以下のようにシェルのプロンプトにディレクトリ名が表示される。
```sh
(env) $
```

# 仮想環境の無効化

```sh
(env) $ deactivate
```

システム共通の環境に戻る。

# 仮想環境の削除

```sh
rm -rf env
```

仮想環境のディレクトリが削除される。
Proxmox VEでVM/コンテナをまとめてハイバネート・シャットダウンするスクリプト

定時シャットダウン用。基本的に全部ディスクにハイバネートして、コンテナとかPCIパススルーとか失敗したVMはシャットダウンする。
```bash:shutdown.sh
#!/bin/bash

# VMとコンテナのリストを取得
VMS=$(qm list | awk 'NR>1 {if ($3=="running") print $1}')
CTIDS=$(pct list | awk 'NR>1 {if ($2=="running") print $1}')

# VMをハイバネートする関数
hibernate_vm() {
  local vmid=$1
  # PCIパススルーをチェック
  if qm config ${vmid} | grep -q 'hostpci'; then
    echo "VM $vmid はPCIパススルーを使用しているため、シャットダウンします。"
    qm shutdown $vmid --timeout 300
  else
    echo "VM $vmid をハイバネートを試みます..."
    if ! qm suspend $vmid --todisk; then
      echo "VM $vmid をハイバネートできませんでした。シャットダウンします。"
      qm shutdown $vmid --timeout 300
    fi
  fi
}

shutdown_ct() {
  local ctid=$1
  echo "コンテナ $ctid をシャットダウンします..."
  pct shutdown $ctid
}

# すべてのVMを処理する
for vm in $VMS; do
  hibernate_vm $vm
done

# すべてのコンテナを処理する
for ctid in $CTIDS; do
  shutdown_ct $ctid
done

# VMとコンテナのシャットダウンが完了するのを待つ
for vm in $VMS; do
  while qm status $vm | grep -qw "running"; do
    echo "VM $vm がまだシャットダウンしていません。待機中..."
    sleep 1
  done
done

for ctid in $CTIDS; do
  while pct status $ctid | grep -qw "running"; do
    echo "コンテナ $ctid がまだシャットダウンしていません。待機中..."
    sleep 1
  done
done

# 全てのVMとコンテナがシャットダウンした後、ホストをシャットダウン
echo "全てのVMとコンテナをシャットダウンしました。ホストをシャットダウン出来ます..."
shutdown -h now
```

あとは適当な場所に突っ込んで`crontab -e`とかで定時シャットダウンさせればOK。
なお失敗してVMやコンテナやデータがぶっ壊れても自己責任でお願いします。
また、何らかの原因でVMやらコンテナがロック状態でループした場合の処理を入れてないので、一生シャットダウンできない場合があります。slackのwebhookとかで通知できるようにしたほうが良いかも。
Dockerをインストールする手順

# はじめに
ターミナルでdockerコマンドを使いたいので、Dockerをインストールしていきたいと思います。

### 【STEP1】 Docker Desktopをインストールします。
下記のリンクからダウンロードページに飛べます。

https://www.docker.com/products/docker-desktop/


### 【STEP2】 自分の環境に合わせてダウンロードします。
(私は、Downroad for Macを選択)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031451/e1fdf0f5-0484-21fd-5d5d-51125448f0c8.png)


### 【STEP3】 ダウンロードされたDocker.dmgをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031451/161306f6-1cee-025c-8f00-9adb3b5189c0.png)

### 【STEP4】 drag and dropをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031451/19b58c50-ac7f-c97e-a6a1-d12fe2bcd659.png)
Dockerアプリがインストールされました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031451/1a291a32-ef78-9680-e4bb-ed6a1bc3b6a2.png)

### 【STEP5】  Dockerアプリを開いて、Dockerを起動します。
Docker Desktop is runnningになってればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031451/9a661862-1a6f-3a9a-5d89-99fc893139d6.png)

### 【STEP6】 ターミナルでDockerコマンドが使えるか確認します。
```
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```
上記のようにターミナルでdockerコマンドが使えればOK。

# まとめ
今回は、Docker Desktopを利用してDockerを使えるようにしてみました。