OmniAICreator/Qiita-1.07M huggingface dataset:
統計検定準1級の勉強備忘録　～母関数～

皆様、お疲れ様です！
株式会社ジール 新米SIerの窪田です。

統計検定準1級に向けての勉強中に母関数でつまずいたので、自身の理解を備忘録として残しておこうと思います。

# 母関数のモチベーション

ズバリ、**「期待値と分散を求めたい！！」** です。
このモチベーションを理解しないまま統計学実践ワークブックを読んでしまうと、難しい数式が現れノックアウトされます。（私は、ノックアウトされました。。。）

# 母関数について
統計学実践ワークブックには、下記の様に記述されております。
> 整数値をとる確率変数 *X* の確率関数を *p(x)* とし、 *s* を任意の実数とするときに *X* の確率母関数を
> ```math
> G(s) = E[s^X] = \sum_{k=1} s^xp(x)
> ```
> と定義する。

この定義をみて、なぜ確率変数を指数におくのかわからずノックアウトされました。
ここで終わると難しい数式が登場しただけになるのですが、微分を駆使することで非常に有能な数式になります！

### *X* の期待値を求める!
まずは *G(s)* を *s* で微分します。
```math
G'(s) = E[Xs^{X-1}]
```
ここで *s* = 1とすると、
```math
G'(1) = E[X]
```
なんと母関数を微分した関数の *s* を1とすることで、確率変数 *X* の期待値を求めることができました！

### *X* の分散を求める！
先ほど微分した式をもう一度 *s* で微分します。
```math
G''(s) = E[X(X-1)s^{X-2}]
```
ここで *s* = 1とすると、
```math
G''(1) = E[X(X-1)]
       = E[X^2-X]
       = E[X^2]-E[X]
```
ここで分散の式を思い出すと
```math
V[X] = E[X^2]-(E[X])^2
```
です。 *E[X]* を足して引くと、
```math
V[X]=E[X^2]-(E[X])^2-E[X]+E[X]=G''(1)+G'(1)-(G'(1))^2
```
となります。
母関数を2回微分した関数の  *s* を1とした式を利用することで分散も求めることができました！

# 母関数の例題
統計学実践ワークブック問2.2を例題に解いてみたいと思います。
### 問題
> 問2.2
> *X* を幾何分布に従う離散確率変数とする。すなわち *X* は非負整数値をとりその確率関数を
> ```math
> p(x) = p(1-p)^x , x = 0,1,2,...
> ```
> とする。ただし、0 < p < 1は幾何分布のパラメータである。*X* の確率母関数 *G(s)* を求めよ。また確率母関数を微分することにより *X* の期待値と分散を求めよ。

### 解答
##### 母関数を求める
まずは定義から確率母関数を書いて整理しましょう。
```math
G(s) = E[s^X] = \sum_{x=0}^{∞} s^xp(x)=\sum_{x=0}^{∞} s^xp(1-p)^x=p\sum_{x=0}^{∞} (s(1-p))^x
```
次にΣ以降を計算していきます。これは、無限等比級数の和の公式を使用します。
> 無限等比級数の和の公式
> ```math
> 等比数列a_n=ar^{n-1}に対する無限等比級数の和は、
> ```
> ```math
> |r| < 1のとき、一定の値 \cfrac{a}{1-r} に収束する。
> ```
> ```math
> |r| \geqq 1のとき、発散する。
> ```
*s(1-p)* を公比（ *r* ）と考えると、
```math
p\sum_{x=0}^{∞} (s(1-p))^x = p×\cfrac{1}{1-(1-p)s} = \cfrac{p}{1-(1-p)s}
```
これで、確率母関数 *G(s)* が求められました。
ただし和が収束するのは公比の絶対値が1以下の場合なので、 *|s| < 1/1-p* という条件が付きます。

##### 母関数を微分して期待値を求める
先ほど求めた母関数を微分するには下記の公式を使用します。
> ```math
> \biggl(\cfrac{u}{v}\biggr)'=\cfrac{u'v-uv'}{v^2}
> ```
*u = p*、*v=1-(1-p)s*とおいて*s*で微分すると
```math
 G'(s)=\cfrac{0-p×(1-(1-p)s)'}{(1-(1-p)s)^2}=\cfrac{p(1-p)}{(1-(1-p)s)^2}
```
ここで*s*=1を代入すると
```math
 G'(1)=\cfrac{p(1-p)}{(1-(1-p)×1)^2}=\cfrac{p(1-p)}{p^2}=\cfrac{1-p}{p}
```
従って期待値は
```math
 E[X]=G'(1)=\cfrac{1-p}{p}
```
となります。

##### さらに微分して分散を求める
母関数の2回微分をしたものを駆使することで分散を求めることができましたので、*G'(s)* をさらに微分します。
*u = p(1-p)*、*v={1-(1-p)s}^2*とおいて*s*で微分すると
```math
 G''(s)=\cfrac{0-p(1-p)×\{(1-(1-p)s)^2\}'}{(1-(1-p)s)^4}
 ```
 ```math
 =\cfrac{-p(1-p)×\{2(1-(1-p)s)×(-(1-p))\}}{(1-(1-p)s)^4}
``` 
```math
 =\cfrac{-p(1-p)×\{2(1-(1-p)s)×(-(1-p))\}}{(1-(1-p)s)^4}
```
式が整理されていませんが、*s=1*を代入しましょう。
```math
 G''(1)=\cfrac{-p(1-p)×\{-2p(1-p)\}}{p^4}=\cfrac{2p^2(1-p)^2}{p^4}=\cfrac{2(1-p)^2}{p^2}
 ```
 これで *G'(1)* と *G''(1)* が求められたので、分散を算出することができます。
 ```math
 V[X]=G''(1)+G'(1)-(G'(1))^2=\cfrac{2(1-p)^2}{p^2}+\cfrac{1-p}{p}-\biggl(\cfrac{1-p}{p}\biggr)^2=\cfrac{1-p}{p^2}
 ```
 以上で、母関数、期待値、分散を求めることができました！
 
# まとめ
期待値と分散を求めたいときは母関数を考えてみる！

ご拝読頂き、ありがとうございます。
お疲れ様でした！
[TinyML] Memoryの使用量を下げる方法


# In-place depth-wise Convolution
depth wise convolutionは2N(入力N,出力N)のPeak Memoryを使用する。
しかしdepth wise convolutionはchannel間の依存関係が無いため、計算が終わったChannelはデータを書き換えても問題ない。
そこでtemporally bufferを用意する事で、N+1のPeak Memory Usageに抑える事が出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/68d2d265-78ea-aefe-8207-017b74f75c6c.png)

# interpretation to code generation
ほとんどのinference libraries(e.g., TF-Lite)はinterpreter-baseである。使わないfunctionなども準備して置く必要があり、MemoryのOverheadが生じてしまう。runtimeにoperationを呼ぶのではなく、compilation時にコードを生成する事で必要最低限のfunctionで動くためMemoryを節約出来る。


# Reference
[MCUNet: Tiny Deep Learning on IoT Devices]()
繰り返し処理の基礎学習(for文について)

# 1.for文って？
プログラミングで使われる構文の一種です。
指定した数まで繰り返しの処理を行いたい場合によく使います。
 <font color="Red">便利な構文</font>となっています。

# for文の利便性について
では、実際に使う場合と使わない場合でどのように便利なのか
今回はJava言語を使用して凡例を比較します。
では、実際に見てみましょう!!

### 実現したいこと
1～10番目という文字を出力したい。

## ①for文を使わない場合

```java:1～10番目という文字をするサンプルコード(for文を使わない場合)
class SampleNumSQ {
    public static void main(String[] args) {
        System.out.println("1番目");
        System.out.println("2番目");
        System.out.println("3番目");
        System.out.println("4番目");
        System.out.println("5番目");
        System.out.println("6番目");
        System.out.println("7番目");
        System.out.println("8番目");
        System.out.println("9番目");
        System.out.println("10番目");
    }
}
```

### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565927/d467cd27-c4a4-b3b1-5634-171944476904.png)

## ②for文を使う場合

```java:1～10番目という文字をするサンプルコード(for文を使う場合)
class SampleNumSQ {
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            System.out.println(i + "番目");
        }
    }
}
```

### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565927/ce70b284-04f9-3b61-16c0-996dac37f045.png)
どうでしょうか？
同じ出力結果なのにfor文を使うと使わないでは、コード量が段違いです。
また、コード量が少ないので可読性も向上します。
これらのことを踏まえて、どのようにfor文を使えばいいのか
掘り下げてみましょう。

# for文の使い方
以下の様にfor文は<font color="Red">初期化式</font>、<font color="Red">条件式</font>、<font color="Red">変化式</font>の3要素で構成されています。

```java
for ("初期化式";"条件式";"変化式";) {
    // 条件式がtrueのときに繰り返す処理
}
```

### <font color="Red">初期化式</font>(initialization)
変数を初期化してくれる式のことを指します。
### <font color="Red">条件式</font>(condition)
作業を繰り返すための条件を与える式のことを指します。
### <font color="Red">変化式</font>( increment / decrement )
実行処理を終え、最後に行われる処理のことを指します。また、変化式の処理が行われたあとは条件式に戻ります。
##
最後に、ここまでの情報を抑えた上でいくつかのfor文を使った例を見てみましょう!!

