OmniAICreator/Qiita-1.07M huggingface dataset:
TerraformでセットアップされたAKSのVMサイズをダウンタイムなしで変更する方法

AKSをTerraformでセットアップするとDefault node poolを設定しなければいけません。
システムを運用し始めて、VMのサイズを変更する必要があることも出てきます。

```terraform
resource "azurerm_kubernetes_cluster" "example" {
  name                = "example-aks1"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  dns_prefix          = "exampleaks1"

  default_node_pool {
    name       = "default"
    node_count = 1
    vm_size    = "Standard_D2_v2"
    os_disk_size_gb = 
  }
...
}
```
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/kubernetes_cluster

 >  vm_size - (Required) The size of the Virtual Machine, such as Standard_DS2_v2. Changing this forces a new resource to be created.

こちらに書かれている通り、Sizeの変更をすると新しいリソースが作られます。このまま変更を実行するとNodeが作り変えられるので、その間はダウンタイムとなります。本番環境ではこれは受け入れられません。

ダウンタイムなしでデフォルトのノードプールを変更するには、以下の方法で行えます。

* 新しいノードプールの追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/e7804d96-7470-f9ba-ec14-96009413bb1a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/09392dcc-ac09-1b89-1ca4-a111b795be5d.png)
AKSは少なくとも１つのシステムノードプールが必要ですので、追加するノードプールのモードはシステムとします。

* 古いノードをCordonする
`kubectl cordon aks-default-1111-vmss000000`

* Deploymentなどのリスタート
```bash
kubectl -n my-app rollout restart deployment my-app
kubectl -n my-app get pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP              NODE                          NOMINATED NODE   READINESS GATES
my-app-e4dfd   1/1     Running   0          1d    172.40.6.11     aks-default-1111-vmss000000   <none>           <none>
my-app-se15b   1/1     Running   0          1h    172.40.6.12     aks-newpool-1111-vmss000001   <none>           <none>
```
これで、アプリケーションが新しく作られたノードプールにデプロイされます。

* 古いノードをDrainする
`kubectl drain aks-default-1111-vmss000000 --ignore-daemonsets  --delete-emptydir-data`

* 古いノードプールを削除
Drainが完了すれは、ノードプールを削除します。ポータルからもできますし、コマンドで行う場合は以下のような感じです。
`az aks nodepool delete --name <ノードプール名> --cluster-name <クラスター名> --resource-group <リソースグループ>`

* Terraformの編集
最後にTerraformの編集です。
`terraform plan`で変更箇所を確認して、Terrformのコードに変更をかけます。サイズだけ変更した場合は、`name`と`vm_size`だけかもしくは、`os_disk_size_gb`を設定していた場合はそれも変更がかかる可能性があります。

```terraform
resource "azurerm_kubernetes_cluster" "example" {
  name                = "example-aks1"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  dns_prefix          = "exampleaks1"

  default_node_pool {
    name       = "newpool" # <=====
    node_count = 2
    vm_size    = "Standard_D2_v3" # <=====
  }
...
}
```
再度`terraform plan`で変更箇所が出てこなければ完了です。

この方法で行うと、システムのダウンタイムを避けながらTerraformの編集後はTerraformでの管理も続行できます。
実際のノードプールの入れ替えは手作業ですが、VMのサイズを頻繁に変更することもないと思われますので十分有効的な手段かと思います。
[Kotlin]ファイル名が被ってimportするとどっちかがフルパスになっちゃうとき（メモ）

## 答え
importのところに as を使って新しい名前をつけてあげる。

## 公式
https://kotlinlang.org/docs/packages.html#imports

## 例
```
import org.example.Message
import org.test.Message 
```

ファイルは違うんだけどMessageって名前被ってるからどっちかがフルパスになる...

## なので
```
import org.example.Message
import org.test.Message as testMessage
```

下のtest.Messageの方をtestMessageってことで名前をつけてあげる。

使う感じ
```
import org.example.Message
import org.test.Message as testMessage

fun xxx():String{
        Message.foo() + testMessage.bar()
}
```

みたいな。
PostgreSQLでhaving句のalias

# MySQLで使えたはずのhaving句のaliasが使えない
PostgreSQLでは、having句でselect内でのaliasを使うことができない。

https://dba.stackexchange.com/questions/281438/why-does-an-alias-with-a-having-clause-not-exist-in-postgresql

```sql:MySQLでは動くが、PostgreSQLでは動かない
SELECT
    status,
    count(*) AS status_count
FROM
    Users
GROUP BY status
HAVING status_count > 10;
```

PostgreSQLでは、実行順番でSELECT句よりも先にHAVING句が評価される。
そのため、PostgreSQLでは、以下のように書く必要がある。

```sql
SELECT
    status,
    count(*) AS status_count
FROM
    "Users"
GROUP BY status
HAVING count(*) > 10;
```
同じ`count(*)`が、2回書かれていて気になる。
`count(*)`の部分が、もっと複雑な計算式や条件分岐になった時に、冗長になる可能性がある。

## 綺麗に書けそう
```sql
WITH user_status_counts as (
    SELECT
        status,
        count(*) AS status_count
    FROM
        "Users"
    GROUP BY status
)
SELECT * from user_status_counts usc WHERE usc.status_count > 10;
```
`WITH`を使うことで、`count(*)`の部分が1回で済みそう。

https://stackoverflow.com/questions/7511064/postgresql-aliases-column-and-having
Windows11/Outlookで検索が効かなった

## 状況
- Outlookでメールの検索や、Windows11全体の検索がうまく動いていない
- Windowsの設定>プライバシーとセキュリティ>Windows検索を確認すると、インデックス作成の状態が「中断」になっており、保留中も数万件あった
- インデックス作成が何らかの理由で動いていない模様…

## 解決策
- レジストリエディタで
- HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search
- 新たにDWORD値「DisableBackoff」を作成、データ値を「1」に
- パソコンを再起動

## 参考
- Windows検索のサービスを再起動してもうまく動かず
- Google検索で10年以上前の記事を見つける　https://news.mynavi.jp/article/windows-159/
- この記事はWindwos7だけど、現在も有効な模様　https://learn.microsoft.com/ja-jp/windows/client-management/mdm/policy-csp-search#search-disablebackoff
ポートフォリオを今日から制作するのですが、温かく見守って頂けると嬉しいです！よろしくお願いいたします。

こんにちは！
記事をご覧いただきありがとうございます。

スナガクと申します！

今日から、転職などのためにポートフォリオを制作させて頂きます！
言語はPythonで、基本的な文法は、本などで学習しました！

制作するポートフォリオの内容は、
Djangoを使ったWebアプリケーションです！
Webアプリケーションの中身は、
It技術の最新情報・トレンドを確認できる、そんなサイトです。
時間がない、ご多忙なエンジニアの方でも、
意欲があれば、このサイトを見て勉強できる。
そんなサイトを作れば、周りの方に貢献できるかな？
と思っています！

具体的な方法は、
Webスクレイピング等を用いて、
最新技術や、気になるトピックを一目見て確認できる。
そんなサイトです！
また、機能は順次追加していければ、と思っています！

更新頻度は、1週間に1～2回になると思います！
（2022/11/12　現在）

見守って頂けると幸いです！
ご指導、ご鞭撻のほど、よろしくお願いいたします。

スナガク
[Kotlin]sealed interfaceの使い道（メモ）

## 使い所
- enumみたいに使いたいとき
- elseを書きたくないとき
- (他にもあるはずだけど私はわからない)

## sealed interfaceとは
- ざっくり、「interfaceを継承できる範囲に制限をかけれる」
- interfaceの中に書いたやつ、もしくは同じファイル内のやつしか継承できない。
- なのでwhenで条件分岐したときに"else"が要らなくなる。


## 例：ただのinterfaceの場合
```
fun eval(expr: Expr): Int =
    when (expr) {
        is Num -> expr.value
        is Sum -> eval(expr.left) + eval(expr.right)
        else -> throw IllegalArgumentException("Unknown expression")
    }

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
```

## sealed interfaceを使うと
```
fun eval(expr: Expr): Int =
        when (expr) {
            is Num -> expr.value
            is Sum -> eval(expr.left) + eval(expr.right)
        }

sealed interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
```

elseがなくてもいい...!

## 元コード
https://play.kotlinlang.org/koans/overview

## 参考ページ
https://qiita.com/reoc-software/items/fdc6a7f09621ecf9d202
AWS EC2で立ち上げたRails（unicorn）サーバーのログ確認方法

## 前提条件
RailsアプリをEC2（unicorn）にデプロイして、サーバー起動済みの場合のログ確認方法

## 結論
該当アプリのlogディレクトリで以下のコマンドを実行すればOK
```terminal:terminal（EC2インスタンス内）
$ tail -f production.log
```

## 詳細
デプロイしたリポジトリで以下のコマンドを実行してください！
```terminal:terminal（EC2インスタンス内）
$ ls
Gemfile  Gemfile.lock  README.md  Rakefile  app  bin  config  config.ru  csv  db  lib  log  public  spec  storage  tmp  vendor

$ cd log

$ ls
production.log  unicorn.stderr.log  unicorn.stdout.log

$ tail -f production.log
以下にサーバーのログが流れてくる
```


