OmniAICreator/Qiita-1.07M huggingface dataset:
EC-CUBE4の管理画面、商品説明のtextareaにaタグでtarget="_blank"を使いたい。（いろいろなタグを使えるようにする）

EC-CUBE4（4.2）にて、商品説明などの入力欄では、HTMLを使えるが、idや今回やりたかったtarget="_blank"などの記述は、保存時に自動で除去されてしまう。

処理には`HTML Purifier`が入っているそうだが、EC-CUBE4での設定に特化した記事がなかったのでメモ書きしておきます。

## 手順

設定ファイルが初期状態では存在しないため、以下の場所にファイル`exercise_html_purifier.yaml`を新規作成し、中身に以下を記載します。
```text
/app/config/eccube/packages/exercise_html_purifier.yaml
```


```yaml:exercise_html_purifier.yaml
exercise_html_purifier:
    html_profiles:
        default:
            config:
                Attr.AllowedFrameTargets: ['_self','_top','_blank']
```
今回は、`_blank`の他、ついでに`_self`と`_top`も許可しておきました。

その他色々な設定は参考文献より

## 参考文献
- HTML Purifier
    -  http://htmlpurifier.org/
- HTML Purifier Configuration Documentation
    - http://htmlpurifier.org/live/configdoc/plain.html
オリジナルアバターでGoogle Meetに参加しよう

# <font color=royalblue>はじめに</font>
本稿では、Vroid Studioで作った3DアバターをGoogle Meetのオンライン会議で自身のアバターとして活用する手順を紹介します。

# <font color=royalblue>Vroid Studioでの3Dアバター生成</font>
Vroid Studioを使った3Dアバター生成は様々な記事があるのでそちらにお任せして、本稿では事前に3Dアバター生成(.vrm)が生成されているとします。
※Vroid Studioは、インストールから3Dアバター生成まで簡単に行えます

https://vroid.com/studio

 # <font color=royalblue>環境</font>
 Macbook Pro(Intel版)で検証しています。Macbook M1/M2/M3の場合は、最後の仮想カメラのCam Twistは使えなと思いますので、代わりにOBS Studio等で代替することになると思います（未検証）。

# <font color=royalblue>3teneのインストール、設定</font>
まずは、`3tene(フリー版）` をインストールします。

https://3tene.com/

インストール後、メニューの`新規アバターの登録`から `+` をクリックし、生成した3Dアバター(vrm ファイル)を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/d00546ee-253d-13ab-5707-aca434a55141.png)


右のメニューの上にある`フェーストラッキング` と `リップシンク` の `開始` ボタンを押下します。そうすると自分と同じ動きをするようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/03a8d3d2-e3f1-0065-023f-1704ccb238e3.png)





## <font color=green>顔のアップ</font>
オンラインミーティングでは全身を映すよりも顔を中心に映した方がいいので位置調整を行います。
左メニューの上から２番目の `アバター調整` ボタンを押下し、表示された設定画面の `位置XYZ`　パラメータを調整します。 サンプルを下記に示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/1a503229-93fd-4270-25d5-d47e67dbb5b0.png)



顔がアップされました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/bd54787c-8a71-8742-1194-e8df12f95246.png)




# <font color=royalblue>Cam Twistのインストール、設定</font>
Cam Twistをインストールします。

https://camtwiststudio.com/download/

インストール後、アプリを起動し下記のように設定します。

画面左から、
+ Step1 Select a video source
  `Desktop+` を選択
+ Step2 Select some effect
  `AppleScript` を選択 
+ Step3 Adjust setting
  `Desktop+` を選択
+ Setting  
  `Confine to Application Window`を選択、　`Filter out untitled windows`を選択、`Select from existing windwos`　を選択し、下のリストボックスから　`3teneFREE_beta(xxx)`

を選択します（`3teneFREE_beta(xxx)`の画面を仮想カメラで映すイメージです）。　


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/19e21e3a-77c5-29e9-d044-62c772de7c63.png)



# <font color=royalblue>Google Meetの設定</font>
Google Meetを立ち上げ、設定の「ビデオ」で `Cam Twist ...`を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/17831ea6-b429-dc27-7fd3-5de474152697.png)


&nbsp;
3Dアバターが自身の顔の動きをトラッキングしながらGoole Meetに参加できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1413278/1c7391b6-d6ea-20da-ab98-a9518ced9da2.png)


# <font color=royalblue>おわりに</font>
年末年始のGoogle Meetでオリジナルの３DアバターでM参加すると楽しそうですね。
今回は、Intel MACでの実装でしたが、今後M1/M2 MACでも実装検証して追記します。
WebUI のドキュメント

## はじめに
タイトルがわかりにくいですが、ここで書いている WebUIというのは、Chrome（Chromium）の WebUIのことであり、普段からChromeを通して使っているものです。chrome://から始まる特別な表記のURLをアドレス欄に入力してアクセスします。chrome://about を見ると一覧があります。この部分に使われている Chromeの UIのことをWebUIと呼んでおり、HTML/CSS/Javascript で作られています。

Chromeチームの人がWebUIを開発する開発者向けにドキュメントを整備しています

https://chromium.googlesource.com/chromium/src/+/main/docs/webui_explainer.md


## WebUI

私は普段 Javascriptを書かないので、Javascriptのちょっとしたことを調べたりするのにコードを書くというよりも毎回Webを検索したりしています。
最近は（Webの検索もしますが）代わりにchromium のWebUIのコードを検索する事が増えました。

WebUIのコードを見たり検索したりするのは少し考えてみるとWebUIというのが
 - いつでもアクセスできるところにある
 - 古いコードとモダンな実装が混在している
 - ドキュメントがあるのでコードを読む気になる

というのが理由なんじゃないかなぁと思っています。


最初の理由のいつでもアクセスできる、というのは大きいと思います。
どのOSを使っている時でも手元にchromeがインストールされていることが多いですし。
常に手元に情報源があると参照回数は増えます。なにか思い出せない事があるときにWebの検索の前にまずmanコマンドで調べろ！という話を思い出します。私なんかは（物理キーボードをLinuxに繋ぐ機会も最近はなくなりましたが）Linuxを触っていてキーボード配列を少し変えたいときはいつも、man xmodmapとしてCapsについての段落を検索してCtrlとSwapする、みたいなお決まりの作業をするのですが、手順をWebの検索に頼るのではなく手元ですぐに出せるのは非常に便利です（manは最高）。Javascriptのコードや動作例をWebUIで短時間で確認できたことが結構な回数あって、このことからmanの例と少し似ているなぁと思いました。

次の理由の古いコードについてはchromiumは開発の歴史も長く、継続的に改善する中で一部モダンなやり方で実装されますが、全体的には昔のコードがメンテナンスされている、という状況によります。WebUIという枠組みをなんとなく把握しておいて時代を感じるコードやモダンなコード例を同時に辿れる状態がすぐ手元にあるのが好きです。
Promissのresolve/rejectの動作例とかは、xxxPromiseのような関数名で呼びだして、以下のように処理するコードが主流だったりします。
```
export function webUIResponse(id, isSuccess, response) {
    const resolver = chromeSendResolverMap[id];
    assert(resolver);
    delete chromeSendResolverMap[id];
    if (isSuccess) {
        resolver.resolve(response)
    } else {
        resolver.reject(response)
    }
}
```


最後のドキュメントが用意されている部分については冒頭に書いた`webui_explainer.md` の他に`webui_in_chrome.md` があります。

https://chromium.googlesource.com/chromium/src/+/main/docs/webui_in_chrome.md

このドキュメントに書かれているWebUIの例としては以下の３つです。
 - chrome://hello_world
 - chrome://donuts
 - chrome://history

それぞれ
 - chrome://hello_world が C++/Javascriptをどのようにセットアップするかという前提部分の説明で `webui_in_chrome.md`のメイン部分で、
 - chrome://donuts は `webui_explainer.md` のメインの部分です
 - chrome://history は実際のサンプルとして引用している

という感じです。冒頭にも書きましたがこのドキュメントは主にchromium開発者向けに書かれているのであまり頑張って読むものではないです。私は一通り目を通してあとは `chrome://history` を chrome devtools で調べた、みたいな感じでした。

内容も開発者向けの注意点といった感じです。セキュリティに問題がないようにCallJavascriptFunctionを直接使わせず、きちんとAllowJavascriptを使わせる、みたいな内容です。書き方もMojo、Pre-Mojo（イベントベースとresolve/rejectパターン）の両方について記述されています。

WebUIに親しみを覚えたのは、はやりこのドキュメントのおかげです。Javascript関連でWeb検索よりも色々なコードを読むようになれた気がします。


Mojoというのはブラウザとレンダラー間のプロセス間通信(IPC)のために、Ninja/GNの上に構築されてた仕様でmojomというIDLが用意されており仕組みとして面白いと思います。

さて、chrome:// （WebUI）のjavascriptが参照するもので `chrome://resources/js/cr.js` というのがあります。いろんなWebUIから参照される共通の（グローバルな）処理を集めた小さなファイルでいつも参照します。

この `cr.js` の `webUIListenerCallback` という関数にブレークポイントを貼って挙動を見るというのが最初は簡単でした。例えば、chrome://history だと `foreign-sessions-changed `というイベントがブラウザプロセスからレンダラプロセスに送られてきます。`foreign-sessions-changed` だと、複数端末でブラウザを同期している時のスマホや別のマシンでタブを開く/閉じるなどを行うと発火されるイベントになっています。こういうのを入り口にして、色々仕組みを覗いていくと色々と発見があって楽しいと思います。このあたりに興味がある人は是非試してみてください。


