OmniAICreator/Qiita-1.07M huggingface dataset:
Engineer Guild Hackathon 2024に出場しました！

## はじめに

2024年11月2日～2024年11月16日でEngineer Guild Hackathonに出場してきたのでその雰囲気や感想をまとめます。

https://event.gaishishukatsu.com/hackathon_2024_november

## Engineer Guild Hackathon 2024について

### 概要

Engineer Guild Hackathonとは外資就活ドットコムという就活サービスを運営しているHowTelevision主催のハッカソンで、今回が第1回だったらしいです。
CyberAgent, Microsoft, PKSHA TECHNOLOGY, M3の超豪華なスポンサーがついていて、優勝賞金も50万円とすごいです。

チーム参加と個人参加があり、個人参加の場合は即席チームをランダムで組まれて開発します。
今回自分は個人で参加しました。

1週間でプロダクトを開発して発表するという流れで、今回のプロダクトのお題は「**テクノロジーを使って、インバウンド観光客（外国人観光客）の体験を最高に**」というものでした。

### スケジュール

- 11/2：事前説明
- 11/2~11/8：予選開発期間
- 11/9：予選発表会 @ Zoom
- 11/10~11/15：決勝開発期間
- 11/16：決勝発表会 @ アーク森ビル32F ハウテレビジョンオフィス（東京）

### 審査項目

- 実用性
- 創造性
- ユーザビリティ
- 完成度
- プレゼンテーション
- 技術的挑戦

## 開発したプロダクト

「**SmaGoMap: IoTごみ箱SmaGoと連携可能なごみ箱の位置マップ**」というプロダクトを開発しました。

観光客の、ごみ箱の数が少ないという課題を解決するために開発した、ごみ箱の位置をマップで表示するというものです。
詳しくは発表用スライドを見てみてください。

## 予選開発+予選発表会

4人の即席チームで開発を行いました。

開発はこのようなスケジュールで進めました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/ef7ba1a2-f4f8-24eb-483d-5a39bcce83b7.png)

自分の納得いくところまで開発しきることはできませんでしたが、なんとか開発できたところまでをうまく発表しようということになりました。

以下が実際に作った発表用スライドです。

https://speakerdeck.com/ryutarom/egh-timu16

1チームあたり持ち時間12分で発表を行いました。

即席チームの中で唯一決勝まで進出することができました！
まさか決勝に進出できるとは思っていなかったのでとても嬉しかったです。

## 決勝開発+決勝発表会

決勝開発期間はこのようなスケジュールで進めました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/6c829825-8d69-4677-d1b6-3319087144b7.png)

1チームあたり発表15分+企業からの質疑応答5分でした。

発表用スライドは以下です。

https://speakerdeck.com/ryutarom/engineer-guild-hackathon-2024-jue-sheng-timu16

どのチームも技術レベルが高く、プロダクトも洗練されていて、よく考えられているなあととても感動しました。
また、技術面でも学ぶことは多々ありましたが、ビジネスやマーケティングの視点を全てのチームが取り入れていてすごいなと思いました。

決勝では惜しくも入賞はできませんでしたが、結果として予選も合わせると全21チーム中5位になることができました！

## さいごに

さいごまで読んでいただき、ありがとうございました。

新たな視点を取り入れられたり、刺激を受けることができたりと、とても貴重な経験になりました。

みなさんもぜひハッカソンに参加してみてください！

## おまけ

参加賞
![IMG_2503.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/47f3fdac-0ea6-3af3-63a9-c1577a263c7e.jpeg)

会場の様子
![IMG_2484.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/9a945bea-f629-7bc2-507d-aaeb11ca460c.jpeg)

![IMG_2486.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/6276678e-8af5-972e-c067-c9174ab845a6.jpeg)


懇親会
![IMG_2493.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2906464/b988f9d5-e83b-c491-18fb-a7e65da0d4a0.jpeg)
【Nuxt】layoutsがlayouts/default.vueしかないなら、layouts/を削除して、app.vueに書け！

そっちの方がパフォーマンスがいいらしい

https://nuxt.com/docs/getting-started/views#layouts

https://github.com/nuxt/nuxt/discussions/18957

https://vuetifyjs.com/en/getting-started/installation/#manual-setup
【ゲーム紹介】最近話題の「２つ」を組み合わせてみた！

## はじめに
　今回は自作のゲームを紹介したいと思います。その前に、タイトルにある最近話題の「２つ」とは何か話しておきます。と言っても１つはタグに書いてありますが。（もう１つはタグにすると不穏当すぎるので止めました）
　１つ目は、Pyxelです。先日[こちらの記事](https://qiita.com/kitao/items/eae53dd47c663b497352)が公開されてから、Pyxelがすごい盛り上がっていると個人的に感じています。~~この波にちゃっかり乗っかって見ようなんて邪な気持ちもありつつ~~普段はpygameを使ってゲームを作っているのですが、今回はPyxelでのゲーム開発に挑戦してみました！Pyxelは本当に初めてで、pygameと違う部分が多くて手こずったので、特に強く意識した違いも、また今度記事にしようと思います。
 　２つ目は闇バイトです。いきなり何の話だと思われるでしょうが、今回のゲームのテーマの話です。軍手を落とすバイトって、都市伝説的な話で聞いたことあるんじゃないでしょうか。最近の闇バイト関連のニュースを見て、この話を思い出したので、少し攻めた内容かもしれませんが、ゲームにしてみました。軍手を落とすっていうのはモチーフとして分かりやすいですし、それ自体が反道徳的すぎることもないと思いますので、「闇バイトに警鐘を鳴らす目的のゲーム」としておこうと思います。これで大義を得たので、早いとこ攻めた内容のゲームを公開してしまいましょう。

## ぜひ試しにプレイしてみて！

https://prosamo.github.io/glove-dropper/

<a href="https://prosamo.github.io/glove-dropper/">![](https://prosamo.github.io/glove-dropper/title.png)</a>

　***↑こちらから遊べます***。PyxelってGitHub使えば、結構簡単にWeb上へゲームを公開できるんですね。まぁ簡単と言っても、筆者の場合はPyxelもGitHubも不慣れだったもので、かなりトライアルアンドエラーな感じでしたけども。（初心者の視点からの記録も需要あるかと思うので、こちらも後で記事にしようかなと思います。）

#### 追記:記事にしました
https://qiita.com/Prosamo/items/6e2f7147e38aca3db5ca

## 操作説明
　PCの方はタイトル画面でH、スマホの方はswitchでいうところのXボタンを押せば、似たものが見れます。

### 軍手落とし　バイトマニュアル
 　勤務していただく上で、必要な情報となります。必ず、一度目を通しておいて下さい。

#### 仕事内容
　軍手を投げて、街中のコインを集めます。落下中の軍手でないと、上手くコインが入らないので注意してください。

 #### 基本技術
 前投げ　　　→　F　　　　（十字キー左）
 落とす　　　→　D　　　　（十字キー下）
 後ろ投げ　　→　S　　　　（十字キー右）
 ジャンプ　　→　スペース 　(Bボタン）
 リスタート　→　エンター 　(ゲームパッド非対応)
 タイトルへ　→　Q　　　　（ゲームパッド非対応）

 ※スマートフォンでご参加の方は、仕事中以外は、エンターの代わりにAボタンを押してください

 #### 時給について
 　完全歩合制です。１つコインを集めていただけば、報酬として100円が支払われます。軍手は30個支給しますので、時給は最大3000円となります。コインを見逃した場合には、ペナルティとして、軍手を一つ回収させていただきます。ご注意ください。

#### 勤務時間
　勤務時間は深夜の2:00～3:00の１時間です。深夜に働いていただくため、時給を高めに設定しています。決して怪しい仕事ではなく、ホワイトな案件ですので、安心してご参加ください。


 ## 最後に
 　ここまで読んで下さり、ありがとうございました。筆者は開発中も含めて、もう50回くらいプレイしてるので、時給3000円とれるのですが、友達にプレイしてもらったところ、難しいと言われました。製作者としては、最初の数回であきらめずに、ちょっと慣れるまで頑張ってみれば、結構面白いんじゃないかなって感じです。合計の金額が10000円になるくらいまで粘ってみるといいんじゃないかな...？と思います。以上です。
Render.com で作成した PostgreSQL データベースを pgAdmin で操作できるようにする

【前置き】
Render.com で Web アプリ、DB を構築した後テストも兼ねて操作して残してしまった DB のレコードが余計だったので何とか削除できないかと思っていた所、[こちらの記事](https://zenn.dev/nyaru_tech/articles/2336d629c7828f)と出会ったため実行。<br>結果として問題なく使用できたため記事にまとめました。

# 作業環境について
* Windows に pgAdmin をダウンロードして作業
* Render.com で PostgreSQL データベースを作成済み
    * データベースの項目 `info` でDB情報諸々を確認できる状況
* 2024/11/18 時点で最新の「pgAdmin 4 v8.13 (released Nov. 14, 2024)」 をダウンロード (記事内後述)
* Render.com の無料枠で利用

---
# 作業手順
以下の資料が大変参考になりますので困ったらご覧ください

https://avinton.com/academy/postgresql-setup/


## 1. pgadmin をダウンロード

:::note info
**pgAdmin** ： PostgreSQL 用の DB を GUI で操作・管理できるツール
:::

以下、公式サイトからダウンロードしてください

https://www.pgadmin.org/

※ 自分は 2024/11/18 時点で最新の「pgAdmin 4 v8.13 (released Nov. 14, 2024)」をダウンロードしました

## 2. pgadmin の画面から DB の登録
ダウンロードした pgAdmin を起動して Render.com 上の DB を pgAdmin に登録します

### (1) DB サーバー登録画面を開く
* pgAdmin を開く場合は 「Add New Server」を選択する
    * 選択すると「Register - Server」画面が開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518714/aa825ef7-1f45-2726-b9a6-7107e0b397a4.png)


:::note warn
既に pgAdmin で作業済みの場合は、次の画像のように右クリックで新規登録 (Register) のメニューを選択すれば以降の作業を実施できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518714/40026521-156e-c347-dff7-504282b8f831.png)
:::


### (2) 「Register - Server」画面 ＞ General
* この画面の `Name` を入力します
    * この `Name` は接続情報ではないので自由に命名可能なので適当に命名してください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518714/0dc7f3a3-431d-a037-2b69-36f40a2110c9.png)


### (3) 「Register - Server」画面 ＞ Connection
* ここから接続情報を入力します
* Render.com で作成済みの DB の `Info` を参照してください

:::note info
こちらの QA 回答を参考にしたところ上手く接続できました
https://community.render.com/t/connecting-to-pgadmin/2024
:::


| | pgAdmin 画面上 | Render.com 上　(DB の `Info` 参照) |
|--:|:--|:--|
| 1 | Host name/address    | `External Database URL` の `@` から `@` を含めず `.render.com` までの文字列 |
| 2 | Port                 | 5432 |
| 3 | Maintenance database | `Database` |
| 4 | Username             | `Username` |
| 5 | password             | `Password` |

:::note alert
"Host name/address" は `External Database URL` をそのままコピペではありません
以下【例】の**太字部分**を入力してください

【例】
postgresql://dammy_dammy_user:dammydammy@ **sample-sample.sample-postgres.render.com** /sample_db

:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518714/50e311b8-2d5a-f303-d94f-a1b799f18dd6.png)


