OmniAICreator/Qiita-1.07M huggingface dataset:
【パルワールド】パル7000体捕獲すると起きるクラッシュ問題を解決してみる

Steam版 patch v0.1.4.0 にて修正されたようです！
以下の記事は備忘録として置いておきます！

## 概要
パルワールドで現在ギルドで7000体捕獲するとクラッシュするというバグがあります。
バグの詳細については参考記事より。

症状としては
・拠点名が「NoNameGuild」になる
・拠点がマップから表示されなくなり、ファストトラベルが不可能になる
・無限ローディングで接続出来ない

などがあります。
今のところ解決方法としてはギルドを解体ぐらいしかないみたいです。

## 具体的な方法
※今から記載する方法は全て自己責任でお願いします。
※必ずセーブデータのバックアップを取って作業を行ってください。

前提としてこの症状が起きた後のセーブデータから修復を試みます。
（データが破損しているのか確認のため）

有志作成のセーブデータ変換ツールによりセーブデータを変換
おそらくギルド情報は個人のデータではなくサーバー側だと思ったのでとりあえず

Saved/SaveGames/0/長いID/Level.sav

をjsonに変換

かなり大きいサイズ（うちのサーバーでは1.7Gほどでした）のjsonファイルが作成されるのでvscodeで展開
環境によっては右下の言語モードを素早くプレーンテキスト変えないと大量のテキストにjson用の変換を行おうとしてフリーズします。

ギルド名で検索するとおそらくギルド情報と思われるかたまりが1件ヒット
※ギルド名が日本語の場合はUnicodeエスケープシーケンス変換してから検索してください。参考サイトに変換サイト張ってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3687309/2e05dfa7-bd21-033c-1fe3-2298a5267093.png)
※一部マスクしてます

ちょうどこの少し上に大量のguidとinstance_idが書かれている配列がありました
上までさかのぼるとindividual_character_handle_idsというパラメーターらしいです。
このパラメーターの行数が29000行ほど
配列1個で4行使ってるから29000 / 4 = 約7000
という事で問題なのこれじゃない？と思いとりあえず削除してみる

※この状態にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3687309/a76ca654-05ea-a6b0-e12f-014d2d05c112.png)

削除後jsonファイルを元のLevel.savに変換
サーバーにLevel.savをアップロードして起動

あ、マップに拠点出るようになった。
という事でおそらく直ったみたいなのでしばらく様子見てみます。

## その後
副作用として下記のような現象が起きました。
##### 解決済
・拠点のパルが持ち上げられない
おそらくギルドのパルのログを削除したので自分のギルドのパルだと認識出来ていないみたい？
一度該当のパルを手持ちに入れてドロップ、再取得する事で直りました。
ギルド単位なので誰か一人が行えば他のメンバーは問題ないです。

##### 調査中
・プレイヤーが拠点内の鉱石へ攻撃してもダメージが発生しない
・マウス押しっぱなしで連続近接攻撃ができない
・グラップリングフックや銃器の挙動がおかしい
いずれもギルド脱退→再加入を行えば直るみたいです。

コメントで教えていただいた方々ありがとうございます！

## 参考サイト様
##### 【パルワールド】捕獲するとクラッシュするバグの対処方法 (+その他のバグ対処方)
https://yokkaichinonikki.blog.fc2.com/blog-entry-181.html

##### 有志作成のセーブデータ変換ツール
https://github.com/cheahjs/palworld-save-tools?tab=readme-ov-file

##### Unicodeエスケープシーケンス変換ツール
https://tech-unlimited.com/escape-unicode.html

## 変更履歴
2023/01/30 ギルド名が日本語の場合の対応を記載
2023/01/30 その後の経過と対応策を追記
【Rails】carrierwaveでローカルに保存したファイルをアクションを経由して取得する

## はじめに
carrierwaveでpdfファイルを投稿し、そのファイルをクリックするとファイルを開く機能があります。
今回は、ファイルをローカル上のpublicディレクトリに保存しているためurl直打ちでファイル表示がされる対策のために、保存先をpublicディレクトリから変更し、ファイルのパスから直接取得するのではなくアクション経由で取得する方法に変更してurl直打ちで表示するのを防ぐ対応をしました。
carrierwaveでのファイルの投稿機能などについては今回のテーマの趣旨とは違うため省略します。

## 環境
`ruby 3.1.2p20`
`Rails 7.0.4`

## テーブル
| Posts | 
|:-----------|
| name       |
| file       |

## コントローラー
~~~ruby:app/controllers/posts_controller.rb
def show_file
  file_path = Rails.root.join('uploads', 'post', 'file', params[:id], "#{params[:file_identifier]}.pdf") # ローカルに保存されているファイルのパス。保存先に合わせて変更する。

  if File.exist?(file_path) # ファイルがある場合
    send_data File.read(file_path), type: Mime::Type.lookup_by_extension(File.extname(file_path).delete('.')).to_s, disposition: 'inline' # send_dataでファイルを表示します。
  else # ない場合
    render plain: 'ファイルが見つかりません', status: 404
  end
end
~~~

## ルーティング
~~~ruby:config/routes.rb
resources :posts do
  member do
    get 'show_file/:file_identifier', to: 'posts#show_file', as: :show_file # urlに:file_identifierを含めることでposts#show_fileでファイル名を取得できるようにします。
  end
end
~~~

## view
~~~ruby:post.html.erb
# :file_identifierのパラメータに@post.file.identifierを渡すことでリンク先のposts#show_fileで:file_identifierを扱えるようにします。
<td><%= link_to @post.file, show_file_path(file_identifier: @post.file.identifier) %> </td>
~~~

## 最後に
これでリンクをクリックするとファイルが画面に表示されます。
アクションを経由して表示するため、ログインチェックやユーザーチェックなども実装できるようになりました。
本来はファイルはS3などにアップロードするのが一般的かもしれませんが、ローカルにファイルをおく場合はこのように実装していくのがいいのかなと思いました。
他にもっと良い実装方法はいくらでもあるとは思いますが、ひとまずこれで形にはなるかと思います。
この投稿に不手際や実装のアドバイスがありましたら、コメントいただけますと幸いです。
TypeScriptでメソッドチェーンを使って与えた文字列や数値を次々に変換する方法

こちらの記事のコードを少し変えて、ジェネリクス型を使って汎用的に[値を変換する関数]を引数にとるメソッドを用いてメソッドチェーンを実現する方法を考えました

https://qiita.com/takahasinaoki/items/f0106aab067a1bb20124

```typescript
class Manipulator<T> {
  public value: T;
  
  constructor(input: T) {
    this.value = input;
  }

  changeValue(fn: (value: T) => T): this {
    this.value = fn(this.value);
    return this;
  }
}
```

実行例
```typescript
class Manipulator<T> {
  public value: T;
  
  constructor(input: T) {
    this.value = input;
  }

  changeValue(fn: (value: T) => T): this {
    this.value = fn(this.value);
    return this;
  }
}

// ひらがな変換
function kanaToHira(str: string): string
{
  return str.replace(/[\u30a1-\u30f6]/g, (s) =>
    String.fromCharCode(s.charCodeAt(0) - 0x60)
  );
}

// 使用例
const str = new Manipulator<string>("アイウabc")
  .changeValue(kanaToHira) //ひらがな変換
  .changeValue(str => str.toUpperCase()) //大文字変換
  .changeValue(str => str.split('').reverse().join('')) //文字列を逆順にする
  .value
console.log(str);  // "CBAういあ" 
```
【備忘録】terraform のimport ブロックを使ったSnowflake リソースのimport でつまづいた

初歩的すぎるミス。絶対に忘れないために書く。
# import ブロックについて
すでに存在するオブジェクトをterraform 管理するterraform importを、tfファイルに書ける。
terraform plan 時にimport を行なってくれる上、import後に消さなくてもいい。
#### import block 記述方法
```
import{
  id = "<リソースのid>"
  to = <リソースタイプ>.<リソース名>
}
```
# 発生したこと
snowflake_schema のリソースをimport してこよっかな〜とplanしたら、import idがおかしいという旨のエラーが出てきた。
(エラー文の控えをわすれてしまった・・・・)
# 原因
書いたimport ブロックがこれ。
```
import{
    id = "<スキーマ名>"
    to = snowflake_schema.<スキーマ名>
}
```
snowflake_schema の公式リファレンスの最下部にあるimport 例文がこれ。
```
# format is dbName | schemaName
terraform import snowflake_schema.example 'dbName|schemaName'
```
....
'dbName|schemaName' ...?
# やったこと
import ブロックの記述を修正。全然import できた。
```
import{
    id = "<DB名>|<スキーマ名>"
    to = snowflake_schema.<スキーマ名>
}
```
リファレンスを読もう！
AWS Security Hubについて書いてみた

## はじめに
おはこんばんにちは。キティちゃんです。最近仕事でもAWSに触れる機会が増えてきているので色々充実感を覚えています。今回はAWS Security Hubについて書いてみようと思います。

## きっかけ
参加したセミナーにて「AWS Security Hubは有効化しとけ」という話を聞いて、どんなものかと調べてみようと思ったためです。