## tailコマンドについて
ファイルの最終行から数行を表示する。
-fオプションをつけた場合、ファイルの追記を監視し、随時表示する。
（ローカルのrails sのようにログを表示することができる。）


## 参考にさせていただいた記事🙇‍♂️
- [【Rails】 AWSのEC2にデプロイする方法~画像で丁寧に解説！ \| Pikawaka](https://pikawaka.com/rails/ec2_deploy#git%E3%81%A8%E3%81%AE%E9%80%A3%E6%90%BA%E3%82%92%E3%81%97%E3%82%88%E3%81%86)
- [tailコマンドについて詳しくまとめました 【Linuxコマンド集】](https://eng-entrance.com/linux-command-tail#-f--follownamedescriptor)


## 最後に
本記事の内容がネット上にあまりなかったので執筆しました。
この記事が多くの悩める方に届くことを願っています🌱
エラーが発生したときにプログラムの SEQ（行番号）を表示する方法

## はじめに

エラーのプログラムメッセージはこちらの記事で紹介したように、プログラム内で問題となっている箇所を教えてくれます。

しかし、初期設定ではコンパイルした際のスプールファイルに対するステートメント番号（行番号）を表示しています。
場合によってはコンパイル時のスプールファイルを確認することが難しいこともあるかと思います。

この記事では、エラーが発生したときに表示される行番号をプログラムの SEQ に変更する方法をご紹介します。


## 方法

コンパイル時のパラメーターである、コンパイラー・オプションに`*SRCSTMT`を指定します。（画像１）

（画像１）
![errorProgramSeq_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/1fe5f4e2-cb93-571c-7036-c0d0a52de9e0.png)


## 結果

コンパイラー・オプションに`*SRCSTMT`を指定した場合、プログラムの SEQ（行番号）が表示されます。（画像２）（画像３）

（画像２）
![errorProgramSeq_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/65b69486-58a5-6c06-a622-925c501ed1e3.png)

（画像３）
![errorProgramSeq_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/06e84873-9e67-8710-fe73-78ad948053ce.png)

一方、コンパイラー・オプションに何も指定しない場合はコンパイルした際のスプールファイルに対するステートメント番号（行番号）が表示されます。（画像４）（画像５）

（画像４）
![errorProgramSeq_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/d6bd6186-c9fb-5700-b0f3-7f5108ce924f.png)

（画像５）
![errorProgramSeq_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/f8736916-176a-4d8b-9d4c-d9abde05013b.png)


## おわりに

コンパイラー・オプションの`*SRCSTMT`は V4R4 での変更点として[ILE RPG 解説書](https://www.ibm.com/docs/ja/i/7.2?topic=wn-whats-new-in-v4r4-1)で案内されています。

ご参考になれば幸いです。最後までお読み頂きありがとうございます。

## 関連した投稿

[エラーが発生したときの原因を確認する方法](https://qiita.com/tamaday/items/7e42703c170510250548)
英語でプロジェクト進捗報告をする際のパワーポイント例

## はじめに
英語は少し話せるけどプレゼンはちょっと重いな…と思う方は意外と多いのではないでしょうか。
私もPMとして業務で英語プレゼンを初めてすることになった際は、かなり焦りました…。
今回は私なりに、何とかプレゼンができた際の、スライドの例と、立ち回りについて説明したいと思います。

## スライド全体構成

- 表紙
- オーバービュー
- 各プロジェクト/インシデントごとのスライド
※各プロジェクト/インシデント毎に以下セットを作成します。
　- 1枚目：概要スライド
　- 2枚目：詳細スライド
　- 3枚目：補足資料スライド

## 表紙スライド
以下のような感じで、会社のフォーマットスライドを作成します。
![表紙.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/d3875dc1-c240-97ca-b1ce-c00d79c3bbe9.png)

実際MTGの際は初めの5分ぐらいは、雑談をするのが、マナーなように感じます。
MTGに遅れる人もいるため、「家族の話題」「現地時間の話題」「流行っているニュース」等の話題で場を持たせます。
```:会話例
Hi, 〇〇. How are you? You look good.
How was your summer vacation?
```
## オーバービュー
### 目次のようにオーバービューを説明する場合
以下のような箇条書きスライドを先に出します。
![オーバービュー1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/1e544eaf-ea90-9598-3850-669cf5b5a007.png)

もしアジェンダが多くて、スキップする可能性のある項目については、時間があったら話します的なことを伝え、重要度の高いもの低いものを明確にしておきます。
```:会話例
I would like to talk about following topics.
If we still have time after topic 3, we would like to talk about micellaneous topics.
```
### プロジェクト/インシデントのリストベースでオーバービューを説明する場合
リストを表示し、何が終わったのか、何が新たに始まったのか、状況の概要を説明します。
![オーバービュー2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/dd408a87-e70d-b27e-31cd-76b8f81ea8c8.png)

```:会話例
"We have some progress in ongoing projects."
"We still have issue on 〇〇"
```

## 各プロジェクトのスライド：システム導入等のプロジェクトを説明する場合
### 1枚目(概要)
プロジェクトの場合は最初にマイルストーンのスライドを表示し、現在置を一目でとらえられるようにします。
各プロジェクトのスライドの右上に(1/2)(2/2)と記載し、後何枚くらいボリュームがあるのかわかるようにします。
各工程だけでなく、協力するBPや作業員の契約期間等も入れると、全体像がつかみやすいかなと思いました。
![P1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/73946321-68ec-06f7-c763-2f952ee19d61.png)

### 2枚目(詳細)
2枚目では現在やっていること、やったこと、これからやることを詳細に書きます。
![P2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/7fb20246-edd8-26d1-9af4-bca946f5da15.png)

### 3枚目(補足資料・図)
もし、システムの構成図等補足的な図等があれば載せておきます。

## 各インシデントのスライド：社内システム不具合等のトラブルを説明する場合
### 1枚目(概要)
インシデントの場合、概要を把握してもらうために、同じ問題が多数発生している場合は、以下のように何が誰に起きているのか一覧表を出した方が良い場合があります。
もし、同じような問題が数えきれないほど発生している場合は棒グラフなどで件数を出した方が良いと思います。
問題が多数発生しているのではなく、大きな問題が一つ発生している場合は、「各プロジェクトのスライド」のようにマイルストーン形式で説明するのもありかと思います。
![I1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/d375f7bd-b082-30e4-69a2-2c10b311f213.png)

### 2枚目(詳細)
こちらもプロジェクトと同じく、現在の状況とこれからすることを書きます。
![I2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1879925/4b7a68a5-2acc-73a2-7a42-d5f8195bf3f9.png)

### 3枚目(補足資料・図)
もし、補足的な図等があればスライドを作成します。
エラー画面等を載せるのも相手がイメージしやすくなるので良いと思います。

## 発表終了時
会議終了時も、会議開始時と同様に、少し雑談を話すイメージを個人的には持っています。
```:会話例
Do you have any questions or concerns?
Do you have something to talk?
What are you doing this weekend?
I think that's all for today. Thank you very much.
```

## 最後に
海外客向けに進捗報告をする際の注意点と言っても、日本語のプレゼンと大して変わらないかもしれません。ただし、相手が外国籍の方になるので、言語以上に共通言語な「図」を多様することが重要だと思います(この記事ではあんまり触れられていませんが…)。また、必ずしも英語ができる人がPMになるとは限らないと思います。その際は、PMがうまく話せない場合は英語ができるメンバーが助ける、もしくは代わりに話す等、より助け合いが必要だと、自分が発表をした中で思いました。
【求対案】Python3 で時計算をやってみる

非情報学科生向けのプログラミング講義で、以下のような問題が出題されました。




>時刻を入力したら、時計の短針と長針のなす角の角度aを求めるプログラムを作成しなさい。
>(0°≦a≦180°)
>また、入力される時(h)と分(m)は以下の条件を満たす整数であるとする。
>0≦h<12, 0≦m≦59

<h2>正時(m=0)の場合</h2>

60分進むごとに、短針は30度進むこと、6時丁度のとき180°になることを考慮して、以下のような愚直解を考えた。

```python
#h = 8, m = 0
def solution(h, m):
    if m == 0:
        if 6 > h:
            a = 30 * h
        elif h == 6:
            a = 180
        elif h > 6:
            a = 360 - (h*30)
    return a
#120
```

<h2>すべての場合</h2>

しかし、以上のような解では、正時以外の場合対応できない。幸い、時と分は整数のみであるから、1.5分のような場合は考慮しなくて良い。

長針は1分毎に6°進み、短針は0.5°進むから、求めるなす角aはこれらの差であることがわかる。

```python
#h = 5, m = 10
def solution(h, m):
    plane_time = h * 60 + m #単位変換
    long_hand = m * 6
    short_hand = plane_time * 0.5

    if abs(long_hand - short_hand) > 180:
        a = 360 - abs(long_hand - short_hand)
    else:
        a = abs(long_hand - short_hand)
    return a
#95.0
```

愚直な解であることは間違いないので、随時皆様のアドバイスをお待ちしております。
オフラインのubuntu 20.04にWI-U2-433DMSを認識させる


いろいろ面倒だったので手順ベースで残しておきます。必要な諸々のファイルは別のPCを使って入手しましたが、有線など別経路でインターネットに接続できるなら1台で完結するはず。

## 参考記事

[ubuntu 20.04に、WI-U2-433DMSを認識させる](https://qiita.com/mitoneko/items/47841692945acbb657da)

https://iyuniy.hatenablog.com/entry/2020/05/06/223940

https://stackoverflow.com/questions/13756800/how-to-download-all-dependencies-and-packages-to-directory/27469489#27469489

https://tclug-list.mn-linux.narkive.com/B59AhOw3/tricks-with-installing-linux-on-the-hp-pavilion-x360-convertible-15-cr0017nr

## 方針
ドライバを持ってきて手動でビルドする。
必要なパッケージはネットワークにつながる環境で apt-get download を用いて.debを入手し、外部ストレージ経由で直接突っ込んで dpkg する。

## 手順
インターネットにつながる環境でドライバのダウンロード
```
git clone https://github.com/aircrack-ng/rtl8812au.git
```

依存パッケージの.deb取得
```
# 依存関係を取得するためのパッケージ
sudo apt install apt-rdepends
mkdir pkglist
cd pkglist

sudo apt-get download $(apt-rdepends dkms| grep -v "^ " | grep -vE '^(libc-dev|kldutils|c-compiler)$' | sed 's/debconf-2.0/debconf/g')
```
要するにDKMSと依存関係を一式そろえたい。ドライバのビルドに要求されます。


参考記事https://iyuniy.hatenablog.com/entry/2020/05/06/223940 と同じ怒られが発生したためいろいろ小細工をしています。debconfは正式名称？に置換してdebを取得しているようで、これが正しい対処なのでしょうが、libc-dev、kldutils、c-compilerはbuild-essentialがちゃんと入っている環境であれば要らないはずなので無視。

ここまでの作業で作ったrtl8812auとpkglistを目的の環境にコピー。
それらの親ディレクトリで以下

```
sudo dpkg -iR --no-force-depends pkglist
cd rtl8812au
sudo make dkms_install
```

マシンを再起動すると認識しました。
エラーが発生したときの原因を確認する方法

## はじめに

皆さんはエラーが発生した際にどのように原因を調査していますか？
`STRDBG`を使用してデバッグする事もあるかと思います。

しかし私自身、原因が曖昧なまま`STRDBG`を使用すると問題解決までに必要以上に時間を要することがあります。

この記事では、エラーが発生した際の基本的な原因の確認方法をご紹介します。


## コンパイル時のエラー

コンパイルエラーの原因はスプールファイルを確認することで調査することが可能です。

1. 「メッセージの要約」から MSG-ID とエラー内容を確認する。（画像１）
2. MSG-ID を検索する。
3. 問題となっているプログラム内の SEQ（行番号）とエラーの詳細を確認する。（画像２）

（画像１）
![errorCauseInvestigation_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/d6d0da9d-fb87-6019-0391-372d4cde1deb.png)

（画像２）
![errorCauseInvestigation_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/c756ff85-4dea-39fe-895f-719b29c78c88.png)

上記の手順により、プログラム内でエラーとなっている箇所を調査することが可能です。


## プログラム実行中のエラー

プログラム実行中にエラーが発生した際は ① スプールファイル、② プログラムメッセージ、又は ③ メッセージ識別コードから調査することが可能です。

### ① スプールファイル

エラーのプログラムメッセージが表示された際の応答に「D：RPG 定様式ダンプの取得」を選択することで、エラー発生時にフィールドに何がセットされていたかを調査することができます。
例として（画像３）の場合、数字型である W#INT002 に文字型がセットされているため、W#INT002 に値をセットするロジックに問題があることが分かります。

（画像３）  
![errorCauseInvestigation_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/5e72226e-d62b-b5d9-14e1-00ea0084f6e7.png)


### ② プログラムメッセージ

エラーメッセージは、（画像４）のようにコンパイルした際のスプールファイルに対するステートメント番号（行番号）を表示しています。（※プログラム内の行番号を表示することも可能です。）
このステートメント番号からプログラム内でエラーとなっている箇所を調査することが可能です。

（画像４）  
![errorCauseInvestigation_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/29af7966-553d-26d8-2938-1f414edd4a78.png)

### ③ メッセージ識別コード

コマンド`DSPMSGD`のパラメーターであるメッセージ ID の下限値にエラーメッセージに表示されているメッセージ識別コードを指定し、実行することで表示されているメッセージ自体の詳細を知ることが可能です。（画像５）

この方法は見当がつかないエラーに対処する際、解決への手掛かりとなる場合があります。

（画像５）  
![errorCauseInvestigation_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/9ab242c0-0fd0-7efb-a5b3-a568048d2521.png)


## おわりに

IBM i は様々な方法でエラーの原因を調査することができます。

ご参考になれば幸いです。最後までお読み頂きありがとうございます。

## 関連した投稿

[エラーが発生したときにプログラムの SEQ（行番号）を表示する方法](https://qiita.com/tamaday/items/35d788a4aa0182ac13aa)
【Flutter】archiveのバージョンが変わらない

## 詰まった
AppStoreのアプリをアップデートするためにバージョンを変えたかったのだが、Xcodeで何度変更してarchiveしても、変わらない。
![](https://storage.googleapis.com/zenn-user-upload/4c37c4beb539-20221112.png)

## 解決方法
pubspec.yaml内の
```
version: 1.0.1+1
(+の右側はビルド番号)
```
↑この部分に任意のバージョンとビルド番号を入れる
その後、```flutter pub get```して、下記コマンドを実行
```
flutter build ios
```
↑↑これ大事
Sysinternalsについて

Sysinternalsで公開されているいくつかのツールはなんとなくで利用した事はありますが。
そもそもこのツール群がどういう立ち位置のモノなのか確認してまとめてみました。

## ドキュメント等

[Microsoft Learn - Sysinternals](https://learn.microsoft.com/ja-jp/sysinternals/)
[wikipedia - Sysinternals](https://en.wikipedia.org/wiki/Sysinternals)
[Sysinternals Overview | Microsoft, tools, utilities, demos](https://www.youtube.com/watch?v=6RqFPrCcWfY)

## Sysinternalsについて

Sysinternalsについて詳しくしりたければ、公式のドキュメントが詳しいのでここを読めばよさそうです。

[Microsoft Learn - Sysinternals](https://learn.microsoft.com/ja-jp/sysinternals/)

自分の理解をまとめると、Sysinternalsは元々Windowsを高度に管理、診断するのに役立つユーティリティとなります。

もともとは1996年11月にWindowsの開発者や管理者向けのwebサイト [Sysinternals.com](Sysinternals.com)(現在はMicrosoft Learnのページに転送される)で公開されたツールとなっており。

2006年7月にSysinternalsがMicrosoftに買収された事により、以降はMSから提供されるようになりました。

現状、有志によるサポートが行われており。（[ライセンス](https://learn.microsoft.com/ja-jp/sysinternals/license-terms)のサポートサービスより）

何かあった場合は、コミュニティを参照すれば色々と情報がありそうです。

[Sysinternals community support](https://learn.microsoft.com/en-us/answers/products/sysinternals)

## Sysinternals.comについて

1996年11月に立ち上げられており、Windowsのコミュニティでは広くしられたサイトだったようです。

で、このSysinternalsで提供されていたツール類を販売するために、Winternals Software社が起業され、そのWinternals Software社が2006年7月にMSに買収されたといった流れのようです。

下記に、当時の記事が残ってました。

[マイクロソフト、Windows用ユーティリティのWinternals Softwareを買収](https://japan.cnet.com/article/20175087/)

[rootkit問題指摘の研究者がMS入り――Winternals Software買収で](https://www.itmedia.co.jp/news/articles/0607/19/news013.html)

## Sysinternals Suite について

[Sysinternals Suite](https://learn.microsoft.com/ja-jp/sysinternals/downloads/sysinternals-suite) 

SysinternalsをまとめたSuiteが上記から入手できます。

今現在は、`Microsoft Store`から`Sysinternals Suite` をインストールするのが手早くてよさそうです。（wingetからもインストールできますし）

ちなみにwingetからインストールする記事を別で書いています。

[Sysinternals Suiteをwinget（msstore）からインストールしてみる](https://qiita.com/SAITO_Keita/items/46950bde5953a8011379)

## 総評

なんとなく昔からあるよなと言った感じで利用していましたが。
調べてみると想像以上に歴史のあるユーティリティでした。
【Perl初学者】Data::Dumper備忘録

本日はまったり`Data::Dumper`でございます。
基本的に関数に渡す配列などはリファレンスにしてから渡す、という暗黙の了解（まあ普通はそうするべきらしいけど）があるので今回の`Data::Dumper`も同じ感じでやっていきます。
画面に出力したい場合は`print`関数を使用します。

### Data::Dumper
- スカラ変数
    - `my $fluit = "apple";`
    - `print Dumper $fluit;`
- 配列
    - `my $fluits = [apple, banana, orange];`[リファレンス化]()
    - `print Dumper $fluits;`
- ハッシュ
    - `my $fluits = {apple => りんご, banana => バナナ, orange => みかん};`
    - `print Dumper $fluits;`

すっきり＾＾
SketchfabとUSDZとBlender

# SketchfabとUSDZとBlender

SketchfabとUSDZとBlenderについての簡単な紹介です。

## Sketchfabとは

[Sketchfab](https://sketchfab.com/)は、3Dコンテンツの公開、共有、売買ができるプラットフォームです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/d5d30028-9b63-4782-b465-7f35e804def3.png" width="500">



Sketchfabでは、`blend`など[いろいろなフォーマットでファイルをアップロードできます](https://help.sketchfab.com/hc/en-us/articles/202508396-3D-File-Formats)。
アップロードしたファイルは、[可能な限り`glTF`と`USDZ`に変換されます](https://help.sketchfab.com/hc/en-us/articles/360046421631-glTF-GLB-and-USDZ)。

下記は、`blend`のファイルをアップロードした場合のダウンロード画面です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/051a202c-4321-ff27-d05c-01bba19d1243.png" width="400">

オリジナルの`blend`に加え、`USDZ`、`glTF`、`GLB`でダウンロード可能です。
`blend`ファイルは、`glTF`に変換され、`glTF`から`USDZ`に変換されます。`GLB`は、`glTF`のバイナリ版です。

## USDZとは

`USDZ`は、`usdc`をzipで圧縮したファイルです。
`USDZ`は、[いくつかの制限があります](https://help.sketchfab.com/hc/en-us/articles/360046421631-glTF-GLB-and-USDZ#usdz-limitations)。たとえば、アーマチュアや特定のアニメーションはデータに含まれません。

多くの場合、USDZのファイルはスリム（サイズが小さい）です。

## BlenderでUSDZを読み込む方法

Blenderは、（ブレンダー）は オープンソースの統合3DCGソフトウェアです。
3Dモデルの作成だけでなく、スカルプト、アニメーション、物理シミュレーション、合成、動画編集など多くの機能があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/a177700d-533f-19d5-1300-a52ed03365da.jpeg" width="500">

BlenderではUniversal Scene Description形式のファイル（usd, usdc, usda）のインポート／エクスポートができますが、拡張子がusdzのファイルは対応していないようです。

なぜ、対応していないのかわかりませんが、次のようにすると読み込むことができます。

- 拡張子をzipに変更
- zipを解凍
- 解凍したusdcをインポート

また、Blenderにはアドオンという機能拡張のしくみがあります。直接usdzをインポート可能なアドオンも存在するようです。

## まとめ

Sketchfabでは、USDZでサイズの小さいファイルをダウンロードできます。USDZは、ひと手間かけるとBlenderで読み込むことができます。
ネットワークについて学びなおす0


大学でコンピュータサイエンスを専攻していたものの、しっかり勉強していなかったなぁと
振り返って思う部分があり、また一から学びなおすことにしました。

本記事では、コンピュータサイエンスの分野の中でも、ネットワークについて学びなおすことにします。
参考書として利用しているのは、「ネットワークはなぜつながるのか」という本です。
[Amazonリンク](https://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84TCP-IP%E3%80%81LAN%E3%80%81%E5%85%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%90%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E6%88%B8%E6%A0%B9/dp/4822283119)

こういった記事を書くのも初めてで、読みづらいと感じるかもしれませんが、そこは今後の成長に期待していただけると嬉しいです。

# ネットワークの全体像
ネットワークの全体像は、ユーザーが利用するWEBブラウザ、WEBブラウザからの要求（リクエスト）を受け取るWEBサーバ、WEBブラウザとWEBサーバ（ネットワークアプリケーション）を繋げる仕組み、の３つから構成されています。
これを、ユーザーがURLでブラウザからリクエストを送って、サーバがリクエストに応じた返答（レスポンス）を送って、ユーザーが受け取るという流れを通して理解していきます。

# 概要
### WEBブラウザ
WEBブラウザが行うのは、ユーザーが入力したURLで何をどうしたいのか解析することです。WEBブラウザ自体がリクエストを送るのではなく、解析した後は、ブラウザとサーバを繋げる仕組みの役割です。
### ブラウザとサーバを繋げる仕組み
ここでは、WEBブラウザからのリクエストをパケットに変換して、WEBサーバに届けるまでを行います。さらに言うと、OS内のネットワーク制御用ソフトウェアでリクエストをサーバまで届けられる形に変換して、LAN、インターネット、サーバのLANなどを通してサーバまで送られます。
### WEBサーバ
ここでは、WEBブラウザからのパケットを元のリクエストに復元し、その内容からレスポンスを作成し、パケットに変換します。その後、WEBブラウザからWEBサーバまでリクエストを送信するのと同じ様にWEBブラウザにレスポンスが送られます。

ユーザがレスポンスを受け取って、望み通りの内容であれば、終了です。

次回以降の記事では、いよいよ中身に入っていきたいと思います。
[次回の記事](https://qiita.com/yasaigaoisi/items/b6327b7411bd09433ce7)
DS（データ構造）の長さや属性をリテラルで宣言しない方法

## はじめに

DS（データ構造）を使用してフィールドを合成／分割する方法は、RPG を使用している方なら一度は記述したことがあるかと思います。

その際、皆さんはどのように定義をしていますか？
大抵の場合、以下のように各変数の長さや属性を宣言しているのではないでしょうか？

```rpgle
D  W#YYYYMM                 1      6  0
D   W#YYYY                  1      4  0
D   W#MM                    5      6  0
```

日付のように桁数が変わらないフィールドを合成／分割する際はさほど問題は起こらないかと思います。
しかし、もし DDS で宣言したフィールドを合成／分割する場合はリテラルで宣言すると、DDS の桁数が変更になった際に、DS も再度定義し直す必要があります。

その際、再定義のし忘れや桁数間違え等のミスが起こる可能性が考えられます。

この記事では、このようなミスを防ぐために DS の長さや属性をリテラルで宣言しない方法をご紹介します。


## キーワード

使用するキーワードは以下の２つです。

1. OVERLAY
2. LIKE


## DS の長さ宣言

以下の例では、OVERLAY( DS 名 :\*NEXT)を記述することで、DDS で宣言したフィールドを合成しています。

```rpgle
D  W#WSKA00       DS
D   WSKA01                            OVERLAY(W#WSKA00         )
D   WSKA02                            OVERLAY(W#WSKA00  :*NEXT )
D   WSKA03                            OVERLAY(W#WSKA00  :*NEXT )
D   WSKA04                            OVERLAY(W#WSKA00  :*NEXT )
D   WSKA05                            OVERLAY(W#WSKA00  :*NEXT )
```

```dds
A            WSKA01         1A
A            WSKA02         2A
A            WSKA03         3A
A            WSKA04         4A
A            WSKA05         5A
```

もし、これをリテラルで宣言しようとするとこのようになります。

```rpgle
D  W#WSKA00       DS
D   WSKA01                1      1
D   WSKA02                2      3
D   WSKA03                4      6
D   WSKA04                7     10
D   WSKA05               11     15
```

OVERLAY( DS 名 :\*NEXT)は、サブフィールドを DS 内の次に使用可能な位置に宣言することができます。


## DS の属性宣言

もし DDS のフィールドを直接合成せずに変数を使用する際は、LIKE を使用すると便利です。

```rpgle
D  W#WSKA00       DS
D   W#KA01                            LIKE(WSKA01    )
D                                     OVERLAY(W#WSKA00         )
D   W#KA02                            LIKE(WSKA02    )
D                                     OVERLAY(W#WSKA00  :*NEXT )
D   W#KA03                            LIKE(WSKA03    )
D                                     OVERLAY(W#WSKA00  :*NEXT )
D   W#KA04                            LIKE(WSKA04    )
D                                     OVERLAY(W#WSKA00  :*NEXT )
D   W#KA05                            LIKE(WSKA05    )
D                                     OVERLAY(W#WSKA00  :*NEXT )
```

LIKE は属性を取得することができます。


## おわりに

DS をリテラルで宣言せずに OVERLAY や LIKE を使用することは、長い目で見たときにより効率の良いコーディングであると思います。

ご参考になれば幸いです。最後までお読み頂きありがとうございます。


## 関連した投稿

[DS（データ構造）を LIKE,OVERLAY で宣言したときにコンパイルエラーになる原因](https://qiita.com/tamaday/items/9a238c74bc0a6a9f49be)
if,for文の文法と真偽値,演算子について解説

【if文】
もし◯○だったら××してね〜。

(基本)
```
if (判定したい条件(変数名))
{
  // 条件式が成功した場合(true)に実行する処理
} 
```
条件文を実行するか、しないか
true(真)の場合のみ処理が実行される

(多分岐)
```
(else if(複数の条件を判定))

if (判定したい条件(変数名))
{
  //①条件式が成功した場合(true)に実行する処理
} 
else if 
{
    //②ifの条件が失敗(false)の場合else ifを実行する
}
else 
{
    //③上記の条件式が失敗(false)の場合に実行する処理
}
```
①がfalseの場合②へ、①②がfalseの場合③の処理をする

```
(else(条件を満たせない場合))

if (判定したい条件(変数名))
{
  // ①条件式が成功した場合(true)に実行する処理
} 
else 
{
    // ②条件式が失敗(false)の場合に実行する処理
}
```
trueの場合は①、そうでない場合は②というように処理
false(偽)の場合にelseの処理が実行される


then節：if文の条件に一致したら行う処理
else if節：if文の条件に一致しなかったけどelse ifの条件に一致したら行う処理
else節：上記処理のすべてに一致しなかったら行う処理



【for文】
```
基本文法

for(回数を格納する用の変数 = 始まりの値; 繰り返しが続く条件; カウントアップする数)
{
繰り返したい処理を記述…
}

```

【真偽値】
・true(真) 
・false（偽）
true(真)→カッコ内に書く　/ false（偽）→カッコ外に書く

【演算子】
( ！ )否定文になる
true(真)→カッコ外に書く　/ false（偽）→カッコ内に書く

(等値演算子)
( == )  左右の値が等しい場合に真
( != )  左右の値が等しくない場合に真

(関係演算子)
( > ) 左の値が右の値より大きい場合に真

( < ) 左の値が右の値より小さい場合に真

( >= ) 左の値が右の値以上の場合に真

( <= )  左の値が右の値以下の場合に真

(代入演算子)
　( = )	代入
( += )	加算して代入
( -= )	減算して代入
( *= )	乗算して代入

(論理演算子)いちどに複数の条件判定が出来る
( && )  AND(2つの真偽値がどちらも真)条件が成立した場合に真

( || )  OR(2つの真偽値のいずれかが真)条件が成立した場合に真

(インクリメント(++)、デクリメント(--)演算子)
( ++ ) 変数の値を1だけ増やす
( -- ) 変数の値を1だけ減らす


【合わせて読みたい記事】
foreachについて
https://qiita.com/hanatan079/items/9c29d7ab61729177cbe3
４０代おっさんFastAPIを勉強する(簡易Web API作成)

## 本記事について

この記事はプログラミング初学者の私が学んでいく中でわからない単語や概要を分かりやすくまとめたものです。
もし不正などありましたらコメントにてお知らせいただければ幸いです。

## 簡単なAPIを作って、ローカル環境で試す

main.pyを作成

```python
from fastapi import FastAPI
from pydantic import BaseModel

class Data(BaseModel):
    x: float
    y: float

app = FastAPI()

@app.get('/')
def index():
    return {'message': 'Hello Data'}

@app.post('/')
def calc(data: Data):
    z = data.x*data.y
    return {'result': int(z)}
```

sample.py作成

```python
import requests
import json

def main():
    url = 'http://127.0.0.1:8000'
    data = {
        'x': 1.2,
        'y': 3.0
    }

    res = requests.post(url, json.dumps(data))
    print(res.json())

if __name__ == '__main__':
    main()
```

## Deta

Herokuのような無料で使えるクラウドサービスで、クレカ登録も必要ないので安心して使うことができます。Detaには現在、以下の3つのサービスがあります。

Deta Base：機能豊富なAPIを備えたすぐに使用できるNoSQLデータベース。
Deta Micros：スケーラブルなNode.jsおよびPythonアプリを数秒でデプロイします。
Deta Drive：画像とファイルをアップロード、ホスト、提供します。

### 実践

#### Detaに登録

とりあえず、初めての方はDetaにユーザー登録を

<https://www.deta.sh/?ref=fastapi>

#### requirements.txtを作成

次に
先ほど作ったmain.pyと同じフォルダ内に作成
`requirements.txt`
を作成

```tex
fastapi
```

ライブラリの情報を書く

#### CLIのインストール

自分はwindowsなので

```bash
iwr https://get.deta.dev/cli.ps1 -useb | iex
```

インストールしたら再起動（ターミナル閉じるだけではダメでした…）

成功したか確認

```bash
deta --help
```

こちらがうまく行ったらとりあえず大丈夫です。

#### CLIでログイン

```bash
deta login
```

#### Deta でデプロイ

かならず実行フォルダに移動

```bash
deta new
```

```bash
{
    "name": "fastapideta",
    "runtime": "python3.7",
    "endpoint": エンドポイント,
    "region": "eu-central-1",
    "visor": "disabled",
    "http_auth": "disabled"
}
```

となれば成功

これでエンドポイントにアクセスすると確認が出来ます。

#### 他色々

Micros
Read tha docs
を見ると色々書かれているので参照

APIキーなどの設定も書かれている。

## 参考

https://www.udemy.com/course/python-fastapi
DS（データ構造）を LIKE,OVERLAY で宣言したときにコンパイルエラーになる原因

## はじめに

DS（データ構造）は、LIKE、OVERLAY を使用することで、リテラルの属性や長さを固定せずに宣言することを[DS（データ構造）の長さや属性をリテラルで宣言しない方法](https://qiita.com/tamaday/items/d551ea21d1846b3bc575)でご紹介しました。
しかしこの方法を使用すると、（画像１）のようなコンパイルエラーが発生する事があります。

（画像１）  
![dsCompileError_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/1cf0d9f0-948c-d74c-205c-093f4bb2f29c.png)

もちろん、使用している変数のデータタイプ／長さは正しく宣言しています。
この記事では、このようなエラーが発生する原因をご紹介します。


## 原因

DS のサブフィールドの桁数がオーバーする原因は以下の 2 つの理由が関係しています。

1. DDS でゾーン十進数と宣言しても、IBM i はパック十進数として認識する。
2. DS で宣言した変数は、ゾーン十進数として認識する。

実際にコンパイルリストを見て、これらの原因を確認してみましょう。


## IBM i が認識しているフィールドの属性

まず前提として、DDS でフィールドを以下のように宣言します。

```dds
A            WSKA01         6S 0       COLHDG(' 年月 ')
A*
A            WSKA11         4S 0       COLHDG(' 年 ')
A            WSKA12         2S 0       COLHDG(' 月 ')
```

そして、D 仕様書内では DDS で宣言したフィールドを使用して、以下のように宣言します。

```rpgle
D                 DS
D  W#WSKA00                          LIKE(WSKA01    )
D   WSKA11                           OVERLAY(W#WSKA00         )
D   WSKA12                           OVERLAY(W#WSKA00  :*NEXT )
```

一見すると、問題がないように思いますが、コンパイルリストを確認すると、冒頭で紹介した通り、（画像１）のようなコンパイルエラーが発生します。

ここで、コンパイルリストの相互参照表を確認することで、IBM i が認識しているフィールドの属性を知ることができます。
（画像２）  
![dsCompileError_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/6a4d329e-d134-0377-6ccb-0297ea9f5ff8.png)

この相互参照表から、IBM i はゾーン十進数を以下のように認識する事、属性は D 仕様書を優先する事が分かります。

1. DDS で宣言したフィールド → パック十進数
2. DS で宣言したフィールド → ゾーン十進数


## おわりに

IBM i の数字タイプへの認識、属性は D 仕様書を優先する事を踏まえると以下の記述を追記することで、コンパイルエラーを回避することができます。

```rpgle
D                 DS
D  WSKA01
```

（画像３）  
![dsCompileError_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/2cfac4be-2126-f8d0-4579-f37669c64af6.png)

もし似たようコンパイルエラーでお困りの際に、ご参考になれば幸いです。
最後までお読み頂きありがとうございます。

## 関連した投稿

[DS（データ構造）の長さや属性をリテラルで宣言しない方法](https://qiita.com/tamaday/items/d551ea21d1846b3bc575)
【Linux】動的共有ライブラリの概要

# 0. はじめに
Linuxにおける動的共有ライブラリ（以下、共有ライブラリ）に関する備忘録です。
参考文献のブログが大変参考になりましたので、より詳しく知りたい方はそちらもご確認ください。

# 1 共有ライブラリの役割
共有ライブラリは、実行ファイルを実行する際に動的にリンクされ、共有ライブラリに実装された機能を実行ファイルに提供します。

# 1.1 実行ファイルが必要とする共有ライブラリの確認方法
**readelf**コマンドや**ldd**コマンドによって、実行ファイルが必要とする共有ライブラリを確認できます。
lddコマンドの場合は、共有ライブラリが必要とする共有ライブラリも表示されますので、より多くの共有ライブラリが表示されます。
```
# readelf -d /bin/ls
Dynamic section at offset 0x1fa38 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
```
```
# ldd -d /bin/ls
	linux-vdso.so.1 (0x00007ffffa256000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f719cdc9000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f719c9d8000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f719c767000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f719c563000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f719d213000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f719c344000)
```

# 1.2 共有ライブラリのバージョン確認方法
共有ライブラリの命名規則は、<ライブラリ名>.so.<メジャーバージョン番号>.<マイナーバージョン番号>.<リリースバージョン番号>となっています。
libgdal.so.20.3.2を例にすると、以下のように対応しています。

- メジャーバージョン番号：20
- マイナーバージョン番号：3
- リリースバージョン番号：2

バージョンの話になると、バージョンの不一致が気になる方も多いと思います。
結論としては、**メジャーバージョン番号までを気にすれば良い**です。理由は、メジャーバージョン番号が同じであれば、[ABI](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)が保たれるため、実行ファイルを実行する際に問題とならないからです。readelfやlddで共有ライブラリを確認した際にも、メジャーバージョン番号までしか表示されないようになっています。これは、シンボリックリンクを使って、マイナーバージョン番号やリリースバージョン番号が書かれた実体を隠蔽するように作り込まれているからです。

# 2. 共有ライブラリの保存先
共有ライブラリの保存先は、/etc/ld.so.confや環境変数（$LD_LIBRARY_PATH）に指定されています。

# 2.1 /etc/ld.so.conf
共有ライブラリの保存先は **/etc/ld.so.conf**に記載されています。
筆者の環境で確認すると、/etc/ld.so.conf.d/*.confの中身を読み込むようで、
```
# cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
```
例えば、/etc/ld.so.conf.d/x86_64-linux-gnu.confを確認すると、以下のように共有ライブラリの保存先が記載されていました。
```
# cat  /etc/ld.so.conf.d/x86_64-linux-gnu.conf 
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
```

# 2.2 $LD_LIBRARY_PATH
共有ライブラリの読み込み先として独自ディレクトリを追加する場合は、**$LD_LIBRARY_PATH**という環境変数を利用します。
```
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"追加したいディレクトリのパス"
```
# 3. 参考文献

https://gihyo.jp/lifestyle/serial/01/ganshiki-soushi-2/0029

https://gihyo.jp/lifestyle/serial/01/ganshiki-soushi-2/0031

https://torutk.hatenablog.jp/entry/20090208/p1
checkbox 複数の値を送信する

# []で複数の値を送信
```html
      <label><input type="checkbox" value= "送信する値"
name="example[]"> ラベルの名前 </label>
```
```name="example[]"```のように```[]```をつけると、```配列の型で送信```される。

# 注意
テーブルのデータ型が配列に対応していない場合は、配列を文字列にしたり工夫が必要。
rubyは```join()```を使って文字列にする。
"Warning message: In normalizePath(path.expand(path), winslash, mustWork) :"の解決策

　Rや、RStudioをインストールしたのに、RやRStudioを開くたびに以下の警告メッセージが出ることありませんか？
**"Warning message:In normalizePath(path.expand(path), winslash, mustWork) : path[1]="C:/Users/あなたのパソコンの名前/OneDrive/??????": ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。**"

　Rの勉強会を主催しているのですが、新しくRをインストールされる方の中にこのようなWarning messageが出る方が毎年一人以上はいらっしゃいます。これはWarning messageですが、毎回これが表示されるのは何か気持ち悪いです。そして、今後RやRStudioを使う上であなたを困らせる可能性が高いので対処しておきましょう。
　毎年ネットの記事を参考にしながら何とか解決するのですが、そのノウハウを自分へのメモもかねて記録しておきます。同じような現象で困っている方のヒントになればと思います。

先に一つ断っておくと、僕は**Windowsユーザー**で、これまで**対応した方々全員Windowsユーザー**ですのでWindows以外の方がこの方法で解決するのかは分かりません。

# 原因
　ホームディレクトリがOne Drive側に展開していることがWarning messageの原因のようです。なぜホームディレクトリがOne Driveではだめなのかについては僕自身分かりません（わかる方教えてください）。

# 解決策
　色々な解決策があると思いますが、僕が対応してきた経験ではWindowsの環境変数に、**R_USER**を設定することですべて解決できました（環境変数とは、プログラム間で共有できる情報で、この変数によりユーザーごとに起動時設定を変更できるようです）。

## 環境変数の設定
1．パソコンで［システムの詳細設定の表示］と検索し、それを開いてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344524/6b03d47d-afb7-9f3f-8cc1-bc3bda432fa8.png)

2.　ポップアップが表示されるので［環境変数(N)...］をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344524/872f8e96-976f-2af3-0405-0a966a742439.png)

3.　［新規(N)...］をクリックし、［変数名(N)...］に**R_USER**と入力します。そして、［ディレクトリの参照(D)...］をクリックし、任意のフォルダーを開きます。この際、One Drive配下のフォルダーは指定しないでください。指定した後［OK］を押してください（赤のモザイクの箇所はそれぞれのパソコンで違います）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344524/7d62a368-8a27-b545-ebda-8a46d7189de2.png)

4.　Windowsを再起動してください　**←忘れないで！**
環境変数を有効にするには再起動が必要みたいです。
もう一度RやRStudioを開くとおそらくWarning messageは消えているでしょう！

# 最後に
　Rの環境変数は"R_USER"だけではなく、他にもあるようです（参考記事参照）。

# 参考記事
## 環境変数の設定方法
https://sites.google.com/view/pcmanabitai/r%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88-%E3%83%AB

## Rの環境変数
https://www.agr.nagoya-u.ac.jp/~seitai/document/R2009/Rsettings.pdf
VMware vSphereでADサーバを構築してみた

# はじめに

### 作成の背景
現職でADサーバのオンプレからVMware vSphere環境への移行プロジェクトに携わることになりました
プロジェクト概要としては

1:VMware vSphere環境上にADサーバを構築
2:既存ドメインコントローラーの降格
3:新規ドメインコントローラーの昇格
4:ドメインに参加しているサーバのDNSに切り替え

となりますが、取り急ぎ
**VMware vSphere環境上にADサーバを構築**　のステップを記事にさせていただきます。


### 環境
・vSphere client6.5
・Windows　Server 2019
# 基礎知識

### ・VMware vSphereとは
これは、VMware社の仮想環境ハイパーバイザー製品の「ソフトウェアスイート」です。
つまり様々なツールの一式で、図にすると以下のようになります。

![スクリーンショット 2022-11-12 13.47.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666121/0a08579d-1260-4d2c-0c03-ef9471d1e120.png)

vSphereというソフトウェアスイートの中に
・仮想ハイパーバイザーである「EXSi」
・EXSiを管理する「vCenter]
・vCenterに接続して、GUIで操作をするツールである「vSphere Client」
などが含まれていることになります。

今回は、
1:「vSphere Client」に接続
2:「EXSi」上にゲストOSをインストール
3:Active Directryをインストール

という手順で作業を進めていくことになります。
本作業であまり意識することがありませんでしたが、VMware vSphere環境上では**共有ストレージ**というボリュームが存在し、**VMFS（Virtual Machine File System)**と呼ばれるファイルシステムによってフォーマットされています。

### ・Active Directryとは
Windows Serverにインストールすることのできる機能の一つで、**会社や組織が保有している人材や情報などの各種リソースを管理するためのディレクトリ**です

Active Directoryでは**ドメイン**と呼ばれる大きなフォルダのようなものが作成されます
ネットワーク内のサーバやクライアント端末は、このドメインに参加することで、一元管理がされていきます

この一元管理するサーバのことを**ドメインコントローラー**と呼び、DCと呼称されます。このDCのReplacementこそが、本プロジェクトの目的となります


# 作業内容
※画像がないのが悔やまれます・・・
### 新規サーバの構築
・vSphere Cliientにログイン後、コンソール上で「新規作成」を選択
・データセンターを選択後、対象の仮想マシンを実行するホストを選択
・データストア（ESXiが仮想マシン等の物理ファイルを格納する為のストレージ）
・ゲストOSの設定
・NIC、Diskの設定
・データストアにアップロードされているISOファイルを指定し、OSのインストール
※「パワーオン時に接続」というチェックボックにチェックがついている必要があります
・「VMware tool」（VMware vSphereの操作性を向上するソフトウェア）

### ADのインストール
・構築された仮想サーバにRDP、もしくはvSphere Clinetからログイン
・サーバマネージャーを開き「役割と機能の追加」を選択
・「インストールの種類」及び「対象サーバの選択」を実施
・「サーバの役割の選択」で「**Active Directry ドメインサービス**」を選択
・内容を確認し、インストール

全く新しい環境での構築の場合、ADインストール後はドメインコントローラーへの昇格を実施する必要があります
今回は、この後本サーバをドメイン参加させるのですが、現時点でまだ実施できておりませんで、
内容としてはここまでとします

# まとめ
VMware vSphereでの構築が初めてだったため、用語の理解から始めました
あくまで正確な作業手順を作成するのではなく、**VMware vSphere上でのADサーバの構築の全体像を掴む**を目的とした記事の作成でしたので、参考情報をご確認ください。といった具合の温度感のものです

元文系人間が「えいやっ」でインフラエンジニアになってみて、正直職場の皆さんの会話は外国語です。
こういったアウトプット活動を増やし、少しでも実力を伸ばしていくことができればと思います。

# 参考情報
### VMware vSphere

https://www.kagoya.jp/howto/engineer/vm/vsphere-client/

https://www.depthbomb.net/?p=4500

https://e-words.jp/w/VMware_ESXi.html

https://blogs.vmware.com/vmware-japan/2014/01/vsphere-basic-storage1.html

https://licensecounter.jp/engineer-voice/blog/articles/20211224_kiso_vsphere_3_datastore.html

https://pfs.nifcloud.com/navi/words/vmwaretools.htm#:~:text=%E6%9C%8820%E6%97%A5-,VMware%20Tools%E2%84%A2%E3%81%AF%E3%80%8CVMware%E3%82%92%E5%8A%B9%E7%8E%87%E7%9A%84%E3%81%AB%E7%AE%A1%E7%90%86,%E3%81%97%E3%81%A6%E5%88%A9%E7%94%A8%E3%81%97%E3%81%BE%E3%81%99%E3%80%82


### Active directry
https://www.rem-system.com/win2019-adsetup/
Codpen で HTMLを全画面表示する

上のアイコンから「Full Page View」または「Debug Mode」を選べばOK

![image](https://user-images.githubusercontent.com/13635059/201459761-cd44dc88-7249-437e-891f-674636725eed.png)

# Fill Page View

Code Pen のヘッダがある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/60e89daf-3f74-55ff-049c-35fe033eb244.png)

# Debug Mode

Code Pen のヘッダなし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/68e0d6e8-2f20-f69d-b79a-1fec93c80777.png)


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
My SQL を気軽にブラウザから試す DB Fiddle  ( Play Ground )

https://www.db-fiddle.com/f/kyJ1gm8ZuifCjsxwQvdAkX/1

<img width="1431" alt="image" src="https://user-images.githubusercontent.com/13635059/201459175-dff780ce-ef04-4ad3-b5f2-0ab8303eba42.png">


# 特徴

- ログインしなくても使える。
- URL経由で簡単にSQLと結果をシェア出来る。
- DBのデータは自分でCREATE文を書くなどして用意しなければいけない。サンプルテーブルとかはなさそう。
- 不要なデータが残って環境を汚すようなこともない。

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
hugoで静的なサイトを構築する（①はじめに）

## はじめに

ExcelやWordで作られている設計情報は参照しにくく、メンテもしにくい。先方の事情があるならともかく開発中に参照する資料をOffice製品で作るのは避けたいところ。
今回は静的サイトジェネレーターを使って、文字ベースの仕様や用語などの情報をドキュメント化しましょう。

## やりたいこと

- 開発中に、開発の指針となる設計書をブラウザで確認したい
- 設計書の元になるソースはエディタで編集して、Gitで差分管理したい
- CI/CDで自動ビルド、自動デプロイまでしたい

## まずは

設計書といっても種類があります。まずは比較的やりやすいと思われる「用語集」のテンプレートを作るところを目標にします。

## で、hugo

https://github.com/gohugoio/hugo

色々あるようですが以下のような理由でhugoを採用。

- HTMLまたはMarkdownで書ける静的サイトジェネレーター
- テーマやテンプレートが豊富
- ビルド環境の用意が簡単（非公式のdocker版が公開されている）
- コミット頻度が比較的多い（hugo自体の開発が盛んである）
- Go言語で作られている

この辺まで調べてチャレンジすることに決定。

次回は使ってみた編。
Pythonで球面調和関数をピラミッド型にプロットする話

コードの解説は後ほど書きますが先にコードだけ公開します。
このソースコードを利用するときは一言連絡していただけると幸いです。

# 遊び方
- `lmax`の値を自由にいじってあそぶ。大きい値を選びすぎるとなんかうまく出力されませんが`lmax=10`ぐらいだといい感じになります。
- `plt.subplots_adjust(wspace=0, hspace=-0.95)`はいい感じに、`hspace`の値を設定してあげてください。

```python
from scipy.special import sph_harm
import numpy as np

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.cm as cm

def Y_lm(l, m, θ, φ):
    return sph_harm(m, l, φ, θ)

def real_Ylm(l, m, theta, phi):
    
    if m == 0:
        Y = Y_lm(l, m, theta, phi)
    elif m > 0:
        # m>0の場合、以下の線形結合を取る
        Y = 1/np.sqrt(2)*(Y_lm(l,-m, theta, phi) + (-1)**m * Y_lm(l, m, theta, phi))
    else:
        # m<0のとき、下の解に対応させる
        Y = 1.j/np.sqrt(2)*(Y_lm(l ,m, theta, phi) - (-1)**(-m) * Y_lm(l, -m, theta, phi))
    
    return np.real(Y)

# 極座標(r,Θ,φ)からデカルト座標(x,y,z)への射影
def Polar_to_Descartes(r, theta, phi):
    x = r*np.sin(theta)*np.cos(phi)
    y = r*np.sin(theta)*np.sin(phi)
    z = r*np.cos(theta)
    return x, y, z

def my_plot_surface(l, m, fig, ax, 
                    F, θ, φ,
                    c_F, c_type='bwr', c_alpha=1,             # 色設定
                    ax_lim=0.5, ax_title=None,               # ax設定
                    cb_shrink=0.5, cb_pad=0.1, cb_name=None): # color bar設定


    # 色の正規化
    norm = matplotlib.colors.Normalize(vmin=np.min(c_F), vmax=np.max(c_F))  # 最大値を1に規格化
    
    # グラデーションの設定
    cmap = cm.get_cmap(c_type)
    
    # サーフェスプロット
    x, y, z = Polar_to_Descartes(F, θ, φ)  # Fが正の実数でなければエラー
    
    if l == 0 and m == 0:
        ax.plot_surface(x,y,z, color='red', alpha=c_alpha, linewidth=0)
    else:
        ax.plot_surface(x, y, z, 
                    facecolors=cmap(norm(c_F)),  # c_Fが実数でなければエラー
                    alpha=c_alpha, linewidth=0)
        
    # 軸範囲、ラベル、グラフタイトル
    ax.set_xlim(-ax_lim, ax_lim)
    ax.set_ylim(-ax_lim, ax_lim)
    ax.set_zlim(-ax_lim, ax_lim)
    ax.set_title(ax_title)

# 座標
theta = np.linspace(0, np.pi, 100)
phi = np.linspace(0, 2*np.pi, 200)
θ, φ = np.meshgrid(theta, phi)  # 2Dデータに変換

lmax = 10
J = []
J.append(lmax+1)
for k in range(1,lmax+1,1):
    for kk in range((lmax+1)+(2*lmax+1)*k-k,(lmax+1)+(2*lmax+1)*k+k+1,1):
        J.append(kk)
i=0
fig = plt.figure(figsize=(100,100))

for l in range(lmax+1):
    for m in range(-l,l+1,1):
        ax = fig.add_subplot(lmax+1,2*lmax+1,J[i], projection='3d')
        F = np.abs(real_Ylm(l, m, θ, φ))**2
        c_F = real_Ylm(l, m, θ, φ)
        my_plot_surface(l,m,fig, ax, F, θ, φ, c_F)
        ax.tick_params(labelbottom=False,
            labelleft=False,
            labelright=False,
            labeltop=False)
        ax.tick_params(bottom=False,
            left=False,
            right=False,
            top=False)
        plt.subplots_adjust(wspace=0, hspace=-0.95)
        i = i+1
```
SQLを勉強してみる。

#### SQLとは

プログラミングの学習を始めると必ずお会いする言葉、それはSQL。
SQLとはデータベース内のデータを操作するプログラム言語のことです。
データベースにデータを登録するときや、何かのデータを参照するために取り出すときは、
実はSQLを介して行なっています。
命令文を実行することで、必要なデータを簡単に取得できるのです。
ちなみにフルネームは「Structured Query Language」で、これを直訳すると
「構造化問い合わせ言語」という意味らしいです。逆に難しい...。
SQLを覚えると、データベースに保存されている情報を効率的に扱えるようになります。


![undraw_add_information_j2wg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2909373/fe00ee19-5cc7-9168-d46f-5b3e49a893fd.png)



##### Rails内でのSQL

Rails内ではSQLを意識することはあまりないかもしれません。
例えば、通常データベースとやりとりをするためにはこのSQLでアクセスする必要があります。（SQL＝データベース言語ともいう）
しかし、Railsではモデルを使うことでデータベースとのやりとりが簡略化されており、
SQLを記述しなくてもデータベースのやりとりができるようになっています。
RailsではモデルがSQL文をデータベースに渡すことでデータを操作できているんですね。

#### SQLを構成する３つの言語

SQLの命令文はDDL・DML・DCLの3種類で構成されています。
●DDL（Data Definition Language）・・・データを定義
●DML（Data Manipulation Language）・・・データを操作
●DCL（Data Control Language）・・・データ制御や管理
definitionは定義っていう意味だし、manipulationは操作って意味だし、Controlはそのままだし
そう考えると覚えやすいですね！


:::note info
 <strong>DDL（データ定義言語）</strong>
SQLのデータベースの定義や作成に関わる。代表的なのは以下３つ。
♦︎CREATE文・・・データベースやテーブルの作成
♦︎DROP文・・・データベースやテーブルの削除
♦︎ALTER文・・・データベースやテーブルの変更
:::
:::note info
 <strong>DML（データ操作言語）</strong>
データの取得/登録/更新/削除などのデータ操作に関わる。
♦︎SELECT文・・・データを取得
♦︎UPDATA文・・・データ更新
♦︎DELETE文・・・データ削除
♦︎INSERT文・・・データ挿入
:::
:::note info
 <strong>DCL（データ制御言語）</strong>
データベースを管理、操作するときに使用する言語。
トランザクションの制御やデータベースへのアクセスを制御。
♦︎BEGIN文・・・トランザクション開始
♦︎COMMIT文・・・実行した処理の確定
♦︎GRANT文・・・権限を与える
♦︎REVOKE文・・・権限を奪う
♦︎ROLLBACK文・・・データの戻し
:::
※トランザクション？何それ？ってなった方は以下記事ご参照ください。
>https://wa3.i-3-i.info/word142.html

##### SQL活用方法の例

| 生徒番号 | 名前 | クラス |
| :-- | --: | --: |
| 1 | Apiyo  | 2 |
| 2 | Bpiyo | 1 |
| 3 | Cpiyo | 3 |
| 4 | Dpiyo| 1 |


```sql
1. SELECT 名前　EROM 生徒テーブル WHERE 生徒番号 = 1
```
例えば、上のリストから１番の生徒のデータを取り出したい ➡︎ SELECT文を使用
結果、生徒番号１番のApiyoちゃんを取り出せるはずです。

今回はSQLの基本中の基本をまとめてみました！以下記事も参照ください。
>https://wa3.i-3-i.info/word15640.html
>https://udemy.benesse.co.jp/development/system/intro-sql.html
Advent Calendar がなにかを改めて調べてみた

エンジニア文化として一般的になりつつある「Advent Calendar」の起源や歴史について改めて調べてみた。

### 概要
> アドベントカレンダー (Advent calendar) は、クリスマスまでの期間に日数を数えるために使用されるカレンダーである。

### 起源
> アドベントカレンダーの起源は、19世紀初頭よりドイツ・ルーテル派がクリスマス前の24日間を数えるために始めたとされる。ドアに毎日チョークで印をつけたことから始まったとすることもある。アドベントリースの様に毎日ロウソクを灯していったり、毎日新しい宗教画を壁に掛けていくと言う習慣の家庭もあった。
> 最も古いアドベントカレンダーとして知られているのは1851年の手作りのものである。

https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%89%E3%83%99%E3%83%B3%E3%83%88%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC

いわゆる、化粧品やお菓子が入った窓を一つずつ開ける様式だけでなく、さまざまな形で降誕祭を待ち望む文化ということらしい。

### エンジニア文化としての発端
調べた限りでは [Perl Advent Calendar 2000](https://perladvent.org/archives-Yd.html) がその発端のよう。

日本では [Qiita Advent Calendar](https://qiita.com/advent-calendar) と [Adventar](https://adventar.org/) が Advent Calendar 2大プラットフォームとして君臨。
他方、海外では各企業のオウンドメディアを主体として開催していたり、[Advent Of Code](http://adventofcode.com/) なんてものがあったりするみたい。

### 所感

Advent Calendar の形式は文化や地域にによって様式はさまざまで、エンジニア文化圏でも「技術ブログをリレー形式で投稿していく」だけではないということが分かった。
これからの Advent Calendar の進化も楽しみ！
[python] ファイルにログを書き込む [日付]

# 0.初めに
タスクスケジューラ使って透明化してマクロを動かしていると、ごくまれに発生するバグのデバッグができない。
ファイルにログを残す必要を感じた。(バックグラウンド・透明化しないと作業の邪魔)
日付順に分けられたら便利そう。

# 1.ファイル名に日付を使ってログを書き込む
以下ソースの解説

yyyy-mm-dd.logというファイルがlogフォルダに作られる。logフォルダは手動で作ってください。
"w"は上書きモード
datetime.datetime.now()を書いてからログを書くことで時刻もわかる。

```python:py_log.py
import datetime

py_log = open("log\\"+str(datetime.date.today())+".log", "w")　　#　上書きモード
print(str(datetime.datetime.now())+"ログです。")　　#　コマンドプロンプトにログを残す
print(str(datetime.datetime.now())+"ログです。", file=py_log)　　#　ファイルに書き込む
py_log.close()　　#　閉じないと保存されない
```
自然数ビットから実数ビットとその応用

```
char = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
bit = 6


charCount = len(char)
bitCount = 2**bit

which = input('Which do you do StringID to BinaryCode/ BinaryCode to StringID(a/null) >>')
if bool(which):
    sID = input('input StringID >>')
    print('StringID: ' + sID)
    charID = list(sID)
    charIDCount = len(charID)
    Sum = 0
    for cID in charID:
        charIDCount -= 1
        Sum = Sum + (char.index(cID) * charCount**charIDCount)
    print('IntID: ' + str(Sum))
    binaSum = bin(Sum)
    length = len(str(binaSum)) - 2
    if length % bit != 0:
        length = (length // bit) * bit + bit
    print('BinaryID: ' + str(binaSum))
    print('BinaryLength: ' + str(length))
else:
    binaryID = input('input BinaryID >>')
    print('BinaryID: ',str(binaryID))
    intID = int(binaryID,2)
    print('IntID: ', str(intID))
    charID = []
    while True:
        charID.insert(0,char[int(intID%charCount)])
        intID = intID / charCount
        if intID < 1:
            break
    print('StringID: ' + ''.join(charID))
```
で作成可能
8文字目から1文字当たりの容量が実数ビットになっている
Powershell でアプリを起動する方法

# はじめに

私はPowershell超初心者です。業務でPowershellを使用する機会は今まで時々あったのですが、
あまり意味をわからず実行していました。なので少しづつ自主的に学習を始めました。

# アプリ起動コマンド

今回はいちいちGUIで開くのがめんどくさいアプリを一発で起動できるファイルを作成しました。
カレンダーをすぐ見たかったので試しに作ってみました。（カレンダーアイコンをクリックすればよいと言われるとそれまでなのですが、、）

```
Start-Process -FilePath "/対象アプリがあるフォルダ/Calendar.app”
```

上記のようになります。ファイルの拡張子は「.ps1」です。
OpenAPI Generatorが内部利用するテンプレートについて

# TL; DR

- 言語ごとのテンプレートファイルにOpenAPIの情報を流し込んでソースコード生成
    - [テンプレート一覧](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources)
- テンプレートは [handlebars](https://handlebarsjs.com/) で記載
    - 利用可能なヘルパー関数（一部Java独自実装あり）: [handlebars.java](https://github.com/jknack/handlebars.java/tree/master/handlebars/src/main/java/com/github/jknack/handlebars/helper)

# はじめに

OpenAPI Generatorは、OpenAPIで書かれたAPI仕様からSDK等のソースコードを自動生成できるツールです。非常に多くの言語、フレームワークをサポートしているのが特徴です。

https://github.com/OpenAPITools/openapi-generator

これらのソースコードは、テンプレートファイルを利用して生成されます。
OpenAPI Generatorの実装内部を見る機会があったので、備忘録としてこのテンプレートについてまとめました。

# ソースコードのテンプレート

ソースコードは、テンプレートファイルへOpenAPIドキュメントの情報を流し込むことで生成されています。

https://github.com/OpenAPITools/openapi

テンプレート言語には handlebarsが使用されています。

https://handlebarsjs.com/

流し込まれる情報には、OpenAPIドキュメントをパースして得られた `OpenAPI` オブジェクトのフィールドが利用されます。

例：レスポンス `CodegenResponse` class

https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenResponse.java#L22

# 使用可能な文法

handlebarsはテンプレート言語mustacheを拡張したもので、制御構文として使える文法 (`{{#if}}`, `{{#each}}` 等)が追加されています。

https://mustache.github.io/

素のmustacheには、「Logic-less templates」の紹介文の通り制御構文や関数は一切定義されていません。ただし、レンダリングを制御するためのユーザー定義関数 (`lambda`) を実装することが可能です。 

（[公式](https://mustache.github.io/mustache.5.html)より引用）

```mustache:テンプレート
{{! #hoge ~ /hoge で囲まれた範囲に適用 }}
{{#wrapped}}
  {{name}} is awesome.
{{/wrapped}}
```

```js
{
  "name": "Willy",
  // lambda定義
  "wrapped": function() {
    return function(text, render) {
      return "<b>" + render(text) + "</b>"
    }
  }
}
```

```html:結果
<b>Willy is awesome.</b>
```

handlebars独自の制御構文 (`helpers`) はこの `lambda` と同様の文法を持ち、一般的なプログラミング言語のようなif文、ループを記述可能です[^1]。

https://handlebarsjs.com/guide/builtin-helpers.html#if

```mustache:公式より引用
<div class="entry">
{{#if author}}
<h1>{{firstName}} {{lastName}}</h1>
{{else}}
<h1>Unknown Author</h1>
{{/if}}
</div>
```

OpenAPI GeneratorではhandlebarsのJava実装が使われています。注意点として、**Java実装特有のhelperが追加されています**　（例: `{{#and}}`, `{{#or}}`）。
(公式ページを見ても載っていないので注意！)

構文の挙動を調べる際には、以下のディレクトリを検索するのが確実です。

https://github.com/jknack/handlebars.java/tree/master/handlebars/src/main/java/com/github/jknack/handlebars/helper

# おわりに

以上、OpenAPI Generatorのテンプレートについての簡単な紹介でした。
拡張機能の親子関係が分かってしまえばなんてことはないのですが、検索途中では「この文法の説明はどこに？？」と沼にはまってしまうことがありました...

[^1]: 文法形式が異なるだけで、mustache自体にも同様の表現力はあります。