OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Glue Crawlerの設定方法

## はじめに
GlueCrawlerの設定周りを調査したので、設定内容についてまとめていきます。
今回はS3のCSVデータをAthenaからクエリ出来るように設定することを想定しています。

## GlueCrawlerとは
DBやS3などからメタデータを取得し自動でデータカタログを作成してくれるツールでスキーマの更新やパーティションの追加なども行ってくれます。

## 事前準備
データカタログを登録するデータベースを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/503941ea-e6ed-8676-578d-714511cfe0f3.png)

s3にcsvファイルを用意します。
(作成されるテーブル名は指定したバケットのディレクトリ名になるので注意する。)

## Step1
Crawlerの名前を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/adfc0dcc-c1ce-e9e4-b4f5-509f94cb8c90.png)

## Step2
#### Data source configuration
データカタログの元となるデータソースを選択します。
既に既存のテーブルがデータカタログに登録されている場合はYesを選択しますが、今回はs3のデータから新規でテーブルを作成するのでNot yetを選択します。
#### Custom classifiers
非標準フォーマットのデータや複雑なスキーマの場合にはclassifiersを作成し設定することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/d9241962-fb19-ed1d-33d5-48b61d87086e.png)

#### Data source
S3を選択します。S3以外にJDBCやDynamoDBなどを指定することも可能です。
#### S3 path
S3のpathを入力します。
#### Subsequent crawler runs
**Crawl all sub-folders**
すべてのサブフォルダを毎回クロールする方法で、データ変更の頻度が高い場合や、全体的な確認を行いたい場合に適しています。
**Crawl new sub-folders only**
新たに追加されたサブフォルダのみをクロールする方法で、効率的でリソースの節約になります。
**Crawl based on events**
S3のイベントを使ってクロールをトリガーする方法で、リアルタイムでのデータ更新に対応し、処理の無駄を省きます。
Crawl new sub-folders onlyの場合、カラムの更新やパーティションの追加がされないので今回はCrawl all sub-foldersを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/d21bb8ba-6f43-dc30-4205-5c8060312abc.png)

## Step3
crawlerを実行するIAM roleを設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/a1e8b362-cd34-53f1-98f4-f96a0616220f.png)

## Step4
#### Target database
事前準備として作成したデータベースを選択する。
#### Table name prefix
クローラーで作成されるテーブル名はS3の親ディレクトリ名の名前になりますが、テーブル名にプレフィックスを追加することが可能です。
#### Maximum Table Threshold
クローラーが生成できる最大テーブル数を指定することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/358e2e66-5a9c-d22d-001e-6651c1c99f12.png)

#### S3 schema groupingAdvanced options
指定されたS3パス以下のすべてのオブジェクトに対して、互換性のあるスキーマを1つのテーブル定義にまとめる設定。
#### Table Level 
データの階層構造に基づいてテーブルの作成位置を決定する設定。
#### When the crawler detects schema changes in the data store, how should AWS Glue handle table updates in the data catalog?
スキーマの変更を検出したときに、データカタログ内のテーブルの更新をどのように処理するかを決定する設定。
#### Update all new and existing partitions with metadata from the table
クローラーが新しいパーティションや既存のパーティションのメタデータをテーブルから更新する際の設定。
#### How should AWS Glue handle deleted objects in the data store?
データストアからオブジェクトが削除された場合の設定。
#### Create partition indexes automatically
自動パーティションインデックス作成の設定。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683091/c9789935-054f-362e-b436-642d1b9d8403.png)

#### Crawler schedule
手動実行でのOn demand以外にcron形式で設定することが可能です。

## 最後に
Glue Crawlerの具体的な設定手順と項目の説明を記述しました。
作成したCrawlerを実行するとAthenaで対象のcsvデータが確認できるようになります。
ぜひ試してみてください。
【crxjs/vite-plugin】chrome-extensionとReactの速攻開発設定

## crxjs/vite-pluginを使うモチベーション
chrome-extensionを作成する際、HTML、CSS、JS等を配置すれば作成できるのですが、これをReactで開発できたら、アイテムの反復表示やインタラクティブな操作を素早く実装できそうです。  
それを可能にしてくれるプラグインが、`crxjs/vite-plugin`になります。

 
今回のサンプル
https://github.com/tonakai-it/extension-with-vite-sample
## インストールする

```bash
pnpm create vite extension-with-vite-sample --template react-ts
cd extension-with-vite-sample && pnpm i

pnpm i -D @crxjs/vite-plugin@beta
pnpm i @types/chrome @extend-chrome/storage
```

## 設定例

```diff:vite.config.ts
...

+ import { crx, defineManifest } from "@crxjs/vite-plugin";
+ import { manifest } from './manifest'

export default defineConfig({
  plugins: [
    react(),
+   crx({ manifest: defineManifest(manifest) })
  ],
})
```

manifest.tsに切り出しています。型のサポートやコメント等付けられるので、jsonよりtsにしています。satisfiesなのは、一般的な型定義方法(変数名の後の`:Type`)だとcrxの`defineManifest`と噛み合わせが悪かったからです。
```typescript:manifest.ts
export const manifest = {
  manifest_version: 3,
  name: "extension-with-vite-sample",
  version: "0.0.1",
  action: {
    default_popup: "index.html",
  },
  options_page: "option.html",
} satisfies chrome.runtime.ManifestV3
```

## develop or build

```bash
pnpm run dev
# OR
pnpm run build
```

- distディレクトリをブラウザ拡張機能として読み込み
やる気を出す

# とにかくやれ！！
### いますぐやれ！！

とある画像を壁紙にすると仕事が捗ると話題である。
やる気は脳の `側坐核` が司っているとされており、その `側坐核` の活動は `やり始める` ことによってスイッチが入るので、やる気を出すための作戦として `とにかくやれ！！` は理に適ったものと考えられる。

参考:
https://x.com/Edwise3/status/1862109773942165845
https://automaton-media.com/articles/newsjp/masahiro-sakurai-20241202-320178/
https://togetter.com/li/2473082

ただ、壁紙にしていても、デスクトップ環境の構成によってはあまり視界に入ってこない。
画像ビューワーなどが定期的に起動されて目に入ってくれた方が効果がある気がする。
視界に強制カットインさせるために、タスクスケジューラに設定する。

##### タスクスケジューラを起動
最近の Windows では、プログラムの起動は検索窓から行くのが早くて個人的に気に入っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/a7576633-2547-e518-f310-e0a40ffef961.png)

起動したタスクスケジューラ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/f180b730-7f4e-b0a7-9ce2-4a6b127ab835.png)

##### タスクの作成
ウィンドウ右にある `タスクの作成` をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/fe378944-4121-9886-df36-bdfa77bee39b.png)
`トリガー` と `操作` を設定する必要がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/d9eb0891-d9af-efad-456f-973e251b5a04.png)

##### トリガー設定
好みの間隔でトリガーされるように設定する。
`トリガー` タブで `新規` ボタンから設定を作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/dfaa8318-c4e6-a47c-f5d8-9ace82c18992.png)
インターバルを分刻みで設定することができる。
人間の集中力は 15 分間程度で一旦切れることが多い (?) ので 15 分間程度に設定すると無難かもしれない。
頻繁にスマホや SNS などを触りたくなってしまったりする人は、もっと短くしてもよさそうだ。

##### 実行コマンド設定
`操作` タブで `新規` ボタンから設定を作成。
表示させたい画像は、適当に拾ってきて個人利用の範囲内でローカルに保存しておこう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/c7b6ac66-704a-cdad-a497-1ed5634fd3fd.png)
`プログラム/スクリプト` の欄に、表示させたい画像のフルパスを指定しておけばよい。
拡張子に紐づけられているビューワープログラムで立ち上がるようになる。

その他、音声付きにするなどして鼓舞をより効果的にしたければ、動画を切り出して保存しておくなどして、それがプレイヤーで強制再生されるようにしてもよいだろう。

##### いますぐやれ！！