### (4) 「Register - Server」画面 ＞ Save ボタンを押下
* 「Save」ボタンを押下すれば DB 接続一覧にご自身の DB が表示されます
    * 入力内容が誤っている場合はエラー文が表示されるので入力内容を見直して修正してください

　
以上になります

---
### 参考資料
https://zenn.dev/nyaru_tech/articles/2336d629c7828f

https://community.render.com/t/connecting-to-pgadmin/2024

https://www.pgadmin.org/

https://www.sraoss.co.jp/tech-blog/pgsql/pgadmin4/

https://avinton.com/academy/postgresql-setup/
Dev Container でも Git コミットに SSH 鍵署名したい

::: note warn
この記事では Git コミットに SSH 鍵を用いて署名する方法については触れない。
:::

Git コミットに署名する方式として、最近では GPG 鍵より SSH 鍵を使用するほうがカジュアルで良い。


しかし Git コミット時に SSH 鍵を用いた署名を行うには、Git (2.34 以降) と SSH エージェントが必要であり、そのあたりが入っていない Dev Container などでコミットをしようとすると

> Git: unsupported value for gpg.format: ssh

> Git: cannot run ssh-keygen: No such file or directory

などとエラーが出てしまう。

Dev Container 内に Git (2.34 以降) と SSH エージェントを入れればいいという単純な話なので、その方法についてまとめる。

## (方法1) DevContainer の Dockerfile に書く
例えば Debian 系のイメージを使用している場合は以下のように書けばよい。

``` Dockerfile:Dockerfile
RUN apt-get update \
 && apt-get install -y --no-install-recommends git openssh-client
```

ただし Debian 11 (Bullseye) で入る Git は 2.30 なので SSH 鍵による署名には対応していない。Debian 12 (Bookworm) の場合は 2.39 なので問題はない。Debian 11 (Bullseye) ベースのイメージで新しめの Git を入れたい場合は Debian Backports を使うとよい。(下記記事を参照)

https://qiita.com/hoto17296/items/913665130e42c519cdf8

## (方法2) Dev Container Features を使用する
Dev Container Features という「Dev Container に機能を追加する仕組み」があり、Dockerfile をわざわざ書きたくない場合はこれを使うこともできる。