## 最後に

つれづれと書いていて最後に気がついたのですがWebの検索が減ったというのはChatGPTを使っているからなのでした。最近、Webの検索が超めんどくさくなったからだと思います。検索が面倒、というのは今だと当たり前なのでした。
ビジョンを形にする図解ソリューション！図解⽣成AI「Visually」リリース！

こんにちは！インター・ラボ株式会社でございます。
この度、テキストを入力するだけでコード生成やフローチャート、マインドマップなどを自動生成するサービス、図解生成AI「Visually」をリリースいたしました！
そこで、この記事では「Visually」にできることを紹介したいと思います。

![](https://storage.googleapis.com/zenn-user-upload/0355f4bea9ec-20231122.png)


# 〇図解生成AI「Visually」とは
「Visually」は、フローチャートやマインドマップといった図解をテキスト入力だけで、簡単に自動生成するツールです。https://itl-portal.com/visually/
その他にも、チャット、ビジネス文変換、翻訳といった機能をはじめ、コード生成・解釈、変数や関数の命名などエンジニアにとって便利な機能を搭載！
![](https://storage.googleapis.com/zenn-user-upload/36cda7c93c30-20231122.png)

# 〇機能
**・チャット**
チャット機能は、ChatGPTを活用しています。
技術的な問題点や悩み事の相談など幅広い内容に答えることができます。
![](https://storage.googleapis.com/zenn-user-upload/2b423caa64d6-20231122.png)


**・翻訳（日本語化）**
AIやプログラミング言語、IT関連のニュースや技術ドキュメントなどを日本語に翻訳します。

**・ビジネス文**
文章をビジネス表現に変換します。メールの返信や報告書など、ビジネス文章を書かなければいけないときに役立ちます。

**・やさしい化**
難しい表現の文章を、読みやすいやさしい文章に変換することができます。
技術知識が求められる内容を簡潔に言い換えることでユーザーにわかりやすい説明文を作成することができます。
また、プログラムを入力すると簡潔に処理内容を解説することも可能です。

**・ふりがな**
文章中の漢字や英単語にふりがなをふることができます。

**・コード生成**
入力したテキストをもとにコードを自動生成します。
![](https://storage.googleapis.com/zenn-user-upload/7503c4831847-20231122.png)


**・コード解釈**
コードの意味や動作を解釈してコメントを挿入します。
![](https://storage.googleapis.com/zenn-user-upload/953cd754af53-20231122.png)


**・命名**
変数や関数などの名前を提案します。
![](https://storage.googleapis.com/zenn-user-upload/cda9c25d53c7-20231122.png)


**・テーブル化**
データを表形式に整理して表示します。
![](https://storage.googleapis.com/zenn-user-upload/45662419eb19-20231122.png)


**・円グラフ**
数値データを円グラフとして可視化します。
![](https://storage.googleapis.com/zenn-user-upload/3a3bfcc72f56-20231122.png)


**・マインドマップ**
アイデアや情報をマインドマップとして整理します。![](https://storage.googleapis.com/zenn-user-upload/4f47b062081b-20231122.png)


**・フローチャート**
手続きやプロセスをフローチャートとして表現します。
![](https://storage.googleapis.com/zenn-user-upload/3bf5fd82c07b-20231122.png)


**・ガントチャート**
プロジェクトの進捗状況などをガントチャートとして表示します。
![](https://storage.googleapis.com/zenn-user-upload/fe1a40c3164a-20231122.png)


**・シーケンス図**
プログラムの処理の流れをシーケンス図として表現します。
![](https://storage.googleapis.com/zenn-user-upload/cfd35004c600-20231122.png)


# 〇価格
価格は全て税抜き価格です。フリープランはアカウント登録だけで、月額無料でご利用いただけます。ぜひお試しください。
![](https://storage.googleapis.com/zenn-user-upload/4adb7757debe-20231122.png)

# 〇まとめ
図解生成AI「Visually」は、普段の業務で図解を書いたり文章書いたりといった業務を頻繁に行う、エンジニアやコンサルタントの業務効率化を支援するツールです。フリープランはアカウント登録のみ、月額無料でご利用いただけます！ぜひ一度お試しください！

# 〇図解生成AI「Visually」
https://itl-portal.com/visually/
if __name__ == '__main__'

## 対象の読者
Pythonを学習中の方、またはPythonの特殊変数__name__と'_\_main__'の使い方について理解を深めたい方向けの記事です。


## \_\_name__
Pythonのモジュール、クラス、関数はそれぞれ__name__という特別な属性を持っています。モジュールの場合、__name__の値はそのモジュール名(.pyを除いたファイル名)になります。クラスや関数の場合、__name__の値はそのクラス名や関数名になります。
```example.py
class MyClass:
    pass

def function():
    pass
```
```another_file.py
import example

print("Module name: ", example.__name__)
print("Class name: ", example.MyClass.__name__)
print("Function name: ", example.function.__name__)
```
このanother_file.pyを実行すると、以下の出力が得られます。
```terminal
Module name:  example
Class name:  MyClass
Function name:  function
```


## '_\_main__'
'_\_main__'は、Pythonファイルがスクリプトとして直接実行されたときに__name__変数に設定される値です。
これはプログラムのエントリーポイントを表します。

```example.py
print(__name__)
```
このexample.pyを直接実行すると、以下の出力が得られます。
```terminal
__main__
```


## if \_\_name__ == '_\_main__'
if \_\_name__ == '_\_main__'という条件式は、ファイルがスクリプトとして直接実行された場合にのみTrueとなります。これにより、ファイルが直接実行されたときだけ実行したいコードをこの条件式の中に記述することができます。ファイルがインポートされた場合、この条件式の中のコードは実行されません。

```example.py
def function():
    print("This is a module function")

if __name__ == '__main__':
    print("This is a script")
```
このexample.pyを直接実行すると、以下の出力が得られます。

```terminal
This is a script
```

しかし、別のファイルからexampleをインポートしてfunction()を呼び出すと、"This is a script"は出力されません。

```another_file.py
import example

example.function()
```
このanother_file.pyを実行すると、以下の出力が得られます。

```terminal
This is a module function
```
このように、__name__と__main__を使うことで、ファイルがスクリプトとして実行されているのか、他のファイルからインポートされているのかを区別し、それに応じた動作をさせることができます。これは、モジュールを再利用しやすくするためのPythonの便利な機能です。

また、Pythonファイルがモジュールとして実行された場合と直接実行された場合で、__name__変数の値が異なることを利用して、特定のコードをモジュールとして実行された場合だけ、または直接実行された場合だけに実行させることも可能です。

```example.py
if __name__ == "__main__":
    # このコードはファイルが直接実行された場合にのみ実行されます
    print("This file was run directly")
else:
    # このコードはファイルがモジュールとしてインポートされた場合にのみ実行されます
    print("This file was imported as a module")
```

## まとめ
Pythonの特殊変数__name__と'_\_main__'を理解することで、Pythonのコードをより効率的に再利用することができます。


## 参考資料
https://docs.python.org/3/library/__main__.html?ref=morioh.com&utm_source=morioh.com


## 用語の解説
- モジュール
Pythonファイルが他のPythonファイルからインポートされて使用される場合、そのファイルはモジュールとして扱われます。
モジュールは、関数、クラス、変数などを定義し、それらを他のPythonファイルから再利用するためのものです。
モジュールの名前は、Pythonファイルの名前(.py拡張子を除く)になります。

- スクリプト
Pythonファイルが直接実行される場合、そのファイルはスクリプトとして扱われます。
スクリプトは、一連の命令を含み、それらの命令は上から下へと順番に実行されます。

- エントリーポイント 
プログラムの実行が始まる場所であり、通常はプログラムの最初に呼び出される関数やコードブロックを指します。
Pythonにおいて、if \_\_name__ == '_\_main__'の中のコードがエントリーポイントとなる。
丁寧な質問の仕方を考えてみた

## 質問するの難しくない？
こんにちは。駆け出しエンジニアのえくれあです。
突然ですが、質問の仕方って難しくないですか？

自分でどう頑張ってもわからない…
人の意見を聞きたい…
わかりやすく質問がまとまらない…
自分で考えた？って怒られそうで質問するの怖い…

そんな不安を持ったことがある人はいませんか？
私のことです！！！

駆け出しということで、自分の知識のなさに焦りや劣等感を感じ、質問することが申し訳なく思ったり億劫になることもありますよね…

## 質問から逃げない
でも質問しなかった結果被るダメージと、質問へのフィールドバックで受けるダメージ、どちらが大きいでしょう？
私は前者だと思います。

黙ってたことに後々怒られるくらいなら、質問して「もっと自分で考えろ！」と言われたほうがマシです。

## できれば怒られずに求めた解答を得たい
自分で考えろ！って怒られないために
あわよくば望んだ返答が得られるように

私が日頃意識して割となんとかなってる質問の仕方をここにのこしておきます。

## 想定読者
私のように質問するのに苦手意識のある駆け出しエンジニア

## 質問の例
#### 例①

>◯◯エラーが出てるのですがどうしたらいいですか？

#### 例②

> 1.いまお時間よろしいですが？
2.XX機能の製造について質問なのですが、
3.△△をすると〇〇エラーが出てしまいます。
4.ZZが原因かと思い解決策として□□を試したのですが
それでも改善しませんでした。
5.自分では他に解決策が思いつかないのですが
6.どうしたらよいかご意見いただけないでしょうか？

②のやり方の方が良さげじゃないですか？
私が上司だったら②で聞かれたら嬉しいです。

## 例②がなぜ良さげか言語化していく
例②がどんな構成が整理していくと、
1.相手の都合を把握する
2.何の話か伝える
3.課題点を伝える
4.自分で試したことと結果を伝える
5.手順4を踏まえて今の状況を伝える
6.お伺いを立てる
といった形になっています。

①は色々すっ飛ばして3と6しかしていませんね。
#### なぜ例①がだめなのか
* 情報量が少なく、質問後のコミュニケーションコストが増える
* 相手に問題解決を丸投げしている
* 自分の都合で話し始めている
この辺が理由になると思います。
こう見てみると、①のような質問は回答者にとって優しくないことがわかりますね。

#### なぜ例②が良いか
例①のダメな点を改善した構成になっているからです。　
項目ごとに発言の意図を確認していきましょう。

## 1.相手の都合を把握する
相手が先輩だろうと同期だろうと、相手は相手のタイミングがあります。
質問する前に相手の都合を聞くと良いでしょう。

「ごめん今ちょっと手放せなくて…/これから会議入っちゃうんだよね…」
と返される場合もあるでしょう。そうした場合は
「そうでしたが、すみません…」で終わらずに

1.代わりに他の人に聞いてみる旨を伝える
2.いつ頃がいいか確認を取る(相手のカレンダーを自分で確認できるなら具体的な時間を提案してみても◯)
をしてください。
1が必要な理由は、質問相手が手が空いたときに、「そういえばあれどうなったかな？」と心配させないためです。
もし代わりの人に聞いて問題解決した場合は、最初に質問した人にも「あの件解決しました！」と伝えておくのも親切でしょう。

2が必要な理由は、問題解決を先延ばしにしないためです。質問相手が忙しいことに負い目を感じて質問をしないままでいると、結果的に自分や相手の首を絞めることになりかねません。
ガツガツ、でも手順を踏んで相手のスケジュールに入り込んでいきましょう。

## 2.何の話か伝える
自分が持っている情報、相手が持っている情報は違います。

自分の頭の中は〇〇機能のことでいっぱいだとして、
相手も同じタイミングで同じことを考えているというのはなかなか考えにくいでしょう。

なので、最初に何の話なのか伝えたほうが、質問相手が話についてきやすくなり親切と言えます。

## 3.課題点を伝える
ここまで来てやっと、課題点を伝えます。
質問が複数ある場合は、
「聞きたいことは3点で、ひとつめは〜」
といった形で始めると良いでしょう。
何点あるか伝えておくことで、相手は心の中で会話の所要時間を予想することができます。
いつ終わるかわからない会話は、タスクを抱える人にとって優しくないですよね。
会話に安心感を与えるため、所要時間が類推できるようにすることは大事です。

課題はできるだけ粒度細かく伝えます。
* なにをして
* どうなったか
* エラーならなんというエラーが出たのか

質問相手が容易に想像できるような状況説明を心がけます。

## 4.自分で試したことと結果を伝える
自分のスキルアップのためにまず自分で原因を考えてみる。
その上でわからなければ助けを求める。

そんな順序が駆け出しエンジニアには必要かと思っています。

「まず自分で考えた？？」って言われないための対策にもなります。
結果的に自分で解決できていないが、試せることは試したぞ！！という姿勢を見せましょう。

## 5.手順4を踏まえて今の状況を伝える
「解決の心当たりがあるが具体的にわからない」
なのか、
「今思い当たることは何もない」
のか、言語化しましょう。

質問相手がどこからどこまで説明が必要なのかの判断材料になります。

## 6.お伺いを立てる
質問相手にどうしてほしいか伝えます。
6に至るまでに、質問者は置かれた状況や解決したい課題を丁寧に伝えてきました。

これだけ情報を伝えておけば、親切な相手であれば「どうすればいいでしょうか」の「ど」を言い出したくらいから返答を話し始めてくれるかもしれません。

質問の構成についてのポイント説明はここで終了です。

## なにか相談したいとき
わからないことを聞きたいわけじゃないけど、

・自分のアイデアに迷いがあり他者の意見を聞きたい

そんなときにも上記のポイントを意識すれば親切な質問が出来上がります。
今回はチャットでの依頼風に書いてみます。

>【XX機能の〇〇処理の実装方法について】
>△△と□□の2パターン思い付いたのですがどちらがベターか迷っている状況です。
>
>私としては△△の方が▲▲なので良いと思っているのですが、
□□のも■■の面で採用に値する気がします。
>
>上記についてご相談したく、15:00から10分ほどMTGのお時間いただけないでしょうか？
>お忙しいところ恐縮ですが、ご確認お願いいたします。

前の例と話の展開の順番は違いますが、
* 相手の都合を聞き
* どんな要件が伝え
* まず自分で考えてみたうえで相談する
という内容は共通しています。

## 良い質問は優しい
質問という行為は、相手の時間をいただく行為です。
とはいえ、質問しないと解決できないこともたくさんあると思います。

質問に関わる時間をより短くし、効率の良いコミュニケーションを取るために、質問の仕方を今後も気をつけていきたいと思っています。

質問の仕方について、
「もっとこうした方がいいよ〜」
とか
「私はこうしてるよ〜」
などあれば、ご指摘してもらえたら嬉しいです。

長くなりましたが以上です！
質問するの怖い……
質問したら怒られた……
という私のような人が一人でも少なくなったら嬉しいです！
読んでいただきありがとうございました。
えーー！たのれんの工嶺祭担当箇所がバグだらけ！？

### 謝罪
```
　　　　　　　　　　　　　／￣＼
　　　　　　　　　　　　 |　　　|
　　　　　　　　　　　　　＼＿／
　 　 　 　 　　　　／ ⌒｀"|⌒｀ヽ、
　 　 　 　 　 　／,,　／￣￣￣￣＼
　　　 　 　 　 /,／/::　　　　　　＼
　 　 　 　　　;/⌒'":::..　　 　 　 |⌒ヽ
　　　　　　　/　　/､:::::... 　 　 /ヽ_　＼
　　　　 _＿（　⌒ー-ｨ⌒ヽ、 　 /⌒`ー'⌒　 ）
　 　 　━━━━━　`ー──ゝィｿﾉー ‐ヾy＿ﾉー─"
```

# はじめに
この記事は、[長野高専 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/nnct "長野高専 Advent Calender 2023") 3日目の記事です。

こんにちは。長野高専電子情報工学科5年、チュウニズムプレイ回数2700回のたのれんと申します。
2023年10月20日(金)～10月23日(日)にかけて長野高専で開催された第58回工嶺祭で5Jの「JABEET MANIA」の開発を@BetAmotoと共に行いました。開発の裏話を書けたらなと思っています。技術的なことは多分書かないです。

# JABEET MANIAとは
**4鍵音ゲーです。**
画面上部から降ってくるオブジェクトに対応するボタンを、タイミングよく押すリズムゲームです。4つのレーンにオブジェクトが降ってくるので、それぞれのレーンに対応した位置のボタンを押すことでオブジェクトを叩くことができます。
1曲につき4つの難易度の譜面を遊ぶことができます。



これ↓
<blockquote class="twitter-tweet"><p lang="zxx" dir="ltr"><a href="https://t.co/K8utnrvvhd">pic.twitter.com/K8utnrvvhd</a></p>&mdash; 動画 (@kosen38s) <a href="https://twitter.com/kosen38s/status/1728933997429035326?ref_src=twsrc%5Etfw">November 27, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 序章 経緯
Ａ　「工嶺祭どうするよ？」
ぼく「音ゲーつくりたい」
Ａ　「おけ」



6月あたりにプロジェクトが進み始め、音ゲーの譜面を作る曲を決めたり、4つの難易度それぞれをどれくらい離すか、どの程度の難易度にするか等を決めていました。
実際に私が「このくらいの難易度感で作ってね」という意味合いで4つの難易度に分かれた譜面を1曲完成させてました。

**小夏の候、7月_____**
編入が終わった次の週にはリポジトリが生えてました。
早速音ゲー製作にとりかかるわけですが、なかなか難しいのなんの
上から降ってくるオブジェクトを`BaseNote`クラスとし、`BaseNote`クラスを配列として持ったレーンである`Lane`クラス、`Lane`クラスを配列で持った`Field`クラスに分けました。
こんなかんじで
![こんなかんじ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2240661/b18c50e5-babf-38c5-1b36-229ea24b8905.png)

そんなこんなで譜面エディターを作ってました。
譜面はCSVで保存してました。
レーン番号(1～4)、オブジェクトの種類(ロングノーツなど)、オブジェクトが降ってくるタイミング[s]で保存していました。

できたエディター↓
![editor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2240661/242c508e-5571-29ce-36cc-254d1c301981.png)

# 二章 進捗モリモリなつやすみ
ディズニー行ってました

# 三章 エフェクトたくさん、電力もたくさん(泣)
夏休みが終わった9月、今まで[Siv3D作品置き場](https://scrapbox.io/Siv3D-tanoren/)にて作ってきたエフェクトやシーン遷移トランジションをふんだんに使ってJABEET MANIA本体を作り始めました。
遊べる形になってきて楽しかったですが、デザインなんて全くできないのでとにかく画面の装飾が大変でした。
地獄の座標手打ち作業を延々と繰り返していい感じの画面にできました。~~あんまり納得いってないけど~~
![teuti](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2240661/ff288e4d-0614-be72-9a27-cc9526af124e.png)

# 終章 当日
筐体作って...パソコン持ってきて...チラシ作って...会場セットアップして...

完成～！！！

![筐体](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2240661/d164cab8-77aa-ce9d-08d5-13e892dae84a.jpeg)

1000人近くの方が来てくれたし、何回も来てくれるリピーターの方もいて良かったです。


# 反省点
## 選曲が若者向け過ぎた
現在稼働している音ゲーが美空ひばりとか入れないのは客層がマッチしておらずマネタイズができないからで、マネタイズとか関係ない工嶺祭展示では昔の曲を取り入れるべきでした。そもそも工嶺祭に来る年齢層が老若男女満遍ない感じだったのでもし次音ゲーを展示するところがあれば昔の曲を取り入れることをおすすめします。

## オフセット調整が人によってバラバラであった
譜面を作る人それぞれがあっていると思ったタイミングで作っているので、曲に対して譜面が早かったり遅かったりバラバラになってしまいました。最終的に誰か一人のタイミングに合わせて調整しようとも思ったのですが、時間がなかったため断念。

## 知名度の高いの曲は音ゲー上級者が担当するべきであった
とりあえずで選ばれるような曲の譜面はしっかりと監修するべきでした。特に低難易度に気を付けるべきで、本当に簡単な譜面でよかった気がします。ただ、私も開発しながら5曲分の譜面を作っていたのでそこまで手が回りませんでした。

# おわりに
いかがでしたか？
普段から音ゲーの譜面を作っていないと"良い譜面"はなかなか作れないので難しい問題だったかなと思っています。~~私は作ってましたが~~
音ゲーを作るという人生の目標が達成できたので良かったです！
それでは
グリッドレイアウト備忘録

## 背景
久しぶりにHTML/CSSを勉強することになり、その備忘録を残しておきたいと思ったので、本記事を投稿しました。

## グリッドレイアウト
グリッドレイアウトとは、以下の図のように、水平と垂直線で分断し、格子状に配置したレイアウトのことを言います。


![スクリーンショット 2023-12-07 13.36.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465903/8dd31ac9-e851-a746-6ed6-acf4159a9e0f.png)


## 実装

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Grid レイアウト</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <div class="area1">area1</div>
        <div class="area2">area2</div>
        <div class="area3">area3</div>
    </div>
</body>
</html>
```
```style.css
.container {
    width: 300px;
    display: grid;
    //縦線を入れる、「1fr」は今回の場合は300px-100px=200pxと言う意味
    grid-template-columns: 100px 1fr;
    //横線を入れる
    grid-template-rows: 100px 100px;
    // 中央よせ
    margin: 0 auto;
}

.area1 {
    background-color: red;
    // 図の縦線No.1-2
    grid-column: 1/ 2;
    // 図の横線No.1-3
    grid-row: 1 / 3;
}

.area2 {
    background-color: blue;
    grid-column: 2 / 3;
    grid-row: 1 / 2;
}

.area3 {
    background-color: yellow;
    grid-column: 2 / 3;
    grid-row: 2 / 3;
}
```

![スクリーンショット 2023-12-07 13.37.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465903/d036a9dd-a83b-b591-adde-353fc75e4b64.png)

## 最後に
昔勉強した時とグリッドシステムの記述法が違うような気がするのは気のせいだろうか。
最後まで読んでいただき、ありがとうございます。
NTTドコモCCoEが手掛ける共通基盤の取り組み

<iframe src="https://docs.google.com/presentation/d/1JXk_9GqYZK9Zdq3XbnJUxBTE6k9gZp8fZrKjtJ_KVdQ/embed?start=false&loop=false&delayms=3000" frameborder="0" width="960" height="569" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
【Apache2.4】Win10環境でPHPと連携してみた(PHPモジュール)

この記事では、Apache2.4とPHPを連携して、
PHPファイルをApacheが扱えるようにする方法を紹介します。
この記事では、PHPに同梱のPHPモジュールを使用します。

(Windows11環境がないので、Windows10の環境です)

**この記事はPHPファイルをApache2.4で使いたかったので、同時にQiita記事を書いたものです。
一部間違いがある可能性があるので、心配な場合は別の記事も見てみることをお勧めします。**

# 注意点
この記事では、Apache2.4とPHPがインストール済みなことを前提としています。
Apacheのインストール方法は以下の記事で紹介しています。

https://qiita.com/TechCat56/items/aba26453c10414ce68f6

この記事ではPHPが`C:\php`にあり、Apacheが`C:\Apache24`にあることを前提として進めます。

# 連携

## PHP.iniを作成(既にできている人は飛ばしてください)
まず、PHP.iniが必要です。
同梱されている`php.ini-development`か`php.ini-production`を`php.ini`という名前にします。
変更するのが怖い場合は、複製して、複製したものを`php.ini`にするのでもOKです。
`php.ini-development`は開発向けで、`php.ini-production`は本番環境向けです。
僕は趣味でプログラミングをするために使うので、`php.ini-development`を名称変更しました。

## Apache側の設定ファイルを変更

設定ファイルを変更します。`C:\Apache24\conf\httpd.conf`を開きましょう。
`Dynamic Shared Object (DSO) Support`と書いてある行を探してください。
その行の近くに`LoadModule モジュール名 パス`というような感じに書いてあるはずです。

### LoadModuleとは
`LoadModule モジュール名 パス`という感じの書き方で、
モジュール(拡張機能のようなもの)を読み込んでいます。
`#`でコメントアウトしているものもあります。
コメントアウトされたLoadModuleは機能しません。
使いたいときに`#`を消せば有効化できます。

### PHPのLoadModuleが見つからない
LoadModuleが書いてあるのは、Apacheに同梱しているモジュールのみです。
PHPのモジュールはApacheに同梱されていないので、自分で書く必要があります。

### 書いてみよう
php7の場合は、以下のコードをhttpd.confの末尾に追加します。
```conf:httpd.conf(一部)
LoadModule php7_module "c:/php/php7apache2_4.dll"
AddHandler application/x-httpd-php .php

PHPIniDir "C:/php"
```

php8の場合は、以下のコードをhttpd.confの末尾に追加します。
```conf:httpd.conf(一部)
LoadModule php_module "c:/php/php8apache2_4.dll"
AddHandler application/x-httpd-php .php

PHPIniDir "C:/php"
```

さらに、htmlファイルではなくphpファイルを読み込むように変更します。
```diff_conf:httpd.conf (一部の変更)
<IfModule dir_module>
-    DirectoryIndex index.html
+    DirectoryIndex index.php
</IfModule>
```

## PHP側の設定ファイルを変更

このまま起動するとエラーが出るので、
PHP.iniファイルを開き、以下の変更をしてください。

```diff_ini:php.ini (一部の変更)
; Directory in which the loadable extensions (modules) reside.
; https://php.net/extension-dir
;extension_dir = "./"
; On windows:
- ;extension_dir = "ext"
+ extension_dir = "ext"
```

# 起動確認
index.phpを`C:\Apache24\htdocs`に作成し、起動してみましょう。

```bash:終了コマンド(管理者権限で実行)
httpd -k stop
```
念のため終了してから...

```bash:起動コマンド(管理者権限で実行)
httpd -k start
```
起動して...

この状態で http://localhost/ にアクセスすると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518709/a3b29a74-0e03-0a33-dd53-6c8f186b1493.png)
出ました！！！
Raspberry Pi OS 2023-12-05 / 2023-12-11（Lite版)  Release-note 翻訳

（追記：2024/03/14に、Raspberry Pi OS 2024-03-12 がリリースされています）
https://qiita.com/utaani/items/331ec5eabdd445ee9f94

https://downloads.raspberrypi.org/raspios_full_armhf/release_notes.txt
https://downloads.raspberrypi.org/raspios_lite_armhf/release_notes.txt
2023-12-11:
  * Lite版イメージにおけるRaspberry Pi ImagerのWLAN設定を変更

2023-12-05:
  * rc_gui と raspi-config のシリアル ポートの切り替えが Raspberry Pi 5 をサポートするように変更されました
  * 複数のタッチ スクリーンがデバイスごとに固有の文字列で識別されるようになり、ディスプレイデバイスと正しく関連付けられるようになりました
  * RP1 ディスプレイとの互換性が追加
  * テーマファイルは pixdecor プラグインによって監視され、その場で変更をロードするように
  * The Magpi Web サイトへのメイン メニューのショートカットを復元
  * GTK+2 テーマは GTK+3 テーマと調和し、Qt アプリケーションでさらに均一なテーマ設定を可能にします
  * バッテリーモニタープラグインを有効化
  * タスクバーの環境設定メニュー項目がパネルの右クリックメニューに追加
  * オンザフライのテーマ変更のリロードの改善
  * Wayfireレンダリングのさまざまな改善
  * ダーク GTK テーマが追加されました
  * バグ修正 - ファイルシステムがマウントされていない USBデバイスを取り外す際の警告通知を抑制
  * バグ修正 - 一部のデバイスで音量キーボード ショートカットがロックされないように
  * バグ修正 - 同じ名前の複数の USB オーディオデバイスを正しく処理されるように
  * バグ修正 - 一部の翻訳がパネルプラグインに読み込まれない
  * バグ修正 - 並べて表示するとウィンドウのタイトルバーが消える
  * バグ修正 - ローカルインストーラサービスがローカル deb ファイルのインストールに失敗する
  * バグ修正 - 明示的なUTF-8文字セットが必要な場合にウィザードがロケールを正しく設定しない
  * バグ修正 - アップデートにインストールされているパッケージの削除が必要な場合、システムのアップデートが失敗する可能性がありました
  * バグ修正 - ファイル マネージャー ウィンドウが画面サイズよりも大きく開かないようにする
  * バグ修正 - GPU プラグインの負荷パーセンテージが -1 として表示
  * バグ修正 - 特定のウィンドウタイプの影に関連するさまざまなウィンドウマネージャーのクラッシュ
  * バグ修正 - RealVNC または WayVNC のいずれかがインストールされている場合に VNC を有効にできるように
  * WayVNC - 暗号化接続のサポートを改善
  * Mathematica は Raspberry Pi 5 および 64 ビットで動作するように
  * Scratch 3 は Raspberry Pi 5 および 64 ビットでも動作するように
  * Thonny はバージョン 4.1.4 に更新
  * Chromium は 119.0.6045.171 に更新
  * Firefoxは119.0 に更新
  * gpiod バイナリ ツールはライト イメージに含まれるように
  * python3-venv はライトイメージに含まれるように
  * 日本語訳を更新
  * 外観設定にドイツ語の翻訳を追加
  * Raspberry Pi ファームウェア 12af703dd07d7721c1f2f58c6f71d9fe66270838
  * Linux カーネル 6.1.63
HTMLで画面実装したときに閲覧したページ

### <font color="SeaGreen">+* HTML *+</font>

要素と属性
https://so-zou.jp/web-app/tech/html/specification/element-attribute.htm

idとclassとの違い
https://www.sejuku.net/blog/85629

### <font color="SeaGreen">+* CSS *+</font>

IDを指定
https://www.tagindex.com/stylesheet/basic/format3.html

CSSの無効化
https://magazine.techacademy.jp/magazine/38815

### <font color="SeaGreen">+* JavaScript *+</font>

タグを追加
https://www.javadrive.jp/javascript/before/index2.html

タグに属性を追加
https://kasumiblog.org/javascript-setattribute/

### <font color="SeaGreen">+* jQuery *+</font>

指定したid属性の要素へHTMLタグを追加
https://qiita.com/sola-msr/items/6e3cfa2e90a7abb06999
https://www.buildinsider.net/web/jqueryref/007

### <font color="SeaGreen">+* Bootstrap *+</font>

色の値（文字色とカラーコード）
https://getbootstrap.jp/docs/5.0/utilities/colors/

要素の枠線を調節
https://getbootstrap.jp/docs/5.0/utilities/borders/

要素のサイズを調整
https://getbootstrap.jp/docs/5.3/utilities/sizing/

要素の余白を調整（クラスに指定）
https://design-studio-f.com/blog/bootstrap-utilities-spacing/

チェックボックスの大きさを変更する
https://qumeru.com/magazine/443

フレックス（直下の子要素の位置を変更）
https://getbootstrap.jp/docs/5.3/utilities/flex/

バッジ
https://getbootstrap.jp/docs/5.3/components/badge/

モーダル（ポップアップみたいな画面）
https://getbootstrap.jp/docs/5.3/components/modal/

モーダルのネスト
https://qiita.com/tomlaw/items/1fd8edc9ca1522ad270e
https://qiita.com/a__i__r/items/165ed939438300e083d9

スイッチ（トグル）
https://getbootstrap.jp/docs/5.3/forms/checks-radios/#%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81

検索フォーム
https://nllllll.com/bootstrap/bootstrap5-searchform/
【データベース勉強中】初心者がSQLでハマったことと解決方法


# はじめに
これはSQL勉強中の私がSQLでハマった時の対応記録用の備忘録

## 「;」は忘れないこと！
SQL文の最後に「;」を忘れると一生SQLが終わらない。

```
mysql> show tables from alter_table
    ->
    ->
    ->
    ->
    ->
    ->
```
### 解決方法
「;」をつける

```
mysql> show tables from alter_table　;　←コレ
```


## テーブルをCREATEするときはカラムを最低1つ指定すること！
テーブルを新規で作成する時にカラムを何も指定せずにcreateすると怒られる。
```
mysql> create table test;
ERROR 1113 (42000): A table must have at least 1 column
```

### 解決方法
実務ではカラムなしはあり得ない（テーブル定義してからCREATEするから）が、練習で作るときはとりあえず何でもいいからカラムは指定する。
```
mysql> create table test(id int, name varchar(10));
```

## データ型のTEXTとCHARとVARCHARってなんや
文字列のデータ型は主に3つ（今のところ）。
- CHAR
- VARCHAR
- TEXT

### CHAR
CHARは「CHARacter　（キャラクター）」という意味。
入るデータの桁数（バイト数）が決まっている場合に利用する。
CHAR(10)とすると、10バイト以上は追加することができなくなって、
6文字（6バイト）のデータの場合、残りは空白が4文字（4バイト）追加され10バイトにしてくれる。

### VARCHAR
VARCHARは「VARiable CHARacter　（ヴァリアブル　キャラクター）」という意味。
CHARと違って余った場合に空白は追加されない。
VARCHAR(10)とすると10バイト以上は追加することができなくなる点は同じだが、
6文字（6バイト）のデータの場合にはそのまま6文字として登録される。
(255文字以上になった場合はTEXTにするのがよさそう！)

### TEXT
CHARとVARCHARは国際標準のSQLの規格で定義されているらしい。
TEXTはMySQLやPostgreSQLなど一部のDBMSで使用できる文字列のデータ型。
文字数を指定する必要もなく柔軟に登録してくれるから便利だが、前述の「国際標準のSQLの規格」ではないため、ちゃんとしたプロジェクトならCHARとVARCHARを使うようにすること！（たぶん）

続く:point_up:
屋内でも正確なGPSを使いたい！

この記事は、[筑波NSミライラボ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/tsukuba-ns-mirailabo)、20日目の記事です。

## はじめに
S高等学校　通学プログラミングコースに所属している@mono0218です。
コンテストなどに応募するプロジェクトとして開発をしている屋内GPSについての記事です。

## 目的
・東京駅や大阪駅のような迷路施設でも正確な位置情報を入手できマップ機能が使えるようにするアプリケーションを開発すること

## やりたいこと
・Wifi-APやBluetoothからの距離をアプリ側で測定し、3点測量方式を用いて場所を推定する。

・推定した位置情報を端末のOSレベルで上書きする。（GoogleMapなどのすべてのマップアプリで推定した位置を使用できるようにするため）


## 使ったもの

### [Kotlin](https://kotlinlang.org/)

今回はAndroidでのリリースを考えているのでKotlinを選択しました。UIコンポーネントはJetpackComposeでmatelial3使用しています。

### [M5StampS3](https://shop.m5stack.com/products/m5stamp-esp32s3-module)
Wifi-APやBluetoothの発信源としてM5StampS3を使用しています。

### [Processing](https://processing.org)
実際にどのぐらいの精度・誤差なのか視覚的に分かりやすくするために使っています。
スマホ側から送られてきたM5Stampの距離をProcessingに送信しています。

## できたもの
Processingに描画してみたもの

イメージ図
![スクショ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819887/05e3536d-ce97-5da7-f616-653169332b29.png)

PC初期化時にProcessingプロジェクトをバックアップしなかった人の末路
（作り直し途中につき動くものなし）

[INGS-(Github)](https://github.com/mono0218/INGS)

## 頑張ったこと
Wifiの電波はチャンネルが一緒だと干渉しあい誤差を生みやすくなるため、espnowという規格を使いWIFI-AP同士でp2p通信をさせチャンネルを被らせない仕組みを作成することを頑張りました。

## 大変だったこと
M5Stampを使って開発をする前は、学校に設置されているAPを使って位置情報を取ろうとしていました。APの情報を得るために、ニョゴニョしなきゃいけなくなりAPを実際に外してみたりと、物理的な作業が結構大変でした。

外している図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819887/eb5ae94d-afb8-1ca3-1d06-41173b91af7b.png)
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819887/22d2b3e7-0a68-515b-685b-0f3adb191642.png)
![i.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819887/53556090-833e-eaf6-33fb-c4a363125e22.png)

## NS高生の方々へ
N/S高等学校の設備は、角川ドワンゴ学園のものだけはありません。今回のAPも企業様のネットワーク機器です。APを触ったり間取り図をいただけたのは、メンターの方を含めた様々な方に許可をとっていただいた結果です。

同じような面白いことをしたければ、メンターや通学運営部の方々に許可をとりましょう。せっかくN/S高という日本で一番自由であろう高校にいるので、確認を取れば少なくとも話を聞いてくれますし、もしかしたら今回のように実現するかもしれませんよ。

:::note alert
絶対に、許可を取らず他の人が管理しているものに触る・接続してはなりません。
:::

## おわりに
現在のこのシステムは屋内位置測定の基盤を開発しているだけに過ぎず、この基盤を使ってもっと楽しいことができるのではと考えています。今後はこの基盤を使用して、屋内版ポケモンGOや、デジタルスタンプラリーなどの制作を進めていく予定です。

この屋内GPSを作るために多くの学園関係者の方にご協力いただきました。本当にありがとうございました。
Terraform初心者必見: 7つのステップで学ぶTerraform指南書

## はじめに
Terraform歴2ヶ月の筆者が、個人的に最も効率が良いと考えるTerraformの手順を7ステップに分けて紹介します。

歴が浅い筆者でも、以下のステップでスムーズに開発できたので参考になれば嬉しいです！

## 前提:Terraformとは
Terraformは、HashiCorpによって開発されたオープンソースのインフラストラクチャアズコード（IaC）ツールです。APIを介してクラウドサービス等を安全かつ効率的に作成、管理、更新するために広く使用されています。

## Terraformの7ステップ

Terraformでのリソースの作成・管理は以下の7ステップで行うと効率的です。（筆者の感想です）

- 【step1】 キーとバケットの準備、ステートやファイルレイアウトの確認を行う
- 【step2】 GUIでリソースの確認を行う
- 【step3】 生成AIにプログラムの雛形を作ってもらう
- 【step4】 プログラムの雛形の修正
- 【step5】 `% terraform plan`で変更の差分を確認する
- 【step6】 `% terraform apply`で変更を適用し、動作確認を行う
- 【step7】(必要に応じて)`% terraform destory`で作成したリソースを削除する

以下でそれぞれのステップについて解説します。

### 【step1】 キーとバケットの準備、ステートやファイルレイアウトの確認を行う
Terraformを記述するための初期準備として、アクセスキーとシークレットキーやS3のバケットの用意が必要です。各プロジェクトごとに方法が異なると思うので、まず初めに確認してください。

またステートやファイルレイアウトなど、どこに何を記述すれば良いのかをはじめに確認してください。

:::note warn
最初の確認を怠ると、以降のTerraformプログラム実行時の律速となり、タスクの見積もりにズレが生じてしまいます。筆者はまず一番最初に確認をすると良いと考えています。
:::

### 【step2】 GUIでリソースの確認を行う
いきなりTerraformを記述したいところですが、作るものの実体を何となくでも良いので理解してからTerraformを書いた方が**圧倒的に**効率が良いです。

ここでパラメータの意味まで理解するのがベストです。

そして理解のために最も手っ取り早いのが、GUIでリソースを作ってしまうことだと考えています。作成が困難である場合（例えばVPCやサブネットの準備等で工数が大きい場合）は、作成画面でリソースの設定の確認まで出来れば良いと思います。

以下にAWSのECSonEC2を例にして説明していきます。

![スクリーンショット 2023-12-07 10.45.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/10e28e7d-6e5e-74c6-4788-32bcab28ba97.png)

ECSonEC2の作成のために必要な設定は上記です。
ここで、ASGやオペレーティングシステム、インスタンスタイプ等の詳細な設定が必要になることがわかります。

このような設定すべきパラメータを一つ一つ理解し、Terraformのプログラムに反映することが必要です。このタイミングで不明点を調べる&作成すべきものは何なのかを認識合わせすることが必要です。

:::note
パラメータがわかりやすくなっているこのタイミングで、全てのパラメータの意味を理解しておくことが今後のTerraform作成で効いてきます。
またパラメータの要件をメモしておくと、PR作成時に役に立つのでオススメです。
:::

:::note
不明点あれば、些細なことでもissueに書き溜めておくと、見つけやすく共有しやすいのでオススメです。
:::


### 【step3】 生成AIにプログラムの雛形を作ってもらう
Terraformのプログラムを記述していきます。

とは言っても初心者にとっては0から全て書くのは大変なので、生成AI(ChatGPTやCopilot)にプログラムの雛形を書いてもらいます。

この時、step2で確認した詳細な要件を具体的に入れて指示すると良いです。例えば以下の指示を出して生成AIにプログラムの雛形を作成してもらいます。

>###プロンプトの例
あなたは卓越したTerraformプログラマーであり、AWSについて専門家と同等の知識を持っています。
TerraformでECSonEC2のプログラムを書いてください。
詳細な条件は以下です。
(1)ASG新規作成(2)プロビジョニングモデルはオンデマンド(3)EC2のインスタンスタイプ:`t2.micro`(4)必要な容量は最小1、最大4(5)SSHの接続可として新しいキーペアを作成

### 【step4】 プログラムの雛形の修正
step3で生成AIが作成した雛形の完成度は100%ではないので、逐一修正することが必要です。

生成AIが作成したTerraformプログラムの設定と要件を1対1対応をさせることて過不足を判定し、それに応じてドキュメントを見ながら修正を行うと良いです。(Terraformの開発においてドキュメントは至高です。)

またstep5、step6において要件が満たされていなければ本step4に戻ります。step5の`% terraform plan`ではTerraformの文法チェックができるので、適宜使って文法の確認をすると良いかもしれません。

### 【step5】 `% terraform plan`で変更の差分を確認する
`% terraform apply`実行前に必ず変更差分を確認を行ってください。（1番最初のみ`% terraform init`が必要です。）
特に**何が作られて**、**何が消されるか**を一つ一つ確認してください。

:::note warn
リソースの削除はとても危険なので、`% terraform plan`の時点で注意深く確認してください。
:::

### 【step6】 `% terraform apply`で変更を適用し、動作確認を行う
`% terraform plan`が終わったら`% terraform apply`で適用します。
`% terraform apply`が完了したら、GUIでリソースの確認を行うと良いです。

必要に応じて動作確認のテストを行ってください。


### 【step7】 (必要に応じて)`% terraform destory`で作成したリソースを削除する
確認が終わり不要になったリソースは`% terraform destory`で一括削除できます。特にDBのインスタンスは起動しているだけでお金がかなりかかるので、不要なものは消しておくと良いと思います。

:::note warn
リソースの削除はとても危険です。実行する際には、削除してはいけないリソースがないかどうか必ず確認してください。
:::

## おわりに
以上で解説を終わります。

少しでも参考になれば幸いです。
【Tomcat】カスタムValveを作ってみた

# はじめに
[Java Advent Calendar 9日目](https://qiita.com/advent-calendar/2023/java)の投稿です。よろしくお願いします。
最近、TomcatにValveという機能があることを知ったので、作ってみたことを記事にしようと思います。

# アーキテクチャ
Tomcatは以下のコンポーネントで成り立っています。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/378dd3ff-3b59-b4cb-d6f0-21c16e133c38.png)

- Server
    - APサーバのTomcatインスタンス自身。
- Service
    - ConnectorとEnginを結びつける。
- Connector
    - リクエストを受け付ける。通信プロトコルごとにConnectorがある。
- Engine
    - リクエスト処理をおこなう。実際にはConnectorが受け付けたリクエストをHostに処理させてConnectorに返却する。
- Host
    - Tomcatがホストする仮想サーバのような役割。ドメイン名を割り当てることで仮想的に複数のホストを定義できる。
- Context
    - 仮想ホスト内で実行されるWebアプリケーション。
- Wrapper
    - Webアプリケーション内の1つのサーブレット。

# Valveって？
リクエストがリクエスト処理パイプラインを通過するときに、インタセプトを行う仕組みです。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/ceab6568-0273-4035-54ca-bdfec471c852.png)

AdapterがEngineのValveの呼び出しをして、呼び出しが終わるとHostのValveを呼び出し、HostのValveの呼び出しが終わるとContextのValveを呼び出し、、、という風に連鎖して各コンポーネントのValveを呼び出して最後にサーブレットが呼び出されます。
リクエストからサーブレットが呼び出されるまでに、各コンポーネントでインタセプトした処理を割り込むことができます。

Valveはログ出力処理や、フィルタリング処理などがTomcatから提供されていて、デフォルトではHostでログ出力のValveが有効になっています。
```server.xml
<!-- 抜粋 -->
<Host name="localhost"  appBase="webapps"
      unpackWARs="true" autoDeploy="true">

    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log" suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
```
このValveは独自で作成することができるらしいので、今回は作ってみようと思います。

## 作ってみる
Valveを作るためには、`org.apache.catalina.valves.ValveBase`を実装します。
自分は↓から取得しました（Tomcatにも入ってます）。

https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-catalina

```CustomSampleValve.java
package valve;

import java.io.IOException;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;

import jakarta.servlet.ServletException;

public class CustomSampleValve extends ValveBase{

	@Override
	public void invoke(Request request, Response response) throws IOException, ServletException {
		
		// 前処理
		before();
		
		getNext().invoke(request, response);
		
		// 後処理
		after();
	}

	private void before() {
		
		System.out.println("before do something!");
	}

	private void after() {
		
		System.out.println("after do something!");
	}
}
```
コンパイルするためには、`catalina.jar`と`servlet-api.jar`が必要です。クラスパスに追加してコンパイルします。
```
> javac -encoding UTF-8 -classpath catalina.jar;servlet-api.jar CustomSampleValve.java
```
JARファイルにして、作成したJARファイルを`$CATALINA_HOME/lib`配下に配置します。
```
> jar -cvf CustomSampleValve.jar valve/*.class
```

`server.xml`にカスタムValveの設定を追加します。
```server.xml
<!-- 抜粋 -->
<Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log" suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    <!-- 追加ここから -->
    <Valve className="valve.CustomSampleValve" />
    <!-- 追加ここまで-->
</Host>
```
以上でカスタムValveを作ってHostに設定が完了です。

Tomcatにデプロイしたアプリケーションにアクセスするとコンソールログにメッセージが表示されることを確認できます。
数珠繫ぎのコード

# はじめに

私がwebアプリケーションを開発して初めて組んだコードでの体験談です。
そのままだと出せないので疑似コード化しています。
恥ずかしくて後輩に見せられないのですが、吐き出して楽になりたいと思います。

# 数珠繫ぎって？

例えばこんな感じです。

```
function 処理を受け付ける関数（）｛
  なんらかの実行
  function 処理を実行する関数
｝

function 処理を実行する関数（）｛
  function 非同期な処理の関数（callback 成功時の処理）
｝

callback 成功時の処理（）｛
  function なんらかの後処理
｝
・・・
```

あぁぁぁ今書いていても恥ずかしい！！！（実際もっと繋がります笑）
関数内から関数コールするというのはまぁ別にだめじゃないのですが、この関数再利用してないんですよね。
１機能を実現するために関数達を処理単位で作って数珠繫ぎにしていくという。
これだとせっかく分かれている関数なのに処理の流れの中でしか使えずにただただ分割しているだけというだけでした。
こうしてしまうと受け付けたら非同期実行して成功時に〜するというのが追いかけにくい・・・と自分でも思っていました。


# 知らなかったんです

上記JavaScriptのコードなのですが、無名関数とか、即時実行関数とか当時理解していなかったことが原因かと。
少なくともcallbackのあたりは無名関数で良さそうですよね。
あとはPromiseあたりの理解ですかね。

# 今なら？

thenとかでもいいですがとりあえず
```
function async 処理を受け付ける関数 （）｛
  const result = await 非同期な処理（）
  if（result）｛
    成功時の処理
  ｝

｝
```

うん。全然違いますね。

# おわりに

過去を漁るともっとやばいでコードもありましたが、ここでは数珠繫ぎのコードを紹介させていただきました。
LangChainでChatGPTの返答をストリーミングレスポンスでSlackに返却する

1. Slack Botにメンションしてメッセージを送る
1. まず、「Typing...」とスレッドに返信が来る
1. ストレーミングレスポンスで徐々に返信が更新されていく

```
import os
import re
import time
from typing import Any

from dotenv import load_dotenv
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from langchain.chat_models import ChatOpenAI
from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema import LLMResult

CHAT_UPDATE_INTERVAL_SEC = 0.4

load_dotenv()

# ボットトークンを使ってアプリを初期化
app = App(
    signing_secret=os.environ["SLACK_SIGNING_SECRET"],
    token=os.environ["SLACK_BOT_TOKEN"],
    process_before_response=True,
)

# ストリーミングレスポンスでSlackにメッセージを送る処理の記述
class SlackStreamingCallbackHandler(BaseCallbackHandler):
    last_send_time = time.time()
    message = ""

    # メッセージを送るチャンネルやスレッド、メッセージの更新頻度を設定
    def __init__(self, channel, ts):
        self.channel = channel
        self.ts = ts
        self.interval = CHAT_UPDATE_INTERVAL_SEC
        self.update_count = 0

    # ストリーミングレスポンスを受信しSlackのメッセージを更新
    def on_llm_new_token(self, token: str, **kwargs) -> None:
        self.message += token
        
        now = time.time()
        if now - self.last_send_time > self.interval:
            self.last_send_time = now
            self.update_count += 1

            # Slackのchat_updateは１分間に50回のコール制限があるため
            # intervalを調整し、chat_updateのコール数を制御する
            if self.update_count / 10 > self.interval:
                self.interval = self.interval * 2

            app.client.chat_update(
                channel=self.channel, ts=self.ts, text=f"{self.message}..."
            )

    # ストリーミングレスポンスの最後の部分を更新
    def on_llm_end(self, response: LLMResult, **kwargs: Any) -> Any:
        app.client.chat_update(
            channel=self.channel,
            ts=self.ts,
            text=self.message
        )

# @app.event("app_mention")
def handle_mention(event, say):
    channel = event["channel"]
    thread_ts = event["ts"]
    message = re.sub("<@.*>", "", event["text"])

    # まずメッセージを返す
    result = say("\n\nTyping...", thread_ts=thread_ts)
    ts = result["ts"]

    # ChatGPTにプロンプトを投げ、返答をストリーミングレスポンスでメッセージを更新していく
    callback = SlackStreamingCallbackHandler(channel=channel, ts=ts)
    llm = ChatOpenAI(
        model_name=os.environ["OPENAI_API_MODEL"],
        temperature=os.environ["OPENAI_API_TEMPERATURE"],
        streaming=True,
        callbacks=[callback],
    )
    llm.predict(message)

def just_ack(ack):
    ack()

# lasy_listenerでhandle_mentionを非同期で実行
app.event("app_mention")(ack=just_ack, lazy=[handle_mention])

# ソケットモードハンドラーを使ってアプリを起動
if __name__ == "__main__":
    SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
```

動作結果
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37817/00d8e414-37ab-a70f-f4e1-a071999136be.gif)
国際ロボット展2023（iRex2023）に出展しました！！ これまでの経歴を添えて…

# はじめに
この記事は、<font color="Red">金沢工業大学 Advent Calendar 2023</font> :christmas_tree: の9日目の記事です！
今回は、私の経歴も含めて、<font color="Blue">国際ロボット展2023</font>に出展側で参加した感想を書いていきたいと思います。

# 自己紹介
金沢工業大学 工学部 情報工学科 4年です。[この記事](https://qiita.com/naoyuki0920/items/5f697ee7bbbc819fcbc2)を書いてから、もう2年も経ったかと思うと、時間の流れの速さを身に染みて感じます。来年から某ネットワークインフラを支えている会社でネットワークエンジニアとして働く予定です。

# 経歴
これまでやってきたことを振り返る機会ってあんまりないので、これを機に振り返りたいと思います。興味ない方は読み飛ばしてください～

| 時期 | 内容 |
| ---- | ---- |
| 2020年4月 | KIT入学 |
| 2020年12月 | みらいごとラボ、DMMWEBCAMPにjoin |
| 2021年4月 | BusStopプロジェクトにjoin |
| 2021年7月 | BusStopプロジェクトでAndroidアプリ（Kotlin ver）の開発を開始 |
| 2022年1月 | palan株式会社の長期インターンにjoin |
| 2022年7月 | Android版のっティバスどこ リリース |
| 2022年8月 | CARTA HOLDINGSのインターン「Treasure」に参加 |
| 2022年9月 | 楽天インターン「二子玉川夏の陣」に参加 |
| 2022年10月 | KotlinからFlutterに変更し新たに「のっティバスどこ」の制作開始 |
| 2023年4月 | 就活終了 |
| 2023年8月 | Flutter版のっティバスどこ リリース |
| 2023年11月 | 自分のホームページ作成 |
| 2023年11月 | 国際ロボット展2023に参加 |

大学に入学してからたくさんの経験をさせていただきました。プロジェクトの仲間やインターン先の人がいたからこそ経験できたことがたくさんあると思っています。感謝です。

特にインターンに参加したことが就職活動でとても役に立ったと思います。

# 国際ロボット展について
それでは本題です。
会場は東京ビッグサイト。初めて行きました。

![DSC_0017.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2299375/58434616-5970-969d-4bb4-1875905c63a2.jpeg)
![DSC_0019.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2299375/662371f9-32c5-1f88-7032-0c6c4aa2e487.jpeg)

僕が所属する研究室から院生3名、学部生2名、高専生1名が出展しました。
それぞれが行っている研究テーマをポスター形式で壁に貼り、会場でデモを行いました。

![IMG_4528.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2299375/d4a2cbc8-357f-2bbc-c8b5-da0beff76388.jpeg)
↑準備中の様子

### 僕の研究テーマについて
[これ](https://minorunakazawa.github.io/i2lab/poster2023/B4_masuda.pdf)です。
研究室内で実験してデータを取る分には問題なかったのですが、複数台同時接続を考慮したより実践的なデモを行った場合、ラズパイのWi-Fiモジュールでは力不足ということがわかり、機材搬出の2日前に、ラズパイのクリーンインストールを行い、システムを換装するという荒業を行いました。展示中は特に大きなトラブルがなかったので一安心でした。

![DSC_0010.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2299375/c5327cd8-6800-d288-90d3-9488e8637d02.jpeg)
↑徹夜でクリーンインストールの図

### そのほかのテーマについて
やはり院生の行っている研究は一朝一夕でできるものではないなと感じました。また、外国の方に対しても英語で対応している先輩がかっこよく見えました。英語勉強しようかな。

おなじ学部生の方もレべチでした。基盤からロボット全部作るってどういうこと！？スゴスギィ！！

全国放送の取材も2局から来ていただき、大繁盛でした。やはり遠距離恋愛抱き枕のインパクトは強いようです。
![DSC_0032.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2299375/c5345452-3d83-a791-81fb-5d485bf79cf4.jpeg)
↑取材中の様子。

### ほかのブースについて
今回の国際ロボット展2023は過去最大規模とのことで、確かにものすごい数の企業、団体が出展していました。現地だけでなく、オンライン上でも開催されていたようです。

企業のブースに至っては、どんだけお金と時間をかけてきたんだろうと勘ぐってしまうほど、すばらしいブースばかりでした。やはり、最新技術を売り出す場として力を入れているんでしょうね。そこらのポップアップストアより断然力はいってました。
ロボットにそんなに詳しくない僕でも思わず足を止めて見入ってしまうほど会場の熱気は高かったです。
たくさんのブースでいろんな人とお話ししましたが。ロボット制作に携わっている人はいい意味でとがっている人が多い印象でした。ハードウェアの知識もソフトウェアの知識も両必要な分野なので、必然的にツヨツヨな人が集まる分野なのかもしれないですね。

# さいごに
自分の大学生活を振り返りつつ、国際ロボット展の紹介をすることができました。このような機会をくれた後輩に感謝です。先日、KITの学生で執筆した技術書のVol1が発表されました。残念ながら僕は執筆できませんでしたが、Vol2を書くときは僕も参加したい！と伝えてあるので、その時がくるまでにネタを考えておきたいと思います。就職してもいろんなことに挑戦して楽しい人生を送りたいと思っています。幸い、入社先はめっちゃホワイト企業で副業もOKなので、いろんなことたくさんできますね！

ではまたどこかでお会いしましょう！最後まで見ていただきありがとうございました！！
Google Apps Script (GAS) ローカル開発環境の構築方法

Google Apps Script (GAS) ローカル開発環境の構築方法のメモ

### 必要な条件
- **VSCode** のインストール
- **Node.js** のインストール（npm使用可能）

### 開発環境の構築手順
1. **GoogleAppsScriptAPIの有効化**: 
   - GoogleAppsScriptAPIを設定画面から有効にします。

2. **asideを用いたプロジェクト作成**:
   - `npx @google/aside init` コマンドでプロジェクトを初期化。
   - claspの設定、Typescript記述、ESLint、Prettier設定、Jestテスト環境が整備されます。

3. **デプロイ**:
   - 開発環境へのデプロイ: `$ npm run deploy`
   - 本番環境へのデプロイ: `$ npm run deploy:prod`
   - 必要に応じて、`clasp-dev.json`と`clasp-prod.json`を編集します。
【Chrome拡張】Plasmoで独自の環境変数が読み込めない

# はじめに

環境変数を使いたいと思い軽く調べたが、サンプル[^1]のREADMEに詳しい使い方が書いていないため戸惑った。
当たり前だが、やりたいことがあったら最初から公式ドキュメント[^2]をよく読もう。

# 問題

`.env` に定義した環境変数が何故か読み込めない

```env:.env
HOGE=hoge
FUGA=fuga
```
```js:呼び出し側
console.log(process.env.HOGE);
// output: undefined

console.log(process.env.FUGA);
// output: undefined
```

# 解決方法

公式ドキュメントに「`PLASMO_PUBLIC_` プレフィックスがついてる環境変数だけ読み込まれます」と、しっかり書いてある。
>Only env vars prefixed with `PLASMO_PUBLIC_` will be injected.

解決方法は「全ての環境変数に `PLASMO_PUBLIC_` プレフィックスを付ける」

:::note warn
環境変数を編集した後は再度 `pnpm dev` を実行してdevサーバーを再起動してください
:::

```env:.env
# プレフィックスをつける
PLASMO_PUBLIC_HOGE=hoge
PLASMO_PUBLIC_FUGA=fuga
```
```js:呼び出し側
console.log(process.env.PLASMO_PUBLIC_HOGE);
// output: hoge

console.log(process.env.PLASMO_PUBLIC_FUGA);
// output: fuga
```

解決。

# おわりに

公式ドキュメントをよく読もう。 (n回目)

# 参考

- [サンプル](https://github.com/PlasmoHQ/examples/tree/main/with-env)
- [公式ドキュメント](https://docs.plasmo.com/framework/env#custom-environment-variables)

※記事の構成についてはこちらの記事を参考にさせていただきました。

https://qiita.com/Sicut_study/items/9b20ac5ded003cb6d55a

[^1]:https://github.com/PlasmoHQ/examples/tree/main/with-env
[^2]:https://docs.plasmo.com/framework/env#custom-environment-variables
Ubuntu22.04 で Could not resolve host

## 経緯

朝起きたらこうなっていた(何もしてないのに壊れたが、昨日の僕が多分なんかしたんだと思う)

```shell
git push
fatal: unable to access 'https://gitlab.com/hogehoge1234/fugafuga.git/': Could not resolve host: gitlab.com
```

DNSの解決ができてなさそうなので、確認のためにgoogleにcurl

```shell
curl https://www.google.co.jp/
curl: (6) Could not resolve host: www.google.co.jp
```

当たりっぽい

## 解決策

パッとググると/etc/resolv.conf を書き換えるという記事が出てくるが、Ubuntu22.04ではNetplanを利用すると良いらしい

https://ubuntu.com/server/docs/network-configuration

すでに /etc/netplan/01-netcfg.yaml が存在しているので、01より大きい数字のファイルを作成する。
ドキュメントでは99-netcfg.yamlを作ったりしているが、大きければいいので02でも可能なはず

```shell
sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/02-netcfg.yaml
sudo vim /etc/netplan/02-netcfg.yaml
```

nameserversの記述を追加する。パブリックDNSとしてよく使われているのはGoogleさんの8.8.8.8だと思う。

https://developers.google.com/speed/public-dns?hl=ja

個人的にはCloudflareさんの1.1.1.1及びフィルタリング有りの1.1.1.3をよく使っている。

https://1.1.1.1/ja-JP/


```yaml
      nameservers:
        addresses:
          - x.x.x.x
```


```02-netcfg.yaml
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  ethernets:
    ens192:
      dhcp4: true
      dhcp6: true
      dhcp-identifier: mac
      nameservers:
        addresses:
          - 1.1.1.3
    ens224:
      dhcp4: true
      dhcp6: true
      dhcp-identifier: mac
      nameservers:
        addresses:
          - 1.1.1.3
  version: 2
  ```

書き換えたらnetplan apply で設定を適用する

```shell
sudo netplan apply
```

pushできるようになった

```shell
git push
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 2 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 1.30 KiB | 667.00 KiB/s, done.
Total 6 (delta 4), reused 0 (delta 0), pack-reused 0
```

## その他メモ

今回は直接の原因ではなかったっが、systemd-resolveが起動して設定が書き換わっていることもあるらしい

https://wiki.archlinux.jp/index.php/Systemd-resolved
回転に対してのコード

local test = vci.assets.GetTransform("Empty2")
local a = 0
local SubItem = vci.assets.GetTransform("アイテムの名前")
local angle = 1

function updeteAll()
    a = 0 + 1
    if a > 360 then
        a = 0
    end
    test.SetLocalRotation(Quaternion.euler(0,a,0))

    angle = angle + 1
    SubItem.SetLocalRotation(Quaternion.Euler(-90,0,0) * Quaternion.Euler(0,0,angle))
end



 SubItem.SetLocalRotation(Quaternion.Euler(-90,0,0) * Quaternion.Euler(0,0,angle))
 ここに関しては、回転速度と軸の固定するところになります。
 そして複雑に回したいなら、(Quaternion.Euler(-90,0,0)ここを()の数字の中を変えるだけです。
 失敗したくないなら最初は、C♯で作って動きを確認してからLuaに組み込むといいかと思います。
詰まったEthチェーンのトランザクションをキャンセルする

## 注意
本手順のキャンセル処理が必ず成功するとは言い切れないため、本記事によって生じたあらゆる不利益に対して責任を負いかねます。シードフレーズに関しては慎重に扱ってください。

## 経緯
Ethチェーンのガス代をケチってAverageの半分に設定をして進めると、6,7時間経っても詰まったままで困ったため。メタマスクでガス代を高く設定して、トランザクションを送信してもエラーが表示される。

## 結論
MEW Offlineを用いてトランザクションを作成し解決しました。
日本語の解説が見当たらなかったので、備忘録として手順を記載します。

## 手順
- 前準備
    1.  トランザクションを送った端末、オフライン状態のパソコン
    2.  MyEtherWalletリポジトリの[Release](https://github.com/MyEtherWallet/MyEtherWallet/releases)より、最新版のMyEtherWallet-vx.x.x-Offlineをダウンロードして解凍。解凍したフォルダをUSBに入れてオフラインのパソコンに移す。    
- - -
- キャンセル手順
    1.  [MyEtherWallet](www.myetherwallet.com) にアクセスし、フッターまでスクロールする。
    2.  フッターのOffline Helperをクリックし、その後左のメニューのSend Offline Helperをクリック。
    3.  STEP1で任意のネットワークを選択、今回はETHを選んでNextをクリック。
    4.  STEP2で詰まったトランザクションのウォレットアドレスをFrom Addressに入力。画面下部のExport JSON fileをクリックし、ダウンロードしたJSONファイルをオフラインのパソコンに移動。
    5.  以下オフラインのパソコンで手順を進める。MyEtherWallet-略-Offlineのindex.htmlを開く。Softwareをクリックし、任意の方法で進める。（私はMnemonic Phraseを入力。）トランザクションが詰まっているアドレスとネットワークを選択。利用規約を確認して進める。
    6.  Send Offlineの画面が表示される。画面下部のUpload JSON Fileより先ほど移動したJSONファイルをアップロードする。 
        - Amount: 0
        - To Address: 詰まっているトランザクションのウォレットアドレスを入力
        - Nounce: 自動入力(詰まっているトランザクションと同じNounceを入力)
        - Data: 自動入力
        - Gas Limit: 自動入力
        - Gas Price: 自動入力(現在の[Gas gwei](https://etherscan.io/gastracker)を確認して少し高めに設定し直す)
        
        以上を確認して問題が無ければGenerate Transactionをクリック。Signed Transactionが表示され、JSONファイルをDownloadをする。
    7.  トランザクションを送った端末に戻り、Nextをクリック。オフラインのパソコンでダウンロードしたJSOONファイルをUpload JSON fileよりアップして、Confirm & Sendを押すとキャンセル用のトランザクションの作成完了です。お疲れ様でした。

ガス代を高めに設定しておけば、おおよそ数秒で反映されます。

## 解決できなかった手法
- メタマスクの再インストール
- メタマスクでガス代を高く設定しNounceを同一にしたトランザクションの送信

## 参考
[Using MEW Offline](https://help.myetherwallet.com/en/articles/6512619-using-mew-offline)
[Etherscan Gas Tracker](https://etherscan.io/gastracker)