OmniAICreator/Qiita-1.07M huggingface dataset:
Vim基本操作チートシート

## アジェンダ
基本的なVim（またはVi）のコマンドをまとめたチートシートです。
※よく使うものにはチェックを入れてます。

## **基本モード**
- **コマンドモード**: デフォルトのモード。Vimの操作はこのモードで行います。
- **挿入モード**: テキストを入力するためのモード。`i` で挿入モードに移行します。
- **ビジュアルモード**: テキストを選択するモード。`v` で移行します。
- **コマンドラインモード**: ファイルの保存や終了などのコマンドを入力するモード。`:` で移行します。

## **モード切り替え**
- **コマンドモードに戻る**: `Esc`
- **挿入モードに入る**: `i`（カーソルの前に挿入）、`a`（カーソルの後ろに挿入）、`o`（次の行に新しい行を挿入）
- **ビジュアルモードに入る**: `v`

## **コマンドモードの基本操作**
- **カーソル移動**
  - `h`: 左へ移動
  - `j`: 下へ移動
  - `k`: 上へ移動
  - `l`: 右へ移動
- **単語単位で移動**: `w`（次の単語の先頭へ）、`b`（前の単語の先頭へ）
- **行頭・行末に移動**: `0`（行頭）、`$`（行末）
- **ページ移動**: `Ctrl + f`（次のページ）、`Ctrl + b`（前のページ）
- **行番号へ移動**: `:行番号`（例：`10G`で10行目に移動）

## **編集コマンド**
- **文字を削除**: `x`
- **1行削除**: `dd`
- **単語削除**: `dw`（カーソルから単語の終わりまで）
- **複数行削除**: `n dd`（n行分削除、例：`2dd`で2行削除）
- **元に戻す**: `u`
- **やり直す**: `Ctrl + r`

## **挿入モードの基本操作**
- **挿入モードに入る**: `i`（現在の位置に挿入）、`I`（行頭で挿入）
- **挿入モードからコマンドモードに戻る**: `Esc`

## **コピー & ペースト**
- **コピー（ヤンク）**: `yy`（1行コピー）、`y`（範囲指定でコピー）
- **ペースト**: `p`（カーソルの後にペースト）、`P`（カーソルの前にペースト）
- **範囲選択 & コピー**: ビジュアルモードで選択後、`y`

## **検索 & 置換**
- **検索**: `/検索ワード`（下方向に検索）、`?検索ワード`（上方向に検索）
  - 次に進む: `n`
  - 前に戻る: `N`
- **置換**: `:s/検索/置換/`（現在行の最初のマッチを置換）
  - 行全体で置換: `:s/検索/置換/g`
  - ファイル全体で置換: `:%s/検索/置換/g`

## **保存 & 終了**
- **保存**: `:w`
- **終了**: `:q`
- **保存して終了**: `:wq`
- **変更を破棄して終了**: `:q!`

## **その他便利なコマンド**
- **行を分割して挿入**: `o`（次の行に新しい行を挿入）、`O`（前の行に新しい行を挿入）
- **特定の行にジャンプ**: `:行番号`（例：`:5`で5行目にジャンプ）
- **行番号表示**: `:set number`（行番号を表示）、`:set nonumber`（行番号を非表示）
- **ファイルを開く**: `:e ファイル名`
- **ファイルを閉じる**: `:bd`

## **ビジュアルモードでの操作**
- **範囲選択**: `v`（通常の選択）、`V`（行単位の選択）
- **選択範囲を削除**: `d`
- **選択範囲をコピー**: `y`
MacとiPadでネットワーク共有

ちょっとニッチな需要かもしれませんが、自分へのメモも兼ねて。

# やりたいこと
業務で接続する開発環境へのアクセスがIP制限がかかっていて、VPN経由でしか接続ができない設定となっている。
ここに、開発で使うiPadの実機で接続をしたいが、会社で導入しているVPNのアカウントが開発マシンとして使っているMac側に設定されている状態で、iPadにはVPN設定ができていなかったので、Macのネットワークを共用してiPadからVPNを経由したアクセスをさせたい。

# やったこと
1. MacとiPadをUSBケーブルで接続する。
1. Macはあらかじめ経由させたいVPN接続を有効にしておく。
1. Macのシステム設定から 一般 > 共有 と進み、 `インターネット共有` 欄の右側の `i` ボタンをクリックする。
    1. 開くダイアログが以下の画面。![スクリーンショット 2024-09-05 13.14.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45794/cda2ee64-f706-12b8-7b82-d90ab1275f0c.png)
        *※ `共有する接続経路` 欄（画像ではマスクさせていただいています）に、経由させたいVPNネットワークの名前が表示されていることを確認する。*
    1. 選択肢上の `iPad USB` のスイッチをONにして、画面上部にある `インターネット共有` のスイッチをONにする。
        1. このとき、あらかじめMacとiPadを繋いでいないと選択肢に `iPad USB` 自体が表示されない。もし接続していても表示されていない場合は一度ケーブルを抜き差ししてみる。
        1. 上部の `インターネット共有` スイッチをONにすると、下の共有先デバイス欄は操作ができなくなるので、大本はOFFの状態で個別のスイッチをONにしてから、大本をONに変更する）

これで、iPadはMacのVPN経由でネットへアクセスするようになる。
念の為、iPad自体は `機内モード` に切り替えて、無線通信をしないようにした状態でSafariなどで通信ができることを確認すれば間違いなし。


以上、どなたかの参考になれば幸いです。
Warning: cocoapods not installed. skipping pod install.の対処法

## 概要
すでにcocoapodをインストールしてあるのにも関わらず上記のエラーが表示された解決方法のメモです。

## 環境
- macOS (M1)Sonoma 14
- Android Studio Giraffe |2022.3.1
- Flutter 3.22.3
- Dart 3.4.4
- cocoapod をhomebrew経由でインストール済み

## 解決した手順
- M1で必要な手順らしい（要らないかも)
```
sudo arch -x86_64 gem install ffi
arch -x86_64 pod repo update
arch -x86_64 pod install
```
command + Tab + q などでAndroid Studioを完全に終了させる
以下のコマンドを実行する
```
open /Applications/Android\ Studio.app
```

## 参考
https://qiita.com/tetsukick/items/24ffa82f84682e0066d0
https://hack-it-iron.hatenablog.com/entry/2021/06/09/103729
https://forums.developer.apple.com/forums/thread/699454
https://zenn.dev/hi_okuma/articles/1193c0b5df8a29
Textの描画サイズ

Flutter 3.24.1, Dart 3.5.1

String と TextStyle だけでサイズを求める方法しか見つからなかったので、Text 丸ごと渡して求めるバージョンを作ってみました。やってることは同じです。

```dart
extension TextExtensions on Text {
  Size drawingSize({double maxWidth = double.infinity}) {
    final painter = TextPainter(
      text: textSpan ?? TextSpan(text: data, style: style),
      textAlign: textAlign ?? TextAlign.start,
      textDirection: textDirection ?? TextDirection.ltr,
      textScaler: textScaler ?? TextScaler.noScaling,
      maxLines: maxLines,
      //ellipsis: ,
      locale: locale,
      strutStyle: strutStyle,
      textWidthBasis: textWidthBasis ?? TextWidthBasis.parent,
      textHeightBehavior: textHeightBehavior,
    )..layout(maxWidth: maxWidth);
    return painter.size;
  }
}
```
何も考えずに全部渡しています。`ellipsis` は何を渡していいのか分からなかったのでコメントアウト中。

# 問題点

赤が実際の Text 描画、青が求めたサイズですが、求めたサイズの方が少し小さくなっています。Android の方はけっこう差がありますね。（フォント依存か？）

## Web
![textsize_web.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18828/32906768-8b64-cbc4-7160-58fb3f94682b.png)

## Android
![textsize_android.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18828/b1d74216-f9f9-3617-e5fc-24f10153135b.png)

このままじゃ使い物にならないので、原因や解決方法をご存じの方がいらっしゃいましたら教えていただけると助かります。

詳細はこちら [Gist](https://gist.github.com/fuzz6001/885318bf9422fb124fafee79c73051c1)
動作サンプルはこちら [DartPad](https://dartpad.dev/?id=885318bf9422fb124fafee79c73051c1)
備忘録：フォレンジックについて

<h2>イベントログフォレンジック</h2>
イベントログとは、Windowsにおいて、ユーザーに通知するかログに記録する必要のあるWindowsシステムまたはプログラム上のログです。

イベントログ解析とは、Windowsシステムまたはプログラム上で起こったことの
記録を読み解き、何が起きたのかを確認する技術です。

特に標的型攻撃のインシデントレスポンスにおいては、組織内コンピューター間
での不正プログラムや攻撃者の動きが読み取れるため効果的です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477527/8a606599-9aac-cf27-926f-958357433441.png)

<h2>イベントログ取得方法</h2>
C:\Windows\System32\winevt\Logs
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477527/eacb9422-82ec-de1f-7233-25535ab9e88c.png)

