OmniAICreator/Qiita-1.07M huggingface dataset:
STM32G031J6M6でOLEDにイメージを表示(SSD1306)(Arduino)(Adafruit SSD1306,GFX)




x 過去ログをみよ



x Adafruit GFXをインストール
x Adafruit SSD1306をインストール


x OBは、ブートをレガシーピンを有効
x OBは、PA2は、GPIO (リセット無効)


目的
OLEDのテスト

設定
ホード　- Nucleo-32
Nucleo G031K8
Enabled(generic Serial)
なし
Low Full Speed
Smallest ( -Os defult)
STM32CubeProgrammer(SWD)


![o_cop389.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4b8dc54a-6928-e67d-6906-065d0d96a095.jpeg)


![o_cop388.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a97fa262-e497-71b1-d2ee-dab6ea4482b5.jpeg)






```c++



//OLED_SSD1331_BITMAP_TEST1_UNO


//ヘッダーファイル
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


// ビットマップデータ
uint8_t databytes[8] = 

{

0b01100110,
0b10101111,
0b10111111,
0b11011111,

0b01111110,
0b01111110,
0b00111100,
0b00011000

};


//初期化
void setup() {

  //i2cの初期化
  Wire.setSDA(PA12);
  Wire.setSCL(PA11);
  Wire.begin(); //pa12 pa11

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

}//setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.fillScreen(BLACK);

  //ビットマップの表示
  display.drawBitmap(0, 0, databytes, 8, 8,  WHITE);

  // 描画バッファの内容を画面に表示
  display.display();


  delay(1000); //1秒待つ

}//loop




```
Elasticsearch Kibana構築


# はじめに
ElasticsearchとKibanaの構築についてまとめます。
OSはRocky8を使用します。
単純にレポジトリを登録し、dnfでインストールします。
## Elasticsearch インストール
1. /etc/yum.repo.d/elasticsearch.repoを作成
2. elasticsearch.repoに以下を記入
```elasticsearch.repo
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
```
3.dnfコマンドを実行して、インストールする。
```
sudo dnf install --enablerepo=elasticsearch elasticsearch
```
4.elastic ユーザのパスワードを発行
 ```
/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
```
5.elasticsearchの起動時にjournalにログが残らないようなので、
[/usr/lib/systemd/system/elasticsearch.service]内のExecStartから、
--quietを削除する
```
ExecStart=/usr/share/elasticsearch/bin/systemd-entrypoint -p ${PID_DIR}/elastics
earch.pid --quiet ← これを削除
```

6.curlコマンドで、elasticsearchの動作確認をする。
```
 curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200
```
実行すると、以下のように結果が返ってくる。
```
Enter host password for user 'elastic':
{
  "name" : "elastic",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "IWhFw9_aQU-kyfOF26xYqw",
  "version" : {
    "number" : "8.6.2",
    "build_flavor" : "default",
    "build_type" : "rpm",
    "build_hash" : "2d58d0f136141f03239816a4e360a8d17b6d8f29",
    "build_date" : "2023-02-13T09:35:20.314882762Z",
    "build_snapshot" : false,
    "lucene_version" : "9.4.2",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}
```
## Kibana インストール

1. /etc/yum.repo.d/kibana.repoを作成
2. kibana.repoに以下を記入
```kibana.repo
[kibana-8.x]
name=Kibana repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
```
3.dnfコマンドを実行して、インストールする。
```
sudo dnf install -y kibana
```
4.Elasticsearch登録用のトークンを生成する。
```
'/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana'
```
5.ブラウザからアクセスすることになるので、/etc/kibana/kibana.ymlより、以下を修正する。
```/etc/kibana/kibana.yml
server.host: "＜KibanaサーバのIPアドレス＞”
```


## KibanaへElasticSearchを登録


「 http://＜kibanaのIPアドレス＞:5601 」 へブラウザでアクセスする。以下のような画面が表示される。

![elastic_int.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143329/255db54f-59fb-0075-3063-9d78b180fe3d.png)

生成したElasticsearch登録用のトークンを入力し、[Configure Elastic]をクリックする。
トークンが通ると、code入力画面が表示されます。

![elastic_verifi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3143329/20f71d6c-1fc1-77b6-04fe-601f30b1b4b5.png)

「/usr/share/kibana/bin/kibana-verification-code」を実行し、codeを生成します。
生成したcodeを入力すると、kibanaの画面が表示されます。

## まとめ
今回は以下参照
https://www.elastic.co/guide/en/elasticsearch/reference/8.6/rpm.html
Vimを始めるならVim Bootstrap + LSP だけでよい

Vim・neovim, 十数年のつきあいです.

長い間, 設定ファイル (vimrc, init.vim) を育てメンテナンスしてきましたが, 移ろいゆくプラグイン管理や補完入力の方式などに正直つかれてきました.

今は Vim Bootstrap と neovim 標準のLSPの組み合わせで, そこそこ満足に運用できているので, そのあたりのことを紹介してみます.

# Vim Bootstrap とは

Vim Bootstrap は Vim/neovimの設定ファイルを生成してくれます.

https://vim-bootstrap.com/

https://github.com/editor-bootstrap/vim-bootstrap

いくつかのプラグインとそれらの設定とイカした外観が手に入ります.


## プログラミング言語の選択はしなくても良い

Vim Bootstrap で設定ファイルを生成する時に主に使うプログラミング言語を選んでおくと, その言語固有のプラグインと設定も加わります.

しかし, LSPを使うことを想定するなら, とりあえず選ばなくてもいいのかなと思います.

設定ファイルを `~/.config/nvim/init.vim` として設置したあとなら,

```vimscript
let g:vim_bootstrap_langs = ""
```

ここに使いたい言語を追記した上で, 次のコマンドを実行することでプログラミング言語固有の設定を追加できます.

```
:VimBootstrapUpdate
```

## 生成したファイルは変更しない

生成した設定ファイル init.vim は変更しなくても運用できるようになっています.

```vimscript
"" Include user's extra bundle
if filereadable(expand("~/.config/nvim/local_bundles.vim"))
  source ~/.config/nvim/local_bundles.vim
endif

"" Include user's local vim config
if filereadable(expand("~/.config/nvim/local_init.vim"))
  source ~/.config/nvim/local_init.vim
endif
```

自分の設定を入れたい場合は, `~/.config/nvim/local_init.vim` に, プラグインを追加したいなら `~/.config/nvim/local_bundles.vim` に追記します.

powerlineフォントを有効にすると, 見た目を特にいい感じにできるのでおすすめです.

```vimscript
let g:airline_powerline_fonts = 1
let g:airline_theme = 'luna'
```


# LSPの導入

LSPを導入する手段はいくつかありますが, いまはneovim組み込みのLSPで導入しています.

この記事を参考にしました.

https://zenn.dev/botamotch/articles/21073d78bc68bf

言語固有のオペレーションは可能な限りLSPで賄う. LSPでカバーできないと思ったら, 別途プラグインを用意するくらいの方針でいいかなと思っています.

# 所感

* 良くも悪くもプラグインや設定へのこだわりがなくなる.
* Vim Bootstrap にて導入済みのプラグインや設定を把握しておく必要はないけど, ときどき init.vim を覗いたり, `:map` コマンドで使い方やキーマップを調べて理解を深めることに努める.
* 使いづらいと思った設定やキーマップは, 調べてどんどん変更する.
NestとReactを使った簡易版twitterの作成

# NestとReactを使った簡易版twitterの作成
事前学習お疲れ様でした。多くの学習サイトがあり大変だったと思います。
今回は、事前学習で勉強してきたことを元にNestとReactを使った簡易版twitterの作成をしていきます。


