OmniAICreator/Qiita-1.07M huggingface dataset:
Gitリポジトリの取得について git init || git clone

# 記事の目的
+ "git init"の"git clone"違いについて記載
+ Gitプロジェクトを始める方法について記載
:::note info
+ [Pro Git]((https://git-scm.com/book/ja/v2)
)を基に記事を作成しました。
+ 後ほど記事の改修しやすいように[元の記事](https://qiita.com/yuyas7/items/cafc6ff737b20e33e4d0)から分離しました。

:::


# 本文
## Gitプロジェクトを取得する方法（２通り）
+ 既存のプロジェクトやディレクトリをGitにインポートする方法 "git init"
+ 既存の Gitリポジトリを別のサーバーからクローンする方法 "git clone"

### 既存のディレクトリでのリポジトリの初期化 "git init"
既存のプロジェクトをGitで管理し始める時は、そのプロジェクトのディレクトリに移動して次のように打ち込む。
```
$ git init
```
これを実行すると、 **.git** という名前の新しいサブディレクトリが作られ、リポジトリに必要な全てのファイルがその中に格納されます。
これを実行した時点ではプロジェクト内のファイルは一切監視対象になっていない。
すでに存在するファイルのバージョン管理を始めたい場合は、そのファイルを **git add** コマンドを実行した後で **git commit** コマンドを実行すればいい。
```
$ git add readme.txt
$ git add LICENSE
$ git commit -m 'initial project version'
```
この時点で、監視対象のファイルを持つGitリポジトリが出来上がり最初のコミットまですんだ。

### 既存のリポジトリのクローン
+ 既存のGitリポジトリのコピーを取得できるコマンドが **git clone** 。
+ "checkout"ではなく"clone"なのは、Gitは一部だけをコピーするのではなくてサーバーが保持しているデータをほぼ全てコピーするから。（全てのファイルの全ての歴史も）
仮にサーバーが壊れても、どこかのクライアントに残っているクローンをサーバーに戻せば復元できる。
+ リポジトリをクローンするには **git clone [url]** とします。
+ 例えばGitライブラリ **sample** をクローンする場合は次のようになる
```
$ git clone https://github.com/sample/test
```
これは、まず **test** というディレクトリを作成してその中で、Gitを初期化し、リポジトリの全てのデータを引き出し、そして最新バージョンの作業コピーをチェックアウトします。
新しくできた **test** ディレクトリに入ると、プロジェクトのファイルを見れます。

#### もし **test** ではない別の名前のディレクトリにクローンしたい場合
コマンドラインオプションでディレクトリ名を指定できます。
```
先ほどと同じ処理をしますが、ディレクトリ名は mytest になる
$ git clone https://github.com/sample/test mytest
```
+ Gitはさまざまな転送プロトコルを使用することができる。

:::note info
以降、例で使うGitライブラリは多言語へのバインディングが可能な"libgit2"をクローンしたものとします。
:::

```
$ git clone https://github.com/libgit2/libgit2
```


# 参考文献
+ [Pro Git ver.日本語訳](https://git-scm.com/book/ja/v2)

# Gitについてのリンク
+ [Gitを理解するためにProGitを読んでみた。](https://qiita.com/yuyas7/items/cafc6ff737b20e33e4d0)
RubyVMの高速化の仕組み：中間言語と最適化

# RubyVMの高速化の仕組み：中間言語と最適化

Rubyは、そのエレガントな構文と高い生産性から多くの開発者に愛されていますが、従来の実行速度の遅さが課題となっていました。この問題を解決するために導入されたのがRuby VM (YARV: Yet Another Ruby VM) です。この記事では、Ruby VMがどのようにRubyの実行を高速化しているのか、その背後にあるメカニズムとテクノロジーに焦点を当てて解説します。

### バイトコードインタプリタの導入

従来のRubyインタプリタは、ソースコードを直接解釈して実行するプロセスを採用していました。これは、コードの各行を逐一解析し、対応するマシンコードに変換するため、オーバーヘッドが大きくパフォーマンスのボトルネックになることがありました。

Ruby VMの導入により、ソースコードは先に「バイトコード」という中間表現に変換され、このバイトコードがRuby VM上で実行されます。バイトコードは、高レベル言語とマシンコードの間に位置する、より実行に適した形式です。このステップが、実行時間の短縮と、より効率的なコードの最適化を可能にしています。

### JITコンパイラの活用

Ruby 2.6以降、JIT（Just-In-Time）コンパイラが導入されました。JITコンパイラは、プログラムの実行時にバイトコードをマシンコードに動的にコンパイルします。これにより、頻繁に使用されるコードパスは高速化され、プログラム全体の実行時間が大幅に削減されることがあります。

### ガベージコレクションの最適化

メモリ管理もパフォーマンス向上の鍵です。Ruby VMは、ガベージコレクションのアルゴリズムを改善し、不要になったオブジェクトのメモリを効率的に解放することで、メモリフットプリントを小さく保ちます。これにより、プログラムがスムーズに実行され、リソースをより効率的に使用することができます。

### フットプリントとオーバーヘッドのバランス

最適化されたバイトコードインタプリタやJITコンパイラを使用することで、Ruby VMはオーバーヘッドを削減しながらも、アプリケーションのフットプリントを最適化します。これは、システムリソースの更なる効率的な使用と、高速な実行時間の実現に寄与しています。

### Rubyの命令実行フロー：Ruby VM導入前と導入後

**Ruby VM導入前**:

従来のRubyインタプリタ（MRI: Matz's Ruby Interpreter）では、ソースコードの実行プロセスが直接的でした。このプロセスは、以下のステップで構成されていました。

1. **ソースコードの解析**: Rubyインタプリタは、プログラムのソースコードを読み取り、トークン化（字句解析）し、構文解析を行います。この結果、抽象構文木（AST）が生成されます。

2. **実行**: 生成されたASTに基づき、インタプリタはノードを順に評価し、対応するオペレーションを実行します。このプロセスは、ソースコードの各部分が直接マシンコードに変換されるため、一定のオーバーヘッドが発生します。

この方式は、すべての命令が実行時に解釈されるため、パフォーマンス上のオーバーヘッドが大きいという課題がありました。

**Ruby VM（YARV）導入後**:

Ruby VMの導入により、実行プロセスにおけるいくつかの変更があり、パフォーマンスが向上しました。

1. **ソースコードの解析**: このステップは従来と同じく、ソースコードのトークン化と構文解析が行われ、ASTが生成されます。

2. **バイトコードの生成**: Ruby VMでは、ASTは中間表現である「バイトコード」にコンパイルされます。このバイトコードは、実行をより効率的にするために最適化された形式です。

3. **バイトコードの実行**: 生成されたバイトコードは、Ruby VMによって直接実行されるか、またはJITコンパイラによってさらにマシンコードに変換されます。このステップは、実行速度を大幅に向上させます。

Ruby VMの採用により、バイトコードへのコンパイルとその最適化実行のプロセスが加わり、プログラムの実行が大幅に高速化されました。特に、再利用可能なコードの解析を一度だけに抑えることができ、コードの実行パスを効率的に最適化することが可能になりました。

### まとめ

Ruby VMの高速化テクノロジーは、開発者が愛するプログラミング言語のパフォーマンスを革命的に改善しました。バイトコードインタプリタの採用、JITコンパイラの導入、そしてメモリ管理の効率化など、これらの最適化手法はRubyのポテンシャルをさらに引き出し、より多くのシナリオでの使用を可能にしています。これからもRuby VMの進化に注目して、その成長を見守りたいと思います。
CodeLlamaを試してみる

# 概要
llama2に元に作成されたcodeing用のLLMであるCodeLlamaを動かしてみようと思います。

# 環境構築
### vscodeの設定
vscodeのContinuというアドオンをインストールします。

### llama.cppの構築
llama.cppのレポジトリをクローンして、ビルドします。
```
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make
```

次にHuggingfaceからモデルをダウロードします。
```
# 7Bのインストラクトモデルをダウンロードします。
cd path_to_llama.cpp/models/
wget https://huggingface.co/TheBloke/CodeLlama-7B-Instruct-GGUF/resolve/main/codellama-7b-instruct.Q8_0.gguf
```

### モデルの起動
次のコマンドでローカルPC内にサーバを立ち上げます。
```
cd /path-to-llama.cpp/
./server -c 4096 --host 0.0.0.0 -t 16 --mlock -m models/codellama-7b-instruct.Q8_0.gguf
```
ブラウザを開いてlocalhost:8080にアクセスして、ちゃんと起動してるか確認しています。下の画像の画面が開けばOKです。
![スクリーンショット 2023-10-25 17.37.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088169/c730efcb-0e86-17c8-2fac-32843eaa16f7.png)

次に、Continueのタブ？を開いて、LLMのprovierをllama.cppにします。
![スクリーンショット 2023-10-25 17.39.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088169/dc0dae46-8915-5cb2-df80-3d68e1722eb1.png)

そして、モデルの選択で、7bのCodeLlama Instructを選べば完了です。
![スクリーンショット 2023-10-25 17.40.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088169/7b3e71f5-2ec3-a9ea-7c8f-68a7085b29eb.png)

好きなことをお話ししてみましょう。自分の環境では、11.57 ms/tokenほどで、結構サクサク答えてくれます。
![スクリーンショット 2023-10-25 17.43.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088169/bc834ba2-f3b2-7c22-ae00-02287eef7863.png)
バージョン管理ツール(VCS)とGitについて

# 記事の目的
+ [Pro Git]((https://git-scm.com/book/ja/v2)
)を基に記事を作成しました。
+ 後ほど記事の改修しやすいように[元の記事](https://qiita.com/yuyas7/items/cafc6ff737b20e33e4d0)から分離しました。
+ バージョン管理システムとはなんぞやGitとはなんぞやをコンセプトに書きました。

# 本文
## 1.バージョン管理(VCS)
+ そもそもVCSとは
一つのファイルやファイルの集合体に対して時間とともに加えられていく変更を記録するシステムで、後で特定バージョンを呼び出すことができるようにすること。
+ できること
・ファイルを以前の状態に戻す。
・プロジェクト丸ごとを以前の状態に戻す。
・過去の変更履歴を比較
・問題が起こっているかもしれないものを誰が最後に修正したかを確認できる。
・誰がいつ問題点を混入させたかを確認したり。
・ファイルを失ったり、やっていることがメチャクチャになっても普通は簡単に復活させられる。
などなど
しかも、これらのことにかかるオーバーヘッドは僅かである。

+ ローカルバージョン管理システム
・有名なVCSツール：RCS
・多数の人々が使っているバージョン管理手法は、他のディレクトリにファイルをコピーする。
特徴：シンプルで分かりやすいがすごく間違いが起こりやすい。
問題点：うっかり間違ったファイルに書き込んだり、上書きするつもりのないファイルを上書きしてしまったり。
例：
```
: ls
新しいファイル, 新しいファイル２, 真新しいファイル,
真新しいファイル２, 真新しいファイル２-1
```
・解決法：ローカルのVCSの開発
バージョン管理下のファイルに対する全ての変更を保持するシンプルなデータベースによるもの
問題点：他のシステムを使う開発者と共同作業ができない（もしくは面倒臭い）。バックアップをとってなかったらパソコンが壊れたら全て失うリスクあり。

+ 集中バージョン管理システム（CVCS）
・有名なシステム：CVS, Subversion, Perforceなど
・ローカルとの比較：他のシステムを使う開発者と共同作業ができる。
・特徴：バージョン管理されたファイルを全て持つ一つのサーバーと、その中心点からファイルをチェックアウトする多数のクライアントでなっている。長年の間、バージョン管理の標準だった。
・利点：ローカルと比べて、プロジェクトの他の皆が何をしているのか、全員がある程度わかる。管理者は、誰が何をできるのかについて、きめ細かくコントロールできる。一つのCVCSを管理するだけなので、全てのクライアントのローカル・データベースを取り扱うより、ずっと簡単。
・マイナス面：中央サーバーがダウンすると共同作業ができなくなる。ローカルVCSと同じく壊れたら全て失うリスクあり。

+ 分散バージョン管理システム（DVCS）
・有名なシステム：Git, Mercurial, Bazaar, Darcs
・特徴：CVCSの良いところを継ぎ、マイナス面を改善した。
・一は全、全は一みたいな感じ
・クライアントは、ピックアップするのみでなくてリポジトリ全体をミラーリングする。
つまり、サーバーをコピーすることになるので実質バックアップをとっている。
・階層モデルなどの、集中システムでは不可能な幾つかのワークフローが構築できるようになった。

## 2.Gitとは
+ Gitざっくり略史
Linux開発コミュニティが今まで使っていたDVCS（BitKeeper）が無課金で使えなくなったから作った。
Gitは、DVCSを扱っていた教訓を元に作った。

+ Gitシステム開発時の目標
・スピード
・シンプルな設計
・ノンリニア開発（数千の並列ブランチ）への強力なサポート
・完全な分散
・Linuxカーネルのような大規模プロジェクトを（スピードとデータサイズで）効率的に取り扱い可能

+ 特徴
データについての考え方：スナップショットで、差分ではない
ネットワークについて：ほとんど全ての操作がローカル
履歴について：完全性を持つ。転送中に情報を失う、もしくは壊れたファイルを取得することはない。
データベース操作：通常はデータを追加するだけ
三つの状態：コミット済み、修正済み、ステージ済み(Working Directory, Ataging Area, .git directory(Repository))

+ 通常ワークフロー
1\.作業ディレクトリのファイルを修正します。
2\.修正されたファイルのスナップショットをステージング・エリアに追加して、ファイルをステージします。
3\.コミットします。


## 3.Gitと他VCSの違い
Gitは、他のVCS(CVS, Subversion, Perforce, Bazaar等々)とは大きく異なっている。
|  | Git | 他 |
|:-:|:-:|:-:|
| データについての考え方 | ミニ・ファイルシステムのスナップショットの集合  | 情報をファイルを基本とした変更のリストとして格納  |
|  スピード |  ほぼローカルだから早い |  ネットワーク遅延損失してるからモッサリ |
| データの保証  | 情報ロスなし  | あるらしい |
|データ作業|追加するだけ|複雑な操作があるらしい|

# 参考文献
+ [Pro Git ver.日本語訳](https://git-scm.com/book/ja/v2)

# Gitについてのリンク
+ [Gitを理解するためにProGitを読んでみた。](https://qiita.com/yuyas7/items/cafc6ff737b20e33e4d0)
wslでelixir その85

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

# 練習問題
Livebookでyoutubeを表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c441e646-fbf8-c20c-0a8e-569e6ea11559.png)


# サンプルコード

```
defmodule KinoHTML.Iframe do
	use Kino.JS
	def new(html) do
		Kino.JS.new(__MODULE__, html)
	end
	asset "main.js" do
		"""
		export function init(ctx, html) {
			const iframe = document.createElement("iframe");
			iframe.setAttribute("src", html);
			iframe.style.width = "100%";
			iframe.style.height = "500px";
			iframe.style.border = "0";
			ctx.root.appendChild(iframe);
		}
		"""
	end
end

KinoHTML.Iframe.new("https://www.youtube.com/embed/SEcxzrggdIo")


```

以上。
Mongooseのモデルをホットリロードすると上書きできなくてエラーで死ぬので、モデルが存在していたら上書きしないようにするが、雑にやると型がつかないしきっちりやると面倒なのをどうにかする

# タイトルを参照のこと

言いたいことはタイトルに詰めてある。
長いタイトルですまない。

Mongooseで型定義する。ミニマムだとこんな感じ
```typescript
import { model } from 'mongoose'
const USER = 'user'
const UserSchema = new Schema({
  name:String
})
export const UserModel = model(USER, UserSchema)
```

これで良いのだが、開発中にホットリロードをさせると、以下のエラーで死ぬ。
```
 Cannot overwrite model once compiled Mongoose
```
`model()`を呼び出す際に同じ名前で登録してはいかんと。

ググるとこういう解法がいくつかヒットする。

```diff_typescript
- import { model } from 'mongoose'
+ import { model, models } from 'mongoose'
- export const UserModel = model(USER, UserSchema)
+ export const UserModel = models[USER] || model(USER, UserSchema)
```
定義したモデルは`models[model_name]`にあるので、すでに定義されていたら(ホットリロード時)それを利用すればよいということだ。
~~(上書きしてないのに更新したモデルが反映される仕組みは正直よくわからない。まぁコネクションのバッファリングのようにうまいことやってんでしょう)~~
(上書きしていないので当然モデルの更新自体は反映されない。モデルが更新される場合は大人しく再起動しよう)

これで確かに動作するのだが、この場合の`models[USER]`だと戻る型が汎用のモデルとなり、利用する側で具体的な型情報が使えない。これでは何のためにtsを書いているのかわからない。

更にググると、これを解消するのに、スキーマを以下のように定義する方法が出てくる。
```typescript
import { model, models, Model } from 'mongoose'
const USER = 'user'
const UserSchema = new Schema({
  name:String
})
type TUser = {
  name:string// < ????
}
interface IUser extends Model<TUser> {}
export const UserModel = models[USER] as IUser || model(USER, UserSchema)
```

さっきまでスキーマの中にしかなかった`name`が二重管理になってしまう。他のフィールドやメソッドを増やすたび同期させるのは地獄だし、なによりホットリロードのためにこんなコードが増えるというのは耐え難い。
これは公式にも載ってる型定義の方法でクールだみたいな反応があったが正気なのか。
DRY原則ってもうおじさんしか知らないの？

こんな解法もあった
```typescript
function getModel(){
  return model(USER, UserSchema)
}
export const UserModel = (models[USER] || getModel()) as ReturnType<typeof getModel>
```
これはなるほど賢い。やはりホットリロードのためにほぼ無意味な関数を作るところに若干引っかかるものの、まぁ許容範囲だろう。
この"引数によって戻りの型が変わる関数を実際には実行せずに結果の型だけ得たい"時、関数でラップしてReturnTypeを使うというのはtsのパターンの一つであろう。覚えておいて損はない。
これでいいかと妥協しかけたその時天啓が降りてきた。
こうすりゃいいんじゃないか。

```typescript
const _UserModel = models[USER] as unknown as null
export const UserModel = _UserModel ?? model(USER, UserSchema)
```
`models`にストアされている定義は常にnullであり、(推論としては)常に`model()`の実行がされるのだと型システムを騙すことで、返される型情報としては`model()`実行時のものだけとなる。
もちろん実際のホットリロードの際にはmodelsにある定義が返り、`model()`の実行はされない。
ランタイムの動作と型情報に齟齬が起きるのはいかがなのかという指摘はあろうが、そういう型システムをハックしている感も含めて極めてエレガントだと思っている。HRのための型のための型など書きたくないのだ。
それをさらにゴルフしてこうだ。
```typescript
export const UserModel = models[USER] as unknown as null ?? model(USER, UserSchema)
```

調べた限りではこの方法は見当たらなかったので特許を取りたいくらいだ。
このパターンに名前がついていたら教えてほしい。

なお元も子もないがこれでもいいというのも見た。
ライブラリの用意しているオブジェクトを壊すのは動作に不安があるのと、行儀としても抵抗があったので採用していない。
```typescript
delete models[USER]
export const UserModel = model(USER, UserSchema)
```

## というか
[StackOverflowのトピック](https://stackoverflow.com/questions/19051041/cannot-overwrite-model-once-compiled-mongoose)は立てられたのが10年前で、最近まで投稿されている。
本来差し替えられるような方法用意してくれるべきよな。

## 参考
https://stackoverflow.com/questions/19051041/cannot-overwrite-model-once-compiled-mongoose

https://zenn.dev/azukiazusa/articles/4431b9e66ff9dc
無料＋4日でMongoDB Associate Developer Certificationに合格した

## TLDR

タイトルの通り、**MongoDB Associate Developer試験**に合格しました。

https://learn.mongodb.com/pages/mongodb-associate-developer-exam

通常$150ですが、学生は無料（一般の人でもコースを修了すれば半額になります）で受験でき、失効がない資格です。
試験範囲もそこまで広くなく、僕の場合、**勉強開始～受験日まで4日間、トータル15時間くらい**で完了できました。
すごくおすすめの試験なのですが、日本のコミュニティではメジャーでない様子ですし、日本語の受験記録情報が全然みつからなかったので、記事にまとめてみます。

## この試験について

この試験は名前の通り開発者用の試験です。クエリ操作や各言語のドライバ（ライブラリ）を使ってMongoDBを操作する方法を問われます。
ドライバに関する出題は、C#, Java, Node.JS, PHP, Pythonの中から１つの言語を選んで、その言語のドライバに関するものになります。

この資格はMongoDBのメジャーバージョンごとに発行されますが、失効期限はありません。
つまり、2023年10月現在にこの試験を受験すると、メジャーバージョンであるMongoDB 7系の知識に対して認定が発行されます。次回メジャーバージョン（つまり8）がリリースされたときには、新しく追加された機能等の知識についてこの資格を再受験することができます。

試験範囲は全てMongoDBのスタディリソースであるMongoDB UniversityのMongoDB Developer Learning Pathsでカバーされます。
MongoDB Universityのセルフペースラボは誰でも無料で受講できます。
同期型の講師によるリモートクラスもありますが、そちらは有料のようです。

https://learn.mongodb.com/pages/mongodb-developer-learning-paths

試験範囲はこのスタディガイドに示されています。
MongoDB独自のクエリについてもそこまで範囲は広くありません。

https://learn.mongodb.com/learn/course/mongodb-associate-developer-exam-study-guide

模擬試験も無料で提供されています。

https://learn.mongodb.com/pages/mongodb-developer-practice-questions

試験形式は自宅＋オンライン受験のみです。ウェブカメラとマイクと画面共有をオンにして、試験官による監視を受けながら受験します。
試験は英語で行われますが、英語ネイティブスピーカーでない場合は試験時間の延長リクエストと試験中にGoogle翻訳を使うことが認められています。

## 学生用無料バウチャーor一般用半額バウチャーの入手方法

上で示した、MongoDB UniversityのMongoDB Developer Learning Pathsをひとつ修了すると自動的に送付されます。
学生の場合、GitHub Student Developer Packageとのリンクがうまくいっていない場合、自動的に送付されません。手動で申し込みをする必要があります。
僕はこのパターンで申し込みを行いましたが、対応めちゃめちゃ早かったです。30分くらいでバウチャーが発行されました。

https://education.github.com/pack

↓手動申し込みリンクはここにあります
https://www.mongodb.com/students


## 認定取得までのプロセス

今回、僕はPythonで受験しました。
簡単に認定までにやったことをまとめます。

1. MongoDB Developer Learning Pathを完了する（10時間くらい）
1. 満点を取れるまで模擬試験を受けなおす（5時間くらい）
    模擬試験は問題の解答に関しての解説がありません。ここでChatGPTを併用して、間違えた問題については逐次ChatGPTに解説してもらいながら理解を深めていきました。
1. 試験を受験する！

全く特別なことはやっていません。無料で提供されている公式のリソースをしっかりやりこむだけで高得点で合格できました。（リザルト保存しなかったのでうろ覚えですが各分野85~100%でした）

## 試験の流れ

この試験は英語でのオンライン試験だけが提供されています。
前述のように、Google翻訳を使うことができるので試験受験に関しては困りません。
ただ、一点、試験開始前に試験官と英語でコミュニケーションする必要があります。多分ここが一番の難所なので試験を受ける人が少ないと思われますが…
ネイティブスピーカーでないことを伝えれば多分配慮してくれるとは思います。
とりあえず、試験前準備としてやったことを流れで書いておきます。

1. ブラウザで試験サイトに接続する
1. 試験官がログインして、試験前の環境確認を始める
1. 受験する試験、受験者の名前等の確認。
1. 免許証、パスポートなどのIDを表示する。このIDは英語表記がないものでも許可されている
1. 注意事項が読み上げられる。ただ聞いているだけでOK。
1. 試験環境の周囲を360度試験官に見せる。カメラを持ってぐるっと回って、デスクを映す。デスクは整頓されて余計なものが置かれていない状況である必要がある。
1. 試験開始！
1. 試験が終わったら試験サイトを終了して完了。

## まとめ

MongoDBについては完全素人でしたが、短期間である程度理解することができました。
これについてひとつ資格を取得しておくだけで、NoSQLについての理解も示すことができると思いますし、履歴書を飾るにはちょうどいい資格です。
英語の壁はありますが、ぜひぜひチャレンジしてみてください！
【2023年10月最新】shopifyにFontAwesomeを導入する

# はじめに
「shopify fontawesome」でググった時に日本語の記事1件、qiitaでは記事が見当たらず、3時間ほど溶かしたため(・ω・;)書いておきます。

shopifyでFontAwesomeを使う場合、以下の２パターンに大別されるはず。

1. FontAwesomeのファイルをassetsに格納して呼び出す
1. CDNをテーマファイルに記述する 

動作環境に左右されづらい、１が推奨だが、自分の環境ではAseetsに格納して呼び出すことができなかったため、2で対応しました。

:::note info
以下の環境で動作確認済。
shopifyテーマのバージョン : Dawn 11.0.0
FontAwesomeバージョン: 6系（v6.2.1）
※ 使用するFontAwesomeアイコンは無償版のみ
:::

> 参考: 
[Shopifyのテーマのバージョン確認方法](https://lumpgather.com/move/theme-update/#:~:text=Shopify%E3%81%AE%E3%83%86%E3%83%BC%E3%83%9E%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95)
> [Versions of Font Awesome](https://fontawesome.com/versions)

# 導入手順
theme.liquid の`<head>`タグ内に以下の一文を挿入

```html
<!-- この一文を挿入 -->
<link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.2.1/css/all.css">
```

```html:theme.liquid
<html class="no-js" lang="{{ request.locale.iso_code }}">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="theme-color" content="">
    <link rel="canonical" href="{{ canonical_url }}">
    <!-- この一文を挿入 -->
    <link rel="stylesheet" href="https://site-assets.fontawesome.com/releases/v6.2.1/css/all.css">
...
```

以上。後は、FontAwesomeを使いたい箇所にFontAwesomeのhtml記法`<i class=""></i>`を記述するだけ。

# FontAwesomeアイコンを画面に表示する

以下は、shopifyのコード編集を始めて触る方向けの参考例。

### FontAwesomeアイコン用snippetsを作成する(liquidファイル)

例としてFontAwesomeアイコン`circle-arrow-up`を使用
※ 自前の作成クラスを併用する場合は、`class = custom-css`の記述を参考。

```html:font-awesome.liquid
<i class="fa-solid fa-circle-chevron-up fa-3x custom-css" style="color: #424242;"></i>

<style>
.custom-css{
  position: fixed;
  bottom: 15px;
  right: 10px;
  background-color: white;
  border-radius: 28px;
}

```

### FontAwesomeアイコンを埋め込む

`theme.liquid`の`</body>`タグ直前に以下の記述を挿入

```html:theme.liquid
...
    <!-- FontAwesomeアイコン -->    
    {% render "font-awesome" %}
  </body>
</html>
```

`"font-awesome"`がFontAwesomeアイコン用snippetsのファイル名に対応しています。

以下のようにshopify画面のヘッダー右下にFontAwesomeアイコンが表示されていれば成功です。


![fontAwsome.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121397/1f66cd1d-7938-2ccd-3ee7-e3d24348a773.jpeg)


## 参考記事
> [ShopifyにFont Awesome（無料版）を導入する](https://blog.mayo31.info/archives/3504)
> [Can't Get FontAwesome Brand Font To Work In Footer
](https://community.shopify.com/c/shopify-design/can-t-get-fontawesome-brand-font-to-work-in-footer/m-p/1883663)
ABC-001 A「積雪深差」解説

# 前置き
皆さん、こんにちは！
今回はABC-001のA問題「積雪深差」について解説していきたいと思います！
（https://atcoder.jp/contests/abc001/tasks/abc001_1)


# 目次
- 問題概要
- 制約
- 入力形式
- 解説
- おまけ


# 問題概要
ある時刻の積雪深$H_1$とその1時間前の積雪深$H_2$が与えられる。
この1時間前の間に降った雪の量$H_1 - H_2 $を出力してください。

# 制約
$0 \leq H_1, H_2 \leq 2000$

# 入力形式

$H_1$
$H_2$


# 解説
問題文に書いてある通りに $H_1 - H_2 $ を出力すれば正解になります。
$H_1, H_2$が2行にわたって与えられているので、`int(input())`を2回書いて入力を行うと正常に数字を受け取ることができます。


↓こちらが正しい出力をするコードです。
```python:001-A.py
h1  = int(input())
h2  = int(input())
ans = h1-h2

print(ans)
```

[AtCoderで提出したコード](https://atcoder.jp/contests/abc001/submissions/37968521)



## おまけ
この問題をFortranで実装したコードも置いておきます。
Fortranの基礎を習得してみたい方は是非ご覧下さい。
```Fortran:001-A.f95
Program Answer
Implicit None
 
INTEGER H1,H2,ans
read *, H1
read *, H2
ans = H1 - H2

PRINT "(I0)" , ans

END Program Answer
```

[FortranバージョンのACコード](https://atcoder.jp/contests/abc001/submissions/46930451)
ローマ字表記(Tokyo, Hokkaido等)の都道府県のリストを取得する

# 目的
都道府県のリストを取得する

# 準備
pycountryを
```pip install pycountry```
でインストール

# コード
```
import pycountry
def get_subdivision_name(iso_code):
    subdivision = pycountry.subdivisions.get(code=iso_code)
    if subdivision:
        return subdivision.name
    return None
prefecture_list = []

for i in range(1,48):
    num = str(i)
    if i<=9 :
        num = "0"+num
    prefecture_list.append(get_subdivision_name("JP-"+num))

print(prefecture)
```

# やっていること
ISO_3166-2:JPという都道府県ごとに一意に割り振られているコードを利用している。
この都道府県コードは"JP-01"から"JP-47"まである。
その都道府県コードをこちらでfor文で生成し、それらをデコードしてリストに追加していくことで、目標の全都道府県のリストを得ている。
https://ja.wikipedia.org/wiki/ISO_3166-2:JP
【windows】ユーザーブロファイルを別のユーザーで再構築する

# 前書き
### はじめに

windowsアップデート後に再起動をすると、以下のようなエラーが表示された。

***
<b>プロファイルエラー
ユーザー設定の読み取りも、ユーザー設定への変更保存もできません。すべての機能を使用できない可能性があります。</b>
***
おそらく何らかのエラーでユーザープロファイルが破損したと読み取れる。
sfc /scannow してみたり、セーフモードで入ってみたり、chkdsk *: /f やってみたり、ネットに転がっている一般的な処置をいろいろ試してみたがどれもうまくいかなかった。ユーザープロファイルが破損する原因は一つではなく、実に多様で様々な要因が絡み合って発生することがあるため、今回はユーザーを作り直す方が早いと判断し解決した。この記事はその対処法の一連の流れをまとめたものである。

#### 前提条件
本記事を取り扱う上での前提条件で以下の状態に問題がないか要確認。(これらが確認できない場合、他の手法を検討してください)
* ショートカットキー「windows + R」から、「cmd」と検索し、 コマンドプロンプトを立ち上げることができる。
* エクスプローラを開くことができる。


# 実行環境
windows11 Home 22H2

# コマンドプロンプトで使用するコマンド
### コマンドプロンプトを管理者で開く

はじめに、「windows + R」を押すと以下の画像のような画面が出るので、「cmd」と入力する。
管理者権限で実行するため、「Shift + Ctrl」を押しながらOKボタンをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/8505247a-9458-3809-4ac3-cd91a6be6867.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/2c426212-d337-9a63-8954-dac7e21ffcbc.png)となっていればOK


### ローカルアカウント作成
```
net user <user_name> /add
```

### 追加したアカウントを管理者グループに追加
```
net localgroup administrators <user_name> /add 
```

### 追加したアカウントが管理者グループに入ってること確認する
```
net user <user_name>
```

### アカウントのパスワードを変更する(初期はパスワードなしになってる)
```
net user <user_name> <password>
```

### ユーザーの切り替え
ショートカットキー「Ctrl + Alt + Del」 から「ユーザーの切り替え」でユーザーを切替える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/447e6f36-2fe0-9d1e-897a-5c98f93dd4e6.png)

### 新しいユーザーにデータを引っ越す
新しいユーザーにログインしたらエクスプローラーを開き、
<b>C:¥users¥{コピー元のユーザー名}</b>を検索窓で検索

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/260fea1a-297e-d12b-2150-f6b41f301a0e.png)

::: note warn
※検索して出てこなかったら、C:¥ユーザー¥{コピー元になるユーザー名}で検索
:::


この階層のフォルダやファイルをすべてコピーする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/d6e12520-a884-beae-1deb-55a6bd46b288.png)

その後、<b>C:¥users¥{コピー先のユーザー名}</b>を検索窓で検索して同じ階層にペーストする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704823/14a60937-c9f8-5937-3f68-b7f94947955b.png)

SSDの書き出し読み取りの速度やフォルダーの数・サイズによってコピペの時間が大きく変わるが、私の場合55GBでおよそ12分ほどだった。

::: note alert
思わぬエラーやフリーズを避けるためにも、アプリケーションは再度改めてインストールしなおしたほうが良い
:::

### 前のユーザーアカウントを削除する

```
net user <old_user_name> /delete
```

プロファイルエラーが起きているうちは完全に修復が見込める可能性がない限り前のユーザーアカウントは削除しといた方が良い

## おわりに
GUIで操作しようにも設定画面が開けなくてどうしたら困っていたので、コマンドプロンプトで簡単に実行できたのは非常に楽で便利だった。今後も起こりかねないエラーなので一連の操作は覚えておきたい。

## 参照サイト
- [net userコマンドでユーザーアカウントとパスワードを作成・削除・管理する - 協栄情報ブログ](https://cloud5.jp/net-user/)
JavaのSteam APIを使ってみた

```java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class HelloWorld {
    public static void main(String[] args) {

        List<Map<String, String>> msgList = new ArrayList<>();
        
        Map<String, String> msgMap = new HashMap<>();

        msgMap.put("1", "test[warning_726]");
        msgList.add(msgMap);

        msgMap = new HashMap<>();
        msgMap.put("1", "test3333[warning_727]");
        msgList.add(msgMap);

        msgMap = new HashMap<>();
        msgMap.put("1","test2[warning_736]");
        msgList.add(msgMap);

        msgMap = new HashMap<>();
        msgMap.put("1","test21[914_warning]");
        msgList.add(msgMap);

        msgMap = new HashMap<>();
        msgMap.put("1","test255[warning_737]");
        msgList.add(msgMap);

        msgMap = new HashMap<>();
        msgMap.put("2","error_728");
        msgList.add(msgMap);

        // msgList: [{1=test[warning_726]}, {1=test3333[warning_727]}, {1=test2[warning_736]}, {1=test21[914_warning]}, {1=test255[warning_737]}, {2=error_728}]
        System.out.println("msgList: " + msgList);

        /*
         * test3333 の値を含む物の数を取得
         */
        var a = msgList.stream()
            .flatMap(msg -> msg.entrySet().stream())
            .filter(entry -> entry.getValue().contains("test3333"))
            .count();

        // a : 1
        System.out.println("a: " + a);

        /*
         * test3333 の値を含む物を取得
         */
        var b = msgList.stream()
            .flatMap(msg -> msg.entrySet().stream())
            .filter(entry -> entry.getValue().contains("test3333"))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // b: {1=test3333[warning_727]}
        System.out.println("b: " + b);

        /*
         * warning_726 の値が含まれない物を全て取得
         */
        msgList = msgList.stream()
            .filter(map -> map.entrySet().stream()
                .noneMatch(entry -> entry.getValue().contains("warning_726")))
            .collect(Collectors.toList());

        /*
         * warning_727 の値が含まれない物を全て取得
         */
        msgList = msgList.stream()
            .filter(map -> map.entrySet().stream()
                .noneMatch(entry -> entry.getValue().contains("warning_727")))
            .collect(Collectors.toList());

        // msgList: [{1=test2[warning_736]}, {1=test21[914_warning]}, {1=test255[warning_737]}, {2=error_728}]
        System.out.println("msgList: " + msgList);
    }
}
```
【HTML】【CSS】文章を改行文字で改行する方法

以下のように`white-space: pre-wrap`とすることで`<p></p>`タグの内容を改行文字で改行することができます。

```html
<style>
  .p1 {
    white-space: pre-wrap;
  }
</style>

<p class="p1"></p>

```
DIについて知りたくなった

# はじめに
Dependency Injection（依存性の注入）、通称DIは、オブジェクト指向プログラミングにおける設計原則の1つであり、特に大規模なアプリケーションやモジュール間の疎結合を実現するための手法。

# DIとは？
DIは、オブジェクトの依存関係を外部から注入する手法です。これにより、以下のような利点が得られます。

- 疎結合: クラス間の依存関係が少なく、コンポーネントの再利用や交換が容易になります。
- テスト容易性: テスト時に実際の依存をモックオブジェクトに置き換えることが容易になります。
- コードの可読性向上: 依存関係が明確になるため、コードの理解が容易になります。
# DIの動作原理
通常、オブジェクトは自身の依存関係を内部でインスタンス化します。しかし、DIを使用すると、依存関係は外部から注入され、オブジェクトのライフサイクルとは独立して管理されるようになります。

```python
# 通常の方法
class UserService:
    def __init__(self):
        self.repository = UserRepository()

# DIを使用した方法
class UserService:
    def __init__(self, repository):
        self.repository = repository
```
- コンストラクタ注入
依存関係をコンポーネントのコンストラクタを通じて注入します。

```python
class ServiceA:
    pass

class Client:
    def __init__(self, service):
        self.service = service

client = Client(ServiceA())
```
- プロパティ/セッター注入
依存関係をコンポーネントのプロパティやセッターメソッドを通じて注入します。

```python
class Client:
    @property
    def service(self):
        return self._service

    @service.setter
    def service(self, service):
        self._service = service

client = Client()
client.service = ServiceA()
```
- メソッド注入
依存関係をメソッドの引数として注入します。

```python
class Client:
    def execute(self, service):
        service.do_something()

client = Client()
client.execute(ServiceA())
```
## PythonでのDI
PythonでDIを実践する方法としては、[コンストラクタインジェクション](https://qiita.com/mt_tashi/items/f425584f1e6079fcee61)、[セッターインジェクション]()、またはDIフレームワークを使用する方法などが考えられます。

以下は、コンストラクタインジェクションを用いた例です。

```python
class UserRepository:
    def get_user(self, user_id):
        # データベースからユーザーを取得
        pass

class UserService:
    def __init__(self, repository: UserRepository):
        self.repository = repository

    def get_user_details(self, user_id):
        return self.repository.get_user(user_id)
```

# 具体的な使用例

1. Webアプリケーション
例: ユーザー認証サービス、商品管理システム、CMS等
DIを使用することで、データベース接続、外部APIとの通信、認証ロジックなどの異なる部分を柔軟に切り替えることが容易になります。

2. モバイルアプリケーション
例: 通知サービス、位置情報サービス等
異なるデバイスやOSバージョンで動作する機能の実装をスムーズに行えます。
3. マイクロサービスアーキテクチャ
例: 顧客サービス、在庫管理サービス、注文サービス等
サービス間の依存を疎結合に保ち、サービスの単体テストや統合テストを容易に行うことができます。
4. ゲーム開発
例: AIの動作、物理エンジン、グラフィックレンダリング等
異なるゲームエンジンやレンダリング技術の切り替え、AIの振る舞いの変更などが簡単に行えます。
5. IoT
例: センサーデータの収集、デバイスのリモート制御等
異なるハードウェアやプラットフォームに対して、共通のロジックを適用する際に便利です。
ObjectiveCからSwiftへコンバート

## ObjectiveCコンバーター

勉強のためObjectiveCで公開されているソースを
Swiftに書き換えてアプリを作成している。

ただ、これを自動でコンバートしてくれるツールはないかと探してみた。
あった。

https://techblog.yahoo.co.jp/ios/objc2swift/

のだが、2023年10月25日現在、Githubのページが404になってしまった。
404になるまえにソースコードを入手したので何とか実行しようと試みた。

## Gradleとはなんぞや

実行はgradleで一発らしい。
gradleとはjavaの実行環境らしい（適当）
home brewでとりあえずgradleをインストールする。

展開しているobjc2swiftのフォルダに移動してgradleした

```
cd objc2swift
gradle jar
```

さっそくエラー
```
Could not find property 'compile'
```


StackoverflowによるとCompileはもう廃止されたからimplementationを使ってくれよな！とのこと。

https://stackoverflow.com/questions/23796404/could-not-find-method-compile-for-arguments-gradle

build.gradleファイルを書き換える。
よっしゃ、もう一度gradle！からの、やっぱりエラー。
compileClasspathに書き換えるといいらしい。

https://qiita.com/MirrgieRiana/items/d3271f6979c1451207a6

結果、やっぱりエラー。
そうか、とにかくgradleのバージョンが新すぎるのがダメなんだな。

ということでsdkmanを利用して古いgradleをインストールしよう。

```
curl -s "https://get.sdkman.io" | bash
sdk list gradle
````
古いgradleがリストに表示されるのでインストール。
なんかコマンドが通らなくなったのでPATHを通す。
そんでもって、もう一度gradle！やっぱりエラー！

あとなんかリアルjavaも入れた気がする

https://zenn.dev/satokazur222/articles/66568417b291d8

でもやっぱり上手くいかない。
なんせobjc2swiftも2015年公開のものですから、そりゃ、ね。
時代も変わりますわ。

ということでコンバータはあきらめました。
JavaScript

# 初学者の備忘録
初学者の備忘録です。今回からJavaSpcriptの学習をしていきます。まずは基本編

## JavaScript基本情報
JavaScript（ジャバスクリプト）とは、オブジェクト指向スクリプト言語です。
Webページに動きをつけるためのプログラミング言語です。ボタンに触れると形や色が変わる機能や、スライドショー、ポップアップウィンドウ、ログインなど、さまざまな機能の実装に用いられます。


## 質問

【質問１】
何ができるの？

【回答】
HTML、CSSで静的Webページが作成できて、JavaScriptで動的なWebが作成できるようになります。非同期通信などが例にあります。
それとWebサーバでもJavaScriptが実行することができます。Node.jsという技術を使用します。Node.js記述を使用することでアプリケーションを作成する事も可能です。


【質問２】
おすすめフレームワークは何？

【回答】
・React（リアクト）
AndroidとiOSの両方のプラットフォームに対応していること、UI/UXを意識した開発が可能であることなどが挙げられます。最近勢いのあるフレームワークです。

・Vue.js（ビュー）
シンプルかつ自由度が高いJavaScriptフレームワークです。多くのエンジニアが利用しています。
主に中規模のWebアプリケーション開発に適しています。

・jQuery（ジェークエリ）
JavaScriptのライブラリでも歴史が古く、今でも非常に人気が高いです。
短いコードで、リッチなUIを実現することができます。つまり、jQueryはJavaScriptよりも短いコードで実装可能であるため、短縮簡易版として使用出来ることが最大の特長です。
ただし近々終了するという話も聞きます。

上記３種類が人気フレームワークです。
業務委託面談についてちょっと真面目に考えた

ある日の、アサインしたての**テックリード経験あり**の業務委託エンジニアXさんとの会話。

ワイ「XさんがコーディングしたService Classの**カバレッジ**が85%達してないので、テストコード実装してください！」

Xさん「いいえ。**テストサマリー**は100%になっています。」

ワイ（...カバレッジゆうたやん）「テストサマリーはテスト成功数/失敗数を表示しているところで、**カバレッジとは別です**。」

Xさん「そうですか。**どうやったら**カバレッジ85%になりますか？」

ワイ（えぇ...あんた面談でテスト実装のリードしてたゆうてたやん）「あー、Xさんの実装のケースだと、こういったケースの引数を渡せばここの処理到達できそうですね〜」

Xさん「すみません。**カバレッジってなんですか？**」

ポカーン

## なんでこんなことが起こるの？

これは私のケースですが...
業務委託面談は正社員の面談とは異なり、面談前準備・面談時間をかけず、代替コストも正社員と比較して軽いため比較的**雑**にアサインを決めてしまうケースが多いと思います。

雑にアサインを決定してしまった結果

* 面談者/候補者間で認識のギャップが生まれる
* 営業や候補者の誇張したセールストークを鵜呑みにしてしまう
* 求めるスキルレベルに達していない

のではないかなと。

とわ言え、あまり工数をかけるのも非効率なので、**業務委託面談についてちょっと真面目に考えてみました。**

## 注意事項

:::note warn
個人的な見解であり、所属する会社、組織とは全く関係ありません
:::

## 候補者の言葉に余計な推測を加えない

実際にあった例

<b>候補者: 「このプロジェクトではPLとしてアサインされ、顧客との要件定義から開発メンバーのマネジメント、コードレビューまで担当しました。同時に、プレイヤーとしても開発を実施していました。」</b>

このような発言から、私は以下のような解釈をしました。
> * 顧客と直接要件について協議していた
> * 要件定義書や設計書などのドキュメント全般を作成
> * 開発チームのタスクやスケジュールの全てを管理
> * 独立して開発を行う能力がある

しかし、実際の内容は以下のようなものでした。
> * 顧客との調整はPMが主に行っており、直接の接点はなし
> * 要件定義書は作成したが、開発者向けの基本設計や詳細設計のドキュメント作成の経験はなし
> * 開発チームのタスクやスケジュールの管理は、PMが作成したタスクリストやWBSに基づき進行。要件やスコープの変更、遅延が発生した際の調整はPMが実施
> * 開発経験は入力フォームの追加程度で、大規模な機能の実装経験はなし

すべてを詳しく確認するのは**難しく**、限られた時間内での確認は特に**難易度が高い**です。したがって、求めるポジションや役割に基づき、重要なポイントに焦点を当てて質問を絞ることが大切です。

たとえば、要件定義やビジネスサイドとのブリッジが主要な役割であれば、`顧客との要件定義`について深く探る必要があり、開発のスキルが中心であれば、`プレイヤーとしての開発経験`について詳しく聞くべきでしょう。

正直いえば**なんでもできる人が欲しい**ので、広く浅く聞いてしまいがちなのですが、**そんな人材は滅多にいません。**

## 実際のコードを見せ、ディスカッションを通じてコーディング能力を確認する

これはもっと早くやるべきでした。

正直、業務委託面談でここまでやるべきかなぁ〜と考えていたのですが、**この工程を挟むことで、かなりギャップが減ります。**
**正しい答えが出せるか**も大切ですが、私は**どういったコミュニケーションをとるか**の方を重視しています。

例えば、

>「こうでしょ、ここはこうでしょ。え〜こうでしょ！」
>「いや〜それってどうなんですかねぇ〜（嘲笑）」

このような、少し攻撃的なコミュニケーションをとる方もいますし、

> 「最近コーディングしてないから分かんないっす！」
> 「Java...分かんないっす...」

**なんでこの面談きた？** って方もいます。

逆に、答えられなくても、

> 「すみません、この処理ってこういうことですか？」

このように、問題解決に向けて前向きなコミュニケーションをとる方もいます。これは実際の業務でも大事なスキルです。事前に確認することで、トラブルを減らせると考えています。

実際に、私はこういった問題を出しております。
下記のようなJavaのコードを10-15分程度の間で見せ、それに関する質問を投げかけます。

```java
public class Fibonacci {
    public static int fibonacci(int n) {
        if (n <= 1) {
            return n;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
 
    public static void main(String[] args) {
        int result = fibonacci(5);
        System.out.println("Fibonacci(5) = " + result);
    }
}
```
質問例:

<b>Q.このコードを実行した際の出力結果は何ですか？</b>
<b>Q.このコードをレビューするとすれば、どのような指摘をあげますか？</b>

## 言語モデルの活用に関する質問を取り入れる

近年、**ChatGPT**や**GitHub Copilot**のような言語モデルを活用したAI技術が急速に発展・普及しており、これらの技術を活用することで、**エンジニアの情報処理能力**に天と地の差が出ると考えております。

しかし、多くのエンジニアがまだこれらの技術に**触れていない**のも事実です。

セキュリティ上の制約や業務環境の問題で、これらの技術を導入することが難しいケースも存在します。ただ、このような最新の技術トレンドに疎いことは、エンジニアとしての**情報収集能力**や**適応能力**に疑問を感じさせます。

私は、現代のソフトウェアエンジニアにとって、言語モデルの理解や活用は**必須のスキル**の一つだと考えています。そこで、面接では、言語モデルをどのように活用しているか、またはなぜ活用していないのかの理由を質問しています。

## まとめ

**良い人材と働く**ことよりも**環境・現場とマッチしていない人材と働かない**ことが大事。
なので、面談では**マッチしてない部分**の確認を主軸で行うべきだなぁと思いました。

**こんな観点もあるよ〜** や **こんな質問も良いよ〜** などあればアドバイスをいただきたいです！
[Docker]dockerコマンドの時だけ発生するエラーに苦しんだ

本記事では、エラーの内容と解決した方法のみ記載してます。

環境
ubuntu 18.04
Docker 24.0.2
docker-compose 1.29.0

# いつエラーが発生したのか
Proxy環境下でDockerイメージをpullしたとき

# エラー詳細
エラーはDockerfileのFROMの行で発生しており、内容は下記の通り

```javascript
ERROR: failed to solve: python:3.9.7-slim-buster: failed to authorize: failed to fetch   
anonymous token: Get "https://auth.docker.io/token?scope=repository%3Alibrary%2Fpython%3Apull&service=registry.docker.io": read tcp x.x.x.x->x.x.x.x:443: read: connection reset by peer
```

# エラーについて色々試した結果
「どうせプロキシ周りだろう」と思い色々調べていくとどうやらdockerコマンドで実行した時だけエラーが発生していた。
docker-composeでイメージを作成する時はエラーが発生しない。

```javascript
$ docker pull alpine // NG
```

```javascript
// docker-compose.yaml
version: '3'
services:
  alpine_container:
    image: alpine
    container_name: my_alpine_container
    command: tail -f /dev/null
```

```javascript
$ docker-compose up --build // OK
```

# 解決方法
Dockerのバージョンを下げることで解決した。具体的には20.10.24をインストールした。
docker-composeのバージョンと異なりDockerは比較的新しかったので変えてみるとすんなり動いた。

強引な方法だがとりあえず解決したので良しとしておこう。
同じ状況で困っている方は一度バージョンを変えてみても良いかも知れない。

# おまけ
初めてアプリをリリースしました
https://t.co/TM0EsZKOWi
【備忘録】wsl2で立ち上げたdockerコンテナの中にうまく入れなかった話

# 初めに
wsl2を上でmysqlのコンテナを立ち上げ、そのコンテナ内でmysqlのログインをしたところ、ログイン後に文字入力ができなくなりました。
おま環かもですが、以下で解決したのでメモを残します。




# 事象

### 再現手順
①WSL2上でUbuntuディストリビューションを立ち上げ、`docker compose up -d`コマンドでコンテナを立ち上げました。
`webapp-mysql-1`がmysqlのコンテナです。
```
$ docker compose up -d
[+] Running 5/5
 ✔ Network webapp_default        Created                                                                           0.0s
 ✔ Container webapp-mysql-1      Started                                                                           0.1s
 ✔ Container webapp-memcached-1  Started                                                                           0.1s
 ✔ Container webapp-app-1        Started                                                                           0.1s
 ✔ Container webapp-nginx-1      Started                                                                           0.1s
```

②`webapp-mysql-1`のコンテナに`docker exec`コマンドで入ります。

```
$ docker exec -it webapp-mysql-1 /bin/bash
bash-4.4#
```

③mysqlにログインします
```
bash-4.4# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.34 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

手順③の後、キーボードで値を入力しても画面に表示されず、`Enter`や`Ctrl+c`も反応しなくなってしまいました。コピペも同様に入力されません。
日本語入力ができないという記事はあるものの、半角英数も入力できないので別事象です。

# 解決策
Docker DesktopのWSL integrationにあるUbuntsのチェックをONにしたら治りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/541ff6f0-91ad-8ad1-61b3-9db3599f28ec.png)

この設定は、WSL上のディストリビューションでDockerを使えるようになる設定みたいです。
そもそもなぜこのチェックがついてない状態で`docker compose up -d`ができたのか、いろいろ調べてみましたがわかりませんでした（分かる方いたらご教授ください）。



# 最後に
疑問点は残りますが、ひとまず解決できたのでメモだけ残します。
同じ状況の方いたら試してみるといいかもしれません。

# 参考
https://tech-blog.rakus.co.jp/entry/20231025/isucon-try
https://kawadev.net/wsl2-docker-desktop/
git grep がかなり便利

## git grep がかなり便利

普段開発をしている中で、特定の単語でファイル内を手軽に検索したい場合がある。
もちろんソースコードをvscodeで開いて検索しても良いが、一工程加わるので、面倒な時がある。そんなときに git 管理しているものであれば、git grep コマンドが使える。
感覚的には Linux の locate コマンドに近い。

## How to use?


```sh
 $ git grep "検索したい文字列"
```
のような感じで使える。

例えば、以下を実行すると、
```sh
 $ git grep 'def current_user'
```

下のような結果が得られる。
```ruby
app/lib/inline_renderer.rb:  def current_user
app/policies/application_policy.rb:  def current_user
app/serializers/rest/announcement_serializer.rb:  def current_user?
app/serializers/rest/poll_serializer.rb:  def current_user?
app/serializers/rest/reaction_serializer.rb:  def current_user?
app/serializers/rest/status_serializer.rb:  def current_user?
app/serializers/rest/tag_serializer.rb:  def current_user?
```
ちなみに上は、mastodon の repository を fork & clone してローカルで試した結果。

参考: https://github.com/mastodon/mastodon

### 他の使い方

公式ドキュメントには様々なオプションが載っている。
色々やってみると面白いかもしれない。

https://git-scm.com/docs/git-grep
【Swift】Package.swiftのdependenciesをタイプセーフに扱う

# はじめに
`Package.swift`の`dependencies`を文字列で指定しているとタイポしてしまう可能性があります。
そこでXcodeに補完を出してもらうことによってタイポを防ぎます。

# 実装
```swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

extension PackageDescription.Target.Dependency {
    static let dependencies: Self = .product(name: "Dependencies", package: "swift-dependencies")
}

extension PackageDescription.Target.Dependency {
    static let appFeature: Self = "AppFeature"
    static let core: Self = "Core"
    static let home: Self = "Home"
}

let package = Package(
    name: "Package",
    defaultLocalization: "en",
    platforms: [.iOS(.v16)],
    products: [
        .library(name: "AppFeature", targets: ["AppFeature"])
    ],
    dependencies: [
        .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0"),
    ],
    targets: [
        .target(name: "AppFeature", dependencies: [
            .core,
            .home,
        ]),
        .target(name: "Core", dependencies: [
            .dependencies,
        ]),
        .target(name: "Home", dependencies: [
            .dependencies,
        ]),
    ]
)
```

:::note warn
**注意**
`PackageDescription.Target.Dependency`を`Package`の前に置いておかないと補完が出てきません。
:::

# おわり
これは便利ですね
業務でよく使うExcel機能について

# 1,はじめに
お疲れ様です。
2回目の投稿になります。
現場に配属になってから2年が過ぎました。
私は2年間の現場作業で、
Excelを活用して資料などを作成していたので、
よく使っていたショートカットキーや機能について紹介したいと思います。


# 2,よく使うショートカットキーについて
#### 全選択
・ctrl+a
表やアクティブなセルを全て選択してくれる。

#### 文字検索
・ctrl+f
Excelファイル上で探したい文字などあれば便利。

#### アクティブなセルまで移動
・ctrl+矢印キー
表の一番上や一番下などマウスで動かさなくても一気に移動可能。

#### アクティブなセルの選択
・ctrl+shift+矢印キー
矢印の方向に入力済みのセルまで選択する。

#### 元に戻る
・ctrl+Z
一つ前の作業に戻る。

#### 置換
・ctrl+H
文字列を置換できる。

#### 全選択
・ctrl+a
表やアクティブなセルを全て選択してくれる。

#### セル内を編集・記載できる
・F2
マウスでダブルクリックの必要なし。

#### セル内の改行
・Alt+Enter
セル内に文字を入力した際に改行するときに使用。

# 3,よく使うExcel機能3選
1,フィルタリング
・表などを作成した際に、昇順・降順、特定の文字検索に役立つ。
![Qiita](http://www.telln.com/lesson/wp-content/uploads/2018/02/fil1.png)

2,データの入力規則
・プルダウンで、データリストからクリックするだけでセルの中に入力できる。
![Qiita2](https://excel-doctor.jp/wp-content/uploads/pulldown-dropdownlist-add3-min.png)

3,ウィンドウ枠の固定
・Excelで行見出しや列見出しなど、常に表示しておきたい部分を固定表示する方法
![Qiita3](https://image.itmedia.co.jp/ait/articles/1903/04/wi-excelfixcell04.png)

# 4,おわりに
まだまだ、自分の知らない便利な機能などあると思うので、
色々と調べて取り入れたいです。
最後までご覧いただき、ありがとうございました。
情報処理技術者試験のSQL問題を動かして試す

情報処理技術者試験（基本情報技術者試験、応用情報技術者試験、データベーススペシャリスト試験など）には、データベースのSQLの問題が出ます。
試験会場では頭で考えるしかないですが、勉強としては実際に動かして確かめたいところです。その方法を紹介します。

### 問題
例えば、この2023年秋の応用情報技術者試験の問題です。
相関副問合せが使われている難問です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577053/ae5efd11-c5f6-1ceb-8eb3-deb0f5e7fa59.png)

### 頭で考える
SQL文の意味を日本語で書けば、「“製品”表にある各製品番号のうち、“在庫”表の中で、在庫数が30個を超える倉庫が一つもない製品番号を挙げよ」です。
- 製品番号**AB1805**：倉庫コードWH101に、30個を超える在庫があるので、抽出されない
- 製品番号**CC5001**：倉庫コードWH100とWH103に、30個を超える在庫があるので、抽出されない
- 製品番号**MZ1000**：どの倉庫にも在庫がないので、**抽出される**
- 製品番号**XZ3000**：倉庫コードWH101とWH102に在庫があるが、どちらも30個を超えないので、**抽出される**
- 製品番号**ZZ9900**：倉庫コードWH100に、30個を超える在庫があるので、抽出されない
よって得られる表の行は、**MZ1000**と**XZ3000**の**2つ**となります。

### paiza.ioで実行する
https://paiza.io/ja/projects/new にアクセスし、左上の緑色の言語選択ボタンで「MySQL」を選んで、次のようにコードを入力します。
- 表定義
問題のとおりに、“製品”表と“在庫”表を定義するCREATE TABLE文を入力します。文字列型はVARCHAR(100)、数値型はINTとします。
```
CREATE TABLE 製品(製品番号 VARCHAR(100), 製品名 VARCHAR(100), 単価 INT);
CREATE TABLE 在庫(倉庫コード VARCHAR(100), 製品番号 VARCHAR(100), 在庫数 INT);
```
- 行挿入
“製品”表に行を挿入するINSERT文を入力します。
```
INSERT INTO 製品 VALUES
('AB1805', 'CD-ROMドライブ', 15000),
('CC5001', 'デジタルカメラ', 65000),
('MZ1000', 'プリンタA', 54000),
('XZ3000', 'プリンタB', 78000),
('ZZ9900', 'イメージスキャナ', 98000);
```
“在庫”表に行を挿入するINSERT文を入力します。
```
INSERT INTO 在庫 VALUES
('WH100', 'AB1805',  20), ('WH100', 'CC5001', 200),
('WH100', 'ZZ9900', 130), ('WH101', 'AB1805', 150),
('WH101', 'XZ3000',  30), ('WH102', 'XZ3000',  20),
('WH102', 'ZZ9900',  10), ('WH103', 'CC5001',  40);
```
- SELECT文
問題文のSELECT文を入力します。
```
SELECT DISTINCT 製品番号 FROM 製品
 WHERE NOT EXISTS (SELECT 製品番号 FROM 在庫
   WHERE 在庫数 > 30 AND 製品.製品番号 = 在庫.製品番号);
```

- ここまで入力したら、実行ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577053/1991904e-f3d2-5605-361e-e181484f4847.png)

出力として、確かに製品番号**MZ1000**と**XZ3000**が得られました。
INSERT文で挿入するデータを変えたり、`在庫数 > 30`の部分の数字や不等号の向きを変えたり、いろいろ試してみるとよいでしょう。
.NET6 から TLS=true で Amazon DocumentDB に接続する

## はじめに
Linuxコンテナに配置した.NET6のアプリケーションからTLSを有効にしたDocumentDBへの接続で沼ったので、誰かがしなくて良い苦労をしないために、備忘録を残しておきます。

私の環境は`mcr.microsoft.com/dotnet/aspnet:6:0`をベースとしたコンテナをECSに配置していました。

## TL;DR

https://www.appsloveworld.com/mongodb/100/97/cert-error-connecting-to-aws-documentdb-from-docker-c-app#google_vignette

こちらの記事にある通りですが、以下の記述をDockerfileに追記することでTLSによる通信ができるようになりました。

```dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

# add AWS RDS CA bundle
ADD https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem /tmp/rds-ca/aws-rds-ca-bundle.pem
# split the bundle into individual certs (prefixed with xx)
# see http://blog.swwomm.com/2015/02/importing-new-rds-ca-certificate-into.html
RUN cd /tmp/rds-ca && cat aws-rds-ca-bundle.pem|awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ""}' \
    && for CERT in /tmp/rds-ca/cert*; do mv $CERT /usr/local/share/ca-certificates/aws-rds-ca-$(basename $CERT).crt; done \
    && rm -rf /tmp/rds-ca \
    && update-ca-certificates

WORKDIR /app
EXPOSE 80
EXPOSE 443
...
...
...
````

接続文字列はDocumentDBの管理画面でアナウンスがあったものをそのまま使用しています。

```
mongodb://<user>:<password>@<endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
```

## なぜ沼ったか

公式ではpemをダウンロードし、それをアプリケーション内で証明書のストアにインポートしてと書かれているからです。

恐らくそれで動く環境もあると思います。
RDSやWindowsサーバーだとまた違ってくるのかもしれません。
ですが、もし私と同じような状態で困っている人はこの方法を試してみてください。

以下、公式ドキュメント

https://docs.aws.amazon.com/documentdb/latest/developerguide/connect_programmatically.html
パスワード付きZIPファイルを解凍する際に「ん？何で？」となった話

## はじめに

ご存知の方も多いのかも知れませんが、筆者は知らなかったので「ん？何で？」となってしまいましたという話です。

## パスワード付き ZIP ファイルを解凍する

先日、パスワード付きの ZIP ファイルを作成する機会がありました。

きちんとパスワードがかかっていることを確認したく、作成後すぐに解凍してみました。

解凍は Windows  10 標準の右クリックメニュー内にある「すべて展開」から行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/e1b703e7-39cc-050f-60ee-6f6d729cefa7.png)

「すべて展開」を選択するとパスワード入力を求められたので、きちんとパスワードがかかっているであろうことを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/86a194f1-5ec8-2c4d-ae32-a70ba0b0b0f1.png)

ここで正しいパスワードを入力し、問題なく解凍することができました。

ここで、心配性の筆者は、**誤ったパスワード**を入力したらきちんとエラーになるよね？を確認したくなり、もう一度右クリックして「すべて展開」を選択しました。

すると、今後は、パスワード入力画面が表示されず、そのまま解凍が完了するではありませんか。。。

１回目の解凍では間違いなくパスワード入力を求めたられたので、パスワードはきちんとかかっているようですが、一体どういうことでしょうか。

## パスワードがキャッシュされていた

調べてみると、どうやら、１回目に入力したパスワードが**キャッシュ**（記憶）されていたようで、２回目の解凍ではパスワード入力が不要になったようです。

普段は 7-Zip で解凍するのでまったく気づかなかったのですが、「すべて展開」で解凍すると、このような挙動になるのですね。

ちなみに、キャッシュされたパスワードは「Windows 資格情報の管理」の**汎用資格情報**から確認できます。もちろん、削除もできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/8fdf169f-9f46-9d5a-4af1-f094998ba979.png)

## さいごに

まさか、ZIP のパスワードがキャッシュされているとは思いもしませんでした。
7-Zip は毎回パスワードを聞いてくるので（面倒ですが）安心感があり、今後も 7-Zip で解凍しようと思います。
今後の習慣として

アプリ開発として、Flutterを使ってみたいと思った今日この頃。　
右も左もわからず、ゆっくりでいいから勉強をしていこうと思い、昔に登録していたQiitaに勉強メモとして残していこうと思います！
ここであれば、プログラミングの先輩方からいろいろなアドバイスをいただけるし、何よりモチベーション人もつながるのではないかなと...

頑張るぞーーーー
Rで「あてはめ」ができるまでの道筋　制御構文

# 制御構文
今回は制御構文を扱います。条件分岐と繰り返しです。繰り返しのfor やwhile は遅いので要注意です。(詳しくは[こちら](https://stats.biopapyrus.jp/r/basic/loop-flow.html)をご覧下さい)
これらはどのプログラミング言語にもあるものですが、言語によって書式が微妙に異なります。すなわち"else if"の代わりに"elif"を用いたり、{}が必要だったり必要でなかったり、...といった違いがあります。 本稿はR における制御構文の書式をまとめたものです。

## 条件分岐
### if
言わずと知れた、もし◯◯◯ なら××× という構文です。
Rでは以下の書式で書きます。
```R
if(a < 5) {
  print("yes")
} else {
  print("no")
}  
```
選択肢が複数ある場合はif ... else if ... else を使います。書式は以下の通りです。
```R
if(a < 5) {
  print("low")
} else if(a < 8) {
  print("middle")
} else {
  print("high")	
}
```

### switch
R にはswitch 構文はありますが、上記のif ... else if ... else の例を代替するようなものではないようです。詳細は[こちら](https://stats.biopapyrus.jp/r/basic/divergence-flow.html)を参照してください。

## ifelse
いわゆる3項演算子です。ifelse(A, B, C) の書式で、AがTRUE ならばB をFALSE ならばC を返す、というものです。
```R
> h <- 10
> ampm <- ifelse(h<12, "AM", "PM")
> ampm
[1] "AM"
```

## 繰り返し
### for
R にも他のプログラミング言語と同様にfor 文があります。R では以下のように書きます。
```R
# example(A)
> for (i in 1:3) {
+ 	print(i)
+ }
[1] 1
[1] 2
[1] 3
```
蛇足の注意ですが、上記example(A)は
```R
# example(B)
for (i in 1:3) {
	print(i)
}

```
を入力すると
```R
[1] 1
[1] 2
[1] 3
```
という出力を得る、という意味です。行頭の">"や"+"を含めて入力してはいけません。ただ、エディタからexample(B)のように入力するとコンソールにはexample(A)のように表記されます。コンソールの表記をそのままコピペしたものがexample(A)です。

さて、注意すべきは、"1:3" という表現を用いると、3を「含む」ということです。Python やC など他のプログラミング言語に慣れた人にとってはとても違和感のあるところかもしれません。

### while
while 文は以下の書式で書きます。
```R
> i = 0
> while(i<3) {
+ 	print(i)
+ 	i <- i + 1
+ }
[1] 0
[1] 1
[1] 2
```
こちらはあまり違和感がないでしょう。

## 参考文献
[biostatistics](https://stats.biopapyrus.jp/r/basic/loop-flow.html)

トップページは[こちら](https://qiita.com/sflabtech/items/562dd78418926f00a0d5)
AWSで、Terraformを利用する方法をまとめてみた(8/10)

VPC、サブネット、ルートテーブル、およびインターネットゲートウェイを作成する
--
__1.	Terraformをインストールし、AWSプロバイダを設定します。__
~~~
provider "aws" {
  region = "us-west-2"
}
~~~

__2.	VPCを作成するためのリソースを定義します。__
~~~
resource "aws_vpc" "my_vpc" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "My VPC"
  }
}
~~~

__3.	サブネットを作成するためのリソースを定義します。__
~~~
resource "aws_subnet" "public_subnet" {
  vpc_id     = aws_vpc.my_vpc.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
  map_public_ip_on_launch = true
  tags = {
    Name = "Public Subnet"
  }
}
~~~

__4.	ルートテーブルを作成するためのリソースを定義します。__
~~~
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.my_vpc.id
  route {
    cidr_block = "10.0.1.0/24"
    gateway_id = aws_internet_gateway.my_igw.id
  }
  tags = {
    Name = "Public Route Table"
  }
}
~~~

__5.	インターネットゲートウェイを作成するためのリソースを定義します。__
~~~
resource "aws_internet_gateway" "my_igw" {
  tags = {
    Name = "My Internet Gateway"
  }
}
~~~

__6.	パブリックルートテーブルとパブリックサブネットを関連付けます。__
~~~
resource "aws_route_table_association" "public_subnet_association" {
  subnet_id      = aws_subnet.public_subnet.id
  route_table_id = aws_route_table.public_rt.id
}
~~~

__7.	パブリックルートテーブルに、インターネットゲートウェイをルートとして追加します。__
~~~
resource "aws_route" "public_internet_gateway_route" {
  route_table_id = aws_route_table.public_rt.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id = aws_internet_gateway.my_igw.id
}
~~~
これで、VPC、サブネット、ルートテーブル、およびインターネットゲートウェイが作成され、関連付けられました。


__8.セキュリティグループを作成するためのリソースを定義します。__

作成されたセキュリティグループは、名前がweb_server_sgで始まり、VPCに関連付けられており、ポート番号80と443のTCPトラフィックを許可しています。また、Nameタグには"Web Server Security Group"という値が設定されます。
~~~
resource "aws_security_group" "web_server_sg" {

  name_prefix = "web_server_sg"

  vpc_id = aws_vpc.my_vpc.id

  ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port = 443
    to_port = 443
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "Web Server Security Group"
  }
}
~~~
すべてのリソースを定義したら、Terraformを使用してAWSに適用することができます。


__Terraformを初期化します。__
~~~
$ terraform init
~~~
__Terraformの実行計画を確認します。__
~~~
$ terraform plan
~~~
__Terraformを使用してAWSにリソースを作成します。__
~~~
$ terraform apply
~~~

AWSで、Terraformを利用する方法をまとめてみた(1/10)
https://qiita.com/kimuni-i/items/ffde2f8df96fe5d9513f
AWSで、Terraformを利用する方法をまとめてみた(2/10)
https://qiita.com/kimuni-i/items/6298ed10adc6ad450488
AWSで、Terraformを利用する方法をまとめてみた(3/10)
https://qiita.com/kimuni-i/items/4d2f90506eb2dd4ee702
AWSで、Terraformを利用する方法をまとめてみた(4/10)
https://qiita.com/kimuni-i/items/b97089a820cc06ed2d9c
AWSで、Terraformを利用する方法をまとめてみた(5/10)
https://qiita.com/kimuni-i/items/11efb60b9a731d212211
AWSで、Terraformを利用する方法をまとめてみた(6/10)
https://qiita.com/kimuni-i/items/943daf8f4e80af12b70e
AWSで、Terraformを利用する方法をまとめてみた(7/10)
https://qiita.com/kimuni-i/items/b2cc6e1e4b5d5c1a92cb
AWSで、Terraformを利用する方法をまとめてみた(9/10)
https://qiita.com/kimuni-i/items/edbdc88f0bca9c0354d2
AWSで、Terraformを利用する方法をまとめてみた(10/10)
https://qiita.com/kimuni-i/items/2f900d792c38ad93979c
【備忘録】PDFに日本語テキストを追加する


[ cpdf ]  https://community.coherentpdf.com/

「Download pre-built cpdf command line tool」よりDLする。
master.zip内に各種OS用の実行ファイルが入っている。


>マニュアルで透かしとかテキストの追加が書いてある。この辺を読め！
https://www.coherentpdf.com/cpdfmanual/cpdfmanualch8.html#x12-720008.2　


---
★★　サンプル

cpdf -load-ttf A=NotoSansJP-Regular.ttf -font A -topleft 15 -add-text "テストだよ！ %Y%m%d" in.pdf 1 -o out_.pdf

---

テキストが半角文字であればフォントの追加無しでテキストが追加表示される。
日本語のテキストを追加する場合は日本語のフォントを用意する事。フォントの埋め込みというやつだと思う。
https://fonts.google.com/noto
今回は上記より入手。マニュアルの「8.2.5　Font　and Size」に記載あり。
フォントもcpdfと同じところにおいておけばOk？かな

-load-ttf A=NotoSansJP-Regular.ttf -font A

---
テキストの表示位置。今回は左上。ヘッダーを追加する感じ。

-topleft 15

---

追加するテキスト。今日の日付も後ろに追加してみた。

-add-text "テストだよ！ %Y%m%d"

---
元のＰＤＦです。通常はすべてのページにテキストが追加される。
今回のサンプルにある１は最初の１ページ目のみテキストを追加してくれる。
ちなみに2にすると２ページ目にのみテキストが追加される。

in.pdf 1 

---
出力PDF名。これは明示的に-oを付ける。

-o out.pdf

---


下記のようなエラー？メッセージが出るけど　無視でいいかな？

read_encoding_table: format 12 not known
read_encoding_table: format 14 not known
read_encoding_table: format 12 not known
read_encoding_table: format 12 not known
read_encoding_table: format 14 not known
read_encoding_table: format 12 not known

---
>詳しくは下記マニュアルを読む。
https://www.coherentpdf.com/cpdfmanual/cpdfmanual.html

---
---
おまけ：

★★　上記サンプルにページ数の表示を追加してみた。

cpdf -load-ttf A=NotoSansJP-Regular.ttf -font A -topleft 15 -add-text "テストだよ！ %Y%m%d" in.pdf 1 AND -bottom 10 -add-text "%Page/%EndPage" -o out_.pdf

---
追加したのはこれ　＞＞＞　　　AND -bottom 10 -add-text "%Page/%EndPage"

in.pdf と out.pdf　の間に上記を追加する。と、上記例ではフッターの位置中央にページ数が追加される。