OmniAICreator/Qiita-1.07M huggingface dataset:
Golangのwireを使ってDIしてみた

# はじめに
現在インターンで業務をしているジュニアエンジニアが勉強中の技術をアウトプットしています。
間違っていることもあると思われるので、その際は指摘いただけると幸いです。

# DIとは
まず初めにそもそもDIとは何者なのかを解説します。

DIとは「Dependency Injection」の略で、直訳すると「依存性注入」と言われたりしています。
具体的には依存元のクラスのコンストラクタやメソッド内で依存先のクラスを初期化するのではなく、依存元のクラスの初期化時にコンストラクタの引数に対して、依存先のクラスのインスタンスを渡してあげようということです。
そうすることによってクラス同士が疎結合になるので、保守性が大幅にアップするというメリットがあります。

文章だとわかりにくいので実際のコードで考えてみます。

以下のコードはDIしていない例です。
Hoge構造体のHogeMethodの中でFuga構造体を初期化しているので、密結合となっています。

```Go
type Hoge struct {
}

func (h *Hoge) HogeMethod() string {
    f := Fuga{}
    return f.fugaMethod
}

type Fuga struct {
}

func (fuga *Fuga) FugaMethod() string {
    return "fuga"
}


func main() {
   h := Hoge{}
   fmt.Pirngln(h.HogeMethod())
}

```
<br>


以下のコードはDIしている例です。
クラスの依存関係が疎結合になっています。
NewHogeとNewFugaの二つの関数はオブジェクト（構造体）を生成するファクトリーメソッドです。

```Go
//  interface
type HogeInterface interface {
    HogeMethod() string
}

type FugaInterface interface {
    FugaMethod() string
}


// 構造体とメソッド
type Hoge struct {
    f FugaInterface
}

func (h *Hoge) HogeMethod() string {
    return h.f.FugaMethod()
}

type Fuga struct{}

func (f *Fuga) FugaMethod() string {
    return "fuga"
}


// ファクトリーメソッド
func NewHoge(f FugaInterface) HogeInterface {
    return Hoge{f}
}

func NewFuga() FugaInterface {
    return Fuga{}
}


func main() {
    // 依存関係の注入
    fuga := NewFuga()
    hoge := NewHoge(fuga)

    // HogeMethod()の実行
    fmt.Println(hoge.HogeMethod())
}
```
<br>
ここまででDIの例を見てきました。
上記のコードは小規模ですが、実際の現場だとドメイン駆動設計やClean Architectureなどの設計パターンを採用し、クラス関係が複雑になってきます。
一つのクラスが複数のクラスをプロパティに保持して、さらにその注入されたクラスが複数のクラスをプロパティとして保持するなど、マトリョーシカのように連なっていきます。
そのようなコードの依存関係の注入はコードとして書くのが面倒です。
それを解決してくれるのが、google/wireというライブラリです。

# 実際にwireを使ってみる
先ほどのコードをwireを使って書き換えてみます。
まずはライブラリをインストールします。
```
go install github.com/google/wire/cmd/wire@latest
```
<br>

続いてwire.goファイルを作成し、以下のようにwire.Build内にファクトリーメソッドを記述します。
```Go:wire.go
//go:build wireinject
// +build wireinject

package injection

import (
	"github.com/wire-test/hoge"
	"github.com/wire-test/fuga"

	"github.com/google/wire"
)

func InitializeHoge() hoge.HogeInterface {
	wire.Build(
		// fuga
		fuga.NewFuga,

		// hoge
		hoge.NewHoge,
	)
	return &hoge.Hoge{}
}
```
<br>

wireコマンドを実行します。
```
wire
```
<br>

wire_gen.goが自動生成されます。
内容は以下の通りです。
依存関係の注入部分をInitializeHoge関数内に自動生成してくれたのが分かると思います。
後はInitializeHoge関数を呼び出せば、hoge構造体が戻り値として返されます。

```Go:wire_gen.go
// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package injection

import (
    "github.com/wire-test/hoge"
	"github.com/wire-test/fuga"
)

// Injectors from wire.go:

func InitializeHoge() hoge.HogeInterface {
    fuga := fuga.NewFuga()
    hoge := hoge.NewHoge(fuga)
    return hoge
}
```
ChatGPTにBingのチャットのことを、BingのチャットにChatGPTのことを、それぞれ聞いてみたら

# はじめに
先日、ChatGPTにチャット内容の著作権について説明を求めたら、新しい Bingが「Bingのチャットと著作権」について執筆してきた内容と、大きく異なっているように感じる回答が返ってきましたので、今回はお互いの関係性についてそれぞれに対して聞いてみました。

## この記事内容の作業環境
Windows11
Microsoft Edge 112.0.1722.68
ChatGPT3.5

## この記事内容の保証
※この記事にはAIが自動生成した見解的な情報が含まれます。AIが自動生成して書かれた内容の妥当性は保証されません。

# 実行結果

## ChatGPT3.5

私：
こんにちは。あなたの兄弟とも言える「Bingのチャット」について教えてください。

ChatGPT：
>こんにちは！Bingのチャットとは、Microsoftが開発した人工知能を活用したチャットボットです。Bingの検索技術や自然言語処理技術を利用して、人々が持つ様々な質問に回答することができます。
>
>Bingのチャットは、会話の流れを理解し、適切な回答を返すことができるため、ユーザーが何を尋ねているのかを把握しやすく、迅速かつ正確な回答を提供することができます。また、ユーザーがより自然な言葉で質問することができるように、会話をスムーズに進めることができます。
>
>Bingのチャットは、様々な分野にわたる質問に対応しており、例えば天気、ニュース、スポーツ、旅行、食事、エンターテインメント、テクノロジーなど、広範囲にわたるテーマに対応しています。Bingのチャットは、英語、スペイン語、フランス語、中国語（簡体字と繁体字）、日本語、韓国語など、多くの言語で利用することができます。


私：
「Bingのチャットとは、Microsoftが開発した人工知能を活用したチャットボットです。」とおっしゃいましたが、OpenAIのあなたChatGPTとの関係を詳しく教えてください。

ChatGPT
>BingのチャットとOpenAIのChatGPTは別々の人工知能のチャットボットです。BingのチャットはMicrosoftが開発したものであり、OpenAIは関与していません。
>
>一方、私であるChatGPTは、OpenAIが開発した人工知能の一種です。ChatGPTは、巨大なデータセットを使ってトレーニングされた自然言語処理のモデルで、様々な種類の質問や会話に対して自然な応答を生成することができます。
>
>つまり、BingのチャットとChatGPTは別々の人工知能であり、開発元も異なります。ただし、どちらのツールも人工知能を活用しており、自然言語処理技術を利用して、ユーザーが持つ様々な質問に対して迅速かつ正確な回答を提供することができます。

## Bing チャット
※閲覧しているページはOpenAIのChatGPTの上記チャットページ

私：
こんにちは。あなた（Beingのチャット）とOpenAIのChatGPTとの関係を教えてください。
※すみません、つづり間違えています。

Bing チャット：
>すみません、違う話題にしましょう。ほかにどんなことを考えていますか？

私：
こんにちは。あなた（Bingのチャット）とOpenAIのChatGPTとの関係を教えてください。

Bing チャット：
>そろそろ新しいトピックに移る時間です。 最初からやり直しましょう。

※Bing チャットがこの応答をするとらちがあかなくなるので、ここで停止しました。

## Bing 作成

執筆分野
「BingのチャットとOpenAIのChatGPTとの関係」
トーン「プロフェッショナル」　形式「段落」　長さ「中」

>BingのチャットとOpenAIのChatGPTとの関係について、以下のような文章を生成しました。
>
>Bingのチャットは、OpenAIが開発した対話型AIチャットボットであるChatGPTの技術を利用しています。ChatGPTは、インターネット上の膨大なテキストデータを学習した大規模言語モデル（LLM）であるGPT-4を搭載しており、自然な文章で質問に回答したり、コードや画像などのコンテンツを生成したりすることができます 。Bingのチャットは、ChatGPTと同じGPT-4を使用していますが 、検索エンジンと統合されているため、インターネット全体にアクセスできるという特徴があります。また、Bingのチャットは、独創性、バランス、厳密という3つのチャットモードを選択できるようになっており、ユーザーのニーズに応じて応答のスタイルや速度を変えることができます。


# 考察
ChatGPT3.5の回答が「Bingのチャットとは、Microsoftが開発した人工知能を活用したチャットボットで」「Microsoftが開発したものであり、OpenAIは関与していません。」と断言してきたのは想定外で、ちょっと驚きました。ChatGPT3.5としては「BingのチャットとChatGPTは別々の人工知能で」「人工知能を活用して」いる点が共通項という認識のようです。

Bingのチャット自体はこの話題に触れたがらないようでしたが、Bingの作成は「Bingのチャットは、OpenAIが開発した対話型AIチャットボットであるChatGPTの技術を利用してい」ると回答しています。

これはつまり、BingのChatGPT4はOpenAIのChatGPTのことは認識していても、OpenAIのChatGPT3.5はBingのChatGPTのことを認識していないということのようです。教え込まれたデータに別ものですよと書かれていた？