### 追記
より簡単で効果的なやり方。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/0c493db4-c2a3-afc1-6655-418d523b7f4b.png)
YouTube の [当該動画のシーン](https://www.youtube.com/watch?v=JV3KOJ_Z4Vs&t=108s) をブラウザで強制再生するとよい。
`プログラム/スクリプト` に
```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
```
などとブラウザの実行ファイルのフルパスを記入し、
`引数の追加 (オプション)` に
```
"https://www.youtube.com/watch?v=JV3KOJ_Z4Vs&t=108s"
```
動画の URL を秒数指定で入力する。

##### とにかくやれ！！
業務コンサルから戦略策定へ。3年間で得た気づきと挑戦

## はじめに
　記事をご覧いただきありがとうございます！アドベントカレンダー19日目を担当いたします、ニッセイ情報テクノロジー株式会社 プロダクト・サービス事業推進室の平賀です。

　当社では、従来のSI開発に加えて、プロダクトやサービスを活用した事業の拡大に取り組んでおります。その中で、私は、事業拡大に向けた戦略策定や具体施策の立案に携わって、早3年となります。

　本記事では、これまで業務コンサルとしてキャリアを積んできた私が、戦略策定業務へシフトする中で感じた気づきや学びを共有します。同じような転換期にいる方や、新しい視点を求める方が、自分のキャリアや業務へのヒントを得るきっかけになれば幸いです。

## 業務コンサルから戦略策定を担当するにあたっての気づき
　最初に、戦略策定に携わった3年間で感じた業務コンサルとの違い（難しさ）を、3点あげます。

### 1. アウトプットの評価軸が曖昧になる難しさ
　戦略策定では、正解のない問題に対して「会社としてどうあるべきか」を考え抜き、自分なりの答えを出す必要があります。しかし、具体的な成果が出るまで評価されにくく、特に初期段階では、自分の考えに自信を持ち続けることが難しいと感じています。

　業務コンサル時代は、顧客や上司のレビューを通じて成果物のフィードバックが得られましたが、戦略策定では自ら責任を持ち、信念を持って進める力が求められると考えています。

### 2. 現実に即した戦略策定の重要性
　業務コンサルでは、フレームワークや他社事例を活用し、顧客の事業戦略に合わせた効率的な施策を提案することで、一定の成果をあげることができました。
 
 　一方、戦略策定では、いくらフレームワークや他社事例を活用しても、自社の状況や文化には合致せず、策定した戦略案も経営陣には響きませんでした。

　この経験から「具体的に誰がどのように行動するのか」を想像し、実現可能性を重視した戦略設計が鍵であると学びました。

### 3. 社内の賛同を得ることの重要性
　戦略策定は、部署内だけで完結するものではなく、他部門を巻き込む必要があります。特に、戦略を推進するためには、他部署の課題感を共有し、共通の目標を描くことが重要です。

　私自身は「まずは自身の目指したいことと熱意を伝え、小さな共感を積み重ねる」ことを意識しながら取り組みました。その結果、少しずつ社内の協力を得ることができたと考えています。

## 戦略策定において心がけていること
　上記の失敗や気づきを踏まえて、今の私は次のようなことを心がけて業務にあたっています。

### 1. 会社と自分のゴールを重ね合わせる
　自分にとってのメリットを見つけることで、戦略に対するモチベーションが上がると思っており、社会や会社への貢献が自分へのご褒美になるようなフローを思い描くようにしています。これによって、他の人への説明にも熱意がこもると思います。

### 2. 最初から綺麗に整理しようとせずに、情報を広く集めて俯瞰する
　戦略策定では、通常のプロジェクト活動と違って、最初に落としどころを決めたり、細かい成果物やスケジュールを決めてその通りに進めようとすると失敗することが多いように感じます。

　ですので、初期段階では、結論を急がずに考えを広げ、多角的な視点で情報を整理することを心がけています。

### 3. 現実的な実行可能性を考える
　具体的な人を想像して、彼らがどのように考えて行動するのか、実行段階での具体的な動きを想像し、不足している要素を補完します。

　これを、頭の中で人が動き出すまで繰り返します。上手に説明できないのですが、小説を読みながら、頭の中で登場人物を動かして、喋らせるようなことを、繰り返しやっています。

### 4. 社内の賛同を得るための熱意を持つ
　他部門の視点を尊重しながら、自分の思いを伝えることで協力を得ます。これは、一度で終わることはなく、何度も、同じ内容のことを、手を変え品を変えて伝え続ける根気が必要になります。
 
## おわりに
　戦略策定は孤独な道のりに思えることもありますが、今回、3年間を振返って思ったのは、自分を信じて地道に努力し続けることが大切で、それによって、少しずつ味方が増えて、いずれ必ず道は開けるということです。

　また蛇足ですが気付いたこととしては、戦略立案で重要なポイントは、プロダクト開発にも通じるものがあるということです。たとえば「机上の空論ではなく、具体的な実行を見据えた設計をすること」や「関係者を巻き込みながら共感を得ること」は、プロダクト開発でも欠かせない要素です。

　戦略立案もプロダクト開発も、単なる計画や理論ではなく、人の行動や感情を動かし、価値を生み出すプロセスであるという点で共通しているのだと思います。

　これからも、これらの視点を大切にしながら、自分自身も会社も成長していけるよう取り組んでいきたいと思います。
第6回OSEDAフォーラムIN福岡@百道浜でLTしませんか？（〇酒もあるよ？）

# 第6回OSEDAフォーラムIN福岡@百道浜

皆さんこんにちは。ロジックリサーチの浦です。

平素より格別のご愛顧を賜り、誠にありがとうございます。

‐以下、フォーラムの詳細を記載‐

オープンソースEDAフォーラム（第６回）のご案内
■開催日時

12/11（水）13:00 ～ 17:30  フォーラム （受付：12:00～）

　　　　　  17:45 ～ 18:30  懇親会

■開催場所

福岡システムLSI総合開発センター（2階：B会議室）とオンラインのハイブリッド開催

会場地図<https://www.ist.or.jp/foundation/access>


■プログラム 及び 参加申し込み方法

以下のURLにアクセスいただき
申し込みについては同ページ内のリンクより、12月9日（月）午前中までにお申込みください。

https://www.oseda-silicon.org/eda%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0/%E7%AC%AC%E5%9B%9E%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0_2

LT：募集★

※ 懇親会場でのライトニングトークは、当日でも受け付けます。

‐以上‐ 

…

え？つまんなそう？
LTはウェブ参加もOKなので大丈夫です！

ただ、実際に百道浜のLSIセンターに来られるのであれば
懇親会の時に軽食を準備しておりますので
楽しくご歓談できますので
是非ともご参加の程お願い致します！
LTをせずとも、参加だけでもOKです！

今度から写真撮っとこうかな…と
rmでシンボリックリンクを削除して事故った話

# はじめに
しばらく真面目な記事を書き続けていたので、閑話休題ということでこの記事では自分の仕事での失敗談を話していく。

筆者は新卒でインフラのバックグランド0の状態でやる気だけ持ってインフラ関係の部署に配属された人間である。この話はよくコマンドの内部構造を理解せず強い力を行使してしまったというものである。

# 事故の概要
下記のようなディレクトリ構成があってmodule1→module2にシンボリックリンクが貼られていた。(本来は同じディレクトリ名ではあるが説明用に名前を分けている)

```
infra-files/
  ├ project/
    └ module2
  └ module1
```

このような構成でmodule2のシンボリックリンクを削除したいとなったときに自分が打ったコマンドは、
`rm -rf module2`
確かにmodule2は抹消された。だがmodule1もこの時抹消されてしまったのだ。

# rmとunlinkの違い
シンボリックリンクを削除するときよく言われるのはunlinkを使えというものだろう。
ではunlinkとrmの違いは何か、それは内部処理として再帰的にファイルを探索するかである。unlinkはシステムコールであり、rmはunlinkとrmdirを組み合わせていい感じにリッチにしたコマンドであったのだ。

それぞれのmamページを見ていこう。
- rm
    - ファイルやディレクトリの削除を行う
    - https://manpages.ubuntu.com/manpages/jammy/ja/man1/rm.1.html

- unlink
    - unlink 関数を呼び出し指定されたファイルを削除する
    - https://manpages.ubuntu.com/manpages/jammy/ja/man1/unlink.1.html

このようにunlinkもrmの機能もファイルを削除するコマンドであることがわかる。
実際のコードの中身を見てみよう
https://github.com/coreutils/coreutils/blob/master/src/remove.c#L394
unlinkatはunlinkの上位互換コマンドであるため同様の中身であることがわかる。
コード内の以下の部分を見ると、rmはディレクトリツリーを構成して、そこを走査してファイルを削除していっていそうなことがわかる。

```
enum RM_status
rm (char *const *file, struct rm_options const *x)
{
  // ...
  FTS *fts = xfts_open (file, bit_flags, nullptr);

  while (true)
    {
      FTSENT *ent = fts_read (fts);
      // ...
      enum RM_status s = rm_fts (fts, ent, x);
      // ...
    }
}
```

# まとめ
rmコマンドはなんでも消せる、実際消せた。
自分はそういう理解で生きてきたが、小さいものに大きすぎる力で挑むと誤って周りに被害を出してしまうかもしれない。
自分と同じことを起こす人が1人でも減るように祈っている。
h5aiでDirectoryIndexをきれいに表示する

https://github.com/lrsjng/h5ai/releases

```sh
wget https://github.com/lrsjng/h5ai/releases/download/v0.30.0/h5ai-0.30.0.zip
unzip h5ai-0.30.0.zip
```

Apacheの設定を修正する

* /etc/apache2/conf.d/default.conf

```diff
        <Directory /var/www/html/>
                Options Indexes FollowSymLinks MultiViews
+               DirectoryIndex index.php index.html  /_h5ai/public/index.php
                #Order allow,deny
                #allow from all
                Require all granted
        </Directory>
```

restart

## 注意点

* DirectoryIndexをサブディレクトリにしたい場合は対応していないので注意
Python3.12でBERTopicをインストールできない

# 環境
<!-- 問題が発生したOS・ソフトウェアのバージョン等 -->
- Ubuntu 20.04.6
- Python: 3.12.2
- Poetry: 1.8.1
- BERTopic: 0.16.4

# 問題
<!-- 具体的にどのような問題が発生したか, どのようなコマンドを試したか -->
- `poetry add bertopic` でインストールしようとすると、numbaのインストール時にエラー発生
  - `Note: This error originates from the build backend, and is likely not a problem with poetry but with numba (0.51.2) not supporting PEP 517 builds. You can verify this by running 'pip wheel --no-cache-dir --use-pep517 "numba (==0.51.2)"'.`

# 解決の経緯
<!-- どのような経緯で解決できたのか -->
- python3.11でも同様のエラーが発生
- BERTopicのissuesを漁っていると関係ありそうなissueを発見: [BERTopic install fails due to numba not supporting Python 3.11 · Issue #1216 · MaartenGr/BERTopic](https://github.com/MaartenGr/BERTopic/issues/1216)
    - 原因はnumbaが現在のPythonバージョンに対応していないこと

# 原因
<!-- どのようなことが原因だと考えられるか -->
- 自動でインストールされる `numba 0.51.2` は、Python 3.6 ~ 3.8 までしか対応していない
    - [Installation — Numba 0+untagged.871.g53e976f.dirty documentation](https://numba.readthedocs.io/en/stable/user/installing.html#version-support-information)

# 解決法
<!-- どのようなことをすれば解決できるか, 具体的なコマンド等 -->
- 最初にnumbaの最新バージョンをインストールしてから、bertopicをインストールする

    ```bash
    $ poetry add numba==0.60.0
    $ poetry add bertopic
    ```


# 参考
<!-- この問題を解決するにあたってどのようなソースを参考にしたか, タイトル・URL等 -->
- [BERTopic install fails due to numba not supporting Python 3.11 · Issue #1216 · MaartenGr/BERTopic](https://github.com/MaartenGr/BERTopic/issues/1216)
- [Installation — Numba 0+untagged.871.g53e976f.dirty documentation](https://numba.readthedocs.io/en/stable/user/installing.html#version-support-information)
SttpBackendStubのfallbackでハマった話

## sttpとは
ScalaのHTTP Clientライブラリです。このライブラリの特徴の1つとして、リクエスト送信時にbackendが設定できるというのがあります。backendを設定するとが何がうれしいかというと、返り値をモナドにしたり、Stubをセットできるという点にあります。Stubを書けば、テスト用に実際にリクエストをせず、リクエストパターンに応じて決まった値を返すとかできて便利なんですね。

今回はこのStubをさわっていたら色々ハマりどころがあったのでメモを残しておきます。

## やりたかったこと
とあるプロジェクトで、develop環境において特定サーバへのリクエストが必ずエラーになるため、Stubで決まった値を返そうとしていました。特定サーバ以外はもちろん今まで通り通信してほしいという要件です。ちなみにStubはDIを使って環境別に注入していて、分かってくるとそこそこDIも便利ですね。

## 問題点
さて、そのStubは最初以下のように書いてました

```scala
HttpURLConnectionBackend.stub
  .whenRequestMatches(req => matchUri(req)).thenRespond(res)
  .whenRequestAny.thenRespond(HttpURLConnectionBackend())
```

実際のところ、実行してみるとmatchしないパターンで `ClassCastException` が出ます。Scalaではあまり見ないエラーですし、全然関係ないところで出てきたのでびっくりしました。

まず問題なのは `thenRespond` にbackend渡しているところです。コンパイルエラーが出ないし大丈夫やろ、っていうScala開発スタイルに慣れ切っていたのでそういう雑なコード書いたんですが、内部的にCastしてるらしくて型が仕事してくれない。これはあまりイケてない仕様な気がします。

で、stubのメソッド一覧を目を皿のようにして見渡してみますが、それっぽい機能がなく、ライブラリのソースコードを読んでみたところ（これは大変読みやすかったです）、fallbackという引数が発覚します。あるやんけ！

しかしどっかのサイトで見たこのHttpURLConnectionBackend.stubという記法には欠点があって、このfallback引数に値を渡す方法がないらしいことも分かります。機能が制限されるAPIっていうのもイケてないですね…。

もうちょっとソースコードに目を通すと、どうもSttpBackendStubを直接呼び出すのが正解らしい。（公式ドキュメントにもそう書いてあった）というわけで最終解は以下です。

```scala
SttpBackendStub.withFallback(HttpURLConnectionBackend())
  .whenRequestMatches(req => matchUri(req)).thenRespond(res)
```

## 蛇足
Sttpのエッジケースでハマったし微妙に再現性が高そうだったのでQiitaにメモっておきました。誰かの役に立つなら幸いです。個人的な反省点はコンパイル通すだけで満足せずに動作テストをしろってやつですね…。
Googleドキュメント+GASでmermaid.jsの図を描画！！

## 概要
GASを使ってGoogleドキュメントに書いたmermaidのコードを図で描画させるます

嬉しい点
- Googleドキュメントのコードを変更すると連動してデプロイした図も変更される

## やり方

Googleドキュメントを作成して、mermaidのコードを貼ります
![スクリーンショット 2024-12-03 17.24.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/cc6a701a-4470-4c9e-8182-1f5f4bf0f522.png)


拡張機能→Apps Scriptをクリック
![スクリーンショット 2024-12-03 17.26.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/a02d59e4-e29a-22f6-6305-61e67a9f147f.png)

エディタが開かられるので、以下のコードを貼り付けて、DOC_IDを書き換えます。
```js
//ドキュメントのID
//https://docs.google.com/document/d/ここの部分がDOC_ID/edit?tab=t.0
var DOC_ID = 'XXXXX';

// HTMLを表示する
function doGet() {
  return HtmlService.createTemplateFromFile("index").evaluate();
}

// ドキュメントの内容を取得する
function getDocs() {
  var docs=DocumentApp.openById(DOC_ID);
  return {
    title: docs.getName(),
    text: docs.getBody().getText()
  }
}
```

次に表示するhtmlファイルを作ります。
ファイル欄のプラスボタンから作成

![スクリーンショット 2024-12-03 17.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/8ce4fc0d-60fe-9dd1-4d05-10e5c06f4e34.png)


名前をindexにして登録
![スクリーンショット 2024-12-03 17.28.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/4c5b342c-4c45-bea1-3fc9-1640595e0f95.png)

htmlタグを以下で書き換えます

```html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script src="https://unpkg.com/mermaid@11.4.1/dist/mermaid.js"></script>
  </head>
  <body>
    <h1 id="title"></h1>
    <div id="mermaid" class="mermaid"></div>
    <script>
    function update() {
      google.script.run
        .withSuccessHandler(function(result) {// 戻り値に対する処理
          document.querySelector('#title').innerHTML = result.title;
          document.querySelector('.mermaid').innerHTML = result.text;
          mermaid.init();// mermaidを更新
        })
        .getDocs();
    }
    
    update();// 初回実行
    
    mermaid.initialize({startOnLoad:false});
    </script>
  </body>
</html>
```

そしたら画面右上のデプロイボタンをクリックし、新しいデプロイを選択

![スクリーンショット 2024-12-03 17.32.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/a9316c10-70cb-f252-73e9-600d9cc4480b.png)


ウェブアプリを選択
![スクリーンショット 2024-12-03 17.32.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/cc8ab3f6-70a2-2215-9e07-64a0d76d98cc.png)

アクセスできるユーザーを調整して、デプロイボタンをクリック！


アクセスを承認しろと言われたら、Advancedをクリックして、Gotoなんとかをクリックし承認！！

デプロイされたURLリンクが記述されてるのでアクセス！

ぱんぱかぱーん！！！表示されました！！！
![スクリーンショット 2024-12-03 17.35.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/44f5f3fa-aea4-abb4-fa00-6b41f5c72682.png)


## 超絶参考

https://naosim.hatenablog.jp/entry/2018/11/01/171811
【TIPS】Enum.reduceでEnum.map同等の処理を書くテクニック

この記事は、[Elixir Advent Calendar 2024 シリーズ7](https://qiita.com/advent-calendar/2024/elixir) の4日目です

---

【本コラムは、2分で読め、2分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

役に立つかは不明ですが、Enum.reduceでEnum.map同等の処理を書くテクニックです

まず、Enum.mapのサンプルです

```diff_elixir
[1, 2, 3]
|> Enum.map(& &1 * 3)

結果：[3, 6, 9]
```

これをEnum.reduceで再現すると、こうなります

```diff_elixir
[1, 2, 3]
|> Enum.reduce([], & &2 ++ [&1 * 3])

結果：[3, 6, 9]
```

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:
watsonx.data Milvusを使えるように払い出してみた

### watsonx.data Milvusを払い出してみる


IBM Cloudのログイン後、カタログから「watsonx.data」のインスタンスを立ち上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/31872148-68d6-b39e-9a11-e6dd6c07b75f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/2b60b4a6-4f1d-1313-4ffe-aeec32b992e2.png)
諸々の情報をいれて作成をしてください。

作成が完了すると、左側のハンバーガー・メニューの「リソース・リスト」を選択し、その後「データベース」から作成したwatsonx.dataがアクティブになっていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/593df616-c31f-d530-1cf9-f540b1d869c7.png)
Webコンソールを開いて、watsonx.dataの初期設定をしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/1dc43a36-d879-e7a2-0ff7-fcaccdc39ca4.png)

さて、諸々の設定をしていきます。
watsonx.data（レイクハウス）は、エンジンとストレージが疎結合をしているのが特徴です。そこで、まずはストレージを設定していきます。ストレージは新しいINSIGHT管理バケットでも、既存で持っているストレージ、どちらでも設定ができます。
![スクリーンショット 2024-10-20 2.28.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/4dde4891-099f-b820-6898-4bd93fc266eb.png)
既存の場合、IBM Cloud Object Storage、IBM Storage Ceph、Amazon S3、Apache Ozoneなどから選択することができます。
![スクリーンショット 2024-10-20 2.28.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/9007811e-af7c-d6da-104f-54a5c8d5516e.png)
その後、テーブルフォーマットを設定します。ストレージとエンジンが疎結合するためには、どこにどんなデータがあるのか、テクニカルメタを管理するためのメタストアが必要です。そのメタストアに保存するためのテーブルフォーマットを指定します。Icebergは過去時点のスナップショットをとっておいて、当時のテーブルの状況でクエリを実行できるなどの特徴を持っています。細かい説明は省略します。
![スクリーンショット 2024-10-20 2.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/ed46b5bb-9cbe-bb58-3f3c-427045539667.png)
エンジンを選択します。2024年12月時点では、JavaベースのPrestoとC++ベースのPrestoを選択することができます。そして、最後に作成をします。
![スクリーンショット 2024-10-20 2.47.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/d4ae3d5e-cf8c-56ba-2e80-6c3b57a8384f.png)

作成後無事ログインできたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/a9ece2bc-4ad2-e2f8-c135-75d4be294660.png)

Milvusをデプロイするためには、ハンバーガーメニューから、「インフラストラクチャー・マネージャー」を選択後、「コンポーネントの追加」を選択してください。そうすると、「Service」の箇所に「Milvus」があるので、選択ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/35a78de5-00d7-f0a1-c7ac-f7e834787fc2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/ac524332-eea2-853a-83a1-fb017a129a15.png)
Milvusの構成は、「スターター」「小」「中間」「大」の６つです。スターターでも、100万ベクトルもメモリ上で処理できるので、結構ありますね。Prestoのエンジンと同様にMilvusもエンジンとストレージが分離しているため、ストレージをIBM管理バケットか外部バケットかを選択して作成することができます。その後作成をしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/b3416ae2-21f6-5ca7-44db-6fa48f009ec5.png)
無事Milvusのデプロイが完了すると、インフラストラクチャー・マネージャーで、Milvusのアイコンが出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/3f9686dc-7937-677d-03a2-6e2e36302d21.png)
なお、接続情報などは、Milvusのアイコンを選択すると確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2505349/f90a9c2f-eced-e85a-a33e-63acbc837f4b.png)