* 環境構築編：[NestとReactを使った簡易版twitterの作成-環境構築編](https://qiita.com/toshiki19/items/f6ee7a1738aec6522430)
* バックエンド編：[NestとReactを使った簡易版twitterの作成-バックエンド編](https://qiita.com/toshiki19/items/ea4db21f2e19ebff6a22)
* フロントエンド編：[NestとReactを使った簡易版twitterの作成-フロントエンド編](https://qiita.com/toshiki19/items/9b47e629bc36a4cc37b9)

確認はしておりますが、バグ等があったらslackでご報告ください。

# 提出
提出方式:動作のスクショもしくは動画をスラックに投稿(ソースコード送ってくれればレビューとかします)
提出期限:3/10 23:59
提出内容:環境構築編〜フロントエンド編

# 注意
この教材は全部3年生が自作したものです。内容やコードの書き方はできるだけ正確性を重視していますが、あくまでも個人の意見です。

取り組む際、ソースコードを完全に理解する必要はありません。今回はWebアプリ制作に慣れてもらうことが目的です。
動くものを完成することが大事です。DONE IS BETTER THAN PERFECT ってザッカーバーグも言ってます。
理解を深めたい場合はそれぞれの作者、Slackでお気軽にお聞きください。
LaravelでTarget class [App\Http\Controllers\〇〇Controller] does not exist.が出た時の対処法

# この記事の背景
Laravelサーバーを起動する時に以下のエラーが出てしまい止まってしまいました。

![スクリーンショット 2023-02-26 3.56.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748789/91b4bf34-c573-db77-abd5-e34501def865.png)

調べたらなんだそんなものかーって感じでしたね。

# 解決法
下の参考資料をヒントにしたら解決できました。

```UsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index()
    {
        return view('welcome');
    }
}
```
usersControllerを作成しました。

```web.php
<?php

Route::get('/', 'UsersController@index');
```
ルーティングでは***'UsersController@index'***で設定していたにもかかわらず
usersControllerでは***UserController***になっていました。***UsersController***に修正しました。

```UsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UsersController extends Controller
{
    public function index()
    {
        return view('welcome');
    }
}
```

# よくあるミス
参考資料にも書いてあるのですが、Target class ~  does not exist.だと
以下の原因があるみたいです。

```1. コントローラのnamespaceが間違っている```

```2. 複製したコントローラのエクステンドが違う```

```3. ルーティングのスペルミスかパスが違う```

```4. コントローラーに記述した use App\Xxxx\xxxxで大文字小文字の違い```

下の資料に詳しく書いてあるので参考にしてみてください。


# 参考資料

https://qiita.com/kawa_matsu/items/607ccb742235ea04bf0c
CISSPとCEHについて（個人的な比較）

# はじめに

以下の記事について自分の見解も含めて書いていきます。というかわりと有名な記事かもしれません。。

https://www.isc2.org/articles/CISSP-versus-the-CEH-certification#

# Who am i ?

IT系の会社で仕事をしています。ちなみにCISSPとCEHは既に取得済です。

# 想定読者

特になし

# 本題

結論からいうとその人の立場で変わるのでは？というのが自分の意見なのですが、私の経験上ではCISSPを取得している人はCEHも取得していることが多いので、どっちが優れているとかそういう考えはあまり意味をなさない気がします。

https://www.isc2.org/articles/CISSP-versus-the-CEH-certification#

CISSPについては有名かもしれませんが、基本的にはCISOや経営者の立場等を踏まえた上で、国の法律などを気にする前段階として、「そもそも組織としてビジネスを継続するためにはこういう人間の倫理観や考え方が必要だよ」と説いています。いわゆるCISSP的な考え方というやつです。

一方でCEHにも似たような考え方を求められている所があって、ホワイトハッカーとしての倫理感についても理解しておく必要があります。ツールの使い方（コマンドのオプションなど）もそうなのですが、結局の所、求められている考え方自体はオーバーラップしている所が多かれ少なかれ存在します。

もちろん、試験問題数や試験時間などではCISSPの方がきついということは承知の上ですけどね。CEHは教育受講をすれば審査も不要になるので。


# 余談

そういえば最近、EC-CouncilからCCISOという資格が出てましたよね。。こちらにも少し興味が出てきました。

https://ciso.eccouncil.org/cciso-certification/

# 終わりに

セキュリティの資格はどんどん新しいものが出てきて楽しいですね！
LaravelでUnfined type 'Route'と出た時の対処法

# この記事の背景
Laravelを学んでいる時にweb.phpでRouteの記述をした時に以下のようなエラーが出ました。

```web.php
<?php

//省略

Route::get('/', 'UsersController@index');
```
```Unfined type 'Route'```と出てきてなかなか解決できませんでした。

# 解決法
単純に```LaravelでUnfined type 'Route'```でググってみると参考資料から
以下のパターンが参考資料から出てきました。

***対処法2：use Illuminate\Support\Facades\xxx を記載***

これをweb.phpに追記しました。

```web.php
<?php

use Illuminate\Support\Facades\Route; //追記

//省略

Route::get('/', 'UsersController@index');
 ```
これで解決しました。

その他のエラーも

```
use Illuminate\Support\Facades\Hash
use Illuminate\Support\Facades\DB
use Illuminate\Support\Facades\Auth
```
など最後の部分を変えていけばエラーは解決しそうです。


# 参考資料

https://zenn.dev/hainare/articles/1997e2e6703f67
OpenFOAMの結果をblenderで可視化してみる#05 Blenderでの読み込み

# はじめに
今回は，Paraviewで生成したopenFOAMの結果のx3dファイルをBlenderで読み込む

# Blender での読み込み
Blenderでx3dファイルを読み込む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/a5e16fde-2113-154f-571d-d0a032fd9925.png)

読み込むと，以下のオブジェクトが生成される。
- DirectLight.xxx
- Shape_IndexedFaceSet
- Viewpoint

このうち，流体の箇所を表すのは，Shape_IndexedFaceSetであり，ほかのものはいらない。
ちなみに，Viewpointは，x3dを出力した際のParaviewでの視点となっている．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/6a1b2bef-c16f-19cf-5c1e-4dc1440f3274.png)

# Blender Scriptによる複数データの読み込み
GUIからx3dファイルを読み込む場合は，複数ファイルを読み込むことができないため，pythonでデータを読み込むこととする。
以下のスクリプトでは，ファイルを読み込み，読み込まれたもののうち，オブジェクトのタイプがMESH以外のもの（上記で説明した視点やライトのオブジェクト）を削除している．
``` python
import glob
import bpy
from pathlib import Path
TARGET_DIRECTORY=r"C:\GithubData\OpenFOAM_Vis_Blender\cal_data\PV_x3d"

#TARGET_DIRECTORYに保存されているx3dファイルを読み込む
lists = Path(TARGET_DIRECTORY).glob("*.x3d")
for fullPath in list(lists):
    bpy.ops.import_scene.x3d(filepath=str(fullPath))

#MESH以外を削除
for i in bpy.data.objects:
    print(i.type)
    if i.type != "MESH":
        print("del")
        bpy.data.objects.remove(i, do_unlink=True)
```

これで読み込むと以下のように，各ステップのメッシュが表示されるはず．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/7b860b61-ae51-0cc4-f8f4-5ded34818e54.png)

# キーを打つ
Blenderでアニメーションを生成できるように，各オブジェクトにキーフレームを設定する。
ここでは，5フレーム（dt）ごとに表示させるobjectを切り替えている。

``` python
import bpy

def on_of_setanimation(ob, t):
    bpy.context.scene.frame_set(0)
    ob.hide_viewport  = True
    ob.hide_render = True
    ob.keyframe_insert(data_path="hide_viewport")
    ob.keyframe_insert(data_path="hide_render")

    bpy.context.scene.frame_set(t[0])
    ob.hide_viewport  = False
    ob.hide_render = False
    ob.keyframe_insert(data_path="hide_viewport")
    ob.keyframe_insert(data_path="hide_render")

    bpy.context.scene.frame_set(t[1])
    ob.hide_viewport  = True
    ob.hide_render = True
    ob.keyframe_insert(data_path="hide_viewport")
    ob.keyframe_insert(data_path="hide_render")
    
    
obs = bpy.data.objects
t0 = 0
dt = 5
for i, ob in enumerate(obs):
    if ob.type == "MESH":
        t = [dt*i, dt*(i+1)]
        on_of_setanimation(ob, t)
```
blenderで表示した例
![Loop-animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601976/150cf6df-d658-2463-3f43-603968d286ee.gif)
Android Kotlin fundamentals 1

![スクリーンショット 2023-02-26 2.41.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275576/373e350c-7535-883a-4856-f69ec2e96633.png)