## AWS Security Hubとは
AWSで設定されたセキュリティがベストプラクティスに沿って設定がされているかを自動でチェックしてくれるサービスです。

## 利用するメリット
大きく考えて2つあるのではないかなと思います。

1.直ぐに利用が可能

2.一元管理が可能

## 直ぐに利用が可能
AWS Security Hubは有効化にすることで、直ぐに利用が可能となり、AWSリソースがベストプラクティスに沿った設定になっているのかのチェックが行えます。

## 一元管理が可能
複数のサービス（AWS Config、Amazon GuardDuty etc...）からも検出結果を自動収集し、検出結果を一元管理することができるため、他のサービスにわざわざ見に行くという手間が省けます。

## セミナーで聞いた話
参加したセミナーでは、「AWS Security Hubは自動でベストプラクティスに沿った設定になっているかを自動検出してくれるからまず有効化してくれ、有効化推奨です」と強く導入することを薦めていました。確かに、数クリックでAWSリソースがセキュアな状態と言えるのか自動で検出してくれるわけなので、企業としても有難いことだよねって思います。

## 所感
本サービスに関しては、どのイベントに参加しても利用を推奨している印象です。ベストプラクティスに沿った設定をしているかどうかをほんの数クリックだけで判定してくれるわけなので使わない手はないと思います。特にAWSを触り始めたばかりの企業にとってはとてもありがたいサービスだと思います。

## まとめ
今回はAWS Security Hubについて書いてみました。数クリックするだけでベストプラクティスに沿った設定になっているのか自動で検出結果を表示してくれるのはとてもありがたいことだと思います。ベストプラクティスに沿った設定にすることで、AWSリソースをセキュアな状態にすることができます。なので、まずは導入してAWSリソースがセキュアなのか有効化してチェックしてみましょう。

## 参考
・『AWS Security Hub　AWS のセキュリティチェックの自動化とセキュリティアラートの一元化』
https://aws.amazon.com/jp/security-hub/

・『AWS Security Hub - セキュリティチェックの自動化、セキュリティアラートの一元管理』ソフトバンク社
https://www.softbank.jp/biz/blog/cloud-technology/articles/202210/aws-security-hub/
ここ最近で追っている技術をまとめてみた

どうもこんにちは、たくびー(@takubii)です。

今回は最近追っているWeb技術について書いていこうと思います。

# フロントエンド関連

去年はフロントエンドの技術の進歩がとても活発で様々なフレームワークが台頭してきました。
以下は私が気になったものです。

## [Next.js](https://nextjs.org/)

バージョンアップしApp Routerが導入され今までのルーティングとはガラリと使用感が変わりました。
また、Server Actionなどまだまだ目玉機能の進歩が控えているためこれからも眼が離せないフレームワークです。

## [Remix](https://remix.run/)

主にNext.jsと比較されがちなフレームワークです。
最初からSSRに比重を置いて設計されているのが特徴です。
Next.jsのバージョンアップにより安定感に懸念を持った方が移行している印象が多いです。
今後はSPAモードの追加などが検討されていて十分にWebフレームワークとしての地位を獲得できそうな勢いを持っています。

## [Svelte](https://svelte.dev/)/[SvelteKit](https://kit.svelte.dev/)

React系技術の対抗馬として着実な地位を獲得したと感じました。
なによりもバンドルサイズが小さいのでパフォーマンスを重視している場合には真っ先に候補に上がるようになったかもしれません。
もう少しシェアが伸びてきたら積極的に追っていくべきフレームワークになると思います。

## [Astro](https://astro.build/)

SSGのフレームワークとして急上昇してきたフレームワークです。
パフォーマンスが高く、コードの書き方もほぼHTMLなので使用するハードルが低いのが特徴です。
簡単なWebサイトや静的サイトの場合は候補に上がることになると思います。

## [htmx](https://htmx.org/)

最近注目されているフレームワークです。
HTMLを拡張したような書き方で動きのあるサイトも作れるようです。
Web界隈では注目されているので今後さらに伸びてくるのか楽しみなフレームワークです。

## [Solid.js](https://www.solidjs.com/)

Reactとほぼ同じ書き方ができるフレームワークですが、パフォーマンスはほぼVanilla　JSと同程度という魅力を持ったフレームワークです。
一時期は注目されていましたが、最近は他のフレームワークに押され気味な印象を受けます。
Solid.js内でグローバルステートの管理が可能など1つのフレームワークで完結しているところもあるので今後のアップデートに期待です。

# バックエンド関連

Node.jsのフレームワークはほぼExpressかNest.jsしか選択肢が無かったところに登場し瞬く間に注目を集めたので気になりました。

## [Hono](https://hono.dev/)

とにかくパフォーマンスが高いことを全面に出してアピールしているバックエンドのフレームワークです。
このフレームワークの作者は日本人で個人的にはそこも驚きました。
バックエンドは専門ではありませんが、Node.jsフレームワークに新しい対抗馬が誕生したので今後が楽しみです。

# スタイル関連

フロントエンドとスタイルは切っても切れない関係です。
CSSのみだとフロントエンドフレームワークと組み合わせた時にあまり恩恵を受けられませんがCSSフレームワークを使うことで開発効率が上がります。

## [Tailwind CSS](https://tailwindcss.com/)

最近はCSSフレームワークのディファクトスタンダードになりつつあると感じています。
Bootstrapよりも細かくスタイルの指定ができるのでより柔軟にデザインを作成することができます。
フロントエンドフレームワークと特に相性がいいのでTailwind CSSはこれから覚えても損はない技術だと思います。

## [shadcn/ui](https://ui.shadcn.com/)

Tailwind CSSをベースにしたUIコンポーネント集です。
Tailwind CSSのみだとデザインの作成にclassにそれなりのスタイル用のclass名を追加しなくてはなりませんが、shadcn/uiを使うとすでに出来上がったコンポーネントを使うことができます。
独自デザインなどで悩んでいる場合はUIフレームワークを使うことで既存のものを使えるので選択肢の一つとして良いと思います。

# その他

その他で気になった技術をこちらにあげます。

## [Biome](https://biomejs.dev/)

Linter、FormatterをまとめたものをRustで実装されています。
Rustで作成することで高速で一つのパッケージで全て行えるようになります。
まだ、対応言語やテストカバレッジなどは低いので実際に使えるかは人それぞれになりますが、成熟していけばBiomeで完結する日が来るかもしれません。

# 終わりに

去年はここ最近でも特にWeb技術の発展が著しかったかなと感じた一年になりました。
ここにあげた技術以外にもトレンドを追っていくべきものはまだまだあるかもしれません。
人それぞれ専門分野は違うと思いますが、幅広くインプットをすることでそれぞれの領域に適した実装を行えるようになりたいですね。

他にもこんな良い技術あるよという方は是非コメントで教えて頂けると嬉しいです。
また、間違いなどありましたら指摘なども大歓迎です。

それでは今回はこのあたりで締めたいと思います。
ここまで読んでいただきありがとうございます。
機会があればまたお会いしましょう。
npm installできないときの解決策①（元の環境に一致させる）