<h2>イベントログ取得方法</h2>
FTK Imager などで
イベントログの取得が可能OSが起動している状態のPCからはイベントログがコピーできない場合があるため　FTK Imagerなどのツールを使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477527/72fee71a-b013-a90e-5973-4315b9799c33.png)

<h2>イベントログ解析ツールの説明</h2>
Event Log Exploreを使用してイベントのログを見ます。
<h6><INS>ネットワーク経由のログオン(他端末への侵入)</INS></h6>ネットワーク経由のログオン

　　セキュリティログ
　　イベントID 4624
　　ログオンタイプ 3
　　
<h6><INS>ネットワーク経由のログオン(他端末への侵入)</INS></h6>RDP経由のログオン

　　セキュリティログ
　　イベントID 4624
　　ログオンタイプ 
<h6>イベントログの削除(攻撃痕跡の削除)</INS></h6>

　　セキュリティログ
　　イベントID 1102
VSCodeのRuby LSPが Gem::MissingSpecErrorで立ち上がらないエラーがでた備忘録

## エラー内容

```console
/Users/user/.rbenv/versions/3.3.4/lib/ruby/3.3.0/rubygems/dependency.rb:301:
in `to_specs': Could not find 'sorbet-runtime' (>= 0.5.10782) among 210 total gem(s) 
(Gem::MissingSpecError)
Checked in'GEM_PATH=/Users/user/.gem/ruby/3.3.0:/Users/user/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0', 
execute `gem env` for more information

Error starting the server: 
Pending response rejected since connection got disposed
```

## 読んで欲しい人

- Ruby LSPで上記に似たエラーが出た人
- 過去の俺

## 問題発生までの経緯

- rbenvで最新Rubyバージョンをインストール：3.3.0→3.3.4
- 最新Railsのバージョンをインストール：7.1.2→7.2.1
- 新しいプロジェクトを立ち上げようとしたらLSPが動かない

## 原因

- dependency.rbファイル内の`to_specs`を呼び出した時に、RubyGemsが`sorbet-runtime`というGemを見つけられなかった


### dependency.rb

- RubyGemsがGemファイルや依存関係を扱う際に使用するクラスとメソッドを定義しているファイル

## 解決した経緯
- `Checkedin'GEM_PATH=/Users/user/.gem/ruby/3.3.0:/Users/user/.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0'`というエラーを確認する
- `.rbenv/versions/3.3.4/lib/ruby/gems/3.3.0'`を確認しに行った
- `sorbet-runtime`を探したが、ない
- `gem install sorbet-runtime`を実行
- LSPが立ち上がる

## 学び

- rbenvで管理しているRubyはバージョンごとにgemを管理していると知れた
- VSCodeに出てくるエラーは無視しないで確認した方が良い
- 別バージョンになっても、実際にgemを確認する方法は使えそう
- 拡張機能がはいているエラーをちゃんと読む
[Rails]stubを使うときは評価順序に気をつけた方がいいという話

# はじめに
皆さん`stub`は好きですか？私は正直嫌いです。しかし、外部と通信を行う機能を作成したりする時には切ってもきれない便利な機能です。今回はそんな機能を使うにあたって沼ったポイントがあったので共有していきます。


# 開発環境
- Ruby 3以上
- Ruby on Rails 6以上
- Minitest

# 最初に結論
`Object.new`を`stub`する際は、`.new`される前に引数が評価されるので注意が必要です。

これだけではわかりづらいと思うので、コードで例を見ながら解説します。


# ケーススタディ
以下のような外部とやり取りを行う、`GetterService`があったとします。外部通信を行うのは`GetterClient`なので、テストを行う際は`GetterClient.new`を`stub`することになります。
``` ruby
class GetterService < ServiceBase
  def call
    pp '1'
    data_list = getter_client.fetch_data_list
    pp '2'
    Formatter.format(data_list)
  end

  private

  def getter_client
    pp '3'
    GetterClient.new(Authorizer.authorizer)
    pp '4'
  end
end

class Authorizer
  def authorizer
    pp '5'
  end
end
```

以下はそのテストコードの一例です。

``` ruby
class InsertServiceTest < ActiveSupport::TestCase
  test '情報を取得して整形できる' do
  client_mock = Minitest::Mock.new
  client.expect(:fetch_data_list, 'dummy_response')

  GetterClient.stub(:new, client_mock) do
    res = GetterService.new.call
    # 以下resのassert処理
    end
  end
end
```
## ここで問題
上記のコードに出力用として「1〜5」の数値を`pp`していますが、テストを実行した場合、どの順番でこれらが表示されると思いますか？

1. 「1→3→4→2」と表示される
2. 「1→3→5→4→2」と表示される
3. どれも表示されない。エラーになる


### 正解
正解は2の「1→3→5→4→2」と表示される、です！
...ゑ?どうして「5」が表示されるの？`GetterClient`が`.new`される時に`stub`されるから引数の`ApiAuthorizer.authorizer`は呼ばれないはずでは？
そう思った方、私と同じです。仲良くしましょう。


### 解説
ここでのポイントは、「`GetterClient`が`.new`されるときに`stub`しているから`Authorizer.authorizer`は呼ばれないのでは？」という部分です。

確かに`GetterClient`が`.new`された段階で`stub`は正常に働いており、その後本来の`GetterClient`が呼ばれることはありません。そう、 **「`.new`された段階」でstubが効いているのであって、`.new`される前は`stub`が適応されていない** のです。

具体的には、`GetterClient.new(Authorizer.authorizer)`では、`GetterClient`が`.new`される前に`Authorizer.authorizer`が評価されています。つまり、`.new`の引数が評価されてから、`.new`が実行されるという順序になっているのです。
## Rubyの評価順序について
[Rubyのリファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/doc/spec=2feval.html)を見てみると、
> まずレシーバ式を評価してレシーバとなるオブジェクトを得ます。レシーバ式が省略された場合は呼び出しを行っているブロックのself がレシーバです。
続いて引数式を左から右の順番で評価し、レシーバに対してメソッドの検索を行います。検索が失敗したら例外 NameError を発生、成功したらメソッドを実行します。

とあります。まとめると、
1. レシーバ式（ここでは`GetterClient`）が評価される
2. 引数式（`Authorizer.authorizer`）が左から右の順で評価される
3. レシーバに対してメソッドが実行される

コードで表すと以下のようになります。


``` ruby
class ExampleService
    def call
        ExampleObject.new(call_first, call_second)
    end

    private

    def call_first
        pp '1'
    end

    def call_second
        pp '2'
    end

end

class ExampleObject
    def initialize(callable1, callable2)
        @callable1 = callable1
        @callable2 = callable2
        pp '3'
    end
end

ExampleService.new.call
# "1"
# "2"                                                                         
# "3"                                                                         
```
このコードでは、`pp`が評価される順序に従って`pp`を配置しています。実際にコンソールで実行してみると、上記の順番で表示されるはずです。
つまり、`Object.new`を`stub`しようとすると、`.new`の中身が評価された後に`stub`が効くことになります。

# まとめ

`Object.new`を`stub`する際も含めて、Rubyの言語仕様として、`.new`の引数が先に評価されることを覚えておくといつか役に立つかもしれません。今回の例のような単純な処理であれば問題ありませんが、テスト環境で動作しないような処理が含まれている場合には、原因が特定しづらくなる可能性があるので、注意が必要です(1敗)



# 参考
[Rubyのリファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/doc/spec=2feval.html)
JavaScriptのdebounce実装方法

#### どんな時にdebounceを使うか
高頻度で発火するイベントを制御したいとき、特定の時間間隔内に再度イベントが発火し、重複に関数を実行することを防ぐときに利用する一つ手法です


#### 実装例
```js
function debounce(fn, delay) {
    let timer_id;
    return function (...args) {
        clearTimeout(timer_id);
        let fn_this = this;
        timerId = setTimeout(function () {
          fn.apply(fn_this, args);
        }, delay);
    }
}

var tag_name = document.querySelector('tag_name');
tag_name.addEventListener('input|mousemove', debounce(function (e) {
    console.log('ユーザの操作：', e, this.value, '遅延させる');
}, 1000));


```


