OmniAICreator/Qiita-1.07M huggingface dataset:
【Go】rangefuncでループ終了後にfor文本体を呼び出すとエラーになる

# TL; DR

```go
var f func(string) bool

func capture(yield func(string) bool) {
	f = yield
}

func main() {
	for s := range capture {
		fmt.Println(s)
	}
	f("foo")
}
```

```
panic: runtime error: range function continued iteration after exit
```

# はじめに

Go1.22のexperimentalの機能として、for文の `range` に関数が使用できるようになりました。
イテレータとして値を生成しながらループをする場合などに便利です。

https://go.dev/wiki/RangefuncExperiment

```go:
func main() {
	// 関数が使える！
	for i := range Fact {
		if i > 1000000 {
			break
		}
		fmt.Println(i)
	}
}
```

```
1
2
6
24
120
720
5040
40320
362880
```

```go
func Fact(yield func(int) bool) {
	fact := 1
	i := 1
	for {
		// yieldを呼ぶたびに、引数がイテレーション変数に渡されfor文の本体が実行される
		// breakやreturn等でfor文を抜けた場合、戻り値にfalseが返る
		if !yield(fact) {
			return
		}
		i++
		fact *= i
	}
}
```

# yieldを呼べる条件
ところで、for文本体を `yield` で呼び出せるのであれば、`yield` を保持しておけばループを抜けた後でもfor文の本体を実行できるのではないでしょうか？
...この目論見は冒頭の通り失敗しました。

```go:再掲
var f func(string) bool

func capture(yield func(string) bool) {
	// グローバル変数に代入
	f = yield
}

func main() {
	for s := range capture {
		fmt.Println(s)
	}
	f("foo") // panic: runtime error: range function continued iteration after exit
}
```

エラーメッセージの通り、ループを抜けた後に `yield` を呼ぼうとすると実行時にpanicします。

https://github.com/golang/go/blob/cda1e40b44771f8a01f361672cba721d0f283683/src/cmd/compile/internal/rangefunc/rewrite.go#L146

> To permit checking that an iterator is well-behaved -- that is, that it does not call the loop body again after it has returned false or after the entire loop has exited (it might retain a copy of the body function, or pass it to another goroutine) -- each generated loop has its own #exitK flag that is checked before each iteration, and set both at any early exit and after the iteration completes.
> 
> イテレータが正しくふるまう―言い換えると、イテレータが `false` を返したりループ全体が終了したりした後にはループボディが呼び出されない（イテレータはボディ関数のコピーを保持していたり、別のゴルーチンに渡してしまうかもしれない）―ことをチェックするため、生成された各ループは個別の `#exitK` フラグを持ち、各イテレーションの前にチェックされ、早期終了やイテレーション完了後の両方で設定されます。

内部的に以下のように置き換えられるという記載もありました。

```go:before
for x := range f {
	...
	if ... { break }
	...
}
```

```go:after
{
	var #exit1 bool
	f(func(x T1) bool {
		if #exit1 { runtime.panicrangeexit() }
		...
		if ... { #exit1 = true ; return false }
		...
		return true
	})
	#exit1 = true
}
```

~~というわけで、黒魔術には応用できないようです。悪いことができないようになっていて安心ですね~~
cscの作法 その466

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
Buttonを使わずに、ボタンを実現せよ。

# 方針
- 画像を用意して、マウスクリック取って、マウスの位置で判定する。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ac5bc873-deca-c72e-3888-3d450d7df2bc.png)

# サンプルコード

```

using System;
using System.Drawing;
using System.Windows.Forms;

class Form1: Form {
	public Form1() {
		this.MouseClick += new MouseEventHandler(Form1_MouseClick);
		this.BackColor = SystemColors.Window;
	}
	protected override void OnPaint(PaintEventArgs e) {
		Graphics g = e.Graphics;
		Font fontv = new Font("@MS ゴシック", 20);
		g.DrawString("1", fontv, Brushes.Red, 60, 10);
		g.DrawString("2", fontv, Brushes.Red, 60, 40);
		g.DrawString("3", fontv, Brushes.Red, 60, 70);
		g.DrawString("4", fontv, Brushes.Red, 60, 100);
	}
	void Form1_MouseClick(object sender, MouseEventArgs e) {
		Point pt = e.Location;
		Console.WriteLine(pt.X);
		Console.WriteLine(pt.Y);
		if ((70 - pt.X) * (70 - pt.X) + (30 - pt.Y) * (30 - pt.Y) < 30)
		{
			MessageBox.Show("ok1");
		}
		if ((70 - pt.X) * (70 - pt.X) + (60 - pt.Y) * (60 - pt.Y) < 30)
		{
			MessageBox.Show("ok2");
		}
		if ((70 - pt.X) * (70 - pt.X) + (90 - pt.Y) * (90 - pt.Y) < 30)
		{
			MessageBox.Show("ok3");
		}
		if ((70 - pt.X) * (70 - pt.X) + (120 - pt.Y) * (120 - pt.Y) < 30)
		{
			MessageBox.Show("ok4");
		}
	}
	[STAThread]
	static void Main() {
		Application.EnableVisualStyles();
		Application.Run(new Form1());
	}
}





```


以上。
Python x Uniswap v3で自動注文したい

# 趣旨
DEXを扱う時はJavaScriptの方が遥かに扱いやすいのですが、Pythonでも扱えるといろいろと便利だなと思い、価格取得と注文を出すのだけ簡潔にできる方法を探してみました。

- 間違えてプライベートキーを流出させないように環境変数を利用しています。
- Infuraの活用方法は割愛します。
- EthereumはETHの単位を合わせるのが大変ですね。
- CEXとは違って小さなミスが命取りになりかねないです。
- ロジックなどはなく一通りとりあえず動くものを準備しました。
- 便利そうだったのでUnipyを利用しています。


https://uniswap-python.com/getting-started.html#getting-started

# コード
Pythonが読める方なら、ドキュメント読みながら以下のコードを何度かいじくりまわしながら実行すると数十分で扱えるようになると思います。

```python
from uniswap import Uniswap
from dotenv import dotenv_values
import os
from web3 import Web3

# 環境変数をセットしています。
current_directory = os.path.dirname(os.path.realpath(__file__))
env_path = os.path.join(current_directory, '.env')
config = dotenv_values(env_path)
address = config.get('WALLET_ADDRESS')
private_key = config.get('WALLET_PRIVATE_KEY')

# Uniswapのバージョン変更も以下の数字を変えるだけでできます！超便利。
version = 3
provider = config.get('INFURA_URL')
uniswap = Uniswap(address=address, private_key=private_key, version=version, provider=provider)

# 以下EtherscanやGoogle検索で取ってこれる情報です。
eth = "0x0000000000000000000000000000000000000000"
bat = "0x0D8775F648430679A709E98d2b0Cb6250d2887EF"
dai = "0x6B175474E89094C44Da98b954EedeAC495271d0F"
usdc = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"

# eth_input = uniswap.get_price_input(eth, dai, 10**18) show eth value in dai
# eth = Web3.from_wei(eth_input, 'ether')
# print(uniswap.get_price_output(eth, dai, 1_000 * 10**18)) show dai value in eth

# 以下、WEIの扱いの部分で直感的には分かりづらい数値を扱うので結構だるいです。
# Example conversion for printing ETH balance in Ether instead of Wei
eth_balance_wei = uniswap.get_eth_balance()
eth_balance_eth = Web3.from_wei(eth_balance_wei, 'ether')
print(f"ETH Balance: {eth_balance_eth} ETH")

eth_amount_to_get_1000_dai =  Web3.from_wei(uniswap.get_price_output(eth, dai, 1_000 * 10**18), 'ether')
print(f"ETH amount to get 1000 DAI: {eth_amount_to_get_1000_dai} ETH")

eth_amount_to_get_1000_usdc =  Web3.from_wei(uniswap.get_price_output(eth, usdc, 1_000 * 10**6), 'ether')
print(f"ETH amount to get 1000 USDC: {eth_amount_to_get_1000_usdc} ETH")

# 1 ETHを購入するのにどれくらいのUSDCが必要になるか計算しています。
eth_amount_in_wei = 1 * 10**18
# Get the USDC amount required to buy 1 ETH, in USDC's smallest unit
usdc_amount = uniswap.get_price_input(eth, usdc, eth_amount_in_wei)
# Since USDC uses 6 decimal places, we don't need to convert it from wei to ether
print(f"USDC amount to get 1 ETH: {usdc_amount / 1e6} USDC")

# ETHをWEIにWEIをETHに変えています。
ether_amount = 1
wei_amount = Web3.to_wei(ether_amount, 'ether')
print(f"{ether_amount} ETH is {wei_amount} Wei")
wei_amount = 1000000000000000000  # 1e18
ether_amount = Web3.from_wei(wei_amount, 'ether')
print(f"{wei_amount} Wei is {ether_amount} ETH")

# 適当なメイン関数を置いてIF分で条件分岐させてみました。資金をいれていないウォレットだったので毎回エラーで返ってきました。
def main():
    if eth_amount_to_get_1000_usdc < 0.2:
        order = uniswap.make_trade(eth, usdc, 1*10**18, fee=500)
        print(order)
    elif usdc_amount / 1e6 > 3000:
        order = uniswap.make_trade_output(eth, bat, 3000*10**18)  # buy ETH for 3000 USDC
        print(order)
    else:
        print('nothing happened')

if __name__ == '__main__':
    main()
```
cscの作法 その465

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
式を評価して、グラフ化せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5a0e4215-d8c6-f3cb-a665-4b81e4c29e76.png)