# トレーニングコース
 - [Android Kotlin の基礎](https://developer.android.com/codelabs/kotlin-android-training-get-started#2)

# メモ

 - すべてのアプリには、エントリ ポイントとして少なくとも 1 つのアクティビティが必要です。このエントリ ポイント アクティビティは、main()他のプログラムの機能と考えてください。

 - Package nameについて。会社のドメインとしてデフォルトのandroid.example.comを受け入れるか、固有の会社のドメインを作成します。この値にアプリの名前を加えたものが、アプリのパッケージ名です。アプリを公開する予定がない場合は、デフォルトを受け入れてください。アプリのパッケージ名は後で変更できますが、それは余分な作業です。

 - 最小 API レベルがAPI 19: Android 4.4 (KitKat)であることを確認します。 この Codelab が作成された時点で、Android Studio は、この API レベルでは、アプリがデバイスの約 95.3% で実行されることを示していました。

 - 	3.generatedJavaフォルダーに注意してください。このフォルダーには、Android Studio がアプリをビルドするときに生成するファイルが含まれています。アプリを再構築すると、変更内容が上書きされる可能性があるため、このフォルダーでは何も編集しないでください。ただし、デバッグ中にこれらのファイルを確認する必要がある場合は、このフォルダーについて知っておくと便利です。

 - resフォルダーには、リソースが保持されます。Android のリソースは、アプリで使用される静的コンテンツです。リソースには、画像、テキスト文字列、画面レイアウト、スタイル、および 16 進数の色や標準寸法などの値が含まれます。

 - Manifestについて。<intent-filter>内の要素に注意してください<activity>。このインテント フィルタの要素<action>と<category>要素は、ユーザーがランチャー アイコンをクリックしたときにアプリを起動する場所を Android に伝えます。

 - gradleについて。2.build.gradle(Project: HelloWorld)ファイルを探します。
このファイルには、プロジェクトを構成するすべてのモジュールに共通の構成オプションが含まれています。すべての Android Studio プロジェクトには、最上位の Gradle ビルド ファイルが 1 つ含まれています。このファイルは、プロジェクト内のすべてのモジュールに共通の Gradle リポジトリと依存関係を定義します。
 - 3.build.gradle(Module:app)ファイルを探します。プロジェクト レベルのbuild.gradleファイルに加えて、各モジュールにはbuild.gradle独自のファイルがあります。モジュール レベルのbuild.gradleファイルを使用すると、各モジュールのビルド設定を構成できます。(HelloWorld アプリには、アプリ自体のモジュールという 1 つのモジュールしかありません。) このbuild.gradleファイルは、アプリ レベルのビルド構成を変更するときに最も頻繁に編集するファイルです。
VBA ある文字がCobining DiaCritical Marksと合成されているかを判定する関数

# 分記要素とでも訳すべき
https://symbl.cc/jp/unicode/blocks/combining-diacritical-marks/
英語でも日本語でも長すぎる。
分記要素とすべきだろう。要素だから合成可能。分記は分音記号の意味。
そもそもDiaCritical自体が分音記号という意味があるので冗長ですらある。
このような分記要素が追加されているか、判定する関数がVBAにはない。
[Splitting string by combining character groups](https://stackoverflow.com/questions/48819144/splitting-string-by-combining-character-groups)
ここをヒントにして、2つの関数を作った。
まず分音記号要素が使われているかどうかを判定する関数である。
# 現在はVersion 1.0だけ
Combining Diacritical Marks (0300–036F), since version 1.0, with modifications in subsequent versions down to 4.1
1.0だけといっても、コード上は後から追加すればいいような気もするが0300台よりさらにマイナーになる。
Combining Diacritical Marks Extended (1AB0–1AFF), version 7.0
https://symbl.cc/jp/unicode/blocks/combining-diacritical-marks-extended/
そもそも表示できない
Combining Diacritical Marks Supplement (1DC0–1DFF), versions 4.1 to 5.2
https://symbl.cc/jp/unicode/blocks/combining-diacritical-marks-supplement/
古代ギリシア語！？
Combining Diacritical Marks for Symbols (20D0–20FF), since version 1.0, with modifications in subsequent versions down to 5.1
https://symbl.cc/jp/unicode/blocks/combining-diacritical-marks-for-symbols/
記号用ダイアクリティカルマーク（合成可能）

などがあるが使い方が思い浮かばない。

# コードの原理
Len関数で文字の長さを計る。あれば必ず2字以上になる。
`        char = AscW(Mid(str, i, 1))`
### 鍵は2つ
#### 1 AscWとMid
まずMidを使う。そして
<Font color = "Bright Red">Asc</font><Font color = "Red">W</font>(<b>Mid</b>(str, i, <font color ="blue black"><b>1</b></Font>))

<ol>
<li> AscWを使う
<li> Midを使う。
<li> Midで切るのは1字
</ol>

#### 2 値が該当するか

`If Not (char >= &H300 And char <= &H36F) `
ここで判定している。
理論的に言えば、ここのコードを追加すれば他も判定できそうだ。しかし、使用されている状況が不明なため、これ以上はコードを改善することが難しい。

```vb
Function isDiaCriticalMark(str As Variant) As Boolean
Dim i As Long
Dim strLen As Integer
  strLen = Len(str)
 Dim unicode() As String
    ReDim unicode(strLen)
 Dim unicodeLength As Integer
     unicodeLength = 0

    ' Split str into unicode()
 Dim char As Integer
    For i = 1 To strLen
        char = AscW(Mid(str, i, 1))
      If Not (char >= &H300 And char <= &H36F) Then
                unicodeLength = unicodeLength + 1
        Else
                isDiaCriticalMark = True
                Exit Function
       End If

    Next i
isDiaCriticalMark = False
Exit Function
End Function
```

# 1文字になっているのはそのままなので検知できない。
例えば
 &#xC4;
これは1文字`&ExC4;`なので分音記号を分解できないため、記号があるかどうか判定できない。
ただし、こうした文字はコード表ではある程度固まっているので、必要であれば正規表現で探して判定することになるだろう。そもそも分解して分記要素の有無を判定するのはコードが変わるからだが、`&ExC4;`は分解できないし、そのまま入力もコードに変換することも可能なので、今回の関数の判定対象でない。別途作成する必要がある。

# このコードの必要性
## 目的と長所
例えばダブルローラインはU+2017に分解されることがあるが、実際にコードポイントとして存在する。&#x2017;`&#x2017;`しかし、これは合成可能ではない。合成可能なものは&#x0333;`&#x0333;`である。ところが文字の分解のしかたを間違うと、0333が出てこない。そこで、この関数で判定して分解方法を変える必要がある。ほかにやり方があるのかもしれないが、とりあえず、これだとWinApiや参照設定は必要ない。

## 短所
 - 最初から1文字になっているものは判定できない。例&#xC4;`&#xC4;`
 - 2文字以上連続している場合に向かない。
 - 主要なコード0300番台のみ判定。しかしこれでもかなり判定できる。あとは表示ができないとか、古代ギリシア語など。表示ができずさらに使い方がわからないので今回は断念。判定を追加すればいいと思われるが確証が持てない。
PycharmからEC2のmysqlサーバに接続する。

# 外部からEC2のMySqlサーバに接続する
ツール:Pycharm professional

## 概要
* 参画しているプロジェクトの環境整備でデータベースとの接続を行う必要があったのでメモとして残しておきます。

* 前提としてサーバ内にmysqlクライアントでデータベースを作成して何かしらのテーブルも作成している。

* 外部(ローカル)からこのサーバに接続したい人向け

### 手順
![スクリーンショット 2023-02-26 0.39.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/24876265-eb49-a413-2a3c-302cfc68bdcc.png)

1.データベースを押す
2.+からデータソースを選択する

![スクリーンショット 2023-02-26 0.41.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/db9f12e3-7088-941f-ba32-244d9e227c20.png)

3.データソースからMySQLを選択する

![スクリーンショット 2023-02-26 0.42.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/3737fae6-7250-b839-c63f-1a3dbb8aa63e.png)

こんな画面になるからSSH/SSLを選択。この時接続したいデータベースを置いているサーバの3306番のportが空いてることを確認する。

4.SSHトンネルにチェックをつけ右端の紙マーク(?)をクリック

![スクリーンショット 2023-02-26 0.47.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/41f33a3b-9541-728f-46a1-9e3b0de35539.png)

5.ホスト(H)にパブリックipアドレスを入力
6.認証タイプをキーペアを選択(人によって違う、自分の場合は鍵認証にしてるのでこれにする)
7.秘密鍵ファイルに秘密鍵への絶対パスを記入
8.接続テストを押してテスト成功すればとりあえずトンネリング設定はオッケー

![スクリーンショット 2023-02-26 0.55.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/07a8a192-92d1-c1cc-a0df-e1d0abed66d7.png)

9.OKを押して一般に戻る
![スクリーンショット 2023-02-26 0.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/1c63a568-e0eb-36b3-cf31-0c94c5bf100e.png)

10.ユーザにmysqlに登録しているユーザ名を入力(開発環境なら大体root?)
11.パスワードにユーザと一緒に登録したパスワードを入力
12.保存に関しては用途によって自由に選択しよう
13.データベースに接続先に作ってあるデータベース名を入力
14.接続テストをしてみて成功すればほぼオッケー
![スクリーンショット 2023-02-26 1.01.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/2e0b942d-275c-28a3-a653-f0aa0d75975d.png)

15.OKを押したら右の枠に接続先のサーバでCREATEしてあるテーブルが表示されればOK

![スクリーンショット 2023-02-26 1.05.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074783/0434dcef-7a94-4359-20a9-c2abff4de2e0.png)

### 振り返り
大学の授業ではデータベースとの接続は完全に先生が作成した資料を全コピーでやってきて自分でできるか不安だったけどjetbrainsのIDEは直感的にさわれてスムーズに設定できた。IDE最高！
開発手法について

開発手法とは、プロジェクトを実行するための手順や方法論のことです。これには、ウォーターフォール、アジャイル、スクラムなどの様々な手法があります。

## ウォーターフォール

### 概要

ウォーターフォールは、最初に全体の計画を立て、その後、段階的に開発を進めていく手法です。一度に1つのフェーズ（計画、設計、開発、テスト、運用）を完了させてから、次のフェーズに進みます。

### 利点

- 進捗状況を管理しやすい。
- 計画に基づいた開発ができるため、品質を保証しやすい。

### 欠点

- フェーズごとに完了するため、変更に対応しづらい。
- 完成物ができるまで顧客に見せることができず、顧客のニーズに合わせた開発がしにくい。

## アジャイル

### 概要

アジャイルは、小さなサイクルで開発を進め、顧客のフィードバックを取り入れながら進めていく手法です。開発チームと顧客が密にコミュニケーションを取り合いながら、柔軟に開発を進めていきます。

### 利点

- 顧客のニーズに合わせた開発ができる。
- 開発チームと顧客が密にコミュニケーションを取れるため、トラブルや問題に素早く対応できる。

### 欠点

- 進捗状況が不透明になりやすい。
- チームメンバーのスキルやコミュニケーション能力に依存しやすい。

## スクラム

### 概要

スクラムは、アジャイルの中でも開発チームが自己組織化され、目標に向けて取り組んでいく手法です。開発チームは2週間から4週間の「スプリント」と呼ばれる短い期間で、プロダクトの一部を完成させていきます。

### 利点

- 開発チームが自己組織化されるため、高い生産性を実現できる。
- スプリントごとに成果物が出るため、進捗状況が明確になる。

### 欠点

- 開発チームが自己組織化されるため、組織によっては適用しづらい場合がある。
- スプリントごとに成果物が出るため、計画変更に対応しづらい場合がある。
timeBeginPeriod でどう変わるのか

# これは何？

先日。Windows の禁断のAPI だった [`timeBeginPeriod`](https://learn.microsoft.com/ja-jp/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) の仕様が変わったことに気がついた。

普通に使って良さそうなので使ってみてどうなるか試してみた。

# timeBeginPeriod - 禁断のAPI からの仕様変更

先程のリンクにある通り、昔は

> Windows 10バージョン 2004 より前のバージョンでは、この関数はグローバル Windows 設定に影響します。 

という邪悪な API だった。どこかのプロセスが `timeBeginPeriod` を呼ぶと、そのプロセスを動かしている OS 全体の動きが変わり、何も知らない Excel とかも巻き込まれる。

組み込み機器上で動いている Windows 以外で呼ぶのは禁忌とされていた。と思う。

それが

> Windows 10 バージョン 2004 以降では、この関数はグローバル タイマー解決に影響しなくなりました。 【略】 この関数を呼び出していないプロセスの場合、Windows は既定のシステム解像度よりも高い解像度を保証しません。

となり、安心して呼んでいい感じになった。

ちなみに「Windows 10 バージョン 2004」の 2004 ってのは '20年4月 のことなので、約三年前。2004年じゃない。

# 試してみたこと

go の `time.Ticker` で 1ms 間隔でなんかする、という処理を試みたらどうなるのかを試してみた。

```go:go
func test(msg string) {
	const size = 5000
	ticks := make([]uint64, 0, size)
	ticker := time.NewTicker(time.Millisecond)
	defer ticker.Stop()
	for range ticker.C {
		ticks = append(ticks, queryPerformanceCounter())
		if size < len(ticks) {
			break
		}
	}
	show(msg, ticks)
}
```

こんな感じ。`queryPerformanceCounter` は `syscall.LoadDLL` で呼べるようにしてある。

`timeBeginPeriod` にわたす値を 1, 15, 16, 256 と変えてみて、処理が来る時間を記録。
ついでに macOS でも記録。
前回時刻との差がどう分布するのかをグラフにしたのが下図。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6854/90af0828-d01b-4dc9-3c62-ba68a079cc60.png)

「before」は、`timeBeginPeriod` を呼ぶ前。「tbp:N」は、 `timeBeginPeriod(N)` を呼んだあと。
「macOS」は macOS上なので `timeBeginPeriod` は無関係。

縦軸はミリ秒。横軸は頻度。

ターゲット環境は、macOS 以外は、いわゆる Windows 11 2022。CPU は Ryzen 3 PRO 4350G。
macOS は、MacBook Pro (Apple M1 Pro 非MAX)。

負荷は特にかけてないけど、負荷がかからないような努力もしていない。全然厳密じゃない感じ。

グラフを見ると

* 1と15 は同じ。
* 呼ぶ前と 16・256 は同じ。

という事になっているように見える。

1 と 15 は、1ms 付近と 2ms 付近の二箇所に山がある。最長でも 3ms ぐらいの間隔になる。

呼ぶ前・16・256 は、16ms 付近に山があり、1ms 間隔になることはない模様。

# まとめ

Windows で `timeBeginPeriod(1)` の効果は絶大。
今までは `time.Ticker` で 1ms と指定しても 16ms にしかならなかったのが、CPU が暇なら、半分以上は 1ms 間隔になるっぽい。

しかし、macOS なんかとくらべると精度が低く、2ms になっちゃうことも多い。残念。

# 蛇足

1ms より短くできないのも残念。

禁断の関数 `timeBeginPeriod` の闇の力を利用していた人は、この仕様変更で困ることになった思う。

そういう意味では、別の API を用意してくれたほうがハッピーだったと思うけど、そうできなかった理由はなんだろうね。
CloudFormationのクロススタック参照とスタックのネスト化の違いについて


CloudFormationのベストプラクティスに沿って
とりあえずスタックを分割したものの、
実際に使う際にはスタックをまとめて使いたい時って結構ありますよね。

ちなみにCloudFormationのベストプラクティスについては
以下の公式サイト参照

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/best-practices.html

そんな時に便利なのが、クロススタック参照とスタックのネスト化ですが、先に結論を言っておくと、公式で推奨しているのは「クロススタック参照」です。

ただ、用途によってはスタックをネスト化した方が便利な場合も？(あるかも)

ってことで、私が実際に試行錯誤して得た知識を記事に残しておこうと思います
図は拡大参照推奨です！！

◆クロススタック参照◆

![クロススタック参照.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840619/8cbda208-aef8-8f8e-71f9-3d29aafa5f61.jpeg)


◆スタックのネスト化◆
【概要】

![スタックのネスト化1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840619/d3859b50-977b-17de-0c35-5b18e62eaaac.jpeg)


【詳細】

![スタックのネスト化2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840619/f34ff903-3ea0-261c-c3a8-fa286a39d720.jpeg)



◆結論◆
大規模アーキテクチャでのスタックのネスト化は
管理が煩雑になるためおすすめしませんが
お試し環境(テスト環境よりさらに格下環境)など、
ワンオペで環境構築したい場合は
スタックをネスト化しておくのも一つの方法かもしれません。

CloudFormationのスタックについて理解度向上に繋がれば幸いです。
最後までお読みいただきありがとうございました！

コメントやいいねをいただけると励みになりますのでお願いいたします。
整数の除算「整数 / 整数」は、ゼロ側の整数へ寄せる動作になる (正負の間で特性が変わり特殊)

# ゼロ付近の整数の除算

ゼロ付近の「整数 / 整数」の整数の除算を、下記のコードで確認すると、

(int: 7→-7までをint: 3で割った時)
```C#
using System;

namespace ConsoleApp1 {
    class Program {
        static void Main(string[] args) {
            /* 結果: 
▼ゼロ付近の整数除算の確認用 正値・負値の双方でゼロ側の整数へ寄せるFloorとなる
int:  7 / 3 =  2
int:  6 / 3 =  2
int:  5 / 3 =  1
int:  4 / 3 =  1
int:  3 / 3 =  1
int:  2 / 3 =  0
int:  1 / 3 =  0
int:  0 / 3 =  0
int: -1 / 3 =  0
int: -2 / 3 =  0
int: -3 / 3 = -1
int: -4 / 3 = -1
int: -5 / 3 = -1
int: -6 / 3 = -2
int: -7 / 3 = -2
            */

            WL("▼ゼロ付近の整数除算の確認用 正値・負値の双方でゼロ側の整数へ寄せるFloorとなる");
            var a = 7;
            var b = 3;
            for (; a >= -7; a--) {
                var c = a / b;
                WL($"int: {a,2} / {b} = {c,2}");
            }
        }
    }
}
```

ゼロ付近では、ゼロが5回続く結果となり、ゼロ側の整数へ寄せる動作となることが分かります。(これは、正の範囲ではFloor、負の範囲ではCeilをした結果と同じ)

# double型でのMath.Floor・Math.Ceilingの動作

double型でのMath.Floor・Math.Ceilingの本来の動作を、下記のコードで確認してみると、

```C#
using System;

namespace ConsoleApp1 {
    class Program {
        static void Main(string[] args) {
            /* 結果: 
▼ゼロ付近のFloor関数の確認用 正値・負値の双方で小さい側の整数へ寄せる
double:  7 / 3 =  2
double:  6 / 3 =  2
double:  5 / 3 =  1
double:  4 / 3 =  1
double:  3 / 3 =  1
double:  2 / 3 =  0
double:  1 / 3 =  0
double:  0 / 3 =  0
double: -1 / 3 = -1
double: -2 / 3 = -1
double: -3 / 3 = -1
double: -4 / 3 = -2
double: -5 / 3 = -2
double: -6 / 3 = -2
double: -7 / 3 = -3

▼ゼロ付近のCeil関数の確認用 正値・負値の双方で大きい側の整数へ寄せる
double:  7 / 3 =  3
double:  6 / 3 =  2
double:  5 / 3 =  2
double:  4 / 3 =  2
double:  3 / 3 =  1
double:  2 / 3 =  1
double:  1 / 3 =  1
double:  0 / 3 =  0
double: -1 / 3 = -0
double: -2 / 3 = -0
double: -3 / 3 = -1
double: -4 / 3 = -1
double: -5 / 3 = -1
double: -6 / 3 = -2
double: -7 / 3 = -2
            */

            WL("▼ゼロ付近のFloor関数の確認用 正値・負値の双方で小さい側の整数へ寄せる");
            var p = 7.0;
            var q = 3.0;
            for (; p >= -7; p--) {
                var r = Math.Floor(p / q);
                WL($"double: {p,2} / {q} = {r,2}");
            }
            WL("");

            WL("▼ゼロ付近のCeil関数の確認用 正値・負値の双方で大きい側の整数へ寄せる");
            p = 7.0;
            q = 3.0;
            for (; p >= -7; p--) {
                var r = Math.Ceiling(p / q);
                WL($"double: {p,2} / {q} = {r,2}");
            }
        }
    }
}
```

* Floor関数は、正値・負値の双方で、常に小さい側の整数へ寄せる動作となり、
* Ceiling関数は、正値・負値の双方で、常に大きい側の整数へ寄せる動作となる

ことが分かります。

# 整数の除算は正負の間で特性が変わり特殊

前章で、double型でのMath.Floor・Math.Ceilingの本来の動作を調べた結果と比べると、

整数の除算「整数 / 整数」は負値を含めると特殊で、正負の間で特性が変わり、正の範囲ではFloorの値、負の範囲ではCeilの値と同じになっています。
Javascript(Typescript) Map vs Object(インデックスシグネチャ)

どちらもキーバリューで管理できますが使い分けについて調べたり考えてみたので記載。

## Map
・キーにString、シンボル以外も使える
・iterableである
・プロトタイプチェーンによるプロパティはない
```typescript
const mp = new Map();
mp.set("hoge", "hogeValue");
mp.set(1, "one");
mp.set(true, true);

mp.forEach((v, k) => {
  console.log(k); // hoge, 1, true
  console.log(v); // hogeValue, one, true
});

// こういうふうにロジックを入れることも可能
mp.set("fn", () => console.log("execute"));
mp.get("fn")(); // execute
```

もちろんtypescriptであれば下記のように型定義もできます
```typescript
const mp = new Map<string, string>();
mp.set(1, "one"); // エラー. Argument of type 'number' is not assignable to parameter of type 'string'.
```

## object（インデックスシグネチャ）
・キーにstring, シンボルしか使えない
・iterableでない
・プロトタイプチェーンによるプロパティが存在する
```typescript
const obj = {
  hoge: 'hogeValue',
  1: 'one',
}

// objectでイテレートしたい場合は下記のように
Object.entries(obj).forEach(([k, v]) => {
  console.log(k); // hoge, 1
  console.log(v); // hogeValue, one
});
```

## どっちが良いん？
基本的にはMapを使っていくべきと感じました。
~~ただ、私は一意なキーバリューを定数として定義し、区分値の変換として使うことが多く、その際はobjectを使うとエラー出してくれるので重宝しています。~~
~~（プログラムミスによる定義重複を検出できます）~~

すみません、Javascriptだと後勝ちとなるようです。。。普段Typescriptでしか書いてないので気づきませんでした。。。
Typescriptだとtscやlinterでエラーとしてくれるので、この書き方をよくしています。
TypescriptはEnumあるじゃん！という意見もあると思うのでEnumではなくobjectを使う理由は別途まとめようと思います（ググるといっぱい出てくるけど。。。）

```typescript
const STATUS_OBJ = {
  success: "成功",
  warn: "警告",
  success: "成功2", // エラー. An object literal cannot have multiple properties with the same name.
}

const STATUS_MAP = new Map(
  [
    ["success", "成功"],
    ["warn", "警告"],
    ["success", "成功2"] // エラー出てほしいけど出ない。後から定義されたもので上書きされる
  ]
);
```

以上です。他の視点があれば教えてください。
【C++】漸化式と行列累乗

# 何の記事か
漸化式を行列に変換することで、より高速に高次の項を求めることができる「行列累乗」というアルゴリズムについて説明するとともに、2項間漸化式を例にとって``C++``での実装例を紹介する記事です。(この記事の内容は[蟻本](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8%E3%83%96%E3%83%83%E3%82%AF-%E7%AC%AC2%E7%89%88-%EF%BD%9E%E5%95%8F%E9%A1%8C%E8%A7%A3%E6%B1%BA%E3%81%AE%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E6%B4%BB%E7%94%A8%E5%8A%9B%E3%81%A8%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF%E3%82%92%E9%8D%9B%E3%81%88%E3%82%8B%EF%BD%9E-%E7%A7%8B%E8%91%89%E6%8B%93%E5%93%89/dp/4839941068)3-4節の内容に基づきます。)
# 2項間漸化式の行列累乗
例えば次のような問題を考えます。

- 数列${a_i}$が、$a_0=s,a_1=t$で、
```math
a_{i+2} = pa_{i+1}+qa_i
```
のような関係式で記述されるとき、$n=10^{16}$に対して$a_n$を$998244353$で割ったあまりを求めてください。


こういった問題を、行列累乗を用いることで$O(logn)$で解くことができます。漸化式を行列を用いて表すと、
```math
\begin{pmatrix}
a_{i+2} \\
a_{i+1}
\end{pmatrix}
=
\begin{pmatrix}
p &q \\
1 & 0
\end{pmatrix}
\begin{pmatrix}
a_{i+1} \\
a_{i}
\end{pmatrix}
```
となることが分かります。つまり、
```math
\begin{pmatrix}
p &q \\
1 & 0
\end{pmatrix}
= A
```
とすると、
```math
\begin{pmatrix}
a_{n+1} \\
a_{n}
\end{pmatrix}
=
A^n
\begin{pmatrix}
a_{1} \\
a_{0}
\end{pmatrix}
```
のようにして$a_n$を求めることができるのが分かります。ではどうやって$A_n$を求めるかというと、繰り返し二乗法を行列演算に拡張することで$O(logn)$で求まります。繰り返し二乗法は、$n$を$2$の累乗の和で表して、$i$乗の項を二乗することで$i+1$乗の項を求めることを言います。$n$をシフトするだけなので実装は非常に単純です。

```cpp
const int M = 998244353;
typedef vector<int> vi;
typedef vector<vi> vvi;

//行列の乗算
vvi matrix_multiply(vvi X, vvi Y) {
	vvi Z(X.size(), vi(Y[0].size()));
	rep(i, X.size()) {
		rep(k, Y.size()) {
			rep(j, Y[0].size()) {
				Z[i][j] = (Z[i][j] + X[i][k] * Y[k][j]) % M;
			}
		}
	}
	return Z;
}

//A^nの計算
vvi matrix_pow(vvi A, ll n) {
	vvi B(A.size(), vi(A[0].size()));
	//単位行列でBを初期化
	rep(i, B.size()) {
		B[i][i] = 1;
	}

	while (n>0) {
		if (n & 1) { B = matrix_multiply(B, A); }
		A = matrix_multiply(A, A);
		n = n >> 1;
	}
	return B;
}

int main() {
	int n, s, t, p, q; cin >> n >> s >> t >> p >> q;
	vvi A(2, vi(2));
	A[0][0] = p; A[0][1] = q;
	A[1][0] = 1; A[1][1] = 0;
	A = matrix_pow(A, n);

	cout << (A[1][0] * t + A[1][1] * s) % M << endl;

	return 0;
}
```

# m項間漸化式の行列累乗
一般のm項間漸化式
```math
a_{i+m} = \sum_{j=0}^{m-1} p_j a_{i+j}
```
のような場合でも、
```math
A=
\begin{pmatrix}
p_{m-1} & \cdots & p_1 & p_0 \\
1 & \cdots & 0 & 1 \\
\vdots & \ddots & \vdots & \vdots \\
0 & \cdots & 1 & 0
\end{pmatrix}
```
とすることで、同様の実装で動作します。行列の乗算部``matrix_multiply``が重くなり、計算量は$O(m^3logn)$となります。
libil2cpp.so failed with output

`libil2cpp.so failed with output`というエラーが出てビルドできなくなってしまったときのメモ。

# 状況

* Unity 2021.3.5f1 Personal
* Android
* JDK, NDK は installed with Unity

# 対処1

Build Settings > IL2CPP Code Generationを Faster (smaller) builds にする。
サイズ超過のときに出るっぽい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/cede6ce2-239b-5eff-c981-618eec72c522.png)


https://forum.unity.com/threads/im-able-to-build-both-production-and-development-but-not-script-debugging-on.1187170/

# 対処２

Libraryディレクトリを削除する。
github-actionsを使ってCI環境を作るのに1年以上かかったけどできた

## はじめに
大概のWeb現場はCIが整備してあるだろう。いつかやりたいと思いながらも、結局やり方はわからないままだったのでチャレンジしたらすごく難しかったという話

https://docs.github.com/ja/actions

## stackoverflowに助けを求めた
thax Azeem san! 2,000円分ぐらいpaypal送金しようとしたけど結局アカウントを教えてはくれなかった。いい人だな。
英語で質問すると英語力もついていいことずくめやで（急いでると翻訳サイトつかっちゃうけど...）

https://stackoverflow.com/questions/75500304/test-not-found-in-github-actions

https://stackoverflow.com/questions/75541794/how-to-grant-permissions-to-mysql-in-github-actions

## 手順
### requirements
1. `requirements.txt` の書き出し
1. リポジトリに push（CIが `requirements.txt` を使用する）
  ```console:console
  dev\Portfolio> pip freeze > requirements.txt
  ```
### workflowの新規作成
1. django用のテンプレートはあった（最終的にあまり役には立たなかったけど）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/d134285d-f754-1ea1-7637-78fce82ab1d2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/8b95c1bf-f4c7-086e-5e0c-3952f5d047e2.png)