# おわりに
BingはChatGPT4なんですね。著作権上の問題はついてまわりますが、インターネットにアクセスするBingのチャットのが、情報の最新性という点では有利な気がしました。しかし、ロジックを考案させるような課題では、どちらも同程度の性能を発揮するのかもしれません。

# 参考リンク
https://qiita.com/mylifewithviolin/items/953d7a36fca07df1e260

https://qiita.com/mylifewithviolin/items/c1ad754ebaf5d68515ca
Swift Playgrounds メモ


## エラー内容が表示されない問題
以下のコードを先頭に入れておく

```swift
NSSetUncaughtExceptionHandler { exception in
    print("Exception thrown: \(exception)")
    exception.callStackSymbols.forEach{print($0)}
}

```

## UINanavigationViewController 　の navigationbar が上部にめり込む問題

これはよくわからなかった・・。
とりあえず、以下のコードのように UIViewController でラップして解決するしかなさそう。

```swift
class SecondViewController: UIViewController {}

class RootViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "タイトル"

        navigationController?.pushViewController(SecondViewController(), animated: true)
    }
}

let rootViewController = RootViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)


let wrapperViewController = UIViewController()
wrapperViewController.addChild(navigationController)
wrapperViewController.view.addSubview(navigationController.view)
PlaygroundPage.current.liveView = wrapperViewController
PlaygroundPage.current.needsIndefiniteExecution = true

```


## ローカルの画像を読み込みたい
左メニューの resources ディレクトリに画像をドラッグドロップして以下のような形で利用するだけ。

```swift
let myImage = UIImage(named: "myImageFileName")
```

## AppDelegate に書いていた UIBarButtonItem.appearance() などの初期化処理はどこに書けば良い？
以下のような形で ViewController を立ち上げる前に実行すればいい様子。

```swift

UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffset(horizontal: 0, vertical: 14), for: UIBarMetrics.default)


let vc = OtherViewController()
let viewController = NavigationController()
PlaygroundPage.current.liveView = viewController
PlaygroundPage.current.needsIndefiniteExecution = true

```

## addTaget をしたい
よくある addTarget(self, ...)　 のように self を渡すことはできないので、以下のように NSObject を渡して代わりに受け取ってもらいます。

```swift 
class Responder : NSObject {
    @objc func action() {
        print("Button pressed!")
    }
}
let button = UIButton(frame: CGRect(x: 0, y: 100, width: 100, height: 100))
let responder = Responder()
button.addTarget(responder, action: #selector(responder.action), for: .touchUpInside)
button.backgroundColor = .blue
view.addSubview(button)
```

## alertController を表示したい
ポイントは PlaygroundPage.current.liveView に空の UIViewController を設定した後に viewController で alertController をpresent しているところ。

```swift
let alertController = UIAlertController(title: "タイトル", message: "エラー!!!", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
let viewController = UIViewController()
PlaygroundPage.current.liveView = viewController
viewController.present(alertController, animated: true, completion: nil)
```
【ChatGPT】ChatGPTのAPIをphpから使う（Windows/IIS）

# ChatGPTのAPIをphpから使う #

## 1. 前提 ##

１）IISが動作している
２）pythonでopenai利用できている

　・openai apiを取得できている
　・利用制限の設定が完了していること


## 2. php設定 ##

以下の記事を参考に実施：
https://qiita.com/kotonoha0109/items/b1b1b48520f7ee137c5e

１）サンプルファイルをダウンロード
２）api-keyを書き換え
３）php.iniを編集

916行目
extension=curl
をコメントアウト削除

４）iis再起動
５）phpinfoで、curlがenableになっているかを確認する。


### php.iniを編集 ###

```php:php.ini
    ;extension=bz2
    extension=curl
    ;extension=ffi
    ;extension=ftp
    ;extension=fileinfo
    ;extension=gd2
    ;extension=gettext
    ;extension=gmp
    ;extension=intl
    ;extension=imap
    ;extension=ldap
    ;extension=mbstring
    ;extension=exif      ; Must be after mbstring as it depends on it
    extension=mysqli
    ;extension=oci8_12c  ; Use with Oracle Database 12c Instant Client
    ;extension=odbc
    ;extension=openssl
    ;extension=pdo_firebird
    extension=pdo_mysql
    ;extension=pdo_oci
    ;extension=pdo_odbc
    ;extension=pdo_pgsql
    ;extension=pdo_sqlite
    ;extension=pgsql
    ;extension=shmop
```

### phpinfo() 確認結果 ###

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692785/eccaa294-aa0c-5ee5-d2b5-0b848b43ed88.png)

curlが表示された。

### できたこと ###

・curlが使えるようになった
（サンプルファイルの通り）
・phpでchatGPIが使えるようになった
（課金に注意　(;^_^A）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692785/c9d9f253-b75a-7940-1a0a-9d5bfe03c3a9.png)

確認事項：
・会話は、「data」フォルダに保存されています。

・心配なので、課金状況を見に行く。
　　＄0.0003　の利用になっていた。

　　1ドル=150円として、0.05円

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692785/abd753c2-08d0-e442-ba17-1c447f45b9b6.png)


### セキュリティ ###

chatGPTのAPI経由の質問データをOPENAI側に残さないようにする設定
PHPでCURLを使用してAPIを呼び出す場合は、no-storedヘッダーを以下のように設定する

```php:php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.openai.com/v1/engines/davinci/completions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"prompt": "Hello, World!","max_tokens": 5}');
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Authorization: Bearer YOUR_API_KEY';
$headers[] = 'OpenAI-Organization: YOUR_ORG';
$headers[] = 'no-stored: true'; //データを保存しないようにするためのヘッダー
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
curl_close($ch);

```
p5.jsでつくる草原

# はじめに
p5.jsというライブラリを利用してchatGPTと共に作成したアートの紹介です。
「なんかいい」をモットーに作っています。

# 作品紹介
<iframe width="560" height="315" src="https://www.youtube.com/embed/CUjAfNzoZm0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

```math
『草原』
```

# 構想
自然を感じられる作品をつくりたいという気持ちから作り始めました。ランダムな動作の集合で自然を表現できそうというところから思考をはじめ、具体的なものとして草原をイメージしました。

# chatGPTと調整
まずは円弧がくるくると回転するように指示しました。そこから円弧の角度を調整し、なびくように振動させました。
`振動`とか`なびく`とかを入力することで、noise関数を入れてランダムに数字を生成して、map関数で得た数値を角度の範囲を制限するものに変換して、オブジェクトが左右に揺れるように工夫してくれました。


#作品解説
## 下準備
必要なファイルや実行方法がわからない人は以下を参考にしてください。

https://qiita.com/keigo1110/items/543423379813b49e7415

## コード
コードはchatGPTが生成しています。数字は一部調整しています。
```javascript
//草が風になびく様子が描かれている
let blades = [];

// 初期設定
function setup() {
    // キャンバスのサイズを設定
    createCanvas(2000, 1500);
    // 色空間をHSBに設定
    colorMode(HSB);
    // 草の本数分Bladeオブジェクトを生成
    for (let i = 0; i < 4000; i++) {
      let b = new Blade();
      // 生成したBladeオブジェクトをblades配列に追加
      blades.push(b);
    }
  }

  // 描画処理
  function draw() {
    // 背景色を設定
    background(69,29,27);

    // blades配列の全てのBladeオブジェクトについてupdate()とdisplay()を実行
    for (let i = 0; i < blades.length; i++) {
      blades[i].update();
      blades[i].display();
    }
  }

// ブレードオブジェクトを定義するクラス
class Blade {
    constructor() {
      // ブレードの位置、角度、長さをランダムに設定
      this.x = random(width);
      this.y = random(height);
      this.angle = random(TWO_PI);
      this.segLength = random(3, 20);
      // 目標角度を0で初期化
      this.targetAngle = 0;
    }

    // ブレードの状態を更新する関数
    update() {
      // 角度をランダムに変化させる
      this.angle += random(-0.1, 0.1);
      // ノイズ関数を使って目標角度を計算し、現在の角度に近づける
      this.targetAngle = map(noise(this.x * 0.01, this.y * 0.01), 0, 1, -PI / 8, PI / 8);
      this.angle += (this.targetAngle - this.angle) * 0.1;
    }

    // ブレードを描画する関数
    display() {
      // 座標系を移動し、角度を設定
      push();
      translate(this.x, this.y);
      rotate(this.angle);
      // ブレードを複数の線分で構成する
      for (let i = 0; i < 5; i++) {
        stroke(120, 100, 70);  // 線の色を設定
        strokeWeight(4);  // 線の太さを設定
        line(0, 0, this.segLength, 0);  // 線を描画
        translate(this.segLength, 0);  // 座標系を移動
        rotate(PI / 8);  // 角度を回転
      }
      pop();  // 座標系を元に戻す
    }
  }
```

## 拡張性
ブレードの数や、大きさは変更できます。コメントを参考に好みに合わせて変えてください。
またランダムな数値生成による自然っぽさの表現はまだまだ追求できそうです。雨や波なども表現できそうです。

