OmniAICreator/Qiita-1.07M huggingface dataset:
Google Analytics 4をBigQueryで集計する時に気をつけること

Google Analyticsはコンソールから設定するだけで、簡単にBigQueryへのエクスポートが可能です。BigQueryにエクスポートすることで正確に集計できるだけではなく、新規ユーザーや独自のパラメータでの条件なども正確に設定可能になります。

この記事ではBigQueryで集計する際に、知っておくべき注意点などをまとめていきます。


# 気をつけること
## 基本的に数値は一致しない
BigQueryで集計した結果は、Google Analyticsのコンソールの数値と完全に一致することはほぼありません。これはBigQueryや集計の問題ではなく、Google Analytics 4（以下GA4）のコンソールの仕組みのためです。

GA4ではコンソールに表示する際に以下の2つの仕組みが働いています。
1. [推定値](https://support.google.com/analytics/answer/9191807?hl=ja)を用いた集計値の表示
1. プライバシーを守るための[フィルタリング](https://support.google.com/analytics/answer/9383630?hl=ja)

推定値はその仕組みからPVやユーザー数が多いサービスほど差が大きくなりますし、フィルタリングはデータが少ない場合に適用されるものになるため、ほとんどのサービスが影響を受けることになるかと思います。

[公式ドキュメント](https://support.google.com/analytics/answer/9191807?hl=ja)にも
> 元データからより正確な結果を取得したい場合は、BigQuery で結果を確認してください。

と記述されていることからBigQueryのデータを信じるべきなようです。他のページでも2-5%ほどのずれは存在すると言われているので、以下のページを参考にBigQueryの集計を検証しましょう。

[GA4] アナリティクス レポートと BigQuery にエクスポートされたデータを比較する

https://support.google.com/analytics/answer/13578783



## ユーザー関連のデータが抜け落ちる
具体的にはユーザーの新規アクセスの情報と、性別などの個人の情報が減ることになります。
こちらは[Googleシグナル](https://support.google.com/analytics/answer/9445345)という仕組みがBigQueryでは使えないことが原因です。

GoogleシグナルとはGoogleアカウントと紐付けて分析が行える機能で以下のようなメリットがあります。
- 複数のデバイスやブラウザでのアクセスも、同一のユーザーとして認識できる
- 性別や年齢などの個人情報を正確に把握できる

しかしこれらは前項でも述べたプライパシーの観点から、BigQueryにはエクスポートされない情報となります。ですのでBigQueryの集計結果では新規ユーザー数が増える可能性が高いです。

解決するには独自でユーザーのIDを設定したり、性別などの情報を集めることになります。Google Analyticsのコンソールと一致させることが重要であれば、Googleシグナルの機能をOFFにすることも考えられます。しかし後で有効にすると整合性の問題もありそうなので、以下のページを確認してからOFFにしてください。

[GA4] Google アナリティクス 4 プロパティで Google シグナルを有効化する

https://support.google.com/analytics/answer/944534


## テーブルの違いとタイミング
[エクスポートされるデータ](https://support.google.com/analytics/answer/9358801)は速報のテーブルと確定後のテーブルの2種類が存在します。

GA4のコンソールのデータは反映されるまで時間がかかりますが、速報のストリーミングテーブルはほぼリアルタイムでデータが蓄積されるため、当日のデータをすぐに確認したい場合に適していると言えます。

具体的な違いは[公式ドキュメント](https://support.google.com/analytics/answer/9358801)から確認できます。注意点を抜粋すると下記となります。

**速報テーブル （events_intraday_YYYYMMDD）**
- 新規ユーザーの場合、流入元のデータが存在しない
- データが漏れている可能性がある

**確定テーブル（events_YYYYMMDD）**
- 反映まで最大72時間かかる

反映のタイミングを気にしなければ確定テーブルを利用することが推奨です。実際に利用していると次の日の夕方ごろまでには生成される感覚ですが、日によるブレが大きく段々と長くなっている印象です。（2023/12時点）


# まとめ
全て公式ドキュメントに記述されていることにはなりますが、情報が散らばっており筆者は苦戦しました。事前に知っておかないと要件を満たせない可能性もありそうなので、これから移行を考えている方の助けになれば幸いです。

ZOZO NEXTではエンジニアを募集中です。新しい技術を活用した開発にどんどんチャレンジできる環境ですので、興味がある方はカジュアルに応募いただければと思います。

https://hrmos.co/pages/zozo/jobs/0000209

https://hrmos.co/pages/zozo/jobs/0000210

https://hrmos.co/pages/zozo/jobs/1809846973241688076
テキストベースでの意思確認をスムーズに行うためのコミュニケーション

## はじめに
こんにちは、私はシステム開発のディレクションを生業としている者です。
フルリモートで勤務しているため、コミュニケーションは基本slackを使用しております。
この資料では、そんな私がテキストでのコミュニケーションをとる際に意識しているコミュニケーション方法を紹介いたします。

## テキストベースの意思確認のメリットとデメリット
### 【メリット】
#### ・任意のタイミングで確認ができる
会話ベースの意思確認の場合、全ての関係者が同じタイミングで時間を確保する必要があります。
そのため、多忙な人や勤務時間が異なる人とのコミュニケーションに役立ちます。

#### ・文章としてやり取りが残る
後の確認が容易で、システムによっては簡単に検索ができる。
引き継ぎが発生した場合も、後任者が確認しやすい。

### 【デメリット】
#### ・意思確認に時間がかかる
会話ベースであれば、不明点や他の情報が欲しければその場で質問し回答をもらうことができます。
しかし、テキストベースでは、質問が発生するたびにタイムロスが発生します。
→論点を明示して質問の回数を減らす工夫が必要になります。 (2)参照

#### ・会話ベースに比べてコミュニケーションロスが起こりやすい
相手が誤った理解をしてしまったり、返信がなくそのまま放置されてしまうことがあります。
→理解しやすい文章を心がける必要があります。(1)参照
→返信をもらえるように工夫する必要があります。(3)参照

## テキストベースのコミュニケーションで工夫できること
上記に記載したようにテキストベースでのコミュニケーションは、
時間に縛られないという大きなメリットがありますが多くのデメリットも抱えています。
このデメリットを克服するための工夫を以下に記載します。

### (1)文章の冒頭でコミュニケーションの目的を伝える
メッセージの冒頭で「質問をしたいのか」「何かを共有したいのか」「お願いをしたいのか」などの目的を冒頭で記載します。
```
(記載例:質問)
⚪︎⚪︎さん
お疲れ様です。
XX案件について2点質問させてください。
①リリース時期は、、、
②成果物の納品方法は、、、

(記載例:共有)
XX案件について2件ご認識いただきたいことがあります。
①担当者の変更が、、、
②進捗の遅れが、、、

(記載例:お願い)
XX案件の要件定義着手にあたり、2つお願いごとがございます。
①情報の提供をお願いします。ご用意いただきたい情報は、、、
②マスタデータのご準備を、、、
```
このように文章の冒頭で相手に何をして欲しいかを記載することで、
相手の理解力、返信の精度を高めることができます。
また、質問の件数を伝え、①、②のように番号を振ることで
片方の質問しか回答が返ってこないというコミュニケーションロスを予防できます。
返信する際も、「①の回答は、、、」というようにコミュニケーションがとりやすくなります。

### (2)論点を明示する
質問をする場合は、何に困っているのか何が論点なのかを明示します。
さらに、その論点に関するメリットデメリットを合わせて伝えます。

```
(記載例)
①リリース時期はいつが良いでしょうか？
11月末にリリースする場合
(メリット)年末年始需要を取り込むことができます。
(デメリット)リソースの追加が必要になります。

12月末にリリースする場合
(メリット)体制変更なしで安全にリリースすることができます。
(デメリット)年末需要の真っ只中にリリースすることになります。
```

漠然と「リリース時期はいつが良いでしょうか？」
と質問した場合、「いつ以降ならリリースできるんですか？」といった質問返しや
「9月リリースでお願いします」などこちらの想定していない回答をもらいやすくなります。
回答の選択肢とメリットデメリットを添えることで、軽い誘導とスムーズなコミュニケーションが実現できます。

### (3)返信をもらえるようにする工夫
#### 文章を長くしすぎない
あまりにも文章が長いと確認を後回しにされて、返信を忘れられてしまうかもしれません。
すぐに回答をもらいたいなら10行くらいまでにまとめてみてください。

slackなどで文章が長くなってしまう場合は、スレッドに分割して記載するなど、読みやすくなるように工夫しましょう。
![スクリーンショット 2023-12-06 14.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986066/d34e0295-832b-9d8e-789c-f83a05a3e538.png)
↓スレッドの中身
![スクリーンショット 2023-12-06 14.52.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986066/d4b118ae-ebee-5de5-017c-86998b3025b0.png)


#### 期限を設定する
いつまでに回答が欲しいのか伝えましょう。
期限を設定しておけば、回答をもらえなかった時に
自然にリマインドすることができます。
```
(記載例)
ご多忙のところ恐縮ではございますが⚪︎月⚪︎日(金)までにご回答よろしくお願いいたします。
```

## 最後に
以上、私がテキストベースのコミュニケーションで意識していることを紹介させていただきました。
みなさんが工夫していることやご意見があればぜひコメントに記載してください。
UiPath グローバルハッカソン参加してきた　前編

インドで開催されたUiPathグローバルハッカソンに参加してきたのでレポを書いていきます。

# 概要
インドのバンガロールで開催されます。
24時間耐久で自身のアイディア(開発)とプレゼン資料を0から作成するという短期決戦型ハッカソンになります。
最大4人チームで参加することが可能です。
https://community.uipath.com/events/details/uipath-hackathons-presents-ai-at-work-hackathon-bengaluru-24-hours/

私自身の英語力は某出川と同じくらいです。
ハッカソンに参加するくらいならなんとかなりますので、
ハッカソンに参加してみたいけど英語がなーって方は二の足を踏む必要ないですよ！


# 参加までの流れ
UiPathフォーラムを眺めていたらハッカソンの登録受付してるよ！という記事を発見、今回はUiPathとAIを組み合わせたものがお題でした。
https://forum.uipath.com/t/ai-at-work-in-person-24-hours-hackathon-is-in-bengaluru-this-25th-26th-november-registrations-extended-till-november-7/647505

### 1. アイディアの登録
```
フェーズ 1: アイデア (オンライン登録)
このフェーズでは、選択した問題/ビジネス チャンスに対する解決策を開発するための戦略を登録します。
コミュニティの専門家チームは、独自性、革新性、解決される問題の潜在的な影響に基づいてアイデアを評価します。

この段階で最終候補に残った上位チームは、LIVE 対面ハッカソンに招待されます。
```

ということでまずはオンラインでアイディアの登録をします。
主催者に評価されると登録した時のメールアドレスに直接最終候補に残った旨のメールがきます。

### 2. 最終候補に残ったので渡航準備
ハッカソンが11/25開催でメールが来たのが11/7なので準備期間は20日弱
でも大丈夫！パスポートの発行が1週間待たされるだけです。
ビザも日本人であればインドの空港で取れるので用意すらしていきませんでした。。。

### 3. 技術検証と情報収集
* 技術検証
自分の提出したアイディアを一度事前に組んでおきましょう。
事前練習をしておくだけでハッカソン当日のコーディングが作業に代わります。

* 情報収集
以前ハッカソンに参加した人にアドバイスをもらうのが一番！
UiPath Friends Festival 2023に参加してハッカソン参加者に沢山質問させていただきました。
初対面の私でも快く対応いただき、プレゼンの方法などをアドバイスをしていたきました。
UiPath Friendsに感謝！！

# いざハッカソンに参戦
日本から乗り継ぎを含み13時間、インドのバンガロールに到着。飛行機の時間の関係で1日前乗りしました。
ハードモードが好きな私は今回の旅で縛りを加えることにしました。制約と誓約ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630106/2014eea7-065e-4f0e-53a2-296d14873709.png)
内容は以下のようなもの
* タクシーの使用禁止：バスと電車で移動して現地人と触れ合う
* 分かったフリをしない：分かるまで聞こう、分かったフリをしてその場を乗り切るのは簡単
* 目が合ったら話しかける：フレンドリーさを忘れずに


### ハッカソン開催前日のUiPathオフィスにアポ無し突撃
※褒められる行為ではありません。

明日の会場を確認しにUiPath Indiaのオフィスビル前まで行きました。
平屋が多い中、いきなり超近代的なビルがドーンと建っていてめちゃくちゃ存在感あります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630106/49158588-3781-721e-77a5-12e0d856c720.png)

せっかく来たんだから挨拶だけでもしておこうと考えていざオフィスに、、、門前払いされたら仕方ないの精神です。

警備員に事情を説明し、待つこと約10分、UiPathグローバルコミュニティーマネージャーと対面
アポなしなのにもかかわらず「よく来たな！」的な感じでオフィス内に通してもらい、備え付けのバーラウンジで談笑しました。
その時の様子がこちら
https://www.linkedin.com/posts/rohitradhakrishnan1_uipathcommunity-automation-uipathhackathon-activity-7133780648795799552-bVfF?utm_source=share&utm_medium=member_desktop


# ハッカソン当日
こちらの詳細は
UiPath Friends 2023 ~ 🎄ハッピーオートメーションクリスマス🎄~
でお話させていただきます。ぜひご参加ください。
https://uipath-friends.doorkeeper.jp/events/166867

後日Qiitaにも書きますのでお楽しみに！
俯瞰して視る思想の変化

本記事は [オルトプラス Advent Calendar 2023](https://qiita.com/advent-calendar/2023/altplus2023) の12/13の記事です。

アドベントカレンダーも折り返しを迎えました！
初めまして！
オルトプラスでSREをやっております安藤と申します。
社内と心の平穏を担えるエンジニアを目指して日々思考を廻らせております

## ◇はじめに

オルトプラスに入社してもうすぐ3年になります。
お恥ずかしながら入社時の私は業界経験も浅く、今でもまだまだ未熟さが抜けない部分も多々あります。
そんな私が、運や縁もあり、現在はSREチームのリード役を任せていただいております。
日々チームのために目を向け、あれこれ思考し、チームを良くしようと行動し、会社への影響も与えることも少なくもなくなってきた私が、入社してから今までの経験の中で変わってきた考え方について、お伝えできればと思います。

## ◇自己を高める

いきなりですが、この記事を読まれているあなたの仕事に対するモチベーションはなんでしょうか？
…プロジェクトを成功させてお金を稼ぐことでしょうか？
…最新の技術を用いてあれこれ業務改善することでしょうか？
…はたまた、たくさんの成果を出して上司に認められ、評価されることでしょうか？

じゃあ、安藤さんのモチベーションは何ですか？と聞かれたとしたら
迷わず今の私なら"人と繋がりを持つこと、他者に幸福感を与えられること"と答えます。
単純な話、人との繋がりが増え、私自身の成果で他者へ良い影響を与えることが喜びに繋がります。

どうしてこんな話をしているのだろうか？と思う方もいらっしゃると思いますが
私自身、モチベーションを理解することのメリットには、仕事に対してのやりがいや幸福感を増幅させることができると思います。

例えばの話…
私は、正直なところ、技術やお金には関心が薄い自覚があります…
新しいサービスが出ました、新機能で今までの〇〇が改善されるようになりました。
新しいプロジェクトで導入しましょう、という話になっても
…いいねぇ！とはなっても他の人ほどわくわくしません。
対応が功を奏して売上で〇〇万円上がりました、と言われても
…「やりました！」とはなっても、感激したり、心が高ぶることはそれほどありません。

成果や物事に対して関心が薄いというのは、どうしても生産性や仕事の質の向上感のなさは否めません。

では、これらモチベーションと繋げて意識的に考えたらどうでしょう？
新しい技術を導入 -> それによってカンファレンスやコミュニティ等に参加し、それによって人との繋がりを作る
お金を稼ぐ(売上をあげる) -> 成果を出して、お客さんとの信頼関係を作る

このように、関心がないことであっても自分のモチベーションに繋げることを意識するだけで、物事に対する向上心を得られるようになったと思います。

## ◇チームリーダーとして

モチベーションの話でもしましたが、もともと人と関わるのが好きで世話好きの私です。
チームリーダーを任され、同僚としてのサポート役ではなく、メンバーそれぞれが自走し、生産性をあげられるチーム作りを考えることになりました。
ただ、先頭にたってぐいぐい引っ張っていくというのもなかなか難しいところ…
そこで私自身どういうリーダーになりたいか考えた先が、サーバントリーダーシップという考え方でした。

### サーバントリーダーシップとは

サーバントリーダーシップとは、リーダーシップを取る方法のひとつで、リーダーが自らをサービス提供者と見なし、チームや組織のメンバーの成長と福祉を最優先に考えながらメンバーにアプローチし、チーム運営をしていきます。
従来のリーダーが主導権を握り、意思決定を一方的に行う支配型リーダーシップとは違い、成長を促すことに重点を置き、チームワーク、協力、個人の発展を促進し、組織全体の健全な成長を目指します。

### 仲間に奉仕する

サーバントリーダーシップとして私が心がけていることいくつか記載します。

①観察

サーバントリーダーシップでは、チームや仲間を視点や心理的な感情を理解するため、些細な変化や動きを観察することが重要になってきます。安藤のほうでは、定例での報告を対話形式にしてみたり、1on1で面談するなどして、個人個人と話す機会を増やすようにしてみました。

プロジェクトが滞りなく進行しているか、SREメンバーのタスクの進捗状況を把握するのはリーダーとして当然やるべきことですが、その個人の内面まで意識を向けるようにしています。
・現在高負荷な状況になってないか？
・他のメンバーと人間関係は問題ないか？
・外部的要因で疲弊していないか？
どんな人間でもメンタルヘルスが低下していれば、必ずパフォーマンスに影響してしまいます。そうしたものもいち早く気づけるようになりたいと思っています。

②傾聴と説得

話し手に寄り添えるよう、傾聴の姿勢を取り入れました。話された内容が、たとえ受け入れがたい内容であってもすぐさま否定するのではなく、どうしてそのような考えに至ったのかを理解し、関心を持って聴くようにしています。
その上で、肯定できない場合にも、お互いが納得できるように、切り口を変えて話すよう心がけています。

③褒めること、感謝することを意識する

成果をあげたのみならず、周りに些細でも影響を与えられるようなことがあれば、できるだけ褒めるようにしました。その際、ただ褒めるだけではなく、必ず感謝の言葉と合わせて伝えるようにしています。
"〇〇してくれてありがとうございます"
”〇〇してくれたことですごく助かっております”

それでも本人が良かれと思ってた行動がよくないことを引き起こす場合もあります。
”〇〇してくれてありがとう、でもね…”
と、必ず行動に対する感謝は行った上で、進む道を正すようにしています。

## サーバントリーダーシップを意識した上で

SREというのはその職種の性質上、少人数で幅広くさまざまな業務を行います。弊社でも、ひとりで複数プロジェクトを抱え、個々が独立して動いている状況でした。得意なことは千差万別、IaCが得意な人がいれば、コスト削減や監視や分析が得意…と、人によってさまざまです。このため業務の属人化やプロジェクト毎で品質に大きく差が出てしまうことがありました。
そんな私が、リーダーとして改善のために考えたことは、それぞれの好きなことや得意なことを活かせる、いわゆる強みを発揮できるチーム作りでした。メンバーがプロジェクトを横断して得意な分野を見るような体制にすることで、品質向上はもちろん、チーム内の連携をより強固にすることを目的としました。
でも、言うだけでは、簡単には物事は進みませんでした。メンバーは忙しく、手元の仕事で手一杯です。そこで、これまでに述べたことを意識し、構想を伝えつつ、各々のタスクを解消するため一人一人で会話する時間を増やすことに費やすようにしました。これにより、チーム内の関係は以前よりも良好になり、お互いが助け合えるチームになってきています。少しずつですが、改善の兆しを感じてます。

### ◇まとめ

今回記述した内容については、極々一部になります
…とはいえ、正直これで良いのかと悩みつつ、勉強しつつでもあり、答えに迷う日々でもあります。
またいずれ、変わっていったところを記事にしてお届けできればと思います。
ログハイライターtailspinのインストール手順

# 目的
ログをハイライト表示するtailspinをインストールしてみたので、備忘録的に記述する。

# 環境
|名称|バージョン|
|---|--:|
|RedHat Enterprize Linux|8.9|

# インストール
## Rustインストール
```
# dnf module install rust-toolset
```
:::note info
RHEL7の場合、`yum install rust-toolset-1.35-cargo`(未検証)
RedHatはRustコンパイラはrustcよりもcargoを推奨している。
https://access.redhat.com/documentation/ja-jp/red_hat_developer_tools/2019.3/html/using_rust_toolset/chap-cargo
:::

## tailspinインストール
```
# cargo install tailspin
```
~/.cargo/bin/にインストールされるのでPATHを通す。

## 実行
```
# tspin -f 対象ログファイル
```
:::note warn
コマンド名は `tspin`。`tailspin`ではないので注意
:::


:::note info
ハイライト表示のオプションについては、下記GitHubを参照のこと
:::

# 参考
https://github.com/bensadeh/tailspin
Metricsの不可分な分割tagの確認方法

書きたい事がいい具合なブログ記事っぽい文章にならなかったのでQA形式にしてみました。これは僕がDatadog入社当時疑問に思って、社内で問い合わせた事です。現状は変わってないですが、いずれ新機能などで改善する可能性はあります。

Question
「メトリクスはたとえばCPU使用率だったらマシン単位（Datadogではホスト）でデータが入ってきて、、アプリのメモリ使用量だったらアプリケーション単位なんだろうけど、どういう単位でデータが入ってくるかGUI上で確認可能なのだろうか」。つまりメトリクスの不可分な分割tagが何か確認可能か。

Answer
app.datadoghq.comのGUI上では確認できない。ただし、Metrics Summary　https://docs.datadoghq.com/ja/metrics/summary/
を確認してメトリクスについているタグのリストから予想するのが良い。
補足として、不可分な単位でのGroup byは一つのタグで出来るとは限らず２つ以上のタグでgroup byする必要があるケースもある。2つ以上のタグを使う必要があるケースの具体例として同一アプリケーションが複数ホストで走っている環境でそのアプリケーション関連のメトリクスを不可分で取得したい場合、アプリケーション名だけでは複数ホストでのそのアプリケーションの値がアグリゲーションされるため、ホストタグとアプリケーションタグ両方で初めて不可分なgroup byになる

こちらのQAの内容で質問や補足の希望などある場合コメントもらえれば余裕がある時の本文訂正します。
docker + WSL2 + expoでreact native開発環境の構築

WSL2上のdockerでexpoの開発サーバーを建てたときに外部端末からアクセスする方法。
色々なサイトを参考にやってみたが、詰まったので、解決した方法をメモ程度で記載する。
# 0.0. やること
※ 前提としてWSL2上にUbuntuがあることとする
1. ポート開放
1. ポートフォワーディング
1. docker compose
# 1.1. ポート開放
PowerShellを管理者権限で実行して以下を実行する。
``` PowerShell
New-NetFireWallRule -DisplayName "WSL 2 Firewall Unlock" -Direction Inbound -LocalPort <port> -Action Allow -Protocol TCP
```

:::note warn
\<port>を任意に変更する
:::

# 1.2. ポートフォワーディング
expoは19000, 19001、Webは8080を使う。
PowerShellを管理者権限で実行して以下を実行する。
``` PowerShell
netsh interface portproxy add v4tov4 listenport=<port> listenaddress=* connectport=<port> connectaddress=<WSLのIP>
```

:::note warn
\<WSLのIP> \<port>を任意に変更する
:::

以下のコマンドでポートフォワーディングしているポートを一覧で見れる。
```PowerShell
netsh interface portproxy show all
```

# 1.3. docker compose
ちなみに、今回はMakeファイルを用いてビルドを行う為直接の`docker compose`は行わない。
ディレクトリ構成
root
┣ app 
┣ .env
┣ compose.yml
┣ dockerfile
┣ grepIP.sh
┗ Makefile

### 1.3.1 grepIP.sh
composeするときにローカル側のipが必要なのでシェルスクリプトを用いて自動で取ってくる。
``` grepIP.sh
IP=$(/mnt/c/Windows/system32/ipconfig.exe | iconv -f CP932 -t UTF-8 | sed -e 's/\r//' | grep 'IPv4' | head -1 | cut -d ':' -f 2 | awk '{print $1}')
sed -i".bak" -e "/LOCAL_IP_ADDR=/d" .env
echo "LOCAL_IP_ADDR=$IP" >> .env
```
<details><summary>やってること</summary>

ipconfigして 'IPv4'を含む行を抽出。その一行目のIPをenvファイルに書き込む。
なお、複数端末で実行に問題が無いことは確認済みですが、この方法は環境に依存するので、もっと良い方法があれば教えてください。
</details>

### 1.3.2 compose.yml
``` compose.yml
version: '3'

services:
  expo:
    build: .
    tty: true
    environment:
      - NODE_ENV=development
      - REACT_NATIVE_PACKAGER_HOSTNAME=${LOCAL_IP_ADDR}
    ports:
      - "19000:19000"
      - "8080:8080"
    volumes:
      - ./app:/usr/src/app
    working_dir: /usr/src/app

volumes:
  node_modules:
  
```
### 1.3.3 dockrfile
``` dockerfile
FROM node:latest
RUN npm -g add expo-cli
```
### 1.3.4 Makefile
``` Makefile
expo_sample:
	chmod +x ./grepIP.sh
	./grepIP.sh
	docker-compose up -d
	docker-compose exec expo /bin/bash
```
### 1.3.5 makeする
rootディレクトリに移動して`make`コマンドを実行。
あとはコンテナ内で`expo init`して開発していく。

# 9. 後始末について
### 9.1. ポート開放を解除
PowerShellを管理者権限で実行して以下のコマンドを実行。
``` PowerShell
Remove-NetFirewallRule -DisplayName "WSL 2 Firewall Unlock"
```
### ポートフォワーディングを解除
PowerShellを管理者権限で実行して以下のコマンドを実行。
``` PowerShell
netsh interface portproxy delete v4tov4 listenport=<port> listenaddress=*
```
:::note warn
\<port>を任意に変更する
:::
OpenAI公式npmモジュールでAzure Open AIのGPT APIを使うコピペサンプル


Azure Open AIのAPIをNode.jsから使ってみます。Azure Open AIのライブラリ(@azure/openai)を使ったら上手くいかず公式(openai)を使ったら上手くいきました。

https://zenn.dev/n0bisuke/scraps/c18f0da1fdc980


## 色々準備

### まずはOpenAIのライブラリインストール

ライブラリを入れておきましょう。

```bash
$ npm i openai
```

公式を使う場合のはこちらに残しています。

https://qiita.com/n0bisuke/items/6759ff0b0e481892f810

### モデルを作成する

Azureの管理画面からOpenAIのリソースを作成し、モデルデプロイをします。
（ちなみに、現状この時にどこのリージョンを選ぶかで、GPT4が使えたり使えなかったりします)

> ![スクリーンショット 2023-12-06 13.53.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/6eaa4e71-d49d-cf60-8606-01ca6919a82e.png "スクリーンショット 2023-12-06 13.53.29.png")

Azure AI Studioっていうページに連れて行かれます。
デプロイってところでモデルを選んでデプロイし、名前をつけます。

例えば`n0bisuke-gpt-35-turbo`など自分で分かる名前にしましょう。

> ![スクリーンショット 2023-12-06 13.52.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c6e72705-3937-8257-27f0-1a3cf683e699.png "スクリーンショット 2023-12-06 13.52.54.png")


### APIキー

APIキーは`キーとエンドポイント`の項目で確認できます。

> ![スクリーンショット 2023-12-06 13.56.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4f8cf689-4c4d-1eca-a328-5bf63d3050f2.png "スクリーンショット 2023-12-06 13.56.28.png")


次のコードでリソース名を入れる場所がありますが、ここで表示されるエンドポイントの以下の部分です。

> `https://リソース名.openai.azure.com`

### 公式ライブラリを使ったAzure Open AIの使い方コード

こちらにあったコードでうまくいきました。

https://github.com/openai/openai-node/blob/a048174c0e53269a01993a573a10f96c4c9ec79e/examples/azure.ts

`apiVersion`はこちらを見ましょうとのこと。

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/reference#rest-api-versioning

```js
const OpenAI = require('openai');

const resource = 'リソース名'; //エンドポイントの最初の文字列 "リソース名".openai.azure.com
const model = 'n0bisuke-gpt-35-turbo'; //作ったモデル名

const apiVersion = '2023-06-01-preview';
const apiKey = `APIキー`; //APIキー

const openai = new OpenAI({
  apiKey,
  baseURL: `https://${resource}.openai.azure.com/openai/deployments/${model}`,
  defaultQuery: { 'api-version': apiVersion },
  defaultHeaders: { 'api-key': apiKey },
});

async function main() {
	const completion = await openai.chat.completions.create({
		messages: [{ role: 'user', content: 'あなたの名前は?' }],
		model: model,
	});
	
	console.log(completion.choices[0].message.content);
}
  

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
```

```bash
$ node app.js

私はGPT-3という人工知能です。
```

## @azure/openaiは?

ちょっと検証中ですが、こういうエラーが出続けます。

> The completion operation does not work with the specified model, gpt-35-turbo. Please choose different model and try again. You can learn more about which models can be used with each operation

ライブラリのバグなのか、サンプルコードのバグなのか、以下の記事をみるとなんとなく別のエンドポイント(`/chat`にしないといけないけどそうなってない?)に向いてしまっているのかも

https://ninthcode.net/230822-aoai-apierror/


### 追記: モデルが違うっぽい?

すぐコメントもらえました。 @horihiro さんありがとうございます！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">コメントしました<a href="https://t.co/nDyHIyx2ga">https://t.co/nDyHIyx2ga</a></p>&mdash; ほりひろ loves ＜⚡＞ (@hori__hiro) <a href="https://twitter.com/hori__hiro/status/1732263370055905470?ref_src=twsrc%5Etfw">December 6, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
VirtualBoxのUbuntuでターミナルをつかう

2023/12/06 12:25
この記事はUbuntu初心者かつCUI初心者がUbuntuでターミナルを使えるようにするまでの過程を忘れないようにメモしておくものです．

環境
ノートパソコン
OS　Windows10 Pro 22H2
CPU　Inter(R) HD Graphics 620
メモリ　20.0GB
SSD　Samsung SSD 980 1TB
これで足りるかな...？

## VirtualBoxで新しくUbuntuをたてる．
- 新規(N)で新しいマシンの名前を決定する．私は`Ubuntu-ros2`にした．
- ISO Imageは`ubuntu-22.04.2-desktop-amd64.iso`を選択する．
- Usernameは初期設定のまま`vboxuser`で進めた．パスワードは自由に．
- メインメモリーは12800MB，Processorsは2コア．
- Create a Virtual Hard Disk Nowの選択のまま，Disk Sizeは初期設定の25.00GB．
- あとはそのまま次へを押していった．

これでUbuntuのマシンを作ることができた．

ただ，このままではターミナルを開けない．

## ターミナルを開けるようにする

- Ctrl+Alt+F3で仮想コンソールを表示する．
- Usernameはvboxuser，パスワードはさっき設定したものを入力してログインする．
- localeファイルを確認する．
```
vboxuser@Ubuntu-ros2:~$ cat /etc/default/locale
```
- ここで，おそらく
```
LANG="en_US"
```
と書いてある部分がある．ターミナルが開けないのはここが問題らしい．これを書き換えていくわけなのだが，このままでは読み込みのパーミッション(権限)しかないので，書き込むことができない．

### パーミッション変更

- 普通に考えればこのまま
`sudo chmod o+w locale`
を書けばいいと思うのだが，残念ながらsudoも使えないので，まずroot権限でvboxuserにsudo権限を付与する必要がある．

- まず，rootユーザーに切り替える．
```
vboxuser@Ubuntu-ros2:~$ su
```
パスワードを求められるので入力する
- 次に，sudo権限をユーザーに付与する．
```
root@Ubuntu-ros2:~# usermod -G sudo vboxuser
```
- ちゃんとユーザーに権限が付与されているかを確認する．
```
root@Ubuntu-ros2:~# groups vboxuser
vboxuser : vboxuser sudo
```
こうなっていれば権限は付与されている．
- 最後に，指定のユーザーに戻る
```
root@Ubuntu-ros2:~# su vboxuser
vboxuser@Ubuntu-ros2:~$
```
sudoを使えるようになった．
- パーミッションを変更する
```
vboxuser@Ubuntu-ros2:~$ sudo chmod o+w /etc/default/locale
```
これでlocaleファイルを編集できるようになった

### localeファイルを編集する

- viをつかって編集する
```
vboxuser@Ubuntu-ros2:~$ vi /etc/default/locale
```
- ここで，`LANG="en_US"`の後ろの`"`にカーソルを合わせて，`i`を押すと，追加で書き込めるようになる．
(ここでなんか画面下部に色々書いてある画面が出てくるけどEnterで続ける)

```
LANG="en_US"
```
を
```
LANG="en_US.UTF-8"
```
に書き換える.
- もし書き違えたら`x`でカーソル上の文字を一文字消せる．
- 書き換え終わったら，`esc`キーを押して書き込みモードを終え，`:wq`で保存してviを終了する．
- ここで注意して欲しいのが，パソコンのキーボードがたとえ日本語配列であったとしても，入力はすべてUS配列の認識をされるということだ．つまり，日本語配列で`:`を打ったつもりでも，パソコン側の認識は`'`になっているというようなことがあった．US配列のキーボードを参考にして打って欲しい．
- viを終了したら，
```
vboxuser@Ubuntu-ros2:~$ reboot
```
と入力し，再起動する．

## ターミナルを開いてみる

- 実際にターミナルが開けるかどうかを確認する．うまくいけばターミナルが無事開けるだろう．


## 最後に

今回はUbuntuのISOイメージの入れ方などは全く省略したが，そのうちまとめたいと思う．


#### 参考サイト
https://qiita.com/towamz/items/2052f08e9e1af4068a56

https://eng-entrance.com/linux-command-vi

https://linuc.spa-miz.com/2021/08/24/running-out-of-virtual-console/

https://qiita.com/shisama/items/5f4c4fa768642aad9e06

https://it-kyujin.jp/article/detail/1375/

https://qiita.com/kohei-takao/items/3beb89fb95d9cc472125
プロジェクトのプロセス改善についての雑談

こんにちは！

ALICEです！

今回も雑談に近いですが、ちょこっと仕事関連の話をしてみようかと思います。

私はQAグループのマネージャーをやっておりますが、
直接プロジェクトに関わる仕事もするプレイングマネージャーです
主にチームのプロセスの改善を任されてます


QAのフローを変えたり、
QAが関わる部分の全体を変えたり、
そもそものQAの認識を変えたり
QAを立ち上げたり
色々やっております


ここで最近思うのですが、

みなさんはこのプロセス改善、どれくらいで完了すると思いますか？
半年？1年？
もちろんプロジェクトによる。
という回答もあると思います

私は大体１か月から２か月かからないくらいで改善します
なので、他の人もそうだと思っていました
なんて傲慢な人なんでしょうw w


ちょっと話ずれますが、
こないだ開発本部QA全員で、「コンセンサスゲーム」をしました

QAはコミュニケーション能力も、交渉する能力も必要なので、という！

とっても面白くて、有意義な時間でした。
メンバーは普段関わりの少ないPJのメンバーでシャッフルして4-5人でやりました。

結果を言いますと、もちろん私が個人の点数１位になれました！
私のチームも１位になれました！
合同ですが！w w w

でも、もっと自分の意見をメンバーに説明できてたら圧倒的な点数で１位になれたかなと
反省点もありました、悔しさですね、もっとスキル上げるべきだと思いました！


ここで話を戻します
結局、状況把握、リスク管理、全体的な対応がわかっていても、
それがステークホルダーに伝わらなければ、プロセス改善にはつながらないとのことです。

ステークホルダーに伝えるために何をすればいいか・・・・
ちゃんとした根拠が一番だいじかなと思います

なぜ？
をなくす

私は普段もよく、なんで？と疑問を浮かべているのですが、
それが解決すると、割と物事はスムーズに行きます。
私だけですかね？w w


そういえば、
私のグループの中で、海外メインのものがありまして、本番環境をQAは触ることができないのですが、
開発の人たちは触ることができます。
そこでQAも触れるようにして欲しいと打診したことがありますが、断られました。
本番と同じSTG環境あるじゃないかと。
その時私は、なぜ？をなくすことができなかったのだと思います。

でも最近はQAの人も触れるように出張に行ったりしてます。よかた！


プロセス改善は私一人が頑張ってできるものではないので、
人間関係、コミュニケーション、チームの利益、全体の方針など把握しておく必要がありますが、
私はそれができているのか？
と最近考察するようになりました。

全然できてないかもしれない！

これからもプロせず改善を頑張っていくので、
また新しく学んだことなどあれば共有します。
それ，numpy で書かない？-- 2 --

## それ，numpy で書かない？

Python ではリストがよく使われる。また，for ループが遅いのでリストに特化したリスト内包表記も推奨されることが多い。

それなりの根拠があるからではあるが...

課題：[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]] のような二重リストを作る。

[n×n, 2] の二重リストを trial 回作成し，処理時間の平均値と標準偏差を記録する。  


```Python
from statistics import mean, stdev
from time import time
n = 1000
trial = 100
```
### 二重の for ループと append()

```Python
def for_loop(n):
    start = time()
    list1 = []
    for y in range(n):
        for x in range(n):
            list1.append([y, x])
    return time() - start

for_loop_times = [for_loop(n) for i in range(trial)]
print(f"二重for文  平均値: {mean(for_loop_times): .3f},  標準偏差: {stdev(for_loop_times): .3f}")
```

    二重for文  平均値:  0.255,  標準偏差:  0.019


### リスト内包表記で


```Python
def comprehension(n):
    start = time()
    list1 = [[y, x] for y in range(n) for x in range(n)]
    return time() - start

comprehension_times = [comprehension(n) for i in range(trial)]
print(f"comprehension  平均値: {mean(comprehension_times): .3f},  標準偏差: {stdev(comprehension_times): .3f}")
```

    comprehension  平均値:  0.252,  標準偏差:  0.018


### numpy で 二重 for ループ


```Python
import numpy as np

def numpy(n):
    start = time()
    a = np.zeros((n**2, 2), dtype=int)
    for i in range(n**2):
        a[i, 0] = i / n
        a[i, 1] = i % n
    return time() - start

numpy_times = [numpy(n) for i in range(trial)]
print(f"numpy  平均値: {mean(numpy_times): .3f},  標準偏差: {stdev(numpy_times): .3f}")
```

    numpy  平均値:  0.162,  標準偏差:  0.001


### numpy で 二重 for ループ（その2）


```Python
def numpy2(n):
    start = time()
    a = np.zeros((n**2, 2), dtype=int)
    for i in range(n):
        i0 = i*n
        for j in range(n):
            a[i0+j, 0] = i
            a[i0+j, 1] = j
    return time() - start

numpy_times2 = [numpy2(n) for i in range(trial)]
print(f"numpy2  平均値: {mean(numpy_times2): .3f},  標準偏差: {stdev(numpy_times2): .3f}")
```

    numpy2  平均値:  0.153,  標準偏差:  0.004

### numpy, itertools を使う

一行で書ける。

```Python
import itertools

def numpy3(n):
    start = time()
    a = np.array(list(itertools.product(range(n), repeat=2)))
    return time() - start

numpy_times3 = [numpy3(n) for i in range(trial)]
print(f"numpy3  平均値: {mean(numpy_times3): .3f},  標準偏差: {stdev(numpy_times3): .3f}")
```

    numpy3  平均値:  0.193,  標準偏差:  0.004

## 結論

numpy() は for を使っても十分に速い。
[FromBody]で指定したPostリクエストがnullになる(個人メモ)



**原因1：**
JSONを正しく取得できていない

[参考リンク](https://qiita.com/hogeco/items/ccc8271459e9d3e5daaf)

**原因2:**
Jsonで渡す値の型とModelの型が違うから

Modelではint型を設定しているが、JSONでは''(空値)を渡した場合、
内部ではエラーになるためnullとなる

原因2が全然気づくことができず、１つずつ項目をコメントアウトしていって
やっとこさ理解できた。

どっかでエラー吐かせるやり方とかあるのかなぁ
JAXA航空シンポジウムに行ってきた話

⚠記事の内容は学生個人の見解であり、所属する学科組織を代表するものではありません。

# はじめに
AdventCalendar 7日目となりました！
先日は奥平さん（＠Kiyoaki‗aero）が人工衛星についての話をしてくださいました～面白かったですね！！！
ちなみに自分は奥平さんと軌道力学のゼミを行っています。毎週ケプラーってすげーみたいな話をしてる感じです。楽しいです。

さて、自分は先日東京都で開催されたＪＡＸＡ航空シンポジウムに突撃してきました！

![IMG_20231013_154644.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624095/3e6ec3c8-7e7d-4b44-c80c-0331c248950f.jpeg)

ところで皆さんはシンポジウムと呼ばれるものに参加したことはありますか？？

シンポジウムとは、「ある一つのテーマに対して、複数の有識者が異なる観点から、一般聴衆者の前で発表・議論・質疑応答等を行うイベント」の事で、今回はJAXAや三菱重工さんなどの研究者の方が集まって様々な研究についての発表を行っていました。

シンポジウムではポスターセッションと講演と、二種類の形式で発表が行われていたのですが、実はポスターセッションでは、JAXAで実際に研究をしていらっしゃる本職の研究者の方々から一対一で直接研究内容についてお話を聞かせていただくことが可能なのです！
私は研究者の方々に素人質問（ガチ）をしまくっていたのですが、非常に丁寧に対応していただきました。

そこで、私が実際に研究者の方からお話を聞かせていただいた研究内容をいくつかピックアップしてこの場でゆるく紹介できたらと思います。


## 「低炭素排出と静粛性を目指した吸音ライナ技術の研究」

「吸音ライナ」とは、航空機のエンジンの出入り口に装着されるハニカム構造によって騒音を内部に閉じ込める働きをするパーツで、この研究では吸音ライナの低コスト化や軽量化、吸音性能の向上を目的としてます。

この研究では３Ｄプリンターが大きな役割を果たしており、航空宇宙産業における３Ｄプリンターの存在感の高まりが感じられました。

ちなみに九大では航空機製造に向けて金属３Dプリンターを物理的視点からの改良を試みるという研究もおこなわれており、関連性が感じられて面白かったです。

## 「ヒト飛行装置“emblem”」

人飛行装置はこれまでにニュージーランドやフランスの実業家が開発したものがたびたび話題になっていましたが、この分野にJAXAも参戦するようです。

実は、人飛行装置の開発に大企業や研究機関が参加した例はこれまでなく、大手で言うとJAXAが初となるそうです。航空機やロケットの開発などが中心となっているJAXAではかなり挑戦的な立ち位置となっているようですが、実用化が進めば、災害救助や建築業界において大きな変革につながると期待されてます。

これまでは操縦難易度の高さや機体の価格などが問題となり、世間一般での実用化には至っていませんでしたが、最新のテクノロジーを組み合わせることでこれらの問題の解決への道筋が見えてきたようです。

特に、AIを活用して人の動きに連動した制御を可能にしたことは操縦に関する問題の解決に大きく役に立ちました。

# さいごに
シンポジウムに参加すれば第一線で活躍している研究者の方から研究内容などについて直接お話を聞くことができます！
私は研究内容以外にも航空宇宙業界の実情や研究者の方々の思いなどについて知ることができ、自分のこれからについて多くのアドバイスも貰え、非常に良い経験をすることができました。
ぜひこの機会に皆さんも気になる分野のシンポジウムや学会にどしどし突撃していきましょう！！！


（注）これらの研究内容の詳細について知りたい方は、このサイトで発表資料が公開されているのでぜひ確認してみてください！
https://www.aero.jaxa.jp/news/event/sympo231013_rep.html
◆HTML/CSS　備忘録① 親子関係

# ◆HTML/CSS　備忘録① 親子関係

## 親子関係
HTMLのタグには、親子関係と兄弟関係というものがあります。

簡単に言うと、囲んでいる部分を『親』
囲われている部分を『子』と言います。

同じ親に囲われている『子』同士を『兄弟』と言います。
 
![説明①.png](https://storage.googleapis.com/topdowncom/content/7BvAkPVBM0h4jzZ1nSbMcsT8E493/114fd195-232a-4156-8fb8-fee4724aa556/%E8%AA%AC%E6%98%8E%E2%91%A0.png)

親子関係の把握が必要になる理由は、
HTMLの親子関係がCSSの指定に影響を及ぼすからです。

例えば、親要素に設定した内容が子要素にも反映されます。
### 例）親要素側【div】に文字の配置中央揃えを設定すると、子要素の【p】にも反映される。

**親要素【div】に設定前**
 
![例題1.png](https://storage.googleapis.com/topdowncom/content/7BvAkPVBM0h4jzZ1nSbMcsT8E493/114fd195-232a-4156-8fb8-fee4724aa556/%E4%BE%8B%E9%A1%8C1.png)

**親要素【div】に設定後**
 
![例題2.png](https://storage.googleapis.com/topdowncom/content/7BvAkPVBM0h4jzZ1nSbMcsT8E493/114fd195-232a-4156-8fb8-fee4724aa556/%E4%BE%8B%E9%A1%8C2.png)

他にも内容によっては、親要素に必ず設定しなければいけないものや、子要素に設定する必要があるものなどもあるため、親子関係の把握が重要です。
std.Treapをordered_mapとして振る舞わせるTips

## はじめに

`zig`言語の標準ライブラリには、木構造を扱う型として、`std.Treap`が提供されている。
順序集合(`ordered set`としての使用が主な目的となるが、ひと工夫することで順序マップ(`ordered map`)として扱う方法が見い出せたため、記録として残す。

## 方法

:::note warn

実装依存の方法のため、将来のバージョンで動かなくなるかもしれないことに注意。
確認は、2023-11-02時点のnightlyで行った。
:::

`std.Treap`型は、以下のように定義されている。

```zig
pub fn Treap(comptime Key: type, comptime compareFn: anytype) { ... }
```

`Key`は集合の要素となる値の型、`compareFn`はコンパレータで、以下のインターフェースを想定している。

```zig
fn compare(a: Key, b: Key) std.math.Order { ... }
```

コンパレータのインターフェースはキー同士を比較し、その順序を返すものとなっている。

`Key`には任意の型を指定できるため、以下のような構造体とコンパレータを指定するで、真のキーと値とのマップを模倣できる。

```zig
const Data = struct { 
    key: SomeKeyType, // 真のキー
    value: SomeValueType, // キーにマップしたい値
};

const Comparator = struct {
    pub fn compare (a: Data, b: Data) std.math.Order {
        // a.keyとb.keyの比較結果を返す。
    }
```

エントリを追加する際は、以下のように行う。

* `Treap.getEntryFor`に対して、真のキーのみを詰めた値で探索させる。

```zig
var tree = Treap(....){};

// 探索の際、値は不要のためundefinedを詰めておく
var entry = tree.getEntryFor(Data{ .key = ..., .value = undefined, });
```

* 探索結果の、`Treap`の`Entry`のキーを本来セットしたいものに差し替え、ツリーを更新する。

```zig
if (entry.node == null) {
  // 追加したい真のキーと値を割り当てる
  // entry.setメソッドでは、entry.keyを使用して木構造を再構成するため
  entry.key = Data{ .key = ..., .value = ... };

  // Nodeを作成する
  var node = try allocator.create(Treap(...).Node);
  node.* = undefined;

  // ツリーの要素を更新する
  entry.set(node);
}
```

`zig`言語バージョン、0.12系で、`Treap`に対するイテレータを取得する`inorderIterator`メソッドが追加されたため、このイテレータを使用することで真のキーでソートされた結果を取り出すことができる。

```zig

var iter = tree.inorderIterator();
while (iter.next()) |node| {
  // node.key.value はnode.key.keyでソートされた順に取り出せる
}
【v4対応】シンプルにNode.jsからOpen AIのGPT APIを使うメモ


2023年8月頃にOpenAIのライブラリがv3からv4にSDKがアップグレードがあり、今までのコードが使えなくなったりしてました。 某授業で先生が詰まってましたね... ということでメモです。

## 準備

APIキーを取得してライブラリもインストールします。

- APIキー発行
	- https://qiita.com/okinakamasayoshi/items/247c58342e5cf15c7bcd
- npmライブラリのインストール

```bash
$ npm i openai
```

## コピペ実行用

```js
const OpenAI = require('openai');
const key='API キー'

const openai = new OpenAI({
    apiKey: key, // defaults to process.env["OPENAI_API_KEY"]
});
  
async function main() {
	const completion = await openai.chat.completions.create({
		messages: [{ role: 'user', content: 'あなたの名前は?' }],
		model: 'gpt-3.5-turbo',
	});
	
	console.log(completion.choices[0].message.content);
}
  
main();
```

```bash
$ node app.js

私はGPT-3という人工知能です。
```

うまくいきました。

## v3->v4への移行話

新しく作る場合は関係ないですが、変更点がありました。

色々ありますが、`openai.createChatCompletion()`って書いてた部分が`openai.chat.completions.create()`って書きましょうみたいな感じでメソッド名が結構変わってたりします。

https://github.com/openai/openai-node/discussions/217
今更ながらのJaSST23 kyushu参加備忘録パート2

お疲れ様です！

ALICEです！

気づいたらだいぶ時間が経ってました。
１ヶ月前とかになりそうだった危ない！

今回は登壇いただいた方たちのセッションを聞いた感想を書きます！
こちらも前回同様私の感想なので思ったことずらりと並べていきたいと思います！


まずは基礎講演をしていただいたりなさんのセッション！

わからないをわかるにしよう！って素晴らしい！！
と一番先に思いました。なんていいことだ！

今回QAをやったことない初心者の方が対象でしたので、
内容もわかりやすく、自分もまたベースのことを改めて考えることができてとてもよかったです

ワークショップ形式で、自分で書いて考えたり、色々試してみたりとか
楽しいお時間でした、今考えてみると割とながい時間だったなーと思いつつ、
当時全くそう感じなかったので、それもまたすごいな！！！と思うところでした。


語彙力がだいぶないことに今更気づき始めていますw w w


そして末村さんのセッション！
自動化に関するセッションでした

めちゃくちゃ面白い方で、
難しい内容だったにも関わらず、笑顔あふれるとても良いセッションでした

そして最後の最後になんとChat GPTを利用して作成したとのことで、
驚きもあってよかったです

https://x.com/jasstkyushu/status/1731454953515082216?s=20

結構良い話たくさんあったので、ぜひセッションみて欲しいので、
各リンクから動画もぜひみてみてください！

私のただの感想だったのと１か月以上経ってしまって・・・だいぶ覚えてない・・・
申し訳ない・・・

次はJaSST東京の参加予定なので、その時も備忘録書きます

あ、私はスクフェス登壇を狙っています
【FileMaker】【補足】今年度の集計をしたいのだ

この記事は、前回の「【FileMaker】今年度の集計をしたいのだ」の補足になります。
まだ読んでいない方は、先に一読お願いします。

https://qiita.com/tyuma/items/861fc14dbb26893077a2

前回の記事では、集計を計算フィールドで行なっていました。

いや、配列にデータが入るごとに集計が行われるのはFileMakerに無駄に計算させてない！？

と感じますよね。
そうなんですよね。。。

計算フィールドで計算する方法だと、スクリプトに書かなくていいので楽といえば楽です。
ですが、やはり無駄な計算はない方がいいので、スクリプトでも同じように実装する例をこの記事では紹介します。

# 実装
そんな大袈裟なことではありません。
計算フィールドに書いていた内容を、スクリプトに持ってくるのが改修のメインになります。

## スクリプト
利用人数_合計フィールドの内容をコピペして、、、
![スクリーンショット 2023-12-06 13.22.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/661f5378-5209-a3cc-5fd4-c69a07df4ddc.png)

集計のスクリプトで用意した変数にセットします。
![スクリーンショット 2023-12-06 12.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/ae7968e9-79fd-e380-ffaa-072dbcb7e62b.png)
注意するのは、スクリプトにペーストした時に、集計対象のテーブルオカレンスを意識することです。
赤丸の部分、計算フィールドに書いた時はテーブルオカレンスが無いですが、スクリプトではテーブルオカレンスを追加します。

## フィールド定義
利用人数_合計フィールドを、計算タイプから、数値タイプに変更します。
![スクリーンショット 2023-12-06 12.55.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/7df79311-aa2d-ceea-6290-223857fb83a1.png)

これで、修正は完了です。
同じようにスクリプトを実行すると、同じ結果が得られると思います。
ICU4Jの変換が強力すぎるので文字種を規制したい

## とどのつまり…
UnicodeSetを使って正規表現で文字種を規制してFilterに設定すべし
```java
    // カタカナとか巻き込まれて半角になると困る！全角英数字だけ半角にさせてくれ！！
    Transliterator transliterator = Transliterator.getInstance("Fullwidth-Halfwidth");
    transliterator.setFilter(new UnicodeSet("[０-９ａ-ｚＡ-Ｚ]").freeze());
    return transliterator.transliterate("ＦＵＬＬ　ｗｉｄｔｈ　ｔｅｘｔ");
```
【UEFN】Verseで消せないDeviceを消す方法

## 背景
何かをクリアした条件にダメージボリュームデバイスを消したかったのですが非表示にするようなメソッドを持ち合わせていませんでした。そこでどのようにやるか考え始めました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692976/32f292fe-f8fa-3f09-9846-2b3e0f3c6a22.png)


## 解決方法
**非表示にしたと見せかけるように遠くにテレポートさせるという方法で解決しました。**
### 動画
<iframe width="560" height="315" src="https://www.youtube.com/embed/CjsyAx90C_M?si=gsz6tpd0QBDj3dov" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## 実装
```
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }<-忘れずに追加して

hide_creative_device := class(creative_device):

    @editable
    Trigger:trigger_device=trigger_device{}

    @editable
    damageVolume:damage_volume_device=damage_volume_device{}

    OnBegin<override>()<suspends>:void=
        Trigger.TriggeredEvent.Subscribe(HideDevice)

    HideDevice(QAgent : ?agent):void=
        NewRotation := rotation{}
        vec := vector3{X:=10000.0, Y:=10000.0, Z:=0.0}
        if(damageVolume.TeleportTo[vec, NewRotation]):
```

### やっていること
トリガーを押したら遠くへテレポートさせて消えたように見せかけています。
```
        NewRotation := rotation{}
        vec := vector3{X:=10000.0, Y:=10000.0, Z:=0.0}
        if(damageVolume.TeleportTo[vec, NewRotation]):
```
テレポートした先での向きとその位置を指定しています。Teleportを呼ぶときは必ず`if():`で囲ってください。

:::note warn
忘れずに追加しましょう！
```
using { /UnrealEngine.com/Temporary/SpatialMath }
```
:::

## まとめ
まだまだVerceも成長している途中で欲しいと思った機能がないことがあるのであの手この手で実装する必要がありそうですね。

## 余談
この度UEFN/Verseに関するオープンコミュニティサーバーを建ち上げました。ちょっとでも興味があれば奮ってご参加くださいませ。

https://discord.gg/cK4daQyD
ファイル共有のコマンドフォーマット

net use 共有ドライブ名: \\対象のPC/Server¥フォルダ名

192.168.1.100 のPCがTCPフォルダを共有し、Xフォルダに追加したい場合

net use x : \\192.168.1.100\TCP


事前確認として、相手側のPCにFWでファイル共有（port:445）が空いていること
【PHP8.x】 switch文をmatch式で書き換えてみよう

## 概要
PHP8からmatch式が導入されました。今までswitchで書いていた部分をモダンにmatch式に書き換えてみましょう

## 例

### switch文
```php
$variable = "value2"; // 変更可能な値

// switch文
switch ($variable) {
    case "value1":
        $result = "値はvalue1です。";
        break;
    case "value2":
        $result = "値はvalue2です。";
        break;
    case "value3":
        $result = "値はvalue3です。";
        break;
    default:
        $result = "その他の値です。";
}

echo $result;
```

### match式

```php
$variable = "value2"; // 変更可能な値

// match式
$result = match ($variable) {
    "value1" => "値はvalue1です。",
    "value2" => "値はvalue2です。",
    "value3" => "値はvalue3です。",
    default => "その他の値です。",
};

echo $result;
```

switch文の冗長感が無くなってスッキリになりましたね

## 違い

`match`式は値を比較し、一致するケースの結果を返す式です。
そのため、変数に代入したり、関数の引数として渡したりすることができます。

`switch`文は文の一部で、直接的な式としての利用は出来ません。
結果を返すのではなく、出力や変数への代入など、他の文と組み合わせて利用するのが一般的です。

## 参考

https://www.php.net/manual/ja/control-structures.match.php

https://tech-blog.rakus.co.jp/entry/20200917/php
今更だけどGoogle Playのアカウント削除要件のリンク先は、削除手順の箇条書きだけでOKだった話

こんにちは、個人でアプリ開発をしているYuKiOです。これまで最高にかっこいいメモアプリ「Hacker Memo」など 15本アプリをリリースしています。

この記事を書いているのは2023/12/６です。

Androidアプリに関して、2023/12/7までに「アカウントの削除に関する新しい質問」に回答しないと、アプリが削除対象になるかもしれないので対応必須なのですが、この対応方法について勘違いが発生している可能性があるため書いています。（延長申請をすれば期限は伸びます）

というのは、アプリ内でアカウントを作成している場合は、アプリストアにユーザーがアカウントと関連データの削除をリクエストする場合に使うリンクを指定する必要があります。

このリンクが曲者でどんなWebページを用意すれば良いのか悩んでいる人も多いと思います。結論で言えば削除手順の箇条書きだけのシンプルなページでOKでした。


なので以下の様なフォームを提供されている方は、セキュリティリスクを考えても変更しておいた方が無難かもしれません。

## 削除フォームのセキュリティリスク
この対応についてGoogleフォームでアカウント削除依頼フォームを作ったら審査が通ったという記事を見かけました。行動力やアイデアは素晴らしいとは思ったのですが、セキュリティ的によろしくないと思ったわけです。

というのは可能性は低くとも悪意のある第３者がメールアドレスを入手して、問い合わせをすれば、パスワードなしでアカウントを削除できてしまう状態を構築してしまうからです。

アカウントと問い合わせの人物が同じ人である保証もありません。

運用ではアプリ上での削除に誘導するとありますが、ユーザーに対して「ここで削除できます」と伝えているのに、「ここではなくアプリ上での削除を推奨します」というのは「じゃあ、このフォームはなんやねん！」ということにつながりますし、仮に「アプリがダウンロードできないから無理」と言われてしまったら、上記のセキュリティリスクを負うことになります。

あくまで運用者として、そのようなセキュリティホールを作ってしまうのは信頼を損なう可能性もあります。

## もしかして、削除フォームについて僕達は勘違いしている
安全な削除を可能にするには、やはりWeb上でログインさせてから削除フォームを入力できるようにしたらいいのですが、
それには毎回専用サイトを作るのも大変です。

ふと、天下のGoogle様が、そんなセキリティ甘々を許すのかな？と疑問に思ったので説明文をよく読みかえしたのですが、「ユーザーがアカウントと関連データの削除をリクエストする場合に使うリンクを指定してください」という文言が混乱の元になっていそうです。

求められる要件には以下とあります。

### 削除URLに関する要件
このリンクは Google Play ストアの掲載情報に表示されます。表示されるための条件は次のとおりです。

ストアの掲載情報に表示されるアプリまたはデベロッパーの名前に言及している
ユーザーがアカウントの削除をリクエストするための手順が目立つように表示されている
削除 / 保持されるデータの種類を特定し、さらに保持期間を指定している


よく見てみると、削除をリクエストするための手順が目立つように表示されているとあります。つまり別にこのリンクでアカウントを削除できる必要はないわけです。

もう少し詳細に見てみると・・・
https://support.google.com/googleplay/android-developer/answer/13316080?sjid=1529695562492165007-AP

### アカウント削除要件をチェック
ユーザーがアプリ内からアカウントを作成できる場合、ユーザーが自分のアカウントの削除をリクエストできるようにすることが求められます。"アプリ内およびアプリ外（ウェブサイトにアクセスするなど）でアプリ アカウントの削除を開始するオプションを、ユーザーが簡単に見つけられるようにしてください。"アプリ外のウェブリソースへのリンクは、Google Play Console 内の指定された URL 形式の項目に入力する必要があります。

抜き出すと、「アプリ内およびアプリ外（ウェブサイトにアクセスするなど）でアプリ アカウントの削除を開始するオプションを、ユーザーが簡単に見つけられるようにしてください。」

少し意味が難しいですがあくまで自分的には、ユーザーがアカウントの削除方法を見つけらればいいのであって、外部で削除する方法を提供するものではないと判断しました。


## アカウントの削除方法を記載したリンク
Xでもこのやり方で審査が通った方がいたのですが、自分もアプリ上での削除方法を箇条書きにして審査に出したところ無事に通過しました。

単純に審査が甘く、今後はもっと厳格化されるかもしれませんが、悩んでいる方の参考になれば幸いです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">HackerMemoを大幅にアップデートしたので、<br><br>海外向けのPVを作ってみました😆<br><br>夜なべして頑張って作ったので、拡散頂けたら泣いて喜びます😭🙏<br><br>音有りがオススメです！<br><br>元ネタわかる人いるかな〜🤔<br><br>アプリはこちら🔽<br>■iPhoneの方<a href="https://t.co/6T10L94Ld1">https://t.co/6T10L94Ld1</a><br><br>■Androidの方<a href="https://t.co/uBevCXrNw2">https://t.co/uBevCXrNw2</a> <a href="https://t.co/wiGLv46kaG">pic.twitter.com/wiGLv46kaG</a></p>&mdash; YuKiO｜アプリ個人開発｜Flutter × Firebase (@oo_forward) <a href="https://twitter.com/oo_forward/status/1348103082769453056?ref_src=twsrc%5Etfw">January 10, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
スキル系の説明文検証補助ツールを作った話

# はじめに
この記事では、過去に私が新規開発でのテストで直面した問題と、その解決方法について記載しています。

内容としては、検証工数が十分でない中での、スプレッドシートを利用したスキル系の説明文の検証で補助ツールを作成して、検証時間と工数を効率化した話です。
システムの仕組みの違いや、資料の管理方法の違いなどありますが、考え方の参考になれば良いなと思い記載しましたので、よろしければ最後までご覧になってください。

# 読了時間
約5分

# 作成に経った経緯
新規のスキル開発というのは、どれだけ準備していても思い通りに進行しないことが多いものだと個人的に思ってます。
私が担当していたプロジェクトでも、スケジュール通りに検証が完了し、間もなくリリースというところで
「検証終わってますがギリギリまでスキルの微調整を入れたい」
という変更作業が入りました。
リリース直前まで調整が入るスキルの検証はスケジュールに余裕がなくなることが多くありました。
このように更新頻度が高い、ギリギリまで調整が入るデータのテストに対して都度対応を行うと費用も工数もかかります。
さらに、「スキルの各数値を変更したが、スキルの説明文を変え忘れてしまう」
という障害リスクの要因にもなります。

であれば、マスタの数値から自動で説明文を作ってしまえば、自動で毎日チェックできるんじゃないかという考えに至り作成することになりました。

# 前提
導入できる前提として下記が挙げられます。

・マスタがスプレッドシート上で管理されている

・ある程度文章構成に規則性がある
　└ユニークすぎるものだと導入が困難です

・説明文が手入力の仕組みになっている

# どのようなものだったか
実際はもっとカラムが多くなりますが、説明のためわかりやすくしています。

![スクリーンショット 2023-12-05 22.49.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542716/b95db2ea-4d7b-4d0f-d503-3e7933067f9c.png)


### 画像の①
③の「参考にするマスタ」からVlookup関数やIndexとMatch関数を混ぜた関数を使用して、値を参照させてください。
個人的には、参考にするマスタのカラムが増えた時にも対応できるように、IndexとMatch関数を使用するほうが、メンテナンスが楽かと思います。

### 画像の②
実際に①で入力されている値からF列で文字として自動で出すようにしています。
今回のものだと下記のように記載しています。
```
=ArrayFormula(If($A$2:$A$10="","",
if($D$2:$D$10=1,"自分の",
if($D$2:$D$10=2,"敵の","Error"))
&
if($C$2:$C$10=1,"体力が",
if($C$2:$C$10=2,"パワーが","Error"))
&
if($E$2:$E$10="","",
if($E$2:$E$10>=0,$E$2:$E$10&"アップする",
if($E$2:$E$10<0,$E$2:$E$10&"ダウンする","Error")))))
```
各カラムに新しい法則が入った時に検知できるようにError処理を行うと良いかと思います。
そして、出力した説明文をG列で比較しています。

### 画像の③
チェックシートとは別にシートを作成して、「参考にするマスタ（名前はなんでも良いです）」シート上で、Importrange関数を使用して自動でマスタの数値を参照できるようにしてください。
参考にしたいマスタが複数の場合は、シートを分けて作成してください。

# 効果
効果としては以下のように、効率化と品質向上の2点ありました。

### 効率化
【工数の約80%を削減することができた】
このチェックのシートを作成して、最低限の挙動やデータの反映を実機で確認することによって予定していた工数の約80%を削減することができました。

### 品質向上
【人力のチェックでは気付きづらいものの検知が容易になった】
![スクリーンショット 2023-12-11 9.32.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542716/333a4b97-a579-9801-ea74-9ced999f9b0a.png)


例えば
この画像の水色の部分では「自身の」になっていて、自動で作成される規則では「自分の」なので判定ではFALSEとなります。
実際に人の目でこの説明文単体をチェックした時、効果と意味的には問題がないので特に違和感が感じられない可能性があります。
このように、規則と外れていることを報告し、合わせたほうがいいという提案も容易にできるようになりました。

# 作成のポイント
実際マスタの作りは様々ではあるので、決まった作成方法を提示するのは難しいですが、作成時のポイントを挙げたいと思います。

#### まずはマスタの仕組みを理解する
時間はかかるかもしれませんが、各カラムの仕組みを理解するのが大切です。

・どのような数値なのか
・どのような数値の種類があるのか
・どのように使用されるのか
・カラム同士で紐付いているものはないか

を意識して紐解いていきましょう。

#### 作成する関数はできるだけ複雑にならないようにする
他の人がメンテナンスできるように、できるだけ基本的な関数を使用するのもポイントです。

#### シート自体が重くなりすぎるものも極力使わない
ある程度動作が重くなってしまうので、
・条件付き書式
・query
この辺りは、極力使わないのが効果的でした。

# さいごに
あくまで補助ツールではあるので、挙動などの担保は基本的には実機上でするべきと考えます。
また
・リリース後はパターンが増えてくるので、メンテナンスは大変である
・作成者以外でもメンテナンスの容易性を上げたほうがいい
など、課題は多いと思います。
とはいえ、マスタの知識がないテスターにも文章として可視化して、検証の補助ができて非常に有効なものになりました。
今回の記事が少しでも参考になれば良いし、もし他にもこんな方法、仕組みが効果的だったなどありましたら教えてもらえると嬉しいです！
最後まで読んでいただきありがとうございました！
[7日目] 学校の食堂をIT化させる話　混雑度カメラの状況をリアルタイムで見れるようにする

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の7日目の記事です。

この話は、1日目から始めた学校の食堂をIT化させる話の続きとなります。前回でカメラの映像をリアルタイムに送信する部分が出来ました。

今回は、ウェブページからリアルタイムにカメラの映像と人数・混雑度を確認できるようにしたいと思います。

# どのようにリアルタイムに取得するか
まず、前回も話しましたがリアルタイムに取得する手順はポーリングでリアルタイム風に取得したいと思います。
今回のカメラでは、1秒間隔でデータを更新するので、ウェブページ側では2秒ごとの情報更新を行っていこうと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/68408f5e-b5a5-0947-e1fb-477ed17ebe7b.png)

# ページを作る
今回は、Nuxt3でページを作っていこうと思います。
最終的な取得するコードがこのようになります。

カメラは現時点で１台しかセットアップしていませんが、複数台に対応できるように配列で定義しています。
また、カメラのデータに関しては、キャッシュを無視したいのでタイムスタンプをパラメーターに設定しています。
```js
const cameraList = ref([
  {
    name: "Camera 1",
    data: {
      count: 0,
      timestamp: 0
    },
    max: 120,
    imgId: "camera-1"
  }
])
onMounted(() => {
  for (const cameraKey in cameraList.value) {
    setInterval(async () => {
      const { pending, data: getData } = await useLazyFetch(`https://<domain>/${cameraList.value[cameraKey].imgId}/data.json?t=${new Date().getTime()}`, {
        key: String(new Date().getTime())
      });
      cameraList.value[cameraKey].data = getData.value;
    }, 1000);
  }
});
```

表示部分はこのようになっています。（Tailwindcssを使ってます。クソ長いクラス部分はすべて排除してます。）

シンプルに表示するだけです。なお、画像のリンクはキャッシュが効くように最終データのタイムスタンプを活用しています。

```vue
<div v-for="camera in cameraList">
  <img :src="`https://<domain>/${camera.imgId}/image.png?t=${camera.data.timestamp}`" v-if="camera.data.timestamp"/>
  <div>
    <div class="flex flex-row justify-between">
      <p class="font-bold text-2xl">{{ camera.name }}</p>
      <div class="flex flex-row text-gray-500">
        <p>データ更新時間: </p>
        <p>{{ new Date(camera.data.timestamp).toLocaleDateString() }} {{ new Date(camera.data.timestamp).toLocaleTimeString() }}</p>
      </div>
    </div>
    <div class="grid grid-cols-2">
      <div class="flex flex-col">
        <p class="text-xl py-1">人数</p>
        <div class="flex flex-row flex-nowrap">
          <p class="text-4xl">{{ camera.data.count }}</p>
          <p class="text-2xl ml-2 mt-2">人</p>
        </div>
      </div>
      <div class="flex flex-col">
        <p class="text-xl py-1">混雑度</p>
        <div class="flex flex-row flex-nowrap">
          <p class="text-4xl">{{ (( Number(camera.data.count) / camera.max ) * 100).toFixed(2) }}</p>
          <p class="text-2xl ml-2 mt-2">%</p>
        </div>
      </div>
    </div>
  </div>
</div>
```

# ページの認証
今回、学校の生徒だけがページを見れるようにしたいのでGoogleアカウントで認証を設けました。
内部としては、Firebase Authenticationを使ってメールアドレスのドメイン部分が学校のメールアドレスであれば認証を通すようにしています。

コードは、まあネットにありふれているようなコードなので省略します。

# 最後に
最近ちょっと時間が無くて、記事の内容が大分大雑把になっていますが、書きたいことはかけたので満足です。
最後までお読みいただきありがとうございました。
AssetGuidlineを利用して、不足しているプラグインや設定を知らせる


小ネタです。

# AssetGuidlineとは

プラグインとプロジェクト設定の情報を保持するアセットです。
プラグインやサンプルBlueprintなどを配布する時に利用します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/26b0d8b2-4996-d1e7-912d-92a259323d9b.png" width=25%>

これを利用すると、アセットを開いた時に 以下のような表示を出せます。
（ここではOCSプラグインとVirtualTextureを有効化する必要があるよ というメッセージが出ています）

||
|--|
|![31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/2bda15db-fdf3-3e28-7f77-106ccee6d1ed.png)|

アセットを配布する際は、依存するプラグインや設定を確認し、必要あればAssetGuidlineを仕込んでおきましょう。
導入先にて設定不足の情報が出るので、トラブルを回避できます。

# 設定方法

AssetGuidline を継承したActorを作成します。

||
|--|
|![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/2765374f-2d26-3900-9220-77a66bb7e65d.png)|

依存するプラグイン名や、設定項目を記述します。

||
|--|
|![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/8d4ea955-6659-9bed-6025-f5e60fad4723.png)|

これをActorComponentのAssetUserDataにセットすれば完了です。
エディタで開いたり、レベルに配置した瞬間に設定がチェックされます。

|Actorで設定|レベル上で設定|
|--|--|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/256bc66d-6ce9-c442-727c-fe78676d3cee.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36233/96126399-5228-c32d-3937-99052cf72183.png)|



# 余談

私がアセットを配布する際は、ControlRigやPython, OCSを使うBlueprintに AssetGuidlineを設定していました。
ただこれらのプラグインはUE5.3ではデフォルト有効化されているので、メッセージを見かける機会は減りました。

ここ最近のUEで使うなら、PCG(ProceduralContentGeneration)や、AI関連のプラグインが対象になりそうです。これらはデフォルト無効化されているので、プロジェクト側で設定が必要です。
もしプラグインに依存するアセットを配布する際には、参考にしてみてください。
翻訳QA（LQA）のネイティブ/非ネイティブテスターの検証領域について考えてみた

## はじめに
みなさんこんにちは！

1年間程、翻訳QA（LQA）のテスト管理を行って感じたことの一部を今回共有させていただきます。
ネイティブ/非ネイティブテスターそれぞれの検証領域についての考えをまとめてみました。
いわゆる一般的なゲームアプリでの翻訳QAの検証観点の話になるのでご理解ください。

少しでも翻訳QAに興味のある方の参考になればと思います。


## ネイティブ/非ネイティブテスターの定義

翻訳QAのテスター人材の定義について、
今回の話では以下のように定義しております。

**ネイティブテスター：海外言語の理解のあるバイリンガル人材**

**非ネイティブテスター：一般的な日本人テスター**


## 検証観点の領域について

それぞれのテスターごとに不具合の検知しやすさは違います。
翻訳QAの大まかな検証観点とテスターごとの不具合を検知できる領域をまとめた表がこちらになります。

![lqa_bug.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3065150/cfcbbfab-e193-ce49-ceaa-16b039b38aaa.png)


翻訳QAで翻訳確認～画面表示の確認まで実行を想定した場合、検証観点を大きく分類すると以下の2点に分類されます。

・言語「翻訳内容が適切なものになっているか」
・非言語「画面表示に異常がないか」


右の列ではそれぞれのテスターが不具合の検知しやすさで〇△✕で振り分けています。
検証対象の性質によって内容に差が出るとは思いますので参考までにご覧ください。

非言語の領域はどちらも検知しやすさが〇になっていますが、非ネイティブテスターの方が不具合を検知しやすい傾向にあり強みであると考えております。
理由としては日本語との比較しやすさや、仕様書の読み取りやすさなどが要因だと思います。

## テスターごとの強みを踏まえた検証領域

テスターごとの強みを踏まえたうえで、不具合を検知しやすい検証領域は以下となります。

**・ネイティブテスターはニュアンスなどを指摘可能なので翻訳内容の検証を対応**
**・非ネイティブテスターは表示崩れの指摘や違和感をより精度高く指摘可能なので非言語の検証を対応**

テスターのそれぞれの強みを理解して作業を振り分けることで、より効率的な翻訳QAを実行できると思います。


## さいごに

1年間翻訳QAのテスト管理を行ってきたことを通して、
不具合検知の傾向が以前より鮮明に見えてきたので今回のような記事を書かせていただきました。

これ以外にもテスターの性質は細かく分析するとまだまだ沢山あると思います。
少しでも参考になりましたら幸いです。

最後までご覧いただきありがとうございました！
COVID-19変異株の管理はGithubが支えている

みなさん、github使ってますか？
  
githubといえば主な目的はソースコードの管理ですが、そのほかにも工夫次第で使い道があります。

その一つが、**COVID-19変異株の管理**です。

ウイルスは感染を繰り返すうちに、生存能力を高めるために新たな変異を獲得します。
こうした変異を共通言語の下に管理するために、特定の変異には都度「lineage」という名前が付けられます。
「B.1.1.7」「BA.5」「XBB.1.5」といった表記を目にしたことがある方がいらっしゃるかもしれません。これがlineageです。


このlineageの管理に、実はgithubが一役買っています。

https://github.com/cov-lineages/pango-designation

最新のlineageの一覧をまとめるlineage_note.txtを公開する、lineageの更新があった際はRelease noteを記録するといったように、最新の状況をトラッキングできる管理がなされています。

中でも注目したいのがissuesです。

https://github.com/cov-lineages/pango-designation/issues


issueは最新の変異株についてディスカッションする場となっています。
世界中の研究者がgithubに集まり、絶えず新しい変異株について報告をしています。
その中でピックアップされた変異株にlineageが付与され、世界中のスタンダートとなっていくのです。

各issuesの管理にもLabelやMilestoneが利用されており、githubの機能を上手く活かした運用がなされています。

単にソースコードを扱うためだけにgithubを使うのではなく、こうしたプラットフォームとして使ってみるのも面白いかもしれません。
【Slackの新ワークフロービルダー（Workflow Builder）】ショートカットはどこへ

# はじめに
こんにちは。
この記事はHRBrain Advent Calendar 2023の8日目の記事です。

https://qiita.com/advent-calendar/2023/hrbrain

Slackのワークフロービルダーが新しくなりましたね。
旧来のものがレガシーワークフローと呼ばれるようになって、少しだけしんみりとしてます。
本記事では新しくなってショートカットがいなくなり戸惑ったので、どうやって使用できるのかを書きます。
# ショートカットはどこへ
レガシーワークフローではこのような画面がありました。

![スクリーンショット 2023-12-04 20.13.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/de393650-ad6c-b0a9-94b3-c2fc2355795a.png)

ショートカットボタンを選択し、作成して公開すればチャンネルにワークフローが出来上がっていました。簡単ですね。
しかし、今はこうです。

![スクリーンショット 2023-12-04 20.14.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/07084cd8-29c8-5399-6a11-aac084d1112c.png)

**ショートカット→Slack内のリンク** に変化しています。
私はショートカット無くなったの...？と錯覚してしまいました。
もちろん、ショートカットという便利な機能が無くなるわけもなく残っています。
しかし、今までは作成すれば勝手にできていましたが少し工数が必要になりました。
# チャンネルでショートカットのようにワークフローを使用する方法

## STEP1　トリガーで「Slack内のリンクから」を選択

![スクリーンショット 2023-12-04 20.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/63f26e13-228e-6cee-28f8-cc76fec82209.png)

## STEP2　良い感じのワークフローを作成して公開
:::note warn
「誰がこのワークフローを見つけて使用できますか？」で、ワークフローを使用するユーザやチャンネルをしっかりと入力してください。ここで選択されていないチャンネルやユーザはワークフローを使用できません。
:::
:::note info
後々、使用できるチャンネルやユーザを変更したい場合は編集画面の設定から変更できます。
:::
![スクリーンショット 2023-12-06 12.40.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/07d5ccf1-0937-2421-e574-12f942a6faeb.png)

## STEP3　リンクをコピーする
:::note info
完成時にもリンクをコピーできますが、完成後にリンクをコピーしたい場合は編集画面からできます。
:::
![スクリーンショット 2023-12-06 11.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/1ff71dbb-1550-dab8-0ca8-7f90ce932bdc.png)

## STEP4　ワークフローを追加したいチャンネルを開く

## STEP5　ページ左上のブックマークバーにワークフローフォルダを追加
:::note info
既存ワークフローがある場合はとばしてもらって大丈夫です。
:::
1️⃣「フォルダを作成する」を選択

![スクリーンショット 2023-12-06 11.38.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/1462dd50-55a0-46e9-2cc6-6ce233a588fc.png)

2️⃣「ワークフロー」と入力して作成

![スクリーンショット 2023-12-06 12.12.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/6f085ca5-ac90-efb2-5fd6-7d23871e4ac0.png)


## STEP6　ワークフローフォルダにワークフローを追加
1️⃣「関連ページを追加する」を選択

![スクリーンショット 2023-12-06 12.08.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/af11b1ba-878e-744e-f4c9-6bbd7d7ccc0f.png)

2️⃣「ワークフローのURL」を入力して追加

![スクリーンショット 2023-12-06 12.22.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/16c3c0b7-dd95-1413-5dc2-501dd8649f98.png)

## STEP7　ワークフローフォルダから使用
![スクリーンショット 2023-12-06 12.28.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472415/6518e8e6-e8dc-a07e-086c-c0b92319fe5c.png)


といった感じになります。

# おわりに
今まで、一回で済んでいたことが色々しなくてはならなくなったみたいです。他に簡単な方法や良い感じの方法知ってる方がいれば教えていただけると嬉しいです。

# PR
株式会社HRBrainでは新卒の方も中途の方も新しいメンバーを募集しています！

https://www.hrbrain.co.jp/recruit