- データベースにアクセスするようなテストがなければ、ほぼ初期設定でよくて、`requirements.txt` を使用して、djangoのテストが流せそう
- `master` にコミットするぞって言われるので OK したあと pull でローカルPCに引き込める
- 試行錯誤するごとに commit してCIを走らせるしか検証方法はないようだ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/d4091cc1-db13-f912-93dd-d0bf870f878b.png)

- Actions の画面に戻るともう試行結果が出てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/a9663f92-f636-d9bc-54fa-8558a5a02ae7.png)

### Actions最終版
結局
- 事前に `test_portfolio_db` はつくらなくて良い
- mysqlの起動が必要
- `python`ユーザは必要
- 権限付与は必要
- `makemigrations` は必要（※ただし、テストには合格するがログをよく見ると `portfolio_db` へのアクセスを試みて失敗している）
- `DJANGO_SECRET_KEY`は必要

```yaml:最終版Actions
name: Django CI

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      max-parallel: 1
      matrix:
        python-version: [ 3.12 ]

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v3
        with:
          python-version: ${{ matrix.python-version }}
          cache: pip

      - name: Set up
        run: |
          sudo systemctl start mysql
          mysql -u root -proot -e "CREATE USER 'python'@'localhost';"
          mysql -u root -proot -e "GRANT ALL ON test_portfolio_db.* TO 'python'@'localhost';"
          
          python -m pip install setuptools
          python -m pip install -r requirements.txt
          python manage.py makemigrations vietnam_research gmarker shopping linebot_engine warehouse taxonomy soil_analysis securities

      - name: Run tests
        run: |
          export DJANGO_SECRET_KEY="$(base64 <<< "$RANDOM|TeStiNg|$RANDOM" | tr -d '\n')"
          python manage.py test
```

