OmniAICreator/Qiita-1.07M huggingface dataset:
You have uncommitted work pending.Please commit or rollback before calling out.


Spring 24で以下のように仕様が変わるみたいです。

[DML のロールバックとセーブポイントの解放後のコールアウトの実行](https://help.salesforce.com/s/articleView?id=release-notes.rn_apex_SavepointCallouts.htm&release=248&type=5)

セーブポイントを使用してコミットされていないすべての DML をロールバックします。その後、新しい Database.releaseSavepoint メソッドを使用して、目的のコールアウトを実行する前にセーブポイントを明示的に解放します。以前は、セーブポイントの作成後にコールアウトを実行すると、コミットされていない DML があるかどうか、または変更がセーブポイントにロールバックされているかどうかに関係なく CalloutException が発生していました。この機能は、IdeaExchange のアイデアのおかげで実現しました。


+ [公開日: 2019年11月30日:「You have uncommitted work pending.Please commit or rollback before calling out. (未確定の作業が保留中です。コールアウトを実行する前に確定またはロールバックしてください。)」エラー](https://help.salesforce.com/s/articleView?id=000385708&type=1)

解説記事

+ [Solution to : “You have uncommitted work pending” in Salesforce](https://salesforce-specialist.medium.com/solution-to-you-have-uncommitted-work-pending-in-salesforce-e5bd277c8362)


質問

+ [Database.savepointRelease is not working](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007agkG4)

:::note
I spent some time on that and finally made it work. My problem was related to API version 59+, specifically in the current class where you release the savepoint and the class where the callout is performed.
:::


# コールアウトするApexをフローから呼び出してみる

:::note alert
An Apex error occurred: System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
:::

+ [Notesからジョブカンに機能を移行＋Salesforceにも連携させる](https://qiita.com/Keiji_otsubo/items/fe6da72830732e8c3ff6)

同じ現象だね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cdfc897f-7c09-524f-0e79-c20e0761268d.png)
Data Move Utility

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


+ [SFDX Data Move Utility (SFDMU)](https://github.com/forcedotcom/SFDX-Data-Move-Utility)

+ [一度に大量のレコードを移行しようとするとURI TOO LONG等のエラーが出て中断されるが処理上限の目安となる値が分からない。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007YwHXH)


URI TOO LONGのエラーですがリターンコード414であれば、サーバーに対するGETリクエストの文字列が長いことが問題になっていることを示していると思います。

今まであまり深く考えてなかったのですが、匿名ウィンドウでApexを使ってレコードを更新するような処理でも時々起こってました。

以下を見ると匿名ウィンドウもGETメソッドみたいです。

This should have been accepted as the correct answer. There is no way in the Anonymous Apex window to use POST instead of GET, 

https://salesforce.stackexchange.com/questions/224420/bad-message-414-reason-uri-too-long


今回の長さの件ですが以下の長さが推奨されているみたいです。
The recommendation is to limit the URI to 2000 bytes, and headers to 8000 bytes.

詳細の説明は以下にかかれています。

https://salesforce.stackexchange.com/questions/195449/what-is-the-longest-uri-that-salesforce-will-accept-through-the-rest-api

# 設定方法

+ [SFDX Data Move Utilityによるデータ移行の際に、親子関係にあるレコードをそのまま移行する場合、JSONフアイルにはどのように記述をすればよいでしょうか。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmAqf)

:::note
以下に解説がありますので、参考にしてみてください。
[Salesforce組織間データ移行ツール SFDX Data Move Utility (SFDMU)の使い方](https://note.co-meeting.co.jp/n/n126171ad4e9f)

移行ジョブの定義ファイルの準備
export.jsonという名前の設定ファイルを用意します。
以下は取引先と取引先責任者を移行する例です。 

``` Json
{
    "objects": [
        {
            "query": "SELECT Id, Name, Type, BillingAddress, Phone, Description FROM Account",
            "operation": "Upsert"
        },
        {
            "query": "SELECT Id, AccountId, LastName, FirstName, Phone, Email FROM Contact",
            "operation": "Upsert",
            "externalId": "Email"
        }
    ]
}
```
JuliaでDeep Learningを理解する: 4.2 Clipping functions

[Understanding Deep Learning](https://udlbook.github.io/udlbook/)の[ノートブック](https://github.com/udlbook/udlbook/blob/main/Notebooks/Chap04/4_2_Clipping_functions.ipynb)をJuliaで確認する。

# 4.2 Clipping functions
[JuliaでDeep Learningを理解する: 4.1 Composing networks](https://qiita.com/dokudo9191/items/8ae56b0df9b49515594f)では簡単のために特殊な形の２層ニューラルネットワークを確認した。
![DeepConcatQuestion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/0f5415ab-8131-e274-0a8f-8afe3f687ecd.png)
(画像は[udlbook](https://github.com/udlbook/udlbook/tree/main/PDFFigures)より引用)
一般には２層ニューラルネットワークは以下のようになる。
![DeepTwoLayer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/a3cd06e7-4191-aaf4-c58e-5a8fb89033ec.png)
(画像は[udlbook](https://github.com/udlbook/udlbook/tree/main/PDFFigures)より引用)
式で表すと
```math
\begin{align}
y' = &\phi'_0 + \phi'_1a\left[\psi_{10} + \psi_{11}a\left[\theta_{10} + \theta_{11}x\right] + \psi_{12}a\left[\theta_{20} + \theta_{21}x\right] + \psi_{13}a\left[\theta_{30} + \theta_{31}x\right]\right] \\
     &+ \phi'_2a\left[\psi_{20} + \psi_{21}a\left[\theta_{10} + \theta_{11}x\right] + \psi_{22}a\left[\theta_{20} + \theta_{21}x\right] + \psi_{23}a\left[\theta_{30} + \theta_{31}x\right]\right] \\
     &+ \phi'_3a\left[\psi_{30} + \psi_{31}a\left[\theta_{10} + \theta_{11}x\right] + \psi_{32}a\left[\theta_{20} + \theta_{21}x\right] + \psi_{33}a\left[\theta_{30} + \theta_{31}x\right]\right]
\end{align}
```
となる。
これをJuliaで実装する。
```julia
function shallow(x, activation_fn, phi, psi, theta)
    pre1 = theta * [1; x]
    h1 = activation_fn.(pre1)
    w_h1 = psi' .* [1; h1]
    pre2 = sum(w_h1, dims=1)'
    h2 = activation_fn.(pre2)
    w_h2 = phi' .* [1; h2]
    y = sum(w_h2, dims=1)'
    y, pre1, h1, pre2, h2
end
```
具体的に値を入れて関数の形を確認する。
```julia
theta = [
    0.3 -1.0
    -1.0 2.0
    -0.5 0.65
]
psi = [
    0.3 2.0 -1.0 7.0
    -0.2 2.0 1.2 -8.0
    0.3 -2.3 -0.8 2.0
]
phi = [
    0.0 0.5 -1.5 2.2
]
x = 0:0.01:1
results = shallow.(x, ReLU, phi |> Ref, psi |> Ref, theta |> Ref)
y = first.(getindex.(results, 1))
lines(x, y)
```
![shallow_1_1_3_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/20efbc4c-5cff-6133-41b4-da202fa1140b.png)
[JuliaでDeep Learningを理解する: 4.1 Composing networks](https://qiita.com/dokudo9191/items/8ae56b0df9b49515594f)では周期的な性質が見て取れたが、一般的な形では隠れユニット数6の２層ニューラルネットワークでも周期性はわからない程度になる。多層で各層の隠れユニット数を増やせば非常に柔軟に関数が作れることが想像に難くない。
大事なのはこのような柔軟な関数が線形関数の組み合わせでできるということである。線形関数は特に勾配計算が高速に実行でき、高速に実行できるからこそ、層を重ねて関数を複雑にして、本質的に複雑な現象の予測ができるようになるのである。
自分のキャリア振り返ってみた

# はじめに
Qiitaのイベントでキャリアを振り返ろうというイベントがあったため、
運用保守は10年目になったため、様々な現場で学んだことやこれからについてまとめました。


技術派遣がメインになりますが、
**案件が合えばしっかり働けると評価されていました**
一人の担当営業さんからは信頼しているエンジニアの一人と評価されていました。
待機時にその営業さんが一番に積極的に案件を探してくれました。

待機になっても別支店に異動にならなかったため、誰かが評価していたと思います。
一つ目の派遣先のお客さんから退場時に別の案件を紹介してくれた。
また来てほしいと言ってくださる現場もいくつかありました。

3社目の技術派遣で資格手当がついたので毎月最大3万円まで頑張って取得しました。
また残業が平均30時間ある現場で働いていたこと。新人を育成してリーダーからの評価を高い評価になったため、年収が退職時には90万ぐらい上がりました。


## Fラン理系大学
高校時代は数学B、物理学が授業になかったため、独学で学び
一般入試　英語、数学B、物理で情報科学含む物理学の学科で入学できました。
難しくて単位を取るだけで大変でした。

趣味でCG検定3級、2級を取得してShadeR5で作品を作っていました。
https://qiita.com/gama1234/private/bc73f681e80c326506a7

## 半導体業界 7年間
半導体業界でPcell作成と検証業務をしてきました。
SKILL言語(LISP系）の言語でCADの部品を作成します。
OSはlinuxを使用していました。

学んだことは
CADの図形をプログラムで作成するため、プログラムの知識が身に付きました。
linuxは毎日使っていたため日常の操作は可能になりました。
後輩の育成をしました。

ここで学んだこと
linuxに慣れたこと
シェルスクリプトの作成するスキルがついた

# 様々な派遣先で転々としていました。
レイアウト設計の補佐業務をしたり事務の仕事をしたり
会社の寮に入って引っ越し込みで現場に働いていました。

**何か専門性のスキルがほしい**と思うようになりました。


# 2014年～現在　インフラエンジニアになりました
2014年からlinuxの経験とシェルスクリプトの経験があり、金融系でJP1 AJSとシェルを使用する現場に配属しました。半導体業界で身に着けたlinuxのスキルを活かすことができました。

JP1 モニタリングについて
運用保守の考え方が身に付きました
※以下はここ現場で身に付いた運用保守で気を付けることをまとめた記事です。
https://qiita.com/gama1234/items/5a6fb54194f687ab9f4a

シェルスクリプトを作成して単体テストと結合テストなどしていました。

**ここでの経験が運用保守での大事な土台となる経験になりました。**
その後、半年間のインフラエンジニアの経験で構築のJP1の仮想化基盤の現場に派遣されました。
常に21時帰りでエビデンスの整備や申請書の作成と事務的なことがインフラエンジニアは結構多いいことが分かりました。**教えていただいたことを手順にしてほかの方ができるようにするという習慣が身に付きました。**

インフラエンジニアの業務は意外と地味な作業　エビデンス整備　申請書作成などの作業もたくさんあります。
そのため、みんなの雑用であっても間に合っていないところのお手伝いするように心がけています

# 様々な現場でインフラエンジニアの派遣先で働きました　(JP1　AJS関連)
オンプレミスの案件がメインだったため、データセンターでの作業もありました。
構築のフェーズで朝9時～19時までデータセンターでの作業、20時～23時まで派遣先のオフィスで業務でした
21時からモニタリングのテストの確認があり、帰りが終電になることもよくありました。
平均60時間の現場もあり分からないことが多く辛い現場もありましたが、ベテランエンジニアがフォローしていただいたため、乗り越えることができました。

# Gsuiteのシステム運用の現場で1年半働きました。

Gsuiteのシステム運用の現場は1年半働きました。
ここでは業務量が多く確認者不足していて21時帰りが毎日続いていました。
技術というよりはコミュニケーションの現場でした
電話対応スキル、メールを書くスキルが身につい来ました。

20代～50代の新人をフォローしながらみんなで協力して業務をしました。
雑談があって楽しい現場でした。

スクールに通いLPICレベル2を取得しました。

# AWSを使う現場に配属になりました
僅か10ヶ月で環境が合わずに退場しましたが、ここでの現場ではスクリプト作成とAWSの知識が身に付きました。
現場で気軽に話せる先輩が辞めていき、分からないことを抱え込むことが多くなり体調不良になりました。

システム保守の現場でしたが、
主にVBAの自動化のスクリプト作成、サーバー構築業務　Bash pythonのシェルスクリプトの作成をしていました。


# AWSを専門に扱う会社Sierに転職しました 
現在も働いております。今では4年目になりました。
10ヶ月のAWSシステム保守の経験と様々なインフラエンジニアの経験が評価されて2次システム運用保守として採用されました。
今では大型案件でシステム運用保守として今までのインフラエンジニアの経験を活かしながらフルリモート環境で働いています。

障害対応スキル、AWSの経験、フルリモートの環境でのコミュニケーション力がつきました。
**今までたくさんの現場で構築の補佐と運用保守してきた経験はフルリモートのAWSの業務で活かせています。**

AWS資格を7冠とGCP2冠になりました。今は資格更新で大変な時期です。
https://qiita.com/gama1234/items/8ca518a13750a78baedf
# まとめ
システム運用保守メインで10年目になりました。
派遣社員として働いてきたため、お客さんとの折衝経験が少ないです。
今では新卒からプロパー社員として働いてきた方とスキルの差を感じています。

振り返ると契約更新の厳しさを知りました。引っ越ししながら派遣先を渡り歩く生活でした。

**会社に寄りかからないように、自分のキャリアを考える大切さを知りました。今後も目標を決めて学習を継続していきます。**
ブラウザ拡張機能を6月以降も使い続けるために

# はじめに
いかがお過ごしでしょうか。プロ行き当たりばったリスト、「スキマ」です。とある製造業で現場作業員をしていますが、ひょんなことから社内チャットボットの中の人になったり「社内ヘルプデスクのヘルプデスク」を勝手に立ち上げたりしています。
# 社内SNSに投稿がありまして
「単発質問コミュニティ」に「ブラウザの拡張機能が6月から使えなくなる？（超意訳）」と投稿がありまして、私はjs書けない民なので慌てて調べました。
* ブラウザ拡張機能にはmanifest.jsonがある
* manifestにV2とV3がある
* manifestV2はどうやら2024年6月を境に利用できなくなっていくらしい

なるほど。
なお社内の状況として
* ブラウザ拡張機能を作る市民開発者が結構居る
* 拡張機能は公開されていて利用者もわんさか居る

ついでに私の立ち位置としては
* 情シス部門に所属していない現場作業者
* 「デジタルで職場を愉快にしたい」と公言している

さてと。
# 回避したい状況＝作者に無益な問い合わせが殺到して忙し殺される
利用者の不安も理解しますが、だからといって拡張機能作者に個別に「この拡張機能は6月以降も使えますか？」などとカジュアルに問い合わせをしていたら作者が忙殺されてしまいます。
これを避けたいので
* 自分で調べる方法を提供する（この記事）
* 問い合わせフォームを作って情報を集約する

この2本立てで行きます。

# １：使っている拡張機能を確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/78c45c70-84b8-0602-599f-1fbdcaa2487a.png)
ブラウザの右上、パズルのピースの様なアイコンを押すと、あなたがお使いの拡張機能が表示されます。スクショなりメモなりしておいてください。

# ２：拡張機能が保存されているフォルダを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/adc7053c-8a3a-2fee-6677-a1915835f3ae.png)
（この画像は個人環境なのでディレクトリ構成が異なります）
C:\ユーザー\ユーザ名\AppData\Local\Microsoft\Edge\User Data\Default\Extensions
に拡張機能ファイルが格納されています。
必要に応じて検索など駆使してExtensionsフォルダまでたどり着いてください。

# ３：manifest.jsonファイルを探す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/be3df228-1054-e7bd-5f43-aecd298152fc.png)
こんな感じでフォルダを掘り下げていくと出てくるはずです。（ファイルの場所は拡張機能によって異なります）
なお、png画像を開くとアイコンが確認できるので、これが何の拡張機能なのか、アイコンで当たりを付けるのも良い方法です。

# ４：メモ帳にドラッグ＆ドロップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851752/589d2954-10a6-e65f-7cc7-4d438234171b.png)
manifest.jsonの中身が見れます。［Ctrl-F］でmanifest_versionを検索すると一発で出てくるはずです。
（おまけ：大体その近所にnameがあり、拡張機能の名前が記載されていたりします。png画像もしくはnameでどの拡張機能のmanifest.jsonかを突き止め、１：のスクショやメモと照合してください。）
manifest_versionが”３”であれば、既に対応済みです。安心して便利な拡張機能を存分に使って楽をしてください。

# ５：manifest_versionが2だった時
まずは拡張機能にアップデートが無いか探して下さい。アップデートがあれば適用して、再度manifest_versionが3になっているかどうかを確認してください。
アップデートが無かったとしても、あわてて作者に連絡を取るのは一旦待ってください。2024年6月までは使えます。落ち着いて。
社内にSNSなどあって、どこかに質問できるチャネルがあれば、質問してみましょう。
* 既に情報を持っている人が回答してくれるかもしれません
* 同じ問題に行き当たっている人が居るかもしれません
* 作者、もしくはサポートチームが気づいて反応してくれるかもしれません

6月以降も使えないと困るのであれば、データを集めましょう。あなた個人のわがままではなく、拡張機能が無くてはならない大切なものであるとデータで示しましょう。ここで言うデータとはすなわち利用者数を指します。
もしかしたら同じ事を考えている人が、フォームなどで情報を集めているかもしれません。個人戦から団体戦に移行しましょう。個人で出来ることには限りがあります。
あなたの仕事が大変なのは理解しています。だからこそ、あなたの活動をオープンにして欲しいのです。
良い回答は良い質問が作ります。作者にメールする時間を使って、質問チャネルへの投稿をオススメします。

# 最後に
「デジタルで職場を愉快にする」という目標を私は勝手に掲げています。デジタルで便利にする、というのは職場が決めます。便利になったかどうか、効果は測定可能でなければなりません。それが組織です。
しかし、愉快かどうかは個人で決めます。人の数だけ愉快があります。なので私は「多くの人が愉快でない状況」が減らせるように活動しています。
普段はXやYoutubeで活動しています。たまにQiitaで真面目なことも書きますが、普段は行き当たりばったりに暮らしています。
https://twitter.com/1RRhcSB6HSUu9hF
https://youtube.com/@user-tq3vw1on2y?si=1hSiKCu2R3f29kIm
OpenAPIとは

# OpenAPIとは
OpenAPI（旧称Swagger）は、APIの設計、構築、ドキュメント化、およびテストを支援するためのフレームワークです。OpenAPIは、RESTful APIのための規格であり、APIのリソース、エンドポイント、リクエストおよびレスポンスの形式、認証方法などを定義するための仕様書を記述します。

OpenAPIは以下の主な機能を提供します：

1. **API仕様書の定義**: OpenAPIはAPIの仕様書を記述するためのJSONまたはYAML形式のファイルを提供します。この仕様書には、APIのエンドポイント、パラメータ、リクエストおよびレスポンスの形式、認証方法などが含まれます。

2. **自動生成されたドキュメント**: OpenAPI仕様書は、APIのドキュメントとして自動的に生成されます。これにより、開発者はAPIの使用方法を理解しやすくなります。

3. **クライアントコードの生成**: OpenAPI仕様書から、多くのプログラミング言語向けのクライアントコードを自動的に生成するツールがあります。これにより、開発者はAPIを使用するためのクライアントコードを手動で作成する手間を省くことができます。

4. **APIのテスト**: OpenAPI仕様書はAPIのテストのための優れた出発点となります。自動化されたテストツールは、仕様書に基づいてAPIの動作を検証し、エラーを特定します。

OpenAPIは、APIの設計から実装、テスト、ドキュメント化までのフルライフサイクルをサポートすることで、開発者やチームの生産性を向上させます。
【Laravel】GitHubのPush時にPHPUnitでテストする

# はじめに

こんにちは、プログラミングを始めて約3年のエンジニアのkeitaMaxです。

前回の記事

https://qiita.com/keitaMax/items/1d995293f383f66b29af

今回は前回作成したPHPUnitをGitHubActionsでGitHubにPull Requestを出した時に、テストできるようにしようと思います。

# GitHubActionsのymlファイルを作成

まずはGitHubActionsを作成します。

https://zenn.dev/naonao70/articles/44bc859c3ebc37

この記事を参考に作成しました。

`.github/workflows`フォルダの中に`phpunit.yml`を作成します。

```yaml:phpunit.yml
name: phpunit

on: [pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./src
    steps:
      - uses: actions/checkout@v2
      - name: docker-compose up
        run: |
          # docker-compose build
          docker-compose up -d
      - name: composer install
        run: |
          docker compose exec app composer install
      - name: Laravel Settings
        run: |
          docker-compose exec -T app cp .env.example .env
      - name: phpunit
        run: |
          docker compose exec app php artisan test
```


# GitにPushしてGitHubで実行する

これをGitHubにPushすると以下のように実行されます。

![スクリーンショット 2024-03-12 21.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/2d9cb0f0-9285-20fd-0c1e-b98c8372fd11.png)

そして処理が終わると、下のように全てにチェックがつきます。

![スクリーンショット 2024-03-12 21.56.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/9774720e-86ee-9e5f-aba1-2e457dab1680.png)

# 失敗させてみる

ちゃんと動いているかを確認するためにわざとPHPUnitのテストを失敗させてみます。
```php
$response->assertStatus(200);
```
このようなテストをもともと作成していたので、このコードを以下のように失敗するようにします。

```php
$response->assertStatus(404);
```

これでPushすると、以下のように失敗しているので、正しくテストが実行できていることが確認できました。

![スクリーンショット 2024-03-12 22.18.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/be548755-b17f-4d15-ca69-9495b5473e9b.png)

# 実装した時に困ってたこと

GitHubでPHPUnitを動かすのに、`.env`を作成しなくてはいけないことを忘れていて、PHPUnitを動かした時に困りました。

以下のようにGitHubActionsで`.env`を作成する処理を書いて解決しました。
```yaml
- name: Laravel Settings
run: |
  docker-compose exec -T app cp .env.example .env
```

以下の記事を参考にしました。
https://qiita.com/ucan-lab/items/237d2058eb46ab657ae3




# おわりに

GitHubActionsでDockerを立ててコマンドを実行するのが初めてだったので色々勉強になりました。

次回はPHPUnitでできることについて調べてみようと思います。

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！


# 参考文献

https://zenn.dev/naonao70/articles/44bc859c3ebc37

https://qiita.com/ucan-lab/items/237d2058eb46ab657ae3


# 次の記事
wslで、最小のカーネルをコンパイル その5

# 概要
wslで、kernel.elfのコンパイル、やってみた。
cで、書いたカーネルで、九九、fizzbuzz、zundoko、実行してみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4014604a-893e-95f8-7c93-a9e26215b9f3.png)

# サンプルコード

```
#include "kernel.h"

uint32 vga_index;
static uint32 next_line_index = 1;
uint8 g_fore_color = WHITE,
	g_back_color = BLUE;
int digit_ascii_codes[10] = {
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
};
uint16 vga_entry(unsigned char ch, uint8 fore_color, uint8 back_color) {
	uint16 ax = 0;
	uint8 ah = 0,
		al = 0;
	ah = back_color;
	ah <<= 4;
	ah |= fore_color;
	ax = ah;
	ax <<= 8;
	al = ch;
	ax |= al;
	return ax;
}
void clear_vga_buffer(uint16 ** buffer, uint8 fore_color, uint8 back_color) {
	uint32 i;
	for(i = 0; i < BUFSIZE; i++)
	{
		(* buffer) [i] = vga_entry(NULL, fore_color, back_color);
	}
	next_line_index = 1;
	vga_index = 0;
}
void init_vga(uint8 fore_color, uint8 back_color) {
	vga_buffer = (uint16 *) VGA_ADDRESS;
	clear_vga_buffer(&vga_buffer, fore_color, back_color);
	g_fore_color = fore_color;
	g_back_color = back_color;
}
void print_new_line() {
	if (next_line_index >= 55)
	{
		next_line_index = 0;
		clear_vga_buffer(&vga_buffer, g_fore_color, g_back_color);
	}
	vga_index = 80 * next_line_index;
	next_line_index++;
}
void print_char(char ch) {
	vga_buffer[vga_index] = vga_entry(ch, g_fore_color, g_back_color);
	vga_index++;
}
uint32 strlen(const char * str) {
	uint32 length = 0;
	while(str[length])
		length++;
	return length;
}
uint32 digit_count(int num) {
	uint32 count = 0;
	if (num == 0)
		return 1;
	while(num > 0)
	{
		count++;
		num = num / 10;
	}
	return count;
}
void itoa(int num, char * number) {
	int dgcount = digit_count(num);
	int index = dgcount - 1;
	char x;
	if (num == 0 && dgcount == 1)
	{
		number[0] = '0';
		number[1] = '\0';
	}
	else
	{
		while(num != 0)
		{
			x = num % 10;
			number[index] = x + '0';
			index--;
			num = num / 10;
		}
		number[dgcount] = '\0';
	}
}
void print_string(char * str) {
	uint32 index = 0;
	while(str[index])
	{
		print_char(str[index]);
		index++;
	}
}
void print_int(int num) {
	char str_num[digit_count(num) + 1];
	itoa(num, str_num);
	print_string(str_num);
}
static int randseed = 12345;
int rand(void) {
	return (randseed = randseed * 12345 + 17);
}
void kernel_entry() {
	int i,
		j,
		k;
	uint8 r = 243;
	init_vga(WHITE, BLACK);
	print_string("0 Hello World!");
	print_new_line();
	print_int(123456789);
	print_new_line();
	print_string("4 Goodbye World!");
	print_new_line();
	for (i = 1; i < 10; i++)
	{
		for (j = 1; j < 10; j++)
		{
			k = i * j;
			print_int(k);
			print_string(" ");
		}
		print_new_line();
	}
	for (i = 1; i < 101; i++)
	{
		if (i % 15 == 0)
		{
			print_string("FizzBuzz");
			print_new_line();
		}
		else if (i % 3 == 0)
		{
			print_string("Fizz ");
		}
		else if (i % 5 == 0)
		{
			print_string("Buzz ");
		}
		else
		{
			print_int(i);
			print_string(" ");
		}
	}
	i = 0;
	while (i < 4)
	{
		r = r * 5;
		r = r - 1;
		if (r < 127)
		{
			print_string("zun ");
			i++;
		}
		else
		{
			print_string("doko ");
			i = 0;
		}
	}
	print_string("doko kiyosi!!");
}





```


以上。
Amazon Verified Permissionsな世界とAmazon API Gateway

# はじめに

　AWS Verified AccessやAmazon Verified Permissionsって紛らわしいですよね。どっちがどっちだかわからなくなるところなのですが、今回は、[Amazon Verified Permissions](https://aws.amazon.com/jp/verified-permissions/)を使った認可制御についてのアーキテクチャを考えます。
　ゴールとしては、Amazon Verified Permissionsはどんなやつなのか理解する、です。


# Amazon Verified Permissionsとは
　[Amazon Verified Permissions](https://aws.amazon.com/jp/verified-permissions/)は、アプリケーションのアクセス許可の管理およびきめ細かな承認サービスです。制御については、ポリシー言語である [Cedar](https://www.cedarpolicy.com/en) を使用して、ロールと属性を使用してポリシーベースのアクセス制御を定義し、よりきめ細かくコンテキストに応じたアクセス制御を行うことができます。
　単純に認可だけするサービスです。

# 認可制御するとき
### よくあるアーキテクチャ（EC2）
　EC2でアプリケーションを起動していることを考えてみます。いろいろなフレームワークがありますが、認可制御するための情報は、例えば、設定ファイルでEC2に持っていたり、DBに持っていたりします。
 　リクエストがくる（/usersにgetなど）と、アプリケーションが認可制御するための情報を読み取り、アクセスを許可するか、拒否するかを判断し、制御を行います。
 　オンプレでもよくある構成ですが、システムそれぞれで設定する手間などがありますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129814/d561aa66-2c25-00b6-7407-d017876fd0c0.png)


### クラウドネイティブアーキテクチャ（API Gateway + Lambda）
　次にクラウドネイティブアーキテクチャについて考えてみます。認証はCognito、APIとしてAPI Gateway、Lambdaの構成を例にします。（API GatewayはLambda Authorizerパターンです。細かい説明は割愛します。）
 　よくあるアーキテクチャ（EC2）と同様に認可制御するための情報を設定ファイルやDBで持っていたりします。ハードコーディングもあるかも？！
 　Lambda（アプリケーション部分）で認可制御するための情報を読み取り、アクセスを許可するか、拒否するかを判断し、制御を行います。または、CognitoでIAMロールのクレデンシャルを払い出して、AWSリソースごとの制御も可能です。その場合、認可制御するための情報はCognitoに持つこととなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129814/6ffafa95-b28a-9106-7ca3-42c7d5bcd60b.png)


# Verified Permissionsの世界
### Verified Permissionsなクラウドネイティブアーキテクチャ（API Gateway + Lambda）
　では、次にVerified Permissionsを利用したクラウドネイティブアーキテクチャについて考えてみます。
 　認可制御は、Verified Permissionsが担います。リクエストがくる（/usersにgetなど）と、Lambda（Authorizer）がisAuthorizedまたはisAuthorizedWithTokenでVerified Permissionsにアクセスを許可するか、拒否するかを聞き、その結果でレスポンスを制御します。制御内容については、Verified Permissionsの設定になるため、変更があってもシステム側（アプリケーションなど）を修正する必要がありません。
 　 Verified Permissions側では、そのアクセスが誰からなのかを識別し、アクセスして良いかを[Cedar](https://www.cedarpolicy.com/en)を使って記述し、制御することになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129814/5cb07f4e-bd3b-e5e1-278b-2402469624aa.png)

　例えば、以下のような設定です。ユーザ「User001」でアクセスすると全て許可します、というポリシーになります。
 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129814/b4ae8696-24a0-4ae6-612a-6228d6a5be78.png)


### Verified Permissionsを使う時の注意点

:::note alert
isAuthorized、IsAuthorizedWithTokenは、1秒あたり200リクエストが上限なので超えそうな場合は、上限緩和申請をしましょう。
https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/quotas.html
:::

# まとめ
　Amazon API Gatewayを使ったアーキテクチャの際にAmazon Verified Permissionsをどう使うのかを見てみました。使うポイントは理解できたかと思うのですが、そのメリットはどこに？というところではないでしょうか。今回のようなアーキテクチャのシステムが複数あり、中央集権的にアクセスの承認を制御する場合に非常にメリットが生まれると個人的には思っています。単純に1つのシステムだけなら使うという選択は難しいかと思います。（コストもかかりますし、複雑でなければ他の機能で制御できちゃいますし。）
 　利用する際は、注意が必要ですね。次回はAppSyncでのAmazon Verified Permissionsな世界をもう少し踏み込んでみたいと思います。
wslでelixir その145

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。

# 練習問題
Livebookで、俺言語のzundokoを実行するインタープリターを書け。

# サンプルコード

```


defmodule Main3 do
    def src(n) do
        str = """
10 a=0
20 b=:rand.uniform(2)
30 #=b<2*80
40 ?="zun"
50 a=a+1
60 #=a>3*110
70 #=20
80 ?="doko"
90 a=0
100 #=20
110 ?="doko"
120 ?="kiyosi!!"
130 #=0
"""
      Enum.map(String.split(str, "\n", trim: true), fn l ->
		    s = String.split(l, " ")
		    cond do
		  	String.to_integer(Enum.at(s, 0)) == n ->
			  	l
			  true ->
				  nil
			  end
	    end)
    end
    def run(0) do
    end
    def run(pc) do
        m = src(pc)
        m = Enum.reject(m, fn(x) -> 
	        x == nil 
        end)
        Enum.map(m, fn l ->
          b = String.replace(l, "=", " ")
          s = String.split(b, " ")
          cond do
		      Enum.at(s, 1) == "?" ->
	    	    Sim2.print(Enum.at(s, 2))
		      Enum.at(s, 1) == "#" ->
		   	    Sim2.loop(Enum.at(s, 2))
		      Enum.at(s, 1) == "a" ->
			      Sim2.a(Enum.at(s, 2))
		      Enum.at(s, 1) == "b" ->
			      Sim2.b(Enum.at(s, 2))
		      true ->
			      IO.puts ""
		      end
		      cond do
		      Sim2.pc == 777 ->
		        run(pc + 10)
		      true ->
		        run(Sim2.pc)
		      end
    	end)
	end
end

Sim2.start_link
Main3.run(10)
```

# 実行結果

```
doko zun doko zun doko zun doko doko zun zun zun doko doko zun doko doko zun zun zun zun doko kiyosi!! 
```


以上。
Storybook が 8にアップデートされたので、その個人メモ

# Storybook 8のリリース

バージョンアップの報告は2024年3月13日に行われました。

# インストール

Storybook 8 を新規インストールするには、次のコマンドを実行します。

```terminal
npx storybook@latest init

```

既存の Storybook を Storybook 8 にアップグレードするには、次のコマンドを実行します。


```terminal
npx storybook@latest upgrade

```

Storybook 7 から Storybook 8 への移行ガイド
https://storybook.js.org/docs/migration-guide?ref=storybookblog.ghost.io

Storybookの移行(GitHub)
https://github.com/storybookjs/storybook/blob/4780ae31030197488d66b4fba483867f416bdb0a/MIGRATION.md?ref=storybookblog.ghost.io


# 主なアップデート

📸 ビルトインのビジュアルテスト
⚛ React Server Component のサポート
🎛 アップグレードされた Vue と React コントロールの自動生成
⚡ Vite サポート、Vitest テスト、Vite 5 サポート
🧪の再設計 テストビルド
✨が2〜4倍高速 デスクトップUI
📲の刷新 モバイルUX
🙅 ♀の再構築 非 React プロジェクトの React 依存関係を削除


Storybook 8は、テストとドキュメントの機能を大幅に改善し、React、Vue、Angular、web-components、Svelteなどのフレームワークの互換性とユーザーエクスペリエンスを強化しています。

* ビジュアルテストの追加: 新しいVisual Testsアドオンにより、UIのバグを以前よりも迅速かつ簡単に検出できます。ChromaticというビジュアルテストクラウドサービスがStorybookに初めて統合されました。

* React Server Componentのサポート: React Server Componentsは、コンポーネントがサーバー上でのみレンダリングされるReactの新しいパラダイムです。Storybook 8では、Next.jsとの互換性を持つ実験的なサポートが導入されました。

* フレームワーク固有の改善: React、Vue、Angular、Web Components、Svelteなど、さまざまなフレームワークに対する多くの改善が行われています。例えば、Reactには新しいdocgenライブラリが導入され、Vueには公式のVue docgenパッケージがサポートされています。また、Vite 5のサポートや、テストビルドの高速化なども含まれています。
React Storybook の起動時間が最大 50% 速くなりました。

* 2〜4倍高速なテストビルド
Storybook 8 では、Storybook の静的ビルドを 2-4 倍高速化する新しい「テストモード」が導入されました。

* モバイルとデスクトップのUIを更新
StorybookのモバイルUIを全面的に見直しました。これで、ナビゲーションサイドバーとアドオンパネルの両方がページの下部からポップアップし、電話の親指で簡単にトリガーできるようになりました。

* Chromaticの導入
これがデフォルトで導入された？この会社の業界標準になってからユーザーを取り込む戦略のようだ。

# Chromatic

無料版もあるが、 Chromatic は値段が非常に高い。



|プラン|価格|機能|
|:----|:----|:----|
|Essentials|無料|すべてのコンポーネント、アプリ、デザインシステムにフロントエンドインフラを提供します。|
|Starter|$149/月|テストとレビューを開始します。 Chrome 35,000 スナップショット カスタムドメイン 動的 IP アドレス + コア機能|
|Standard|$349/月|確立された UI を持つ経験豊富なチーム。 Chrome、Firefox、Safari、Edge 85,000 スナップショット カスタムドメイン 動的 IP アドレス + コア機能|
|Pro|$649/月|プロフェッショナルな高速度組織。 Chrome、Firefox、Safari、Edge 165,000 スナップショット カスタムドメイン 静的 IP アドレス利用可能 + コア機能|
|Enterprise|カスタム|卓越したチーム向けの産業グレードインフラ。 シングルサインオン カスタム Git 統合 優先サポート 請求書など Pro プランのすべて 追加スナップショット：0.006 ドル|


FREE
ストーリーブックの制限なし
共同制作者に上限なし
コンポーネントのバージョン管理
チーム向けの安全な CDN アクセス
5,000 件の無料スナップショット/月
Git と CI の統合
FREEはクレジットカードの登録は不要

自動テストで動かしていると、5000回/月では足りない可能性があります。

クロスブラウザテスト、アクセシビリティチェック、高度な視覚回帰ツールなどの高度な機能は、無料プランでは利用できません。

# メモ

日本語のマニュアルが欲しい。
JuliaでDeep Learningを理解する: 4.1 Composing networks

[Understanding Deep Learning](https://udlbook.github.io/udlbook/)の[ノートブック](https://github.com/udlbook/udlbook/blob/main/Notebooks/Chap04/4_1_Composing_Networks.ipynb)をJuliaで確認する。

# 4.1 Composing networks
１層のニューラルネットワークで何が起こっているかは[JuliaでDeep Learningを理解する: 3.1 Shallow neural networks I](https://qiita.com/dokudo9191/items/e3ce231fdb2ab36b5a98)で確認した。層を増やすと実際のところ何が起きるのだろうか？
以下のような２層のニューラルネットワークを考える。
![DeepConcatQuestion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/0f5415ab-8131-e274-0a8f-8afe3f687ecd.png)
(画像は[udlbook](https://github.com/udlbook/udlbook/tree/main/PDFFigures)より引用)
```julia
function shallow(x, activation_fn, phi, theta)
    pre = theta * [1; x]
    act = activation_fn.(pre)
    w_act = phi' .* [1; act]
    sum(w_act, dims=1)
end
ReLU(z) = ifelse(z < 0, zero(z), z)
n1_theta = [
    0.0 -1.0
    0 1.0
    -0.67 1.0
]
n1_phi = [
    1.0 -2.0 -3.0 9.3
]
n2_theta = [
    -0.6 -1.0
    0.2 1.0
    -0.5 1.0
]
n2_phi = [
    0.5 -1.0 -1.5 2.0
]
```
それぞれのネットワークがどのような関数か確認する。
```julia
using CairoMakie

x = -1:0.001:1
net1_out = first.(shallow.(x, ReLU, n1_phi |> Ref, n1_theta |> Ref))
net2_out = first.(shallow.(x, ReLU, n2_phi |> Ref, n2_theta |> Ref))
fig = Figure()
ax1 = Axis(fig[1, 1])
lines!(ax1, x, net1_out, label="n1")
lines!(ax1, x, net2_out, label="n2")
fig[1, 2] = Legend(fig, ax1)
```
![n1_n2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/32119685-a927-cf6f-de81-9b47008e3f42.png)

`net1_out`をネットワーク2の入力とすると
```julia
net12_out = first.(shallow.(net1_out, ReLU, n2_phi |> Ref, n2_theta |> Ref))
fig = Figure()
ax1 = Axis(fig[1, 1])
lines!(ax1, x, net1_out, label="n1")
lines!(ax1, x, net12_out, label="n12")
vlines!(ax1, [0, 0.67], color=:red, linestyle=:dot)
fig[1, 2] = Legend(fig, ax1)
```
![n12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2279125/5bac4b27-8d42-ab2b-0fb7-44ae4fefc27f.png)
これが層を増やすことにより起こることである。２層目の関数を１層目で作った領域数分、1層目の値に沿って繰り返している。
１層目で３分割し、２層目で４分割しているので、3x4=12分割されている。
１層のみで隠れユニットを6個にした時、分割数は7なので、効率よく分割できている。
1層のみの場合は、それぞれの領域で異なる線形関係にできるが、2層の場合は形が図のように制限されることになる。
制限がある分、表現力に劣るわけだが、この制限は正則化という形で精度に貢献することになる。
なぜニューラルネットワークを深くしたいかが何となく理解できたと思う。
development.csr 証明書の作成

# はじめに

パソコンを新しく乗り換えて、初めての証明書更新
毎年手順が覚えられないので、メモメモです


# 手順

ローカルPCの証明書を発行する。

![スクリーンショット 2024-03-13 1.06.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/4794427a-382b-e07d-5cc6-742ee712f04a.png)


![スクリーンショット 2024-03-13 1.07.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/f1219b20-18bf-fe6e-1167-9b100ac3f78b.png)


![スクリーンショット 2024-03-13 1.08.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/8d655642-b3e0-64cc-3670-1d0d625b2f3a.png)


CertificateSigningRequest.certSigningRequest
を生成させる。


下記のサイトにログイン
https://developer.apple.com/account/resources/certificates/list

![スクリーンショット 2024-03-13 1.09.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/9dd2fbe1-5e06-0517-333b-59197a78351b.png)


![スクリーンショット 2024-03-13 1.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/53996e6e-94a6-57dd-b529-1ce7048d159b.png)


![スクリーンショット 2024-03-13 1.10.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/9e516bb1-16c4-71c0-8743-02d0fd4a0928.png)

手順に従い、development.cerをダウンロード

ダウンロード後、development.cerをダブルクリックしてキーチェーンに登録



×マークのついた期限切れは、削除しても良い

![スクリーンショット 2024-03-13 1.11.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/8aae4a39-d858-ca0d-7801-9bbf43e82d1c.png)

以上で完了

# 簡単な説明

ローカルPCで証明書署名要求:CSR を作成し、developer.apple.comに渡す(CertificateSigningRequest.certSigningRequest)
これは、Appleに自分の開発者アカウントを確認して、アプリの署名に使用される証明書を発行するためです。

このCSRを用いて、development.cerが作成されるのでダウンロードします。

development.cerをインストールすることで、XcodeがAppleDeveloperProgramの資格を持つと認識し、アプリの署名や実機テスト等を許可しています。

# おわりに

流れを掴んでしてしまえば、理解が進みますね
Amazon EventBridge で毎月最初の平日に実行するルールを指定する（cron式）


cron 式というものを使ってAmazon EventBridge で
毎月最初の平日に実行するルールを指定する方法のメモです

具体的にはこれによって
商用環境は毎日起動しているが、テスト環境は土日起動していないので
月初が土日のときにテスト環境で失敗してしまう、というのを防げるはずです

# 結論

```
cron(0 1 1W * ? *)
```

# 詳細

## 1. そもそも Amazon EventBridge とは何か

ものすごくざっくりいうと
1. イベントが発生し、
1. そのイベントが定義したルールと一致する場合、
1. ターゲット に Amazon EventBridge イベントを送信する

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-what-is.html


今回だと
- イベント：日時
- ルール：cron 式
- ターゲット：任意

という感じです

## 2. cron 式とはなにか

そもそも cron とは：
- Unix系オペレーティングシステムのジョブ管理ツール
- 指定した日時または間隔でジョブを実行する

この日時を指定するのに使うのが cron 式[^1]


ひとことでcron式といっても、サービスごとに方言があるようです

例：
- 使用する文字数が違う
- 使用できる文字が違う
- 指定方法が違う（曜日が `0-6` なのか `1-7` なのか など）


[^1]: wikipedia は cron で間隔を指定するといっていたが、cron式で指定する方法は探せなかった（Amazon EventBridge だと rate 式というものを使って間隔を指定できる）

# Amazon EventBridge の cron 式

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-cron-expressions.html

```bash
*     *     *     *     *     *
-     -     -     -     -     -
|     |     |     |     |     |
|     |     |     |     |     +----- 年　  (1970-2199)
|     |     |     |     +----------- 曜日  (1 - 7 または SUN-SAT)
|     |     |     +----------------- 月　  (1 - 12 または JAN-DEC)
|     |     +----------------------- 日　  (1 - 31)
|     +----------------------------- 時間  (0 - 23)
+----------------------------------- 分　  (0 - 59)
```

cron 式の書き方は[こちら](https://zenn.dev/kisukeyas/articles/6d50c1d015d066)を参考にさせていただきました


- ６文字（６つのフィールド）が必須
- 数字と文字（ SUN など）以外にワイルドカードが使用できる
（フィールドによって違う）


## cron 式のワイルドカード（ Amazon EventBridge ）

詳細は上記のユーザーガイドを参照ください

- `-`：範囲を指定（使用できるフィールド：すべて）
- `*`：そのフィールドのすべての値を指定（使用できるフィールド：すべて）
- `?`：任意の値（使用できるフィールド：日・曜日）
- `L`：最終日を指定（使用できるフィールド：日・曜日）
- `W`：平日を指定（使用できるフィールド：日）


## 注意点

Amazon EventBridge において
cron 式で指定したスケジュールは **UTC+0** として解釈される

つまり、日本時間（ UTC+9 ）で実行したい場合
cron 式のスケジュールを +9 して考える必要がある

（サマータイムとかどうなってるんでしょうね？）

# 結論の cron 式はどういう意味か

```
cron(0 1 1W * ? *)
```

左から順に
- 分　：0　→　0 分
- 時間： 1　→　1 時
- 日　： 1W　→　月の 1 日目に最も近い平日
- 月　： *　→　毎月（ 1-12 ）
- 曜日： ?　→　任意の曜日
- 年　： *　→　毎年（ 1970-2199 ）

なので、
「 1970 年から 2199 年の間、毎月一番最初の平日の午前 1 時」
日本時間に直して
「 1970 年から 2199 年の間、毎月一番最初の平日の午前 10 時」

というのがこの cron 式で定義されているルールになります


# 考えたもの


```
cron(0 16 L * SUN-FRI *)
```

曜日が先に評価されるなら、これでも行けるのでは？と考えた式
意味として期待したのは
「 1970 年から 2199 年の間、毎月一番最後の日、曜日は日曜から金曜、時間は午後 4 時」
→ 「 1970 年から 2199 年の間、毎月一番最初の日、曜日は月曜から金曜、時間は午前 1 時」
と評価されてくれること

### 結論：エラーになる

公式ページの制約事項にまさに引っかかる書き方でした

> cron 式の日フィールドと曜日フィールドを同時に指定することはできません。一方のフィールドに値または * (アスタリスク) を指定する場合、もう一方のフィールドで ? (疑問符) を使用する必要があります。

- 曜日フィールドに SUN-FRI
- 日フィールドに L

はダメで、どちらかを ? にしないといけないようです
しかしどちらかを ? にしてしまうと、毎月月初というのが成り立たなくなるのでこれはダメな書き方です
Project:;COLD 謎の動画「顕現」の楽譜取得までのWriteup

# はじめに
この記事は 「現実と仮想が交錯する不可逆性SNSミステリー『Project:;COLD』(プロジェクトコールド)」で現在展開中の「アルター・カーニバル」の謎解き部分のネタバレを含みます。

現在物語が終盤へ向けて動いているところです。
今週末にまた展開が有りそうです。

今からでも遅くない！
https://www.project-cold.net/story/altarcarnival/ などをお読みいただき、
物語を追われることを推奨します。

# 謎の動画「顕現」について

ちょっと怖い雰囲気のある動画なので閲覧注意です。
https://www.youtube.com/watch?v=QNO1bx0rC80　

この動画に含まれる「字幕」と「バーコード」を解析することで謎の手がかりを得ることができる仕組みになっています。

## 字幕

字幕の方は
「。」は0、「゜」は1を示していそうなので、これをデコードすることで以下の文章を得ます


```python
binary_data_utf8 = "0100010001001101001000000110110101100101001000000111010001101000011001010010000000110001001100000010110101101100011001010111010001110100011001010111001000100000011000010110111001110011011101110110010101110010001000010000101001011111001111110101111100111111010111110101111101011111001011000010000000111111010111110011111100100000010111110101111100111111001111110011111101011111010111110010000000111111010111110010000001011111010111110011111100111111010111110101111101011111"
binary_bytes = int(binary_data_utf8, 2).to_bytes(len(binary_data_utf8) // 8, byteorder='big')
decoded_text_utf8 = binary_bytes.decode('utf-8')
decoded_text_utf8
# DM me the 10-letter answer!
# _?_?___, ?_? __???__ ?_ __??___
```

## バーコード
バーコードについては、動画をフレームごと書き出し、zbarimg(画像からバーコードがあれば読み取ってくれるコマンド)を利用してバーコードを読み取ります。

各バーコードは `1D13D1D13D1D1601D160` のような値が入っているので、
これを5文字ずつ区切ってunicodeとして解釈してデコードします。

この問題の答えの核がJupiterなのでそれにちなんでJupyter形式のgistを以下に記します。(ちなんでいるというのは冗談です)

https://gist.github.com/k-karen/806fe1eb6a1c394a69f8e12c482004e6

なお、これはGoogle Driveの `mymn/kengen/kengen.mp4` に当該動画をアップロードし、
`mymn/kengen/frames` へフレームを書き出すコードになっている点に注意してください。
(=もし再現のために実行するときは適宜そこら辺をreplaceしてくださいということ)

```
𝄽𝄽𝅘𝅥𝅮𝅘𝅥𝅮 𝄀𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅮 𝅘𝅥𝅮𝅭𝅘𝅥𝅯𝄀 𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥𝅘𝅥 𝄀𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥 𝅘𝅥𝄀𝅗𝅥𝅘𝅥𝅮 𝅘𝅥𝅮𝄀𝅘𝅥𝅘𝅥𝅮 𝅘𝅥𝅮𝅘𝅥𝅮𝅭𝅘𝅥𝅯 𝄀𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥 𝅘𝅥𝄀𝅘𝅥𝅮𝅘𝅥𝅮 𝅘𝅥𝅘𝅥𝄀𝅗𝅥 𝅘𝅥𝅮𝅘𝅥𝅮𝄀𝅘𝅥 𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅮𝄀 𝅘𝅥𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅮 𝄀𝅘𝅥𝅘𝅥𝅘𝅥𝅮 𝅘𝅥𝅮𝄀𝅗𝅥𝅘𝅥𝅮 𝅘𝅥𝅮𝄀𝅘𝅥𝅘𝅥 𝅘𝅥𝄀𝅘𝅥𝅘𝅥 𝅘𝅥𝄀𝅘𝅥𝅮𝅘𝅥𝅮 𝅘𝅥𝅘𝅥𝄀𝅗𝅥 𝅘𝅥𝅮𝅘𝅥𝅮𝄀𝅘𝅥 𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥𝅮𝅭 𝅘𝅥𝅯𝄀𝅘𝅥𝅮𝅘𝅥𝅮 𝅘𝅥𝅘𝅥𝄀𝅘𝅥𝅮 𝅘𝅥𝅮𝅘𝅥𝅘𝅥𝄀 𝅗𝅥𝅘𝅥𝅮𝅘𝅥𝅮𝄀 𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥𝅮 𝅭𝅘𝅥𝅯𝄀𝅘𝅥𝅮 𝅘𝅥𝅮𝅘𝅥𝅘𝅥𝄀 𝅘𝅥𝅮𝅘𝅥𝅮𝅘𝅥𝅘𝅥 𝄀𝅗𝅥𝅭𝄂
```

こうして以上のような結果を得ます。

これを「見る人が見る」事によって「『木星（原題：Jupiter, the Bringer of Jollity）』であることが判明
」し、字幕の情報と合わせることで得た文字列を並び替えることで「Guillotine」という答えを得られます。

# さいごに
実際はこれらが動画公開から1時間足らずで解かれており、
「なんかすげ～～！」と見てるだけで終わってしまったので、
時間に備えて、これらの手順を自分でも行えるようにと言うことでコードを書いてみました。

凄まじいスピードで解かれていく謎を見ているだけでも面白いコンテンツなので、
ぜひ物語の途中からでも楽しまれる方が増えてくれたら良いなと思います。

# 参考

こちらが今回の謎の公式解説になります
https://www.project-cold.net/story/story-41/
DynamoDB の KeyConditionExpression と FilterExpression で詰まった話

DynamoDB に触ったこともない人間が
KeyConditionExpression と FilterExpression の違いで詰まったのでメモとして残しておきます

# 結論

- KeyConditionExpression
    → パーティションキー or ソートキー の属性にのみ使用できる
- FilterExpression
    → パーティションキー or ソートキー でない属性（非キー属性）にのみ使用できる
- FilterExpression の方がだいぶいろいろできる

# 詳細

## 1. そもそも何に使うものか

KeyConditionExpression も FilterExpression も
DynamoDB のテーブル中から項目を検索する（ `Query` を投げる）ときに使います

厳密には
1. KeyConditionExpression を使用して、DynamoDBテーブルにクエリを投げる
1. 1 の結果に対して FilterExpression を適用し、結果を返す 

という流れのようです


詳細はこちら

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/APIReference/API_Query.html


## 2. ２つの違いはなにか

自分が理解している範囲で大きく３つあります

1. 使用できる属性の違い
1. 使用できる演算子の違い
1. 読み込みキャパシティー消費の有無


### 違い１：使用できる属性の違い
結論で述べたとおり

- KeyConditionExpression
    → パーティションキー or ソートキー の属性にのみ使用できる
- FilterExpression
    → パーティションキー or ソートキー でない属性（非キー属性）にのみ使用できる

### 違い２：使用できる演算子の違い

FilterExpression の方が大分幅広いです

#### KeyConditionExpression
ざっくり
- 等しいかどうか
- 大小関係
- 指定した範囲に収まるかどうか
- 特定の文字列から始まるかどうか

かつ、仕様できる演算子は属性につき１つです

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.KeyConditionExpressions.html


#### FilterExpression
KeyConditionExpression の演算子に加えて
- 指定したリスト内の値に含まれるか
- 指定した値でないかどうか

などいろいろできます

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.FilterExpression.html

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Syntax



### 違い３：読み込みキャパシティー消費の有無

DynamoDB の料金体系にかかわるのは
- キャパシティーユニット
- データストレージ（保存容量）
- データ転送
- その他オプション

https://qiita.com/Takayuki_Nakano/items/b1b383391a930dac43c7


読み込みキャパシティは 
DynamoDB に保存されているデータの大きさ（返す結果の大きさではなく）
をもとに消費されるらしく、

つまり DynamoDB からデータを引っ張ってこようとすると
KeyConditionExpression の有無にかかわらずキャパシティーを消費するようです


対して、FilterExpression の方は `Query` 完了後に適用されるので、
FilterExpression があってもなくても読み込みキャパシティーが消費されるということはないようです


#### ちなみに
では、KeyConditionExpression を設定せずに FilterExpression だけで何とかすればいいのでは？とも思ったのですが、
`Query` はパーティションキーの指定が必須らしいので FilterExpression だけというのは不可能のようです

https://www.yokoyan.net/entry/2018/07/18/181500


# 気になっている点
1. できるだけ KeyConditionExpression を使用し、FilterExpression は最小限
1. できるだけ KeyConditionExpression は使用せず、FilterExpression を多用

（それが可能なテーブル構造であるという前提）

この場合、
読み込みキャパシティ的には変わらない（つまり料金的には変わらない）様なのですが、
速度とかどうなんでしょうか？（次回の課題にします）
React Server Components と SSR の違いを理解する

# はじめに
一言で述べると`React Server Coponents`は**ハイドレーションが起きないコンポーネント**です。

`React Server Coponents` と `SSR` の違いを学ぶためには
`SSR`の土台となる`Pre-rendering`の知識が必要なので
`Pre-rendering` -> `SSR` -> `React Server Components` の順で説明します。

# Pre-rendering とは？
リクエストが飛んできた時に
1.サーバ側でコンポーネントを実行し、`HTML`を生成する
2.`HTML` + `クライアント側で実行する必要のあるJSファイル` をクライアント側に返す
3.まず、クライアント側では返された`HTML`が描画される。
4.その後に、少し遅れて`クライアント側で実行する必要のあるJSファイル`が実行されて、完璧なDOMとなる。
4番目の事をハイドレーションと呼びます。

**ここで大事なのはコンポーネントはサーバ側でHTMLを生成する時に実行されるし、クライアント側でハイドレーションされる時にも実行されるということです。**

**つまりサーバ側・クライアント側どちらでも実行されるということです。**

**さらにハイドレーションは`クライアント側で実行する必要のあるJSファイル`が存在しなくても発生します。**

# SSR とは？
`Pre-rendering`でコンポーネントが実行されるのは**サーバ側**と**クライアント側**どちらもですが、`SSR`や`SSG`というキーワードはサーバ側でコンポーネントが実行される時の話です。

* SSR -> **リクエストされた時に**サーバ側でコンポーネントを実行してHTMLを生成する。
* SSG -> **ビルド時に**サーバ側でコンポーネントを実行してHTMLを生成する。

# React Server Components とは？
サーバ側だけでコンポーネントを実行し、`HTML`を生成し返すコンポーネントのこと

**つまりクライアント側で実行されるJSファイルを返さずHTMLだけを返すということ**
**ようするにハイドレーションが起きません。**

# 違いは？
`SSR`はハイドレーションされることを前提として`Pre-rendering`時のサーバ側の挙動についてという意味を持ちますが、
`React Server Components`はそもそもハイドレーションされません。
名前が似ているので混乱しがちですが、そもそも土台が違う話です。
データベースの View と Materialized View の違いを説明できる？？

みなさんは、View と Materialized Viewの違いはご存知でしょうか。

私は、Viewといえば仮想的なテーブル？のイメージでいましたが具体的に何が違うのか理解できていなかったのでここにメモとして残したいと思います。

## View(ビュー)とは

まず、前提となるViewとはなんだったのかの確認からしていきましょう。

View(ビュー)とは、複数のテーブルからデータを取得し一時的に作成した仮想的なテーブルのこと

postgreSQLでは、以下のコマンドで実行できる。
```sql
-- Viewを作成する
CREATE VIEW ビュー名 AS SELECT文...;

-- Viewを削除する
DROP VIEW ビュー名;
```

- メリット
  - クエリをシンプルにできる
  - 容量を圧迫しない。
    - レコードは保存せずに使用するSELECT文を保存しているため。
- デメリット
  - パフォーマンスが劣化する可能性がある
    - データ量が多い場合や複雑なクエリの場合にはパフォーマンスが低下する可能性がある


## Materialized View(マテリアライズドビュー)とは

Materialized View(マテリアライズドビュー)とは、Viewと同じく複数のテーブルからテーブルを作成する。

ただし、仮想ではなく実体化されたビューであり実データを保持する。

postgreSQLでは、以下のコマンドで実行できる。
```sql
-- Materialized Viewを作成する
CREATE MATERIALIZED VIEW ビュー名 AS SELECT文...;

-- 最新のデータで作成する
REFRESH MATERIALIZED VIEW ビュー名;
```

- メリット
  - パフォーマンスが改善できる
    - 主キーやindexが定義できる
- デメリット
  - リフレッシュが必要
    - 仮想的なビューと違い使用している表のレコードと食い違ってくる
    - そのため、定期的なリフレッシュが必要
  - 普通のテーブル同様に容量を圧迫する



## まとめ

#### Viewの使い所

Viewは、最新のデータをリアルタイムで反映できますが、パフォーマンスが低下する可能性がある。
更新がおこなわれやすいテーブルや複雑なクエリを単純化したいときなどに適している。

#### Materialized Viewの使い所

Materialized Viewは、読み込みのパフォーマンスは速度が早くハイパフォーマンスが見込めるが、データの更新が多いテーブルには不向きである。
更新があまりおこなない、または最新のデータを必要としない場合やViewではパフォーマンスに問題がある場合などに適している。
【Go】ユニットテスト実行時、ログファイルのパスがズレるせいでFileNotFoundエラーになる

## 状況
- ファイルをログ出力に行う
- テストコードを書いている

## 問題
- VSCodeでユニットテストを行うとき、File Not Found エラーによりテストが実行できない

## 原因
- テスト時、作業ディレクトリがテストファイルの存在するディレクトリに移動してしまう
- このため、相対パスで記述したログファイルがNot Foundになってしまう

## 解決策
- テスト実行時はログファイルを使わないようにしよう

## 具体的に
- go runをする際、環境変数に起動モードのフラグを記述する
- さらに、本番モードで起動されたときはログファイルを起動しないようにする

## コード
- Bash
    ```makefile
        run:
        	MODE="prod" go run $(CMD)

        test:
        	MODE="test" go run $(CMD)
    ```

- ログファイルを扱うコード
    ```go
    	if os.Getenv("MODE") == "prod" {
        	file := os.OpenFile()
    		logrus.SetOutput(file)
    	} else {
    		logrus.SetLevel(logrus.DebugLevel)
    	}
    ```
到達保証（Delivery Guarantees）とは？

## はじめに
企業の応募要件で、到達保証について理解していることが必須条件としてあったのですが、初めて見た概念？でして、まとめてみました。
## 到達保証（Delivery Guarantees）とは？
メッセージ配信システムやデータストリーム処理で非常に重要な概念である。
到達保証には、「Exactly-Once（正確に一度）」、「At-Least-Once（少なくとも一度）」、「At-Most-Once（最大でも一度）」の3つのタイプがあります。
これらは、データの信頼性と整合性をどのように確保するかという問題に対する異なるアプローチを提供します。

### 正確に一度（Exactly-Once）
この保証タイプは、メッセージが正確に一度だけ受信されることを保証します。これは、重複やデータの損失なしに、データが正確に処理されることを意味します。例えば、銀行の取引システムではこのレベルの厳格さが求められます。ただし、この保証を実現することは技術的に最も難しく、システムのパフォーマンスに影響を与える可能性があります。

### 少なくとも一度（At-Least-Once）
メッセージが少なくとも一度は受信されることを保証します。これは、メッセージが失われることはないが、同じメッセージが複数回受信される可能性があることを意味します。システムは、重複したメッセージを適切に処理する能力が必要ですが、これによってデータの損失を避けることができます。多くの場合、バランスが取れた選択と見なされます。

### 最大でも一度（At-Most-Once）
メッセージが最大でも一度だけ受信されることを保証します。これにより、メッセージの重複受信は発生しませんが、メッセージの損失が発生する可能性があります。リアルタイムのデータストリーム処理や、メッセージの損失が許容されるシナリオで使用されます。パフォーマンスが優先される場合に適していますが、データ損失のリスクを考慮する必要があります。

### 終わりに
割と簡単な概念でした。バックエンドエンジニアには知っておくべき内容ではないかと思いました。まだまだ勉強不足なのがわかったいい機会でもありましたね。
最後まで読んでいただき、ありがとうございました！
A Tour of GoでExercise: rot13Readerをやってみた

Goの学習でA Tour of Goをさらっています。
Methods and interfacesの章で[Exercise: rot13Reader](https://go-tour-jp.appspot.com/methods/23)をやったのでメモです。

# 解答
https://go.dev/play/p/-rVIDII1EaL

# やったこと
やったことは下記です

1. 状況把握
1. Readメソッドの返り値とReadメソッド中で変換するための文字列を取得する
1. Readメソッド内でROT13の処理をする

## 1. 状況把握
"Lbh penpxrq gur pbqr!"をROT13という変換方法を利用して文字列変換したものを出力する。
初期状態として下記が与えられている。このまま実行するとrot13Readerにio.Reader(Readメソッド)がないと言われます。

```
package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r) // ここで標準出力するためにrot13ReaderにReadメソッドを追加する
}
```

## 2. Readメソッドの返り値とReadメソッド中で変換するための文字列を取得する
返り値の文字数、errorは、rot13Readerの構造体中のio.ReaderのReadメソッドの返り値をそのまま利用すればいい。
また、rot13Readerの構造体中のio.ReaderのReadメソッドを呼び出した際に、byte配列bに`Lbh penpxrq gur pbqr!`を入れてくれている。

```
func (r rot13Reader) Read(b []byte) (int, error) {
	n, err := r.r.Read(b) // ここで、rot13Readerの構造体中のio.Readerを利用し、返り値と文字列をゲットする
	if err != nil {
		return n, err　// n, errをそのまま返せる
	}
     ...
	return n, nil // nをそのまま返せる
}
```

## 3. Readメソッド内でROT13の処理をする
やり方は色々あると思いますが、
`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`を
`NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm`に変換できればok

大文字と小文字に分けて13個ローテーションさせました。

```
func (r rot13Reader) Read(b []byte) (int, error) {
	n, err := r.r.Read(b)
	if err != nil {
		return n, err
	}

    // bに入れていく
	for i := 0; i < len(b); i++ {
		if b[i] >= 'A' && b[i] <= 'Z' {
			b[i] = (b[i]-'A'+13)%26 + 'A' // 大文字の場合、13個ローテーションする
		} else if b[i] >= 'a' && b[i] <= 'z' {
			b[i] = (b[i]-'a'+13)%26 + 'a'　　// 小文字の場合、13個ローテーションする
		}
	}

	return n, nil
}
```
Google SlidesやGoogle Docsで入力内容を取得する

数時間が溶けてしまったので、自分用メモを兼ねて公開しておく。

# 問題点
ブックマークレット等、任意のWEBサイトにコードを流し込める状態で、ユーザが入力した文字を取得したい。Google Spreadsheetを含む多くのWEBサイトでは、以下のようなコードを流し込むと可能である。

```js:Google Slides 内
window.addEventListener("keydown", e=>{
    console.log(e.key+"を押した！");
});
```

しかし、Google Slides（Googleスライド）とGoogle Docs（Googleドキュメント）は、このコードでは思っている通り、動作しない。正確に言うと、上部にあるメニューの部分をクリックした後に入力したキーは取得できる。しかし、スライド内の文字を編集している時は、このイベントは発火しない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/d97c73a7-b345-7d5e-c48c-aedd81a92893.png)

# 解決方法
iframe内でkeydownイベントを処理しているため、そこに`addEventListener`をつけてあげる。

```js:Google Slides 内
document.getElementsByClassName("docs-texteventtarget-iframe")[0].contentDocument.addEventListener("keydown", e=>{
    console.log(e.code+"を押した！");
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/004996c1-14c9-2777-d9f4-19dc038b548e.png)

# 参考文献

https://stackoverflow.com/questions/4373666/capture-keypress-in-javascript-google-docs

https://docs.google.com/document/d/1RRBJqK9TPGFA5pQPnafDTa0VWKq6Wh9DNiKjsLaZ63U/edit?pli=1
今あるEPUB作成ソフトの問題点

## EPUB作成ソフト

　EPUBの問題はビュワーが対応しているか、どのビュワーでも同じ表示になるかが気になる。検索するといろいろなEPUB作成ソフトが見つかるが実際に使ってみると使いようがないものもある。検索すると出てくるものの問題点を挙げていきたい。
　
  「sigil、ibookauthor、kindlegen、indesign、Googleドキュメント、LeME、でんでんコンバーター、ロマンサー、暇つぶし雑記帳、一太郎、Pages」
  
+ sigilはEPUB編集ソフトであって作成ソフトではない
+ ibookauthorは７年前に終了してる
+ kindlegenは配布が終了している
+ indesignは対応するビュワーが少ない
+ Googleドキュメントはビュワーごとに表示が変わる
+ PagesのEPUBは対応するビュワーがApple Booksのみ

 「LeME、でんでんコンバーター、ロマンサー、暇つぶし雑記帳、一太郎」は出力されるEPUBに問題はないが、入力するファイルの種類が異なる、マークダウンと、WORD、専用の注記などエディターが異なっていてすべての機能が使えるわけではない。

 　ここでWORDといったのはdocxファイルであっても作られたソフトによって表示が変わる問題がある。
  docxファイルの問題点はテキストファイルと違いGithubなどで管理がしにくい。

## どのビュワーでも同じ表示になるEPUB
 　昔のウェブブラウザはブラウザごとに表示が異なっていて、同じ表示になるような苦労があった。EPUBも同じ問題を抱えていて、同じ表示にするには苦労がある。
  日本語の電子書籍ビュワーの表示は電書協EPUBに対応しているので、電書協の通りに作ると問題が少ない。ただしシェア的な問題で、kindleに対応するように書き換える必要がある。海外では、kindle以外にもApple Books、Google Play ブックスにも対応させる。
  そこで電書協をベースにしつつ、KADOKAWA-EPUBにも対応させながら、Kindle パブリッシング・ガイドライン、Apple Books アセットガイド、Google Play ブックス パートナー センター ヘルプ　EPUBを読んで制作する必要がある。
  

 
 改造版AozoraEpub3、FixedEpub3JSでは電書協EPUBのCSSを使ったepubを作成できる。

改造版AozoraEpub3

https://github.com/kyukyunyorituryo/AozoraEpub3/wiki

FixedEpub3JS

https://kyukyunyorituryo.github.io/FixedEpub3JS/

http://ebpaj.jp/counsel/guide

https://kadokawa-epub.bookwalker.co.jp/

https://kdp.amazon.co.jp/ja_JP/help/topic/GU72M65VRFPH43L6


 https://support.google.com/books/partner/answer/3316879?hl=ja&ref_topic=3238502&sjid=18384185215897497455-AP

 https://help.apple.com/itc/booksassetguide/ja.lproj/static.html
Lambda Node.js serverlessを使うほどでもないちょっとした関数を書きたいときのDocker環境を作ってみた

## 概要

Lambdaにて小規模なコードを記載したい場合にちょっと楽できるようなDocker環境を作ってみました。

## 発端

小規模な処理（例えばSESのバウンス情報をSNSからLambdaを経由してSlack通知したい場合）をLambdaで使いたい場合、下記のようなジレンマがある。
- Lambdaのブラウザのエディタで書くのはなんかテンションが上がらない、普段から慣れてるエディタを使いたい。。。
- serverlessだとリッチ過ぎる、学習コストもかかる。。。
- 慣れてるエディタで書こうとしてローカルPCのNode.jsを使って書くと、複数の開発者がいる場合バージョン合わせが大変。。。

Dockerならこの辺を一挙に解決できるのではと思い今回環境を作ってみました。

## 御託はいい、早くその環境をよこせ

もちろんどうぞ！
↓こちらから取得いただけます。完全にフリーで利用いただけます。おそらく利用方法はREADMEを呼んでいただければ大丈夫だと思います！

https://github.com/miriwo0104/nodejs_20_lambda_local_docker

小規模処理作成時によかったら使ってあげてください！
フォークしてもいいし、まるコピして修正入れていただいてもいいし、本当にどう使っていただいてもOKです。

## あとがき

きっとこれで、チーム無いで「あのLambdaは環境構築方法が不明だから触れない、、！」なんてこともなくなるはず、、！
ただ、serverlessとは違ってテストはできないのでzip化 → Lambdaにアップロード → Lambdaでテストを実行の手順を踏む必要はあります。
最近はGPTも便利なので、ここだけは腹くくってLambdaのテストで渡されるeventの中身を定義するしか無いかも、、！
自分は下記のように定義してLambda上でテスト実行を行いまくってます！

https://qiita.com/miriwo/items/b0bf854e0ae263f6d2d2
RaspberrypiでNASを作成する

# RaspberrypiでNAS作成
OpenMediaVaultを使うと簡単にNASを作成できるらしい・・・？

# 導入方法
## 1. まずRaspberrypiにOSを導入する
以下の画像のように設定をして，OSを導入する．
注意点としては，自分の使っているRaspberrypiの型を選ぶことと，OSをLITEを選ぶこと！
![スクリーンショット 2024-03-12 23.35.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256914/f6d4754c-4d63-7815-17bd-c49df15034cb.png)

## 2. Raspberrypiを有線接続する
下にある詰まったところにも記載をしているが，無線接続sshで実行を行なっていると途中でネットが切れる．ここで自分はダウンロードが失敗したのかと思い，何度かやり直しが発生した．

## 3. OpenMediaVaultをRaspに入れる
```
sudo -i
apt update
apt upgrade
wget -O - https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install | sudo bash
```
導入に結構時間がかかります．


# 詰まったところ
一番最初，RaspberrypiをWiFiで接続すると，OpenMediaVaultのダウンロード中にネットが切断され止まってしまいます．有線LANで行いましょう．
【Pino】levelを数値ではなく文字列にする方法

以下のように`logger.js`に記述することで`level`を数値ではなく'error'などの文字列で出力できます。

```js:logger.js
import pino from 'pino'

export const logger = pino({
  formatters: {
    level: (label: string) => {
      return {
        level: label,
      };
    },
  },
})

```
[Google Drive API v3] JavaでDriveのゴミ箱を空にする

Google Drive API v3（Java）を使用して、
Driveのゴミ箱を空にする方法
についてご紹介します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Drive API v3] JavaでDrive APIを使う](https://qiita.com/doran/items/15b2c59adb410ddeeb8a)
を参照ください。
:::

|No||目次|
|---|---|---|
|1||[ゴミ箱を空にする](#1-ゴミ箱を空にする)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|

## 1. ゴミ箱を空にする
Driveにあるゴミ箱を空にします。

### 1.1. スコープ
このAPIを実行するには、以下のスコープを指定してください。

DriveScopes.DRIVE

[⧉[Google Drive API v3] JavaでDrive APIを使う(2.2 Driveインスタンスを取得)](https://qiita.com/doran/items/15b2c59adb410ddeeb8a#22-driveインスタンスを取得)
でスコープを指定してください。

### 1.2. 実行

```
public static void main(String[] args) throws Exception{
    Drive drive = getDrive();
    Drive.Files files = drive.files();
    
    Drive.Files.EmptyTrash emptyTrash = files.emptyTrash();
    
    emptyTrash.execute();
}
```
#### 1.2.1. HTTPリクエスト
DELETE：　https:\//www.googleapis.com/drive/v3/files/trash
が実行されます。

#### 1.2.2. クエリパラメータ
Drive.Files.Deleteのsetメソッドにより、クエリパラメータを追加できます。

|メソッド|引数|説明|
|---|---|---|
|setDriveId|String|指定したドライブIDのゴミ箱を空にする|

#### 1.2.3. リクエストボディ
リクエストボディはありません。

### 1.3. レスポンスの内容

成功した場合は何も返しません。
失敗した場合は例外を出力します。

<br>
<br>
おしまい。。
ESMとは

# ESMとは

今まで、フロントエンドエンジニアにもかかわらず、`ESM` とはよく分からずに開発をしていたので、今回調べてみました。

### ESMについて

`ECMAScript` の仕様の一部で、JavaScriptにおけるモジュールシステム。

- JavaScriptファイルで別のJavaScriptファイルを読み込む仕組み
- `Common.js` の上位互換
- `Node.js` にも対応

---

**モジュール（例）**
~~~ JavaScript
// sample.js
const sample = () => {
 return 'test'
}

export {
 sample
}
~~~

**呼び出して使う（例）**
~~~ JavaScript
// index.js
import {sample} from './index.js'

const handleClick = () => {
 sample()
}
~~~

---

以上、`ESM` についてです。  
今後追加で分かったことがありましたら、更新していく予定です。  
**間違いなどございましたら、教えていただきたいです。**