OmniAICreator/Qiita-1.07M huggingface dataset:
NERDTreeを使い始めた。設定メモ

## Vim起動時にファイル引数がなければNERDTreeを開く
[公式README](https://github.com/preservim/nerdtree)より
```vim
" Start NERDTree when Vim is started without file arguments.
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists('s:std_in') | NERDTree | endif
```

## NERDTreeを開く or 閉じる
```vim
" Start/Toggle NERDTree
nnoremap <silent> <leader>ne :NERDTreeToggle<CR>
```

## ヘルプ表示を消す
```vim
" remove the help line
let NERDTreeMinimalUI=1
```

## キーバインド変更
ディレクトリの出入りのキーバインドを変更。  
変数名は[plugin/NERD_tree.vim](https://github.com/preservim/nerdtree/blob/master/plugin/NERD_tree.vim)を参照。  
```vim
" Change keybind
let NERDTreeMapChangeRoot='<C-l>'
let NERDTreeMapUpdir='<C-h>'
```
デフォルトのキーバインドから奪い取ってhelpにも反映される。

## ソート変更
ファイル名順とファイル更新日時降順のソート変更をキーバインド。  
```vim
" Change sort order
let g:NERDTreeSortOrder=['\/$', '*', '\.swp$',  '\.bak$', '\~$', '[[-timestamp]]']
function! Nerd_sort_default() abort
  let g:NERDTreeSortOrder=['\/$', '*', '\.swp$',  '\.bak$', '\~$']
  :NERDTreeRefreshRoot
endfunction
function! Nerd_sort_timestamp() abort
  let g:NERDTreeSortOrder=['\/$', '*', '\.swp$',  '\.bak$', '\~$', '[[-timestamp]]']
  :NERDTreeRefreshRoot
endfunction
autocmd FileType nerdtree nnoremap sd <CMD>call Nerd_sort_timestamp()<CR>
autocmd FileType nerdtree nnoremap sn <CMD>call Nerd_sort_default()<CR>
```
配列の順に表示される。  
`'\/$'`はディレクトリ、`'*'`は(その他の)全ファイル。  
`['*', '\/$']`と書けばディレクトリが最後に来る。  

## 自動的に表示更新
```vim
" Auto Refresh
autocmd BufEnter NERD_tree_* | execute 'normal R'
autocmd FocusGained NERD_tree_* | execute 'normal R'
```

## NERDTreeのバッファーの上書きを抑止
```vim
" Prevent buffer loads within NERDTree
autocmd BufWinLeave * if &filetype == 'nerdtree' | call interrupt() | endif
```

## 使い方メモ
- 表示ディレクトリルート(ツリールート)変更

  ```
  :cd ~/xxx
  CD
  ```
  これ、1コマンドでやりたいね。
レーザー通信してみた話

電波より盗聴されにくいのかな？

# はじめに
- M5StickCPlus2を買ってから、パーツ欲がとまらず、Laserモノも購入した。
[送信機(laser.tx)](https://docs.m5stack.com/ja/unit/laser-tx)、[受信機(laser.rx)](https://docs.m5stack.com/ja/unit/laser-rx)
- 購入したからには当然動かすしかない。

# 実際の動作状況
・M5StickCPlus2からM5AtomS3にレーザーを飛ばしている。
・macのシリアルモニタで「sdf」を入力して、M5AtomS3に表示させた。
![GIF_20240323_230957_023.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/315706d8-59f3-2a0b-7aac-d716c9a7f241.gif)


# コード(ArduinoIDE)
- M5StickCPlus2
```cpp
#include <M5Unified.h>

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  //レーザー通信をSerial2で行う
  Serial2.begin(9600, SERIAL_8N1, 33, 32);  //cp2用pin

  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(YELLOW);  //タイトル色
  M5.Lcd.println("LASER TX");   //タイトル表示
  M5.Lcd.setTextColor(CYAN);    //送信色
}

void loop() {
  //PCから文字列を受信し、レーザーでatomS3に送信する
  if (Serial.available()) {
    String str = Serial.readStringUntil('\n');
    M5.Lcd.println(str);
    Serial2.println(str);
  }

  //ボタンAを押すとabcdeを送信
  if (M5.BtnA.wasPressed()) {
    String str = "abcde";
    M5.Lcd.println(str);
    Serial2.println(str);
  }
  M5.update();
}
```

- M5AtomS3
```cpp
#include <M5Unified.h>

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  //レーザー通信をSerial2で行う
  Serial2.begin(9600, SERIAL_8N1, 1, 2);  //atomS3用pin

  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(YELLOW);  //タイトル色
  M5.Lcd.println("LASER RX");   //タイトル表示
  M5.Lcd.setTextColor(GREEN);   //受信色
}

//受信のみするループ
void loop() {
  if (Serial2.available()) {
    String str = Serial2.readStringUntil('\n');
    M5.Lcd.print("_");//文頭にアンダーバーを付けた
    M5.Lcd.println(str);
  }
}
```

# コードの解説
- Serial2にpin番号を設定して通信するだけ。以上。

# おわりに
- あっさり動いた。M5Stackの商品は、簡単に動くのが良い。
- 今回一番苦労したのは、動作状況の撮影だったかもしれない。いい感じの位置を決めるのが難しかった。
- そのうち、実用距離がどれくらいなのか実験して報告したい。
Mac備忘録

WindowsとMacを行き来すると忘れちゃうので備忘録

# Macの修飾キー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/4cd3a9ed-74b5-4d0c-f655-c937b1215635.png)

[Macのメニューに表示される記号](https://support.apple.com/ja-jp/guide/mac-help/cpmh0011/mac)

# Windows用のキーボードを使う
|用途|ショートカット|
|:--|:--|
|英語<->かな|Ctrl + スペース|
|コピー|windowキー＋c|
COBOLに入門してみた・・・

レガシーなCOBOLから別言語に移行したい。
COBOLを読むために最低限のCOBOL知識が必要というのが学習のモチベーション。

## COBOLの構成
以下4部で構成。
- 見出し部（IDENTIFICATION DIVISION）
  - プログラム名、作成者名、作成日などが書かれる
- 環境部（ENVIRONMENT DIVISION）
  - 環境変数、ファイルなどが書かれる
- データ部（DATA DIVISION）
  - 変数定義、ファイルレイアウトなどが書かれる
- 手続き部（PROCEDURE DIVISION）
  - 処理が書かれる

## 命令文

- DISPLAY
  - 表示内容をコンソールに出力する
- ACCEPT
  - キーボードからの入力を受け取る 
- IF～THEN
  - 条件分岐
- EVALUATE
  - 条件分岐（switch文のような）
- PERFORM UNTIL
  - 繰り返し
- PERFORM VARYING UNTIL
  - 繰り返し（VARYINGにより、カウンタが自動的にカウントアップ）
- PERFORM TIMES
  - 繰り返し（固定回数の繰り返し）

## データ定義
以下のように定義する。
```
レベル番号 変数名 PIC 型(桁数)
例：01 I PIC 9(3).
```

聞きなれないレベル番号は、階層を表す。
集団項目をみるとイメージがつく。
```
01 EMP.
    03 NMB PIC 9(5).
    03 NAME PIC X(40).
```

## データ型

- 数値
  - 9：数字。例えば、9(5)と書くと、数字5桁という意味になる。
  - S：符号。例えば、S9(2)と書くと、負数を扱える数字2桁という意味になる。
  - V：小数点の位置。例えば、9(5)V9(2)と書くと、整数部5桁小数部2桁という意味になる。
　
- 英数字
  - X：任意の文字(英字、数字、空白含む)。例えば、X(40)と書くと、任意の文字40桁という意味になる。
　
- 書式編集
  - Z：指定桁数に満たない場合、空白に置換え。例えば、Z(3)のように書く。
  - ,：カンマが挿入される文字位置。例えば、9(5),9(2)のように書くと、数字5桁,数字2桁という意味になる。

## コード例
COBOLでFizzbuzzのコード例。
```
IDENTIFICATION DIVISION.
PROGRAM-ID. FIZZBUZZ.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 I PIC 9(3).
01 FIZZ PIC 9(1).
01 BUZZ PIC 9(1).
PROCEDURE DIVISION.
   PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
   
       COMPUTE FIZZ = FUNCTION MOD(I 3)
       COMPUTE BUZZ = FUNCTION MOD(I 5)
   
       IF FIZZ = 0 AND BUZZ = 0
           DISPLAY "FizzBuzz"
       ELSE IF FIZZ = 0
           DISPLAY "Fizz"
       ELSE IF BUZZ = 0
           DISPLAY "Buzz"
       ELSE
           DISPLAY I
       END-IF
   END-PERFORM
   STOP RUN.
```
[Swift]SDK does not contain 'libarclite' at the path '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a'; try increasing the minimum deployment target

# 概要
SDK does not contain 'libarclite' at the path '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a'; try increasing the minimum deployment target

Xcode15で上記のようなエラーが出る事があります。

# 本文
エラー文にも解決のヒントが書かれていますがminimum deployment targetを増やすと解決します。（上手くいかなかったらライブラリのminimum deployment targetも上げてみてください ※下記動画参照）

![スクリーンショット 2024-03-23 17.31.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/7b96e6c4-4c9b-a749-63be-691284deacd1.png)


作成中のアプリの目的に合わせて適切な値まで引き上げてみてください！


# 補足
参考にさせて頂いた動画
[SDK does not contain 'libarclite' at the path (libarclite_iphoneos.a) - XCODE 15 Solution](https://www.youtube.com/watch?v=xgCmui2L_QE)
Javaの解答例：ABC085B - Kagami Mochi  , AtCoder Beginners Selection

# はじめに
自分用の備忘録です。参考になれば。

# 問題文
以下のリンクを参考にしてください。
[ABC085B - Kagami Mochi, https://atcoder.jp/contests/abs/tasks/abc085_b](https://atcoder.jp/contests/abs/tasks/abc085_b)

# 解答例　自作
```java: Main.java
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int N = sc.nextInt();
        List<Integer> D = new ArrayList<Integer>();
        for (int i = 1; i <= N; i++) {
            D.add(sc.nextInt());
        }

        List<Integer> hashD = new ArrayList<>(new HashSet<>(D));
        System.out.println(hashD.size());
    }

}

```

# 公式の解答１をJavaに変換

```java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int[] d = new int[N];
        for (int i = 0; i < N; ++i) d[i] = scanner.nextInt();

        int[] num = new int[110];  // バケット
        for (int i = 0; i < N; ++i) {
            num[d[i]]++;  // d[i] が 1 個増える
        }

        int res = 0;  // 答えを格納
        for (int i = 1; i <= 100; ++i) {  // 1 <= d[i] <= 100 なので 1 から 100 まで探索
            if (num[i] > 0) {  // 0 より大きかったら
                ++res;
            }
        }
        System.out.println(res);
    }
}
```

# 公式の解答２をJavaに変換
```java
import java.util.Scanner;
import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int[] d = new int[N];
        for (int i = 0; i < N; ++i) d[i] = scanner.nextInt();

        HashSet<Integer> values = new HashSet<>(); // insert するときに重複を取り除いてくれます
        for (int i = 0; i < N; ++i) {
            values.add(d[i]); // 挿入します
        }

        // set のサイズを出力します
        System.out.println(values.size());
    }
}
```

# 参考文献
[https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-7-%E5%95%8F--abc-085-b---kagami-mochi-200-%E7%82%B9](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-7-%E5%95%8F--abc-085-b---kagami-mochi-200-%E7%82%B9)
[https://codingls.com/java/773/](https://codingls.com/java/773/)
WHERE句で絞り込んでから結合する方法

多対多の関係を持つ下記のER図を例に説明します。

![hasmany_table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734882/011b40d2-bc39-d92b-7785-5eb4f9ab79ac.png)

## 課題

Itemsテーブルの全レコードを列挙して、ある特定のCustomerの「買った・買っていない」を表示したい場合、SQLでどんなクエリを発行するのか悩みました。

## 失敗作

単に結合すると、全てのCustomerの購入履歴が表示されてしまいます。

``` sql
sqlite> SELECT * FROM Items LEFT OUTER JOIN 
    Orders ON Items.id = Orders.item_id; 
```

![結合のみ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734882/514a2bf9-24e0-1fb1-3b9f-2aa8957f8c0e.png)

テーブルを結合した後にWHERE句で絞り込むと、指定したCustomerが購入したItemは表示されますが、購入していないItemは表示されません。

``` sql
sqlite> SELECT * FROM Items LEFT OUTER JOIN 
    Orders ON Items.id = Orders.item_id WHERE Orders.customer_id = 1;
```

![結合して絞り込み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734882/2a7d600d-dc42-4002-e6c3-b919152c54ae.png)




## 解決策

サブクエリ（副問い合わせ）を使うことで解決できました。
サブクエリでOrdersをWHERE句で、特定のCustomerに絞り込んでから結合します。

``` sql
sqlite> SELECT * FROM Items LEFT OUTER JOIN 
    (SELECT * FROM Orders WHERE customer_id = 1) o ON Items.id = o.item_id;
```

![絞り込んでから結合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734882/633bb4b1-d730-672a-e790-f60d916c38f9.png)



## まとめ

ActiveRecordのようなORMを使うと簡単に扱えるhas-manyの関係ですが、SQLで扱うのは少し難しいです。
色々と asdf に移行してみる 2024年3月

# asdf とは


asdf-vm/asdf-plugins: Convenience shortname repository for asdf community plugins 
https://github.com/asdf-vm/asdf-plugins

# 色々とasdfに移行しようと思ったわけ

主な動機は2つ

* これまで、 rubyenvやらpipenvやらSDKMANやらasdfやら色々と使っては移行して、いい加減しんどいので asdf に寄せようと思った。
* そろそろメインマシンに性能不足を感じているので新マシン購入に備えての準備。(動機大事)


# 今回 asdf で管理する対象としたもの


* deno
* helm
* kind
* kubectl
* kubeval
* kustomize
* minikube
* nodejs


# 所感

プラグイン数が凄いことになっていてちょっと感動した。もう asdf だけで生きていければ嬉しいなぁ...

asdf-vm/asdf-plugins: Convenience shortname repository for asdf community plugins 
https://github.com/asdf-vm/asdf-plugins
自動PUSH機能について

### 背景

開発に夢中になるとついついPUSHし忘れて、いろんな機能追加でコミットするコメントを考えてしまうので、筆者は少し便利な提案をします。

### タスク登録
筆者はこまめに小さな機能ごとにタスクを登録して、終わったら、完了をつけるようにしています。

以下が筆者が登録するタスクの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/9f0e0b1f-1a8b-05d7-6424-519268139047.png)

完了したら、完了ボタンを押すとリストから表示しなくなる

この後、筆者が気が付いたときにPUSHしたりしていますが、PUSHする単位にばらつきがある。

### 解決法

[完了にする】ボタン押したら、Pushすればいいじゃん。
はい→おわり

以下がコードになります。
```py
import subprocess as cmd

class push_git:

    @staticmethod
    def shell_cmd(id, content):
        num_id = str(id).zfill(10) + ':'
        try:
            cp1 = cmd.run(f'git add .', shell=True)
            # cp1 = cmd.run(f'ls -la', shell=True)
            cp2 = cmd.run(f'git status', shell=True)
            if cp2.returncode == 0:
                cp3 = cmd.run(f'git commit -m {num_id}{content}', shell=True)
                cp4 = cmd.run(f'git push')
                print('push Success')
            else:
                print('NG')
        except:
            print('Push Error')
```

このようにして、筆者が内部で管理しているIDとタスク名がそのまま、修正内容になっているので、happy。
rails testしたら "Migrations are pending. ..." とか出る

# はじめに
最近、Railsを触り始めました。
転職先で使用するかもしれないので学習するためにはじめてます。
(この時はまだ決まってない。この先も決まらない…かも…しれない :relaxed: )

今回は自分が遭遇したエラー対応の備忘録として書いてます。

# 環境
* Ruby 3.2.3
* Rails 7.1.3
* SQLite3 1.4

## `rails test` したら、'Migrations are pending.' と出る

`rails test` コマンドを実行しようとしたら、以下のエラーが出る。
```terminal
C:\Users> rails test
Migrations are pending. To resolve this issue, run:

        bin/rails db:migrate

You have 2 pending migrations:

db/migrate/20240227131218_create_users.rb
db/migrate/20240302042818_create_microposts.rb
```

`Migrations are pending.` → " **マイグレーションが保留中です。** "
> ※ Google翻訳です 

保留中？ようわからん。
マイグレーションがなんか、途中的な感じ？

## マイグレーションの状況を見てみよう
じゃあ、`rails db:migrate:status` でマイグレーションの状態見てみよう。
```terminal
C:\Users> rails db:migrate:status

database: storage/development.sqlite3

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20240227131218  Create users
   up     20240302042818  Create microposts
```
どちらも状態は"up"なので、問題なさそう。

### 解決策も提示されていたが...
もう一度、エラー内容を見てみると
「この問題を解決するには `rails db:migrate` してね。」
みたいなことを仰っております。
```terminal
C:\Users> rails test
Migrations are pending. To resolve this issue, run:

        bin/rails db:migrate
：
```
でも、**`rails db:migrate` や `rails db:reset` → `rails db:migrate` しても治らない...**
## `rails db:setup` で治った

`rails db:setup --trace` で解決しました。
```
C:\Users> rails db:setup --trace
** Invoke db:setup (first_time)
** Invoke db:create (first_time)
** Invoke db:load_config (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:load_config
** Execute db:create
Database 'storage/development.sqlite3' already exists
Database 'storage/test.sqlite3' already exists
** Invoke environment
** Invoke db:schema:load (first_time)
** Invoke db:load_config
** Invoke db:check_protected_environments (first_time)
** Invoke db:load_config
** Execute db:check_protected_environments
** Execute db:schema:load
** Invoke db:seed (first_time)
** Invoke db:load_config
** Execute db:seed
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke db:load_config
** Execute db:abort_if_pending_migrations
** Execute db:setup
```
`rails test`コマンドも動作しました！:sob:

### `rails db:setup` はDBを設定するもの
コマンド実行後、
「データベースの作成」、「スキーマの読み込み」、「seedデータでのDBデータ初期化」
をやってくれるコマンドみたい。

https://stackoverflow.com/questions/68282949/rails-tests-not-running-due-to-apparently-pending-migrations

> DBが既にあっても同じ手順を踏む？

似たもので `rails db:prepare` コマンドは既にDBがあるかどうかを気にするみたいだけど
`rails db:setup` は気きにしないのか…な？(だとしたら安易にコマンド叩かない方がいい)


https://railsguides.jp/active_record_migrations.html#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B

# おわりに
自分の場合は今回、DBからおかしかったのだろう
だから、`rails db:migrate` でテーブルをどうこうしても治らなかったのかな

# 参考資料

https://stackoverflow.com/questions/68282949/rails-tests-not-running-due-to-apparently-pending-migrations

https://qiita.com/ken_ta_/items/9d2dd0d032f530311d2a

https://railsguides.jp/active_record_migrations.html#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B
pythonのclassとアトリビュート

# 変数と関数
pythonの全てのものはオブジェクト

変数x：オブジェクトのインデックス(別名、お前に名前をつけてやる)
関数f(x)：pythonオブジェクトを受け取ってpythonオブジェクトを吐き出すpythonオブジェクト(入力を受け取って出力を出すpythonオブジェクト)

# 構造体
pythonにはない
強いて言えばdataclass

構造体：変数の集合に名前を付けたもの
複数の変数が並んでる

例

```python
@dataclass
class Student:
    name: string
    age: int
    major: string
    address: string
    birthday: int

# 使用例
student_hina = Student("hina", 20, "sleep", "Waseda", 20040323)
```

# class
class：ひな型
構造体の中である処理をしたい！関数の機能を取り込んだ
関数と構造体がくっついているようなイメージ

```python
class Student:
    def __init__(
        self,
        name: string
        age: int
        major: string
        address: string
        birthday: int
    ):
        # アトリビュート
        self.name=name
        self.age=age
        self.major=major
        self.address=address
        self.birthday=birthday

    # 関数
    def convert_to_japansese_calendar(self):
        return ""

# 使用例　インスタンス化
student_hina = Student("hina", 20, "sleep", "Waseda", 20040323)
```

classのインスタンス化
```hoge = class名()```
ひな型から実体を作る作業→```__init__```を呼んでいる


# ダンダ―メソッド
```def __init__```はインスタンス化した際に呼ばれる

```def __call__```はインスタンス化した後に関数のように呼び出せる
```
hoge = Student()  # ここで__init__が呼び出される
hoge(<__call__の引数>)  # ここで__call__が呼び出される
```

```def __getitem__```はindexなどで何番目のものが欲しいと表記したときに呼ばれる

```python
class Student:
    def __init__(
        self,
        name: string
        age: int
        major: string
        address: string
        birthday: int
    ):
        self.name=name
        self.age=age
        self.major=major
        self.address=address
        self.birthday=birthday
        
    def __getitem__(self, index):
        if index == 0:
            return self.name
        elif index == 1:
            return self.age
        else:
            raise IndexError

student_hina = Student("hina", 20, "sleep", "Waseda", 20040323)

print(student_hina[0])
"hina"
        
```

```def __len__```は長さを定義するときに使用する



# アトリビュート
classの中のどこでも使える変数
```self.hogehoge```
Co Drone EDUの紹介

# **はじめに**
プログラミングドローンは、興味を持っていたので、私は、2024年の1月に「Robolink Basecamp」という無料オンライン学習サービスを元にPythonを使ってCoDroneEDUを飛ばしたりしました。
現在、Blocklyを使って、飛ばしたりしています。


# **Co Drone EDUとは？**
##  **Robolink社が開発したPythonとBlocklyのみに対応した屋内専用の教育プログラミングドローンの事。**


# Co Drone  EDUの特徴
会社名:Robolink
拠点:　アメリカ　カリフォルニア州　サンディエゴ
飛行時間: 7~8分
重量: 57g(100g未満)
バッテリー充電時間: 60分
対応プログラミング言語: Python, Blocklyのみ
７つのセンサー: 加速度センサー、ジャイロセンサー、正面距離センサー、
　             底面距離センサー、気圧センサー、オプティカルフローセンサー、カラーセンサー
その他：音やLEDライトの設定
技適マーク:2.4GHZ対応(※HDL社での購入のみ)

# HDL合同会社とは？
Co Drone EDUを販売しているRobolink社の日本総代理店。
(※2.4GHZの技適マークの対応を販売しております。)
詳細は、以下のリンクとなります。
[HDL合同会社](https://www.hdl-edu.com/codrone-edu-introduction "HDL")

# Robolink Basecampとは
プログラミングドローンやロボットを通じて、PythonとBlocklyを学ぶ事ができる
Robolink社が提供している無料オンライン学習サイトとなります。
詳細は、以下のリンクとなります。
[Robolink Basecamp](https://learn.robolink.com/ "Robolink Basecamp")
※現在、日本語対応されていないので、グーグル翻訳を使ってください。

# 最後に
Co Drone EDUを最初飛ばす時、エラーが起こって、飛び続けたり、上昇したり、
室内の壁にぶつけたりと色々ありましたが、それでも楽しく飛ばしたりしています。
もし、興味があれば、ぜひ挑戦してください。
PHPでファイルのタイムスタンプをマイクロ秒精度で取得するには

Linux系OSなら素直に`stat`コマンドを使ったほうが早い。

## ファイルのマイクロ秒単位での最終修正タイムスタンプ

```php
/**
 * ファイルのマイクロ秒単位での最終修正タイムスタンプを返します。
 *
 * @param   \SplFileInfo|string $file   ファイルパス
 * @return  string|false        ファイルのマイクロ秒単位での最終修正タイムスタンプの文字列表現 取得に失敗した場合はfalse
 */
function micro_mtime(\SplFileInfo|string $file): string|false
{
    $pipes      = [];

    $process    = \proc_open(['stat', '--format=%z', \is_string($file) ? $file : $file->getPathname()], [
        0 => ['pipe', 'r'],
        1 => ['pipe', 'w'],
        2 => ['pipe', 'w'],
    ], $pipes);

    if (!\is_resource($process)) {
        return false;
    }

    $dateTime   = \DateTimeImmutable::createFromFormat(
        'Y-m-d H:i:s.u P',
        \preg_replace('/\.(\d{6})\d+ /', '.$1 ', \trim(\stream_get_contents($pipes[1])))
    );

    \fclose($pipes[1]);

    \proc_close($process);

    return $dateTime === false ? false : $dateTime->format('U.u');
}
```

## ファイルのマイクロ秒単位での最終状態変更タイムスタンプ

```php
/**
 * ファイルのマイクロ秒単位での最終状態変更タイムスタンプを返します。
 *
 * @param   \SplFileInfo|string $file   ファイルパス
 * @return  string|false        ファイルのマイクロ秒単位での最終状態変更タイムスタンプの文字列表現 取得に失敗した場合はfalse
 */
function micro_ctime(\SplFileInfo|string $file): string|false
{
    $pipes      = [];

    $process    = \proc_open(['stat', '--format=%y', \is_string($file) ? $file : $file->getPathname()], [
        0 => ['pipe', 'r'],
        1 => ['pipe', 'w'],
        2 => ['pipe', 'w'],
    ], $pipes);

    if (!\is_resource($process)) {
        return false;
    }

    $dateTime   = \DateTimeImmutable::createFromFormat(
        'Y-m-d H:i:s.u P',
        \preg_replace('/\.(\d{6})\d+ /', '.$1 ', \trim(\stream_get_contents($pipes[1])))
    );

    \fclose($pipes[1]);

    \proc_close($process);

    return $dateTime === false ? false : $dateTime->format('U.u');
}
```

## ファイルのマイクロ秒単位での最終アクセスタイムスタンプ

```php
/**
 * ファイルのマイクロ秒単位での最終アクセスタイムスタンプを返します。
 *
 * @param   \SplFileInfo|string $file   ファイルパス
 * @return  string|false        ファイルのマイクロ秒単位での最終アクセスタイムスタンプの文字列表現 取得に失敗した場合はfalse
 */
function micro_atime(\SplFileInfo|string $file): string|false
{
    $pipes      = [];

    $process    = \proc_open(['stat', '--format=%x', \is_string($file) ? $file : $file->getPathname()], [
        0 => ['pipe', 'r'],
        1 => ['pipe', 'w'],
        2 => ['pipe', 'w'],
    ], $pipes);

    if (!\is_resource($process)) {
        return false;
    }

    $dateTime   = \DateTimeImmutable::createFromFormat(
        'Y-m-d H:i:s.u P',
        \preg_replace('/\.(\d{6})\d+ /', '.$1 ', \trim(\stream_get_contents($pipes[1])))
    );

    \fclose($pipes[1]);

    \proc_close($process);

    return $dateTime === false ? false : $dateTime->format('U.u');
}
```
Android Studioで行コメントをインデント幅に自動で合わせる

## はじめに
JavaとAndroid Studioを並行して学習しています。
Android Studioでの操作中、Javaファイルでのコメント行の設定で手間取ったので設定方法を記載します。

## 問題
コメント欄をコード入力時に自動でインデントに合わせたかった
![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677610/120734fd-e104-b52f-8c20-60fa482610bb.png)


## 解決方法
以下の設定２つを変更し、解決しました。

### 設定１(コード整形時のフォーマットスタイル)
・設定＞エディター＞コードスタイルのJavaを選択
　折り返しと括弧＞整形時の保持＞最初の列にコメントを入れるをチェックオフ
 英語の場合は
・Setteing＞Editor＞Code Style＞Java
　Code Generation＞Comment Code＞Line comment at first columnをチェックオフ
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677610/a9c5cb5d-d71e-c097-269c-ef4c779ce8d9.png)

この設定だけだと、コード整形のショートカット押下時(Ctrl ＋ Alt + L)でインデントが揃いますが、コード入力時は最初の列のままになります。

### 設定２(コード入力時のスタイル)
・設定＞エディター＞コードスタイルのJavaを選択
　コードのコメント＞最初の列に行コメントを入れるをチェックオフ
 英語の場合は
 ・Setteing＞Editor＞Code Style＞Java
　Wrapping and Braces＞Keep when reformatting＞Comment at first columnをチェックオフ
![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677610/73455359-7ff4-c74d-3e33-83ea862c7692.png)

## おわりに
最初設定１だけを変更してコード入力時に変更できず、解決に少し時間がかかってしまいました。
今回はチーム開発ではないので必要ありませんでしたが、 プロジェクトごとのSchemeも使いこなせるようになりたいです。

ところで日本語化パッチを試してみたのですが、なかなか動作安定しないのでアンインストールするか悩みどころです。
Xcodeのビルド先にvisionOS Simulatorが出てこないんですが！？

# Xcodeのビルド先にvisionOS Simulatorが出てこないんですが！？

Vision Pro用のアプリをUnityでビルドし、visionOS Simulatorでデバッグしようとしたところ、XCodeのデバイス一覧に `visionOS Simulator` が出てきません！困った！

![スクリーンショット 2024-03-23 15.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/97f47eff-e56b-bd74-0bfb-6af1deae8490.png)



# 原因はUnity側の設定

Unity側の `BuildSettings` で、 `Target SDK` に `Simulator SDK` を選択するのを忘れていたことが原因でした！

![スクリーンショット 2024-03-23 15.47.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/3ed30b11-7a64-d813-fed9-33fd39303465.png)

再ビルドしたところ、以下のように `visionOS Simulator` を選択できるようになりました！

![スクリーンショット 2024-03-23 15.47.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/42701708-4b97-72eb-4cef-619e170b976e.png)


# さいごに

本記事作成にあたり、以下のページを参考にさせていただきました。
ありがとうございました！

https://qiita.com/afjk/items/74c35b254f31a0e3646b
新卒エンジニアの成長記録: React学習2か月目

# はじめに
React学習を始めて2カ月になりました。
**ちなみに学習当初は「JavaScriptってなに？」状態から始まったので、ゼロから新しい言語や技術を勉強してみたい！って方の励みになればと思います。**

私のざっくりとした経歴や1カ月目の状況はこちら！

https://qiita.com/AK_React/items/a2ff98e74a64bdca340c
# 学習2カ月目にやったこと
まず、<font color="Red">**2カ月間のざっくりとした動き**</font>はこちらです。
**2カ月目はほとんどTypeScript×Reactでのアプリ作成に費やしました。**

**JavaScript基礎（Udemyインプット）**
↓
**JavaScript×Reactでアプリ作成（詳細は下記記事にて！）** 

https://qiita.com/AK_React/items/526c3da30ca8d69a4307

↓
**TypeScript基礎（Udemyインプット）**
↓
**TypeScript×Reactでアプリ作成（近日記事投稿します！）**

# 学習2カ月目の心境の変化
学習1カ月目にはできなかったこと、最近思うことなど、ざっくばらんに書いていきます。
***
<font color="Red">**１．公式ドキュメントを参照するようになった**</font>

**特に、Reactの公式ドキュメントは非常に充実している**と思います。
各ライブラリやフックの説明だけではなく「コンポーネントってなんだろう？」「ステートってどうやって管理するんだろう？」みたいな**基本的な考え方から解説してくれています。**
私もReactについてはまだまだ理解が浅いので、**必要に応じて基本に立ち返りつつ学習しています。**

https://ja.react.dev/learn/your-first-component
***
<font color="Red">**２．「わからない」のレベルを意識するようになった**</font>

これは先輩エンジニアから教えてもらいました。

「わからない」のレベルというのはざっくりこんな感じに分かれると思います。

**・何がわからないのかもわからない
・わからない部分を言語化できる
・わかるけど実践はできない
・わかるし実践できる
・わかっていることを他人に教えることができる**

学習1カ月目の私は、ほぼ「何がわからないのかもわからない」状態でした（笑）
**しかし2カ月目になると、学習内容によって「わからない」のレベルが多様化してきました。** 従って、**「自分は今どのレベルにいて、どの程度のサポートが必要なのか」** をぼんやりと考えるようにしています。
もし仮に「何がわからないのかもわからない」状態であった場合、なるべく早くサポートを受ける必要があるので、先輩に対して意思表示をするようにしています。

https://www.nlp.co.jp/000015.php
***
<font color="Red">**３．毎日淡々とできることを積み重ねていく**</font>

マインド面でも少し変化がありました。
**やっぱり学習をしていく中で、周りの状況が気になってしまうんですよね。**
特にSNSを見ていると、様々な学習方法や精神論が蔓延しています。
でも、**自分にとっての正解は自分の中にしかない**はずなんです。
その自分にとっての正解を考えた時に、**今は本業とバランスを取りながら、将来のビジョンに向かって毎日細々と着実に学習を積み重ねていく時期にしよう。** という答えにたどり着きました。
人の数だけ正解があると思うので、これはあくまでも私の考えです。

# 最近のちょっとした決意
技術ブログでお話しすることでもないかもしれませんが、
**今年、ボディメイクの大会に初出場します！！**

私にはもともと
**筋トレが大好きなので、SEとして筋トレ系のサービスを立ち上げたい！**
という将来のビジョンがあります。

なので、**競技者としてステージに立つことで、ユーザーに寄り添ったサービスを展開する＆自分のブランディング強化**　が見込めると考えました。

大会出場に伴い、トレーニングに加えて減量もしないといけないので、飲み会はしばらくの間我慢することになります。。でも勉強会やLTは積極的に参加していきます！
# おわりに
以上、React学習2か月目の振り返りでした。
3カ月目もこれまでと引き続きアウトプット中心の学習を行いつつ、定期的に記事投稿していきます。
一緒に頑張りましょう！
# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
気になる方はぜひHPからライン登録お願いします！

https://projisou.jp
Docker ボリュームマウント 学習記録#2

ボリュームとは
------------------------
* コンテナ内に追加したデータは、永続性がない。一方で、ボリュームをマウントし、マウントしたボリュームにデータ等を書きこめば、永続的にデータを保存できる。

利点
------------------------
* バックアップの取得とボリュームの管理が楽
* ボリュームは複数のコンテナ間で共有可能
* ボリュームを容易に操作できる
* パフォーマンス向上

使用方法
------------------------

１．ボリュームを作成する
```
$ docker volume create httpd_volume
httpd_volume
```
２．作成したボリュームを確認
```
$ docker volume ls
DRIVER    VOLUME NAME
local     httpd_volume
```

３．コンテナを起動し、ボリュームをマウントする
```
$ docker run --name httpd_dev_container -d --rm -p 8062:80 -v httpd_volume:/usr/local/apache2/htdocs httpd
ea70337c388247be4b6a0063dca0c784ee4dac22845a2ec44bb571de32084d89

#ボリュームの詳細とマウントされたことを確認する
$ docker volume inspect httpd_volume
[
    {
        "CreatedAt": "2024-03-23T06:29:01Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/httpd_volume/_data",
        "Name": "httpd_volume",
        "Options": null,
        "Scope": "local"
    }
]
```

４．マウントしたボリュームが永続性の有無を確認する
```
$ docker exec -it httpd_dev_container bash
$ cd htdocs/
$ echo "cat,cat,cat,array !" >  index.html
$ cat index.html 
cat,cat,cat,array !
$ exit
$ docker stop httpd_dev_container
httpd_dev_container
$ docker ps -all
$ docker run --name httpd_dev_container2 -d --rm -p 8062:80 -v httpd_volume:/usr/local/apache2/htdocs httpd
$ docker exec -it httpd_dev_container2 bash
$ cat htdocs/index.html
cat,cat,cat,array !
$ curl localhost:8062
cat,cat,cat,array !
```
５．ボリュームの削除
```
docker volume rm ボリューム名
```
テスト設計の逆、裏、対偶

「テスト設計　逆　裏　対偶」や「テスト技法　逆　裏　対偶」で検索してもなぜかヒットしないようなので、記載してみようと思います。

<h3>テスト対象</h3>
入力装置と出力装置がある単純なシステムです。

![スクリーンショット 2024-03-23 14.45.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2451997/83679ca6-11d1-4a04-59c4-a5ef990f5114.png)

プラスの値が入力された場合、同じ数字を出力します。

![スクリーンショット 2024-03-23 14.45.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2451997/8e2f3305-5cb7-56f7-78de-bf1fb2af0297.png)

マイナスの値が入力された場合、マイナス記号「-」の代わりに黒三角「▲」を出力する仕様です。

![スクリーンショット 2024-03-23 14.45.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2451997/29a29e21-84a4-13d9-70f7-6865c2e9bb0a.png)

<h3>逆、裏、対偶を考える</h3>
仕様通りに「▲」が出力する、または出力しないことをテストしたいので、命題、逆、裏、対偶を書き出します。

＜命題＞
マイナスの値を入力　→ ▲を出力
＜逆＞　※矢印を逆にする
マイナスの値を入力　←　▲を出力
＜裏＞　※命題を否定する
「マイナスの値を入力」ではない　→ 「▲を出力」ではない
＜対偶＞　※矢印を逆にして、命題を否定する
「マイナスの値を入力」ではない　←　「▲を出力」ではない

![スクリーンショット 2024-03-23 15.03.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2451997/63e7c5ed-c9dd-6584-477d-7ee1b34b1ec4.png)

<h3>テストケースを考える</h3>
上で書き出した命題、逆、裏、対偶をテストケース化します。

＜命題＞
事前条件：出力装置が空欄
アクション：入力装置に「-1」を入力
期待結果：出力装置に「▲」が表示すること

＜逆＞
事前条件：出力装置に「▲」が表示
アクション：なし
期待結果：入力装置にマイナスの値が入力されていること

＜裏＞
事前条件：入力装置が空欄
アクション：入力装置に「1」を入力
期待結果：出力装置に「▲」が表示しないこと

＜対偶＞
事前条件：出力装置に「▲」が非表示
アクション：なし
期待結果：入力装置にマイナスの値が入力されていないこと

![スクリーンショット 2024-03-23 15.11.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2451997/3e137236-8a8c-a3ae-4605-88d4068423e9.png)


<h3>探索的テストの場合</h3>
人によって得意な思考法が異なるので、必ずしも上記の順序でテスト設計してからテスト実行に移る必要はありません。

継次処理型の脳に生まれてきた人は、上記の順番でテスト設計してからテスト実行すると考慮もれを防止できるかもしれません。

同時処理型の脳に生まれてきた人は、まず手を動かしてテスト実行が終わってから、探索したことを”効果的に人に説明するために”、上記のようにテストケースを考えて書いておけば説得力を担保できると思いますし、書いた内容を本当にテストしたかどうか不安を覚える項目があれば、もう一度テストすれば良いと思います。

以上です。
Prisma　忘備録①

# はじめに

Qiitaには初投稿です。Prismaを学習した内容をアウトプットするのと、自分の忘備録として書いてみました。

# Prismaとは

Node.jsとTypeScript環境向けのオープンソースのオブジェクトリレーションマッピングツールのこと。

Prismaにはに3つのコンポーネントがある。

1. **Prisma Client**：SQLではなくJavaScript/TypeScriptメソッドを使用してデータベースとやり取りできるクエリビルダーであり、型安全性や自動補完機能を提供。
2. **Prisma Migrate**：PrismaスキーマからSQLマイグレーションを作成し、データベーステーブルの作成に完全なカスタマイズと制御を提供。
3. **Prisma Studio**：Prismaプロジェクト内のデータを探索および編集するための使いやすいインターフェースを提供し、テーブルを閲覧し、フィルタリング、ページネーション、関連付けのトラバース、データの安全な編集が可能。


## プロジェクト設定の作成
最初のステップとして、プロジェクトディレクトリを作成し、移動する。
```
mkdir hello-prisma
cd hello-prisma
```

次に、TypeScriptを初期化し、それに開発依存関係としてPrisma CLIを追加する。

```
npm init -y 
npm install prisma typescript ts-node @types/node --save-dev
```

これにより、アプリの初期設定がpackage.jsonに作られる。

次に、TypeScriptの初期化
```
npx tsc --init
```

次に、次のコマンドを使用してPrisma スキーマファイルを作成し、Prisma ORM プロジェクトをセットアップする。
```
npx prisma init
```

このコマンドは次の 2 つのことを行う。

- schema.prismaというファイルを含むprismaという新しいディレクトリを作成します。このディレクトリには、データベース接続変数とスキーマ・モデルを含むPrismaスキーマが含まれる。

- プロジェクトのルート ディレクトリに.envファイルが作成される。このファイルは、環境変数 (データベース接続など) を定義するために使用される。
動画再生 (WPF+OpenCV)

<font COLOR="blue" >

### 動画生成
</FONT>

::: note
* Waitをスライダで変えて再生速度を自由に操作したり、
表示フレームを指定すれば特定の間をループ再生も簡単に行える。
* 動画再生はVLC等使えば良いが自分で作ったアプリ内に動画を入れる時には必要となる。
* このサンプルでは大量のjpgが作成されます。動画をフレーム毎にjpg保存してます。

:::

![B.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/2d7432ad-56e1-d3ec-6c77-07c7e200695c.jpeg)

</FONT>

### WPF C# .NETFramework
``` c#
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;

namespace openCV4 {
    public partial class MainWindow : System.Windows.Window {
        public MainWindow() {
            InitializeComponent();
        }

        private async void Window_Loaded(object sender, RoutedEventArgs e) {
            VideoCapture capture  = new VideoCapture("C:\\1.AVI");
            var img = new Mat();

            // 101番目のフレームから再生 MAXFRAME が100の場合は99が最大
            //capture.PosFrames=101;
            
            // フレームカウンタ
            int cnt=1;
            while (capture.Read(img)){

                Title=capture.Fps.ToString()+"Fps,MAXFrame"+capture.FrameCount.ToString()+"/Frame"+cnt.ToString();
                cnt++;

                var x=BitmapSourceConverter.ToBitmapSource(img);

                // 開始5秒後を表示
                // capture.PosMsec=5000;
                             
                // 保存 
                using (Stream stream = new FileStream("c:\\test"+cnt+".jpg", FileMode.Create)){
                    PngBitmapEncoder encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(x));
                    encoder.Save(stream);
                }
                image.Source=x;
                await Task.Delay(10);
            }
            image.Source=null;
        }
    }
}
```

``` xml
<Window x:Class="openCV4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:openCV4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid>
        <Image x:Name="image"/>
    </Grid>
</Window>
```
DiscordActivityの開発チュートリアルでユーザー認証出来ない問題が解消された

# 結論
embedded-app-sdkをv1.0.2にアップデートすれば解決した

# 問題
Discord Activityの開発が一般公開されたので、以下のチュートリアルを試したところ、ステップ5のユーザー認証の項目で認証画面が出なかった。

https://discord.com/developers/docs/activities/building-an-activity#step-5-authorizing-authenticating-users

具体的には、``getting-started-activity/client/main.js``の``await discordSdk.ready();``から進まずにいました。

この時はembedded-app-sdkがv1.0.1だったのですがv1.0.2が公開されたので、アップデートすると問題なく動きました。現状は、embedded-app-sdkのinstall時に最新が落ちてくるので、問題なく進めます。
JS/TSでvarは何で嫌われてるの？ 【JavaScript Node.js TypeScript 初心者プログラマー】

## 最初に
今回は**初心者向け**に何故varが嫌われているのか書いてみました。
誤字脱字等ありましたら、優しく教えていただけると幸いです。

# なんでvarって嫌われてるの？
そもそもconst let varの違いを理解していますか？
一旦それぞれの特徴について、もう一度まとめてみましょう

| 宣言方法 | 再宣言 | 再代入 |
|:-------- |:------|:-------|
|const | 不可 | 不可 |
| let | 不可 | 可能 |
| var | 可能 | 可能 |

これをふまえた上で嫌われている理由をまとめていきます。

### 1: 再宣言が可能
初心者の方は再宣言可能の何がいけないのか？と思いますよね？再宣言はプログラムが長くなればなるほど、面倒な仕様になっていきます。

```js
var hello = "hello world"

var hello = "hey"

console.log(hello)

// console: hey
```
このくらいの行数ならhelloが再宣言されているのでログ出力時にはhello worldではなくheyと表示されるのが分かります。

しかし、これが数百行、数千行、数万行に膨れ上がると面倒なことになります。
本来、関数が代入されていたはずなのに、いつの間にか変数になっていたりなど、再宣言は大規模なプログラムになればなるほど、エラーを吐く原因になっていくのです。

近年は、Visual Studio Code等のエディターの発達にともなって、事前にエラー個所を知らせてくれるので、**もしlet constで再宣言をしようとしたら、エディターが教えてくれます。**

### 2: 独特な仕様「巻き上げ」

まずこちらのプログラムを見てください
```js
var hello = "hello world";

function greet() {
    console.log(hello);
    var hello = "hey";
    console.log(hello);
}

greet()
```

これを実行するとどうなると思いますか？
ほとんどの人は以下のようにログが出力されると思います。
```console
hello world
hey
```
**しかし、実際はこうです。**
```console
undefined
hey
```
何で？って思いますよね？
これは「巻き上げ」という仕様によるものです。
具体的には**関数内部で変数を宣言すると関数内ではその変数が優先されるというものです。**

そのため、**一個目のconsole.logではhello変数は宣言していない判定になる**ので、undefinedが出てしまうのです。

**結論: この二つの仕様からがあるため、varは使わないほうがいいのです。**

## 番外編
**ここからは番外編です。varが嫌われている理由以外は特に興味ないという方は、ここでブラウザバックしていただいて大丈夫です。**
### 何故昔のコードにはvarが使われている物が多いの？
実はconstとletが追加されたのはECMAScript2015(ES6)からで結構最近なんです。
その為、昔のコードにはvarが使われている事が多いんです。

### const と let の使い分け
const と let の違いは再代入のみなので、再代入する可能性の有無で考えるのがいいでしょう
大雑把に言うと

関数、パッケージを代入するための変数 → **const**
それ以外 → **let**

もちろん例外はありますが、自分はこのように使い分けています。
参考にしていただければ幸いです。

## 最後に
自分は他にもJS/TSに関する記事を複数投稿していますので、良かったら見ていただけると幸いです。

## 引用元
https://qiita.com/ist-t-s/items/49ed558bd837452353b8

https://ja.javascript.info/var
Flutter 〜別ファイルでウィジェットを定義して呼び出す〜

1.lib配下にsample_widget.dartを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/ff72be96-eac7-6b45-29ec-50b956147111.png)


2.外部ファイルのコーディングは以下の通り。画像とテキストが並んだレイアウトが表示される
```
import 'package:flutter/material.dart';

//クラス名は大文字から始める
class SampleCounter extends StatelessWidget {
  const SampleCounter({super.key});

  @override
  Widget build(BuildContext context) {
    //buildの中にコーディングする
    //画像1
    final pic = Image.asset('assets/images/画像A.png');

    //テキスト
    final text = Text('テキスト文字列');

    //rowで横に並べる
    final row = Row(
      children: [pic, text],
    );

    //色と大きさを設定したContainerに入れる
    final con = Container(
      //コンテナの色を黄色に指定
      //画像ファイルは白色なので黄色にならない
      color: Colors.yellow,
      child: row,
    );
    return con;
  }
}
```

3.main.dartで外部ファイルのウィジェットを呼び出す

```
import 'package:flutter/material.dart';
//外部のファイルを呼び出す時はimportする
import 'package:youtubedemo/sample_widget.dart';

void main() {
  //外部ファイルのWidgetを呼び出す
  final s = SampleCounter();
  final a = MaterialApp(
    home: Scaffold(
      body: Center(
        child: s,
      ),
    ),
  );
  runApp(a);
}

```

4.実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/e2a381de-561c-d71c-8d9c-60392a7811bd.png)
Salesforceで無料App Exchange使ってみた～uSonarニュース～

こんにちは
本橋孝昭です

今回はユーソナー株式会社様が無料で提供しているSalesforce　App ExchangeのuSoner（ユーソナー）ニュースを試してみたのでご紹介します。

なお、細かい設定や機能についてなどはユーソナー株式会社様の公式サイトで問い合わせなどを行うことをお勧めします

## uSonarニュース 初期設定マニュアル・機能マニュアル　はこちらから
https://usonar.co.jp/dl/5916.html


## uSonar（ユーソナー）ニュース App Exchange サイト
https://appexchangejp.salesforce.com/appxListingDetail?listingId=a0N4V00000HZfTvUAL


なお、一般的なApp Exchangeのインストール方法はこちらを参考にしてください。
また、一般的にApp Exchangeはすぐに本番環境でインストールするのではなくSandbox環境やPlaygroundで検証することをお勧めします。

https://trailhead.salesforce.com/ja/content/learn/modules/appexchange_basics/appexchange_basics_install


## uSonerニュースで何ができるの？

uSonerニュースをSalesforceにインストールしてできることの一部をまとめてみました


### uSonerニュースでできること1 Salesforce のデータと連携しそのレコードの会社情報のニュースを表示する



画像は「ユーソナー株式会社」の取引先レコードです
このように、タイムラインのような表示でその会社（今回でいえばユーソナー株式会社）のニュースが一覧として表示されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/78df7c33-2a5c-75aa-9db4-d2c32d287814.png)

最新ニュースが時系列に並んでいるので見やすいですね。
ジャンルも絞り込めます（下記は株式会社セールスフォース・ジャパンのニュース一覧）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9e2437e8-daed-7de5-d568-04a521e1da09.png)


### uSonerニュースで多くのニュースを閲覧可能　Salesforce上にデータが無い取引先はuSonerニュースから取引先登録可能

uSonerニュースではSalesforce上にデータの有無にかかわらずニュースの閲覧をすることが可能です


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ca99d915-f857-4eba-5611-7a36ba8ced9d.png)


また、ニュースの一連ではSalesforce上の取引先にデータが無い場合、「取引先登録」ボタンが表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/3b6f2822-b48f-66ac-b857-c9fdf409d878.png)

こちらをクリックすると取引先作成画面になるのですが、取引先名や電話番号、住所、WEBサイトなどが記載されている状態で登録が可能です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/5c4bc246-1290-ffec-30fe-189965c118e2.png)

こちらの機能を使えば、ニュースで確認した気になる企業を効率よく取引先作成することができますね






## 本橋的所感　こんな時に使えそう！？

無料で会社のニュースが見やすく一覧で出てくるのはいいですね。
例えば１日何十件も売り込みをかけなくてはいけない営業をしている会社の場合は、（事前情報を調べる時間などないと思いますので）
Salesforce上で最新ニュースが見えるとお客様の雑談や話のネタのなるので営業力がUPしそうですね

また、uSonerニュースは既存の会社データにニュースが見えやすく配置するだけでなく、まだSalesforce上に登録されていない企業についてもニュースを確認することが出来て効率よく取引先作成をすることが可能です

この機能を使用してまだアプローチできていない企業もアプローチできそうですね。
Salesforce認定アドミニストレーター過去問+時々解説　Q61 ~ Q70

## Q61. ケース割り当てルールでは誰にケースを割り当てることができますか? 答えを3つ選べ.

A 社内のSalesforceユーザ
B 取引先責任者
C パートナーポータルユーザ
D ケースチーム
E キュー

<details><summary>解答</summary>
A, C, E

解説: ケースの割り当てルールは, 「ユーザー」と「キュー」に　割り当てることができる. パートナーポータルユーザーも作成するとユーザー画面にユーザーとして表示されるから, ケースを割り当てることができる.
</details>

## Q62. A社は非公開モデルを採用しています. 米国の営業担当者が所有するすべてのレコードに米国の営業マネージャがアクセスできるようにするため, 必要な設定はどれですか?

A レコードの直接(手動)共有を設定する
B ロール階層
C プロファイルの「すべてのデータの編集」権限を米国の営業マネージャに付与する
D 米国の営業マネージャと営業担当者をキューにアサインする

<details><summary>解答</summary>
B

解説: 共有設定が「非公開」かつ「階層を使用したアクセス許可」を有効にしている場合, レコード所有者と上位ロールユーザーがアクセス可能になる.
</details>

## Q63. 承認プロセスにおいて, ユーザを承認者にするには何が必要ですか？1つ選べ.

A 承認が要求されたときに、ユーザは、電子メールアラートを受信するためにオプトインする必要がある。
B ユーザは、代理承認者として設定する必要がある
C そのユーザは承認提出者とロール階層で同じロールにならないといけない
D そのユーザは承認プロセスにおいてそのオブジェクトへの参照権限を持たなくてはならない。

<details><summary>解答</summary>
D

解説: 参照権限がない場合, 承認者にされたユーザーがそのオブジェクトにアクセスしようとするとエラーが出る. なので, 承認者に指定する際は, 参照権限の確認を行うべき.
</details>

## Q64. リードを変換して商談レコードを作成した際にデフォルトで商談に関連付けされるのは, どのオブジェクトですか？

A 取引先
B リード
C ケース
D 取引先責任者

<details><summary>解答</summary>
A, D

解説: 取引を開始するとリード情報に基づいて, 取引先, 取引先責任者, 商談が作成されるので, 作成された商談オブジェクトには「取引先」と「取引先責任者」が関連つけられる.
</details>

## Q65. マルチ言語ソリューション検索機能はどこで有効化できますか？2つ選べ.

A Salesforceコンテンツ
B ソリューションタブ検索
C 公開ナレッジ
D セルフサービスポータル

<details><summary>解答</summary>
C, D

解説: ヘルプにそう書いてある.
https://help.salesforce.com/s/articleView?id=sf.sol_enable_translate.htm&type=5
</details>

## Q66. ユーザーのパスワードを管理する際, システム管理者が可能な作業はどれ？

A 管理者はユーザのセットにパスワードを割り当てることができる。
B 管理者は全てのユーザに対し一度でパスワードをリセットできる。
C 管理者は、すべて数字のパスワードポリシーを強制することができる。
D 管理者はユーザに「パスワード無期限」権限を付与できる。
E 管理者はロックアウトされたユーザに送るメッセージをカスタマイズできる

<details><summary>解答</summary>
B, D, E
</details>

## Q67. 時間ベースのアクションが実行されるワークフローを設定しています. ワークフローキューで待機中のアクションがスケジュール解除されるのはどのような場合ですか?

A 別のレコードが同じワークフロールールをトリガーする場合
B レコードがルール基準に一致しなくなった場合
C 入力規則がレコードに対してトリガーされた場合
D ワークフローキューからアクションが削除された場合

<details><summary>解答</summary>
B, D
</details>

## Q68. 削除されたレコードがゴミ箱に保管される期間は？

<details><summary>解答</summary>
15日間

公式ヘルプ
https://help.salesforce.com/s/articleView?id=sf.home_delete.htm&type=5
</details>

## Q69.「リードの取引開始プロセス」の設定に関する説明で, 正しいものを2つ選択してください.

A リードのカスタム項目はカスタムオブジェクトの項目にマッピングできます
B リードの積み上げ項目は取引先責任者のカスタム項目にマッピングできます
C リードのカスタム項目は取引先、取引先責任者、商談の項目とマッピングできます
D リードの標準項目は自動的に取引先、取引先責任者、商談の項目に引き継がれます

<details><summary>解答</summary>
C, D
</details>

## Q70. カスタムレポートタイプで設定するものは何ですか？

A 結果レポートのレポート形式
B 結果レポートに表示されるカスタム集計数式
C レポートを作成する際に列として使われる項目
D レポートを作成する際使用できるオブジェクト

<details><summary>解答</summary>
C, D
</details>

## Q71~Q80
https://qiita.com/taiga-shiokawa/items/d98b145d5ed20afcfdd4
Finderで選択しているフォルダ・ファイルを2022以降のAdobe Bridgeに開かせるAppleScript

Keyboard Maestroで実行させたり、スクリプトエディタでアプリケーションにしてFinderウインドウのツールバーに置いてもよいですね。

Bridgeが本当にAppleScript非対応になってしまったため、従来の
・選択したファイルを、Bridgeウインドウ内で選択状態で開く
という動作ができなくなりました。

いや実際にはできるんですが、jsxなどを渡すとBridgeが開こうとしやがるので、しょうがなく上位フォルダを開かせるに留めています。

まぁ無いとあるとでは大違いなんで、使ってみてください。


```AppleScript:OpenBridge.scpt
-- Bridge2024以前はidにバージョン番号が付くので調べて書き換える
set myBridge to application id "com.adobe.bridge"
set myBridgeName to name of myBridge
tell myBridge to activate

tell application "System Events"
	
	set waitCount to 0
	repeat until exists application process myBridgeName
		delay 0.1
		set waitCount to waitCount + 1
		if waitCount > 50 then error "Bridge起動失敗"
	end repeat
	
	tell process myBridgeName to click menu item 1 of menu 1 of menu bar item 3 of menu bar 1
	
end tell

tell application "Finder"
	set mySel to selection
	if mySel is {} then
		set myPATH to insertion location as alias
	else
	
		set myPATH to item 1 of mySel as alias
		
		try
			set myPATH to original item of myPATH as alias
		end try
		
		if (class of myPATH) is folder then
			set myPATH to container of myPATH as alias
		end if
		
	end if
end tell

set myPATH to POSIX path of myPATH
do shell script "open -a " & quoted form of myBridgeName & " " & quoted form of myPATH
```
【RSpec】先輩のテストの書き方が美しかったので真似できるようにメモ

## これはなに？

タイトルの通りです。

## どんなテスト？

例を3つ作成したので、実際に見て頂いた方が早そうです。

### 期待値が具体的にある場合

例えば今、以下の関数を作成し、その挙動を確かめるテストを作成するとします。

```ruby
def some_func(n)
  n + (n + 1)
end
```

与えられた値と、その次の値を足すだけの単純な関数ですね。

これをテストしましょう。

```ruby
describe '#some_func' do
  # テストケースの配列を定義 ([入力値, 期待される出力])
  test_cases = [
    [1, 3],  # 1 + (1 + 1) = 3
    [2, 5],  # 2 + (2 + 1) = 5
    [5, 11], # 5 + (5 + 1) = 11
    [10, 21], # 10 + (10 + 1) = 21
    [100, 201] # 100 + (100 + 1) = 201
  ]

  test_cases.each do |input, expected|
    context "when n is #{input}" do
      it "returns #{expected}" do
        result = some_func(input)
        expect(result).to eq(expected)
      end
    end
  end
end
```

このテストでは、`test_cases`配列に入力値と期待される出力のペアを格納します。
そして、`each`メソッドを使ってこの配列をループし、各テストケースで`some_func`関数を呼び出し、結果が期待通りであるかどうかを検証します。

contextブロックは、各テストケースで何がテストされているのかを簡潔に記述するために使用されます。
`it`ブロック内では、実際の関数呼び出しの結果が期待値に一致しているかを`expect(result).to eq(expected)`を通じて検証します。

### true, falseを検証する場合

次の例は、「入力した文字列が10文字以内の半角英字であること」を確認するバリデーション関数を作成しました。

```ruby
def validate_string(input)
  input.is_a?(String) && input.match?(/\A[a-zA-Z]{1,10}\z/)
end
```

この関数は、条件とマッチしていたら`true`, 不一致の場合は`false`を返します。

```ruby
describe '#validate_string' do
  # テストケースを定義 ([入力値, 期待される結果（true/false）])
  test_cases = [
    ['abc', true],              # 3文字の英字
    ['a' * 10, true],           # ちょうど10文字の英字
    ['a' * 11, false],          # 11文字の英字（範囲外）
    ['ABC123', false],          # 数字を含む
    ['A_BC', false],            # アンダースコアを含む
    ['', false]                 # 空文字
  ]

  test_cases.each do |input, expected|
    it "returns #{expected} when input is '#{input}'" do
      result = validate_string(input)
      expect(result).to eq(expected)
    end
  end
end
```

このテストコードでは、関数の戻り値が`true`または`false`であるため、期待される結果もそれに応じて変更されています。
`test_cases`配列に各テストケースを定義し、`each`でループして各入力値に対する`validate_string`関数の結果が期待どおりかどうかを検証します。

itブロックでは、テストの説明を動的に生成しています。これにより、どのテストケースであっても、その具体的な内容がテストの出力に明確に表示され、デバッグが容易になります。

### 複数の入力値が存在する場合

続いて、与えた文字列がすべて完全一致していたらtrueを返す関数を作成します。

```ruby
def strings_match?(str1, str2, str3)
  str1 == str2 && str2 == str3
end
```

この場合、テストケースを入力値部分と結果部分に分けましょう。

```ruby
describe '#strings_match?' do
  # テストケースを定義 ([入力値の配列, 期待される結果])
  test_cases = [
    [["apple", "apple", "apple"], true],
    [["banana", "banana", "apple"], false],
    [["orange", "banana", "cherry"], false],
    [["cherry", "cherry", ""], true]
  ]

  test_cases.each do |inputs, expected|
    it "returns #{expected} when inputs are #{inputs.join(', ')}" do
      result = strings_match?(*inputs)
      expect(result).to eq(expected)
    end
  end
end
```

`each`メソッドに与えられるブロックの中の変数を少なくすることで、テストケースの可読性が向上します。

## なぜ美しいのか？

説明するまでもなく、感覚として美しいと感じるこのテスト。
わざわざ言語化してみます。

- 短いコードで複数のテストを実行できる
- テストケースが分かりやすい
- テストの説明や結果を動的に生成している
- やってることは単純（技術自体は初学者レベル）

しびれますね。

## 注意点

ただし、何でもかんでもこの方式のテストが正解という訳では無さそうです。
一応注意点も記載します。

### パフォーマンス
大量のテストケースを`each`で回す場合、テストの実行時間が問題になることがあります。
特に、重いセットアップ処理を伴うテストや外部システムとの連携が必要なテストでは、性能に配慮することが重要です。

### テストの独立性
各テストケースが互いに独立していることを確保することが重要です。
1つのテストケースの結果が別のテストケースに影響を与えないようにしましょう。
これには、適切なセットアップやティアダウンの処理が含まれます。
Raspberry Pi 5のマイクロSDカード

## ラズパイ5のマイクロSDカード

64GのGigastoneのマイクロSDXC UHS-Iを使用すると起動できない。
| スピードクラス | UHSスピードクラス | ビデオスピードクラス | アプリケーションパフォーマンスクラス | 
|:---|:---|:---|:---|
|Class 10|U3|V30|A2|

```
I/O error, dev mmcblk0, sector 1056768 op 0x1:(WRITE) flags 0x800 phys_seg 1 prio class 2
Buffer I/O error on dev mmcblk0p2, logical block 0, lost sync page write
EXT4-fs (mmcblk0p2): I/O error while writing superblock
EXT4-fs (mmcblk0p2): re-mounted xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx ro. Quota mode: none.
I/O error, dev mmcblk0, sector 1056768 op 0x1:(WRITE) flags 0x800 phys_seg 1 prio class 2
Buffer I/O error on dev mmcblk0p2, logical block 0, lost sync page write
EXT4-fs (mmcblk0p2): I/O error while writing superblock
I/O error, dev mmcblk0, sector 0 op 0x1:(WRITE) flags 0x800 phys_seg 0 prio class 2
・・・
Waiting for root device PARTUUID=xxxxxxxx-xx...
```

新しめの規格に対応しているとダメなのかも、32GのSanDiskのマイクロSDHC UHS-Iを買い直し。
| スピードクラス | UHSスピードクラス | ビデオスピードクラス | アプリケーションパフォーマンスクラス | 
|:---|:---|:---|:---|
|Class 10|U1|-|A1|
【Amazon Cognito】ログイン失敗とロックアウトを見分ける方法

Amazon Cognito のユーザー認証機能を使ってログイン機能を実装しているシステムで、連続で複数回ログインに失敗するとロックアウトが発生するが、単にログインに失敗しているだけなのか、ロックアウトが発生しているかが見分けがつかなかった。

そこで、今回はロックアウトを見分ける方法について調査結果を共有します。

# 結論
ログインに失敗した場合も、ロックアウトによる失敗もNotAuthorizedExceptionが発生するが、メッセージに違いがあるため、それを参照することで見分けることができる。

ログイン失敗の場合
```
Incorrect username or password.
```

ロックアウトによる失敗の場合
```
Password attempts exceeded
```

# 調査と検証
Cognitoでのイベント履歴はCloudTrailで確認することができる。
CloudTrail > イベント履歴でイベント名「InitiateAuth」でフィルタリングするとわかりやすい。
![スクリーンショット 2024-03-23 12.30.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/2f45e4e9-2b23-c855-a208-8038b97ec66e.png)

１つずつイベントの中身を確認したところ、最初にログインが失敗した時のログではエラー情報が下記のようになっていた。
![スクリーンショット 2024-03-23 12.10.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/b872815c-6e77-1bc7-b129-2c72c06840ea.png)

しばらくは同じエラーが続いたが、あるタイミングから下記のようにerrorCodeは変わらないが、errorMessageに変化があっった。
![スクリーンショット 2024-03-23 12.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/59740464-9cd5-ad9e-f4a5-93b0a2875a09.png)

このことから、例外の種類はNotAuthorizedExceptionで変わらないが、エラーメッセージを見れば見分けがつくということがわかった。

念の為、下記のコードで検証を行った。
```javascript
try {
    await cognito.initiateAuth(params);
} catch (error) {
    if(error.name === 'NotAuthorizedException' && error.message === 'Password attempts exceeded'){
        return {
            code: 'ロックアウトされているよ';
        };
    }

    return {
        code: 'ロックアウト以外の理由で失敗しているよ';
    }
}
```
その結果、複数回ログイン失敗を連続で行うと途中から返されるコードが'ロックアウトされているよ'に変化することが確認できた。

## ロックアウトの仕様について
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html

> 認証されていないか、または IAM 認証でのサインインに 5 回失敗すると、Amazon Cognito はユーザーを 1 秒間ロックアウトします。ロックアウトの期間は、試行が 1 回失敗するたびに 2 倍になり、最大で約 15 分になります。ロックアウト期間中に試行すると Password attempts exceeded 例外が生成され、その後のロックアウト期間の長さには影響しません。サインイン試行の累積失敗回数 n (Password attempts exceeded 例外を含まない) に対して、Amazon Cognito はユーザーを 2^(n-5) 秒間ロックアウトします。ロックアウトを n=0 初期状態にリセットするには、ユーザーは、ロックアウト期間後にサインインに成功するか、連続 15 分間、サインイン試行を開始してはなりません。この動作は変更される可能性があります。この動作は、パスワードベースの認証も実行しない限り、カスタムチャレンジに適用されません。

## initiateAuthが出すエラー
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#API_InitiateAuth_Errors