OmniAICreator/Qiita-1.07M huggingface dataset:
rex0220 項目書式プラグイン 日付による書式設定

項目書式プラグインで、日付による書式設定例です。

# 概要

日付による書式設定を行います。

- 受付日時と当日の比較によって、対応状況の書式を設定
    - 対応状況が完了なら、グレー
    - 受付日時から5日過ぎていれば、オレンジ
    - 受付日時から1日過ぎていれば、イエロー
- 期限と完了日の比較によって、期限の書式を設定
    - 完了日（未入力時は当日）が期限を過ぎていれば赤
    - 完了日（未入力時は当日）が期限の3日前を過ぎていればオレンジ

![2023-12-22_17h08_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5104d0b2-d00e-72db-cd30-62cd233391bc.png)

# 項目書式プラグイン設定

![2023-12-22_17h12_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1d090436-13ea-887f-8db5-cf6c21eafc24.png)

## 対応状況の設定

優先順位の高い条件から、順番に設定していきます。

- DATE_ADD(受付日時,5,"day")
    - 受付日時の5日後を"YYYY-MM-DD" 形式の文字列で返す
- TODAY()
    - 当日 "YYYY-MM-DD" 形式の文字列

```.js
// 対応状況が完了なら、グレー
対応状況="完了"

// 受付日時から5日過ぎていれば、オレンジ
DATE_ADD(受付日時,5,"day")<TODAY()

// 受付日時から1日過ぎていれば、イエロー
DATE_ADD(受付日時,1,"day")<TODAY()
```


![2023-12-22_17h13_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/39500ed0-cc7a-bdcf-a948-6ce5d0044505.png)

## 期限の設定

NVL 関数は、パラメータで最初に値があるものを返します。

- DATE_FORMAT(期限)
    - 期限 を"YYYY-MM-DD" 形式の文字列に変換
- NVL(DATE_FORMAT(完了日),TODAY())：
    - 完了日が入力済みなら、完了日。未入力なら、当日日付を返す。

```.js
// 完了日（未入力時は当日）が期限を過ぎていれば赤
DATE_FORMAT(期限)<NVL(DATE_FORMAT(完了日),TODAY())

// 完了日（未入力時は当日）が期限の3日前を過ぎていればオレンジ
DATE_ADD(期限,-3,"day")<NVL(DATE_FORMAT(完了日),TODAY())
```

![2023-12-22_17h14_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3b365bba-a127-73ee-fffc-77fff0994e49.png)
会社のイベント企画・運営をした話

この記事は デジタルキューブ ＆ ヘプタゴン Advent Calendar 2023 の 12月22日分の記事として執筆しています。

## はじめに
普段インフラエンジニアとして働いてる自分がイベント運営をすることになった。今まで企画やマネジメントなんてしたこともないし、サーバーいじってただけの自分が頑張った記録を残す。

## 参加することになった経緯
「若手メンバーで会社のイベント企画してよ」と言われ、始まった右も左も分からないイベント企画。若手メンバーだけということもあり、他のメンバーも何をすればいいか分からない状態。とりあえず、集まって話し合ってみることになった。

## 企画してみよう
とりあえず、はじめは顔合わせて自己紹介から始めた。その後、上司の方にいろいろ企画について教えてもらいながら、自分たちで当日のスケジュールや実施する内容を企画をしてみる。自分たちは一生懸命考えたつもりだけど、「他の人から見るとどうだろうか？」、「みんなが楽しめるような企画なってるだろうか？」いろいろ悩んだ。正直、「これ本当に面白いんか？」っていう不安はあった。

ちなみに、当日やったイベント内容は以下の通り
- アイスブレイク
- LT会
- トークセッション
- 懇親会

## 次々出てくる問題点
やることは決まった後は、登壇者への依頼・会場の予約・資料の準備などなどタスクが大量に発生する。自分たちではちゃんとやってるつもりでも、若手メンバーたちは詰めが甘い。あとから問題点が出てくる。

例えば、

- トークセッションの依頼をして登壇OKの依頼をもらった！→当日の流れも進行も伝えたし、バッチリだ！（でも、登壇者ってどんな人か普段どんなことやってるのか調査してないよね？モデレーターとしての仕事内容調べた？）
→数日前に調べ始めて辛い・当日の進行グダグダ

- 会場は⚪︎⚪︎駅から近くで収容人数・機材もこれだけあれば大丈夫だ！（現地行ってみないとどのぐらい広くて、どんな環境にあるのか分からないよね？）
→当日行ってみたら思ってたよりも狭くて地下にあったのでスマホの電波が入らない・備え付けの機材との相性が悪くて映像がブツブツ切れる・映らない

- 各企画の時間配分したし、これぐらいあれば大丈夫だろう（時間の見間違ってない？タイトに予定組すぎてない？）
→スケジュール見直したら時間見間違えて時間配分していた（登壇の依頼してた人たちが参加できなくなって何とかなった）・きっちり時間配分し過ぎて盛り上がった時などドンドン時間が押していく

他にもいろいろあって大変だった。準備はやり過ぎて悪いことはないので、イベント企画・運営する人は100%以上の準備をした方がいい。また、上手くいくことの方が少ないので常に悪い状況を想定して対応策まで考えておくと吉。

## 感想
めちゃくちゃ大変だった。普段の業務とは違うから何をするにしても調べながらで進捗が悪いし、人とのやりとりが発生するから思うように進まないこともある。でも、イベント当日に楽しそうにしてる人たちを見るとやって良かったという達成感もあった。またやる機会があった時には、今回の経験を活かして頑張りたい。

## 宣伝
上記で今回の経験を活かしたいと語ったけど、2024年1月20日に仙台でJAWS-UGのイベントで司会をすることになったので頑張ろうと思います。内容としては、re:Inventの感想を話してもらったり、新サービスの話をしてもらうイベントです。よかったら、きてください。

https://jaws-tohoku.doorkeeper.jp/events/166528
「オブジェクト指向設計実践ガイド」を読んだ

## はじめに

[オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方](https://www.amazon.co.jp/dp/477418361X) を読みました。

![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143317/039fd29c-4a6f-e6ef-393f-0b10d7c1fabd.png)

この本は、オブジェクト指向の設計について、Rubyのプログラムをサンプルに、分かりやすく解説されています。
設計について学びたいRubyエンジニアにおすすめできます。

これを学ぶことで、変更しやすい、メンテナンス性の高いコードを書くための考え方が身につけられます。
メンテナンス性の高いコードを書きたいと思っているRubyエンジニアは、個人的には、リーダブルコードの次に読むべき本だなと感じました。 (リーダブルなコードについては前提として知っておいたほうがいいです)

## どうしてこの本を読んだのか

クラスの設計、インターフェースの設計に苦手意識を持っており、元々社内でも多くの人がおすすめしている本だったので、読んでみようと思いました。

今まで、インターフェースを使ったオブジェクト指向の言語をあまりきちんと使ってきたことがありませんでした。そして、ある実装のレビューで、インターフェースがいまいちというコメントをもらったとき、きちんと腹落ちできていないことがありました。

「インターフェース」が存在しないRubyにおいて、インターフェースをどのように考えて、どうクラスを設計するのかを学びたいと思い、この本を読みました。

デザインパターンについて学ぶことも検討したのですが、先にコアとなる設計の概念を学んでから、実装のパターンを学びたいと思ったので、また次にしようと決めました。

## 目次

第1章　オブジェクト指向設計
第2章　単一責任のクラスを設計する
第3章　依存関係を管理する
第4章　柔軟なインターフェースをつくる
第5章　ダックタイピングでコストを削減する
第6章　継承によって振る舞いを獲得する
第7章　モジュールでロールの振る舞いを共有する
第8章　コンポジションでオブジェクトを組み合わせる
第9章　費用対効果の高いテストを設計する

## 感想、学び

- 「世界を、オブジェクト間の自発的な相互作用」という観点で捉える意味が、本を読んで理解が深まった
    - 相手のオブジェクトに対して、何をしてほしいのかのメッセージを送るが、どのようにしてほしいかという手順は知らなくていい
- 生み出す利益と、実現するためのコストを比較。この変更コストを下げるようにする。というのがシンプルでわかりやすかった
- 設計ができないことはプログラミングの抑止力にならない。後々の変更で苦しむという部分から、「設計が大事」と実感するときにはすでに遅く、効果が聞くまでに時間がかかることを感じた
- 「振る舞いに依存する」というのは、オブジェクト間だけでなく、オブジェクト内でも当てはまるという学び
    - インスタンス変数というデータではなく、アクセサメソッドを使う
- 別クラスとして切り出すべきか悩むのであれば、将来切り出せるように単一責任のメソッドとして実装するという方法もあること
- 「依存する」の理解がはっきりした。以下を知っていること
    - 「他のクラスの名前」「メッセージの種類(メソッド名等)」「メッセージが要求する引数」「引数の順番」
    - メソッドを呼び出した時点で、それに依存しているという点がスッキリした
- クラスのインターフェースを決める時、そのクラスが「何をするか」ではなく、「何をpublicにするか」を決める
    - publicなメソッドはそのクラスがどう振る舞うのか、責任を明らかにするもの
    - オブジェクトがどんなpublicメソッドを持っているかという抽象化したものがインターフェースとなる
    - そこに、他者が依存をする
    - ダックタイプも、このインターフェースに依存している
- 逆に呼び出す側は、どういうメッセージを呼び出したいか。「どのように」ではなく「何を」を頼む
    - そして、誰がそれに応答すべきか
- Moduleを、共通部分の切り出しくらいの意味合いで使っていたが、「ロールとして振る舞いを定義し、mixinしたクラスがそのロールを担う」ということができる
    - 今まで知らずにそのように実装していたが、明確に意味づけができるようになった
    - 同じモジュールをincludeしているオブジェクト同士は、同じインターフェースを実装しているので、入れ替えが可能になる
    - includeをすると、そのModuleが定義するパブリックインターフェースを持つことになるというのが発見だった
    - この抽象的なロールは具象よりも安定している
- コンポジションを使って、大きいオブジェクトを、小さい部品で組み立てる
    - 言語化していなかったけど、DDDの値オブジェクトとかもこれの一種なのかなと繋がった
- コンポジションを使うと、シンプルで利用性が高いオブジェクトを組み合わせて作っていける
    - 部品は理解しやすいが、組み合わされた全体は理解しやすいとは言えないこともある
    - 設計をしっかりすると、全体像が理解しづらくなるのは感じたことがあり、どちらに重きを置くかというところなのかなと感じた
- プライベートメソッドを持ちすぎたクラスは、責任を大量に持ちすぎている可能性がある

### 全体を通して

- 「設計」の苦手意識について考えていたが、「読みやすいコード」、「設計」、「アーキテクチャ」と、どれも重複する内容があり、どこが苦手なのかのマッピングが難しいと感じた
    - この本も設計の話でありながら、実装の詳細にも触れられていたりする
    - 自分はちょうどインターフェースの「設計」の部分が刺さったが、人によっては違うので、目次等を見ながら身につけたいところを探ったほうが良さそう
    - 他にも、手続き or オブジェクト指向、DDD、プログラミングの原理、原則、[Rubyのスタイルガイド](https://github.com/rubocop/ruby-style-guide)等関連するところはあるので、人によってどこからやるのかが違うのかもしれない
terraformでGKEを立ち上げてみた。

# はじめに

naritomoと申します。

本職はインフラエンジニアを行っています。

最近色々活用し始めているterraformからのK8Sインフラ構築を実施してみました。

いろいろアドバイスいただけると嬉しいです。

## 立ち上げ概要

terraformでGKE(GCP上のK8S)を立ち上げるものになります。

必要なソースは以下にまとめてあります。

https://github.com/naritomo08/terraform_GKE_public

## 前提

以下のページなどを参考に、terraform稼働環境を作成し、GCPでの適当なリソースが作成できる状態にあること。

とくにgcp.jsonファイルを作成できていること。

[Terraformをdocker環境で立ち上げてみる。](https://qiita.com/naritomo08/items/7e5a9d1b7eaf18dc0060)

Dockerを使用しない場合、以下のコマンドを利用できている状態になっていること。
```bash
aws

brew
*Terraform導入時に必要

tfenv
*terraform稼働コンテナを利用しない場合は必要
```

k8s関連コマンド(kubectl)を使用できていること。

以下のページを参考に手動コマンドでのGKE構築できていること。

[gcloudコマンドでGKEを立ち上げてみた。](https://qiita.com/naritomo08/items/d1a3122264b248915360)


### (コンテナ利用しない場合)指定バージョン(1.５.7)のterraformを導入する。

```bash
tfenv install
```

## terraformソースファイル入手

terraformを動かすフォルダ内にて、以下コマンドを稼働する。

```bash
git clone https://github.com/naritomo08/terraform_GKE_public.git
cd terraform_GKE
```

後にファイル編集などをして、git通知が煩わしいときは
作成したフォルダで以下のコマンドを入れる。

```bash
 rm -rf .git
```

gcp.jsonファイルを本フォルダに持ってくる。

## 作成（基本ネットワーク、GKE作成）

tfstateフォルダに行き、tfstate用バケットを作成する。

作成する際、”main.tf”内の<バケット名>部分を適当な名前に変更すること。

同じく、”provider.tf”内の<プリジェクト名>部分を使用しているプロジェクト名にする。

defaultフォルダ内へ順番入り、リソース作成を実施する。

作成する際、”backend.tf”内の<バケット名>部分を前の手順で指定した名前に変更すること。

provider.tf,varidate.tf内の<プロジェクト名>をgcpで使用するプロジェクト名にする。

### 作成コマンド

以下のコマンドで作成可能

一度作成できれば最後のコマンドのみでよい。
```bash
terraform init
terraform plan
terraform apply
→　yesを入力する。
```

*いくつかエラーでてくる際は落ち着いてエラーを訳して対応すること。大体API立ち上げかAMI権限追加になります。

## GKE利用方法

```bash
gcloud container clusters get-credentials cluster --region asia-northeast1

kubectl config get-contexts 
→コンテキスト情報が出ること
kubectl get nodes
→3台のノードがでてくること。
```

## サンプルデプロイ実施。

manifestフォルダに移動。
```bash
kubectl apply -f deploy.yml

kubectl apply -f svc-lb.yml
```

確認

```bash
kubectl get svc
→External-IPの値を確認する。(数分待つ。)
```

以下のサイトへアクセスしてnginx画面が出てくること。

```bash
http://<External-IP>
```

## サンプルデプロイ削除

```bash
kubectl delete -f .
```

## 削除方法

以下のコマンドで削除可能

```bash
ｃcd ../default
terraform destroy
cd ../tfstate
terraform destroy
kubectl config current-context
→はじめに出てくるnameのものを控える。
kubectl config delete-context <コンテキスト名>
```

# おわりに

この記事がTerraform/GKEを扱う方の助けになればと思います。
Node.jsでYouTube再生リストに含まれる動画リストを取得


こちらの記事の続きです。

https://qiita.com/n0bisuke/items/680ab634463eee2dbfd3

## OAuthクライアントとトークン情報を準備

- client_secret.json
- token.json

の二つを準備しておきます。


## 再生リストから動画の検索

色々なAPIがあっていまいちわからなかったのですが、ChatGPTに聞いて出てきたサンプルが役立ちました。

playlistItemsのメソッドが該当する模様です。

> ![スクリーンショット 2023-12-22 17.02.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/6ade5d17-8706-dca5-1970-0af322dbe301.png "スクリーンショット 2023-12-22 17.02.33.png")

ドキュメントを調べる -> サンプルではなく、ChatGPTに聞く -> ドキュメントを見るという流れ、効率的かも


https://developers.google.com/youtube/v3/docs/playlistItems/list?hl=ja

## 再生リストのIDを指定して、リスト内の動画を検索

```js
'use strict';

const fs = require('fs');
const {google} = require('googleapis');

const googleAuth = () => {
    const CREDENTIALS_PATH = 'client_secret.json';
    const TOKEN_PATH = 'token.json';  
    const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
    const token = JSON.parse(fs.readFileSync(TOKEN_PATH, 'utf8'));

    const {client_secret, client_id, redirect_uris} = credentials.installed;
    const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
    oAuth2Client.setCredentials(token);

    return oAuth2Client;
};


//↑ここまでは認証で共通 ↓ここから
(async () => {
    const auth = googleAuth();
    const youtube = google.youtube({version: 'v3', auth});
    // console.log(youtube.channels)
    try {
        const res = await youtube.playlistItems.list({
            part: 'snippet',
            maxResults: 50, // 一度に取得する最大動画数
            playlistId: `再生リストのID`
        });

        const videos = res.data.items.map(item => {
            return {
                title: item.snippet.title,
                videoId: item.snippet.resourceId.videoId
            };
        });
        console.log(videos);
    } catch (error) {
        console.log('The API returned an error: ' + error);
    }
})();

```

## 結果

アップロードして再生リストに追加してある動画が取得できました。

> ![スクリーンショット 2023-12-22 17.06.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c7570a99-3c5c-afaa-64f4-772eb5d8b5bb.png "スクリーンショット 2023-12-22 17.06.24.png")
Workato：lookup関数利用時の注意点

# はじめに
Workatoには `lookup` という関数があります。これは、特定の[Lookup Tables](https://docs.workato.com/features/lookup-tables.html)を検索し、その結果（値）を取得する関数です。

`lookup`関数を利用するメリットは、関数からLookup Tablesの値を取得できることです。例えば、条件分岐（if）のようなタスク消費に影響しないステップLookup Tablesの値を参照する場合、前段にLookup Tablesのアクションを追加することなく、関数で値を取得することができるため、タスク数の抑制に寄与します。タスク数の抑制は、レシピのコスト削減にもつながります。

# 注意点

`lookup` 関数で参照しているテーブルの名称を変更した場合は、 `lookup`関数のテーブルの名称もあわせて変更する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/5c96f953-f36d-0c9c-58e9-598803aaea27.png)

`lookup`関数側を変更しなかった場合、以下のようにエラーが発生しレシピが停止します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/afea74a4-216f-28b3-e80b-68235ed327de.png)

なお、関数ではなく、Lookup Tablesコネクタを利用する場合は、テーブルの名称変更の影響は受けません。タスク数は増えますが、メンテナンス性を考慮した場合（長期的な視点で考えた場合）、`lookup`関数ではなく、出来る限りLookup Tablesコネクタの利用をお勧めします。
ZealのCO-ODEデータを用いたDatabricksにおけるデータ分析

Zeal様がDatabricksマーケットプレイスのプロバイダーになることが、こちらのニュースリリースで発表されました。

https://www.zdh.co.jp/topics/20230914/

こちらのデータセットです。

https://www.zdh.co.jp/products-services/external-data/co-ode/

> オープンデータや外部データを収集・加工して配信しているサービス
> ～自社データ×外部データでデータ分析の高度化を実現～
自社データと外部データを掛け合わせると、要因分析・原因分析や将来予測を立てやすくなります。

![Screenshot 2023-12-22 at 16.28.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d892b0d7-3d1b-c719-b0ce-75c5ea479ab1.png)

Databricksマーケットプレイスからアクセスを申請します。申請する前に[こちら](https://www.zdh.co.jp/products-services/external-data/co-ode/)で料金体系をご確認ください。

承認されると以下のようなメールが届きます。
![Screenshot 2023-12-22 at 14.19.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/20da0dc9-3fc4-c145-f14d-0c4ec4bf1345.png)

マーケットプレイスの画面では**即時アクセス権を取得**ボタンが表示されます。
![Screenshot 2023-12-22 at 14.19.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/81f6c5f0-dfcd-703e-af5a-64779bca5f28.png)

取り込む際にはカタログ名を指定します。
![Screenshot 2023-12-22 at 14.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/34bdb7be-a9cf-1e27-0d36-2be465deaa77.png)

取り込みが完了すると、カタログエクスプローラでテーブルにアクセスできるようになります。
![Screenshot 2023-12-22 at 14.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/13142da7-a294-bd30-27db-557edcd8f297.png)

日本のデータなのが嬉しいですね。
![Screenshot 2023-12-22 at 14.25.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/925aaa48-7e52-4461-169c-962bfd343ebd.png)

今回はこちらの人口データを使います。

https://marketplace.databricks.com/details/bc3c9f86-6797-484e-82e5-016f09de8b7b/Zeal-Corporation_-

ノートブックで確認します。
```sql
SELECT * FROM zeal_corporation_population.coode_sample.population_2020;
```

[プロファイラ](https://docs.databricks.com/ja/visualizations/index.html#create-a-new-data-profile)でデータの傾向を把握します。
![Screenshot 2023-12-22 at 16.52.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/75610d44-2568-c4f1-914d-52e5d21eb401.png)

都道府県は1つしか無いので2020年時点の東京都のみのデータであることがわかります。その他の列を見ていくと、世帯や人口、職業などに関する定量データが含まれていることがわかります。

今回はクイックに[Lakeview](https://docs.databricks.com/ja/dashboards/lakeview.html)でダッシュボードを作ります。ところどころ[日本語で指示](https://qiita.com/taka_yayoi/items/4b3c4fe62e183cdf7d84)したりしてます。
![Screenshot 2023-12-22 at 16.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/460ca005-e662-f779-d21c-5e25b7583b11.png)

上の二つのグラフからは世田谷区や品川区の人口増加が著しいことがわかります。特に増減数のグラフからは23区の増加とそれ以外の地域の減少が顕著であることがわかります。

右下のグラフでは、人口数の少ない地域での高齢化を確認することができまます。こうなると3年後の今年のデータも見てみたくなりますね。
![chart (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5e3db7c0-e6cc-07ea-8665-187dfa2313fb.png)

分析のエクササイズには適したデータだと思います。この他のデータも見てみようと思いますし、データエンジニアリングして更なる観点で分析したいとも思いました。是非活用をご検討ください！詳細は[こちらのページ](https://www.zdh.co.jp/products-services/external-data/co-ode/)下部にあるお問い合わせフォームからお願いします。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Google APIのトークン取得で"このサイトにアクセスできませんlocalhostで接続が拒否されました。"


自分が管理しているYouTubeの再生リストを操作したいなと思ってAPI調べつつの詰まったところです。

何回かやってるけどいつも忘れている

## YouTube DATA APIのクイックスタート

こちらをやっていきます。

https://developers.google.com/youtube/v3/quickstart/nodejs?hl=ja

> ![スクリーンショット 2023-12-22 16.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/6c28a8c9-6e65-45fc-c323-0ab99e613e3e.png "スクリーンショット 2023-12-22 16.48.57.png")

### 準備など

- OAuthクライアントIDを作成して認証情報のJSONをDL
	- `client_secret.json`
- サンプルコードを作成して実行

### スコープ

サンプルコードでトークン作成するときにスコープの指定がありますが、何をしたいかによってSCOPESの値を変えると良さそうです。

- 読み込みのみ

```js
const SCOPES = ['https://www.googleapis.com/auth/youtube.readonly'];
```

- 管理全般

```js
const SCOPES = [
	`https://www.googleapis.com/auth/youtube`,
	`https://www.googleapis.com/auth/youtube.upload`
]
```

ドキュメントを参照すると以下のように書いています。

> ![スクリーンショット 2023-12-22 15.25.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/8a26a6a6-dbe1-7829-6f8c-0b10580ebfda.png "スクリーンショット 2023-12-22 15.25.44.png")
> https://developers.google.com/youtube/v3/guides/auth/installed-apps?hl=ja#handlingresponse

## サンプルコードの実行(認証)

以下のようにURLが発行されるので、アクセスします。

> ![スクリーンショット 2023-12-22 16.52.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5e0cb8ad-5517-b5c8-f916-fa340f58ce7e.png "スクリーンショット 2023-12-22 16.52.25.png")

進むとGoogleアカウント選択 -> YouTubeアカウント選択 -> 許可を求められます。

> ![スクリーンショット 2023-12-22 15.27.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/876448c9-1a3b-58b9-0b21-fd751587dac6.png "スクリーンショット 2023-12-22 15.27.39.png")

## 許可をすると`このサイトにアクセスできませんlocalhost で接続が拒否されました。`と表示される

されるんですけど、URLをよくみるとlocalhost/?code=コード&scope=~~~といったURLになっています。

> ![スクリーンショット 2023-12-22 15.41.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/dc637c49-b99b-2568-b9f7-a1cd5e25a0ad.png "スクリーンショット 2023-12-22 15.41.48.png")


```
http://localhost/?code=<この部分>&scope=https://www.googleapis.com/auth/youtube%20https://www.googleapis.com/auth/youtube.upload
```

このcode部分をコピーして、ターミナルの入力を求められている箇所に貼り付けて進めばOKです。

> ![スクリーンショット 2023-12-22 16.55.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/88b57111-e5c3-9f9b-6613-bb513cec8068.png "スクリーンショット 2023-12-22 16.55.52.png")

おそらくデフォルトのままだと`ホーム/.credentials/`の中に`youtube-nodejs-quickstart.json`というファイルで認証情報が入ったjsonファイルが保存されます。

> ![スクリーンショット 2023-12-22 15.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/578cf551-ee15-0d80-b2f6-71ea5c7285f0.png "スクリーンショット 2023-12-22 15.43.07.png")

これをtoken.jsonなどに名前を変えて他の場所でも利用できます。

## 参考

こちらの記事が参考になりました。

https://www.y-hakopro.com/entry/google_oauth_api
わかりやすく汎用的なリテンション率の求め方

# リテンション率とは

リテンション率とは、Web サービスやアプリなどの新規顧客が一定期間内に再訪した割合を示す数値です。「定着率」「継続率」「顧客維持率」とも呼ばれています。

# 課題感
リテンション率を SQL で求める参考記事はインターネット上にいくつかありますが、以下のような課題感があったので改めて自分なりにまとめてみました。
- 初回訪問から３０日間でのリテンション率を求める場合、愚直に 1 日ずつ ３０ 列カラムを用意している
- 初回訪問日を基準として集計している記事が少なく、モニタリングの際にどの時点でのどのユーザー群のリテンション率を表しているか理解するまでに時間がかかる（できれば直感的に素早く理解したい）


# やること
1. リテンション率を求める
2. Looker Studio で可視化

※今回は GA 4 のサンプルデータを利用します。

# 1. リテンション率を求める



```sql:retention_rate.sql
DECLARE from_date STRING DEFAULT '20201201';
DECLARE to_date STRING DEFAULT '202112０１';
DECLARE rr_days INT64 DEFAULT 7;

WITH first_visit_log AS (
    SELECT DISTINCT
        user_pseudo_id,
        DATE(TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo') AS first_visit_date,
        i AS diff_days,
        DATE_ADD(DATE(TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo'), INTERVAL i DAY) AS target_date
    FROM
        `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`,
        UNNEST(GENERATE_ARRAY(0, rr_days, 1)) AS i
    WHERE 1=1
        AND _TABLE_SUFFIX BETWEEN from_date AND to_date
        AND event_name = 'first_visit'
)
, 
action_log AS (
    SELECT DISTINCT
        user_pseudo_id,
        DATE(TIMESTAMP_MICROS(event_timestamp), 'Asia/Tokyo') AS action_date
    FROM
        `bigquery-public-data.ga4_obfuscated_sample_ecommerce.events_*`
    WHERE 1=1
        AND _TABLE_SUFFIX BETWEEN from_date AND to_date
        AND event_name = 'session_start'
)
, 
flag AS (
    SELECT
        a.user_pseudo_id,
        a.first_visit_date,
        a.target_date,
        a.diff_days,
        case when b.action_date is not null then 1 else 0 end AS action_flag
    FROM
        first_visit_log AS a
    LEFT JOIN
        action_log AS b
    ON a.user_pseudo_id = b.user_pseudo_id
        AND a.target_date = b.action_date
)
SELECT 
    first_visit_date,
    target_date,
    diff_days,
    count(user_pseudo_id) as user_cnt,
    SAFE_DIVIDE(sum(action_flag), count(user_pseudo_id)) as rr
FROM flag
WHERE target_date <= PARSE_DATE('%Y%m%d', to_date)
GROUP BY 1,2,3
ORDER by 1,2,3
```
ポイントは `UNNEST(GENERATE_ARRAY(0, rr_days, 1)) AS i` です。愚直にカラムを生成していないため、`rr_days` を変更すればリテンション期間を簡単に変更できます。
あとは、flag 句でリテンションのターゲット日にアクションがあったかどうかを action_flag で判定し、最終的にカウントすれば終わりです。簡単！！


# 2. Looker Studio で可視化
上記のクエリを実行 & BigQuery にテーブルを作成し、Looker Studio で以下のように可視化しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616917/dfeefd53-699f-da0a-21fa-97b54ad4ae5c.png)
diff_days = 1 は 常に 100 % であるためフィルタ機能で除外しています。
また、カラースケールを付けておくと、パッと見てリテンション率の変化が分かります。例えば、上記の表では 2020/12/02 に新規登録したユーザーの 1 日後・ 2 日後のリテンション率は高くなっていますが、3 日後にはガクッと下がっていることがわかります。（短期型の施策を打ったからでしょうか？）

また、時系列で確認してみるのもおすすめです。どうしても表だと長期的な比較は厳しいので。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616917/9932e8cb-7773-3bfa-143f-f7080e4d043e.png)
このグラフから、年末年始で全体的にリテンション率が下がり、それ以降は回復していることがわかります。

# まとめ
リテンション率を求める際に毎度インターネットで求め方を検索していましたが、自分が求めたいリテンション率に整形するためにかなり苦労していましたが、これからは上記のクエリ一発で求められるようになりました。
【Unity】ML-Agents学習結果のTensorBoardグラフがださいので自分で作る

[KuMA Advent Calendar 2023](https://adventar.org/calendars/9549) の 22日目の記事です．

Unity ML-Agentsで学習すると自動でログファイルが作成され，TensorBoardで確認することができます．

こんな感じのコマンドでTensorBoardを呼び出します．
![powershellTensorboard.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/1a6a310d-f4ad-d119-0745-9ec22eb45d20.jpeg)

表示されるグラフはこんな感じ．
![tb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/89362479-f89d-865d-9fae-f6ee15f3cf0c.jpeg)
軸のラベルがなかったり，1000が1e+3となっていたりして，レポートや論文でこの画像をそのまま貼るだけだと少しださいので，ログファイルを自分で読んでグラフを作ってみます．


ログは.tfeventsのファイルにバイナリデータとして保存されています．
![UG2d4_q-.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/1a7db305-8379-105b-f67f-54ec4211c303.jpeg)


バイナリデータなのでメモ帳とかで開いても読めないようです．
![binary.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/2133778c-d7c9-0b1e-8732-b9b47bc0b94f.jpeg)

これを読むにはTensorFlowをインストールする必要があります．ここでは一番簡単そうなGoogle Colaboratoryを使うことにします．Colab上で読めるように，以下のようなコードを作成しました．

```Python
import tensorflow as tf
import pandas as pd
import matplotlib.pyplot as plt

# TensorFlow 2.xのEager Executionを有効化（Colabではデフォルトで有効）
tf.compat.v1.enable_eager_execution()

# TensorBoard ログファイルのパス
log_file_path = '/content/events.out.tfevents.1686475046.DESKTOP-SOFV0RV.2812.0'
# 出力CSVファイルのパス
output_csv_path = '/content/output_data.csv'

# タグ
tags_of_interest = [
    'Environment/Cumulative Reward',
    'Environment/Episode Length',
    'Losses/Policy Loss',
    'Losses/Value Loss'
]

# データを格納するための辞書
data = {tag: [] for tag in tags_of_interest}

# TFRecordDatasetを使用してログファイルを読み込む
for raw_record in tf.data.TFRecordDataset(log_file_path):
    event = tf.compat.v1.Event.FromString(raw_record.numpy())
    for v in event.summary.value:
        if v.tag in tags_of_interest:
            data[v.tag].append({'Step': event.step, 'Value': v.simple_value})

# タグごとにデータフレームに変換し、CSVに保存
for tag, values in data.items():
    df = pd.DataFrame(values)
    df.to_csv(f'/content/{tag.replace("/", "_")}.csv', index=False)

    # グラフをプロット
    plt.figure(figsize=(10, 5))
    plt.plot(df['Step'], df['Value'], marker='o', label=tag)
    plt.title(f'{tag} Over Training Steps')
    plt.xlabel('Training Step')
    plt.ylabel(tag)
    plt.legend()
    plt.grid(True)
    plt.show()

```

ログファイルのパスの部分を自分のファイル名に合わせて変更してください．

先ほどの.tfeventsをcolab上の「ファイル」にアップロードして実行すると，無事，読み込んだデータから以下のようなグラフを作成できました．
![reward.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/3f61f782-661b-fbc0-8c5a-fac3d3299ff4.png)

![episodeLength.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/0f078eb2-95fa-ae61-9da0-1f922c7c7909.png)

![policyloss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/9acb97d5-10e4-15f9-0a1d-0061d4af0e6d.png)

![ValueLoss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/c5e85ab0-cde3-7b83-171c-a929a4676fbb.png)

もう少し細かい周期で値を記録してもよかったかもしれません（.yamlファイルのsummary_freq:	12000の部分で指定する値）．

あとは，お好みに合わせて調整ください．



ここまで読んでいただきありがとうございました．
【初心者向け】4STEPでわかる! IETF WG入門

# はじめに
IETF116にNOCとして参加したことをきっかけに技術標準化に興味を持ち、社内の有識者の方々からアドバイスをもらい、IETFの情報収集をしていましたが、非常に学びが多かったため今回は初心者向けのIETF情報収集STEPをご紹介します。

ご紹介の中では、実際に例があったほうがIETFの探検ステップがイメージしやすいと思うため、私が実際にどのようなジャーニーをたどったか記載しています。

# そもそもIETFとは
IETFとはInternet Engineering Task Forceの頭文字で、インターネットのプロトコル標準化などを行う組織・会議を指します。毎年3月・7月・11月の3回開催されており、大体6日間(日曜〜金曜)開催されます。

日本開催はIETF116が8年ぶりで前回は2015年のIETF94でした。

# STEP1:　Working Groupの選定
そもそも「技術の標準化」といっても面食らう方が多く、どのようなテーマの標準化に関して自分の知見を深めていきたいかわからない方も多いのではないでしょうか?

IETFではWorking Group(以下WG)と呼ばれる、各トピック・テクノロジーごとに標準化に取り組むメンバーが集まり議論を行うグループがあります。

[Active IETF working groups](https://datatracker.ietf.org/wg/)から現在活動中のWorking Groupを見つけることができます。

それぞれのWorking GroupページのAboutにはCharterと呼ばれる、そのWGの活動内容や目標を記した文章があり、そこで大まかな方向性や現状の課題を把握することができます。

私は全WGのCharterを読み、自分の興味分野を探してました。
私は特にCDNの相互接続の標準化を行うWG、CDNI　WGの活動に共感したので参考までに[CDNIのCharter](https://datatracker.ietf.org/wg/cdni/about/)をこちらにおいておきます。

# STEP2:　基本情報の収集
自分の興味や志と一致するWGを見つけたら、より深ぼりをする前に基本情報の収集を行いましょう。
技術情報の収集は本・Web・技術雑誌・Speakerdeck等あると思いますが、今回私はCDNに関してより現状の課題の分析等をしたかったため、田中祥平さん著の「Web配信の技術」を読みました。

このSTEPは意外と重要で、STEP3,4等で出てくる標準化のバックグラウンドを理解・予想する際に役立ちます。


# STEP3:　WG Draftを読む
基本情報の収集が終わったら、WG　Draftを読みます。Draftとは、現在IETF　WGにて検討中の新しい技術標準となります。
例えば、CDNIのDraftは2023年12月現在7本あり、

```
・Content Delivery Network Interconnection (CDNI) Control Interface / Triggers 2nd Edition
・CDNI Metadata for Delegated Credentials
・CDNI Cache Control Metadata
・CDNI Edge Control Metadata
・CDNI Protected Secrets Metadata
・CDNI Capacity Capability Advertisement Extensions
・CDNI CDNI delegation using Automated Certificate Management Environment
```
になります。私はこのDraftの中でも特にCDNI Cache Control MetadataとCDNI Protected Secrets MetadataのDraftは特に現代のCDNの抱える課題の解消や、よりよいCDNの実装に貢献できるものだと考え、この2つに関して更に深堀りして調査することにしました。

# STEP4:　メーリングリストのアーカイブを読む
現在のDraftを読んだだけでは、どのような文脈で現状のDraftの形になっているのか、また直近のDraftから今日までどのような議論が行われているかのキャッチアップができません。これを解決するためにメーリングリストのアーカイブを読んでみるのがおすすめです。こちらもWGページのAbout→Mailing List Archiveから閲覧できます。

例:[CDNI メーリングリストアーカイブ](https://mailarchive.ietf.org/arch/browse/cdni/)

# まとめ
今回はIETF WG入門と題して初心者の方向けの記事を書きました。

私自身、有識者の方からいろいろとご教示いただき、実際に正しいIETF　Datatrackerの歩き方がわかっていると、情報の海に溺れることなく楽しんで標準化の動向を追いかけることができると感じました。
本記事をきっかけに少しでも標準化トレンドを追いかけ、楽しんでいただける方が増えればと思います。

# 参考情報
[IETFの動向について](https://www.soumu.go.jp/main_content/000683102.pdf)
[真に“オープン”な実践が技術進化を加速-IETFの存在意義とは何か？](https://gblogs.cisco.com/jp/2023/03/ietf116yokohama-blog1-miyakohno/)
実務6ヶ月エンジニアがPHP8技術者認定初級試験に合格した話

# PHP8技術者認定初級試験合格体験談

## 自己紹介

2023年7月、未経験エンジニアとして株式会社コネクタージャパンに入社。PHPのLaravelを使って開発をしている中で、何か学んでアウトプットする機会が欲しいと思い、PHP8技術者認定初級試験にチャレンジしました！

## 勉強時間と教材

トータルの勉強時間は大体20～30時間だったと思います。使った教材は下記の２冊です！

- **独習PHP第４版**
  - [Amazonで見る](https://www.amazon.co.jp/%E7%8B%AC%E7%BF%92PHP-%E7%AC%AC4%E7%89%88-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/4798168491)

- **徹底攻略PHP7技術者認定［初級］試験問題集**
  - [Amazonで見る](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5PHP7%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A-%E5%88%9D%E7%B4%9A-%E8%A9%A6%E9%A8%93%E5%95%8F%E9%A1%8C%E9%9B%86-%E5%86%85%E5%B1%B1-%E7%A5%A5%E6%81%B5/dp/4295006645)

問題集はPHP技術者認定機構の公式本ではないものの、PHP8版の公式問題集が手に入らなかったため代替品として利用しました。

## 勉強法

1. **独習PHP第４版の一通りの読了**
   - 全部理解する必要はなく、できない部分もある。基本を押さえることが目的。

2. **問題集を解く**
   - **1周目**
     - わからないことを簡単にメモしながら問題を解く。
     - 問題集の解説が充実しているため、解説を自分なりに文章でまとめる。
     - 通勤時にもメモをパラパラ読みながら記憶の定着を図る。

   - **2周目（2週間前ぐらい）**
     - 記憶の定着の確認を目的にさっと解く。
     - 理解が難しいところを重点的に独習PHP第４版を使って理解する。
     - このタイミングで[公式模擬試験](https://study.prime-strategy.co.jp/study/ph8el1/)を受験。（私は6割しか取れなかった。。）

   - **3周目（1週間前ぐらい）**
     - 苦手なところを中心に、自分なりに解説を作りながらアウトプット型の勉強を行う。
     - PHP8からの新機能を見ておく。（match式など）
     - 公式の模擬問題や世に出回っている問題も手当たり次第解く。

3. **試験直前**
    - 問題集、模擬試験ともに100点取れる状態まで復習する
    - 関数などの暗記系に力を入れる。

## 試験の難易度と感想

**難易度**
本番の試験は結構難しかったです！！
問題集よりかは難易度が高く、模擬試験の難易度と似ています。
PHP８の新機能も少なからず出たので対策必須かなと思います。

**感想**
試験終了後すぐ結果がわかるのですが、私の場合迷った問題が40問中10問もあったため最後クリック押すときの手汗はとんでもなかったです・・

ただ、基本的な問題も多く出るので問題集を完璧にするのはとても重要だと感じました。
試験時間はよっぽどでなければ余ると思うので十分見直しできます！

地味に戸惑った点としては、章ごとに問題が出ると思っていたのですが、本番の問題ではランダムで出たということです。

資格があるから大きなメリットがあるというわけではないですが、アウトプットも兼ねてチャレンジしてみてよかったなと感じました！実際にPHPの仕組みがわかってきたので、実務でも役に立っています！

少しでもお役に立てれば幸いです！

## 一緒に働く仲間を募集しています！
株式会社コネクター・ジャパンでは一緒に働いてくれる仲間を募集しています！

事業拡大に伴い、エンジニアさんを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/cnctor/about
▼代表メッセージ
https://cnctor.jp/10years-anniversary/
▼応募はこちら
https://www.wantedly.com/projects/1522201

「ご質問があれば、Xまで気軽にDMをお送りください！」
Power Automate Desktopで複数フォルダを一気に圧縮

## Power Automate Desktopで複数フォルダを一気に圧縮

https://twitter.com/MitsuhiroM82423/status/1729848716368990502

みなさん、こんにちは。
紙、印鑑、手作業に埋もれて業務をしている昭和男子の会社員です。

毎月、**請求書を大量に発行**し、メール送信している業務を行っています。
前回、請求書のExcelファイルをメールに添付し間違えないように取引先ごとに**Excelファイルを仕分け**しました。

[前回の記事はこちら](https://qiita.com/miyabe-mitsuhiro/items/de8086c3c7cd5bca6216)

https://qiita.com/miyabe-mitsuhiro/items/de8086c3c7cd5bca6216

複数のファイルをいちいちメール添付するのが手間だし、**容量も大きく**なります。
そこで仕分けしたフォルダを**PowerAutomateDesktopで一気に圧縮**しました。
## 使用するもの
・Power Automate Desktop
## Power Automate Desktopの設定
![2023-12-22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288463/f8290734-d54b-77e1-2990-d7f76db02c1d.png)

**フローのソースコード**
```ruby:複数フォルダを一気に圧縮
Folder.GetSubfolders Folder: $'''\\\\mvssmain\\共有\\05_商品\\専用\\11_契約関連\\02_リベート契約\\2023年度\\割り戻し計算確認書自動作成用\\メール送信用フォルダ作成''' FolderFilter: $'''*''' IncludeSubfolders: False FailOnAccessDenied: True SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Subfolders=> Folders
LOOP FOREACH CurrentItem IN Folders
    SET NewVar TO CurrentItem.Name
    Compression.ZipFiles ArchivePath: $'''\\\\mvssmain\\共有\\05_商品\\専用\\11_契約関連\\02_リベート契約\\2023年度\\割り戻し計算確認書自動作成用\\メール送信用フォルダ作成\\%NewVar%.zip''' FilesOrFoldersToZip: $'''\\\\mvssmain\\共有\\05_商品\\専用\\11_契約関連\\02_リベート契約\\2023年度\\割り戻し計算確認書自動作成用\\メール送信用フォルダ作成\\%NewVar%''' CompressionLevel: Compression.CompressionLevel.BestBalanceOfSpeedAndCompression ArchiveComment: $'''''' ZipFile=> ZipFile
END
```
## メール添付が楽に
**メールの自動送信**をしたくて、添付ファイルをフォルダ毎にまとめることにし、**フォルダを圧縮**したのですが、自動メール送信が出来ていない状態の今でも、添付間違いも発生しにくいし、添付作業が**一回で済むので楽**になりました。
自動メール送信にまた一歩近づきましたが、一部の取引先様から、「**文字化けする**」との連絡が・・・
「**文字化け**」の課題がありますが、現時点でも**ミスの減少、作業軽減**に繋がっています。
実際にメール送信しているパートさんからも「**楽になった**」喜んでいただいています。
簡単な割に、意外と効果がありますよ～。ぜひ、使ってみてくださいね:ok_hand:
Pythonでasyncなexecを実現する方法

:::note info
この記事は、[Python Advent Calendar 2023](https://qiita.com/advent-calendar/2023/python)の23日目です。
:::

`exec` を使うべきじゃないといった話は一旦置いておくとして。

# 実現したいこと
引数で指定した文字列をPythonコードとして実行する `exec` 関数。
しかし、その中で `await` を使いたい！ と思っても、単純にはできません。

次のコードはエラーになります。
```python:exec.py
import asyncio

async def run():
    print('start')
    await asyncio.sleep(3)
    print('end')

async def main():
    script: str = 'await run()'
    exec(script)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
```
```shell-session
awayume@assam:~/programming/playground$ python exec.py
/home/awayume/programming/playground/exec.py:13: DeprecationWarning: There is no current event loop
  loop = asyncio.get_event_loop()
Traceback (most recent call last):
  File "/home/awayume/programming/playground/exec.py", line 14, in <module>
    loop.run_until_complete(main())
  File "/usr/lib/python3.11/asyncio/base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/awayume/programming/playground/exec.py", line 10, in main
    exec(script)
  File "<string>", line 1
SyntaxError: 'await' outside function
```

`await` を非同期関数外から使っていると怒られます。
というわけで、結論。

# ならば非同期関数を作ってしまおう
つまり、実行したいコードを非同期関数の中に入れて定義し、`exec()` の外からその非同期関数を呼び出してやればいいのです。

```python
def get_script(code: str) -> str:
    return 'async def _exec():\n ' + ' \n'.join(code.split('\n'))
    #       ^ 非同期関数を定義        ^ インデントを追加

async def main():
    exec(get_script('await run()'))
```

非同期関数を定義することができました。
では、それを呼び出してみましょう。しかし、`_exec` は `exec` のローカルスコープで定義されているので、直接呼び出すことはできません。呼び出そうとすると、`NameError: name '_exec' is not defined.` が発生します。
それを解決する方法は複数あります。

## `locals()` を使う
```python
await locals()['_exec']()
```
`locals()` でローカル変数の辞書を取得し、定義した関数を取り出して実行しています。

## `exec()` に名前空間として辞書を渡す
よく知られているように、`exec` は第一引数に実行するコードのオブジェクトを取りますが、Optionalな第二引数、第三引数も存在します。
第二引数は `exec()` 内でコードを実行するときのグローバルスコープ、第三引数はローカルスコープをそれぞれ取ります。
```python
dic = {}
exec(get_script('await run()'), None, dic)
await dic['_exec']()
```
ローカルスコープとしての辞書を定義し、そこから定義した関数を取り出して実行しています。

個人的には前者の方が好みです。

# まとめ
パンが無いなら作ればいいじゃないの。
Google Cloud　Eventarcをトリガーにしたときに送られてくる情報一覧

## Eventarcをトリガーにしたときに送られてくる情報一覧

以下のコードに書いてあります。

https://github.com/googleapis/google-cloudevents/blob/5e0764ca0f5732db44aacde4f8e9d53849dd3f1f/proto/google/events/cloud/storage/v1/data.proto

https://github.com/googleapis/google-cloudevents/blob/5e0764ca0f5732db44aacde4f8e9d53849dd3f1f/jsonschema/google/events/cloud/storage/v1/StorageObjectData.json
変数の型について再考～PHP組み込み関数"trim"の実行結果より～


## はじめに
先日、PHPのプログラムを実行中に、"Warning: number_format() expects parameter 1 to be double, string given in ..."というWarningが発生した。

原因は、DDSで数値型で定義されていたフィールドをPHPが参照し、その結果に対して組み込み関数"trim"を使用し、文字列となった値をテンプレート側で数値を期待しているフィールドに値をセットしていたことであった。

## 組み込み関数"trim"
説明するまでもないことかと思うが、PHPの組み込み関数"trim"は、指定した引数（文字列）の前後の空白を除去する機能を持っている。

以下は、"trim"を数値型の変数に対して使用した場合のコードである。

```php:trim_test
<?php
$test = 20231225;
$teststr = '20231225';
$trim = trim($test);
var_dump($test);
var_dump($trim);
var_dump($teststr);
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3070417/adfec721-dca6-8de9-c871-165d9f098088.png)


上記の例を見ると、"trim"は文字列に対して行う関数であるが、数値に対して使用すると数値を文字列に変換しており、今回のWarningが発生したことがわかる。

最も"trim"は文字列に対して使用する組み込み関数であるため、数値型に対して使っていること自体が適切ではないことは明白だが、変数の型について再考するきっかけとなった。


## RPGでの変数の扱い
RPGでは変数を宣言する際、必ず型桁の定義をする。これにより変数には、定義された型の値を転送することや定義された型によって使用する命令に制限がかかる。

例えば、数値型の変数同士の値転送では"Z-ADD"を用いるのに対し、数値型の変数を文字列型のフィールドや変数に転送するときは"MOVEL"命令を使う。

使用する命令が異なるため、意図的に変数の型変換を行っていると言える。

命令に制限がかかることなどは、一見窮屈に感じるかもしれないが、予期せぬ挙動を防ぐという点で見れば理にかなっているのではないだろうか。

## 変数型について
PHPの学習をしている中で、PHPは変数の型の定義をすることなく、変数に数値をセットしたらint型、文字列をセットしたらstring型として扱ってくれるなど柔軟性が高いと感じた。

筆者自身プログラマーとしての期間がまだ１年半ほどと経験が浅いこと、未経験の状態で最初に学んだ言語がRPGであることに起因する部分も大きいと思うが、今回のWarningを経て、変数の型は定義した方がよいと感じた。

変数を扱う上で、意図的に型を変更するのと意図せず型が変わっているのとでは、予期せぬ挙動が起こりかねないことも踏まえて大きく意味が異なるからだ。

## 最後に
今回は、変数の型から意図したコードを書くことの重要性を再確認したが、変数の型に限らずコードを書くときは、何のために、何の目的があってそのロジックを書くのかということが非常に重要であると思う。

実行結果に問題がないからOKではなく、目的を持ったコードを書くことを大切さを再認識した。
[IBM Cloud認定試験] IBM Cloud DevSecOps v1 Specialty 受験体験記

# IBM Cloud DevSecOps v1 Specialtyについて
IBM Cloud DevSecOps v1 Specialtyは、主にIBM CloudにおけるDevSecOpsの分野の専門性を認定する試験です。
現在は英語だけではなく、日本語でも受験可能な試験となっています。

https://www.ibm.com/training/certification/ibm-cloud-devsecops-v1-specialty-S2112100

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/97bddce5-bdb5-f2ae-4557-8f7dfc776257.png)

# 学習教材
### ラーニングパス （おすすめ度：★★）

https://www.ibm.com/training/path/ibmclouddevsecopsspecialty

- IBMが公式で提供しているラーニングパス（試験対策のe-Learningコース）です。
- ラーニングパスの中に記載されている細かい内容についても問われる場合がありますので、一通り内容を抑えておくとよいかもしれません。
- 途中で出てくるQuizに合格するとOpen Badgeがもらえます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/021f8856-23f5-42b5-d286-49e7c2d15d41.png)

### IBM Cloud Prep （おすすめ度：★★★★）

https://ibm-cloud-prep.yourlearning.ibm.com/certifications/ibm-cloud-devsecops

- 模擬試験とStudy Guideを提供しているIBM Cloud認定試験の専用対策サイトです。
- 基本的には、ラーニングパスを一通りやったあと、ここの模擬試験をやって、わからないところがあったらStudy Guideを参照するという流れで学習を進めました。
- Study Guideの内容は、ラーニングパスの内容で網羅されている印象でしたので、わからないところがあったときにチラ見したくらいでした。
- 模擬試験とStudy Guideは、英語で提供されていますが、日本語で受験される場合は、Google翻訳やDeepL翻訳などのツールを利用して、学習を進めるとよいと思います。

# 試験結果
テストセンターで受験し、無事に合格することができました（まさかの満点）
ちなみに試験言語は日本語でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134250/25af0741-0169-c2e3-bd4f-0d390b1d3fc3.png)

# 受験した感想
- IBM Cloud Prepでの対策をきちんとやっていればとても簡単でした（ラーニングパスはやらなくてもよかったかも？）
- 試験ページのOverviewに記載されていますが、受験前にProfessional Architect, Professional Developer, Professional SREのいずれかを取得されることを強くおすすめします。
- 私の場合、この試験を受ける前に[IBM Certified Professional Developer - Cloud v6](https://www.ibm.com/training/certification/ibm-certified-professional-developer-cloud-v6-C9005400)を受験していたのが大きかった気がします。

# 個人的に抑えておいたほうがよいと思った範囲
メモ書き程度ですが、以下のあたりは特に抑えておくとよいと思いました。
当然ですが、これらが試験に必ず出るという意図ではありませんので、ご注意ください。

- DevSecOpsの概要やベストプラクティス
    - LeftShiftとか
- DevSecOps Reference Pipelinesのそれぞれの違い
    - Pull Request (PR) Pipeline
    - Continuous Integration (CI) Pipeline
    - Promotion Pipeline
    - Continuous Deployment (CD) Pipeline
- Continuous Delivery
    - [Toolchain Templateの種類](https://cloud.ibm.com/docs/ContinuousDelivery?topic=ContinuousDelivery-cd_about&locale=ja)
    - DevOps Insightsの概要とユースケース
    - Code Risk AnalyzerやVulnerability Advisorで検知できる内容
    - Security and Compliance Center（SCC）との連携
- Sauce LabsやSonarQubeなど各種ツールの概要
- SchemanticsとTerraform,Ansibleの連携
【PostgreSQL】デフォルトロールについて

## 初めに
PostgreSQLでは、特定のデータベース操作を行うための権限を持つ「ロール」が事前に定義されています。これらは「デフォルトロール」または「組み込みロール」と呼ばれ、データベースの管理やセキュリティを効率的に行うための道具となります。
PostgreSQL14では、データベース管理に必要な特権を持ついくつかの事前定義されたロールが提供されています。これらのロールは、データベースの機能や情報へのアクセスを容易にするために存在します。管理者は、これらのロールをユーザーや他のロールに付与することで、特定の機能や情報へのアクセスを許可できます。

## デフォルトロール
- pg_read_all_data
すべてのデータ（テーブル、ビュー、シーケンス）を読み取る権限。
- pg_write_all_data
すべてのデータに対してINSERT、UPDATE、DELETE権限。
- pg_read_all_settings
スーパーユーザーのみが通常読み取れる全ての設定変数を読み取る権限。
- pg_read_all_stats
スーパーユーザーのみが通常読み取れるpg_stat_*ビューと統計関連のエクステンションを使用する権限。
- pg_monitor
監視ビューや機能を読み取り/実行する権限。pg_read_all_settings、pg_read_all_stats、pg_stat_scan_tablesのメンバー。
- pg_signal_backend
他のバックエンドに問い合わせのキャンセルやセッションの終了のシグナルを送信する権限。
- pg_read_server_files
サーバ上の任意の場所からファイルを読み取る権限。
- pg_write_server_files
サーバ上の任意の場所にファイルを書き込む権限。
- pg_execute_server_program
サーバ上でプログラムを実行する権限。

## ポイント
- ロールの理解
PostgreSQLのロールは、データベース内でのユーザーやグループの権限を管理するための重要な概念です。
- セキュリティの重要性
これらのロールを付与する際は、セキュリティを考慮し、必要な場合にのみ付与することが重要です。
- 管理の容易さ
事前定義されたロールを使用することで、データベースの管理がより簡単かつ効率的になります。

## 参考
- [PostgreSQL公式ドキュメンテーション](https://www.postgresql.jp/document/14/html/predefined-roles.html)
ECSライフサイクル設定メモ(terraform)

# 初めに
現場でAWSのコンテナサービスであるECSを利用し、システムを構築した際のハマったポイントについて共有します。

# そもそもECSとは
Amazon ECS(Elastic Container Service)はコンテナ化されたアプリケーションを簡単にデプロイ、管理、スケーリングできる、完全マネージド型のコンテナオーケストレーションサービスです。(AWS公式ドキュメントより)

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/Welcome.html

コンテナ化したアプリをマネージドサービスで利用したいという場合に選択されることが多く、　CI/CDパイプラインと合わせて導入されるケースも見受けられます。

ECSでは、コンテナをタスク定義という形で記述します。

![ECSサンプル.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50168/f9867560-548b-b7b3-0a67-0d8703a8441e.png)


ECSの詳細な説明は割愛するため、上述の公式ドキュメントをご確認ください。

# 利用してみて気になること

マネージドサービスを利用している分、ユーザ側ではコンテナをデプロイしたら気軽に使える一方、以下のようなことを調べるときに時間がかかることが多いです（筆者の経験より
- 起動しなかった場合の状態把握（インフラ起因？アプリ起因？）
- スケールアウトした場合の発生時刻や原因調査

**ECSのイベントを知ることで、よりECSの運用に対するハードルを下げることができます**

# ECSのライフサイクルについて
ECSのサービスやタスクの見える化EventBridgeを活用し、ECSイベントを取得できるようにします。

具体的には、以下の4つ状態変化イベントについて知ることが出来ます。

| No | イベント名 | 説明 |
|:-:|:-|:-|
| 1 | コンテナインスタンス状態変更イベント  | コンテナインスタンスの起動・停止やタスク停止によるインスタンスのリソース変化など |
| 2 | タスク状態変更イベント  | タスクの状態変化(PENDING から RUNNING または RUNNING から STOPPED)  |
| 3 | サービスアクションイベント  | サービスのレベルをINFO(正常な状態)、WARN(サービスがタスクの起動に失敗する状態)、ERROR(サービスがタスクの配置に失敗する状態) で分類  |
| 4 | サービス展開状態変更イベント |  サービスがアプリをデプロイするときに発生する状態変化(デプロイの成功や失敗)で分類 |



https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cloudwatch_event_stream.html

## 具体的な手順
こちらを参考に進めました。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/container-insights-ECS-lifecycle-events.html

### Terraformでは以下のリソースを用意
 1. [aws_cloudwatch_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group)
 2. [eventbridge](https://registry.terraform.io/modules/terraform-aws-modules/eventbridge/aws/latest)

当初2つを用意したのですが、イベントブリッジのイベントが全てFailedとなり、ライフサイクルイベントが取得できておりませんでした。
再度ドキュメントを確認したところ、以下のリソースを追加したところ、ライフサイクルイベントを取得することができるようになりました！

 - [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document)


# まとめ
- クラウドベンダのマネージドが多いことは運用者にとっての負担軽減につながる一方、状態の把握が難しい時がある
- ECSライフサイクルを活用することで、マネージドなコンテナサービスでも状態を見える化できることで、障害発生時や高負荷時における原因切り分けが容易になるため、ぜひ設定はしておきたい


皆様のコンテナライフのお役に立てば幸いです！！
初めてJAWS-UGに参加して運営もやることになった話

## はじめに
2020年に入社してすぐにコロナが流行して、オフラインイベントの開催が難しい期間が続いた。当時オンラインイベントなど開催されていたが、最近になってやっとオフラインイベントの開催が増えてきた。両方参加してみた自分がオンラインイベントとオフラインイベントの違い・JAWS-UGに参加してどうだったかまとめてみようと思う。

## 参加することになった経緯
コロナが落ち着いてオフラインイベントが開催されるようになり、社内でも話題に上がったのが「JAWS-UG 東北 〜東北エンジニアの祭典〜」。なんでも東北支部が全部集まって開催するからJAWS-UGの中でも規模が大きいらしい。「そこで登壇してみない？」と上司に誘われた。

正直、初めてのオフラインイベントがそんな人の多いところは緊張するけど、これも経験だと思って登壇者枠で申し込んだ。これがJAWS-UGに参加することになったきっかけ。（社内にトップエンジニアなど最前線で活躍する方がいて、自分もそうなりたいと思ったのもある。）

## JAWS-UG 東北 〜東北エンジニアの祭典〜
仕事が忙しく、その合間に発表資料の準備をする。平日は忙しくて土日に作業することが多かった。正直、準備は大変だった。話すネタもなく、周りは難しそうな内容をやってる中で自分は何を話すか悩んでいたのを覚えている。

自分は当時SESの設定ミスで障害を起こし、結構大きめの被害を出してしまった。そんな自分が自戒も込めて「SESで失敗した話」という内容で発表をした。以前オンラインイベントでも登壇したことがあるが、発表を聞いてる人の反応が見えないため、淡々と話してるだけで不安になることがあった。しかし、オフラインイベントでは、聞いてる人の顔だったり反応が見えるので発表しやすかった。オフラインイベントも気軽に参加できるなど利点はあるが、「初めて登壇するよ！」っていう人はオフラインイベントの方が発表しやすいかもしれない。

他の人の発表に比べると質が低かったと思うが、そんな自分の発表も「聞いてて面白かった」、「自分も昔こういうことがあって〜」と話しかけてくれる人が多くて嬉しかった。その後の懇親会でも、発表について質問されたり、普段話せないような方々とお酒を飲みながら楽しく時間を過ごせた。懇親会できるのもオフラインイベントならではのいいところ。

## JAWS-UG TOHOKU サーバレスハンズオン勉強会
初めて参加したJAWS-UGが楽しかったのもあり、自分も運営メンバーに加わりたいと思い相談してみた。いきなりの申し出にも快諾してもらい、運営メンバーとして参加することになった。運営メンバーとなり、初めて参加したのが、サーバレスハンズオン勉強会。内容としては、AWS Step Functionsの使い方を勉強するものだった。

以前は登壇者の立場だったが、今回は教える立場。まずは、自分が理解する必要がある。この時までAWS Step Functionsを使ったことがなかったため、他のメンバーが作成してくれた資料を読み進めながら勉強してみようと思った。しかし、前回同様仕事が忙しくて中々手がつけられない。それに加えて当日の運営に関するアレコレを他の運営メンバーと話し合う。イベントを運営する立場がこんなに大変だとは考えてもいなかった。でも、当日の段取りや資料作りなどとても勉強になる。

いろいろと準備が終わってイベント当日、早めに会場に行って準備して受付して質問に答えて・・・やることが多い。そんなこんなで大変だったけど、イベントは無事終了。登壇する時とは違った達成感があるので、興味ある人は運営もやってみてほしい。

ずっとリモートワークで働いてた自分にはなかった他者との交流も増えて人脈も広がるし、面白い話も聞けるので参加できる人は懇親会にも出よう。

## まとめ
コロナで緊急事態宣言が出てからずっと家に引きこもってた自分が、初めてオフラインイベントに参加してみたふりかえりを書いてみた。JAWS-UGは雰囲気も良く、活動的なコミュニティなので初めてのイベントに参加する人には是非オススメしたい。

また来年の目標として、以下の3つがある。
- SAPを取得する
- 登壇を増やす
- 自分が主体となって運営してみる

また来年振り返った際に、いい報告ができるように頑張ろうと思う。

## 宣伝
2024年1月20日に仙台でre:Inventの感想を話してもらったり、新サービスの話をしてもらうイベントを開催します。よかったら、参加してください。

https://jaws-tohoku.doorkeeper.jp/events/166528
非エンジニアが気軽に使えるURLからドメイン(eTLD+1)を抽出する社内ツールを作ってみた

## はじめに

[Metaps Advent Calendar 2023](https://qiita.com/advent-calendar/2023/metaps) 23日目の記事です！

普段はマークアップエンジニアから半分フロントエンドエンジニアに足を突っ込んだような領域でお仕事をしています！

## 何を作りたいのか？

諸事情あって、ビズ側（セールスやマーケターetc.）の業務で個別の企業を特定する手がかりとしてドメイン(eTLD+1)をキーとして使うことになったのですが、彼らが手作業でURLからサブドメインやディレクトリ、パラメーターを抜こうとするとミスやエラーも多く、何より時間がかかってしまうため、すきま時間で開発してみることにしました。

## でもJavaScriptで作るのはなかなかに難しい……

例えば、`.jp`や`.com`などのTLDを正規表現でマッチさせようとすると、`.jpn.com`のような二つのドメインを組み合わせたドメインがあったりします。`.jp`は必ずしも一番最後にならないし、2文字で終わるとは限らないので正規表現でうまくマッチできません。



また、`.co.jp`や`.com`などTLDやeTLDを総当たりに正規表現で並べるのも、これらのドメインは`.toyota`や`.sharp`など年々増えておりとても現実的ではないのです。
なので、Javascriptで処理するのは諦めました。


## JavascriptとPythonを連携させるのにチャレンジ
JavasciptではダメでもPythonなら色々便利なライブラリがあるらしいということで連携させて使うことにしてみました。

今年Python1年生を見ながら触り始めた正真正銘のPython1年生ですが、ちゃんと欲しい形のドメインを簡単に抽出することができるツールを作れました。Pythonすごいな…

### ツール概要

テキストエリアに貼ったURLをJSONデータとしてAPIにPOSTして
API側で各URLに分解して、ドメイン抽出のライブラリにかけています。
そして、抽出したドメインを配列で返して表示しています。


### どんなライブラリを使ったのか？

https://pypi.org/project/tldextract/


## 動作サンプル

<iframe width="560" height="315" src="https://www.youtube.com/embed/EJc4-_De5DI" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

## 終わりに

簡単に使えるドメイン抽出ツールを作ることができました。
社内で利用してもらうことができ、だいぶ省力化できたとのことで嬉しいです。

サブドメインで子会社を分けたり、ドメイン以下のディレクトリで子会社が分かれているところは、全て同じドメインになってしまって使えないのが…心残りですね。
AWS CostExplorerの直近2日間のデータは当てにしてはいけない

AWS CostExplorerについて、最近「え〜？！」と思ってしまったことがある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/e977739a-acd6-8212-97af-bb0eb9b326af.png)

__表示日時がUTCである__ ・・・それはまあそうだと思う。違和感はない。

__当日のデータは今まさに増加中の数値__ であって結果ではない（例えばラベルが「12月11日」なら日本時間で12月11日09時から12月12日09時まえまでの時間は今まさに増加中の数値）。これも当然そうだと思う。

__データの更新頻度はそんなに高くない__。 _"Cost Explorer refreshes your cost data at least once every 24 hours."_（[引用元](https://docs.aws.amazon.com/cost-management/latest/userguide/ce-what-is.html)） そうだよね、そんなもんだと思う。

ただ _"..., and some data might be updated later than 24 hours."_ （同）ともあって、__実際 例えば今日が12月12日なら、CostExplorerで表示される請求額のうち12月12日のデータはもちろん11日のデータも未確定で、12月10日以前になってようやく確定__ になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/3ed6f80d-1a85-a623-f262-62d7fac4043d.png)

12月12日9時（午前9時）ちょっと過ぎにこの状態ならまだわからなくもないが、同日夕方になってもこの状態。。。
夕方、流石にもう確定しているだろうと思って（それっぽい数字だったから）、それを前提にプロジェクト内で会話をしていたのに、翌日になってから見てみるとあら不思議。全然数値が違っている。

結論。
__AWS CostExplorerの直近2日間のデータは当てにしてはいけない❗__
Github Copilot ショートカット一覧 【VSCode】

最近になって Github Copilot を学生は無料で利用できるということを知り（いまさら……）学生の登録と Github Copilot の利用を開始しました．

:::note 
学生が Github Copilot を無料で利用するための申請についてはこちらの記事を参考にさせて頂きました．
https://qiita.com/SNQ-2001/items/796dc5e794ac3f57a945 (SNQ-2001(たいしん)様)
:::

ショートカットキーについてまとめている記事が少なかったため，自分用のメモとしてこちらにまとめておきたいと思います．なお，本記事は[GitHub Copilot の概要](https://docs.github.com/ja/copilot/using-github-copilot/getting-started-with-github-copilot)をまとめたものになります．

|項目|コマンド|説明|
|--|:-:|:-|
|コードの生成|`ctrl + Enter`|コメントに従ってコードの生成をおこなう|
|インラインチャット|`ctrl + i`|Github Copilot に会話形式でコードの生成を依頼できる|
|候補の生成|***|コードの候補を生成してくれる|

|候補に対する操作|コマンド|説明|
|--|:-:|:-|
|候補の受け入れ|`tab`|提示された候補を受け入れる|
|代替候補の表示|`Alt + [` or `Alt + ]`|次の候補を表示 or 前の候補を表示|
|候補の部分的な受け入れ|`ctrl + →`|表示された候補のうち，次の単語を受け入れる|


# コードの生成
コメントに従ってコードを生成してくれます．コマンドは`ctrl + Enter`です．

```python: test.py
# 素数をmax_numまで挙げていき，それらを格納したリストを返り値とする関数
```

上記のようなコメントに対して，`ctrl + Enter`を実行すると下のような結果が得られました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/c9cb7c1f-1c63-d346-c837-3ed6942ad04e.png)

いくつかの候補が出てくるので，気に入ったコードの`Accept Solution`を実行することでコードに反映されます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/2e6feaa4-23a3-f2ac-1974-d0c3b5e43c00.png)

# インラインチャット
Github Coplilot に会話形式でコードの生成を依頼できます．コマンドは`ctrl + i`です．
いくつかの操作については既に特定のコマンドが用意されているようです．その呼び出しは`/`でできます．今回は`/doc`を試してみました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/24959f4d-4be2-4859-a82a-32ce1312d32b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/df98ba58-2447-32ed-cab9-6c6e7fe569f1.png)

関数のdocstringが自動で生成されました！

# 候補の生成
候補の生成には特に操作は必要ありません．ただコードを記述していくとそれに合わせて候補を生成してくれます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693436/27b68af2-111b-c6fe-7418-5f097b25ade3.png)

候補に対する操作は下表の通りです．

|候補に対する操作|コマンド|説明|
|--|:-:|:-|
|候補の受け入れ|`tab`|提示された候補を受け入れる|
|代替候補の表示|`Alt + [` or `Alt + ]`|次の候補を表示 or 前の候補を表示|
|候補の部分的な受け入れ|`ctrl + →`|表示された候補のうち，次の単語を受け入れる|

# 最後に
ここに紹介している以外にも便利なコマンドがあれば紹介頂けますと幸いです．

また，今回 Github Copilot に書いてもらったコードを掲示しておきます．

```python: test.py
# 素数をmax_numまで挙げていき，それらを格納したリストを返り値とする関数
def make_prime_list(max_num):
    """
    指定された範囲内の素数のリストを作成する関数。

    Parameters:
    max_num (int): 素数を探索する範囲の最大値。

    Returns:
    list: 範囲内の素数のリスト。
    """
    prime_list = []
    for num in range(2, max_num + 1):
        for i in range(2, num):
            if num % i == 0:
                break
        else:
            prime_list.append(num)
    return prime_list


def make_prime_list_v2(max_num):
    prime_list = []
    for num in range(2, max_num + 1):
        for p in prime_list:
            if num % p == 0:
                break
        else:
            prime_list.append(num)
    return prime_list

if __name__ == '__main__':
    print(make_prime_list(100))
    print(make_prime_list_v2(100))  
```

出力結果は以下のようになります．

```bash
>> python3 test.py 
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
```
回転制御　コマンド

local test = vci.assets.GetTransform("Empty2")
local a = 0
local SubItem = vci.assets.GetTransform("アイテムの名前")
local angle = 1

function updeteAll()
a = 0 + 1
if a > 360 then
a = 0
end
test.SetLocalRotation(Quaternion.euler(0,a,0))

angle = angle + 1
SubItem.SetLocalRotation(Quaternion.Euler(-90,0,0) * Quaternion.Euler(0,0,angle))
end

SubItem.SetLocalRotation(Quaternion.Euler(-90,0,0) * Quaternion.Euler(0,0,angle))
ここに関しては、回転速度と軸の固定するところになります。
そして複雑に回したいなら、(Quaternion.Euler(-90,0,0)ここを()の数字の中を変えるだけです。
失敗したくないなら最初は、C♯で作って動きを確認してからLuaに組み込むといいかと思います。
私も失敗していろいろと教えてもらいながら勉強しています。
皆さんもがんばって作れるように見守っていきたいと思います。

私は、初めての投稿になりますが今後、新たな商品を作っていきたいと思います。
応援よろしくお願い致します。

結城明日奈アクセサリーショップ　
https://natuirokisek.thebase.in/?_gl=1*16vaufz*_ga*MTU0MDE2NjY0NC4xNzAzMDE0MzE4*_ga_574HL6KGKQ*MTcwMzAxNDMxOC4xLjEuMTcwMzAxNDM5MC40OC4wLjA.
もし、興味がありましたら覗いてみてください。
ザシードオンラインで販売中のSAO記録媒体になります。これに回転のプログラム入れて動かしております。
無料なので、取得してみてね。
https://virtualcast.jp/products/17d5a49e09ea922e0c221e873228302c455a1607635c072f1a4b336402d1a109