OmniAICreator/Qiita-1.07M huggingface dataset:
ReactのWebアプリに機能追加してエディタアプリ風にしてみた

## はじめに
[Reactで簡単なWebアプリを作ってみた](https://qiita.com/Oyuhaat/items/66be093898050de9fe3e)の続きになります。
アプリ概要を簡単に言うと、ボタンを作って、色をカスタマイズしたり、Reactコード化したりするアプリになります。

今回、以下の機能を追加しましたので、それぞれ説明や工夫した点、難しかった点を書いていきます。

- 保存、ロード機能
- ドラッグ&ドロップ機能
- 戻る・進む機能

今回実装したサイトは[こちら](https://y-o-shi.github.io/color-pickers/)、Githubリポジトリは[こちら](https://github.com/y-o-shi/color-pickers)にあります。
## 保存、ロード機能
- 概要
現在のボタンの状態を保存します。次回ブラウザからのアクセス時、ロードするか聞かれるので、「はい」を押すと保存していたデータが読込まれます。ブラウザ側ローカルストレージに保存しているので、ブラウザキャッシュを削除するとデータも消えます。また、キャッシュ機能がOFFの場合は正常に保存されません。
最後に保存したデータから変更が無い場合は保存ボタンはグレーアウトされて押すことができなくなります。

![ver2-save.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620936/8c6d1eee-a9e2-5838-ca09-cf210c7694fc.gif)

- 感想
実装はLocalStorageを使って1時間程でサクッとできました。今までクライアント側のデータ管理はCookieしか使ったこと無く、LocalStorageは初めて使ったのですが、あまりの簡単さにビックリしてしまいました。
ただの保存、ロード機能だけだと物足りないので、最後のセーブデータから変更が無い場合は保存ボタンはグレーアウトされて押せなくしました。

## ドラッグ・ドロップによる入替え機能
- 概要
ドラッグ入替え機能ボタンを押すことで、ボタンの配置をドラッグで移動することが可能になります。再度入替え機能ボタンを押すことで入替えモードが終了し、選択モードに戻ります。戻る・進むボタンも有効で、入れ替えた順番を戻ったり進むことができます。

![ver2-dnd.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620936/98d53bce-d554-df5d-9985-ee46f26c097b.gif)


- 感想
実装には少し苦労して、5時間程かかりました。苦労は別記事（[Reactでドラッグ&ドロップ dnd-kitのstrategy関数をカスタマイズした話](https://qiita.com/Oyuhaat/items/864fb1c4128d64c9926b)）にまとめました。詳しくはそちらにまとめましたが、react-beautiful-dndやreact-dnd-kitを使って、公式設定だけで簡単に実装するのは難しそうだったのでreact-dnd-kitの移動量計算関数を自作しました。5時間程度かかりしたが、半分以上は公式設定だけでできないか試行錯誤した時間なので、移動計算を自作することを決めてからは2時間ぐらいで実装できました。

## 戻る・進むボタン
- 概要
  各操作を取り消したり、取り消したものを再実行することができます。以下、アプリの全操作が、戻る・進むができる操作です。戻る操作、進む操作が無い場合はそれぞれグレーアウトされて操作は実行されません。
  - ボタンテキスト変更
  - ボタンカラー変更
  - ドラッグによる配置入替え
  - ボタン選択
  - ランダムボタン追加
  - ボタン複製
  - 背景色変更
  - ボタン削除

![ver2-back-forward.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620936/e41c8853-3625-f495-3356-33ba21ebb96f.gif)


- 感想
実装には7-8時間程かかりました。今回の改修で一番時間がかかりました。ライブラリは使わず、今までの操作履歴をグローバル状態変数として管理し、以下のようにすることで実装できました。
  - 状態変数をスタックのように扱い、戻る用のスタック・進む用のスタックを作る。
  - ユーザが何か新しい処理をしたときは、戻るスタックにその操作が追加され、進むスタックは空にする。
  - 戻るボタンが押された時、戻るスタックの末尾を取り出して逆の処理を実行し、進むスタックに逆の処理を追加
  - 進むボタンが押された時、進むスタックの末尾を取り出して逆の処理を実行し、戻るスタックに逆の処理を追加

各操作の種類化や、種類に応じて逆の操作をするための関数を作ったりとで時間がかかってしまいました。
実はもっと簡単に実装する方法もあったのですが（全ボタンの色やテキストのリストを状態管理する変数を全履歴を保持する状態変数を作る方法）、保存するデータ量の効率が非常に悪くクライアント側のリソースを多く使ってしまうかなと思い、難しいけど効率的である今回の方法にしました。勉強にもなったので良かったです。

## まとめ
今回は、保存&ロード機能、ドラッグ&ドロップによる配置換え機能、戻る&進む機能を付け加えました。エディタによくある機能を実装出来ていい勉強になりました。
このアプリではボタンコンポーネントしか対象としていませんが、色んなコンポーネントのUIを試せて自由配置してデザインもできるようにしたらちょっとしたノーコードデザインエディタ風にできそうな構想もありますね。しかしこのアプリの目的はユーザが付くことが目的では無く、やりたいと思っていたことも試せたので今回の機能追加をもって開発は終えたいと思います。
次はユーザが付くことを目的したサーバーレスWebアプリを作っていきたいと思います。
Layout Parser をWindowsで使う。

# 1. Layout Parser
Layout Parserは、論文や新聞、書籍などのレイアウトを検出して「ここは本文、ここは図表」などを検出する機械学習モデルである。


# 2. Layout Parserのこまったところ
この記事にたどり着いたということは多分、「Windows OSを使っててLayoutParserをinstallできない」という困りごとに直面した人なのではないかと思う。従ってあまり多くは語らない(語れない)が、原因としては「LayoutParserに使われている検出部分のBackboneがDetectron2であり、Detectron2をWindowsOSにinstallするのが大変」ということに尽きると思う。LinuxOSを導入することをいとわなかったり、[公式に書かれているように](https://layout-parser.readthedocs.io/en/latest/notes/installation.html#for-windows-users)Visual Studioを導入して～というやり方ができて解決した、という人ならばもうこの記事は読む必要はないと思う。


# 3. LayoutParserのinstall方法
結局、どんな方法で解決すればよいのか言うと、「Backboneをefficientdetにしたものをinstallする」である。
やり方はシンプルで、pipでinstallする際に
`pip install "layoutparser[effdet]"`
でinstallすればよい。公式には「WindowsでLayoutParserを使いたかったらこれを使ってください」みたいな記載はないため、結構わかりづらい…。[efficientdetを導入しました](https://github.com/Layout-Parser/layout-parser/releases/tag/v0.3.0)、ということやそれの[installのやり方](https://layout-parser.readthedocs.io/en/latest/notes/installation.html#install-the-layoutparser-library)は書いてあるのだが…。

# 3.2 追記。モデルのダウンロード先の設定
このままではモデル読み込みの際にエラーが発生し、モデルがインストールされない。そこで、以下の対処でモデルを読み込めるようにする。
```
https://github.com/facebookresearch/iopath.git --single-branch --branch v0.1.8
```
を実行し、iopathのファイルをcloneする。
その後、iopath/iopath/comman/file_io.py
の中の753行目の
```
filename=path.Split("/")[-1]
```
の部分を
```
filename=parsed_url.path.split("/")[-1]
```
へと変更する。

その後、
```
pip install -e iopath
```
を実行することで準備が完了する。[参考](https://github.com/Layout-Parser/layout-parser/issues/15#issuecomment-819546751)

# 4. 他にやること
あとは基本的にやることは変わらない。モデルを設定して検出をするだけである。
ただ、モデルを設定する際に、Detectron2をbackboneにしていた場合は
```python:test.py
pip install layoutparser as lp
model=lp.Detectron2LayoutModel(~~~
```
と記載していた部分を
```python:test2.py
pip install layoutparser as lp
model=lp.EfficientDetLayoutModel(~~~
```
と記載する必要がある。

# 5.注意
一応注意事項としては、検出性能が、Detectron2をbackboneにした場合と異なることが挙げられる。性能が良くなるか悪くなるかは何とも言及できないが…。
Kaggleなどで利用したいときはどうなるのだろう？有利になるのか不利になるのか…？

# 6.まとめ
ということで、やや「逃げ」のような方法でLayoutParserをWindowsOSにinstallする方法を紹介した。
「どうしてもDetectron2をBackboneにしたい」という人以外の要望は満たせたのではないかと思う。
M1 Macで intel系コンテナをdevcontainer.jsonで起動する

# devcontainer.jsonは便利
開発環境をコンテナ化しているのですが、VSCodeをdevcontainerを使ってより加速してきた感じがあります。
ただ、Applie SiliconのMacはCPUがArm系なのでデフォルトだとArmのイメージを使用します。

# Rosetta2
M1 移行期はいろいろできないこともありましたし、いまではRosetta2を使わないでコンテナを動かせればいいのですが、それでもコンテナのビルド環境によってはプラットフォーム依存になっていることが多いので、どうしてもx86_64を使わないとねということもあります。

# 前提
- Rosetta2を（諦めて）インストールする
- Docker Desktopもインストールする
- VSCode

# devcontainer.json
以下の情報を追加します。
```
"runArgs": ["--platform=linux/amd64"],
```

# 確認方法
VSCodeから開発コンテナーで起動し、Docker DesktopのContainersで`AMD64` の情報が出ていればOKです。
![Containers_-_Docker_Desktop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26274/c3aa2b84-dbb9-a9d6-a692-09d5a6812db6.png)
表示されない場合は、VSCodeで`コンテナーのリビルド`をします。
next14がCloudflareでデプロイできない

## はじめに

Next.js(14)でApp Roterやzero runtime CSSを使用してサイトを作成してる。

## 問題点

Next.jsのプロジェクトをCloudflare Pagesでデプロイしようとした失敗する。

以下のログが出力された

```
➤ YN0000: ┌ Post-resolution validation
➤ YN0028: │ The lockfile would have been modified by this install, which is explicitly forbidden.
➤ YN0000: └ Completed
➤ YN0000: Failed with errors
Error: Exit with error code: 1
    at ChildProcess.<anonymous> (/snapshot/dist/run-build.js)
    at Object.onceWrapper (node:events:652:26)
    at ChildProcess.emit (node:events:537:28)
    at ChildProcess._handle.onexit (node:internal/child_process:291:12)
Failed: build command exited with code: 1
Failed: error occurred while running build command

```

## 解決策

バージョンを指定しない場合はYarn v2(Berry)で実行されてまう。

そのため、Cloudflareの環境変数にYarnのバージョンを1で指定すると問題なくデプロイされた。

![スクリーンショット 2023-11-26 16.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481470/b4d1fcf8-ca1f-6d00-6545-e7000d238c9d.png)


## まとめ

yarn1のyarn.lockファイルをyarn2で`yarn install`すると自動的にyarn2用の形式に書き変わってしまうため、それを防ぐためにデプロイが落ちたのが原因だった。

バージョンを1で固定することで、変更が入らずデプロイできるようになった。
ISUCON12予選参加でインフラ担当をやろうとした話

感想
悔しい
準備したわりに何もできなかった
何故
参考書や過去問の解法を読んで、試験対策をした気になっていたが実戦で問題が解けないのと同じような感覚
何やったっけ
本番何をやっていたかの記憶も朧げ
ログを書いてましたね
ssh の config を書いた
nginx の config を git に反映
github にアップロード出来るようにした
3台編成で git で管理する方法を考えていなかった
1台目で作成した repository を2台目に影響がある部分のみ反映させる方法がわからず
github で本番で organization を使おうとして ssh key の置き場が分からなくなる
準備が足りてなかった、色々やっていたはずなのだが

反省点
環境構築で3時間くらいかかっている→ script で自動化したい
slow query と access log は見方がわかるが fgprof の使い方がわかっていない
みんなで問題点について話し合う時間が取れない
演習ができていない

来年に向けて
出来るところは script でさっと反映できるようにする
git は ssh key と　config file は scp で転送
mysql の　config に git は script
netdata、notify_slack, 
ansible
ROS2 xmlのlauncherで条件分岐をする

# 概要

ROS1でも使われていたxml形式のlauncherは見やすく扱いやすい反面、イマイチどんな時にどう書けば良いのかのドキュメントが不足している印象があります。

本記事では下記の2ケースについて書き方を記します。

- 通常の条件分岐
- 重ね合わせの条件分岐


# 通常の条件分岐

group ifの構文を使って条件分岐が可能です。

```xml
<let name="true_arg" value="true"/>
<let name="eval_str" value="hogefuga"/>

<!-- normal case1 -->
<group if="$(var true_arg)">

<group/>

<!-- normal case2 -->
<group if="$(eval &quot;'$(var eval_str)'=='hogefuga'&quot;)">

<group/>
```

# 多重の条件分岐

ちょっと凝ったlauncherを考えるとANDやORで条件分岐を重ねたいときがあります。（設計として良いかは別問題ですが）

動作確認はROS2 humbleで行いました。

## ANDとORの正解ケース

結論から言うと下記のように書くことで複数条件のAND/ORの条件分岐が可能でした。
3つ以上の要素は未検証です。（誰かやってみてください）

```xml
<let name="true_arg" value="true"/>
<let name="false_arg" value="false"/>

# AND
<group if="$(eval &quot;'$(var false_arg)'=='true' and '$(var true_arg)'=='true'&quot;)"> #ちゃんとFalse
<group/>
# OR
<group if="$(eval &quot;'$(var false_arg)'=='true' or '$(var true_arg)'=='true'&quot;)"> #ちゃんとTrue
<group/>
```

なお、当時のmarkdownのメモ書きなのでコメントなどの文法が無効な点にはご注意ください。


## 意図しない挙動をする書き方例

`True and True` みたいな文をイメージして下記のように書くと意図しない挙動になるのでご注意ください。  
eval quotの中身がPythonの記述として処理されるらしいのですが純Pythonだとそうはならないと思ってるので自分は理由をうまく説明できません。

```xml
#後ろが評価される
  <group if="$(eval &quot;'$(var false_arg)'and'$(var true_arg)'&quot;)"> これはTrue

#前が実行される
  <group if="$(eval &quot;'$(var false_arg)'or'$(var true_arg)'&quot;)"> これはFalse
```

## おまけ（boolではなく0,1の数値の場合）

0,1でフラグ管理すること自体は不可能ではなく、珍しくもないですが重ね合わせ時には見づらいのでやめたほうが良いと感じました。

```xml
  <let name="true_arg" value="1"/>
  <let name="false_arg" value="0"/>

  <group if="$(eval &quot;$(var false_arg)+$(var true_arg)&quot;)"> これは怒られる
  expected one of [true, 1, false, 0] but got '01'内部ではStringになっているみたい。

  <group if="$(eval &quot;$(var false_arg)+$(var true_arg)&quot;)"> これなら平気だが1+1=2になると怒られる

  <group if="$(eval &quot;$(var true_arg)+$(var true_arg)==2&quot;)"> これはANDとして使える

  <group if="$(eval &quot;$(var false_arg)+$(var true_arg)>0&quot;)"> ORはこう書ける
```


# おわりに

他にもROS2のxmlのlauncherでcontainerを設定したりなど、「あまりどこにも書かれていないけど実はできる」みたいな機能が結構あるのでもし知っている人が居たら雑記ぶん投げでも良いので公知にしていってほしいです。
複雑なDeepLinkをJetpackComposeで実装するPart3

# はじめに
今回は、複雑なDeepLinkが来たときやDeepLinkの内容によってホーム画面で出しわけないといけない時の実装を紹介していきます

### 本文
本パートではMainViewで表示するための遷移用ネストナビゲーション部分を実装していきます。
ネストナビゲーションとは従来のNavGraphファイルをKotlinで書いたもので、基盤になるViewやBottomNavigation等のナビゲーションを一括で持っておく場所のことです。
`startDestionation`には最初に表示したいViewのユニークIDを、`route`にはそのNavGraph用のユニークIDを設定します
各種IDはObject等で一箇所にまとめておくと便利です。
```kotlin:NestNavigation
fun NavGraphBuilder.hogeNavGraph(
    navController: NavHostController,
    navigateScreenType: NavigateScreenType
) {
    navigation(startDestination = BottomBarNav.home, route = DeepLinkNav.hogeRoot) {
        homeView(navController, navigateScreenType)
    }
}

fun NavGraphBuilder.fugaNavGraph(
    navController: NavHostController,
    navigateScreenType: NavigateScreenType
) {
    navigation(startDestination = BottomBarNav.home, route = DeepLinkNav.fugaRoot) {
        homeView(navController, navigateScreenType)
    }
}

fun NavGraphBuilder.homeNavGraph(
    navController: NavHostController,
    navigateScreenType: NavigateScreenType
) {
    navigation(startDestination = BottomBarNav.home, route = BottomBarNav.homeRoot) {
        homeView(navController, navigateScreenType)
        settingView(navController)
        exampleView(navController)
    }
}
```
### 最後に
今回は、DeepLinkの遷移部分を紹介してみました
次のパートは下記になります
https://qiita.com/ryuji_sato/items/b2c5c8586190e5b42c3a
どなたかのお役に立てれば幸いです
NAND 演算の基本 (paizaランク D 相当)

https://paiza.jp/works/mondai/logical_operation/logical_operation__basic_step5

今やっているのは論理演算メニューシリーズ。
とりあえず書き方は下のコード通り覚えておけばOKだけど
論理については理解しておいたほうがいいです。
論理と覚えるところは区別しましょう

pythonだと、論理積、論理和、否定、排他的論理和があり、それらをつかって
他の論理も表現します。

```py
A, B = map(int, input().split())
#論理積
print(A and B)
#論理和
print(A or B)
#否定(単項演算）
print(int(not A))
# EOR,XOR演算(排他的論理和）
print(a ^ b)
# NOR演算(否定的論理和）
print(int(not(A or B)))
# NAND演算(否定的論理積）
print(int(not(A and B)))
# XNOR演算(排他的否定的論理和）
print(int(not(A ^ B)))
```
ド・モルガンの法則なんて久しぶりに聞いたわ。
数学の授業以来だな。

>次の命題([Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%89%E3%83%BB%E3%83%A2%E3%83%AB%E3%82%AC%E3%83%B3%E3%81%AE%E6%B3%95%E5%89%87))

>「私の身長は160cm以上であり、かつ私の体重は50kg以上である」
>の否定、すなわち
>
>「「私の身長は160cm以上であり、かつ私の体重は50kg以上である」ではない」
>は、ド・モルガンの法則によれば、次の命題と等しい。
>
>「私の身長は160cm未満である、または私の体重は50kg未満である」

こんな感じにするとわかりやすいなと思う。
なんて数学の授業ではあんなに難しく説明するんだろうか笑
Ubuntu用BIOS設定

### ハマりそうな項目
* Windows「高速スタートアップを有効にする」をオフ
[コントロールパネル]-[ハードウェアとサウンド]-[電源オプション]-[電源ボタンの動作を選択する]-[現在利用可能ではない設定を変更する]
* Windows BitLockerをオフ
* BIOS Secure Bootをオフ
* BIOS General→Boot Sequence→Boot List
* BIOS Intel RST(Rapid Storage Technology) をオフ
* BIOS bios-sata-operation=AHCI
* 時刻のずれ

https://www.abten.net/2017/02/1094/

https://hnakamur.github.io/blog/2018/03/23/ubuntu-17.10-windows10-dual-boot/

https://qiita.com/tomorin123/items/efdbe5bc1e939f6ed3aa

https://qiita.com/ryu136/items/956364a476998988e2d7

https://qiita.com/SekkenOne/items/4ee2db9ff336c9bb5f3c

https://qiita.com/sathoshi-metal/items/72f16f5f7f6a23a3962f

https://qiita.com/peijun/items/8f7958d2bc194183985b

https://qiita.com/Toyo_S_J/items/4001ed0181ed0aec718a

https://digitallife.tokyo/archives/2020/05/dell-g5-15-windows-10-ubuntu-18-04-dual-boot.html

https://takacity.blog.fc2.com/blog-entry-207.html

https://kledgeb.blogspot.com/2018/04/ubuntu-1804-uefi-2-uefipcubuntu-1804.html
ハフマン符号

### 前提
- 符号化
    - 情報を2進数のデジタルデータに変換
    - なるべく少ないビット数が望ましい
        - 処理効率・メモリ効率から


### ハフマン符号化
- データの出現頻度に着目した圧縮方法
- 出現頻度の高いデータに短いビット列を割り当て、出現頻度の低いデータに長いビット列を割り当てる

### アルゴリズム
- 貪欲法
    - コストを小さくするためには、小さい2つをマージしていくことを繰り返す。それを降順に扱えばよい。
    - 頻度の小さいデータをマージすることをくりかえすと、頻度の小さいデータほど２分木の深いところに位置するようになる。
    - 二分木で一段ごとに文字を追加していけばよい。
【Android】WorkManager実装時に使えるテンプレートまとめ

# はじめに
少し前の話ですが、Android12からフォアグラウンドサービスの起動に関する制限が入り、本格的にWorkManagerへの移行を余儀なくされましたね。
公式でも代替策としてWorkManagerの使用を提示していました。
また、現時点で正しく上記に対応できていないと、ForegroundServiceStartNotAllowedExceptionにより見事にクラッシュしてしまう最悪の結果を招くことになります。

今後は特別な理由がない限りWorkManagerを優先して使用すべきだと思いますが、このWorkerの実装はプロジェクトの性質によってはそれなりに使用頻度が多く、毎度実装方法を確認するのも手間なので、今回はコピペで使えるテンプレートを記事としてまとめておこうと思います。

# WorkManager実装テンプレート
テンプレートは一度きりの起動と、繰り返し起動の設定2種とWorker側の基本的な実装をおいておくことにします。

まず、一度きり起動する場合の起動時の設定をテンプレートとして記述します。
```main.kt
// TODO 起動条件を個々に合わせて設定します。
val constraint = Constraints
            .Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

// TODO delayは必要であれば設定します、必要なければ内部で初期値０で定義されているので設定は不要です。
val request = OneTimeWorkRequestBuilder<TestWorker>()
            .setInitialDelay(duration = 10, timeUnit = TimeUnit.MINUTES)
            .addTag(TestWorker::class.java.name)
            .setConstraints(constraint)
            .build()

WorkManager.getInstance(context)
            .enqueueUniqueWork("Test", ExistingWorkPolicy.REPLACE, request)
```

次に繰り返し起動させたい場合の設定になります。

```main.kt
// TODO 起動条件を個々に合わせて設定します。
val constraint = Constraints
            .Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

/**
 * TODO インターバルとフレックスタイムに適切な値を設定します。
 * 最小はそれぞれインターバルが15分、フレックスタイムが5分です。
 * 注意点として、フレックスタイムは任意のパラメータですが、設定しないとインターバル時刻がフレックスタイムとして使用され、
 * 想定した通りの動作にならない可能性があります。
 * Worker自体ピンポイントで動作するというのが難しい性質を持っていますが、なるべく適した時間に処理を行いたい場合は、
 * フレックスタイムに最小時刻を設定してあげれば良いと思います。
 */
val request = PeriodicWorkRequestBuilder<TestWorker>(
            repeatInterval = PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
            repeatIntervalTimeUnit = TimeUnit.MINUTES,
            flexTimeInterval = PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
            flexTimeIntervalUnit = TimeUnit.MINUTES)
            .addTag(TestWorker::class.java.name)
            .setConstraints(constraint)
            .build()

WorkManager.getInstance(context)
            .enqueueUniquePeriodicWork("Test", ExistingPeriodicWorkPolicy.UPDATE, request)
```

最後にWorker側の基本的な実装です。

```TestWorker.kt
class TestWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
    override fun doWork(): Result {
        return Result.success()
    }
}
```

テンプレートは以上です、上記に足りない部分に関しては各プロジェクトに合わせて調整を行うようにしてもらえたらと思います。
また、WorkManagerは少し複雑な仕様の上で動作しているので、上記テンプレートの設定やその他不明点等あれば、以下の公式ドキュメントを参照いただければと思います。

https://developer.android.com/topic/libraries/architecture/workmanager/basics?hl=ja

#　さいごに
少しでも実装時に楽ができるように、テンプレート記事増やしていきたいですね。
Ruby on Rails　配列関係のメソッドを理解する(pluckメソッド)

## 1.なぜこの記事を作ったのか
　学習中に、配列関係のメソッドを使用する機会が増えました。ロジックのインプットのみしかしておらず、理解が怪しい部分があり、検証するなら記事にして見直せる様にしようと思いました。

 ## 2.環境
 - ruby 3.2.2
 - Rails 7.1.2
 ## 3.pluckメソッド(カラムを配列に変換)
 テーブル作成
![fruitsテーブル.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627896/4a0d6239-8a57-c4f6-af7c-e77dffe57cc3.jpeg)

### 1.挙動の確認
```ruby:console
irb(main)> Fruit.pluck(:name)
=> ["apple", "pear", "lemon"]
```
```ruby:console
irb(main)> Fruit.pluck(:color)
=> ["red", "green", "yellow"]
```
指定した引数を配列にしていることが分かった。

### 2.引数を複数指定した場合
```ruby:console
irb(main)> Fruit.pluck(:name, :color)
=> [["apple", "red"], ["pear", "green"], ["lemon", "yellow"]]
```
引数を複数にした場合、二次元配列になっていることが分かった。

### 3.メソッドチェーンの位置に注意
```ruby:console
irb(main):002> Fruit.pluck(:name).limit(2)
(irb):2:in `<main>': undefined method `limit' for ["apple", "pear", "lemon"]:Array (NoMethodError)
```
配列に対して`limit`メソッドを実行してしまい、`NoMethodError`が発生。
`pluck`メソッドは配列を返す為、クエリメソッドとメソッドチェーンする際は後ろに書く必要がある。
クエリメソッドとはDBからデータを取得するメソッド(order, find, where等)。
```ruby:console
irb(main)> Fruit.limit(2).pluck(:name)
=> ["apple", "pear"]
```
前後を逆にすることで上手く読み出す事が出来た。
### 4.SQLの発行について
```ruby:console
irb(main):011> Fruit.pluck(:name)
  Fruit Pluck (0.3ms)  SELECT "fruits"."name" FROM "fruits"
=> ["apple", "pear", "lemon"]
```
`SELECT "fruits"."name" FROM "fruits"`となっており、fruitsテーブルのnameカラムのみを取得する。なのでメモリの無駄使いをすることなく取得出来ていると分かった。
```ruby:console
irb(main):012> Fruit.all.map(&:name)
  Fruit Load (0.4ms)  SELECT "fruits".* FROM "fruits"
=> ["apple", "pear", "lemon"]
```
こちらの場合だと、`SELECT "fruits"."*" FROM "fruits"`となっており、全要素を取得してしまうので「メモリのムダ使い」になってしまう。
Windowsのブルースクリーンの話し

元々Linuxを使っていたユーザーですが、今はwindowsを使っています。
windowsが使いやすいという訳ではないですが、業務用のイラストペイントソフトを使っているから、windowsを主要に使っています。

それで最近悩みなのですが、windowsのブルースクリーンなのですが、これが割りと深刻にとらえているのですが、これを他の人でもそれぐらい深刻に考えている人がいれば幸いです。

Linuxのubuntu時はそんな事無かったような気がするし、ファイルシステムが壊れている時も、コマンドでやっていたような感じがするのですが、windowsの場合だと、そんな事無しで、再起動するので、なんか、やりずらいなと思っている感じです。

この話しを書いたきっかけですが、最近悩みだしているので、安易にパーツの増設とかできないのかなと考えているのですが、何か案がある方は、一緒に考えてくれると助かります。

それでは失礼いたします。
Go：レシーバについて解説（Rubyとの違いも合わせて解説）

# はじめに
レシーバは一般的に利用される関数と違い形式がわかりづらいです。
本記事を読んでいただき、レシーバの理解に役立てていただければ幸いです。

# レシーバとは
レシーバは特定の型に対するメソッドを定義する際に使用されます。
メソッドが操作する主体を指し、メソッドがどの型に属するかを定義します。

# レシーバの書き方
```go
package main

import "fmt"

// 1. 型の定義：
// type ~ structは、Rectangle構造体を定義しています。Rectangleは長方形を表します。
type Rectangle struct {
	Width, Height int
}

// 2. レシーバを持つメソッドの定義：
// Rectangle構造体に対するAreaメソッドを定義しています。これは長方形の面積を計算します。
func (r Rectangle) Area() int {
	return r.Width * r.Height
}

func main() {
    // 3. Rectangle構造体のインスタンスを作成
	rect := Rectangle{Width: 10, Height: 5}
	// 4. メソッドの呼び出し
	fmt.Println("長方形の面積:", rect.Area())
}
```

## 実行結果
```sh
$ go run main.go
長方形の面積: 50
```

## コードの説明
1. 型の定義：
type Rectangle struct { Width, Height int }でRectangleという新しい型を定義しています。Rectangleは長方形を表し、Width（幅）とHeight（高さ）という2つのフィールドを持っています。

1. レシーバを持つメソッドの定義：
func (r Rectangle) Area() int { ... }はRectangle型のメソッドです。ここで(r Rectangle)の部分がレシーバです。Rectangle型のオブジェクトに対して呼び出すことができ、そのオブジェクトのWidthとHeightを使用して面積を計算します。

1. Rectangle構造体のインスタンスを作成：
main関数内でRectangle型のインスタンスrectを作成しています。rectのWidthとHeightはそれぞれ10と5に設定されています。

1. メソッドの呼び出し：
main関数内でRectangle型のインスタンスrectを作成し、rect.Area()を呼び出しています。これにより、Areaメソッドがrectに対して実行され、rectの幅と高さを使用して面積が計算されます。

# レシーバの機能
- レシーバr Rectangleは、AreaメソッドがRectangle型に属することを示しています。このメソッドはRectangle型のインスタンスに対してのみ呼び出すことができます。
- メソッド内でrはそのインスタンス自体を参照し、r.Widthやr.Heightのようにしてインスタンスのフィールドにアクセスします。

# Rubyの場合
Rubyでは、レシーバではなく、クラス(`class`)やインスタンス変数(`@width`,`@height`)を使って同じことを実現します。
```rb
class Rectangle
  attr_accessor :width, :height

  def initialize(width, height)
    @width = width
    @height = height
  end

  def area
    @width * @height
  end
end

r = Rectangle.new(10, 5)
puts "長方形の面積: #{r.area}"
```

# GoとRubyの違い
- Go：
    - 「構造体」というものを使って、データを保持します。そして、その構造体に関連する関数を定義します。
    - Go言語では、クラスベースの言語に見られる複雑さを回避し、よりシンプルで明示的なコード構造を提供します。
- Ruby：
    - 「クラス」というものを使って、データと関数を一緒に定義します。クラスから作られた「オブジェクト」は、そのデータと関数を持っています。
    - Rubyのようなオブジェクト指向言語では、クラスを通じてオブジェクト指向の特徴が表現されます。
ジンドゥーで鍵付きブログができないから、microCMSで近いものを作ってみたい

## 概要

ジンドゥークリエイターでは、パスワード認証のページ（パスワードを知っている人だけが見られるページ）を作れます。
また、ブログを作ることもできます。

ところが、ブログにパスワード認証をかけることはできません。

そこで、パスワード認証をかけたシングルページの中に、microCMSで作ったブログを入れてしまおうと考えました。

## microCMS側の作業

（アカウントの作成手順は省略します）

1. サービスを作成の画面で、一から作成するを選択します。
1. サービス名、サービスIDを決めて、サービスを作成します。
  このとき、【サービスID】をコピーしておいてください。
1. サービスにアクセスしたら、APIを作成します。
  とりあえず、ブログを選びました。
1. しばらく待つと、APIが作成されます。
1. 画面右上に、API設定があると思うので、そこをクリックしてください。
  【エンドポイント】があると思うので、コピーしておいてください。
1. 画面左下に、1個のAPIキーというところがあるので、そこをクリックしてください。
  【APIキー】を、コピーしておいてください。
1. [リンク先（github）のscript.html](https://github.com/thirdcake/microcms-into-jimdo/)をコピーして、【サービスID】などを埋めておいてください。

※ なお、ソースコードからAPIキーは丸見えになります。
絶対に、与える権限はGETのみとしてください。

## ブログのAPIスキーマ

将来、microCMSでブログのAPIの自動作成がなくなってしまうかもしれないので、apiスキーマの設定を以下に残しておきます。

```json
{
    "apiFields": [
        {
            "idValue": "xxxxxxxxxx",
            "fieldId": "title",
            "name": "タイトル",
            "kind": "text",
            "isUnique": false
        },
        {
            "fieldId": "content",
            "name": "内容",
            "kind": "richEditorV2"
        },
        {
            "fieldId": "eyecatch",
            "name": "アイキャッチ",
            "kind": "media"
        },
        {
            "fieldId": "category",
            "name": "カテゴリ",
            "kind": "relation"
        }
    ],
    "customFields": []
}
```

```json
{
    "apiFields": [
        {
            "idValue": "xxxxxxxxxx",
            "fieldId": "name",
            "name": "カテゴリ名",
            "kind": "text",
            "isUnique": false
        }
    ],
    "customFields": []
}
```

## ジンドゥークリエイター側の作業

1. ジンドゥークリエイターで、新しいページを作成してください。
1. 左上の管理メニュー->基本設定->パスワード保護領域と進むと、パスワードが追加できます。
  先ほど作ったページにパスワードを設定してください。
1. 新しく作ったページの編集画面に戻ってください。
1. コンテンツを追加し、その他のコンテンツ&アドオンから、ウィジェット/HTMLを選択してください。
1. HTMLの入力画面が出てきます。
  microCMSの手順で作成したHTMLを入力してください。

## 感想

ジンドゥークリエイターは、ノーコードのwebサイトビルダーの中では珍しく、無料プランでも素のJavaScriptが使えます。
ヘッドレスCMSのような外部サービスと組み合わせて、いろいろなことができそうです。
CloudFormation yaml構文エラー

CloudFromationのyaml作成時に出た構文エラーについてまとめてみました。
## 構文エラー1
```: エラー例1
Property vaildation failure: [Value of property {該当箇所} does not match type {Array}, THe property {/Tags/0/Value} is required, The property {/Tags/1/Key} is required}
```
対処方法：下記のようにSecurityGroupIds部分を修正することで解決しました。
```javascript: コード修正前
    RedshiftServerlessWorkGroup:
      Type: AWS::RedshiftServerless::Workgroup
      Properties:
        SecurityGroupIds: !Ref RedshiftServerlessSecurityGroup
```
```javascript: コード修正後
    RedshiftServerlessWorkGroup:
      Type: AWS::RedshiftServerless::Workgroup
      Properties:
        SecurityGroupIds:
          - !Ref RedshiftServerlessSecurityGroup
```
## 構文エラー2
```: エラー例2
Resource <リソース名> must be in ARN format or "*". (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: XXX; Proxy: null)
```
対処方法：下記のようにResource部分を修正することで解決しました。
```javascript: コード修正前
    RedshiftServerlessPolicy:
      Type: AWS::IAM::ManagedPolicy
      Properties:
        Statement:
          -Effect: Allow
           Action:
           - 省略
           Resource: !Ref RedshiftServerlessBucket
```
```javascript: コード修正後
    RedshiftServerlessPolicy:
        Type: AWS::IAM::ManagedPolicy
        Properties:
          Statement:
          -Effect: Allow
           Action:
           - 省略
           Resource: !GetAtt RedshiftServerlessBucket.Arn
```
## 構文エラー3
```: エラー例3
Properties validation failed for resource <論理名> with message: #/IamRoles: expected type: JSONArray, found: String
```
対処方法：下記のようにIamRoles部分を修正することで解決しました。
```javascript: コード修正前
    RedshiftServerlessNamespace:
      Type: AWS::RedshiftServerless::Namespace
      Properties:
        IamRoles: !GetAtt RedshiftServerlessRole.Arn
```
```javascript: コード修正後
    RedshiftServerlessNamespace:
      Type: AWS::RedshiftServerless::Namespace
      Properties:
        IamRoles:
          - !GetAtt RedshiftServerlessRole.Arn
```
## 最後に
上記のような構文エラーが出た際は、公式ドキュメントを参照したり、エラー文を検索することで解決できることが多いかと思います。
どなたかのお役に立てれば幸いです。
PHP ファイルの内容をブラウザに表示し、意図的に文字化けさせたい場合

# PHP ファイルをあえて文字化けさせたかったのだが・・・
* PHP ファイルの文字コード：UTF-8
* PHP ファイル内の `<head>` の charset：Shift_JIS

上の条件で、PHP ファイルを表示して文字化けを起こそうとした。しかし、結果は **文字化けせず**。「？」となったが、**原因は単純だった**。

![article4-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601609/6379344d-9326-d514-90e8-57252e82752a.png)

### ブラウザの表示
![article4-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601609/03e62ce4-fcf9-346d-21e8-8972c3eae71f.png)

### 使用環境
Windows + Apache + PHP
ブラウザ：Google Chrome

# 文字化けしなかった原因
ブラウザで、PHP ファイルを表示した時の **「php.ini」 の `default_charset` の設定値が、UTF-8 になっていたため**。

![article4-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601609/86a1f45f-cd14-ef87-e916-5d00a0e83f8b.png)

ついでに、この時の HTTP レスポンスの Content-Type に指定されている charset を見てみたら、**UTF-8** になっていた。つまり・・・
* **PHP ファイルの文字コード：UTF-8**
* **「php.ini」の `default_charset`：UTF-8**
で文字コードが一致していたために、文字化けが起きなかったのだ。

# 結局、文字化けさせるには・・・
「php.ini」の `default_charset` の設定値を **UTF-8 以外** の文字コードにする。（今回は、**Shift_JIS** にした）

![article4-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601609/357d24dc-bba7-349b-9b90-041f5f3803c7.png)

![article4-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3601609/08a71c8a-ba00-4321-1f48-db78c6f255f9.png)

【2023年12月2日 追加】
ただし、提示した **「php.ini」を書き換える方法は、全てのPHP ファイルに影響を与えてしまう** とのコメントをいただいた。**まったくそのとおりだ**。開発環境を他人と共有している場合は、迷惑を掛けてしまうことになる。
* [該当コメント](https://qiita.com/bpg_ts/items/ea8ef7d58863dd602bb1#comment-4ea9100b088c505a3e54 "該当コメント")

よって、「php.ini」の書き換えで対応するよりは、該当コメントのとおり、**文字化けさせたいPHP ファイルの文頭に `ini_set()` を追加する方法の方が良い**。ちなみに、この関数の有効期間は、PHP マニュアルには以下のとおり。
> スクリプトの実行中は新しい値を保持し、 スクリプト終了時に元の値へ戻されます。

# まとめ
* 文字化けさせたい場合は、「php.ini」の書き換えで可能。ただし上で書いたとおり、本記事では、**文字化けさせたいPHP ファイルの文頭に `ini_set()` を追加する方法がベスト** との結論とした。逆に、**文字化けを解消したい場合にも応用可能**。
* **PHP ファイル内の `<head>` の charset の変更では文字化けをあえて起こすことはできず**、「php.ini」の `default_charset` の設定値が優先されていることがわかる。
VCI開発するときのお役立ちtips Unity編-その１

この記事はVCIアドベントカレンダー2023 １日目の記事です。

VCIを開発していると、だんだんたくさんのオブジェクトを使うようになってきたりします。いじるものが少ないうちはいいのです。でもそのうち初心者を卒業して、なまじできることが増えてくる **中級者になってくると** 管理すべきパラメーターが膨大になってきて **作業が煩雑になってきてしまいます**。今回はそういう **めんどくさい状況を少しでも楽にする**趣旨で３回くらいの続きで記事にしようと思います。（本当は１回にしようとしたら多くなったので...）

# Unity
### 連番
オブジェクトをコピーすることが多くあると思います。VCIでは一つでも同じ名前のオブジェクトがあると不具合のものになりますが、unityはオブジェクトのコピーの際に自動的に名前を変えてくれます。デフォルトでは"object"というオブジェクトをコピーすると"object (1)"という表記になります。ですが、これは少し気持ち悪いと感じる方もいらっしゃるかと思います。スペースが入っていたり、かっこが入っているのがスクリプトを組むうえで面倒を起こしかねませんし、単純に長ったらしいです。

そこで、Edit>project settingsを開いて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/bfc38e4b-cc8b-4a39-2385-b053549c73fd.png)

Editorタブの下のほうに、"Numbering Scheme"のところに"Game Object Naming"の欄に"Prefab (1)"と書かれています。これを変更することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/efe96ade-7836-a6a2-396d-fee7bfe57f8b.png)

"Prefab.1"と"Prefab_1"が選べますが個人的にアンダースコアのほうが好き（システム文字と重なる懸念が少ない）ので今回はこちらにしておきます。
これで次回からは自動的に連番がobject_1,object_2...という風になっていきます。

すぐ下の"Game Object Digits"で桁数を変えることができます。これを2にするとobject_01,object_02...という風になります。こうしておいたほうが何かと便利なこともありますので、必要ならいじってみましょう。
※以上は、unity2022からの機能です。

### まとめて数値の記入
game objectが増えてくると、管理が大変ですよね。たくさんあるオブジェクトを平行移動したくなったり..unityではオブジェクトをまとめて変更できる機能があるので活用していきましょう。
使い方は簡単、以下のように複数選択するだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/3a926bff-aab7-12c6-efa0-7e53685bffcd.png)

すると、共通するコンポーネントに入れる数字はいっぺんに入力することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494837/173cde3f-c2f1-4b13-503c-512d6c5135b1.png)
ここに数字を入れるだけです（もともと共通の値が入っていないところはーで表示されます）。出現位置が低すぎるときに上にあげたりなどでよく使います。
Transform以外でもできちゃいます。rigidbodyなどはもちろん、subitemなどのVCI固有のコンポーネントも可です。これでIsKinematic切り忘れやGravity切り忘れなどの初歩ミスを防ぎやすくなります

以上は結構基本になるので覚えておいて損はないと思います。
そんな基本を使ったさらに便利な内容は..その２につづく..?
自作レジアプリを作りやした。

# はじめに
s科の人です。第58回工嶺祭の屋台で使用した自作レジアプリを紹介したいと思います。

# 作ったやつ

## 仕様
・個数を入力して金額を計算する
・クーポン機能（３個以上で利用できる。１人用につき、１個無料で追加）
・預り金を入力しておつりを計算する
・キーパッドのみで動作(変更可）
・履歴保存
・価格変更
![スクリーンショット (62).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/04b1a831-167b-8010-db51-dae26cc66992.png)
![スクリーンショット (64).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/3904ae89-3f03-2a6f-0478-398d7959db8d.png)

## 動作
個数、預り金を入力しておつりを計算
おつりを渡して取引終了キー
![スクリーンショット (67).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/370f80be-4420-3ce3-29c1-9968ad023d68.png)


ポップアップが表示され、確認キーを押して次の会計へ
![スクリーンショット (63).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/16e5ae26-0744-c151-8fcc-568b79d1fee5.png)

### アピールポイント
クーポン利用のため、注文個数と提供個数を分割
現入力場所を強調表示
確認ポップアップ

キーパッドのみで入力できる
キーコンフィグ機能
![スクリーンショット (66).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/e0729605-2430-8c06-397e-4deadc51f439.png)

会計履歴の保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628760/2fdab7cc-d62e-8045-33d4-fa7a7e422a43.png)

キーコンフィグ、会計番号を保存　アプリを開きなおしても続きからできます。

# 使ってみて
当日は屋台が大盛況でめちゃくちゃ並んでたけど、レジシステムのおかげで会計で詰まっている様子はなかったので大成功でした。

かなり活躍してたと思います。

ただ、普通にプログラムをミスって270会計前後(多分）で落ちていたのはここだけの話。
原因は型の記述ミスでした。アプリを立ち上げなおしても会計番号とか、引き継いで開始できるようにcsvファイルに保存してたのですが、その型をint32のところ、uint8で書いてました。(siv3dで書いてます。）
最悪です。こんなうんこミスを…

# 終わりに
今回開発するにあたって、ファイル分けとか、自作クラスとか、キーコンフィグとか、初めてやってみて結構技術力が上がったきがしてよかったです。
文化祭ではタブレットを貸してくれる人がいなかったので、pcを使ってやっていました。
ｊ科はタブレットを充電しながら、ポップコーンの熱気の中で使ってたのでトラブルがあったようです。なのでまあ正解だったようです。

ですが、なんかパソコンでレジとかダサい気がしたので、タブレットでもできるように新しくunityで開発中です。googleストアとかで公開してみたいなと思います。あとappストア。
unityって数クリックでandroidもiosも書き出しできていいですよね。

##  終わりの終わりに
開発中って書きましたが、ストップなうです。POSレジとか業務用じゃない、文化祭とかバザーとかで使う簡単なレジアプリがなかったので作り始めてましたが、見つけちゃいました。
超完成度高くて、完全に上位互換です。ガン萎えです。
レビュー〜リリース期間半減！大きな過ちは早く潰せ！

「[人数半減の中で総開発量UPを実現させた秘訣 by エイチームコマーステック Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ateam-commerce-tech)」の4記事目(8日目)は村林がお送りします。よろしくお願い致します！

私たちのチームでは、常に開発後にメンバー間でコードなどのレビューを行っています。問題がなければそのままリリースを行いますし、問題があれば解決されるまで、修正、レビューを繰り返します。
今日から2日間に分けて施策リリースまでの1つの重要な工程である「レビュー期間」の短縮というテーマで書かせていただきます！レビュー期間が延びがちという方はぜひ読んでいただければと思います！よろしくお願い致します！

## なぜレビュー工程を効率化したのか・効率化してどうなったか

ここから2記事にわたってレビューについての記事を書いていきますが、本題に入る前に「なぜレビューの効率化を重点的に行ったか」について多少触れておきたいと思います。

重点的に効率化を行った理由を一言で言えば「レビュー工程が最も非効率だったから。」に尽きます。ソースコードが完成したと思ってから、レビューを出し、リリース準備完了までの期間は、大きな改修でなくとも1週間以上かかることが良くありました。また時間がかかるだけではなく、レビュー・修正にかかる期間が全く読めないという問題もありました。レビュー・修正にかかる時間を読み誤ると、次の施策のスケジュールにまで影響を与えスケジュール調整に時間を要するということも多く経験してきました。
レビュー期間の短縮に力を入れたことにより、昔は1週間以上かかっていたレビューも今では感覚値ですが2営業日程度で完了させることができ、リリース遅延も減少したことによりスケジュール調整工数も大きく抑えることができました。

## レビューの大敵！設計変更

なぜレビュー工程に大きく時間がかかっていたのか？その原因の一つに「設計変更等、大きな変更をレビュー工程で指示せざるを得なかったから」があります。
「もうすぐリリースできる！」と開発者が思っていても、実際にレビューに出したら「このライブラリはあんまり使用するべきではないですね。。。ライブラリの選定を変えてください！」と言われれば、修正・再レビューに時間を要するのは容易に想像できるかと思います。単なるコードの変更ではなく、設計の変更、技術選定の変更、仕様の変更をこのコードレビューで要求していたことがレビュー期間に時間を要していた原因の一つです。

## 最終段階から設計段階に戻らないために

このような問題は、開発に着手する前に設計など大枠の開発方針を各メンバー相談し合意をとっておくことで解消することが可能です。ということは、多くの方が理解できる基本的なことかと思いますが、なぜ当時はやれなかったのでしょうか？その理由は下記のようなことがあったかと思います。

- 相談すべき相手が忙しいかもしれないと思って相談できずにいる
- 誰にどのような方法で相談すればよいのかがわからない
- メンバー全員に相談する機会が少なく、待っていると開発スケジュールが遅れてしまう
- 相談が必要なこと(ほかの人が別意見を持っていること)だと気づけない
- などなど

[2記事目](https://qiita.com/kazzzzzz/items/492623648d8dc85a9711)で触れた朝会を手厚くしたことによって、毎日のように自分が担当の施策の実装方針の相談ができる機会が生まれたり、[タスクボードによって他のエンジニアが何をやっているかの透明性が増した](https://qiita.com/kazzzzzz/items/492623648d8dc85a9711)ことによって、「躓きそうだから先に設計方針を聞いておこう」等レビュアーが先回りすることが可能になりました。
もちろん、「大枠の開発方針の事前合意をとっておいた方がよい」という共通認識があることが大前提になりますが、コミュニケーションの見直しがこれらの改善に大きく寄与しました。詳細はぜひそちらの記事をご覧いただければと思いますが、まとめると下記のようなことが貢献したかと思います。

- 誰もが気軽に相談ができる機会を毎日作った
- 他メンバーのタスクの見える化によって、周りのメンバーがフォローできる体制を作った

## 事前合意をとるべき対象は何か？

「開発着手前に大枠の合意をとるべき」という話を今までしてきましたが、大枠とは何でしょうか？1～100まですべて合意をとるとそれはもはやコードレビューと変わらないですし、少なすぎてもレビュー段階でひっくり返りで戻りが大きくなることになります。

大枠の定義はチームとして正解がこれだ！というものを定義したわけではないですし、厳密なルールとして運用しているわけではありませんが、一つの目安として我々のチームでよく議論の対象となっているものを例示させていただいています。

- 要件の問題点と回避策
- DBのスキーマ構造
- フロントエンド/バックエンドの役割分担
- APIのI/F
- 使用ライブラリ
- その他プログラム全体にかかわる意思決定

## 最後に

これらのコミュニケーションの工夫によってレビューの時間が大幅削減できました。大きな手戻りを発生させないのが、効率的なレビューを行う上での第一歩になりました。
「最終段階のレビューで何とかする」という流れを是正し、「レビューは設計に関するレビューなら開発前のフェーズに行うなど、フェーズごとに細かな単位で実施する」という流れにもっていくことで、大きく効率化を達成しました。

今回の記事では出戻りが大きな指摘をどう回避するか？という話を記載しました。次回記事では細かな粒度の話について書いていきます！もしご興味がありましたら次回記事もご購読いただければと思います！よろしくお願い致します！
【Unity】iOS ビルド時に Command PhaseScriptExecution failed with a nonzero exit code となってしまう。

# 環境

Unity 2023.1.10f1
Xcode 15.0.1


# 問題

iOS ビルド時に以下のエラーが出る
```text
Command PhaseScriptExecution failed with a nonzero exit code
```

# 対処法

Unity を~~最新版に~~アップデートする

👇
~~Unity 2023.2.1f1~~

~~Unity 2023.1.20f1~~

👍👍👍 Unity 2023.1.15f1 👍👍👍

以下をやるなら、`Unity 2023.2.1f1`　でも良いかも。

https://qiita.com/kaedeee/items/38d6b66a2dc4f784a73c
【Rails】APIのコントローラでparamsを受け取る方法

## 実装

```ruby: /app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  before_action :set_params

  def set_params
    params = {}
    request.query_parameters.each do |key, value|
     params[key] = value.to_s
    end
    @params = params
  end
end
```

## 解説
### [10.1requestオブジェクト](https://guides.rubyonrails.org/action_controller_overview.html#the-request-object)
以下、日本語訳＆要約

> ・リクエスト オブジェクトには、クライアントから受信したリクエストに関する多くの有用な情報が含まれています。
・このオブジェクトでアクセスできるプロパティには次のようなものがあります。

| パラメータ         | 説明                                                   |
| ------------------ | ------------------------------------------------------ |
| host               | このリクエストに使用されるホスト名。                    |
| domain(n=2)        | n右から始まるホスト名の最初のセグメント (TLD)。         |
| format             | クライアントによって要求されたコンテンツ タイプ。       |
| method             | リクエストに使用される HTTP メソッド。                  |
| get? / post? / patch? / put? / delete? / head? | HTTP メソッドが GET/POST/PATCH/PUT/DELETE/HEAD の場合は true を返します。 |
| headers            | リクエストに関連付けられたヘッダーを含むハッシュ。     |
| port               | リクエストに使用されるポート番号 (整数)。              |
| protocol           | 使用されるプロトコルに「://」を加えた文字列 (例: 「http://」)。 |
| query_string       | URL のクエリ文字列部分、つまり「?」以降のすべて。       |
| remote_ip          | クライアントの IP アドレス。                           |
| url                | リクエストに使用される URL 全体。                      |



### [10.1.1 path_parameters、query_parametersおよびrequest_parameters](https://guides.rubyonrails.org/action_controller_overview.html#path-parameters-query-parameters-and-request-parameters)

以下、日本語訳＆要約

> ・リクエストオブジェクトは、リクエストとともに送信されたすべてのパラメーターをハッシュで収集する。（クエリ文字列か、POST本文として送信されたかは関係ない）
・リクエストオブジェクトは、3つのアクセサーがある。
・query_parametersには、クエリ文字列の一部として送信されたパラメータが含まれている。
・request_parametersには、投稿本文の一部として送信されたパラメータが含まれている。
・path_parametersには、この特定のコントローラーとアクションにつながるパスの一部としてルーティングによって認識されたパラメーターが含まれている。

→ requestオブジェクトのquery_parametersメソッドでアクセスできる。
XBUSServoをESP32やTeensyで使う

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) Serial2などを使えるようにライブラリを雑改造

## やること

https://qiita.com/Ninagawa123/items/6e5be1db678e7556ad79

の続きです。

JR PROPOブランドのXBUSServoをシリアルコマンドで動かしますが、ESP32などのSerial1,Serial2などで使えるようにします。

## 作業環境
* Arduino UNO
* Arduino IDE
* ESP32DevkitC

## ライブラリの導入
今回は**ESP32などのSerial2などでも使える様にしたバージョン**をテスト用としてGithubにアップしておきました。
XBUSServo**EX** とライブラリ名を変更しました。

https://github.com/Ninagawa123/XBusServoEx

から、[前回の要領](https://qiita.com/Ninagawa123/items/6e5be1db678e7556ad79)でライブラリをインポートしてください。


#### ESP32との接続

|サーボ線|機能|ESP32|
|-|:-:|-|
|外側の黒線|GND|GNDピン|
|中央の黒線|Vcc|5Vピン|
|外側の白線|信号線|17番ピン(Serial2)|

今回はハードウェアシリアルとサーボシリアルは別系統になります。
サーボを接続したままでも書き込みはできるはずですが、サーボが暴れる可能性があるので書き込み時はサーボの電源を抜いておくと安心です。

# サンプルコード
メニューから「ファイル」→「スケッチ例」→「XBusServoEX」→「ESP32_demo」

```c++:ESP32_demo.ino
#include <XBusServoEx.h>

#define  kMaxServoNum    1       // XBusサーボの接続数 : 1 - 50
#define  kDirPinNum      -1      // 送受信切り替えピンの番号. -1 で送信のみ.

XBusServoEx      myXBusServo(kDirPinNum, kMaxServoNum); // ライブラリのインスタンス化
unsigned int   servoValue = 32767;// サーボ位置の値. 0x7FFF がXBusServoのサーボ位置の中央値
float radiansval = 0.0; // サインカーブ算出用のラジアン値
float radiansIncrement = 0.03; // ループ毎のラジアン値の増加量

void setup()
{
  myXBusServo.begin2();
  myXBusServo.addServo(0x01, kXbusServoNeutral);    // 最初のサーボID. 今回は1番(0x01)のみ. 
}

void sendPacket()
{
  myXBusServo.sendChannelDataPacket2();
}


void loop()
{
  // サインカーブ用の値を算出
  radiansval += radiansIncrement;  //ラジアン値を増加
  radiansval = (radiansval > 2 * PI) ? 0 : radiansval; //ラジアン値が2πを超えたら0にリセット

  // サーボの値をセットする
  servoValue = 32767 + int(sin(radiansval) * 30426); // サーボ位置の上限下限の許容範囲でサイン揺動させる
  myXBusServo.setServo(1, servoValue); //サーボ値をセットする
  myXBusServo.sendChannelDataPacket2(); //データを送信する
  delay(10); //10ミリ秒ディレイ. 14ミリ秒以下の必要がある.
}
```

# 起動と動作結果
1秒間隔ぐらいでサーボが加減速しながら左右に回転すれば実験成功です。

# Teensy4.0では？
Teensy4.0でもSerial5まで使えることが確認できました。（送信のみですが）

# さいごに

コマンドを使ってデータをとったりいろいろ試してみたいと思います。
複数のサーボを使った時にうまく動くかもテストが必要です。

よき電子工作ライフを〜
FlutterでFreezedを使ってみる

こんにちは。
今日はFlutterにて不変クラスを作成するツール「Freezed」についてまとめたいと思います。

まず「不変」って何?ってところからだったんですが、
Flutterでは一度作ったインスタンス（オブジェクト）のプロパティやフィールドが変更されることがないことを指しています。

そうすることで予期せぬ状態になることを防ぐことが出来ます。
仮にオブジェクトの状態を変更する必要がある場合は、新しいインスタンスを作成してその状態を変更します。

そしてFreezedはそんな不変クラスを簡単に作ることのできるDartのパッケージです。
後述するような規則に沿ったコード（設計書）を書き、コマンドを叩くことで、Freezedが不変クラス（プロパティやメソッド込み）を作ってくれます。

Freezedで実際に定義する際のコードが下記になります。
```
@freezed
class User with _$User {
  const factory User({
    required String name,
    required int age,
  }) = _User;
}

```

この定義ではUserクラスをfreezedで自動生成される_$Userクラスをミックスインしています。
要はUserクラスに自動生成される関数とかを取り込むよって書いてます。

ミックスインはDartのような単一継承しかできないプログラミング言語において、様々なクラスを取り込みたい時に使うキーワードでwithを用いることがその宣言になります。

そして次はfactoryですね。
こちらはファクトリコンストラクタといい、コンストラクタの一種なのですが、
オブジェクトの生成をより柔軟にすることができるツールです。
例えば条件に合う場合はAを返し、合わない場合はオブジェクトを作って返す、みたいなことが出来ます。

今回の場合は必須プロパティとしてnameとageを受け取り、_Userオブジェクトを返しています。
なぜファクトリになっているかというと、実際のインスタンス生成はFreezedで自動生成されるソースコードの方で行うからです。

では実際に定義したUserクラスでコードを自動生成してみます。
```
$ flutter pub run build_runner build
```
生成されたコードがとても長いので割愛します。

状態に関するメソッドとして
whenとmapが登場していたのでそちらをまとめますと、

whenはインスタンスのプロパティにアクセスしたいときに使います。
例えば、

```
user.when(
  loading: () => 'ロード中',
  data: (name, age) => '名前: $name, 年齢: $age',
  error: (message) => 'エラー: $message',
);
```
みたいな感じです。

そしてmapはインスタンス自体にアクセスしたい時に使います。

```
user.map(
  loading: (loadingState) => 'ロード中',
  data: (dataState) => '名前: ${dataState.name}, 年齢: ${dataState.age}', 
  error: (errorState) => 'エラー: ${errorState.message}',
);
```

以上、Freezedを使っての不変クラス作成とメソッドのまとめでした。
【Flutter】ツリー構造

# 初期コード main.dart のツリー構造を整理
```mermaid
graph TB
  Start(MyApp : StatelessWidget)-->B(MaterialApp : アプリケーション全体を管理する)
  B-->C(MyHomePage : StatefulWidget)
  C-->D(Scaffold : 画面全体を構成する)
  D-->E1(AppBar)
  D-->E2(Center)
  D-->E3(floatingActionButton)
  E1-->E1F(Text)
  E2-->E2F(Column)
  E2F-->E2FG1(Text)
  E2F-->E2FG2(Text)
  E3-->E3F(Icon)
```
初期コードで返すのは`MaterialApp`か`Scafford`だが、他にiOSに特化したWidgetもある。
`MaterialApp`と`Scafford`はMaterialデザイン用のウィジェット。
## Scaffoldで管理できるUI部品
- AppBar
    - 画面上部に表示するヘッダーのような部分。タイトルやアイコンなどを表示できる。
- BottomNavigationBar
    - 画面の下部に表示するフッターのような部分。ボタンが配置されたりする。
- Drawer
    - ドロワーメニュー。左か右側から表示できるメニュー。
- BottomSheet
    - 画面下部から表示できる領域。スワイプで引っ張り出せる。
- SnackBar
    - ユーザーが行った（もしくは行う予定の）動作に直接関係する通知
      - ユーザーが行った動作に関連しないもの（システムからのお知らせや通知）を表示する場合は`Fluttertoast`が使える
- FloatingActionButton
    - デフォルトでは右下に配置されているボタン。複数配置することも、位置を変えることもできる。
# 参考
- [【Mermaidの紹介】Qiitaでダイアグラム・チャートが簡単に書けるようになりました！ | Qiita](https://qiita.com/Qiita/items/c07f3262d8f3b25f06c9)
- [FlutterのUIウィジェットを理解するための基本を知ろう！](https://codezine.jp/article/detail/13329)
- [snackbarとtoastの違いまとめ | note](https://note.com/dreamarts_design/n/na830aedec855)
- [fluttertoast | pub.dev](https://pub.dev/packages/fluttertoast)
- []()
[JavaScript]イベント処理 初心者

# 1. はじめに

本記事では、JavaScriptのイベント処理についてをまとめていきます。

JavaScriptのイベント処理には3種類の書き方があります。それぞれの特徴を整理し、どのような場面でどのような記述方法を用いることが適切かを判断できるようになれればと思います。

# 2. イベント処理の種類

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello</title>
    <style>
      button {
        margin: 10px;
      }
    </style>
  </head>
  <body>
    <button>click</button>
    <script>
      /* JavaScript 記載箇所 */
    </script>
  </body>
</html>
```

上記のHTMLファイルを例として説明していきます。

実現したい処理としては、`<button>click</button>`をクリックすることで「Hello」と画面に表示させたいです。

## 2-1. イベントハンドラープロパティ

```jsx
const btn = document.querySelector("button");

btn.onclick = () => {
	alert('Hello');
}
```

１つ目は、イベントハンドラープロパティを使用する方法です。イベントハンドラープロパティとは、上記のコードでいうonclickのことです。

要素オブジェクト(btn)のプロバティ(onclickプロパティ)に、処理内容を代入することでイベント処理を実現しています。

この記述方法は、ブラウザ間の互換性が高く、IE8でも動かすことができます。しかし、各イベントに対して1つの関数しか割り当てることができないという弱みがあり、複数の関数を処理させたい場合には不向きです。

## 2-2. イベントリスナー

```jsx
const btn = document.querySelector("button");

btn.addEventListener("click", () => {
    alert('Hello');
});
```

２つ目は、イベントリスナーを使用する方法です。具体的には、要素オブジェクトのaddEventListener()関数を使用します。

addEventListener関数は、addEventListener(イベントの種類, 処理内容, イベントの伝播方法)というように記述することができます。

今回の場合だと、第１引数にclick、第２引数に「Hello」と表示させる処理を記載することでイベント処理を実現しています。
※第３引数は特別なことがない限り、false or 省略で問題ございません。

この記述方法は、イベントハンドラープロパティとは異なり、各イベントに複数の関数を処理させることが可能なため、より柔軟な処理を可能にします。しかし、IE9以降でのサポートとなるため、動作環境を意識する必要がございます。

## 2-3. インラインイベントハンドラー

```html
/* buttonタグにonclick属性を追記 */
<button onclick="alertHello()">click</button>
```

```jsx
function alertHello() {
  alert('Hello');
}
```

３つ目は、インラインイベントハンドラーを使用する方法です。インラインイベントハンドラーとは、上記のコードで言うHTMLに記載したonclick属性のことです。属性値として処理内容を記載することで、イベント処理を実現しています。

HTMLとJavaScriptが混在しているため、この記述方法は推奨されていません。上記コードのような単純なプログラムであれば問題ございませんが、大規模な開発となった場合、管理が大変となり保守性が欠けてしまします。

# 3. まとめ

基本的にはイベントリスナーを使用し、環境に合わせてイベントハンドラプロパティに変更するという記述方法が良いと感じました。

イベントリスナーには、addEventListener関数に加え
removeEventListener関数もあるため、非常に拡張性があると言えるでしょう。

# 4. 参考文献
- [mdn web docs 「イベントへの入門」](https://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Events)
- [【JavaScript】3種類のイベント処理の書き方(利点と欠点)](https://ict-skillup.com/javascript/1402/#google_vignette)
AWS lambdaの新機能

AWSのLambdaでロギングについて新機能が追加されました！

>AWS Lambda では、JSON 構造化形式でネイティブにログをキャプチャし、ログレベルを調整し、Lambda 関数用の Amazon CloudWatch ロググループを選択できる高度なロギングコントロールを発表しました。
(公式サイトより引用)

# 変更内容
+ JSON形式でLambdaログを取得
+ ログレベルの制御
+ CloudWatchのロググループを選択

# JSON形式でLambdaログを取得
LambdaのログをJSON形式で管理できるようになったため、keyとvalueの値からログの検索がしやすくなりました。
また、Kibanaなどのダッシュボードで分析しやすくなりました。

# ログレベルの制御
ログレベルを変えるにはソースコードを変更する必要がありましたが、Lambdaの新機能でログレベル（INFO、WARNING、ERRORなど）を調整できるようになりました。
これによりデバッグがしやすくなりました。

# CloudWatchのロググループを選択
Lambdaがログを送るCloudWatchのロググループを選択できるようになりました。アプリケーション内の複数のLambdaからのログを一箇所や業務レベルで管理できるようになりました。
ログをまとめて管理することでセキュリティ監視や不正アクセスの追跡が容易になります。

# おわりに
公式からの発表は下記よりご覧ください

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/aws-lambda-controls-search-filter-aggregate-lambda-function-logs/
ABC330 参加記(ABCD)


AtCoder Beginner Contest 330に参加しました。

https://atcoder.jp/contests/abc330

https://atcoder.jp/users/x__0/history/share/abc330

ABCD四完です。椅子はあったまりました。

# A - Counting Passes

https://atcoder.jp/contests/abc330/tasks/abc330_a

やるだけ。普通に全探索

```cpp:abc330_a.cpp
#include<bits/stdc++.h>
using namespace std;

int main(){
	int N, L;
	cin >> N >> L;

	int ans = 0;
	for (int i = 0; i < N; i++)
	{
		int A;
		cin >> A;

		if(A >= L)
			ans++;
	}

	cout << ans << endl;

	return 0;
}
```

https://atcoder.jp/contests/abc330/submissions/47889477

# B - Minimize Abs 1

https://atcoder.jp/contests/abc330/tasks/abc330_b

複雑そうに見えるけど、$L \leq A_i \leq R$ なら $A_i$ 、 $A_i < L$ なら $L$ 、いずれでもないなら $R$が答え。

```cpp:abc330_b.cpp
#include<bits/stdc++.h>
using namespace std;

int main(){
	int N, L, R;
	cin >> N >> L >> R;

	vector<int> X(N);
	for (int i = 0; i < N; ++i)
	{
		int A;
		cin >> A;

		if(L <= A && R >= A){
			X[i] = A;
		}else if(A<L){
			X[i] = L;
		}else{
			X[i] = R;
		}
	}

	for(int i = 0; i < N; ++i){
		cout << X[i] << (i != N - 1 ? " " : "\n");
	}

	return 0;
}
```

https://atcoder.jp/contests/abc330/submissions/47897695

# C - Minimize Abs 2

まず $x$ は $x^2 \leq D$ の範囲で全探索して、 $y$ は $\sqrt {D - x^2}$ の切り捨てと切り上げで最小値を探せばいい。

$\sqrt {D - x^2}$ と $\log_2 {D-x^2}$ 間違えて時間ロスした

ちなみに、`uint64_t`でやってるから複雑になってるけど、普通に`int64_t`でいけました

```cpp:abc330_c.cpp
#include<bits/stdc++.h>
using namespace std;

template<typename T>
void chmin(T &a, T b){
	if(a > b){
		a = b;
	}
}

uint64_t solve(uint64_t a, uint64_t b){
	if(a > b)
		return a - b;
	else
		return b - a;
}

int main(){
	uint64_t D;
	cin >> D;

	uint64_t ans = UINT64_MAX;
	for (uint64_t i = 0; i * i <= D;++i){
		auto tmp = floor(sqrt(D - i * i));

		chmin(ans, solve(D, i * i + tmp * tmp));
		chmin(ans, solve(D, i * i + (tmp + 1) * (tmp + 1)));
	}

	cout << ans << endl;

	return 0;
}
```

https://atcoder.jp/contests/abc330/submissions/47913495

# D - Counting Ls

$i$ 列目と $j$ 行目に何個`o`が含まれているかを管理して、

列の個数を $A_i$ 、行の個数を $B_i$ として、
二重ループで $S_{ij}$ が`o`なら $(A_i-1) \times (B_i-1)$ を随時答えに足していく

```cpp:abc330_d.cpp
#include<bits/stdc++.h>
using namespace std;

int main(){
	int N;
	cin >> N;

	vector<string> S(N);
	for(int i = 0; i < N; ++i){
		cin >> S[i];
	}

	vector<int> A(N,0), B(N,0);
	for (int i = 0; i < N; ++i){
		for(int j = 0; j < N; ++j){
			if(S[i][j] == 'o'){
				A[i]++;
				B[j]++;
			}
		}
	}

	int64_t ans = 0;
	for (int i = 0; i < N; ++i)
	{
		for(int j = 0; j < N; ++j){
			if(S[i][j] == 'o'){
				ans += (A[i] - 1) * (B[j] - 1);
			}
		}
	}

	cout << ans << endl;

	return 0;
}
```
V 分で説明する RISC-V

秋葉原ロボット部 第135回勉強会 で発表するために調べた内容です。
https://akbrobot.connpass.com/event/300169/

# 特徴

- オープン
- 教育用➯シンプル
- スケーラブル
- すぐ動く

# オープン

ライセンスは?

- BSDライセンス下で提供を目指す
- 自由に利用可能
- 作ったものをクローズドにして独占することも自由
 
# 教育用➯シンプル

わかりやすい

# スケーラブル

過去の反省

#  すぐ動く

- GCCやエミュレータなどが存在する
- FreeBSD が動く
- Debian,Fedoraは安定して動く
- U-boot が移植されている


 # Q&A

- お金は?
  - 商標を使用するにはライセンスが必要


- 同じようなもので MIPS があったんじゃないの?

  - MIPS 命令セットは MIPS 社が所有、ライセンス料が必要

> MIPS は、学生が MIPS 互換の学生プロジェクトを設計できるようにするためのライセンスとしてバークレー大学に 300 万ドルを求めていましたが、これがバークレー大学がそもそも RISC-V を設計することに決めた理由でした。
Svelte クラス付け替え

# Svelteでクラスをつけたり外したりしたい
このボタンをクリックすると、変数`active`のtrue falseが切り替わる。
変数`active`がtrueのときだけactiveクラスをこのボタンにつけることができる
```svelte
   <button
		class="card {active ? 'active' : ''}"
		on:click={() => active = !active}
	>
 ```
 ↓
 省略記法

 ```svelte
    <button
		class="card"
		class:active={active}
		on:click={() => active = !active}
	>
 ```
↓
 クラス名が、依存する変数名と一致する場合、
 さらに省略記法
```svelte
    <button
		class="card"
		class:active
		on:click={() => active = !active}
	>
 ```

 # スタイルもつけたり外したり
 
```svelte
    <button
		class="card"
		class:active
		on:click={() => active = !active}
		style:background-color={active ? 'red' : ''}
	>
システムコンテキストでのインストール中にユーザコンテキストでコマンドを実行する

# はじめに

IntuneでWin32アプリのインストールを行う場合、ユーザまたはシステムコンテキストのどちらかを選択します。大半のアプリは管理者権限でのインストールの為、システムコンテキストでの実行を選択すると思います。

インストールの途中にユーザコンテキストで実行したいコマンドがある場合に、何か対応方法がないか検索したところ、PSAppDeployToolkitで実行できることがわかりましたので、その方法を共有します。

一例として、インストールするかどうかをユーザに意向確認するとか、インストール中にファイルサーバにアクセスをして、何らかのパラメータファイルをコピーするようなケースです。(たぶんシステムアカウントではファイルサーバにはアクセスできない。。と思っています。)

# 実行方法
キーとなるのは以下のfunctionです。

[Execute-ProcessAsUser](https://allnewandimproved.psappdeploytoolkit.com/functions/Execute-ProcessAsUser.html "Execute-ProcessAsUser")

どうやら、タスクスケジューラにタスクとして実行コマンドを登録し、それを実行することで、ユーザコンテキストでのプロセス実行を行うようです。
なかなか面白い方法です。

# 実践編
では、実際にやってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/98e4799c-f587-d76e-00db-15bd85da0fa8.png)


Filesの下には以下の2つのファイルを配置します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/98e89c62-486a-ca98-bd71-ae5b10dc9946.png)

checkuser.vbsは以下のような簡単なものです。インストールをするかどうか確認し、Yesなら0を、Noなら1を返します。

```vbs:checkuser.vbs
x = Msgbox ("Install?", vbyesno , "InstallCheck")
If x = vbYes then
WScript.Quit(0)
ElseIf x = vbNo then
WScript.Quit(1)
End If
```

Deploy-Applicationの中に以下のコードを追加します。
-checkuser.vbsを誰でもアクセスできるフォルダにコピー(この例ではC:\)
-ExecuteProcessAsUserを利用してスクリプトを実行します。(この例では、ログオンユーザで実行されます)
ユーザがNoを選択した場合には、exit code 1で終了します。Yesの場合にはそのまま継続し、後続のインストール処理を行います。

```powershell:Deploy-Application.ps1
    ## <Perform Pre-Installation tasks here>
    Copy-File -Path "$dirFiles\checkuser.vbs" -Destination "c:\checkuser.vbs"
    $a=Execute-ProcessAsUser -Path "wscript.exe" -Parameters "c:\checkuser.vbs" -Wait -PassThru
    if ($a -eq 1 ) {
       Exit-Script -ExitCode 1
    }
```


それではテストしてみます。システムコンテキストで実行する為にpsexecを利用しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/faf838a1-a593-2c20-b11a-e969fbfca345.png)


コマンドプロンプトを管理者権限で実行します。そして、以下のように実行します。

```コマンド
psexec -s <Deploy-Application.exeの絶対パス>
```
psexec経由でDeploy-applicationが実行されます。
そして、checkuser.vbsのダイアログが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/0fc4439f-996c-7e25-81a1-38e916b7eff0.png)


Deploy-Applicationは正しくシステムコンテキストで実行されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/088ef827-c3ac-9822-e5a6-71091fc24271.png)

一方のcheckuer.vbsはログオンユーザで実行されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/93509f10-9699-0594-e3db-9ecea21773b4.png)

タスクスケジューラを開くと、psappdeploytoolkitが作成したタスクが確認できます、実行中になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/5a434b26-ec76-7a79-eb3d-5392c6e4eceb.png)

ログオンユーザで実行する設定になっていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/7c19c1d7-18cf-0264-8318-117b8fb8bc18.png)

ちなみにこのタスクは実行終了後に削除されていました。

なかなか他ではできない便利な機能ですね、何かのお役に立てばと思います。



# 参考リンク


* [PsAppDeployToolkit(本家)](https://psappdeploytoolkit.com/ "psappdeploytoolkit")
* [PsAppDeployToolkitの使い方(入門編)](https://qiita.com/DeviceManager/items/6e28a2b2adb36d5c9d18 "psappdeploytoolkit")