OmniAICreator/Qiita-1.07M huggingface dataset:
BlazorとWebAssemblyを圧倒的に理解するための個人的なリンク集

## これはなに？

リンク集です。Blazorをやっていくべきことはわかった。WebAssemblyがとても面白い技術であることもわかった。ただ、生半可な理解では「WebAssemblyはJSより速い（ドヤ）」みたいな言い切りをしてしまいかねないほど、正確な理解が難しいものであることもわかった。

外野から眺めて満足するだけならまだしも、実際に当事者としてBlazorで開発をやっていくにあたってはそれでは困る。間違った認識からは間違った行動が生まれてしまうし、何より「知っている」ことが失敗を防ぎ改善策を生む原動力になるわけで、だったらいろいろ調べてできるだけ正確な理解を目指した方が結局は近道になる。

というわけで、自分の勉強のためにリンク集を構築していくことにする。

## WebAssemblyの技術解説

* [A cartoon intro to WebAssembly](https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/)
    * 2017年2月の記事。MozillaのRustおよびWebAssemblyの開発者Lin Clarkによる6つの連続記事。
    * JavascriptとJITの歴史、コンパイラとインタプリタの特徴、JSの行っている最適化手法とその限界、コンパイラとアセンブリとバイトコードと中間表現（IR）、.wasmへのコンパイルとJSからのロード、.wasmとスタックマシンの関係、JSとWebAssemblyの実行プロセスの比較、（2017年時点での）ブラウザ上でのWebAssembly実行の高速化や追加されていくだろう機能の展望、などなど盛りだくさん。
    * 2017年時点の記事なので、この当時想定されていたことがどれくらい実現され、まだ実現されていないのかを確認するのが良い。
* [WebAssemblyに注目](https://postd.cc/pay-attention-to-web-assembly/)
    * 2022年1月の記事の日本語翻訳。Yale大学のCS学部の学生Harshal Shethによる記事。
    * WebAssemblyについてコンパクトにまとめつつ、どのようなプロダクトに使われているか、使用例についても言及している。WebAssemblyが単にWEBフロントエンドで有効なだけでなく、仮想化やコンテナ技術に類する技術として発展するという予想や、パッケージマネージャなどが整っていないことなどから言語を超えた相互運用にまでは至っていない現状などについて言及している。
    * WebAssemblyには「高速で」「様々な言語からコンパイル可能で」「実行環境をブラウザに限定しない」という性質があり、想像以上に高いポテンシャルがあることを示している。もう数年経てば具体的なプロダクトとして世に出てくるだろう可能性が感じられ興味深い。

## Blazorと他のJSフレームワークの比較

* [【2023年版】Blazor vs React 比較 - どちらを選ぶべきか？](https://blogs.jp.infragistics.com/entry/Blazor-vs-react-2023)
* [【2023年版】Blazor vs Angular 比較 - どちらを選ぶべきか？](https://blogs.jp.infragistics.com/entry/blazor-vs-angular-2023)
    * 2023年2月の記事。BlazorとReact、BlazorとAngularをそれぞれを比較している。


## Blazorの技術解説

* [マイクロソフト、.NET中間言語をWebAssemblyにコンパイルする「Jiterpreter」をBlazor WebAssemblyに搭載へ、.NET 8で](https://www.publickey1.jp/blog/23/netwebassemblyjiterpreterblazor_webassemblynet_8.html)
    * 2023年4月の記事。
    * BlazorはWebAssemblyで.NETランタイムを実装し、その上でC#などの.NETバイナリを動かすか、AOTコンパイルによりWebAssemblyを生成するか、の2択だったが、.NETランタイムから「インタプリタのバイトコードを小さなWebAssemblyコードに置き換える」ことで最適化するJiterpreterという技術を.NET8から搭載する、という内容。
【Swift】UIDeviceを使った端末情報、バージョンの取得方法

# はじめに
お問い合わせメールを送信するとき、**端末情報**・**端末のバージョン**を自動で記入する機能を実装した。

この記事では、`UIDevice`を使った端末情報の取得処理を備忘録として記録。

# 実装
``` swift:ViewController.swift
let device = UIDevice.current
print(device.model)
// iPhone
print(device.systemVersion)
// 15.2.1
```

# プレビュー
上記の実装, [【Swift】アプリ内でメールを送信する](https://qiita.com/kasiwa/items/5253b90b0d8417ed68e9)を活用すると以下のようなお問い合わせメールを送信できる。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802393/09485d8a-5b88-a60c-406a-5005d1450eda.png">


# おわりに
端末、バージョンを自動で記入することで、ユーザーからのお問い合わせ対応が行いやすいメリットがある。

# 参考リンク
[UIDevice | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uidevice/)
【python】ハノイの塔の実装

# はじめに
ハノイの塔の実装コードです。

# 実装
```python:tower_of_hanoi.py
from typing import List, Tuple


def hanoi(disk: int, src: str, dest: str, support: str):
    if disk < 1:
        return

    hanoi(disk-1, src, support, dest)
    print(f'move {disk} from {src} to {dest}')
    hanoi(disk-1, support, dest, src)


def get_hanoi_movement(disk: int, src: str, dest: str, support: str) -> List[Tuple[int, str, str]]:
    result = []

    def _hanoi(disk: int, src: str, dest: str, support: str):
        if disk < 1:
            return

        _hanoi(disk-1, src, support, dest)
        result.append((disk, src, dest))
        _hanoi(disk-1, support, dest, src)

    _hanoi(disk, src, dest, support)
    return result


if __name__ == "__main__":
    hanoi(3, "A", "C", "B")
    for r in get_hanoi_movement(4, "A", "C", "B"):
        print(r)

```

# 参考
https://www.udemy.com/course/python-algo
tableauでのレーダーチャートの作成方法

レーダーチャートですが、Tableauでもつくることができるらしいです。ので、今回はTableauでレーダーチャートにトライしてみようと思います。


:arrow_forward:参考文献
https://qiita.com/MYS_moyashi/items/3564dd8d24832e2afaed
http://blog.livedoor.jp/tab_hiro/archives/16297700.html


:black_medium_square:多角形を用いた作成方法

・レーダーチャートで表したい指標は5つ、値の最大値は5、最小値は0であることを想定します。
・各項目においてxyの2次元上に座標点を取得する計算式を書く
　xはcosθ、yはsinθで表す(サイン、コサインで座標を表す)
　x = 指標の値 * cosθ 　　　y = 指標の値 * sinθ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/59127cad-ab2e-fae4-d015-a9bf7d841d26.png)


最初のKPI1 ⇛ π/2(cosπ/2 = 0 sinπ/2 = 1となります)
次のKPI2 ⇛ π/2 - 2π/5
次のKPI3 ⇛ π/2 - 4π/5
次のKPI4 ⇛ π/2 - 6π/5
次のKPI5 ⇛ π/2 - 8π/5
次のKPI1' ⇛ π/2 - 10π/5
のように続きます。


①データを用意(下記画像を参照、今回はカタールワールドカップで活躍した堂安選手のFIFAでの能力値を使用したいと思います。)
・エクセルでレーダーチャートで表したいデータ(選手名：堂安律)と
　レーダーチャートのグラフ(Avg、Avg-1,Avg-2,Avg+1,Avg+2)を用意します。

・レーダーチャートのグラフ(Avg、Avg-1,Avg-2,Avg+1,Avg+2)は「真」
　レーダーチャートで表したいデータ(選手名：堂安律)は「偽」となるようなカラムも用意
　※グラフの太さを変更する際に使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/c126735e-5c63-a1ef-fd39-a016360e1452.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/c3d71294-2af1-3c34-d560-200f4317d5ae.png)

②データが用意できたら、レーダーチャートを作成するのに必要なメジャーを作成します。
・index
INDEX()

・能力詳細_Counts_adj
今回は能力詳細の名前が6個(ペース'も含めて)あるので、-1する。
{FIXED:COUNTD([能力詳細])} - 1

・Radians：cos,sin でつかう角度
PI()/2 - 2*PI()/avg([能力詳細_Counts_adj])*([index]-1)

・X座標
sum([能力値])*COS([Radians])

・Y座標
sum([能力値])*SIN([Radians])

・能力値 for Label：KPIの値を表示するためのラベル
　//KPIの値を表示するためのラベルです。外枠であるAVG+2の場合はnullにします。
if
ATTR([Name]) = "AVG+2"  then null 
elseif LAST() != 0 then sum([能力値]) 
end

③Tableauで下記の図のように設定するとレーダーチャートが表示される。
　線の太さや色は「Line」と「Product」で調整します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/f5e591e9-863b-4f1e-5be0-c13655de2891.png)
③-1
列のX座標を右クリックし、次を使用して計算:能力詳細
行のY座標も同様に行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/016d6c3b-c28c-2c52-f541-2130c5821427.png)

③-2
列のX座標を右クリックし、軸の編集から、範囲を固定に変更。
開始値と終了値を設定する。今回はレーダーチャートの範囲がMAX100なので、-100~100とする。
Y座標も同じように変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/e52492a2-350c-53aa-74a3-450d05c2d91d.png)

③-3
マーク内のラベル「能力値 for Label」を選択し、次を使用して計算：能力詳細を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/f75db868-693b-20d9-e899-5e57727836a5.png)