## 確認
https://github.com/duri0214/portfolio/actions/runs/10021066141/job/27699320674

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94562/0b8d9b15-43fd-f9c3-e8cc-09b9428072d2.png)
[Python] YOLOを用いた物体検出と行動パターンの可視化 [Splatoon]

# はじめに
あるゲームにおける**上位勢と中級者の違いを可視化**できないかと考えて、行動パターンの可視化を試みました。
今回はTPS (Third-Person Shooter)ゲームとして、Splatoon3を選択しました。

# Splatoon3とは
インクを撃ち合う、任天堂のシューティングゲーム『Splatoon』シリーズの3作目。インクを撃って自分の陣地を広げるという斬新なゲームシステムだけでなく、BGMやSEもイカしています。筆者のウデマエはXP2500程度で、中級者～ぐらいだと思います。

https://www.nintendo.co.jp/switch/av5ja/index.html

# YOLOとは
YOLO (You Only Look Once)は、一枚の画像から複数の物体を検出できるアルゴリズムで、検出した物体のクラスも分類できます。その他のアルゴリズムと比べて、YOLOは処理が高速で、リアルタイムのアプリケーションも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676917/eb99ea9c-d9b9-983c-0df5-5fb43ac78911.png)
[You Only Look Once:Unified, Real-Time Object Detection](https://arxiv.org/pdf/1506.02640.pdf)より引用
上記はYOLOの例です。人がairplaneとして検出されてしまっている箇所がありますが、おおむね精度よく検出できていることがわかります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676917/7ebaa0d0-4383-77a6-827f-d0617029d7f0.png)
[YOLOV5](https://pytorch.org/hub/ultralytics_yolov5/)より引用

今回は比較的小さなモデルであるYOLOv5sを使います。
コードなどは別の記事でまとめたので[こちら](https://qiita.com/yzrnb/items/91df7168082b4451962c)でどうぞ。

https://qiita.com/yzrnb/items/91df7168082b4451962c

# LabelImgと学習データ
キャプチャーボードで自分のプレイ動画を録画しデータとしました。異なるステージやインク色で学習を行いたかったので、10試合の動画を使いました。
各試合から15枚ずつ、合計150枚の画像を取り出します。訓練用に100枚、検証用に50枚に分け、モデルの学習を行います。その際に、画像内から検出するものとして、以下のように8種類のラベルを手作業で作成しました。
+ イカ移動
+ 人移動
+ メインウェポン
+ サブウェポン
+ マップ
+ デス
+ 潜伏
+ スペシャルウェポン

![LabelImg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676917/5c5c2695-3178-44b9-e91c-3d73b0993a0b.png)
LabelImgを用いたラベル作成例。図の場合は"メインウェポン"。

学習にはある程度時間がかかりますが、そのモデルを使って物体検出するのは非常に高速です。
![run_time.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676917/4351d5b8-f873-2fbb-0347-eda6268f7ae4.png)
実行中の画像ですが、1枚あたり10msほどです。


# 結果
このように学習させたモデルで、1試合分の行動検出を行ってみました。
![trained_exp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676917/1bb7e295-9ddb-e845-dbe2-7c69336e6ddf.gif)

学習データで使っていたブキは、ボトルガイザーとドライブワイパー、ジムワイパーでしたが、ロングブラスターでも検出できていますね。
また、飛沫の上がっていないイカ移動を潜伏（hide）としましたが、ある程度検出できて驚いています。

ただし、今回は動画から適当に選んだ画像で学習したので、イカ移動やメインウェポンの学習データが多く、サブウェポンやスペシャルのデータがほとんど学習できなかったと思います。集めるデータを工夫すれば、精度はもっと改善すると思います。

次は
+ 自チームと敵チームの人数差をを有利 or 不利状況の度合いとし、各状況における行動パターン or 俯瞰視点から見た移動量の可視化（＋上位勢と中級者の比較）
+ 自チームと敵チームのデスのタイミングとカウントの進行から、寄与の大きい行動の可視化

などを行いたいと思います。
LLMを用いたMLOpsについて

大規模言語モデル (LLM) スペースの開発ペースは、過去数か月で爆発的に増加しました。最も興味深いストーリーの 1 つは、<INS>これらの言語モデルでまったく新しいエンゲージメント パターンをサポートする新しい技術スタックへの急速な移行です。</INS>このブログ投稿では、LLM の技術スタックで行われている変更と、それが開発者にとって何を意味するかを探ります。

### 既存の NLP 技術スタック
最近まで、NLP 開発者は、テキスト分類、名前付きエンティティの認識、名前付きエンティティの明確化などの NLP タスク用に最適化された技術スタックに依存してきました。この技術スタックは通常、データ前処理パイプライン、機械学習パイプライン、および埋め込みと構造化データを格納するためのさまざまなデータベースで構成されます。このアーキテクチャは、大量のトリプル、単語の埋め込み、文の埋め込み、シーケンスからシーケンスへの出力、言語モデルの確率、注意の重みなどを生成するのにうまく機能しました。開発者は通常、これらの構造化された出力を ElasticSearch、Postgres、または Neo4j データベースに保存し、ユーザー (またはサービス) がクエリできるナレッジ グラフとして利用します。

このアーキテクチャは、エンタープライズ システム内に展開して主要なプロセス (ドキュメントの分類、エンティティとエンティティ間の関係の検索など) を自動化できる、信頼性の高い構造化データの生成に適しています。しかし、それらは立ち上がるのが遅かったため、広く採用されるのに苦労しました (大量のラベル付きデータとかなりのモデルの微調整が必​​要でした)。実行するのに費用がかかります (これらのアーキテクチャでは、パイプライン/システムに 30 以上のモデルが含まれることがよくあります)。また、取り込みパイプラインとモデル パイプラインは、新しいドキュメント レイアウトとデータ タイプに対して脆弱でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242965/ac318d5a-4792-af30-5fb0-80ecd390e158.png)

### 新興の LLM 技術スタック
2022 年の秋以降、LLM の可能性を最大限に活用するように設計された新しい技術スタックが出現し始めています。以前の技術スタックとは対照的に、これはテキスト生成を可能にすることを目的としています。これは、以前の機械学習モデルと比較して、最新の LLM が最も得意とするタスクです。この新しいスタックは、データ前処理パイプライン、埋め込みエンドポイント + ベクター ストア、LLM エンドポイント、LLM プログラミング フレームワークの 4 つの柱で構成されています。古い技術スタックと新しい技術スタックの間には、いくつかの大きな違いがあります。まず、ChatGPT、Claude、Flan T-5 などの LLM には、GPT 2 などの以前のモデルよりもはるかに多くの情報がエンコードされているため、新しい技術スタックは構造化データ (トリプルなど) を格納するナレッジ グラフに依存していません。 2 つ目: 新しい技術スタックは、カスタム構築された ML パイプラインではなく、既製の LLM エンドポイントをモデルとして使用します (少なくとも開始するため)。これは、今日の開発者が特殊な情報抽出モデル (名前付きエンティティ認識、関係抽出、感情など) のトレーニングに費やす時間を大幅に短縮し、わずかな時間 (およびコスト) でソリューションを作成できることを意味します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2242965/88790af1-f08e-82c9-d6bc-24f856fc5cd0.png)