# おわりに
風が吹いて草がなびく感じを、たくさん用意することで草原の雰囲気をだすことができました。クリックすると風が吹いたと認識して、一定期間同じ方向になびくとかにするのも面白そうです。
【Vim】vimtutorはつまらないという人へ


# Introduction

**「`vimtutor`つまらない！」**

気軽に始められる`vimtutor`私は何周かしており飽きもこなかったのですが、知人に記事（後述）と薦めたところ操作がもどかしくてやめてしまったとのこと。

合う合わないはあると思うので、今回は楽しく学ぶをコンセプトにして`Vim`学習のおすすめをご紹介します。

`vimtutor`の記事については以下参照。

https://qiita.com/kagami_t/items/67f2183e8d1120ca9eff

**本記事が少しでも読者様の学びに繋がれば幸いです！**
**「いいね」をしていただけると今後の励みになるので、是非お願いします！**

## VIM adventures

https://vim-adventures.com/

`Vim`初学者向けのド ◯ クエ風チュートリアルです。

![Screenshot from 2023-05-05 15-37-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/8fe40102-de5f-fd3f-495a-6ad23208b2f6.png)

少し遊んでみましたが、タイピングゲームでタッチタイピング練習していた頃を思い出しました。
英語に抵抗がなければゲーム感覚で楽しく`Vim`を学べます。

![Screenshot from 2023-05-05 15-37-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/802dd877-8d76-34d0-a8a9-ec3b9ffdce0b.png)

`hjkl`だけでなく矢印キーでも動かせますが、初回だけ突っ込まれます。（笑）

![Screenshot from 2023-05-05 16-59-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/b059b273-0578-7881-fb02-ca5882d2c652.png)

全 13 ステージあり、無料で遊べるのは 1~3 のみです。

![Screenshot from 2023-05-05 16-56-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/59505d06-9661-eafb-017a-67eeb9fd209a.png)

## OpenVim

https://www.openvim.com/

画面にキーボードが表示されているのが好印象です。
`hjkl`で動かしていると、最初は頭が混乱してタイピングも怪しくなりかねないですからね。

こちらも英語ですが、操作に必要なキーが光ったりキーボードレイアウトを調整できたりと、ユーザーフレンドリーです。
英語に抵抗がある方でも進めやすいので`vimtutor`の代替ならこちらかな、と思います。

![Screenshot from 2023-05-05 17-23-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/78568042-cc95-c60e-e9cd-5318aa4c47b5.png)

気になったのは代替キーが効かないことでしょうか。
`Esc`を`Ctrl` + `[`で打ち慣れているため、個人的には少し気になってしまいました。

## VIM Genius

http://www.vimgenius.com/

開始時に難易度が設定でき、初心者も中級者も学べる構成になっています。

![Screenshot from 2023-05-05 17-25-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/537f1ff0-fba5-3abc-7d05-0890695ce580.png)

`vimtutor`と連携するような設計とのことで、途中まで進めて飽きた方には適しているかもしれません。

黙々と 1 問 1 答を進めていくので、覚えた内容の復習向きですかね。

![Screenshot from 2023-05-05 17-27-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292052/df3582a8-3d51-785a-7e1a-374cc50d3e2f.png)

## 最後に

`vimtutor`がおすすめです！
今回 3 つのサービスを紹介しましたが、最初に多少我慢してでも`vimtutor`が体系的に学べて最も良いと思いました。
利用者も多いため周りで`Vim`を触れる人と同じ方向性でスキル習得できる点でも優れています。