③-4
マーク内のパス「能力詳細」を選択肢、並び替えから、
最初と最後の項目が同じになるように手動で並び替える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/32773b34-d618-1d7d-d8f0-4a177c50594a.png)

③-5
ペース'のラベルが重複して表示されてしまっているので、グラフ上のペース'の上で
右クリックし、マークラベル>表示しないを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/2f4d048c-57cf-d64b-af85-bd0c2af77cdd.png)

マークラベルを必要な個所のみ表示して完成です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119468/e83257f1-999d-5631-c910-ef8a4dd73fac.png)
SteamVR InputのOpen binding UIが開けない

# SteamVR InputのOpen binding UIが開けない

`SteamVR Input` の `Open binding UI` を開こうとしたら、 `ERR_CONNECTION_REFUSED` というエラーが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c6deab57-e6b5-f621-e0de-dc919a43d92c.png)

今回はこれを解決したので、忘れないうちにメモを残します。


# 調査編

まずは調べたことを記載します。
解決方法だけ知りたい方は、 [解決編](#解決編) まで飛ばしてください。

## SteamVRのバージョンを調べた

SteamVRのバージョンが古いのかと思い調べたところ、最新の `1.25.8` でした。
（2023年5月8日現在）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/a94be95f-4a4f-201e-a0e9-ef5eb11ad520.png)


## Open binding UIの出し方を調べた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/d0d55dcf-8278-1e89-39d8-7f4ad129ea07.png)

`Window > SteamVR Input` をクリックすると、以下のダイアログが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/0141f9d1-9263-84a8-80ef-6ccb9ffc4a55.png)

右下の `Open binding UI` をクリックすれば、ブラウザでバインド設定のページが開くはずです。
しかし、以下のようなエラーページが表示されてしまいます…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c6deab57-e6b5-f621-e0de-dc919a43d92c.png)

ブラウザのアドレス欄を確認すると、URLは http://localhost:8998/dashboard/controllerbinding.html となっていました。（クエリを除く）


## ポート番号を調べた

この http://localhost:8998 というのが、そもそも起動してなさそうな雰囲気です。

海外のサイトをいくつか調べたところ、以下のページを見つけました！

https://www.reddit.com/r/SteamVR/comments/dus70m/what_happened_to_the_steamvr_console/

ポート番号 `27062` を試そう！という記述があります。


# 解決編

## ポート番号を `27062` に変更したら開けた！

ためしに、ポート番号を `27062` に変更したら開けました！

http://localhost:27062/dashboard/controllerbinding.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/a3cabb7c-426d-d447-f1c7-d7e94f4d3fcc.png)

ポート番号を変更する作業はちょっと面倒ですが、当面はこの対応で乗り切ろうと思います！


# さいごに

本記事作成にあたり、以下の記事を参考にさせていただきました。ありがとうございました！

- [#8「VIVEトラッカー2018を有効化してUnity上で位置座標と回転を取得」【初心者】HTC VIVE Pro Eyeを使ってUnityでVRの開発を行ってみる．](https://qiita.com/RyoyaHase/items/015bbb8671833ef8e740)
- [What happened to the SteamVR console (localhost:8998/console/index.html)?](https://www.reddit.com/r/SteamVR/comments/dus70m/what_happened_to_the_steamvr_console/)
jsonで特定のキーがない、または余分にあるレコードをスキーマ指定してGlue（Sparkジョブ）で読み込んだ時の挙動

## はじめに
Glueでjsonをロードしたいことはよくあると思います。
その時、jsonのレコードが全て同じキーで揃っていることが理想です。
ただ、実際のデータは想像よりも汚いものです。キーが揃っていない時、スキーマを指定してGlueでロードするとどうなるかを検証します。

## 知りたいこと
GlueでSparkのDataFrame（DynamicFrameではない）として、スキーマを指定してjsonをロードした時、そのjsonが以下の時の挙動を確認します。
① 特定のキーがないレコードが含まれる
② 余計なキーがあるレコードが含まれる

## 前提条件
- Glue version: 3.0
- Spark version: 3.1.1
- jsonファイルはS3に格納
- name, price, countの3つのカラムを持つスキーマを指定してロード
- DynamicFrameではなくSparkのDataFrameとしてロード

## 結論
jsonで特定のキーがないレコードは、そのキーが**nullとして読み込まれる**。
余分に特定のキーがあるレコードは、そのキーが**読み込まれず**指定されたスキーマのデータだけがロードされる。

## 実験内容
### 理想のjson
4つのレコードに、name, price, countのキーが含まれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/bc6ac600-7e91-7796-0a04-2e4fc37ead3f.png)

これを3つのカラムを指定して読み込んだところ、想定通り3つのカラムで4つのレコードが読み込まれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/cc69c498-37c5-bbc2-a7c3-c9b8f270be47.png)

### ①（特定のキーがないレコードが含まれる）のjson
4レコード目のcountのキーがない状態です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/17614e0a-5b18-9bb4-08c0-5658c0cc24c9.png)

これを3つのカラムを指定して読み込んだところ、4レコード目のcountは**nullとして**読み込まれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/4bb49d42-309e-ec7c-7ef5-983181f1e7fe.png)

### ②（余計なキーがあるレコードが含まれる）のjson
3レコード目にupdate_dateという余計なキーが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/95c903ef-6208-e3b3-8e51-31aa81a1d4c7.png)

これを3つのカラムを指定して読み込んだところ、3レコード目のupdate_dateというキーは読み込まれませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/603c1325-3f29-9506-30da-313ddeb85f3f.png)

## 追加実験
①（特定のキーがないレコードが含まれる）のとき、スキーマの指定では"count"のnullable = Trueとoptionで指定していました。つまり、nullを許容する状態でした。
これをFalseと指定してみましたが、結局スキーマとしてはnullable = trueの状態でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/427a991d-8d05-6fa3-d27b-e723eda0842f.png)

スキーマでnullableをFalseと指定しても、結局内部的にはtrueになってしまうので、スキーマを補正しないといけないようです。

https://tech-blog.tsukaby.com/archives/1333

## おわりに
このあたりのスキーマに関するところは、Sparkを使うときに型の指定とともに悩まされるポイントですね。
これに関しては、Glueのデータカタログ + DynamicFrameで扱う方がやりやすそうだなと感じました。
SparkのDataFrameの処理を使いたい場合も、
DynamicFrameでデータカタログからロード ⇒　SparkのDataFrameで処理 ⇒ DynamicFrameでデータカタログに書き込み
という変換が可能です。
ただ、どうしてもSparkのDataFrameとしてロードさせたい（Choice型を最初から持ちたくない、など）場合は今回のようにスキーマを指定してあげたほうが無難そうです。

## 参考
実行したコードを以下に記載しておきます。
実験では、以下のコードのロードのパスを変えているだけです。
```python
from pyspark.sql.types import *

schema = StructType([
      StructField("name",StringType(),True),
      StructField("price",IntegerType(),True),
      StructField("count",IntegerType(),True)
])

df_with_schema = spark.read.schema(schema).json("s3://sample-bucket/correct/")
df_with_schema.show()
```
【SwiftUI】アクセシビリティで「ボタンの形」がオンになっているかを判定する

# はじめに
アクセシビリティで「ボタンの形」がオンになっているかを判定します。

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @Environment(\.accessibilityShowButtonShapes) var accessibilityShowButtonShapes
    var body: some View {
        Text(accessibilityShowButtonShapes ? "「ボタンの形」がオンです" : "「ボタンの形」がオフです")
    }
}
```

# おわり
アクセシビリティでUIが変わることがあるのできちんと把握しておきたいです。
時間経過で変化するアニメーションをTimelineViewとCanvasでつくる

![画面収録_2023-05-08_22_34_09_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648522/c44c719f-beee-38ec-f2cf-86974ffd8cfe.gif)

Figmaとかでそれっぽい形のSVGを作って、[このサイトとか](https://svg-to-swiftui.quassum.com/)でSwiftUIのパスに変換する。
あとは時間で増減する値を`TimeLineView`で作って各ポイントを動かしたり、`rotationEffect`で動かしたり、グラデーションをつけたりすれば完成。

```swift
struct BlobView: View {
    @State var appear = false
    
    var body: some View {
        TimelineView(.animation) { timeline in
            let now = timeline.date.timeIntervalSinceReferenceDate
            let angle = Angle.degrees(now.remainder(dividingBy: 3) * 60)
            let x = cos(angle.radians)
            let angle2 = Angle.degrees(now.remainder(dividingBy: 6) * 10)
            let x2 = cos(angle2.radians)
            
            Canvas { context, size in
                context.fill(
                    path(in: CGRect(x: 0, y: 0, width: size.width, height: size.height), x: x, x2: x2),
                    with: .linearGradient(
                        Gradient(colors: [.pink, .blue]),
                        startPoint: CGPoint(x: 0, y: 0),
                        endPoint: CGPoint(x: 400, y: 400)
                    )
                )
            }
            .frame(width: 400, height: 414)
            .rotationEffect(.degrees(appear ? 360 : 30))
        }
        .onAppear {
            withAnimation(.linear(duration: 10).repeatForever(autoreverses: true)) {
                appear = true
            }
        }
    }
    
