OmniAICreator/Qiita-1.07M huggingface dataset:
[React] JSXを理解するところから始めてみる

### JSXとは?
`JavaScript`の構文拡張。
`XML`のようなマークアップ形式で記述ができる。

コンポーネントを作成するために利用される。

#### JSXのサンプル
```tsx
import React from 'react';

type Props = {
  message: string;
}

const SampleComponent: React.FC<Props> = ({ message }) => {
  return <h1>{message}</h1>;
}

export default SampleComponent;
```

---

### JSXによって何がされているのか？
JSXは、`ReactElement`を作成する関数です。
`ReactElement`とは`React API`を介して、`HTML`に変換されるオブジェクトのことです。

#### イメージ
```jsx
<MyComponent foo="bar">baz</MyComponent> 
```
↓ `ReactElement`を生成する`createElement`メソッドに変換
```jsx
React.createElement('MyComponent', { foo: 'bar' }, 'baz');
```
↓ `createElement`によって、`ReactElement`オブジェクトが作成
```jsx
{ type: 'MyComponent', props: { foo: 'bar', children: 'baz' }, key: null, }
```

---

### JSXの拡張子
JSXの拡張子はJavaScript, TypeScriptによって異なり、それぞれ以下の通りです。
`.jsx`（JavaScript）
`.tsx`（TypeScript）

---

### JSX構文

#### React.FC
`React.FC`は関数コンポーネントを定義するための型です。
```tsx
const SampleComponent: React.FC = () => { ... }
```

**型定義**
```typescript
// React.FC
type React.FC<P = {}> = FunctionComponent<P>;

// FunctionComponent
interface FunctionComponent<P = {}> {
  (props: P & { children?: ReactNode }, context?: any): ReactElement | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}
```
`FunctionComponent`のエイリアスであることがわかります。
`props`を受け取り、 `ReactElemement | null` を返す関数ということです。

---

#### 式を埋め込む
`JSX`で`JavaScript`の値を扱うには、中括弧 `{}` を使用します。

```tsx
const user = 'Taro';
const element = <h1>Hello, {user}!</h1>;
```

尚、`if`などの式以外の構文は埋め込むことができません。

---

#### 条件による表示制御
`JSX`では、`if`文などの式が埋め込めないため、`&&`、`||`、`??` といった演算子を使って表示を制御します。

```tsx
{isLoggedIn && <LogoutButton />}
```

```tsx
{user.name || "Anonymous"}
```

```tsx
{user.name ?? "Anonymous"} 
```

---

#### 繰り返し
`JSX`でリストや配列の要素を繰り返し表示する場合、アロー関数を用います。

```tsx
<ul>
    {items.map(item => (
        <li key={item}>{item}</li>
    ))}
</ul>
```

---

#### コメントアウト
JSXでコメントを書くには、一般的に`{/* */}`を使用します。

```tsx
{/* コメント */}
<div>Hello, world!</div>
```

---

#### フラグメント
Reactのコンポーネントでは、戻り値として単一の要素しか返すことができません。

`div`などで要素をラップすることで解決することができますが、これだと不要な要素が作成されてしまいます
```tsx
return (
    <div>
      <ChildA />
      <ChildB />
      <ChildC />
    </div>
)
```

フラグメント（`<>`）を使うと、余分なDOMノードを追加せずに複数の要素をグループ化できます。
```jsx
return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
)
```

### まとめ
JSXの基本についてまとめてみました。
参考になると嬉しいです。
久しぶりにGNS3（その32：リアルネットワークへ接続その５）

# Appleシリコン上のGNS3でリアルネットワークへ接続
こちらの記事「[久しぶりにGNS3（その30：Appleシリコン）](https://qiita.com/infinite1oop/items/222997491fb564de3a57)」の続編である。久しぶりにMacで、リアルネットワークに接続をしたときに、ブリッジ接続が実現できたので、記録を残す。

## NAT（Remote Main Server(GNS3 VM使用)）
まずは、NATでの実現。これは、以前の記事「[久しぶりにGNS3（その13：リアルネットワークへ接続その４）](https://qiita.com/infinite1oop/items/165b64a84d3da8239732)」と同じ考え方である。Remoteサーバーとして、GNS3 VMを使う点が同じである。Remoteサーバーの下記のとおり。
![PreferencesAtVM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/25c169ef-4dc5-43e7-0df5-663b72ac88f2.png)
IPアドレスやポートはVM情報に記載されているものを入力。
![RemoteServer(VM).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/33f5eb64-9f9e-9515-a107-2516a80ba5d4.png)
ネットワークは下記のようなもの。ルーターR1からVMであるCloud1からリアルネットワークに接続される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/766fa39a-86f2-6621-a2f6-f583ec51c53d.png)
ルーターR1の設定はいたって単純。
```
interface FastEthernet0/0
 ip address dhcp
 duplex auto
 speed auto
```
このときのログは下記となる。
```
*Feb 24 11:21:19.419: %DHCP-6-ADDRESS_ASSIGN: Interface FastEthernet0/0 assigned DHCP address 192.168.252.130, mask 255.255.255.0, hostname R1

R1#ping 8.8.8.8

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 8/12/16 ms
```
VMと同じネットワークのIPアドレス（192.168.252.xxx）が取得され、外部（8.8.8.8）への疎通が確認できる。

## ブリッジ（GNS3 VM未使用）
本題。結論的には、ブリッジの実現には、GNS3 VMを使わないことであった。まず、ブリッジ化するために借りる（？）、実ネットワークI/Fを調べる。
```
% ifconfig
（略）
en0: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
	options=50b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV,CHANNEL_IO>
	ether 18:kk:53:xx:yy:rr
	inet6 fe80::xxxx:eggg:d4xz:bUU0%en0 prefixlen 64 secured scopeid 0x6 
	inet 192.168.2.41 netmask 0xffffff00 broadcast 192.168.2.255
	nd6 options=201<PERFORMNUD,DAD>
	media: autoselect (1000baseT <full-duplex,flow-control,energy-efficient-ethernet>)
	status: active
```
ここでは、Ethernet I/Fである”en0”を選択。次に、GNS3にて、”Local Server”を利用する（GNS3 VM未使用）。
![192.168.2.x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/560ef626-8c8d-33a6-15de-48d5c8ffd4be.png)
Cloud1として、”en0”を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/15d16284-4d69-6d89-7941-f781b799ec32.png)
ネットワークは下記となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/3ae19880-58f4-6b74-a61b-02f2d31230b3.png)
ルーターR1の設定は先ほどと同じ。

このときのログは下記となる。
```
*Mar  1 00:00:13.327: %DHCP-6-ADDRESS_ASSIGN: Interface FastEthernet0/0 assigned DHCP address 192.168.2.46, mask 255.255.255.0, hostname R1

R1#ping 8.8.8.8

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 60/61/64 ms
```
”en0”と同じネットワークのIPアドレス（192.168.2.zzz）が得られている。外部（8.8.8.8）への疎通もある。