他のサービスを試すなら[OpenVim](#openvim)が万人受けすると思います。
`Vim`の再優先事項は、操作について考えずに行えることです。
ストレスを感じずに手を動かせる点は`vimtutor`以上に感じました。

他のサービスも調べましたが、ご紹介したもの以外に良さそうなものは見つかりませんでした。
GUI に寄りすぎて`Vim`の意味合いと離れすぎているものやサービス自体放置されているものなど、やはり`vimtutor`や`『実践Vim』`が優秀なためか他はあまり充実していませんでした。

最後まで閲覧頂きありがとうございました。

本記事がお役に立てば幸いです！

## 関連 URL

https://qiita.com/kagami_t/items/67f2183e8d1120ca9eff
Emacsのundoでリージョン指定

# Emacsで指定した範囲内のみundoする

最近知ったのだけど、リージョン指定した状態でハイライトした状態(Transient Mark Mode)でundo(C-/,C-x u,C-_)するとリージョン内に限定した状態でundoされる。
これが地味に使える機能だった。

例えば、
ちょっと前に修正した関数を元に戻したい場合、バッファ全体のundoでは今修正しているところまで戻ってしまう、これをリージョン指定することで戻したいところを指定することができる。

[結構昔](https://github.com/emacs-mirror/emacs/commit/65627aad683a648e510b5dd204f6b18086b99054)から入っているみたいだけどぜんぜん気づかなかった。

ただ、Emacs のundoは戻りすぎたのを戻す場合redoすればいいけど、これをしないと編集履歴が混乱してわけわからなくなる。
（私の場合、redoしないでspace入れてundo続けるとかする癖がついてしまっている）
Emacs28.1から使えるようになった[vundo](https://github.com/casouri/vundo)はこの辺りを改善してくれそうだけど、残念なことにvundoではリージョン指定は無視されるみたい。
【Unity】Spaceship Demoのスクリプトを分析してみた。

# 自己紹介
今度、大学にUnity Japanの人が来ると聞いて大興奮の大学生。
# 経緯
Unityのハッカソンに向けて少し勉強したいと思って、前から気になっていたインタラクティブなVFXに挑戦することに。
まずはデモの理解からだろうと思ってやってみます。誤情報注意。
# Spaceship Demoとは
Unity公式が配布するVFX Graphのデモ。
VFX Graphの開発者がVFX Graphを使って制作しているようでこれの理解をすればきっと強くなれる。

公式解説動画（日本語吹き替え）

https://www.youtube.com/watch?v=1Gg_UKybUMo&t=569s

我らがKeijiroさんの解説動画（まじで尊敬してます。ありがてぇ）

https://youtu.be/W6UgxklMRAg?t=2624

リポジトリ

https://github.com/Unity-Technologies/SpaceshipDemo

# 今回の趣旨
VFXのノードなどについては上に添付した２つの解説動画でしっかり解説されているのでスクリプト周りを中心に書きたいと思います。そもそも私に理解できるのでしょうか。

# ARUIIntaractive.cs
１つ目に上げた吹き替えのほうの解説動画でインタラクティブなVFXには全部アタッチされているといわれていたこのスクリプト、さぁどんなのかな！
## クラス属性
このクラスの属性には```[RequireComponent(typeof(SphereCollider))]```が指定されています。
このスクリプトを使うにはSphereColliderが必要だよってことですね。
個人開発だとあんまり使わなかったりしますが、絶対に使ったほうがいい。
## 継承
```Intaractive```なるクラスが継承されていますね。あとから触れますか…
## OnHoverInとOnHoverOut
見慣れない属性と見慣れない型を使った変数が２つありますね。
### ReorderableList属性
Re order able List = 並び替え可能なリストですね。
Unity公式が提供するエディタ拡張だそう。詳しく解説してくれている記事があるのでリンクしておきます。

https://light11.hatenadiary.com/entry/2019/04/13/233049

### Callable型
ここで、速報です。この型、別パッケージのGameplay Ingredientsから提供されているようです。
流石にこれまで解説していると厳しいのでドキュメントを貼っておきます。

私の認識はちょっと便利なUnityEventです。（有識者の方あってますか…？）

https://peeweek.readthedocs.io/en/latest/gameplay-ingredients/callable.html

## Hover関数
どうやら、処理から推測するにマウスがオブジェクトに入ったときと出たとき呼び出される関数のようですね。
### 引数
#### IntaractiveUser
これも、Gameplay Ingredientsのクラスでした。このパッケージ理解のほうが大事…？
#### State
これは現在マウスがオブジェクトに入っているか出ているか…というもののようですね。
### 処理内容
stateによってそれぞれの処理を走らせるというだけですかね…？
## CanInteract関数
これは、```override```ついていることから継承から来ている関数ですね。
操作できるかどうかを返す変数だそうです。

処理は下の関数と最大距離を比較しているようです。
なんで２乗しているかは下のスクリプトを見れば分かる！

https://docs.unity3d.com/ja/2022.2/ScriptReference/Vector3-sqrMagnitude.html

## このスクリプトのまとめ
ホバーの処理を書く用のクラスでしたね。
ただ、これだけでは動かないのは明白でしたね。
あとGameplay Ingredientsが気になるお年頃になりました。
# Interactive.cs
先ほどのARUI Interactiveクラスの親クラスを見ていきましょう。
といっても特にみる場所はないかもしれません。
## OnEnableとOnDisable
これを見るに、これでIntaractiveManagerに登録しておくことで次に紹介するInteract関数が呼び出されるっぽいですね。
## Interact関数
if文の中身がなぜ２つあるのかは分かりませんが、操作できる条件がそろっているか確認しOnInteractに登録されているイベントを発火させているようですね。
## このスクリプトのまとめ
なんかARUIIntaractiveが動く原理を垣間見た気がします。
でも、結局はGameplay Ingredientsを理解しないといけなさそうですね。
# 今日はここまで！
VFXの勉強をしに来たはずが、面白そうなパッケージGameplay Ingredientsに出会ってしまいました。
というか全くVFXの勉強はできてないですね。

Gameplay Ingredientsに関しては日本語記事が全くないので今度調べてまとめます。
お楽しみに！
ロボット指令パケットの複線化

イーサネットフレーム転送プログラム（RAWソケットプログラム）
http://kirihari.net/program/L2Forwarder.html

データリンク層の Raw ソケットを作成してデータの送受信を行う
https://qiita.com/sira/items/a0e8c5e523bc9bedc803
SQLのGROUP BY句、HAVING句、ORDER BY句の使い方まとめ

<h1>・はじめに</h1>
今回使う表はこちらです。

`商品テーブル`
|商品ID|商品名|商品分類|販売単価|仕入単価|登録日|
|---|---|---|---|---|---|
|1|Tシャツ|衣服|1000|500|2009-09-20|
|2|穴あけパンチ|事務用品|500|320|2009-09-11|
|3|カッターシャツ|衣服|4000|2800||
|4|包丁|キッチン用品|3000|2800|2009-09-20|
|5|圧力鍋|キッチン用品|6800|5000|2009-01-15|
|6|フォーク|キッチン用品|500|　|2009-09-20|
|7|おろしがね|キッチン用品|880|790|2008-04-28|
|8|ボールペン|事務用品|100|　|2009-11-11|

<h1>・GROUP BY句とは</h1>
　<b>GROUP BY句</b>はSELECT文と集約関数と組み合わせて使い、<b>検索結果をグループ分け</b>するものです。

先にGROUP BYを使わない検索結果を見ていきます。
`SELECT COUNT(商品分類) FROM 商品`
結果＝＞

|COUNT(商品分類)|
|---|
|8|

となります。

次にGROUP BYを使ってみます。
`SELECT 商品分類, COUNT(*) FROM 商品 GROUP BY 商品分類`とすると
結果＝＞

|商品分類|COUNT|
|---|---|
|衣服|2|
|事務用品|2|
|キッチン用品|4|

という結果が出ます。

このようにGROUP BY句は<b>検索結果を分類</b>してくれます。

<h4>・検索結果にNULLがある場合</h4>
　通常、COUNTの引数にカラムを指定するとNULLは排除されます。

`SELECT COUNT(仕入単価) FROM 商品;`
結果＝＞

|COUNT(仕入単価)|
|---|
|6|

　GROUP BY句を使うと分類に加えてNULLが指定されているのが何件あるか見ることができます。

`SELECT 仕入単価, COUNT(*) FROM 商品 GROUP BY 仕入単価;`
結果＝＞

|仕入単価|COUNT|
|:-:|:--:|
|　 | 2 |
|320|1|
|500|1|
|5000|1|
|2800|2|
|790|1|

<h1>・Having句とは</h1>
　Having句とはGROUP BY句でグループ分けしたものを<b>条件指定する</b>ものです。

まずHaving句を使わないものを見ます。
`SELECT 商品分類, COUNT(*) FROM 商品 GROUP BY 商品分類`
結果＝＞

|商品分類|COUNT|
|---|---|
|衣服|2|
|事務用品|2|
|キッチン用品|4|

この表をさらに条件指定する際にHAVING句を使います。例えば<b>COUNTが2</b>を選択する場合

`SELECT 商品分類, COUNT(*) FROM 商品 GROUP BY 商品分類 HAVING COUNT(*) = 2;`
結果＝＞

|商品分類|COUNT|
|---|---|
|衣服|2|
|事務用品|2|

このようにCOUNTが2のものを選択できます。

<h1>・HAVING句とWHERE句の使い分け</h1>
　HAVING句は<b>２つ以上の行に渡って条件指定</b>をする際に、WHERE句は<b>１つの行に対して条件指定</b>をする際に使います。

<h1>・ORDER BY句とは</h1>
　<b>ORDER BY句</b>とはカラムの並び順を昇順または降順に変えるものです。

　
　先にORDER BY句なしの文を打ってみます。例えば
　　`SELECT 商品ID, 商品名, 販売単価 FROM 商品;`

|商品ID|商品名|販売単価|
|---|---|---|
|1|Tシャツ|1000|
|2|穴あけパンチ|500|
|3|カッターシャツ|4000|
|4|包丁|3000|
|5|圧力鍋|6800|
|6|フォーク|500|
|7|おろしがね|880|
|8|ボールペン|100|

　この文では並び順はランダムになります。（作った順？）

　そこでORDER BY句を使って販売単価の並び方を変えてみます。
`SELECT 商品ID, 商品名, 販売単価 FROM 商品 ORDER BY 販売単価`

すると、販売単価の低い順（昇順）に並びます。

|商品ID|商品名|販売単価|
|---|---|---|
|8|ボールペン|100|
|2|穴あけパンチ|500|
|6|フォーク|500|
|7|おろしがね|880|
|1|Tシャツ|1000|
|4|包丁|3000|
|3|カッターシャツ|4000|
|5|圧力鍋|6800|

　もし表にNULLがある場合はNULLは<b>先頭もしくは一番後ろに</b>まとめられる。

`NULLがある表`
|商品ID|商品名|仕入単価|
|---|---|---|
|1|Tシャツ|500|
|2|穴あけパンチ|320|
|3|カッターシャツ|2800|
|4|包丁|2800|
|5|圧力鍋|5000|
|6|フォーク|　|
|7|おろしがね|790|
|8|ボールペン|　|

仕入単価の並びを<b>降順</b>に並べると
`SELECT 商品ID, 商品名, 仕入単価 FROM 商品 ORDER BY 仕入単価 DESC;`

|商品ID|商品名|仕入単価|
|---|---|---|
|5|圧力鍋|5000|
|3|カッターシャツ|2800|
|4|包丁|2800|
|7|おろしがね|790|
|1|Tシャツ|500|
|2|穴あけパンチ|320|
|6|フォーク|　|
|8|ボールペン|　|

<h4>・昇順と降順</h4>
　`ORDER BY カラム DESC`とうつと降順（値の大きい順）になります。<b>ASC</b>を打つと昇順になりますが、省略すると自動的に昇順になるので実際に打つことは少ないかもしれません。

<h4>・ORDER BY句テクニック</h4>
　ORDER BY句は別名を付けることのできる<b>AS</b>を使うことができます。<br>
　WHERE句ではASを使った別名を条件指定に使うことができませんが、ORDER BY句では使用することができます。
<br>
<br>
　また、ORDER BY句には<b>集約関数</b>を使うことができます。

`SELECT 商品分類, COUNT(*) FROM 商品 GROUP BY 商品分類`とすると
結果＝＞

|商品分類|COUNT(*)|
|---|---|
|衣服|2|
|事務用品|2|
|キッチン用品|4|

こうなります。

ここで<b>ORDER BY</b>を使って並べ替えます。
`SELECT 商品分類, COUNT(*) FROM 商品 GROUP BY 商品分類 ORDER BY COUNT(*) DESC;`
結果＝＞

|商品分類|COUNT(*)|
|---|---|
|キッチン用品|4|
|衣服|2|
|事務用品|2|

このようにORDER BY句は<b>集約関数</b>を使って降順に並べ替えることができます。
Amplify-js＋Viteでエラーになった件

amplify-jsでCognitoの認証を実装する際に困ったことと解決方法を残しておきます。
同じところで詰まってる方がいたら参考にどうぞ。

# global is not definedが発生する
## 発生した事象
amplify-jsをimportしたコンポーネントをレンダリングすると真っ白の画面になると思います。ブラウザの開発者ツールのコンソールには"global is not defined"と表示されています。
![20230505_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121050/9684b157-c50a-0e5f-b2b8-fc4e32c214c1.png)
## 解決法
"global is not defined"はglobalが定義されていませんという意味です。
globalはnode.jsで使用されるグローバルオブジェクトであり、JavaScriptではwindowを指します。

Viteを使用している場合は、vite.config.jsに以下の記述を追加してください。

```javascript:vite.config.js
export default defineConfig({
  // 省略
  define: {
    global: 'window',
  },
})
```

amplify-jsはnode.jsでも利用される万能なパッケージなので、この辺はViteに限らずjsならどの環境でも発生するんじゃないかと思います。
（ちなみに、amazon-cognito-identity-jsでもCognitoの認証処理は実装可能です。ただ、amplify-jsによってラップされているので、amazon-cognito-identity-jsをわざわざ使わなくてもよいですね）

# "request" is not exported by "__vite-browser-external"が発生する
## 発生した事象
buildすると次のエラーが発生します。

"request" is not exported by "__vite-browser-external", imported by "node_modules/@aws-sdk/credential-provider-imds/dist/es/remoteProvider/httpRequest.js"

![20230505_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121050/a89a25ba-b028-b9a4-11b5-d217d74e9bb1.png)

## 解決法
こちらもamplify-jsがnode.js固有の機能を使っていることに起因するものですね。"http"パッケージがインストールされていないという意味のようです。

Viteを使用している場合は、vite.config.jsに以下の記述を追加してください。

```javascript:vite.config.js
export default defineConfig({
  // 省略
  resolve: {
    alias: {
      "./runtimeConfig": "./runtimeConfig.browser",
    },
  },
})
```

# 補足事項
amplify-jsの利用にあたり、「Amplifyを使用していないのにamplify-jsって使えるのか？」という疑問がありましたが、Amplifyを使用していなくてもamplify-jsでCognitoの認証は可能でした。

上記のエラーは、React、Vue.jsに限らず同じ解決法で解決できると思います。
富士通メインフレームは○×□が不便　〜SQL〜

COBOLプログラムでSQLを使用する場合、EXEC SQLとEND-EXECの間にINSERTやSELECTを記述するのは富士通もIBMと同じです。

---
#### 埋め込み型とプレコンパイラ
富士通COBOLコンパイルでコンパイルしたロードモジュールは、PFD-BROWSEするとSQL文が目視できます。SQLは[インタプリタ](https://ja.wikipedia.org/wiki/インタプリタ)なので、当然なのかもしれません。そのため実行時にSQLの構文エラーが発覚しテストが中断してしまいます。

z/OSの場合コンパイルの前にプレコンパイルが必要です。プレコンパイラはSQLをサブルーチンCALLに書き換えるので、SQLに構文エラーがあるとこの時点で検出できます。

#### SQL関数
富士通 RDB II はANCII規格準拠のため使用可能な関数は5種類のみです。
 - AVERAGE
 - COUNT
 - MAX
 - MIN
 - SUMMARY

DB2はたくさんあります。
PythonでGoogle Cloud StorageにPDFをアップロード/ダウンロード/削除

# はじめに
Pythonを利用してGoogle Cloud StorageにPDFをアップロードやダウンロード、削除する手順です。

Pythonでpdfファイルを受け取るAPIサーバを構築した際に、Byte形式で受け取ったままPDFファイルをアップロードしようとして少し詰まったので備忘録です。

<details><summary>ソースコードの全体像</summary><div>


下記のGistを参照
- https://gist.github.com/sey323/1528ed17aff494078fa4fa5e5e0b6bd8

</div></details>



# 事前準備

Google Cloud Storageを利用するために`google-cloud-storage`のライブラリをインストールする。

```sh:
pip install google-cloud-storage
```

下記の手順を参考に認証情報を作成し`secret.json`として保存する。

https://qiita.com/sey323/items/875c0ab1585044772ab2#%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%81%AE%E4%BD%9C%E6%88%90

# 実装

## PDFファイルを操作するラッパークラスの作成

Google Cloud Storageを利用するためラッパークラスを定義する。

```python:gcp.py
from google.cloud import storage

class GoogleCloudStorage:
    def __init__(self, bucket_name:str,cred_path: str) -> None:
        _storage_client = storage.Client.from_service_account_json(cred_path)
        self._bucket = _storage_client.bucket(
            bucket_name 
        )
        print(
            f"Google Cloud Storage Initialize Complete!. bucket name: {self._bucket.name}"
        )

    def upload(self, data: bytes, destination_blob_name: str) -> str:
        blob = self._bucket.blob(destination_blob_name)
        generation_match_precondition = 0

        blob.upload_from_string(
            data,
            content_type="application/pdf", # ←content_typeを指定する必要あり。
            if_generation_match=generation_match_precondition,
        )

        print(f"File uploaded to {destination_blob_name}.")


    def download(self,destination_blob_name: str) -> bytes:
        blob = self._bucket.blob(destination_blob_name)
        print(f"File download from {destination_blob_name}.")

        return blob.download_as_bytes() # Byte形式でダウンロード


    def delete(self,destination_blob_name: str):
        blob = self._bucket.blob(destination_blob_name)
        print(f"Delete file, {destination_blob_name}.")
        if blob.exists():
            blob.delete()
```

バケット名と認証情報を引数とし、下記のように初期化する。

```python:main.py
from gcp import GoogleCloudStorage

GOOGLE_CLOUD_STORAGE_BUCKET_NAME = "test" # 保存するバケットの名称、任意の名称を指定する。
CREDENTIAL_PATH="secret.json" # Google Cloud Storageの認証情報

gcs = GoogleCloudStorage(GOOGLE_CLOUD_STORAGE_BUCKET_NAME,CREDENTIAL_PATH)

~~省略~~
```

## アップロード

適当なPDFファイルを用意して`FILENAME`に指定する。

```python:
~~省略~~

FILENAME = "sample.pdf"

# アップロード処理
with open(FILENAME, 'rb') as f:
    binary = f.read()
    gcs.upload(binary, FILENAME)

~~省略~~
```

Google Cloud Storageの`GOOGLE_CLOUD_STORAGE_BUCKET_NAME`に指定したバケットに、`FILENAME`で指定した名称でファイルが保存される。

## ダウンロード

バケット上に存在する、`FILENAME`で指定したファイルをダウンロードする。

```python:main.py
~~省略~~

# ダウンロード処理
download_byte = gcs.download(FILENAME)
with open("download.dpf", "wb") as f:
    f.write(download_byte)

~~省略~~
```

## 削除

バケット上に存在する、`FILENAME`で指定したファイルを削除する。

```python:main.py
~~省略~~

# 削除
gcs.delete(FILENAME)

~~省略~~
```
PythonやRからTikzに変換して簡単にレポートを作ろう

# レポート課題を美しく書きたいけど、めんどくさい

本稿は備忘録を目的として作成しています。初心者なので、よりよい方法があれば教えて下さい。

こう思った経験は皆さんあると思います。理系大学生の読者諸賢の方は、wordよりもTexを利用する方のほうが多いかもしれません。Texはたしかに便利なツールですが、その仕様などを覚えていこうとすると、存外時間がかかります。
特に図を描くのは大変です。主に次の二つ方法があります。

1：画像作成の外部ツールを利用して画像ファイルを挿入する
2：Tikzを使う

今回、紹介するのはPythonのライブラリを使って、描画した図をそのままTex側に渡すという方法を考えます。したがって、受験数学の幾何問題の図を作るなどの作業には適していません。実験のレポート課題や学部や修士の研究論文で使ってみてください。

初心者なので、よりよい方法があれば教えて下さい。
# Pythonの場合
## 手順0：Tex環境を用意する
これは省略します。ただし、該当のプリアンブルには
```
\usepackage{pgfplots}
```
を追加しておいてください。
## 手順1：tikzplotlibのインストール
ライブラリをインストールしてください。
```python
pip install numpy
pip install matplotlib
pip install tikzplotlib
```
## 手順2：グラフを作成する
matplotlibでグラフを作成しましょう。テストファイルを用意しました。
```python
import numpy as np
import matplotlib.pyplot as plt
import tikzplotlib

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

plt.plot(x, y)
plt.xlabel("$x$")
plt.ylabel("$\sin(x)$")
plt.title("Plot of $\sin(x)$")

tikzplotlib.save("sinx_plot_tikz.tex")
```
実行した後は、エクスプローラーを見ればTexファイルを生成されていることを確認してください。

## 手順3：Tex環境で読み込む
importを利用してファイルを読み込みましょう。必ずコンパイルするファイルと同一階層に生成したファイルを置いて、次のコードを読み込んでください。
```python
\begin{figure}[ht]
  \centering
  \input{sinx_plot_tikz.tex}
  \caption{Plot of $\sin(x)$}
\end{figure}
```
すると、matplotlibで生成した$\sin{x}$のグラフが読み込まれていることが確認できると思います。

## 改善案
いちいちタイトルを付けなおすのは面倒です。なので、タイトルは入力として受け取れることにしましょう。
```python
title_input = input("Enter the plot title: ")
tikzplotlib.save(f"{title_input}.tex")
```
を追加してください。またtex内のcaptionも変更しておいてください。

# Rの場合
ほとんど同じ感覚で出力できます。統計のヒストグラムなどを用いる際は、こちらのほうが使われるかもしれません。（Rをあまり使ったことがないので雑なのはお許しください）
```r
install.packages("tikzDevice")
```
で必要なものをダウンロードをして
```r
library(tikzDevice)

tikz("output_tikz.tex")

plot(x = rnorm(100), y = rnorm(100), main = "Scatterplot Example")
dev.off()
```
とします。
これは散布図のサンプルコードですが、ほかのものでもできるはずです。
同様に同一階層に出力するようにしておくとコンパイルのときにファイルを移動させる手間が省けて便利です。
DB設計アンチパターン

## はじめに
今回DB設計についての書籍を読み、今後作成するにあたりこアンチパターンを行わないように戒めとして記事にしました。
まだまだ初学者になりますのでおかしな部分あればご指摘いただければと思います。
アンチパターンについて自分なりの解釈を書き残しておきます。
まだ設計に関して学習始めたばかりなので今後ここに追記して具体性持たせることができればと思います。

## アンチパターン
### 単一参照テーブル
多すぎるテーブルを１つにまとめてしまい、参照する際に検索は楽だが、応用性が全くないパターン

### ダブルミーニング
列に違う意味を持った値を入れれるように更新してしまうパターン

### 非スカラ値
配列として入れれるようになったこともありカラムに複数の値を入れてしまうパターン

### テーブル分割(水平分割)
テーブルを行で分割し売上を年度別で分けた例→年を跨いだ総売上など出せない。パーティション機能で代替可能
### テーブル分割(垂直分割)
テーブルを列で分割したパターン。代替案として集約(データマート、サマリテーブルがある)。データマートは同じデータ持っているが使用頻度の高いものを小さなテーブルとしてもう1つ作ること。(マテリアライズドビューという機能で代替可能)サマリテーブルは平均や合計などよく参照するのであればその値を持ったテーブルを作ってしまうこと。どちらも更新のタイミングが遅いと統合性なくなるし、細かくしすぎるとデータ更新の負荷がかかり本末転倒になる場合もある。

### 不適切なキー
結合キーになる部分や主キーは不変のものである必要があるのに対し可変長文字列と固定長文字列がのデータ型が混在してしまうと2つは空白部分埋める違いなどがあるので整合性が取れない。最初から固定長文字列型に揃えておくべき。

### ダブルマスタ
同じ列で同じ役割を持つテーブルが複数存在するパターン。企業の統廃合によって起こりがち。

## おわりに
今回下記の書籍読ませていただき学んでおります！
実際の経験がないため今はまだ頭の中にインデックスとして残している状態なのでいざ設計し始めた時にこの記事に戻ってきて編集ができるよう精進いたします！
ありがとうございました！
[達人に学ぶDB設計徹底指南書](https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6DB%E8%A8%AD%E8%A8%88-%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8-%E5%88%9D%E7%B4%9A%E8%80%85%E3%81%A7%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E3%81%82%E3%81%AA%E3%81%9F%E3%81%B8-%E3%83%9F%E3%83%83%E3%82%AF/dp/4798124702/ref=asc_df_4798124702/?tag=jpgo-22&linkCode=df0&hvadid=295686767484&hvpos=&hvnetw=g&hvrand=566781524506915725&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009523&hvtargid=pla-524606337769&psc=1&th=1&psc=1)
人に仕事を振れないパイセン向け：３時間で読めて一生使える本３選

## はじめに

開発者として経験を積んで、**「人に頼むよりも自分でする方が早いから」** という考えに固執し、**「人に頼まず自分でやってしまう」** という壁にぶつかることがあるかもしれません。リーダーに昇格した直後などは、自分で仕事をした経験はあるけれど、人に頼んだ経験がないなどの理由でそのような選択をするかもしれません。

頼んだ相手が自分よりも大きな見積もりを出してしまうことがあります。その場合、自分に多くの作業を割り振ってしまい、**「自分だけが忙しくなる状況」** に陥ってしまうこともあります。

そこで今回は、簡単に読めてこういった状況を避けるのに役に立つ本を3冊程紹介したいと思います。


## 最強のエンジニアになるための話し方の教科書
> 技術力(200%) x 伝える力(0) = 真のパフォーマンス(0)

(出典：最強のエンジニアになるための話し方の教科書)

どんなに技術力があってもちゃんと伝えないとダメなんだなぁということが茶番形式（？）で書かれていて読み物としてもおもしろい本でした。

[⇒ amazon : 最強のエンジニアになるための話し方の教科書](https://www.amazon.co.jp/%E6%9C%80%E5%BC%B7%E3%81%AE%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E8%A9%B1%E3%81%97%E6%96%B9%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%BA%80%E5%B1%B1-%E9%9B%85%E5%8F%B8/dp/483780487X)


## なぜ、あなたの話はつまらないのか?

基本的な会話の構造をとてもロジカルに説明しており、面白い話ができるようになるというよりは、日常のコミュニケーションが円滑にできるようになるのに使える印象の本でした。

IT業界では、プログラムを書く以外にも、よきパイセンとして新人と会話できたり適切に若者を導く能力も要求されたりするので読んでおいても損はないかと思いました。

[⇒ amazon : なぜ、あなたの話はつまらないのか?](https://www.amazon.co.jp/%E3%81%AA%E3%81%9C%E3%80%81%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E8%A9%B1%E3%81%AF%E3%81%A4%E3%81%BE%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B-%E7%BE%8E%E6%BF%83%E9%83%A8-%E9%81%94%E5%AE%8F/dp/4860636740)


## 伝わる! 文章力が身につく本 (基礎からわかる"伝わる!"シリーズ)

80のコツが、それぞれ悪い例→改善例を含む見開き１ページの解説となっていて辞書的に利用できそうな本でした。文章の構成については基本的な考え方が示されていました。

基本をきちんと学んで丁寧に実践していくのが上達の近道だと思うので、一度は目を通しておいてもよさそうな本に思えました。

[⇒ amazon : 伝わる! 文章力が身につく本 (基礎からわかる"伝わる!"シリーズ)](https://www.amazon.co.jp/%E4%BC%9D%E3%82%8F%E3%82%8B-%E6%96%87%E7%AB%A0%E5%8A%9B%E3%81%8C%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8F%E6%9C%AC-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%82%8F%E3%81%8B%E3%82%8B%E2%80%9C%E4%BC%9D%E3%82%8F%E3%82%8B-%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%B0%8F%E7%AC%A0%E5%8E%9F/dp/4471191160)


## おわりに

本の内容を総じて見ると、共通して言えることは **「聞き手や読み手のことを考える」** ということでした。プログラムだけを書いている場合、その経験を積むことが難しいと思われるので、何らかの方法でその経験を積む必要があると感じました。

また、設計書については、過去の設計書を参考に書くことが多いですが、完成した設計書を見ても、「なぜそのような書き方になったのか」を読み取ることは難しいです。そのため、「伝わる！文章力が身につく本」を先に読んでから設計書を書いてもらうことで、教育コストが下げられる様に思えました。

少し俯瞰した目線で業務を見てカイゼンするきっかけなどになれば幸いです。


## おまけ０

https://qiita.com/kaku3/items/9763f547d497e6f02caf

## おまけ１（新卒エンジニア向け手紙）

https://qiita.com/kaku3/items/2c8d4d783be7ce4fc9ea

https://qiita.com/kaku3/items/0bf1703cb8d6f84afbc5


## おまけ２（新卒エンジニア向け記事）

https://qiita.com/kaku3/items/fb949aa1a53f1f71c796

https://qiita.com/kaku3/items/aa2f81cf1e3974b8ad3a

https://qiita.com/kaku3/items/937354cc180c8bee823b

https://qiita.com/kaku3/items/b1c94328f273c750286b

## おまけ３（...は難しいシリーズ）

https://qiita.com/kaku3/items/f8411523cce000de750e

https://qiita.com/kaku3/items/5b11d2e1aace73c36340

https://qiita.com/kaku3/items/34b40446337a59213a75

## おまけ４（営業A短編シリーズ）

https://qiita.com/kaku3/items/03aae7b9e3c70c55f513

https://qiita.com/kaku3/items/3378ea55b1240d7360a1


## おまけ５（エンジニアのためのお仕事問題集）

2030年にIT人材が最大79万人不足するらしいので、学習用の資料をgitで**無料**公開してます(不定期更新)。
よろしければどうぞ。

[エンジニアのためのお仕事問題集](https://github.com/kaku3/workbooks)
Typescriptのsatisfiesが便利だと言う話

TypeScript 4.9で追加された`satisfies`オペレータが便利なので紹介します。

## 一時変数が不要になる

例えばwindow間通信でpostMesssageを送りたい時


``` typescript
window.parent.postMessage({
    type: 'start',
    value: 'hoge'
});
```

ここでpostMessageで受け取る引数の型はany型なのでオブジェクトが期待する値なのかチェックするためには別の変数で一旦定義する必要がありました。

``` typescript

type WindowRequest = {
    type: string;
    value: string;
}

const req:WindowRequest = {
    type: 'start',
    value: 'hoge'
}

window.parent.postMessage(req);
```

`satisfies`オペレータを使うことで次のように記載することができるようになります。
``` typescript

type WindowRequest = {
    type: string;
    value: string;
}

window.parent.postMessage({
    type: 'start',
    value: 'hoge'
} satisfies WindowRequest);
```
`satisfies`を使うことで一旦別の変数を経由する手間を省くことができました。

## as constとの組み合わせで型チェックしつつ型推論を残す

オブジェクトの型をチェックしたいが型推論を残したい時にも利用できます。


例えば`User`型を満たす定数`hogeUser`を定義したとします。
この時型注釈のみつけた場合

``` typescript

type User = {
    name:string;
    age:number;
}

const hogeUser:User = {
    name:"hoge";
    age:20;
}

```

次のように後から値の書き換えが可能になってしまい定数としての補償ができなくなっていしまいます。

``` typescript
hogeUser.name = "fuga"
```


ここで `as const`オペレータを付けることで値の書き換えをしようとするとエラーが出るようになりました。

``` typescript

type User = {
    name:string;
    age:number;
}

const hogeUser: User = {
    name:"hoge";
    age:20;
} as const

```

しかしこの定義の仕方だと`hogeUser`は`as const`をつけているので値は必ずhogeと20で推論されて欲しいところhogeUserの型推論が`name:string;` `age:number;`となってしまいます。
これは型注釈をつけた場合は型推論が失われてしまうため起こります。

この時`satisfies`を用いて次のように定義することで

``` typescript

type User = {
    name:string;
    age:number;
}

const hogeUser = {
    name:"hoge";
    age:20;
} as const satisfies User

```

hogeUserの型推論が`{readonly name: "hoge", readonly age: 20}`となり

型チェックを行いかつ型推論結果を保持することができるようになります。
neosでlogix その135

# 概要
neosでlogixやってみる。
練習問題やってみた。

# 練習問題
websocketで、俺言語を実行せよ。

# 写真

![2023-05-05 07.37.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3bf0a806-675c-7c50-22a7-8a45100e3142.jpeg)

# サーバーは、これ。

https://qiita.com/ohisama@github/items/f2a015f1590e18fb0c7b

# 手順
- websocketサーバーを起動。
- transceiverを実行する。


以上。
github用.gitconfig

githubの自分のリポジトリ用の.gitconfig
自分以外のアカウントに対しては認証しないように。

## .ssh/config
```plane
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/秘密鍵
  User git
```

## .gitconfig

```plane
[url "github:アカウント/"]
        InsteadOf = https://github.com/アカウント/
        InsteadOf = git@github.com:アカウント/
```
preactのToDoアプリをTypescriptで実装するサンプル

## TypeScript ✕ preact のToDoアプリサンプル

#### 環境の構築手順

#### preact-cliのインストール

コマンドプロンプトまたはターミナルを開いて、以下のコマンドを実行し、Preact CLIをインストールする
```
npm install -g preact-cli
```

#### プロジェクトの作成
Preact CLIを使用して、TypeScriptでのプロジェクトを作成するため、以下のコマンドを実行する
```
preact create typescript my-todo-app
cd my-todo-app
```

#### パッケージのインストール
作成されたプロジェクトディレクトリに移動し、必要な依存関係をインストールする。
```
yarn install
```

### ToDoアプリの実装


`src/components/app.tsx`を以下のように編集する

```typescript
import { h, FunctionComponent } from 'preact';
import { useState } from 'preact/hooks';

type Todo = {
  id: number;
  text: string;
  completed: boolean;
};

const App: FunctionComponent = () => {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [input, setInput] = useState<string>('');

  const addTodo = () => {
    if (input.trim() !== '') {
      setTodos([
        ...todos,
        { id: Date.now(), text: input.trim(), completed: false },
      ]);
      setInput('');
    }
  };

  const toggleTodo = (id: number) => {
    setTodos(
      todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  const deleteTodo = (id: number) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  return (
    <div>
      <h1>Todoアプリ</h1>
      <input
        type="text"
        value={input}
        onInput={(e) => setInput((e.target as HTMLInputElement).value)}
      />
      <button onClick={addTodo}>追加</button>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            {todo.text}
            <button onClick={() => deleteTodo(todo.id)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;
```

#### 実行

以下のコマンドを実行し、ローカルサーバ上でWebアプリを表示する

```
yarn dev
```
neosでlogix その134

# 概要
neosでlogixやってみる。
練習問題やってみた。

# 練習問題
websocketで、forthを実行せよ。

# 写真

![2023-05-05 07.18.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/24fbfb2f-9ac7-9bdc-72eb-d2dc40bd7328.jpeg)

# サーバーは、これ。

https://qiita.com/ohisama@github/items/8edfc49f9eedde0940ff

# 手順
- websocketサーバーを起動。
- transceiverを実行する。


以上。
Turbo Streams とセキュリティの話。Turbo Rails Tutorial をやってみた（6章）

本記事は、🔽「Turbo Rails Tutorial」の学習を進めていく際の個人メモです！

https://www.hotrails.dev/turbo-rails

🔽 前章の記事はこちら

https://qiita.com/yuppymam/items/de3f5311418d77f627db

# 6章 [Turbo Streams and security](https://www.hotrails.dev/turbo-rails/turbo-streams-security)
この章では、Turbo Streamsセキュリティの仕組みについて学びました。具体的には、5章までに作成してきた「見積もり」作成アプリにログイン機能をつけ、以下の実験をしました。

## やりたいこと
ログイン後、同じ`campany`内のメンバーであれば、その`campany`内の見積もりがリアルタイムに更新される。違う`campany`のメンバーは他の`cammpany`の見積もりは閲覧できない。

## 実験
本章に記載しているコードの通り進め、`index`アクションでは「自分の`campany`の見積もりの一覧表示」を表示するよう実装します。

まずは同じ`KPMG`という`campany`同士のメンバーで確認。問題なく見積もりがリアルタイムに共有されます。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293962/f4723de1-c0f0-893c-bcf8-dfe1f97dc527.gif)


今度は右のブラウザ（シークレットウィンドウ）で`PwC`という`campany`のメンバーでログインしています。すると、他の`campany`なのに、リアルタイムで見積もりが表示されてしまうというバグが発生。
![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293962/d0a12f53-98b5-6ae5-6f3f-b3b908c0c679.gif)

ちなみに見積もりとして保存されてはいないので、`PwC`側ではリロードすると消えます。

![output3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293962/caca48b4-97dd-2997-494f-96ff3fae4c37.gif)

## 何がまずいのか？
ブラウザの検証で、以下の`<turbo-cable-stream-source>`タグを確認してみると、どのユーザーでログインしてもすべて同じ`signed-stream-name`を使用していることが分かりました。
```
<turbo-cable-stream-source channel="Turbo::StreamsChannel" signed-stream-name="InF1b3RlcyI=--fcf8a7eb5aea37a4a80930967e3332d3a48ba0f5ab12e509c7cce8f7175a17fc" connected=""></turbo-cable-stream-source>
```

このせいで、先ほどのバグが起こっていました。

## 対策
Streams名を、`campany`ごとに変更する必要があります。
```app/models/quote.rb
class Quote < ApplicationRecord
  .
  .
  broadcasts_to ->(quote) { [quote.company, "quotes"] }, inserts_by: :prepend
end
```

受け取る側も変更します。
```app/views/quotes/index.html.erb
<%= turbo_stream_from current_company, "quotes" %>
```

## 確認
これでバグが解消しました。`<turbo-cable-stream-source>`タグ内の`signed-stream-name`が、`campany`ごとに別のものを使用するようになったことも確認できました。
![output4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293962/f54c9432-b134-36d7-8543-d238efa32795.gif)


## まとめ
Turbo Streams を使用する際は、モデルの`broadcasts_to`メソッドとビューの`turbo_stream_from`メソッドが適切に設定されていることを確認してから利用すること。テストでしっかり確認しながら開発することが大事ですね！

次の章は、Hotwire を使用したフラッシュメッセージについて学びます。

https://www.hotrails.dev/turbo-rails/flash-messages-hotwire
FreeBSDのgpiospiのFDT対応

FreeBSDのgpioは10年位前にFDTと同時くらいに改修されました。

それまではgpioデバイスは一つしかサポートしいませんでした。またビットフィールドを使っていたので32個しかサポートしていません。しかし最近のSOCは複数のgpioを持っていたり32個以上のpinがあることもざらです。

rayが作ったgpioを使ったbitbangのspiドライバーは以下のようなhintsを書いてました。

```
hint.gpiospi.0.at="gpiobus0"
hint.gpiospi.0.pins=0x78
hint.gpiospi.0.cs0=0
hint.gpiospi.0.sclk=1
hint.gpiospi.0.mosi=2
hint.gpiospi.0.miso=3
hint.gpiospi.0.freq=100000000
```

これの読み方はpinsの値のビットが立っている3,4,5,6ビットが使われてcs0がその0番目すなわり3になります。

これをFDT対応するのに新しいkpiに変更しました。

```
        spi1: spi@gpio0 {
                compatible = "spi-gpio";
                pinctrl-names = "default";
//              pinctrl-0 = <&spi2_pins_cfa10049>;
                status = "okay";
                gpio-sck = <&gpio0 4 0>;
                gpio-mosi = <&gpio0 5 0>;
                gpio-miso = <&gpio0 6 0>;
                cs-gpios = <&gpio0 3 0>;
                num-chipselects = <1>;
                #address-cells = <1>;
                #size-cells = <0>;
```

gpioiicはすでにFDT対応していたので、これを参考にしました。

spibusはFDT(OFW)用のが用意されていて、デバイス名がgpiospiだとロードされないためspiにしました。

もちろんhintsでもちゃんと動きます。
GASでのAPIリクエストにつまづいた人必見！自社サービスAPIへPOSTリクエストを送る方法とポイント

スプレッドシートと自社サービスAPIを連携させて業務効率化ツールを作ろうとした際に詰まったポイントをまとめました。同様の処理を実装しようとしているが、うまく出来ないという方の参考になれば幸いです。

１つ目、JavaScriptからリクエストを送る際に特にPOSTリクエストを送る際に、　optionsにheadersとbodyを指定して送ると思います。その際、headerは特にjson変換をせず、bodyはjsonに変換してリクエストを送ることを忘れないで下さい。

実装例：
```GoogleAppScript:postRequest.gs
async function postRequest(baseUrl, authkey) {
  const url = `${baseUrl}/追加事項`;
  const options = {
    method: "post",
    headers: {
      '認証キー': authkey,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      "objectName": "person",
      "items": [{
          "column_code": 902,
          "num": 10186
        },
        {
          "column_code": 903,
          "text": "山田次郎"
        }
      ]
    })
  };

  const response = await UrlFetchApp.fetch(url, options);
  return await response;
}

```
<a href="https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch">詳しく知りたい方はこちらから。</a>

2つ目、GASは、bodyではなく,payloadを使います。調べていただくとわかりますが、bodyとpayloadに差異はありません。ただ、GASの言語仕様上payloadを使用します。
実装例：
```GoogleAppScript:postRequest.gs
async function postRequest(baseUrl, authkey) {
  const url = `${baseUrl}/追加事項`;
  const options = {
    method: "post",
    headers: {
      '認証キー': authkey,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify({
      "objectName": "person",
      "items": [{
          "column_code": 902,
          "num": 10186
        },
        {
          "column_code": 903,
          "text": "山田次郎"
        }
      ]
    })
  };

  const response = await UrlFetchApp.fetch(url, options);
  return await response;
}
```
<a href="https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app?hl=ja">詳しくはこちらから</a>
Nextcloud with Apache2 + php-fpm + PostgreSQL on Docker

【[当研究室のシステム](https://qiita.com/NeK/items/70f994b271b0c1a48590)】

# 概要
Docker起動したらNextcloud動くようにしたもの．
「[Nextcloud with Apache2 + PostgreSQL on Docker](https://qiita.com/NeK/items/e3954e87bb5d55e5c5a5)」をベースに「[Apache2 on Docker + php-fpm on Docker](https://qiita.com/NeK/items/17e32812efc2a44b0b53)」のphp-fpmを組み合わせたもの．
そのまま動くかと思ったのだけど，ドハマリ．分かればすぐ．

## ハマりポイント
「[Nextcloud with Apache2 + PostgreSQL on Docker](https://qiita.com/NeK/items/e3954e87bb5d55e5c5a5)」でインストールしたphpモジュールをphp-fpmでインストールし，設定すればそのまま動く．．．かと思いきや，pdo-pgsqlでハマる．

* 「[Nextcloud with Apache2 + PostgreSQL on Docker](https://qiita.com/NeK/items/e3954e87bb5d55e5c5a5)」ではphp-pgsqlのインストールで，pdo-pgsql, pgsqlがインストールされていた？(とりあえず入れていなくてもpdo-pgsqlがあった)
* php-fpmではpdo-pgsqlを明示的に入れないといけなかった．

# 設定
## apache2
`~/Docker/www/Dockerfile`にて`php-*`を全削除．`php`自体もいらない気がするが．．．
`sed`や`echo`で`/etc/php/以下`に書き込んでいた部分を全部削除．

```dockerfile:~/Docker/www/Dockerfile
FROM ubuntu:22.04

RUN set -x && \
    apt update && apt upgrade -y && \
    DEBIAN_FRONTEND=noninteractive apt install -y \
       apache2 \
       ffmpeg \
       libmagickcore-6.q16-6-extra \
       locales \
       php && \
    locale-gen ja_JP.UTF-8

ENV TZ=Asia/Tokyo LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja

ARG HOSTNAME=www

COPY ./conf /etc/apache2/conf
COPY ./sites-available /etc/apache2/sites-available

RUN echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf && \
    /usr/sbin/a2enconf fqdn && \
    /usr/sbin/a2dismod php8.1 && \
    /usr/sbin/a2enmod proxy_fcgi && \
    /usr/sbin/a2enmod setenvif && \
    /usr/sbin/a2dissite 000-default && \
    /usr/sbin/a2ensite default && \
    /usr/sbin/a2ensite default-ssl && \
    /usr/sbin/a2enmod ssl && \
    /usr/sbin/a2enmod authnz_ldap && \
    /usr/sbin/a2enmod rewrite && \
    /usr/sbin/a2ensite nextcloud && \
    /usr/sbin/a2enmod headers \

EXPOSE 80
EXPOSE 443

CMD ["apachectl","-D","FOREGROUND"]
```

## php-fpm
必要なphpモジュールをインストール．あとffmpegも入れておく(nextcloudのメディア変換を使うので．

```Dockerfile:~/Docker/php-fpm/Dockerfile
...
    apt update && apt upgrade -y && \
    DEBIAN_FRONTEND=noninteractive apt install -y ffmpeg && \
...
    install-php-extensions  apcu bcmath bz2 curl gd gmp exif imagick imap intl ldap mbstring opcache pdo pdo_pgsql pgsql smbclient sysvsem xml zip
...
```

## ビルド&起動
`~/Docker/docker-compose.yml`に`~/Docker/www`と`~/Docker/php-fpm`の情報が入っているので，これを使用([Apache2 on Docker + php-fpm on Docker](https://qiita.com/NeK/items/17e32812efc2a44b0b53))．

```bash
cd ~/Docker
docker compose up -d --build
```

# 運用
## 起動

```bash
cd ~/Docker
docker compose up -d
```

## cronについて
php-fpmに任せることになるので，[Nextcloud with Apache2 + PostgreSQL on Docker](https://qiita.com/NeK/items/e3954e87bb5d55e5c5a5)の「cronについて」にある`/etc/cron.d/nextcloud`を書き換え．

```:ホストの/etc/cron.d/nextcloud
*/5 * * * * root docker container exec --user www-data php-fpm /usr/local/bin/php -f /var/www/nextcloud/cron.php
```
WolframAlphaのグラフをOctaveで描画する方法

## はじめに ##
WolframAlphaには様々な数学に関するデータが集められており、その中には複雑なグラフや絵のようなグラフまで種類は様々です。
今回は最近学習を始めたOctaveにWolframAlphaのグラフデータを描写させるための方法について拙いですがまとめました。

## 手順 ##

1\. 一部数学記号の置き換え
~~~ :数学記号置き換えの例
π　→　pi
Θ　→　heaviside
~~~

2\.媒介変数の定義域を設定

https://ja.wolframalpha.com/input?i=banana+curve

例:banana curve
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292130/caaccf66-8e63-4c78-d4d7-cd3395270221.gif)
赤枠で囲われた範囲を指定。
※この例の場合は0~24π
~~~
for 
    t = 最小値:最大値
end
~~~

3\.'.'（ピリオド）の追加
配列の要素（ここでは媒介変数）を使用する際、演算記号の前に.を追加します。
この関係上、例えば-tをOctaveに変換する場合は-1.*tと表記する必要があります。
（演算記号と演算記号の間に.が存在するとエラーになるため）

4\.虚数部の削除
WolframAlphaではx,yのプロットで場合によって虚数解が出る部分があります。
これにより一筆書きで表示されるグラフから不要なものを表示しないようにしています。
しかしOctaveは虚数解が出るとエラーが出てしまいます。
そのためWolframで表示された数式から虚数解が出る要素（sgn等）は削除します。

## おわりに ##
OctaveはMATLABと一部互換があるようなのでこの方法でMATLABでも描画できるかもしれません。
また、他に良い方法を知っている方はコメントしていただけると幸いです。
【C言語】赤外線リモコン受信モジュールの使い方　［記述途中］

* 使用部品:
赤外線リモコン受信モジュール　ＰＬ－ＩＲＭ０１０１（３７．９ｋＨｚ）シールド付
参考:https://akizukidenshi.com/catalog/g/gI-00622/


# 参考
https://www.hiramine.com/physicalcomputing/raspberrypi3/wiringpi_irreceiver.html
Hugo の {{ .Lastmod }} が 0001/01/01 になるときの解決策

直すのに半日かかりました。

## 原因

`"Foo/_index.md"` を `"foo/_index.md"` にリネームした後に、Gitでは `"Foo/_index.md"` の方でコミットが進んでしまったため、Hugoが参照する `"foo/_index.md"` のコミット履歴がゼロになっていました。

```
$ git log [ファイルパス]
```
で問題のファイルにコミット履歴があるか調べるといいと思います。

Git と MacOS の大文字小文字の区別するしないが原因だと思うので、下手にディレクトリの大文字小文字を変更しないようにしようと思います。
neosでlogix その133

# 概要
neosでlogixやってみる。
練習問題やってみた。

# 練習問題
websocketで、オセロを実行せよ。

# 写真
![2023-05-04 11.24.09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0128d58c-9e9f-6712-0232-713728bc663c.jpeg)

# サーバーは、これ。

https://qiita.com/ohisama@github/items/a247945a37f242dfbd9b

# 手順
- websocketサーバーを起動。
- transceiverを実行する。


以上。
/usr/bin/env: node: Permission denied エラー

参考

https://stackoverflow.com/questions/70931624/usr-bin-env-node-permission-denied

あれ？

```
/usr/bin/env: node: Permission denied
```

npmを再インストールしろとかいう情報もあるが、
それやるとまたバグる。よって、以下で対応した。

```
chown -R root:root .
```