この新しい LLM 技術スタックへの移行は、開発者がより強力な NLP アプリケーションを構築および展開できるようにするエキサイティングな開発です。新しいスタックは、古いスタックよりも効率的でスケーラブルで使いやすく、LLM の可能性を最大限に引き出します。開発者が LLM の力を活用する新しい方法を探し続けているため、今後数か月から数年の間に、この分野でさらに多くのイノベーションが見られることが期待できます。
Sinatra + rack 環境にて、アクセスログとアプリログを分ける方法

sinatra で、 config.ru を書いて rackup で動作させている場合、アクセスログとアプリログが混じってしまいます。

Rackの吐き出す アクセスログは access.log、自分のアプリログは app.log に出せるようにする方法。

# アプリログ用のクラスを作る

```app_logger.rb
class AppLog
    def initialize(app, logger)
      @app, @logger = app, logger
    end

    def call(env)
      env["app.logger"] = @logger
      @app.call(env)
    end
end

```
# config.ru にて、二つのロガーを指定する

``` config.ru
require 'logger'

require_relative './app_logger'
require_relative './app'

logdir = File.dirname(__FILE__) + "/log"
access_logger = ::Logger.new(logdir + '/access.log')
app_logger = ::Logger.new(logdir + '/app.log')

def access_logger.write(msg); self << msg; end
use Rack::CommonLogger, access_logger		# アクセスログ
use AppLog, app_logger		#　アプリログ


run MyApp::Application
```