考えて見れば簡単。以前、Mac(Intel)を使って、トライした「[久しぶりにGNS3（その12：リアルネットワークへ接続その３）](https://qiita.com/infinite1oop/items/c9994ae934851e42dc62)」では、ブリッジ接続が実現できなかったが、ここでは実現できている。環境依存かもしれない。

EOF
robloxでassistant その26

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
インタープリタを書け。

# 方針
- 俺cpuのアセンブラを書く。
- stack machine 
- 命令コード
  \+ , - , + , * , dup, drop, .の７つを実装。
  \+は、加算
  \-は、減算
  *は、乗算
  \/は、除算
  dupは、コピー
  dropは、捨てる
  
# サンプルコード

```
local function forth(src)
	local stack = {}
	function stack.push(item)
		table.insert(stack, item) 
	end
	function stack.pop()
		return table.remove(stack)
	end	
	local l
	local t1
	local t2
	local v
	for l in string.gmatch(src, "[^ ]+") do 
		if l == "dup" then
			t1 = stack.pop()
			stack.push(t1)
			stack.push(t1)
		elseif l == "drop" then
			t1 = stack.pop()
		elseif l == "." then
			t1 = stack.pop()
			print(t1)
		elseif l == "+" then
			t1 = stack.pop()
			t2 = stack.pop()
			v = t2 + t1
			stack.push(v)
		elseif l == "-" then
			t1 = stack.pop()
			t2 = stack.pop()
			v = t2 - t1
			stack.push(v)
		elseif l == "/" then
			t1 = stack.pop()
			t2 = stack.pop()
			v = t2 / t1
			stack.push(v)
		elseif l == "*" then
			t1 = stack.pop()
			t2 = stack.pop()
			v = t2 * t1
			stack.push(v)
		else
			stack.push(l)
			print(l)
		end
	end 
end

forth("14 6 + .")
forth("1 2 + 3 4 + + .")


```

# 実行結果

```

  08:05:17.902  14  -  サーバー - Script:46
  08:05:17.902  6  -  サーバー - Script:46
  08:05:17.902  20  -  サーバー - Script:23
  08:05:17.903  1  -  サーバー - Script:46
  08:05:17.903  2  -  サーバー - Script:46
  08:05:17.903  3  -  サーバー - Script:46
  08:05:17.903  4  -  サーバー - Script:46
  08:05:17.904  10  -  サーバー - Script:23

```

以上。
【Salesforce】多要素認証アシスタント

この記事は2024年5月時点での、Salesforceの多要素認証アシスタントについてです。

### 多要素認証アシスタントとは？
Salesforceの多要素認証アシスタントは、Salesforceの機能の1つで、MFAの設定や管理をサポートするツールや機能のことを指します。
多要素認証アシスタントを使用すると、パスワードに加えて認証アプリケーションやセキュリティキーなどを使って認証することができます。これにより、アカウントへの不正アクセスを防ぎ、セキュリティを強化することができます。

多要素認証アシスタントの手順通りに従うだけで、MFAの準備、ロールアウト、管理までのロードマップが一気通貫で行えるイメージです。

### MFAとは？
MFA（Multi-Factor Authentication）は、アカウントを守るために役立つ方法です。
通常のパスワードだけではなく、もう1つ以上の証拠を使ってユーザーを確認します。
例えば、ATMではカードと暗証番号が必要ですよね。これにより、アカウントを守るセキュリティが強化され、悪い人がアカウントに侵入するのが難しくなります。

MFAを使うと、ログイン時に追加の認証が必要になります。最初にログインするときは、追加の認証方法を選んで登録します。次回以降のログインでは、パスワードの後に登録した認証方法を使って認証を完了させる必要があります。

### 猶予期間
2024年4月8日以降に作られた組織では、30日間の猶予期間があります。この期間中はMFAを使わずにログインできますが、期間が終わったらMFAが必要になります。

組織内のすべてのユーザーに同じ猶予期間が適用されます。例えば、猶予期間開始から20日後にログインした場合、MFAを使わずにログインできるのは残り10日間です。

### 設定方法
多要素認証アシスタントには、Lightning Experience の [設定] からアクセスします。

#### 準備フェーズ
発見および計画期間から多要素認証 (MFA) プロジェクトを開始します。
![01多要素認証アシスタント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/e9083345-f250-1f85-c1ee-a98bd42faa4b.png)

#### ロールアウトフェーズ
変更管理活動を使用して MFA に向けてユーザーを準備し、実装およびテスト計画に取り組んでから、稼働を開始します。
![02多要素認証アシスタント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/c0662c57-a161-2535-c720-f578d6028344.png)

#### 管理フェーズ
MFA ロールアウトの効果を測定し、継続的な日々の業務でユーザーをサポートし、MFA 実装とセキュリティ体制全体を最適化します。
![03多要素認証アシスタント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/eb3ef7e3-50b0-1a3a-5efd-2ebfa2f2f927.png)

### MFAの有効化
ちなみに、MFA は [Salesforce 組織へのすべての直接 UI ログインに多要素認証 (MFA) が必要] 設定によって、本番組織で有効にされます。 
![04ID検証.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/2843630d-7617-5087-ee95-e9257bb7343b.png)

下記の公式の記事ですと、Identity Verificationですが、日本語の場合ですと、ID （検証）で検索してみてください。
![05公式ページ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/fe5d6e2e-7efe-6e74-911f-b47418f21324.png)

#### ※参考
#### MFA の自動有効化およびその他について知っておくべきすべての情報 (Salesforce Platform に構築された製品)

https://help.salesforce.com/s/articleView?id=000389361&type=1

#### 多要素認証アシスタントの概要

https://help.salesforce.com/s/articleView?id=sf.mfa_mfa_assistant.htm&type=5
【ポエム】Qiitaの良いところ：

・SEO対策がしっかりしている。エラーでググるとQiitaの記事が見つかり解決したことは数知れず。
・発信側としても記事へのアクセス数が表示されるので、どんな内容が世の中に求められているのかある程度知ることができる。
・投稿用のエディタが非常に使いやすい。
・マニアックな内容でも必ず同じ趣味嗜好の人がいてお互いに切磋できる。
Go gosimple S1016 警告について


go-golangci-lint(gosimple)で、以下のような警告が表示されました。

```
S1016: should convert v 
(type github.com/nanato-okajima/repository/internal/model.User) 
to github.com/nanato-okajima/repository/internal/model.UserResponse
instead of using struct literal (gosimple)go-golangci-lint
```

## 構成

以下のような実装をしています。
DBから取得したデータをクライアントへ返却する際に
構造体同士の移し替えを行っています。
この際にgo(gosimple)で警告が表示されていました。

```go
// データベースから取得したデータを入れるDTO
type User struct {
	ID        uint64
	Name      string
    Age       uint64
}

// クライアントへ返却するデータ
type UserResponse struct {
	ID        uint64
	Name      string
    Age       uint64
}
```



```go
	results := make([]model.UserResponse, len(users))
	for i, v := range users {
		results[i] = model.UserResponse{ //　ここでlintの警告
        	ID:        v.ID,
        	Name:      v.Name,
        	Age:       v.Age,
		}
	}
	return results, nil
```

## 原因
フィールドが同じ構造体同士でしたので、
一つずつフィールドにバインドするよりも
キャストするとコードがシンプルになるよ。
と教えてくれていたみたいです。

```diff_go
results := make([]model.UserResponse, len(users))
	for i, v := range users {
+ results[i] = model.UsersResponse(v)
- results[i] = model.UsersResponse{
-	ID:        v.ID,
-	Name:      v.Name,
-	Age:       v.Age,
- }
	}
	return results, nil
```

## 終わりに
改めて読んでみると警告メッセージの通りですが、
初め見た際に？となってしまったので、備忘録として残しておきます。
(linterさんいつもありがとう 😭)
Splunk SPL 小ネタ | eval{field}

`Splunk Version 9.2.1`
# SPLで気づきにくい便利コマンドの紹介



下記のデータについて、my_int フィールドを値別に別フィールドで管理したい場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789518/b895a365-d6c8-ba1c-ad2b-836a49fc6744.png)

下記SPLを使うと便利
```ruby:qiita.rb
| eval {field} = field
```
　※勿論 eval式なので、= 以下は変数でも定数でも可。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789518/c58d9a50-7400-0d58-b59b-f32e9f41ac34.png)

my_intの値を、1, 3 にするとこんな感じになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789518/6bdaa686-300c-71f3-0b62-8581c82c19fb.png)

# SPL例
```ruby:qiita.rb
| makeresults format=csv
data="my_int,my_char
1,aaa
1,bbb
3,ccc
3,ddd"
| table my_int my_char

| eval {my_int} = my_int
```

# 記事終了
Camera (Intrinsic/Extrinsic)Parameterを使ったDepth Estimation

# Monocular Depth Estimationの課題
- focal lengthが変わると画像上の物体の大きさが変わる
- camera heightとpitch angleが分からないと、地面を基準にした距離推定が出来ない。

# Focal Lengthの対処方
Focal Lengthを仮定したカメラモデル(Virtual Camera)を作り、それに合うようにGround TruthのDepthをFocal Lengthの比でScalingする。

# Camera HeightとPitch Angleの対処方
## MLP
MLPによってCamera HeightとPitch AngleをDepthのScale Parameterを推定する。
下の公式ではRotation, Translation, Intrinsicの全てをMLPに入力して、2DのFeature MapへのScaling Parameterを推定している。精度が上がったと論文にはあるが、Focal Length単体のScalingから得れる精度向上と比較した方が良い。Extrinsicの情報は精度に寄与していない可能性がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/2d46cc6c-b71f-c3aa-94b9-3bb707d10abd.png)