### 感想
簡単にデプロイメントできました。これから色々触ってみようと思います。
elementorで500エラーが出る件メモ

サーバー：さくらのレンタルサーバー  
PHP：7.4.33   
WordPress：6.7.1  
elementor: 3.23.4

elementorで500エラー更新不可に。  
メモリの問題で対処しても改善されず。  
おそらくphp.iniを書き換えた時点でWPに警告が表示されはじめた。

```
Warning: call\_user\_func\_array() expects parameter 1 to be a valid callback, 
function 'twpp\_enqueue\_styles' not found or invalid function name in 
/home/example/www/recruit/wp-includes/class-wp-hook.php on line 324
```

これは初めて見たので。例のあいつ(Chatgpt）に聞いてみたら、テーマのfunctions.phpに以下書き込んでみろと。

```
if (\!function\_exists('twpp\_enqueue\_styles')) {  
function twpp\_enqueue\_styles() {  
wp\_enqueue\_style('theme-style', get\_template\_directory\_uri() . '/style.css');  
}  
}
add\_action('wp\_enqueue\_scripts', 'twpp\_enqueue\_styles');
```

これで警告も消えた上に、elementorの500エラーも消えて更新可能に。
特別なことはしないSAA合格までの道

こんにちは！
新卒エンジニアのさわまりんです:rabbit::dizzy:

今回はAWS SAAに合格に際しての投稿です。
こちらの記事では、受験の経緯＆マインド、勉強方法、当日してよかったこと、の3つをご紹介します。

# 受験の経緯＆マインド
私がSAAを受験した理由は2つありました。
1つ目は、SREとして取得しておくべき資格だったから、
2つ目は、社内でSAA勉強会が開催されていたからです。

当初はただ合格するためだけに、だらだらと勉強をしていました。
しかし受験日が近づくにつれて勉強量が足りないことに焦っていました。
社内勉強会にたくさんの同期を誘っていたこともあり、私が落ちるわけにはいかないと最後の1週間は必死の思いで勉強していました。

# 勉強方法
勉強で使用したのは以下の3つです。
1. 社内勉強会
1. Udemyの講座
1. CloudLicense

それぞれどんなポイントを意識して勉強していたのかご紹介します。

### 社内勉強会
社内勉強会ではサービスや問題の解説が主に行われていました。
その中でも特に、すでに合格した人がどんな判断基準をもって問題を解いているのかを意識して聞いていました。
サービスの組み合わせなのか、そのサービスだけの特徴なのか、消去法なのかなど、今後どのようなところを意識していけばいいのか知ることを目的に参加していました。

### Udemyの講座
Udemyの講座は正直そこまで活用できなかったのでスルーします。
勉強会で使用していたのがUdemyだっただけです。

### CloudLicense
CloudLicenseがいちばん参考になりました。コツはとにかく問題数をこなすことと、間違った問題の解説は必ず読むことです。本試験でもCloudLicenseで解いた問題が複数出題されました。

# 当日してよかったこと
当日してよかったことは、支給されるホワイトボードを活用したことです。
普段の勉強で紙に書くことはしませんでした。しかし本試験で、文章の長い問題、ややこしい問題を解く際に、ホワイトボードに整理したことでケアレスミスに気付くことができました。

# さいごに
ここまで読んでいただきありがとうございました。
これから受験される方は不安と緊張ばかりだと思いますが、
自分がどうすれば勉強効率が上がるのかを模索しながら、勉強頑張ってください！！！
ちなみに私は試験1週間前からコメダのコーヒーチケットを買って、仕事終わりはコメダにこもってました。
次はまた別のAssociateの試験を受ける予定です。みなさん一緒に頑張りましょう！
C#でTXTをExcelに変換する

TXTからExcelへの変換は、テキストファイルからExcelスプレッドシートにデータをパースして再フォーマットし、データの表示、編集、分析を容易にするプロセスです。この記事では、無料のNETライブラリを使用して、**C#でTXTテキストファイルをExcelに変換する方法**を紹介します。

## 無料の.NETライブラリ - インストール
TXTからExcelへの変換には[**Free Spire.XLS for .NET**](https://www.e-iceblue.com/Introduce/free-xls-component.html)ライブラリが必要です。製品パッケージは[Nuget](http://www.nuget.org/packages/FreeSpire.XLS/	)経由で直接インストールできます。または、以下のリンクからダウンロードし、手動でdllを参照として追加することもできます。

https://www.e-iceblue.com/Download/download-excel-for-net-free.html


## C#でTXTをExcelに変換する方法
C#を使ってテキストファイルからエクセルにデータをインポートするには、次のようにする必要がある：

1. **`File.ReadAllLines(string path)`** メソッドを使用して、テキスト・ファイルのデータを行ごとに読み取ります。
1. **`Trim()`** メソッドを使用して、各行の先頭および末尾の空白文字をすべて削除します。
1. **`Split()`** メソッドを使用して、指定した区切り文字でデータを分割し、リストに格納します。
1. リスト内の各行と各列を繰り返し処理する。
1. **`Worksheet.Range[].Value`** プロパティを使用して、指定した Excel セルにデータを入力します。
1. **`Workbook.SaveToFile()`** メソッドを使用して、生成された Excel ファイルを保存します。

```python
using Spire.Xls;
using System.IO;
using System.Linq;

namespace ExcelToTXT
{
    class Program
    {
        static void Main(string[] args)
        {
            //テキストファイルを読み込み、その中のすべての行を読み込む
            string[] lines = File.ReadAllLines("sampleR.txt");

            //各行の先頭と末尾の空白文字をすべて削除し、データを分割してリストに格納する
            var data = lines.Select(line => line.Trim().Split(' ').ToList()).ToList();

            //エクセルのワークブックを作成する
            Workbook workbook = new Workbook();

            //最初のワークシートを取得する
            Worksheet sheet = workbook.Worksheets[0];

            //リストの各行と各列を繰り返し処理する
            for (int rowNum = 0; rowNum < data.Count; rowNum++)
            {
                for (int colNum = 0; colNum < data[rowNum].Count; colNum++)
                {
                    //Excelワークシートの指定されたセルにデータを書き込む
                    sheet.Range[rowNum + 1, colNum + 1].Value = data[rowNum][colNum];

                    //ヘッダー行のフォントを太字にする
                    sheet.Range[1, colNum + 1].Style.Font.IsBold = true;
                }
            }

            //列幅の自動調整
            sheet.AllocatedRange.AutoFitColumns();

            //エクセル (xlsx/ xls) ファイルとして保存する
            workbook.SaveToFile("TXTtoExcel.xlsx", ExcelVersion.Version2016);
            workbook.Dispose();
        }
    }
}
```

**出力：**
![TXTtoEXCEL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/dc44374f-5e14-43ab-6973-2850007dee7e.png)


* * *
無料の.NET Excelライブラリが提供するExcelファイル処理機能の詳細については、ドキュメントを確認してください：

https://www.e-iceblue.com/Tutorials/Spire.XLS/Spire.XLS-Program-Guide/Spire.XLS-Program-Guide-Content.html
ApaxyでDirectoryIndexをきれいに表示する

## 文字化け解決のためファイル名をUTF-8にしたい場合

* `+Charset=UTF-8`を指定するとよい様子

```apache
# index options
IndexOptions +Charset=UTF-8 +FancyIndexing +FoldersFirst +HTMLTable +IconsAreLinks +IgnoreCase +NameWidth=* +SuppressDescription +SuppressRules +XHTML -SuppressHTMLPreamble
```

## apaxyを使う

https://wiki.georgeorge.com/docs/tech/apaxy/

```sh
cd /var/www/html/

git clone https://github.com/AdamWhitcroft/Apaxy.git

cp Apaxy/apaxy/htaccess.txt /etc/http/conf.d/apaxy.conf
```


* /etc/http/conf.d/apaxy.conf

内の`{FOLDERNAME}`をPATHが通るように修正する。

```diff
- AddIconByType (ps,{FOLDERNAME}/theme/icons/image-x-eps.svg) application/postscript
+ AddIconByType (ps,/Apaxy/apaxy/theme/icons/image-x-eps.svg) application/postscript
```

Apacheを再起動し表示が変わったことを確認。
DATA Saber チャレンジ備忘録 Ord5 Q3

DATASaberの最終試験に向けた振り返り＆定着用備忘録です。
職場などで動画を視聴できない場合やViz作成を高速で復習するために作成しています。
今回はOrd5からパラメーターの使い方を書いていきます。
詳しくは↓2つ目の動画をご覧ください。

<iframe width="560" height="315" src="https://www.youtube.com/embed/hhk_pcgH8KM?si=MVtpAANPp5RD4Ues" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/qtR_8luMfIg?si=LFR8cBwJhqzqZeAe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


>Q3:
1行単位の利益金額1万円ごとに区切ったとき、どの価格帯のオーダーが最も多いでしょうか。
なお、区切る金額は見る部門によって違うことがあるようなので5千円ごとに5千~2万円で変更できるようにして下さい。
これはパラメータとビンを使用して実現します。

**完成図**
![Ord05_Q3_99完成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/97aa084d-559f-0042-f145-8ab48b60fe2d.png)

---
さっそく進めていきましょう。

**1.パラメーターの作成**
左ペインで右クリック→パラメーターの作成を選択
![Ord05_Q3_01パラメーター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/b232368c-f1bb-aa99-f325-5459d716834d.png)

パラメーター名：prm_利益ビンのサイズ変更　←パラメーターだとわかりやすい名前
データ型：整数　　表示形式：自動
許容値：範囲　　最大値：20,000　　最小値：5,000　　ステップサイズ：5,000
でOK
![Ord05_Q3_02パラメーター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/f53e6ef0-8a3a-809b-98ae-a64c8162a657.png)

**2.ビンの作成**
次にビンの作成です。
利益で右クリック→作成→ビンを選択
![Ord05_Q3_03ビン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/0b3c41ae-7a4c-ef72-300f-9e7aba16a6b1.png)

新しいフィールド名：利益 (ビン)_5000区切り可変　←ビンだとわかりやすい名前
ビンのサイズ：先ほど作成したパラメーターを選択
OK
![Ord05_Q3_04ビン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/e1e30a7c-5044-0c30-0887-4a71d7fe578d.png)

**3.グラフの作成**
グラフを作成していきます。
列：先ほど作成したビン
行：オーダーIDのカウント
一番大きな要素にだけ色を付けたい場合、↓の計算式を作成して色に入れる
計算式：WINDOW_MAX(COUNT([オーダー Id]))=COUNT([オーダー Id])
![Ord05_Q3_05グラフ作成と計算式.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/1a42735f-3e1a-ac87-2e67-60fe4a88e6d4.png)

最後にパラメータの表示
パラメーターで右クリック→パラメーターの表示
![Ord05_Q3_06パラメーターの表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/175f9463-2154-793e-db4c-906f34de64c5.png)
右側にパラメータが表示されるようになりました。
![Ord05_Q3_07パラメーターの表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/3b39f95a-5f17-5c81-26e9-a0c9d1720bd1.png)

最後に最大値のみにラベル表示して完成
![Ord05_Q3_08ラベルの表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3951242/f84169b6-5ce4-0bbb-fe8b-0d61deb54fd0.png)
Looker Studio で AB テストの結果を可視化する際の Tips

# はじめに
こんにちは。推薦基盤ブロックの宮本です！（早いもので新卒 5 年目です）
最近は ZOZOTOWN のホーム画面のユーザーパーソナライズ化に関するプロジェクトに携わっています。

推薦システムをリリースする上で、必要不可欠なのが AB テストです。弊チームでは、AB テストの実施サイクルを高速化するために Looker Studio を活用しています！
Looker Studio は、以下のようなメリットがあります。

- BigQuery との連携が簡単
- 社内での共有がしやすい
- 一元管理が可能

一方で、制約も存在しており、「**やりたいことができない**」と感じることも多々あります。
今日は **Looker Studio を使用して AB テストの結果を可視化する際に工夫したこと**を紹介します！

BI ツールの選定に関しては、以下の記事が参考になります。

https://qiita.com/yan_yan/items/3aa4cb23a221b0db0c18


# 課題
AB テストの結果を可視化する際、必ず確認したい指標の一つが、treatment/control 比、すなわち、新ロジック（treatment）が従来のロジック（control）に対してどれだけアップリフトをもたらしたかを示す値です。

しかし、残念ながら Looker Studio の UI 操作では、この treatment/control 比を算出することができません。（もし実現可能な方法をご存じの方がいれば、ぜひ教えてください！）

スプレッドシートでは簡単に計算できる操作ですが、Looker Studio は可視化専門のツールであるため、データの操作は BI ツール側で対応せず、ユーザーがあらかじめ必要なデータを用意する設計となっているのではと考えております。

そこで、treatment/control 比を算出するクエリを紹介します。

# treatment/control 比を算出するクエリ

愚直に書いた場合、以下のようなクエリになります。

``` sql:sample1.sql
WITH control AS (
  SELECT * FROM `target_table` WHERE variant_name = 'control'
)

, treatment1 AS (
  SELECT * FROM `target_table` WHERE variant_name = 'treatment1'
)

, treatment2 AS (
  SELECT * FROM `target_table` WHERE variant_name = 'treatment2'
)

, tre1_con AS (
  SELECT 
    control.calendar_date
    ,"treatment1" AS variant_name
    ,SAFE_DIVIDE(treatment1.order_price,control.order_price) order_price
  FROM control
  LEFT JOIN treatment1
    ON control.calendar_date = treatment1.calendar_date
)

, tre2_con AS (
  SELECT 
    control.calendar_date
    ,"treatment2" AS variant_name
    ,SAFE_DIVIDE(treatment2.order_price,control.order_price) order_price
  FROM control
  LEFT JOIN treatment2
    ON control.calendar_date = treatment2.calendar_date
)

SELECT * FROM tre1_con
 UNION ALL 
SELECT * FROM tre2_con

```

このクエリの問題点は、treatment が増えるたびにクエリのコード量が増え、その都度修正が必要になることです。
サンプルクエリ程度のコード量であれば問題は小さいですが、実際の AB テストでは以下のような状況が想定されるため、問題が顕著になります。

- 使用するロジックが増える
- 確認したい指標が増える

その結果、冗長なコード量が膨大になり、メンテナンスが困難になります。

そこで、上記の問題点を踏まえて改良したクエリが以下です。

``` sql:sample2.sql
WITH control AS (
  SELECT * FROM `target_table` WHERE variant_name = 'control'
)

, treatment AS (
  SELECT * FROM `target_table` WHERE variant_name != 'control' -- ポイント1
)

, tre_con AS (
  SELECT 
    c.calendar_date
    , concat(t.variant_name) as variant_name -- ポイント2
    ,SAFE_DIVIDE(treatment1.order_price,control.order_price) order_price
  FROM treatment AS t, control AS c -- ポイント3
  WHERE t.calendar_date = c.calendar_date
)

SELECT * FROM tre_con
```
このクエリでは、そもそものコード量が減っており、treatment が増えてもコードを修正する必要がありません。



# まとめ
本記事では、Looker Studio の制約である treatment/control 比の算出が難しい点と、その解決策として汎用的なクエリを紹介しました。改良クエリにより、treatment が増えてもコード修正が不要になり、メンテナンス性と効率性が大幅に向上します。
これからも、実務で役立つこうした Tips を随時紹介していきます！
EventBridge Schedulerによる開発環境コスト削減

# 解決したい問題
- 開発環境のコストを下げたい
- 勤務時間内だけEC2とRDSを起動したいが、手動で操作したくない

# 設定手順(EC2)
## 自動起動
- [**EventBridge→Schedules**]からスケジュールを作成
![スクリーンショット 2024-12-03 11.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935079/001d8fde-1be4-46fd-7aed-5f53d01dcfb6.png)

### schedule detail(スケジュール詳細)
- 繰り返しで実施したいので、「**Recurring schedule**」を選択
![スクリーンショット 2024-12-03 11.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935079/57fbd532-3c97-4e71-775d-301dc28b3b8e.png)

- 実施時間まで指定したいので、Cron式設定の「**Cron-based schedule**」を選択
※ Cron式にAWS独自の部分があるので、詳細は[こちら](https://docs.aws.amazon.com/ja_jp/scheduler/latest/UserGuide/schedule-types.html#cron-based)を参照
※ 月-金朝9時の場合は以下の設定になります。
※ 設定が有効の場合、実行時間が一番近い10件表示される
![スクリーンショット 2024-12-03 11.42.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935079/7bf2157d-5e90-91cb-33f4-45b669e468ba.png)

- 指定時刻で実行したいので、[**Flexible time window**]は[**Off**]を選択

### target(設定対象)
- [**All APIs**]から[**EC2**]、さらに[**StartInstances**]を選択
![スクリーンショット 2024-12-03 15.27.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935079/cd0acb71-1005-1664-5b21-6df2ff4aea60.png)

- JSONのフォーマットで[**EC2のInstance ID**]を指定
```
{
  "InstanceIds": [
    "i-0000000000000000a",
    "i-0000000000000000b"
  ]
}
```

### settings(異常時設定)
- デフォルトの[**Retry policy**]は(正常実施できなかった場合、)24時間以内、最大185回というもので、
  日次のタスクに向いていないため、1,2時間内最大10回くらいに変更をおすすめ
  ※ EC2インスタンスタイプ一時利用できない可能性があるため、起動設定のリトライ回数と期間は少し余裕を持つように設定するのをおすすめ
![スクリーンショット 2024-12-03 15.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935079/d2763b2e-9d11-8395-1c89-e473387e3e11.png)

- [**Permissions**]はEC2起動権限を持つIAMRoleを別途作成後指定
※ 同じリソースの起動と停止Policyを一つのRoleにまとめるほうが管理しやすい

## 自動停止
基本流れは起動設定時と同じため、違うところと注意点だけを書きます。
- 対象APIは[**StopInstances**]
- 0時を跨いて停止する場合、実行日は火-土になるため、CRON式の日付設定は変わる

## 設定有効・無効化
Schedules一覧画面で変更したい設定を選択、Disable・Enableをクリック

# 設定手順(RDS)
基本流れはEC2と同じため、違うところだけで書きます。
- 起動と停止のAPIは[**StartDBInstance**]と[**StopDBInstance**]になるため、管理対象が複数の場合、台数分の設定が必要
- **RDSのDB identifier**を以下のように指定
```
{
  "DbInstanceIdentifier": "DB identifier"
}
```

# 効果
インスタンス費用がメインの開発環境では、
稼働率と同じ割合で費用削減できます。

| スケジュール | 稼働率 |
|:-:|:-:|
| 土日停止  | 73.3%  |
| 平日0時〜9時＋土日停止  | 48.3% |

土日停止だけでも現在コストの7割、平日も追加した場合は5割以下に削減できる見込みのため、設定次第リザーブドインスタンス以上のコストダウン効果があります。
開発環境ならではの節約術ですので、ぜひ実際の環境で実践してみてください。
Svelte5の$stateを使ったリアクティブなバリデーション

## はじめに

[Svelte]5がリリースされました。`Runes` という機能が追加されています。

このうち最も基本的な `$state` ルーンが `class` に対応しているので、リアクティブなバリデーションを実装できそうと思いました。



## 実装

まずはクラスを定義します。`#errors = $state({})` が重要です。

```svelte:data.svelte.js
import {z} from 'zod';

const DataSchema =z.object({
	name:z.string({ required_error: 'nameを入力してください'})
	      .nonempty({ message: 'nameを入力してください'}),
	age: z.string({required_error: 'ageを入力してください'})
	      .nonempty({ message: 'ageを入力してください'})
	      .regex(/^[0-9]+$/,'ageは0以上の整数を入力してください')
});

export class Data {
	#id = crypto.randomUUID();
	#name;
	#age;
	#errors = $state({});

	constructor(props) {
		this.#name = props?.name;
		this.#age = props?.age;
		this.#validate();
	}

	get id() {
		return this.#id;
	}

	get name() {
		return this.#name;
	}

	set name(name) {
		this.#name = name;
		this.#validate('name');
	}

	get age() {
		return this.#age;
	}

	set age(age) {
		this.#age = age;				
		this.#validate('age');
	}

	get errors() {
		// 変更されないようにコピーを返却
		return {...this.#errors};
	}

	#validate(targetName) {
		Object.keys(DataSchema.shape).forEach(key => {
			if (!targetName || targetName === key) {
				const res = DataSchema.shape[key].safeParse(this[key]);
				if (!res.success) {
					this.#errors[key] = res.error.issues[0].message;
				} else {
					delete this.#errors[key];
				}
			}
		});
	}

	isValid() {
		return Object.keys(this.#errors).length === 0;
	}

}
```

入力フォームで使ってみます。ポイントはバリデーションが自動的に実施されるため `App.svelte` でバリデーションを実施するコードがない点です。

```svelte:App.svelte
<script>
	import { Data } from './data.svelte.js';
	let data = $state(new Data());	
	function add() {
		alert(`登録! ${data.name}、${data.age}`);
		data = new Data();
	}
</script>

<div>
	<label>
		<span>名前</span>
		<input bind:value={data.name} />
		<span class="error">{data.errors.name}</span>
	</label>
</div>
<div>
	<label>
		<span>年齢</span>
		<input bind:value={data.age} />
		<span class="error">{data.errors.age}</span>
	</label>
</div>
<button disabled={!data.isValid()} onclick={add}>登録</button>

<style>
	div {
		margin-bottom: .5rem;
	}
	.error {
		color: red;
		display:block;
		height: 1.5rem;
		margin-left: 2.5rem;
	}
</style>
```

`data.svelte.js` の `errors` が変更されると `App.svelte` の `#errors` を使用している箇所が再レンダリングされる、という動きになります。これが `$state` を使う意味になります。ちなみに、`#errors` から派生する `isValid()` 関数を使用している箇所も再レンダリング対象になります。

## 動作確認

[こちら](https://svelte.dev/playground/c3a45c9c0d8840efbb66a05fad2d00bc?version=5.4.0) で動作確認できます。`data.svelte.js` で `$state` を使わない場合にどうなるか、ぜひ試してみてください。

## 考察

`data.svelte.js` の `constructor` 以下はお決まりの実装なので [Preprocessor] を自作して自動生成するのもありですね。

ただ、一般的なフォームバリデーションは [Superforms] のようなバリデーションライブラリを使ったほうが断然楽なので、時と場合によって使い分けるのがよさそうです。

## まとめ

クラスのフィールドに `$state` ルーンを使うことでリアクティブなバリデーションを実装することができました。これによって `App.svelte` ファイルではバリデーションを実行する手間がなくなり、すっきりしたコードを書くことができました。

`Runes` が導入されたことで、コードが冗長になってしまうのかなと心配していましたが、杞憂でしたね！:smiley:

[Svelte]:https://svelte.dev/
[Preprocessor]:https://svelte.dev/docs/svelte/svelte-compiler#Preprocessor
[Superforms]:https://superforms.rocks/
Kubernetesコミュニティに参加するためのトレーニングを2019年から開催している話

この記事は[NECソリューションイノベータ Advent Calendar 2024アドベントカレンダー](https://qiita.com/advent-calendar/2024/nes)の12/4の記事です。
昨日は、@shu-mutowさんの「[Kubernetes クラスター全体を実働不可能にさせかねない不注意な memory-backed emptyDir の利用](https://qiita.com/shu-mutow/items/292d43606ad4c658c2ae)」でした。

# Kubernetesコミュニティに参加するためのトレーニングとは
「Kubernetes Upstream Training」として年に約2回開催しているトレーニングです。
Kubernetesコミュニティでは同様のトレーニングが世界で開催されており、その日本語版という位置づけになります。
講師はKubernetesコミュニティに参加しているメンバーで構成されており、弊社だけでなく他社の人も参加しています。

このトレーニングでは、KubernetesのOSSコミュニティを知ること、コントリビューション活動（貢献活動）を始めるための準備をすること、そして実際のコントリビューション活動をハンズオンで経験することが可能です。
このトレーニングを通してKubernetesコミュニティへの参加者が増え、OSSコミュニティがより大きくなることがゴールといったところでしょうか。

トレーニングのレポジトリは以下になります。
https://github.com/kubernetes-sigs/contributor-playground/tree/master/japan
普段はイベントに合わせて集合トレーニングを実施していますが、自分のタイミングでトレーニングを進めるアドホックな実施も可能ですので、もし興味のある人はぜひ。

と、色々書いていますが、より具体的な内容や経緯などはこちらの記事に書かれています。
https://jpn.nec.com/oss/community/blog/kubernetes-upstream-training.html

さて、Qiitaの記事ですし、ここからは少し視点を変えてカジュアルに「講師としてこれまでトレーニングを開催してきた中で感じたこと」を書いていきましょう。

# 講師として感じたこと
2019年から開催してきて、2024/11/26(火)に開催したトレーニングで12回目となりました。活動としては6年目ですね。
COVID-19が始まる前から開催してましたので、はじめはオフライン(対面)でのトレーニングだったのが、途中から完全リモートでの開催となり、最近になってオフラインを復活させ現在ではハイブリッド開催となっています。
トレーニングの内容も参加者からのフィードバックを反映したり、トレーニングの全体時間を短くして参加しやすくしたり工夫をしてきました。

それらの活動を通して感じたことを1つ共有させてもらうと「効果が出てくるには時間がかかる」と言うことかなと思います。
これは私の感覚ですが、トレーニング参加者が実際にKubernetesコミュニティで活躍している様子を知る機会が増えたのは1年ほど前からでした。
もちろんその人の活躍は、その人の活動の結果であり、トレーニングだけが要因ではないと思います。

これまで継続的に講師のロールで教えてきたことはなかったため、この経験と感覚を得ることができたのはとても貴重だと思っています。
そしてこの感覚が意味することは、OSSのコントリビューション活動を始め、継続するということの難しさでもあるのだろうなと思います。

そんな中でも少しずつその効果が現れてきているのは1つ嬉しかったことですね。

# 今後は？
トレーニング開催は今後も続いていくと思います。
一方で、講師陣の追加・変更やトレーニング内容の更新も含めて徐々に良くする活動も続ける必要があると思っています。

OSS（ソフトウェアそのものとそのOSSのコミュニティ）の良さとして言えるのは、改善するためのアクションを取りやすいということかなと思います。
OSSは「やりたい人がいれば参加できる」という文化が根っこにあり、コミュニティとして少しずつ良くする行動が取りやすい構造になっていると思います。

今年になりKubernetes Upstream TrainingはCNCJの中のSIGの1つとなりました。
https://community.cncf.io/cloud-native-community-japan/

これまで以上に活動が大きくなる準備が整ってきていますね。
もう来年が間近に迫ってきていますが、来年の活動は更に大きなものになりそうですね。
逐語的文字列リテラルにびっくり

逐語的文字列リテラルを使用しない場合、\nや\tを出力したい！と思った時、\をエスケープするために
\n→\\n \t→\\t
としてエスケープさせなくてはいけない

逐語的文字列リテラルを使用すると...
使用前
```
Console.WriteLine("aa \\\n \\\t \\"Hello\\"");
```
使用後
```
Console.WriteLine(@"aa \n \t ""Hello""");
```
→ わざわざ"\\"でエスケープしなくても"@"1つですべてエスケープしてくれる！

※注意点
逐語的文字列リテラルを使用して「" "」をエスケープしたいとき、
Console.WriteLine(@""Hello"");→✖

「""」で1つのダブルクォーテーションを判断されるから、正しくは

Console.WriteLine(@"""Hello"""); → ○
プロダクトヒストリーカンファレンス2024初参加レポ

 # 参加した経緯
11/30(土)に開催された、プロダクトヒストリーカンファレンス2024に参加してきました:raised_hands:

https://lp-a.youtrust.jp/phc2024/

普段全く外に出ないうえ、朝からオフラインのイベントに足を運ぶことハードルの高さを感じていましたが、各企業のCTOやトップレベルのエンジニアの話を聞ける貴重な機会を逃すまいと思い参加を決めました。

参加申請は事前にGoogleフォームに回答するだけで完了しました。
当日の受付で、YOUTRUSTのアプリをダウンロードすることで会場に入場することができました。
**参加費は、ランチや懇親会のお酒やお寿司を含めて完全無料**で、とても有難かったです:pray:

 # 聴講したセッション
 
 ## GitHubの軌跡：リポジトリからAIプラットフォームへ
 Speaker : [服部祐樹](https://x.com/yuhattor)さん GitHub, Inc. Sr. Architect
 ### 感想
　ソースコード管理の巨人であるGitHubから、コード生成の分野に進出しAIプラットフォーマーとなるまでの説明がとても腑に落ちました。OSS開発のプラットフォーマーとして、開発者体験の向上につながる機能を提供してきたことが、良質なコード及び良質な学習データを持つことにつながり、生成AIの分野でもGitHub Copilotのようなインパクトのある製品をリリースできたのだなと感心していました。
 
　また、開発者と生成AIの向き合い方として、**AIとの協業には良いコードが必要**とおっしゃっていたのも印象的でした。適切な命名がされていて、関心の分離ができているようなコードは、AIにとっても可読性が高く、間違った出力をすることが減り、生産性が上げられるとのことでした。昔から言われているコードの可読性ですが、生成AIの時代になっても重要とのことなので、またリーダブルコードを読み直して、自分のコードの可読性を高めるモチベが湧いてきました。

 ### 登壇資料
 https://speakerdeck.com/yuhattor/github-history-and-ai
 
 ## 領域を絞ったマルチプロダクト開発における技術戦略＆組織戦略
 Speaker1 : [畠中翔一](https://x.com/punk_punx)さん 株式会社メディカルフォース　CTO
 Speaker2 : [河合俊典](https://x.com/vaaaaanquish)さん エムスリー株式会社　VPoE
 ### 感想
　医療系のサービスの技術系役員という肩書きを持つ二人のトークセッションという形でした。特に感銘を受けたのは、どのようにエンジニアにドメイン知識を持ってもらうかを熱心に話されていたことでした。ドメイン知識をプロダクトマネージャーに丸投げするのではなく、エンジニア一人一人がドメイン知識を得ることで、より当事者意識を持って現場の課題を認識し、その課題を解決できるソリューションを提供できることにつながるんだなと理解しました。
 
　私たちも人事パッケージを扱うエンジニアとして、人事ドメインを理解することによって、現場の課題をクリティカルに解決できるように、技術だけでなくドメイン知識の吸収も頑張っていきたいなと思いました。


 ## ライブコミュニケーションアプリPocochaで学ぶ！サービスを成長させるレコメンド
 Speakrer : [吉田知貴](https://youtrust.jp/users/birdwatcher)さん 株式会社DeNA ソリューション本部データ統括部AI技術開発部ライブコミュニティグループ グループリーダー

### 感想
　DeNAのライブ配信アプリであるPocochaのレコメンドが、どのような思想で設計されているのかを詳しく伺うことができました。昨今のAIブームの中で、とりあえずNNベースのモデルを使ってみようとするプロジェクトも多い中で、目的を明確化し、メンテナンス性なども考慮した上でモデルを選定することが重要であるという話をされていて、AIという煌びやかにみえるワードに踊らされず、課題解決にフォーカスした技術選定を行うことが重要なんだなと改めて理解することができました。

　また、PocochaではレコメンドのAIモデルを毎日更新しているとのことで、その裏側にあるML基盤についてもミートアップでお話を聞くことができました。社内のAPI基盤を利用することで、サービスを止めることなく毎日モデルを更新することができるという話を聞いて、AI技術者に魅力的な環境を用意するには、開発基盤を整える必要があるなと再認識しました。

# スポンサーブース
セッションだけでなく、スポンサーブースもとても楽しかったです:v:
スタンプラリー形式で各企業のお話を聞いていくことができ、12ポイントを集めると、夜の懇親会への優先入場権が手に入るという仕組みになっていました。
![1000003536.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828633/0e79f787-570c-d30f-9a4c-3e75c23ef931.jpeg)

ブースでは各企業が様々なグッズを用意してくれて、ネタに振り切ったものから実用的なものまで色々なグッズを貰うことができました。
私が特に気に入ったのはLegalscapeさんの`そのOSSライセンス大丈夫？`シールで、今はノートPCの裏に貼っています（笑）

# 懇親会
18時半からは懇親会が開かれました。お寿司:sushi:やビールが:beers:振舞われて、セッションの登壇者の方々ともお話をすることができました。
生成AIの話から、エンジニアのマネジメント、ゴールドジム:muscle:の話まで、お酒の力も借りながら色々なお話を聞くことができました。
![1000003532.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828633/9cfe29a7-860d-3c81-6462-712fcd66e882.jpeg)

# 振り返って
参加する前までは、オフラインイベントに参加するハードルの高さを感じていたのですが、今振り返ると、各企業のエンジニアと直に交流し、貴重なお話を沢山聞けて、イベントをとても楽しむことができました:blush:

また、オフラインのエンジニアのイベントがあれば、積極的に参加していきたいです！
ContactForm7 と WP rocket の互換性

## Contact Form 7 と WP Rocket の互換性について

Contact Form 7 は多くの WordPress サイトで使用されている定番のフォームプラグインですが、WP Rocket との組み合わせで互換性の問題が発生することがあります。この記事では、私が直面したオレンジ色のエラー問題と、その解決方法について共有します。

### 問題の概要

Contact Form 7 を利用中に、フォーム送信時にオレンジ色のエラーが表示されるようになりました。このエラーは通常、スパムとしてフォーム送信が判定されている場合に発生します。

### 調査ポイント
まず、WP Rocket の「遅延読み込み」設定を確認しました。以下のスクリプトについては、既に主要な設定がされていました。

/jquery-?[0-9.](.*)(.min|.slim|.slim.min)?.js
Hammer.min.js
/wp-content/plugins/contact-form-7/
にもかかわらず、フォーム送信は失敗し続けました。

### 原因の特定

さらに調査を進めた結果、原因は reCAPTCHA のスクリプト読み込みが遅延されていることにあると判明しました。WP Rocket のキャッシュ設定で遅延読み込みの対象となっていた以下のスクリプトが影響していました。

https://www.google.com/recaptcha/api.js
https://www.gstatic.com/recaptcha/releases/
reCAPTCHA のスクリプトが遅延されると、Contact Form 7 のスパム判定機能が正しく動作せず、オレンジのエラーが表示されていたのです。

### 解決方法

この問題を解決するために、以下の手順を実施しました。

1. WP Rocket の「遅延読み込み」設定を調整
WP Rocket の管理画面で以下のスクリプトを「遅延読み込み」の除外リストに追加しました。

https://www.google.com/recaptcha/api.js
https://www.gstatic.com/recaptcha/releases/

2. キャッシュのクリア
設定を変更した後、WP Rocket のキャッシュをすべてクリアしました。また、ブラウザのキャッシュもクリアして動作確認を行いました。

### 結果

設定変更後、フォーム送信が正常に動作するようになりました。Contact Form 7 のエラーも解消され、スパム判定に関連する問題は発生しなくなりました。

### まとめ

WP Rocket の「遅延読み込み」機能はサイトパフォーマンス向上に有効ですが、特定のスクリプト（特に reCAPTCHA）の動作に悪影響を及ぼす場合があります。Contact Form 7 を使用していて類似の問題が発生した場合は、WP Rocket の設定を確認し、reCAPTCHA 関連スクリプトを除外リストに追加することで解決できるかもしれません。

もしこの記事が役立ったら、「いいね」やコメントでフィードバックをお願いします！
Ruby レシーバについて

# はじめに


#### <font color="red">※以下の内容には誤りが含まれる可能性があります</font>


# Ruby レシーバとは何か



プログラミングにおいて、「レシーバ」はメソッドが呼び出される対象となるオブジェクトのことをいう。

Rubyでは全てのメソッドは何らかのオブジェクトに対して呼び出されます。

そのオブジェクトがレシーバとなるのです。


# レシーバの使い方例（レシーバを使った文字列操作）

```
greeting = "hello, Takashi!"
upper_case_greeting = greeting.upcase
puts upper_case_greeting
length_of_greeting = upper_case_greeting.length
puts length_of_greeting
HELLO, TAKESHI!
15
```
"hello, Takeshi!"という文字列が大文字に変換されて、その長さが12であることが出力されます。



# まとめ

Rubyのレシーバは他にも応用した使い方が数多くあるので学習が進み次第まとめていく
Unity ECSのSystemAPI.Queryの関数早見表

# 環境
Unity 6000.0.25f1
Entities 1.3.5

# 関数一覧
| 関数名 | 説明 |
|:-:|:-:|
|GetEnumerator| クエリ内のエンティティのEnumeratorを返却|
|WithAbsent|指定したコンポーネントが存在しないもの|
|WithAll|指定したコンポーネントを全て含むもの|
|WithAny|指定したコンポーネントを一つでも含むもの|
|WithChangeFilter|指定したコンポーネントが変更されているもの|
|WithDisabled|指定したコンポーネントが存在し無効化されているもの|
|WithEntityAccess|エンティティに直接アクセスするためのタプルを追加|
|WithNone|指定したコンポーネントが存在しないor無効化されているもの|
|WithOptions|独自のEntityQueryOptionsを指定できる|
|WithPresent|指定したコンポーネントが有効か無効かに関係なく存在するもの|
|WithSharedComponentFilter|共有コンポーネントに指定された値を持つチャンクのみを選択|
|WithSharedComponentFilterManaged|管理対象の共有コンポーネントに指定された値を持つチャンクのみを選択|


> 参考: https://docs.unity3d.com/Packages/com.unity.entities@1.3/api/Unity.Entities.QueryEnumerable-2.html

間違いや訂正がありましたら連絡くださいmm
NetSuiteの仕組み　NetSuiteのSuiteCloudプラットフォーム概要

# はじめに
　NetSuiteのカスタマイズの為に様々な機能が備わっており、プラットフォームについて、簡単に触れたいと思います。今後は、各ツールを深堀り、記事を投稿しようと思います。

# SuiteCloudプラットフォーム概要図(図は英語)
　SuiteCloudプラットフォームは、NetSuite画面からのカスタマイズ(いわゆるセルフカスタマイズ)やコーディングを行う事でのビジネスロジックの開発、NetSuiteの状態を参照したり、利用者の役割に応じたアクセス権限の設定・カスタマイズ、カスタマイズ成果物の他、環境(アカウント)への移植、外部システムとの連携などをサポートしています。

:::note info
図は、英語表記を引用し、概要説明は、日本語で補足しつつ、ご説明致します。
:::
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114483/03f02294-a170-06c7-dc68-6ac34e353e3d.png)

|トピック| 概要説明|
|:-:|:-:|
|Point-and-Click Customization|　日本では、セルフカスタマイズとしてご案内している機能です。項目を追加したり、新たにレコード(テーブル)を作成したり、画面処理の自動化のカスタマイズをしたり(SuiteFlow)、社外向け、社内向けの帳票を作成したり、Eメールテンプレートを作成したり、ダッシュボードの作成をNetSuiteの画面上から作成及びカスタマイズすることが可能です。また、一部のカスタマイズオブジェクトを他の環境へ移行する事もツールを利用し、画面上から可能です。|
|Access Control|　ロール(担当者)の定義をカスタマイズ及び新規に作成することが可能です。ロールでは各機能へのアクセス権限等の設定が可能です。プリセットされたロールも豊富に存在するため、まずは、プリセットされたロールを元にカスタマイズすることをお勧めいたします。また、各ロールへはセンターと呼ばれるものを紐づける必要があります。センターは、営業向け、経理向け、経営層向けなどのタブセット(メニュー構成)毎に分かれており、各ロールに応じたセンターを指定します。センター自体もカスタマイズが可能です。|
|Customization Tools|SuiteCloud Software Development Kit(以下、SuiteCloudSDK)を利用し、開発することが可能です。Visual Studio Code,WebStormにプラグイン(※)が提供されており、そのプラグインを利用することによって、ファイルキャビネットのアップロード、ダウンロードやカスタムオブジェクトの環境移行、SuiteScriptのコード補完機能などを利用することが可能です。また、より蔵人向けにコマンドラインツールも提供されています。|
|Business Intelligene|データ分析、データ出力等の機能です。NetSuite内のデータをピボット分析、グラフ表示など可能なSuiteAnalyticsWorkbook、NetSuite外のデータソースも含めて、分析可能なNetSuite Analytics Warehouse、KPI,トレンドグラフなどのデータを一元的に参照可能なダッシュボード、必要なデータ出力が可能な保存検索、定型出力可能なレポート機能、3rdパーティのレポートツールへ連携を想定したSuiteAnalyticsConnectなどが存在します。|
|Integrations|NetSuiteと外部システムとの連携するための機能です。CSV,SOAP WebService,REST WebServiceで連携可能です。日本で対応可能な機能等、詳細は今後、改めて触れて行こうかと思います。|
|Distribution|Suite App MarketplaceへUPするためのツールです。SuiteAPPはこちら:point_right_tone2:https://www.suiteapp.com/|
|Custom Coding|SuiteScriptというJavaScrpit言語をベースとしたプログラミング言語でNetSuiteUIの開発、ビジネスロジックの開発が可能です。クライアントスクリプト、サーバーサイドスクリプトどちらも開発可能です。お客様へは、アドオン開発としてご提供している場合もありますが、広義ではカスタマイズの一部となります。|

:::note info
2024/12現在、NetSuiteから提供されているプラグインは、Visual Studio Code, WebStormのみとなります。
:::
:::note info
今回ご説明の機能の中には、追加で費用が発生する可能性のあるものも存在します。お気をつけください。
:::

引用)NetSuite Application Online Help：

https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_1529088392.html#subsect_1568818300
デザイナーが本業の傍らYouTubeを運営してみた →年内に収益化できた話

この記事は  [クラウドワークス グループ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ1の4日目の記事です。

## はじめに
クラウドワークスで働く、デザイナーの[@466548](https://x.com/466548) です。
新規事業の[PARK](https://park.jp/)と[メンバーペイ](https://memberpay.jp/)のデザイナーをしております。

2024年3月から、あるYouTubeチャンネルの運営に携わることになりました。視聴者としては長年YouTubeに親しんでいましたが、運営は完全な未経験。そんな状態からスタートし、試行錯誤を重ねた結果、1年も経たないうちに収益化条件をクリアすることができました。今回は、その過程で実践して効果のあった事案をご紹介します。

## 検索に強いチャンネルを作る！概要欄の最適化
チャンネル運営で最初に注力したのが、概要欄の徹底的な最適化です。視聴者の多くは検索やレコメンドから動画にたどり着くという事実に着目し、以下の点に特に注意を払いました：

- 詳細な情報を漏れなく記載
- 関連リンクの戦略的な配置
- 検索されやすいキーワードの戦略的な配置
- ハッシュタグの効果的な活用

## クリック率を高める！サムネイルABテストの実践
知名度の低いチャンネルにとって、サムネイルの質は視聴者獲得の生命線です。以下の具体的な施策で、サムネイルの改善を図りました：

- 小さな表示でも視認性の高いデザイン
- インパクトのある大きめの文字使い
- 定期的なABテストによる改善
- データに基づくデザインの最適化

## 驚きの相乗効果！ショート動画×通常動画
本編動画が充実してきた段階で、ショート動画の活用を開始。その結果、予想以上の効果を生み出しました：

- 本編動画に関連したショート動画の制作
- 「続きは本編で」という誘導の仕掛け
- ショート動画導入前と比較して月間再生回数が70%以上増加


## 今後の展望：1万登録者への道筋
収益化条件のクリアは、あくまでもスタートラインです。次なる目標として1万登録者達成を見据え、以下の施策を継続していきます：

- SEO対策の強化
- サムネイルのさらなる改善
- 週1回の定期的な動画投稿の継続
- 視聴者とのエンゲージメント強化

これらの取り組みを通じて、ショップ機能の解放など、新たなチャンネル運営の可能性も追求していきたいと考えています。

## おわりに
未経験からのスタートでしたが、データに基づく戦略的なアプローチと地道な改善の積み重ねで、思いがけず早いペースで成果を上げることができました。この記事が、これからYouTubeチャンネルを始める方の参考になれば幸いです。
今後も新しい取り組みにチャレンジしながら、視聴者の皆様により良いコンテンツを提供できるよう努めていきます。チャンネルの成長過程で得た新たな知見についても、随時共有させていただく予定です。