# いろいろな繰り返し処理

## ①初期化式を0と置いた場合の出力

```java:int i=0と初期化式に変更を加えた場合
class SampleNumSQ {
    public static void main(String[] args) {
        for (int i = 0; i <= 10; i++) {
            System.out.println(i + "番目");
        }
    }
}
```

### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565927/fe37156f-3869-30e2-0259-fe09c2bd85a3.png)

int i=0と初期化式に変更を加えました。
出力結果に0番目が追加されているのがわかりますね。

## ②初期化式を10,条件式を i>=1,変化式をi--と置いた場合の出力

```java:初期化式を10,条件式を i>=1,変化式をi--と置いた場合の出力
class SampleNumSQ {
    public static void main(String[] args) {
        for (int i = 10; i >= 1; i--) {
            System.out.println(i + "番目");
        }
    }
}
```

### 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565927/71c1849e-3fac-30b8-b776-d2955ce8d2a8.png)

初期化式にint i=10、条件式に i>=1、変化式をi--と3つの要素に変更を加えました。
出力結果が今までの結果と違い降順に数字が出力するようになりました。
3要素をうまく入れ替えるとこのように出力する内容も変更することができます。
上手くfor文を使い、for文マスターになろう!!
以上、繰り返し処理の基礎学習(for文について)でした。
本当に効果のある改善施策なのか？ GSMフレームワークを使ってデータ駆動で評価する （書評から）

この記事は「Googleのソフトウェアエンジニアリング ―持続可能なプログラミングを支える技術、文化、プロセス」という本の１つの章を読んでの感想になります。

本書を読んだ中で特に「エンジニアリングの生産性の計測」という章について読みました。
翻訳本であり、そもそも高度な組織と内容を扱うため、わかりにくい部分がある本のため、
自分が理解した概要とキーワードなどを抜き出して記録しておきたいと思います。

この章の概要は、 **エンジニアリングの生産性を計測することの意義とその手段** について、
コードのリーダビリティ（読みやすさ）を改善することを例に、 **その計測手法** を紹介するものでした。

## エンジニアリングの生産性を計測する
エンジニアリングの生産性を計測することについて次のような内容と理解しました。

　ビジネス拡大を考える際、組織の規模が大きくなるとコミュニケーションコストが増大し、ビジネスの対象範囲をスケールアップすることは難しい。
そのため、 **エンジニアの生産性向上** を通じてビジネスを拡大する方が良いが、その際にも人的コストがかかる。
単に生産性を改善するだけでなく、効率的に改善することが重要。
そこで、エンジニアリングの生産性の計測をすることによって、データによる裏付けを行いながら改善する。

## エンジニアリングの生産性向上の計測手法について
生産性向上の施策として「コードのリーダビリティを改善」する場合、
この施策の計測手法についてはいくつかの観点が紹介されました。

### トリアージ：そもそも計測するほどの価値があるか？
　計測できる部分は多いが何を計測すべきなのか？
  その計測が改善の行動の結果を判断でき、次の行動に繋げられるものでないと
  計測自体の価値がないかもしれないとありました。

### GSMフレームワーク
　ゴール、シグナル、メトリクスの頭文字をとった名称。
　・ゴール：望ましい最終結果
　・シグナル：最終的な結果を達成したことを知る方法（それ自体は計測できない可能性もある）
　・メトリクス：シグナルの代用品（実際に計測可能なもの）

　これは目標に対する達成指標を決める際に大事なステップであると思いました。
 　ありがちな失敗として、計測しやすい指標だけを集めて、そこから結論に紐付けようとしてしまいがちですが、
　このフレームワークに従ってゴール、シグナル、メトリクスを繋いで示しておくことで、
 　ゴールから外れないようになると思いました。
  また、メトリクスについては定性的なものであっても、複数の指標を持って継続的に観察することでおおまかには外れない指標になるという考え方が紹介されていました。（アンケートのようなもの）

### 街灯効果
　計測しやすいものを採用してしまうことで、本来の目的にふさわしくない指標となってしまうこと。
  本書では、コードの品質を探る際のコード行数などが指標にはなり得ないことをなどを例示。
　夜道で鍵を落として探そうとする際に、街灯で照らされている箇所だけを探してしまうと
　正しい場所を探していることにはならないという例から。
 　GSMフレームワークはゴールから辿ることができるため、街灯効果になりにくい。

### 生産性の５つの中心要素（QUANTS）
 　・コード品質(Quality of the code)
 　・エンジニアの注意(Attention from engineers)
 　・知的複雑性(Intellectual complexity)
　 ・テンポと速度(Tempo and velocity)
   ・満足(Satisfaction)

　ゴールの網羅性を取るために用いる指標として紹介。
　たとえば極端な例として、レビュー速度を早くしたいならば「レビューを省いてしまう」などの施策が良い結果として計測してしまうなどの問題が発生しうる。
　コードの品質と開発速度などトレードオフな要素を抜き出したものである。
 　ゴールを決めるための網羅的な観点も必要と記載されていました。

## まとめ
　感想として2点を得ました。
 1つ目は、エンジニアリングの生産性を計測することの意義。
　システムの開発現場ではさまざまな改善施策をうつことになるが、その成果を評価することは正直に言うとあまり意識されていません。
 　実際に効果があったのか評価をする際も様々な観点を用いることはなく、感覚的な指標になっているのが現実だと思いました。
 2つ目は、GSMフレームワークは、データを裏付けてなにかの施策の効果を計測したい場合にたいへん有効だろうと思ったことです。
 　街灯効果（言葉そのものは今回知りましたが）になってしまい、結果としてそのゴールに近づけたのかよくわからなくなってしまうなどはよくあることと思います。

特に2点目GSMフレームワークはエンジニアリングの範囲にかかわらず、学習や自己啓発の目標設定などの場面にも使える考え方で、応用して取り込んでいきたいと思いました。


---
「Googleのソフトウェアエンジニアリング ―持続可能なプログラミングを支える技術、文化、プロセス」 - オライリー
https://amzn.to/3UQpuCy
ざっくりわかるMonoBehaviourと継承

# はじめに
今回はMonoBehaviour の理解を深めるのが主な目的です
なので継承についての細かい説明は省きます
MonoBehaviour と継承についてざっくり概要を知りたい人向けの記事になってます

# 継承の概要
オブジェクト指向には三大要素「カプセル化」、「継承」、「ポリモーフィズム」というものがあります
継承はそのうちの１つです、三大要素っていうくらいなのでよく使われてるし使います

## 継承とは
あるクラスから機能を　継承　して新しいクラスをつくることです

## 親クラスと子クラス
継承するときに継承元となるクラスを親クラス（基底クラス）といい、継承されるクラスを子クラス（派生クラス）といいます
親クラスを継承したのが子クラスです
この記事では親クラスでやっていきます！

## 継承のイメージ
矢印の向いてる方が、親クラス （ スライム ） です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669184/c6efca2d-614c-7597-cf30-ca7019a28fde.png)
親クラスは子クラスよりも抽象度が高いです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669184/45d4c19b-a664-9bf4-5ec8-c0d6c0609682.png)

## 継承のメリット
子クラスは親クラス の機能をすべて継承しているので共通の処理を書かなくて済みます！
なのでコードの量が減り、機能を追加したときの手間が減るので管理がしやすくなります
エンジニアの大好きな再利用性が向上します

# MonoBehaviour
ここからが本題です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3669184/844d2230-a603-9a5d-04a1-603180997f1b.png)
Unityで新しくクラスを作ると絶対に MonoBehaviour がついてくるので結構馴染み深いですよね
馴染み深いわりには MonoBehaviour が一体何者なのかよく知らないけど使ってる人も多いと思います

## MonoBehaviourの機能 
MonoBehaviourの機能を大きく分けると以下の２つになると思います

### イベント関数
Start、Update、FixedUpdate などの特定のタイミングで処理される関数

### GameObject 
transform、tag、GetComponent などのゲームオブジェクトに関するクラス

[GameObject 公式ドキュメント](https://docs.unity3d.com/ja/2020.3/ScriptReference/GameObject.html
"GameObject UnityDocs")
[MonoBehavior 公式ドキュメント](https://docs.unity3d.com/ja/2020.3/ScriptReference/GameObject.html 
"MonoBehaviour　UnityDocs")

## MonoBehaviour とは
ざっくりいうと Unity が提供してくれた Unity で開発するときに必要な機能の盛り合わせクラスです

## MonoBehaviour を使わない（継承しない）パターン
上記の通り MonoBehaviour はゲーム開発をする上でほぼ必須級の機能が備わっています、ですが継承しなくてもいいパターンもあります

MonoBehaviourを継承しない　=　MonoBehaviourの機能を使わない
つまりイベント関数もGameObject関連の機能も使わない（Hierarchyに実体がない）場合です！

具体的にはキャラクターのステータスなどのデータ系です
データ系なら実体が必要ないのでMonoBehaviourを使わなくてもいいしイベント関数も必要ないですよね！
## なんでMonoBehaviourアンチがいるのか
前述の通り MonoBehaviour にはたくさんの機能が入っています
クラスに必要以上の機能が入っていると、その機能が使われている可能性を考えないといけなくなります
なので大規模開発やチーム開発をする場合に大きな被害となってしまいます