# サンプルコード

```
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Windows.Forms.DataVisualization.Charting;
using ClosedXML.Excel;
using System.Data;

namespace App
{
	public partial class Form1: Form {
		public Form1() {
			this.Size = new Size(600, 400);
			this.Text = "sin";
			Chart chart1 = new Chart();
			chart1.ChartAreas.Clear();
			chart1.Series.Clear();
			chart1.Legends.Clear();
			chart1.Dock = DockStyle.Fill;
			chart1.ChartAreas.Add(new ChartArea());
			ChartArea chartArea = chart1.ChartAreas[0];
			chartArea.AxisX.IsMarginVisible = false;
			chartArea.AxisY.IsMarginVisible = false;
			chartArea.CursorX.IsUserSelectionEnabled = true;
			chartArea.CursorY.IsUserSelectionEnabled = true;
			chartArea.CursorX.Interval = 0;
			chartArea.CursorY.Interval = 0;
			chartArea.InnerPlotPosition.Auto = false;
			chartArea.InnerPlotPosition.X = 8.0f;
			chartArea.InnerPlotPosition.Y = 4.0f;
			chartArea.InnerPlotPosition.Width = 84.0f;
			chartArea.InnerPlotPosition.Height = 84.0f;
			this.Controls.Add(chart1);
			Series series = new Series {
				Color = Color.Blue,
				MarkerColor = Color.Blue,
				MarkerSize = 7,
				MarkerStyle = MarkerStyle.Circle,
				ChartType = SeriesChartType.Line
			};
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Formulas");
			for (double i = 0; i < 720; i++)
			{
				string formula = string.Format("SIN({0} / 360 * PI() * 2)", i);
				ws.Cell(1, 1).FormulaA1 = formula;
				var v = ws.Cell(1, 1).Value;
				series.Points.AddXY(i, v);
			}
			chart1.Series.Add(series);
		}
		static void Main() {
			Application.Run(new Form1());
		}
	}
}


```

以上。
[obnize]警告Update obniz.js 3.0.0 or higher to controlが出た

obnizeのプログラムをいじっていると、次のような警告がでた。

Warning: Update obniz.js 3.0.0 or higher to control obnizOS 3.4.5. see https://obniz.com/doc/cloud_device/ota
![スクリーンシ-05 081054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/a91c5882-23b5-ca6a-3a55-23de9319b47e.png)

obniz.jsのバージョンが古いため、現時点(2024年3月)のSDKの最新に差し替えると解消する。
https://github.com/obniz/obniz/releases

例：
script src="https://unpkg.com/obniz@3.x/obniz.js"></script>
　※先頭の<を省略※

 以上。
cscの作法 その464

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
式を評価して、計算結果を求めよ。
式は、SIN(90 / 360 * PI() * 2)です。

# 方針
- ClosedXMLを使う。

# サンプルコード

```
using ClosedXML.Excel;
using System.Data;
using System;

namespace App
{
	class test0 {
		static void Main() {
			string formula = "SIN(90 / 360 * PI() * 2)";
			var wb = new XLWorkbook();
			var ws = wb.Worksheets.Add("Formulas");
			ws.Cell(1, 1).FormulaA1 = formula;
			var v = ws.Cell(1, 1).Value;
			Console.WriteLine(formula);
			Console.WriteLine(v);
		}
	}
}

```

# 実行結果

```

SIN(90 / 360 * PI() * 2)
1

```

以上。
cscの作法 その463

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
Chartで、sin波を表示せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e3db6e97-50cd-b337-6617-ebb6d77b9b3f.png)

# サンプルコード

```

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Windows.Forms.DataVisualization.Charting;

namespace App
{
	public partial class Form1: Form {
		public Form1() {
			this.Size = new Size(600, 400);
			this.Text = "sin";
			Chart chart1 = new Chart();
			chart1.ChartAreas.Clear();
			chart1.Series.Clear();
			chart1.Legends.Clear();
			chart1.Dock = DockStyle.Fill;
			chart1.ChartAreas.Add(new ChartArea());
			ChartArea chartArea = chart1.ChartAreas[0];
			chartArea.AxisX.IsMarginVisible = false;
			chartArea.AxisY.IsMarginVisible = false;
			chartArea.CursorX.IsUserSelectionEnabled = true;
			chartArea.CursorY.IsUserSelectionEnabled = true;
			chartArea.CursorX.Interval = 0;
			chartArea.CursorY.Interval = 0;
			chartArea.InnerPlotPosition.Auto = false;
			chartArea.InnerPlotPosition.X = 8.0f;
			chartArea.InnerPlotPosition.Y = 4.0f;
			chartArea.InnerPlotPosition.Width = 84.0f;
			chartArea.InnerPlotPosition.Height = 84.0f;
			this.Controls.Add(chart1);
			Series series = new Series {
				Color = Color.Blue,
				MarkerColor = Color.Blue,
				MarkerSize = 7,
				MarkerStyle = MarkerStyle.Circle,
				ChartType = SeriesChartType.Line
			};
			for (double i = 0; i < 720; i++)
			{
				double v = Math.Sin(i / 360 * 3.14 * 2);
				series.Points.AddXY(i, v);
			}
			chart1.Series.Add(series);
		}
		static void Main() {
			Application.Run(new Form1());
		}
	}
}





```

以上。
JavaScriptのJSONでDateを扱う

# 困ったこと
さて、困りました。
`JavaScript`でデータを保存しようとしたらDate型がデータに入っていると
そのままパースできませんでした。
つまり、
```javascript
let saveData = {
  loginDate: new Date(),
  name: "taro",
};

let json = JSON.stringify(saveData);

// データを取り出したい
let parsedData = JSON.parse(json);
// loginDateが何日か知りたい
console.log(parsedData.loginDate.getDate());
```
これで最後のconsole.logでloginDateが何日かを知ることができる！と思ったら実際には
```shell
Error: parsedData.loginDate.getDate is not a function
```
というエラーが...
今回はこれを解決したいです。

# 解決方法
JSON.parseの第2引数(reviver)を利用してパースします。
上の例ではJSON.parse以降を以下のようにします。
```javascript
// データを取り出したい
let parsedData = JSON.parse(json, (key, value) => {
  if (key === "loginDate") {
    // parseは数値表現にするだけなのでDateコンストラクタに渡す
    return new Date(Date.parse(value));
  }
  return value;
});
// loginDateが何日か知りたい
console.log(parsedData.loginDate.getDate());
```
これで無事console.logで日付が表示されるようになります。

# そもそも何が起こったのか
そもそも、なぜJSON.stringifyで生成しただけの文字列をJSON.parseでパースできなかったのでしょう？
これは
- ~~JSONには日付を表すデータ型が存在しない~~ 
-> [Date.toJSON](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON) の存在によりISO文字列表現にされる (2024/03/05修正 @juner さんありがとうございます)
- JavaScriptには型の概念がない

という2つが組み合わさった結果発生します。
つまり
1. JSON.parseでDateオブジェクトが日付の文字列として出力される
1. JavaScriptには型の概念がないのでそのまま文字列としてパースされる
1. 文字列なのでDateに存在している関数等が使えない

ということでエラーが発生してしまうのでした。
知っていればなんてことはないですが、稀に忘れて引っかかるので
そのたびにこれを思い出します...

# まとめ
JavaScriptでDateをJSONにする時はパース処理に気を付ける！
GooglePlayConsole｜クローズドテストは審査後に開始出来る

# クローズドテストの開始タイミングについて
GooglePlay のクローズドテストを申請する際、審査が行われます。クローズドテストの申請を行うと、GooglePlay運営チームによってアプリが審査され、適切かどうかの確認がされます。審査に通過すると、クローズドテストを開始出来る準備が整います。審査には数日から数週間かかる場合があります。

## クローズドテスト開始の流れ
以下の手順でクローズドテストを申請し、実施することができます。

1. Google Play 上でクローズドテストの申請を行います。
1. Google 運営側がアプリを審査します。
1. 審査が通過した場合、クローズドテストを開始することが可能になります。
1. テストを行うテスターに、アプリへの参加を依頼します。

## クローズドテストは、20名以上のテスターが必要
クローズドテストは、20人以上のテスターが14日以上連続でオプトインする必要があります。
Datadog Agentを使ってローカル環境でDatadog APMにトレースを送信する

Datadog APMを使ったTraceの改善を実装していたのですが、ローカルで動作確認したくなったので試してみたらいけました。その手順をまとめます。

# 1. Datadogアカウントに登録
多くの場合、会社のDatadog アカウントがあると思うのでこの手順はスキップで良さそうです。
以下のリンクの「無料で始める」ボタンから登録できます。
14日間無料です。

https://www.datadoghq.com/ja/

# 2. (Optional) APIキーの発行
初回登録時にAPIキーは自動で発行されたきがしますが、もしなければ発行してください。
Organization Setting > API Keysからできます。

![スクリーンショット 2024-03-05 7.36.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/65dba8be-400f-e622-a1b4-e01a973c19b1.png)