#### APIの利用例

```js
const loadAd = debounce((query) => {
    fetch(`https://api.example.com?q=${query}`)
        .then(response => response.json())
        .then(data => {
            // 結果の表示や処理
        });
}, 1000);


document.querySelector('tag_name').addEventListener('click', (e) => {
    loadAd(e.target.value);
});
```
Azure PowerShellでの初回サインイン失敗時のエラー対応

# 概要
Azureの某ハンズオン本でAzure PowerShellを使用してサインインしようとしたところ、エラーが出た。
# 環境
Windows10 Home 22H2
PowerShell 5.1.19041.4780
# エラー内容
前提として、PowerShellでAzure PowerShellモジュールがインストール済であること。ここではモジュールインストールについては解説しないので他記事を参照頂きたい。
```PowerShell
PS C:\> Install-Module az
```

この後、サインインのコマンドレットを実行する。
```PowerShell
# サインイン
PS C:\>  Connect-AzAccount
# サインイン(多要素認証設定済の場合)
PS C:\>  Connect-AzAccount -TenantId aaaa-bbbb-ccccc-00000 #引数でテナントIDを指定する必要がある
```
すると、エラーが表示された。
```
Connect-AzAccount : 'Connect-AzAccount' コマンドはモジュール 'Az.Accounts' で見つかりましたが、このモジュールを読み込むことができませんでした。
詳細については、'Import-Module Az.Accounts' を実行してください。
発生場所 行:1 文字:1
+ Connect-AzAccount -TenantId aaaa-bbbb-ccccc-00000
+ ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Connect-AzAccount:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CouldNotAutoloadMatchingModule
```

# 原因
エラーメッセージに書いてある通り、`Import-Module Az.Accounts`コマンドレットを実行してみる。
```
PS C:\> Import-Module Az.Accounts
Import-Module : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Program Files\WindowsPowerShell\Modules\Az.Accounts\3.0.4\A
z.Accounts.psm1 を読み込むことができません。詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照
してください。
発生場所 行:1 文字:1
+ Import-Module Az.Accounts
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) [Import-Module]、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand
```
どうやら、PowerShellの実行ポリシーが制限されていたことが原因らしい。

# 解決策
PowerShellの実行ポリシーを変更する。実行ポリシーは5段階あり、現在は**Restricted**になっていたため全スクリプトの実行が禁止されていた。（初期設定）
今回のような通常のケースでは、ローカルスクリプトとネットからDLした署名付きスクリプトにのみ実行を許可する**RemoteSigned**への変更が妥当と思われる。

:::note warn
よりポリシーを緩くすることもできるが、その分セキュリティリスクは高くなる。5段階のポリシーの詳しい条件については下記記事に記載があるので、参照の上自身のセキュリティ要件に適切なポリシーを選択頂きたい。
:::

https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750

現在のポリシーを確認する
```PowerShell
PS C:\> Get-ExecutionPolicy
Restricted
```
RemoteSignedへのポリシー変更。確認メッセージが表示されるので、`Y`を入力。
```PowerShell
PS C:\>  Set-ExecutionPolicy RemoteSigned