# さいごに
・Unity開発をしていて設計の勉強をはじめた一番最初にぶち当たる壁が MonoBehaviour だったのでまとめてみました
・思ったよりざっくりになってしまいましたが、この記事で MonoBehaviour の概要はわかるようになると思います
・まだ初心者なので勘違いやミスがあると思います、もしあったら教えてもらえると嬉しいです

以上です、お読みいただきありがとうございました。
5/29(水)に AI駆動開発(AI-Driven Development)勉強会 第2回を開催します！

こんにちは。クリエーションラインの荒井です。皆さんGWは如何お過ごしでしょうか？
今回は2024年5月29日(水)開催予定のAI駆動開発(AI-Driven Development)勉強会 第2回の開催について紹介していきます。

（勉強会の詳細や参加については以下をご確認ください。）
https://connpass.com/event/317096/

### なぜ勉強会をしようと思ったのか？

ChatGPTをはじめとする生成AI・LLMの登場により、コード生成や自動補完、バグ修正の支援などがAIでできるようになりつつあります。もちろんまだまだ精度・実用性や品質確保についての課題は多くありますが、これらを利用することで、アプリ開発の生産性が大きく変わったという話も良く聞くようになってきました。
参考までに以下はKDDIアジャイル開発センター(KAG)さんの記事ですが、開発に与えた影響が解りやすく整理されています。

参考：GitHub CopilotがKAG社エンジニアの開発効率に与えた影響
https://developers.kddi.com/blog/JeaNGpkzrgQ83xN8jywwQ

今後、AI・LLMの精度向上と更なる開発プロセスへの適用によってその効果は更に上がっていくと予想されます。

特に2024年の3月〜4月にかけてはDevin, AutoDevの発表に続いて、GitHub Copilot Workspacesもテクニカルプレビューが開始され非常に注目を浴びています。
Devin, AutoDev、GitHub Copilot Workspacesは、コーディングの支援だけではなく、Issueを元、ソフトウェア設計、実装、デバッグ、テストまでをAIが自動的に実行するソリューションになっています。これらのソリューションの動向を踏まえて考えると、近い将来に、アプリケーション開発やシステム開発、コーディングのスタイルは大きく変わることが予想されます。

また今後は、各社クラウドベンダーも要件詳細化やUIデザイン、設計、実装、デバッグ、テスト、デプロイ、リリースをAIを利用して自動かつ統合的に行うサービスを出してくると予想されます。このような流れの中で、エンジニアの役割・求められるスキル・学習方法のみならず、マインドセットやあり方も大きな変化が必要になると予想されます。

このような技術は現段階ではまだまだ進化過程の技術でありまだまだ施行錯誤になりますが、大きな変化の中で、最新のトレンド・技術をキャッチアップし開発に活かしていくことはエンジニア個人個人にとっても、また組織においても非常に重要になると思います。このような背景から皆さんと共に生成AI・LLMを使った新たな開発手法について勉強・議論できる場が作れればと思い、AI駆動開発勉強会と名付けて企画をしました。

### 勉強会の概要
AI駆動開発(AI-Driven Development) 勉強会では、AI技術を使った開発に興味を持つ方々向けに、ChatGPTやGitHub CopilotなどのAIツールを使った開発のノウハウや、AIによる開発プロセスの最適化、生成AI・LLMを最大限に活用した新たな開発方法・開発スタイルやテクニックや今後の新しい開発スタイルについて共有・議論していきます。

5/29(水)開催の第2回では、GitHub Copilotの最新情報、注目を浴びているDevin, AutoDev, SWE Agent, GitHub Copilot Workspaceの話に加えて、「女子大生が100日連続で生成AIで100本のプログラムを書いたらどうなったか？」をチャレンジした大塚あみさんにもお話いただく予定です。

生成AI・LLMを利用した開発に興味・関心があるエンジニアの皆さん、また、これからの新たな開発スタイルを積極的に取り入れて行きたい皆さんの参加をぜひお待ちしております！

日時：5月29日(水) 19:00〜20:50（開場：18:30）
開催形式：オンサイト＋オンライン
会場：KDDI DIGITAL GATE (東京都港区虎ノ門2丁目10-1 虎ノ門ツインビルディング 西棟3階)
主催：AI駆動開発勉強会 運営委員会
協力：KDDIアジャイル開発センター株式会社、クリエーションライン株式会社

https://aid.connpass.com/event/317096/

### アジェンダ

GitHub Copilotの最新情報、Devin, AutoDev, SWE Agent, GitHub Copilot Workspace等のお話、「女子大生が100日連続で生成AIで100本のプログラムを書いたらどうなったか？」の続き、LTなどのコンテンツを予定しています。

| 時間         | セッション内容                                 | 発表者                                       |
| ------------ | -------------------------------------------- | ------------------------------------------- |
| 19:00-19:05 | イベント案内＆会場案内 | Yasuhiro Arai |
| 19:05-19:30 | GitHub Copilot Enterprise と今後のロードマップ - GitHub Copilot の最新情報とちょっと先の未来について、お知らせします | GitHub Senior Architect Yuki Hattori さん |
| 19:30-19:55 | 新たなAI駆動開発の潮流 〜Devin, AutoDev, SWE Agent, GitHub Copilot Workspace等の登場と将来の開発スタイル 〜 | 鈴木章太郎(shosuz)さん |
| 19:55-20:20 | 女子大生が100日連続で生成AIで100本のプログラムを書いたらどうなったか？ | 大塚あみさん |
| 20:20-20:35 | (セッション調整中) | |
| 20:35-20:40 | 【LT枠】AI駆動開発の2つのパターン（仮）| @eltociearさん | 
| 20:40-20:45 | 【LT枠】| @lemilemilemioさん | 
| 20:45-20:50 | 【LT枠】| @hackhackさん |
CPU

## 主記憶装置を学ぶ

データを一時的に保存：容量がちいさい、処理が早い。

補助記憶装置：容量が大きい、処理遅い。。

![Screenshot 2024-05-10 at 8.03.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/0b798d63-fc6d-1365-7a7e-3daae5c97c81.png)
![Screenshot 2024-05-10 at 8.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/f7e7a26e-0f23-684d-8fbc-5264ae4069f5.png)

![Screenshot 2024-05-10 at 8.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/530a0477-a4b3-877c-aa81-1e9f70a32c62.png)
![Screenshot 2024-05-10 at 8.06.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/8c6db137-9dac-1c1b-d4c2-fd3553876cad.png)



コンデンサとは電気を蓄える回路、なので、電気を蓄えてビットを処理する。

## 主記憶装置の高速化
![Screenshot 2024-05-10 at 8.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/cb06384e-2c9f-9d05-05d8-c7b3f7c211e6.png)
レジスタと主記憶装置の間の速度の差を埋めるため。

![Screenshot 2024-05-10 at 8.30.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/71def09e-8424-76e4-89f9-ccfda1426c28.png)

![Screenshot 2024-05-10 at 8.30.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/a524ed25-316b-edfb-c67f-d481993433bc.png)
AWS Amplifyについて

# はじめに
副業でAmplifyを使ったアプリケーション開発に従事しているので、学んだことをアウトプットとして書いていきます。

# ドキュメント

https://docs.amplify.aws/gen1/react/start/getting-started/introduction/

# Amplifyとはなんぞや

https://aws.amazon.com/jp/amplify/

AWS Amplifyは、Webアプリケーションおよびモバイルアプリケーションの構築などを簡単に行えるようにし、開発に集中できるよう設計されたAWSのサービスです。主な機能は次のとおりです。
- **ホスティング**

Amplify Hostingを使用すると、フロントエンドのWebアプリケーションをプロビジョニング、構築、デプロイ、ホスティングできます。
GitHubなどのソースコード管理システムと統合されており、自動デプロイパイプラインを構成できます。

- **認証**

Amazon Cognito とシームレスに統合されており、ソーシャル認証機能やユーザープールの管理が可能です。

- **API**

AWS AppSync や Amazon API Gatewayを使って、サーバーレスAPI(GraphQLやREST)を構築できます。

- **データの保存**

Amazon DynamoDBなどのAWSデータストアに簡単にデータを保存できます。

- **ファイルストレージ**

Amazon S3や Amazon Elasticsearchにファイルやデータを保存できます。

# Amplifyを使用するメリデメ
Amplifyは便利なサービスですが、メリットとデメリットがあります。
## メリット
- **開発の効率化**
Amplifyは、認証、API、ストレージ、アナリティクスなどの機能を提供しているため、開発者はこれらの機能を素早く実装できます。これにより、開発時間を大幅に短縮できます。
- **コスト削減**
Amplifyはマネージドサービスなので、開発者はインフラストラクチャの管理やスケーリングの心配をする必要がありません。これにより、運用コストを削減できます。
- **セキュリティ**
AWSのサービスはセキュリティ面で信頼性が高いため、Amplifyを使用することでセキュリティリスクを軽減できます。
- **統合性**
Amplifyは他のAWSサービスと連携しやすいため、必要に応じて機能を拡張することができます。