# sinatraメインアプリで、自作のロガーを使えるようにする


```app.rb

require "sinatra"

Module MyApp
		def logger; env['app.logger'] || env['rack.logger']; end

		get '/' do
			logger.info "HELLO!"
			erb :index
		end
end
```

# できました

これで / にアクセスすると、 app.log に "HELLO!"と記載されます。
エクセルマクロ(VBA)入門編その２変数・繰返し処理

# はじめに
Excelマクロ(VBA）を使いこなせば、様々な業務が効率化されます。
今回は、入門編その２と題して、変数や繰り返し処理について、ご紹介します。
尚、主な操作はYoutubeの動画をご覧頂き、完成したプログラムを、以下にご紹介しています。

# 環境
Windows10
Microsoft365バージョンのExcel

# 解説の流れ:
・セルの情報取得とセット
・変数について
・Forループによる繰返し処理
・表の最終行取得方法

# YouTubeでの解説：
上記の作業の流れをYoutubeで詳しく解説していますので、ぜひ、ご覧ください。
<iframe width="560" height="315" src="https://www.youtube.com/embed/fSOHvI2g7FM" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

# サンプルソース
YouTubeで紹介している処理のプログラムソースです。
```vb:練習2
Sub 練習2()

    Y = 0
    Last_ROW = Range("A" & Rows.Count).End(xlUp).Row
        
    For I = 2 To Last_ROW
        X = Range("C" & I).Value
        Y = Y + X
        ' MsgBox ("X=" & X & " Y=" & Y)
        
    Next I
    Range("F2").Value = Y
    
End Sub
```


# 最後に：
今回は、エクセルマクロの入門編２ということで、徐々にプログラムらしくはなってきました。
ただ、これだけでは、エクセル関数の方が簡単です。
今後、徐々にレベルアップして、最終的には業務に役立つプログラムもご紹介していきたいと思います。
tarやmysqldumpでローカルとS3に同時バックアップを実行 & 速度向上の施策

mysqldumpやtarでサイトのバックアップを取得することはよくあると思います。
実データと同じサーバに保存しておけば操作ミスのリカバリーに有用ですが、それだとサーバのデータが飛んでしまうとどうしようもないので、バックアップは実データとは別のストレージにするのが鉄則です。

とはいえ念のためサーバ内にもバックアップが欲しい！というときには、少し工夫すると1コマンドでサーバとリモートに同時にバックアップを保存することができます。
数サイトくらいでは同時に実行せずとも良いのですが、多数あるとそれなりに所要時間が違ってきて役に立ちます。

さらに、今回はバックアップの所要時間を減らしたいというケースに遭遇したので、この機会にパターンをいくつか用意してコマンドと所要時間を比較してみました。

ここでは、AWS S3をリモートの保存先とした例を記載します。

## mysqldump

mysqldump は出力先がstdoutなので、ファイルとして保存する際にはリダイレクトを利用します。
合わせて gzip で圧縮してあげると容量が節約されていい感じです。

```
mysqldump --defaults-extra-file=${HOME}/.mysql/login ${DB_NAME} | gzip | tee ${DB_NAME}.sql.gz | aws s3 cp - s3://${BUCKET}/${FOLDER}/${DB_NAME}.sql.gz
```

ポイントは、 `tee` でデータの流れ先をファイルとstdoutに分岐させるところになります。
aws s3 コマンドがストリームをソースとして使えるところもありがたいですね。

## tar

tar についても、fオプションを使わなければ出力先は stdout になりますので、その後は mysqldump と同様に扱えます。

```
tar cz ${DIR_NAME} | tee ${DIR_NAME}.tar.gz | aws s3 cp - s3://${BUCKET}/${FILDER}/${DIR_NAME}.tar.gz
```

## (おまけ) 所要時間の最適化について

12GBのディレクトリ test を圧縮してローカルに保存し、かつS3にも保存するケースでコマンド別に完了までの所要時間を比較します。

#### Command 1. tarでフォルダを1ファイルに圧縮して保存し、その後S3にもコピー

```
tar czf test.tar.gz test/ && aws s3 cp test.tar.gz s3://${BUCKET}/test.tar.gz
```

よく使われるケースと思います。この所要時間を基準とします。

所要時間: **10m 19s**

#### Command 2. tarの圧縮とs3へのコピーをワンライナーで実行

```
tar cz test/ | tee test.tar.gz | aws s3 cp - s3://${BUCKET}/test.tar.gz
```

所要時間: **9m 54s**

1ファイルでは思ったほどの差異はありませんでしたが、Command 2.の方はCPU使用率が低く抑えられており、並列で複数フォルダを同時実行するのにも耐えうる状況でした。
一方で Command 1. の方は tar 実行時にCPUをフルに使っており、処理の並列化はやや難しそうでした。

#### Command 3. gzipのレベルを調整

```
tar c test/ | gzip -v4 | tee test.tar.gz | aws s3 cp - s3://${BUCKET}/test.tar.gz
```

所要時間: **6m 23s**

gzipを個別に実行し、かつ圧縮レベルを4に落とした例も確認しました。
速度は大幅に向上し、圧縮後のサイズは 3.5GB -> 3.6GB へと増えましたが多くの場合にて許容範囲となりそうです。

#### 結果のまとめ

以下の結果となりまして、圧縮レベルもそれなりで所要時間の短いCommand 3.を採用することにしました。
なお7zipやbzipも試してみたのですが、圧縮レベルの割に所要時間が激増したので利用は難しかったです。用途次第ですね。

| Command 1. | Command 2. | Command 3. |
| --- | --- | --- |
| **10m 19s** | **9m 54s** | **6m 23s** |
CMakeListsでfind_packageした時にPythonモジュールが見つからなかった場合

# 先に結論
cmakeの3.12前と3.12以降でFinePythonの設定を切り替えるようにしました。
```python
if( ${CMAKE_VERSION} LESS 3.12 )
    find_package(PythonLibs REQUIRED)
    include_directories(${PYTHON_INCLUDE_DIRS})
else()
    find_package(Python COMPONENTS Interpreter Development)
    include_directories(${Python_INCLUDE_DIRS})
endif()
```
もっとスマートなコードがあればコメントまでお願いします！

# 'Python.h' file not found
cmakeを使ってPythonのライブラリをインクルードしているC++のコードをmakeすると、こんなエラーが出てしまいました。
```
fatal error: 'Python.h' file not found
#include "Python.h"
```

# PythonLibsは3.12から非推奨

https://cmake.org/cmake/help/latest/module/FindPythonLibs.html?highlight=pythonlibs

では最初に以下のように書いてあります。
```
Deprecated since version 3.12: Use FindPython3, FindPython2 or FindPython instead.
```

　`cmake_minimum_required` を `3.12` にして、`FindPythonLibs`→`FindPython3`に変更すれば解決になりそうではありますが、そこまで上げられない場合には両方サポートしてあげたほうが良さそうです。（Python2はもういいとは思いますが）

# パラメータの闇
`find_package`さえ変更すれば、問題ないかと思っていたのが大きな問題で、`include_directories`にも影響があることが判明。
(これを見つけるのに時間がかかってしまった)

https://cmake.org/cmake/help/latest/module/FindPythonLibs.html?highlight=pythonlibs

https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython

これを見ても、最初何が違うのかわからなかったです。（なぜ大文字小文字で区別するのか...）

||FindPythonLibs |FindPython |
|---|---|---|
|Python.h の検索パス    |PYTHON_INCLUDE_DIRS |Python_INCLUDE_DIRS |
|Python ライブラリのパス  |PYTHON_LIBRARIES    |Python_LIBRARIES    |

## こんなデバッグを入れておきました
cmakeのmassageコマンドでこれらのパラメータを出力しておくとエラーの時に参考になりそうです。
```cmake
message(STATUS "CMAKE_VERSION:${CMAKE_VERSION}" )
message(STATUS "include_directories(PYTHON_INCLUDE_DIRS):${PYTHON_INCLUDE_DIRS}" )
message(STATUS "include_directories(Python_INCLUDE_DIRS):${Python_INCLUDE_DIRS}" )
message(STATUS "include_directories(PYTHON_LIBRARIES):${PYTHON_LIBRARIES}" )
message(STATUS "include_directories(Python_LIBRARIES):${Python_LIBRARIES}" )
message(STATUS "include_directories(Python_LIBRARY_DIRS):${Python_LIBRARY_DIRS}" )
```

# 参考
解決した後に調べたら参考になる記事がありました。

https://qiita.com/syoyo/items/7c154f10b75b324da2fa
Macでのuntruncコマンドのインストール方法と使い方

`untrunc`コマンドを使って破損した動画を修復します。

:::note warn
この記事はやり方を書いてる記事が他に見当たらなかったので、初学者が自力でなんか出来た方法を書いてるだけです。他に詳しそうな記事があればそちらを参考にしてください
:::

# untruncコマンドのインストール

↓ソース元
https://github.com/ponchio/untrunc

ここのinstalling from gitの手順通りにやればインストールできます。
作業ディレクトリはよく分からないなら一応ダウンロードフォルダでやりましょう。
具体的には下のコマンド達を1行1行やるだけです。
```
git clone --recurse-submodules https://github.com/ponchio/untrunc
cd untrunc/libav
./configure
make
cd ..
g++ -o untrunc -I./libav file.cpp main.cpp track.cpp atom.cpp codec_*.cpp codecstats.cpp codec.cpp mp4.cpp log.cpp -L./libav/libavformat -lavformat -L./libav/libavcodec -lavcodec -L./libav/libavresample -lavresample -L./libav/libavutil -lavutil -lpthread -lz -std=c++11
sudo install -vpm 755 ./untrunc /usr/local/bin/ 
which -a untrunc
```



ただし自分がやったときは./configureを実行した時に下のような注意が出ました。
```
asm/yasm not found or too old. Use --disable-x86asm for a crippled build.
```
これはここに書いてある通り、`--disable-x86asm`を./configureの後に付ければ大丈夫です。

そして上の手順を進めると次はg++…のコマンドでエラーが起きます。しかしこれはソース元にも書かれてるように適切なオプションを最後に付け加えればOKです。

>Depending on your system and Libav configure options you might need to add extra flags to the command line:
>add -lbz2 for errors like undefined reference to 'BZ2_bzDecompressInit',
add -llzma for errors like undefined reference to 'lzma_stream_decoder',
add -lX11 for errors like undefined reference to 'XOpenDisplay',
add -lvdpau for errors like undefined reference to 'VDPAU...',
add -ldl for errors like undefined reference to 'dlopen'.

>On macOS add the following (tested on OSX 10.12.6):
add -framework CoreFoundation -framework CoreVideo -framework VideoDecodeAcceleration.

この文章には要は「こういうエラーが出た時はこのオプション付けてね」とざっくり書いてます。なので例えばエラー文にBZ2_bzDecompressInitと書いていればg++…のコマンドの最後に`-lbz2`をつけてください。
Macの場合は最後に書かれてる-frame…のオプションもつけてください。

これであとは手順通りに進めればインストールできるはずです。

# untruncの使い方

untruncのファイルが置かれている場所（上の手順を終えた後なら今いるディレクトリ）で以下のコマンドを入れれば動画ファイルを修復できます。
```
./untrunc /path/to/working-video.m4v /path/to/broken-video.m4v
```
ここで必要になるファイルは二つ、「修復したい動画ファイル」と「修復したい動画ファイルと同じ方法で撮影したけど、破損しなかった正常な動画ファイル」です。これは正常な動画ファイルを参考に破損した動画を修復するからです。撮影方法や録画方法が同じならいいので動画内容は別になんでもいいです。

この「正常な動画ファイル」のパスを上のコマンドの/path/to/working-video.m4vのところに、「修復したい動画ファイル」のパスをもう一つの方に置き換えてください。それで修復できるはずです。

修復結果は新しい動画ファイルとして破損した動画ファイルのある場所に出力されます。

# まとめ
・untruncコマンドで動画を修復できる
【VSCode】C++の自動整形をインデント4&行頭カッコしないように設定する

行頭カッコしないよう、Googleスタイルを使用。
```json
"C_Cpp.clang_format_style": "Google"
```
ただこの設定だと、インデント2にされて悲しい。

インデント4にするには以下のように設定する。
```json
"C_Cpp.clang_format_style": "{ BasedOnStyle: Google, IndentWidth: 4 }"
```
もしくは
```json
"C_Cpp.clang_format_style": "{ BreakBeforeBraces: Attach, IndentWidth: 4 }"
```
参考:
https://gist.github.com/9sako6/458def885387e8dcd2f0f2742a1dc3e4
AWSアカウントの作成

AWSの検証用にアカウントを新規に作成する．

AWS公式に手順があったため，そちらに沿ってアカウントを作成しルートユーザーを作成する．
https://aws.amazon.com/jp/register-flow/?sc_icampaign=acq_aws_takeover-abandoner_jp&sc_ichannel=ha&sc_icontent=awssm-1524&sc_iplace=hero&trk=ha_awssm-1524&refid=94c18984-27d1-4395-8dae-cdbf523f1ae5


作成後ルートアカウントでログインすることができた．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194141/8d9c77cb-86d5-fb88-5b31-ac9b2f12f8ea.png)