# 3. Datadog Agentのインストール
初回登録時にDatadog Agentのインストール画面に遷移します。
もし忘れていた場合は、Datadog管理画面のIntegration > Agentからインストールできます。

![スクリーンショット 2024-03-05 7.34.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/7c1c5b07-e9de-a429-30b9-3f486e366416.png)

# 4. Datadog Agentの設定
Datadog Agentのインストールが完了すると、メニューバーに骨のアイコンが追加されると思います。
「Open In Web UI」を押すとDatadog Agentの設定画面にアクセスできるので、Settingから
Datadog Agentの設定ファイルを編集しましょう。

![スクリーンショット 2024-03-05 7.40.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/a300710e-6466-8272-6ec6-a6f2072d248f.png)

![スクリーンショット 2024-03-05 7.40.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/1538bdab-3d6c-9f1f-2959-1f00ce5ce002.png)


```yaml
api_key: 

site: 
logs_enabled: true

apm_config:
  enabled: true
  env: local
```

手元ではこの辺りの値を入れました。api_keyとsiteはインストール時点で入力されていると思います。

# 5. アプリケーション側でDatadog Agentにトレースを流す
railsであればddtraceのinitializerとかで設定していると思います。

```ruby
Datadog.configure do |c|
 c.agent.host = 'your host'
 c.agent.port = 8126
 c.service = "rails"
 c.env = "local"
 c.tracing.instrument :rails, service: "rails"
end
```

c.agentでagentの設定、e.envでDatadog Agentのenvを入れます。
`c.agent.host`はDatadog Agentの設定画面の右上に記載があります。
`c.agent.port`は特に弄らなければ8126になっていると思います。

# 6. アプリケーションを立ち上げて、動かす
しばらくするとTraceが流れてきます。

![スクリーンショット 2024-03-05 7.44.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/31920e57-b834-57a1-401d-7feb32c1105e.png)

わーい

# どういう時に役立つの？
ddtraceを使ってカスタムスパンを実装しようとしていたのですが、スパンがどうやって表示されるのかいちいちデプロイしなくても確認できるのがグッドですね〜。これで開発工数が半分以下になると思います・・・

少しでもお役に立てば幸いですmm
品質マネジメント・品質管理・品質保証

## 品質マネジメントとは
品質に関する「組織を指導し、管理するための調整された活動」（ISO 9000:2015）
顧客の要求事項を満たすことおよび顧客の期待を超える努力をすること（ISO 9000:2015）
以下の活動が含まれる。
- 品質方針及び品質目標の設定
- 品質計画
- 品質保証
- 品質管理
- 品質改善

## 当たり前品質・魅力的品質
当たり前品質・・・充足されれば「当たり前」、不十分なら「不満」
魅力的品質・・・充足されれば「それいいね」、不十分なら「仕方ない」

## 品質マネジメント・品質管理・品質保証

- 品質マネジメント・・・全体を包括する用語
- 品質管理・・・品質要求事項を満足させること
- 品質保証・・・品質を保証する対象が「顧客から求められている品質を満足する」という確信を顧客自身に与えること→本当に顧客のためになっているか


