OmniAICreator/Qiita-1.07M huggingface dataset:
Elixirのスーパーバイザー(Supervisor)について

- [スーパーバイザー](#スーパーバイザー)
  - [スーパーバイザーを記述する](#スーパーバイザーを記述する)
    - [start\_link](#start_link)
    - [init](#init)
    - [監視ツリーへの追加](#監視ツリーへの追加)
  - [まとめ](#まとめ)
  - [使用方法](#使用方法)


# スーパーバイザー

スーパーバイザーはプロセスを監視することができ、
<font color="red">プロセスが終了したとき自動で再起動</font>させることができる。

プロセスが異常終了(異常でない場合も)したとき、
**strategy**によって指定された手順で再起動が行われる

## スーパーバイザーを記述する

スーパーバイザーのモジュールを記述する場合、
以下の要点を考慮して記述を行うこと。

* `use Supervisor`を記述する
* `start_link()`を実装する
* `init()`を実装する

### start_link

`start_link()`は以下のように記述する

```elixir
def start_link(_) do
  Supervisor.start_link(__MODULE__, :ok)
end
```

### init

スーパーバイザーの監視ツリーにプロセスを追加するためには、
init関数で以下の記述を行う。

1. プロセスのモジュールをリスト化する
2. プロセスの**終了時の動作を指定**して、スーパーバイザーを初期化する。

### 監視ツリーへの追加

例としてlibディレクトリに以下のファイルがあるものとする。

* my_supervisor.ex
* sample_process.ex

スーパーバイザーツリーに追加して監視したいプロセスを、以下のように記述してリスト化する。

```elixir
children = [
  # ここにプロセスモジュール名を記述する。以下は例
  {SampleProcess, 値}
]
```

このリストは、スーパーバイザーの監視ツリーとして使用する。

スーパーバイザーを初期化するために以下を記述する

```elixir
Supervisor.init(children, starategy: プロセス終了時の動作)
```

starategyで選択できるものには以下のものがある

* :one_for_one - 終了した子プロセスを再起動する
* :one_for_all - 子プロセスが終了する、他の子プロセスも終了させすべて再起動させる。
* :rest_for_one - 子プロセスが終了すると、その子プロセスのあとに開始したプロセスを含め終了。その後再起動する。

## まとめ

ここまでをまとめると以下のようになる。またここでは、終了時の動作を:one_for_oneとしている

```elixir
def init(:ok) do
  children = [
    # ここにプロセスモジュール名を記述する。以下は例
    {SampleProcess, 値}
  ]

  Supervisor.init(children, stararegy: :one_for_one)
en
  
```

## 使用方法

スーパーバイザーはネストすることができる。

したがって、**Mixプロジェクト**の**application.ex**内の管理ツリーに、
個別に作成したスーパーバイザーを追加することもできる。

スーパーバイザーを`start_link()`で起動させると、子プロセスも起動される。

起動された子プロセスのプロセスIDを取得するには、以下のコマンドを使用する。

`Supervisor.which_children(スーパーバイザーのプロセスID)`

この関数の戻り値から子プロセスのIDを取得するとよい。

以下は例
```elixir
    # スーパーバイザーの起動
iex>{:ok, sup} = MySuperviosr.start_link []
    {:ok, #PID<0.161.0>}

    # 子プロセスを取得する
iex>Supervisor.which_children sup
    [
      {Sample, #PID<0.163.0>, :worker, [Sample]},
      {GenServerTuto, #PID<0.162.0>, :worker, [GenServerTuto]}
    ]

iex>[{_, pid, _, _}, _] = Supervisor.which_children sup
```
unar & lsar

<!--
2023/11/6
-->
[picoCTF][Forensics][File types]

## Writeup
* 基本の'file'コマンドから。
![screenshot 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/b88680ff-7ac4-af57-7852-3186ea5d4c73.png)

* とりあえず中身を確認する。
![screenshot 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/bdf78246-15b2-cd40-fc7b-adc94bf748e3.png)

* とりあえず実行してみる。
![screenshot 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/ca428f3a-b9c9-df9c-137d-c7ede2e61644.png)

* 'uudecode'が見つからないようなので、ググってインストール。
後で気づいたけど、シェルコードにも記載がありました。
`sudo apt install -y sharutils`
![screenshot 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/1ee3613d-0dbb-ff15-34a5-e9ecd06c4b0f.png)

* flagを確認しても、中身が見れない。
`ar`アーカイブだって。
![screenshot 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/20511a0e-a68f-4d48-9352-78b9ca32bacc.png)

* 中身を確認するとflagがあります。
一応上書きしないようにして、出力してみた。
次は`cpio`アーカイブだって。
![screenshot 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/e0a73957-2843-ecc0-fa6f-ec0fa51b4414.png)

* 中身を確認するとflagがあります。
上書きだとエラーになるようなので、名前を変更してから、出力してみた。
次は`bzip2`圧縮だって。
![screenshot 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/c10d733a-acf4-faef-5c4c-af73268b49c6.png)

* `bzip2`を解凍します。
次は`gzip`圧縮だって。
![screenshot 13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/c227e9b3-0bcb-9073-7f35-aab263af4303.png)

* `gzip`を解凍します。
拡張子が`gz`でないと、エラーになるようです。
次は`lzip`圧縮だって。
![screenshot 14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/3deb9014-e903-7d2e-2653-b8c5356ca1eb.png)

* `lzip`はデフォルトでは、インストールされていないようなので。
`sudo apt install -y lzip`
次は`LZ4`圧縮だって。そろそろゴールにしてほしかった。
![screenshot 15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/b967b766-08b9-16b7-9f95-792bde3ea988.png)

* `lz4`はデフォルトでは、インストールされていないようなので。
拡張子が`lz4`でないと、エラーになるようです。
`sudo apt install -y lz4`
次は`LZMA`圧縮だって。
![screenshot 16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/ecc122e1-4ab0-53db-508c-f5b59d3b91c6.png)

* `LZMA`を解凍します。
拡張子が`xz`でないと、エラーになるようです。
次は`lzop`圧縮だって。
![screenshot 20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/eaf66851-b449-a9dc-ce4c-1f61664846f8.png)

* `lzop`を解凍します。
上書きだとエラーになるのか、名前を変更してから、出力してみた。
次は`lzip`圧縮だって。
![screenshot 21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/a1c32a77-6425-245f-0080-edc5a8464706.png)

* `lzip`を解凍します。
上書きだとエラーになるので、不要なファイルを消してから、出力してみた。
次は`xz`圧縮だって。
![screenshot 23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/79d46df2-9bbe-07e9-5f2d-135eefe84d0d.png)

* `xz`
拡張子が`xz`でないと、エラーになるようです。
やっとASCII Text。
![screenshot 24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/9715db02-5901-4ea2-6a1a-f759c1394bbf.png)

* `xxd`をインストールして、実行
`sudo apt install -y xxd`
`cat flag | xxd -r -p`
![screenshot 25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160736/82118676-c3f8-b980-747c-750be002c524.png)

* 以上です。

## 参考サイト
* unarというツールを使用すると、少し楽になりそうでした。

https://www.kali.org/tools/unar/
CSSセレクタのさまざまな設定方法

## アジェンダ
以下に、CSSセレクタのさまざまな設定方法とそのコード例をまとめます。

## 基本的なセレクタ
**タグセレクタ**:特定のHTMLタグにスタイルを適用します。
```css
p {
    color: blue;
}
```

**クラスセレクタ**: `.クラス名` の形式で、HTMLのclass属性に一致する要素にスタイルを適用します。
```css
.button {
    background-color: red;
}
```

**IDセレクタ**: `#ID名` の形式で、HTMLのid属性に一致する要素にスタイルを適用します。
```css
#header {
    height: 100px;
}
```

**複数セレクタの適用**: カンマで区切ることで、複数のセレクタに同じスタイルを適用。
```css
h1, h2, h3 {
    font-family: Arial, sans-serif;
}
```

**CSSで複数のclass名を指定**: カンマ、半角スペース、または繋げて記述することで、複数のclass名を指定します。
```css
.text.large {
    font-size: 24px;
}
```

## 関係セレクタ

**子孫セレクタ**: `親セレクタ 子セレクタ` の形式で、特定の親要素の下にある子要素にスタイルを適用します。
```css
article p {
    font-size: 16px;
}
```

**子セレクタ**: `親セレクタ > 子セレクタ` の形式で、直接の子要素のみにスタイルを適用します。
```css
ul > li {
    list-style-type: square;
}
```

**隣接兄弟セレクタ**: `セレクタ1 + セレクタ2` の形式で、セレクタ1の直後にあるセレクタ2にスタイルを適用します。
```css
h2 + p {
    margin-top: 10px;
}
```

**一般兄弟セレクタ**: `セレクタ1 ~ セレクタ2` の形式で、セレクタ1の後にあるすべてのセレクタ2にスタイルを適用します。
```css
h2 ~ p {
    color: gray;
}
```

## 擬似クラス
**擬似クラス**: `:擬似クラス名` の形式で、特定の状態や位置にある要素にスタイルを適用します。
以下にいくつか例をあげます。

**`:hover`**: 要素にマウスカーソルが乗ったときにスタイルを適用。
```css
a:hover {
    text-decoration: underline;
}
```

**`:nth-child()`**: 子要素の中での位置に基づいて要素を選択。
```css
li:nth-child(odd) {
    background-color: lightgray;
}
```

**`:nth-of-type()`**: 特定のタイプの子要素の中での位置に基づいて要素を選択。
```css
p:nth-of-type(2) {
    font-weight: bold;
}
```

## 擬似要素
**擬似要素**:　擬似要素は、実際にはDOMに存在しない要素を表現するためのセレクタです。

**`::before`**: 要素の内容の前にコンテンツを追加。
```css
p::before {
    content: "開始";
}
```

**`::after`**: 要素の内容の後にコンテンツを追加。
```css
p::after {
    content: "終了";
}
```

## 属性セレクタ
**属性セレクタ**: `[属性]` の形式で、特定の属性を持つ要素にスタイルを適用します。
```css
input[type="text"] {
    border: 1px solid black;
}
```

## 参考
- [CSS セレクター - ウェブ開発を学ぶ | MDN](https://developer.mozilla.org/ja/docs/Learn/CSS/Building_blocks/Selectors)
- [CSSでセレクタを自由に操る！便利な指定方法をわかりやすく解説！ | ZeroPlus Media](https://zero-plus.io/media/css-selector-specify/)
- [【HTML・CSS】class属性を複数指定するには？CSSセレクタを並べる方法もサンプルコードで解説 - WEBCAMP MEDIA](https://web-camp.io/magazine/archives/87658)
Terraform Provider for Google Cloud Platform v5 で tfmigrate がうまく利用できない場合がある(2023/10/31時点)

terraformのリソースを管理する際、importコマンドなどを直打ちする代わりにtfmigrateを利用しているチームや企業は多いと思います。
しかし、Google Cloudをterraformで管理するための　[hashicorp/terraform-provider-google](https://github.com/hashicorp/terraform-provider-google)　ではv5以降の仕様変更により`tfmigrate plan(apply)`コマンドが失敗する場合があります。

## どのような時に失敗するのか

BigQueryのDatasetなど、labelsが存在するリソースをimportしたい時です。
terraform-provider-google では v5.0.0から`labels`, `effective_labels`, `terraform_labels`の3種類に分かれるようになっています。

https://zenn.dev/cloud_ace/articles/terraform-google-provider-5#%E3%83%A9%E3%83%99%E3%83%AB%E8%A8%AD%E5%AE%9A%E5%8F%AF%E8%83%BD%E3%81%AA%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%A7-terraform_labels%2C-effective_labels-%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%8C%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9F

これがどう影響が出るのかというと、importした際に3つのラベルのうち`effective_labels`しかimportされず`labels`と`terraform_labels`に差分が出てしまいます。

具体的には、下記のような出力になり`tfmigrate plan`などが失敗します。
```terraform
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # module.data_platform.google_bigquery_dataset.sample_dataset will be updated in-place
  ~ resource "google_bigquery_dataset" "sample_dataset" {
        id                              = "projects/sample/datasets/sample_dataset"
      ~ labels                          = {
          + "env"     = "production"
        }
      ~ terraform_labels                = {
          + "env"     = "production"
          + "managed" = "terraform"
        }
        # (14 unchanged attributes hidden)

        # (6 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: /tmp/tfplan********

To perform exactly these actions, run the following command to apply:
    terraform apply "/tmp/tfplan********"

stderr:
```

`effective_labels`が実際に適用されるラベルで、`labels`と`terraform_labels`はterraform内部が持つもののようなので、差分はどうしても生まれてしまいます。

## 回避策

ラベルを使わない、というのは難しいと思うのでtfmigrateの利用を一旦やめて`terraform import` `terraform apply`しましょう。
一時的に差分は出てしまいますが、applyすることで直ります。
javascriptからクリックイベントを発生させる

# 結論

　イベントを発生させるのは一般に、`const e = new Event(～);`などと記述できます。
　しかし、"click"イベント自体は（MouseEventを継承した）**PointerEvent**型なので、正しく扱うには`const e = new PointerEvent("click");`のような書き方となります[^click]。

　ターゲットのhtml要素 targetElement に対して、例えば
 ```javascript
 targetElement.dispatchEvent(new PointerEvent("click"));
 ```
 とすることで、クリックされたものとしてイベントが送り込まれます[^dispatchEvent]。

[^click]: Element: click イベント - Web API | MDN 
https://developer.mozilla.org/ja/docs/Web/API/Element/click_event#%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E5%9E%8B 

[^dispatchEvent]: EventTarget: dispatchEvent() メソッド - Web API | MDN 
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/dispatchEvent
Ubuntu22.04 + Docker + TF2.13.1 をGPUありで動かす

# Could not find cuda drivers on your machine, GPU will not be used.

どうしてもこの~~呪い~~メッセージが消えない。

## やったこと

多すぎて思い出せないくらい。
- ホストのnvidia driver入れ替え
- cuda　いろいろバージョン
- TF いろいろバージョン
-  pip install "tensorflow-gpu<2.11
- OS再インストール
- 環境変数設定
- ライブラリローカルビルド
- Dockerイメージ入れ替え（10個くらい試したが当たりを引けず）。しかし当たりはあった（後述）
：

しかし解呪はできなかった。。。

# あっさり解決

ベースのDockerイメージで動くものがありました。

2023/10 現在であれば
FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu20.04
をベースに
pip install tensorflow
で
> ＞tf.config.list_physical_devices("GPU")
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

解呪できました。

# いばらの道が好きな方
たぶん
FROM nvidia/cuda:11.8.0-base-ubuntu22.04
ベースにcudnnとか入れていっても動くかもです（というか１回動いてたのに手順をメモってなかったので再現できず）。

# TF 2.14.xは？
https://www.tensorflow.org/install/source?hl=ja#gpu
によれば 11.8 で動くはずなんですが、先ほどのイメージでpipでTFを入れると2.13.1が入っちゃいます。手で入れられるかもですがためしていません（疲れた）
「Python」 PDF ページの回転

## はじめに
PDFファイルを操作する際に、ページが逆さまになったり正しく読み取れなかったり印刷できなかったりすることがあります。そのような場合、PDFページを回転させて文書の向きを調整することができます。このチュートリアルでは、Pythonを使用してPDFページを回転させる方法について説明します。回転する際には、必要に応じて時計回りまたは反時計回りに異なる角度で回転することができます。詳細については以下をご覧ください。

## ライブラリ
* [Spire.PDF for Python](https://www.e-iceblue.com/Introduce/pdf-for-python.html)
これは独立したプロフェッショナルな Python ライブラリです。 PDF の作成、編集、変換をサポートします。

## 事前準備
* まず、[Python](https://www.python.org/downloads/) をダウンロードしてインストールします。
* Visual Studio Codeで「Extensions」をクリックし、「Python」を検索してインストールします。
* 「Explorer」-「NO FOLRDER OPENED」-「Open Folder」
* フォルダーを作成します。
* そのフォルダーに「.py」 ファイルを追加し、任意の名前を付けます。
* 「Terminal」-「New Terminal」
* 次のコマンドを入力して、[Spire.PDF for Python](https://www.e-iceblue.com/Introduce/pdf-for-python.html) と plum-dispatch v1.7.4 をインストールします。
```
pip install Spire.PDF
```
## サンプルコード
```python
from spire.pdf.common import *
from spire.pdf import *

#PdfDocument オブジェクトの作成
pdf = PdfDocument()

#PDFを読む 
pdf.LoadFromFile("C:/Users/Administrator/Desktop/Sample.pdf")

#各ページをループする
for i in range(pdf.Pages.Count):
    page = pdf.Pages.get_Item(i)

    #ページの元の回転角度を取得する
    rotation = int(page.Rotation.value)

    #ページを元の状態から時計回りに180度回転させる。
    rotation += int(PdfPageRotateAngle.RotateAngle180.value)
    page.Rotation = PdfPageRotateAngle(rotation)

#結果文書の保存
pdf.SaveToFile("C:/Users/Administrator/Desktop/Result.pdf")
pdf.Close()
```
上記のコードでは、まず**PdfDocument**オブジェクトを作成し、PDFをロードします。次に、すべてのページをループします。**PdfPageBase.Rotation.value**プロパティを使用して、ページの元の回転角度を取得します。回転角度を変更し、**PdfPageBase.Rotation**プロパティで新しい回転角度をページに適用します。最後に、結果のファイルを保存します。

---------------------------------------

このコードを実行すると、すべてのページが回転します。
ただし、特定のページのみを回転させたい場合は、すべてのページをループするのではなく、指定のページを取得することができます。
```python
# 最初のページを取得する
page = pdf.Pages[0]
```
これのパラメータは「0」から計算されます。

---------------------------------------
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/b2e5b8cc-b89f-afb1-9abb-e198d32c0182.png)
【ChatGPTニュース】『All Tools』


　どうも、カーブミラーです。

　今回は、ChatGPTの新しい機能の紹介です。

:::note info
本記事の内容は、X-Twitter上でし
か確認できていません。ChatGPT
有料版利用者のみなさんのSNSへ
の報告を楽しみにお待ちしており
ます。

　よろしくお願いしますね。
:::
　ニュースです。

　ChatGPTの
　　アップデートがあったようです。
　　　有料版のみですけど(泣)

　『All Tools』という
　　　ものらしいです。

　以下が内容についてです。

　これまでは、
　　ファイルアップロード、
　　DALL-E3、
　　Advanced Data Analysis、
　　Browse with Bingは、
　　　それぞれのセッションで
　　　　行なう必要がありました。

　それが、このアップデートで、
　　セッションの切り替えをする
　　　必要がなくなるそうです。

　入力されるプロンプトを
　　解釈して、それぞれの機能を
　　　自動的に使い分けてくれる、
　　　　というものらしい。

　順次、開放されているようで、
　　X-Twitter上では、
　　　実際に使ってみた報告が
　　　　多々、上がっています。

　無料版利用者には、
　　とても羨ましい(泣)

　なお、ファイルアップロードは、
　　PDFもアップロードできる
　　　そうです。
***
　以下が、
　　現れるであろう画像です。
![20231029_142018.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/678c6858-62b2-2b34-d31a-a958239997eb.jpeg)

　Googleレンズで
　　翻訳すると
![Screenshot_20231029-142127.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/9b5b67b8-732a-41e3-0c94-7f135783fa67.png)

***
　用途は、
　　使用者次第ですが、
　　　以下がX-Twitterで
　　　　紹介されています。

　・クレジットカード画像
　　　→デザインした画像を生成
　・写真（カピバラ）
　　　→画像生成（ピクサー風）
　・現在の天気情報
　　　→画像生成
　・画像
　　　→Pythonでパワポ資料作成
　・飛行機の発着時刻表
　　　→移動スケジュール作成
　・PDF読み込み
　　　→要約・ポイント作成
　　　→ストーリー作成
　　　→画像生成
　　　→プログラム作成
***
　ほかにも
　　いろんな使い方が
　　　出てきそうです。

　有料版利用者のみなさん、
　　ぜひ、使って、
　　　SNSにアップしてください。

　今回は、ここまで。
【AWS】AWS Cloud Questが日本語化になったのでやってみた ### 01 登録編

## はじめに
AWSにはトレーニング用にAWS学習ができるコンテンツや情報サイトがたくさんありますが、その中でもゲームベースで行うことができるコンテンツがあります。

それが[AWS Cloud Quest](https://aws.amazon.com/jp/blogs/news/aws-cloud-quest-jp-is-now-available/)です。

先日(2023/10/10)、ついに日本語化しましたので、実際にやってみたいと思います。

## 登録方法
##### 1.以下のURLにアクセスし、「ENROLL」をクリックします。
[AWS Cloud Quest: Cloud Practitioner (Japanese) 日本語版](https://explore.skillbuilder.aws/learn/course/external/view/elearning/17553/aws-cloud-quest-cloud-practitioner-japanese-ri-ben-yu-ban)

![qiita23101102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/e0614ed4-6112-24cc-3880-75f693155063.png)

##### 2.「AWS SKILL BUILDER」をクリックします。
![qiita23101103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/aa0a66bb-ecf1-96c0-45d1-d102c02557e8.png)


##### 3.「Create or Sign in」をクリックします。
![qiita23101104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/6fbcac39-8955-b053-9e5b-e6b2e8a87332.png)


##### 4.「すでにAWS BuilderIDをお持ちですか？サインイン」をクリックします。
※AWS BuilderIDを持っている場合
![qiita23101105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/1452679c-2f58-82f1-781c-bebbb769d59b.png)

##### 5.該当するメールアドレスを入力後、「次へ」をクリックします。
![qiita23101106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/9507787d-1bcd-9e96-f9cc-f010bef31057.png)


##### 6.パスワード入力後、「サインイン」をクリックします。
![qiita23101107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/95d72c3a-1a79-2503-db38-cab39b2d1669.png)

##### 7.「マイコースを表示」をクリックします。
![qiita23101108.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/9b22f3ab-eb75-653e-feb1-d3735935f58d.png)

##### 8.マイコースにある「AWS Cloud Quest」をクリックします。
![qiita23101109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/f82ebe6c-d57d-a723-cfd8-06208d70d93a.png)

##### 9.「ゲームを開始する！」をクリックします。
![qiita23101110.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/28fe1b42-4796-322c-e725-7c24a3045f3a.png)



##### 10.スタート画面が表示されます。
![qiita23101111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/85397c46-9bee-2d39-ff9b-b3ef6970a724.png)

## 日本語変更
##### 1.「歯車マーク」をクリックします。
![qiita23101112.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/43efd249-d383-4f51-feb3-7bbd4505a845.png)
##### 2.「日本語」を選択します。
![qiita23101113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/f33fd0e5-88e1-26be-5414-438518f537b9.png)

##### 3.「I Understand」をクリックします。
![qiita23101114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/be9f0c71-c3c1-da0f-901f-7e7bf5655938.png)

##### 4.「ゲーム開始」と日本語で表示されていることを確認します。  
##### 問題なければ、「ゲーム開始」をクリックします。
![qiita23101115.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/e7255db1-8c59-945d-fe43-8732965e955b.png)

## 所感
登録まで実施してきましたが、
特に難しいことはありませんでした。

次回は、ゲームを開始するまでの準備を進めていこうと思います。
JavaScriptと.NETのRegexは解釈が異なる（言語によって異なる）

JavaScriptと.NETとのRegexは、正規表現の解釈が異なります。
つまり、結果が異なることがあります。

[regex101](https://regex101.com/)で確認。

## 例
Regular Expression
`(([ABC]*)|([abc]*))?`

Test String
`ABacAB`

#### ECMAScript(JavaScript)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/acc90615-606a-bb3b-e04a-622aabd9fe8f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/a7129aef-664b-1ba3-cb1e-6ab52401b17b.png)

4つに一致。
その内、文字列に一致は3つ。
AB
ac
AB


#### .NET
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/789b6818-a0a8-0a56-a949-4f70eba8c4b9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/37263cea-6099-cc8f-1f19-cc66ba4f39cf.png)

5つに一致。
その内、文字列に一致は2つ。
AB
AB

### メモ
- JavaScriptから、.NETへコードを移植の際、ユニットテストで分かりました。テスト大事。
- 言語によって、解釈が異なるそうです。やっかいですね。
- 例にあげた文字列を、`JavaScript`のように3つに一致させる正規表現(.NET)がわかりません（この`TestString`なら、`*`を`+`に変更で可。コメントを参照）。仕方ないので、`Regex`で抽出するのはあきらめて、一文字ずつ確認するコードを作成する予定です。
huggingfaceからダウンロードしたlocal modelでembeddingしたい

 # 状況

貧乏な自分はOpenAIのエンベディングモデルを利用するには無理があった
そこでhuggingfaceにあるエンベディングモデルを利用することにした

# huggingfaceからモデルをダウンロード

今回はmultilingual-e5-largeを利用する想定

```
pip install sentence_transformers
```

```
from huggingface_hub import snapshot_download

download_path = snapshot_download(repo_id="intfloat/multilingual-e5-large", local_dir="ダウンロードしたいところ")
```


# 利用

```
pip install langchain
pip install InstructorEmbedding
```

```
from langchain.embeddings import HuggingFaceInstructEmbeddings
```


モデルの指定
```
def embedding_model():
  # em = OpenAIEmbeddings(model='text-embedding-ada-002', deployment="embedding-ada-002")
  model_name = "さっきのダウンロードしたところのパス"
  model_kwargs = {'device': 'cpu'}
  encode_kwargs = {'normalize_embeddings': True}
  em = HuggingFaceInstructEmbeddings(
      model_name=model_name,
      model_kwargs=model_kwargs,
      encode_kwargs=encode_kwargs
  )
  return em
```

今回chromaを利用しています。

実際利用
```
　persist_directory = f"db/{texts_name}"
　texts = "おかねをくれ~~"
　embeddings = embedding_model()
  vectordb = Chroma.from_documents(texts, embeddings, persist_directory=persist_directory)
  vectordb.persist()
```

# 結果

短いテキストとかならエンベディングできたんですけど
長いテキストはスペックが足りずにできませんでしたｗ

GPU付のPCを買うお金がないので詰みました😢
世はLLM時代　お金がかかる・・・
【Appsheet】Googleグループのデータを使用し表示制限を行う

## はじめに
AppsheetのEnterpriseプランであればGoogleグループごとにアプリの共有を行うことができるようなのですが、アプリの中でGoogleグループの権限を参照し表示制限をしたかったので、GoogleグループのデータをGASで取得しアプリケーションの判定として組み込みました。

## グループ情報の取得
まずGASでアプリ内の管理者データを表示させたいグループのデータを取得します。


```javascript
//スプレッドシートにメニューを追加
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu("実行");
  menu.addItem("グループ・権限取得", "getGroupMembersToSheet");
  menu.addToUi();
}
function getGroupMembersToSheet() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var groupEmail = 'データ取得したいグループのメールアドレス';
  //グループ情報取得
  var group = GroupsApp.getGroupByEmail(groupEmail);

  //スプレッドシート書き込み
  if (group) {
    var members = group.getUsers();
    
    if (members.length > 0) {
      //一行目にカラムを追加
      sheet.getRange(1, 1).setValue("メールアドレス");
      for (var i = 0; i < members.length; i++) {
        sheet.getRange(i + 2, 1).setValue(members[i].getEmail());
      }
    } else {
      sheet.getRange(1, 1).setValue('このグループにはメンバーがいません。');
    }
  } else {
    sheet.getRange(1, 1).setValue('指定したメールアドレスのグループが見つかりません。');
  }
}

```
onOpen()を実行後
スプレッドシート実行タブに「グループ・権限取得」が生成されるので実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/ddfd3560-ea39-ab83-fa56-531d71eeb66b.png)

GASのトリガーを使用し定期実行させることも可能です。
今回はgetGroupMembersToSheet関数を毎日午前0時から1時で実行させるよう設定しております。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/ac913ca9-7902-8601-3cd3-9c9db920a226.png)

## グループデータ取り込み
作成したスプレッドシートのデータをAppsheetで取り込みます。
更新や削除を行うことはないのでRead-Onlyを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/17787eed-ce4d-82a2-c6a9-7948f3f5829b.png)


## 判定作成
観覧を制限したいViewsの中の「ShowIf」でアプリ使用者のメールアドレスがグループに無い場合表示させないように記載します。
今回は「在庫一覧（管理者）」Viewを表示させないようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/875b57be-bafc-5a84-986c-2b08308bbef2.png)

作成した管理者グループデータの中にアプリユーザーが含まれている場合表示させるようにIN関数を使用し設定します。
```javascript
IN(USEREMAIL(),SELECT(管理者グループデータ[メールアドレス],true))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/7a4ddeef-0aad-2d73-ef7c-4c7c0f5f4be5.png)


## 動作確認
データソースに無いメールアドレスを指定すると
「在庫一覧（管理者）」Viewが表示されていないことが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2699599/bd2f4719-8298-7826-af4d-6e17da1c6ef1.png)

## まとめ
アプリの表示権限をテーブルとして持つと管理に別途運用コストが発生してしまうのでGoogleグループのデータでアプリ内の挙動を変更したい場合の参考になれば幸いです。
RaspberryPi 3BへのOpenCVのインストール

RaspberryPi 3B(os:Raspbian Release11)とPi Cameraを使って、画像認識をさせたいと考え、OpenCVをインストールすることにした。
色々とネットでインストール方法を探して、試したが、なぜか、Numpyがインポートできないようなメッセージが出た、OpenCVのインポートができない。
まずは、うまくいかなかったインストール方法（「import cv2」とOpenCVをインポートしたときに出たエラーメッセージなど）を示します。

■うまくいかなかったインストール
最初に、OpenCVに必要なライブラリをインストール
```
$ sudo apt-get install -y libatlas-base-dev
```
numpyモジュールもバージョンが低いとエラーになりやすいとあったので、バージョンアップしておく
```
$ pip3 install numpy --upgrade
```
最後にopencv-pythonをインストールする
```
pip3 install opencv-python
```

これで、一応、エラーなくすべてインストールは完了した。
```
$ python3
```
として、Python対話モードを起動して、Opencvをインポートできるか試してみる。
```
>>> import cv2
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/numpy/core/__init__.py", Line 24, in <module> from . import multiarray
  File "/usr/local/lib/python3.9/dist-packages/numpy/core/multiarray.py", Line 10, in <module> from . import overrides
  File "/usr/local/lib/python3.9/dist-packages/numpy/core/overrides.py", Line 8, in <module> from . import numpy.core._multiarray_umath import (
ImportError: Libopenblas.so.0: cannot open shared object file: No such file or directory
・
・
・
と続く
```
で、よくよく考えてみる。Raspbianには、Pythonはもともとインストールされている。Raspbianは、apt-getを使っている。pipを使うと、別のところにインストールされる。パスが通ってないのか？
そのあたりもいろいろと調べたが、解決しません。
で、pipでインストールした、OPencvとnumpyをアンインストールしました。
```
$ pip3 uninstall numpy
$ pip3 uninstall opencv-python
```

普通に、apt-getでインストールモジュールのアップデータを行う。
```
$ sudo apt-get update
$ sudo apt-get upgrade
```
そして、apt-getでOpenCVをインストールする。
```
$ sudo apt-get install python3-opencv
$ sudo apt-get install python3-numpy
```
Pythonの対話モードで試してみる
```
$ python
ちょっと省略
>>> import cv2
>>>
```
とエラーがでない。うまくインポートできたみたいだ。バージョンを表示させてみる。
```
>>> print(cv2.__version)
4.5.1
>>>
```
やった！。うまくいきました。
Windowsとかで、Pythonを使っていたので、ついついpipコマンドを使ってしまっていましたが、環境に応じて、モジュールをインストールしないと、うまくモジュールをインポートできないのだと、改めて思い知らされました。
IBM i 7.5でQSECOFRなのにシステム値を変更できない件

IBM i 7.x以降？では初期インストール状態ではセキュリティが強化されており、デフォルトではシステム値などを変更できなくなっています。たとえばPowerVSなどで新規インスタンス作成して、さてシステム値を変更しよう回、、な時などに今でもときどき質問があります。

例：QAUTOVRTを変更しようとしてエラーCPF18C0が発生
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/fe889397-f20b-92d2-69f8-38a73c5235a8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/b45ba15d-93fa-7af1-0999-74590c9c016d.png)



■対応策■
STRSSTコマンドからQSECOFRでサインオンして、以下の設定を変更します。
7.Work with system security を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/03759364-1807-cf04-ca89-82865de92df7.png)

Allow system value security changes を 1に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/8e010692-50ad-484e-9cf9-ac80cdd3c2d2.png)

以上でシステム値を従来通り変更可能になりました。
SSTを終了して、WRKSYSVAL, CHGSYSVAL等で目的のシステム値を変更してください。

無事QAUTOCFGを100に変更できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/79f46ca9-e5ee-e2b0-b451-baefb9bb72d9.png)

■考察■
システム値は本番業務稼働後に変更することはあまりないと思いますので、作業が完了したら
SSTのAllow system value security changes　は0に戻しておいた方がセキュリティ的にはよろしいかと思います。

■参考
PowerVS IBM i 導入後のおすすめシステム値（ほか）設定変更
https://qiita.com/gomAnomalocaris/items/80013b1407dc6be468b7
動画サイトで使われるDVRとは何か?

## DVRとは？

DVR（デジタルビデオレコーダー）は、テレビ番組やライブストリーミングの映像をデジタル形式で録画して、後で見られるようにする装置や機能のことを指します。

これを使えば、「あ、これ見たかった！」という番組やイベントをリアルタイムで見逃しても、後からゆっくりと視聴することができます。

## ストリーミングサイトでのDVRの利点

ストリーミングサイトでは、DVR機能を使ってライブの映像を一時停止したり、巻き戻して見たりすることができます。
これにより、視聴者は自分のタイミングでコンテンツを楽しむことが可能です。

## JavaScriptでDVRを使う方法

JavaScriptを使ってウェブページ上でDVR機能を実装することもできます。例えば、ライブストリーミングのビデオを制御する小さなプログラムを作ることができます。

## 簡単な例

```html
<video id="video" controls></video>
<button onclick="rewind()">10秒巻き戻し</button>
<button onclick="forward()">10秒早送り</button>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1.0.11"></script>
<script src="script.js"></script>
```

上のコードは、ウェブページ上にビデオプレイヤーと「10秒巻き戻し」、「10秒早送り」のボタンを作ります。そして、HLS.jsというライブラリを使ってビデオをコントロールします。

```javascript
const video = document.getElementById('video');
const hls = new Hls();
hls.loadSource('your-live-stream-url.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
  video.play();
});

function rewind() {
  video.currentTime = Math.max(video.currentTime - 10, 0);
}

function forward() {
  video.currentTime = Math.min(video.currentTime + 10, video.duration);
}
```

上のJavaScriptコードは、ビデオを制御するためのプログラムです。ビデオを10秒巻き戻したり、10秒早送りしたりする関数を提供しています。

このようにして、JavaScriptとHLS.jsを使うことで、ウェブページ上で簡単にDVR機能を実装することができます。
Emotion: CSS in JSのフレームワーク




Emotionは、JavaScriptの中でCSSを書くことを可能にするフレームワークです。

ReactなどのJavaScriptライブラリと一緒に使うことで、効率的で美しいスタイルをアプリケーションに適用することができます。

2023/10/31現在、以下のようなサイトで利用されています。

![スクリーンショット 2023-10-31 11.18.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/bc328680-020b-8652-24be-d967b5cc686e.png)

## 1. インストール
Emotionを使い始めるには、まずパッケージをインストールする必要があります。
```bash
npm install @emotion/react @emotion/styled
```
👉 **ポイント:** npmを使ってパッケージをインストールすることで、Emotionをプロジェクトに追加できます。

## 2. スタイルの適用
Emotionを使ってスタイルを適用する基本的な方法は、スタイル付きのコンポーネントを作成することです。
```javascript
import styled from '@emotion/styled'

const Button = styled.button`
  background-color: hotpink;
  font-size: 16px;
`
```
👉 **ポイント:** `styled` 関数を使ってHTMLタグを指定し、テンプレートリテラル内でCSSを書くことで、スタイル付きのReactコンポーネントを作成できます。

## 3. プロップを使ってスタイルを変更
Emotionでは、プロップを使って簡単にスタイルを動的に変更することができます。
```javascript
const Button = styled.button`
  background-color: ${props => props.primary ? 'hotpink' : 'white'};
`
```
👉 **ポイント:** プロップを使って条件に応じたスタイルを適用することができます。この例では、`primary` プロップが `true` の時に背景色を `hotpink` に設定しています。

## 4. グローバルスタイルの適用
Emotionを使って、アプリケーション全体に適用されるグローバルスタイルを設定することも可能です。
```javascript
import { Global, css } from '@emotion/react'

const globalStyles = css`
  body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif;
  }
`

function App() {
  return (
    <>
      <Global styles={globalStyles} />
      {/* 他のコンポーネント */}
    </>
  )
}
```
👉 **ポイント:** `Global` コンポーネントを使って、CSSをグローバルに適用することができます。これにより、アプリケーション全体で共通のスタイリングを設定できます。

以上がEmotionの基本的な使い方です。
これらのポイントを押さえることで、美しいスタイルを簡単に適用することができるようになります。


Emotionは柔軟で強力なツールなので、ぜひ試してみてください！
SwiftとFirebaseを使ってログイン認証作成

使用した技術Firebaseを使用してログイン機能を実装していく
1.まずはどんな流れで処理を作成することができるのか大まかに理解する
FirebaseをAppleプロジェクトに追加する

以下のURLの手順通りに作業を行う
https://firebase.google.com/docs/ios/setup?hl=ja

ここまでの作業が完了したら、ソースコードを書いていく。

2.実装

2-1.AppDelegateの作成
1の手順の中にFirebaseApp共有インスタンスを構成するとあるため、AppDelegateを作成しなければならない。
SwiftUIを使用している場合には、AppDelegateは作成されないため自分で作成する必要がある。

:::note info
インフォメーション
AppDelegateとはiOSアプリ起動時など特定のライフサイクルの中で呼ばれる処理のこと。
:::

```swift:qiita.Swift
// 以下のソースコードをプロジェクト名App.swiftファイルに追加する
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
```

```swift:qiita.Swift
@main
struct morutokuApp: App {
    // 追加されたソースコード
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    var body: some Scene {
        WindowGroup {
            NavigationView{
                ContentView()
            }
        }
    }
}
```

:::note warn
警告
上のソースコードを追加しただけだとAppDelegateクラスが作成されていないため、エラーとなる。
したがって、クラスを作成していく。
:::

```swift:qiita.Swift
// AppDelegateクラス
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication,
                    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // FirebaseApp共有インスタンスの構成
        FirebaseApp.configure()
        return true
    }
}
```

2-2.新規ユーザ作成

ログインにまつわるドキュメントURL:https://firebase.google.com/docs/auth/ios/manage-users?hl=ja

今回はメールアドレスとパスワードを作成して、新規ユーザー作成を行う。

```swift:qiita.Swift
// Auth.auth().createUserはFirebaseのPackageで定義されているもの
// ドキュメントを参考にログインにまつわる処理を作成することができる
Auth.auth().createUser(withEmail: mail_s, password: password_s) { result, error in
                        if let user = result?.user {
                                let request = user.createProfileChangeRequest()
                            request.displayName = mail_s
                                request.commitChanges { error in
                                    if error == nil {
                                        user.sendEmailVerification() { error in
                                            if error == nil {
                                                print("仮登録画面へ")
                                            }
                                        }
                                    }
                                }
                            }
                    }
```


ここまでの処理を行うことでFirebase上に新規ユーザーが作成されることを確認した。

3.ログイン認証について
参考URL:https://firebase.google.com/docs/auth/ios/start?hl=ja

ログインボタンを実装し、ログインボタンを押下した時に以下の処理を記載する。
```swift:qiita.Swift
Auth.auth().signIn(withEmail: mail_s, password: password_s) { result, error in
// ログインが成功後の処理を以下に記載していく
                    }
```
ユーザーが存在していれば、ログインが成功する。


続きはアプリの作成が進んだら記事にします。
決定木からlightGBMまで、なぜLightGBMが機械学習で最も広く使われているのかについて説明します

機械学習の回帰と分類タスクに対しては、ほとんどの場合はlightGBMが使われています。
今日は決定木からLightGBMまでの流れと、その過程でどのような改善がなされたのかについて、木モデルの全体像を紹介したいと思います。
木モデルに関して完全に理解しているわけでもないので、間違っているところがあればぜひ教えていただきたいです。

## ①決定木
まず木モデルで一番ベースとなっているのは決定木です。
決定木とは、データの特徴ごとの優先順位や分割ポイントを学習して、データをカテゴリに分類または数値予測を行うモデルです。
木は一個しかないために、非常に過学習しやすいかつ精度も低いというのは特徴となります。
それを改善するために、Bagging（複数モデルの平均値を取ること）の考え方に基づいて、ランダムフォレスト（RandomForest）というモデルが生まれました。


## ②ランダムフォレスト
ランダムフォレストは、一回で複数個の決定木を作って、それぞれの結果の平均値/多数決を取ることで、過学習しやすい問題を解決できました。
ですが、たくさんの決定木を作っても、個々の決定木の精度には限界があり、全体としての精度は必ずしも非常に高くなるわけではありません。
精度をさらに向上させるために、Boostingというアプローチが考えられました。

## ③GBDT
最初公開されたBoosting手法のモデルはGBDTとなります。
GBDTも決定木で予測しますが、１回で複数個の決定木を作るではなく、一つずつ順番に作成します。
各決定木は、前の決定木の予測結果の誤差を学習対象とし、これを繰り返すことで全体としてのモデルの精度を向上させます。
最初の決定木がデータの大まかな特徴を学習して、以降の決定木が誤差を補正していく流れです。
最後すべてのモデルの結果を合わせると、非常に高い精度に達します。

## ④XGBoost
GBDTはモデルより考え方に近いです。GBDTの考え方を元に使いやすくパッケージ化されたモデルはXGBoostです。
精度が低いという問題点はXGBoostで解決されましたが、決定木を一つずつ順番に作成する必要があるため、
処理時間が非常に長いという新たな問題が生じました。

## ⑤LightGBM
そこで、2017年にMicrosoftがLightGBMを公開しました。
LightGBMも決定木を一つずつ作る仕組みですが、XGBoostを基に様々な調整を行いました。
主に改善された点は２つあります。（他にも多くの改善がありますが、最も重要なのは以下の2点です）
1. Goss（Gradient-based One-Side Sampling）という計算方法の導入
非常に複雑な計算方法ですが、簡単的に言えば、誤差の学習順番をモデル自身で優先順位をつけて、優先順位が高いものから学習する仕組みです。
ある程度の精度に達したら、残りの誤差を学習しても精度が大きく変わらないと判断し、学習を止めます。一方で、XGBoostは特に優先順位などなくて、全ての誤差を学習します。
2. 連続値の特徴量を離散値に変換
例えば、「10」,「11」,「12」,「13」,「14」みたいな特徴があれば、これらを「10-14」という一つの特徴量にまとめます。
そうすると、少し精度が落ちますが、データの計算量や学習量は大幅に減少できます。
これら２点の改善により、精度がほんのわずかだけ落ちますが、処理時間はXGBoostの数十倍短くなります。
LightGBMは公開されてから、多くの予測・回帰問題はLightGBMしか使わないようになりました。

ちなみに、今LightGBMとXGBoostはあまり処理時間の差がないです。XGBoostもLightGBMが改善されたところを取り入れて自分のモデルに直しましたので、現在ではどちらにしてもほぼ差がないです。

参考イメージとして以下の図でまとめました。

![10-31-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/902a0a8b-16e2-0cdf-fb30-64e7faea399e.png)




LightGBM論文:

https://proceedings.neurips.cc/paper/2017/hash/6449f44a102fde848669bdd9eb6b76fa-Abstract.html

END
未経験が1ヶ月で基本情報技術者試験受けてみた！

# はじめに
現在プログラミングスクールで学習していますnishiharaと申します。
スクール内イベントで「Advent Calender Challenge」に参加しており、最終日を務めさせて頂きます。

<br>

https://advent-calendar-challenge.onrender.com


# 目次
<table>
  <thead>
    <tr>
      <th>章</th> <th>タイトル</th>
    </tr>
  </thead>
  <tr>
    <td> 1 </td> <td>基本情報技術者試験とは？</td>
  </tr>
  <tr>
    <td> 2 </td> <td>勉強時間</td>
  </tr>
  <tr>
    <td> 3 </td> <td>勉強方法</td>
  </tr>
  <tr>
    <td> 4 </td> <td>エンジニアに必要になりそうな知識</td>
  </tr>
  <tr>
    <td> 5 </td> <td>受けた後の感想</td>
  </tr>
  <tr>
    <td> 6 </td> <td>終わりに</td>
  </tr>
</table>

# 基本情報技術者試験とは？
IPA(情報処理推進機構)が実施、運営する国家資格です。
科目Aは90分60問の4択形式、科目Bは100分20問の多項目選択形式、それぞれ1000点満点中600点以上で合格になります。

https://www.ipa.go.jp/shiken/kubun/fe.html


# 勉強時間
期間は約1ヶ月、勉強時間は80時間程度勉強しました。
スクールのカリキュラムでTCP/IP辺りを少し学んだといった感じです。
結果としてはA試験、B試験共に1割程度合格点に足らず不合格かなといった感じでした...(最終的な合否発表はまだでておりません)

# 勉強方法
### ・[【基本情報技術者試験YouTuber】すーさん](https://www.youtube.com/@kihonzyouhou)
科目Bのアルゴリズムで躓く人が多いと他の記事でも言っている人が多かったのでYoutubeで解き方を学びました。
初見で過去問を見た時は解き方すら分からなかったのですが、どういうふうに解けばいいのか流れを覚えられました。

### ・[令和05年 イメージ＆クレバー方式でよくわかる 栢木先生の基本情報技術者教室 情報処理技術者試験](https://amzn.asia/d/2ofHcOh)
基本情報技術者試験について何も知識がない状態でしたので、とりあえず1周し試験に必要な知識を入れました。
過去問解いた後で間違った所の理解深めにも役立ちました。
ページ数が500p以上と厚めですが、出題頻度に時々、必須、超重要と分かれていて最悪絞って学習すれば辛くないと思いながら進めました。
法務関連は苦手でした...


### ・[令和05年【下期】基本情報技術者 パーフェクトラーニング過去問題集](https://amzn.asia/d/3KlwxWG)
科目B対策で購入しました。長いアルゴリズム問題についても詳しく解説があり分かりやすかったです。
科目A対策もできて助かりました。

<br>

Youtubeと栢木先生の参考書を同時並行で進め約2週間、後半2週間で過去問を解きました。

# エンジニアに必要になりそうな知識
私自身が試験勉強している際に将来的に必要になりそう、知っておいて損はないかなと思ったところを書いてみます。

### ・アルゴリズム
実務とかでも必要な知識かなと思いました。
特に繰り返し処理で、現時点でこの変数には何が入っていてどう分岐するのか？等を考える論理的思考能力は養えられたかなと思いました。

### ・IPアドレス周り
この辺りは試験勉強する前まではなんとなくといった感じから、大まかに理解できたかな〜といった感じです。
AWS等クラウド系のサービスを使うときに役に立つのかな〜と考えていました。


### ・暗号技術（共通鍵、公開鍵)
個人的にとても興味深かったです！
公開鍵方式でもRSA暗号方式、楕円曲線暗号方式など様々な種類があり、いつかこの辺りを深く学習してみたいなと思えたほどでした。


# 受けた後の感想
### ・過去問をもっと解けばよかった
サンプル問題合わせ4年分しか解いていなかったので試験中ももっとやっとけば似た傾向が出てたのでは、と思ってました。
後3、4年分くらい解ければ不安を感じずにいけるかなと思いました。

### ・時間を測って問題を解くべし
科目Aは時間的に余裕がありましたが、科目Bは時間が足らずといった感じになってしまいました。
過去問を解く際に本番と同じ時間で設定して解くといったことをもっとしとけばな、と思いました。

### ・不得意問題にもっと注力すべきだった
科目Bでいうと、スタックやキュー、情報セキュリティの問題には自信がありました。
逆にリスト操作、探索系がとても弱かったです。
その辺りをもっとしっかり対策しておけばと思いました。
こちらの[基本情報技術者過去問道場](https://www.fe-siken.com/)では分野別に解けるので使うべきだったなと思っています。

<br>

全て基本的な内容だと思いますが、こうした基本的な事をコツコツできれば合格できるのかなと思いました。

# 最後に
不合格という形で終わってしまい、とてもショックでした。
正直、記事にするのも恥ずかしく悔しいですが、今後受験される方の参考になれば幸いかなと思います。
失敗には再現性があると聞くのであまりネガティブにならず進んでいきます。
また、Web系エンジニア転職で資格はあまり重要視されないと聞いたこともありますが、知識については間違いなく知っていて損はないはず！と思いながら学習していました。
来月か再来月受験するのでその際は合格して追記できればと思います!

<br>


最後に、このような素敵な企画を考えて頂いた[けーすけさん](https://twitter.com/saku0suke)、ありがとうございました！
jest-dom で \u00a0 (&nbsp;) をチェックする方法

testing-library で単体テストを作成している場合の話です。

単体テストで、`\u00a0` (`&nbsp;`) が表示されていることを確認したい場合があります。例えば選択肢のラベル。空の選択肢を表示したいのだけど、空文字だと高さが確保されないので、`\u00a0` を使用するという場合があります。

テキストのチェックには、testing-library/jest-dom の `toHaveTextContent()` がよく使われますが、`\u00a0` についてはハマります。

`expect(node).toHaveTextContent('\u00a0');`

と記載しても、チェックされません。`toHaveTextContent()` は、デフォルトで、テキストに対して `text.replace(/\s+/g, ' ').trim()` の処理を行います。その上でチェックを行います。

`toHaveTextContent()` には `normalizeWhitespace` というオプションがあって、これを false にすることで `text.replace(/\s+/g, ' ').trim()` の処理を抑制できます。

`expect(node).toHaveTextContent('\u00a0', {normalizeWhitespace: false});`

残念ながら、これでも `\u00a0` はチェックできません。抑制しても `text.replace(/\u00a0/g, ' ')` の処理が働いてしまうからです。つまりどうやっても `\u00a0` は変換されてしまいます。

この処理を理解した上でスペースのチェックで諦めるか

`expect(node).toHaveTextContent(' ', {normalizeWhitespace: false});`

`toHaveTextContent()` を使わない

`expect(node.textContent).toEqual('\u00a0');`

のいずれかになります。
Cloud SQLの一部のデータを毎月保存しなさいと言われたら

# はじめに

仕事をしていると、Cloud SQLの中の一部のデータを毎月保存しておいてくれと言われるのは、稀に良くあると思います。

## 最初に思いついたアーキテクチャ

私が最初に思いついたのは、以下のようなアーキテクチャです。

1. Cloud SQLのエクスポート機能（※1）を使い、必要な情報をCloud Storageに保存するスクリプトを作成
1. 先ほどのスクリプトをCloud Functionsに登録
1. Cloud Schedulerから先ほど作成したスクリプトを定期実行

※1
Cloud SQL for MySQL から CSV ファイルにデータをエクスポートする

https://cloud.google.com/sql/docs/mysql/import-export/import-export-csv?hl=ja#export_data_to_a_csv_file_from

世は大クラウド時代、一見難しそうな依頼もこんな簡単にできてしまうことに、感謝の念を禁じ得ません。
しかし、私は極度に怠惰な人間でございますので、上記のアーキテクチャでも「結構やりたくない」という感情の芽生えを抑えることができなかったのです。

## 最終的なアーキテクチャ

調査をしていたところ、とんでもない方法が見つかりました。

1. BigQueryから、Federated QueriesでCloud SQLの情報を抽出し、EXPORT DATA関数を使ってCloud Storageに保存
1. Big QueryのScheduled Queryを使い定期実行

完全に勝利しました。
Cloud Storageを作成し、あとはSQL一本書いて終わりです。
繰り返しますが、完全に勝利です。
全てのエンジニアに幸あれ。

```sql
EXPORT DATA
  OPTIONS(
    uri='gs://bucket/folder/*.csv',
    format='CSV',
    overwrite=true)
AS (
  SELECT
    *
  FROM
    EXTERNAL_QUERY('project-id.locations.connection-id',
      '''SELECT * FROM users LIMIT 10;''')
);
```

https://cloud.google.com/bigquery/docs/exporting-data?hl=ja#export_table_data
【Github】レビュワーになったPRのみをフィルタリングするtips

# できるようになること
* 自分がレビュワーになったPRを取得
* コメント済みのPRももれなく取得 <- これ大事
# やり方
自分がレビュワーになったPRをフィルタリングする時って、

```
is:open is:pr review-requested:{user name}
```

のようにやるのがよくネットで挙がってくる方法だと思いますが、これだと一度コメントしたらレビュー済みって扱いになって再レビューのボタンを押さないと上記の検索クエリではヒットしなくなってしまいます。

なので、自分に関連するPRを全件取得して、そこから自分の分を除外してあげます。

```
is:open is:pr involves:{user name} -author:{user name}
```
`involves`を使うことで、自分に関連したIssue及びPRを取得できます。
さらに検索クエリの前にハイフン（「-」）をつけることによってその検索結果を除くことができるので、自分が作成したPRを指定してあげたら完成です。

# おまけ
aproveしたやつを表示させないようにするには以下を追加してあげればOK
```
-review:approved
```

# 公式リファレンス
* involvesについて
  * https://docs.github.com/ja/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-a-user-thats-involved-in-an-issue-or-pull-request
* 「-」による検索除外機能について
  * https://docs.github.com/ja/issues/tracking-your-work-with-issues/filtering-and-searching-issues-and-pull-requests#about-search-terms
Oracle Analytics Cloud：移動平均を求める

# はじめに
売上金額や売上数量などの推移を分析する際に、トレンドを見るために移動平均を計算してみます。
ここでは、当月を含む一定期間の平均値を求めます（単純移動平均）。

# 使用するデータ
こちらチュートリアルからダウンロードできるSample_order_lines.xlsxを使用します。

https://docs.oracle.com/en/cloud/paas/analytics-cloud/tutorial-export-to-excel/index.html#before_you_begin

# 販売金額の推移を見てみる
sample_order_liensデータセットを使用してワークブックを作成します。
「Order Date」を展開し「月」を選択し、コントロールキーを押しながら「Sales」も同時に選択します。
そのまま2つの列をキャンバスにドラッグ＆ドロップして折れ線グラフを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/9bba510f-6a37-c77f-34c6-476ba356f185.png)

# マイ計算で計算（移動平均）の作成
「マイ計算」を右クリックして表示されたメニューから「計算の作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/7a23c6ab-abb1-7190-d4c7-3c27090843a4.png)
「名前」に任意の名称を入力し（例えば「Sales 移動平均」）、式を入力します。
ここでは、12ヶ月分の移動平均を求めることとし
「mavg(Sales, 12)」という式を入力しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/c4d27371-2429-93e1-03f2-61d9870a4046.png)
「保存」をクリックします。
作成した式を折れ線グラフに追加しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/9278e91c-c777-3b7d-3b44-d19109d7ffd9.png)

# パラメータで区間の変更を容易にする
移動平均の期間をパラメータを使用して簡単に選択できるようにしてみます。
パラメータに移動し、追加（＋）をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/67a30b1b-4857-3654-dc3e-9e92f5f99a5e.png)
名前を「区間」にします。
データ型は「整数」にします。
使用可能な値を「値」として、「3」「6」「12」を追加します。
初期値は「値」として、「12」にします。
すべて入力できたら「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/b2e8a738-3201-ac5a-a445-fd076fba01a7.png)
ビジュアライゼーションから、ダッシュボード・フィルタを折れ線グラフの上にドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/b2e36c9c-0c4a-7986-f2d5-ed678e82de1e.png)
もう一度、パラメータに移動して先程作成した「区間」パラメータをダッシュボード・フィルタにドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/e2b8b95f-5c16-c905-141e-b8bdd42fe260.png)
今のところ、パラメータの値を切り替えても折れ線グラフは変化しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/0b6a97e8-1195-cb26-17af-4a45cb7703d5.png)
先程作成した計算式を改造して、パラメータの値を参照するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/5e7b5859-7e6b-b129-8da8-73b2c91db79e.png)
第二引数の「12」を削除して代わりに「@parameter」と入力すると作成済みのパラメータのリストが表示されるので「区間」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/a5f8623a-38e8-c31a-8e69-0b5aed66aea2.png)
デフォルト値を12として、「保存」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/1346f87e-672f-cc7d-be56-9e860e6c5d01.png)
折れ線グラフのプロパティで、タイトルをカスタムに変更し「Sales 移動平均（@parameter("区間")ヶ月）」と入力しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/a2c989ae-5a21-9c8b-335c-3cceb03967b9.png)
これで、ダッシュボード・フィルタでパラメータの値を変更することで、移動平均を示すオレンジの折れ線が変化しタイトルも変更されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/4d869e16-42b5-9988-426d-e71460085e51.png)
Docker_CheatSheet

## Dockerfileの構成

```docker
# ubuntu:18.04 の Docker イメージからレイヤを作成
FROM ubuntu:18.04

# Dockerクライアントで操作しているディレクトリから、ファイルを（コンテナのレイヤに）追加
COPY . /app

# RUN はアプリケーションをmakeで構築/Dockerfileからimageを作成する時に実行
RUN make /app

# CMD はコンテナ内で何のコマンドを実行するか指定/DockerイメーシからDockerコンテナを作成される時に実行
CMD python /app/app.py

# bashを使う方法
SHELL ["/bin/bash", "-c"]
```

## Dockerfileを使用してDockerイメージをビルド

```bash
docker image build -t {イメージ名:タグ名} {Dockerfileのディレクトリ}

docker image build -t test-image:v1 .
```

- `t`オプションを使用すると、イメージ名(REPOSITORY)とタグ(TAG)を指定できます。
- `t`オプションを使用しない場合、イメージ名(REPOSITORY)とタグ(TAG)の値は`<none>`になります。

## Dockerイメージの一覧

```bash
docker image ls # docker imageの一覧を表示
REPOSITORY        TAG      IMAGE ID       CREATED             SIZE
<none>            <none>   a086e6cb87f0   40 seconds ago      800MB
test-image        v1       806faed5d0a8   About an hour ago   800MB
```

## Dockerイメージを使って、作成実行

```bash

# docker container run [options] イメージ名:[タグ名]
docker container run --name {コンテナ名} -it {image名} /bin/bash

docker container run --name test-container1 -it test-image:v1 /bin/bash

root@71fdfe8dfb61:/# cat /etc/issue
Ubuntu 18.04.6 LTS \n \l
```
## コンテナの作成

```bash
# -pを使用してポートを開くことも可能　EX）　ginでは8080ポートを使用するので　XXXX:8080(gin)
docker container create　　-p 8080:8080  --name {コンテナ名} -it {image名} 
```


## コンテナの起動

```bash
docker container start {CONTAINER IDまたはコンテナ名}
```

## コンテナのbash、shに入る

```bash
docker exec -it {CONTAINER IDまたはコンテナ名} /bin/bash
docker exec -it {CONTAINER IDまたはコンテナ名} /bin/sh
```

## コンテナに入る

```bash
$ docker attach {CONTAINER IDまたはコンテナ名}
```

## コンテナの一覧

```bash
docker ps
実行中のコンテナのみ
docker ps -a
```

## コンテナを削除

```bash
docker rm -f {CONTAINER ID or コンテナ名}
```

## Dockerイメージの削除

```bash
docker rmi {IMAGE ID or イメージ名}
```
plunkerでd3 その11

# 概要
plunkerでd3やってみた。
練習問題、やってみた。

# 練習問題
v5でcluster表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/81b0b93f-7d82-2c8a-b474-d59893040bf8.png)


# サンプルコード

```

var diameter = 960,
  radius = diameter / 2,
  innerRadius = radius - 120;
var cluster = d3.cluster().size([360, innerRadius]);
var line = d3.radialLine().curve(d3.curveBundle.beta(0.85))
  .radius(function(d) { 
		return d.y; 
	}).angle(function(d) { 
		return d.x / 180 * Math.PI; 
	});
var svg = d3.select("body").append("svg").attr("width", diameter)
  .attr("height", diameter).append("g")
  .attr("transform", "translate(" + radius + "," + radius + ")");
var link = svg.append("g").selectAll(".link"),
  node = svg.append("g").selectAll(".node");
function packageHierarchy(classes) {
  var map = {};
  function find(name, data) {
    var node = map[name], 
      i;
    if (!node) 
		{
      node = map[name] = data || {name: name, children: []};
      if (name.length) 
			{
        node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
        node.parent.children.push(node);
        node.key = name.substring(i + 1);
      }
    }
    return node;
  }
  classes.forEach(function(d) {
    find(d.name, d);
  });
  return d3.hierarchy(map[""]);
}
function packageImports(nodes) {
  var map = {},
    imports = [];
  nodes.forEach(function(d) {
    map[d.data.name] = d;
  });
  nodes.forEach(function(d) {
    if (d.data.imports) 
      d.data.imports.forEach(function(i) {
        imports.push(map[d.data.name].path(map[i]));
      });
  });
  return imports;
}
d3.json("lib/flare.json").then(function(data) {
  var root = packageHierarchy(data).sum(function(d) { 
		return d.size; 
	});
  cluster(root);  
  link = link.data(packageImports(root.leaves())).enter().append("path")
    .each(function(d) { 
			d.source = d[0], 
      d.target = d[d.length - 1]; 
		}).attr("class", "link").attr("d", line);
  node = node.data(root.leaves()).enter().append("text")
    .attr("class", "node")
    .attr("dy", "0.31em")
    .attr("transform", function(d) { 
			return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); 
		}).attr("text-anchor", function(d) { 
			return d.x < 180 ? "start" : "end"; 
		}).text(function(d) { 
			return d.data.key; 
		});      
}).catch(function(error) {
	alert("ng")
});




```

# 成果物

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


以上。
plunkerでd3 その10

# 概要
plunkerでd3やってみた。
練習問題、やってみた。

# 練習問題
v5でforceSimulationを表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f4d61dfe-9bf7-36f7-f815-09d3e78d6639.png)


# サンプルコード

```

var src = document.getElementById('node');
var src2 = document.getElementById('link');
var blob = new Blob([src.value], {
    type: "text/csv"
});
var url = URL.createObjectURL(blob);
function process_network(nodesData, linksData) {
  var link = d3.select("svg").selectAll("line").data(linksData).enter().append("line").attr("stroke-width", 1).attr("stroke", "black");
  var node = d3.select("svg").selectAll("g").data(nodesData).enter().append("g").call(d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended));
  node.append("circle").attr("r", 10).attr("stroke", "black").attr("stroke-width", 1.5).attr("fill", "peachpuff");
  node.append("text").attr("text-anchor", "middle").attr("dominant-baseline", "middle").style("fill", "gray").text(function(d) {
    return d.id;
  }).append("title").text(function(d) {
    return d.id;
  });
  var simulation = d3.forceSimulation(nodesData).velocityDecay(0.3).alpha(0.7).force("link", d3.forceLink().distance(130))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(200, 200));
  simulation.nodes(nodesData).on("tick", ticked);
  simulation.force("link").links(linksData);
  function ticked() {
    link.attr("x1", function(d) {
      return d.source.x;
    }).attr("y1", function(d) {
      return d.source.y;
    }).attr("x2", function(d) {
      return d.target.x;
    }).attr("y2", function(d) {
      return d.target.y;
    });
    node.select("circle").attr("cx", function(d) {
      return d.x;
    }).attr("cy", function(d) {
      return d.y;
    });
    node.select("text").attr("dx", function(d) {
      return d.x;
    }).attr("dy", function(d) {
      return d.y + 40;
    });
  }
  function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }
  function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }
  function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }
}
d3.csv(url).then(function(data) {
  var node = [];
  var link = [];
  for (var i = 0; i < data.length; i++)
  {
    node.push({
      id: data[i]['tosi'] + data[i]['tiku']
    });
  }
  var data2 = src2.value.split("\n");
  for (var i = 0; i < data.length; i++)
  {
    var o = data2[i].split(",");
    link.push({
      source: o[1], 
      target: o[0]
    });
  }
  process_network(node, link);
});




```

# 成果物

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


以上。