OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter初学者向けのおすすめ学習方法

## はじめに
この記事では、今年の3月頃からFlutterの学習を始めた自分が参考にしてきたサイトや勉強方法を紹介していきたいと思います。

## ミクシィ22新卒技術研修
ミクシィさんが公開しているFlutter研修動画では、プロジェクトの作成からウィジェットの解説など、全くFlutterを知らない人でも理解できるペースで進んでいく動画になっているため、初学者の方にとてもおすすめです！
<iframe width="560" height="315" src="https://www.youtube.com/embed/oQCJZFqDwIo?si=KFbjIdekWCteqo15" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## Flutter Doc JP
このサイトはFlutterの基本的なウィジェット等の使い方を日本語で解説し、まとめてくれています。コードだけでなく実際の画面も一緒に表示して解説してくださっているため、視覚的にわかりやすくとてもお世話になっていました。
https://flutter.ctrnost.com/
![](https://flutter.ctrnost.com/images/top_thumnail.png)

## flutter-study.dev
このサイトではTODOアプリやFirebaseの使用したアプリなどのより実践的なコードの解説をしてくださっているため、基本的なウィジェットは大体覚えて、そろそろ手をもっと動かしてアプリを作ってみたいと思った方におすすめです。
https://www.flutter-study.dev/
![](https://www.flutter-study.dev/images/top/top-steps.png)

## YouTubeチャンネル　「ルビーDog」
ルビーDogさんは数々のFlutterに関する動画をアップロードしているチャンネルです。一本一本の動画は短いですが、とても聞き取りやすく内容がわかりやすく参考になるものばかりなのでおすすめのチャンネルです！

<iframe width="560" height="315" src="https://www.youtube.com/embed/GN6HXSrObzg?si=bfHxtnea8MYnlMs_" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

## Flutter大学
最後はYouTubeチャンネルやコミュニティの運営をしているFlutter大学です。紹介するまでもないかと思いますが、特にYouTubeチャンネルのkboyさんやこんぶさんによるノーカットでのコーディング風景や、Flutter大学内で行われている共同開発では、より業務に近いチームでの開発を経験することもできるため、時間にゆとりのある方はぜひ参加してみると良いかと思います！
<iframe width="560" height="315" src="https://www.youtube.com/embed/qLUT2qMCQ1Q?si=6iLwAyuuaclCWAWm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
pythonでFigの作成（細かい設定）

# pythonでFigを作る際によく使うコード
<b>※随時更新</b>

<br>すごいサイト。イメージに合う可視化方法を探してコードを知りたいときにとても便利。

https://www.data-to-viz.com/

matplotlibにおける`fig`, `ax`の概念について勉強になる記事。
https://python-academia.com/matplotlib-plt-ax/
https://qiita.com/skotaro/items/08dc0b8c5704c94eafb9

# 基本構文
```python
fig = plt.figure(figsize=(6,4)) #figsizeを指定せずplt.figure()でもOK
ax = fig.add_subplot(1,1,1)

##ここにFigを描画するコードを書く。

plt.show()
```
複数並べる際は、
```python
fig = plt.figure(figsize=(6,8)) #figsizeを指定せずplt.figure()でもOK

ax1 = fig.add_subplot(2,1,1) #縦2個、横1個の1個目
##ここにFigを描画するコードを書く。

ax2 = fig.add_subplot(2,1,2) #縦2個、横1個の2個目
##ここにFigを描画するコードを書く。

plt.show()
```
こっちでもいける、
```python
fig, axes= plt.subplots(2,2)   # axesはAxesオブジェクトの2x2の配列

axes[0][0].plot(#####)
axes[1][0].plot(#####)  #Axesオブジェクトは行・列で呼び出せる

plt.show()
```


# 軸関係
### 軸ラベルの表示
```python
ax.set_xlabel("x軸ラベル名")
ax.set_ylabel("y軸ラベル名")
```

### 軸の値を消す
```python
ax.xaxis.set_ticklabels([])
ax.yaxis.set_ticklabels([])
```

### 軸の最大値・最小値の設定
```python
ax.set_xlim(最小値, 最大値)
ax.set_ylim(最小値, 最大値)
```

### 目盛の表示値を変更
```python
ax.set_xticks(###)
ax.set_yticks(###)

### [0, 500, 1000]
### np.arange(0, 1001, 500)
### [] 非表示

#文字列で表示したい場合は2行で書く
ax.set_xticks([0, 500, 1000])
ax.set_xticklabels(["zero", "five hundred", "thousand"])
```

### 対数目盛に変更
```python
ax.set_xscale('log')
ax.set_yscale('log')
```
### 軸の線を消す
```python
ax.spines['right'].set_visible(False) #右
ax.spines['top'].set_visible(False) #上
ax.spines['left'].set_visible(False) #左
ax.spines['bottom'].set_visible(False) #下

```
### 軸の目盛り線を消す
```python
ax1.tick_params(bottom=False, left=False, right=False, top=False)
```
### 全部消す
```python
ax.axis("off")
```

# 文字サイズの設定
```python
ax.tick_params(labelsize=12)
```

# legend関係
### legendを非表示にする
```python
plt.legend([], [], frameon=False)
ax.legend().get_legend().remove()
```

### legendを表示する
```python
plt.legend()
ax.legend()
```

# タイトル関係
### タイトルをつける
```python
plt.title('Title')
ax.set_title('Title', fontsize=30)
```
### タイトルの位置を変更する
```python
ax.set_title('Title_left', loc='left')
ax.set_title('Title_center', loc='center')
ax.set_title('Title_right', loc='right')
```
### 全体のタイトルをつける
```python
fig.suptitle("全体のタイトル")
```
# 複数のfig, axをいい感じに配置する
```python
fig.tight_layout()
```
# 
```python

```
# 
```python

```
# 
```python

```
# 
```python

```
# 
```python

```
# 
```python

```
# 
```python

```
【Python】座標圧縮ライブラリをつくろう

座標圧縮は頻出ですが、値の復元はなんとなく億劫になりがちなのでもろもろライブラリ化しました。

# 1 次元の場合
```py
class Compress:
  def __init__(self, arr):
    values = sorted(set(arr))
    self.translator = dict([(values[i], i) for i in range(len(values))])
    self.inv_translator = values

  def to_comp(self, x):
    return self.translator[x]

  def from_comp(self, v):
    return self.inv_translator[v]
```

`to_comp`: `arr` に登場する値を入れると、圧縮後の値が返ってくる
`from_comp`: 圧縮後の値を入れると、対応する `arr` の値が返ってくる

点列の圧縮から、多次元座標列の圧縮に拡張することもできます。

# 2 次元の場合
```py
class Compress2D:
  def __init__(self, arr):
    self.x = Compress([x for x, y in arr])
    self.y = Compress([y for x, y in arr])

  def to_comp(self, x):
    return (self.x.translator[x[0]], self.y.translator[x[1]])

  def from_comp(self, v):
    return (self.x.translator[v[0]], self.y.translator[v[1]])
```

2 次元座標列が与えられた時、それぞれの座標軸で圧縮を行います。

`to_comp`: `arr` に登場する座標を入れると、圧縮後の座標が返ってくる
`from_comp`: 圧縮後の座標を入れると、対応する `arr` の座標が返ってくる

## 例題
<details><summary>ネタバレ</summary>
二次元の座標圧縮を行う

https://atcoder.jp/contests/abc168/tasks/abc168_f

</details>


# おわり
座標圧縮してセグ木に載せてまた戻すところまでをライブラリに
大学からプログラミングを始めてゲームエンジニアになるまでの話

## 大学からプログラミングを始めてゲームエンジニアになるまでの話

こんにちは、趣味でゲーム開発をしているCOCOです。
今回は僕がゲームエンジニアとして内定を頂くまでのやってきた活動や考えていたことを書こうと思います！

:::note info
#### 本記事の主な対象者
* 大学からプログラミングに触れ、ゲームエンジニアを目指す人
* ゲームエンジニア就活の一例を知りたい人
* エンジニアかプランナーかで迷っている人
:::

## 目次
* [著者について](#著者について)
* [入学から内定までの軌跡](#入学から内定までの軌跡)
* [実は就活中ギリギリまで職種を悩んでいた話](#実は就活中ギリギリまで職種を悩んでいた話)
* [面接対策](#面接対策)
* [まとめ](#まとめ)

## 著者について
### 著者の現在

* 名前　：COCO
* 所属　：情報系の学科に通う大学生
* 内定先：モバイルゲーム開発を主に行っている会社
* 職種　：クライアントエンジニア

### 大学入学前の著者はどんな人？
* 大学入学前はどちらかというと体育会系で、スポーツばかりしていた（もちろんゲームも好きでした）
* モノづくり自体は好きで工作はたまにしていた
* 大学までPCすらまともに触ったことがなかった

こんな感じで、大学で情報系の分野を学ぶまではプログラミングの知識は皆無でした。。
でも、意外とそういう人は多いんじゃないでしょうか？少なくとも僕のいる学科では似たような人が結構いました。
じゃあどう過ごしてきてエンジニアとしての内定をいただくに至ったのか？についてを以降では書いていきます！あくまで僕の話をするだけなので、こういう人もいるんだという参考程度に読んでいただきたいです！

## 入学から内定までの軌跡
何はともあれまずは自分がどう過ごしてきたかざっくりと以下に載せます。

![スクリーンショット 2023-12-17 152048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2401352/3e714fea-059c-aea7-34fd-d99c646bc783.png)

こんな感じです。こうやって書き出してみると大学生活ってほんと短いですね～。就活も大事ですけど大学はそれだけじゃないってことを一度思い出してから以下読んでください！笑

上図の主要なイベントについて補足で説明します。
大学2年次に出したコンテストは、ゲームクリエイター甲子園（通称GC甲子園）という学生向けのゲームコンテストでした。こちらのコンテストには本当にお世話になりました！以下は2023年版のサイトです。

https://game.creators-guild.com/gck2023/

このGC甲子園経由で、当時自分がはまっていたVRゲームを開発しているVRゲーム会社の方からありがたいことに長期インターンのオファーをいただきました！このVRゲーム会社の社員さんから、最終的に内定を頂く会社の短期インターンを紹介していただいたので、すべてのきっかけとなったGC甲子園には感謝です。

## 実は就活中ギリギリまで職種を悩んでいた話
ゲームを個人規模で開発していたので、普段から企画と開発両方に携わっていたのもあり、いざ就活だ！となると自分は企画側がやりたいのか、開発側がやりたいのか分からなくなっていました。

なので大学3年の夏ではプロモーション/マーケティングのインターンやゲームプランナーとして短期開発を行うインターンなどに参加してみました。

こんな感じで色々インターンで実際に活動しているうちに、どれも楽しくはあったんですがやはり自分は実際に手を動かしてモノづくりをすることが今は好きであること、エンジニアでも企画側に携われる会社があることを知り、最終的にエンジニアとして就活をしました！

同じように職種に悩んでいる方は実際にインターンを体験してみて、その職種が自分に合っているか見てみるのはおすすめです！

## 面接対策
面接でスムーズに自分のことを伝えられるように面接直前では以下5点をまとめていました！
1.　なぜその職種を選んだのか
2.　将来どんな人物になりたいか
3.　なぜその会社なのか
4.　現在の自分の弱みとその対策
5.　これまでやってきたことのまとめ

特に1、2、3については自分のこれまでの体験に紐づけて考えると、面接で大抵のことを聴かれても説得力のある回答がしやすくなる（と僕は思っています）

### 各項目の詳細
上の1～5の面接対策について、自分なりに考えたものを少し書きます。

**1.　なぜその職種を選んだのか**
**2.　将来どんな人物になりたいか**

この2項目に関しては、面接までに参加してきたインターンでの経験をもとに考えました。インターンでこういう経験をし、自分はこう感じたのでこの職種を志望しました、みたいな感じですね。

**3.　なぜその会社なのか**

自分の場合は、その会社のインターンに参加したときに感じた雰囲気や環境について主にまとめました。やっぱり面接を受ける会社のインターンに参加しているとその経験を絡めて話せることが増えるのでおすすめです。

それと企業理念についても調べておくと良いかもです。自分はこういう経験があり、こう考えているので、御社の企業理念に共感しています！が言えるようになる。

**4.　現在の自分の持つ課題とその対策**

これについては項目名の通りです。当時自分が抱えている課題とその対策をまとめていました。一応以下にその例を記載します！
* 現状Unity以外のスキルが乏しい
➡UnrealEngineにてゲームを何本か制作し、スキルの幅を広げようとしている
* コンピュータサイエンスに関する知識が乏しい
➡教本を買い、とりあえず一部だけでも理解して面接時に勉強していることを話せるようにする

という感じです！自分の弱みを把握していて、それを克服するための行動を起こしている or 計画があることを伝えられると、将来性もアピールできるかなと思います！

**5.　これまでやってきたことのまとめ**

単純に自分がやってきたことをすぐに話せるようにするための整理です。ちなみに僕の場合は
* ゲームを制作してきて苦労したこと、その解決策
* 共同制作ではどんな役回りをしたか
* 大学で学んできたこと
* サークル活動の内容

という感じでした！

## まとめ
というわけで、大学からプログラミングを始めたとある人間のゲームエンジニアとして内定を頂くまでのお話でした。
大学入学後に頑張ったとはいえ、やっぱりもっと前からプログラミングを始めていた人とかに比べると僕の技術力は全然高くないです。それでも内定を頂けたということは、少なくとも新卒は技術力以外にも見てもらえる要素がたくさんあるということだと思います。技術力に関して上を見るとキリがない業界だとは思いますが、それ以外のところも大事にしていきたいですね。
PowerShellに喋ってもらう

初期化

```powershell
Add-Type -AssemblyName System.Speech
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
```

喋る

```powershell
$synth.Speak('エル・プサイ・コングルゥ')
```

## 設定

```powershell
# 速さ (-10 ～ 10) デフォルトは0
$synth.Rate = 3

# 音量 (0 ～ 100)
$synth.Volume = 100
```

### 声を選ぶ

声一覧を表示 といってもデフォルトじゃ2つしかない

```powershell
$synth.GetInstalledVoices().VoiceInfo | Select-Object -Property Name, Culture, Gender, Age
```

> ```
> Name                     Culture Gender   Age
> ----                     ------- ------   ---
> Microsoft Haruka Desktop ja-JP   Female Adult
> Microsoft Zira Desktop   en-US   Female Adult
> ```

```powershell
# 声を選択
$synth.SelectVoice("Microsoft Haruka Desktop")
```

## 関数作っておく

`code $profile`に書き込んでおく

```powershell
function say {
  param(
    [Parameter(ValueFromPipeline=$true)]
    [string]$InputString
  )

  process {
    if (!$synth) {
      Add-Type -AssemblyName System.Speech
      $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
      $synth.Rate = 2
    }
    if ($InputString) {
      $synth.Speak($InputString)
    } else {
      Write-Host "文字列を渡してください"
    }
  }
}
```

引数でもパイプでも渡せる

```powershell
# 引数で渡す
say hello

# パイプで渡す
"はろー" | say
```

TODO: VOICEVOXでずんだもんでも喋ってもらえるようにしておきたい
【環境構築】PowerShell上でC#やF#のスクリプトをコンパイルする

# 目標
```: PowerShell
> & csc .\Hello.fs
Microsoft (R) Visual C# Compiler バージョン 4.7.0-3.23416.8 (43b0b05c)
Copyright (C) Microsoft Corporation. All rights reserved.
> ./Hello
Hello, C# World!
```
```: PowerShell
> & fsc .\Hello.fs
Microsoft (R) F# Compiler バージョン F# 7.0 のための 12.7.0.0
Copyright (C) Microsoft Corporation. All rights reserved.
> ./Hello
Hello, F# World!
```
というようにコンパイルできるように設定します。
<details><summary>スクリプト</summary><div>

```cs: Hello.cs
using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Hello, C# World!");
    }
}
```
```fsharp: Hello.fs
printfn "Hello F# World"
```
</div></details>

# 方法
### Visual Studio 2022 Developer Command Prompt を立ち上げる
「Windows」キー＋「Q」キーで検索窓を立ち上げて、「Developer Command Prompt」と入力します
### whereコマンドを使って、csc.exeとfsc.exeのパスを特定します
```: Developer Command Prompt
>where csc
C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\Roslyn\csc.exe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe
```
```: Developer Command Prompt
>where fsc
C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools\fsc.exe
```
### 「環境変数を編集」を開き、変数のPathにこれらのパスを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/f8f94608-4d27-8ae9-566e-233e4b80c639.png)

# 注意
Visual Studio にF#がインストールされていない場合は先にインストールしてください。
以下のリンクなどが参考になると思います。

https://learn.microsoft.com/ja-jp/dotnet/fsharp/get-started/install-fsharp#install-f-with-visual-studio-code


以上です！
MATLAB Flipbook Mini Hack に参加して ～ 2000文字でアニメーション

[<B>MATLAB/Simulink Advent Calendar 2023</B>](https://qiita.com/advent-calendar/2023/matlab)に参加しました。

カレンダー2の12/21分として追加しました。

・使用ツール
<dt>　MATLAB</dt>
<br>

<H4><a href="https://note.com/leftbank/n/n6b7b262cfc1a"</a> [<B>note</B>]にUpしました。</H4>
Dockerコンテナ内とローカルでMakefileの実行コマンドを切り替える方法

VSCode Dev Containerで、Makefileの内容をコンテナ内で作業しているときと、ローカルにいるときで分けたくなりました。

prefixをつけて別コマンドとしても良いですが、同じ動作を期待するなら自分がコンテナかローカルのどちらにいるかを気にせずに、同じコマンドで動いたほうがいいですよね。

私はMakefileについてはど素人だったので、色々手探りで実装してみました。

## TL;DR
```Makefile
ifeq (,$(wildcard /.dockerenv))
	@echo "I am not in docker"
else
	@echo "I am in docker"
endif
```

## Makefileで条件分岐をする
基本的な構文として`ifeq` `else` `endif` が使えます。他のプログラミング言語とほとんど同じです。
```Makefile
ifeq (AAA, BBB)
    @echo "true"
else
    @echo "false"
endif
```
このコードでは`AAA`=`BBB`のとき、`true`が出力され、それ以外のときに`false`が出力されます。

## プロセスがDockerコンテナで動いているかを判定する
いろいろ方法はあるらしいですが、`/.dockerenv` ファイルの存在確認をするのが早そうです。
ただし、Makefileでファイルの存在を確認するときは少しトリッキーな方法が必要です。

`wildcard`という関数があり、本来はワイルドカード`*`を利用し特定の拡張子を持つファイルをすべて展開するためのものです。

この関数をワイルドカードを使わず単にフルパスで用いると、ファイルが存在するときはファイル名を、なければ空文字を返しますので、ifeqで分岐に使えます。
```Makefile 
ifeq (,$(wildcard /.dockerenv)) # /.dockerenv ファイルが存在しない場合
```

## おまけ
`ifeq (,$(wildcard /.dockerenv))` はファイルが **存在しない** 場合なので、存在するときのみ処理を行いたいときは `ifneq (,$(wildcard /.dockerenv))` とするとよいです。
turtlesimの亀をなるべく簡単にたくさん出したい

# はじめに
`turtlesim`の亀をたくさん出したいです。一匹だけでは寂しいので。そしてなるべく簡単に出せたら嬉しいと思います。

# ノードを起動
とりあえずノードを立ち上げてみます。

```sh
ros2 run turtlesim turtlesim_node
```

青い背景に亀が配置されたウインドウが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/b64c30f6-dfc9-6b27-ff41-23900ce00861.png)

やっぱり一匹だけなので寂しいですね。

# 亀をたくさん出す
乱数で位置と姿勢を決めつつ、100匹の亀を配置します。

```sh
awk 'BEGIN{for(i=0;i<100;i++){print rand()*10.0,rand()*10.0,rand()*6.28}}' | xargs -n3 bash -c 'ros2 service call /spawn turtlesim/srv/Spawn "{x: $0, y: $1, theta: $2}"'
```

いい感じに亀を配置できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/d699804b-e3cb-af81-7ffa-a81740c544eb.png)

どことなく亀も楽しそうですね。

ちなみに1000匹の亀を配置するとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/7f1e1969-2616-f543-2c14-6e0cb77aeaf9.png)

乱数の範囲を間違えましたが、綺麗なので良しとします。

# おわりに
`turtlesim`は奥が深いですね。
【Python】openai と streamlit で AI チャットアプリ

よくあるネタです。

# コード
```main.py
import streamlit as st
import pandas as pd
from openai import OpenAI

client = OpenAI()

class ChatPage:
  def setup(self):
    def post_completion(message):
      return client.completions.create(
        model="gpt-3.5-turbo",
        prompt="あなたは未知の言語 A で会話をするロボットです。ユーザへの返答は常に未知の言語 A を使って行ってください。\n\nユーザ: {message}\n\nロボット: "
      )[0].message["content"]
    self.post_completion = post_completion

  def components(self):
    st.title("Chat")
    user_input = st.text_input("メッセージを入力: ")
    if user_input:
      response = self.post_completion(user_input)
      st.text_area("返答: ", value=response, height=200)

page = ChatPage()
page.setup()
page.components()
```

https://qiita.com/lowking/items/906e5e1890cdc88394a3

これと同じタイプの実装です。
`setup` で関数を定義して `components` で定義したコンポーネントで呼び出しています。

`OPENAI_API_KEY` が環境変数にあれば、OpenAI の client は勝手にそのキーを使用します。

# おわり
関心の分離が難しい。大きなアプリを作るのには向かないかもしれない。
【img2pdf】アスペクト比がばらばらな画像をPDF化

## 概要
アスペクト比や画像幅がばらばらの画像をPDF化したいのでimg2pdfとPILで実装してみた。
（専用ツールを使うのがめんどくさい人向けです）

## まずはディレクトリ内の画像を一括PDF化してみる
img2pdfを使用しPDF化してみます。
このコードだけだとmacのプレビューのような余白はなく、また画像の横幅にばらつきがある場合がたつきのあるPDFになります。
```python:jupyter notebook
import os
import re
import img2pdf

def convert_images_to_pdf(directory):
    # 並び替えて画像を取得
    image_files = sorted(
        [
            os.path.join(directory, filename)
            for filename in os.listdir(directory)
            if filename.lower().endswith(('.png', '.jpg', '.jpeg'))
        ],
        key=lambda x: [int(n) if n.isdigit() else n for n in re.split(r'(\d+)', x)],
    )

    if not image_files:
        print("指定された拡張子の画像ファイルは見つかりませんでした。")
        sys.exit(1)

    pdf_file_name = 'output.pdf' # 出力するpdf名
    pdf_bytes = img2pdf.convert(image_files)
    with open(pdf_file_name, "wb") as f:
        f.write(pdf_bytes)

    print("PDFファイルが作成されました。")

directory = '/path/to/input_directory/' # 画像が保存されているディレクトリパス
convert_images_to_pdf(directory)
```

## 予め、画像サイズを全て揃えて余白をつける
PILを使用し、PDF化する前にディレクトリ内の画像を編集します。
```python:jupyter notebook
from PIL import Image
import os

def resize_image(image_path, target_width=800, margin=10):
    with Image.open(image_path) as image:

        old_width, old_height = image.size # 元画像のサイズを取得
        target_height = int((target_width / old_width) * old_height) # リサイズ後の高さを計算

        # 新しいサイズの画像を作成し、余白を含める
        resized_image = Image.new("RGB", (target_width, target_height), (255, 255, 255))
        resized_image.paste(image.resize((target_width - 2 * margin, target_height - 2 * margin)), (margin, margin))
        return resized_image


def resize_images(input_directory, output_directory, width=800):
    os.makedirs(output_directory, exist_ok=True)

    # ディレクトリ内の画像ファイルを取得
    image_files = [
        f
        for f in os.listdir(input_directory)
        if os.path.isfile(os.path.join(input_directory, f))
        and f.lower().endswith((".jpg", ".jpeg", ".png"))
    ]

    # 画像をリサイズして新しいディレクトリに保存
    for image_file in image_files:
        # 画像のパスを取得
        image_path = os.path.join(input_directory, image_file)
        
        # 横幅を指定した値に揃える
        resized_image = resize_image(image_path, width)

        # 新しい画像の保存パスを作成
        new_image_path = os.path.join(output_directory, image_file)

        # リサイズされた画像を保存
        resized_image.save(new_image_path)

    print("画像のリサイズが完了しました。")
    
input_directory = '/path/to/input_directory/' # 画像が保存されているディレクトリパス
output_directory = '/path/to/output_directory/' # リサイズされた画像が保存されるディレクトリパス
resize_images(input_directory, output_directory)
```

## リサイズしてpdf化
最後に作成した関数を合わせて実行します。
```python:jupyter notebook
resize_images(input_directory, output_directory)
convert_images_to_pdf(output_directory)
```

## 最後に
Pythonはできることが幅広い分、適当な専用ツールを探すことが疎かになっています。反省しなければ。
（プレリリース）Spring '24 個人的に気になるLightningページ周辺アップデート

# はじめに

Spring ’24のリリースノートが公開されましたね！リリースノートの中にLightningページ周りで気になったアプデートがあったので確認します。

https://help.salesforce.com/s/articleView?id=release-notes.rn_lab.htm&release=248&type=5

:::note warn
2023年12月現在Spring '24は、プレリリース組織での提供となってます。
:::

# 親オブジェクトの項目を配置可能に

取引先責任者のページを編集してみます。

## 1. 親オブジェクトを選択

主従関係項目、参照関係項目名の横に`>`という表示が増えています。

![取引先責任者-レコードページ-Lightning-アプリケーションビルダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/dba28af1-9490-d7f1-7702-329b16542ff4.png)

主従関係項目、参照関係項目名の横にある`>`を選択すると取引先の項目が表示されます。

![スクリーンショット 2023-12-21 0.56.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/048c84e0-efe1-8298-b8ce-4df05b2739d9.png)


:::note
なんと
**さらに親の項目も設置できます。**
:::

![スクリーンショット 2023-12-21 1.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/d10ae85c-ac8f-8f26-e86d-17f6842677ab.png)


## 2. 親オブジェクトの項目を配置

親レコードを何階層かたどることが用意になったことで
ある程度正規化したオブジェクト構成でもレイアウトの設定が容易になります。

![スクリーンショット 2023-12-21 1.09.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/263a4eb7-26d6-1247-beb2-63215328688a.png)

# 動的関連リストの表示ラベルにカスタムラベルが使用可能に

オブジェクトの表示ラベルを変更することなく、表示ラベルを変更できる
関連リストの表示ラベル名ですが、複数のページに設置すると設置する数分、
別の名前に設定する必要がありました。

今後はカスタムラベルを一箇所変更するだけで済みます。

![スクリーンショット 2023-12-21 1.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/09322e71-a126-1c4a-29c0-01be20993a60.png)

## 1. カスタム表示ラベルを作成する

![スクリーンショット 2023-12-21 1.18.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/86fbd341-0839-349d-efb0-97973099d2e3.png)

## 2. カスタム表示ラベルを表示ラベルに設定

`{!$Label.customLabelName}`の`customLabelName`を作成した`Contact`にして設定します。

登録した`担当者名`というテキストに変換されました。

![取引先-レコードページ-Lightning-アプリケーションビルダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/520d0288-2155-f022-9c35-7992a0c1280b.png)


# 最後に

Lightningページ周辺アップデートを確認してみました。

`動的関連リストの表示ラベルにカスタムラベル`はオブジェクト名をユーザー向けのわかりやすい言葉への変換をカスタム表示ラベルでできるようになりました。複数ページで一貫して同じ言葉を使えるのはいいですね！

`親オブジェクトの項目を配置可能に`は子オブジェクトから複数階層上の項目もそのまま配置できるようになりました。
今までは数式項目で対応、カスタムコンポーネントで対応していた親項目を配置することがカスタムせずできるようになったのは良いですね！
個人的には今までページの構成上どうしても正規化しなかったデータを**正規化して別オブジェクトにしてもページに配置**できるのがなかなか嬉しく思ってます。
アルファベットで連番を作るプログラム

# 目的

サンプルでデータを用意する際にA~ZときてAA~ZZ,AAA~ZZZとなるようなアルファベットの連番を作るためのプログラム

# プログラム

```Rust
fn main() {
  const DATA_AMMOUNT: i32 = 100000;
  
  for i in 1..=DATA_AMMOUNT {
    let id = i;
    let age = 20 + (i % 30);
    let name = "田中";
    let name_suffix = get_suffix(i);

    println!("{},{}-{},{}", id, name, name_suffix, age);
  }
    }

fn get_suffix(index: i32) -> String {
  let mut suffix: String = String::from("");
  const ALPHABET_NUM: i32 = 26;

  // 'A'のASCIIコードの値
  const START_ASCII: i32 = 65;
  
  let mut length: u32 = 1;
  let mut base = index;

  // 連番に対応するアルファベットの桁数計算
  loop {
    if base <= ALPHABET_NUM.pow(length) {
      break;
    }
    base -= ALPHABET_NUM.pow(length);
    length += 1;
  }
  
  // 2桁以上の計算  
  for i in 1..length {
    // 今の桁数の基底になる値(26の桁数乗)
    let unit = ALPHABET_NUM.pow(i);

    // 下の桁数分の差分を補正
    let mut base = index;
    for j in 1..=i {
      base -= ALPHABET_NUM.pow(j);
    }
    
    base = (base + ALPHABET_NUM.pow(i + 1) - 1) % ALPHABET_NUM.pow(i + 1);
    let offset = base / unit;
    let ascii: u8 = (START_ASCII + offset) as u8;
    suffix.insert(0, ascii as char);
  }

  // 末尾の文字の計算
  let offset = (index + ALPHABET_NUM - 1) % ALPHABET_NUM;
  let ascii = (START_ASCII + offset) as u8;
  suffix.insert(suffix.len(),ascii as char);
  suffix
}
```

# 出力

```text
1,田中-A,21
2,田中-B,22
3,田中-C,23
~中略~
25,田中-Y,45
26,田中-Z,46
27,田中-AA,47
28,田中-AB,48
29,田中-AC,49
30,田中-AD,20
~中略~
51,田中-AY,41
52,田中-AZ,42
53,田中-BA,43
54,田中-BB,44
~中略~
701,田中-ZY,31
702,田中-ZZ,32
703,田中-AAA,33
704,田中-AAB,34
~中略~
18277,田中-ZZY,27
18278,田中-ZZZ,28
18279,田中-AAAA,29
18280,田中-AAAB,30
~中略~
99999,田中-EQXC,29
100000,田中-EQXD,30
```

# 最後に

アルファベットを26進数として10進数から変換するというのが基本の考え方なのだろうけど、自分でやってみるとかなり苦戦しました。
もっと綺麗な書き方があると思いますが必要な連続アルファベットが得られたので良しとします。
カシオのカラーグラフ関数電卓 fx-CG50 に MicroPython がのったゾ(その後)

# はじめに

AdventCalendar 2018の記事で「[カシオのカラーグラフ関数電卓 fx-CG50 に MicroPython がのったゾ](https://qiita.com/inachi/items/41dbe628be64cfea4193)」という記事を投稿しました。本記事では、その後の変化について書きます。

# グラフィック機能の拡張

以前の記事の時点では、グラフ電卓にも関わらず、グラフィック機能が一切無かった MicroPython ポートでしたが、現在では `casioplot` モジュールで簡易なフラフィック機能を提供しています。

詳細は[日本語マニュアル](https://www.casio.com/content/dam/casio/global/support/manuals/calculators/pdf/004-ja/f/fx-CG50_Soft_v370_JA.pdf)の 17.5 章「描画関数の利用（casioplotモジュール）」を参照してください。

まあ、できることは、ピクセル描画とテキストをグラフィック表示するぐらいです。

# matplotlib

それではあまりにもということでしょうか、それとも NumWorks を意識してでしょうか、フランスの CASIO Education が matplotlib 機能をスクリプトとして提供しました。

fx-CG50 のファイルシステムの制約を受け、モジュールは `matplotl.py` です。このため、fx-CG50 のフランス版 Graph 90+E ではファームウェアに取り込まれ、 `matplotlib.pyplot` で使えるようになったとのことなのですが、fx-CG50 ではなぜか使えません。ファームウェアは同じはずなので、機種を見て使えなくしているのかどうか...

`matplotl.py` も CASIO　のサイトからは見つけられなくなったようなのですが、以下から入手は可能です。

https://tiplanet.org/forum/archives_voir.php?id=2648498

以下は簡単なサンプルです。

```python
from matplotl import *

plot([1, 2], [3, 4])
show()
```

![IMG_7227.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/56a4c4e7-e34d-382a-00f1-05ad5480166c.jpeg)

# タートルグラフィック

同様に、フランスの CASIO Education がタートルグラフィックの機能をスクリプトとして提供していました。こちらもファームウェアに取り込まれたことになっているのですが fx-CG50 では機能しません。

そのため、こちらも使いたい場合は以前い提供されていた外部スクリプト版 `turtle.py` を使うことになります。以下から入手可能です。

https://tiplanet.org/forum/archives_voir.php?id=2648501

以下は簡単なサンプルです。

```python
from turtle import *

speed(0)
for i in range(12):
    left(30)
    for j in range(8):
        forward(30)
        left(45)
```

![IMG_7228.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/d5d98d24-8d25-90af-1c6c-8030e9a368cc.jpeg)
マナビDXQuestの魅力

## 自己紹介

はじめまして、マナビDX Quest 2023に参加させていただいています。
**ららら**です。本業は、地方でソフトウェア開発業務を営んでいます。

###

マナビDX Questについての詳細は下記リンク[^1]や他のアドカレ参加者[^2]が詳しく書いてくださっているので割愛させていただきます。
この投稿を初めて見てしまった方は**是非**、他の方のアドベントカレンダーも読んでみてください。

https://dxq.manabi-dx.ipa.go.jp/

https://qiita.com/advent-calendar/2023/manabi-dx-quest2023

[^1]:https://dxq.manabi-dx.ipa.go.jp/

[^2]:https://qiita.com/advent-calendar/2023/manabi-dx-quest2023

## 参加理由

マナビDX Quest 2022に参加して**純粋に楽しかった！！**
これにつきました。

### 魅力

#### 其の壱 コミュニティ

マナビDX Questには日常的なコミュニケーションツールとして**Slack**と**HEERE**(バーチャルオフィス)が提供されており、課題期間中には昼夜を問わずSlack上で様々な議論が交わされ、HEEREでは勉強会や交流イベントが開催されています。
一度、社会に出てしまうと新たなコミュニティに参加することも難しく感じていました。
マナビDX Questはオンラインを前提としたコミュニティなので、積極的にコミュニケーションをとっていくことで様々な業界のかたと知り合い、お話しすることができることが最大の魅力だと感じています

まだ、Slackで発言したことのない方、HEEREにログインしたことのない受講生の皆さんは是非、一歩踏み出してみてほしいです。

#### 其の弐 相互レビュー

みんなで一斉に課題を解いて、水平レビューする機会は、学生時代から考えてもそんなに多くないのはないでしょうか？
マナビDX Quest、同じPBLの課題に取り組んだ数百人の中から7名の資料を読んでレビューすることになります。自分と同じ方向性の方もいれば全く違う方向性の方もいる
自分が書きたくて上手に書けなくて消してしまった内容を上手に読ませてくれる資料を目にすることもできる


#### 其の参 チャレンジングな取り組みができる

PBLの課題に取り組むなかで仕事ではなかなかできないチャレンジングな内容を書いて評価を探ることもできます。うまくハマれば実務にフィードバックしてもいいし、評価が悪ければ指摘内容に合わせてブラッシュアップすることもできます。
だからって上司やお客様がいるわけではないから怒られることもない。このような機会はなかなかないと思います。
是非、日ごろ試してみたいけど心に秘めているアプローチがある方は披露の場にしてみてはいかがでしょうか？

## 謝辞

このような企画がないとQiitaで記事を書いてみよう！と思っていなかったと思います。
hata(@awonohata) さん
魅力的な企画を立ち上げて、また背中を押して出さりありがとうございます！！

## マナビDX Quest 参加履歴

- マナビDX Quest 2022
  - 需要予測・在庫最適化 (小売)
  - 加工内容の図面解析による自動見積(製造)
  - 現場研修プログラム
- マナビDX Quest 2023
  - 業務最適化 (建築製造)
  - 地域企業協働プログラム
  - 店舗型小売業OMOビジネス(予定)
Crsytalで実行が終了したらnotifyするコマンドラインツールを作る

## はじめに

Crystalのアドベントカレンダーです。

Ubuntuのデスクトップ通知を出すCrystalのライブラリが notify.cr です。

https://github.com/woodruffw/notify.cr

これを使って、時間のかかるコマンドを実行したときに、通知を出すコマンドラインツールを作ってみます。

## アイディア

こんな感じのツールを想定しています。

```sh
nt crystal build huge_project.cr
```

ビルドが終わると通知が出ます。もちろん引数や標準入出力も自在に使えてほしいですね。

## 使い方

とりあえず次のようなコードを書きました。


```cr:nt.cr
require "notify"

notifier = Notify.new

command = ARGV.join(" ")
status : Process::Status 

elapsed_time = Time.measure do
  status = Process.run(command, shell: true, input: STDIN, output: STDOUT, error: STDERR)
end

if status.success?
  notifier.notify "成功 #{elapsed_time}", body: command
else
  notifier.notify "失敗 #{elapsed_time}", body: command
end
```

細かいところ、大丈夫か確信はありませんが、なんとなく動いてますね。

（notify.crの動作確認してテスト追加して[PR](https://github.com/woodruffw/notify.cr/pull/8)送ってたら深夜になってしまいました）

この記事は以上です。
非同期処理が難しすぎるから少しだけ整理してみた

## はじめに
今まで特に意識せずにAPIコールしていたのですが、JavaScriptの[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API)を使うことになり、いざ書いてみるとasyncやawait、Promiseなどの非同期処理がわかっていないことに気づいたので、整理しようと思いました。

まだ理解や解釈が曖昧なところがあるため、間違っているところなどありましたら教えてくださると嬉しいです🙇

### 参考
https://jsprimer.net/basic/async/

## JavaScriptはシングルスレッド
まずはJavaSctriptがどのようにプログラムを実行しているのかを知る必要があります。

JavaScriptでは、プログラムの実行は**シングルスレッド**で行われます。
プログラムを実行しているのが1人しかいないイメージです。コードを順番に処理していきます。**複数の処理を同時に行うことはできません。**

## 非同期処理とは
では非同期処理とはなんでしょうか。

>非同期処理はコードを順番に処理していきますが、ひとつの非同期処理が終わるのを待たずに次の処理を評価します。 つまり、非同期処理では同時に実行している処理が複数あります。

時間がかかる処理があった時に、それが終わるのを待たずに他の処理を進めておいて、終わったら合流するようなイメージです。
先輩がとても良い例えを教えてくれたのですが、「コードのレビューを依頼して、レビューが返ってくるのを待っている間、何もしないで待っているのではなく、他のタスクを進めておいて、レビューが返ってきたらそのタスクに戻る」という例えがとてもしっくりきました。

ここで疑問が1つ。
**シングルスレッドなのになぜ非同期処理では複数の処理を同時に実行できるの？？🤔**
最初の説明と矛盾していますよね。

少し調べてみたのですが、**イベントループ**という仕組みによって実現できているらしいです。
残念ながら難しくて理解できなかったのですが、多分JavaScriptには**コールスタック**と**タスクキュー**というものが備わっていて、現在実行中のタスクはコールスタックに積まれていきます。非同期処理の場合はタスクキューに積まれて、コールスタックが空になり次第実行される、みたいな感じらしいです。

やはり、先輩が教えてれた例えがかなり正確なイメージな気がしました。
- コードレビューを依頼する=>レビューが返ってきたらタスクキューに積まれる
- レビューを待っている間他のタスクを進める=>コールスタックに積まれたタスクを実行
- キリが良くなったタイミングで返ってきたレビューを確認する=>コールスタックに積まれたタスクが空になり次第、タスクキューに積まれたタスクを実行

この解釈が合っているかどうか、もっと良い例え、説明がありましたら教えてください🙇

実務でよく使われる非同期処理はAPIコールです。
時間がかかる処理なので処理が完了するのを待っていたら、表示が更新されない時間が数秒続く…なんてことが起きる可能性があります。

## 非同期処理と例外処理
非同期処理では、[`try...catch構文`](https://jsprimer.net/basic/error-try-catch/)を使っても非同期的に発生した例外をキャッチできません。

try...catch構文がよくわかっていなかったので復習すると、**例外（エラー）が起こる可能性があるときに使って、エラーが起きた時にどうするか**を書きます。
```javascript
try {
    throw new Error("同期的なエラー");
} catch (error) {
    console.log("同期的なエラーをキャッチできる");
}
console.log("この行は実行されます");
```
ここで注意点があります。
`try句{}`の中で発生した例外をキャッチする構文であるため、外で発生したエラーは感知できません。

そのため、非同期処理の例外をキャッチしたい場合は、非同期処理のコールバック関数の中にtry...catch構文を書いてエラーを感知できるようにします。
```javascript
// 非同期処理の外
setTimeout(() => {
    // 非同期処理の中
    try {
        throw new Error("エラー");
    } catch (error) {
        console.log("エラーをキャッチできる");
    }
}, 10);

console.log("この行は実行されます");
```
しかし、非同期処理の中で例外が出たとしても、非同期処理の外はそれを感知できないので、最後の行が実行されてしまいます。
APIコールはエラー出る可能性高いですよね。なんとかして、エラーをキャッチして非同期処理の外に伝えなくてはなりません。
この非同期処理において例外を扱うために重要なのが、`Promise`と`async`です。

いや難しすぎる！！！！
続きは明日書きます。
【Rails】config/settings.ymlについてまとめてみた

:::note
Ruby on Railsアプリケーションにおいてconfig/settings.ymlは、アプリケーション全体の設定を管理するために使用されるYAML形式のファイルです。このファイルを使用することで、アプリケーションの設定を一箇所に集約し、環境変数やハードコードされた値に依存しないようにすることができます。
:::

## `settings.yml`の主な特徴と利用方法
#### 設定の中央集権化
`settings.yml`はアプリケーションの様々な設定値を一箇所にまとめるために使用されます。これにより、設定値の管理が容易になり、コード内でのハードコードを避けることができます。

#### 環境固有の設定
通常、アプリケーションは開発、テスト、本番など複数の環境で動作します。`settings.yml`を使用すると、これらの異なる環境に対して固有の設定を行うことができます。

#### YAML形式
YAML（Yet Another Markup Language）は、データを階層的かつ読みやすい形式で表現するためのデータシリアライゼーション言語です。`settings.yml`ファイルはこの形式で書かれており、編集が容易で理解しやすいです。

#### アクセスと使用
このファイル内で定義された設定は、アプリケーション内の異なる部分から簡単にアクセスできます。多くの場合、Railsアプリケーションでは`Rails.application.config_for(:settings)`を使用してこのファイルから設定を読み込みます。


## 使用例
```yaml
# 基本的なアプリケーション設定
app:
  name: "MyApp"
  timezone: "Asia/Tokyo"
  language: "ja"

# メール関連の設定
email:
  smtp_host: "smtp.example.com"
  smtp_port: 587
  username: "user@example.com"
  password: "password123"
  from_address: "noreply@example.com"

# データベース設定（本番環境用）
production:
  database:
    adapter: "postgresql"
    host: "prod-db.example.com"
    username: "prod_user"
    password: "prod_password"
    database_name: "myapp_production"

# 外部APIの設定
external_services:
  payment_service:
    api_key: "1234567890abcdef"
    secret: "secret12345"
  analytics_service:
    tracking_id: "UA-XXXXX-Y"

# 機能フラグ
features:
  enable_signup: true
  enable_beta_features: false
  maintenance_mode: false

# セキュリティ関連の設定
security:
  session_timeout: 3600 # セッションタイムアウト（秒）
  password_policy:
    min_length: 8
    require_uppercase: true
    require_numbers: true
    require_special_chars: false

# その他のカスタム設定
custom:
  file_upload_limit: 10MB
  support_email: "support@example.com"
```
すべてが私になった日

# はじめに
昔の自分がやらかした過ちをここらへんで懺悔しておきます。
願わくば同じ失敗をしてしまう人が少しでも減りますように。

「いやこんなコマンド打たんだろ…」と思いますよね。なんか流れでやっちゃう時があるんです。ホントに。

<a id="# Chapter1"></a>
# 【第１章】不穏な依頼・/直下の作業パス
もう何年前になるでしょう。IT業界に就職して数年、とあるUNIX系OSで管理系機能はそれなりに理解し、開発にも操作にもすっかり慣れてきて、ちょっとした自信もついてきた頃のことでした。

先輩：「わたし君、明日お客さんセンターに搬送するマシンで最後にちょっとしたテストしたいんだ。やっといてくれないかな。オレ今日はもう用事があって。」

わたし君：「あ、いっすよ。どこに置きました？」

先輩：「作業ディレクトリ消しちゃった後だから、/直下にtest.tmpって作ってftpで入れてあるから実行権限付けて動かしてみて。じゃあ、お先～」

わたし君：「（ええ、/test.tmpってw・・・まあいいか）」

<a id="# Chapter2"></a>
# 【第２章】破滅への第一歩・rootを使用

状況を確認。
```
# こんな出力でしたーというイメージです
#
[watashi@host1 test.tmp]$ ls -lR
.:
合計 0
-rw-------. 1 ftpusr ftpusr  0 12月 20 23:40 test_main.sh
drwxrwxrwx. 2 ftpusr ftpusr 48 12月 20 23:41 test_sub1
drwxrwxrwx. 2 ftpusr ftpusr 48 12月 20 23:41 test_sub2
drwxrwxrwx. 2 ftpusr ftpusr 48 12月 20 23:42 test_sub3
：
：
./test_sub1:
合計 0
-rw-------. 1 ftpusr ftpusr 0 12月 20 23:41 test_sub1.sh

./test_sub2:
合計 0
-rw-------. 1 ftpusr ftpusr 0 12月 20 23:41 test_sub2.sh
：
：
```

わたし君：「あー、ftpusr:ftpusrで600か。実行するならファイルのownerもwatashiにしたいし、rootでオーナー変更して実行権限も付けるか」

```
[watashi@host1 test.tmp]$ su -
パスワード:
[root@host1 ~]#
[root@host1 ~]# cd /test.tmp
[root@host1 test.tmp]#
```

<a id="# Chapter3"></a>
# 【第３章】破滅への第二歩・再帰処理

わたし君：「サブディレクトリあるから-R付けなきゃ」

```
[root@host1 test.tmp]# chmod -R a+x *.sh
[root@host1 test.tmp]# chown watashi:watashi -R *
```

わたし君：「よし実行っと」

```
[root@host1 test.tmp]# ./test_main.sh
エラー：設定ファイル .test_main.ini を読めません
[root@host1 test.tmp]# ll .test_main.ini
-rw-------. 1 ftpusr ftpusr 0 12月 20 23:41 .test_main.ini
[root@host1 test.tmp]#
```

わたし君：「は？ ".test_main.ini" とか何で設定ファイルを隠しにしてんだよ。*でヒットしないからftpusrのままじゃん。
もう面倒だからこれで全設定ファイル直そ。」

```
# 非常に危険な処理です！ダメ！絶対！
#
[root@host1 test.tmp]# chown watashi:watashi -R .*
```

そして流れるように出力される大量のエラー。しかもやたら時間がかかってる。なにこれ怖い。

もう一個ログインセッションがあるから覗いてみるか。

<a id="# ChapterF"></a>
# 【終章】そしてすべてが私になった

```
# こんな出力でしたーというイメージです
#
[watashi@host1 ~]$ ls -l /
合計 28
drwxrwxrwx.   3 watashi watashi   18 12月  6 16:35 adm
lrwxrwxrwx.   1 watashi watashi    7  6月 21  2021 bin -> usr/bin
dr-xr-xr-x.   5 watashi watashi 4096 10月 16 16:52 boot
drwxr-xr-x.  20 watashi watashi 3180 12月 20 23:31 dev
drwxr-xr-x. 144 watashi watashi 8192 12月 20 23:39 etc
drwxr-xr-x.  14 watashi watashi  185 12月 20 23:39 home
lrwxrwxrwx.   1 watashi watashi    7  6月 21  2021 lib -> usr/lib
lrwxrwxrwx.   1 watashi watashi    9  6月 21  2021 lib64 -> usr/lib64
drwxr-xr-x.   2 watashi watashi    6  6月 21  2021 media
drwxr-xr-x.   4 watashi watashi   28 10月 27 13:32 opt
：
：
```

わたし君：「ちょ、え、何これ？全部のファイルのオーナーがwatashiになってる？なんで？…」

賢い諸氏はお分かりでしょうが解説します。

わたし君は作業ディレクトリ下のドットファイルをヒットさせる為に、よく考えずに次のワイルドカードを使った。
```
.*
```
確かにドットファイルはヒットする。しかし、当然ながら次のパスがヒットする。
```
..
```
親ディレクトリ………そしていま作業している /test.tmp の親ディレクトリは /

つまりrootで以下のコマンドを打ったのと同じ結果となる。
```
[root@host1 test.tmp]# chown watashi:watashi -R /
```

/ 以下を再帰処理で全ファイルの所有者を一般ユーザwatashiに変更…

そして、すべてのファイルが私(watashi)のものになった…

# その後

その後、システムは丸っと動かなくなりました。セッションは暫くして切れ、もうログインも出来ません。ローカルターミナルもダメ。再起動してももう正常には起動しません。

そこから、OSのシステムファイルをインストールメディアから上書きインストール。デプロイした各種ファイルやミドルウェアのオーナー設計を設計書から確認して手で復旧。そして、全ファイルシステムに渡る私(watashi)探しの旅を終えて、OS、ミドルウェア、アプリの全正常起動を確認した時には、もう明け方でした。

# 教訓

root使ってるときはコマンド打つ前に一拍考えろ
AWS EC2にJava Servlet アプリケーション構築

# Eclipse で作成したWebアプリケーションをEC2で起動したので手順(コマンド)記録

### Eclipseでwarファイルを作成
Eclipse内対象プロジェクト→[エクスポート]→[Web]→[WARﾌｧｲﾙ]→適当な箇所に保存

### EC2インスタンス作成
VPC→Subnet→EC2インスタンス(ｷｰﾍﾟｱ作成)

### EC2セキュリティグループ インバウンド(HTTP, SSH, Tomcat)
|タイプ|プロトコル|ポート範囲|ソース|CIDRブロック|
|:---|:---|:---|:---|:---|
|HTTP|TCP|80|カスタム|0.0.0.0/0|
|SSH|TCP|22|カスタム|0.0.0.0/0|
|カスタムTCP|TCP|8080|カスタム|0.0.0.0/0|

### EC2インスタンスへ SSH接続(EC2作成時のｷｰﾍﾟｱを使用)
```
ssh -i ｷｰ.pem ec2-user@ec2~.amazonaws.com
```
※エラーが出る場合、キーのセキュリティを確認

### Java 1.8 インストール
```
sudo yum install java-1.8.0
```

### Apatch インストール
```
sudo yum install httpd
```

### Apatch 起動
```
sudo systemctl httpd
sudo systemctl httpd.service
```

### Tomcat9 インストール
```
sudo yum install tomcat9
sudo yum install tomcat9-webapps
sudo yum install tomcat9-admin-webapps
```

### Tomcat9 起動
```
sudo systemctl start tomcat9
sudo systemctl status tomcat9
```

### war ファイルをEC2にアップロード(EC2作成時のｷｰﾍﾟｱを使用)
```
scp -i ｷｰ.pem warﾌｧｲﾙ.war ec2-user@ec2~.amazonaws.com:/usr/share/tomcat9/webapps

or 適当な場所にアップロードして移動
sudo cp warﾌｧｲﾙ.war /usr/share/tomcat9/webapps
```

### 動作確認
Apatch
```
http://パブリックIPv4アドレス
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/fc448ffe-3228-3752-0a70-bc0e1fc34345.png)

Tomcat
```
http://パブリックIPv4アドレス:8080
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517045/1a50e475-8765-4314-a76b-f8907e50c080.png)

アップロードしたWebアプリケーション
```
http://パブリックIPv4アドレス:8080/アプリケーション名
```
作成したアプリケーションが起動すればOK

以上
Array.prototype.shift(),unshift(),push(),pop()を理解する。

shift(),unshift(),push(),pop() 
どれがどれだかわかりにくい!!
ということで、分かりやすくまとめてみました。

### shift
`配列の最初の要素を削除` し、その要素を返します。
例えば、[1, 2, 3] という配列で shift を使うと、1 が削除されて 2, 3 が残ります。
「次の段階へ`シフトする`」とか言いますね。
それはつまり、`元の所からはいなくなる`(削除)ということですね。
こんな感じです。
```js
const array = [1, 2, 3] 
const first = array.shift() // 先頭をシフト
console.log(first) // 1
console.log(array) // [2, 3]
```

### unshift
配列の最初に一つ以上の要素を追加し、新しい配列の長さを返します。
例えば、[1, 2, 3] という配列に unshift(0) を使うと、配列は [0, 1, 2, 3] になります。
`un`は、元の単語の意味を反転させる意味を持ちます。（ラッキー！アンラッキー...など）
こんな感じ。
```js
const array = [1, 2, 3]
const count = array.unshift(0)
console.log(count) // 4
console.log(array) // [0, 1, 2, 3]
```

### push
配列の最後に一つ以上の要素を追加し、新しい配列の長さを返します。
例えば、[1, 2, 3] という配列に push(4) を使うと、配列は [1, 2, 3, 4] になります。
カバンにものを詰め込んでいくイメージでしょうか。
こんな感じです!!!!!
```ts
const bag = []
const count = bag.push('iPhone')
console.log(count) // 1
console.log(bag) // ['iPhone']
```

### pop（ポップ）:
`なんでunpushやないねん！`という声が聞こえます(?)。
配列の最後の要素を削除し、その要素を返します。
例えば、[1, 2, 3] という配列で pop を使うと、3 が削除されて 1, 2 が残ります。
popを日本語訳すると、`突然現れる` や `弾ける`といった意味があります。
末尾の要素が「弾ける」ように配列から消え去ります。。。:rolling_eyes:? (ポップコーンかな)
こんな感じです。
```ts
const array = [1, 2, 3]
array.pop() // 末尾の要素を削除
console.log(array) // [1, 2]
```

## まとめ

いかがだったでしょうか。
完全に身についたかと思います(？)
私はこの記事を書きながら復習ができました！

配列の操作で必ず出てくる4つですので、必ずマスターしておきましょう！
GitHub Actionsを使用してDockerイメージのプルとキャッシュの最適化を行おう！

Optimizing Docker Image Builds with GitHub Actions

こんにちは、みなさん！今回のブログでは、GitHub Actionsを使用してDockerイメージの生成とプッシュを最適化する方法についてお話しします。Dockerイメージのプルとキャッシュの活用により、ビルドの速度を向上させ、Docker Hubからの制限を回避できるようになります。

以下のGitHub ActionsおよびDockerの公式ドキュメントを参考にしながら進めていきましょう。

- [GitHub Actionsにおけるキャッシュの使用方法](https://docs.docker.com/build/ci/github-actions/cache/#github-***)
- [docker/build-push-actionのGitHubリポジトリ](https://github.com/docker/build-push-action)

上記のドキュメントは、実際に使っている方にとっては既知の情報かもしれませんね。しかし、Docker Hubからの制限を受けやすい場合や、ローカルビルドの時間を削減したい場合には、これらの手法を導入する価値があるかもしれません。

さて、実際のコード例を見てみましょう。

```yaml
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: user/app:latest
    ***-from: type=registry,ref=user/app:latest
    ***-to: type=inline
```

こちらのコードは、Dockerイメージのビルドとプッシュを行います。上記のコードは、`docker/build-push-action`を使用しています。詳細な設定やオプションは公式リポジトリを参照してください。

では、なぜこういった手法が役立つのでしょうか？それは、CIパイプラインのパフォーマンス向上に繋がるからです。時間のかかるイメージのプルを削減し、スムーズなデプロイメントを実現することができます。

ただし、一部制約事項もあります。GitHub Actionsのキャッシュの容量には最大10GBの制限がありますので、過度に欲張ったセットアップを行うことはできません。しかし、この手法を使用することでビルド時間の削減が実現できるため、十分効果的な方法と言えます。

また、ドキュメントをざっと見ただけのため、実際にお布施が必要かどうかは分かりませんが、お布施案件である可能性もあります！（笑）

最後に少し脱線しますが、ドキュメントを読む限りでは、おそらくRedisなどのキャッシュストアを裏側で使用しているのかな？という気がしました。ただし、それが本当に当てはまるかどうかはわかりませんので、詳細は気になる方はドキュメントをご確認ください。

以上、GitHub Actionsを使用してDockerイメージのビルドとプッシュを最適化する方法についてお伝えしました。ぜひ、この手法を活用して効率的な開発環境を構築してみてください。

それでは、次回のブログ記事でお会いしましょう！楽しみにお待ちしています。
Kubernetesがキャッシュ済みのDockerイメージを使い続けてしまう問題の解決方法

# 背景

DockerレジストリにプッシュしたイメージをKubernetesのPodで利用しようとしたが、イメージ内にちょっとしたミスがあったため動かなかった。そのためイメージを修正して、同一バージョンで上書きプッシュした。

これで動くはず！と意気込んでPodを再起動したが、さっきと同じエラーで動かなかった。どうやらミスが解消されていないらしい。かくかくしかじかの調査を経て、どうやらこれはキャッシュの問題でありそうだということが判明した。

どうすればキャッシュを無視して新しいイメージを取得できるか？

# 結論

`imagePullPolicy`を`IfNotPresent`にしているとキャッシュを使ってしまうので、キャッシュを手放したいなら`Always`にしよう。

具体的には、PodやDeploymentのマニフェスト内で

```
spec:
  containers:
    image: 'matoruru/dummyserver:1.0.0'
    imagePullPolicy: IfNotPresent
```

を

```
spec:
  containers:
    image: 'matoruru/dummyserver:1.0.0'
    imagePullPolicy: Always
```

にしよう。

# 反省

そもそも同一バージョンを上書きするなよ（小さいミスかつ自分しか使わないイメージだったので許してほしい）
Reactが実験的に提供する楽観的更新を試してみる

## はじめに
Reactの[Canaryチャンネル](https://ja.react.dev/community/versioning-policy#canary-channel)や[Experimentalチャンネル](https://ja.react.dev/community/versioning-policy#experimental-channel)ではUIの楽観的更新を行う`useOptimistic`が提供されています。
この記事では`useOptimistic`がどのように利用できるかについて解説します。

## 楽観的更新とは
楽観的更新とはUIのパフォーマンス向上のための試作の一つです。
あるイベントが起きてからUIに反映するまでに、ネットワーク通信などが挟まると反映までの時間が長くユーザーのストレスになります。楽観的更新ではあるイベントが起きたら、ネットワーク通信などの時間がかかる処理をバックグラウンドで実行させて、UIにイベントが成功したとして直ちに反映させます。

例えば、楽観的更新を行うと、ユーザーが「いいね」ボタンをクリックしたとき、アプリケーションはサーバーにリクエストを送信し、そのレスポンスを待つ代わりに、直ちにユーザーインターフェースを更新して「いいね」の数を増やします。

このアプローチを行う場合は、更新後にネットワーク通信などで失敗したときのハンドリングが重要となることに注意してください(ロールバックしたり...)。

## useOptimistic
 `useOptimistic`はReactの状態を楽観的に更新させるために利用されるhooksです。
```ts
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);
```
楽観的更新を行う状態を第1引数に、更新を行う術を記述する関数を第2引数に渡します。返り値は配列です。１つ目は楽観的な更新が行われた状態、2つ目は楽観的な更新を行うための関数です。
第2引数の関数は第1引数に更新時の状態、第2引数に楽観的更新のための材料が渡されます。関数の中にはどのように更新するかを記述します。
そして、`addOptimistic`は第2引数を元に、楽観的更新の引き金を引きます。

https://codesandbox.io/embed/7t4hjg?view=Editor+%2B+Preview&module=%2FApp.js

実際に`useOptimistic`を使って上記のように更新できます。
`User`というオブジェクトの`name`を大文字にしたり小文字にしたりしますが、それぞれ変更に１秒かかります。`useOptimistic`を利用することで、１秒待つ前に、大文字になるとして楽観的に更新された`User`オブジェクトを扱えるようになりました。
UnityとUnrealEngineのSequence機能をさわり比べ

この記事は[Unity Advent Calendar 2023の21日目](https://qiita.com/advent-calendar/2023/unity) の記事です。

仕事でUnityを使う機会が出てきそうな為、学習し直しも兼ねてQita記事を書きます。
私自身は、普段の業務では、UnrealEngineを使用している為、ゲームエンジンの機能的な違いも比較しながら、さわっていきました。

# 目標

今回、目標とした事は以下の項目です。下の二つは時間が足りず検証する事ができませんでした。

* Unityの最新環境で実際に触ってみる
* Timeline / Sequenceをさわってみる
* レンダリングまで行ってみる
* AnimeToolBoxをさわってみる(※できたら)
* ポストプロセスかけてレンダリングしてみる(※できたら)


# 確認環境
Windows 11 Home
Unity 2023.2.3f1

# 参考にしたサイト

[こちらの荒川さんと林さんの動画](https://www.youtube.com/watch?v=74VblliIzfQ)を参考にしました。

# 躓いた点

* 一つ目が、用語です。当然ですが、UnrealEngineとは同じ意味で同じ単語ではない為、さわってみて、『これは○○に相当する』という手探りな理解の仕方になった為、レンダリングするだけでも、時間が取られました。

* 二つ目が、キャラや背景のアセットの置き方です。UnrealEngineだと、直接Sequenceに配置していましたが(オブジェクトをSequeceに置くことがトラックとして管理される)、カテゴリごとに、必要なオブジェクトを配置していく工程は、何度か動画を見直しました。逆に言えば、最初から管理できる仕組みをUnityが提供している為、誰が作業しても見やすくまとめられる形になるかと思います。

* 三つ目が、トラック周りです。UnrealEngineとは違い、Unityの場合だと、ユニティちゃんを走らせるアニメーションをレンダリングするだけでも、3段階くらい階層が深くなってしまった為、管理はしやすいが、理解するまでに時間がかかりました。また、Sequenceについても、UnrealEngineでは、『レベル』『レベルシーケンサ』が別管理になっていますが、UnityではScene内にSequenceが管理(依存)している点も大きく違っていました。

:::note info
UnrealEngineだと、『シーン』と『Sequence』が別管理されている為、『シーン』や『Sequence』を別のシーンや別のSequenceで使うという事も出来ます。
基本的には、1:1の関係となって運用されます。
:::



# 良かった点

[3D人](https://3dnchu.com/)などを見ていて、『こういう機能はUEには無いかな』っと思う事もいくつかありますが、実際にさわってみて思うところもありました。

* RecorderClipの出力できる形式が豊富。特に、『FBX』や『Alembic』で出力できるのなら、DCCツールにも持っていけそうだなと思いました。(※UnrealEngineでFBXを出力できない訳ではない)
* 『躓いた点』にも書きましたが、『Charcter』『FX』『Lithing』などカテゴリ分けして、オブジェクトの管理が整理されている点
* プレイボタン押すだけで、レンダリングが開始される。UnrealEngineだと、『ムービーシーンキャプチャ』なり『Movie Render Queue』なり、専用のツールを立ち上げる必要がある為、『これだけレンダリングできるんだ！』と感心しました。
* 情報が豊富。これはケースバイケースになりますが、エラーが出ても、エラーが文でそのままでググれば、情報が出てきて対処できた点はUnityユーザーが多いと感じます。
* ユニティちゃん可愛いよね。気軽に使えるモデルを公式が用意してくれているのはとてもありがたいですね。Unityでテストする際は、SDのユニティちゃんを使ってたりします。


# 共通していた点

* アセットストアへのアクセスは、どちらも同じくらいの利便性
* ノーコードでレンダリングまで行けた
* マーケットプレイスのアセットやサンプルプロジェクトの豊富さ(※単純に検証や調査に使いたいだけなら困ることはなかった)

# 今回気になった事を検証

正直、調査不足感は否めないところです。
『FBX』や『Alembic』が書き出せる事が分かった為、出力したファイルがUnrealEngineやDCCツールで読み出せるかテストしてみました。
結果として、3DSMax、UnrealEngineで、インポートはできるが、ユニティちゃんがアニメーションが入った形式でモデルを書きだせませんでした。
また、Alembicの場合は、3DSMax、UnrealEngineで、ジオメトリとアニメーションを持っていくことができましたが、マテリアアルは持っていけませんでした。

# 感想

せっかくなので、AnimeToolBoxをさわってみたいと思うので、タイミング見つけて、Qita記事を上げてきたいと思います。

試せていない事も結構あり、

* DCCツールで書き出したカメラをインポートの仕方
* カメラのTransformのSequence上での変え方
* ポストプロセスを使用してレンダリング
* AnimeToolBoxを利用したレンダリング
* AnimeToolBoxは3D背景も行けるのか
* 機能拡張(C#)でのレンダリングの制御のしやすさ / どこまで手を入れられるのか

など、気になる課題があります。
今回は、以上です。
[Nuxt3]プロジェクトの作成

# Nuxtプロジェクトの作成の手順
1. プロジェクト作成コマンドの実行
    - 作業ディレクトリ上で以下のコマンドを実行する。
    ```
    npx nuxi init プロジェクト名
    ```

2. 依存パッケージのインストール
    - 作成したプロジェクトに移動し(`cd プロジェクト名`)、以下のコマンドを実行する。
    ```bash
    npm install
    ```
    :::note info
    パッケージのインストール中に次のメッセージが表示されることがある。
    ```
    Nuxt collects completely anonymous data about usage.                
    This will help us improve Nuxt developer experience over time.
    Read more on https://git.io/nuxt-telemetry
    
    ? Are you interested in participating? (Y/n)
    ```
    これはNuxtの開発者に、Nuxtの利用状況を匿名で送りますか？というもの。Nuxtの開発に利用されているみたいなので、特に問題がないならYを入力し、嫌ならnを入力してからエンターを押す
:::

# Nuxtプロジェクトの実行コマンド
```
npm run dev
```
上記のコマンドを実行すると、開発用サーバが起動する。

開発サーバを起動すると同時に、自動でブラウザを開きページを表示させるコマンドもある。
```
npm run dev -- -o
```
- このコマンドでは、`-o`オプションを指定している。`--open`を指定しても同じ。
:::note
`npm run dev`は`nuxi dev`コマンドのエイリアスとなっており、`-o`や`--open`はこの`nuxi dev`コマンドのオプションであるため、`npm run dev -o`のように直接オプションは渡せないらしい。
そのため、`npm run dev`にオプションを渡すときは、オプションの前に`--`を記述する必要がある。
:::

# nuxtプロジェクト内の構成
```
hello-nuxt ←プロジェクトルートフォルダ(プロジェクトを作成した時にできたフォルダ)
    |
    |- .nuxt      ←ビルドされたNuxtアプリケーションが格納されたフォルダ
    |- node_modules     ←プロジェクトの依存関係(パッケージ)が格納されたフォルダ
    |- public    ←Webに公開するファイル類(画像など)を格納するフォルダ
    |- server    ←エンドポイントAPIサーバ処理を行うファイル類を格納するフォルダ
    |- .gitignore     ←Git管理対象から除外するファイルの設定ファイル
    |- .npmrc      ←npmコマンドの設定ファイル
    |- app.vue     ←メインの単一コンポーネントファイル
    |- nuxt.config.ts     ←このNuxtアプリケーションの設定ファイル
    |- package-lock.json     ←npmの依存関係に関する設定ファイル
    |- package.json     ←npmに関する設定ファイル
    |- README.md      ←READMEファイル
    |- tsconfig.json   ←TypeScriptに関する設定ファイル
```
Nuxt3では、新規作成プロジェクト内の構成要素は必要最低限のもののみとなっている。（コンポーネントは`app.vue`のみ、設定ファイルやフォルダも必要最小限のもののみ）
ここから必要に応じてフォルダやファイルを追加していく必要がある。
C#のエラー：CS1069の原因と解決方法

### きっかけ
C#でSqlExceptionをtry~catchで実装する際、このエラーが出たこと

### 原因
NuGetの参照が足りてなかった。必要なパッケージがインストールされていないため。

### エラー解消法
ソリューションを右クリック、「Nugetパッケージの管理」から
「System.Data.SqlClient」をインストール
文字コードの基礎を解説

# 1. はじめに
文字コードであるshift-jisやutf-8はよく触れる機会がありますが、内容を理解していなかったため、記事としてまとめます。


# 2. 文字コードとは
文字コードは、コンピュータで文字や記号をバイナリ形式で表現するための規則です。文字コードは、それぞれの文字や記号に一意な数値を割り当て、これをコンピュータが理解できる形式に変換します。以下では具体例を挙げます。

## 2.1 UTF-8とは
UTF-8は、Unicode文字をエンコードするための一つの手法です。Unicodeは、異なる言語で使用される文字を一貫して扱うためのコードセットです。

UTF-8は世界的に広く使われています。。多くのソフトウェア開発プロジェクトでも利用されています。

## 2.2 JISとは

JIS(ジス)は、JIS(日本工業規格)が定めた情報交換用の文字コードのことです。また、下記のような文字の種類もJISのなかに含まれます。

・ASCIIコード
・ひらがな
・漢字
・カタカナ

なお、JISは電子メールを日本語で送受信する際の標準規格となっています。また、インターネット上においても標準的な文字コードです。

## 2.3 shift-jisとは
Shift_JIS(シフトジス)は、SJISとも呼ばれているMicrosoft社が開発した文字コードです。世界的標準であるASCIIコードの文字に、日本語を追加した文字コードになります。
日本語を扱う文字コードとしてMS-DOSやWindows、MacやUNIXなど幅広く利用されています。また、Shift_JISは、JIS規格によって定められたJISコードの改良版です。

# おわりに
文字コードについて理解を深めていただけたら幸いです。
【Day 21】ブログ一覧を取得し、表示する - API アーキテクチャ

## はじめに

![スライド22.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/ff60b5e6-310f-e808-6f97-cdb4f386889b.png)


---

**2023年アドベントカレンダー20日目**です。

https://qiita.com/advent-calendar/2023/life-sync-app

昨日に引き続き、「ユーザーはトップページでブログタイトルの一覧を見ることができる」を進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/6eb0ef2a-c7f4-7a75-add7-a866d28b214d.png)

現在はRustのAPIを作成しており、本日はアーキテクチャを検討していきます

## モジュラーモノリス

モジュラーモノリスとは、モノリシックな構造を持ちつつも内部でモジュールに分割されているのが特徴である、ソフトウェアアーキテクチャの一つです。

ソフトウェアアーキテクチャの一つで、簡潔にアプリケーションを表現することが可能です。

アプリケーションが大きくなる際は、マイクロサービスのようなアーキテクチャを採用すると良いと思いますが、今回のAPIではそれほど複雑になる予定は今のところないので、モジュラーモノリスを選択しました。
(作ってみたかった）

今回は図のように`ブログモジュール`だけで良さそうなので、ブログモジュールを持ったAPIを作っていきます

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/dfcab05e-8600-fbba-d69e-2101f138e7eb.png" width=400 />

### ディレクトリ構造

ブログモジュールを持つ、RustのAPIのディレクトリ構造を考えました。

```bash
.
├── Cargo.lock
├── Cargo.toml
├── blog      ・・・・ブログモジュール
|   ├── src/
|   └── Cargo.toml
├── db　　   　・・・・DB
├── e2e　　　　・・・・E2Eテスト
├── src       ・・・・メインモジュール
```

これをベースに作っていきます

## クリーンアーキテクチャ

Webと同様にクリーンアーキテクチャの思想に基づいてアプリを構築していきます

クリーンアーキテクチャについては【Day 11】で解説しています。

https://qiita.com/maaaashi/items/449709d121214c51eab1

### アーキテクチャ図

このようになりました。

```plantuml
@startuml

package "Domains" <<Frame>> #FFFFAA {
  class BlogId {
    +0: string
  }
  class BlogTitle {
    +0: string
  }
  class BlogAuthor {
    +0: string
  }
  class BlogBody {
    +0: string
  }
  class BlogDate {
    +0: Date
  }
  class Blog {
    +id: BlogId
    +title: BlogTitle
    +author: BlogAuthor
    +body: BlogBody
    +createdAt: BlogDate
  }
  BlogId <-- Blog
  BlogTitle <-- Blog
  BlogAuthor <-- Blog
  BlogBody <-- Blog
  BlogDate <-- Blog
}

package "Usecases" <<Frame>> #FFAAAA {
  class GetBlogsUsecase {
    run(): Result<Vec<Blog>>
  }

  package Port {
    interface BlogPort {
      +get(): Result<Vec<Blog>>
    }
    GetBlogsUsecase ..> BlogPort : <<uses>>
  }
  Blog <-- GetBlogsUsecase
}

package "Gateways" <<Frame>> #AAFFAA {
  class BlogGateway {
    +get(): Result<Vec<Blog>>
  }
  BlogPort <|.. BlogGateway : <<implement>>
}

package "Drivers" <<Frame>> #AAAAFF {
  class BlogDriver {
    +get(): Result<BlogsJson>
  }
  BlogGateway --> BlogDriver : <<uses>>
}


package "Rest" <<Frame>> #AAAAFF {
  class GetBlogRest {
    run(): Json<BlogsJson>
  }
  GetBlogRest -right-> GetBlogsUsecase : <<uses>>
}

package "DB" <<Frame>> {
}
BlogDriver --> DB : <<uses>>

@enduml
```

明日からはついにモジュラーモノリスで、クリーンアーキテクチャに基づいてアプリの実装を進めていきます！