# 1. 問題
[他人のNode.jsプロジェクト](https://github.com/ZeroCho/nodejs-book/tree/2pan/ch16/16.5/nodebird)をgit cloneしてnpm installしてみたが、パッケージが一個もインストールされない。


# 2. 環境
node 18.17.1
npm 9.6.7
Windows 10

:::note warn
当時記録するのを忘れたので、上記のバージョンはnvm listを基に後で推測したものである。
:::


# 3. 解決
プロジェクトの元の環境に一致させてもう一度インストールしてみたら、殆どのPackageのインストールに成功した。

→[GitHub リンク](https://github.com/sarifor/nodejs-practice/commit/478aad28cd8f7bb075b309571c9e01ba3d1fe084)


# 4. 詳細
## 4.1 元の環境に一致させる手順
### 4.1.1 基本環境に合わせる
まず、元プロジェクトの基本環境に合わせる。
私が実行しようとしたプロジェクトは元々[Node.js基本書](https://www.yes24.com/Product/Goods/91213376)の付録ソースなので、
著者が本文に親切に記載してくれていた。
| 環境 | バージョン |
|:-|:-|
| node  | 14  |
| npm  | 6.14.4  |
| os  | Windows 10  |

### 4.1.2 各Packageのバージョンに合わせる
`Cache`を削除して、`npm ci`する。
```terminal
npm cache clean --force
npm ci
```

## 4.2 未解決
一部のPackageはまだインストールできない。
でもnpm installのエラーメッセージを見てもどこが問題なのか分からない。


# 5. 次の記事
- npm installのエラーメッセージが何を言っているかを知るには？
  →[npm installできないときの解決策②（ChatGPT）](https://qiita.com/Mihamakun/items/3ac5692fd317aaeb28e5)
- npm ciとは？
  →[npm install vs. npm ci]()（作成中）


# 6. まとめ
他人のNode.jsプロジェクトで`npm install`ができない場合、
プロジェクトの元の環境に徹底的に合わせたら大体解決。
①基本環境：`node`、`npm`、`OS`のバージョン
②各パッケージ：`npm ci`で各Packageのバージョンまで正確に統一。


# 7. 感じたこと
npm packageインストールできないとき、一応`node`のバージョンに原因があるのでは、と思っていいかも。


# 8. 参考	
[「何もしてないのに急にnpm installできなくなった」への立ち向かい方](https://qiita.com/piroor/items/eee2c8c10e42cbf92ddf)
[[Node.js] npm cache 解決](https://icerabbit.tistory.com/78)
Rubyを始めるにあたってyumのインストールで躓いた話

こんにちは！

最近は気温も寒く何かとやる気が出なくなりがちですが、技術は日々の積み重ねですので気合を入れなおして頑張っていきましょう！！

つい先日、Rubyで開発を行うことになり、初めてのRubyなのですが、セットアップからなにからバタバタしています(´;ω;｀)

## 最新のUbuntuではyum ではなくyum4が搭載されている！？！

普段私は個人開発含め、Ubuntu を用いて開発をしているのですが、Rubyを始めるにあたり以下のサイトを見ながら作業を進めていました。

https://www.ruby-lang.org/ja/documentation/

````
sudo yum install ruby
````

yum がないよというメッセージが出てきたので、yumをインストールするために以下のコマンドを打ちました。

````
sudo apt install yum
````
とコマンドを打ち込んだところ、どうもうまくいかなかったのです、、、。

いろんなサイトを確認し、対応策として以下のコマンドを打つといいとのことで以下のコマンドを打ち込みました。

````
sudo apt-get update
````

そのあとにもう一度インストールを試みましたが、依然として返ってきたメッセージは以下の内容でした。

````
install: missing destination file operand after 'yum'
Try 'install --help' for more information.
````

何とか解決策はないかとyumとだけ打ち込んで

````
Command 'yum' not found, did you mean:
  command 'gum' from snap gum (0.13.0)
  command 'uum' from deb freewnn-jserver (1.1.1~a021+cvs20130302-7build1)
  command 'num' from deb quickcal (2.4-1)
  command 'sum' from deb coreutils (8.32-4.1ubuntu1)
  command 'zum' from deb perforate (1.2-5.1)
  command 'yum4' from deb nextgen-yum4 (4.5.2-6)
See 'snap info <snapname>' for additional versions.
````

このエラーメッセージを読むと、yumは見つからないのでこの辺のどれかと間違えてません？みたいなニュアンスで返事してきたので、yum4だったら可能性が高いかもしれないと思い、以下のコマンドを打ち込んでみました。

````
sudo apt install yum4
````

すると、スルスルインストールが進んでいき、Y/nの選択が出てきてYを押してインストールが完了しました！！

おそらくUbuntu のバージョンの関係とかも含めて、yum4はあるが、yumはないよ～ってことなのかなと思います！！

参考程度に私の利用しているUbuntuのバージョンをここに載せておきます。

````
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
````

今回はここまでにします！！

ガンガンRubyの勉強を進めていくのでまた何かあったら投稿します！！
AWS Shieldについて書いてみた

## はじめに
おはこんばんにちは。キティちゃんです。最近は突然の頭痛に悩まされたりしています。今回はAWS Shieldについて書いてみようと思います。

## きっかけ
AWS Shieldはセキュリティ対策の一つとしてよく名前が挙げられるため書いておこうと思いました。

## AWS Shieldとは
マネージド型のDDoS保護サービスで、AWSで実行しているアプリケーションを保護することを目的としています。

## AWS WAFと何が違うの？
結論から言うと守備範囲、防御できる攻撃が異なるということです。AWS ShieldはAWSが提供しているDDoS攻撃対策サービスですが、AWS WAFはDDoS攻撃だけではなく、SQLインジェクションやクロスサイトスクリプティングといったアプリケーションへの攻撃に対しての防御が可能です。

## AWS Shield StandardとAWS Shield Advancedの違い
AWS ShieldにはStandardとAdvancedの2つのタイプがあります。この2つの違いは防御範囲が異なることです。Standardの場合、OSI参照モデルでいうところの第3層、第4層が保護対象となります。AdvancedはStandardの上位プランであり、Standardの保護対象にプラスして第7層も保護対象となります。一見AWS WAFと大きな違いがないように思われますが、AWS WAFの場合は第7層のみが保護対象であり、かつ、アプリケーションに対しての攻撃全般の防御が可能となります。

## AWS WAFとAWS Shieldのどちらを導入すべき？
よりセキュリティを強固するのであれば、どちらも導入することが望ましいと思います。上記でも述べましたが、それぞれ守備範囲、防御できる攻撃が異なります。AWS WAFだけを導入しても、第7層以外のレイヤーを守れません。AWS Shieldのみの場合、Advancedプランであったとして第3、4、7層は守備範囲ではありますが、防御できる攻撃はDDoS攻撃のみです。それぞれ一長一短であるため、どちらも導入することが推奨されると思います。

## 所感
AWS Shieldもプランによって、防御できる範囲を広げているとはいえ、サービス単体だけでベストなセキュリティ対策かと言われると微妙です。上記でも述べましたが、AWS WAFと併用してよりシステムの堅牢化を図ることが望ましいと思います。ですが、堅牢化するためには、それ相応の費用も発生してきます。セキュリティはどの企業にとっても重要事項ではありますが、予算の中でどこを優先的に防御するかを検討しなければいけませんね。

## まとめ
今回はAWS Shieldについて書いてみましたが、AWS ShieldはあくまでもDDoS攻撃に対しての保護サービスとなります。AWS WAFと両方を導入することが望ましいですが、企業によって懐事情というのもあると思います。ただ、セキュリティというのは強固であるべきです。正しく運用できない場合、情報漏洩といった最悪のケースが考えられますので何が最適なのかは見極める必要がありそうです。

## 参考
・『AWS Shield　マネージド DDoS 保護でアプリケーションの可用性と応答性を最大化する』
https://aws.amazon.com/jp/shield/

・『AWS WAFとAWS Shieldどちらを入れるべき？違いをわかりやすく解説！』
https://www.wafcharm.com/jp/blog/aws-waf-vs-aws-shield-for-beginners/#%25e3%2581%25be%25e3%2581%259a%25e7%25b5%2590%25e8%25ab%2596%25e3%2581%258b%25e3%2582%2589aws-waf%25e3%2581%25a8aws-shield%25e3%2581%25ae%25e9%2581%2595%25e3%2581%2584%25e3%2581%25a8%25e3%2581%25af
Amazon Inspectorについて書いてみる

## はじめに
おはこんばんにちは。キティちゃんです。最近はAWSの資格取得をしたりとAWSの学習に力を入れています。今日は久々に記事を書いていきたいと思います。

## きっかけ
Amazon Inspectorを触る機会があったので、学んだことについてまとめてみようと思いました。

## Amazon Inspectorって
EC2インスタンス、コンテナ、Lambda関数などに対してスキャンを行い、ソフトウェアの脆弱性や意図しないネットワークの露出がないかを管理する脆弱性管理サービスです。

## 利用するメリット
大きく考えて2つあるのではないかなと思います。

1.セキュリティチェックが自動でできる

2.脆弱性の早期発見に繋がる

## セキュリティチェックが自動でできる
まず、1についてセキュリティは非常に大事なポイントです。ですが、セキュリティ対策が施されておらず、脆弱性を悪用され情報が流出するといったことは悲しいことながら多々あります。しかしながら、セキュリティについて一つ一つチェックを行うということは時間もかかりますし、何より人的コストも掛かってきてしまいます。また、企業であればセキュリティ以外にも業務は多々あり、セキュリティだけに時間を割けないのも一つの課題です。そこで、Amazon Inspectorを利用することで、自動的にセキュリティチェックを行うことができます。自動的にセキュリティチェックができることで、検知された脆弱性に対してパッチ適用をすればよいので、一つ一つ調べる必要がなく、効率的になります。

## 脆弱性の早期発見に繋がる
Amazon Inspectorは継続的にセキュリティチェックが行えるため、脆弱性を早期で発見することができる可能性が高まります。常に新しい脆弱性は発見されますので、日頃からセキュリティチェックを行うことで、最新のセキュリティの問題が発見されたときに迅速に対応することで、セキュアな状態を保てます。常にセキュアな状態が保つことができれば情報漏洩に繋がる可能性を低減させることができます。

## 脆弱性診断とは違うのか
個人的には、同じなのかな思います。よく言われる脆弱性診断はアプリケーション診断、プラットフォーム診断といわれ、アプリケーションやネットワーク周り（サーバーなど）に対して、疑似的に攻撃を行い、セキュリティの問題がないかをツールや手動にて確認を行います。Amazon Inspectorの場合は、既存で発見されている問題に対して、パッチが最新であるかなどを自動でスキャンをしてくれますのである意味診断なのかなと。ですので、単に対象としているターゲットが違うだけなのかなと思います。

## 所感
Amazon Inspectorを使うことで、脆弱性がないかを調べることができるのは良さそうだなとは思います。ただ、Amazon Inspector単体ではセキュリティ対策は不十分だと思います。あくまで脆弱なパッケージがないかなど脆弱性を管理しているだけであって、防御対策をしているわけではありません。別のサービスで防御対策をする必要がありそうですね。

## まとめ
今回はAmazon Inspectorについて書いてみましたが、文章だけでは分かりにくいこともあると思います。AWS Black Beltの動画を視聴してみたり、無料期間を使って利用してみるのもいいかなと思います。私も無料で触れそうなら触ってみたいと思います。

## 参考
・『Amazon Inspector　大規模な自動化された継続的な脆弱性管理』
https://aws.amazon.com/jp/inspector/

・『Amazon Inspector 【AWS Black Belt】』
https://www.youtube.com/watch?v=QTqvtIIGDVg&ab_channel=AmazonWebServicesJapan%E5%85%AC%E5%BC%8F
HTMLにTypeScriptを書いてブラウザで直接実行できるって知ってた？

# 百聞は一見に如かず
空のHTMLファイルにコピペしてウェブブラウザで開いてみてください。

```html:ts.html
<!doctype html>
<meta charset="utf-8">

<script async type="module">
    import {transpile, ScriptTarget} from "https://esm.sh/typescript@5.6.3?target=esnext";
    import {minify} from "https://esm.sh/terser@5.36.0?target=esnext";

    // esnext-polyfill
    Uint8Array.prototype.toBase64 ??= function() {
        return btoa(Array.from(this, (v) => String.fromCharCode(v)).join(""));
    }

    for(const {type, textContent} of document.getElementsByTagName("script")) {
        if(type !== "text/typescript" || !textContent) {
            continue;
        }

        const js = transpile(textContent, {
            target: ScriptTarget.ESNext
        });

        const {code} = await minify(js, {
            module: true
        });

        await import(`data:text/javascript;base64,${new TextEncoder().encode(code).toBase64()}`);
    }
</script>

<script type="text/typescript">
    interface Test {
        a: string;
        b: number;
        c: boolean;
    }

    const test: Test = {
        a: "foo",
        b: 111,
        c: true
    };

    await new Promise<void>(done => setTimeout(done, 100));
    console.log(test);
    document.getElementById("status").textContent = "Complete!";
</script>

<title>TypeScript on Web</title>
<h1>TypeScript on Web</h1>
<p>TypeScript realtime transpile and execution demo.</p>
<p>[Status] <span id="status">Processing...</span></p>
```

# 何が起きている？
まず [esm.sh](https://esm.sh) はESMを配信するCDNです。
新進気鋭ということで高機能かつ使いやすく、旧来の [jsdelivr](https://www.jsdelivr.com) や [unpkg](https://www.unpkg.com) などの上位互換となり得そうです。

### 1. TypeScript記述
ウェブブラウザは読み込み時に `script` 要素の `type` 属性を見てJavaScriptかどうかを識別し、実行する仕様となっています。
(無い場合は暗黙的にJavaScriptと見なす)

この挙動を利用し、明示的にメディアタイプを指定することでTypeScriptを記述しつつ実行を阻止しています。

### 2. トランスパイル
[typescript](https://www.npmjs.com/package/typescript) をインポートしています。
これは本家本元のTypeScriptパッケージです。
`script` 要素のうち、メディアタイプがTypeScriptな要素のみを抽出しJavaScriptにトランスパイルします。

### 3. ソースコード圧縮
[terser](https://www.npmjs.com/package/terser) をインポートしています。
これはソースコード圧縮、いわゆる「ミニファイ」を行うパッケージです。
トランスパイルしたJavaScriptを圧縮します。

### 4. 動的インポート
実はESMの `import` はDataURLも読み込めます。
つまりスクリプトを埋め込めるわけです。
圧縮したJavaScriptをUTF-8でエンコードしBase64のDataURLにして埋め込み、実行します。

`export` は存在せず、ただスクリプトの中身を上から実行できれば良いので、特に代入はしません。
また、スクリプト(DataURL)の肥大化によりインポート処理が不安定になる可能性を低減するため、前項で圧縮しています。

# まとめ
ちなみに同じ理論で [SASS/SCSS](https://www.npmjs.com/package/sass) も行けます。
が、こちらは既に [Nesting](https://developer.mozilla.org/ja/docs/Web/CSS/CSS_nesting) や [Scope](https://developer.mozilla.org/ja/docs/Web/CSS/@scope) があるので...
是非 [ECMAScript Type Annotations](https://github.com/tc39/proposal-type-annotations) も何卒よろしくお願い致します...

意外とそのままウェブブラウザで動くnpmパッケージは多いので、ダメ元でesm.shに打ち込んで試してみるのはアリ。
Node.jsやOS固有の機能を呼び出してる場合は当然ながら動かないです。
Remix with Cloudflare and Vite

Vite について。

https://twitter.com/remix_run/status/1750942666638897227

Cloudflare で動くようになったので試す。2023年1月29日現在は unstable[^1]

Remix を Vite で Cloudflare に deploy する。

## Why Vite
>Well, we did some quick testing on the Indie Stack with a M1 Max MacBook Pro and here’s what we found:
10x faster HMR[^5] 🔥
5x faster HDR[^4] 🔥
> 
> さて、M1 Max MacBook Proを使ってIndie Stackで簡単なテストをしてみた
HMRが10倍速い 🔥
HDRが5倍速い 🔥

https://remix.run/blog/remix-heart-vite

ここでも Rust による高速化の影響を受けている。

## Usage
- Vite への migration で code の変更は無し。

```bash
npx create-remix@nightly --template https://github.com/remix-run/remix/tree/dev/templates/unstable-vite-cloudflare
```

```bash: npm run dev
node ➜ /workspaces/my-portfolio-remix-vite (main) $ npm run dev

> dev
> remix vite:dev

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
```

Remix + Vite + Cloudflare はこちら。

https://my-portfolio-remix-vite.pages.dev/portfolio

code はこちら。

https://github.com/danny-yamamoto/my-portfolio-remix-vite

## BTW
Rust に関して FRAIM[^2] さんと話す機会がありました。

FRAIM さんはプロダクト[^3]の Backend を Rust で開発しているみたいです。

Engineer の方々も geek な方々でとても魅力的でした。


[^1]: https://github.com/remix-run/remix/tree/dev/templates/unstable-vite-cloudflare
[^2]: https://fraim.co.jp
[^3]: https://lawgue.com
[^4]: アプリケーションによってフェッチされたデータが定期的にリフレッシュされ、最新であることを確認するプロセスを指す。
[^5]: 主にアプリケーションの開発中に使用される機能で、特にwebpackのようなツールを使用したWeb開発のコンテキストで使用されます。HMRは、ページ全体をリフレッシュすることなく、実行中のアプリケーションのモジュールを更新する方法を提供し、開発プロセスを大幅に高速化します。
論文収集を快適に（PythonでのXML解析）

# はじめに
論文収集が手間だと感じている方必見！
J-STAGE WebAPIを用いて、J-STAGEで検索した論文の一覧をExcelにまとめます。

# 環境
python 3.10.13

# J-STAGE WebAPI
J-STAGE WebAPIへリクエストを送ると、XML形式のレスポンスが返ってきます。
また、リクエスト用URLのパラメータを変更すると、検索条件を変えることができます。

J-STAGE WebAPIの詳しい仕様は、以下に記載されています。
[J-STAGE WebAPIについて](https://www.jstage.jst.go.jp/static/pages/JstageServices/TAB3/-char/ja)

# Code
### リクエストの送信
今回は、**タイトル** に **「健康」** が入った論文を取得します。
検索条件を変更したいときは、**「健康」** の部分を変更してください。
また、 **本文** に記載されている情報で検索したいときは、urlの「article=」を **「text=」** に変更してください。
```python:リクエスト送信
import requests

#リクエスト用URL
url = 'https://api.jstage.jst.go.jp/searchapi/do?service=3&article="健康"'

#APIにリクエストを送信
response = requests.get(url)
response.encoding = response.apparent_encoding
```
### XML解析
**BeautifulSoup**は、Pythonのスクレイピング用のライブラリで、HTMLやXML形式のテキストからデータを抽出するための便利なツールです。こちらを用いて、XML形式のAPIレスポンスを解析していきます。

**find_all()** で条件に合致する全ての要素をリストとして取得できます。
```python:BeautifulSoup
from bs4 import BeautifulSoup

soup = BeautifulSoup(response.text, "xml")
entries = soup.find_all('entry')
```


### データ抽出とDataFrameへの格納
タイトル、リンク、筆頭著者、年、ジャーナル、巻、号、ページ をDataFrameへ格納します。

**and**は、各条件が**None**でないかつ存在する場合に、それぞれの属性やテキストを取得し、それ以外の場合は**None**として扱っています。このようにして、**None**チェックと値の取得を一度に行っています。
```python: DataFrameへの格納
import pandas as pd

# DataFrameの初期化
columns = ['article_title', 'article_link', 'first_author', 'publish_year', 'journal', 'vol'\
           , 'number', 'starting_page', 'ending_page']
df = pd.DataFrame(columns=columns)

# entryごとにデータ抽出と DataFrame への格納
for entry in entries:
    data = {
        'article_title': entry.find('article_title') and entry.find('article_title').find('ja') and entry.find('article_title').find('ja').text.strip(),
        'article_link' : entry.find("article_link") and entry.find("article_link").text.strip(),
        'first_author' : entry.find("author") and entry.find("author").find("ja") and entry.find("author").find("ja").find("name") and entry.find("author").find("ja").find("name").text.strip(),
        'publish_year' : entry.find("pubyear") and entry.find("pubyear").text.strip(),
        'journal'      : entry.find("material_title") and entry.find("material_title").find("ja") and entry.find("material_title").find("ja").text.strip(),
        'vol'          : entry.find("prism:volume") and entry.find("prism:volume").text.strip(),
        'number'       : entry.find("prism:number") and entry.find("prism:number").text.strip(),
        'starting_page': entry.find("prism:startingPage") and entry.find("prism:startingPage").text.strip(),
        'ending_page'  : entry.find("prism:endingPage") and entry.find("prism:endingPage").text.strip(),
    }

    # DataFrameに追加
    df = pd.concat([df, pd.DataFrame([data], columns=columns)], ignore_index=True)

# Excelに出力
df.to_excel('articles.xlsx', index=False)
```

# さいごに
今回、XML解析はBeautifulSoupを用いましたが、正直xmltodictを用いた方が見やすいコードになるかと思いました。

xmltodictを用いている方がいらっしゃったので、そちらの記事を添付しておきます。
[#03 J-STAGEから論文タイトルで検索をしてcsvファイルでDL](https://qiita.com/ytsuchiya/items/61acea47c18d235534ed)
Macの動きが重い〜原因はGoogle Chrome？

### Macの動きが重くてイライラ

先日、Macユーザーになってからまもない人が「Macの動きが重いんですけど、原因わかりますか」と質問されました。いろいろ調べていじった結果、Macはスムーズに動くようになりました。

その中で分かったこと、原因、解決策について、端的にシェアしていきます。


# 1.問題解決の手順
### 1.アクティビティモニタの確認：
Macのアクティビティモニタを確認し、何が処理に使用されているのかをチェックしました。すると「diskimages-helper」プロセスがCPUの大半を占めていることがわかりました。

### 2.PCの再起動：
とりあえず、問題の詳細の特定と解決のため、PCを再起動し、システムのパフォーマンスに影響を与えるプロセスをリセットしました。

### 3.Google Chromeの再インストール：
何度か再起動したのですが、再起動するたびにGoogle ChromeのDMGファイルが立ち上がることがわかりました。なのでGoogle Chromeを再インストールし、DMGファイルを削除しました。結果「diskimages-helper」プロセスが処理しなくなり、問題を解消できました。

# 2. 原因はGoogle Chromeのインストール手順の誤り

### 1.DockのGoogle Chromeが「？」マークになっていた
再起動するたびに、インストールしたはずのGoogle ChromeがDockから消えている（正しくは「？」になっている）ことに気がついたことで、この問題の解決につながりました。ちなみにDockにあったのはGoogle ChromeのDOMファイルへのショートカットでした。（Google Chromeのアプリケーションへのショートカットではありませんでした）

### 2.DMGファイルの正しい取り扱い：
Google Chromeのインストーラーを右クリックし、「取り出す」を選択してDMGファイルを適切にマウントします。その後、Macを再起動し、インストール画面が表示されないことを確認します。

### 3.Google Chromeの正しいインストール方法
Google ChromeをMacに正しくインストールするためには、以下の手順を踏む必要があります。

①公式サイトからDMGファイルをダウンロードし、開きます。
②アプリケーションを「アプリケーション」フォルダにドラッグしてインストールします。
③DMGファイルを取り出し、不要であれば削除します。

※今回の問題は③の手順が抜けていたことで起きました。

# まとめ
Macでのアプリケーションインストール問題は、時にシステムのパフォーマンスに大きな影響を与えることがあります。特に、外部からダウンロードしたDMGファイルを介したアプリケーションのインストールでは、正しい手順を踏むことが重要です。この記事で解説した手順と注意点を守ることで、MacユーザーはGoogle Chromeを始めとするアプリケーションのインストールに関する一般的な問題を回避できます。
UiPathで楽する引継ぎ(属人化防止)

# 1,はじめに
前の記事で引継ぎを少しでも楽にする方法について、まとめますと書いたのでそれをまとめることにしました。
この記事は**UiPath**の引継ぎについてまとめています。

# 2,引継ぎ資料はいつから作成するもの？
:::note alert
引継ぎ資料などは日頃から作成するものです！
:::

:::note info
どうしたらこの認識に変えられるかというと「いつでもこの現場をいなくなってもいい」と常に思い込ませることです。
:::

:::note warn
「いつでもこの現場をいなくなってもいい」はいい加減な言い方かもしれないのですね。
これを言い換えると、**「いつでも長期休みをとれるようにするため」** とした方がいいでしょうか。
:::

この認識に変えることで引継ぎ資料を常に作成するようになります。

# 3,UiPathの引継ぎ資料とは？

:::note info
(1)実行中の動きやロボットの説明を動画にする。
(2)改修履歴を残す。
(3)Configファイル(設定ファイル)の備考やUiPath Studioのアクティビティの注釈を書く。
:::

## (1)実行中の動きやロボットの説明を動画にする。

:::note warn
実行中の動きは**UI操作**があるものに対してはかなり効果があります。
:::

:::note info
・Excelなどの資料と違って書くことも読むこともなく、動画は見ているだけで済む。
・実行中の動画では普段の環境(ネットワーク、システムなど)の把握を動的に見ることができる。
・普段の保守運用でも画面の何が変わったのかを比較しやすい。
※ちなみにおすすめはデバックモードで強調表示を使用とするわかりやすいです。
:::

:::note alert
・画面が変わるごとに動画を撮らないといけない。
・個人情報が残ってしまう場合もあるので動画で残すのはNGの場合がある。
:::


## (2)改修履歴を残す。

記載する観点としては下記の通りです。

:::note warn
a,いつどういう事象が起きたか。
b,aに対して、xmal内のスクショも含めどのように修正したか。
:::

:::note info
・a,bの履歴があることでUiPath初心者でない限り状況把握をしやすい。
・他のロボットでも同じエラーが起こったときには、この改修履歴を見ることで参考にできる。
:::

:::note alert
改修の頻度や内容が多いと記載することが大変。
:::

## (3)Configファイル(設定ファイル)の備考やアクティビティに注釈を書く。

:::note warn
ここをしっかりと残しているかで次の人への助けになります。
:::

:::note info
・Configファイルの備考には何故それを設定したのか記載する。
・注釈を書く視点は下記の通りです。
　a,Vb.Net
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/4a79c506-8200-9636-8351-9cae3ff924d3.png)

　b,Configファイルなどに持たせているパスなど
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/0c2b29f7-6273-7b2d-ede3-f3c4dbe38329.png)

　c,環境起因や普段と異なる考え方を用いて開発をしたとき
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/e0857f58-8863-3714-dec2-d2c5e20f47e1.png)

:::

:::note alert
・説明文が長いとかえってわかりにくくなることがある。
・改修毎に直す必要があり、都度変更することが大変。
:::

# おわりに
よく属人化という言葉を耳にしてそれを防ぐためにはどうしたらいいのかと考えてみた結果、この記事を作成できました。
**「いつでもこの現場をいなくなってもいい」** や **「いつでも長期休みをとれるようにするため」** と思うことで、後に楽になります！
db.collection.count()は非推奨 

下記クエリのうち、```db.collection.find().count();```の結果が異なる事がある。
MongoDBのバージョン3.2以降では、db.collection.count()は非推奨
``` javascript
db.collection.find().count();

db.collection.count();

db.collection.countDocuments();

db.collection.aggregate([{ $group: { _id: null, count: { $sum: 1 } } }]);
```
TextMeshProで1文字ずつ表示していると、前の行の文字が移動する事がある

## メッセージを1文字ずつ表示するウィンドウを作っていたら、前の行の文字が突然次の行に移動した
![45064a4d874d2329555e5c04fe1f5f73.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/24de497c-01d8-646b-c54a-85a401e9ab5f.gif)

## 原因
TextMeshProはデフォルトで禁則処理が入っており
運悪く、自動改行した次の行の頭の文字が行頭禁則に引っかかって
前の行の最後の文字が、新しい行の先頭に追い出されていた。

## どうしよう
事前に改行する位置を調べて、予め改行コードを挿入しておけばいいのでは？

## TextMeshProから改行位置の情報を取得したい
きっとどこかに、改行位置の情報があるに違いないと思い探したらありました。
https://docs.unity3d.com/ja/Packages/com.unity.textmeshpro@3.0/api/TMPro.TMP_LineInfo.html
``` c#
 TextMeshProUGUI.textInfo.lineInfo

 // 行の最初の文字のindex
 lineInfo.firstVisibleCharacterIndex
 // その行に何文字表示されるか
 lineInfo.characterCount

 ```

 ### 改行位置を取得して、改行コードを挿入してみる
 ``` c#
// TextMeshProに文字列をセットして、自動改行の位置を計算してもらう
textMeshProUGUI.text = srcText;
// 改行コードを挿入する
 var lineInfo = textMeshProUGUI.textInfo.lineInfo;
string text = string.Empty;
foreach (var info in lineInfo) {
    if (info.visibleCharacterCount > 0) {
        text += textMeshProUGUI.text.Substring(info.firstVisibleCharacterIndex, info.visibleCharacterCount) + "\n";
    }
}
 ```
 #### 結果
 ![スクリーンショット 2024-01-29 18.07.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/adcf5575-3afe-1f05-24e2-5c2440b88b8a.png)

 ### 取得はできたが、情報が間違っている
 情報の取得はできたが、値が期待してたものと違いました。
 lineInfoはTextMeshProにテキストをセットした瞬間に計算されるわけではなく
 TextMeshProのUpdateの中で計算されるようで
 セットしたフレームに取りに行った情報は、古い情報だったようです。

 ### 1フレーム待ってみる。
 ``` c#
// TextMeshProに文字列をセットして、自動改行の位置を計算してもらう
textMeshProUGUI.text = srcText;
// 自動改行の計算のため1フレーム待つ
await UniTask.DelayFrame(1);
// 改行コードを挿入する
 var lineInfo = textMeshProUGUI.textInfo.lineInfo;
string text = string.Empty;
foreach (var info in lineInfo) {
    if (info.visibleCharacterCount > 0) {
        text += textMeshProUGUI.text.Substring(info.firstVisibleCharacterIndex, info.visibleCharacterCount) + "\n";
    }
}
 ```
#### できた！
![6e6e8778d7e3fe3c4745a011d34718cf.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681368/fe70813c-1f10-7613-afc5-b33048a677c5.gif)
【AWS x MySQL】RDSの同時接続数 (max_connections) をCLIで変更する方法

# 概要
MySQL DBの同時接続数 (`max_connections`) を変更しようと思ったのですが、SUPER権限エラーでSQLではできず。本記事ではAWS CLIを利用して同時接続数を変更する方法を紹介します。


# エラー内容
SQLコマンドで実施する場合は以下で行います。

```
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SET GLOBAL max_connections = 2000;
```


しかし以下のエラーが出ました。

```
SQLエラー [1227] [42000]: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
```

RDS作成時で作ったrootユーザーにはSUPER権限がないみたい。
`max_connections`などのグローバル変数を変更するには、SUPER権限が必要。

DBから見てみると`rdsadmin`というユーザーならSUPER権限があるが、、、これはAmazon RDSサービスが管理用途で使用する特別なユーザーのため、通常のユーザーのようにログインすることはできません。

# 解決方法
RDSで`max_connections`などのグローバル変数を変更する場合は、AWS CLIを使えば良い。
以下のように実施すれば、無事に最大接続数が変更されます。


```
aws rds modify-db-parameter-group --db-parameter-group-name your-db-parameter-group-name --parameters "ParameterName=max_connections,ParameterValue=2000,ApplyMethod=immediate"
```

`your-db-parameter-group-name`の部分は実際のデータベースパラメーターグループに書き換えます。RDSのコンソール画面からパラメータグループの名前を確認してください。

上記の場合は`2000`にセットしています。
変更後10秒くらいたったら`SHOW GLOBAL VARIABLES LIKE 'max_connections'`の実行結果が`2000`に変わりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/4deec983-0400-026a-0fcc-fbed9f599f50.png)

RDSのコンソールからも確認しておきます。

### 変更前

```
GREATEST({log(DBInstanceClassMemory/805306368)*45},{log(DBInstanceClassMemory/8187281408)*1000})
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/3dc139c4-1170-c494-19b3-c00d1512b0ae.png)

### 変更後



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/3c272024-0c0e-94fd-0dd5-f56503d89b1e.png)

`2000`になっていることが確認できました。
Python学習8日目～代入式～

## 代入式
Python3.8から導入された機能
代入式を使うと式の中で変数に値を代入することができる

~~~Python
変数 := 式
~~~

while文とinput関数を使ってキーボードからの入力を繰り返し取得するプログラムを作成する

~~~Python
while True:
    x = input()
    if x == 'q':
        break
    print(x)
~~~
~~~:実行結果
Python
Python
C#
C#
Ruby
Ruby
q
~~~

これを代入式を使って簡略化する

~~~Python
while (x := input()) != 'q':
    print(x)
~~~
~~~:実行結果
Python
Python
ruby
ruby
json
json
q
~~~

入力した価格の合計を求めるプログラムを考える

~~~Python
t = 0
while (x := input('price: ')) != 'q':
    print('total: ', t := t+int(x))
~~~
~~~:実行結果
price: 100
total:  100
price: 200
total:  300
price: 350
total:  650
price: q
~~~
【Salesforce】CRM Analyticsにおける複数値の処理2_複数値の集計作成

前回（以下のリンクをご確認ください）の複数値の初期設定、複数値の変換、および複数値の表示に続き、今回は複数値集合体処理の関数を紹介いたします

https://qiita.com/Helena_Jie/items/a4e59fa7d7d1865d3c8d


今回は以下の関数を紹介いたします。


|関数名|入力型|出力型|説明|備考|
|:-|:-|:-|:-|:-|
|COLLECT_LIST|テキスト|複数値|重複を許した複数値の組合せの作成|Window関数|
|COLLECT_SET|テキスト|複数値|重複を除外した複数値の組合せの作成|Window関数|
|array_distinct|複数値|複数値|重複した値を削除する(set)||
|element_at|複数値|テキスト|指定インデックスの複数値の要素の取り出し||

参考ヘルプ資料
- [複数値関数](https://help.salesforce.com/s/articleView?id=sf.bi_integrate_recipe_multivalueFunctions.htm&type=5)
- [Window Functions for Formulas](https://help.salesforce.com/s/articleView?id=sf.sdp_recipe_windowFunctions.htm&type=5)


## 1. COLLECT_LIST／COLLECT_SET
テキストから複数値の集計配列を作成します。さらに、重複を許した複数値の組合せを作成します。
### ①レシピの変化ノードのカスタム数式を利用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/792905cd-dacb-b917-b42c-9923b6954d0a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/a09d950b-51db-1f17-3fa6-b989fe6d4f3b.png)

### ②各内容の設定
行数式の数式をONにします。
collect_list()を利用します。　※重複を除外した複数値の組合せを作成したい場合、collect_set()をご利用ください。
パーティションの基準及び並び替えの基準を[No.]に設定します。
出力種別を【複数値】に設定します。
ラベル名及びAPI名を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/6a24c67e-b537-7a59-2429-48fcf660d111.png)

※collect_set()の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/8720d4c5-b58a-e43a-dc80-add3af30fe84.png)

## 2.array_distinct()
Collect_listで作成した列の重複値を削除する時、利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/2af6e4d2-dc73-d6be-6a8b-95b05121791b.png)


## 3.element_at

例：Collect_list()の２番目の要素の取り出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3672646/b84c19b1-88d7-3882-2502-131142ada0be.png)
lambdaロググループにメトリクスフィルタ設定してログ監視アラームを作成してみたらsns料金が大変なことになった件

lambdaのロググループに対して特定ログが出たらアラーム起動でsns経由でlambdaがキックされる処理を作ってしまったら、ループ処理して料金で恐ろしいことに発展しました。

すぐにリソースを削除してawsに問い合わせをしましたが、興味本位でもこのような設定はしないように要注意です!

さあ、例文コードを見ましょうか

```python
import json
import logging
import os
import requests

URL = os.environ['WEBHOOK_URL']

def lambda_handler(event, context):
    # ロギングの設定
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # SNSメッセージの取得
    sns_message = event['Records'][0]['Sns']['Message']
    logger.info(f"Received SNS message: {sns_message}")

    # SNSメッセージをJSONオブジェクトにパース
    alarm_message = json.loads(sns_message)

    # アラーム情報の取得
    alarm_name = alarm_message.get('AlarmName')
    if not alarm_name or alarm_name == 'Unknown Alarm':
        logger.info("No valid alarm name found. Skipping message sending.")
        return {"statusCode": 200, "body": "No valid alarm name, message skipped"}

    state = alarm_message.get('NewStateValue', 'Unknown State')
    reason = alarm_message.get('NewStateReason', 'No reason provided')

    # アラーム情報をメッセージに組み込む
    alert_message = f"CloudWatch Alert: {alarm_name}\n" \
                    f"State: {state}\n" \
                    f"Reason: {reason}"

    bot_message = {'text': alert_message}

    message_headers = {'Content-Type': 'application/json; charset=UTF-8'}

    # WebhookへPOSTリクエストを送信
    response = requests.post(
        URL,
        headers=message_headers,
        data=json.dumps(bot_message),
    )

    logger.info(f"Webhook response: {response.status_code}, {response.text}")

    return {"statusCode": 200, "body": "Message sent"}

# ローカルテストのためのコード（必要に応じて）
if __name__ == '__main__':
    test_event = {
        'Records': [
            {
                'Sns': {
                    'Message': json.dumps({
                        'AlarmName': 'Example Alarm Name',
                        'NewStateValue': 'ALARM',
                        'NewStateReason': 'Threshold Crossed: 1 datapoint [30.0] was greater than or equal to the threshold [25.0].'
                    })
                }
            }
        ]
    }
    lambda_handler(test_event, None)
```
3DS MaxからIGESを書き出す

需要があるかは分かりませんが、情報として、結構探して試行錯誤した為、メモを残しておきます。
今回は、3DS MaxからIGESファイルを書き出す方法になります。


# IGESとは

IGESファイルとは、CADで使用されているファイル形式で、拡張子は『igs』になります。
詳細は、Adobeの[説明ページ](https://www.adobe.com/jp/creativecloud/file-types/image/vector/iges-file.html)をご覧ください。


# 書き出し失敗

IGESファイル自体は、標準で3DS Maxでサポートされており、エキスポートできるファイルの一覧にあります。
しかし、そのまま書き出すと、中身が無い(ヘッダー情報しか入っていない)ファイルが出力されました。

![igsへの書き出し失敗.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/aad6c7d8-a4bf-38fe-1bc0-049bf911c35f.png)

では、どうすれば良いかとう言うと、一度、『ポリゴン』または『メッシュ』に変換する必要があります。
『ポリゴン』または『メッシュ』に変換したあと、IGESファイルに書き出した場合は、以下のように正しい内容で出力されています。

![igsへの書き出し成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/7e340e4d-f269-23c5-6a9b-551d843d28a1.png)


# 手順

**① 書き出すオブジェクトを選択し、右クリックで『編集可能ポリゴンに変換』または『編集可能メッシュに変換』**

![ポリゴン変換_メッシュ変換の仕方_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/13e344e8-ae60-9da5-bc9f-7e9d4b9d0766.png)

**② サイドメニューの一番左の『✙』を選択し、『標準プリミティブ → ボディオブジェクト』に変更**

![ポリゴン変換_メッシュ変換の仕方_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/faac7c26-60ab-13df-c627-212342f9c2d4.png)

**③ 『ボディユーティリティ』『ボディオブジェクト』『結合ボディ』『ボディカッター』の内、『ボディオブジェクト』を選択**

![ポリゴン変換_メッシュ変換の仕方_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/578e06c8-93b3-5eed-65ab-78178a21278b.png)

**④ IGESファイルにエキスポートする**
下は、書き出したigsファイルを読んでみた結果です。
無事に書き出せていますね！

![igsへの書き出し成功_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153021/2058c4cd-fb4d-1108-c1b2-b79d3c44693a.png)



# 参考
* [How to export IGES file format from 3ds max](https://www.youtube.com/watch?v=ASq4Mf7gCsI)
Railsにおける複数形`s`の注意

# はじめに
めちゃくちゃつまづいた理由が「複数形`s`」にあったので、
戒めと教訓の思いを込めて、「複数形に気を付けようね！」という記事です。
# 問題
`routes.rb`にて、`resource :login ...`と書くべきところを、
`resources :login ...`と書いてしまい
`id`必要だわ`spec`は通らないわ、
GPTに聞いても「`login`を`logins`と書いてください」と解決にならない解決策（私が悪い）。
大変でした。
# 気を付けるべきところ
## `resource`と`resources`は別物
> ### `resources`
> 
> - `resources`は、複数のリソースを扱う際に使用されます。一般的には、複数のオブジェクトの集合に対するCRUD（Create, Read, Update, Delete）操作を行う場合に使います。
> - 例えば、`resources :users`と記述すると、ユーザーの一覧表示（index）、新規作成（new）、表示（show）、編集（edit）、更新（update）、作成（create）、削除（destroy）に対応する標準的な7つのRESTfulルートが生成されます。
> - これらのルートは、通常IDを含むURL（例：`/users/1`）を用いて特定のリソースを識別します。
> 
> ### `resource`
> 
> - `resource`は、単一のリソースを扱う際に使用されます。これは、IDによって区別されない単一のオブジェクトに対する操作を行う場合（例えば、ユーザーの現在のプロフィールやダッシュボードなど）に適しています。
> - 例えば、`resource :profile`と記述すると、新規作成（new）、表示（show）、編集（edit）、更新（update）、作成（create）、削除（destroy）に対応する6つのルートが生成されますが、一覧表示（index）ルートは含まれません。
> - これらのルートは、IDを含まないURL（例：`/profile`）を用いてアクセスされ、通常はログインしているユーザーの特定のリソースに紐付けられます。

つまり、
- **扱うオブジェクトが単一か集合か**
- **idを使用するかしないか**
- `index`が作成されない
- URLに`s`がつくかどうか

の違いがあるということです。

**ログイン・ログアウトは「1人のユーザーに対する処理」なので、`resource`が適していたわけですね。**
`s`がつく方（`resources`）は、
**「usersでユーザーの一覧と個々の詳細を扱ったり、postsで複数の投稿を扱うとき」**
などに適しています。
## 他にもあるぞ！気をつけろ！

### `resource`と`resources`にまつわる命名
`resource`なら単数形（例：`login`）
`resources`なら複数形（例：`users`）
### 復習：MVCなどの命名
#### モデル
単数形（クラスそのものがユニークなため。また、単一の実体・レコードをあらわすため）
#### ビューのディレクトリ
複数形（ビューファイルが複数入っているから）
#### コントローラ
通常、複数形（アクションがいっぱいあるため）
#### ヘルパー
複数形が多い（コントローラに従う）
#### テーブル（データベース）
複数形（データがたくさんあるから）
# 終わりに
つまづきは痛かったけど、得るものも大きかった。ここで知れてよかったです。
Python学習8日目～ラムダ式～

## ラムダ式
Pythonは手続き型言語、オブジェクト指向型言語に分類されるプログラミング言語
他には関数型言語という分類があり、ラムダ式は関数型言語の機能の一つでPythonで使うことで
関数型言語の便利な部分を使うことができる。

~~~Python
lambda 引数,...:式
~~~

ラムダ式は無名関数を作成するための文法
上記のラムダ式は下記の関数と同じ働きをする

~~~Python
def 関数名(引数,...):
    return 式
~~~

### 例題
引数fとして受け取った関数を0から9までの整数に対して呼び出し、戻り値を表示する関数を定義

~~~Python:loop.py
def loop(f):
    for i in range(10):
        print(f(i),end=' ')
~~~

引数xを受け取りxの2乗を返す関数を定義(square関数)
squareを引数としてloop関数を呼び出す

~~~Python:loop.py
def loop(f):
    for i in range(10):
        print(f(i),end=' ')

def square(x):
    return x*x

loop(square)
~~~
~~~:実行結果
0 1 4 9 16 25 36 49 64 81
~~~

これをラムダ式で簡潔にすることができる

~~~Python:loop.py
def loop(f):
    for i in range(10):
        print(f(i),end=' ')

loop(lambda x: x*x)
~~~
~~~:実行結果
0 1 4 9 16 25 36 49 64 81
~~~

ラムダ式を使えば1行にまとめることができる
IPPONグランプリのプロフィール画像を作りたい（という記事に触発されて）．

# きっかけ
[IPPONグランプリのプロフィール画像を作りたい（わけではなかったのです）．](https://qiita.com/NAT/items/6413df806c2214d76230)の記事がおもしろかったので、つい。
# 変更点
ほぼ元記事のままの処理ですが、できるだけ`numpy`や`opencv`の機能を使って簡潔なコードになるように努めました。また、ガウシアンフィルタによる平滑化で「ノッペリ」となるように前処理しました。
# コード
[rembg](https://github.com/danielgatis/rembg)は導入済みが前提です。
```Python
import cv2
import numpy as np
from rembg import remove

# https://sipi.usc.edu/database/database.php?volume=misc&image=4#top
im = cv2.imread('4.1.04.tiff', cv2.IMREAD_COLOR)

# https://commons.wikimedia.org/wiki/File:Visit_of_Bill_Gates_to_the_European_Commission_-_P062021-967902.jpg
#im = cv2.imread('input.jpg', cv2.IMREAD_COLOR)

im = remove(im).copy() # 背景を削除

# 前景と背景のマスク情報  閾値は適当に127
cond_bg = (im[:,:,3] <= 127) # 背景
cond_fg = (im[:,:,3] >  127) # 前景

# 色分け用のグレイスケール画像
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)

# ガウシアンフィルタで平滑化
# カーネルサイズは画像サイズからテキトーに算出
kn = [int(max(v//256, 3)) for v in im.shape[:2]]
kn = [v+1 if v % 2 == 0 else v for v in kn] # サイズは奇数でなければならない
im = cv2.GaussianBlur(im, kn, 3)

# 結果のカラー(BGR)画像
img_res = np.zeros( list(im.shape)+[3], dtype=np.uint8)
img_res[:,:] = (0, 0, 255) # 動作（漏れ）チェック用に赤で塗りつぶし

# 前景の最明色＝背景のようなのでそれにあわせる
CLR_BG = (0, 238, 238)
COLORS = [(0, 0, 0), (0, 206, 238), CLR_BG]

# とりあえず前景の最暗～最明の範囲で等分割
rng = np.linspace(im[cond_fg].min(), im[cond_fg].max(), len(COLORS)+1)
print(rng)
rng[0], rng[-1] = (0, 255) # 両端は真黒、真白に

# 色分け
for i, clr in enumerate(COLORS):
    cond = ((im >= rng[i]) & (im <= rng[i+1]))
    img_res[cond] = clr

# あらためて背景を塗りつぶす
img_res[cond_bg] = CLR_BG

cv2.imwrite('result.png', img_res)
```
# 結果例
![4.1.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/e5a0e158-bb9b-236d-5529-5fb728c27a2e.png)
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175214/1a5e69b4-ad97-d3e8-c069-3edb6802121e.png)

# その他
このラスタ画像から輪郭抽出してベクター化してみるのもおもしろそうです。

# 参考記事
- [IPPONグランプリのプロフィール画像を作りたい（わけではなかったのです）．](https://qiita.com/NAT/items/6413df806c2214d76230)
Python学習8日目～ジェネレータ式～

## ジェネレータ
イテラブルなオブジェクトの一種
for文などと同じように値を1個ずつ取り出すことができるが、あらかじめ複数の値を格納しておくのではなく、
値を要求されるたびに1個ずつ生成することが特徴

~~~Python:generator.py
# 書き方
式 for 変数 in イテラブル

# 1から9までの値で二乗した数値を出力
print((x*x for x in range(1,10)))
~~~
~~~:実行結果
<generator object <genexpr> at 0x000001CA4331F1D0>
~~~
このようにジェネレータ式は**ジェネレータ(ジェネレータオブジェクト)** を出力する

ということでジェネレータを出力する形に書き換える

~~~Python:generator.py
# 1から9までの値で二乗した数値を出力
for y in (x*x for x in range(1,10)):
    print(y,end=' ')
~~~
~~~:実行結果
1 4 9 16 25 36 49 64 81
~~~

### ジェネレータを使うメリット
消費メモリが少ないので処理速度が上がるという点でメリットがある
そのため多数の繰り返し処理を行う際には通常の内包表記ではなく、ジェネレータを使うメリットがある

## ジェネレータ関数とyield文
ジェネレータ関数を使うことでより通常の関数のような表記が出来る
yield文は通常の関数のreturnと同様

~~~Python:generator.py
# 1から9までの値で二乗した数値を出力
def g():
    for x in range(1,10):
        yield x*x
print(g())
~~~
~~~:実行結果
<generator object g at 0x000001840D6DF1D0>
~~~

ジェネレータが生成されていることがわかる

~~~Python:generator.py
# 1から9までの値で二乗した数値を出力
def g():
    for x in range(1,10):
        yield x*x

for y in g():
    print(y,end=' ')
~~~
~~~:実行結果
1 4 9 16 25 36 49 64 81
~~~

上記同様に出力できた

### yield from文
yield from文を使用することで指定したジェネレータに値を返すことができる

開始値から始めて値を1ずつ増加させながら「終了値-1」までの整数を生成する関数(my_range)と
開始値から「終了値-1」までの整数を生成する動作を指定した回数だけ繰り返す関数(my_range2)を作る

~~~Python:generator.py
def my_range(start,stop):
    x = start
    while x < stop:
        yield x
        x += 1

def my_range2(start,stop,count):
    for i in range(count):
        yield from my_range(start,stop)

for y in my_range2(1,10,3):
    print(y,end=' ')
~~~
~~~:実行結果
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
~~~
ユーザーライセンス関連SOQL

# ユーザーライセンス関連SOQL

### ライセンス種類ことの使用済み、トータル、ステータスなどの情報を取得する
```SQL
select Id, Name, UsedLicenses, TotalLicenses, Status, MasterLabel, LicenseDefinitionKey from UserLicense
```
参照リンク：

[Object Reference: UserLicense](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_userlicense.htm)


### ProfileのUserTypeより使用済み取得
```SQL
Select count(Id), Profile.UserType From User WHERE IsActive = TRUE And Profile.UserType = 'CSPLitePortal' Group By Profile.UserType
```
参照リンク：

[Object Reference: Profile](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_profile.htm)

[Object Reference: User](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_user.htm)
AWS OpsWorks Custom JSONが確認できる場所まで遷移する方法

## 概要

AWS OpsWorksのCustom JSONがブラウザから確認できる場所まで遷移する方法を簡単にまとめる。

## 方法

1. AWSコンソールにてOpsWorksの画面を開く。
1. Go to OpsWorks Stacksをクリックする。
1. 任意のSlack nameをクリックする。
1. 右上のStack Settingsをクリックする。
1. Advanced optionsの中にCustom JSONが表示されている。

## 余談

この時期にこの記事にたどり着いたあなたへ。。。
おそらくあなたはOpsWorks Stacksのサービス終了に伴い、他のデプロイ方法に切り替えるべく奔走していることでしょう。
私もその一人です。迫るサービス終了に焦りながら作業をしています。
正直かなり面倒な作業だなと思いながら作業しています。孤独な戦いですが大丈夫です。あなたはひとりじゃない。
おそらく私の管轄しているサービスはOpsWorksサービス終了直前まで切り替え作業がかかるでしょう。一緒に成し遂げましょう。
Discord WebHookにおける{"embeds": ["0"]}エラー

# はじめに
DiscordのWebHookを用いてEmbedを送信するときに、なぜか正しいはずなのにAPIのレスポンスで`{"embeds": ["0"]}`というエラーが返ってきたため、原因の解明と注意点についての覚え書き。

# 実行環境など

- 言語はPHPを使用
- Discord-PHPなどの特別なライブラリは未使用
- JSONを直書きではなく、自前のプログラムで配列をエンコードしている

# このエラーの原因
基本的にEmbedと呼ばれる埋め込みは、一回で最大10個送れます。
つまりこのエラー`{"embeds": ["0"]}`はそのEmbedsの一つ目に問題があるよということ。
私の場合、Embedを一つだけ送るときにこのエラーが出ていたので紛れもなくそのEmbedがおかしいということになる。

:::note warn
以下はstackoverflowの投稿を簡単に和訳して抜粋したもの。
情報の信憑性の有無に関しては今回スルー。
[引用元の投稿はこちらから](https://stackoverflow.com/questions/53935198/in-my-discord-webhook-i-am-getting-the-error-embeds-0)
:::

### 1. 無効な要素が含まれている
主に値のフォーマットが間違っているパターンと値そのものがおかしいパターンの二通り。

- `timestamp`の要素が[ISO8601](https://en.wikipedia.org/wiki/ISO_8601)に準していない
- `color`がdecimal値(10進数)じゃなくて、`"red"`や`"#ff00ff"`などである
- `icon_url` `avatar_url` `url`などのリンクが要求される要素が`https://`や`http://`で始まっていない
- ブール値であるべき要素で別の型の要素が渡されている
- 空またはnull値がある
- 未定義の値がある

### 2. 特定の要素の制限を超えている
文字数や含められる要素の制限を超過してしまっているパターン。

- `title`の文字数制限 **256** を超えている
- `description`の文字数制限 **2048** を超えている
- `field`の`name`の文字数制限 **256** を超えている
- `field`の`value`の文字数制限 **1024** を超えている
- `footer`の文字数制限 **2048** を超えている
- `author`の文字数制限 **256** を超えている
- `field`の数が **25** を超えている
- 全体の合計文字数が **6000** を超えている

# 私の場合
#### 》原因
- `icon_url` `avatar_url` `url`などのリンクが要求される要素が`https://`や`http://`で始まっていない
- 空またはnullがある

#### 》そもそもなぜそうなったのか
私は上項でも述べたように**JSONを直書きではなく、自前のプログラムで配列をエンコードしている**。
以下がエラーを誘発させていた埋め込みを作る箇所の修正前のコードである。
```php
public function buildEmbed() : array
{
    $embed = [];
    $embed["title"] = $this->title;
    $embed["description"] = $this->description;
    $embed["url"] = $this->url;
    $embed["timestamp"] = $this->timestamp;
    $embed["color"] = $this->color;
    $embed["footer"] = $this->footer;
    $embed["image"] = $this->image;
    $embed["thumbnail"] = $this->thumbnail;
    $embed["author"] = $this->author;
    $embed["fields"] = $this->fields;
    return $embed;
}
```
当初の目的として、様々な用途で使うためにAPIのようなものとして実装をしていたが、初期値である空配列`[]`や空文字`""`がどんな状況であれ確実に埋め込みの要素として含まれてしまうことが原因だった。
すべてのプロパティが初期値である場合のみ条件分岐で`$embed`へ格納しない方法をとることで無事再稼働させた。

# さいごに
とてつもなく初歩的なことでミスをしていたのが恥ずかしい。
でも誰かのためになればいいと思ったので覚え書きとして残した。
[備忘]営業秘密とは

営業秘密について簡単にまとめました。

# 営業秘密とは
不正競争防止法 第 2 条第 6 項より引用
> この法律において「営業秘密」とは、秘密として管理されている生産方法、販売方法その他の事業活動に有用な技術上又は営業上の情報であって、公然と知られていないものをいう。

つまり、**①秘密管理性、②有用性、③非広知性**を満たしているもののことをいう。

## ①秘密管理性
情報に対してアクセスできる人が制限されていること。
情報にアクセスしたときにそれが秘密であるとわかること。
## ②有用性
仕事において有用な情報であること。
## ③非広知性
一般的には知られていない情報であること。



# おわりに
詳しくは各自で調べていただけると幸いです。