参考: [Dev Container Features reference](https://containers.dev/implementors/features/)

この仕組みを使って Git と SSH Agent を追加するには、Dev Container の設定ファイルに以下を追記して再ビルドする。

``` json:.devcontainer.json
{
  "features": {
    "ghcr.io/devcontainers/features/git:1": {"version": "latest"},
    "ghcr.io/devcontainers/features/sshd:1": {}
  }
}
```

`(方法1)` に書いたのと同じ理由で、イメージが Debian 11 のときに SSH 鍵署名未対応のバージョンの Git がインストールされてしまうため、新しめの Git を入れるために `"version": "latest"` と指定している。
【超基礎】TypeScript非同期処理基本まとめ

## 前提
この記事は、初学者の私が、サバイバルTypeScriptで学んだこと+調べたことをまとめたものになります。

従って、経験則に基づいた発言ではないため、一部慣習とは違っていたり、認知にずれがあったりする可能性がありますので、ぜひコメントで指摘していただけると幸いです。

https://typescriptbook.jp/

## 非同期処理とは？
### 概要
 - **待ち時間が発生する処理を並行して行う**ことで効率化を図るもの
 - APIの呼び出しや外部データの読み込みなど
 - コードが複雑になるという欠点があったが、近年は`Promise`や`async`,`await`構文により、可読性の高い実装が可能になった

### 同期処理とは？
非同期処理を理解する前に、対義語となる同期処理について説明する。

同期処理では、一つ一つ順番に処理を行い、前の処理が完了するのを待ってから次の処理に移る。書いたコードが上から下に、順番に処理されていくため実装は簡単だが、一つでも時間のかかる処理が存在すると、以下の処理全体に遅れが生じるため効率的ではない。

## 実装
### Promise
- 非同期処理の最終的な完了、失敗を表す`Promise`オブジェクトを返す関数を作成
- `初期化の際にアロー関数を渡す
- 完了時に返したい値を`resolve`、エラーを`reject`に渡す
- 正常な値は`then`、エラーは`catch`で受け取る
::: note warn
仕様上`resolve`以外の名前を使うこともできるが、慣習的にあり得ない
:::

```TypeScript:Promise
function plusOne(val: number): Promise<number>{ 
//Promise<T>のTは、resolve時の型
    return new Promise<number> ((resolve,reject) => { //Promiseオブジェクトの作成、コンストラクタにアロー関数を渡す。
        if(val < 0){
            reject(new Error("valueが負の数")) //rejct時に返したい値
        }else{
            resolve(val + 1); //resolve時に返したい値を渡す
        }
    });
}

function double(val: number): Promise<number>{
    return new Promise<number>((resolve,reject) => {
        if(val > 100){
            reject(new Error("valueが大きすぎるよ"));
        } else {
            resolve(val * 2);
        }
    });
}

function main(){
    plusOne(3)
        .then((plusedOneValue: number) => { //resolveの値を引数として受け取る
            return double(plusedOneValue); //コールバックすることで、次のthenに渡す
        })
        .then((doubledValue) => {
            console.log(doubledValue);// => 8
        })
        .catch((e: unknown) => { //rejectはcatchで受け取る
            console.log(e.message);
        });
    }

main()
```
### async/await
- 非同期処理を、Promiseより簡単に書ける構文
- `async`と`await`は基本セット

**async** : 関数、メソッドの前につけることで戻り値の型を`Promise`でラップする

**await** : Promiseが解決されるまで待機する。基本的にasyncの中でしか使えない。

::: note
awaitはasync関数によりPromiseでラップされた戻り値をアンラップする演算子であると捉えることもできる。
:::
```Typescript:async/await
//plusOne関数、double関数は同じ。

async function main() {
    try{
        const plusedOneValue = await plusOne(3);　//定数を定義し、関数呼び出しの際にawaitを付けるだけ
        const doubledValue =  await double(plusedOneValue);
        console.log(doubledValue);//=> 8
    } catch(e:unknown) { //then、catchはtry-catchに置き換えてエラーハンドリング
        console.log(e);
    }
}

main() 
```
## まとめ
なんとなく学習時のストレスが大きそうだな、、と思っていた非同期処理ですが、時代の流れとともにより分かりやすい形になっており、ありがたかったです。

当方初学者なため、認知のずれや、モダンな開発現場ではもう使わない表現などがありましたらコメントで指摘していただけると幸いです。😸

### 参考資料
https://qiita.com/soarflat/items/1a9613e023200bbebcb3
https://qiita.com/soarflat/items/1a9613e023200bbebcb3
https://typescriptbook.jp/reference/asynchronous/promise
Amazon RDS for OracleのタイムゾーンをUTCからJSTに変更する

# はじめに
業務でAmazon RDS for OracleのタイムゾーンをUTCからJSTに変更したいとの依頼がありました。
分かっていれば簡単ですが、調査してからCloudFormationに記述するまでに半日程かかったため今回備忘録として、内容をまとめたいと思います。

# オプショングループの作成
デフォルトのオプショングループは編集することができないので、新たにオプショングループを作成します。
エンジン：`oracle-ee`
メジャーエンジンバージョン：`19`

RDS→オプショングループ→グループの作成

![オプショングループ作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929650/a1f79092-ac08-e276-c5bc-617074f02e68.png)


新たに作成したオプショングループにオプションを追加します。
オプション名：`TIMEZONE`
タイムゾーン：`Asia/Tokyo`
すぐに適用：`Yes`

オプショングループ選択→オプションの追加

![オプションの追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929650/6f700658-ee78-ff2c-12c8-e5ff45348be5.png)


オプショングループを作成したら、Oracleのオプショングループをデフォルトから変更します。

# タイムゾーン確認
Oracleに接続し、タイムゾーンが変更されているか確認。
```
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') AS current_time FROM dual;
```

### UTC
![タイムゾーンbefore3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929650/0859fedf-2faa-8aa4-7a9b-dbbdacbd0a91.png)
### JST
![タイムゾーンafter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929650/02271920-6822-3960-ec31-09fafc63d2f8.png)


# CloudFormationテンプレート
今回作成したCloudFormationテンプレート
### yaml
```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: OptionGroup For Oracle

Parameters:
  OptionGroupName:
    Type: String
  Engine:
    Type: String
  MajorEngineVersion:
    Type: String

# Mappings:

Resources:
  # DBオプショングループ作成
  DBOptionGroup:
    Type: AWS::RDS::OptionGroup
    Properties:
      OptionGroupName: !Ref OptionGroupName
      OptionGroupDescription: Option group for Oracle with Timezone set to JST
      EngineName: !Ref Engine
      MajorEngineVersion: !Ref MajorEngineVersion
      OptionConfigurations:
        - OptionName: Timezone
          OptionSettings:
            - Name: TIME_ZONE
              Value: Asia/Tokyo
```

### json
```json
{
    "Parameters": [
        {
            "ParameterKey": "OptionGroupName",
            "ParameterValue": "test"
        },
        {
            "ParameterKey": "Engine",
            "ParameterValue": "oracle-ee"
        },
        {
            "ParameterKey": "MajorEngineVersion",
            "ParameterValue": "19"
        }
    ]
}
```
winapiで参照エラーが出た時の対処法

さっき私が体験したことを描きます.


# エラー内容
VScodeでWINapiの描画アプリを実行すると以下の参照エラーが出ました。
```
C:/Users/ユーザネーム/mingw64/bin/../lib/gcc/x86_64-w64-
mingw32/14.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: 
c:/Users/ユーザネーム/ｭｰｩｳｰ/ｲｼｨ｣ｿ/test3.c:14:
(.text+0x8f): undefined reference to `__imp_Ellipse'
```
このエラーが発生しました。
```
undefined reference to `__imp_Ellipse'
```
見た感じ``Ellipse``の参照エラーです. 
しかし``windows.h``をインクルードしているのでその時はよくわかりませんでした.
そうしてネットの海に出かけたのですが、似たようなエラーはあるがなかなか見つかりませんでした.

まあ..いろいろ探した結果、コンパイラ方法が悪いみたいでした
このやつを
```
gcc -Wall -Wextra -g3 ファイル名.c -o ファイル名.exe 
```
こうする
```
gcc ファイル名.c -o ファイル名.exe -lgdi32 -mconsole
```
これでいいみたいです
homebrewでpip3 更新したら怒られたので仮想環境を作成して実行してみる

<!--
### homebrewでpip3 更新したら怒られたので仮想環境を作成して実行する方法を紹介
-->



pip更新しようとしたら怒られたエラーログ

```
python3 -m pip install --upgrade pip 

[notice] A new release of pip is available: 24.2 -> 24.3.1
[notice] To update, run: python3.13 -m pip install --upgrade pip
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
    xyz, where xyz is the package you are trying to
    install.
    
    If you wish to install a Python library that isn't in Homebrew,
    use a virtual environment:
    
    python3 -m venv path/to/venv
    source path/to/venv/bin/activate
    python3 -m pip install xyz
    
    If you wish to install a Python application that isn't in Homebrew,
    it may be easiest to use 'pipx install xyz', which will manage a
    virtual environment for you. You can install pipx with
    
    brew install pipx
    
    You may restore the old behavior of pip by passing
    the '--break-system-packages' flag to pip, or by adding
    'break-system-packages = true' to your pip.conf file. The latter
    will permanently disable this error.
    
    If you disable this error, we STRONGLY recommend that you additionally
    pass the '--user' flag to pip, or set 'user = true' in your pip.conf
    file. Failure to do this can result in a broken Homebrew installation.
    
    Read more about this behavior here: <https://peps.python.org/pep-0668/>

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
```

HomebrewにないPythonライブラリをインストールする場合は、仮想環境を使用することが推奨されているため、エラーログに従って仮想環境を作成した。

```
python3 -m venv path/to/venv
source path/to/venv/bin/activate
python3 -m pip install xyz
```
仮想環境にうまく入れると(venv)username@computername ~ % となる。
再度、下記を実行するとpip更新することができた。
```
python3 -m pip install --upgrade pip
```

### 次回以降ターミナルを立ち上げて実行する方法

```
python3 -m venv path/to/venv
source path/to/venv/bin/activate
```



### ライブラリ紹介
今回、試しに入れたライブラリを紹介します。

|ライブラリ　　　| 説明 |install コマンド|
|:-:|:-:|:-:|
| pandas  |データ解析や操作を行うためのPythonライブラリで、データフレームという形式でデータを扱うことができます|pip install pandas |
| matplotlib  |グラフや図を描画するためのPythonライブラリで、様々な種類のグラフを作成することができます|pip install matplotlib |
| opencv | Open Source Computer Vision Libraryの略で、コンピュータビジョンや画像処理の分野で広く使用されているライブラリです。OpenCVは、リアルタイムの画像処理を可能にするために設計されており、顔認識、物体検出、モーション解析など多様な機能を提供しています|pip install opencv-python |
| folium  |地図を作成するためのPythonライブラリで、Leaflet.jsを使用してインタラクティブな地図を作成できます|pip install folium |
|  IPython |対話型のPythonシェルで、Jupyter Notebookとしても知られています。コードやテキストを組み合わせたドキュメントを作成できます|pip install ipython |
| selenium  |Webアプリケーションの自動テストやWebスクレイピングなどを行うためのツールで、ブラウザを制御することができます|pip install selenium |
Power AutomateでTeamsのチームメンバー外のアカウントからメッセージを投稿する

Power AutomateでTeamsのチームメンバー外のアカウントからメッセージ投稿をすると、「objectId XXXX の送信者は、チームのメンバーでも所有者もでありません」とエラー表示されます。

現状の回避方法としては、一旦グループにアカウントを追加し、メッセージ投稿完了後にグループからアカウントを削除する処理です。

# 手順1.［グループへのメンバーの追加］でメンバー外のアカウントを追加 
フロー実行アカウントとチームIDを取得したうえで、［Office 365グループ］コネクタの［グループへのメンバーの追加］アクションで、グループIDとユーザープリンシパル名の値をセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/8b98401f-108a-dab3-f6f3-b6b50acd827e.png)


# 手順2.［遅延］で処理反映を待機
このまま［グループへのメンバーの追加］からTeamsメッセージ投稿をしようとすると、Power Automateの処理速度が速すぎてシステムエラーになってしまうので、［遅延］で待機処理を挟みます。設定値は5秒。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/c7e73d11-ca55-976b-b71d-28dca5f0d26e.png)


# 手順3.［グループからメンバーを削除］でメンバー外のアカウントを削除
［Office 365グループ］コネクタの［グループからメンバーを削除］アクションで、グループとユーザープリンシパル名の値をセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640497/b64b414d-5a68-329b-4f05-4f320c68f6ff.png)
Javaユーティリティクラスとコンストラクタのprivate化について

# 導入

こんにちは、もんすんです。

Javaプログラミングにおいて、ユーティリティクラスは非常に便利な存在です。
一方で、ユーティリティクラスが開発者の意図しない使われ方をすることがあります。
このような誤った使用を防ぐためには、設計段階で適切な対策を講じることが重要です。

この記事では、ユーティリティクラスの基本的な役割や特徴の紹介と、**インスタンス化を防ぐ方法**などに触れていこうと思います。

# ユーティリティクラスについて
## ユーティリティクラスとは
ユーティリティクラスとは、すべてが`static`メソッドや`static`フィールド(変数)で構成されたクラスのことです。
たとえば、Java標準ライブラリに含まれている`Math`クラスや`Arrays`クラスがその例です。
これらは、特定の機能(例えば、数学演算や配列の操作)をまとめており、<font color="red">オブジェクトを生成しなくても直接使える</font>ように設計されています。

ユーティリティクラスは、普通のクラスとは異なり、**インスタンス(オブジェクト)を生成する必要がありません**。そのため、「このクラスをインスタンス化する意味がない」という特徴があります。

もし、ユーティリティクラスがインスタンス化可能だと、誤って<font color="red">**そのクラスを使って無駄なオブジェクトを生成してしまう**</font>可能性があります。
これは、プログラムの設計上の誤解を招いたり、不必要なリソース消費につながる可能性があります。

しかしながら、コンパイラは優秀なため、コンストラクタが存在しないクラスに対して、<font color="blue">引数を持たない**デフォルトコンストラクタ**を自動的に生成</font>してしまいます。このデフォルトコンストラクタは、`public`なアクセス権を持つため、外部からそのクラスをインスタンス化できます。

## インスタンス化を防ぐための方法:star:
Javaでは、インスタンス化を防ぐための簡単なテクニックがあります。
それは、**クラスに`private`コンストラクタを追加する**ことです。
コンストラクタが`private`であれば、外部からそのクラスを呼び出してインスタンス化することができません。

以下はその例です。

```java
public class UtilityClass {
    // private コンストラクタを定義して、外部からのインスタンス化を防ぐ
    private UtilityClass() {
        throw new AssertionError("このクラスのインスタンスは作成できません。");
    }

    // static メソッド
    public static int add(int a, int b) {
        return a + b;
    }
}
```

1. **`private` コンストラクタ**：`private`修飾子がついているため、このクラスの外部からは呼び出せません。インスタンス化を試みると、コンパイルエラーが発生します
2. **`throw new AssertionError()`**：(これは必須ではありません。)万が一クラス内からコンストラクタが呼ばれてもエラーとなるようにしています

## ユーティリティクラスを多用するデメリット
便利ではありますが、ユーティリティクラスにもデメリットがあります。
ユーティリティクラスを必要以上に多用すると、`オブジェクト指向プログラミング(OOP)`の基本概念から逸脱してしまいます。

`OOP`の基本的な考え方は、**データ(フィールド)とそのデータを操作するメソッドをまとめた「オブジェクト」を作ること**です。通常、クラスはそれぞれが持つ状態や振る舞いを管理し、インスタンス化されたオブジェクトとして振る舞うことを目的とします。

しかし、**ユーティリティクラスはインスタンスを持たない**のが前提であり、**すべてが`static`なメソッドやフィールドだけ**で構成されています。これにより、OOPの「状態と振る舞いを持つオブジェクト」という設計とは異なり、単なる**機能の集合**として振る舞うことになります。

ユーティリティクラスを多用すると、以下のようなデメリットが生じる可能性があります。

1. **コードの再利用性が低下**：ユーティリティクラスに頼りすぎると、状態(データ)を持つクラスの設計が不十分になり、再利用性や拡張性が低い設計になります
2. **メンテナンスが難しくなる**：すべての処理がユーティリティクラスに集中すると、メソッドが増えすぎて管理しにくくなり、コードが散らばる可能性があります
3. **依存性の増加**：他のクラスがユーティリティクラスのメソッドに依存しやすくなり、クラス同士の結びつきが強くなりすぎてしまいます。これにより、コードが複雑になり、テストやメンテナンスが難しくなります

## 終わりに

ユーティリティクラスは、その簡便さと汎用性から、多くのJavaプロジェクトで利用される重要な設計パターンです。

一方で、過剰に使用すると、オブジェクト指向プログラミングの設計思想から逸脱し、コードの可読性や拡張性に影響を与えることもあります。

ユーティリティクラスを使用する際には、<font color="red">「本当にユーティリティクラスとして設計するべきか」「他の設計パターンが適しているのではないか」</font>を常に検討することが重要ではないかと思います。
Supabase CLI に含まれるローカル開発環境


## はじめに

みなさんは、BaaS (Backend As A Service) の 1 つ Supabase を利用したことはありますか?
検証やちょっとした個人開発であれば Supabase に直接接続し開発を進めることも選択肢の1つになりますが、 Supabase CLI に内包されている ローカル開発環境 を使えば簡単に手元のマシンに環境を用意できるのでその紹介をしたいと思います。

## Supabase CLI とは

はじめに にも記載しましたが、手元のマシンで、Supabase の Project 作成・起動や リモート(supabase.com) のスキーマ情報を取得したり様々なことができるツールです。

https://supabase.com/docs/guides/local-development/overview

## 準備

Supabase CLI を実行する際には以下のインストールが必要です。

- Docker Desktop 等の Docker 実行環境
- Node.js, Scoop, Homebrew のいずれか

上記準備が整ったら Supabase CLI をインストールします。

### Docker Desktop 等の Docker 実行環境

Supabase CLI はバックグラウンドに Docker Desktop を使用します。
下記リンクもしくは Homebrew 等で Docker Desktop をインストールしてください。

https://docs.docker.com/desktop/

```sh
brew install --cask docker
```

Docker Desktop 以外にも下記ツールでも実行可能なようです。
必要に応じてインストールを実行してください。

- [Rancher Desktop](https://rancherdesktop.io/) (macOS, Windows, Linux)
- [Podman](https://podman.io/) (macOS, Windows, Linux)
- [OrbStack](https://orbstack.dev/) (macOS)
- [colima](https://github.com/abiosoft/colima) (macOS)

### Node.js, Scoop, Homebrew のいずれか

下記リンクから、 Node.js, Scoop, Homebrew のうち1つは実行できるように設定してください。
すでにインストールされている場合この手順をスキップしてください。

https://nodejs.org/en/download/package-manager

https://brew.sh

https://scoop.sh

### Supabase CLI のインストール

下記リンク内の手順にそってインストールを進めます。

https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=macos

私は Homebrew を選択したので 下記コマンドを実行しました。

```sh
brew install supabase/tap/supabase
```

## Supabase の起動

使用したい Project のディレクトリに移動し Supabase の初期設定(ファイル生成)と起動を行います。
`supabase init` を実行すると `supabase` フォルダ(ディレクトリ)の作成と設定ファイル生成を行ってくれます。

```sh
cd /path/to/project-dir
supabase init
```

生成された Toml ファイルを確認し、 Project 名や起動ポート等必要に応じて編集します。
編集が終わったら `supabase start` で Supabse を起動します。

```sh
supabase start
```

旧バージョンでは Storage 等使えない機能もありましたが、現在は Storage 含め使えるようになっています。

## Ref

https://supabase.com/docs/guides/local-development

https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=macos
主要プロセス監視ツール５選

プロセス監視を効果的に行うための主要なツールを以下にご紹介します。

**Zabbix**
オープンソースの統合監視ソフトウェアで、プロセスやネットワーク、ログ、ミドルウェアなど幅広い監視に対応します。

‌

![Zabbix Logo PNG Vectors Free Download](https://tse2.mm.bing.net/th?id=OIP.qZUE8LLOHgk4U5b30JcqEQAAAA&w=200&h=112&c=7)

**Nagios**
ネットワークやシステムの監視を行うオープンソースツールで、プロセスの稼働状況やリソース使用率の監視が可能です。

![Nagios Logo Vector - \(.Ai .PNG .SVG .EPS Free Download\)](https://tse4.mm.bing.net/th?id=OIP.oWl3wLluU9eylMQDinsfygHaBs&w=200&h=112&c=7)

**Prometheus**
オープンソースのモニタリングシステムで、メトリクスの収集やアラート機能を備え、プロセス監視にも適しています。

![Prometheus Monitoring System Logo PNG vector in SVG, PDF, AI, CDR format](https://tse3.mm.bing.net/th?id=OIP.ZYl3ns9RYMIFTMb216qnbwHaFj&w=200&h=150&c=7)

**Grafana**
データの可視化ツールで、Prometheusなどと連携してダッシュボードを作成し、プロセスの状態を視覚的に監視できます。

![1200px-Grafana\_logo.svg - MYETV Blog](https://tse1.mm.bing.net/th?id=OIP.14liup9ZXm5FC8sKIXJZnAHaHj&w=200&h=204&c=7)

**Hinemos**
日本発のオープンソース統合運用管理ツールで、プロセス監視を含む多様な監視機能を提供します。

![Hinemosでできることってなに？ - 株式会社GOAT](https://tse1.mm.bing.net/th?id=OIP.Ouo_C1xTc_GWRVuCdj40sgHaE8&w=200&h=133&c=7)

これらのツールは、それぞれ特徴や強みが異なります。自社のシステム環境や監視要件に合わせて最適なツールを選定することが重要です。
【TypeScript】inferってなんやねん

TypeScriptを書いていて、Pathの処理を型でやらなきゃいけない場面がありその際に使用したので復習がてら書いていきます。

`infer` = 推論すると覚えておくと理解が楽かもです。

## 簡単な使用例

[サバイバルTypeScript](https://typescriptbook.jp/reference/type-reuse/infer)より
> inferはConditional Typesの中で使われる型演算子です。inferは「推論する」という意味でextendsの右辺にのみ書くことができます。

最初にこれを読んだ時、あんまりわからなかったので理解のとっかかりになるような簡単な使用例を書いてみます。

```ts
type Infer<T> = T extends Array<infer U> ? U : never;

type a = Infer<[1, 2, 3]>;
// → type a = 3 | 1 | 2

type b = Infer<1>;
// → type b = never
```

inferでやる内容ではないけど...
この例では、`Infer`はなにかしらを受け取り、それが`(infer U)[]`にマッチした場合、`U`を返す。そうでない場合は`never`を返す。

aの例では、`[1, 2, 3]`が`Array<infer U>`にマッチするので、`U`は`1 | 2 | 3`となり、そのまま返される。

bの例では、`1`は`マッチしないので、`never`が返される。

この例を見た上で、最初に提示した以下の文章を読めば、なんとなく納得できるかと思います。
> inferはConditional Typesの中で使われる型演算子です。inferは「推論する」という意味でextendsの右辺にのみ書くことができます。

## 少し複雑めな使用例

ここでは少し複雑な使用例を紹介したいと思います。

要件としては、以下のようなURLパスを型で表現する必要があります。
- openapiのパスパラメータは、`/users/{id}`のように`{}`で囲まれた部分がパラメータである
- MSWのリクエストハンドラは、`/users/:id`のようにパラメータ部分が`:`で始まる形式である必要がある
- パスパラメータは複数である場合がある(`/users/{id}/post/:postId`など)

つまり、`/users/{id}`を`/users/:id`に変換する型が必要です。

これを型で表現するために、以下のような型を作りました。

```ts
type PathParams<T extends string> =
  T extends `${infer Head}/{${infer Param}}${infer Tail}`
    ? `${Head}/:${Param}${PathParams<Tail>}`
    : T;

type c = PathParams<'/users/{id}'>;
// → type c = "/users/:id"

type d = PathParams<'/users/{id}/post/:postId'>;
// → type d = "/users/:id/post/:postId"
```

`PathParams`は、`T`が`/users/{id}`である場合、`/users/:id`のようなパスに変換する型です。

再起的に処理しているため、`/users/{id}/post/{postId}`のような複数のパラメータがある場合も対応できます。

`infer`を使うとこういう型もかなり簡潔に書くことができたりします。

## おわりに

最後まで読んでいただきありがとうございます。
今回は、`infer`を使った型の処理について紹介しました。
私自身もまだまだ型に関しては勉強中なので、間違いや誤解がある場合はコメントいただけると嬉しいです🙇‍♂️
[JavaScript]変数と定数

# 変数/定数の宣言

```js
// 変数の定義
let 変数名 = 値;

// 定数の定義
const 定数名 = 値;

// 変数の定義(昔からある方)
var 変数名 = 値;
```

# 何が違う？

- let: ブロックスコープ
- const: ブロックスコープ
- var: 関数スコープ

```js
if (1 == 1) { // 条件式の判定はtrueなので下記の処理が実行される
    // let の宣言
    let num1 = 0;
    // const の宣言
    const num2 = 1;
    // var の宣言
    var num3 = 2;
}

// 出力
console.log(num1); //=> ブロックスコープの中で宣言されているためエラー
console.log(num2); //=> ブロックスコープの中で宣言されているためエラー
console.log(num3); //=> 2
```

<br />

- let: 再代入できるが、再宣言はできない
- const: 再代入も再宣言もできない
- var: 再代入も再宣言もできる

```js
// 再宣言
let greet = "hello";
let greet = "こんにちは"; //=> エラー

const name = "Mike";
const name = "太郎"; //=> エラー

var age = 12;
var age = 24;

// 出力
console.log(greet); //=> エラー
console.log(name); //=> エラー
console.log(age); //=> 24
```

```js
// 宣言
let myName = "太郎";
const age = 10;
var money = 1200;

// 再代入
myName = "次郎";
age = 100; //=> エラー
money = 0;

// 出力
console.log(myName);
console.log(age); //=> エラー
console.log(money);
```

使うのは基本的にconst、再代入が必要ならlet。
varは予期しないバグやエラーの原因となるため、使わないようにしましょう。

# 参考記事

https://techplay.jp/column/1619

https://tech.adseed.co.jp/javascript-var-deprecated
Springでibatisがインポートできなかった時の対処方法

## 経緯
SpringBootの勉強でAPIサーバを作成しようと以下の記事を見ながら進めていたところ、Mapperインターフェースを作成した際に `org.apache.ibatis.annotations.Param` のインポートが必要になった。しかし記載の通りに進めても認識されなかったため、ライブラリの追加方法を調べた。

https://zenn.dev/msksgm/articles/java-springboot-api-server

Springのプロジェクト自体はSpring initializrで以下のライブラリを加えて作成した。
- Spring Web
- MyBatis Framework
- PostgreSQL Driver
- Lombok

https://start.spring.io/

環境
- OS: MacOS
- IDE: IntelliJ

## 現象
     import org.apache.ibatis.annotations.Param;
上記のような形でインポートをするも認識されなかった。

## 対処方法
pom.xmlのdependencyに書こうにも、どう書いていいのかの情報を発見できなかったため、色々IntelliJをいじり回した。
その結果、`⌘` + `;` でプロジェクト設定を開き、その中の`モジュール`→`依存関係`→`+`をクリックすることでライブラリを追加できることを発見した。さらに`ライブラリ...`→`Mavenから...` を選択することでライブラリを検索することができ、`org.apache.ibatis`で検索して`apache.ibatis.core`をインポートすることができた。

## おわり
ibatisってMyBatis Frameworkに入ってるわけじゃないんですかね...?
TA-LIB インストール for Windows 2024年11月版

pip install がエラーになるときの解決方法。
Windows向けには Visual Studio を入れてビルドせよといった情報があるが、だるいのでビルド向けバイナリを取って済ませたいとき向け。

結論としてはバイナリは https://github.com/cgohlke/talib-build/releases にある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11522/e82330b3-a8a5-561a-b349-e207cfed00e7.png)

DLしたら下記コマンドでインストール

```
python -m pip install TA_Lib-xxx.whl
```

https://zenn.dev/whitecat_22/articles/9e30d88e31c3ec を参考にインストールしようとしたけど、バイナリのダウンロード先がクローズしちゃってたので備忘録。
Vitest を GitHub Actions 上で実行するときに設定したいオプションや composite action - カバレッジレポート編


## はじめに

Vitest をプロジェクトに設定しローカル環境はもちろん CI/CD 環境でも動かす場面は少なくありません。
今回は GitHub Actions で Vitest を実行する際に設定したい内容や composite actions をまとめました。

## レポーター設定

Vitest は GitHub Actinos の workflow command に対応しています。
なお、この設定は `process.env.GITHUB_ACTIONS` が `true` である場合自動的に有効になります。

https://vitest.dev/guide/reporters.html#github-actions-reporter

もし、レポーター設定をデフォルト値以外で使用している場合は、 `github-actions` を追加することで利用可能です。

```ts:vite.config.ts
export default defineConfig({
   test: {
     coverage: {
       reporter: ["dot", "github-actions"],
```

## カバレッジレポート

こちらの記事でも紹介されていましたが、 `vitest-coverage-report-action` を導入することで作成した Pull request にコメントでテストカバレッジを追加してくれます。

https://qiita.com/shun198/items/f640b3d3bf73d2cc3510

https://github.com/marketplace/actions/vitest-coverage-report

`vitest-coverage-report-action` を使用するためには、 `reporter` に下記値を定義する必要があります。

- json-summary (必須)
- json

```ts:vite.config.ts
export default defineConfig({
   test: {
     coverage: {
       reporter: ["json-summary", "json"],
```

## 上記内容適用した設定ファイル

上記内容適用した設定ファイルは以下のようになります。

```ts:vite.config.ts
export default defineConfig({
   test: {
     coverage: {
       reporter: ["dot", "github-actions", "json-summary", "json"],
```

## Ref

https://github.com/davelosert/vitest-coverage-report-action

https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message
AWSのSQSで配信できずにハマった話

## はじめに
普段はAWSについてはほとんど触れないため、不正確な部分があるかもしれませんが、SQSでうまくいかなかった対応について、備忘のために記しておきます。

## 結論
SQSのタイプがFIFOのキューを扱う際には、`MessageDeduplicationId`が一意でなくてはならない。
重複している場合、5分間は配信されない。
※エラーにはならず、ステータスは200で返ってくる。

参考：

https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagededuplicationid-property.html

## 内容の確認
現場のコードは再現できないため、デモコードで確認します。
SQSのタイプがFIFOのキューを扱う際、`MessageGroupId`と`MessageDeduplicationId`の設定が必要になります。

これを画面から設定できるようにしました。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/83485e00-8b23-cbe6-d7cb-fd384501e077.png'>

値を入力して、送信ボタンを押すと、キューの中身が確認できます。

<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/39445310-edab-d4a7-76e9-1c923410565d.png'>

新しく追加すると、キューに追加されます。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/e50f0a7c-df1e-c18c-2fdf-1fe1a943e18c.png'>

ここで、はじめに入力したものと同じ`MessageDeduplicationId`を設定してみます。
<img width='80%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/bbda7ac0-6692-e1ed-6528-d01bc19e154f.png'>

キューには追加されていないことがわかります。

## まとめ
バグ対応でかなりの時間を費やしたのですが、結局は上記で解説した部分がバグの原因になっていました。
普段あまり触らない技術部分の知識もしっかりつけておきたいと思いました。
RWKV/rwkv-4-world-3bはパソコンのキーボードを知っているのか

[昨日の記事](https://qiita.com/KoichiYasuoka/items/faa270a09b5b335c3beb)の[RWKV/v6-Finch-3B-HF](https://huggingface.co/RWKV/v6-Finch-3B-HF)だが、内蔵トークナイザhf_rwkv_tokenizer.pyに[バグがあって](https://huggingface.co/RWKV/v6-Finch-3B-HF/discussions/3)、`decode`や`convert_tokens_to_ids`がマトモに動かない。モデル定義のmodeling_rwkv6.pyにも[バグがあって](https://huggingface.co/RWKV/v6-Finch-3B-HF/discussions/1)、性能低下を起こしているらしい。どうも、内蔵プログラムのレビューが、ちゃんとおこなわれていないように見える。

旧版の[RWKV/rwkv-4-world-3b](https://huggingface.co/RWKV/rwkv-4-world-3b)も試してみたのだが、こちらも内蔵トークナイザtokenization_rwkv_world.pyに[バグがある](https://huggingface.co/RWKV/rwkv-4-world-3b/discussions/1)。さすがにイラっと来たので、`trust_remote_code=True`を使わない形でトークナイザを再設計し、無理矢理RWKV/rwkv-4-world-3bを動かすことにした。Google Colaboratory (GPU版)だと、こんな感じ。

```
!pip install transformers
import ast,json,torch
from transformers import GPT2TokenizerFast,AutoModelForCausalLM
from transformers.utils import cached_file
from transformers.models.gpt2.tokenization_gpt2 import bytes_to_unicode
from tokenizers.models import WordPiece
f=cached_file("RWKV/rwkv-4-world-3b","rwkv_vocab_v20230424.txt")
with open(f,"r",encoding="utf-8") as r:
  v=[s.strip().split(" ") for s in r]
d=ast.literal_eval("{"+",".join(t[0]+":"+" ".join(t[1:-1]) for t in v)+"}")
d[0]="
"
v,x={},bytes_to_unicode()
for i in range(len(d)):
  v["".join(x[j] for j in (d[i].encode("utf-8") if type(d[i])==str else d[i]))]=i
with open("vocab.json","w",encoding="utf-8") as w:
  json.dump(v,w,indent=2,ensure_ascii=False)
tkz=GPT2TokenizerFast("vocab.json","/dev/null")
w=WordPiece(v)
w.unk_token=d[0]
w.continuing_subword_prefix=""
tkz.backend_tokenizer.model=w
mdl=AutoModelForCausalLM.from_pretrained("RWKV/rwkv-4-world-3b",torch_dtype=torch.float16).to(0)
tgn=lambda x:tkz.decode(mdl.generate(tkz(x,return_tensors="pt")["input_ids"].to(mdl.device),max_new_tokens=333,do_sample=True,temperature=1.0,top_p=0.3,top_k=0)[0].tolist(),skip_special_tokens=True)
nlp=lambda txt:tgn(f"User: hi\n\nAssistant: Hi, I am your assistant and I will provide expert full response in full details. Please feel free to ask any question and I will always answer it.\n\nUser: {txt}\n\nAssistant:")
print(nlp("パソコンのキーボードは，なぜABC順・五十音順ではないのですか"))
```

WordPiece版GPT2TokenizerFastでトークナイザを置き換えつつ、「[パソコンのキーボードは，なぜABC順・五十音順ではないのですか](https://kotobaken.jp/qa/yokuaru/qa-35/)」と尋ねてみたところ、私(安岡孝一)の手元では以下の結果が出力された。

> User: hi
>
> Assistant: Hi, I am your assistant and I will provide expert full response in full details. Please feel free to ask any question and I will always answer it.
>
> User: パソコンのキーボードは，なぜABC順・五十音順ではないのですか
>
> Assistant: パソコンのキーボードは，英語の文字を表示するために使用されるため，英語の文字を表示するために使用されています。ABC順・五十音順とは，英語の文字を英語の発音順に並べたもので，英語の発音順に基づいてキーボードを設定するために使用されています。また，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発音順に基づいてキーボードを設定するために，英語の発

うーむ、出力が止まらなくなってしまったようだ。言語モデルとしては、旧版のRWKV/rwkv-4-world-3bより、やっぱり最新版のRWKV/v6-Finch-3B-HFの方がいいのかなあ。
ユーザ定義関数（UDF）活用・・・和暦表示

# はじめに
こんにちは。
夜中に小腹が減っている男です。

かなり昔、プログラマの先輩から
「楽をするためなら、どんな苦労も厭わない」
というセリフを聞いたことがあります。

システム化って、まさにこれだよなって思っています。

「システム化する」という苦労をすると、数時間かかっていた作業が数分で終わるようになります。

また、プログラミング作業自体も同様です。
処理を関数化しておけば、同じコードを何回も書かなくて良いし、他の人のコードを参考にできて楽になります。

ここでは、そんな話をします。

# ユーザ定義関数（UDF）
Power Apps の ユーザ定義関数（UDF = User Defined Function） というものがあります。

UDF はユーザが独自の関数を作成できる機能です。
同じ処理を関数にまとめることができるので、アプリの生産性や保守性を向上できます。

まさに、「楽をするためなら、どんな苦労も厭わない」機能です。

### 補足）UDF を使うための設定
現在（'24/11/17）、UDF は試験段階の機能です。利用するためには以下の設定が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925493/78a9cad9-c57d-c211-2d0b-a5d08688c7a8.png)

# UDF の定義方法
### 書式
関数名 (パラメタ名1: パラメタ型1, パラメタ名2: パラメタ型2, … ): 戻り値の型=式;
### 例
~~~
 // 指定した数に１を足す関数
CountUp (n:Number): Number = n+1;
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925493/1ed3785b-944d-53bd-c9ae-0a01d4643f66.png)

# UDF の利用例
Microsoft は米国企業なんですよね。
日本語ローカライズのためのUDFを定義しておくと便利だろうなぁと思って、こんなものを作ってみました。

### 西暦年 → 和暦年変換
~~~
// 西暦年を指定すると、和暦年に変換するユーザ関数
// （明治1～令和30年、1868～2048年まで）
ConvJapanYear(y:Number):Text = If(
    y < 1868, "（明治以前）",
    y < 1912, "明治 " & (y - 1868 + 1),
    y < 1926, "大正 " & (y - 1912 + 1),
    y < 1989, "昭和 " & (y - 1926 + 1),
    y < 2019, "平成 " & (y - 1989 + 1),
    y < 2049, "令和 " & (y - 2019 + 1),
    "（不明）"
) & " 年";
~~~
利用例： ConvJapanYear(2018)
戻り値 → "平成 30 年"

### 西暦日付 → 和暦日付変換
~~~
// 西暦日付を指定すると、和暦日付に変換するユーザ関数
// （Date関数が1900までしか対応していないので、明治33～令和30年、1900～2048年まで）
ConvJapanDate(d:Date):Text = 
If(
    d < Date(1912,7,30),
    "明治 " & (Year(d) - 1868 + 1),
    d < Date(1926,12,25),
    "大正 " & (Year(d) - 1912 + 1),
    d < Date(1989,1,8),
    "昭和 " & (Year(d) - 1926 + 1),
    d < Date(2019,5,1),
    "平成 " & (Year(d) - 1989 + 1),
    d < Date(2049,12,31),
    "令和 " & (Year(d) - 2019 + 1),
    "（不明）"
) & " 年" & Text(d," m 月 d 日");
~~~
利用例： ConvJapanDate(Today())
戻り値 → "令和 6 年 11 月 17 日"


### 指定した月を漢字表記に変換
~~~
ConvMonthKanji(m:Number):Text=Index(["一","二","三","四","五",
"六","七","八","九","十","十一","十二"],m).Value & "月";
~~~
利用例： ConvMonthKanji(1)
戻り値 → "一月"

### 指定した月を和暦表記に変換
~~~
ConvMonthNameWareki(m:Number):Text=Index(["睦月","如月","弥生","卯月","皐月",
"水無月","文月","葉月","長月","神無月","霜月","師走"],m).Value;
~~~

利用例： ConvMonthNameWareki(1)
戻り値 → "睦月"

### 指定日の曜日を日本語１文字で返す
~~~
ConvWeekDayNameJ1(d:Date):Text=Switch(Weekday(d),
1,"日",2,"月",3,"火",4,"水",5,"木",6,"金",7,"土","");
~~~

利用例： ConvWeekDayNameJ1(Today())
戻り値 → "日"

# 補足）UDF の命名ガイドライン
メンテナンスのため、ある程度は命名のルール決めはした方がいいっすよね。
ボクはこんな感じで定義するようにしています。

### 関数名
- 機能が理解できる名前
- 英字、数字のみ使用可（1文字目数字NG、日本語NG）
- パスカルケースで書く（複数単語をスペースなしで連結、単語１文字目を大文字、それ以外小文字）
- 可読性が上げたい場合、アンダーバー（”_”）使用可

### パラメタ名
- 内容が分かる範囲で、できるだけ短く
- 英字、数字のみ使用可（1文字目は数字NG、日本語NG）

# さいごに
今年も Qiita に助けられることが多かった一年でした。
ありがとうございました。

来年もよろしくお願いいたします。
では、良いお年をお迎えください。
【Dart】Future, awaitの概念について自分なりに整理してみる

# 投稿者について

2024/09~Flutter開発に携わっているモバイルエンジニアです。
間違っている部分などありましたらご指摘いただけると幸いです。


# 概念についてざっくり理解する

dartの公式ドキュメント（[Asynchronous programming: futures, async, await](https://dart.dev/libraries/async/async-await)）を参考にざっくり概念についてまとめてみました。

### 1. 非同期処理って何だろう

**非同期処理** とは端的に言えば **「時間のかかる処理」** を意味します。
逆に **同期処理** というのは **「時間がかからない処理」** を意味します。
（若干乱暴ですが）

公式ドキュメントでは一般的な非同期な処理として以下を挙げています。
- ネットワーク経由でデータを取得
- データベースへの書き込み
- ファイルからデータを読み取り

### 2. Futureって何だろう

非同期処理を書くためのクラスです。

先ほど、非同期処理は「時間がかかる処理」ということを説明しました。Futureは処理が始まってから終わるまでの結果を表し、未完了または完了の2つの状態を持つことができます。

非同期処理が完了した場合に、以下の3つの結果になります。

1. 成功
2. 成功して値を返す（`Future<String>`だったら`String`の値を返す）
3. エラー（失敗）

今回は概念の理解をしたいので、エラーの書き方は省略します。

### 3. asyncって何だろう

非同期関数を定義する際に関数本体の前に配置するものです。

ちなみにasyncだけ付ければ非同期処理自体は正しく実行されます。
つまり、以下2つのコードの違いは戻り値だけになります。

ただ一般的な書き方は2個目の方なので、特に理由がなければ2個目の書き方で書きましょう。

````dart
void main() async {
  /// 非同期処理
}
````

````dart
Future<void> main() async {
  /// 非同期処理
}
````

### 4. awaitって何だろう

非同期処理ですが、時間がかかるがゆえに、他の処理と同時並行で実行できます。

でも、一つの非同期処理を終わらせてから他の処理を実行したい場合があります。
その場合に使用するのがawaitです。

awaitは非同期処理（`Future<T> () async {}`）が完了するまで次の処理を待機してくれます。



# 実際に非同期処理を触ってみる

[dartの試し書きができるサイト](https://dart.dev/)があるので、実験してみました。

例えば以下のように

　1. 3秒後に実行する処理
　2. 1秒後に実行する処理
　3. 同期処理

という順番で`await`を使用せずに実行しても、出力の順番は、
 1. 同期処理
 2. 1秒後に実行する処理
 3. 3秒後に実行する処理

のようになります。
同期処理・非同期処理両方とも同時に実行されているのが分かりますね。

![スクリーンショット 2024-11-17 19.17.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936114/0933af8f-a943-3932-aeb7-71cab845c39a.png)

次に、main関数を`Future<void> main() async {...}`にして、メソッドに`await`をつけてみましょう。

![スクリーンショット 2024-11-17 19.20.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936114/f7fe2652-c375-61e5-897c-1820308c6b4d.png)

なんと先ほどと同じ順番で出力されました。

 1. 同期処理
 2. 1秒後に実行する処理
 3. 3秒後に実行する処理

`await`くん、今の処理が終わるまで次の実行待っててくれる仕組みじゃないんですかね。

では、非同期処理をそれぞれ待ってもらった上で、3秒後に実行→1秒後に実行→非同期じゃない処理の順に行ってもらうにはどうすればいいでしょうか？答えは以下です。

![スクリーンショット 2024-11-17 19.31.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936114/cbecfeb3-c1d4-0463-614a-cd53514d68ec.png)

そう、 **メソッドの中にも`await`を使用していないと待っていてくれません**。

というか、メソッドの中にも実行時にもawaitを使っていないと「順番に処理を終わらせて」くれないみたいです。

↓ main関数内のawaitを削除した場合

![スクリーンショット 2024-11-17 19.35.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936114/a2bcf902-efad-81cf-158b-f94356f18acc.png)

すなわち、**`await`は処理が終わるまで次の処理を待っててくれるが、入れるタイミングを間違えば待っててくれない**ということになります。

もう少し検証してみましょう。

「非同期メソッドの中に同期メソッドが入っていても順番に処理を行ってくれる」のでしょうか？

　1. 3秒後に実行する処理（処理の最後に同期処理「非同期メソッド1が完了しました」）
　2. 1秒後に実行する処理（処理の最後に同期処理「非同期メソッド2が完了しました」）
　3. 同期処理

![スクリーンショット 2024-11-17 20.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936114/6490b316-a47a-e80c-e5ec-55740bfe644f.png)

出力は以下のようになりました。素晴らしい！期待通りです。

　1. 3秒後に実行する処理
　2. 非同期メソッド1が完了しました
　3. 1秒後に実行する処理
　4. 非同期メソッド2が完了しました
　5. 同期処理


## まとめ

- Dartで非同期処理を書く際は`Future`, `async`を使用して処理を書く
- 処理が完了するまで他の処理を待機させる場合は`await`を使用する
- `await`はちゃんと入れないと待機してくれない
第3回：Pythonの応用技術（オブジェクト指向・モジュール・エラー処理）

前回の記事 ⇒ <a href="https://qiita.com/mm02060116/items/8093e784fed68a422179">第2回：Pythonのデータ構造と関数</a>

この回では、より高度なPythonの概念であるオブジェクト指向とモジュールと例外処理を学ぶことで、エラーが発生した際の対処法を習得する。

目次

1.オブジェクト指向プログラミング（OOP）の基礎
　 クラスとインスタンス：クラスの定義とインスタンスの生成
　 メソッドと属性：クラス内での関数と変数の扱い
　 継承：クラスを継承して機能を拡張
 
2.モジュールとパッケージ
　 標準ライブラリ：mathやdatetimeなどの基本モジュール
　 外部パッケージの利用：pipを使ったパッケージのインストールと利用方法

3.例外処理
　 例外の種類：ValueError, TypeError など
　 例外処理の書き方：try, except, finallyによるエラーハンドリング

  1.オブジェクト指向プログラミング（OOP）
  -
Pythonはオブジェクト指向プログラミング（OOP）をサポートしており、クラスとインスタンスを利用してコードを構造化することができる。

<strong>クラスとオブジェクト</strong>
クラスはオブジェクトの設計図で、オブジェクト（またはインスタンス）はそのクラスから作られた実体です。
クラスはclassキーワードで定義し、__init__メソッドで初期化処理する。
```python:example.py
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print(f"Hello, my name is {self.name}.")

person1 = Person("Alice", 25)
person1.greet()  # 出力: Hello, my name is Alice.
```

<strong>継承</strong>
継承により、既存のクラスの特性を引き継いで新しいクラスを作ることが可能。
新しいクラス（サブクラス）は、元のクラス（スーパークラス）の機能を再利用しつつ、独自の機能を追加できる。
```python:example.py
class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)
        self.student_id = student_id

student1 = Student("Bob", 20, "S1234")
student1.greet()  # 出力: Hello, my name is Bob.
```

2.モジュールとパッケージ
-
モジュールやパッケージを使うことで、コードを機能ごとに分割し、再利用可能にできます。

<strong>モジュール</strong>：Pythonファイルを分けて機能を整理したものです。別のファイルからimport文で読み込み、関数やクラスを利用できます。
```python:example.py
# example.py
def hello():
    print("Hello from the module!")
```
```python:main.py
# main.py
import example
example.hello()  # 出力: Hello from the module!
```
<strong>パッケージ</strong>：パッケージは、複数のモジュールをまとめたディレクトリです。ディレクトリには__init__.pyファイルが含まれ、モジュールをパッケージ化して扱うことができます。

3.エラー処理（例外処理）
-
エラー処理は、予期せぬエラーや例外が発生した際にプログラムが停止しないようにするための手法です。

<strong>try-except文</strong>：try-except文を使用してエラーをキャッチし、エラーが発生した際の動作を指定できます。
```python:example.py
try:
    number = int(input("Enter a number: "))
    print("Result:", 10 / number)
except ValueError:
    print("入力が数値ではありません。")
except ZeroDivisionError:
    print("ゼロで割ることはできません。")
```
<strong>finallyブロック</strong>：finallyブロックは、エラーの有無にかかわらず必ず実行されるコードを記述します。
```python:example.py
try:
    file = open("data.txt", "r")
except FileNotFoundError:
    print("ファイルが見つかりません。")
finally:
    print("終了処理を実行します。")
```

4.まとめ
-
第3回では、Pythonでのオブジェクト指向プログラミングやモジュールの活用、エラー処理について書いてみました。
これらを活用することで、効率的なコードとなります。
Angularとは

# Angularとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935725/7035bad7-694a-ff46-f965-60b70f13ac4d.png)

Angular（アンギュラー）は、GoogleのAngularチームと個人や企業のコミュニティによって開発されているTypeScriptベースのオープンソースのフロントエンドWebアプリケーションフレームワークである。(←[Wiki参照](https://ja.wikipedia.org/wiki/Angular))

↑この文章で**TypeScript**と、**フレームワーク**という単語が出てきた。この2つの単語についてまとめ、Angularを紐解く。


## TypeScriptってどんなもの?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935725/448fb40f-c429-e9de-8bf6-278a579ce8c4.png)

Typescriptは、Javascriptが大規模開発向けではないため、その補完として誕生したプログラミング言語、いわばJavascriptを大規模開発向けに拡張したものである。その特徴的な仕組みとして、TypeScriptはJavaScriptのスーパーセットとして設計されており、JavaScriptはTypeScript上でそのまま動作する。
- Typescriptで補完される内容
    
    - **モジュール性**
    functionの前に、exportを付与することで、別ファイルから使用できる。
        ``` sample_ts.ts
        type User = {
                name: string; // 型を明確に指定
            };
            //exportをつけて別ファイルから利用可能
            export function greetUser(user: User): string { 
                return `Hello, ${user.name.toUpperCase()}!`;
            }
        
            console.log(greetUser({ name: "Alice" })); // "Hello, ALICE!"
        ```
        　　
    - **型定義**
    Javascriptの場合、動的型付けが採用されているので、コンパイルの段階でエラーが気づけない。
        ``` sample_js.ts
        function greetUser(user) {
            return `Hello, ${user.name.toUpperCase()}!`;
        }
    
        console.log(greetUser({ name: "Alice" })); // "Hello, ALICE!"
        ```
    
        Typescriptでは、型を明示的に定義。
    
        ``` sample_ts.ts
        type User = {
            name: string; // 型を明確に指定
        };
    
        function greetUser(user: User): string {
            return `Hello, ${user.name.toUpperCase()}!`;
        }
    
        console.log(greetUser({ name: "Alice" })); // "Hello, ALICE!"
        ```
    
## フレームワークとは
フレームワークは、ソフトウェア開発において、共通の問題を解決するための再利用可能な枠組みやライブラリを指す。特定のルールや構造があらかじめ定義されており、開発者はその枠組みに従ってコードを書くことで効率よくアプリケーションを開発できる。たとえば、Angularは以下を提供する。

- データと画面をつなぐ双方向データバインディング
- コンポーネントベースの設計
- 依存性注入（DI）による効率的なモジュール管理
- テストのための仕組み

**フレームワークを「料理キット」にたとえるとわかりやすい。**

ライブラリは、必要な材料（食材）や道具（包丁、鍋など）が個別に提供される状態である。自分でレシピを考え、材料を選び、作り方を組み立てる必要があるが、フレームワークは、それらを示したレシピというイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3935725/9c12d736-ec7a-c1c3-5c4f-3a333bf11a10.png)


**フレームワークのメリット↓**
- レシピ（設計のルール）があるので迷うことなく作業を進められる
- 必要な材料（機能やモジュール）はすべてそろっている
- 工程が決まっているので、効率よく作業できる

## まとめ
Angularは、GoogleのAngularチームとコミュニティが開発した、TypeScriptをベースにしたフロントエンドWebアプリケーションフレームワークである。これにより、効率的にWebアプリケーションの開発が可能になる。

TypeScriptは、JavaScriptのスーパーセットで、特に大規模な開発に適した特徴を持っていて、型定義を明示的に行うことで、エラーを早期に発見でき、モジュール性を高めることで、コードの再利用性や保守性が向上させることが可能。

フレームワークは、アプリケーション開発を効率化するための再利用可能な枠組みであり、Angularは、双方向データバインディング、コンポーネントベースの設計、依存性注入（DI）などの強力な機能を提供する。これにより、開発者は効率よく、かつ品質の高いコードを書くことができる。

例えて言うなら、フレームワークは「料理キット」のようなもので、必要な材料やレシピが整っているため、開発者は迷うことなく効率的に作業を進めることができる。
別OSにjar移動

Raspberry Pi から　Ubuntuに以下をコピー
・HelloJNI.jar  
・libHelloJNIImpl.so
してjar実行
```
tak@tak-VirtualBox:~/JNI/HelloJniMoved$ java -Djava.library.path=. -jar HelloJNI.jar
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/tak/JNI/HelloJniMoved/libHelloJNIImpl.so: /home/tak/JNI/HelloJniMoved/libHelloJNIImpl.so: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません (Possible cause: can't load AARCH64-bit .so on a AMD 64-bit platform)
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1934)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1850)
	at java.lang.Runtime.loadLibrary0(Runtime.java:843)
	at java.lang.System.loadLibrary(System.java:1136)
	at HelloJNI.<clinit>(HelloJNI.java:7)
```
https://www.perplexity.ai/search/linuxte-aarch64-bit-toka-amd-6-0ZmdJuPER7eZO6obLxGlXQcle
AWS ECSタスクの環境変数ファイルは値を引用符で囲ってはいけない


# ECSタスクの動作がおかしい

ECSタスク中でこんな感じのコマンドを実行していました。

```bash
aws s3 syc ${S3_DIRECTORY_URL} /var/www/files
```

S3からファイルをダウンロードする単純なコマンドです。
ところがこんなエラーが発生します。

```
 aws s3 sync <LocalPath> <S3Uri> or <S3Uri> <LocalPath> or <S3Uri> <S3Uri>
```

ここで `${S3_DIRECTORY_URL}` というのは環境変数ファイルから取得するようタスク定義で指定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920697/d920cd58-99e7-da14-d73c-3a26875dac67.png)

```
# .env の中身
VARIABLE1=value1
VARIABLE2=value2
S3_DIRECTORY_URL="s3://sample-bucket/download_source_dir"
```

確実に値は渡っているはずなのになんでエラーになるの？？？
念のため ecs exec で環境変数値を確認してみます。

```bash
$ aws ecs execute-command  \
    --region ap-northeast-1 \
    --cluster {ECSクラスタ名} \
    --task {ECSタスクのID} \
    --container app \
    --command "env" \   ※環境変数値を確認
    --interactive

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-xxxxxxxxxxxxxx
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
VARIABLE1=value1
VARIABLE2=value2
S3_DIRECTORY_URL="s3://sample-bucket/download_source_dir"
```

やっぱ値入ってるよなあ・・・ってあれ？


なんでダブルクォート付きで出力されてんの？？？
もしや・・・

環境変数ファイルを次のように引用符なしに修正してみたら・・・動いた！！

```
# .env の中身
VARIABLE1=value1
VARIABLE2=value2
S3_DIRECTORY_URL=s3://sample-bucket/download_source_dir
```

# ECSタスクの環境変数ファイルは値を引用符で囲ってはいけない

どうやらECSタスクが参照する環境変数ファイルは値を引用符で囲ってはいけないようです。
マニュアルにこう書いてあります。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/use-environment-file.html
> スペースまたは引用符は、Amazon ECS ファイルの値の一部として含まれます

非常に分かりにくいですが、スペースやダブルクォートも値とみなされるようです。試していないですが多分シングルクォートも同じじゃないでしょうか。
うっかり末尾にスペース入ってたりすると死ぬということですね。こういうの気づきづらいから厄介なんだよな・・・

# おまけ
ローカルでは docker compose で動作確認していました。
そこでも環境変数ファイルを読みこんでいたのですが、こちらはダウブルクォートを引用符として認識してくれます。だからECSに上げるまで気づかなかったんですね。

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    env_file:
      - .env
```

# まとめ

ECSタスク定義で環境変数ファイルを使う場合はダブルクォートは引用符として使えません。
末尾スペースも削除しましょう。