実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies のヘルプ トピック
(https://go.microsoft.com/fwlink/?LinkID=135170) で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "N"): Y
PS C:\>
```

ポリシーが変更され、コマンドレットを実行できるようになった
```PowerShell
PS C:\> Get-ExecutionPolicy
RemoteSigned
```

# 余談
・MS社の公式ドキュメント通りにサインインする場合は、ポリシー変更手順も記述されている為本エラーは発生しない想定。
・ポリシー変更時に、現在開いているPowerShellのプロセスのみ、または現在のユーザのみへの対象を絞ったポリシー変更も可能。

https://bonjiri-blog.com/powershell/how-to-change-powershell-execution-policy/
【情シスの星 #予告】情シスのリアルをお届けする新連載、はじまります！–情報システム部門を刺激するメディア「情シスのじかん」より

「情シスのじかん」は、情報システム部門のプロフェッショナルを対象としたメディアです。実務に役立つノウハウや革新的なアイデアを提供し、学びとネットワーキングの場を提供することを目指しています。最新の技術動向やベストプラクティス、成功事例を通じて、情シス担当者のスキルアップをサポートします。

ここで、Qiitaの読者の皆様向けに、「情シスのじかん」で公開された記事をピックアップ＆サマリ紹介します！Qiitaは技術者向けの情報共有プラットフォームとして、より実践的で具体的な技術情報を提供する場です。情シスのじかんは、特に情報システム部門に特化した内容を中心にしていますが、両者の強みを活かして、プロフェッショナルの皆様に有益な情報をお届けします。

### 【情シスの星 #予告】情シスのリアルをお届けする新連載、はじまります！
![title000_f-1-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816554/bab37d65-782b-1e97-6f5a-dda95ed021b1.jpeg)

情報システム（情シス）部門に潜む、知られざる情シスの生態、日常を描いた漫画シリーズ「情シスの星」。本連載は、毎週金曜日の朝10時に配信予定です。金曜日は、一週間の締めくくりでありながら、週末への心の切り替えが始まるちょっと特別な日。「あるある〜」と頷いたり、日々の業務に役立つヒントを得たりしながら、情報システム（情シス）部門に携わる方に楽しく読んでいただける連載を目指します。

https://josys.wingarc.com/hoshi-of-the-josys-000

### 情報システム部門を刺激するメディア「情シスのじかん」とは？
![OGP_情シスのじかん.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3816554/1f0ea482-2835-d6bd-4a8e-5ec733e466eb.png)

初めまして、『情シスのじかん』です。
近日遂に、日本中の情シス部門のあなたを刺激するメディアが発足します！🚨
さぁ、テクノロジーを飼い慣らし、仕事や生活の質を向上させ、一緒に未来を切り拓きましょう。皆様の生活リズムに合わせた情報発信で、常に寄り添い、共に未来を切り拓くためのメディアです。

ぜひ、情報システム部門の皆様の活動の取材をさせてください。

https://josys.wingarc.com/about
script

```
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>動的タイトル設定</title>
</head>
<body>
    <h1>動的タイトル設定のテスト</h1>
    <p id="output">URLパラメータを確認中...</p>

    <script>
        // ハッシュフラグメントからパラメータを取得する関数
        function getHashParameter(name) {
            const hash = window.location.hash; // ハッシュ部分を取得
            const params = new URLSearchParams(hash.substring(hash.indexOf('?') + 1)); // ハッシュからクエリ部分を解析
            return params.get(name);
        }

        // testCdの値をもとに、対応するJSONファイルからtitleを取得する関数
        async function fetchTitle(testCd) {
            const jsonFileName = `./themes/param/json/settings_${testCd}.json`;
            console.log('JSONファイル名:', jsonFileName);  // ファイル名を確認
            try {
                const response = await fetch(jsonFileName);
                console.log('レスポンス:', response);  // レスポンスの確認
                if (!response.ok) {
                    throw new Error('HTTPエラー: ' + response.status);
                }
                const data = await response.json();
                console.log('取得したデータ:', data);  // JSONの中身を確認
                return data.title;
            } catch (error) {
                console.error('JSONファイルの取得に失敗しました:', error);
                return null;
            }
        }

        // ページのロード時にタイトルを設定
        window.onload = async function() {
            console.log('ページがロードされました');
            console.log('window.location.hash:', window.location.hash);  // ハッシュ部分を確認
            const testCd = getHashParameter('testCd');  // ハッシュからtestCdを取得
            console.log('取得したtestCd:', testCd);  // 取得したtestCdを確認
            const outputElement = document.getElementById('output');

            if (outputElement) {
                if (testCd) {
                    outputElement.textContent = '取得したtestCd: ' + testCd;

                    // JSONファイルからタイトルを取得し、ページのタイトルを設定
                    const title = await fetchTitle(testCd);
                    if (title) {
                        // titleの値に応じて異なるタイトルを設定
                        if (title === "1") {
                            document.title = "1TITLE";
                        } else if (title === "2") {
                            document.title = "2TITLE";
                        } else if (title === "3") {
                            document.title = "3TITLE";
                        } else {
                            document.title = title;  // それ以外の値の場合はそのまま表示
                        }
                        console.log('設定されたタイトル:', document.title);  // 設定されたタイトルを確認
                    } else {
                        console.error('タイトルが取得できませんでした。');
                    }
                } else {
                    outputElement.textContent = 'URLパラメータ "testCd" が見つかりません。';
                }
            } else {
                console.error('ID "output" の要素が見つかりません。');
            }
        };
    </script>
</body>
</html>

```
Raspberry pi picoとpico 2の電流比較したら本当に下がってた

Raspberry Pi Pico 2が2024年8月9日に発表され、ようやく日本の販売店でも入荷され、手に入るようになりました。

https://www.switch-science.com/products/9809

大きな違いは、搭載されているマイコンがRP2040からRP2350となりました。
基板を見ると多少回路が変わっている気がしますが、回路図を見つけられなかったため、わかってません。
あとは、搭載されているFlash ROMが2MBから4MBになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/6bc5cf9c-40f3-dbe0-4213-832d25bbe565.png)

スイッチサイエンスさんのページでは、性能比較の結果が掲載されています。

https://www.switch-science.com/blogs/magazine/raspberry-pi-pico-pico-2

RP2350は、CPUアーキテクチャをARM Cortex-M33もしくは、RISC-V Hazard3から選んで使うことが、できます。両方ともデュアルコアで構成されています。
私的には、ARMが好きなので、RISC-V Hazard3じゃないとできないことがない限りは、ARM Cortex-M33一択です。

## ARM Cortex-M33の特徴
Raspberry Pi Pico 2に搭載されているRP2350のデュアルコアARM Cortex-M33は、Raspberry Pi PicoのRP2040のデュアルコアARM Cortex-M0+に比べ、浮動小数点演算とDSP、Arm TrustZone（セキュリティ機能）のサポートが追加されています。
デフォルトのクロック周波数は、133MHzから150MHzに上がっていますが、消費電流が下がっているとのことです。

## picoとpico 2の消費電流計測
性能が上がってるのに消費電流が下がってるということで実際に計測してみました。

電流計測は、以下の記事と同じPower Profiler Kit Ⅱを使いました。

https://qiita.com/jksoft/items/c53d3cb17114a7d88fc4

PicoとPico 2には、Arduino IDEで5秒おきに点滅するようにしたLチカのスケッチを書き込み比較しました。
Arduino IDEのボード定義は、[Arduino-Pico](https://arduino-pico.readthedocs.io/en/latest/index.html)を使用しています。v4.0.1からRaspberry Pi Pico2もサポートされました。

### 計測結果

#### Raspberry Pi Pico（デフォルト 133MHz）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/7c8e56de-6c84-960d-7e35-9c1417fbbfef.png)

#### Raspberry Pi Pico 2（デフォルト 150MHz）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/5f9bf4ba-1b09-3136-8b02-6bcd37702485.png)

#### Raspberry Pi Pico（クロックダウン 50MHz）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/1705ae83-b5c8-23f4-0932-89b853146ac8.png)

#### Raspberry Pi Pico 2（クロックダウン 50MHz）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109992/4ad2ee6e-af00-1b79-5692-94c3af4bb348.png)

### 計測結果について
デフォルトのクロック周波数で、Picoはアイドルで約20mA、Pico 2は約13.2mAということで、思ったより下がってますね。
クロックダウンして、両方とも50MHzの場合は、Picoは約10.1mA、Pico 2は約6.2mAということで、両方ともだいたい4割ほど下がっていることがわかりました。

### 最後に
Raspberry Pi Pico 2は、スペック上は主に性能アップということで、だいたい用途だったら従来のRaspberry Pi Picoで十分だと思っていましたが、消費電流も下がってるということで、電池駆動する場合でもRaspberry Pi Pico 2の方が良いですね！
Rspecにてcreated_atの検証で失敗する

# はじめに
RspecにてJSON形式のレスポンスデータを検証している際に、
`created_at`や`updated_at`にてデータが一致しないことで困っていた

# 困ってたこと

データ形式：
```ruby
{
    'key' => 'value',
    'created_at' => 'instance.created_at',
    'updated_at' => 'instance.updated_at',
}
```

Timeオブジェクトはミリ秒の値まで含んでしまっているため、
データが一致せずにテストが落ちてしまう

```plaintext
# 期待していたデータ
"created_at" => "2024-08-26T10:35:23+09:00"

# 実際に来たデータ
"created_at" => "2024-08-26T10:35:23.000+09:00"

```

# as_jsonで試してみた

https://railsdoc.com/page/as_json

as_jsonではハッシュ形式に変換してくれるらしい

created_atやupdated_atで比較するには、as_jsonを使うと良い

```
# as_jsonを使用した場合
hogehoge.created_at.as_json
"2024-08-26T11:23:03.000+09:00"

hogehoge.created_at
Mon, 26 Aug 2024 11:23:03 JST +09:00
```

https://stackoverflow.com/questions/19126862/test-datetime-fields-as-a-json-string-using-rspec

# be_jsonにしたほうが良さそう

毎回、created_atやupdated_atに対して `as_json` を使用するのはちと大変...
そんなこんなで、RSpec3にはコンポーザブルマッチャとなるものがあるみたい
```
expect(response.body).to be_json include(...)
```

https://qiita.com/jnchito/items/a4a51852c2c678b57868#2%E3%83%9E%E3%83%83%E3%83%81%E3%83%A3%E3%81%AE%E5%BC%95%E6%95%B0%E3%81%AB%E5%88%A5%E3%81%AE%E3%83%9E%E3%83%83%E3%83%81%E3%83%A3%E3%81%8C%E6%B8%A1%E3%81%9B%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%82%B6%E3%83%96%E3%83%AB%E3%83%9E%E3%83%83%E3%83%81%E3%83%A3-composable-matchers

どこかのタイミングで上記の書き方でJSONを比較するようにしたい
android sdk の API レベルを 34にした時のメモ

### bundle.gradle
```:bundle.gradle(:app)
    compileSdk 34
        targetSdk 34
```
```:bundle.gradle(:project)
    classpath 'com.android.tools.build:gradle:7.2.2'
```

### メニュー
:::note info
File > Project Structure
  Android Gradle Plugin Version -> 7.2.2
  Gradle Version 7.4.2
:::
SEO対策：ブラウザに表示される検索結果をベストプラクティスに沿ってコントロールしたい

SEO対策に関して取り組む機会を頂いたので、
備忘録として残します。

# 今回やりたいこと

ブラウザで検索した際に表示される

1. タイトル
1. 詳細
1. 画像

を可能な範囲で意図したものにしたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/0cbbe7ea-20b4-6fa2-2e92-3bcc3ef01640.png)

どちらかというと、具体的にどんな文章が良いか？という観点より、
**どんな実装をすれば良いか？**
というエンジニアの観点から記述しました。

# タイトル

> サイト上のすべてのページに \<title> 要素でページのタイトルが指定されているようにする。

htmlファイルの`<head>`タグ内に`<title>`タグを作成します。
ブラウザのタブに表示される文章ですね。

**ただし、`<title>`に記述した文章が必ず検索結果に表示されるわけではありません。**
Googleさんに適切なタイトルであると、認識して頂く必要があります。
詳しくは下記にて。

[最適なタイトルリンクを出しやすくするためのベスト プラクティス](https://developers.google.com/search/docs/appearance/title-link?hl=ja#page-titles)


# 詳細（スニペット）

> スニペットとは、Google 検索やその他のサービス（Google ニュースなど）で表示される検索結果の説明または要約部分です。

これは`<head>`タグ内に`<meta>`タグを作成します。
`name="description"`属性を付与します。

こちらもタイトルと同じく
**`<meta>`に記述した文書が必ず表示されるわけではありません**

[質の高い説明を使用する](https://developers.google.com/search/docs/appearance/snippet?hl=ja#use-quality-descriptions)

# 画像

> 次のベスト プラクティスを実施することで、画像が Google の検索結果に表示されるよう最適化できます。
> 1. Google が画像を検出してインデックスに登録できるようにする
> 2. 画像のランディング ページを最適化する

上記読んでみて、すぐに実践できそうな内容かいつまむ。

- `<img>`タグで画像を実装する ※cssで実装しない
- `image1.png`など、一般的なファイル名を避ける
- `alt`属性をしっかり書く

[Google 画像検索 SEO ベスト プラクティス](https://developers.google.com/search/docs/appearance/google-images?hl=ja)

# Googleのmetaデータを見てみた

Googleのサイトがどんな実装をしているのか、検証ツールで見てみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836454/72afafd5-0746-c599-b535-0860315d7314.png)

おー、勉強になる。
※`property="og:*"`はSNSでシェアした時のmetaデータなので、本記事では省きます

# 参考記事

- [メタタグとは？SEO対策に重要な7つのmetaタグと最適な書き方](https://emma.tools/magazine/seo/content-seo/seo-writing/meta-tags-for-seo/)
- [Google 検索結果のタイトルリンク（見出し）の変更](https://developers.google.com/search/docs/appearance/title-link?hl=ja)
- [検索結果のスニペットを管理する](https://developers.google.com/search/docs/appearance/snippet?hl=ja)
- [Google 画像検索 SEO ベスト プラクティス](https://developers.google.com/search/docs/appearance/google-images?hl=ja)
CodeSenseiを使ってみる

他にもいろいろサービスがあるだろうけれども、
CodeSensei　使って見たので、インストール手順を紹介する。

## 前提
- github を使っている。
- CodeReview サービスに対してcodeを公開することに対して、組織の了解が得られていること。

## 手順
以下のURLにアクセスする。

https://github.com/apps/getcodesenseijp

次のような画面が表示させるはずだ。

![Screenshot from 2024-09-05 10-54-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/ef05edaa-c5a8-155a-10b2-ccac40c22578.png)

右上にあるConfigure もしくは install をクリックする。
（利用中になっているとconfigureなのかもしれない）

そうすると、あなたのgithubのアカウントに入って
Applicationsの一つであるCodeSensei の設定画面にくる。
![Screenshot from 2024-09-05 10-54-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/512dc654-1105-2684-de56-5a705f24ed82.png)

ここで、どのリポジトリに対してアクセスを許可するのかを選択する。

この状態で、そのリポジトリでPRを上げると、次のようなレビュー結果が生成される。

次に示すのはコードレビューの結果だ。

![Screenshot from 2024-09-05 11-51-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/34f42b68-3efb-e2c1-2a7a-72e1e54e1768.png)

コードの目的に応じて対応してほしい。
書き捨てるためのコードに対して力を入れすぎても仕方ないから。


## ぜったいもっといい同様なサービスがあるはずだ。
- リポジトリの公用語を、英語にとどめておきたい場合には、英語での同様なサービスがあるはずだ。
- 利用するコンピュータ言語によっても、どれだけ適切なレビューを返してくれるかも違うはずだ。

## 他のサービスの場合

- [もう初回コードレビューはAIに任せる時代になった - CodeRabbit -](https://zenn.dev/minedia/articles/7928ef7545b393)
ESP32でMS Teamsに通知するBOTを作る

## やりたいこと

・赤外線センサを用いて一定以下の距離になったらms teamsに通知を投稿したい

## 使うもの、実行環境
- ubuntu22.04
- Ardino IDE
- ESP32 WROOM
- GP2Y0E03(赤外線センサ)

## 準備
### ESP32側
このプログラムを書き込む
```c:isDoorLocked.ino
#include <Wire.h>
//アドレス指定
#define GP2Y0E03_ADDR 0x40
#define DISTANCE_ADDR 0x5E

void setup()
{
	Serial.begin(9600); //シリアル通信を9600bpsで初期化
	Wire.begin();       //I2Cを初期化

	delay(500); //500msec待機(0.5秒待機)
}

void loop()
{
	//変数宣言
	unsigned int dac[2];
	unsigned int i, distance;

	Wire.beginTransmission(GP2Y0E03_ADDR); //I2Cスレーブ「Arduino Uno」のデータ送信開始
	Wire.write(DISTANCE_ADDR);             //距離の測定
	Wire.endTransmission();                //I2Cスレーブ「Arduino Uno」のデータ送信終了

	Wire.requestFrom(GP2Y0E03_ADDR, 2); //I2Cデバイス「GP2Y0E03」に2Byteのデータ要求
	for (i = 0; i < 2; i++)
	{
		dac[i] = Wire.read(); //dacにI2Cデバイス「GP2Y0E03」のデータ読み込み
	}
	Wire.endTransmission(); //I2Cスレーブ「Arduino Uno」のデータ送信終了

	distance = ((dac[0] * 16 + dac[1]) / 16) / (2 * 2); //距離(cm)を計算

	if (distance <= 15)//任意の値。単位はcm
	{
		Serial.println("Locked");
	}
	else
	{
		Serial.println("NotLocked");
	}

	delay(1000); // 1000msec待機(1秒待機)
}
```

### PC側
#### teams上のチームにwebhookを設定し、URLを発行する
https://qiita.com/SDN/items/3754ae1e8960df01cc11
#### ESPからのシリアルを読んでHTTP POSTする
```notify.py
import serial
import requests
import json

# WebフックURLを設定
WEBHOOK_URL = "https://hogehogefugafuga"

# ESP32とのシリアルポートを開く
ser = serial.Serial("/dev/ttyUSB0", 9600)  # '/dev/ttyUSB0'は適切なポートに置き換える

while True:
    # ESP32からのデータを読み取る
    if ser.in_waiting > 0:
        data = ser.readline().decode().strip()
        print("Received:", data)

        # 受信したデータが指定された命令ならば、WebフックにPOSTリクエストを送信
        if data == "the key was Locked!!":
            payload = {"text": "the key was locked!!"}
            headers = {"Content-Type": "application/json"}
            response = requests.post(
                WEBHOOK_URL, headers=headers, data=json.dumps(payload)
            )
            print("Response status code:", response.status_code)
            print("Response body:", response.text)
```

## 実行してみる
ESP側は書き込んで適当に距離を近づけたり遠ざけたりしていれば良い。
pythonの実行は
```sudo python3 serial_data_processor.py ```
import serialやimport requestsできないというようなライブラリが出た場合、ライブラリが入っていないということなのでpipコマンドでインストールする
```
pip install pyserial
pip install requests
```
pipも入っていない場合は先に
~~~
sudo apt install python3-pip
~~~
を実行してからインストールする。

うまく行けばチームに投稿される
![スクリーンショット 2024-10-23 215628.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3315851/58a01b79-11a7-6e36-d4f8-f2895205a919.png)

## 参考リンク集
https://spiceman.jp/arduino-gp2y0e03-program/

https://qiita.com/SDN/items/3754ae1e8960df01cc11

https://qiita.com/sttn/items/567c9f49b88ff275b51a

https://qiita.com/ohbashunsuke/items/ea829f79a723406e9876

https://magazine.techacademy.jp/magazine/19195
EC2インスタンスにssh接続後に自動でNginx、MySQLを起動するための設定方法

## アジェンダ
Nginxをインストールした **Webサーバーインスタンス** と、MySQLをインストールした **DBサーバーインスタンス** は、それぞれ別々のインスタンスであるため、個別にSSH接続を行って設定を進める必要があります。
その手順について簡単にまとめます。

## 手順
### 1. WebサーバーインスタンスにSSH接続してNginxの自動起動設定

WebサーバーインスタンスにSSHで接続し、Nginxの自動起動設定を行います。

```bash
ssh -i <your-key.pem> ubuntu@<WebサーバーのパブリックIP>
```

次に、先ほど説明したようにNginxを自動起動に設定します。

```bash
sudo systemctl enable nginx
```

その後、サーバーが再起動された際に自動的にNginxが起動することを確認します。

```bash
sudo systemctl status nginx
```

### 2. DBサーバーインスタンスにSSH接続してMySQLの自動起動設定

次に、DBサーバーインスタンスにもSSH接続を行い、MySQLの自動起動設定をします。

```bash
ssh -i <your-key.pem> ubuntu@<DBサーバーのパブリックIP>
```

接続後、MySQLを自動起動に設定します。

```bash
sudo systemctl enable mysql
```

同様に、再起動後にMySQLが自動で起動することを確認します。

```bash
sudo systemctl status mysql
```

### 3. サーバーの再起動

各インスタンスで設定を行った後、それぞれのサーバーを再起動し、再起動後にNginxとMySQLが自動で起動することを確認します。再起動後もSSHで接続して、`systemctl status`コマンドでサービスの状態を確認してください。
【AtCoder】計算量の見積り

## 例題1
[ABC227C - ABC conjecture](https://atcoder.jp/contests/abc227/tasks/abc227_c)

```C++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
  ll N; cin >> N;
  
  ll ans = 0;
  for (ll a = 1; a*a*a <= N; a++) {
    for (ll b = a; a*b*b <= N; b++) {
      ll mc = N / (a*b);
      ans += mc - b + 1;
    }
  }
  
  cout << ans << endl;
}
```

```math
\displaylines{
\sum_{a=1}^{\sqrt[3]{N}} (\sqrt{\frac{N}{a}} - a + 1) 
= \sqrt{N} + \sum_{a=2}^{\sqrt[3]{N}} (\sqrt{\frac{N}{a}} - a + 1) \\
\leq \sqrt{N} + \int_{1}^{\sqrt[3]{N}} (\sqrt{\frac{N}{x}} - x + 1)dx
= O(N^{\frac{2}{3}}) \\
i.e. \sum_{n=1}^{\sqrt[3]{N}} (\sqrt{\frac{N}{a}} - a + 1)
\leq O(N^{\frac{2}{3}})
}
```
Anaconda Powershell で Anaconda 起動できずハマった件（にっちもさっちもいかない場合の対応方法）

(普段他WindowsやLinuxを利用しているので) 久々に開いた Windows で Anaconda Powershell(Windows Powershell も同じ)を開いたところ、以下エラーで Anaconda が起動できず、ハマる。conda コマンドが全く機能しない。(Powershell 起動時に base で起動するように戻したい。)

```Error message
& : 用語 'C:\Users\username\anaconda3\shell\condabin\conda-hook.ps1' は、コマンドレット、関数、スクリプト ファイル、または
操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパ
スが正しいことを確認してから、再試行してください。
発生場所 行:1 文字:3
 & 'C:\Users\username\anaconda3\shell\condabin\conda-hook.ps1' ; conda ac ...
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\tiida\...\conda-hook.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