## デメリット
- **ベンダーロックイン**
Amplifyは、AWSのサービスに依存しているため、他のクラウドプロバイダーに移行するのが難しくなる可能性があります。
- **カスタマイズ性の制限**
Amplifyは多くの機能を提供していますが、高度なカスタマイズには制限があります。複雑なアプリケーションの場合、Amplifyだけでは不十分な場合があります。
- SSRに対応していない
AmplifyはSPAを使用した開発を前提としているため、SSRには対応していません。

# Amplifyの利用に向いているケース
- **スタートアップや小規模プロジェクト**
リソースが限られている場合、Amplifyを使うことで開発効率が上がります。
- **マイクロサービスアーキテクチャ**
Amplifyは、マイクロサービスの構築に適しています。各サービスにAmplifyを適用すれば、開発を容易にすることができます。
- **シンプルなWebアプリやモバイルアプリ**
認証、ストレージ、APIなどの基本的な機能が必要な場合、Amplifyを使用すれば、比較的簡単に実装ができるので、有効な選択肢となります。

# 参考記事
Amplifyに関する参考記事をまとめました。

## インストール
Amplifyのインストールについては、以下の記事が参考になります。

https://qiita.com/Junpei_Takagi/items/f2bc567761880471fd54

# アプリケーションをAmplifyでデプロイするまで

https://aws.amazon.com/jp/getting-started/guides/deploy-webapp-amplify/


## Amplify CLIチートシート
Amplifi CLIのコマンドのチートシートは以下になります。

https://qiita.com/bonjiko/items/93e8fad618bd4b588b63

## ドキュメント

https://docs.amplify.aws/

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください！

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
github actionsからteamsにオレオレ通知を送信する

:::note warn
本記事で紹介している方法は2024 年 8 月 15 日に終了します。以降の対応については作業完了次第別記事として投稿します
https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
:::

## 背景

githubからのteams通知をもっと自由にやりたかった。
デフォルトだと通知で「カードを送信しました」しかでてこないので、いちいちteamsを開くのが非常に嫌だった。
で、いろいろ調べたが情報がまとまっておらず嫌に時間をくったのでメモ。

## これでできます

1. teamsでチャネルを作る
1. チャネルにincoming webhooksを追加する
1. incoming webhooksが作成したURLにgithub actionsから通知内容を送信する

## 以下詳細

### teamsにincoming webhooksを追加

以下の記事を参考にさせていただきました。

https://qiita.com/youtoy/items/0bfce1a022c716573f32

### github actionsから通知内容を送信する

以下は例としてワークフローが終わったタイミングでteamsに通知するgithub actionsです

```notify-workflow.yml
name: notify-workflow

on:
  workflow_run:
    workflows: ['workflow1','workflow2']
    types: [requested, completed]

jobs:
  on-requested:
    if: ${{ github.event.workflow_run.conclusion == '' }}
    uses: ./.github/workflows/notify-to-teams.yml

    with:
      url: $incoming webhooksが作成したURL
      payload: >
        '{
          "summary":"${{ github.event.workflow.name }}を開始しました",
          "text":"${{ github.event.workflow.name }}を開始しました"
        }'

  on-success:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    uses: ./.github/workflows/notify-to-teams.yml
    with:
      url: $incoming webhooksが作成したURL
      payload: >
        '{
          "summary":"${{ github.event.workflow.name }}が成功しました",
          "text":"${{ github.event.workflow.name }}が成功しました"
        }'

  on-failure:
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    uses: ./.github/workflows/notify-to-teams.yml
    with:
      url: $incoming webhooksが作成したURL
      payload: >
        '{
          "summary":"${{ github.event.workflow.name }}が失敗しました",
          "text":"${{ github.event.workflow.name }}が失敗しました"
        }'
```

```./.github/workflows/notify-to-teams.yml
name: notify-to-teams

on:
  workflow_call:
    inputs:
      url:
        type: string
        required: true
      payload:
        type: string
        required: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Notify to Teams
        if: always()
        run: |
          curl ${{ inputs.url }} -X POST -H 'Content-Type: application/json' -d ${{ inputs.payload }}

```

temasへのcurl送信は再利用可能なワークフローを作成し、各jobで呼び出しています。

## 送信可能なメッセージ

公式に必要なパラメータが記載されています。

https://learn.microsoft.com/ja-jp/outlook/actionable-messages/message-card-reference#section-fields

アダプティカードなるものを推奨していますが、incoming webhooksを経由する場合はこちらを使うようです。

summary または text は必須。ただしsummaryを設定しないと通知内容が「カードを送信しました」になってしまうので注意。
FeedItem のまとめ



