OmniAICreator/Qiita-1.07M huggingface dataset:
新卒からやって良かったこと、悪かったこと3選

# はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。（同担OKです😉）

本日は3月31日、自分の1年目のキャリアが終わりを迎える日になりました。
そこで、これまでの1年間を振り返って個人的に良かったこと、悪かったことをポエムとしてまとめました。

自分への戒めなので、主観が大いにあります😎

# 目次
全部見てられるかあ！って方のために、最初にまとめておきます。

### やって良かったこと😍
- [1. とりあえず発言してみる](#1-とりあえず発言してみる)
- [2. ポートフォリオを作りながら技術勉強](#2-ポートフォリオを作りながら技術勉強)
- [3. 自分からやりたい仕事を取りに行く](#3-自分からやりたい仕事を取りに行く)

### やって悪かったこと😇
- [1. 書籍を買うだけで満足](#1-書籍を買うだけで満足)
- [2. 勉強会症候群](#2-勉強会症候群)
- [3. 研修に期待するだけ](#3-研修に期待するだけ)

# やって良かったこと😍
まずはやって良かったことからです。主に仕事に対してです。
## 1. とりあえず発言してみる
これまでの就活生活などでも分かったことなのですが、他人任せと言わんばかりに誰も発言しないことがザラにあります。（自分も人のことを言えるほどではないですが😇）

したがって、発言するだけで一定の評価が得られます。💪

また、発言することは自分の顔を覚えてもらえるという特典も付いてきます。
自分は目立ちたがり屋ではありませんが、覚えてもらえるだけで得が結構あったりします。🥳

例）アイスブレークがやりやすくなる、社内でやりたいことをやらせて貰いやすくなる

:::note info
発言するだけ得なので、何か話してみよう
:::

## 2. ポートフォリオを作りながら技術勉強
自分は、本を読むのが得意ではないので、インプットだけだと退屈になってしまいます。😰

そのため、ポートフォリオを作ることを目的とし、制作時に自分が興味のある技術を取り入れることやり方っで勉強しました。

これは周知のことと思いますが、改めて考えると惰性で何か触るより、目的を持って触っている方がその言語、ライブラリの理解の深さや自分自身のやる気がまるで違います。😤

また、ポートフォリオを作るということは、自社開発企業の業務で必要なこと（CI/CDや非機能要件など）も考える必要があるため、思った以上に周辺知識が身に付きます。🤩

ポートフォリオ自体も、自分の技術力のアピールになるので積極的に作っていったほうが良いと思います。

（やりたいことが無い or 要件定義などめんどくさい方は、AIを活用すると勝手にやってくれます🥹）

:::note info
目的を持って手を動かす方が楽しいし学びにつながるので作ってみよう
:::

## 3. 自分からやりたい仕事を取りに行く
やりたい仕事と言っても、自分の場合は特定の言語やライブラリを使う開発であったり、フロント＆バック両方みたいな、技術面でやりたい仕事を取りに行ってました。

まず、部課長にやりたいことを自分で伝えて、ついでに勉強しているスタックも報告してました。
（顔を覚えてもらっていたので話が早かったです🥹）

課長に、その技術スタックならここだろうという風にアサインされたPJが大当たりでした🤩
PJ内でも自分のやりたいことを先輩エンジニアにお伝えし、挑戦させてもらえました。

挑戦すること姿勢も評価して頂けるので、自分からやりたい仕事を取りに行くのはお得のバーゲンセールですね🤭

:::note info
幸福度と周りからの信頼のために、自分から仕事を取りに行こう
:::

# やって悪かったこと😇
## 1. 書籍を買うだけで満足
書籍を買っただけで、一歩前進した気持ちになってしまい今では本棚の中で眠ってしまった書籍が何冊もあります。🫣

原因としては、自分のやりたいことが頭にあった中で、それ以外の興味のある分野に関する書籍を何冊も買っていったことだと思います。

そのせいで、結局手付かずのまま存在が忘れられてしまうので、お金を無駄にしないためにも中途半端な気持ちで書籍を買うのはオススメしません。😨

ああ。。。本棚に眠ったSvelteやGraphQL、OAuthの書籍はいつ読もう。。。

:::note warn
今すぐ欲しい知識で無いのならば、買うべきではない
:::
## 2. 勉強会症候群
意欲がある方の中では案外ハマりやすいのでは無いでしょうか。
自分もそうです。😇

社内で勉強会と名のつくものに興味が惹かれ、なんとなく入ってしまった勉強会。。。
実際なんで入ったんだろう。。。という気持ちになってしまいます。

何も勉強会が悪い訳ではありません。ただ、想像と違うものだった時に抜けづらいのです。😣

そのままズルズルと自分の時間が奪われていくのは勿体無いので、安易に勉強会に入ることはやめましょう。
勉強会に参加してる自分が好き〜🎶（カロリミットファンケルのCM風に（伝われ！））な感じでポンポン入っても、実になることは少ないと思います。

それか、抜けやすいように「自分、見学希望でいいっすか？😎」と言ったラフな形で一回参加してみると良いかも知れませんね。（知りませんけど🥹）

::: note warn
興味のある勉強会でも安易に入らない or 抜けやすいように見学として参加してみる
:::

## 3. 研修に期待するだけ
ほとんどの会社は、新卒には研修があると思います。
自分の勤めている会社でも3ヶ月ありました。（手厚いですね😘）

ですが、その研修に身を任せ、業務時間外に何もしないのは勿体無いです。
基本的に研修は定時がほとんどだと思いますので、その後勉強する機会なんて幾らでもあります😎

自分の場合は、初学者の方に研修レベルが合わせられていたため、着々と力を付けられている実感があまり沸きませんでした。😩

そのため、1ヶ月を過ぎた段階で焦りを覚え、定時後に興味のある技術に関して勉強しアウトプットを行っていました。
（この時のポートフォリオ作成が、自分のやりたい仕事を取りに行く際役立ちました🤓）

また、自分は周りの同期にも恵まれていたので、一緒に勉強できたことでやる気が継続したのはラッキーだと思います。

研修で満足することは悪ではありませんが、配属後のためにも何かやっておくとなお良いと思います。😁

::: note warn
研修で満足して何もしないのは勿体無い
:::

# おわりに
新卒社員が偉そうに。。。😡と思った方もいらっしゃるでしょうが、あくまで個人的な戒めもあるのでご容赦ください。🥹

これを見て何か行動するきっかけになれば幸いです。😁

他にも気になる方がいらっしゃれば、コメント等でお知らせください。
最後まで見ていただき、ありがとうございました🙇
シン・rsync・第4形態

※　タイトルはネタです、ゴジラとはなんの関連もございません。
※　第1~3形態は本人の努力と苦労の作業の彼方に消え去りました。

## `rysnc`コマンドとは
Unix/Linuxで広く利用されているファイル転送ユーティリティです。ローカル・リモートを問わず、ディレクトリ構造を保ちつつファイル同期を行えます。ファイル内の差分のみを転送するデルタ転送機能があり、帯域の有効活用が可能です。SSHなどを介したセキュアな転送や、圧縮転送、帯域制限、進捗表示などの機能を備えています。バックアップ運用や大容量データのレプリケーションに適しています。豊富なオプションと柔軟性の高さから、ファイル操作に携わるエンジニアに広く活用されています。（Claude3の回答より）

## コマンドを使用した背景
- サーバーAで稼働しているWebサイトのディレクトリをまるっとサーバーBに移したい
- サイト全体の容量が１００GBを超えるので、不要なディレクトリを多数排除して移したい
- 動作テストから本番切り替えの間もサーバーAは本番環境として稼働中
- 動作テストを行なった後、本番切り替えとなるため複数回の同じ作業が見込まれる
- 動作テスト中、サーバーBでは稼働させるための独自の修正を加える必要がある

## 今回使用したrsync
```
rsync -rltDvz -n --progress --partial --bwlimit=3000 --log-file=/home/user/log/rsync-`date +"%Y%m%d-%H%M"`.log --log-file-format="%o %f (%M) %l %b" --exclude='exexclude-a' --exclude='exclude/aaa' -e "ssh -p 9999 -i key-file" ssh-user@192.168.XX.XX:/srv/www/the-directory/ /srv/www/the-directory/ | tee /home/user/log/tee/rsync-tee-`date +"%Y%m%d-%H%M"`.log
```
## オプションなどを解説
```
-rltDvz

    -r : ディレクトリの内容も再帰的にコピーする
    -l : シンボリックリンクをコピーする(リンク先そのものではなく、リンクファイルをコピー)
    -t : 時間情報を保持する
    -D :デバイスファイルとスペシャルファイルを転送する
    -v : 詳細モード(転送状況を表示)
    -z : 圧縮して転送する

-n --progress --partial

    -n : 実際の転送は行わず、転送対象を確認するためのドライランモード
    --progress : 進捗状況を表示する
    --partial : 中断されたファイルの転送を再開できるようにする

--bwlimit=3000

    転送帯域幅を3000kbpsに制限する

--log-file=/home/user/log/rsync-`date +"%Y%m%d-%H%M"`.log
--log-file-format="%o %f (%M) %l %b"

    --log-file : ログファイルのパスを指定
    --log-file-format : ログファイルの出力フォーマットを指定
        %o : 送信元のパス
        %f : 転送したファイル名
        %M : ファイルの最終更新日時
        %l : ファイルの長さ(バイト数)
        %b : 転送したファイルのバイト数

--exclude='exclude-a' --exclude='exclude/aaa'

    除外するファイル/ディレクトリのパターンを指定

-e "ssh -p 9999 -i key-file"

    -e : rsyncがリモートシェルを呼び出すときのコマンドを指定
    sshを使ってリモートサーバーに接続し、ポート9999、指定の秘密鍵ファイルを使用

ssh-user@192.168.XX.XX:/srv/www/the-directory/

    リモートサーバーのユーザー名、IPアドレス、転送元ディレクトリのパスを指定

/srv/www/the-directory/

    ローカルサーバー側の転送先ディレクトリを指定

| tee /home/user/log/tee/rsync-tee-`date +"%Y%m%d-%H%M"`.log

    rsyncの標準出力をログファイルに書き出す
```

## ハマりポイント
- `-rltDvz`の代わりに`-a`を使って実行していたがサーバーAとサーバーBで所有者情報などが異なるため、２回目の実行時に所有者情報などが上書きされてしまった。
- 2回目実行する際、`-n`でDryRunした際のログから更新されるファイルを特定しバックアップを作成していたが、実際の実行ではログに出力されたファイル以外も更新され、バックアップしていないファイルも更新されてしまった
- sshを使用してサーバーAに接続して実行しようとしていたが、ポートがデフォルトのポートとは違う番号に設定されていたため実行しても失敗していた。ポート番号の指定が必要なことに気づき`-e`オプションを使用して解決した。
- サーバーAは本番稼働中なので稼働に影響の出ない通信負荷を調査し、`3000kbps`と設定することで稼働に影響なく実行することができた。
- ディレクトリ指定に`/`をつけずに実行した際、指定したディレクトリまでサーバーBに作成されてしまった。`/a →　/a/a`という形に。
AzureOpenAIのAPIを使ったEmbeddingモデルの取得方法

# はじめに
Pythonを使ってAzureOpenAIのエンドポイントを使う場合、`openai`の`1.x`以降ではOpenAIのエンドポイントを使う場合と書き方が異なる模様。
> 参考：https://learn.microsoft.com/ja-jp/azure/ai-services/openai/how-to/switching-endpoints

`Embedding`モデルを使う場合も書き方が異なってくるため、`LangChain`と`LlamaIndex`のそれぞれでどのような方法になるかをまとめる。

いずれも関数として定義し、RAGなどで必要な`Embedding`モデルとして利用できるような形で示す。

# 環境
`openai`: `1.14.1` ※`1.x`以降

# 方法
以下、それぞれの定義はこちら。
## `LangChain`の場合
```python
from langchain_openai import AzureOpenAIEmbedding

def get_embedding():
    embedding = AzureOpenAIEmbedding(
        openai_api_type='azure',
        openai_api_version='{API_VERSION}',
        azure_endpoint='{API_ENDPOINT}',
        openai_api_key='{API_KEYS}',
        model='{EMBEDDING_MODEL}',
        azure_deployment='{MODEL_NAME}'
    )
    return embedding
```

## `LlamaIndex`の場合
```python
from llama_index.embeddings.azure_openai import AzureOpenAIEmbedding

def get_embedding():
    embedding = AzureOpenAIEmbedding(
        model='{EMBEDDING_MODEL}',
        deployment_name='{EMBEDDING_DEPLOYMENT_MODEL_NAME}',
        api_key='{API_KEY}',
        azure_endpoint='{API_ENDPOINT}',
        api_version='{API_VERSION}'
    )
    return embedding
```

# 関連記事
https://qiita.com/yujimats/items/a424f608653c74348bcd
axios.createを使う時の注意点とその対応

# はじめに
ReactでHTTPクライアントとしてよく選択されるものに`axios`があります。
今回はそのaxiosに備わる機能、`Axios Instance`についての注意とその対策法について紹介したいと思います。

その前に、件の`Axios Instance`はどういうものかを一応簡単に解説します。
例えば以下のような設定をした時。

```ts
const customAxiosInstance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
  }
});
```

　この`customAxiosInstance`インスタンスを使用することで、`baseURL`・`timeout`・`headers`を指定した状態でHTTPリクエストを送ることができます。

```ts
await customAxiosInstance.get("/users");
// リクエストを送る時に以下と同等になる！
// const response = await axios.get("https://some-domain.com/api/users", {
//   timeout: 1000,
//   headers: {
//      Authorization: `Bearer *******token***********`,
//   },
// });
```

https://axios-http.com/docs/instance

# 問題
問題となるのは、`Axios Instance`でtokenなどを管理している時です。

例えばlocalStorageに保存しているtokenを`Axios Instance`で使用している場合。
非ログインの状態でサイトにアクセスした時、
```ts
const customAxiosInstance = axios.create({
    baseURL: "https://some-domain.com/api/",
    headers: {
        Authorization: `Bearer null`,
    },
});
```
この時、非ログインなので当然tokenはnullになります。

ここまではいいのですが、ここでユーザーがログインをしたとします。
そうするとtokenが発行され、localStorageに保存されるわけですが...

この`customAxiosInstance`は当然ですが更新されず、従ってtokenはnullのままです。
バックエンド等との通信もうまくいかないことになります。

また、この現象はおそらくウィンドウの再リロードでしか解決できず(間違っていたらすみません🙇🏻‍♂️)、
ログイン、ログアウト時に`window.location.reload()`を実行というような無理矢理な方法をとらなければいけません。

結論としては、ログイン、非ログインなどユーザーの状態によって変動する値をリクエストに含めたい場合、
axiosの別の機能、すなわち`Interceptors`を使用しましょう。

# 解決方法
https://axios-http.com/docs/interceptors

`Interceptors`は、リクエストの前後に任意の操作を挟み込める機能です。
これを使用した場合、先ほどの`customAxiosInstance`は以下のようになります。
※これはミニマムであり、型やLintエラーが出る場合がありますが適宜修正してください🙏

```ts
const customAxiosInstance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
});

const authRequestInterceptor = (config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem("token");

    if (token !== null) {
        // tokenがnullでない時、headerにAuthorizationを追加
        config.headers.Authorization = `Bearer ${token}`;
    }

    return config;
};

// リクエストの前に、authRequestInterceptorの処理をする宣言
coustomAxiosInstance.interceptors.request.use(authRequestInterceptor);
```

こうすることで、`axios.create`の恩恵を受けつつ、tokenなどの状態が変わるようなパラメーターも問題なくリクエストに含めることができるようになります。

# おわりに
最後までお読みいただきありがとうございました！
修正や違う方法の提案等あれば是非是非コメントにお願いします😃

# 参考サイト
https://axios-http.com/docs/instance

https://axios-http.com/docs/interceptors
正規表現ってなに

# 正規表現のメリットデメリット

## メリット

パターンマッチング
テキスト処理

## デメリット

可読性の低さ

# 正規表現の例

| 正規表現 | 意味 |
|:------------:|:------------:|
|.　     | 任意の1文字にマッチする  | 
|\*    | 前にある文字が0文字以上続く     | 
|+ | 前にある文字が1文字以上続く        | 
|[　]         |中にある文字のいづれかにマッチする           | 
|[ - ]        |中の文字を範囲指定できる        | 
|[^ ]    |中の文字を含まない     | 
|{ x }     |前にある文字がx文字続く      | 
|{ x , y }     |前にある文字がx文字以上、y文字以下続く      | 
|\d     |[ 0-9 ]の意味      | 
|^     |行頭      | 
|\A     |行頭      | 
|$     |行末      | 
|\z     |行末      | 


# 正規表現を使う場面の例

**1 郵便番号の正規表現**

郵便番号が正しいフォーマットで入力されているか正規表現を使って確かめる方法
```
"^\d{3}-\d{4}$"
```
**2 電話番号の正規表現**

電話番号が正しいフォーマットで入力されているか正規表現を使って確かめる方法
```
"^0\d{1,4}-\d{1,4}-\d{4}$"
```


# 正規表現があっているか確かめる方法

このサイトを使うと、自分の書いた正規表現があっているか確かめることができる

https://regex101.com/
AzureOpenAIのAPIを使ったLLMモデルの取得方法

# はじめに
Pythonを使って、AzureOpenAIのエンドポイントを使う場合、`openai`の`0.28.1`では、OpenAIのエンドポイントと同じ書き方だったが、`1.x`以降は若干異なるとのこと。
> 参照：https://learn.microsoft.com/ja-jp/azure/ai-services/openai/how-to/switching-endpoints

`LangChain`または`LlamaIndex`のフレームワークを利用する場合も変わってくるため、方法をまとめる。

いずれも関数として定義し、RAGなどで必要なLLMモデルとして利用できる形で示す。

# 環境
`openai`: `1.14.1` ※`1.x`以降

# 方法
## `LangChain`の場合
```python
from langchain_openai import AzureChatOpenAI

def get_llm(temperature=0):
    llm = AzureChatOpenAI(
        api_version='{API_VERSION}',
        azure_endpoint='{API_ENDPOINT}',
        api_key='{API_KEYS}',
        azure_deployment='{OPENAI_MODEL_NAME}'
        temperature=temperature
    )
    return llm
```

## `LlamaIndex`の場合
```python
from llama_index.llms.azure_openai import AzureOpenAI

def get_llm(temperature=0):
    llm = AzureOpenAI(
        model='{GPT_MODEL}',
        deployment_name='{GPT_DEPLOYED_MODEL_NAME}',
        api_key='{API_KEYS}',
        azure_endpoint='{API_ENDPOINT}',
        api_version='{API_VERSION}',
        temperature=temperature
    )
    return llm        
```
引数の`deployment_name`には以下いずれかのモデル名をいれる必要がある。
デプロイしたモデルに合わせて設定すること。

<details><summary>`deployment_name`の候補</summary>
gpt-4, gpt-4-32k, gpt-4-1106-preview, gpt-4-0125-preview, gpt-4-turbo-preview, gpt-4-vision-preview, gpt-4-0613, gpt-4-32k-0613, gpt-4-0314, gpt-4-32k-0314, gpt-3.5-turbo, gpt-3.5-turbo-16k, gpt-3.5-turbo-0125, gpt-3.5-turbo-1106, gpt-3.5-turbo-0613, gpt-3.5-turbo-16k-0613, gpt-3.5-turbo-0301, text-davinci-003, text-davinci-002, gpt-3.5-turbo-instruct, text-ada-001, text-babbage-001, text-curie-001, ada, babbage, curie, davinci, gpt-35-turbo-16k, gpt-35-turbo, gpt-35-turbo-0125, gpt-35-turbo-1106, gpt-35-turbo-0613, gpt-35-turbo-16k-0613
</details>

いずれも`temperature`は任意。



# 関連記事

https://qiita.com/yujimats/items/09e0fbcb49b989eda387
ABC-071 B - Not Found 解説

# あいさつ
皆さん、こんにちは＆お久しぶりです！
今回はABC-071のB問題「Not Found」について解説していきたいと思います！
（https://atcoder.jp/contests/abc071/tasks/abc071_b)

# 目次
- 問題概要
- 制約
- 入力形式
- 解説

# 問題概要
英子文字からなる文字列 $S$ が与えられる。
$S$ に登場しない英子文字のうち、辞書順最小のものを出力せよ。
$S$ にアルファベットすべてが登場している際には `None` を出力せよ。

# 制約
$S$ の長さは $1～10^5$
$S$ はすべて英子文字。

# 入力形式
```text:input.txt
S
```

# 解説
今回必要なのは 「$S$ に含まれているアルファベットが何か」のみです。
そのため、$S$全体を記憶しておく必要はありません。
$S$の入力を終えたらsetに入れてしまいましょう。

下記の例のように、本問では「Sにはa,cのみ含まれている」という情報のみが必要なので、setを利用しても問題ないことがわかります。
`ccccccaaaaa` → `a,c`

Sにどのアルファベットが含まれているかを記憶したsetを作成してしまえば、あとはアルファベットを全探索して
- その文字列がSのsetに含まれていなければ、その文字を出力
- すべてのアルファベットが含まれている際には'None'を出力
というようにしてしまえばACとなります。

```Python:071-B.py
# input
S = input()
set_S = set(S)
# output
alfa = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for alf in alfa:
    if alf not in set_S:
        print(alf)
        break
else:
    print('None')
```
[AtCoderで提出したコード](https://atcoder.jp/contests/abc071/submissions/51915844)
cndt2023-handsonを試したらすごく勉強になった

## はじめに
学習のため、以下ハンズオンを実施しました。

https://github.com/cloudnativedaysjp/cndt2023-handson

想像以上に内容が充実しており勉強になったので、備忘録もかねてブログに残したいと思います。

## 私のレベル
このハンズオンでも紹介されている、Prometheus・Grafana・Argo CDは聞いたことがあるくらいです。業務で使用したこともないです。
Kubernetesについても初心者。[Kubernetes完全ガイド](https://www.amazon.co.jp/Kubernetes%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E7%AC%AC2%E7%89%88-Top-Gear-%E9%9D%92%E5%B1%B1/dp/4295009792/ref=pd_lpo_sccl_1/356-6900141-1359567?pd_rd_w=BDOfm&content-id=amzn1.sym.c9d355d3-7242-4c45-8731-d024dd5a0fb6&pf_rd_p=c9d355d3-7242-4c45-8731-d024dd5a0fb6&pf_rd_r=7H4KJSKX1AXQCKP3NYHP&pd_rd_wg=gePIn&pd_rd_r=b09a2e55-1fbb-4a07-8eee-2f0831220916&pd_rd_i=4295009792&psc=1)を一読しましたが、業務では使用したことは無いです。

## 前提
chapter00～10までありますが、chapter06～chapter07、chapter09～chapter10は飛ばしました。
初心者の私には内容が難しいため飛ばしましたが、理解が深まってきたら後追いで実施します。


## 良かった点
### 実運用を想定して作られているので、導入時のイメージが沸く

`chapter03_grafana`では、実際のダッシュボードの表示はもちろん、アラート設定をしてSlackに通知を飛ばすところまで実施しました。
ここまで解説いただけると、導入したらこういう風に運用するんだなとイメージが沸きました。

### GitOpsを体系的に学べる
GitOpsという用語をよく聞くようになりましたが、実際の導入時のメリット等を理解するまでは至っていませんでした。
本ハンズオンでは、Gitリポジトリの変更をトリガーにして、アプリケーションへの自動デプロイまで実施します。
導入すればデプロイが簡単にできて、リリースの頻度向上が期待できると感じました。

### Kubernetesの勉強になる
Kubernetesクラスタの作成、デプロイまで実施します。
そのデプロイの過程でservices,deployments,ingressなどを使用します。
Kubernetesは一度書籍で学習はしていましたが、実際に使用することで理解が深まりました。


## 最後に
良かった点を箇条書きにしましたが、上記以外にも細かいレベルで勉強になった点がたくさんありました。
未実施分のchapterを実施すればもっと理解が深まる、このハンズオンのうま味を感じられると思います。
（未実施分完了したら記事は更新します）
これからPrometheus・Grafana・Argo CDといったツールを勉強したい人にはピッタリだと感じました。
個人的には、お金を払ってでも受けたいような内容でした。
最後までお読みいただきありがとうございました。
jetpackComposeでTextを装飾するbuildAnnotatedStringを使ってみた

# はじめに
JetpackComposeより以前ではSpanを使ってTextの一部などを装飾していましたが、それと同じことをJetpackComposeでやろうとした時にどうやってやるかを調べて使ってみた所 なんとなくで使うには少しクセがあったので自分で公式の内容を触ってみたメモ的なものを記事にして残しておこうかと思います。


# buildAnnotatedString

[buildAnnotatedString Android公式](https://developer.android.com/reference/kotlin/androidx/compose/ui/text/AnnotatedString)


公式内での使い方の例で一番簡単なのは実際に使ってみるとこんな感じ

```

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {

        Text(text = buildAnnotatedString {
            withStyle(SpanStyle(color = Color.Green)) {
                append("Hello")
            }
        })
    }
```

![スクリーンショット 2024-03-31 21.55.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/d95c759b-57b6-537f-8a8c-85cf9989a0e8.png)

withStyle(SpanStyle())で装飾を設定し、{}内にappend()でテキストを設定します。

別の例にあったのはこんな感じ

```
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {
        Text(text =  buildAnnotatedString {
            append("Hello")
            pushStyle(SpanStyle(color = Color.Green))
            append(" World")
            pop()
            append("!")
            addStyle(SpanStyle(color = Color.Red), "Hello World".length, this.length)
        })
    }
```


![スクリーンショット 2024-03-31 21.33.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/21bc4666-3878-8e52-f42c-ea28416c6214.png)

text に　buildAnnotatedStringを設定し、{}内で装飾をつけていきます。
append()でテキストを設定します。
pushStyle(SpanStyle())で設定された内容は pop()までのテキストに装飾を設定します。
addStyle(SpanStyle())で後から装飾を設定することもできます。
こちらで装飾をつける場合は装飾の範囲を指定する必要があります。


```
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {
        Text(text = buildAnnotatedString {
            append("link: Jetpack Compose")
            addStringAnnotation(
                tag = "URL",
                annotation = "https://developer.android.com/jetpack/compose",
                start = 6,
                end = 21
            )
        })
    }
```

こう言った感じでURLを格納したり、タグをつけることもできる。
JAVAをたまにしか書かないのでコードのメモを置く

# はじめに
1年ほどJAVAを書いておらず、基礎文法を忘れかけていたのでこの記事にメモ書きする。

# JAVAメモ

```java:テンプレ(main.javaだとする)
public class main{
    public static void main(String[] args){
    }
}
```


```java:何かを入力・出力したい時
import java.util.Scanner;

public class main{
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(); //単変数の場合
        int[] A = new int [n];  //配列の場合
        for(int i=0;i<n;i++){
          A[i] = scan.nextInt();
        }
        System.out.print(n);
        for(int j=0;j<n;j++){
          System.out.println(A[j]);
        }
    }
}
```
ソートしたい項目を選択したい　自分用メモ

ソートしたい項目を選択出来るような処理を作りたくて軽く調べて実施しました。


これでソートがいい感じにできるらしい


```js
  const hogeList = [
    {
      name: "saburo",
      number: "3",
    },
    {
      name: "ziro",
      number: "2",
    },
    {
      name: "taro",
      number: "1",
    },
  ]

  hogeList.sort((a, b) => a.num - b.num)
```


なるほど、、、完全に理解した

変数を適当に作っていい感じに渡せれば行けるやろ


```js
  const hogeSort = "num"

  hogeList.sort((a, b) => a.hogeSort - b.hogeSort)
```

あれ、出来てない、、、、
そもそも作った変数を渡せてないナニコレ

この変数のなかの文字列を後ろにくっ付けてあげるようにしたら行けるんじゃねっと思ってたのに出来ない、、、、

よくわからないけどこうやったら変数を渡せるらしい

```js
  const hogeSort = "num"

  hogeList.sort((a, b) => a[hogeSort] - b[hogeSort])
```

とりあえずやり方としてこれ覚えとこう
（メモ）100DaysofYARA

100DaysofYARAというWebページのメモ。

https://cyberpoking.com/tag/100DaysofYARA/

2024年1月1日から連日投稿されているYaraルールのTipsであり、１００日継続するみたいで現時点で９０日目を迎えている。

100日分揃ったら、まとめてみたい。
Ubuntu 20.04 に何も考えずにbazelをインストールする

tensorflow　系のエコシステムを利用していると`bazel`を入れてくれというメッセージが出ることがあって、結構インストールするのがめんどくさいので何も考えずUbuntu 20.04において`bazel`をインストールする方法を記載しておく。

* localhost
```bash
$ sudo apt install curl gnupg
$ curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
$ sudo mv bazel.gpg /etc/apt/trusted.gpg.d/
$ echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list

$sudo apt update && sudo apt install bazel
$ bazel --version
```
* dockerfile
```dockefile
# bazel
WORKDIR /tmp
RUN apt install curl gnupg
RUN curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
RUN mv bazel.gpg /etc/apt/trusted.gpg.d/
RUN echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list
RUN apt update && apt install bazel

```
参考URL:
https://gist.github.com/diegopacheco/10f4d7be75574e53e91c49f19bf2613f

公式URL:
https://bazel.build/?hl=ja
Webカメラから取得した画像を（ファイル保存なしで）Discord webhookで投稿

# 概要

Webカメラから取得したフレーム画像をJPG形式にエンコードし、POSTデータに含める。
OpenCV-pythonを使用する例では、いったん画像ファイルとして保存し、再度そのファイルを開いてPOSTするサンプルしか見つからなかった。ここに全部メモリ上で実施する方法を、個人的備忘録として記載する。

## インストール

適当なLinux機（ラズパイ）でインストールしたときの例。

```bash
sudo apt-get install libopencv-dev
sudo apt-get install python3-opencv
pip install opencv-python
```

## 実装

下記サンプルを使用するときに必要なimport。

```python
import json
import cv2
import numpy
import requests
```

### Webカメラでキャプチャ

dev/0が対象のWebカメラとする。カメラから撮影したframeを取得する。

```python
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
if ret is False:
    raise Exception("cap.read failed")
```

### 画像エンコード

JPEGにエンコードする。

```python
quality = 60 # JPG画像の品質 0～100、60ぐらいで十分かな
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]
result, encoded_image = cv2.imencode(".jpg", frame, encode_param)
if not result:
    raise Exception("EncodeError")
```

JPEGへ圧縮されたbyteデータがNumPy配列（ndarray）で返ってくるので、bytes型へ。

```python
encoded_image_byte = encoded_image.tobytes()
```

### WebhookへPOST

名前`file.jpg`を適当に指定しPOSTする。POST先はDiscordアプリ等から取得したDiscordサーバー/チャンネルのWebhook URLを指定する（[タイトル: Webhooksへの序章 – Discord](https://support.discord.com/hc/ja/articles/228383668-%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB-Webhooks%E3%81%B8%E3%81%AE%E5%BA%8F%E7%AB%A0)を参照のこと）。

```python
files = {"attachment": ("file.jpg", encoded_image_byte)}
params = {
    "payload_json": json.dumps(
        {
            "username": "Webhook Test BOT",
            "content": "画像を添付しました。",
            "tts": False,
        }
    )
}
response = requests.post(
    url="https://discord.com/api/webhooks/000000/xxxxxx...", # 「Discordサーバー/チャンネルのWebhook URL」を設定
    data=params,
    files=files,
    headers={},
    timeout=30.0,
)
response.raise_for_status()
webhook_res = response.json()
print(webhook_res) # 結果確認
```

### WebhookへPOST時、デバッグしたいとき

下記をimport直後等に追加することで、詳細なデータが標準出力に流れるようになる。

```python
import http
http.client.HTTPConnection.debuglevel = 1
```

### 画像を保存したくなったときは

bytes型をそのまま書き込めば良い。

```python
with open("file.jpg", "wb") as binary_file:
    binary_file.write(encoded_image_byte)
```
staticメソッドから非staticメソッドを呼び出す

staticメソッドから非staticメソッドを呼び出したい場合は直接呼び出すことができません。
インスタンスを生成し、そのインスタンスを通して呼び出す必要があります。

この記事ではstaticメソッドの概要に加えて、staticメソッドから非staticメソッドを呼び出す方法について記載します。

目次
[1.staticメソッドとは](#1-staticメソッドとは)
[2.非staticメソッドからstaticメソッドを呼び出す](#2-非staticメソッドからstaticメソッドを呼び出す)
[3.staticメソッドから非staticメソッドを呼び出す](#3-staticメソッドから非staticメソッドを呼び出す)


# 1. staticメソッドとは
staticメソッドは、戻り値の前にstaticを付けることで宣言できます。
staticメソッドで表現された変数はstatic変数またはクラス変数と呼ばれます。

以下の例からは、staticMethodがstatic変数（クラス変数）であり、staticMethodと命名されたメソッドがstaticメソッドであることが分かります。

```java
class TestSample {
    
    static void staticMethod() {
    }
}
```

 # 2. 非staticメソッドからstaticメソッドを呼び出す
Javaではstaticで宣言された変数が含まれるクラスはインスタンス化せずに呼び出すことができます。
呼び出すには「クラス名.」の後にstatic変数名を記載しますが、同じクラス内であれば、クラス名の記載は不要です。
以下の例のように、instanceメソッドや他のstaticメソッドからstaticメソッドを呼び出すことが可能です。

```java
class TestSample {
    
    static void staticMethod() {
    }

    void instanceMethod() {
        staticMethod();
    }

    static void staticMethod2(){
        staticMethod();
    }    
}
```

# 3. staticメソッドから非staticメソッドを呼び出す
反対に、staticメソッドからinstanceメソッド（＝非staticメソッド）を呼び出す場合は、staticメソッド内でインスタンスを生成する必要があります。
非staticメソッドはstaticメソッドから直接呼び出すことはできないので、インスタンスを通して間接的に呼び出します。

以下の例では、TestSampleクラスのインスタンス「testSample」を生成してから、「testSample」を通してinstanceMethodを呼び出しています。

```java
class TestSample {
    
    static void staticMethod() {
        TestSample testSample = new TestSample();
        testSample.instanceMethod();
    }

    void instanceMethod() {
    }
}
```
ITパスポート AI

・機械学習
過去のデータを経験としてコンピュータ自らが学習し、予測や判断ができるようになること
・ルールベース型AI
人がルールを考えてコンピュータに教え込む
・教師あり学習（推測）
問題に正解を与えて学習させる方法
・教師なし学習（グループ分け）
問題に正解を与えずに学習させる方法
・強化学習（制御）
問題に正解を与えずに試行錯誤することで学習させる方法

・ディープラーニング
人の脳神経回路を模倣したモデル（ニューラルネットワーク）を多層に重ねることで、学習能力を高めた機械学習
・バックプロパゲーション
期待している結果とはかけ離れている場合に、出力されたデータを正解データと比較して、その差が少なくなるように逆方向に学習させて修正すること
・過学習
AIが学習に使った訓練データに過剰に適合しすぎて、未知のデータに対しては適合できずに精度が下がってしまう状態
・基盤モデル
大量のデータを用いて学習させ、その後も再学習させながら微調整を行っていく機械学習モデル

・生成AI
文章や画像、動画、音声、デザイン、プログラムコードなどを生成するAI
・ハルシネーション
AIが学習データの誤りや不足などによって、事実に基づかない情報を生成してしまう現象
・ディープフェイク
AIを使って画像や動画などを部分的に交換させることで、元とは異なるものを生成する技術
・説明可能なAI
AIが導き出した出力結果のプロセスがブラックボックスとならないように、人が理解できる形に説明できるAI
・シンギュラリティ
AIの知能が人の知能を上回ってしまう
・サイバーフィジカルシステム（CPS）
実世界でIoT機器のセンサなどからビッグデータを収集し、それをサイバー空間でAIを使ってデータを分析して、解析結果を実世界にフィードバックすることで付加価値を創造する仕組み
・デジタルツイン
IoTなどを活用して実世界の情報をサイバー空間に送り、サイバー空間に実世界の環境を再現すること
aws s3

```
# variable.py
buckets_info = [
    {
        "name": "my-s3-bucket-1",
        "lifecycle_rules": [
            {
                "id": "expire_objects",
                "enabled": True,
                "expiration_days": 8,
            }
        ],
    },
    {
        "name": "my-s3-bucket-2",
        "lifecycle_rules": [
            {
                "id": "expire_objects",
                "enabled": True,
                "expiration_days": 8,
            }
        ],
    },
    # 添加更多桶的配置...
]
```
```
# s3_module.py
from cdktf import App, TerraformStack
from constructs import Construct
from imports.aws import AwsProvider, s3
import variable

class MyS3Buckets(TerraformStack):
    def __init__(self, scope: Construct, ns: str):
        super().__init__(scope, ns)
        
        AwsProvider(self, "AWS", region="us-east-1")
        
        # 根据 variable.py 中定义的信息创建多个 S3 桶
        for bucket_info in variable.buckets_info:
            s3.Bucket(self,
                      bucket_info["name"],
                      bucket=bucket_info["name"],
                      lifecycle_rule=bucket_info["lifecycle_rules"],
                      versioning=[s3.BucketVersioningArgs(
                          enabled=False
                      )])

app = App()
MyS3Buckets(app, "my-s3-buckets")
app.synth()
```
ゲームプログラマとして働き始めたくらいのレベルの人に届けたい、こういう感じのコードとコメントを書いてほしいというメモ書き

# 前提
+ ゲームのプログラミング向け。業務システムとかに向けた話じゃないです。
+ 筆者はゲームプログラマ。主にC++を想定
+ ベテランというほど長くプログラマをやっているわけではない。30代前半
    + 内容についてのツッコミなど歓迎。というかもっと整理されたいい記事を書いてくれる人がいたらうれしい
+ その現場のルールとかが優先
+ Doxygenとか使ってるならちゃんとそれに合わせる
    + ここではとりあえず本質的じゃなさそうな記法については飛ばす。「どんな環境でもなりたちそう」なところを優先して書く
+ コメントの位置とか改行フォーマットとかも現場次第なところがある
+ AIによる支援を受けながらコーディングを行う時代には未対応

# サンプル

```
/**
このファイターの視点から、指定した時間が経過した後の相手との距離を予測する
other 距離を予測したい相手
second 予測したい時間（秒）
返り値は予測した距離(m)
*/
float NankaFighter::PredictDistance( const NankaFighter* other, float second )const
{
    if( other == nullptr ){
        assert(false);
        return 0.0f;
    }
    if( second < 0.0f ){
        assert(false)
        second = 0.0f;
    }
    float resultDistance = 0.0f;
    if( IsDefeated() ){//倒されている場合
        resultDistance = PredictDistanceWhileDefeated( other, second );
    }
    else if( IsSleeping() ){//寝てる場合
        resultDistance = PredictDistanceWhileSleaping( other, second );
    }
    else {//通常の処理
        resultDistance = PredictDistanceStandard( other, second );
    }
    //距離が負の値になるのはおかしい
    if ( resultDistance < 0.0f ){
        assert(false);
        resultDistance = 0.0f;
    }
    return resultDistance;
}
```

# 色々とポイント補足
+ 関数のコメントは、「何を入れて」「何を返すのか」は関数名とかでわかると思っても書いておいた方がいい
    + 必要なさそうでも書くクセをつけておいた方がいい
    + intやfloatのようなプリミティブ型を使う場合、単位などにも気を付けた方がいい
    + 例えばこのサンプルの場合、変数名に second ではなく time を使ってしまうと単位が秒なのかミリ秒なのかフレーム数なのかと混乱を起こす
+ 関数名は、昔はある程度短い方がいいと言われていましたが、今はIDEが優秀なのとPCディスプレイもコードの規模も大きい時代なので長くしてわかりやすくした方がいいはず
+ スマートポインタを使えるなら使っておいた方がいいはずだけど、ここでは余分な情報を減らすため使わない
    + めちゃくちゃ大量にループを回す場合にはオーバーヘッドが無視できないことがあり、使わないことはたぶんある
+ constメンバ関数。つまり、副作用が無い関数
    + 可能な限り関数は副作用が無い方がいい
    + 逆に副作用がある関数は、できるだけ副作用を起こす以外の処理が無い方がいい
        + どんな副作用を起こすか決める関数と、実際に副作用を起こす関数を別にする……とか
+ 最初のif文2つ（ガード節）
    + うっかりミスを回避
    + もしうっかりミスが発生しても、ゲームの場合はクラッシュすることだけを回避して「それなり」の動作をしてもらった方がいい場合が多い
+ 次のif文とif else
    + 状況によってそもそも行うべき処理が違う場合、各if文の中で処理を書くのではなくそもそも別の関数を呼び出すべき
    + パターンとしては「処理A・処理B・通常処理」か「処理A・処理B・例外処理」のどちらかの並びになることが多いはず
    + 後からパターンを増やすときに、他のパターンと並列（同じネストの深さ）で増やせるように
+ 最後のif文
    + 結果がおかしくないかチェック
    + ここではとりあえず0未満の時だけチェックしているが、別のバリデーション関数にした方がいいかも
    + 最初のガード節でもそうだが、問題のある値になった場合に0ではなく「非常に大きい値」を返した方がいいかもしれない
        + そこはそのゲームの仕様次第
+ コメントはガンガン書いておくと、後から検索したりして探しやすい。
    + 「コメントのつけすぎ」に警戒する人がたまにいますが、コメントをつけすぎる人を見たことはありません。コメントが全然足りない人は山ほど見たことあります。つけすぎて困ることより足りなくて困ることの方が圧倒的に多いです。
    
# 悪い例
```
    float param;//パラメータ
```
理由
+ 変数は全て何らかのパラメータです。「何のパラメータなのか」を変数名とコメントに書かなければいけません。
『GitLabに学ぶ 世界最先端のリモート組織のつくりかた』を読んで

## この記事は
[『GitLabに学ぶ 世界最先端のリモート組織のつくりかた ドキュメントの活用でオフィスなしでも最大の成果を出すグローバル企業のしくみ』](https://www.amazon.co.jp/GitLab%E3%81%AB%E5%AD%A6%E3%81%B6-%E4%B8%96%E7%95%8C%E6%9C%80%E5%85%88%E7%AB%AF%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E7%B5%84%E7%B9%94%E3%81%AE%E3%81%A4%E3%81%8F%E3%82%8A%E3%81%8B%E3%81%9F-%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AE%E6%B4%BB%E7%94%A8%E3%81%A7%E3%82%AA%E3%83%95%E3%82%A3%E3%82%B9%E3%81%AA%E3%81%97%E3%81%A7%E3%82%82%E6%9C%80%E5%A4%A7%E3%81%AE%E6%88%90%E6%9E%9C%E3%82%92%E5%87%BA%E3%81%99%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E4%BC%81%E6%A5%AD%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF-%E5%8D%83%E7%94%B0-%E5%92%8C%E5%A4%AE/dp/4798179426)を読んで特に考えることの多かった部分、「GitLab Value」についての簡単なメモ・まとめになります。この記事をきっかけに少しでも興味のでた方はぜひ本を読んでみてください。

## 本の簡単な紹介
1400人の従業員全員がリモートワークで働くGitLab社の組織運営ノウハウを、同社が公開している「GitLab Handbook」をベースに解説した書籍です。オフィスを持たない完全リモート企業として成功を収めているGitLab社の強みは、徹底したドキュメント化にあります。本書では、同社のドキュメント作成・活用方法を詳細に紹介し、リモートワーク環境における課題解決や、高い成果を出すための組織づくりのヒントが紹介されています。
　組織にリモートワークの導入を検討している、導入しているが問題を抱えている、再びオフィス中心に戻ろうと検討しているなど、リモートワークに関わる如何なる状況であっても一読の価値のある内容となっていました。

目次
- 第1部　リモート組織のメリットを読み解く
    - 第1章　世界最大のリモート組織「GitLab」
    - 第2章　リモート組織によって得られるメリット
- 第2部　世界最先端のリモート組織へ移行するためのプロセス
    - 第3章　リモート組織を構築するためのプロセス
    - 第4章　リモートワークで発生する問題と対策
- 第3部　GitLabが実践するリモート組織を活性化させるカルチャー醸成法
    - 第5章　カルチャーはバリューによって醸成される
    - 第6章　コミュニケーションのルール
- 第4部　GitLabが成果を出すために実践している人事制度や業務ルール
    - 第9章　個人のパフォーマンスを引き出す
    - 第10章　GitLab Valueに基づいた人事制度
    - 第11章　マネージャーの役割とマネジメントを支援するためのしくみ
    - 第12章　コンディショニングを実現する
    - 第13章L＆Dを活用してパフォーマンスとエンゲージメントを向上させる

## 「GitLab Value」で印象に残ったこと
### 「GitLab Value」
- 成果
- イテレーション
- 透明性
- コラボレーション
- ダイバーシティ＆インクルージョン、ビロンギング
- 効率性
### カルチャーマッチではなくバリューマッチが重要
- これまでの採用では社風にあっているかどうかというカルチャーマッチを重視する企業が大半だった
- グローバル企業の採用トレンドはカルチャーマッチではなくカルチャーアドという観点を重視する
- カルチャーアドはカルチャー自体をよく成長させることができるかどうかという人材かどうかという観点
- カルチャーは環境に適応させ続けていくために調整しつづけていく必要がある
- カルチャー = バリューを体現した結果の暗黙のパターン
- カルチャーアド ≒ バリューマッチ
### バリューに優先順位をつける
- GibLab Valueには優先順位となるヒエラルキーがある
- ユーザー同士で異なるValueを優先して衝突する際の解決策として使用する
- ただしいかなる場合でも優先されるわけではない

## 以下、「GitLab Value」 の項目ごとにメモしたところ
### コラボレーション(Collaboration)
- コラボレーションのメカニズムを理解して具体的な行動に落とし込んでいく
- 集団で作業する際にプラスとなる「プロセスゲイン」もあればマイナスとなる「プロセスロス」もある
- プロセスロスとしては、生産性が人数の増加に伴って低下する「リンゲルマン効果」などがある
- 仕事を基準として話す
- 責任ではなく問題に集中する
- コラボレーションはコンセンサスではない
### 成果(Results)
- 顧客の成果に貢献する
- ドッグフィーディング
- 約束を書き留める
- 同意しない、コミットする、同意しない
- 障害を取り除くためにマネージャーを動かす
- セルフサービスとセルフラーニング
- 周知は短く
### イテレーション(Iteration)
- MVC(最小限の実行可能な変更)を目指す
- まとめてしまいたい欲求に抵抗する
- 提案を変更することはイテレーションではない
- イテレーションではない12のこと

## ちょっと詳しく
### 仕事を基準として話す
- 人格についてではなく、具体的な仕事内容について提案する
- たとえば「あなたは私の意見を聞かない」ではなく「フィードバックに対するリアクションがなかった」と置き換える
- フィードバックする際はパフォーマンスの向上を目的としているとまず伝える
### ドックフィーディング
- 開発している製品を自分たちも日常的に使う
- 早期のトラブル発見、改善の発見
- ユーザーの気持ちを理解していサービスを開発できる
### 同意しない、コミットする、同意しない
- 責任者とメンバーの双方が意見を述べる責任を果たした上で、責任者が決定したことであれば賛否を問わずにコミットし、全力で支援する
- すべてのメンバーが意見を述べる機会をつくる、フィードバック（意見を述べること）はすべての人が成長し、学ぶ機会になる
- 意見の対立が人間関係を崩さないように感情が交差する難しい対話に対するトレーニングを提供している

## さいごに
「GitLab Value」に関する内容は、今所属している会社のミッションバリューに置き換えたり、ここは足りない部分があるかもしれないなど考えながら読み進めて、学びが多かったと感じました。所属している組織のメンバーで読み合わせてみて、自分たちの組織に取り入れたり改善するところがないか話し合うと面白そうだと感じました。
Salesforce認定アドミニストレーター過去問+時々解説　Q141 ~ Q150

## Q141. ユーザーが商談をキャンペーンに関連づけることができる2つの方法は？

A 商談の主要なキャンペーンソースを選択
B 商談のキャンペーン影響関連リストを使用
C 商談でキャンペーン階層関連リストを使用

<details><summary>解答</summary>
A, B
</details>

## Q142. 管理者が組織を強化するためにAppExchangeで見つけることができる2つのソリューションは？

A コンサルタント
B コンポーネント
C コミュニティ
D お客様

<details><summary>解答</summary>
B, C

コンサルタントやお客様といった人間をAppExchangeで追加することはできないので, 試験対策としては, 残った2つを選択するという感じでいいかも.
</details>

## Q143. 管理者は取引先レコードの[作成日]項目を編集できない. この問題が発生した原因は？

A ユーザーはこれに対する編集権限がない
B システム監視項目であるから既存のレコードに対しては読み取り専用である

<details><summary>解答</summary>
B

解説: [作成日]項目はレコードが作成された時のデフォルトのものであり, 編集できるものではない
</details>

## Q144. 潜在的な顧客が技術的な問い合わせのためにケースを送信できるようにしたいが, コールセンターを設定するためのリソースがなく, 別の手段でサポートを利用できるようにしたい. どの2つのオプションを検討する？

A Webサイトに追加するWeb-to-CaseHTMLコードを生成します
B Email-to-Caseの指定されたルーティングアドレスへのリンクの追加
C 知識を備えたLightningパートナーコミュニティを実装する
D ソリューションの自動応答ルールへのリンクを追加する

<details><summary>解答</summary>
A, B
</details>

## Q145. ダッシュボードに不正確なデータが表示されているが, これはソースレポートの変更によるものだった. ソースレポートの整合性を維持するために管理者が実行する必要がある2つのアクションは？

A ダッシュボードをユーザーのプライベートフォルダーに移動
B ビューアクセス権を持つ新しいレポートフォルダを作成
C ダッシュボードレポートを表示専用フォルダーに移動

<details><summary>解答</summary>
B, C

解説: アクセスを制限し, 表示専用にすることで整合性を保てる.
</details>

## Q146. A社では, 販売コンソールとサービスコンソールで取引先を表示するときに異なるLightningページを表示する必要があります. 管理者はこの要件をどのように満たす必要がありますか？

A ページレイアウトの割り当てを更新します
B Lightningページをアプリケーションのデフォルトとして割り当てます
C 複数のレコードタイプを定義します
D さまざまなユーザープロファイルを作成します

<details><summary>解答</summary>
B

このサイトが解説までしてくれている
https://adminfight.com/administrator-passexam-q57/
</details>

## Q147. レコードタイプを作成する前にビジネスプロセスを作成する必要があるのはどのオブジェクト？

A 商談
B リード
C ケース
D キャンペーン
E ソリューション

<details><summary>解答</summary>
A, B, C, E

セールスプロセス=商談, リードプロセス=リード, サポートプロセス=ケースがそれぞれ該当し, Classic環境に切り替えるとソリューションプロセスもある.
</details>

## Q148. ワークフロー項目の更新を使用している. この機能で完了できる2つのアクションは？

A レコードのレコードタイプを変更します。
B 子オブジェクトの項目値を更新します。
C 項目更新で数式項目を選択します。
D 項目に特定の値を適用します。

<details><summary>解答</summary>
A, D
</details>

## Q149. 機能ライセンスをユーザーレコードに割り当てたい. この状況で割り当てることができる2つの機能ライセンスは？

A ナレッジユーザー
B Service Cloudユーザー
C 商談ユーザー
D コンソールユーザー

<details><summary>解答</summary>
A, B
</details>

## Q150. ケース用のWebフォームがある. ケース割り当てルールが非アクティブの場合, ケースの作成時に誰に所有権が割り当てられるか？

A ケースはデフォルトのワークフローユーザーに割り当てられます。
B デフォルトのケース所有者が割り当てられます。
C ケースはデフォルトのケースキューに割り当てられます。
D システム管理者が割り当てられます。

<details><summary>解答</summary>
C
</details>
Windows API で Windows のバージョンを取得する

Windows のバージョンを取得するための API として `GetVersion`, `GetVersionEx` が用意されていますが、Windows 8.1 以降実質的に使えなくなっています。バージョンに依存した処理を書かないようにというマイクロソフトのメッセージだと思いますが、それでもチェックしたい場面もあると思います。

[いくつか方法](https://stackoverflow.com/questions/47581146/getting-os-build-version-from-win32-api-c)はありますが、ここでは一番単純と思われる [RtlGetVersion](https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion) を使って取得します。

```c++
#include <stdio.h>
#include <Windows.h>

void GetWindowsVersion(DWORD* majorVersion, DWORD* minorVersion, DWORD* buildNumber) {
    DWORD major = 0;
    DWORD minor = 0;
    DWORD build = 0;
    auto ntdll = LoadLibraryExW(L"ntdll.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    if (ntdll != nullptr) {
        using RtlGetVersion = NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW lpVersionInformation);
        auto rtlGetVersion = reinterpret_cast<RtlGetVersion>(GetProcAddress(ntdll, "RtlGetVersion"));
        if (rtlGetVersion != nullptr) {
            RTL_OSVERSIONINFOW versionInfo{};
            versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
            rtlGetVersion(&versionInfo);
            major = versionInfo.dwMajorVersion;
            minor = versionInfo.dwMinorVersion;
            build = versionInfo.dwBuildNumber;
        }
        FreeLibrary(ntdll);
    }
    if (majorVersion != nullptr) *majorVersion = major;
    if (minorVersion != nullptr) *minorVersion = minor;
    if (buildNumber != nullptr) *buildNumber = build;
}

int main()
{
    DWORD majorVersion = 0;
    DWORD minorVersion = 0;
    DWORD buildNumber = 0;
    GetWindowsVersion(&majorVersion, &minorVersion, &buildNumber);
    printf("majorVersion:%d, minorVersion:%d, buildNumber:%d\n", majorVersion, minorVersion, buildNumber);
}
```
Excel-DNA で、log4net を利用する（C#で設定）

Excel-DNAで、log4netの設定を別ファイルにせず（うまくできなかった）、C#のコードで設定する方法を採用した。

```csharp
public static class SomeClass
{
    static SomeClass()
    {
        Logger.Setup();
    }
   public static void SomeMethod()
   {
        WriteLog.Write("log");
   }
}
```
`Logger.Setup()` は、アプリ全体で、1度だけ実行すれば良いはず。

```csharp
/// <summary>
/// ログを記録
/// </summary>
/// <see href="https://qiita.com/n-noguchi/items/5181fc9dc7929ddb7d13"/>
public static class WriteLog
{
    static ILog logger = LogManager.GetLogger(typeof(WriteLog));

    public static void Write(string log)
    {
        logger.Info(log);
    }
}
```

### 設定例
```csharp
public class Logger
{
    public static void Setup()
    {
        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

        PatternLayout patternLayout = new PatternLayout();
        patternLayout.ConversionPattern = "%date [%thread] [%-5level] %logger - %message%n";
        patternLayout.ActivateOptions();

        RollingFileAppender roller = new RollingFileAppender();
        roller.AppendToFile = true;
        roller.DatePattern = "yyyyMMdd'.log'";
        roller.File = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HOGE\HOGE XL Add-In\Logs\Trace_");
        roller.Layout = patternLayout;
        roller.MaxSizeRollBackups = -1;
        roller.MaximumFileSize = "10MB";
        roller.RollingStyle = RollingFileAppender.RollingMode.Composite;
        roller.StaticLogFileName = false;
        roller.ActivateOptions();
        hierarchy.Root.AddAppender(roller);

        hierarchy.Root.Level = Level.Info;
        hierarchy.Configured = true;
    }
}
```
`roller.File`の指定で、`${APPDATA}`は機能しなかった。

### 参照
- [Using Log4Net in an Excel-DNA add-in](https://github.com/Excel-DNA/Samples/blob/master/UsingLog4Net/README.md)
- [.NET Core 3.1でLog4netを使う](https://qiita.com/n-noguchi/items/5181fc9dc7929ddb7d13)
- https://stackoverflow.com/a/19538654/
- https://stackoverflow.com/a/45232665/

### 環境
- .NET6
- ExcelDna 1.7
- log4net 2.0.17

### Note
ExcelDNAで作成したアドインでログを記録するのは、[ガンジス XL アドイン：インボイス用関数](https://ganges.pro/customer/blog/ganges-xl-addin-invoice/)で必要になったため。
拡張for文の使い方

for文を書く際に拡張for文を使うことが多いので、for文と拡張for文の違いや、拡張for文の利便性をまとめます。

目次
[1.for文とは](#1-for文とは)
[2.拡張for文とは](#2-拡張for文とは)

# 1. for文とは
まず、for文について説明します。
for文は以下の要素で成り立ちます。
・for文で使用する変数の宣言と初期化を行う初期化式
・繰り返し処理が実行される条件を記載する条件式
・ループ処理が終わるたびに実行される変化式
```java
for (初期化式; 条件式; 変化式;) {
    処理
}
```
サンプルに当てはめてみます。
iは0から始まり、numに1が足される処理が10回実行されます。
```java
int num = 0;

for (int i = 0; i <10; i++;) {
    num += 1;
}
```
# 2. 拡張for文とは
次に、拡張for文について説明します。
拡張for文は、配列やArrayListなどのコレクションの要素に対して順番に処理を行うことができます。
()内には以下の要素を記載します。
・for文で使用する変数の型
・for文で使用する変数名
・処理を実行したい配列名またはコレクション名
```java
for (型 変数名 : 配列名またはコレクション名) {
    処理
}
```
サンプルに当てはめてみます。
int型のscoresという配列の要素をfor文でループし、処理するたびにnumに1を代入しています。
```java
int num = 0;
int[] scores = {60, 85, 74, 97, 100};

for (int test : scores) {
    num += 1;
}
```
この例は、通常のfor文でも表現することができます。
scoresの配列の数だけループするので同じ処理を実行できます。
ただし、このように比べると配列やコレクションの要素に対して処理を実行する場合は、拡張for文の方が可読性が高いことが分かります。
```java
int num = 0;
int[] scores = {60, 85, 74, 97, 100};

for (int i = 0; i < scores.length; i++) {
    num += 1;
}
```

# 3. おわりに
同じ処理をさせたい場合でもコードの書き方は一通りではないことや、多様な書き方ができる中でも可読性を重視して推奨される表現があることを学びました。

その時々に応じて、最適な表現を選べるように勉強を続けていきたいと思います。
【初心者】link_toの使い方【Rails】

# 初めましてlink_toと申します
私はrailsのview作成時、他のページに飛ばすため、使う目的のメソッドです。
ここ押したらサイト飛べるようにしたいな・・・
そういう気持ちから私は生まれました。
## 私はこういう風に使います。
```ruby
<%= link_to 'untyoko', Prefix　or　URL %>
```
こちらでuntyokoをひとつまみしていただきますと、
リンクに飛ぶシステムとなっております。

###### ※もちろんuntyokoでなくても結構です。

PrefixorURLに関しましてはお好みのどちらかをご入力ください。

ちなみにPrefixはルーティングエラーを出した時のHelperと書いてるものとなっております。
下のスクショで言うdashboads_pathとかproducts_pathとかですね。
rails内でページの移動をするときは、基本URLではなくPrefixで書くのが嗜みとなっております。

![スクリーンショット 2024-03-31 20.02.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665939/3798be4d-55b0-e0eb-0b67-010105da3850.png)

でもこちらのuntyoko、水色文字untyokoとなっており、少し恥ずかしいです。


```ruby
<%= link_to Prefix　orURL do %>
  <%= button_tag 'untyoko' %>
<% end %>
```

そんな時はこういう風にuntyokoにbutton_tagを着せてあげて私を用いていただけますと、また違った趣向となります。

こちらでも用途は変わらずuntokoをひとつまみしていただけますと、指定したページに飛べるような仕様となっております。


ちょっと出先のuntyokoであればこちらでも十分かもしれません。
しかし今日はお食事会untyoko、そういう日はbootstrapを用いたこんな形

```ruby
<%= link_to Prefix　orURL do %>
  <%= button_tag 'untyoko', class: 'btn btn-light' %>
<% end %>
```
untyokoにbutton_tagを着せてbootstrapのclassを装飾してただけますと、
untyokoも陽気になってしまう事でしょう。
classはいろいろございますので「bootstrap　ボタン」とかで調べてuntyokoを着せ替えしていただければ、
皆様もtyokoり手となりうるでしょう。
こういうtyokoり方もありますというご意見ございましたら、
私にご共有いただけましたら幸いです。ご清覧ありがとうございました。

追記
```ruby
<%= link_to 'untyoko',Prefix　orURL, class: 'btn btn-light' %>
```
bootstrapのボタンはこの形式でも書けるようです。
PostgreSQLのjsonとjsonbの違いを実際に検証してみた

## 背景
PostgreSQLのjsonb型に初めて触ったので、[公式](https://www.postgresql.jp/docs/11/datatype-json.html) に書いてあること実際に検証してみようと思いました。今回確認するのは、順番の違いです。(8.14.1. JSONの入出力構文)

```
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
                      json                       
-------------------------------------------------
 {"bar": "baz", "balance": 7.77, "active":false}
(1 row)

SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
                      jsonb                       
--------------------------------------------------
 {"bar": "baz", "active": false, "balance": 7.77}
(1 row)
```

## 手順

### テーブル作成
```
CREATE TABLE json_vs_jsonb (
    id serial PRIMARY KEY,
    data_json json,
    data_jsonb jsonb
);
```

### データ挿入
```
INSERT INTO json_vs_jsonb (data_json, data_jsonb) VALUES
('{"bar": "baz", "balance": 7.77, "active":false}'::json, '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb);

```

### データの選択と比較
data_jsonは挿入したデータの順番と同じだが、data_jsonbでは、挿入したデータの順番と異なることが確認できた！
```
SELECT data_json FROM json_vs_jsonb WHERE id = 1;
                    data_json                    
-------------------------------------------------
 {"bar": "baz", "balance": 7.77, "active":false}
(1 row)

postgres=# SELECT data_jsonb FROM json_vs_jsonb WHERE id = 1;
                    data_jsonb                    
--------------------------------------------------
 {"bar": "baz", "active": false, "balance": 7.77}
(1 row)
```

## まとめ
jsonb型を使うにあたり、[公式](https://www.postgresql.jp/docs/11/datatype-json.html)を読みました。json型よりjsonb型を使うことが推奨されていたこと知りませんでした。今回json型では挿入したデータの順番が保持されるのに対し、jsonb型では順番が保持されないこと確認できました。

## 参考
https://www.postgresql.jp/docs/11/datatype-json.html
GuardDutyでTrojan:EC2/DGADomainRequest.Bを検知した件

# はじめに
GuardDutyでTrojan:EC2/DGADomainRequest.Bを検知し、その調査を行いました。

![スクリーンショット 2024-03-30 000945.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669193/51ff0e3e-18e5-933c-a5ee-09590b69fa84.png)

DGADomainRequest.Bは、ドメイン生成アルゴリズム (DGA) で生成されたと思われるドメインへのアクセスを試み、DNSへクエリを行ったことを検知する仕組みです。

# 調査の実施
トロイの感染が疑われたため、GuardDuty以外にもセキュリティ対策として導入済みのアプリケーションでサーバのフルスキャンを実施し、トロイに感染していないことを即座に確認しました。
トロイに感染していないことが確認できましたが、Trojan:EC2/DGADomainRequest.Bが毎日のように検知されています。

情報を集める中で、SSHサーバが接続元IPアドレスの正逆一致の確認を行う場合があることを知り、確認しました。
対象のサーバはWindows Serverであり、SSHの利用のためにCygwinを使用している環境でしたが、そのようなログはありませんでした。
事例を調査すると、頻発しているものや数時間に1回のケースなどが見つかりましたが、
弊社で検知した際は、起動時に1回のみ検知する状態でした。基本的には起動時に即時発生するため、Cygwinを含めたアプリケーションはほとんど起動していませんでした。
もしトロイに感染していたとしてもこのタイミングでは動作できないでしょう。

同じ事象が複数の環境の複数のサーバで発生しています。
共通点は、ドメイン参加しているWindows Serverであることでしたが、
弊社で管理しているドメイン参加しているWindows Serverのすべてで発生しているわけではありませんでした。
該当サーバのEventlogを確認すると、定期的にActiveDirectoryサーバへの接続が失敗しているようでした。
サーバからDNSクエリを実行しても問題は発生していないようです。

弊社ではGuardDutyを導入したばかりで、導入当初から検知されていたため、何が原因で発生しているのか分からない状態でした。
調査が長引く中、環境の一つでActiveDirectoryサーバの更新を行っており、該当サーバのみDNSの設定を新しいActiveDirectoryサーバに設定変更していないことが判明しました。
通信ログを確認すると、ActiveDirectoryサーバへの通信ができず、2番目に登録したAWSのDNSとの通信が行われていることが確認できました。
ActiveDirectoryサーバへ向けた通信をAWSのDNSへ行うことで、この事象が発生していると推測しました。

# 原因
該当サーバでは、正常な状態でドメインを運用することができていないじょうたいでした。
ドメイン参加時にActiveDirectoryサーバをDNSサーバとして登録していますが、
該当環境では以下のいずれかでした。

１．DNSサーバを複数台設定する際に、1番目にActiveDirectory、2番目にAWSのDNSを指定
２．ネットワーク設定が初期化され、DNSサーバがDHCPで取得されたもの

１の環境の場合、前述したようにActiveDirectoryの指定が誤っているか、何かしらの問題で通信できない場合は、2番目側のDNSへ通信が行われます。
２の場合は、DHCPによって取得される設定であり、該当環境ではAWSのDNSでした。
本来はDNSを固定で設定されていた認識でしたが、設定が初期化されDHCPによる取得となっておりました。

実際に2の環境で必ずAWS側のDNSを利用する状態で、ユーザ認証や更新を行うと、Trojan:EC2/DGADomainRequest.Bを手動で発生させることができました。

上記から、ドメイン参加環境において、ActiveDirectoryサーバへの通信をAWSのDNSに行うと、この事象が発生する事が分かり、セキュリティリスクはないと判断しました。

またドメインに参加しているWindowsServerは起動時にActiveDirectoryに接続し、自分のホスト名やIPアドレスが
ActiveDirectoryに登録されているかの確認を行うようです。
起動時にほぼ必ず、検知するのはこの挙動が原因の様です。

セキュリティリスクはないが、ドメイン参加環境としてはこのメッセージが定期的に発生する状態だと、ドメイン上のユーザ認証ができない状態となっており、ドメイン参加サーバの動作として不安定と考えます。
弊社では、利用するActiveDirectoryが外部NW上にあるため、ActiveDirectoryと通信不可時に、
せめてDNSクエリだけでもAWS側のDNSを利用したいとこの構成にしていますが。
Trojan:EC2/DGADomainRequest.Bが頻繁に検知される場合は、
設定されたActiveDirectoryサーバのメンテナンスやDHCP OptionSetの利用など、設定の改善を行い、
正常動作するようにしていく必要はありますので、検知時は随時調査は必要と考えています。
ChatGPTにGASでスケジュールを追加してもらう

# はじめに
大学などで作業をしていると、ついついサボりがちになりがち...
これって自分以外にも結構いるのかなと思います。

自分は一日の最初にスケジュールをしっかりと決めて以下のアプリ使うことで、かなり作業効率やスピードが大きく向上しました。

https://apps.apple.com/jp/app/%E6%96%B0-%E3%82%B9%E3%83%9E%E3%83%9B%E3%82%92%E3%82%84%E3%82%81%E3%82%8C%E3%81%B0%E9%AD%9A%E3%81%8C%E8%82%B2%E3%81%A4/id1669133971

ただ、スケジュール決めるのがめんどい....
なのでその部分はChatGPTにやってもらおうと思います。


# 使っているGPT

できればスケジュール制作に特化したGPTsを使った方がいいです。理由としては、
- スケジュール制作を対話形式で作ることが可能
- 自動で休憩時間や、一日の作業を確認する時間などを組み込んでくれる
- 時間を漏らさずに作ってくれる


ふつうのChatGPTにやらせると、時間通りに作ってくれません。プロンプロがあるんでしょうが、めんどくさいのでGPTs使った方が楽です。

私の使っているやつ↓

https://chat.openai.com/g/g-Wcw86FIgY-schedule-architect

そして、Google App Scriptを作成してもらうにも別のGPTsを使っています。

https://chat.openai.com/g/g-2DQzU5UZl-code-copilot

ChatGPTにはGPTメンション機能がついており、こちらをメンションしてコード作成をしてもらっています。
（チャット上で[@]を入力すると、メンションすることができます）

# Google App Scriptの実行
作ってもらったコードをGASのスクリプトとして実行します。
GoogleDriveで「＋新規」→「その他」→「Google App Script」と選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/4660d33c-d273-5288-d84a-de7cbc94f5ef.png)


そうするとプロジェクト画面が開くのでそこにコピペしましょう。

この時にAPIを有効にしておきます。
（左側のパネルから、サービスという欄にCalendarを追加する。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/9c445f80-c88e-7ef1-6b28-f3c22849a86b.png)

# 実際の作成過程

ちょうど明日のスケジュールを作成していなかったので、それを作ろうと思います。
まずは時間指定しつつ、話しかけてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/d212fca6-eaaa-d184-735b-46d22e396e76.png)

具体的に伝えてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/7f52a65e-647e-f909-3c24-ee62faf9c4b2.png)

修正箇所を伝えます。
また、ChatGPTがうまくいかない場合、具体例を出すと精度が上がります。
（今回で言う「30分なら5分、60分なら10分、90分なら15分です。」としている部分です。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/b012f81b-7aef-c299-3fc5-9ffdbdcf6502.png)

最後、コード作成に特化したGPTへメンションを行います。
（同一チャット内で別のGPTを呼べる機能です。「@」を入力すると使えます。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/9ded6557-3832-028c-8b48-fba81b09be10.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/6c57ceb6-7fdb-954e-f347-6ad0d0c41728.png)

こちらをコピペして貼り付けます。
そして必ず **保存を押してから実行関数名を変更し** 実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/659b6a53-7951-7ee0-c580-3a55befedf34.png)

そうすると、以下のように自動でGoogleカレンダーに作業スケジュールが追加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/ad623762-8ef7-a3f7-f7fc-91b42501bf62.png)


# まとめ
今回はGoogle App ScriptとChatGPTを組み合わせた自動スケジュール作成からの登録方法をご紹介しました。
自分は仕事や作業に関してはスケジュールでしっかり決まっていた方が動きやすい人間（逆にそうじゃないとサボりがちになる）なので、この方法見つけてからは効率よく時間を使えている実感がありますね。

モチベーションに任せてしまうと、人間上手くいかない部分あるので、ChatGPTとかでこういうところを上手く仕組化して行けるといいなって思う次第です。
WindowsのFirewallが有効になってしまう件

# はじめに
弊社で運用しているWindowsインスタンスでは、稀にFirewallが有効になり、サービスが利用できなくなる事象が発生します。

原因を確認してみました。

## 前提
弊社ではセキュリティグループ・NACLでの制御を行っており、OS上のFirewallは設定せずに無効としています。そのため、Firewallが有効になってしまうと意図しない通信をブロックしてしまいます。作業ログなどから発生日の作業者に確認しても、Firewallの設定の操作は行っていないことが確認されています。

## 原因
確認すると以下の事象が発生していました。
以下が表記されます。（スクリーンショット参照）
![スクリーンショット 2024-03-31 022853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669193/afdd6b96-0586-d182-a530-7b9f059459f3.png)

結果として、「いいえ」を選択していました。

「いいえ」を選択すると、パブリックプロファイルのファイアウォールの状態が有効になります。有効化されたタイミングが、ユーザがログオンし操作を開始した時間とほぼ同じなので、これが原因と判断しました。


## 対処方法
この選択ダイアログですが、案内される設定を拒否することが多い「いいえ」を選択することで、Firewallが有効になるため、作業するメンバーへの周知は難しいです。そのため、設定で対応を行います。

### Case1
通常の設定で
「コントールパネル」＞「すべてのコントロールパネル」＞「管理ツール」
にて、セキュリティが強化されたWindows Defenderファイアウォールを開き、プロパティを確認します。すると、ファイアウォール状態は無効となっていることが分かります。

ローカルグループポリシーエディタを起動し、
「コンピュータの構成」＞「Windowsの設定」＞「セキュリティの設定」＞「セキュリティが強化されたWindows Defenderファイアウォール」＞「セキュリティが強化されたWindows Defenderファイアウォール - ローカルグループポリシーオブジェクト」を選択し、プロパティを確認します（スクリーンショット参照）。

![スクリーンショット 2024-03-31 025739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669193/a32358aa-ac39-5264-6c37-bc8359bb333a.png)

前述のコントロールパネルの設定では、「有効」と「無効」の選択肢がありますが、グループポリシーエディタからの場合には、「未構成」という選択肢が存在します。未構成とすると無効で動作しますが、今回の事象では有効化されてしまいます。したがって、未構成で設定されている場合でも、グループポリシーエディタ上で無効としてしまえば、有効化はされません。

### Case2
この選択ダイアログの表示を抑止することも可能です。ローカルグループポリシーエディタを起動し、
「コンピュータの構成」＞「Windowsの設定」＞「セキュリティの設定」＞「ネットワークリストマネージャーポリシー」を選択し、すべてのネットワークを開きます。その中でネットワークの場所を「ユーザは場所を変更できない」を選択することで抑止することが可能です（スクリーンショット参照）。
![スクリーンショット 2024-03-31 031411.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669193/1a9a4bf8-6f6a-fd2e-602b-5df354229e78.png)

# おわりに
Windowsでは、Network Location Awareness (NLA) というサービスが動作することで、現在接続されている種類を自動判別しているようです。以下の状況で選択ダイアログが表示される場合があるようです。
・OS 起動後、ユーザーがログオンした
・異なるネットワークに接続した
・LAN ケーブルの切断と接続、または、無線接続の切断と接続を行った
・NIC を無効から有効の状態に変更した
・NLA サービスを再起動した
・端末が認証を必要とするホット スポットなどのネットワーク環境に移動された
・端末のルーティング構成が変更された
の様ですが、弊社で見かけるのは圧倒的にOSが起動後、ユーザがログオンした時が多いです。

弊社では、圧倒的にOSが起動後、ユーザがログオンした時にこの現象が見られます。

意図せずWindowsのFirewallが有効になる場合は、確認してみてください。