conda : 用語 'conda' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されませ
ん。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してくだ
さい。
発生場所 行:1 文字:62
+ ... \Users\username\anaconda3\shell\condabin\conda-hook.ps1' ; conda activat ...
+                                                             ~~~~~
    + CategoryInfo          : ObjectNotFound: (conda:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
```

## 「環境変数がー」という記事をいろいろ実行して解決できず、最後の頼みで Chat-GPT に確認して以下のレス試す。

```
Anacondaが正しくアンインストールできない場合や、インストールが破損している場合、以下の手順で問題を解決することができます。

### 1. `Anaconda` フォルダの削除
まず、Anacondaのインストールディレクトリ（通常は `C:\Users\tiida\anaconda3`）を手動で削除します。

1. **エクスプローラーを開く**:
   - `C:\Users\tiida\` に移動し、`anaconda3` フォルダを見つけてください。
  
2. **フォルダを削除**:
   - `anaconda3` フォルダを右クリックして「削除」を選択します。
   - フォルダの削除には少し時間がかかる場合があります。

### 2. 環境変数のクリーニング
Anacondaのパスがシステムの環境変数に残っている場合があります。以下の手順でこれを削除します。

1. **スタートメニューを右クリック**:
   - 「システム」または「システム設定」を選択します。
   
2. **「システムの詳細設定」へ移動**:
   - 「システムの詳細設定」をクリックし、「環境変数」を選択します。

3. **環境変数を確認**:
   - `Path` 変数の中に `C:\Users\tiida\anaconda3` または関連するパスがあれば、それを選択して削除します。

4. **他の関連変数を確認**:
   - `CONDA_*` や `PYTHONPATH` など、Anacondaに関連する環境変数も削除します。

### 3. レジストリのクリーニング (注意が必要です)
Anacondaに関連するレジストリキーが残っている可能性があるため、これを手動で削除することも考えられます。ただし、レジストリを編集する際には注意が必要です。

1. **レジストリエディタを開く**:
   - `Windows + R` を押して「regedit」と入力し、Enterキーを押します。

2. **Anaconda関連のキーを探す**:
   - `HKEY_CURRENT_USER\Software` と `HKEY_LOCAL_MACHINE\SOFTWARE` の下に `Anaconda` または `Continuum` に関連するキーがあれば、それらを削除します。

### 4. インストールのリトライまたは新しいインストール
手動での削除が完了したら、必要であればAnacondaを再インストールするか、他のPythonディストリビューション（例: MinicondaやPyenvなど）をインストールすることができます。
```

## [Add Anaconda to my PATH environment variable] にチェックを入れて再インストールで解決

## 結論：最初からGPTに確認して、それがダメだったら自力検索調査がよかったかもしれない。
### *ここにくるまで数時間、なんだったのか？という事ありませんか？ｗ
Nuxt3 - 静的なHTMLファイルを設置する

publicにHTMLファイルを置けば良いだけ

# 例

ファイルパス

```
public/example.html
```

URLのパス

```
/example.html
```


# 表示例

<img width="416" alt="image" src="https://github.com/user-attachments/assets/be83cb14-7999-45af-9ecc-f5536199f91b">



# チャットメンバー募集


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

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


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
ThinkpadでUbuntuをいれようとしたらUSBが反応しない

# はじめに

WindowsからUbuntuに変更しようとして困ったことを載せます

# 問題

BIOSから優先順位を変えて、起動しても何故かUSBのUbuntuが開きませんでした

# 解決方法

Secure Bootをオフにすると起動ができました

# 参考

https://learn.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/disabling-secure-boot?view=windows-11
OSS LLM をローカルでいろいろ動かしてみる

# やりたいこと
今まで OSS の LLM を触っていないなと気づいてローカルでいろいろやってみようと思い、動かし方など調べたので記事にしてみます。今回は GPU を使わず CPU のみで実行、かつコンテナ上で実行します。

# 環境
OS: macOS Sonoma (14.3)
CPU: M3 Pro
メモリ: 36GB

:::note
Windows の方は WSL で実行できると思います
:::

# 使用するツール
- Docker
    - `docker` コマンドを実行できれば OK

:::note warn
モデルを実行させるのにある程度メモリが必要なので、メモリの割り当てをある程度大きくしておくのが無難です。Llama3.1 だと約6GB必要です。
:::

# 実行
## Ollama
LLM を動作させることのできる、[Ollama](https://ollama.com/) のコンテナを以下コマンドで準備する。

```sh
docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
```

上記で起動したコンテナ上で、`ollama` コマンドが使えるようになる。
今回は CPU のみで実行するので上記コマンドだが、GPU を使いたい場合は以下を参考。

https://hub.docker.com/r/ollama/ollama

## Model
### Llama3
Llama3 を使ってみる。

```sh
docker exec -it ollama ollama run llama3
```

モデルのダウンロードが始まるのでしばらく待つ。
ダウンロードが完了すると `>>> Send a message (/? for help)` というプロンプトが表示されるので、自由にプロンプトを記入する。PC のスペックによって待ち時間は変わるがしばらくすると、回答が返ってくる！

```tex
>>> Hello
Hello! It's nice to meet you. Is there something I can help you with, or would you like to chat?
```

チャットを終了するときは、`/bye` と入力する。

Ollama の [Library](https://ollama.com/library) にあるモデルは上記の方法で簡単に実行できる。

### ELYZA
詳しくは以下の記事を参照。ELYZA 社が llama3 をベースに開発した日本語特化したモデル。

https://note.com/elyza/n/n360b6084fdbd

https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/tree/main

ELYZA は Ollama の Library にないので、自前で準備する必要がある。

まずは、起動してある Ollma のコンテナでシェルを実行する (終了するときは `exit`)。

```sh
docker exec -it ollama /bin/bash  # 好きなシェルで OK
```

モデルをダウンロードする。

:::note warn
`curl` コマンドがインストールされていない場合は、`apt` などでインストールしてください
:::

```sh
mkdir models && cd models
mkdir Llama-3-ELYZA-JP-8B && cd Llama-3-ELYZA-JP-8B
curl -OL https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/resolve/main/Llama-3-ELYZA-JP-8B-q4_k_m.gguf
```

ダウンロードしたモデルと同じディレクトリに、以下の内容で Modelfile を作成する。

```tex
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
TEMPLATE """{{ if .System }}
system


{{ .System }}
{{ end }}{{ if .Prompt }}
user


{{ .Prompt }}
{{ end }}
assistant


{{ .Response }}
"""
PARAMETER stop "
"
PARAMETER stop "
"
PARAMETER stop "
"
PARAMETER stop "<|reserved_special_token"
```

最後に Ollama モデルを作成する。

```sh
ollama create elyza:jp8b -f Modelfile
```

これで準備は完了したので実行してみる。

```sh
ollama run elyza:jp8b
```

```tex
>>> こんにちは
こんにちは！どうぞよろしくお願いします。
```

## チャット UI で動かしてみる
Ollama 対応の Web UI があるので、それを使う。

https://github.com/open-webui/open-webui

こちらもコンテナ上で実行する。

```sh
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
```

コンテナを起動したら http://localhost:3000 にアクセス。サインイン画面が表示されるので指示に従ってサインインすると ChatGPT ライクな UI が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/e0402123-7999-8cf3-aa79-6d30a85659cd.png)

チャット領域の左上で使用するモデルを切り替えられる。複数のモデルと同時にチャットもできるので回答を比較したいときに便利。

# ということで
OSS の LLM をローカルで実行して、チャット UI で使ってみました。
基本的にコンテナで提供されているので、ローカル環境を汚さずに簡単にここまでできるのは非常にありがたいですね！
ローカルで動かすので動作がすごく重たいイメージを持っていましたが、私の環境ではそこまででした (マシンスペックにもよるでしょうけど)。データプライバシーを気にする場合やファインチューニングしたモデルを使いたい場合は、クラウドサービスではなく自前で環境を用意するのも割とありなのではと感じます。


以上です。
金融サービスクラウド向け CRM 分析管理




https://trailhead.salesforce.com/content/learn/modules/crm-analytics-administration-for-financial-services-cloud


otsubo-ltwv@force.com ドメインの問題なのかハンズオン組織には登録できない

最後でエラーになりました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/70f94aec-c62c-c929-ea61-83acbd495a75.png)

```
Unable to create app based on template: [sfdc_internal__FSCAnalyticsIndustryApp].

* Your org does not currently meet minimum data requirements to proceed. Please fix the following issues before creating a 'Analytics for Wealth Management' Application:

In the 'FSC_Digest_ACR' node, the 'FinServ__SourceSystemId__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Opportunity' node, the 'FinServ__Household__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Case' node, the 'FinServ__FinancialAccount__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Account' node, the 'FinServ__CustomerSegment__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User. In the 'FSC_Digest_Account' node, the 'FinServ__CustomerType__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User. In the 'FSC_Digest_Account' node, the 'FinServ__LastTransactionDateJointOwner__c' field ...

* Your org does not currently meet minimum data requirements to proceed. Please fix the following issues before creating a 'Analytics for Wealth Management' Application:

In the 'FSC_Digest_ACR' node, the 'FinServ__SourceSystemId__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Opportunity' node, the 'FinServ__Household__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Case' node, the 'FinServ__FinancialAccount__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User.

In the 'FSC_Digest_Account' node, the 'FinServ__CustomerSegment__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User. In the 'FSC_Digest_Account' node, the 'FinServ__CustomerType__c' field doesn't exist, is deprecated, or isn't accessible to the Integration User. In the 'FSC_Digest_Account' node, the 'FinServ__LastTransactionDateJointOwner__c' field ...
```

+ [I can't see the error to fix it, what now?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007erKK3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/63ebaae9-c959-6cb0-0804-aafa68b0ef29.png)
AWS SecretsManager をCFnで作成

資格勉強では内容を知っているだけで、実際に触ったことがなかったため、今回は初めてAWS Secrets Managerの設定を行います。RDSの認証情報を管理するために利用します。

# AWS SecretsManagerとは
AWS Secrets Managerは、データベースのユーザー名やパスワード、APIキー、OAuthトークンなどの機密情報を安全に保管・管理するサービスです。AWSリソース（例えばECSやLambda）は、適切なIAMロールを使ってSecrets Managerから認証情報を取得することができます。これにより、開発者がパスワードなどを手動で管理する必要がなく、セキュリティが向上します。

また、Secrets ManagerはLambdaと組み合わせることで、パスワードの定期ローテーションが可能です。

CloudFormationを使えば、シークレットの作成や管理を自動化でき、パスワードのランダム生成も行われるため、手動で入力する必要がないのはすごく便利ですね！


## CloudFormationで作成する場合の注意点
RDSインスタンスなどのAWSリソースとSecrets Managerを統合する場合は、SecretTargetAttachmentの設定が必要です。これは、シークレットとリソースを関連付けるためのものなので忘れずに

AWSマネジメントコンソールを使う場合は、これらの設定がバックエンドで自動的に処理されるため、ユーザーが明示的に設定する必要がないとのこと


### CloudFormationで作成されたシークレットの確認方法
AWS Secrets Managerのコンソール画面にアクセスし、確認したいシークレットを選択します。
Secret valueの項目のRetrieve secret valueを押すと確認できます。（権限がある方のみ閲覧可能です！）

リソースの例（一部）
```
{
    "Resources": {
        "CloudFormationCreatedSecret": {
            "Type": "AWS::SecretsManager::Secret",
            "Properties": {
                "Description": "Simple secret created by AWS CloudFormation.",
                "GenerateSecretString": {
                    "SecretStringTemplate": "{\"username\": \"saanvi\"}", # ユーザ名をテンプレートとして指定
                    "GenerateStringKey": "password", # パスワードを自動生成
                    "PasswordLength": 32 #パスワードの長さを指定 
                }
            }
        }
  
  ## Secrets Manager: Secret Target Attachment
  SecretTargetAttachment:
    Type: AWS::SecretsManager::SecretTargetAttachment
    Properties:
      SecretId: !Ref SecretForRDS  # 作成したシークレットのIDを参照
      TargetId: !Ref MyRDSInstance  # 対象となるRDSインスタンスのID
      TargetType: "AWS::RDS::DBInstance"  # 対象リソースのタイプを指定

```

今回はCloudFormation（CFn）を使ってシークレットを作成したので、とっても楽でした！
CFnのリソースについてはAWS公式ドキュメントに詳細が載っているので、それを参考にしながら作成しました。まだまだ理解できていない部分もありますが、少しずつ頑張っていきたいと思います！
Metabaseを活用したデータビジュアライゼーション

## はじめに

データを基にした分析と可視化は、ビジネスにおいて重要な意思決定をサポートします。そのため、多くの企業がBI（ビジネスインテリジェンス）ツールを利用してデータを視覚的に整理し、インサイトを得ています。この記事では、オープンソースのBIツール「Metabase」を使って、データの可視化とその応用方法を紹介し、セットアップから具体的な操作までの基本ステップを解説します。

## Metabaseとは？

Metabaseはオープンソースで提供されているBIツールで、非エンジニアのユーザーでも簡単にデータにアクセスし、クエリを実行して可視化できるプラットフォームです。以下にMetabaseの主な特徴を挙げます。

- **オープンソースで無料利用可能**: コストを抑えつつ、拡張性やカスタマイズも容易。
- **直感的なUI**: SQLを使わずにデータをクエリできるGUI操作が可能。
- **豊富な可視化オプション**: グラフやチャート、地図表示など、多彩なビジュアル形式が揃っています。
- **ダッシュボード作成**: 複数の可視化を組み合わせて、リアルタイムにデータを監視できるダッシュボードを簡単に作成できます。

## Metabaseのセットアップ手順

Metabaseのセットアップは非常にシンプルで、Dockerを使えば短時間で導入できます。以下の手順でセットアップを行います。

1. **Dockerのインストール**  
   MetabaseはDockerを使用して簡単にインストール可能です。公式サイトからDockerをインストールします。

2. **Metabaseのコンテナ起動**  
   以下のコマンドを使ってMetabaseをDockerコンテナとして実行します。

   ```bash
   docker run -d -p 3000:3000 --name metabase metabase/metabase
   ```

   このコマンドでMetabaseがポート3000で動作し、ブラウザからアクセスできるようになります。

3. **ブラウザでアクセスして初期設定**  
   `http://localhost:3000` にアクセスし、初期設定を行います。ここで、管理者アカウントやデータベース接続の設定を行います。
   ![スクリーンショット 2024-09-05 10.36.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/206ca0ab-6576-ba10-86f6-255acdffa520.png)


## データベースへの接続とクエリの実行

Metabaseを使用して外部データベースに接続し、データを操作する方法を説明します。今回はGoogle BigQueryを例に、その接続手順を見ていきます。

1. **Google Cloudでのサービスアカウントキーの作成**  
   [Google Cloud Consoleで新しいサービスアカウントを作成](https://qiita.com/RyutoYoda/items/e42a575d3d46e160a4d7)し、BigQueryへのアクセス権を設定したJSON形式のキーを作成します。
  

2. **Metabaseでデータベースに接続**  
   Metabaseの管理画面から「データベースを追加する」を選択し、BigQueryを選びます。作成したサービスアカウントキーをアップロードし、必要な接続情報を入力します。
   ![スクリーンショット 2024-09-05 10.37.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/3c08be59-85f9-8990-8c2f-3c8ca4a809ed.png)


3. **クエリエディタでのデータ取得**  
   接続が完了したら、Metabaseのクエリエディタを使ってBigQueryのテーブルからデータをクエリします。SQLに不慣れなユーザーでも、Metabaseのビジュアルクエリエディタを使うことで簡単にデータを取得できます。
   ![スクリーンショット 2024-07-30 11.49.27 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/b162d892-40b1-07d8-81ec-95745f66c941.png)


## データのビジュアル化とダッシュボードの作成

Metabaseの魅力は、データを簡単に可視化できる点です。さらに、複数の可視化をダッシュボードにまとめ、プロジェクト全体を一目で把握できる環境を作ることができます。

1. **データのビジュアル化**  
   クエリ結果を元に、棒グラフ、折れ線グラフ、円グラフなどの形式でデータを視覚化できます。Metabaseは多彩なグラフオプションを提供しており、データのトレンドや傾向を視覚的に把握できます。
   ![スクリーンショット 2024-07-30 11.51.22 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/94d5e88c-b21e-037e-b483-13a284ea2630.png)

   

2. **ダッシュボードの作成**  
   複数のグラフやチャートを組み合わせて1つのダッシュボードにまとめ、リアルタイムでデータを監視し、共有できます。これにより、ビジネスの意思決定を迅速に行うための強力なツールとなります。
   ![スクリーンショット 2024-07-30 11.57.43 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/153c070a-bbb5-89d4-c7fa-4ef18f4a65f9.png)


## 結論

Metabaseは、オープンソースでありながら非常に強力なBIツールです。使いやすいインターフェースと豊富な可視化オプションにより、技術的なスキルが少なくても、誰でも簡単にデータの可視化と分析が行えます。Google BigQueryなどのクラウドデータベースと連携させることで、リアルタイムのデータ分析が可能となり、ビジネスにおける意思決定を加速させることができます。ぜひ、Metabaseを活用してデータの力を引き出し、ビジネスの成功をサポートしましょう。
最小構成でPWA

綾坂ことです。

https://axtech.dev/special/profile/

## 本題

https://qiita.com/hidao/items/fb6eab876f05a9a6f820

↑この記事を読みました。
オフライン対応できるのは嬉しいのでできればこっちのほうが絶対にいいです
……が、インストールだけできればいいや〜ってときはもうちょっと削れます
~~私がキャッシュとかの処理を考えるのが面倒ってだけなんですけど……~~

```sw.js
'use strict';
self.addEventListener('fetch', (event) => { // ファイルの受信が必要になったら
    event.respondWith( // 受信結果は以下の通り返すものとする
        fetch(event.request) // 必要なファイルをそのまま要求して
            .then((response) => { // ファイルを受信したら
                return response; // それをそのまま返す
            })
    );
});
```
Vue3 Composition API のTSの書き方メモ

2024-09-09
コメントでいただいた件を修正しました。

## setupする
スクリプトタグにsetupを追加する

``` typescript
<script setup lang="ts">
```

## defineXxxはimportに書かない
キホンの木

```typescript
<script setup lang="ts">
defineProps({
  hoge: { type: String, default: "" }
});
const emit = defineEmits(['render']);
defineExpose({
  onClick: () => {}
});
// など
```

## defineProps内の型の書き方
String, Number, Array, Object, Boolean以外の書き方

```typescript
<script setup lang="ts">
import { PropType, withDefaults } from 'vue';

type Hoge { id: number };
interface Props {
  hoge?: Hoge;
  hoges?: Hoge[];
}
withDefaults(defineProps<Props>(), {
  hoge: undefined,
  hoges: () => []
});
```

## reactiveな変数にはref or reactiveをつける
よく使う

```typescript
<script setup lang="ts">
import { ref } from 'vue';

const isOpen = ref(false);

const toggleOpen = () => {
  isOpen.value = !isOpen.value;
}

... 省略 ...

<template>
<!-- ここでは.valueは書かなくてOK --!>
<Modal :open="isOpen">
```

オブジェクトの場合はreactiveがラク

```typescript
<script setup lang="ts">
import { reactive } from 'vue';

const statuses = reactive({ isOpenA: true, isOpenB: false });

const toggleOpenA = () => {
  statuses.isOpenA = !statuses.isOpenA;
}
```


## refにコンポーネントを設定する 〜 親から子の関数を実行する
よく忘れるし、親コンポーネントから子コンポーネントの関数を叩くのはあまりない

```typescript:Childコンポーネント
<script setup lang="ts">
import { ref } from 'vue';
import Hoge from './hoge.vue';

const hoge = ref<InstanceType<typeof Hoge> | null>(null);
const onClickHoge = () => {
  hoge?.value?.onClick?.();
}

... 省略 ...

<template>
<Hoge ref="hoge">
```

```typescript:Parentコンポーネント
<script setup lang="ts">
defineExpose({
  onClick: () => {} // ←これが親から呼ばれる
})
```

## refの余談
Vitestでテストを運用している ＋ onMounted内でrefを更新している場合、
VitestがonMountedの更新を待たずにスナップショット撮るケースがあり、
以下で回避できる

```typescript
import { nextTick } from 'vue';
import Hoge from './hoge.vue';

describe('ほげ', () => {
  it('ほげほげ', async () => {
    const wrapper = shallowMount(Hoge);
    await nextTick(); // onMountedが完了するのを待つ
    expect(wrapper.element).toMatchSnapshot();
  });
});
```

## emitは$eventもしくは「...」で受け取る
呼び出し元のコンポーネントでご自由にどうぞ

```typescript:Childコンポーネント
const emit = defineEmits(['open', 'close']);
const onOpen = () => {
  emit('open', true)
}
const onClose = () => {
  emit('close', true, false, 123)
}
```

```typescript:Parentコンポーネント
const onClose = (...args) => {
  console.log(args); // [true, false, 123];
}

... 省略 ...

<template>
<Child @open="isOpen = $event" @close="onClose" />
```

## 更新可能なcomputedはgetter, setterを使う
emitとの連携がある場合にはすっきり書ける

```typescript
const props = defineProps<{ isOpen: boolean }>();
const emit = defineEmits(['open'])
const open = computed({
  get: () => props.isOpen,
  set: (val) => emit('open', val),
});
```
Top 5 Pro Video Editing Apps for Creating TikTok Content

1. CapCut
CapCut is one of the most popular video editing apps, especially for TikTok creators. With features like slow-motion, reverse, and keyframe animations, https://capckutapk.com  offers a variety of tools for detailed editing. It’s user-friendly and includes advanced features like chroma key, motion tracking, and multi-layer editing.

2. InShot
InShot is known for its ease of use and powerful video editing tools. It supports trimming, speed control, background music, and transitions, making it perfect for TikTok videos. The app also allows you to adjust aspect ratios for different social media platforms.

3. VN Video Editor
VN Video Editor offers advanced editing features like multi-layer timeline editing, keyframe animation, and motion effects. It’s great for creating detailed and professional TikTok videos. You can also add text effects, filters, and background music.

4. Adobe Premiere Rush
Adobe Premiere Rush is a high-quality video editing app that allows for easy yet professional-level editing. With its drag-and-drop interface, you can quickly create content optimized for TikTok, add transitions, and adjust colors and audio.

5. KineMaster
KineMaster is a versatile video editor that offers layers, filters, transitions, and audio effects. Its pro version gives you access to premium features like 4K video support, chroma key, and no watermarks, which are great for creating TikTok content.
kintoneでのbase64の扱い（決定版？）

# Base64
kintoneではBasic認証やパスワード認証で利用されるBase64エンコード。
やり方によってはエラーが発生します。日本語が含まれるユーザーIDとか。

みなさんどうやって変換していらっしゃるのかな？

# PureなJavaScriptでのBase64エンコード
```javascript
const base64 = btoa('username:password');
console.log(base64);
// dXNlcm5hbWU6cGFzc3dvcmQ=
```
こんな感じで普通のJavaScriptでもできます。
ですが以下の場合はエラーになります。
```javascript
//つまり、IDやパスワードに日本語が含まれる場合
const base64 = btoa('きんとーん:password');
console.log(base64);
```
Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

# 日本語エラーを回避する

https://www.npmjs.com/package/js-base64

上のライブラリを利用しています。

```javascript
import {Base64} from 'js-base64';
Base64.encode(`きんとーん:password`);  
// 44GN44KT44Go44O844KTOnBhc3N3b3Jk
```

CDNからも利用できます。

https://www.jsdelivr.com/package/npm/js-base64

便利ですね。ありがたいです。

---

こちらのサイトで実際に使ってみました。kintoneの接続文字列作成や検証にも使えます。

https://www.pulsar-works.jp/tools/base64/

試してみてくださいね。