OmniAICreator/Qiita-1.07M huggingface dataset:
配列と連結リスト【Algorithm-Data構造入門Ⅱ】

## 配列
配列はデータを連続的に格納するデータ構造であり、インデックスを使用して要素にアクセスします。配列は任意の位置へのデータの読み書きが定数時間で行えますが、要素の追加や削除には全体の要素のシフトが必要であり、これによりO(n)の時間がかかります。

### Pythonでの配列操作例
```python
# 配列の作成
arr = [1, 2, 3, 4, 5]

# 要素の追加
arr.append(6)

# 先頭に要素を追加（O(n)の時間がかかる）
arr.insert(0, 0)

# 先頭の要素を削除（O(n)の時間がかかる）
arr.pop(0)
```

配列の操作メソッドについて詳しくはこちらをご覧下さい。

https://qiita.com/jay_42tokyo/items/56e01f01b39229bc5d5c

## 連結リスト
連結リストは、データとポインタを持つノードが連結しているデータ構造です。連結リストでは要素の追加や削除がO(1)の時間で行えますが、要素の探索にはポインタをたどる必要があり、これによりO(n)の時間がかかります。また、連結リストはメモリ使用量が多いという欠点があります。

### Pythonでの連結リストの操作例
```python
# ノードと連結リストの定義
# ノードと単方向連結リストの定義
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class LinkedList:
	def __init__(self):
		self.head = None

	# 先頭に要素を追加
	def add_at_head(self, data):
		new_node = Node(data)
		new_node.next = self.head
		self.head = new_node

	# 末尾に要素を追加
	def add_at_tail(self, data):
		new_node = Node(data)
		if not self.head:
			self.head = new_node
		else:
			current = self.head
			while current.next: # 末尾の要素を探す
				current = current.next
			current.next = new_node

	# 先頭の要素を削除
	def remove_head(self):
		if self.head:
			self.head = self.head.next

	# 末尾の要素を削除
	def remove_tail(self):
		if self.head:
			if not self.head.next: # 要素が1つだけの場合
				self.head = None
			else:
				current = self.head
				while current.next.next: # 末尾の1つ前の要素を探す
					current = current.next
				current.next = None

	# 特定の要素を削除
	def remove(self, data):
		if self.head:
			if self.head.data == data: # 先頭の要素を削除
				self.head = self.head.next
			else:
				current = self.head
				while current.next:
					if current.next.data == data:
						current.next = current.next.next
						break
					current = current.next

	# リストの要素を表示
	def display(self):
		current = self.head
		while current:
			print(current.data, end=" -> ")
			current = current.next
		print("None")

# 連結リストの操作例
ll = LinkedList() # 空の連結リストを作成
ll.add_at_head(3) # 3 -> None
ll.add_at_head(2) # 2 -> 3 -> None
ll.add_at_head(1) # 1 -> 2 -> 3 -> None
ll.display()  # Output: 1 -> 2 -> 3 -> None
ll.add_at_tail(4) # 1 -> 2 -> 3 -> 4 -> None
ll.display()  # Output: 1 -> 2 -> 3 -> 4 -> None
ll.remove_head() # 2 -> 3 -> 4 -> None
ll.display()  # Output: 2 -> 3 -> 4 -> None
```

## まとめ
配列と連結リストは、それぞれ利点と欠点を持ちます。配列はランダムアクセスが高速である一方、要素の追加や削除には時間がかかります。一方、連結リストは要素の追加や削除が効率的であるが、要素の探索には時間がかかり、メモリ使用量も大きくなる可能性があります。適切なデータ構造の選択は、特定の問題やアプリケーションの要件に合わせて行う必要があります。

## 参考文献
https://www.morikita.co.jp/books/mid/087261
PlunkerでPhaser.Physics その8

# 概要
Plunkerで、Phaser.Physicsやってみた。
spriteInfo、使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/f3a9949a-9722-c932-27ae-8d55ce02fd7e.png)


# サンプルコード

```
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { 
    preload: preload, 
    create: create, 
    update: update, 
    render: render 
});
function preload() {
    game.load.image('arrow', 'assets/sprites/arrow.png');
}
var sprite;
function create() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.stage.backgroundColor = '#0072bc';
    sprite = game.add.sprite(400, 300, 'arrow');
    sprite.anchor.setTo(0.5, 0.5);
    game.physics.enable(sprite, Phaser.Physics.ARCADE);
}
function update() {
    sprite.body.velocity.x = 0;
    sprite.body.velocity.y = 0;
    sprite.body.angularVelocity = 0;
    if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
    {
        sprite.body.angularVelocity = -200;
    }
    else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
    {
        sprite.body.angularVelocity = 200;
    }
    if (game.input.keyboard.isDown(Phaser.Keyboard.UP))
    {
        game.physics.arcade.velocityFromAngle(sprite.angle, 300, sprite.body.velocity);
    }
}
function render() {
    game.debug.spriteInfo(sprite, 32, 32);
    game.debug.text('angularVelocity: ' + sprite.body.angularVelocity, 32, 200);
    game.debug.text('angularAcceleration: ' + sprite.body.angularAcceleration, 32, 232);
    game.debug.text('angularDrag: ' + sprite.body.angularDrag, 32, 264);
    game.debug.text('deltaZ: ' + sprite.body.deltaZ(), 32, 296);
}




```

# 成果物

https://embed.plnkr.co/plunk/dVStOX4SDBykN4ZM


以上。
Pico WでSwitchbot Hub miniの温度と湿度を取得してZabbixに投げる

## 背景

これまでRaspberry Pi 4でSwitchbot Hub miniの温度と湿度を取得してZabbixに投げていたけど、RP4の設定場所を変えたのでbluetoothが届かなくなった。
使っていないPico Wがあったので、代わりにやらせてみた。

## Bluetooth

### 読むフレーム

RP4はbluepy、Pico Wはubluetoothを使いました。
RP4の方はインターネットに多くあるコードを使ってできました。そのコードの意味は深く理解していなかったせいで、Pico Wの最初コードではtypeの判定をしていなかった。そのためアドバタイズフレームを読んでいて、温度・湿度が含まれていませんでした。
Bluetooth LE自体を調査して、SCAN_RSPフレームを読まないといけないことを理解しました。

```python
addr_type, addr, adv_type, rssi, adv_data = data
addr_str = ':'.join(['{:02x}'.format(b) for b in addr])
if addr_str == self.target_addr and adv_type == 4:  # SCAN_RSPフレーム
    self._parseData(adv_data)
```

### サービスデータの取得

Switchbotのドキュメントを読んで0x16のブロックを見つける必要がありました。bluepyではそこがイテレータになっているみたいです。

```python
i = 0
while i < len(adv_data):
    length = adv_data[i]
    type = adv_data[i + 1]

    if type == 0x16:  # サービスデータ
        uuid = bytes(reversed(adv_data[i + 2:i + 4])).hex()
        service_data = adv_data[i + 4:i + length + 1]
        return uuid, service_data

    i += length + 1
return None, None
```

## Zabbixへの送信

RP4では cron -> python -> data.json -> fluentd -> zabbix の流れで動かしていたので、zabbixのことは全部fluentdにお任せしていましたが、Pico Wでは自前で書く必要がありました。
早速インターネットにあふれているコードを持ってきて動かしましたが送信できず、zabbixのドキュメントを読んだらヘッダーが必要とのことで、ヘッダーを付加したら成功しました。

```python
data = {
    "request": "sender data",
    "data": [
        {
            'host': self.zabbix_host,
            'key': key,
            'value': value,
        }
        for key, value in data.items()
    ]
}
data = str(json.dumps(data)).encode('utf-8')
packet = b"ZBXD\1" + struct.pack("<II", len(data), 0) + data
```

## ソース

https://github.com/bugcity/picoblue
AG-Gridでフィルターされた後の件数をカウントする方法


AG-Gridで、フィルター後の件数を取得する方法を解説します。

(React版v28を使用しています。)

:::note warn