次回は通常時の利用のためにIAMユーザーを作成する．
Hubspot CLIについて

# はじめに
HubSpot CLI（Command Line Interface）とは、HubSpotのAPIを利用して、コマンドライン（ターミナル）からHubSpot CMSを操作するためのツールです。
ローカルで開発したテーマファイル（ボイラープレート）やモジュールなどをCMS上に反映することができます。
他には、Hubspotが提供しているテーマやモジュールをローカルに取り込むことができるので、テーマ開発やモジュールを作成する時に役立ちます。

# 使い方
HubSpot CLIを使用するには、まずNode.jsをインストールする必要があります。
Node.jsをインストールしたら以下のコマンドを実行して、HubSpot CLIをインストールできます。

## CLIのインストール
```shell
npm install -g @hubspot/cli
```
**現在のディレクトリーにのみインストール**
```shell
npm install @hubspot/cli
```
**アップグレード**
最新バージョンにアップグレードする。
```shell
npm install -g @hubspot/cli@latest
```
## ローカルでテーマ開発するまでの手順
### 1. init
hubspot.config.ymlファイルを作成し、アカウントの認証を設定します。
```shell
hs init
```
- personalAccessKey　を求められるので[y]を入力
- Hubspotページに遷移するするのでログインする
- アクセスキーページに遷移する
- アクセスキーをコピーしてターミナルに貼り付ける

### 2. テーマを作成する
CMSのボイラープレートを利用します。
```shell
// 説明
hs <command> <src> <dest>
// ボイラープレートが取り込まれたテーマファイルを作成
hs create website-theme my-website-theme
```

### 3. テーマをHubSpotにアップロードする
アップロードするとCMSからテーマを使用することができます。
CMS上部のナビゲーションから[マーケティング] > [ファイルとテンプレート] > [デザイン ツール]に移動して表示されるデザインマネージャーでファイルを確認することができます。
```shell
hs upload my-website-theme my-website-theme
```

## テーマ開発でよく使うコマンド
### watch
ローカルディレクトリーを監視し、ファイルが保存されると変更内容をCMSに自動的にアップロードします。
CMSのライブプレビューでブラウザ表示すれば変更を即時に確認することができます。
```shell
hs watch my-website-theme my-website-theme
```
**注意点**
- 監視対象のファイルをローカル側で削除しても、HubSpotからは自動的に削除されません。ファイルを削除するには、--removeを使用します。
- ローカル側でフォルダーの名前を変更すると、新しいフォルダーが新しい名前でHubSpotにアップロードされます。HubSpot上にある既存のフォルダーは自動的には削除されません。フォルダーを削除するには、--removeを使用します。

### fetch
Gitでいうpullのようなものです。
CMS上で作成したモジュールをローカルに取り込んで編集するときによく使いました。
```shell
hs fetch my-website-theme my-website-theme
```
すでにローカルにあるデータを上書きする場合は```--overwrite```のオプションをつける必要があります。
```shell
hs fetch --overwrite my-website-theme my-website-theme
```

:::note warn
注意
上記のオプションを付け忘れるとローカルデータが更新されません。
その状態でCMSにデータをアップロードすると、CMSのデータが先祖返りする恐れがありますのでご注意ください。
:::