## 参考文献
[ソフトウェア品質体系ガイド（第３版）](https://www.ohmsha.co.jp/book/9784274226311/)
[ソフトウェア品質保証の基本](https://www.juse-p.co.jp/products/view/644)
Pythonのキーボード入力でMac環境でおきるトラブル

# 概要
　Mac環境でKeyboardライブラリが使いにくいという話です。回避策はあるものの、やや使いにくいです。

# キーボード入力

Pythonでキーボード入力をしようとする場合、2つの手法が見つかる。
①input関数を使う
②keyboardライブラリを使う

①は２文字以上の文字とか数字を扱う。エンターキーで確定するまで、入力を受け付ける。②はデバイスとしてのキーボードを扱う。

この投稿では②を扱う。


# keyboardライブラリのインストール
ターミナルからコマンドでインストールする。
```
pip install keyboard
pip show keyboard
```
```
Version: 0.13.5
```

# プログラム例

よくあるコードは、こんな感じです。
また、保存するファイル名を```keyboard.py```にすると、エラーになります。
注意しなければ。
```py:python
import keyboard

while True:
    if keyboard.is_pressed("shift"):
        print("shift")
        break
```
しかし、通常のMac環境ではエラー13になると思います。
２つ理由があり、１つは```ターミナルにアクセス許可が与えられていない```ことです。これに関しては、Macがアクセス権を与える環境設定へ誘導してくれるので、さほど困ったことではないです。
　もう１つはMacのセキュリティ（パスワードを盗むアプリ対策）によって、キーボードへのアクセスが制限されることです。とても不便です。これを回避するには、```sudo```実行する必要がありますが、コマンド操作に慣れていないと、わからない人が多いと思います。一回、コマンドを入れてしまえば、上カーソルキーで履歴を辿れるので、多少はいいのですが。
　また、sudo実行する際には、rootのパスワードを求められますが、普段のアカウントのパスワードと同じじゃないかなと思います。毎回入力する必要はないですが、１０分ぐらい経過すると、またパスワードを聞いてくるので、面倒です。

うまく、実行できた場合、右のshiftキーを押すと、shiftと出力して終了します。左shiftは反応しません。
```shift```の他に
```enter```や
```escape```が使えます。





# 回避策① sudo python3 xxxx.py
先の２つ目について、説明です。
管理者権限(root)で　都度Pythonを実行することが必要で、ターミナルから実行する必要があります。
前提として、cdやpwd、lsなどのコマンドで、フォルダの移動ができる必要があるでしょう。
```
sudo python3 myKeyboard.py
```

良くないことに、プログラム終了時に、入力したキーが、一気に入力されます。shiftキーは影響ないですが、enterキーの場合、１行改行されます。良くない仕様です。

プログラムを終了するには、Command+cもしくは、Command+zを押します。

# 回避策② sudo VS Code
Visual Studio Codeをsudo(root権限)で実行すれば、pythonもroot権限で動きました。起動時に、シェルの環境設定ファイルが見つからないという、エラーが出ますが、そのままpythonは動きました。
Visual Studio Code内のターミナルタブで、入力結果がわかります。デバッグの停止で、終了後、入力していたキーが一度に表示される問題は残っています。

Finderからはアプリの内容の表示はできるものの、windowsのような管理者実行はできません。ターミナルでコマンド打つしかないです。私の環境では、隠されている実行ファイルは、以下の場所にありました。
VS Codeのバージョン: 1.87.0 (Universal)です。
```
sudo /Applications/Visual\ Studio\ Code.app/Contents/MacOS/Electron
```
https://stackoverflow.com/questions/34861791/how-can-i-run-vscode-with-sudo-on-osx


# hotkey使うコード
ctrl+cのような処理に対応できるようです。
以下の例では、関数を登録して、enterかshiftを押して呼び出すプログラムです。
が、escapeは使えませんでした。```^[```と出ます。

```py:python
import keyboard

def hoge1():
    print("ok1")
def hoge2():
    print("ok2")

keyboard.add_hotkey('enter',hoge1)
keyboard.add_hotkey('shift',hoge2)
keyboard.wait()
```


# 参考

sudoで回避

https://stackoverflow.com/questions/46108365/keyboard-listener-for-mac-using-python

https://stackoverflow.com/questions/52940429/unable-to-run-keyboard-is-pressed-on-mac

https://stackoverflow.com/questions/34861791/how-can-i-run-vscode-with-sudo-on-osx

本投稿と同じような状況の投稿
ゲームライブラリPySDL2も試しているようだ。

https://www.tohuandkonsome.site/entry/2017/05/22/002531
RESTについてまとめてみた

この記事はプログラミング初学者が学習した内容を自分なりにまとめた記事です。

# REST APIとは
RESTfulなAPIを意味する。

### APIとは Application Programming Interface
あるサービスをサービス提供者以外の人が自分が制作するサービスの一環として使用できるようにした仕組み(インターフェース)のこと。本来であれば必要なプログラムを組む必要があるが、APIを利用することでプログラムを組まずに機能を利用することができる。

### WebAPIとは
一般的なAPIの場合、APIを利用するにはAPI提供者が用意しているインターフェースを利用して機能を使う。例：Windows API など
WebAPIでは、HTTP/HTTPS通信を使って必要な機能を取り込むことができる。
昨今ではAPIというとWebAPIを指していることが多い。

### RESTfulとは
REST(設計ルール)でもとめられる原則に従っていることを意味する。

REST6原則
#### 1,クライアント/サーバー
クライアントからリクエストしてサーバーからレスポンス
画面(UI)とデータで関心事を分離
クライアンド側がトリガー、サーバー側は受け身の姿勢

#### 2,ステートレス
前の状態を保存しないでそれぞれの会話が独立して成立
サーバーは一つのリクエストだけで内容を理解できる
サーバーに保存されたリクエストは使わない(サーバーセッションは使わない)。
必要な情報はクライアント上に保存される(リクエストに含める)。

メリット：単一のリクエスト以外見る必要がないので、監視が容易
障害発生した一つのリクエストだけを回復すれば良いので、障害復旧が容易
リクエスト全体でサーバーリソースを共有する必要がないので、スケールが容易

デメリット：単一のリクエストで完結させるため、リクエストデータに重複がある
アプリを複数のバージョン同時提供し、状態をクライアントに置いておくとアプリ制御が複雑

参考
ステートフル：前の状態を保存。前のやりとりと次のやりとりが関連している。


#### 3,キャッシュ制御
クライアント側でレスポンスをキャッシュできるようにする
レスポンスは明示的または暗黙的にキャッシュ可能
キャッシュを適切に行う事でクライアント/サーバー間の通信が排除され、ユーザー体験の向上、リソース効率の向上、拡張性の向上が見込める
キャッシュを適切に行えば、必要な情報だけリクエストすればよくなる

メリット：ユーザー体験の向上(レスポンスが早いので)、サーバーの負荷軽減
デメリット：古いデータを使用してしまうとシステムに対する信頼性の低下につながる


#### 4,統一インターフェース
４つの制約で成り立つ
①リソースの識別
リソースは名前が付けられるあらゆるもの、サーバー側にあるデータ
URIを用いてサーバーに保存されたデータを識別する
名前が付けられるあらゆるものがリソース
例；ドキュメント、画像、人、情報、サービス、状態
※抽象的な定義も含む
4/1の天気、最新(今日の天気)
また、URIはリソースを識別するものであり、 動詞は含まない

②表現を用いたリソース操作
表現とはリソース(サーバーに保持されたデータ)のとある断面を表す。
例：クライアントへ返されるレスポンスやサーバーへPOSTするデータを表現という

断面情報を利用してサーバー上のデータを操作することが表現を用いたリソース操作となる。
クライアントからサーバーへ編集リクエストをする際、認証情報などの追加情報を付与するようなメタデータも表現を用いたリソース操作では含めて考える。

③自己記述メッセージ
自己記述とはデータ自身がデータの中身を説明している
メッセージとはサーバーへリクエストするデータやクライアントへレスポンスするデータを言う
メッセージ内容が何であるか、ヘッダーに記述されていることが自己記述メッセージを意味する。
例：レスポンスに含まれるメタ情報(ヘッダー情報)で内容がどのようなものか分かる

④アプリケーション状態エンジンとしてのハイパーメディア(HATEOS)
レスポンスに現在の状態を踏まえて関連するハイパーリンクが含まれている
例：検索結果ページにおける「次のページ」

統一インターフェースに関するメリット、デメリット
メリット：システムアーキテクチャ全体が簡素化されて分かりやすくなる。提供するサービスに集中でき、独自の進化ができる。インターフェース(取り決め)が決まっていれば、異なるブラウザでも同じような画面を表示できる。
デメリット：標準化によって効率が犠牲になる

冗長ではあるが、標準化することで理解しやすい構成をとっているのが統一インターフェース


#### ５、階層化システム
Web AP DB のようにシステムをいくつかの階層に分離する考え方
各サーバーをコンポーネントと呼ぶ

メリット：各システムに役割を決めて独立させることで進化と再利用がで促進できる
デメリット：データ処理にシステムなどへ負荷がかかったりするオーバーヘッドが発生する。ユーザーから見ると応答が悪く見える。キャッシュを利用すると改善が見込める


#### ６、コードオンデマンド
クライアント側でコードをダウンロードして実行できる
サービスをリリースした後にクライアントのコードを変更できる
サーバー側を変更すればクライアントに反映される
メリット：リリース済みのクライアントに対してサーバー主導で機能追加できる
         サーバー側の負荷が下がる(クライアント側に処理を移譲できるため)
デメリット：評価環境が複雑になる(多数のブラウザなど...) safari, chrome, IEなど


CRUD操作のURI, HTTPメソッドの関連表とサンプルURI
|URIの例|操作   |HTTTP method |意味|
|:--|:---  |:----------- |:---|
|https://www.sample.com/users      |Read  |  GET        |読込み(一覧)|
|https://www.sample.com/users      |Create|  POST,PUT   |作成|
|https://www.sample.com/users/12345|Read  |  GET        |読込み(個別)|
|https://www.sample.com/users/12345|Update|  PUT        |更新|
|https://www.sample.com/users/12345|Delete|  DELETE     |削除|
別マシンの Ollama へのアクセス

Ollama は各種 LLM をローカルで手軽に動かせます。HTTP サーバーとして実装されているため、LLM を専用マシンに分離することも簡単です。

https://ollama.com/

デフォルトでは `127.0.0.1:11434` で待ち受けされるため、ローカルからのアクセスに制限されます。

:::note info
`11434` は **llAMA** (LLAMA) ということのようです。
:::

:::note warn
WSL2 はホストとは別の IP アドレスを持っているため、Windows 側の Ollama に WSL2 から `127.0.0.1:11434` でアクセスすることはできません。
:::

外部からのアクセスを許可するには環境変数 `OLLAMA_HOST` と `OLLAMA_ORIGINS` を設定します。👉[FAQ](https://github.com/ollama/ollama/blob/main/docs/faq.md)

```text:設定例
OLLAMA_HOST=0.0.0.0
OLLAMA_ORIGINS=192.168.0.*
```

※ `127.0.0.1` と `0.0.0.0` の違いについては以下の記事が参考になります。

https://qiita.com/amuyikam/items/0063df223aed40193ba9

# クライアント

`OLLAMA_HOST` はサーバーだけでなく、クライアントにも影響します。

`OLLAMA_HOST` が設定されていない、または自ホストが指定されている場合、`ollama` コマンドを実行すると、サーバーが起動していなければ自動的に起動します。一方、他のホストが設定されている場合は、指定されたホストに接続しようとしますが、起動していなければ失敗します。

# ライブラリ

Python からアクセスするための公式ライブラリがあります。

https://github.com/ollama/ollama-python

`OLLAMA_HOST` が設定されていれば、自動的にそちらに接続します。

```py
import ollama
ollama.generate(model="gemma2:2b", prompt="Who are you?")
```

# LangChain

汎用的な LLM ライブラリである LangChain でも Ollama はサポートされています。

https://python.langchain.com/docs/integrations/llms/ollama

ただし LangChain では OLLAMA_HOST は参照されないため、別マシンにアクセスするには `base_url` を指定する必要があります。

```python:例
from langchain_community.llms import Ollama
llm = Ollama(base_url="http://192.168.0.11:11434", model="gemma2:2b")
llm.invoke("Who are you?")
```

# 参考

ローカル LLM の構築は手間が掛かりそうなので敬遠していましたが、Ollama はあっさり動きました。型落ちのノート PC (Core i5-3320M) でも、`gemma:2b` は 5tps くらいは出るので驚きました（`gemma2:2b` も同程度）。Ollama と Gemma の組み合わせは私にとって画期的でした。

https://www.youtube.com/watch?v=6oGbsAg8x5E

https://zenn.dev/seya/articles/03399b9e3d465e
2024/3/5主にITとかセキュリティの記事

Ivanti Avalancheにおける任意ファイルアップロード関連の脆弱性「CVE-2023-46263」について(3/4)
https://www.trendmicro.com/ja_jp/research/24/c/cve-2023-46263-ivanti-avalanche-arbitrary-file-upload-vulnerability.html

「生成AIとセキュリティリスクの深刻な関係とは？」に関するコラム公開およびテレビ番組への監修、協力を実施(3/3)
https://japan.cnet.com/release/30949368/?ref=rss

ギットハブに流出、中国企業I-Soon（安洵）機密文書から分かった中国ハッキングの実態(3/3)
https://www.newsweekjapan.jp/stories/world/2024/03/post-103816.php

ランサムウェア攻撃と誘拐事件を比較、法執行機関の対策は有効か(3/3)
https://news.mynavi.jp/techplus/article/20240303-2895513/

＜主張＞ハッカー組織摘発　国際連携強め「脅威」叩け　社説(3/3)
https://www.iza.ne.jp/article/20240303-JJAMGIEP3ZMS3AGR3ORBCHDZFI/

イランの脅威アクター、航空宇宙や防衛産業を狙ってサイバー攻撃(3/3)
https://news.mynavi.jp/techplus/article/20240303-2895522/

クラウドセキュリティの統合によるサイロ化からの脱却(3/1)
https://www.trendmicro.com/ja_jp/research/24/c/unify-cloud-security.html

スパイ手口まさかの暴露合戦　欧米中露、「ハニトラ」事例も　専門家「日本、学ぶ点ある」(3/3)
https://www.sankei.com/article/20240303-5UEMPYXL5BC7HGSJCG7OXXHU4M/?outputType=theme_weekly-fuji

GMO系の「名将」、サイバー防衛へ正義のハッカー指揮(3/3)
https://www.nikkei.com/article/DGXZQOUC165SD0W4A210C2000000/

適格性評価制度、導入へ。リスクに配慮した透明な運用に期待する(3/1)
https://the-owner.jp/archives/20463

おすすめのリスキリング分野　企業ニーズの高いスキルとキャリアパス事例を紹介(3/1)
https://reskill.nikkei.com/article/DGXZQOLM19A0X0Z10C24A2000000/

「携帯がハッキングされ損害出ている」などと電話　50代男性が1979万円詐欺被害　家族に相談して発覚(3/3)
https://news.yahoo.co.jp/articles/985cd7d94d28bc9396ba2a9853055fdc853e4d2a?source=rss

顧客と仲介業者がグルになって数千万円を要求...頻発する「新手の詐欺」で不動産会社が上げる悲鳴(3/3)
https://news.yahoo.co.jp/articles/ea4c1c16a918e844ea510a5a1e8c581f06d9f838?source=rss

「Elixir実践入門」の所感（第7章〜第11章まで）(3/3)
https://qiita.com/MzRyuKa/items/90f200aa1d43eb3e3278

生成AI登場でプログラマーは「大量失業」時代へ…それでも生き残れる“たった2種類”のプログラマーとは【立教大学ビジネススクール教授が解説】(3/3)
https://news.infoseek.co.jp/article/goldonline_58353/?tpgnr=it

【ソフトウェア設計】簡潔さは力なり？　予測可能な振る舞いと簡潔さについて(3/2)
https://zenn.dev/koduki/articles/51e94bb1f33aec

「宇宙演習」日本も参加へ
NATOなど実施、対ロ念頭　衛星・サイバー攻撃に備え(3/3)
https://www.nikkei.com/article/DGKKZO78936320S4A300C2EA3000/

【舛添直言】マクロン大統領、ウクライナへの地上軍派遣に言及、戦闘激化は必至(3/3)
https://news.yahoo.co.jp/articles/e039f4341a0464daf7d59e66665286c43ca5c816?source=rss

総務省と経産省が「一心同体で」作成した、AI事業者ガイドライン案3つのポイント(3/4)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/08966/

KDDIとトヨタが「モビリティーの安全・安心」、実現可能性を重視した3つの施策(3/4)
https://xtech.nikkei.com/atcl/nxt/column/18/00086/00298/

トヨタは供給網でSBOMフォーマットを統一、ルネサスはセキュリティー管理に工夫(3/4)
https://xtech.nikkei.com/atcl/nxt/column/18/02758/022600003/

能登半島地震　防災DXの理想と現実(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/022800169/

デジタルサービス法（DSA：Digital Services Act）(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/022800163/

若者はSIerの意味が分からない　ITベンダーがご用聞きに堕した訳(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/022900160/

アドレスとテーブルの働きを知る(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/121800181/021600003/

暗号化
第三者が解読できないデータに変換する技術(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/091900172/021600006/

公衆無線LANで仕事をしても大丈夫？(3/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800014/021600079/
自己紹介

# 経歴
**<2018年4月〜2023年9月(約5年半)>**
人材サービスの営業

営業の仕事をする中で、様々なシステムに触れる
(派遣管理システム、勤怠管理システム、CRM、SFAなど)
→Webサービスを作る技術者の仕事に憧れるようになり、転職

**<2023年10月〜現在>**
人材会社でモバイルエンジニア(iOS)
人材サービスの営業員向けのスマホアプリの開発・保守・運用を担当

**・担当しているスマホアプリ採用技術**
フロント Reactnative
バック Java
DB Oracle

**・今直近でやっていること**
下記2点を実施
1.保守・運用業務
└業務を行いながら、担当しているスマホアプリの概要を把握していく
2.学習
└IT基礎知識を固める為に「ITパスポート」「情報セキュリティマネジメント」「基本情報技術者」の学習・資格取得
└基本的なWebアプリ開発の知識をつけるために、XAMPPを使って個人開発
└ReactNative・Java・MySQLを使った個人開発

# 興味のある分野
・ReactNativeを使ったiOSアプリ開発
Railsでの`Unpermitted parameters`警告: 対処法と無視してもよい場合

Railsアプリケーション開発中にはしばしば`Unpermitted parameters`の警告に遭遇します。この警告は、ストロングパラメータによって許可されていないパラメータがリクエストに含まれていることを意味します。この記事では、この警告をどのように扱えばよいのか、そしていつ無視しても安全なのかについて説明します。

## `Unpermitted parameters`とは？

Railsでは、コントローラに送られてくるパラメータを管理するためにストロングパラメータが導入されています。これにより、不正なパラメータによるマスアサインメント脆弱性を防ぐことができます。`Unpermitted parameters`の警告は、ストロングパラメータによって明示的に許可されていないパラメータがリクエストに含まれている場合に出されます。

## 警告が出る原因

- フロントエンドから予期しないパラメータが送信されている。
- コントローラのストロングパラメータの設定が不足している、または誤っている。

## 警告を解消する方法

1. **パラメータを正しく許可する**: 必要なパラメータが警告として出ている場合は、ストロングパラメータの設定を見直して、適切に許可するようにしましょう。

2. **不要なパラメータを削除する**: フロントエンドから送信されるが、実際には使用しないパラメータがある場合は、フロントエンドのコードを修正して送信しないようにしましょう。

## 警告を無視してもよい場合

- データの保存や更新処理に影響を与えない追加のパラメータが含まれている場合。
- アプリケーションのセキュリティポリシーに基づき、特定のパラメータを意図的に無視する場合。


## `Unpermitted parameters`を無視しても良い例

以下の`update`アクションでは、スタッフが提供するサービスの情報（`service_ids`、`service_fees`、`service_durations`）を更新しています。

```ruby
def update
  if current_staff || (current_company && @staff.company_id == current_company.id)
    params[:staff][:service_ids].each do |service_id|
      service = Service.find(service_id)
      fee = params[:staff][:service_fees][service_id].presence || service.default_fee
      duration = params[:staff][:service_durations][service_id].presence || service.default_duration
      @staff.update_or_create_available_service(service_id: service_id, fee: fee, duration: duration)
    end
    if @staff.update(staff_params)
      redirect_to staff_path(@staff), notice: 'スタッフの情報が正常に更新されました。'
    else
      render :edit
    end
  else
    redirect_to root_path, alert: 'アクセス権限がありません。'
  end
end
```
```ruby
class Staff < ApplicationRecord
  # AvailableServiceの更新または作成
  def update_or_create_available_service(service_id:, fee:, duration:)
    available_service = self.available_services.find_or_initialize_by(service_id: service_id)
    available_service.fee = fee
    available_service.duration = duration
    available_service.save
  end
end
```

このケースでは、`service_fees`と`service_durations`は`Staff`モデルの直接の属性ではありません。これらは、`AvailableService`モデルを介して関連するサービスの料金や期間を更新するために使用されます。そのため、これらのパラメータは`Staff`モデルの更新処理には直接関与しません。

この場合、`Unpermitted parameters`の警告が表示されるかもしれませんが、それは`staff_params`メソッドでこれらのパラメータが許可されていないためです。しかし、実際にはこれらのパラメータが適切に処理され、関連する`AvailableService`レコードが更新されています。

## 警告を無視する理由

この例では、`service_fees`と`service_durations`パラメータは特定のビジネスロジックに基づいて処理されており、これらの値が`Staff`モデルに無関係であるため、`Unpermitted parameters`の警告を無視しても問題ありません。重要なのは、アプリケーションのセキュリティを損なわず、意図した通りにデータが処理されているかどうかです。

このようなケースでは、警告を無視する前に、以下の点を確認してください。

- 警告されているパラメータが意図した処理に正しく使用されているか。
- これらのパラメータがアプリケーションのセキュリティに影響を与えないか。

## ベストプラクティス

- **セキュリティを優先する**: 不要なパラメータが含まれている場合でも、それによってアプリケーションのセキュリティに問題が生じないように注意しましょう。
- **警告の原因を理解する**: `Unpermitted parameters`の警告が出る原因を理解し、必要に応じてアプリケーションのコードを修正することが重要です。
- **ドキュメントを参照する**:RailsガイドやAPIドキュメントを参照して、ストロングパラメータの正しい使い方を確認しましょう。

## 結論
`Unpermitted parameters`の警告は開発中に有用な情報を提供しますが、すべての警告が直ちに対処すべき問題を示しているわけではありません。警告の内容を理解し、アプリケーションのコンテキストに基づいて適切に判断することが重要です。
【Ruby】問題集解答 Part2（paizaラーニング）

# 3つのデータの入力 (paizaランク D 相当)
https://paiza.jp/works/mondai/stdin/stdin_3

### 自分の解答
(思いつかなかった）

### ChatGPTの解答
以下は、標準入力から3つの文字列を受け取り、それらを順に3行で出力するRubyのコードです。

```ruby:ruby
# 3つの文字列を標準入力から受け取る
input = gets.chomp.split

# それぞれの文字列を順に3行で出力する
puts input[0]
puts input[1]
puts input[2]
```

このコードは、標準入力から1行を受け取り、それを半角スペースで分割して配列に格納します。そして、その配列の要素を順に3行で出力します。
Oracle Cloud(OCI)の仮想マシンをシングルスレッドで作成してみた

# はじめに
Oracle CloudではCPUの単位として[OCPU(≒物理コア)が割り当てられデフォルトはマルチスレッド](https://speakerdeck.com/mmarukaw/oci-ke-jin-nimatuwaruetosetora?slide=9)となっています。2月のアップデートでSMT(同時マルチスレッディング)を無効化する機能がオプションで追加されたためこちらをオンにしてシングルスレッドの仮想マシンを作成していきます。


# 目次
1.[作成の実施](https://qiita.com/ogacloud/items/cacd9e2b20c2012fbb2e#1%E4%BD%9C%E6%88%90%E3%81%AE%E5%AE%9F%E6%96%BD)
2.[参考ドキュメント](https://qiita.com/ogacloud/items/cacd9e2b20c2012fbb2e#2%E5%8F%82%E8%80%83%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88)

# 1.作成の実施
まずはOCIにログインし左上のメニューバーより[コンピュート]→[インスタンス]をクリックします。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/db136476-7651-97e5-2bc2-094a8c701b46.png)

[インスタンスの作成]をクリックします。
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/4c55527b-8ea4-3872-e489-d225404441a2.png)

イメージとシェイプの項目に移動し[Change Shape]をクリックします。![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/735f9780-5d1d-f53c-dd16-7d150734adde.png)

出てきたメニュー右下の[Show advanced OCPU settings]をクリックします。
![図6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/9702ee43-e4e7-d730-46e7-9acd7afe11e8.png)

[Enable simultanneous multithreading(SMT)]のチェックを外し[シェイプの選択]をクリックします。
![図7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/2a8c7b3a-34d1-504d-71cf-9046aa9d407b.png)

最後に[作成]をクリックして完了です。
![図8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2172788/7ae8bd22-71da-8706-b649-afd674b045a7.png)


# 2.参考ドキュメント
仮想マシンにログイン後のシングルスレッドの確認コマンドや手順についてはこちら
[同時マルチスレッドの無効化](https://docs.oracle.com/ja-jp/iaas/Content/Compute/Tasks/disablesmt.htm)

ベアメタルインタンスの場合、同時マルチスレッドの無効化、コアの無効化、NUMA設定の最適化などはこちらよりご確認ください。
[ベア・メタル・インスタンスのBIOS設定](https://docs.oracle.com/ja-jp/iaas/Content/Compute/References/bios-settings.htm#bios-settings)
【Unity】FPSカメラの作り方について

# 概要
FPSカメラの作り方について様々な方の方法を参考にした結果、自分的に最もいい方法２つを書きます。
# 方法1　CinemachineVirtualCameraの機能
FPSカメラを実装するうえで最も簡単な方法だと思います。大体のゲームではこの方法で良いでしょう。

1. CinemachineVirtualCameraをPlayerの子供にアタッチする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686460/bb51f177-c9e9-5152-450e-b70decb77e8a.png)

2. 画像のようにプロパティを変更
　・Follow
　　　Playerオブジェクト
  　・Body
　　　Transposer
　　　Follow Offset、Dampingを全て0
  　・Aim
　　　POV
　　　SpeedをMaxSpeedからInputValueGainに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686460/99335f60-d323-4424-5133-69f90f805583.png)
MaxSpeedだと視点移動に加速減速が入る。好みかもしれないが。
これだけで簡単にFPSカメラが作れる。
```ChangeSens.cs
[SerializeField] private CinemachineVirtualCamera _virtualCamera;
private CinemachinePOV _cinemachinePov;

private void Awake()
{
    _cinemachinePov = _virtualCamera.GetCinemachineComponent<CinemachinePOV>();
    // InputValueGainでもm_MaxSpeedに代入
    float wishSens = 2;
    _cinemachinePov.m_VerticalAxis.m_MaxSpeed = wishSens;
    _cinemachinePov.m_HorizontalAxis.m_MaxSpeed = wishSens;
}
```
センシをScriptから変えたいときはVirtualCameraから**CinemachinePOV**を**GetCinemachineComponent**する。
# 方法2　Script制御
Cinemachineだと表現できないことがあればScriptで制御する必要がある。
自分はモデルを視点移動と同期させることとリコイルの表現がしたくてこの方法をとった。
リコイルについては[別記事](https://qiita.com/koinuma/private/bc6fd980f7dadb397c5c)。
```POVController.cs
using UnityEngine;

public class POVController : MonoBehaviour
{
    [SerializeField] private Transform _head;
    [SerializeField] private Transform _body;
    [SerializeField] private float _sensX = 5f;
    [SerializeField] private float _sensY = 5f;
    private float _yRotation, _xRotation;

    private void Update()
    {
        Look();
    }

    private void Look()
    {
        Vector2 mouseInput = new Vector2(Input.GetAxis("Mouse X") * _sensX,
            Input.GetAxis("Mouse Y") * _sensY);

        _xRotation -= mouseInput.y;
        _yRotation += mouseInput.x;
        _yRotation %= 360; // 絶対値が大きくなりすぎないように

        // 上下の視点移動量をClamp
        _xRotation = Mathf.Clamp(_xRotation, -90, 90);

        // 頭、体の向きの適用
        _head.transform.localRotation = Quaternion.Euler(_xRotation, 0, 0);
        _body.transform.localRotation = Quaternion.Euler(0, _yRotation, 0);
    }
}
```
マウスのインプット量だけ今の回転を増減させて反映しているだけ。
Bodyオブジェクトの子供にHeadを持っている。VirtualCameraはBodyをTransposer、AimをSameAsFollowTargetにしている。メインカメラを子供に持ってもいいが、VirtualCameraのほうが融通が利く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686460/a990cbb4-60f1-231a-ee22-5f6a8548266e.png)
FPSゲームのモデルは他視点だとX軸の回転は頭が上下し、Y軸の回転は体が左右に回転するのでXYで別のオブジェクトを回転させている。
Scriptで制御したほうがほかの機能に応用しやすい。
[初心者]ラズパイの自動実行が出来ない時にやった事

## はじめに
ラズパイ(というかLinux OS)の自動起動の方法いろいろあるけど、適当にcrontabとかでやったら出来ない！って方向けです。

## ラズパイ推奨
まず、ラズパイに推奨されているのはsystemdを使った自動起動です。よほどの理由がない限りこれでやりましょう。

## systemdの自動起動の方法
 nanoやviなどのテキストエディタを使用して、/etc/systemd/system/ディレクトリ内に.serviceファイルを作成します。例えば、your-service.serviceという名前でファイルを作成します。
```
sudo nano /etc/systemd/system/your-service.service
```

以下のテンプレートを使用して、ファイルに内容を記述します。内容はあなたのプログラムに合わせて適宜変更してください。
```
[Unit]
Description=My custom service
After=network.target

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/your-program-directory
ExecStart=/usr/bin/python3 /home/pi/your-program-directory/your-script.py
Restart=on-failure

[Install]
WantedBy=multi-user.target
```
ファイルを作ったら
```
sudo systemctl daemon-reload #新しいサービスファイルを認識
sudo systemctl enable your-service.service #システム起動時に自動的に起動するように設定
sudo systemctl start your-service.service #サービスを起動
sudo systemctl status your-service.service #サービスの状態を確認
 #以下適宜
sudo systemctl stop your-service.service # サービスストップ
sudo systemctl disable your-service.service #システム起動時に自動的に起動しないように設定
sudo systemctl restart your-service.service #サービス再起動

```


## systemdでやってもできない！
とりあえずログを見てみる。
```
journalctl -u サービス名.service
```

考えられる原因
- .serviceファイルは /etc/systemd/system/ディレクトリですか？
- 実行ユーザーを指定していますか？デフォルトはrootユーザー
- 実行ディレクトリは実行ファイルがあるディレクトリですか？
（絶対パスで書いたら大丈夫だけど、相対パスの場合エラー出ることがある。）

大体これで治ります。

## 最後に
自分は初めて自動起動するときにいろいろな方法を見て、"crontabが一番便利そうだな"って思ってましたがsystemdが推奨の方法なのでこれを覚えましょう。
今回自動起動をやったことがない初心者の方向けに、自分が詰まったところを参考に書きましたがもし参考になれば幸いです。
Railsでデフォルト値をモデルから取得する方法

Railsのアプリケーションにおいて、フォームからの入力がない場合にデフォルトの値を使用したいシチュエーションはよくあります。この記事では、`staff`の編集フォームで特定の入力がない場合に、`services`テーブルの`fee`カラムに設定されている値をデフォルト値として使用する具体的な方法について説明します。

## メソッドの定義場所

この機能を実装するにあたり、デフォルト値を提供するメソッド`default_fee`を`Service`モデル内に定義します。これにより、特定のサービスに関連付けられたデフォルト料金を簡単に取得できるようになります。

## `default_fee`メソッドの定義

`Service`モデルに`default_fee`メソッドを定義することで、特定のサービスのデフォルト料金を取得できます。以下はその定義例です。

```ruby
class Service < ApplicationRecord
  # 既存のコード
  
  # デフォルト料金を返すメソッド
  def default_fee
    self.fee
  end
end
```

## コントローラでの使用例

次に、`Staffs::RegistrationsController`の`update`アクション内で`default_fee`メソッドを使用する方法を示します。この例では、フォームからの入力がない場合に、`Service`モデルからデフォルト値を取得しています。

```ruby
class Staffs::RegistrationsController < Devise::RegistrationsController
  def update
    # 既存の認証処理など
    
    params[:staff][:service_ids].each do |service_id|
      if params[:staff][:service_fees][service_id].blank?
        service = Service.find(service_id)
        
        # 値の入力がない場合はデフォルト値が設定される
        fee = params[:staff][:service_fees][service_id].presence || service.default_fee
        # その他の処理
      end
    end
    
    super
  end
end
```

## 留意事項

- `default_fee`メソッドを使用する前に、`Service`モデルが正しく定義されていることを確認してください。
- フォームからの入力がある場合は、その入力値を使用し、入力がない場合のみ`default_fee`を使用するようにしてください。
【KCNA-JP】認定Kubernetesクラウドネイティブアソシエイトの勉強法・試験対策

# 勉強法について

受験体験記や受験の仕方などは他の方々も語られているため、
今回は「資格取得のために具体的に何をすればよいのか」を解説します。

最短での試験合格を目標として、シンプルに以下の対策をお勧めします。

**1. 模擬試験を用意する**
これだけでOK！【KCNA-JP】認定Kubernetesクラウドネイティブアソシエイト模擬試験問題集（5回分300問）

https://www.udemy.com/course/kcna-jp_kubenetes/?couponCode=KUBE01

:::note info
こちらのぺー（https://qiita.com/t-h345/items/c448b44a73450eb738ba
）にてクーポンコードを配布しています。
割引価格で購入できるので是非ご活用ください！
:::

**2. 初見でまず問題を解いて全体像を掴む**
最初は分からなくて当たり前です。頻出用語に慣れることが大事です。(英語を勉強するのに、まずは単語を覚えるのと一緒です)

**3. 解説を確認して理解する**
ここが資格勉強の肝となる部分です。
よくわからなかった部分は解説・Web・ChatGPTなどを駆使して頭に入れていきましょう！
この資格に限らずですが、資格取得はパターンプラクティスです。
ハンズオンで手を動かして理解したくなったりしますが、最短で合格するためには「資格取得すること」だけに時間を使うことに集中しましょう。

**4. 反復で解き直す**
脳に定着させるためです。

**5. 9割以上安定して取れるようになったら試験に望む**
模擬試験で安定して9割取れるようになれば、本番対策は概ねokです。KCNA-JP試験は一度の申込みで2回受験できるため、この状態で一度チャレンジしてみましょう。

# 公式のレクチャー(LFS-250)は必要か？
体系的に学ぶという意味では参考にはなりますが、「試験に合格する」ためには必要ないと思います。(金額も高いです…)
模擬試験の反復学習で十分取れる資格です。

# さいごに
SAA資格がc02⇒c03で難化されたように、今後は試験が段々と難化していくものと予想されますので、早めの資格取得をお勧めします。

SESさんやSierさんなど、モダンな案件に入りたい方にとって、資格は大きな武器になります。そこまで学習コストがかからない&取っておいて損はない資格なので、ぜひ資格取得してみてください！
【Zod】パース後にデータを変換する方法

パース後にデータを変換するには`transform`を使用します。
以下に使用例を示します。

## 数値を文字列に変換

```js
import { z } from 'zod';

// 数値から文字列への変換
const numberToString = z.number().transform(num => num.toString());

// バリデーションと変換
const result = numberToString.parse(123); // "123"
```

## オブジェクトのプロパティを変換

```js
import { z } from 'zod';

// オブジェクトスキーマの定義
const originalSchema = z.object({
  name: z.string(),
  age: z.number(),
});

// ageプロパティを文字列に変換する新しいスキーマ
const transformedSchema = originalSchema.transform(obj => ({
  ...obj,
  age: obj.age.toString(),
}));

// バリデーションと変換
const result = transformedSchema.parse({ name: 'John', age: 30 }); // { name: 'John', age: '30' }
```

## オブジェクトのキーをキャメルケースに変換

```ts
import { z } from 'zod';

function toCamelCase(str: string): string {
  return str.replace(/([-_][a-z])/g, group => group.toUpperCase()
                                              .replace('-', '')
                                              .replace('_', ''));
}

const originalSchema = z.object({
  first_name: z.string(),
  last_name: z.string(),
});

const transformedSchema = originalSchema.transform(obj => {
  const newObj: any = {};
  for (const key in obj) {
    newObj[toCamelCase(key)] = obj[key];
  }
  return newObj;
});

const result = transformedSchema.parse({ first_name: 'John', last_name: 'Doe' });
// result: { firstName: 'John', lastName: 'Doe' }
```
1年目よちよちVPoEが語る: 開発組織の成長戦略

今年の1月よりアソビューのVPoEを務めている服部([@tkyshat](https://twitter.com/tkyshat))です。

アソビューのプロダクト開発組織は1年半前と比較すると、組織規模は1.5倍。約100人の組織となりました。組織が急拡大したことで、様々な課題に直面しております。

今回、Qiita様 x Findy様企画の『今のシステム開発組織でトライしたこと・トライしていること・トライしようとしていること』に乗っからせていただき、
開発組織の成長に焦点を当てて、今年1年の具体的なアクションプランをつらつらと書いていきます。

# 成長を意識した継続的なジョブローテーション
同じプロダクトに長期間携わることは、特定の分野に対する深い知識や理解を培い、課題への強いオーナーシップを発揮できるようになる大きな利点があります。
しかし、この状況は新たにチームに入ったエンジニアにとってはマチュアなメンバーがいることで良くも悪くも安心し過ぎてしまい、「あの人がいれば大丈夫」と、課題に対して積極的に取り組む機会を逃してしまう可能性があります。
また、特定のドメインやプロダクトに精通した人々が新しいプロダクトやプロジェクトに挑戦したくても、所属している組織に対する責任感に縛られ、新たなチャレンジを躊躇してしまうこともあります。

この課題に対処するため、ジョブローテーションが有効な戦略になると考えています。ジョブローテーションによって新しい成長機会にチャレンジメンバーは、アンラーンとリスキリングにより、自身の視野を広げられるようになります。同時に、残ったチームメンバーはそれまで経験豊富なメンバーに依存していた課題に直面することで、オーナーシップを自ら発揮できるようになると考えています。

ジョブローテーションを実施することによって、個人だけでなく組織全体の成長に寄与できると考えています。アソビューでは他の部署や未経験の職種に挑戦できる「キャリアチャレンジ制度」があります。この制度を基にプロダクト部門でも継続的なジョブローテーションの実施を計画していきます。

# チームで開発生産性を意識する
1年前に「月間100回を超えるリリースを支えるアソビュー！の開発プロセス」の記事を公開してから、弊社のメンバー数も着実に増加しています。これにより、チームとしてのケイパビリティが拡大しているはずですが、リリースサイクルの速度は思ったほど改善できていないと感じています。これは、チームの拡大と共に、コミュニケーションやプロセスの複雑化が生じ、開発の効率が低下していることが原因かもしれません。

https://tech.asoview.co.jp/entry/2022/11/07/102653

リリースサイクルの低下には様々な要因が考えられますが、問題を具体的に把握するには、開発プロセスやチームパフォーマンスを定量的に測定し、開発チーム自身が各々の現在地を知ることが重要です。これができなければ、現状が本当に問題なのか、あるいは予想以上に上手くいっているのかさえも判断できません。

弊社では開発チームのパフォーマンス指標である「Four Keys」を計測できるツール、[Findy Team+](https://findy-team.io/) を、今年の2月から一部の開発チームで導入開始しました。
このツールの導入により、短期間ですがチームごとの強みと弱みが明らかになり始めています。
半年以内の目標として、このツールを全開発チームに展開し、データを基に「どのようにしてアウトプットを最大化できるか」を各チームが試行錯誤し、最適な開発プロセスを模索できるようになる状態を作っていきます。

# 全員技術広報の推進
アソビューは2011年の創業から現在に至るまで、プロダクトの内製にこだわりながら多様な事業を展開してきました。事業の拡大と共に、新しい技術の採用にも検討の余地があります。私たちは技術検証を実施した上で適宜必要な技術を取り入れてきました。
下記の弊社VPoT兼平によるモジュラモノリスに関する記事は、アソビューがどのように技術革新を取り組んでいるかの一例になります。

https://en-ambi.com/itcontents/entry/2022/07/25/093000

上記の取り組み以外にも、私たちは週に1度のLT会を開催しています。社内での技術的な研鑽とチーム間のコミュニケーションを促進する重要な活動だと考えていますが、このような社内のイベントで共有した知識や日々の業務で培った経験を社外にはまだまだ発信しきれていません。

社外に対する発信は内部での発表よりも、準備には多くの努力と時間を要します。
同僚ではない人に対して情報を分かりやすく噛み砕いて伝えることは決して簡単でないですが、このプロセスを通じて自分自身の思考を整理し、知識を定着させることができます。さらに外部発信は個人のブランディングにも繋がるため、今後社会活動を進めていくうえで大きな財産になります。

また、外部への発信をエンジニア社員で積極的に行うことで、エンジニアコミュニティに対するテックカンパニーとしての社会的責任も果たすことができます。社内外問わずエンジニアや開発組織にとってのインスピレーションや学びの源泉となり、エンジニアコミュニティ全体の発展に貢献していきたいと考えています。

そのため、全員で協力しながらブログの発信やイベントの開催を実施していきます。

# 経営とプロダクト開発をつなぐ
経営を継続する上で避けて通れない問題があります。それは、資金が尽きるということです。企業が存続し、さらに成長していくためには、資金の維持と増加が必要です。
この課題を解決するためには、2つのアプローチが考えられます。1つ目は、私たちのユーザー様にさらなる価値を提供し、その結果として利益を上げることです。2つ目は、固定費や変動費等の経費の削減を図ることです。

会社としてユーザー様への価値貢献を増やす方法は様々あります。しかし、エンジニアリングチームとして私たちが直接貢献できる最も効果的な手段は、プロダクトの継続的な成長に努めることだと考えています。
プロダクトの成長とは、単に新機能を追加することだけではなく、市場のニーズに合致した高品質なサービスを提供し続けること、そしてユーザー体験を向上させ続けることです。

しかし、プロダクトの成長には、経営が開発案件毎の収益性を正確に分析し、投資意思決定ができる状態を作り出す必要があります。そのため今以上に管理会計の整備に力を入れ、経営陣がより戦略的な意思決定を行えるようサポートしていきます。

# 最後に
つらつらと思うがままに書いてきましたが、書いたからには来年の今頃どうなっているかのアカウンタビリティがあるので、しっかり振り返りできたらと思っています。

ここまで読んでいただいてもわかるように、アソビューは伸びしろのある組織で、そこら中にボールが落ちているいい意味でやりがいのある組織です。
事業成長や組織改善にコミットしたいエンジニアの方がいらっしゃいましたら、 カジュアル面談もありますので、少しでも興味があればご応募いただければと思います。

https://www.asoview.co.jp/career/engineer
重複するファイルを検出する

重複するファイルを検出する
SDKをあちらこちらにインストールして、管理下に置けてない場合、管理下におくための、検出ツールとして使えます。
YouTubeの動画編集をされてるかたにも有用かもしれませんね。素材がちらばってしまっているとか。

共用PCでWEBコンテンツを作成されているかたにも便利に使っていただけると思います。

![pict.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518713/d167a206-7704-89c0-1185-793f0ebe33e5.png)


ソースコードはGithub上にあります。

変更履歴
・フォルダを選択できるようになりました。
・拡張子で絞り込めるようになりました。
・カスタム拡張子を入力できるようになりました。
・ソースはGithubへのリンクに変更しました。

https://github.com/syntaro/javamidimixer/blob/main/mixrecipe/src/jp/synthtarou/tools/SameFileChecker.java
ブラウザがどう動いているかについて調べてみた

## はじめに
ブラウザがどのように動くか気になったため、
以下の記事を読んでみて勉強になったことについてこの記事に書き残そうと思います。
[How Browsers Work - Behind the Scenes of Modern Web Browsers](https://web.dev/articles/howbrowserswork)

## ユーザーインターフェース
ブラウザの戻るボタン等、ユーザーインターフェースはどのブラウザでも一緒なので使用等があるのかと思っておりました。
以下の文章から、使用があるわけではなく良いユーザーインターフェースが残った結果、どのブラウザでも統一されたようです。
> the browser's user interface is not specified in any formal specification,
it just comes from good practices shaped over years of experience and by browsers imitating each other.
The HTML5 specification doesn't define UI elements a browser must have, but lists some common elements

## パース
ブラウザがコードをパースする際はLexicalとSyntaxの２つのパースが実行されるようです。
Lexicalは意味をなす最小単位に分解する。
Syntaxはコードの文法通りとなっているかを解析すると読み取りました。
> Parser - Lexer combination
Parsing can be separated into two sub processes: lexical analysis and syntax analysis.
>Lexical analysis is the process of breaking the input into tokens. Tokens are the language vocabulary: the collection of valid building blocks. In human language it will consist of all the words that appear in the dictionary for that language.
> Syntax analysis is the applying of the language syntax rules.

## ブラウザのエラー寛容度
自分もhtmlを書いている際にシンタックスエラーが発生しないなとは思っていましたが、やはりHTMLでエラーは発生せず、ブラウザ側で修正しているようです。
>You never get an "Invalid Syntax" error on an HTML page. Browsers fix any invalid content and go on.

# パースの順所について
ブラウザは同期的に処理しておりscriptがある場合はscriptに到達した瞬間に実行、外部から参照している際は取得されるまでパースは止まるようです。
ただし非同期でパースする仕組みがHTML4以降でdefer属性を使うことで可能になっているようです。
>The model of the web is synchronous. Authors expect scripts to be parsed and executed immediately when the parser reaches a <script> tag. The parsing of the document halts until the script has been executed. If the script is external then the resource must first be fetched from the network - this is also done synchronously, and parsing halts until the resource is fetched. This was the model for many years and is also specified in HTML4 and 5 specifications. Authors can add the "defer" attribute to a script, in which case it won't halt document parsing and will execute after the document is parsed. HTML5 adds an option to mark the script as asynchronous so it will be parsed and executed by a different thread.

## 動的な変更
ブラウザは変更された内容に対して、可能な限り最小限の処理を実行するようになっているようです。
>Dynamic changes
The browsers try to do the minimal possible actions in response to a change. So changes to an element's color will cause only repaint of the element. Changes to the element position will cause layout and repaint of the element, its children and possibly siblings. Adding a DOM node will cause layout and repaint of the node. Major changes, like increasing font size of the "html" element, will cause invalidation of caches, relayout and repaint of the entire tree.

# 最後に
普段使っているブラウザですが奥深さを垣間見ました。
次はキャッシュの仕組みや認証情報の保存などについても学ぼうと思います。
【Kintone】ルックアップと関連レコードの違い

情報を参照する際に使用するルックアップと関連レコードの違いをまとめてみました。
両方とも「情報をアプリ内に持ってくる」ことが可能なので混同しがちですが、
よく調べてみると違う点がいくつかでてきました。

## Kintoneの資料に書いている説明
最初は表示の仕方が変わるだけかな？って思ってましたが全然違いました。笑
### ルックアップ
他のアプリに登録されている情報を参照してデータを取得(コピー)できる機能。
主な用途：データを登録しているアプリとそのデータをコピーして活用したいアプリ間
　　　　　例）「人事評価」のアプリと「従業員情報」アプリ
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631802/8c569466-17f5-35fe-1770-8e99c4de219f.png)


### 関連レコード
レコード詳細画面に「条件に一致したレコード」を一覧表示できる機能
主な用途：例）「配属情報」のアプリと「従業員情報」アプリ
　　　　　　　「配属情報」のアプリ内に「従業員情報」アプリ内の
  　　　     　　　　従業員情報をまとめて表示する
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631802/8bfcabac-1f0a-4bea-0f1d-97f052631d2c.png)

## アプリ作成前に知っておきたい違い
### 1.取得の仕方
ルックアップの場合は上記にも記載の通り、データ取得の際は参照元のアプリから
情報を**コピー**して持ってくる。そのため取得したタイミングの情報しか反映されず、
参照元のデータを修正した場合は**再度取得しなおす必要**がある。

一方関連レコードの場合は参照元のアプリから情報を**自動取得**が可能。
レコードを登録後、持ってきたいデータ一覧が自動で反映される。
参照元のデータ変更後も自動で反映されるため、再度取得しなおすなどの手間がかからない

### 2.各フィールドを設定する
ルックアップでは、参照元のキーとなるデータは一意でなければならず、参照元の「値の重複を禁止する」にチェックが入っていないとできない。また、文字列（1行）、数値、計算、ルックアップ、リンク、レコード番号のフィールドのみルックアップのキーにすることができる。
関連レコードは参照元のデータが一意である必要はなく、キーとなるフィールドを基準にレコードを取得することができる。しかし、参照元と参照先のキーとなるフィールドの組み合わせに注意して設定する必要がある。また、下記の写真にないものは関連レコードとして表示させることができない。
![スクリーンショット 2024-03-24 23.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631802/2033d402-a395-10e5-6e5f-47ba736cc5d1.png)


https://jp.cybozu.help/k/ja/user/app_settings/form/lookup/set_lookup.html

https://jp.cybozu.help/k/ja/user/app_settings/form/related_records/display_relatedrecords.html

### 3.参照元のアプリ
ルックアップは他のアプリからのみ参照可能だが、関連レコードの場合は同じアプリ内からも参照が可能

### 4.フォーム内の表示
ルックアップの場合は、持ってきたい情報を自分が設置したい配置通りに置くことができる。
![スクリーンショット 2024-03-24 22.49.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631802/cbb6a45d-ef9a-05ac-2439-c0d4cb7bebc2.png)
関連レコードの場合は、持ってきたい情報は一覧でのみ表示ができる。
自分なりのフォーマットにしたい場合には不向き。
![スクリーンショット 2024-03-24 22.53.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631802/40e203ee-b8c6-4ef1-929b-f219ba116088.png)

### 5.アプリのレコード一覧での表示
ルックアップの場合は参照元から情報をコピーして持ってくるのでレコード一覧の画面でも取得した情報のフィールドを表示させることができる。
関連レコードの場合は、参照元のデータをただ引っ張ってきて違うレコードの中で表示させる機能なため、レコード一覧の画面では表示させることができない。

## ルックアップと関連レコードの使い分け
上記に記載している違いを踏まえ私なりに使い分けを考えてみました。
### ルックアップ
- 参照元から情報を引っ張ってきて参照先にも元々あったデータの方に使用したい時
- 自動更新する必要がない不変なデータを扱う時
- 元々他のSaaSで使用していたフォーマットに似せて使用したい時
- 複数のアプリで同じデータを扱いたい時
- アプリごとの表記ブレを防ぎたい時

### 関連レコード
- ついでに見れたら便利だなと思う情報を表示させたい時
- 同じ商品や人の情報を漏れなく見たい時
- 常に最新の情報を取得しておく必要がある時
- データがよく変わる時
- 同じアプリ内に登録されている情報をまとめたい時

## 最後に
まだKintoneを使用し始めて3ヶ月ほどですが、
ルックアップや関連レコードを使う機会が多かったのでまとめてみました。
私なりに気づいた異なる点をまとめただけなので、他にももしかしたら違いあるかもしれませんが、ぜひKintoneでアプリを作成する際に参考にしていただけたら嬉しいです！