※ これは2022/12/12に[個人ブログ](https://bicstone.me)で公開した記事を移植し、[CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/deed.ja)で提供しています。情報は古い可能性があります。

:::

## フィルター後の件数を取得する関数がない

AG-Gridにおいて、フィルター後の件数を取得する関数は用意されていないみたいです。

一方、公式デモでは選択中の件数を表示していたのでどのように行なっているのかソースコードを見てみました。

enterprise版で用意されているStatus barの実装では、カウンターを用意し、 `gridApi.forEachNodeAfterFilter()` で回してカウントしていく方法が取られていました。 (ライセンスの都合上引用が出来ないので下記ソースコードをご確認ください。)

https://github.com/ag-grid/ag-grid/blob/fc77919c164fb5bcd66a8b2897b20c318f5dd58e/enterprise-modules/status-bar/src/statusBar/providedPanels/filteredRowsComp.ts#L52-L61

フィルター後のNode一覧を取得しゴリゴリ足していく方法しか無さそうです。

## サンプル

Status barの実装を参考に実装してみました。

https://codesandbox.io/embed/ag-grid-filtered-row-count-s0nocs?&theme=light&view=preview

```tsx
import { AgGridReact } from "ag-grid-react";
import { useCallback, useState } from "react";

import type {
  AgGridEvent,
  ColDef,
  ModelupdateDateEvent,
} from "ag-grid-community";

type Data = { id: number; name: string };

export const DataGrid = (): JSX.Element => {
  const rowData: Array<Data> = [
    { id: 1, name: "Item 1" },
    { id: 2, name: "Item 2" },
    { id: 3, name: "Item 3" },
    { id: 4, name: "Item 4" },
    { id: 5, name: "Item 5" },
  ];

  const columnDefs: ColDef<Data>[] = [
    { field: "id", filter: true, floatingFilter: true },
    { field: "name", filter: true, floatingFilter: true },
  ];

  const [filteredRowCount, setFilteredRowCount] = useState<number>(0);

  const onFilterChanged = useCallback((event: AgGridEvent): void => {
    let filteredRowCount = 0;
    event.api.forEachNodeAfterFilter(() => {
      filteredRowCount++;
    });
    setFilteredRowCount(filteredRowCount);
  }, []);

  const onModelupdateDate = useCallback(
    (event: ModelupdateDateEvent): void => {
      onFilterChanged(event);
    },
    [onFilterChanged],
  );

  return (
    <>
      <AgGridReact<Data>
        rowData={rowData}
        columnDefs={columnDefs}
        onFilterChanged={onFilterChanged}
        onModelupdateDate={onModelupdateDate}
        domLayout="autoHeight"
      />
      count: {filteredRowCount}
    </>
  );
};
```

## まとめ

AG-Gridでフィルター後の件数を取得できました。なんとなく辛みがあるので、AG-Gridに実装してほしいです。
JavaScriptとTypeScriptの論理演算子、比較演算子、およびその他の便利な演算子

## アジェンダ
この記事では、JavaScriptとTypeScriptで使用される論理演算子、比較演算子、その他の演算子についてまとめました。

## 論理演算子
### 1. **AND (`&&`)**
ANDは短絡評価で、
- 左辺が`falsy`であれば、その左辺の値が直ちに返され、右辺は評価されません。
- 左辺が`truthy`であれば、右辺の値が返されます。

ANDが両辺がtruthyであるか否かを見たいとするならfalsyで直ちに返されるというのは納得できると思います。

> どちらかがtrueであればtrueを返し、どちらも false である場合、false を返します。

```typescript:
if (true && true) {
    console.log("Both are true"); // このコードは実行されます。
}

// 短絡評価の例
console.log(undefined && 123); // undefined
console.log('HIT' && 'RUN'); // 'RUN'
```

### 2. **OR (`||`)**
ORもAND同様に短絡評価で、
- 左辺が`truthy`であれば、その左辺の値が直ちに返され、右辺は評価されません。
- 左辺が`falsy`であれば、右辺の値が返されます。

ORが、両辺のどこかのtruthyがあるか否かを見たいとするならtruthyで直ちに返されるというのは納得できると思います。

> 両方の値がtrueである場合にtrueを返し、それ以外の場合にはfalseを返します。

```typescript
if (true || false) {
    console.log("At least one is true"); // このコードは実行されます。
}

// 短絡評価の例
console.log(undefined || 123); // 123
console.log('DEAD' || 'ALIVE'); // 'DEAD'
```


### 3. **NOT (`!`)**
オペランドが `false` であれば `true` を返し、`true` であれば `false` を返します。
```typescript
if (!false) {
    console.log("Not false is true");
}
```

また、`!!`を二つ続けることで**二重否定**をすることができます。**二重否定**を使用すると値を真偽値に強制的に変換します。
```typescript
const truthyValue = !!1; // true
console.log(truthyValue);
```
このコードを実行すると、truthyValueは`true`が代入され、コンソールにtrueと表示されます。

### 4. **Nullish Coalescing (`??`)**
`null` または `undefined` でない場合に左辺のオペランドを返し、そうでなければ右側のオペランドを返します。
```typescript
const name = null ?? "default name";
console.log(name);  // "default name"
```
   
## 比較演算子
### 1. **等価 (Equality) (`==`)**
二つの値が等しいかどうかをチェックしますが、型変換を行います。
```typescript
if ("2" == 2) {
    console.log("Equal with type coercion");
}
```

### 2. **厳密等価 (Strict Equality) (`===`)**
二つの値が等しいかどうかをチェックしますが、型変換を行いません。
```typescript
if ("2" === 2) {
    console.log("Strictly not equal");
} else {
   console.log("Strictly not equal");
}
```

### 3. **小なり (`<`)**
さhのオペランドが右辺のオペランドより小さい場合に `true` を返します。
```typescript
if (5 < 10) {
    console.log("5 is less than 10");
}
```

### 4. **大なり (`>`)**
左辺のオペランドが右辺のオペランドより大きい場合に `true` を返します。
   ```typescript
if (10 > 5) {
    console.log("10 is greater than 5");
}
```

## その他の便利な演算子
### 1. **条件演算子（三項演算子）`? :`**
条件に基づいて二つの値のうちの一つを返します。
```typescript
const result = 5 > 3 ? "Greater" : "Lesser";
console.log(result);  // "Greater"
```

### 2. **オプショナルチェイニング演算子 `?.`**
`?.` 演算子の機能は `.` チェーン演算子と似ていますが、参照が nullish (null または undefined) の場合にエラーとなるのではなく、式が短絡され undefined が返されるところが異なります。関数呼び出しで使用すると、与えられた関数が存在しない場合、 undefined を返します。

```typescript
const obj = { a: { b: "value" } };
const value = obj.a?.b;  // "value"
const undefinedValue = obj.c?.b;  // undefined
console.log(value);
console.log(undefinedValue);
```

## 問題の紹介
演算子の理解を定着させるために以下に問題を作ったので興味がある人はチェックしてみて下さい。

[TypeScript 演算子道場](https://gist.github.com/yukisakakima/d34745456a5f660e3433ff180c86fb51)

## リファレンス
- [俺の論理演算子、条件演算子 #JavaScript - Qiita](https://qiita.com/terry_6518/items/817c368b394352c8c9fa)
- [TypeScriptで二重否定を理解する10の実用コード | Japanシーモア](https://jp-seemore.com/web/13968/)
- [オプショナルチェーン (?.) - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining)
Pythonの基本⑥【タプル型のメソッド】

# タプルとは

Pythonのタプル(tuple)型は、複数の要素を順序付きで格納するためのデータ構造です。

タプルはリストとは異なり、**イミュータブル**（変更不可）な性質を持ちます。すなわち、**要素の追加や削除はできません**。

この記事では、Pythonにおけるよく使われるタプル型の操作メソッドについて紹介します。

## メソッド一覧
一覧とは言え、基本的に使用するメソッドは2つだけです。

`count()`: 指定した値と一致する要素の数を返します。
```python
my_tuple = (1, 2, 2, 3, 3, 3)
count = my_tuple.count(3)
print(count)  # Output: 3
```

`index()`: 指定した値の最初の出現位置のインデックスを返します。
```python
my_tuple = (1, 2, 3, 4, 5)
index = my_tuple.index(3)
print(index)  # Output: 2
```

## タプル型の使い道
1. データの保持
タプルはイミュータブルなので、一度作成されたタプルは変更することができません。そのため、データを変更できないようにしたい場合に利用されます。例えば、プログラム内で定数として使用される値や、変更されては困る設定値などをタプルで保持することがあります。
```python
# ユーザーの権限レベルに対する定数
PERMISSION_LEVELS = ('guest', 'user', 'admin')
```

2. シーケンスのパッキングとアンパッキング
タプルは複数の要素を1つの変数にパッキングすることができ、また、逆に複数の変数にアンパッキングすることもできます。これは関数の返り値や複数の値を同時に扱う場合に便利です。
```python
# シーケンスのパッキング
coordinates = 10, 20, 30

# シーケンスのアンパッキング
x, y, z = coordinates
```

3. データの保護
タプルにデータを格納すると、そのデータが不用意に変更されることを防ぐことができます。特に大規模なプログラムや複数の関数やモジュールで共有されるデータに対して、データの不正な変更を防ぐために利用されます。
```python
# 辞書のキーとして利用されるタプル
settings = {
    ('width', 'height'): (800, 600),
    ('background_color', 'text_color'): ('white', 'black')
}
```

以上のように、タプルはさまざまな場面で活用される便利なデータ構造です。特にデータの保持や変更を制限したい場合や、データを安全に保護したい場合にはタプルを使用することでプログラムの安全性や保守性を向上させることができます。

## まとめ
今回はタプル型のメソッドや、タプル型の使い道について紹介しました。
少しでも役に立てば嬉しいです！
[Laravel] コーディング規約

## 1. PSR規格の遵守:
- PSR-4: オートローディングの標準
- PSR-2 および PSR-12: コーディングスタイルガイド。インデント、改行、クラス・メソッドの定義などに関するルール
## 2. 命名規則
- クラス名: アッパーキャメルケースを使用（各単語の最初の文字を大文字）
    - `User`, `UserProfile`
- メソッド名: ローワーキャメルケースを使用
    - `getUser`, `saveUser`
- プロパティ: スネークケースを使用
    - `$user_name`, `$email_address`
- データベーステーブル名: スネークケースを使用（必ず複数形にする）
    - `users`, `user_profiles`
- データベースカラム名: スネークケースを使用
## 3. コード構造
- if, foreach, while などの制御構造の括弧は、メソッドの括弧と同様に取り扱われる
- ファサードの使用: Laravel独特の「ファサード」を通じてサービスコンテナのサービスにアクセスする
## 4. ビューとブレードテンプレート
- Bladeテンプレートエンジンを使用してビューを構築する
- {{ }} はエスケープされたデータを出力、{!! !!} はエスケープされないデータを出力する
## 5. ルーティング規約
- RESTfulリソースコントローラを利用したルーティングにする
- ルート名は通常、動詞ではなく名詞を使用する
## 6.モデル関連
- Eloquent ORMを使用したデータモデリングにする
- モデル名は単数形、データベーステーブル名は複数形にする
## 7. ドキュメントとコメント
- コードには説明的なコメントを記述する
- PHPDocコメントを使用してメソッド、プロパティ、クラスを文書化する
Reactでの条件付きイベントハンドラの設定方法

## アジェンダ
Reactでの開発で、ユーザーのアクションに応じて特定の関数を実行する必要があります。しかし、全てのアクションで関数を実行したいわけではないかもしれません。このような場合、三項演算子を使用して、条件に応じて関数を実行するかどうかを制御することができます。

## 基本構文
Reactの`onClick`イベントハンドラ内で三項演算子を使用する基本構文は以下の通りです。

```tsx
onClick={() => 条件式 ? 関数実行() : undefined}
```

この構文では、`条件式`が`true`の場合に`関数実行()`が呼び出されます。`false`の場合には`undefined`が返され、実質的には何も行われません。

## 実用例
例えば、ある条件下でのみユーザーのクリックを処理したい場合、以下のようにコードを記述できます。

```tsx
<button onClick={() => isUserLoggedIn ? handleLogout() : undefined}>Logout</button>
```

この例では、`isUserLoggedIn`が`true`、つまりユーザーがログイン状態であれば、`handleLogout`関数が実行されます。ログインしていない場合は、クリックしても何も起こりません。

## まとめ
Reactでのイベントハンドリングは非常に柔軟で、三項演算子を使用することで、条件に応じて関数を実行するかどうかを簡単に制御できます。この方法は、ユーザーインターフェイスがより動的でユーザーフレンドリーになるように役立ちます。
【kintone】複数のレコードの取得-kintone Rest API(初心者/入門)

#　はじめに
[前回](https://qiita.com/pomo/items/857c02928da644380242 "1件のレコード取得と値の更新")は`1件のレコードの取得と値の更新`を行いました。
今回は`複数のレコードの取得`をRESTAPIで行います。

# 手順
1. `数値`というフィールドコードを設置
1. 数件、`数値`に値を入れてください。今回のサンプル使用の際、３つレコード作成しそれぞれ1,2,4と設定していただくといいです
1. 下記コードをコピペ保存してアプリ設定で更新
1. 一覧を開きボタンを押して確認してください

:::note info
下記のように1以上3以下の数値が入力されているレコードを取得して、数値を合計して表示する単純なサンプルとなります。
画像ですとレコードが３つあり、取得されるのが1と２が入っているレコードのみ。その合計値3をアラートで表示してます。
:::


![スクリーンショット 2024-02-24 10.05.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719638/178fe927-865c-917f-57e1-7ff85f29f93b.png)

## queryの補足
この辺りは最下部の参考をご確認いただきたいですが、
- `数値 >= "1"`となっていますが、クエリを描く際は`フィールコード = "値"`という風に値の部分をダブルクォーテーションで囲んであげてください
- `order by フィールドコード asc`で昇順。descにすると降順になります
- `limit 数字`で取得件数です。現在2024年2月時点では最大500件まで取得できます。それ以上取得したい場合は別の方法で取得はできます
- `offset 0`で取得位置を変えられます。該当するレコードが3件あって、2番目から取得したい場合`offset 1`を指定してあげてください。特殊な場合に使用するので基本指定しなくても

## fieldsの補足
指定しないで省略可です.フィールドが多すぎて、特定のフィールドの値だけ取得したい時に指定してあげてください。

## コード
```test.js
(() => {
  'use strict';
  
  // ボタン押下時に書きかえる
  const testFunction = async () =>{
    const appId = kintone.app.getId();
    
    // 数値が1以上で３以下が入っているレコードをレコード番号昇順で最大１００個。
    // 取得する位置(offset)は最初の位置から
    const body = {
      app: appId,
      query: '数値 >= "1" and 数値 <= "3" order by レコード番号 asc limit 100 offset 0',
      fields: ['レコード番号', '数値']
    };
    const res = await kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', body);
    const records = res.records
    
    // 合計値をいれる変数
    let total = 0
    // 取得したrecordsの数値の合計
    records.map(record =>{
      // kintoneの値は文字で帰ってくるのでNumberやpaserIntで数値にしてあげてください。
      total += Number(record["数値"].value)
    })
  
    
    alert(`合計は${total}だよ`);
  }
  
  // レコードの一覧画面で実行していきます
  kintone.events.on('app.record.index.show', (event) => {

    // ボタンの設置と作成
    const button = document.createElement("button")
    button.innerText = "実行"
    button.addEventListener("click",testFunction)
    
    // kintoneに表示する要素（位置）を取得して、ボタンを設置。
    const el = kintone.app.getHeaderMenuSpaceElement()
    el.appendChild(button)

  // 必ずeventを返してあげる
  return event
    
  });
  
})();
```

 # おわりに
 RESTAPIを使って`複数のレコードを取得`してみました。kintoneの使用頻度も高く、特定の条件に揃ったレコードを取得集計でき、これを使うだけで社内でスーパーヒーロ-になれる可能性もなくはないかも知れません:metal:

 bodyに設定したパラメータ周りは詳しく公式ドキュメントにもわかりやすく書いてありますので参考ご確認ください。

それでは
 ### 楽しいkintoneライフを:relaxed:

 # 参考
  https://cybozu.dev/ja/kintone/docs/rest-api/records/get-records/
PlunkerでPhaser.Physics その6

# 概要
Plunkerで、Phaser.Physicsやってみた。
applyForceで、力を加えてみた。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/42dfe489-0dce-d579-6a5e-8be112da3797.png)


# サンプルコード

```

var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { 
    create: create, 
    update: update,
    render: render 
});
function create() {
    game.stage.backgroundColor = '#124184';
    game.physics.startSystem(Phaser.Physics.BOX2D);
    game.physics.box2d.gravity.y = 400;
    game.physics.box2d.restitution = 0.8;
    game.physics.box2d.setBoundsToWorld();
    for (var i = 0; i < 10; i++)
    {
        var ball = new Phaser.Physics.Box2D.Body(this.game, null, game.world.randomX, 0);
        ball.setCircle(16);
        ball.bullet = true;
    }
    cart = new Phaser.Physics.Box2D.Body(this.game, null, game.world.centerX, 243);
    cart.setRectangle(60, 20, 0, 0, 0);
    cart.mass = 1;
    cursors = game.input.keyboard.createCursorKeys();
}
function update() {
    if (cursors.up.isDown) 
    {
        cart.applyForce(0, -10);
    }
    if (cursors.left.isDown) 
    {
        cart.applyForce(-5, 0);
    }
    if (cursors.right.isDown) 
    {
        cart.applyForce(5, 0);
    }
}
function render() {
    game.debug.box2dWorld();
}




```

# 成果物

https://embed.plnkr.co/plunk/QOrzjHN4nh4vnyHp


以上。
AstroでWorker is not definedエラーの対処法

AstroでReactコンポーネントを使用時に下記のエラーが出た場合の対処法になります。

```
Workeris not defined
```

## ReactコンポーネントでWorkeris not definedエラー


```js: index.astro
<MyComponent />
```

AstroファイルでReactコンポーネントを読み込むと下記のエラー出てビルドできませんでした。

![Astro Worker is not defined.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/834c9389-af57-adc2-c925-f5f9c250ba7d.png)

```
Workeris not defined

Could not open checkImageBitmap.worker.js in the editor.
The editor process exited with an error: spawn code ENOENT.
```

Reactコンポーネント内でライブラリ（pixi.js）を使っており、そのライブラリの影響かと思われます。

## client:only="react"の指定を追加して解決

```js: index.astro
<MyComponent client:only="react"/>
```
呼び出し側のastroファイルで`client:only="react"`を指定することで解決しました。

## 参考
https://docs.astro.build/ja/reference/directives-reference/#clientonly
rex0220 計算式プラグイン 不要なテーブル行の削除（旧）

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で不要なテーブル行の削除を行います。

# 概要

* TABLE_SORT 関数でテーブル行削除ができますので、今後はTABLE_SORT 関数をお使いください
* [rex0220 計算式プラグイン テーブルソート TABLE_SORT関数版](https://qiita.com/rex0220/items/9c79f548200a09e6e61d)


指定した条件で、レコード保存時に不要なテーブル行の削除を行います。

テーブルの集計用の TLTABLE 関数を使用するため、集計値の数値項目が必要です。
テーブル内にルックアップ項目・ファイル添付項目がある場合は、対応できません。

※[rex0220 計算式プラグイン ルックアップ項目を含む不要なテーブル行の削除](https://qiita.com/rex0220/items/cd57c427164f8bec9ce0)

![2024-02-24_09h59_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/6325aa17-3193-eac0-04ed-5374a8782566.png)

# アプリ設定

テーブル行の識別のため、テーブルに数値項目を配置します。

![2024-02-24_10h08_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/06601482-d52e-f134-03b0-5e703b5b05f0.png)

# 計算式プラグイン設定

「循環参照を許可」をチェックします。

![2024-02-24_10h03_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/773b3395-bb44-3064-a136-29239e622c3b.png)

レコード保存時のイベント時、TLTABLE 関数で不要テーブル行を削除します。
TPFILTER オプションで、必要なテーブル行の条件を指定します。

- TPFILTER(OR(日付1,文字列1,チェックボックス1,数値1))
    - 日付1,文字列1,チェックボックス1,数値1に値がある

```.js
OPTION: 循環参照を許可

// テーブル SUBTABLE (editable)
IF(EV_INFO("mode")!="submit","",
  TLTABLE(テーブル,
    TPFILTER(OR(日付1,文字列1,チェックボックス1,数値1)),
    TPKEY(番号,日付1,チェックボックス1,文字列1),
    TPVAL(数値1),
    TPOUT(番号,日付1,チェックボックス1,文字列1,数値1)
  )
)

// テーブル.番号 NUMBER
ROWNO(テーブル)+1
```
[Mac] ショートカット一覧

## よくに使用するショートカット
- Command (⌘) + Z: アンドゥ（元に戻す）
- Command (⌘) + X: カット
- Command (⌘) + C: コピー
- Command (⌘) + V: ペースト
- Command (⌘) + A: すべて選択
- Command (⌘) + F: 検索
- Command (⌘) + N: 新しいウィンドウを開く
- Command (⌘) + Shift (⇧) + N: 新しいフォルダーを作成する
- Command (⌘) + Delete: 選択した項目をゴミ箱に移動する
## システムとナビゲーション
- Command (⌘) + Space: Spotlight検索を開く
- Command (⌘) + Tab: 開いているアプリケーション間を切り替える
- Command (⌘) + Option (⌥) + Esc: 強制終了ウィンドウを開く
- Command (⌘) + Shift (⇧) + 3: スクリーンショットを撮る
- Command (⌘) + Shift (⇧) + 4: 選択範囲のスクリーンショットを撮る
## ファイルとフォルダー
- Command (⌘) + W: 現在のウィンドウを閉じる
- Command (⌘) + O: ファイルを開く
- Command (⌘) + S: ファイルを保存する
- Command (⌘) + Shift (⇧) + A: 「アプリケーション」フォルダを開く
- Command (⌘) + Shift (⇧) + D: 「デスクトップ」フォルダを開く
- Command (⌘) + Shift (⇧) + G: 「移動」ダイアログを開き、任意のフォルダに直接移動する
- Command (⌘) + Shift (⇧) + O: 「ドキュメント」フォルダを開く
- Command (⌘) + Shift (⇧) + U: 「ユーティリティ」フォルダを開く
- Command (⌘) + Shift (⇧) + Delete: ゴミ箱を空にする
- Command (⌘) + Option (⌥) + I: 選択した項目の情報を表示する（「情報を見る」ウィンドウ）
- Command (⌘) + Option (⌥) + D: ドックを表示/非表示する
- Command (⌘) + Option (⌥) + V: 「移動」ペースト（コピーした項目を移動する）
- Command (⌘) + [: 前のフォルダに移動する
- Command (⌘) + ]: 次のフォルダに移動する
- Command (⌘) + 上矢印キー: 上位のフォルダに移動する
- Command (⌘) + 下矢印キー: 選択したフォルダを開く
カラーマップを対数スケールに設定する ColorScale


データによってはカラーマップを対数スケールにした方が見やすいこともありますが、設定方法が意外と探しづらいのでここで紹介させてください。

```matlab
% 適当なデータ作成
m = membrane;
data = exp(10*m);

% 曲面プロット
surf(data)

% カラーバー表示
colorbar
h = gca;
% カラーマップの対応を対数スケールに
h.ColorScale = 'log';

% ついでにフォントサイズ大きく
fontsize(14,'points')
```

![figure_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/854810ad-1191-d1a9-fa2f-a38271e66bd8.png)

# `ColorScale` プロパティ

これは R2018b で使えるようになった Axes (座標軸) オブジェクトのプロパティです。デフォルト設定だと線形（`'linear'`）になっていますが、ここを `'log'` に変えることで上のような結果になります。


詳細：[https://jp.mathworks.com/help/matlab/ref/matlab.graphics.axis.axes-properties.html#budumk7_sep_budumk7-ColorScale](https://jp.mathworks.com/help/matlab/ref/matlab.graphics.axis.axes-properties.html#budumk7_sep_budumk7-ColorScale)


`ColorScale` は次の値のいずれかとして指定します。

-  `'linear'` — 線形スケール。カラーバーの目盛り値も線形スケールを使用します。 
-  `'log'` — 対数スケール。カラーバーの目盛り値も対数スケールを使用します。 

R2018a 以前だと [カラーマップ，カラーバーを対数軸にする](https://hydrocoast.jp/index.php?MATLAB/log%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E3%81%AE%E7%9D%80%E8%89%B2) で紹介されている方法が大変参考になります。


ちなみに `ColorScale` を変更しない（`'linear'` のまま）とこんな絵になります。値が小さい箇所が同じ色になっちゃって小さい変化が見にくいですよね。

```matlab
% 適当なデータ作成
m = membrane;
data = exp(10*m);

% 曲面プロット
surf(data)
colorbar
fontsize(14,'points')
```

![figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/872dfe22-537a-7676-f461-c999ad904506.png)

# `zscale` で z 軸を対数スケールに

そもそも z 軸を対数スケールにしちゃうのも良いかもしれませんね。[`zscale` 関数](https://jp.mathworks.com/help/matlab/ref/zscale.html)を使います！これも実は　 R2023b で使えるようになったばかり。


x 軸、y 軸に関しても [`xscale` 関数](https://jp.mathworks.com/help/matlab/ref/xscale.html)、[`yscale` 関数](https://jp.mathworks.com/help/matlab/ref/yscale.html)があります。

```matlab
% 適当なデータ作成
m = membrane;
data = exp(10*m);

surf(data)
colorbar
zscale('log') % z 軸を対数スケールに

h = gca;
% カラーマップの対応を対数スケールに
h.ColorScale = 'log';

fontsize(14,'points')
```



![figure_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/8335f9d8-a1b4-dd50-bb31-639fc50700d7.png)

カラーマップに対しても [`zscale`](https://jp.mathworks.com/help/matlab/ref/zscale.html) みたいな `cscale` 関数があるとコードもシンプルになっていいですね。


ちなみに `xscale/yscale/zscale` が使えなかった R2023a 以前のバージョンだと、上で `ColorScale` に対して行った操作と同様に

```matlab
h.ZScale = 'log';
h.ColorScale = 'log';
```

と変更しますね。
【PHP】307リダイレクトをよく理解してなかった話

# はじめに

PHPでリダイレクトをしなくてはいけない時があったのですが、その際に少しはまってしまったのでその話を書きたいと思います。

メソッドとパラメータを変えずにそのまま次の画面に渡す、ということをしようとしていました。

# 勘違いしていたこと

PHPにはheader関数があり、それを使用して
```php
header("Location: {リダイレクト先のURL}", true, 307);
```
というような感じで実装していました。

307リダイレクトは、

>メソッドと本文は変更しません。
（https://developer.mozilla.org/ja/docs/Web/HTTP/Redirections より引用）

というように記載してあったのでてっきりPOSTでもGETでもきたパラメータはすべて渡してくれるのかと思っていました。

# 実際に挙動を見てみる
`index.html`

⇓ GET POST

`index1.php`

⇓ 307リダイレクト

`index2.php`

というような感じでリダイレクトさせ、`index2.php`でGETとPOSTの値を見てみることにします。

各ファイルは以下のようにしました。
```html:index.html
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
  </head>
  <body>
    <form method="POST" action="./index1.php">
      <input type="text" name="name" />
      <button type="submit">POST送信</button>
    </form>
    <form method="GET" action="./index1.php">
      <input type="text" name="name" />
      <button type="submit">GET送信</button>
    </form>
  </body>
</html>
```
```php:index1.php
header("Location: ./index2.php", true, 307);
```
```php:index2.php
echo("POSTの値：");
echo($_POST["name"] ?? "POSTなし");

echo("<br>GETの値：");
echo($_GET["name"] ?? "GETなし");
```
1画面目は画面で見るとこんな具合です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/837eb12f-d217-571b-8ecc-b29c92358f03.png)

### POST

まず、POSTで送信してみます。
POST送信ボタンのとなりにデータをいれ、POST送信ボタンを押してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/5e9d1aa1-0ea1-1be9-e6ed-437dea826830.png)

index2.phpではPOSTの値がうまく取れていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/048354a3-3f9c-fb8c-cc3e-2bf5b0204eca.png)


### GET

次にGETで送信してみます。
先ほどと同じようにGET送信ボタンの横にテストと文字を入力してGET送信ボタンを押してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/3c750561-cc4d-afd1-6a3a-5fa67c42e756.png)

すると、GETの値が取れていませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/f39060fe-4ff5-1c7f-9229-92faeedf9a2b.png)


# 結論

どうやら、GETの時はパラメータを渡してくれないようです。

もしGETのときもPOST同様に値をリダイレクト先に渡したいときは以下のようにリダイレクト処理を変更すると渡すことができました。

```php:index1.php
header("Location: ./index2.php?".$_SERVER['QUERY_STRING'], true, 307);
```
$_SERVER['QUERY_STRING']は、
>ページがアクセスされた際にもし検索引数があればそれが格納されます。
(https://www.php.net/manual/ja/reserved.variables.server.php より引用）

というものです。

つまり、GETパラメータがもしURLについていたら、そのGETパラメータをそのままStringとして取得できるよというものでした。

これをリダイレクト処理に書くことで、GET・POST問わず、リダイレクトをするときにメソッドそのままでパラメータをリダイレクト先に送れるようになりました。

# おわりに

結局なぜPOSTの時は値をリダイレクト先に渡せて、GETの時には渡せないのかがよくわかりませんでした。

もし詳しい方いたらコメントで教えていただけると助かります。

また、もっといいやり方や間違っている点などありましたらご指摘いただけると幸いです。

最後まで読んでいただきありがとうございました。

# 参考

https://developer.mozilla.org/ja/docs/Web/HTTP/Redirections

https://www.php.net/manual/ja/reserved.variables.server.php
vue.jsのチュートリアルを整理していく

Vue.jsの公式ドキュメントを読んでいるが、なんかよくわかんないということで、記事にしながら整理することにした。
公式ドキュメント→https://ja.vuejs.org/guide/introduction.html
## 単一ファイルコンポーネント
HTML,CSS,Javascriptをまとめて持っている一つのファイル。Vue独自のもので、SFCともいわれる。見た目がHTMLファイルっぽいが、HTMLではない。拡張子は「.vue」。
↓単一ファイルコンポーネントの例
```test.vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>
```
補足）コンポーネントとは？
英語でcomponent。大雑把にいえばプログラムの部品。VueみたいなGUI設計では画面に表示される一つ１つのボタンやテキストボックス周りのプログラムを指す。
詳しくはggrks
## ２つのAPIスタイル
Vue.jsでは「Options API」と「Composition API」の2つのAPIスタイルを選択できる。
### Options API
PythonやJavaなどのオブジェクト指向プログラミング言語を使っている人は使いやすいAPI。Composition APIに比べると初心者向き。

↓Option APIの例
```OptionAPI.vue
<script>
export default {
  // data() で返すプロパティはリアクティブな状態になり、
  // `this` 経由でアクセスすることができます。
  data() {
    return {
      count: 0
    }
  },

  // メソッドの中身は、状態を変化させ、更新をトリガーさせる関数です。
  // 各メソッドは、テンプレート内のイベントハンドラーにバインドすることができます。
  methods: {
    increment() {
      this.count++
    }
  },

  // ライフサイクルフックは、コンポーネントのライフサイクルの
  // 特定のステージで呼び出されます。
  // 以下の関数は、コンポーネントが「マウント」されたときに呼び出されます。
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>
```
公式のやつをそのまま張り付けているだけなので変なコメントがついているが、いらないよって人は気にしなくていい。
Option APIでは、まずオブジェクトを作り（上のプログラムではdefault）、そこにいろいろなオプションをつけていく（dataやmethodsなど）。
オブジェクト内のデータにオブジェクト内からアクセスするときにはthisを使う。

イメージとしては、クラスのなかにいろいろなインスタンスやメゾットがあるのと同じ感覚。
### Composition API
Option APIより自由度が高いが少しムズい。
```CompositionAPI.vue
<script setup>
import { ref, onMounted } from 'vue'

// リアクティブな状態
const count = ref(0)

// 状態を変更し、更新をトリガーする関数。
function increment() {
  count.value++
}

// ライフサイクルフック
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>
```
ムズくて筆者もよくわかってないので、解説は割愛。
補足）APIとは？
アプリケーション・プログラミング・インターフェース（Application Programming Interface）のこと。プログラム同士をつないでいるもの。
詳しくはg((略
## どっちのAPIがいいのか
どっちでもいい。
どちらも基本的な考え方は同じらしく、公式ドキュメントでも片方のAPIしか教えてあげないよみたいなことはしていない。
コンテナ版GitLab間のproject移行

## A. やりたいこと

#### 条件

* 同一サーバに2つのコンテナ版GitLabを起動している。共通のSSL証明書を使用している。
* publishしているhttpsポート番号を443と4443に分けている。以下のようなかんじ
  * https://gitlab.hogehoge.net/fugafuga/PJ.git
  * https://gitlab.hogehoge.net:4443/fugafuga/PJ.git

ここの、443から4443に、プロジェクト(リポジトリ)をコピーしたい

## B. 手順

1. 4443側(コピー先)に同名で空のプロジェクトを作成する。README等も作らない。
1. 「コピープロジェクトスクリプト」を実行する
1. 以上

#### コピープロジェクトスクリプト

```
#!/bin/bash
PJ=$1
cd /tmp
git clone https://gitlab.hogehoge.net/fugafuga/$PJ.git
cd $PJ
git remote rename origin old-origin
git remote add origin https://gitlab.hogehoge.net:4443/fugafuga/$PJ.git
git push --set-upstream origin --all
git push --set-upstream origin --tags
rm -rf /tmp/$PJ
```

## C. まとめ

* バージョンの異なるGitLab間でのプロジェクトコピーが必要だったので、「A.やりたいこと」を実現する方法を色々試行しました。最終的にたどりついた「B. 手順」が、一番楽でした。
* コピープロジェクトスクリプトも同じサーバーで起動しようとしましたが、さすがにダメでした。サーバーの外から実行するとうまいいきました。
* gitコマンドだけなので、GitHubからのコピー等もうまくいくと思います。
初心者がよく使うOSモジュール一覧



## はじめに
初心者がよく使うOSモジュール一覧に関しての備忘録です。
初心者です😅
間違えてる部分が多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇
<br>
## 🦁<INS>**結論**</INS>🦁
OSモジュールはPythonにてOS操作ができるモジュール。
ファイル、ディレクトリの操作（作成、削除、状態確認など）
環境変数の取得
などを行うことができる。


:::note info
押さえておくべき点
* パスを操作する際、os.pathモジュールの関数を使用し、OSに依存しないコードを書くことが重要。
* 例外処理を適切に行うことで、プログラムの安定性を高めることができる。
:::  

***  

:::note alert
注意点
* ファイルやディレクトリの所有者でない場合があり、特定の操作を行うための権限が制限されることがある。
* os.environで環境変数を扱う際は、存在しない変数へのアクセスがエラーを引き起こす可能性があることに注意が必要。
:::  

***
# 関数一覧
##  <INS>**os.path.exists()**</INS>
指定されたパスが存在するかどうかをチェックする


## <INS>**os.remove()**</INS>
ファイルを削除する。

## <INS>**os.listdir()**</INS>
指定されたディレクトリ内のファイルやディレクトリ名のリストを返す。

## <INS>**os.rmdir()**</INS>
ディレクトリを削除。ディレクトリが空でなければ削除できない。

## <INS>**os.path.basename()**</INS>
指定されたパスからベース名（ファイル名）を取得する。

## <INS>**os.path.dirname()**</INS>
指定されたパスからディレクトリ名を取得する。

## <INS>**os.path.isdir()**</INS>
指定されたパスがディレクトリであるかどうかをチェック。

## <INS>**os.path.abspath()**</INS>
与えられたパスの絶対パスを返します。

## <INS>**os.getenv()**</INS>
環境変数の値を取得する。


## まとめ😺
まとめてみると新たな発見がいっぱいありました。
OSモジュールで確認しなければいけないことがたくさんあるなと感じました。
tmuxでログのエスケープシーケンスを綺麗に除去

# 前説 - ログのエスケープシーケンスが邪魔 -
~~IT土方~~SE的なお仕事では、証跡が大事だとよく言われます。
GUIのWindowsならスクショ、Linuxならログですね。
Linuxでは多くの場合、Tera Termが使われますが、コマンドライン上でタイプミスを修正したりすると、ログにエスケープシーケンスが混じります。
Tera Termの場合、ログにエスケープシーケンスを除外する設定もできますが、最終的なコマンドラインとは異なる結果になってしまいます。
これはエスケープシーケンス除外処理がVT100の振る舞いに従っていないためであり、Tera Termに限らず多くのエスケープシーケンス除外処理を謳うプログラムやスクリプトはこのような結果になってしまいます。

# tmux でエスケープシーケンスを除去するシェルスクリプト
そこで、古くはGNU screen、近年ではtmuxのスクロールバッファ機能を用いて、ログのエスケープシーケンス除外処理を行う、という内容が僅かにwebで見受けられます。
しかし、具体的にどうするのか、あまり詳細に記述されたweb文書が見当たりませんでした。
仕方なく、私なりに以下のように書いてみました。
```
$ cat ~/bin/tmclog.sh
#!/bin/bash
if [ -e $1 ] && [ "$1" != "" ] ; then
	clear
	tmux clear-history
	cat $1
	tmux capture-pane -pS - > /tmp/hoge
else
	echo "File not found."
	exit 1
fi
```
# 使い方
先ず、**tmuxを実行し、新たなセッションを作成します。**
次に、**tmuxのセッション上で、上記シェルスクリプトを実行します。**
以下はユーザホームディレクトリ配下に ~/bin/ ディレクトリを作成し、そこに上記シェルスクリプトを配置し、 $PATH を通している例です。
```
$ tmclog.sh [full-path-of-logfile]
```
こうすると、 /tmp/hoge という、エスケープシーケンス除外処理を施されたログファイルが出来上がります。
Tera Termだけでなく、 script コマンドによるログファイルも同様に処理できます。
要はVT100エスケープシーケンスが含まれるログなら何でもOKです。
但し、文字コードはUTF-8限定です。~~(今更SJISってないっしょ。え?PowerShell?)~~

Linux, bash限定です。
Ubuntuで動作を確認していますが、 RedHat系でも実行できると思います。
*BSD系でもできるかも?Mac持ってないんでわかりません。
# ここで力尽きました
とは言えども、出力が常に /tmp/hoge じゃあ芸がないですね。
で、出力をもう少し実用的に、なんて考えては見たんですが、

* ユーザの趣味趣向によってあらゆるケースが考えられる
* 出力先次第ではパーミッションやセキュリティを考えなければならない場合がある
* そうなるととてもシェルスクリプトでは賄いきれず、今の私のスキルじゃ対応できない

ので、一旦諦めることとしました。
皆様の手でシェルスクリプトやpython等で便利に改造しちゃってください。
【Saleforce】フロービルダーのBeforeトリガーと割り当て

Salesforceのフロービルダーで、トリガーレコードの場合、高速項目更新（Beforeトリガー）に「割り当て」要素を使いましょう、という記事です。

フロービルダーでレコードを更新したときの、要素の使い分けは下記です。

## 「割り当て」
- トリガーレコードを更新したい
- 高速項目更新

https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_assignment.htm&type=5

## 「レコードを更新」
- 関連レコードを更新したい
- アクションと関連レコード

https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_data_update.htm&type=5

テキストだけだと伝わりづらいかと思います。
なので今回は、フロービルダーの「高速項目更新」と「割り当て」を使って、トリガーレコードの項目自動更新を実装してみます。

## 要件
商談が新規作成されたとき、取引先の「取引先番号」が自動反映される。

### 取引先Aを作成
![01取引先A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/cdea9d78-f7fa-24cf-05bf-ef3b37df41cf.png)

取引先番号「A-00001」の取引先Aを作成します。

### フロー新規作成
![02フロー作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/3cc1e5d9-ed81-ed00-a35e-9c2d72b0ce22.png)

レコードトリガーフローを選択します。

### 開始条件を選択
![03高速更新.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/b01a0f2f-8093-2ddf-75a9-b78cb8c958d0.png)

下記のように選択・設定します。

- オブジェクトを設定：商談

- トリガーを設定：レコードが作成された

- エントリ条件を設定：なし

- フローを最適化:高速項目更新

### 割り当て
![04新規割り当て.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/0c03a554-289d-2338-9029-a9aa185e149c.png)

表示ラベルやAPI参照名は任意で、下記のように選択・設定します。

- 変数：{!$Record.Description}

- 演算子：次の文字列と一致する

- 値：{!$Record.Account.AccountNumber}

今回は、商談の「説明」項目に、その商談の取引先の「取引先番号」を反映させます。

### フローを保存
![05フロー保存.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/06d2f033-785e-746f-245b-a166c135913f.png)

任意の値で保存します。

### フロー完成
![06フローイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/c533aff6-15c0-daf9-2c98-76f38b8250a6.png)

シンプルなフローができました。

### 商談を作成
![07商談作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/fac3bbfc-447e-35a8-b8ee-9f29d9f64b19.png)

商談を作成します。

### 新規作成
![08デモ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/686e9743-1814-06d8-2595-3b54531e0b54.png)

必須項目のみ入力します。

### 取引先番号を確認
![09デモ成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/ff4c7005-2955-ea81-cdbc-1066c3b59749.png)

無事に取引先番号が反映されました。

今回の高速項目更新（Beforeトリガー）の場合は、保存前に割り当てされるので割り当て＝レコード更新となります。
しかし、別のオブジェクトのレコードを更新したい場合には、割り当てでは不適切です。

いかがでしたでしょうか。
高速項目更新はフローの処理が10倍以上早いという記事もありました。
フロービルダーの項目更新で、要素を使い分けたい方のご参考になれば幸いです。

※参考記事

フローのべストプラクティス

https://help.salesforce.com/s/articleView?id=sf.flow_prep_bestpractices.htm&type=5


Record-Triggered Automation

https://architect.salesforce.com/decision-guides/trigger-automation
JLCPCBで金属3Dプリントしてみる

### 1.JLCPCBの金属3Dプリントとは
JLCPCBとはPCBの製造や3Dプリントなどを請け負っている中国深センのサービスです。今回はJLCPCBで金属3Dプリントを発注してみたのでまとめていきます。
[JLCPCB](https://jlcpcb.jp/ "JLCPCB")
![28lmMzBb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/873e55b9-22b0-f4e2-115d-d22ec1a10469.png)

### 2.実際に注文する方法
まずは、Fusion360を用いて発注する部品をモデリングします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/821f462d-e849-f89b-10ce-852958325dbf.png)

他の3Dプリンターで印刷する時と同様にstlファイルを書き出します。
続いてJLCPCBのサイトに移動し3Dプリントを選択したのちにstlファイルをアップロードします。材質をSLM(Metal)を選択します。
[JLCPCB](https://jlcpcb.jp/ "JLCPCB")
![28lmMzBb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/873e55b9-22b0-f4e2-115d-d22ec1a10469.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/f0f79a77-c252-3d29-48d4-4211d350b08d.png)

### 3.実際に届いたもの
実際に完成届いた物が以下の部品になります。

ねじつき厚鋼電線管に取り付ける事ができます。ねじ部分も問題なく、はまります。
![IMG_6727.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/8a10b94d-8a39-fe63-b885-cdf2f2ac991f.jpeg)
![IMG_6726.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/ddb56783-912f-bf22-a9c7-7ef6a89b5081.jpeg)

### 4.感想
想像していたよりも3Dプリント感を感じさせない部品に仕上がっており満足度は高いです。また、他サービスと比較しても値段が高くないことから金属部品が必要な際の選択肢としてありだなと感じました。
[JLCPCB](https://jlcpcb.jp/ "JLCPCB")
![28lmMzBb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632959/873e55b9-22b0-f4e2-115d-d22ec1a10469.png)
Twitch, Youtube ライブコメント連動アプリケーション

![CAEB_256x256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638255/aecef305-906f-bdaf-a0c7-50c3daaf9ab0.png)

|  | 内容 |
|:----:|:-------------|
|  | [はじめに](#はじめに) |
|  | [概要](#概要) |
|  | [機能](#機能) |
|  | [インストール方法](#インストール方法-利用者) |
|  | [使用方法](#使用方法-利用者) |
|  | [使用ライブラリ](#使用ライブラリ-技術者) |
|  | [コードの構造](#コードの構造-技術者) |
|  | [発展](#発展) |

# はじめに
**アプリ利用者用**と**技術者用**で呼んでいただきたい**項目**が異なりますので, 各項目に**対象者**を明示させていただきます(明示されていない場合は**全対象者向け**).

# 概要
`Twitch` or `Youtube`配信のコメントを**リアルタイム**に取得し, 連動して**アクションを発生させる**アプリケーションです.
`Python`を用いたGUIソフトウェアとなっています.

# 機能
* コメント取得時に**効果音**を発生させる. また**発生確率**を設定できる.
* コメント取得時に**動画**を再生できる. 同様に**発生確率**を設定できる.
* [未実装] `!Input` コマンド(配信主の**キーボード**のキーを一つのみ**操作**できる).
* [未実装] `!Display` コマンド(配信上に設定された画像を表示できる).
* [未実装] `!Sound` コマンド(配信上に設定された音声を鳴らせる).

# インストール方法 (利用者)
[こちら](https://drive.google.com/drive/folders/1aqVRyOTzVTlcw8yh_Gacy3-ZjcV3M3Jj)の`Google Drive`からダウンロード可能です.
ダウンロードフォルダを解凍し, `CommentAcquisitionEquipmentBot.exe`をダブルクリックすることで実行可能です.
フォルダ内の`README.txt`は一読いただけると幸いです(更に**詳細**な情報が記載されています).

# 使用方法 (利用者)
1. アプリを実行すると以下のウィンドウが表示されます
![CAEB_Main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638255/a2224352-6734-ef61-7113-fe137686dd00.png)

1. メニューバーの`ファイル`をクリックし, **設定**を開きます
![CAEB_Settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638255/270baa33-9e68-af60-0927-168b52787f16.png)
1. あなたの**配信URL**をコピペします
    Twitch: `https://www.twitch.tv/あなたのuserID`
    Youtube: `https://www.youtube.com/watch?v=あなたの配信ID`
    
1. `+`を押してコメント取得時の**効果音**と**演出**を追加します
1. 右下の`保存`を押して設定終了
1. 最後にメニューバーの`配信`から`参加`をクリックし, 配信上に"**taroutaroupbotがあらわれた**"とコメントが表示されれば成功です(配信を開始した状態で`参加`をクリックすることをおすすめします)

# 使用ライブラリ (技術者)
このアプリケーションの作成には以下の非標準ライブラリが使用されています:
- **Pillow** : 画像処理
- **pygame** : 音声処理
- **twitchio** : TwitchのBotをpythonで作成できる
- **pytchat** : Youtubeのコメントを取得できる
- **nest_asyncio** : イベントループをネストする
- **opencv-python** : 動画処理

# コードの構造 (技術者)
https://github.com/lieeeeeeeee/CommentAcquisitionEquipmentBot

↑ブランチをMainからLegacyに変更していただくと, レガシー版コードが閲覧できます.

#### アーキテクチャ
レガシー版 : **MVCモデル**を採用しています.
モダン版 : **Clean Architecture**を採用する予定です.
#### コンポーネント
レガシー版 : **SplashView**, **MainView**, **SettingView**の3つのView構成です.
モダン版 : 未定.
#### GUI
レガシー版 : **Tkinter**.
モダン版 : **Electron** or **Flet**のどちらかを採用する予定です(**Electron**は**jsフレームワーク**の学習として魅力的).

# 発展
レガシー版からモダン版にするに当たって改善点.
- GUIのモダン化
- 機能追加(コマンドやゲーム等を実行可能にする)
- 配信ゲームによって機能を変更
- 機能のOnOff機能
- アプリアイコンの設定(ちなみにトップに表示されている画像はアプリアイコンです)
Apple Vision ProとMacを接続する方法

# はじめに
XcodeでAppleVisionProのテストアプリを作ったのですが、AppleVisionProとMacを接続するのにちょっと困ったので備忘録として。[こちら](https://www.techno-edge.net/article/2024/02/05/2756.html)を参考にしています。

# 方法

## 前提条件
1. MacとVisionProが同一の無線ネットワークで繋がっていること。
1. MacもVisionProも同一のiCloudアカウントでログインしていること。

# 手順
1. **[VisionPro]** Settingアプリを開く
1. **[VisionPro]** General→Remote Deviceとアクセスして、Ready to Pairの表示を確認してそのままにする。
1. **[Mac]** Xcodeを開く
1. **[Mac]** メニューからWindow→Devices and Simulatorsとアクセスする。
1. **[Mac]** Devicesの一覧から自分のApple Vision Proが表示されているので、それを選んだ後に、Pairボタンを押す。
1. **[VisionPro]** VisionProに表示される6桁コードを確認する。
1. **[Mac]** VisionProに表示される6桁のコードを入力する。
1. **[Mac]** これでXcode側に登録したVisionProが選べるはず。![スクリーンショット 2024-02-23 15.01.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187459/218e0459-d28e-7d31-c0f3-1356eb42910f.png)
1. **[Mac]** とにかくテストアプリで１回ビルドを試みる。エラーになるが一旦放置する。
1. **[VisionPro]** SettingsからPrivacy & Securityを選ぶ。
1. **[VisionPro]** 一番下までスクロールするとDeveloper Modeがあるため、Onにして再起動する。
1. **[VisionPro]** 再起動後もDeveloper Modeを有効にして良いか聞かれるのでAcceptする。

この状態でMac側でビルドすると、Vision Pro側のアプリ一覧に自分のテストアプリが表示されます。

# 参考文献
- 手に入れたApple Vision Proでアプリ開発。シミュレータから実機で開発の設定をしよう
https://www.techno-edge.net/article/2024/02/05/2756.html
Minecraft Launcherの実体はどこにある？

PC版Minecraftインストール時、特に設定を変更せずにインストールした場合、Minecraft Launcherの実体はここにあります：

C:\XboxGames\Minecraft Launcher\Content\Minecraft.exe

---
個人的にCLaunchが好きで、Minecraft Launcherのショートカットを登録しようとしたところ、実体探しに1時間かかりました。

アイコンはうまくCLaunchに反映できず、あきらめました!
ElixirLSでデバッグする

# Brightの対象
Webアプリ開発 Elixir > クラス1 > Elixirテスト／デバッグ > デバッグ > ElixirLS

# 前提事項
ElixirLSがインストールしている事
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/e3d7bc71-8540-9636-e098-48cf2288a7bc.png)

# 使い方
実行とデバッグをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/5fadb1c9-49e0-979e-d43f-1c6b4e81a8a6.png)

Mix Taskをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/acfe6475-8a45-902a-05bf-90cb826967f8.png)

launch.jsonを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/d385fc71-a33f-066a-7ae2-852996dad2b2.png)


デバッグするソースを開き、デバッグポイントを作る（赤丸）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/f2956813-d072-dffc-cd09-5404066f3897.png)

mix testを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/63ba9b43-9417-80ee-1b12-ae4e96e918cb.png)

デバッグポイントで止まるので
「ステップオーバー」し1行すすめる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/ededecdd-d793-1569-1afe-905fe2719397.png)

a変数の状態をみれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/a0f54bb6-62f9-68bb-4fca-138da721be74.png)

以上、ElixirLSを使った「ステップ実行」と「変数の状態」確認ができました
Goでコンソールアプリのexeファイルを実行する

前回、[C#でExcelの.xls形式を.xlsx形式に変換](https://qiita.com/te-k/items/902cdded0793acb58586)する`exe`ファイルを作ったので、それをGo言語で呼び出してみます。

C#でビルドした実行ファイルは、以下のように配置しました。
```
C:.
│  go.mod
│  main.go
│
└─net6.0
        ExcelConverter.deps.json
        ExcelConverter.dll
        ExcelConverter.exe
        ExcelConverter.pdb
        ExcelConverter.runtimeconfig.json
```

`Go`の`os/exec`を使って`exe`を呼び出します。
```go
package main

import (
	"fmt"
	"os/exec"
)

func main() {
	exePath := "./net6.0/ExcelConverter.exe"
 
	arg1 := "C:\\Users\\tek\\Desktop\\ExcelConverter\\testData\\sample.xls"
	arg2 := "C:\\Users\\tek\\Desktop\\ExcelConverter\\testData\\sample.xlsx"

	cmd := exec.Command(exePath, arg1, arg2)

	output, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Println("Error executing command:", err)
		return
	}

	fmt.Println("Completed")
}
```

処理の実行
```bash
go run .
```

`.xlsx`にファイル変換できました:smile:

次は、Go言語のExcelライブラリからファイルを操作してみたいと思います。

## Reference
- [os/exec](https://pkg.go.dev/os/exec)
- [func Command](https://cs.opensource.google/go/go/+/refs/tags/go1.22.0:src/os/exec/exec.go;l=376)
Intellij IDEA での（ビルドツールを使わない）Jarの生成方法

## 一連の流れ
1. プログラムを作る
1. ビルド前準備
1. ビルド
1. 完成！！

#### 環境
- windows 7 (x86)
- Intellij IDEA 2018.2.8
- Java 8
:::note alert
これはビルドツール（Gradle、Maven、Ant）を使用しないJarの生成方法です！
通常Jarファイルを生成する際は必ずどれかのビルドツールを使用しましょう！
そのほうが拡張もし易く、他のJarにも生かし易くなります！
:::


## ビルド前準備
1. [プロジェクト構造] - [成果物] を選択して、「＋」をクリック
1. 出てきたポップアップの内「Jar」 - [依存関係を持つモジュールから] をクリック
1. 「モジュールからJAR生成」ウィンドウが開くので、「メイン・クラス」横の枠内にある薄いフォルダマークをクリックするとmainメソッドを持つクラス一覧が表示される
1. その中からメインクラスに設定したいクラスをクリック
1. 「OK」をクリックすれば

## ビルド
1. 上部メニューの [ビルド] - [成果物のビルド(build to Artifacts)] をクリック
1. 出てきたポップアップ中の「build」をクリックするとビルド開始
1. ビルド前準備で設定されたフォルダにJarファイルが生成される
:::note 
生成されたjarファイルは、デフォルトでは [out] - [artifacts] - [（名称）] の中に置かれる。
```
[out]
  ┗━[artifacts]
           ┗━[test1_jar]
                   ┗━ test1.jar
```
:::
SQLアンチパターン：信号無視

有名な書籍「SQLアンチパターン」を購入したので学習。

パターン①：信号無視

・1カラムにコンマ区切りで値を入れ、複数の紐付きを表現しようとする
```
id 　　　	name　　　　　　	favorite
1	    hoge1	php,ruby
2	    hoge2	javascript,ruby
3	    hoge3	Java,php
4	    hoge4	python
5	    hoge5	ruby,python,php
```
理由

検索しにくい（検索時にLIKE演算子が必要＆検索漏れしやすい）
データの更新・削除がかなり面倒
文字数制限による、格納上限の発生
インデックス不可のため、パフォーマンス低下
集約クエリ関数（COUNT, SUM, AVGなど）が使えない
バリデーション不可(php,1,ruby,Java,98など)
区切り文字の識別ができない(1,3,1,000　←1000?1と000?)
解決手段

中間テーブルを置く

名前
```
name_id 　　　	name　　　　　　
1	        hoge1
2	        hoge2
3	        hoge3
4	        hoge4
5	        hoge5
```
お気に入り言語
```
lang_id 　　　	name　　　　　　
1	　　　　　　　　　　　　　　　　php
2	　　　　　　　　　　　　　　　　ruby
3	　　　　　　　　　　　　　　　　python
4	　　　　　　　　　　　　　　　　Java
5	　　　　　　　　　　　　　　　　javascript
```
名前_お気に入り言語
```
id 　　　	name_id　　　　　　	lang_id　　　　　　
1	        1        	2
2	        1	        3
3	        2	        2
4	        2	        3
5	        3        	4
...	        ...        	...
```
まとめ
値は結合して格納せずひとつひとつ。列、行に格納した方が良い。
--------------------
記事を読んでくださった方は、是非弊社開発課のXもフォローしてね:relaxed:
毎日エンジニアに向けた情報発信を行っています:raised_hands_tone2:
https://twitter.com/tech_cin
Laravel Sailでサクッと環境構築！

今回は、Laravel Sailを使った環境構築を共有です。

以前にLaravelの環境構築について調べていた際に、発見した方法です！

docker-compose.yml書く手間を省き、手早く開発を始めたい方におすすめです！

Sailを使用するメリットは、開発に必要な環境を簡単に用意することができる点です。内部的にDocker Composeを利用し、Dockerの利用環境があれば簡単に開発環境を用意できます。

例えば、MySQLやComposer、Node.jsなどを、PCに個別にインストールする必要はありません。

その他、開発に便利なツールなどはSailで選択することができます。

まず、下記コマンドでLaravel Sailをインストールします。「laravel-app」という名前のディレクトリに新しいLaravelアプリケーションが作成されます。
```
curl -s "https://laravel.build/laravel-app" | bash
```
※ Laravel Sailは新しいLaravelアプリケーションとともに自動的にインストールされます。

※既存アプリケーションへのSailインストールも可能です。

利用するサービスを個別に指定することもできますが、デフォルトではmysql、redis、meilisearch、mailhog、seleniumのコンテナが作成されます。

コマンドを実行すると途中でパスワードの入力を求められます。
```
Please provide your password so we can make some final adjustments to your application's permissions.

Password:
```
プロジェクトの作成が完了しました！
```
Thank you! We hope you build something incredible. Dive in with: cd laravel-app && ./vendor/bin/sail up
```
Laravel Sailを起動
下記コマンド実行後、Dockerイメージをビルドするので少し待ちます。
```
./vendor/bin/sail up
```
以下のURLにアクセスすると、Laravelの起動画面が表示されます。

http://localhost/

Sailを停止するにはcmd(Ctrl) + Cキーを押します。

バックグラウンドですべてのDockerコンテナを起動できるコマンドもあります。（detachedモード）
```
./vendor/bin/sail up -d
```
すべてのコンテナを停止します。
```
./vendor/bin/sail stop
```
毎回./vendor/bin/と入力が面倒な方は、エイリアスを設定しておきましょう！./vendor/bin/の入力が省けます。
```
alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail
```
Sail環境では、基本的にsailコマンドですべて実行していきます。
```
sail php -v
PHP 8.1.14 (cli) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.14, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.14, Copyright (c), by Zend Technologies
    with Xdebug v3.2.0, Copyright (c) 2002-2022, by Derick Rethans
```
とか
```
sail composer -V
Composer version 2.5.1
```
みたいな感じ。

sail artisanでLaravelのartisanコマンドを実行します。
```
sail artisan -V  
Laravel Framework 9.46.0
```
実際の業務ではプロジェクトの要求に合わせたカスタマイズが必要になるため、Dockerに慣れている人は、自分でdocker-compose.ymlを書いたほうが早い場合もあるかも。。。

しかし、各コンテナに入らなくても、sailコマンドでローカルから様々なコマンドが実行が出来る点はとても便利だと感じました！

あとは個人で開発をする際にサクッと環境構築を終わらせたい方には超おすすめです！

--------------------
記事を読んでくださった方は、是非弊社開発課のXもフォローしてね:relaxed:
毎日エンジニアに向けた情報発信を行っています:raised_hands_tone2:
https://twitter.com/tech_cin