+ [FeedComment Trigger のテストクラス](https://qiita.com/Keiji_otsubo/items/261524cc88be622eee7e)
+ [ApexからChatterに投稿する](https://qiita.com/Keiji_otsubo/items/685fe1495627a08863cd)
+ [FIELD_INTEGRITY_EXCEPTION: The record does not exist in specified network.: Entity ID.](https://qiita.com/Keiji_otsubo/items/a51e255aa8ba56f729f3)
+ [chatter いいねのついた投稿を抽出する](https://qiita.com/Keiji_otsubo/items/c764fbbbe467f1d2eae2)
+ [chatter いいねのついた投稿を抽出する2](https://qiita.com/Keiji_otsubo/items/c764fbbbe467f1d2eae2)
+ [特定ユーザのChatter投稿を全て確認可能な方法はございますでしょうか。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007clV58)
+ [ファイルの詳細表示画面で投稿元の情報を表示する](https://qiita.com/Keiji_otsubo/items/a1741625b5466638e933)
+ [SOQLの結果をCSVファイルとして保存するApexバッチ](https://qiita.com/Keiji_otsubo/items/767ed7fbbf2f72943a14)
+ [Salesforce Backup & Restore](https://qiita.com/Keiji_otsubo/items/2afb256e6e48ed83698e)


# Error : Field is not writeable: FeedItem.Body

+ [Why I can't able to update FeedItem object records ....](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PfDqA)

:::note
Well, the issue was "Allow users to edit posts and comments" was not enabled under Chatter Settings. It is working now. 

https://salesforce.stackexchange.com/questions/248419/update-feeditem-body
:::

# コメントを検索したい？

+ [Chatterに関する調査について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ak5rq)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e41bfe04-d0b6-b344-6c02-b4ce0d7d232b.png)

:::note
以下のSQLでFeedCommentsのList変数として格納できると思います。

 
```
select Id,title, Body,ParentId, createddate, createdbyid, (select Id from FeedComments) from FeedItem ORDER BY CreatedDate DESC
```

:::
primary assets and related assets



[help : Track Asset Replacements](https://help.salesforce.com/s/articleView?id=sf.assets_rel_equal.htm&type=5)

# primary assets and related assetsが表示されない

+ [I don't have the options in my assets page layout for primary/related assets.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007clM1l)

:::note
I had the same issue, but then I realized that the issue was that the trailhead lesson didn't highlight it enough, but after you add the related lists to the Account object, you then need to switch to the Asset object. It says to do this, but it's not highlighted and easy to miss. If you go to the Asset object instead of the Account object, you can add all four related lists: 

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A97ohSAB

私も同じ問題を抱えていましたが、Trailhead のレッスンで十分に強調されていなかったのが問題であることに気付きました。ただし、関連リストを Account オブジェクトに追加した後、Asset オブジェクトに切り替える必要があります。これを行うように指示されていますが、強調表示されていないため、見落としがちです。 Account オブジェクトではなく Asset オブジェクトに移動すると、4 つの関連リストをすべて追加できます。
:::

+ [アカウントオブジェクトの関連リストにプライマリアセットと関連アセットが表示されない](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A97ohSAB)

:::note
I also encountered the same issue, but then I realized that I need to work on the layout of the Asset object instead of the Account object. I suggest you check which object's layout you are currently working on and try again.

私も同じ問題に遭遇しましたが、その後、Account オブジェクトではなく Asset オブジェクトのレイアウトに取り組む必要があることに気付きました。現在作業しているオブジェクトのレイアウトを確認して、再試行することをお勧めします
:::
SparkFun qwiicケーブル接続

# SparkFunのボードを使用してみた

qwiicというケーブルのコネクタをご存知でしょうか？
groveなどは比較的触れること多いかも知れませんが,
それとくらべると若干影の薄いqwiicという規格のコネクタを使用してみて、初学者はつまづきそうなポイントがあったので記事にしました。

ベーシックなesp32やm5stamp、atom系のesp32などは使ってきたが、SparkFunのボードは使用したことがなく、使用したいセンサqwiicケーブルで直に接続できるため[こちら](https://www.switch-science.com/products/9488?_pos=3&_sid=b58930d3c&_ss=r)のボードを使用しました。

### 目的
qwiic接続でマイコンとセンサを直で接続してデータを取得

### 使用したマイコン類
[SparkFun Pro Micro - ESP32-C3](https://www.switch-science.com/products/9488?variant=43082469114054)
[SHT40搭載 STEMMA QT/Qwiic互換 温湿度センサ](https://www.switch-science.com/products/7030?_pos=2&_sid=858261d04&_ss=r)
[Qwiicケーブル（Qwiic - Qwiic）500 mm](https://www.switch-science.com/products/6899?variant=42382131134662)

#### 開発環境
m2 macbook air
macOS 14.4.1
arduinoIDE 2.3.2

今回は標準のqwiicコネクタを介してsht40の温湿度の値を取得することが目的なので、sht4x系ライブラリを事前に追加しておきます。
ライブラリマネージャーでAdafruit SHT4Xを検索して最も上に出てきたAdafruit製のライブラリをインストール
インストールが完了するとfile>Examples>Adafruit SHT4X　Libraryというサンプルが追加されます。
SHT4testのファイルなどを見るとqwiic接続で使用するピン番号の宣言がありませんが、qwiic搭載ボード選択して書き込めば自動的に正しいピン位置を判定してくれます。

esp系をarduinoで使用する際に必要なjsonパス貼り付け→ボードマネージャーから追加などはなく、SparkFunの公式サイトの手順を参考にボードをarduinoに追加します。
[公式サイト](https://docs.sparkfun.com/SparkFun_Pro_Micro-ESP32C3/software_setup/)

公式サイトによるとArduino15というディレクトリの中のesp32関連のファイルに追記などするとボードが追加されるとあります。
まずはArduino15ディレクトリを探しましょう。
```
find ~ -name Arduino15
```
と、ターミナルで実行すると結果が表示されますが、Operation not permittedに検索結果が埋もれることもあるので、⌘＋FなどでArduino15を検索してディレクトリを見つけましょう。
ディレクトリが見つかったら

```
Arduino15\packages\esp32\hardware\esp32{version}
```
に移動（versionは各々の環境による）
ｌｓコマンドなどを実行すると中身はこんな感じかと思います↓
![esp32_core_file_structure_overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055872/99ffed8e-f2c8-ff20-1634-641f881c125c.png)

このディレクトリの中に[こちら](https://github.com/sparkfun/SparkFun_Pro_Micro-ESP32C3)の中身をgit cloneしてきて、ローカルのvariantsディレクトリの中にgitよりクローンしてきたファイルのsparkfun_pro_micro_esp32c3をコピーします。

ターミナル内でのコピーの仕方がわからない人はGUIでも大丈夫です。Arduino15はmacであれば基本的にLibrary/Arduino15とライブラリ直下にあるので、Finderを開き、⌘ + Shift + .　を押すと隠しファイルが表示され、user直下にライブラリというフォルダが表示されるかと思うので、その中で上のパスなどを参考にesp32/{version}/のディレクトリに行き作業でも問題なく行けます。

variants内にコピーしたら[このテキスト](https://github.com/sparkfun/SparkFun_Pro_Micro-ESP32C3/blob/main/Arduino_Board_Files/sparkfun_boards.txt)をesp32/{version}/boards.txtの末尾に貼り付けます。

するとArduinoのボード選択のesp32のボード一覧の最下部にsparkfun_pro_micro_esp32c3が選択できるようになります。

このボードを選択した状態でfile > Examples > Adafruit SHT4X　Library > SHT4testなどを書き込むとボード搭載のqwiic接続でSHT40の値を取得することが可能になります。

普段arduinoのセンサ類はピン番号を指定していたのでサンプルを見て若干迷いましたが、よくできていますね👍
robloxでassistant その23

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
湯婆婆を表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3228b45d-6a2d-b4bf-5f57-05c5e9387ff7.png)

# サンプルコード

```
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local gui = PlayerGui:WaitForChild("ScreenGui")

gui.TextButton.MouseButton1Click:Connect(function()
	local res = ""
	local Name = gui.TextBox.Text 
	res ..= "フン。"..  Name .. "というのかい。贅沢な名だねぇ。\n"
	local Len = string.len(Name)
	local Seed = os.time()
	math.randomseed(Seed)
	local rand = math.random(Len / 3) -1
	local cnt = 3 * rand + 1
	local newName = string.sub(Name, cnt, cnt + 2) 
	res ..= "今からお前の名前は".. newName .. "だ。いいかい、" .. newName .."だよ。分かったら返事をするんだ、" .. newName .. "!!"
	gui.TextBox.Text = res
end)




```


以上。
Javaで「数値リテラルにサフィックスを付けて型を指定する」の動作を確認してみた

# 概要

Javaで「数値リテラルにサフィックスを付けて型を指定する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/num/index8.html

# 実装

以下のファイルを作成しました。
```JSample8_1.java
class JSample8_1{
  public static void main(String[] args){
    System.out.println(2200000000L);
  }
}
```

以下のコマンドを実行しました。
```
$ javac -encoding UTF-8 JSample8_1.java
$ java JSample8_1
2200000000
```

# まとめ

何かの役に立てばと。
robloxでassistant その22

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
zundokoを表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6cd43d8c-b3bd-72a4-1228-71353a5e543d.png)

# サンプルコード

```
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local gui = PlayerGui:WaitForChild("ScreenGui")

gui.TextButton.MouseButton1Click:Connect(function()
	local zundoko = {"ズン", "ドコ"}
	local sequence = {}
	local res = ""
	local function checkZundoko(sequence)
		local n = #sequence
		if n < 5 then
			return false
		end
		for i = 1, n - 4 do
			if sequence[i] == "ズン" and sequence[i+1] == "ズン" and sequence[i+2] == "ズン" and sequence[i+3] == "ズン" and sequence[i+4] == "ドコ" then
				return true
			end
		end
		return false
	end
	while not checkZundoko(sequence) do
		local randomIndex = math.random(1, 2)
		table.insert(sequence, zundoko[randomIndex])
		res ..= zundoko[randomIndex]
	end
	res ..= "キ・ヨ・シ！"
	gui.TextBox.Text = res
end)




```


以上。
robloxでassistant その21

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
九九を表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f867bc92-7be0-4bd4-2317-0158039d9ec2.png)

# サンプルコード

```
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local gui = PlayerGui:WaitForChild("ScreenGui")

gui.TextButton.MouseButton1Click:Connect(function()
	local res = ""
	for i = 1, 9 do
		for j = 1, 9 do
			res ..= i * j .. " "
		end
		res ..= "\n"
	end
	gui.TextBox.Text = res
end)

```

以上。
robloxでassistant その20

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
fizzbuzzを表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/89b315b9-eb6e-dc26-7a7e-6b6eda51535f.png)

# サンプルコード

```
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local gui = PlayerGui:WaitForChild("ScreenGui")

gui.TextButton.MouseButton1Click:Connect(function()
	local res = ""
	for i = 1, 100 do
		if i % 3 == 0 and i % 5 == 0 then			
			res ..= "FizzBuzz\n"
		elseif i % 3 == 0 then
			res ..= "Fizz "
		elseif i % 5 == 0 then
			res ..= "Buzz "
		else
			res ..= i.." "
		end
	end

	gui.TextBox.Text = res
end)

```


以上。
【Rails】ルーティングのnamespaceとscopeの違いについて

## はじめに
「管理用の一覧ページを表示したい」と思った時に今までnamespaceを使っていました。
今回、イベントの管理アプリを作成している中で、scopeを使ってみてそれらの違いについてまとめてみました。

### 結論
大きな違いは次の通りです。
|  |url  |ファイル構成  |
|---|---|---|
|namespace  |指定のパスにしたい  |変えたい  |
|scope  |指定のパスにしたい  |変えたくない  |


### ルーティングファイル内容

``` routes.rb

  # 一般ユーザーの一覧ページ
  resources :events
  
  # namespaceの場合
  namespace 'manage' do
    resources :events
  end

  # scopeの場合
  scope :manage do
    get 'events', to: 'events#manage_events'
    # Restfulなルートの場合
    # resources :events
  end
```

(補足)
scopeでは、resourceを使用した場合に通常のindexアクションに対応するルートが自動で生成されて呼び出されます。
例えばindexアクションとは別に、```manage_events```で一覧表示したい場合、手動でルートを作成する必要があることに気づきました。

## namespace
### 特徴
namespace（名前空間）を使うと、指定した名前空間内でルーティングをグループ化できます。
以下の例はmanageという名前空間を付与しています。

#### ルート一覧
![スクリーンショット 2024-05-10 6.14.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/2b038189-7252-d1e2-c21a-0392d42e9445.png)

#### ファイル構成
コントローラー
![スクリーンショット 2024-05-10 5.15.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/66c282a5-ebe2-8466-5e8c-37e98e82948e.png)

ビュー
![スクリーンショット 2024-05-10 6.25.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/c8584108-c626-3ba8-f872-dec663a19e71.png)


### namespaceのメリット
- ルートやコントローラーのグループ化ができる
一般ユーザーと管理ユーザーでファイルを分けたい時などに便利ですね。

- リソースの名前やルートが衝突するのを防げる
resourcesを使用しても、そのルートは通常のリソースとは異なる名前空間に属することになります。
例えば、一般ユーザーと管理ユーザーのページを作成する場合、リソースとは別々に使用できます。

### namespaceのデメリット
- URLが長くなる
深い階層の名前空間に設定した場合にURLが複雑になり、理解しにくくなることがあります。

- コードや構造が複雑になりやすくなる
複数の名前空間を使用した場合、アプリケーションの構造が複雑化し保守しにくくなるリスクがあります。

## scope
### 特徴
namespaceと同様にルーティングをグループ化しますが、
違いはパスのみグループ化できることです。

そのため、ファイル構成は変えなくて済みます。

#### ルート一覧
Restfulなルートの場合
![スクリーンショット 2024-05-10 6.42.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/99ff4ed2-fb99-c0de-3003-2b19b5efd6b2.png)

手動で作成したルートの場合
![スクリーンショット 2024-05-10 6.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/0f65f6a7-aca0-1b63-131a-b5017c908509.png)


#### ファイル構成
コントローラー
![スクリーンショット 2024-05-10 6.48.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/0838ddcc-e80c-fc85-f861-08ed62039f88.png)


ビュー
Restfulなルートの場合
![スクリーンショット 2024-05-10 6.45.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/0d7751f8-0dbb-03cb-6190-d7104be919c7.png)

手動で作成したルートの場合（```manage_events```アクションを呼び出しています）
![スクリーンショット 2024-05-10 6.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/61793518-38da-9b79-7cf0-cf1c6e1feff7.png)


### scopeのメリット
- ファイル構成はそのままでURLのみ変えられる
namespaceのようにファイル構成を変更せずにルートのみ変えることが可能です


### scopeのデメリット
- 通常のリソースと区別することが難しくなる
上記の例のように、scope外のresourcesのindexアクションが呼ばれてしまうという問題がありました。
そのため、手動でルートを作成するなどの対応が必要そうです。


## まとめ
（アプリケーションの要件によると思いますが）
管理者用やAPIの機能を名前空間で明示的に分けたいときは、```namespace```
特定のパスをグループ化したいときは、```scope```
といった使い分けに基本的になるのかな？と思いました。

## 参考記事
[Railsのroutingにおけるscope / namespace / module の違い](https://qiita.com/ryosuketter/items/9240d8c2561b5989f049)
[BigQuery API(V2)] JavaでBigQueryテーブルの行(レコード)を挿入する

BigQuery API V2(Java)を使用して、
BigQueryテーブルの行(レコード)を挿入する方法
についてご紹介します。

テーブルにレコードを挿入するには、
適切なIAM権限が付与されている必要があります。

権限付与に関しては
[⧉[BigQuery API(V2)] JavaでBigQueryを使う(2.権限付与)](https://qiita.com/doran/items/8b7ba29672527426e88d#2-権限付与)
を参照ください。

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

|No||目次|
|---|---|---|
|1||[レコードを挿入](#1-レコードを挿入)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|

## 1. レコードを挿入
指定したテーブルのレコードを挿入します。

### 1.1. スコープ
このAPIを実行するには、以下のいずれかのスコープを指定してください。
```
BigqueryScopes.BIGQUERY
BigqueryScopes.CLOUD_PLATFORM
BigqueryScopes.BIGQUERY_INSERTDATA
```
[⧉[BigQuery API(V2)] JavaでBigQueryを使う(3.2. BigQueryインスタンスを取得)](https://qiita.com/doran/items/8b7ba29672527426e88d#32-bigqueryインスタンスを取得)
でスコープを指定してください。

### 1.2. 実行

```java
public static void main(String[] args) throws Exception{
    Bigquery bigquery = getBigquery();
    Bigquery.Tabledata tabledata = bigquery.tabledata();
    
    Map<String,Object> row = new HashMap<>();
    row.put("field1", "test");
    row.put("field2", 1);
    
    TableDataInsertAllRequest.Rows rows = new TableDataInsertAllRequest.Rows();
    rows.setJson(row);
    
    TableDataInsertAllRequest content = new TableDataInsertAllRequest();
    content.setRows(Arrays.asList(rows));
    
    Bigquery.Tabledata.InsertAll insertAll = tabledata.insertAll("プロジェクトID","データセットID","テーブルID",content);
    
    TableDataInsertAllResponse res = insertAll.execute();
    System.out.println(res);
}
```
#### 1.2.1. HTTPリクエスト
POST:　https:\//bigquery.googleapis.com/bigquery/v2/projects/{プロジェクトID}/datasets/{データセットID}/tables/{テーブルID}/insertAll
が実行されます。

#### 1.2.2. クエリパラメータ
クエリパラメータはありません。

#### 1.2.3. リクエストボディ
TableDataInsertAllRequestのsetメソッドにより、リクエストボディを追加できます。

|メソッド|引数|説明|
|---|---|---|
|setSkipInvalidRows|Boolean|無効な行が存在する場合でもリクエストのすべての有効な行を挿入するか|
|setIgnoreUnknownValues|Boolean|スキーマに一致しない値を含む行も挿入するか|
|setTemplateSuffix|String|テンプレートテーブルを使用する場合のインスタンステーブル名|
|setRows|List\<[TableDataInsertAllRequest.Rows](#tabledatainsertallrequestrows)\>|挿入する行|
|setTraceId|String|リクエストトレースID<br>デバッグ用途|

#### TableDataInsertAllRequest.Rows
|メソッド|引数|説明|
|---|---|---|
|setJson|Map\<String,Object\>|単一行のデータ|

### 1.3. レスポンスの内容
#### TableDataInsertAllResponse
|メソッド|戻り値|説明|
|---|---|---|
|getKind|String|リソースの種類<br>固定文字列："bigquery#tableDataInsertAllResponse"|
|getInsertErrors|List\<[TableDataInsertAllResponse.InsertErrors](#tabledatainsertallresponseinserterrors)\>|リクエストの処理中に発生した特定のエラー|

#### TableDataInsertAllResponse.InsertErrors
|メソッド|戻り値|説明|
|---|---|---|
|getIndex|Long|エラーが適用される行のインデックス|
|getErrors|List\<[ErrorProto](#errorproto)\>|Indexプロパティで示された行のエラー情報|

#### ErrorProto
|メソッド|戻り値|説明|
|---|---|---|
|getReason|String|エラーコード|
|getLocation|String|エラーが発生した場所|
|getDebugInfo|String|デバッグ情報|
|getMessage|String|エラーの説明|

<br>
<br>
おしまい。。
python リストのメソッドたち

### append
```diff_python
list = ['a','b','c']
list.append('d')
print(list) #['a','b','c','d']
```
`append(x)`は、リストの末尾に要素`x`を1つ追加します。

### extend
```diff_python
list1 = ['a','b','c']
list2 = ['d','e','f']
list1.extend(list2)
print(list1) #['a', 'b', 'c', 'd', 'e', 'f']
```
`extend(iterable)`は、`iterable`のすべての要素を対象のリストに追加し、リストを拡張します。（リストを結合するイメージ）

### insert
```diff_python
list = ['a','b','d']
list.insert(2,'c')
print(list) #['a', 'b', 'c', 'd']
```
`insert(i, x)`は、指定した位置`i`に要素`x`を挿入します。

### remove
```diff_python
list = ['a','b','c','a']
list.remove('a')
print(list) #['b', 'c', 'a']
```
`remove(x)`は、リストの中で、`x`と等しい値の最初の要素を削除します。削除されるのは最初の要素だけです。（例では、2つめの`'a'`は削除されていない。）


### pop
```diff_python
list = ['a','b','c']
print(list.pop()) #c
print(list) #['a', 'b']
```
`pop([i])`は、下記の2つの機能があります。
① 指定した位置`i`の要素をリストから取り除く
（インデックスが指定されていない場合、`list.pop()`はリストの末尾の要素を取り除く）
② ①で取り除いた要素を返す

### clear
```diff_python
list = ['a','b','c']
list.clear()
print(list) #[]
```
`clear()`は、リストの中のすべての要素を取り除きます。
位置を指定して取り除きたい場合は、前述の`pop`を使うか、`del`を使います。
```diff_python
list = ['a','b','c']
del(list[1])
print(list) #['a', 'c']
```
```diff_python
#スライスで範囲を指定して複数の要素を一括で削除
list = ['a','b','c']
del(list[1:])
print(list)#['a']
```

### count
```diff_python
list = ['a','b','c','a']
print(list.count('a'))# 2
```
`count(x)`は、リストにある要素`x`の数を返します。

### copy
```diff_python
list1 = ['a','b','c']
list2 = list1.copy()
print(list2)#['a', 'b', 'c']
```
`copy()`は、リストのコピーを返します。

### sort
```diff_python
list = ['c','a','b']
list.sort()
print(list)# ['a', 'b', 'c']
```
`sort`はリスト内の値を並べ替えます。
`sorted()`関数は、`sort`メソッドと似ていますが、リストの中身は書き換えられず、並び替えしたリストを返します。
```diff_python
list1 = ['c','a','b']
list2 = sorted(list1)

print(list2)# ['a', 'b', 'c']
print(list1)# ['c', 'a', 'b'] ←list1はそのまま
```
robloxでassistant その19

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
「hello」を表示せよ。

# 写真

![スクリーンショット 2024-05-10 062207.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f6e85bfc-a6a8-9f4d-8180-49a0bda7630f.png)


# 手順
- エクスプローラーでStartterGuiにScreenGuiを追加
- そこにTextBoxとTextButtonを追加
- ReplicatedFirstにLocalScriptを追加
- スクリプトを書く

```
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local gui = PlayerGui:WaitForChild("ScreenGui")

gui.TextButton.MouseButton1Click:Connect(function()
	--print("Hello world!")
	gui.TextBox.Text = "hello world"
	local src = gui.TextBox.Text
	print(src)
end)

```


以上。
Flutter 〜Paddingのサンプル〜

テキストフィールドをPaddingで位置を変える。

# Padding前

<img width="40%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/09167f4e-0a9c-ce64-20d6-2db7dded544e.png">


```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              decoration: InputDecoration(
                  labelText: '名前',
                  hintText: '名前',
                  icon: Icon(Icons.account_circle)),
            ),
          ],
        ),
      ),
    );
  }
}

```
# Padding後
テキストフィールドが右に寄る。
<img width="40%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/7c79774b-6cd6-cb84-3be4-778432f46795.png" >

変更点はTextFieldをPaddingでラッピングした箇所のみ。
```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //PaddingでTextFieldをラッピング
            Padding(
              padding: const EdgeInsets.all(30.0), //寄せる量を指定
              child: TextField(
                decoration: InputDecoration(
                    labelText: '名前',
                    hintText: '名前',
                    icon: Icon(Icons.account_circle)),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

```
コントローラクラスのコンストラクタをモック化


Spring MVCのテストでコントローラクラスのコンストラクタをモック化する場合、一般的にはMockitoを使用します。コントローラのコンストラクタをモック化するには、Mockitoの@Mockアノテーションと@InjectMocksアノテーションを使用します。

以下は、コントローラクラスMyControllerのコンストラクタMyControllerをモック化する例です。

```java
@RunWith(MockitoJUnitRunner.class)
public class MyControllerTests {
    @Mock
    private MyService mockMyService;

    @InjectMocks
    private MyController myController;

    @Test
    public void testConstructor() {
        // Arrange
        // モック化したいコンストラクタの引数を設定
        // 例: when(mockMyService.someMethod()).thenReturn(someValue);

        // Act - コントローラのインスタンス化は@InjectMocksで行われるので、何もしなくても良い

        // Assert
        // コントローラが正しく初期化されたかどうかを検証
    }
}
```

この例では、MyControllerクラスのコンストラクタMyControllerをモック化しています。@Mockアノテーションを使用してMyServiceをモック化し、@InjectMocksアノテーションを使用してMyControllerをインスタンス化します。その後、コンストラクタの引数をモック化したり、コントローラが正しく初期化されたかどうかを検証したりすることができます。

このようにして、Mockitoを使用してSpring MVCのコントローラのコンストラクタをモック化して、テストを実行することができます。
【図解】ロボットアームの動作計画【概要】

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/2a16e53b-2c6e-7484-cc4d-1b697be688dd.png)


:::note
こちらの記事は，[ロボティクスの辞書的な記事（にしたい記事）](https://qiita.com/akinami/items/eb0741b0d9c322e5d5ec)のコンテンツです．
:::

お疲れ様です。秋並です。

この記事では「ロボットアームの動作計画」について解説します。

# 動作計画とは

ロボットアームの動作計画 (motion planning) とは

- 障害物と衝突しないような「初期姿勢」から「目標姿勢」に至る動作を生成すること

になります。[^1]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/c5847195-6aa3-8bd3-dcdb-7db1543c576b.png)


# 動作計画の解法

動作計画には、以下のような幾つかの解法があります。

各解法については、説明が長くなるのでそれぞれ別の記事で説明します。

- タスク空間(task space) における動作計画：「タスク空間における動作計画」では、タスク空間上で「初期手先位置$\vec{P}\_{\mathrm{start}}$」と「目標手先位置$\vec{P}\_{\mathrm{goal}}$」を結ぶ軌道を求める
- コンフィギュレーション空間(Configuration space) を用いた動作計画：コンフィギュレーション空間上で「初期関節角度$\vec{Q}\_{\mathrm{start}}$」と「目標関節角度$\vec{Q}\_{\mathrm{goal}}$」を結ぶ軌道を求める
- 深層学習による動作計画

# 各手法のメリット·デメリット

各手法のメリット·デメリットは以下のようになります。

::: note
深層学習による動作計画については様々な手法があり、単純に比較できないので割愛します
:::

## タスク空間における動作計画

- メリット
    - タスク空間における軌道を求めるので、人間が**任意の手先軌道を指定することが可能**（動作計画法を用いることで、自動的に軌道を求めることも可能）
- デメリット
    - **逆運動学を何度も解く必要**がある（手先軌道の長さ分）

## コンフィギュレーション空間上を用いた動作計画

- メリット
    - コンフィギュレーション空間上で軌道を求めるため、**逆運動学を計算する回数が少なくて済む**（「初期関節角度$\vec{Q}\_{\mathrm{start}}$」と「目標角度$\vec{Q}\_{\mathrm{goal}}$」の2回だけでよい）
- デメリット
    - コンフィギュレーション空間上で軌道を求めるため、タスク空間において**どのような手先軌道になるか、実際に動かしてみないと分からない**

「タスク空間における動作計画」と「コンフィギュレーション空間を用いた動作計画」を比較すると下動画のようになります。

![Untitled.gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2030125/7710c90a-81ee-9927-d4ca-9a8721d7adc8.gif)

<br>

どちらの手法が良いかは一概には言えませんが、個人的なイメージとしては以下のような使い分けになるかなと思っています。

- タスク空間における動作計画：任意の軌道を描くように手先位置を制御したい時
    - 例：ペンを持って絵を描く
- コンフュギュレーション空間を用いた動作計画：単に、障害物にぶつからないように「初期手先位置$\vec{P}]\_{\mathrm{start}}$」から「目標手先位置$\vec{P}\_{\mathrm{goal}}$」まで移動させたい時
    - 例：A地点からB地点までぶつからないように物を運びたい

<br>

ちなみに、ROSで採用されているロボットアームの動作計画用フレームワークである「[MoveIt!](https://moveit.ros.org/)」では「コンフィギュレーション空間を用いた動作計画」が採用されています。

# 最後に

今回は、ロボットアームの動作計画の概要について説明しました。
次回は、「タスク空間における動作計画」の具体的な手順について解説します。

この記事が少しでも皆さんのお役に立てれば幸いです。

[^1]: 「動作計画」という言葉は「動作を計画する」という割と大雑把な単語なので、書籍や論文によっては意味合いが若干異なることがあります。今回紹介している「動作計画」の定義は一般的ではあると思いますが、あくまでこの記事内での定義であるということにご注意ください。
NLBっていつ使うの？

皆さんお疲れ様です。
社会人2年目になりました。翔太と申します。
今回は、自分自身ちゃんと理解していなかったAWSサービスの一つであるNLBの以下の点について説明していきたいと思います。
間違っていたらご指摘お願いします。
- NLBって何？
- ALBと何が違うの？
- どこが良くていつ使うの？

# ELBとは何か？
ここでは本筋じゃないので簡単に言うと、負荷分散を行うための機能を提供しているフルマネージドサービスです。
その種類としてあげられるのが以下の2点となります。
・ALB(Application Load Balancer)
・NLB(Network Load Balancer)
・CLB(もう今使われていないので、割愛)

# ALBとは何か？
ALBとは、負荷分散の中でもアプリケーション層(L7)で負荷分散を行う機能を持ったフルマネージドサービスです。
例えばですが、ブラウザにて、検索をかけ、どこかのサイトのURLにアクセスするとサイトが表示されますよね。
この際にサイトが表示される簡単な流れとしては以下のような流れとなっています。
1. URLのドメインからDNSサーバーが名前解決をして宛先のサーバーの住所(IPアドレス)を特定する
1. 特定したIPアドレスに向けてサイトの情報をくださいとリクエストを送る
1. サーバーに繋がるとリクエストされたサイトの情報をレスポンスとして返す
1. ブラウザがレスポンスとして返されたHTMLファイルなどを解析してサイトを表示する

この際に、サーバーが一つだと、もしそのサーバーがなんらかの原因でダウンしてしまった時にサイトが表示されなくなってしまいますよね？
そこで使われるのが、ALBというわけです。
ALBは、Auto Scalling機能などと一緒に使われ、サイトを表示する際に以下のような機能を持っています。

- ヘルスチェック
    - サーバーが正常に起動している、接続することができるかのチェック
    - 正常でなければ他方のサーバーにのみ接続する
- 負荷分散
    - 負荷を割合などで複数サーバーへとリクエストを振り分けるなど

これらの機能によって、可用性を高めることができるというのがALBの主な特徴となります。
まー他にも機能はあるのですが、本題ではないので、ここも割愛します。

# NLBとは何か？
本題のNLBです。
NLBも負荷分散を行うフルマネージドサービスです。

## ALBと何が違うの？
ALBと違う点としては、サービス内容において違う点はありますが、本質的に違うこととしては、トランスポート層(L4)で機能するロードバランサーであるということです。

## ALBと比べて何が良くていつ使うの？
### ALBと比べて何がいいのか？
結論から言うと、ALBよりも低レイテンシー(リクエストからレスポンスまでの時間が短い)であると言うことです。
つまりは、ALBより負荷分散の処理が速いと言うことですね。
なぜALBより処理が速いかと言うと、NLBはL4で動作しており、ALBのL7のような少し処理の重い機能(コンテンツベースのルーティングやCookieを使ったスティッキーセッションなど)を行う必要がありません。
これによって、NLBはALBよりもパケットレベルでの処理が効率的なため、処理速度が速いんです。


### どういうシチュエーション使うの？
ではどんな時に使うの？って話になると思います。
NLBはALBと違い、L7をサポートしていませんので、クライアント(ブラウザ)からリクエストを複数サーバーへと負荷分散するようなことはできません。
NLBが真価を発揮するのは、以下のような時です。

- フロントエンドサーバーからバックエンドサーバーへのリクエストを送る際の負荷分散
- バックエンドサーバーからデータベースへのリクエスト
- 静的IPアドレスを利用したリクエストの負荷分散

例えばですが、以下のような場合に役に立ちます。

- フロントエンドサーバーから複数のバックエンドサーバーに負荷を分散したい場合 
- バックエンドサーバーからデータベースに多くのリクエストを短時間で処理したい場合(例：1秒間に100万件のリクエスト)
- 大量のEC2へのリクエストに対する負荷分散

いかがでしたでしょうか？
大雑把かもしれませんが、上記の説明で少しは、NLBの使い所やALBとの違いを感じることができたんではないでしょうか？
今後もこういった記事を作成していこうと思うので、よかったら見てやってください。
DateTimeのズレ

# sqlで範囲検索するとずれる
```rb
irb(main):073:0> a = DateTime.now
=> Fri, 10 May 2024 00:45:56 +0900
```
```rb
irb(main):076:0> Model.where(created_at:b .. a)
  Model Load (0.5ms)  SELECT `models`.* FROM `models` WHERE `models`.`created_at` BETWEEN '2024-05-03 00:00:00' AND '2024-05-09 15:45:56.557590'
=> []
```
```Fri, 10 May 2024 00:45:56 +0900```が```'2024-05-09 15:45:56.557590'```になっている。

9時間前になる。
```+0900```が９時間前になっているからだと思う。```+0000```すると時差が解消される

```rb
irb(main):078:0> a = "#{DateTime.now.to_date} 23:59:59 +0000"
=> "2024-05-10 23:59:59 +0000"
irb(main):079:0> Model.where(created_at:b .. a)
  Model Load (0.5ms)  SELECT `models`.* FROM `models` WHERE `models`.`created_at` BETWEEN '2024-05-03 00:00:00' AND '2024-05-10 23:59:59'
=> []
```
```"2024-05-10 23:59:59 +0000"```が　```'2024-05-10 23:59:59'```になっている。

# 感想
今更DateTimeのことを知った。
十六銀行アプリをインストールしているAndroid端末でマイナポータルへログインできない

マイナポータルにログインするたび、すぐにログアウトされてしまい困っていました。
問い合わせようとスクリーンショットを撮影していた時に、原因に気づくことができましたので記録します。

原因は見出しの通り、地銀アプリとマイナポータルの組み合わせで、症例としては極めて少ないものかと思われます。

# 症状: マイナポータルに表示されるエラーメッセージ

![取得できませんでした 他の端末やブラウザなどでログインされたためログアウトしました。 OK](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667945/d342e577-fd45-8ab4-73be-f7ae50f1b792.png)

取得できませんでした
他の端末やブラウザなどでログインされたためログアウトしました。
OK

エラーが発生しました
undefined
OK

エラーが発生しました
問題が発生しました。
（エラー番号：EL0231）
OK


::: note
一般的な EL0231 エラーの対処方法は下記をご覧ください
https://faq.myna.go.jp/faq/show/5287?category_id=13&site_domain=default
:::


# "標準ブラウザ監視(十六銀行)" をオフにする
1. "設定" アプリを開く
2. "ユーザー補助" をタップ
![Screenshot_20240509-231609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667945/5db8dba3-d44c-6fe3-da65-71654e49c125.png)
3. "標準ブラウザ監視(十六銀行)" をタップ
![Screenshot_20240509-231555.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667945/2fb3d814-cb2c-a509-4257-531506912f1d.png)
4. "標準ブラウザ監視(十六銀行)" のスイッチをタップし、"OFFにする" をタップ
![Screenshot_20240509-231622.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667945/ea223f66-03f9-30ee-d2c7-239e9e2fb6ef.png)

本設定以降、十六銀行アプリによる偽サイトへのアクセス時の警告等は行われません。
必要に応じて、Webレピュテーション可能なブラウザー・外部アプリの導入を検討してください。

もしかしますと上記以外にも原因があるのかもしれませんが、経過観察していきます。
[React＋AWS]で楽天連動家計簿を作ってみた

# ざっくり概要
生活していて日々出ていくお金の分析をしたかったので、家計簿アプリを作りました。
今回作ったアプリで譲れなかった要件は、ざっとこんな感じです。
* 基本的なデータの登録・削除・編集機能
* 複数端末（PC・スマホ）から触れること
* 楽天の利用履歴（楽天Payやクレジットカードを想定）と連携できること

趣味で作っただけなので、細かい設計はしてません。とにかく手を動かそうという発想で始めました。
WebアプリにしてDBを使わなければいけないのはいいとして、まず要件にある楽天の利用履歴うんぬんの話ですが、これは楽天で決済した際に送られてくるメールを分析してDBに取り込むというものです。
私個人はGmailを使ってますので、Gmailを分析できればいいやとなりました。

以下、このアプリを作る上で考えたこと、苦労したこと、完成したものについて述べます。（コードについては触れません。考え方のみです）

# 第1弾：GASで作ってみようの巻
一番最初に思いついたのは、GAS（Google Apps Script）を使うという手法です。
実際に、ドライブ上のスプレッドシートにWebアプリからアクセスして家計簿情報を記録するという方法でアプリを作ってみました。Googleのサービスなので簡単にメールとも連携できていい感じでした。

しかし、しばらく使っていく中でどうしても看過できない欠点がありました。
それは、、**DB（スプレッドシート）へのアクセスが遅い！**
少しの書き込みをするにも5~10秒程度待たなければいけないような状況です。
どうしたら早くアクセスできるかと考えて、AWSを使ってみようという結論に至りました。

# 第2弾：AWSで作ってみようの巻
まず、AWSにて作ってみた構成が以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779819/c1723e45-ecaa-b380-a65e-162dc0cf71d4.png)

家計簿のデータ自体はDynamoDBに保存しており、Webアプリ（TypeScriptで記述）からSDKを通してDBにアクセスします。
GAS時代と比べると、DBへのアクセスは格段に速くなりました。1秒あれば書き込みが終わります。これでDBについてのストレスはなくなりました。

一般的な家計簿アプリから少し踏み込んだ内容である楽天決済の連携については、先ほども申し上げた通りGmailの本文を分析してデータを登録しています。EventBridgeを用いて毎日夜中にバッチ処理を走らせ、DBに明細情報を自動で追加するような設計としています。

また、以前は作成したWebアプリのURLを開くと直接サービスが利用できるような状態でしたが、せっかくAWSを使うようになったのでCognitoと連携してログイン認証ページを通過してからでないとサービスを利用できない設計にしました。
基本的にこのサービスを使用するのは私だけなのですが、ログインページを作ったことで架空の明細情報なども入力できるようになりました。自分が作ったサービスを紹介するハードルが下がります(笑)

次に、完成したアプリについて画像とともに簡単にみていきます。

以下の画像のように、日ごとに明細情報（タイトル、金額、支払方法、カテゴリー）を記録できます。各レコードは裏で一意の識別番号を持っていますので、画面に表示される項目がすべて同一のレコードも当然区別できるようになっています。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779819/c1d6562f-54ff-0803-b356-ca248f1e495b.png)

またこのように、月ごとに明細を集計してどのカテゴリーにいくら使ったか表示できます。これはDBからのデータの取得時に集計を行い、グラフライブラリを用いて表示しています。
![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779819/161c11f2-d806-315e-dd48-d12722bc68ba.png)

# 苦労したこと
まず今回は、TypeScript＆Reactという今まで使ったことのない言語やライブラリで開発を始めたため、その仕組みの部分を理解するのがなかなか大変でした。とはいえWebアプリを開発するうえでは知っておいた方がいい部分でもあったと思うので、勉強してよかったです。その点ではAWSについてもまったく触ったことがなかったですが、一つアプリを作るだけでも以前よりはだいぶ理解が進み、自分にとってはブラックボックスだったところに少しずつ白が混ざってきました。
また、Gmailとの連携の部分も意外に大変でした。GASではまったく何も考えなくても完成してしまうぐらい簡単に連携できたのですが、外部のサービスからのAPI連携は本文へのアクセスの仕方などでちょっと工夫がいりました。
フロントエンドの基本的な部分は、Webサイトを作ったことが何回もあったのであまり苦労しませんでした。

# 今後の目標
現在のところ、データの編集や表示に関わる操作をするときにはDBから全件取得を都度行っています。しかしDynamoDBの制約で、APIをたたくとき一度に取得できるデータ量が1MBまでと決まっているようですので、レコードがどんどん増えた時にどうやって取得しようかと考えているところです。月ごとの金額の推移を表示しなくていいのなら、月ごとに取得するような方法もあるかと思いますが、わりとマストな機能ですのでそういうわけにもいかず、、

あとそれに関連する点として、今のままだとデータ件数が増えるほど編集や表示に要する時間が増えていきますので、AppSyncあたりを活用してWebアプリ読み込み時に一度だけ全件取得してあとは部分的に更新みたいな方法ができないかというのを考えていきたいです。（全然使ったことがないのでトンチンカンなことを言ってるかもしれませんが笑）