# Reference
[BEVDepth: Acquisition of Reliable Depth for Multi-view 3D Object Detection](https://arxiv.org/pdf/2206.10092)
JavaScript (ECMAScript)の勉強リスト

## 参考
https://www.tohoho-web.com/js/what.htm

## リスト
### ES5 の新機能
- [ ] ストリクトモード(strict)
- [ ] ゲッター(getter)とセッター(setter)
- [ ] オブジェクトの最後の属性の後ろにカンマ
- [ ] JSON文字列の変換
- [ ] trim()
- [ ] Object オブジェクトのメソッド強化
- [ ] Array オブジェクトのメソッド強化

 ### ES5.1 の新機能
 - [ ] array.isArray()

 ### ES2015(ES6) の新機能
 - [ ] クラス (class)
 - [ ] テンプレート文字列 (`Hello ${name}`)
 - [ ] モジュール (import, export)
 - [ ] アロー関数 (=>)
 - [ ] デフォルト引数 (function(x=0, y=0))
 - [ ] 可変長引数 (function(x, y, ...arg))
 - [ ] 定数 (const)
 - [ ] 局所変数 (let)
 - [ ] for of ループ (for item of items)
 - [ ] Map オブジェクト
 - [ ] Set オブジェクト
 - [ ] 配列関数 (from(), of())
 - [ ] 分割代入 ([x, y] = [10, 20])
 - [ ] スプレッド構文 (...args)
 - [ ] 型付き配列 (Uint8Array, ...)
 - [ ] シンボルオブジェクト (Symbol)
 - [ ] 8進数(0o)と2進数(0b)
 - [ ] 言語依存フォーマット (NumberFormat())
 - [ ] 非同期処理 (Promise)

 ### ES2016(ES7) の新機能
- [ ] array.includes()
- [ ] べき乗演算子(**)


### ES2017(ES8) の新機能
- [ ] オブジェクト参照 (object.values(), object.entries())
- [ ] パディング (string.padStart(), string.padEnd())
- [ ] プロパティ記述子参照 (object.getOwnPropertyDescriptors())
- [ ] 関数末尾のカンマ (,)
- [ ] 非同期処理(async, await)
- [ ] 共有メモリ (SharedArrayBuffer) ... Meltdown and Spectre対応としてすべてのブラウザで一時無効化

### ES2018(ES9) の新機能
- [ ] テンプレート文字列の強化(\uの扱い)
- [ ] オブジェクトのスプレッド構文とレスト構文 (...obj)
- [ ] 正規表現のsフラグ (/.../s)
- [ ] 正規表現の名前付きキャプチャグループ (?<...>)
- [ ] 正規表現の前方マッチ条件検索 ((?<=...), (?<!...))
- [ ] 正規表現のUnicodeプロパティマッチ (\p{...})
- [ ] Promiseのfinally構文
- [ ] Promiseのfor await (... of ...)構文

### ES2019(ES10) の新機能
- [ ] catch引数の不要化
- [ ] Symbol.description
- [ ] JSON superset
- [ ] Well-formed JSON.stringify
- [ ] function.toString() でコメントも文字列化
- [ ] Object.fromEntries()
- [ ] string.trimStart()と string.trimEnd()
- [ ] array.flat() と array.flatMap()

### ES2020(ES11) の新機能
- [ ] 任意精度整数(BigInt)
- [ ] for-in ループにおける順序保証
- [ ] ヌル合体(Nullish Coalescing)演算子(??)
- [ ] オプショナル連結(Optional Chaining)(?)
- [ ] globalThis
- [ ] string.matchAll()
- [ ] ダイナミックインポート(Dynamic Import)
- [ ] export * as ns from module 構文
- [ ] import.meta
- [ ] Promise.allSettled()

### ES2021(ES12) の新機能
- [ ] 論理代入演算子 (||=, &&=, ??=)
- [ ] 数値セパレータ (1_000_000)
- [ ] string.replaceAll()
- [ ] Promise.any()
- [ ] 弱参照(WeakRefs)

### ES2022(ES13) の新機能
https://www.tohoho-web.com/ex/es2022.html
### ES2023(ES14) の新機能
https://www.tohoho-web.com/ex/es2023.html
Javascriptの歴史

- 1995年05月10日
    - ネットスケープコミュニケーションズのブレンダン・アイクによって開発された（この時はLiveScriptと呼ばれていた）
    - Javaのような外観
    - 初心者に優しく
    - Netscapeブラウザのほとんどなんでも制御できるように
    - Netscape Navigator 2.0
    ※Netscape Navigatorはネットスケープコミュニケーションズが開発していたウェブブラウザ

- 1996年
    - マイクロソフトのInternet Explorer 3.0にJScriptという名前で搭載
    - 急速に普及していく

- 1997年
    - 通信に関する標準を策定する国際団体EcmaインターナショナルによってJavaScriptの中核的な仕様がECMAScriptとして標準化
    ※ECMAScript（エクマスクリプト）は、Ecmaインターナショナルにおいて標準化されたJavaScriptの国際規格
    - 多くのウェブブラウザで利用できるようになった

- 1998年頃
    - windows98によって標準搭載されたIEを使う人が増えた

- 2000年頃
    - ブラウザ上での動きのあるコンテンツにはFlashを使うのが主流になり、Javascriptには逆風に

- 2005年頃
    - a-jaxを利用したGoogleマップの登場によりJavascriptが復活
    - GoogleやAmazonなどのGAFAMもJavaScriptを積極的に利用し始めた
    - jQueryやprototype.jsなどのライブラリの誕生により、簡単な記述で色々な表現が可能に

- 2008年
    - node.jsの誕生により一気拡大
    - サーバサイドでも使用できるように

---
- 参考
    - https://ja.wikipedia.org/wiki/JavaScript
    - https://rightcode.co.jp/blogs/20147
    - https://qiita.com/a_rcsin/items/0a3c8c98c8d703c49a22
Node-REDでobnizが繋がらない時のトラブルシューティング


こんにちは、のびすけです。

某授業でNode-REDからobnizを制御しましたが、Node-REDでプログラムが動いてるはずなのにobnizが動いていない、逆にNode-REDでプログラムを切っているはずなのにobnizが稼働しっぱなしになっている。といった事象が多発してしまったのでトラブルシューティング記事を書いておきます。

> ![スクリーンショット 2024-05-11 1.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/cd5fe0d0-9c9c-2aba-117c-cef349516fe5.png "スクリーンショット 2024-05-11 1.29.54.png")

## おさらい: obnizが起動しているかどうか


前提として、obnizはプログラムが起動して（しまって）いるときと、起動していない（正常に処理を止めらている）ときとでディスプレイの表示が違います。

- プログラムは起動していないけどWi-Fiには接続できている状態

これが通常に他のプログラムの接続を解除できている状態です。
**8桁のobniz IDとQRが表示されている状態**です。

> ![スクリーンショット 2024-05-11 1.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/8ffc2706-0b1f-8abc-abd5-2099dd0e717e.png "スクリーンショット 2024-05-11 1.37.43.png")

- プログラムが起動している状態 / もしくはどこかでプログラムが起動してしまっている状態

画面の表示は異なりますが、 **QRやobniz IDが表示されてない状態**ならばプログラムが起動してしまっている状態となります。

> ![スクリーンショット 2024-05-11 1.39.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/2b41d5f0-ce7b-8336-69ec-cff65e009892.png "スクリーンショット 2024-05-11 1.39.55.png")
> この画像だとディスプレイに文字を表示するプログラムが動いている模様ですね。

この2パターンを覚えておきましょう。

ちなみにこれ以外の状態はobnizがWi-Fiに接続できてない可能性が高いです。

## 1. Node-REDでプログラムを切っているのにobnizが起動しちゃう

プログラムを切っているつもりだけどobnizが起動しちゃってるパターン

> ![スクリーンショット 2024-05-11 1.51.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5328a4c5-dbdc-65e7-b858-f2168cba2356.png "スクリーンショット 2024-05-11 1.51.09.png")

これよく発生してしまうのですが、 

### 1-1. [obnizノードの停止処理](https://qiita.com/n0bisuke/items/28d44edc290a0dddc8b0)をせずにタブの無効化をしてしまっているパターン

これが多そうです。

タブの無効化をすると一見処理が止まっているように見えるのですが、obnizノードはそれだけでは止まりません。

**表示上はDisconnectedと表示されているので間違えますよね...** **実はそれちゃんと停止できてない**可能性があります。

[obnizノードの停止処理](https://qiita.com/n0bisuke/items/28d44edc290a0dddc8b0)をしっかりとしてからタブを無効化しましょう。

具体的な手順は以下です。

- 無効化しているタブを有効化

まずは無効化してしまっているタブを有効にして、`保存（デプロイ）`をしましょう。

> ![](https://i.gyazo.com/c57fefe10bec6092c8069de4f8c01c79.gif)

もしこの段階でobnizノードがconnectedになったらやはり処理が上手く止められてなかった可能性が高いです。

また、この時点で停止処理フローを追加できてない場合は[こちら](https://qiita.com/n0bisuke/items/28d44edc290a0dddc8b0)からJSONを読み込みフローを追加して、設定してみてください。

- 処理停止フローで停止をしてから再度ダブを無効化

処理停止フローのボタンを押してDisconnectと表示が変わったことを確認して、タブの無効化をしましょう。

> ![](https://i.gyazo.com/10d9f01b5ccc065c0a4d7ffeba38e902.gif)


#### 処理停止をする前にタブの無効化をするな

まとめるとこういうことですね。
RailsとAjaxを用いて日付入力フィールドの変更をリアルタイムで反映する方法

## 導入

Webアプリケーションにおいて、フォーム入力のリアルタイム処理はユーザー体験を向上させる重要な要素です。特に予約システムのようなアプリケーションでは、利用者が入力する日付に応じて利用可能な時間帯やサービスの情報を動的に更新することが求められます。この記事では、Railsを使用して日付入力フィールドからの入力をAjaxを通じてリアルタイムに処理し、ページの特定の部分を更新する方法を紹介します。

## 実装手順

### 1. 日付フィールドの準備

まず、日付を入力するためのフィールドを用意します。このフィールドには、JavaScriptでイベントリスナーを設定するためのIDが必要です。

```erb
<%= form_with model: @reservation, local: true do |form| %>
  <%= form.label :date, "日付" %>
  <%= form.date_field :date, id: 'date_field', value: Date.today, class: 'form-control' %>
<% end %>
```

### 2. JavaScriptでのイベントハンドラの設定

日付フィールドの値が変更されたときに、Ajaxリクエストを発行するイベントハンドラを設定します。

```application.js
document.addEventListener('turbo:load', function() {
  const dateField = document.querySelector('#date_field'); // 日付フィールドのIDを指定
  if (dateField) {
    const debouncedFetch = debounce(function(date) {
      fetch(`/reservations/update_slots?date=${date}`, {
        headers: {
          'Accept': 'application/json',
          'X-Requested-With': 'XMLHttpRequest',
          'X-CSRF-Token': document.querySelector("[name='csrf-token']").content
        },
        credentials: 'include'
      })
      .then(response => response.json())
      .then(data => updateTable(data));
    }, 500); // 500ミリ秒のデバウンスタイム

    // inputイベントにデバウンス関数を適用
    dateField.addEventListener('input', function() {
      debouncedFetch(this.value);
    });
  }
});

// デバウンス関数
function debounce(func, wait) {
  let timeout;
  return function() {
    const context = this, args = arguments;
    const later = function() {
      timeout = null;
      func.apply(context, args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

function updateTable(data) {
  // ここでテーブルの内容を更新
  const tableBody = document.querySelector('.table-responsive tbody');
  tableBody.innerHTML = ''; // 現在の内容をクリア
  data.services.forEach(service => {
    let row = `<tr>
      <th class="service-name sticky-left">${service.name}</th>
      <th class="service-duration sticky-duration">${service.duration}</th>`;
    service.time_slots.forEach(slot => {
      row += `<td>${slot.availability}</td>`;
    });
    row += '</tr>';
    tableBody.innerHTML += row;
  });
}
```

### 3. Railsコントローラーの設定

Ajaxリクエストを受け取り、必要なデータを処理してJSON形式で返すアクションをコントローラーに追加します。

```reservations_controller.rb
def update_slots
  @date = Date.parse(params[:date])
  @time_slots = generate_time_slots(@date)
  @services = Service.where(available_on: @date)
  
  render json: @services.map { |service|
    {
      name: service.name,
      slots: format_slots(service, @time_slots)
    }
  }
end
```

### 4. ルーティングの設定
```router.rb
  resources :reservations do
    collection do
      get :update_slots
    end
  end
```

## まとめ

この方法を使用することで、ユーザーが日付を入力するたびにその日に利用可能なサービスの情報を動的に更新でき、ユーザーにとって直感的で反応性の高いインターフェースを提供することが可能になります。AjaxとRailsの組み合わせは、このような動的なページ更新に非常に効果的です。

## 注意点

実装時にはセキュリティ対策（特にCSRFトークンの管理）と、不要なリクエストの発生を抑制するための工夫（デバウンスなど）を忘れないでください。
KintoneAPIを利用した検索時の注意点

Kintoneアプリ上でテキストフィールドとして氏名を設定し「test1 Kintone一郎」「test1 Kintone二郎」などテスト用データを配置する。
「test」で部分一致検索をしてもデータが出てこない。。。
WTF？？？？
モンキーテストを叩いていて発覚したため忘備録として以下を記録

「Kintone」で部分一致検索をするとデータがヒットするのが、どちらにも該当する「Kintone」や「郎」、「test」でテキストフィールドを検索してもデータが出てこない……
調査した結果は以下の通りだった。


英字の部分一致が使えないのが致命的なためKintoneアプリケーション上でテキスト管理する場合は命名規則等でガッチリ固めないとデータが取れないなどトラブルが多発するので要注意。

「test1」「test2」それぞれで一語の扱いになるせいで取れなかった

クエリに以下を
test1：一致するためデータ取得可能
test2：一致するためデータ取得可能
test：英数部分が完全一致でないため取得ができない

下記参考資料の通りにKintoneの仕様のため回避不可なことが判明した

対策：
・バリデーションでKintone上に保管する値を厳密に管理し運用に適合させる
（英字と数字が複合てきないのでPJ規約とにらめっこした結果あとはKintoneを使うのが決まった時点で運用回避をルールに盛り込むくらいしか浮かばない…）


参考：
https://www.ait-labo.com/kintone-basic/2690/

cybozuリファレンス：
https://jp.cybozu.help/k/ja/user/search/search_details.html#search_search_details_60
Javaで「数値リテラルに桁区切り文字を記述する」の動作を確認してみた

# 概要

Javaで「数値リテラルに桁区切り文字を記述する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/num/index9.html

# 実装

以下のファイルを作成しました。
```JSample9_1.java
class JSample9_1{
  public static void main(String[] args){
    System.out.println(1_234_567);
    System.out.println(0b10_11_01_10);
  }
}
```

以下のコマンドを実行しました。
```
$ javac -encoding UTF-8 JSample9_1.java
$ java JSample9_1 
1234567
182
```

# まとめ

何かの役に立てばと。
C#でSlackの通知をWebhook経由で行う

# はじめに
C#でSlackへ通知を送りたい場合、Webhookで通知を行うのが簡単です。

:::note info
**SlackのWebhook登録手順について**
ここではSlack App DirectoryからIncoming Webhookを登録しwebhookUrlを取得するまでの手順は省略しています。
:::

## サンプルソース
これだけでSlackに通知を送る事ができます。

``` メッセージ送信.cs
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

public void SendMsg(string msg)
{
    var webhookUrl = "取得したwebhookUrlを格納";
    var msgJson = new MsgJson { Text = msg };
    var json = JsonSerializer.Serialize(msgJson);
    var client = new HttpClient();
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    var result = client.PostAsync(webhookUrl, content).Result;
}

public class MsgJson
{
    [JsonPropertyName("text")] public string Text { get; set; } = string.Empty;
}
```
FileMergeによるマージ作業

FileMergeを用いたstgへdevの一部のファイルの一部記述をマージする方法を紹介します。

1.stgとdevのクローンを用意する
それぞれ別のクローンを用意します


2.FileMergeによって比較
この際rightにstg(マージ先)としておくと作業が楽です

![スクリーンショット 2024-05-11 0.43.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083286/5c77232b-7aa6-1542-22f5-7f6addfa1f60.png)

3.マージしたい差分ファイルを選択する

![スクリーンショット 2024-05-11 0.46.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083286/10c52dbf-2a9f-6f96-aa6f-2a2332f2a487.png)
FileMergeは変更分があるディレクトリ、ファイルを濃く表示してくれるのでわかりいい

![スクリーンショット 2024-05-11 1.06.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083286/06f05cdf-129f-018a-577a-6d67f2742744.png)
今回`Target file`以外に変更分はない。ファブルクリックで比較画面へ

4.マージしたい部分を選択してマージ

![スクリーンショット 2024-05-11 0.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083286/ad36af39-ff87-14a8-d44e-83b681a452fa.png)
例えば2と4の部分だけをdevの状態に変えたい場合は2と4でそれぞれ選択、右下のプルダウンから
`Choose left`を選択、とする

File → Save Merge As...
としてそのまま保存→ファイルの置き換え

とすることで差分のあるファイルの該当箇所のみを少ない操作で置き換えることができる。





参考記事
https://minacoole.com/macbookpro-filemerge-1/
Railsにおけるコントローラーロジックでの条件分岐とデータ取得の落とし穴

## 導入
Railsアプリケーションにおいて、コントローラー内でデータを条件に応じて取得しセットする際、予期しないバグやデータの不整合が発生することがあります。今回は、特に `action_name` を基に条件分岐を行い、会社のデータをセットするケースに焦点を当て、その問題点と解決策を紹介します。

## 問題の説明
以下のようなコントローラーメソッド `set_company` があります。このメソッドは、アクション名に応じて会社の情報を `@company` 変数にセットする目的で用意されています。

```ruby
def set_company
  @company = case action_name
             when 'new'
               Company.find(params[:company_id]) if current_customer
               current_company if current_company
             when 'create'
               Company.find(reservation_params[:company_id])
             when 'edit', 'update', 'destroy'
               @reservation.company
             end
end
```

`new` アクションの際に、期待していた `@company` が `nil` になる問題が発生していました。

## 原因の分析
問題の原因は、`new` アクションのケースで、`Company.find(params[:company_id])` の後に `current_company` の評価が行われており、Rubyの `case` 文の特性上、最後に評価された式の結果が `@company` にセットされるためです。もし `current_company` が `nil` または `false` を返す場合、`@company` も `nil` となります。

## 解決策
この問題を解決するためには、条件分岐を明確にし、確実に `params[:company_id]` が存在し、かつ `current_customer` が真の場合のみ `Company.find(params[:company_id])` を評価するように修正します。

```ruby
def set_company
  @company = case action_name
             when 'new'
               if current_customer && params[:company_id].present?
                 Company.find(params[:company_id])
               else
                 current_company
               end
             when 'create'
               Company.find(reservation_params[:company_id])
             when 'edit', 'update', 'destroy'
               @reservation.company
             end
end
```

## 結論
この修正により、`@company` が正しくセットされるようになり、`new` アクションでの期待される動作が保証されます。Railsにおいては、コントローラー内でのデータフローを管理する際には、特に複数の条件が絡む場合には慎重にロジックを設計する必要があります。
AtCoder Beginner Contest 352 振り返り

ABC352の振り返りです。今回はバーチャル参加です。

## 今回の結果

A,B,C 3完でした。
バーチャル参加なのでレーティングの変動はなしです。

## 各問題の振り返り

### A - AtCoder Line

- [問題](https://atcoder.jp/contests/abc352/tasks/abc352_a)
- [自分の回答](https://atcoder.jp/contests/abc352/submissions/53215547)

xとyの大小比較して`[x .. y]`と`[y .. x]`を作り、`elem`で存在チェックします。

```haskell
main :: IO ()
main = do
  [n, x, y, z] <- readInputInts

  let lst = if x <= y then [x .. y] else [y .. x]

  putStrLn if z `elem` lst then "Yes" else "No"
```

### B - Typing

- [問題](https://atcoder.jp/contests/abc352/tasks/abc352_b)
- [自分の回答](https://atcoder.jp/contests/abc352/submissions/53215967)

先頭を比較して再帰的に処理していきます。

```haskell
main :: IO ()
main = do
  ss <- getLine
  ts <- getLine
  putStrLn $ unwords . map show $ L.reverse $ solve ss ts

solve :: String -> String -> [Int]
solve ss ts = go ss ts 1 []
  where
    go [] _ _ res = res
    go ss@(hss : tss) ts@(hts : tts) pos res =
      if hss == hts
        then go tss tts (pos + 1) (pos : res)
        else go ss tts (pos + 1) res
```

### C - Standing On The Shoulders

- [問題](https://atcoder.jp/contests/abc352/tasks/abc352_c)
- [自分の回答](https://atcoder.jp/contests/abc352/submissions/53217041)

bをひとつずつ固定して他のaを全て足すという解き方だと`O(N^2)`となり、`2≤N≤2×10^5`なのでTLEになります。

なので最初に総和を取ってaとbの配列を作成しておき、各bを足してaを引く方法で解きます。これだと計算量は`O(N)`になります。

Haskellで気を付ける点としては、リストだと値を取得する時の計算量が`O(N)`となってしまうことです。
これを防ぐためには`Vector`を使用します。(Vectorだと`O(1)`で取得できる。)

実装は以下の通りです。

```haskell
main :: IO ()
main = do
  n <- readLn @Int
  abs <- replicateM n readPairInt

  let as = map fst abs
  let vecAs = V.fromList as
  let bs = zip [0 ..] $ map snd abs

  let sumAs = L.sum as

  print $ L.foldl' (\acc (i, b) -> let tmp = sumAs - (vecAs V.! i) + b in max acc tmp) 0 bs
```

## 全体を振り返って

来週もRated参加できないので、のんびりやろうと思います。

## おまけ

今回もRustの回答を置いておきます。

- [A - AtCoder Line](https://atcoder.jp/contests/abc352/submissions/53253770)
- [	B - Typing](https://atcoder.jp/contests/abc352/submissions/53253996)
- [C - Standing On The Shoulders](https://atcoder.jp/contests/abc352/submissions/53254171)
Next.jsをGithubActionsでFirebaseにデプロイすると環境変数が適応されない

# はじめに

Next.jsの実装をして、GithubActionsをやったときにうまくいかなかったのでまとめます

# 問題

以下のようにデプロイをするステップをGithubActionsにいれました

```yml
  deploy:
    name: deploy
    runs-on: ubuntu-latest
    # needs: test
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Setup Node.js and cache
        uses: actions/setup-node@v2
        with:
          node-version: "18"
          cache: "npm"
      - name: Install firebase-tools
        run: npm install --save-dev firebase-tools
      - name: Decode Firebase service account key
        run: |
          echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./firebase-key.json
          echo "GOOGLE_APPLICATION_CREDENTIALS=${{ github.workspace }}/firebase-key.json" >> $GITHUB_ENV
      - name: change space
        run: |
          ./node_modules/.bin/firebase use ${{ secrets.FIREBASE_PROJECT_ID }}
      - name: Deploy to Firebase Hosting
        run: |
          ./node_modules/.bin/firebase deploy
        env:
          FIREBASE_CLI_EXPERIMENTS: webframeworks
          SERVICE_DOMAIN: ${{ secrets.SERVICE_DOMAIN }}
          CMS_API_KEY: ${{ secrets.CMS_API_KEY }}
          QIITA_API_KEY: ${{ secrets.QIITA_API_KEY }}
          NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
      - name: delete GOOGLE_APPLICATION_CREDENTIALS
        run: rm $GOOGLE_APPLICATION_CREDENTIALS
        if: ${{ always() }}
```

しかしデプロイしたアプリケーションはSSRのAPIだとなぜか環境変数が存在せずにエラーが返却されました
Reactでは動いているのに、Next.jsだとうまくいきませんでした

# 解決方法

.envを作ってそこに環境変数をいれることでうまくいきました

```
  deploy:
    name: deploy
    runs-on: ubuntu-latest
    # needs: test
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Setup Node.js and cache
        uses: actions/setup-node@v2
        with:
          node-version: "18"
          cache: "npm"
      - name: Install firebase-tools
        run: npm install --save-dev firebase-tools
      - name: Decode Firebase service account key
        run: |
          echo "${{ secrets.FIREBASE_KEY }}" | base64 -d > ./firebase-key.json
          echo "GOOGLE_APPLICATION_CREDENTIALS=${{ github.workspace }}/firebase-key.json" >> $GITHUB_ENV
      - name: change space
        run: |
          touch .env
          echo "SERVICE_DOMAIN=${{ secrets.SERVICE_DOMAIN }}" >> .env
          echo "CMS_API_KEY=${{ secrets.CMS_API_KEY }}" >> .env
          echo "QIITA_API_KEY=${{ secrets.QIITA_API_KEY }}" >> .env
          echo "NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}" >> .env
          ./node_modules/.bin/firebase use ${{ secrets.FIREBASE_PROJECT_ID }}
      - name: Deploy to Firebase Hosting
        run: |
          ./node_modules/.bin/firebase deploy
        env:
          FIREBASE_CLI_EXPERIMENTS: webframeworks
      - name: delete GOOGLE_APPLICATION_CREDENTIALS
        run: rm $GOOGLE_APPLICATION_CREDENTIALS
        if: ${{ always() }}
```

# おわりに

沼って気づいたら深夜になっていました。
FirebaseあまりNext.jsとあいしょうよくないなとかんじました
単体テストの考え方/使い方を読んで

## はじめに

https://www.amazon.co.jp/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9-%E4%BD%BF%E3%81%84%E6%96%B9-Vladimir-Khorikov/dp/4839981728

上記の本を読んで私なりにまとめたものです。

## 単体テストとは

単体テストとはなんでしょうか？
ワードはよく聞きますが、その定義は曖昧だったりします。
この本では自動化されていて、次の3つの性質を全て備えるものを単体テストとしています。
- 単体と呼ばれる少量のコードを検証する
- 実行時間が短い
- 隔離された状態で実行される

逆にこれらの性質を１つでも損なっている場合は統合テストになります。

## 単体テストを行う目的

プロジェクトを持続可能なものにするものために行います。
単体テストを行うことで、そのプロダクトの品質を保証することができます。
小規模なプロジェクト、期間が短いプロジェクトではあまりテストの有用性が見えにくいですがプロジェクトが大規模、長期間になるほどテストが有用になります。

## テストの手順

テストはArrange(準備)、Act(実行)、Assert(確認)の3つのフェーズで構成されています。
この手順で行うことで可読性が高いテストを記述することができます。
1. Arrange: 変数の定義、インスタンスの生成
2. Act: テスト対象の呼び出し
3. Assert: 実行結果の確認

## テストのアンチパターン

プロジェクトの状況にもよりますが、一般的に以下の内容はアンチパターンとされています。
- AAAパターンに沿っていない
- テストの中でifを使う
- Actフェーズが1行を超える場合は設計を見直す必要がある
    - 通常1行で良いはず
- constructやsetupでインスタンスの初期化を行う
    - テストを行うたびに呼び出されてしまう
    - 柔軟性がない
    - →テストで呼び出す専用のprivateメソッドを作成すべき
- テスト対象のメソッド名をテスト名に含まない
    - 含めてしまうとテストがコードに紐づくことになる
    - 本来テストがみることはアプリケーションの振る舞いなのでこれは好ましくない
- プライベートなメソッドはテストすべきでない
    - 観測可能な振る舞いのみを検証するという柱に引っかかる
- プロダクションコードに用いたコードをテストコードにも記述する
    - ただプロダクションコードをテストコードにコピーするのはNG
    - 期待値そのものをテストコードに書く

## 良い単体テストの柱

良い単体テストの指標として以下の4つが挙げられます。
- 退行(regression)に対する保護
    - 変更を加えた後に既存の機能が動かなくなること
- リファクタリングへの耐性
    - テストを失敗することなく、リファクタリングを行えるように
- 迅速なフィードバック
- 保守のしやすさ

## ワードの整理

- モック: 対象システムから依存に向かって行われる外部に向かう出力を模倣
- スタブ: 依存からテスト対象システムに向かって行われる内部に向かう入力を模倣
- ダミー: nullや一時凌ぎで使われる文字列などシンプルな値を返すために使われる
- テストスイート: 複数のテストケースをまとめたもの
- Active Recordパターン: ドメインクラスがデータベースから自身のデータを取得・保存する設計パターン
- ハッピーパス: ビジネスシナリオが正常に終わる実行経路のこと
- リポジトリ: データベースにアクセスし、そのデータを変更するクラス

## 単体テストの手法

単体テストには以下のような手法があります。
- 出力値ベース・テスト
    - 出力される結果を検証する
- 状態ベース・テスト
    - 対象の処理が終わった後に対象の状態をテストする
- コミュニケーションベース・テスト
    - モックを用いてテスト対象と協力者オブジェクトとの間で行われるコミュニケーションをテストする

## 心に留めておきたいこと

- テストコードを含めたすべてのコードは負債であるということを理解する
- 単体テストでは通常プロセス外依存のものとの接続は行わない（データベースなど）
- 各層のテストは一つ上の層で行い、テスト対象となる層がその下にある層と何をしているかについては意識しないようにするべき
- バグが発生しうるコードにセーフティネットとなるテストを仕込んでおく
    - 例）マイナスになってはいけないなど
- 単体テストはビジネスシナリオにおける異常ケースをできるだけ多く検証する
- 統合テストは一件のハッピーパスと単体テストでは検証できない全ての異常ケースを検証する

## データベースに関わるテスト

基本的にデータベースはこのアプリケーションからしか編集されないので、管理下にある依存になります。
読み込みのテストは重要性が低いため、特に複雑な処理でなければテストの優先度は低くなります。

## おわりに

正直まだ完全には理解できていないので、テストを記述していく中で理解を深めていきたいと思います。
erbファイルでemmetが効かなくなった

## emmetが効かない・・・
vscodeでerbファイルにdiv.containerなどを途中まで入力してtabキーを押しても自動補完されなくなってしまった・・・

## Ruby LSPを有効化したら
拡張機能のRuby LSPが無効になっていたので、有効化→再起動
[![Image from Gyazo](https://i.gyazo.com/88f5734f6fa8a085f59ce72c75fa845b.png)](https://gyazo.com/88f5734f6fa8a085f59ce72c75fa845b)

無事にemmetが使用できるようになりました！！
FIRフィルタとIIRフィルタの使い分けができない男、ガチで危機感持ったほうがいいと思う

# はじめに
フィルタ設計の経験がない男、FIRフィルタとIIRフィルタの違いが分かってない男、ガチで危機感持ったほうがいいと思う:sweat_smile:

俺の周りで最近、バンドストップフィルタとバンドパスフィルタを言い間違えるやつが続出してるけど、厳しいって:sweat_smile:

テストステロン足りてないって。毎日卵10個食えって:sweat_smile:


# IIRフィルタとFIRフィルタの違い

ざっくりと違いを纏めると、こんな感じですかね。

|  |FIRフィルタ  |IIRフィルタ  |
|---|---|---|
|メリット  |<ul><li>**安定性が抜群**<ol></li></ol></li><li>線形位相 |<ul><li>**急峻な周波数特性**<ol></li></ol></li><li>計算効率 |
|デメリット  |<ul><li>計算量<ol></li></ol></li><li>メモリ使用量|<ul><li>不安定になるリスクがある<ol></li></ol></li><li>非線形位相|


# FIRフィルタ
以下のようなフィルタをFIRフィルタというらしい。
**フィードバックがないので安定します。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/b20314fe-8ca9-3bd4-f366-b178501ce112.png)
https://minidsp.jtesori.com/application/fir-vs-iir/

↑のフィルタは"NタップのFIRフィルタ"なんですが、このタップ数のことを"次数"とも言うらしい。


# IIRフィルタ
下図のようなフィルタをIIRフィルタというらしい。
FIRフィルタと違い、フィードバックがあるのが特徴。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/ed2b18fa-193b-7cc7-5f22-97f8094d20e1.png)

FIRフィルタと比較すると、不安定になってしまうリスクがある。。。
なので、使用する際は↓のような感じでシッカリと安定性の確認をしましょう。

https://qiita.com/yamo1116/items/1c3ef023b3354ec6aa21



# 参考にさせてもらったページ
https://minidsp.jtesori.com/application/fir-vs-iir/

http://www.allisone.co.jp/html/Notes/DSP/Filter/Digital/FIR-IIR/index.html
Fugaku-LLM-13B-instructはパソコンのキーボードを知っているのか

[Fugaku-LLM-13B-instruct](https://huggingface.co/Fugaku-LLM/Fugaku-LLM-13B-instruct)が[リリースされた](https://pr.fujitsu.com/jp/news/2024/05/10.html)ので、[2023年12月22日の記事](https://qiita.com/KoichiYasuoka/items/553038ec96e49a0b6663)を横目に「[パソコンのキーボードは，なぜABC順・五十音順ではないのですか](https://kotobaken.jp/qa/yokuaru/qa-35/)」と尋ねてみることにした。プログラムはこんな感じ。

```
#! /usr/bin/python3
from transformers import pipeline
tgn=pipeline("text-generation","Fugaku-LLM/Fugaku-LLM-13B-instruct",max_new_tokens=128,token="hf_this_token_is_dummy_use_your_own_one")
nlp=lambda txt:tgn(f"以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。\n\n### 指示:{txt}\n\n### 応答:",do_sample=True)[0]["generated_text"]
print(nlp("パソコンのキーボードは，なぜABC順・五十音順ではないのですか"))
```
実行してみたところ、私(安岡孝一)の手元では以下の結果が出力された。

> 以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
>
> \### 指示:パソコンのキーボードは，なぜABC順・五十音順ではないのですか
>
> \### 応答:アルファベット順でも五十音順でもない。しかし、人間はほとんどの単語をアルファベットの順番で覚えており、五十音順はより多くの単語を簡単に見つけることができるため、一般的にはアルファベット順と五十音順のキーボードレイアウトが併用されている。例えば、「logic」と「lobotomy」はアルファベット順では最初と最後に来るが、五十音順では最後と最初に来る。

何が言いたいのかサッパリ理解できない。とりあえず、もう一度やってみよう。

> 以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
>
> \### 指示:パソコンのキーボードは，なぜABC順・五十音順ではないのですか
>
> \### 応答:最初のモデルのキーボードは、タイプライターを使っていた人々のニーズに合わせて作られました。QWERTYは、タイプライターのキーの間隔に合わせており、頻繁に使用する文字をよりアクセスしやすくしています。アルファベットの順番も、単語や文章を書くことを目的としている。しかし、コンピューターは違う目的で設計された。頻繁に使用する文字を保存するためのファンクションキー、アルファベット順ではなく機能別に整理された文字、よく使うプログラムを素早く起動するため

うーん、13Bモデルだと60GBほどメモリが必要なのだけど、それでもこの程度ということなんだろうか。プレスリリースによれば「特に人文社会系のタスクでは高いベンチマーク性能を発揮する」らしいのだけど、パソコンのキーボードはダメなのかな。
【React】要素のサイズ変更を監視する方法

以下のように記述すると要素のサイズ変更を監視できます。

```jsx
// ...

export function Sample() {
    const ref = useRef(null)
    const [height, setHeight] = useState(0)
    
    useEffect(() => {
        const element = ref.current
        const observer = new ResizeObserver(() => {
             setHeight(element.offsetHeight)
        })
    
        if (element) {
             observer.observe(element)
        }
    
        return () => {
            if (element) {
                observer.unobserve(element)
            }
        }
    }, [])
    
    return <div ref={ref} />
}

```

https://developer.mozilla.org/ja/docs/Web/API/ResizeObserver
LinuxでCPUのリソース制限をつけてプロセスを起動する

## はじめに

以前[PHPを(動的に)２０倍遅くする方法](https://qiita.com/murasuke/items/280e929af9798af2aa13)という記事を書きました

この時は、サービスとしてバックグランドで実行中のプロセスに対して、動的にCPUクォータの設定を変更したのですが、新規にプロセスを起動する場合にどのようにCPUクォータを設定すればいいか？と思い調べました


`systemd-run` を使うことで簡単に実現に実現できました

## 実行手順
* CPUを最大10%に制限して&lt;command&gt;を実行する
  * `--scope`：一時的な スコープ ユニットを作成して実行（未指定の場合、サービスユニットとしてバックグラウンド実行される）
  * `--uid`：未指定の場合rootとして実行されるため、現在のユーザー(whoami)を指定
  * `-p`：cgroupsのプロパティーを指定(CPUQuota)
```
sudo systemd-run --scope --uid=`whoami` -p CPUQuota=10% <command>
Running scope as unit: run-r14b02a6f181f44bb9e5109f5fbdbbe31.scope
```

例1：yesコマンド(標準出力に`y`を出力するだけ)を、CPU負荷10%で実行（&をつけてバックグラウンド実行）
```
sudo systemd-run --scope --uid=`whoami` -p CPUQuota=10% yes > /dev/null &
[3] 1674
Running scope as unit: run-r14b02a6f181f44bb9e5109f5fbdbbe31.scope
```

例2：一時的につけられたユニット名を利用して、CPUクォータを変更する
```
sudo systemctl set-property --runtime run-r14b02a6f181f44bb9e5109f5fbdbbe31.scope CPUQuota=50%
```
例3：終了(jobsで番号を調べてから終了)
```
$ jobs
[1]   実行中               sudo systemd-run --scope --uid=`whoami` -p CPUQuota=10% yes > /dev/null &  (wd: ~)
[2]-  実行中               sudo systemd-run --scope --uid=`whoami` -p CPUQuota=10% yes > /dev/null &

kill %1 %2 
```

※`systemd-run` 
* 特定のコマンドを、systemd管理下で実行するためのツール
* プロセスに対して一時的な cgroupを作成したり、定期的に実行することができる
iphoneで操作可能な学習機能付きスマートリモコンを作ってみた。


初投稿となります。

iphoneで操作可能な学習機能付きスマートリモコンを開発した(2か月前)ので、ここに記録として留めておきます。

### 開発経緯
- IRを利用した赤外線スマートリモコンはwebで多く見られるが、iphoneと通信可能な学習機能付きスマートリモコンが無かった。
- IRについて学習したかった。

### 動作
##### 受信(学習)
①iphoneのショートカットからIRSCANを実行
②任意のデバイス名を入力
③任意の機能名を入力
④学習させる信号を送信(２回)
⑤学習完了
![images.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509479/fbe2dcda-111c-48d6-e0e9-71ba4304505f.png)

##### 送信
①iphoneのショートカットからIRSENDを実行
②デバイスを選択
③リストから機能を選択
④LED点灯
![images (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509479/d32e5314-d48f-901c-25cc-da3f8c38ed6e.png)

### 外観
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509479/840f72fc-b7b5-747b-eb77-3bbadc0211ff.jpeg" width=50%>

### 回路
![images (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3509479/f6302296-caa2-c59f-6f29-420dbddcc24e.png)

(googleスライドで作ったけど、普通にspiceかfritzingで作った方が楽そうでした)

### pythonコード
赤外線信号の送受信にはirrp.pyを使用しました。下記サイト参考。irrp.pyはコマンドライン引数を利用して動作を指定できるので、iphoneのショートカット機能と相性が良かったです。
https://ediy-fan.com/ir-remote/

また、送信時に、デバイスと機能のリストを読みとってiphoneに表示するために、ファイル名。もしくはIRデータのtxtファイルの中身から機能名を取得する簡単なコードを作成しました。

get_device_names
```python
import os

def list_device_files():
    files = [f for f in os.listdir() if f.endswith(f)and '.' not in f]
    print('\n'.join(files))

if __name__ == "__main__":
    list_device_files()  
```

get_function_names
```python
import sys

def list_functions(device_file):
    try:
        with open(device_file, 'r') as file:
            functions =  [line.split(':')[0].replace('"', '').replace('{', '').strip() for line in file.readlines()]
        print('\n'.join(functions))
    except FileNotFoundError:
        print('File not found')

if __name__ == "__main__":
    device_file = sys.argv[1]
    list_functions(device_file)
```


### iphoneショートカット
SSH通信を利用してwifi経由でiphoneからいろいろ操作するショートカットです。

##### IRSCAN
iphone側でデバイス名と機能名を入力し、それを読み取ります。その後、入力したテキストをコマンドライン引数とする形で、ラズパイの指定のフォルダに格納されているirrp.pyを実行します。通信にはssh通信を使用しますが、iphoneのショートカット機能にそれはデフォルトで備わっていました。

https://www.icloud.com/shortcuts/0035e3c502dc4e418112125c9ccd1988
##### IRSEND
iphone側からssh通信で、上記2つのpyコードを実行します。その返り値をデバイス名、もしくは機能名としてiphoneでリスト形式で出力、選択させます。その後選択された信号を実行するためにもう一度ssh通信を行い、ラズパイから信号を送信します。

https://www.icloud.com/shortcuts/251af3a4a35742b4a75405cede26e338

### 感想
普段使いできるレベルのものを電子工作で作ったのは初めてだったので、完成したときは嬉しかったです。ただ、赤外線の送信可能範囲はまだ数m程度のため、部屋によっては機能しづらいものとなっています。出力向上のためにはピンの容量が足りないので、リレー回路を組むのが良さそう？？

以上になります。
FastAPIのUvicornログをLoguruで統一する方法

## 背景
FastAPIプロジェクトにLoguru導入したが、Uvicornのログが標準のまま。
UvicornのログもLoguruのログ形式に寄せたい。
```Python
INFO:     Started server process [50656]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
2024-05-10 23:11:23.479 | ERROR    | backend.interface.api.v1.messages:create_user_message:22 - Failed to create user message
INFO:     127.0.0.1:61688 - "POST /v1/messages HTTP/1.1" 500 Internal Server Error
```

## やったこと

1. UvicornログをLoguruの形式に変換
    ```Python
    import logging
    from loguru import logger
    
    
    class InterceptHandler(logging.Handler):
        def emit(self, record):
            # 既存のログレコードの属性を使用してLoguruでログを出力
            logger_opt = logger.opt(depth=6, exception=record.exc_info)
            logger_opt.log(record.levelname, record.getMessage())
    
    
    def setup_logger():
        # uvicornログをInterceptHandlerにリダイレクト
        for _logger in ("uvicorn", "uvicorn.error", "uvicorn.access"):
            logging_logger = logging.getLogger(_logger)
            logging_logger.handlers = [InterceptHandler()]
            logging_logger.propagate = False  # ログが２重出力されるのを防止
    ```
    <br>

2. あとはmainで呼び出すだけ
    ```Python
    from fastapi import FastAPI
    from backend.logging.config import setup_logger
    
    setup_logger()
    app = FastAPI()
    ```

## 結果
Loguruのログに切り替わったことを確認
```Python
2024-05-10 23:22:41.864 | INFO     | uvicorn.server:_serve:82 - Started server process [50805]
2024-05-10 23:22:41.864 | INFO     | uvicorn.lifespan.on:startup:48 - Waiting for application startup.
2024-05-10 23:22:41.865 | INFO     | uvicorn.lifespan.on:startup:62 - Application startup complete.
2024-05-10 23:24:26.892 | ERROR    | backend.interface.api.v1.messages:create_user_message:22 - Failed to create user message
2024-05-10 23:24:26.892 | INFO     | uvicorn.protocols.http.httptools_impl:send:481 - 127.0.0.1:61785 - "POST /v1/messages HTTP/1.1" 500
```
CPU：HDD

補助記憶装置を学ぶ

HDDについての説明
HDD　VS　SSD
HDD：安価でデータ容量が少ない、そして処理も遅い
SSD：高価でデータ容量が多い、処理速度が早い；

プラック：円盤にデータを保存。
円盤の中にセクターがあり一つ５１２バイトの記憶が保存可能。

HDDの容量；
トラック５１２＊２０
シリンダ
５１２＊２０＊６０バイト＝０．６１MB
０．６１＊１５００＝９２２MB保存できるということ

アクセス時間
①算出方法
プラッタからデータを読み出したいとき；
３つの軸を考える。
シーク時間
サーチ時間
![Screenshot 2024-05-10 at 23.14.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/8d1064d7-b999-6582-f0bc-cda25e5e6d64.png)
![Screenshot 2024-05-10 at 23.14.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/f168ed65-d5ed-363a-de02-7e40a17933d3.png)
![Screenshot 2024-05-10 at 23.15.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/bd4cbab0-45ab-1f82-d3b4-1f9871e63f93.png)
![Screenshot 2024-05-10 at 23.15.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/bf3e5b0e-6d6e-3366-81dc-6fd0cc4eab6e.png)
計算するときは回転待ち時間を求める。

②データ管理
データがばらばらだとサーチに時間がかかる。
![Screenshot 2024-05-10 at 23.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/ca9c952b-c233-e49e-b76e-fe02e87e577e.png)

③性能向上
RAID→HDDの処理速度や性能を向上する。
RAI0：２台以上サーバーにデータを保存して書く。
RAI１：２台以上のサーバーにデータをコピーしてデータを保存。
RAID５：３台のHDDに分散してパリティに書き込む。なので、HDD１が壊れても、HDDに１，２にパリティが書き込こまれていれば、復元可能。
Fugaku-LLM-13BでのFew-Shot Promptingによる日本語品詞付与

Terra Blevins, Hila Gonen, Luke Zettlemoyer『[Prompting Language Models for Linguistic Structure](https://aclanthology.org/2023.acl-long.367/)』の手法を[Fugaku-LLM-13B](https://huggingface.co/Fugaku-LLM/Fugaku-LLM-13B)に適用して、国語研短単位でのUPOS (Universal Part-Of-Speech)品詞付与に挑戦してみた。5つの例文は、[この記事と全く同じもの](https://qiita.com/KoichiYasuoka/items/8b63a42dc730d8141dea)を選んだ。

```
>>> class TextUPOSList(list):
...   __str__=lambda self:"\n".join("###text:"+"".join(t for t,u in s)+"\n###UPOS:"+"|".join(t+"_"+u for t,u in s) for s in self)+"\n"
...
>>> ex=TextUPOSList()
>>> ex.append([("一","NUM"),("直線","NOUN"),("に","ADP"),("伸びる","VERB"),("電撃","NOUN"),("を","ADP"),("放ち","VERB"),("、","PUNCT"),("電撃","NOUN"),("ダメージ","NOUN"),("を","ADP"),("与える","VERB"),("。","PUNCT")])
>>> ex.append([("色々","ADV"),("と","ADP"),("面白い","ADJ"),("メニュー","NOUN"),("の","ADP"),("ある","VERB"),("店","NOUN"),("。","PUNCT")])
>>> ex.append([("しかも","CCONJ"),("、","PUNCT"),("ここ","PRON"),("は","ADP"),("コース","NOUN"),("が","ADP"),("リーズナブル","ADJ"),("な","AUX"),("の","SCONJ"),("です","AUX"),("。","PUNCT")])
>>> ex.append([("彼","PRON"),("は","ADP"),("コンピュータ","NOUN"),("を","ADP"),("個人","NOUN"),("の","ADP"),("持ち物","NOUN"),("に","ADP"),("し","VERB"),("まし","AUX"),("た","AUX"),("。","PUNCT")])
>>> ex.append([("2007","NUM"),("年","NOUN"),("9","NUM"),("月","NOUN"),("現在","ADV"),("、","PUNCT"),("以下","NOUN"),("の","ADP"),("メーカー","NOUN"),("から","ADP"),("対応","NOUN"),("製品","NOUN"),("が","ADP"),("発売","VERB"),("さ","AUX"),("れ","AUX"),("て","SCONJ"),("いる","VERB"),("。","PUNCT")])
>>> from transformers import pipeline
>>> tgn=pipeline("text-generation","Fugaku-LLM/Fugaku-LLM-13B",max_new_tokens=128,token="hf_this_token_is_dummy_use_your_own_one")
>>> print("\n".join(tgn(str(ex)+"###text:国境の長いトンネルを抜けると雪国であった。\n###UPOS:")[0]["generated_text"].split("\n")[len(ex)*2:len(ex)*2+2]))
###text:国境の長いトンネルを抜けると雪国であった。
###UPOS:国境_NOUN|の_ADP|長い_NOUN|トンネル_NOUN|を_ADP|抜ける_VERB|と_ADP|雪国_NOUN|で_ADP|あった_VERB|。_PUNCT
```

『雪国』の冒頭文に品詞付与させてみたところ、私(安岡孝一)の手元では、Fugaku-LLM-13Bは「`長い_ADJ`」と「`で_AUX|あっ_AUX|た_AUX`」にうまく品詞付与できなかった。もう一度やってみよう。

```
>>> print("\n".join(tgn(str(ex)+"###text:国境の長いトンネルを抜けると雪国であった。\n###UPOS:")[0]["generated_text"].split("\n")[len(ex)*2:len(ex)*2+2]))
###text:国境の長いトンネルを抜けると雪国であった。
###UPOS:国境_NOUN|の_ADP|長い_NOUN|トンネル_NOUN|を_ADP|抜ける_VERB|と_ADP|雪国_NOUN|で_ADP|あった_VERB|。_PUNCT
```

どうやら同じ結果だ。ならば「予想に反して品詞付与の精度がイマイチ」という文はどうだろう。

```
>>> print("\n".join(tgn(str(ex)+"###text:予想に反して品詞付与の精度がイマイチ\n###UPOS:")[0]["generated_text"].split("\n")[len(ex)*2:len(ex)*2+2]))
###text:予想に反して品詞付与の精度がイマイチ
###UPOS:予想_ADV|に_ADP|反して_ADP|品詞_NOUN|付与_NOUN|の_ADP|精度_NOUN|が_ADP|イマイチ_NOUN|。_PUNCT
```

「`予想_NOUN`」と「`反し_VERB|て_SCONJ`」にうまく品詞付与できていない上、「`。_PUNCT`」が勝手に追加されている。[3月31日の記事](https://qiita.com/KoichiYasuoka/items/b604dbe94db2207d9aa1)に較べると、精度の点で見劣りがするようだ。Few-Shot Promptingによる品詞付与の精度って、どうすれば上げられるんだろう。
Pythonのインストール（Windows11編）

# Windows11のPCを買ってPythonをインストールしたのでその時の手順を残しておくと役に立つんじゃないかな

## 概要

　Pythonのサイトからインストール用プログラムをダウンロードしてPCへインストールします。
　インストール対象はWindows11です。
　Pythonのバージョンは3.12です。

## ダウンロード

　Webブラウザで https://www.python.org/ を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/8683b0f8-0c59-97f3-117a-305fae0452e4.png)

　①Downloads にマウスオーバーするとプルダウンメニューが表示されます。②その中にあるボタンを押してファイルをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/8a7325a1-1fe1-c8eb-c968-a4805d333223.png)

　Edgeの場合右上にダウンロードしたファイルが表示されるので、クリックして実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/b1bd70df-33b0-f733-f0b4-b5b18070a53b.png)

## インストール

　起動したインストーラーの画面で、①"Add Python.exe to PATH"にチェックを入れ、②"Customize installation"をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/0123caa0-3d0d-f1bd-f353-4d1def319673.png)

　Optional Features はそのままで Next ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/9c1789ec-cec3-ef30-4c74-e1310734070f.png)

　Advanced Options では、Customize install location でインストール先フォルダを浅いところに書き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/1368b9cd-2d74-b5d8-d790-dbc1edd79db8.png)

　インストールが終わるのを待ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/b598e491-eb78-1b16-9b5f-df22f0928f4a.png)

　最後にCloseボタンをクリックして終わりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/0ede6ace-06e2-9215-eb27-b5aea839482f.png)

　インストールできたことを確認します。PowerShellを起動して"Python -V"を入力し、インストールされたPythonのバージョンが表示されることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211906/9b0ba477-f87d-6ac8-6a0b-a81ac64e805f.png)

　以上、Windows11でPythonをインストールする手順でした。