    func path(in rect: CGRect, x: Double, x2: Double) -> Path {
        var path = Path()
        let width = rect.size.width
        let height = rect.size.height
        path.move(to: CGPoint(x: 0.9923*width, y: 0.42593*height))
        path.addCurve(to: CGPoint(x: 0.6355*width*x2, y: height), control1: CGPoint(x: 0.92554*width*x2, y: 0.77749*height*x2), control2: CGPoint(x: 0.91864*width*x2, y: height))
        path.addCurve(to: CGPoint(x: 0.08995*width, y: 0.60171*height), control1: CGPoint(x: 0.35237*width*x, y: height), control2: CGPoint(x: 0.2695*width, y: 0.77304*height))
        path.addCurve(to: CGPoint(x: 0.34086*width, y: 0.06324*height*x), control1: CGPoint(x: -0.0896*width, y: 0.43038*height), control2: CGPoint(x: 0.00248*width, y: 0.23012*height*x))
        path.addCurve(to: CGPoint(x: 0.9923*width, y: 0.42593*height), control1: CGPoint(x: 0.67924*width, y: -0.10364*height*x), control2: CGPoint(x: 1.05906*width, y: 0.07436*height*x2))
        path.closeSubpath()
        return path
    }
```
kernel moduleのMakefileでプリプロセッサを機能させる

初心者の備忘録
環境:
  raspberry pi 2B (kernel 6.1.21-v7+)

## 問題
[組み込みLinuxデバイスドライバの作り方 (2)](https://qiita.com/iwatake2222/items/580ec7db2e88beeac3de)を参考にデバイスドライバを勉強しているなか、ふとMakefileでプリプロセッサを機能させる方法を見かけたので試した。
```Makefile
make -C /lib/modules/$(shell uname -r)/build CFLAGS="-DDEBUG" M=$(shell pwd) modules
```

```myDeviceDriver.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/current.h>
#include <asm/uaccess.h>

#define DRIVER_NAME "MyDevice_NAME"
#define DRIVER_MAJOR 63

static int myDevice_open(struct inode *inode, struct file *file) {
	printk("mydevice_open\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	return 0;
}

static int myDevice_close(struct inode *inode, struct file *file) {
	printk("mydevice_close\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	return 0;
}

static ssize_t myDevice_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos) {
	printk("mydevice_read\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	buf[0] = 'A';
	return 1;
}

static ssize_t myDevice_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos) {
	printk("mydevice_write\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	return 1;
}

struct file_operations s_myDevice_fops = {
	.open = myDevice_open,
	.release = myDevice_close,
	.read = myDevice_read,
	.write = myDevice_write,
};


static int myDevice_init(void) {
	printk("mydevice_init\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	register_chrdev(DRIVER_MAJOR, DRIVER_NAME, &s_myDevice_fops);
	return 0;
}

static void myDevice_exit(void) {
	printk("myDevice_exit\n");
#ifdef DEBUG 
	printk("DEBUG\n");
#endif
	unregister_chrdev(DRIVER_MAJOR, DRIVER_NAME);
}

module_init(myDevice_init);
module_exit(myDevice_exit);
MODULE_LICENSE("GPL2");
```

しかし、下記のようにプリプロセッサが効かなかった。
どうもCFLAGSではだめらしい。
```
insmod MyDeviceModule.ko
dmesg
-> mydevice_init
```

## 結論
KernelのMakefileには```ccflags-y, asflags-y, ldflags-y```を使用すればよい（それぞれcc, as, ld用）
昔はEXTRA_CFLAGS, EXTRA_AFLAGS, EXTRA_LDFLAGSだったが現在は非推奨とのこと。
参考:
[Linux Kernel Makefiles](https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt)
[LinuxカーネルのMakefileを解析する その7](http://masahir0y.blogspot.com/2012/06/linuxmakefile-7.html)
[How to set preprocessor directives in makefile for kernel module build target?](https://stackoverflow.com/questions/54118602/how-to-set-preprocessor-directives-in-makefile-for-kernel-module-build-target)
例: DEBUGを定義する
```Makefile
make -C /lib/modules/$(shell uname -r)/build ccflags-y="-DDEBUG" M=$(shell pwd) modules
```

但し、そのまま使うとMakefile内の同一変数の値を上書きする可能性があるため、下記のようにして回避するといいらしい。
```Makefile
ccflags-y += $(FOO_CFLAGS)

debug:
    make -C /lib/modules/$(shell uname -r)/build FOO_CFLAGS="-DDEBUG" M=$(shell pwd) modules
```

## 感想
普通のMakefileとKernel用のMakefileでフラグの作り方が違うことを知って勉強になった。
なんでCFLAGS相当がccflags-yなんだろう?という点が気になった。
HTML5 プロフェッショナル認定試験レベル1　勉強記録-2

Webの基礎知識
（ヘッダフィールド、メッセージボディ）


○HTTPリクエスト
**`ブラウザからWebサーバに対する要求`**
★用いられるメッセージは使用で構造が決められている
★メッセージ構造は、HTTPレスポンスと同じものになる
`メッセージ構造`
①開始行　②HTTPヘッダ　③空行　④メッセージボディ
①開始行：
　・リクエスト先のURL
　・HTTPのリクエストメソッド
　・HTTPのバージョン
②HTTPヘッダ
　・ヘッダ名
　・：（コロン）
　・値
→ Content-Type「ヘッダ名」  :「コロン」   text/plain「値」
★Accept-Languageヘッダフィールド
・HTTPヘッダの一つ
・ブラウザが受け入れ可能な自然言語（日本語や英語等）を指定する
※JavaScriptのようなプログラミング言語は指定できない

※HTTPヘッダフィールドの種類は要検索

④メッセージボディ（リクエストボディ・レスポンスボディ）
`ブラウザ・Webサーバ間で送受信するデータ`
★POSTメソッドでブラウザからWebサーバにデータを送信
→ データはメッセージボディ（リクエストボディ）に含む
★GETメソッドでリクエスト
→ メッセージボディ（リクエストボディ）は空になる

○Acceptヘッダフィールド
**`MIMEタイプでブラウザが受け入れられるコンテンツタイプを指定`**
★JSON形式のMIMEタイプはapplication/json
→下記３項目は誤り
　text/html=HTMLファイル
　text/plain=テキストファイルの規定値
　application/javascript=javascriptを示す 
→text/jsonは存在しない

○ステータスコード404
**`リソースが見つからない事をすめすコード`**

○URL
**`ネットワーク上のリソースを一意に識別するための記述規約`**
★記述規約
スキーマ://ホスト名:ポート番号/ディレクトリ/ファイル名
★URLのうち、「スキーマ://ホスト名:ポート番号」→オリジンと呼ぶ
★同一オリジンポリシー
→異なるオリジンのリソースにアクセスできないようにする制限

○HTTPS
**`安全にHTTP通信を行うプロトコル`**
★HTTPとの違い
HTTPは平文で通信する。
HTTPSは、SSL/TLSで暗号化して通信をする
※暗号化には、認証局（CA）が発行する証明書が必要
★暗号化のメリット
なりすましや盗聴を防ぐことができる
★暗号化と復号が伴うため、HTTP通信と比べると、
クライアントとWebサーバ側の負荷が高まる。

○HTTPで定義されているリクエストメソッド
★「GET」「PUT」「CONNECT」
※UPDATE、DROPは定義されていない

○キャッシュ
**`Webサーバから取得したリソースを保存する技術`**
★リソースのリクエストをした際に、キャッシュが保存されていると、
サーバではなく、近くのキャッシュからリソースを取得する
◇メリット：・通信のパフォーマンス向上　・Webサーバの負荷低減
◇デメリット：リソースの更新が反映されない（ユーザに適切なリソースを返せない）
※そのため、キャッシュの長時間保存は薦めない

**`キャッシュを制御するヘッダフィールドの一例`**
★Cache-Control★
→キャッシュのコントロールを行う
：no-store（ブラウザ、Webサーバでキャッシュが保存されない）
：max-age=60（キャッシュの有効期限を秒単位で指定できる）
★Expires★
→レスポンスの有効期限を指定
：Fri, 28 Oct 2022 08:00:00 GMT（日付形式で指定）
※コントロールフィールドで指定されている場合、無視される
★Age★
→プロキシサーバにキャッシュする期限を指定する
※キャッシュ期限は秒数で指定
：10

○リダイレクト
**`指定したWebページから別のWebページに転送されること`**
★リダイレクトの指定方法
「OK」
・JavaScriptで指定
・<meta>タグで指定
・Locationヘッダフィールドで指定

「NG」
・<Link>タグで指定
→CSSの参照に使うタグのためNG
・Refererヘッダフィールドで指定
→ブラウザが閲覧していた前のURLを示す為NG
Tkinterで透明なウィンドウを作り、クリックは背後のウィンドウに流さない

こういうもの。ひとまずWindows限定です。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Tkinterで透明かつ背後のウィンドウにクリックイベントが流れないウィンドウを作って座標を取るの、意外とたいへんでした。 <a href="https://t.co/4VBtPKRt9g">pic.twitter.com/4VBtPKRt9g</a></p>&mdash; メイユール (@u1F992) <a href="https://twitter.com/u1F992/status/1655556961419825152?ref_src=twsrc%5Etfw">May 8, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 透明なウィンドウを作る

`tk.Tk#wm_attributes`で`-transparentcolor`を設定し、ウィンドウ上の特定の色を透明にすることができます。近い色も透過してくれるような器用なものではなくて、完全一致した色だけを抜きます。全面を指定した色のtk.Frameで覆うことで、ウィンドウ枠だけを表示して背後のアプリケーションに重ねること自体は簡単にできます。

```python
import tkinter as tk


root = tk.Tk()
root.geometry("640x480")

root.wm_attributes("-transparentcolor", "white")
tk.Frame(root, background="white").pack(expand=True, fill=tk.BOTH)

root.mainloop()
```

https://qiita.com/zero-en/items/75e0c4dca646838da2d1

しかし、試せばわかるように、この方法ではウィンドウ内をクリックするとその操作は背後のウィンドウに流れてフォーカスも外れてしまいます。まるでウィンドウに穴が開いてしまったようです。これでは、背後のアプリケーションに重ねて表示させてクリックした座標で何らかの操作をするような用途には使用できません。

## 透明なウィンドウで穴を埋める

見えないウィンドウを重ねて表示することで、この穴を埋めることを考えます。

```python
import tkinter as tk


root = tk.Tk()
root.geometry("640x480")

root.wm_attributes("-transparentcolor", "white")
tk.Frame(root, background="white").pack(expand=True, fill=tk.BOTH)

filler = tk.Toplevel(root)     # 別ウィンドウを作成
filler.overrideredirect(True)  # ウィンドウ枠を削除
filler.transient(root)         # タスクバーから消す
filler.wm_attributes("-alpha", 0.0019607843138)  # ウィンドウを透明にする。0にすると完全に透明になるが、クリックが背後に流れてしまう。

# 変更されるたびにサイズと位置をrootに合わせて、rootの背後に置く
def on_configure_let_filler_track(_):
    filler.geometry(f"{root.winfo_width()}x{root.winfo_height()}+{root.winfo_rootx()}+{root.winfo_rooty()}")
    filler.lower(root)

root.bind("<Configure>", on_configure_let_filler_track)

root.mainloop()
```

透明度を操作する`-alpha`ではウィンドウ枠ごと透過してしまうので希望する用途には適していませんが、穴を埋めるためにウィンドウ枠を消した状態で使用しています。試しに`filler.overrideredirect(False)` `filler.wm_attributes("-alpha", 0.5)`などとすれば、何をしているのかがわかりやすくなるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1550728/8530a8a7-422e-d424-a038-2ebb775c4f15.png)

タイトルバー以外の箇所でリサイズができなくなるのは仕様です。また、rootではなくfillerにクリック時のコールバック関数をバインドする必要があることに注意してください。
[AWS Q&A 365][EKS]AWSのよくある問題の毎日5選 #50

# 1. Amazon EKSのセキュリティ・ベストプラクティスは何ですか？
答え：Amazon EKSのセキュリティ・ベストプラクティスには、ポッドセキュリティポリシーの実装、サービスアカウント用のIAMロールの使用、およびVPCとサブネット要件の適切な設定が含まれます。

# 2. Amazon EKSのデフォルトのポッドセキュリティポリシーは何ですか？
答え：Amazon EKSのデフォルトのポッドセキュリティポリシーは、Amazon EKSデフォルトのポッドセキュリティポリシーです。

# 3. Amazon EKSのロギングをどのように設定できますか？
答え：Amazon EKSのロギングは、コントロールプレーンログの有効化と無効化、およびクラスターコントロールプレーンログの表示によって設定できます。

# 4. Amazon EKSコネクターの検討事項に関するAWSの責任は何ですか？
答え：Amazon EKSコネクターの検討事項に関するAWSの責任には、Amazon EKSコネクターサービスの管理とセキュリティ、およびその可用性の維持が含まれます。

# 5. Amazon EKSコネクターの検討事項に関する顧客の責任は何ですか？
答え：Amazon EKSコネクターの検討事項に関する顧客の責任には、Kubernetesクラスターの設定と管理、およびKubernetes APIサーバーのセキュリティが含まれます。
【Git】どのファイルでignoreされているか確認する方法


## 確認方法

ignoreされているファイルがどこでignoreされているのか確認するには次のコマンドを実行します。  

```terminal
git check-ignore -v ファイルパス
```

```terminal
$ tree
.
├── .git
│   ├── info
│   │   └── exclude
│ 
├── .gitignore
├── example.txt
├── sample.txt
└── test.txt

$ cat .gitignore
/sample.txt

$ cat .git/info/exclude
/example.txt

$ cat ~/.config/git/ignore
/test.txt

$ git check-ignore -v *
.git/info/exclude:1:/example.txt        example.txt
.gitignore:1:/sample.txt        sample.txt
/Users/Username/.config/git/ignore:1:/test.txt     test.txt

```

以上のようにignoreの設定がされているファイルと行数が表示されます。
[AWS Q&A 365][EKS]Daily Five Common Questions #50

# 1. What are some security best practices for Amazon EKS? 
Answer: Some security best practices for Amazon EKS include implementing pod security policies, using IAM roles for service accounts, and configuring VPC and subnet requirements properly. 

# 2. What is the default pod security policy for Amazon EKS? 
Answer: The default pod security policy for Amazon EKS is the Amazon EKS default pod security policy. 

# 3. How can I configure logging for Amazon EKS? 
Answer: Logging for Amazon EKS can be configured by enabling and disabling control plane logs and viewing cluster control plane logs. 

# 4. What are some AWS responsibilities for Amazon EKS Connector considerations? 
Answer: Some AWS responsibilities for Amazon EKS Connector considerations include managing and securing the Amazon EKS Connector service and maintaining its availability. 

# 5. What are some customer responsibilities for Amazon EKS Connector considerations? 
Answer: Some customer responsibilities for Amazon EKS Connector considerations include configuring and managing the Kubernetes cluster and securing the Kubernetes API server.
ECS vs. EKS vs. Fargate

# AWSのサービス比較：ECS vs. EKS vs. Fargate

AWSは、さまざまなクラウドサービスを提供しています。コンテナオーケストレーションに関連するサービスは、ECS、EKS、およびFargateです。これらのサービスを比較しましょう。

## ECS (Elastic Container Service)

- AWSが提供するマネージドコンテナオーケストレーションサービスの1つで、コンテナを実行するためのクラスターを構築することができる。
- Dockerコンテナと互換性があり、Amazon EC2上で実行される。最大利用可能数は10000である。
- ECSは、Fargateを使用することもでき、使用する場合、ユーザーはコンテナが実行されるサーバーを選択する必要がない。

## EKS (Elastic Kubernetes Service)

- AWSが提供するマネージドKubernetesサービスで、オーケストレーションツールであるKubernetesを使ってDockerコンテナを管理することができる。
- Kubernetesは、AWS、Google Cloud、Microsoft Azureなどのクラウドプラットフォームで広くサポートされているため、ベンダーロックインの問題がない。
- クラスター内のインフラストラクチャにアクセスすることができ、自由にカスタマイズすることができる。

## Fargate

- AWSが提供するサーバーレスコンテナプラットフォームで、コンテナオーケストレーションサービスであるECS、またはKubernetesで使用できる。
- EC2などの仮想マシンを管理する必要がなく、インフラストラクチャを管理することができないユーザーにとっては使いやすい。
- Fargateは、実行されるコンテナに応じて自動的に必要なリソースを割り当てるため、費用対効果が高くなる可能性がある。

以上が、ECS、EKS、Fargateの比較になります。使用目的によって、適切なサービスを選択することが重要です。
TypeError:Cannot read properties of undefinedと出た時の対処法

本記事は、GASでRESTAPIからJSONデータを得た際に、そのデータの一部を抜き取って表示する処理で発生したエラーを解消した経験を共有することを目的としています。そのため、どうようのエラーが出た際に、本記事の対処方法が適切でない場合がありますので、予めご了承下さい。

それでは行きます！
```gas:serch.gas
const companyCode = json.values[0].item_data[0].num;
const result = `企業名001株式会社:担当社員:${companyCode}`;
console.log(result); 
```
というコードを書き出力しようとしました。
ちなみにこの際変数jsonに代入されていたのは下記データです。

```json
"obj_name" : "customer",
 "item_data" : [ { "column" : { "code" : 318, "name" : "COMPANY_CODE", "type" : 3 }, "column_code" : null, "text" : null, "num" : 10186, "decimal" : null, "date" : null, "checkbox" : null, "values" : null } ] } ] }
```
そして、上記コードを出力すると
<b>TypeError:Cannot read properties of undefined</b>
の文字が、、
なんでだ！（ ;  ; ）

ただ、よく考えてみると、.values[0].item_data[0].numという書き方はGASのプロパティーでは使えるが、json形式のデータでは使えないのでは、、

そう思い、下記のようにコードを書き換えてみました。
```gas:serch.gas
const gasProperty = JSON.parce(json);
const companyCode = gasProperty.values[0].item_data[0].num;
const result = `企業名001株式会社:担当社員:${companyCode}`;
console.log(result); 
```
すると、企業名001株式会社:担当社員:10186と出力されました！
やはり、json形式をGAS形式に変えなかったことが良くなかったようです！




最後に
有識者の方へ本記事に誤りがあった際には修正しますので、修正依頼を送っていただけますと幸いです。
宜しくお願い致します。
eJPTv2受験記録

# はじめに
2023年5月、eLearnSecurity Junior Penetration Tester V2（2022年夏に改定し、V2に変わりました）を受け、無事合格しました。日本語資料が少ないので、私が受験の際に行ったことをまとめておこうかと思います。

# 自分のレベルについて
普段はペネトレーションテストを行う部署に所属していますが、まだ新設されたばかりで実務経験はありません。HTBやTHMをやってはきていますが、まだ本格的なペネトレーションテストを行うレベルには至っていないかなと思っています。
試験前に取得していた資格は、安全確保支援士とCompTIA Pentest+の２つです。なので、事前にセキュリティの基礎知識やペネトレーションテストの知識は多少身に付けられていたと感じています。

# eJPTv2について
試験のドメインとしては、Assessment Methodologies, Host&Network Pentesting, Web Application Pentesting, Host&Network Auditingの４つが対象です。試験時間は48時間で、35問の問題に回答していくことになります。
試験環境は全てブラウザからアクセスし、用意されたkaliマシンを使います。

# 勉強方法について
INEが提供するラボをメインに行いました。THMで事前に知っていたことも多かったのですが、月5000円を超えるため元を取ろうと全てしっかり受講しました。ただし、１つのセクションが英語の動画とラボがセットになっているため、英語ができる人でないと時間がかかると思います。（私は英語が全然にできないので苦戦しました。）
あらかじめTHMのComptia Pentest+のコースをやっておけば復習にもなってちょうど良いと思います。（THMの方が安い！）
改定されたため、新しく動画も追加されているようですが、古い動画は字幕が英語のみなので受講される方はその点気をつけてください。
仕事をしつつ、大学にも通っているため、なかなか時間が取れず4か月ほど受講しましたが、時間がしっかり取れる方であれば2か月もかからずに終えることができるボリュームだと思います。

# 試験の感想
試験の進め方としては以下の通りです。
- 1日目午前：全てのマシンに対してスキャン等列挙を行う。
- 1日目午後：取っ掛かりがあったマシンから順にイニシャルアクセスを取得する。
- 2日目午前：あらかた権限昇格を終える。
- 2日目午後：どうしても分からない問題をメインに解きなおす。

比較的時間に余裕はあったと思います。休憩もしっかり取っており、2日目も夜中まではやらずに終了しています。ただ、マシンの情報はNotionにまとめておき、後から確認できるようにしておきました。これをしていなければ間違いなく無駄に時間を浪費したのではないかと思います。

# 反省点
WEBとDBの知識経験が圧倒的に足りていませんでした。分からない問題は、ほぼこのドメインです。ある程度情報を集める方法が分かっていても、そこを起点にどう進めていくかが思い描けていないと感じました。INEのトレーニングではあまりWEBに重点を置いていないようだったので、それ以外の部分を重点的にやりましたが、WEBの初期アクセスもDB情報の取得もあったのでもっと事前に勉強しておけば良かったです。

# 今後について
普段の業務ではADに関するペネトレーションテストの知識が求められているので、OSCPは取っておきたいと思います。ただ、1年コースはやはり高いのでしばらくはHTB AcademyでADとWEBの勉強をしていこうかなと考えています。

# 参考にした記事
こちらの記事を参考に受験しました。日本語の記事は全然ないので大変助かりました。

https://qiita.com/v_avenger/items/245fb0b23de4e206396e

https://shinobe179.hatenablog.com/entry/2022/09/23/015454

https://qiita.com/IsaacJ/items/0313c06d259cbe82450e

https://github.com/PakCyberbot/eJPTv2-Notes
AWSの各種サービスの比較

# AWSの各種サービスの比較

AWSには多くのサービスがあり、それぞれの特徴や使い方が異なります。ここでは、代表的なAWSサービスの特徴を比較してみます。

## EC2 (Elastic Compute Cloud)

- 仮想マシンを提供するサービス
- インスタンスタイプによってCPU、メモリ、ネットワーク性能が異なる
- 利用料金はインスタンスの種類や使用時間に応じて課金される

## Lambda

- サーバーレスのコンピューティングサービス
- イベント駆動型で、特定のトリガーが発生した際に自動的にコードを実行する
- 利用料金は実行時間とメモリ使用量に応じて課金される

## S3 (Simple Storage Service)

- オブジェクトストレージサービス
- 任意のデータを保存し、ユーザーからのアクセスに応じてデータを返す
- 利用料金はデータの量、データの転送量、アクセス回数に応じて課金される

## RDS (Relational Database Service)

- リレーショナルデータベースのサービス
- MySQL、PostgreSQL、Oracleなど多数のDBエンジンに対応している
- 利用料金はDBの種類、インスタンスタイプ、使用時間に応じて課金される

## DynamoDB

- NoSQLデータベースサービス
- 高速かつスケーラブルなデータベースを提供する
- 利用料金はデータストレージ量、吞み込み容量、データ転送量に応じて課金される

以上のように、AWSには様々なサービスがあり、それぞれ異なる特徴を持っています。使い分けを考えながら、適切なサービスを選択することが重要です。
【Python】JsonResponseでエンコードの文字化けが起きてしまう場合の原因と解決方法

# エラー概要

* Django(Python)のコードで、`JsonResponse`を使って以下のように実装しておくとします。

```py
return JsonResponse({'status': 'errorです'})
```

* しかし、ログでは以下のように表示されてしまいます。文字化け？みたいな現象が起きています。

```py
{"status": "error\u3067\u3059"}
```

# 原因
* 調べてみると、これは`JsonResponse`がUnicodeエスケープシーケンスを自動的にエンコードするために発生するエラーらしい。
* Unicode文字列をエンコードしないように指定することで解決できます。


# 解決策

* 以下のように変更することで、日本語の文字列が正しく表示されるようになります。

```py
return JsonResponse({'status': 'errorです'}, json_dumps_params={'ensure_ascii': False})
```

* `json_dumps_params`は、Pythonの`json.dumps()`関数に渡すためのパラメーターを指定するためのオプションです。
* `ensure_ascii`はデフォルトでは`True`ですが`False`に設定することで、非ASCII文字をエスケープシーケンスではなく、そのままのUnicode文字列としてシリアル化するため、文字化けが解決されます。
Java用語（自分用）

## Javaでよく使う言葉

・クラス
プログラムを実行する際に必要な処理をまとめた設計図。メソッドと変数から構成される。

・メソッド
クラスが持つ機能を書いたもので、「メソッド名」「引数」「メソッド本体」から構成される。

```
class クラス名{
  メソッド名 (引数){
    // 実行処理
    メソッド本体
  }
}
```
・引数
メソッドに渡す値。入力値。

・戻り値
返ってくる値。出力値。

・変数
一時的にデータを格納しておく「箱」のこと。

・データ型
変数を扱うことができるデータの種類。
例）String,int,char...

※変数を扱う際は、頭にデータ型を付けなければならない。

・配列
複数の値を扱うことができるもの。
```
int[] number = {1, 3, 5, 7, 11, 13, 17, 19, 23, 29};
scores = new int[3];　※int型の要素を3つ生成。
```
・コンパイル
プログラムをコンピューターが実行できる形に翻訳すること。
ソースコードはコンパイラでバイトコードに変換されてから、JVM（Java Virtual Machine：Java仮想マシン）によって実行

---

##### 演算子
　+　足し算

　-　引き算

　* 掛け算

　/　割り算（余なし）

　%　割り算（余あり）

##### 代入演算子
　=　a=b

　+=　a=a+b

　-=　a=a-b

　*=　a=a*b

　/=　a=a/b

　%=　a=a%b

##### 比較演算子
・左辺と右辺が条件を満たしている時に「true」、満たしていない時に「false」を返す。

　==　左と右が等しい。

　<　右がより大きい。

　>　左がより大きい。

　<=　右が等しいかそれ以上。

　>=　左が等しいかそれ以上。

　!=　右と左が等しくない。

---

・インスタンスメソッド
staticがついているメソッド？
※有識者の方、ご教示願います。

・クラスメソッド
staticがついていないメソッド？
※有識者の方、ご教示願います。

---

### 最後に
パッと出てきたものをまとめてみたので漏れがあるかと思います。また、他に必須で覚えるJava用語はありますか。
言葉足らずなところも散見されるかと思いますので、補足等あればよろしくお願い致します。
ChatGPTで縦スクロールシューティングゲームを作ってみた

# はじめに

<B>Generative AI / ChatGPT</B> の可能性を確かめるべく、思いつきのまま専門知識等の準備をせず、AIにゲームのコードを書いてもらうテストをしながら、そのゲームの品質を高めていく試みをしてみたメモです。

# 実行環境
- Mac Book Pro 2021 Apple M1 Pro Ventura 13.3.1
- Python 3.11.3
- pygame

Python3および、ビデオゲーム向け python モジュールである、pygame の事前インストールが必要です。

# コード作成開始 #1

ChatGPTに最低限の言葉でゲームコードの作成をしてみます。
https://chat.openai.com/

<B>「python3 と pygame を利用した、縦スクロールシューティングゲームを作って」</B>

![スクリーンショット 2023-05-08 19.45.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/a9879116-5a15-9be6-b8ab-e4b6d6ae4537.png)

生成されたコードをコピーし、テキストにペーストし、python スクリプトとして、保存します。ここでは<B>「1.py」</B>として保存し、Macの標準の「ターミナル」アプリから、実行してみます。

```sh:Command
python ./1.py
```
背景が黒色の、別 Windowが現れ、下のほうに、白い四角が表示されました。キーボードの「←」「→」キーによって、白い箱を左右に動かすことができました。

![スクリーンショット 2023-05-08 19.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/0385bea5-40f3-7cfa-36e8-969823c3540c.png)

下の白い四角形が左右に動くだけで、とてもシューティングゲーム的な要素を体験できません。

# コード修正 #2
敵機の上方と、自機の一画面以内の弾の数、敵機を撃ち落とす条件、スコアの加算、表示、等の情報を指示してみます。
<B>「このスクリプトに敵を追加してください、弾丸は自機から一画面で3発撃てるようにしてください、自機の残数は3機です、敵を撃ち落とした場合10点が入ります、スコアを画面の中央最上部に表示してください、スコアは撃ち落とした敵の数の合算とします」</B>

![スクリーンショット 2023-05-08 20.20.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/c8f9c51f-5a49-9514-a06b-baffc644bac9.png)

生成されたコードをコピーし、テキストにペーストし、python スクリプトとして、保存します。ここでは<B>「2.py」</B>として保存し、Macの標準の「ターミナル」アプリから、実行してみます。

![スクリーンショット 2023-05-08 20.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/ef87a856-abfa-f157-d2b0-bcf6ae383a69.png)


矢印キーで左右に動かせる下方の白い箱の他に、<B>画面の上から無数の赤い四角形が下に落ちてきました</B>。スペースキーを押すと、<B>自機の白い箱から弾丸が放出され、敵機の赤い箱に当たると消滅</B>し、<B>スコアが10点づつ加算</B>されます。これはシューティングゲームの基礎にかなり近い！

# Tips #3
ChatGPTへコード作成をリクエストした結果、作成したコードのまとめまでされず、途中でタイムアウトしてしまう場合があります。この場合は以下のような指示を出すことによって、途中からのスクリプト情報を得ることができます。

<B>「作成したこのスクリプトの「enemy = Enemy(random.randint(0, WIDTH - 40)」文以降のスクリプトを再表示してください」</B>

![スクリーンショット 2023-05-08 20.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/685bfeaa-f085-14ae-e157-c4a4e40cfec9.png)

# コード修正 #4
この後は、このゲームスクリプトの品質を向上させていく例です。

- 自機、敵機の表示を変更する
　<B>「このスクリプトの自機のイメージを "/Users/user1/ChatGPT/game/me.jpg" の静止画像に変更してください。」</B>

- パワーアップアイテムを追加する
　<B>「ゲーム開始から10秒ごとにパワーアップアイテムが上方から下方に出現し、それを自機が取得するたびに画面で利用できる弾丸数が1発づつ増えるように変更してください。またパワーアップアイテムを取得した場合、弾丸の画像が大きくなるように変更してください。」

- 垂直に迫る敵機をランダムに動かす
　<B>「敵機をランダムで左右に動かすようにしてください」</B>

- ボーナスUFOを出現させる
　<B>「15秒に一回、画面左端から右端に大きめの敵機が自機に迫らず画面上方で水平方向移動します。この敵機を撃ち落とした場合、100点が加算されます。"Destroyed : Score + 100" の文字列をこの敵機が撃ち落とされた場所でしばらく表示させるように変更してください」

![shooting-game.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311200/b390269c-ebb2-af87-101b-4fba6ae2350b.jpeg)

上記を含む最終的なアップデートにより、敵機は左右に移動しながら自機に迫る、ボーナスUFOは出現し、破壊の際には、スコア表示が出る等、このように品質を高めることができました。

https://github.com/sig666/ChatGPT-based-shooting-game-sample

# 参考
[1] https://sakura.ohhappy.jp/sakura/1687
[2] https://zenn.dev/karaage0703/articles/5e77eb77571727
QAOA を用いた素因数分解法について (Part 6: まとめ)

本記事は, Yan 等の中国の研究者が 2022 年 12 月に発表した "Factoring integers with sublinear resources on a superconducting quantum processor" というプレプリントを解説した一連の記事の Part 6 (最終回) です. この論文は QAOA という量子計算を使った素因数分解アルゴリズムを提案しており, その名称を SQIF (Sublinear Quantum Integer Factorization) と呼んでいます. 本記事では SQIF に関する疑問をまとめます. 

[Part 1: 背景](https://qiita.com/izutetsuya/items/f40854aeb63d623410b8)
[Part 2: 平方差法による素因数分解](https://qiita.com/izutetsuya/items/0179d2609d666d95b392) 
[Part 3: Schnorr の素因数分解法](https://qiita.com/izutetsuya/items/a82aa95f11cf0de6ee6b)
[Part 4: SQIF の詳細](https://qiita.com/izutetsuya/items/2ceeb8c8dd581799b4da) 
[Part 5: SQIF の数値実験の分析](https://qiita.com/izutetsuya/items/15a537c6573153c200c3)
Part 6: まとめ (この記事)

https://arxiv.org/abs/2212.12372

# SQIF の概要

SQIF は, Schnorr の素因数分解法が拡張関係式を求める際に Babai アルゴリズムによって CVP の近似解を求めた後に, Schnorr の enumeration algorithm によってより良い近似解を探索する部分を, QAOA によって近似解の近傍からより良い近似解を探索するように変更した素因数分解法です. CVP を最適化問題に変換するために「Babai アルゴリズムの解の近傍により良い近似解が存在する」という仮定を利用しています.

# 疑問

## a. 仮定の妥当性

SQIFは「Babai アルゴリズムの解の近傍により良い近似解が存在する」という仮定を利用しているのですが, この仮定の証明(あるいは妥当性の検証)は必須です. 特に, Schnorr の enumeration algorithm では求まることがないかどうかの議論は欠かせないと思います. 

## b. QAOA の性能評価

QAOA はパラメータサイズが大きくなるにつれて精度が悪くなるため, (少なくとも SQIF で利用するハミルトニアンに関して) パラメータサイズが精度に与える影響を調べる必要があります.

## c. LLL アルゴリズムの影響評価

Babai アルゴリズムに対する LLL アルゴリズムの影響評価も必要だと思います (理屈の上では SQIF が利用する格子に限定した場合に何かが言えてもおかしくないのですが, 実際には難しいでしょうねぇ)

## d. 収集すべき拡張関係式の個数の評価

SQIF の場合, $|u-vN|$ に登場する素数の個数が多くなりがちなので,素因数分解に必要となる拡張関係式の個数評価も必要でしょう. 

## e. 計算量評価

そして何よりも SQIF の計算量評価が必要でしょう. QAOA を使っている以上, 厳密な計算量評価は難しいのかもしれませんが, せめて解くべき CVP の個数くらいは知りたいものです.

## f. SQIF は量子アルゴリズムなのか？ 

一番の疑問は, SQIF は量子アルゴリズムなのか？という点です. もちろん QAOA を使っているので量子アルゴリズムなのですが, SQIF の処理内容を分析していくと, 要は最適化問題が解ければ良いのであって, そのソルバーが QAOA に限定される理由はありません (むしろ, この形のハミルトニアンであれば他のソルバーも使えると思います). QAOA 以外のソルバーで素因数分解できるのであれば、ただの古典的な素因数分解アルゴリズムと呼ぶべきなのでしょう.

仮に QAOA の利用が必然であったとしても, SQIF は数個の拡張関係式を見つけるのがやっとなので, それ以外の大多数の拡張関係式は古典的な手法に頼ることになるわけですが, その場合に SQIF を量子アルゴリズムと呼ぶのは個人的には抵抗があります. まあ, この辺は用法の問題なので...

# まとめ

6 回に渡って "[Factoring integers with sublinear resources on a superconducting quantum processor](https://arxiv.org/abs/2212.12372)" という論文の内容を紹介しました. 誤解や typo をご指摘いただけるとうれしいです.
AIを調べるとよく出てくる最適化関数とは何ぞ？

# 目次
>[最適化関数とは](#最適化関数とは) 
[最適化関数の種類](#最適化関数の種類)
[最急降下法](#最急降下法)
[sgd(確率的勾配降下法)](#sgd(確率的勾配降下法))
[ミニバッチsgd](#ミニバッチSGD)
[モーメンタム](#モーメンタム)
[adagrad](#adagrad)
[rmsprop](#rmsprop)
[adam](#adam)
[まとめ](#まとめ)
# 最適化関数とは
　まず初めに、最適化関数を説明するにあたり、必要な知識が「損失関数」と呼ばれる関数です。
　損失関数を説明すると、想像と結果の差を数式であらわしたものです。そして、その差をなくしていくのが最終的な目標です。その目標に到達するために重みやアイアスを調整するのが、ニューラルネットワークにおける「学習」と呼ばれるものです。この「学習」を行うにあたり、正解値と予測値の差を微分(~~キライ~~)することで、勾配を求めることができます。
　この勾配を利用してどのくらいの強度でパラメータを更新するかを決めているのが、今回解説する**最適化関数**です。
　もうちょっと詳しい損失関数は[**こちら**](https://qiita.com/Lapinna/items/152c75f43682e72ae225 "損失関数ってなぁに?")
# 最適化関数の種類
　最適化関数には様々な種類があります。
　たくさんあるため、今回は代表的な関数のみを解説していきたいと思います。
# 最急降下法
　最急降下法 - 最も基本的な最適化関数です。
　全てのパラメータをもとに、勾配の最も急な方向に損失関数を小さくしていく手法です。
　この手法では、ひたすら小さい方向へと移動していくため、最適解ではなく「局所解」(最適化ッぽく見えるけど実は違うこと)に入ってしまうと抜け出せなくなってしまいます。また、全てのパラメータを利用しているため、計算量が大幅に増加してしまいます。

　これから説明していく最適化関数は、この問題を解決するために生まれたといっても過言ではありません。
# sgd(確率的勾配降下法)
　SGD(確率的勾配降下法) - 基本的な計算方法は最急降下法と同じです。
　違う部分は、全てのパラメータを利用するのではなく、**パラメータの中からランダムに１つ選んで**パラメータを更新していきます。このランダム性を利用することで、局所解にはまってしまっても抜け出せる可能性を高めています。
　しかし、ランダムに1つしかパラメータを使わないため、最適化に時間がかかってしまうというデメリットがあります。
# ミニバッチsgd
　ミミニバッチSGD - ニバッチ学習の最適化関数をSGDにしたものです。
　ミニバッチにすることで、計算量を抑えつつSGDの利点である、局所解から抜け出すことも可能となります。しかし、この方法を利用すると「Pathological Curvature」と呼ばれる鋭い勾配にはまってしまい、振動してしまうことで最小値にたどりつくまで時間がかかってしまう可能性(オーバーシュート)があります。
　これから説明する最適化関数は、全てこのオーバーシュートを抑えることができます。
# モーメンタム
　モーメンタム - ミニバッチSGDに運動量の要素を足したものです。
　勾配の大きさに応じて更新する量を変更しています。イメージとしては、坂道が急な（勾配が大きい）ほうがより速い速度でボールがころがっていき、坂道が緩やかな（勾配が小さい）場合は、ボールは転がらなくなるというイメージです。
# adagrad
　AdaGrad - ミニバッチSGDや最急降下法、またモーメンタムでは少しですが、最小値付近で斜面を行ったり来たりしてしまうことがあります。この問題を解決するために使われるようになりました。
　原理は、学習率を元に更新する量を調整することで、学習はじめの段階では、学習率を高くすることで更新する量を大きくし、最小値に近づいてきた場合は、学習率を小さくすることで更新する量を少なくすることができます。こうすることによって、斜面を通り過ぎてしまう問題をなくしました。
# rmsprop
　RMSprop - AdaGradを改良した最適化関数です。
　改良点は、学習率の調整をする際に過去のパラメータよりも直近のパラメータに注目して学習率を調整するようにしたものです。
# adam
　Adam - 現在最も使われている最適化関数です。
　モーメンタムとRMSpropの良いところを組み合わせることで効率よくパラメータを更新できるようにしています。
# まとめ
　じゃあ結局どれを使えばいいのか？
　学習率やモデルによって変わります……が基本的にAdamがいいとお思われます。
　しかし、元をたどれば全て**最急降下法**が根底にあるので、最急降下法が理解できればほかの最適化関数の理解はさほど難しくはないと思われます。

記事作成：N&Y
リストを変数に代入するときに気を付けること

```python
l = [1,2,3]
l2 = l

l[0] = 2

print(l)
print(l2)
```

実行結果
```
[2, 2, 3]
[2, 2, 3]
```
l2の値まで変わってしまっている。
これを避けるためにはcopyモジュールを使う。
```python
import copy

l = [1,2,3]
l2 = copy.copy(l)

l[0] = 2

print(l)
print(l2)
```
実行結果
```
[2, 2, 3]
[1, 2, 3]
```
<nuxt>ReferenceError: global is not defined

### 環境
- nuxt@3
- vite@4
- amplify@

# 問題
deploy後は動いてそう？
run devしたときにglobalがないと怒られる

# 解決
```js:nuxt.config.js
vite: {
    define: {
      //　↓このコメントを外す
      // global: {},
    },
```

# why
グローバルオブジェクトはnode.jsではglobal, ブラウザではwindow。
viteはデフォルトでglobalを定義しないが今回nuxtかamplify周りでglobalが必要になった？

https://almonta2021blog.com/react-vite-global-error/


# 参考
https://qiita.com/tatmius/items/f28369bb8d10324f6b7b

https://zenn.dev/aoito/articles/b07a4c68be2b96
TypeError: The database usage limit has been exceeded.

https://deno.com/deploy/docs/pricing-and-limits#deno-kv

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/8b95e999-82bc-b485-463b-3298611ad5c9.png)


1GBまでしか保存できませんのでご注意願う
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/22c56132-8cce-e73f-95b7-16aa2dfea099.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/9b8fe29a-6dc0-8578-503e-795e6db829ce.png)


検証コード

```typescript
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";

const kv = await Deno.openKv();

serve(async (req: Request) => {
    const v = crypto.getRandomValues(new Uint8Array(65536))
    for(var i=0; i<1000; i++) kv.set([i + 1000 * Math.floor((Math.random()*100))], v);
    return new Response("How are you")
});
```


16500行くらいストアできます ( `1.01*1024*1024*1024/65536` )
.paddingについてまとめた

paddingは、SwiftUIでビューの周囲にスペースを追加するための修飾子（modifier）です。paddingを使用することで、ビューの外側に余白を設定することができます。

padding修飾子は、ビューに適用する際に四方向の余白を指定することができます。具体的な使用方法は以下の通りです。

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, SwiftUI!")
                .padding()
            Text("Hello, SwiftUI!")
                .padding()
            Text("Hello, SwiftUI!")
                .padding()
            Text("Hello, SwiftUI!")
                .padding()
        }
        .padding()
    }
}
```

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2138087/7122a677-3cf4-333f-a251-988ee634e257.png">


この例では、Textビューにpadding修飾子を適用しています。デフォルトでは、四方向に16ポイントの余白が追加されます。

#####  また、四方向に異なる余白を指定することもできます。例えば、上方向には16ポイント、左右方向には8ポイント、下方向には32ポイントの余白を追加する場合は次のようになります。


```swift
Text("Hello, SwiftUI!")
    .padding(.top, 16)
    .padding([.leading, .trailing], 8)
    .padding(.bottom, 32)
```

padding修飾子では、第一引数に指定した方向に対して第二引数で余白の値を指定します。方向は、.top、.leading（左方向）、.trailing（右方向）、.bottomのいずれかを使用します。また、[ ] 内に複数の方向を指定することも可能です。

さらに、padding修飾子では余白の値を具体的な数値ではなく.edgesIgnoringSafeArea(.all)のような値を指定することもできます。これにより、ビューがセーフエリアの制約を無視して余白を追加することができます。


```swift
Text("Hello, SwiftUI!")
    .padding(.all, 16)
    .edgesIgnoringSafeArea(.all)
```

以上の内容をまとめてサンプルアプリを作りました

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2138087/c742cc11-d3d1-4ff6-a05a-b52284d67ecd.png">

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(spacing: 16) {
            Text("Hello, SwiftUI!")
                .font(.title)
                .foregroundColor(.white)
                .padding() // デフォルトの余白（16ポイント）が四方向に適用される
                .background(Color.blue)

            Text("Hello, SwiftUI!")
                .font(.title)
                .padding(.horizontal, 50) // 水平方向に20ポイントの余白を追加
                .padding(.vertical, 30) // 垂直方向に10ポイントの余白を追加
                .background(Color.yellow)

            Text("Hello, SwiftUI!!")
                .font(.title)
                .foregroundColor(.white)
                .padding(EdgeInsets(top: 40, leading: 1, bottom: 10, trailing: 30)) // カスタムの四方向の余白を追加
                .background(Color.green)
        }
        .padding(.all, 50) // 全体に20ポイントの余白を追加
        .background(Color.gray)
    }
}
```

こちらのアプリのTextに対してbackgroundColorを設定することでpaddingがどのように作用しているのかを分かりやすく確認することができます。

今日はここまで。
【Rails】モデル同士の関連付け「親モデルのフォームから子モデルの属性を同時に作成・更新・削除する場合」

### ① `_attributes`と`accepts_nested_attributes_for`
`accepts_nested_attributes_for`メソッドを親モデルに追加することで、親モデルの作成や更新時に、関連する子モデルも同時に作成や更新することができる。
一方、`_attributes`はストロングパラメータ内で使用され、親モデルとともに子モデルの属性を許可するために使用される。

したがって、親モデルと子モデルの関連を扱い、同時に子モデルの属性を作成や更新したい場合、`_attributes`と`accepts_nested_attributes_for`メソッドをセットで使用するのが一般的。

### ② `dependent: :destroy`オプション
has_manyの関連付けに加えて使用するオプション。
親オブジェクトが削除されると、関連する子オブジェクトも自動的に削除されるようになる。
関連付けをしているにも関わらず、このオプションを付けずに親の削除をしようとするとエラーになる。

### ③ `allow_destroy: true`オプション
`accepts_nested_attributes_for`に加えて使用するオプション。
（②の`dependent: :destroy` は親レコードが削除されたときに、自動的に子レコードも削除するオプション。
しかし、このオプションでは親レコードと子レコードを個別に編集・削除する場合には対応できない。親レコードが削除された場合のみ、子レコードも削除されることになる。）

一方で、`allow_destroy: true` は、親レコードを更新する際に、子レコードを編集・削除することができるオプション。
親レコードが削除されることなく、子レコードを編集・削除することが可能になる。
（例えば、親レコードを更新する際に、子レコードを追加・削除・変更することができる。）

# 結論
総括すると、`has_many :barcodetags`だけでも関連付けの意味があるが、親モデルのフォームから子モデルの属性を同時に扱う場合には、`_attributes`と`accepts_nested_attributes_for`メソッドも使用する必要がある。
また、場合によっては、`allow_destroy: true`を使用して、子要素のみの編集・削除も可能にする必要がある。

### コード例

親モデルのコントローラー（tagsテーブルのnameカラムに書き込みできるように処理を追加）
```ruby
def recipe_params
  params.require(:recipe).permit(:title, :content, :time, :price, :calorie, :image,
                                 tags_attributes: [:name])
end
```
子モデル
```ruby
class Recipe < ApplicationRecord
  belongs_to :user
  has_many :tags, dependent: :destroy

  accepts_nested_attributes_for :tags, allow_destroy: true
end
```
ChatGPTで生産性を爆上げする10個のプラグイン+α [chrome]

ChatGpt使ったことない人は、そろそろいないんじゃないかと思っているんですが、実際にうまく使えてる人はまだまだ少ないと思っています。
今回はChromeの10個の拡張機能を紹介します。作業や仕事の効率を上げるのに役立つから、参考にしてみてください！

## Superpower ChatGPT
ChatGptを便利に使えるようになる。使えばわかります。入れること推奨!

- chatの内容をフォルダでまとめられる
- サイドバーを引っ込めることできる
- txt, json, markdownでexportできる
- プロンプトのテンプレをボタン一つで実行できる
- 出力文の雰囲気を変更できる
    - フォーマルとか馴れ馴れしい感じとか、暗い感じ、明るい感じとか

https://chrome.google.com/webstore/detail/superpower-chatgpt/amhmeenmapldpjdedekalnfifgnpfnkc


## ChatGPT for Google
検索してる時にchatgptに聞きたいことあると思います。いちいちchatgptのタブ開くとかだるいので検索結果と一緒にchatgptも使えるようにすると作業効率アップするかもしれません。

https://chrome.google.com/webstore/detail/chatgpt-for-google/jgjaeacdkonaoafenlfkkkmbaopkbilf

## ChatGPT to Notion
Notion使ってる人ならいいと思う。いちいちコピペとかするの面倒ですって人に。

https://chrome.google.com/webstore/detail/chatgpt-to-notion/oojndninaelbpllebamcojkdecjjhcle


## Perplexity - Ask AI
Chatgptって情報のソースどこだよ!!ってことありませんか。最近は減ってきていますが嘘つきますよね。
Perplexityはchatgptじゃないですけど、情報のソースを表示してくれるchatgptみたいなサービスです。

あと、嬉しい機能で開いているページのドメインから情報を探してきてくれる機能あります。
特定ページの検索が貧弱すぎとか英語だらけでわからんとか、この人だけの情報を得たいって時に良いと思います。

あと、時間ない人に便利な機能で、そのページを要約できます。長すぎてダメだとか他のサービスだと言われるけどこれは大丈夫。長い記事を要約できます。

https://chrome.google.com/webstore/detail/perplexity-ask-ai/hlgbcneanomplepojfcnclggenpcoldo

## GPT Macros
名前の通りChatGptでマクロ使うというもの。
毎回使うようなプロンプトありますよね。プロンプトをメモに貼り付けておいてコピーして条件を変更して、、、
なんて面倒を省く。変数を複数設定することもできるので条件とか指示、内容部分だけを書けば良くすることも可能。おすすめです。

https://chrome.google.com/webstore/detail/gpt-macros/ecbfpbleejhlcgljokfamgjpmlppceda

## Voice Control for ChatGPT
声で指示を出せる。サクッと指示を日本語で話せばいいので便利。
そんなに使うか？と思うかも知れないけど、音声入力を英語で入力できて返答も英語でしてくれる。

つまり、chatGPTを英語の先生にして無料で英会話できる。
私は英語が出来なすぎて英会話しようとしても気が引けたって経験ありました。そんな人におすすめしたいです。無料ですし。

https://chrome.google.com/webstore/detail/voice-control-for-chatgpt/eollffkcakegifhacjnlnegohfdlidhn

## TweetGPT
人によると思いますがTwitterで何かつぶやかないと！って時に感情とつぶやく内容を与えると勝手にそれっぽいの作ってくれます。
まだ、内容的にそのまま使えるかは微妙かもしれないけどたたき台にはなるかも。

あと、リプにも使える。
返信しないといけないなんて時に優等生な返信考えてくれるかも。

https://chrome.google.com/webstore/detail/tweetgpt/lkjblpoingopdeaofcaapmeoojjjnhnc

## YouTube Summary
動画のサマリー書いてくれる。私は動画の要約使う場面があまりないのですが人によっては長い動画を見なきゃいけないとかだったら使えるかも。

https://chrome.google.com/webstore/detail/youtube-article-summary-p/nmmicjeknamkfloonkhhcjmomieiodli

## AIPRM for ChatGPT
ブログ書く人、SEO気にする人は使用すると感動するかも。
最適化されたChatGPTプロンプトを簡単に使うことができるのでブログ書く人、SEOで迷ってChatGPTに聞きたい！だけど、どのように指定すれば良いかわからないなんて人はぜひ。

ブログ記事、SEO以外でも指示をちゃんと出せるプロンプトあるようなので試してみてもいいかもしれません。

## ChatGPT Writer
メール送る時、返信する時など、どんなふうに書き始めるか迷ったり面倒だったりしますよね。そんな時はAIに書かせればいいです。

メール以外にも、web上でメッセージを作る・返信する時にも使えるので便利です！
個人的に嬉しいのは英語のメールとか送る時に日本人の私にはこれめっちゃいいんですよね。日本語で指示したら日本語で書いてくれるし、英語で指示したら英語で返してくれます。

https://chrome.google.com/webstore/detail/chatgpt-writer-write-mail/pdnenlnelpdomajfejgapbdpmjkfpjkp

## ChatPDF
最後にこれは拡張機能でないですけど、便利そうだったので追加しました。
PDFをアップロードして要約したり、質問に答えてくれます。PDFをよく使う人には良いかもしれません。

https://www.chatpdf.com/
Vue.jsでHelloWorld的なプログラムを実装してみた

# 概要
Vue.jsでHelloWorld的なプログラムを実装してみました。以下のページを参考にしました。
https://kojimanotech.com/2021/01/25/282/

# 環境構築
以下のコマンドを実行しました。
```
$ npm install @vue/cli
```

# プロジェクト作成
以下のコマンドを実行しました。
```
$ ./node_modules/.bin/vue create hello-world
```

# プログラム実行
以下のコマンドを実行しました。
```
$ cd hello-world
$ yarn serve
```

# 動作確認
Chromeでlocalhost:8080にアクセスして以下のページが表示されれば無事動いています。
![Screenshot from 2023-05-08 20-01-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/5a5b7f7a-9f5b-a880-55a3-15a1ffe87626.png)

何かの役に立てばと。
【AppStore48位】月文字ジェネレーターがサービス終了したのでワイが作るしかないと決意（王者の風格）アプリ LunArt AI: 月の絵文字ドット絵🌝

# プロローグ
あの人気Web サイト 、**月文字ジェネレーター**がサービス終了していたので、僕が代わりにモバイルアプリを作ることにしました。（英雄気取り）

# アプリ紹介 （リンク）
アプリの名前は**LunArt AI: 月の絵文字ドット絵**で、テキストや画像を入力すると月文字が返ってきます。月文字は、TEXT, JPG, GIF として出力されます。

インストールはここから↓
🍎 AppStore

https://apps.apple.com/jp/app/id6446714099

🍏 GooglePlay

https://play.google.com/store/apps/details?id=com.kaede.emoonji

# アプリ紹介 （動画と画像）
Youtubeに参考動画を載せました。こんな感じです。

https://www.youtube.com/watch?v=HayNaRCB9NU

冒頭数秒だけこちらにも載せますね。

![LunArt5MB.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/44362cab-9b81-af4b-b70f-283b9e7748e3.gif)

うん、、、冒頭だけだと、なんのこっちゃですなぁ。。。やっぱこっち見たほうがいいと思う！

https://www.youtube.com/watch?v=HayNaRCB9NU

イメージ画像はこんな感じ

<img width="180" alt="authorise" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/12aa5550-b278-0b4f-cf6e-b5c46edc16f1.jpeg">
<img width="180" alt="authorise" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/d465e603-9d87-27fe-2232-31ecae93d4ee.jpeg">
<img width="180" alt="authorise" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/a9f84bdd-1295-159e-08af-110448ff2368.jpeg">
<img width="180" alt="authorise" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/6020d323-96da-f85d-1425-a3aa34a5a470.jpeg">

# 技術的な仕組み

仕組みはほとんど下記と一緒

https://qiita.com/tan5o/items/e0fa51ecb62619444e10

つまり、バックエンドには、以下の技術を使用しています。
* FlaskでAPIを作成
* PILを使用して画像の生成と月文字化


異なる点は、
* python 高速化のためにjest を利用していること。
* Flutterを使ってフロントエンドを作成
* ローカライズ対応のためにFastTextを使用して各種フォントを使い分け
* Python高速化のためにJestを利用

です。

# 最後に
よかったらインストールしてTwitterでコラ画像作ってください。 #LunArt つけていただければ反応させていただきます！

🍎 AppStore

https://apps.apple.com/jp/app/id6446714099

🍏 GooglePlay

https://play.google.com/store/apps/details?id=com.kaede.emoonji