OmniAICreator/Qiita-1.07M huggingface dataset:
NVCユーザー会 #2 に参加しました

# 感想
めっちゃいい体験ができた！
参加された皆様、主催いただいた方々にありがとうの気持ちでいっぱいです。

共感サークルを実施したのですが、
ふりかえりのような、1on1の壁打ちのような体験で
ネガティブな事象にもポジティブな事象にも上手く使えるのを感じました。
ニーズを捉えることで、将来同じような事象にあったとしても上手く扱えそうです。

依存症の方の自助グループなどで
自分の体験を話す際にもこういった手法が使われてるのかもですね。

また、体験前は相手と自分の両方がNVCの考えでないと成立しないのでは？
と思っていましたが、まずは自分がその考えを持つだけでよく
一人から始められるのも体験してみなければわからない事でした。

次回も参加したいし、多くの人に体験してもらうことを薦めようと思いました。

# NVC（Nonviolent Communication＝非暴力コミュニケーション）とは
1970年代に、アメリカの臨床心理学者マーシャル・B･ローゼンバーグ博士によって体系化され、提唱された、自分の内と外に平和をつくるプロセスです。
以下略。

# 私のNVCの知識
ほぼゼロです。
https://note.com/nvc_giraffe/n/nd24588aef5c9
こちらのページを読んだ程度。
ユーザー会では、興味を持った方レベルで参加OKだったので
参加してきました。
Javaを使用してPDFのブックマークを展開または折りたたむ方法

PDFのブックマーク機能は、指定された読み取り位置をすばやく見つけることができます。 複数のブックマークに対しては、人々は自分の好みに応じてそれを展開してまたは折りたたむことができます。この記事では、Javaプログラムコードを使用してPDFブックマークを展開または折りたたむ方法を紹介します。

##プログラム環境：

Spire.Pdf.jar（無料バージョン3.9.0バージョン）
JDK1.8.0（バージョン1.6.0以降を使用可能）
IDEA

###JARファイルのインポート：
jarパッケージを手動で[ダウンロード](https://www.e-iceblue.com/Download/download-pdf-for-net-now.html)してインポートします。libフォルダーにあるSpire.Pdf.jarファイルをダウンロードして解凍し、Javaプログラムへの参照を追加します。
jarのインポートは以下の図に示すように：
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/390ec39f-9145-7bea-25e8-1b87299d79a2.png)

##Javaプログラムコード
ブックマークの展開または折りたたみを設定する場合、全文のすべてのブックマークに設定することも、ブックマークに個別に設定することもできます。コードメソッドは次のとおりです。
1.	すべてのブックマークを展開（または折りたたみ）するように設定します

```
import com.spire.pdf.*;

public class ExpandOrCollapseBookmark {
    public static void main(String[] args) {
        //PDFテストドキュメントをロードする
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("sample.pdf");

        //すべてのブックマークを展開する（展開するにはtrue、折りたたむにはfalse）
        pdf.getViewerPreferences().setBookMarkExpandOrCollapse(true);

        //ドキュメントを保存する
        pdf.saveToFile("ExpandAllBookmark.pdf");
        pdf.dispose();
    }
}
```

すべてのブックマークを展開した結果：
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/b4a8ddf6-73f2-4d31-948a-1b62a8692f0c.png)

2.	指定したブックマークを展開（または折りたたみ）するように設定します

```
import com.spire.pdf.*;
import com.spire.pdf.bookmarks.PdfBookmark;
import com.spire.pdf.bookmarks.PdfBookmarkCollection;

public class ExpandOrCollapseBookmark {
    public static void main(String[] args) {
        //PDFテストドキュメントをロードする
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("C:\\Users\\Administrator\\Desktop\\sample.pdf");

        //BookMarkExpandOrCollapseを「true」に設定して、3番目のブックマークを展開する
        PdfBookmarkCollection pdfBookmark = pdf.getBookmarks().get(2);
        ((PdfBookmark) pdfBookmark).setExpandBookmark(true);

        //同時に、3番目のブックマークの下のサブブックマークを展開するように設定する
        for(int i = 0; i < pdfBookmark.getCount();i++)
        {
            pdfBookmark.get(i).setExpandBookmark(true);
        }
        //ドキュメントを保存する
        pdf.saveToFile("ExpandSpecificBookmarks.pdf");
        pdf.close();
    }
}
```

指定したブックマークとサブブックマークを拡張した結果：
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/32a1bd7b-74d0-48f3-5638-cc1b383a2f1f.png)

##結語
以上は今回のPDFのブックマークを展開または折りたたむ方法でした、最後まで読んでいただき誠にありがとうございます。
ReactNativeのScreenでcomponentにpropsを渡したい

ReactNativeのMaterial Top Tabs Navigator（https://reactnavigation.org/docs/material-top-tab-navigator/)
を使う際に、Tab.Screenのcomponentにpropsを渡したいという状況に陥りました。

通常の書き方だと、

```javascript
function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}
```

となってしまって、それぞれのcomponentにpropsを渡せません。

###対処法
公式のScreenの箇所にコンポーネントのpropsを渡す代わりにReact Elementをcallbackで返してくれるという記述が...!
https://reactnavigation.org/docs/screen#children

これを`Tab.Screen`に応用します。


```javascript
function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home">
        {(props)=> <HomeScreen {...props}/>}
      </Tab.Screen>
      <Tab.Screen name="Setting">
        {(props)=> <SettingScreen {...props}/>}
      </Tab.Screen>
    </Tab.Navigator>
  );
}
```

解決しました！子要素はJSXで返さないといけないので`{()=> ...}`の形にすることに注意です。
gitのデフォルトエディタをnanoからviに変更

## 環境
Ubuntu20.4

## やりたいこと
１つ前のコミットメッセージを変更しようとして、次のコマンドを実行すると、nanoが起動されたので、デフォルトエディタをviに変更することにする。

```
git commit --amend
```

## 説明

gitの環境ファイルに、**core.editor vi**の設定を追加すればいいということになるのだが、環境ファイルと一言で言っても３種類存在している。

>
1. .git/config
2. ~/.gitconfig
3. /etc/gitconfig

.git/configは、**git init**したときにプロジェクト内に自動的に作成されが、~/.gitconfigと、/etc/gitconfigは、作りたければ自分で作成する必要があります。

.gitc/onfigで設定した情報は、**git init**をしたプロジェクト内でのみに反映され、~/.gitconfigは、ログインしたユーザーのにみ反映され、/etc/gitconfigはOS全体に反映されます。

つまり、自分が利用しているプロジェクトだけにviを反映させたい場合は、.gitconfigを修正する。今後、自分が作るプロジェクト全てにおいてviを反映させたい場合は、~./gitconfigを修正する。自分以外のユーザーでログインした場合でもviを反映させたい時は、/etc/gitconfigを修正するという使い分けになります。

状況に応じて、下記のコマンドを実行すると、viが設定されます。

```
$git config core.editor vi
$git config --global core.editor vi
$git config --system core.editor vi
```

--globalオプションを付けてコマンドを実行した後、**ls -la ~**すると、**~/.gitconfig**が作成されます。設定を取り消したい場合は、**rm ~/.gitconfig**でファイルを削除します。

設定した後、設定内容を確認する。

```
$cat ~/.gitconfig
[core]
        editor = vi

$git config --global --list
core.editor=vi
```

次のコマンドを実行すると、local,global,systemのそれぞれで設定されている設定内容が合算されて一覧表示されます。

```
git config --list
```
Go言語を0から習得してWeb開発をする

##基本このサイトだけで大丈夫
https://leben.mobi/go/

このサイトで学習を進めれば入門レベルからWeb開発まで習得できます。
ただ一部古い部分があって、現在ではエラーが起きてしまう可能性のあるプログラムやコマンドがありました。本記事ではそういったような、私がこのサイトで学習していた際に必要になったその他の情報や備忘録を書いていきます。

##Web開発編で出てくるデータベースの構築と操作
https://prog-8.com/docs/mysql-env-win

こちらはprogateのサイトになっております。Windows環境と書いてありますが、Mac用のリンクもこのページにあります。このサイトを見るのはWeb開発編に入った後で大丈夫です。

##実行でエラーが起きたので備忘録

###Web開発編「JSON形式で外部設定ファイルを作成・利用する方法」で起きたエラー　その１

~~~
\Go\goWeb> go run main.go
build command-line-arguments: cannot find module for path _/C_/Users/ユーザー名/Go/goWeb/conf
~~~

confファイルが見つからない的なこと言われちゃいました。
このページに出てくる**main.goファイル**は以下のように書かれていると思います。

~~~Go
package main
 
import (
    "fmt"
    "strconv"
 
    "./conf" // 実装した設定ファイルパッケージの読み込み
)
 
func main() {
 
    // 設定ファイルを読み込む
    confDB, err := conf.ReadConfDB()
    if err != nil {
        fmt.Println(err.Error())
    }
 
    fmt.Println("取得した設定内容を出力します")
    fmt.Println("ホスト名: " + confDB.Host)
    fmt.Println("ポート: " + strconv.Itoa(confDB.Port))
    fmt.Println("接続先DB名: " + confDB.DbName)
    fmt.Println("接続ユーザ名: " + confDB.User)
    fmt.Println("パスワード: " + confDB.Pass)
 
}
~~~

で、実はこのファイルの上の方の

~~~
"./conf" // 実装した設定ファイルパッケージの読み込み
~~~

というのがあると思うのですがどうやら今は、import文でのパッケージの読み込みは**相対パスで書いちゃダメ**みたいですね…。
というわけでここを

~~~
"goWeb/conf" // 実装した設定ファイルパッケージの読み込み
~~~

というように、プロジェクトのメインフォルダから**絶対パスに変更**しておきましょう。これで実行成功しました。
ちなみにこれは、**このあとの学習回でも変更が必要なところがあった**ので、import分の中に"."（ドット）で始まるような相対パスがあれば、絶対パスに直しておきましょう。

###Web開発編「JSON形式で外部設定ファイルを作成・利用する方法」で起きたエラー　その２

言われた通りにプログラムを書いて実行したのですが、エラーが起こりました。

~~~
\Go\goWeb> go run main.go
main.go:9:5: no required module provides package github.com/go-sql-driver/mysql: go.mod file not found in current directory or any parent directory; see 'go help modules'
~~~

ちなみに、goWebというのが私が作った今回のプロジェクト名であり、メインの作業ディレクトリです。GoはGOPATHに設定したディレクトリです。詳しくは本記事の最初に引用したサイトの「Goのインストールと動作確認」を参照してください。
さてさて、**go.modファイルが無い**と言われてしまいました。go.modファイルを作る必要があります。方法は、

~~~
\Go\goWeb> go mod init goWeb
go: creating new go.mod: module goWeb
go: to add module requirements and sums:
        go mod tidy
~~~

これでメインの作業ディレクトリにgo.modファイルができました。
そしたらもう実行できるかなーと思ったら、別のエラーが出ました。

~~~
\Go\goWeb> go run main.go    
main.go:9:5: no required module provides package github.com/go-sql-driver/mysql; to add it:
        go get github.com/go-sql-driver/mysql
~~~

言われた通りにgo get github.com/go-sql-driver/mysqlを実行しましょう。

~~~
\Go\goWeb> go get github.com/go-sql-driver/mysql
go get: added github.com/go-sql-driver/mysql v1.6.0
~~~

これでgo run main.goを実行するとようやく成功しました！

###Web開発編「net/httpパッケージでオレオレ証明書を使用してHTTPS(SSL)サーバを立てる」で起きたエラー

署名リクエストファイルを作成して、証明書を発行する段階で、
「最後に、この署名ファイルを元に証明書ファイルを発行します。
ファイル名はlocalhost.crtとします。」
という文の後、

~~~
openssl x509 -days 3650 -req -signkey localhost.key localhost.crt
~~~

をそのまま実行すると何も起こらずに止まってしまいました。
調べてみると、-in localhost.csr が必要だったそうです。

よって、

~~~
openssl x509 -days 3650 -req -in localhost.csr -signkey localhost.key -out localhost.crt
~~~

と入力すると無事localhost.crtが発行されました。
Determining Why Your Organization Needs Web Application Security

If you are a CIO or a key decision-maker of your organization, having a well-defined web security mechanism can be extremely beneficial. Web application security depicts an array of processes, technologies, and methods implemented for protecting an end-user’s web servers, web applications, and web services from all forms of online threats & malware. Having a robust web application security mechanism in place becomes essential for enterprises. This security technique protects users’ and enterprises’ data from all forms of data theft and obstacles that hinder business continuity.

Web application security

Understanding Web Application Security

Web application security is a broad term, and it encapsulates an array of methods and strategies for securing web browsers and applications. The techniques help secure an organization’s digital assets against various cyber threats. Most web application security threats arise due to exploited weaknesses by pushing vulnerabilities through these weaknesses. Cybercriminals deploy malicious techniques to determine these ‘loopholes’ in security mechanisms & get away with user-critical data to have personal gains.
Understanding Web Application Security

Some common targets of these web-based attacks initiated by cybercriminals include content management system tools, database administration tools, along SaaS applications. These systems are often targeted because these hold high business, and a single cyberattack can lead to substantial monetary & non-monetary losses.

Common Web Application Vulnerabilities

Web application vulnerabilities occur in the absence of defined inputs/outputs that cybercriminals exploit for manipulating source codes or gaining illegal access to sensitive data. These vulnerabilities open the scope for an array of attacks, comprising of the following.

Source: https://www.esds.co.in/blog/determining-why-your-organization-needs-web-application-security/
Flutterの状態管理ライブラリ

# はじめに
株式会社THIRD IT開発部でモバイルアプリ（Android及びiOS）の開発を行なっているエンジニアです。

Flutterは、クロスプラットフォーム開発の世界では注目の話題です。今回はFlutterの状態管理について纏めていきたいと思います。

# 状態管理とは
状態管理とは、1つ以上のユーザーインターフェイスコントロールの状態を管理することです。ユーザーインターフェイスには、テキストフィールド、ボタン、ラジオボタン、チェックボックス、ドロップダウン、トグル、フォームなどがあります。

> 参照：[状態管理(wikipedia)](https://en.wikipedia.org/wiki/State_management)

アプリケーションは、数多のユーザーインターフェイスコントロールで構成されていて、１つのユーザーインターフェイスコントロールの状態は、他のユーザーインターフェイスコントロールの状態に依存します。

> 例：入力フィールドに有効な入力値がある場合、ボタンは有効な状態になり、入力フィールドが空または無効な値を持つ場合、ボタンは無効な状態になります。

アプリケーションが成長するにつれて、これは最も複雑な問題の1つになる可能性があります。そのため状態管理は、アプリケーション開発において非常に重要です。

アプリケーションの状態を管理するための状態管理手法を決定する必要があります。Flutterの状態管理は多数のパッケージが存在します。人気のあるものを紹介していこうと思います。


# Provider
Providerパッケージは、[InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html)をより再利用可能で使いやすくするためのラッパーです。このパッケージは、InheritedWidgetを使用して、より簡単な方法でデータを管理したい人に適しています。

**長所**

* InheritedWidgetをシンプルにする
* 広く利用されている
* Flutterチームによる開発サポート

各種リンク

* pub.dev:https://pub.dev/packages/provider
* Github:https://github.com/rrousselGit/provider

# Riverpod
Riverpodは、Providerと同じ作成者によるものであり、Providerの開発中に問題に直面したため、最初からInheritedWidgetを再実装したものです。
単方向のデータフローにより、パフォーマンス、テスト容易性、および可読性が向上します。コンパイル時にプログラミングエラーをキャッチし、開発者を実行時の例外から保護します。また、Riverpodは、プロバイダーで必要なBuildContextへの依存を排除​​します。

長所：

* Providerに似ています


各種リンク

* Official page:https://riverpod.dev
* pub.dev:https://pub.dev/packages/riverpod
* Github:https://github.com/rrousselGit/river_pod


# Bloc
Blocは、人気のある状態管理ソリューションです。BLoCデザインパターンの実装に役立つ予測可能な状態管理ライブラリです。プレゼンテーションをビジネスロジックから簡単に分離できるようにし、テストと再利用を容易にすることができます。

長所：

* ビジネスロジックの分離がしやすい
* ドキュメントが多い
* テストしやすい

各種リンク

* Official page:https://bloclibrary.dev
* pub.dev:https://pub.dev/packages/bloc
* Github:https://github.com/felangel/bloc


# GetX
GetXは、人気のある状態管理ソリューションです。 高性能の状態管理、インテリジェントな依存性注入、およびルート管理を迅速かつ実用的に組み合わせたものです。シンプルで非常に短いコードのために生産性が向上します。

長所：

* 非常に短いコード

各種リンク

* pub.dev:https://pub.dev/packages/get
* Github:https://github.com/jonataslaw/getx


# States_Rebuilder
states_rebuilderは、依存性注入ソリューションと統合ルーターを組み合わせたFlutter状態管理であり、最高の状態管理エクスペリエンスを実現し、開発をスピードアップします。

各種リンク

* pub.dev:https://pub.dev/packages/states_rebuilder
* Github:https://github.com/GIfatahTH/states_rebuilder


# Mobx
MobXは、アプリケーションのリアクティブデータをUIに簡単に接続できる状態管理ライブラリです。この配線は完全に自動化されており、とても自然な感じです。アプリケーション開発者は、2つの同期を維持することを心配することなく、UI（およびその他の場所）で消費する必要のあるリアクティブデータに純粋に焦点を合わせます。

各種リンク

* Official page:https://mobx.netlify.app
* pub.dev:https://pub.dev/packages/mobx
* Github:https://github.com/mobxjs/mobx.dart
Dreamweaver使い方

###テンプレート切り替え

1.ツール　→　テンプレート　→　テンプレートをページに適応

###新規テンプレート作成

1.新規ファイル作成
2.メニュー一番上のHTMLサイトテンプレート作成
3.既存のサイトテンプレートの中身をコピペ
GitHub アクセスの際の認証情報を保存する

# はじめに
GitHub へのアクセスは SourceTree や cli で行うと思いますが、その際にユーザー名やパスワードの入力が非常に面倒です。

URL に PAT を指定する方法も簡単ですぐに実現できるのですが、PAT がオープンになってしまうためあまりいい感じではありませんので、 git-credential-manager-core(GCM) を使用して Mac のキーチェインや Windows 資格情報マネージャーに事前に登録するようにしたいと思います。

環境は macOS を想定していますが、インストール手順以外はほぼ同じコマンドで実行できます。

## 環境準備
git-credentaial-manager-core をインストールします。

https://github.com/GitCredentialManager/git-credential-manager

インストール方法は上記のサイトにも記載されていますが以下で行えます。

```sh
brew tap microsoft/git
brew install --cask git-credential-manager-core
```

すでにインストール済みの場合は

```sh
brew upgrade git-credential-manager-core
```

でアップグレードが可能です。

## GCM の初期設定
認証設定を行う前に初期設定を行います。

```sh
git credential-manager-core configure
```

上記によって .gitconfig などの初期設定が行われます。

## macOS の場合
macOS の場合はキーチェインをデフォルトのログインキーチェインを使用するようですのでログインキーチェインを有効化しておきましょう。

```sh
security list-keychains -d user -s ~/Library/Keychains/login.keychain-db
```

https://github.com/GitCredentialManager/git-credential-manager/blob/main/docs/credstores.md#macos-keychain

## 認証情報の設定
認証情報の設定は以下のコマンドを入力することで保存することが可能です。

```sh
git credential-manager-core store << EOS
protocol=https
host=github.com
username=<ユーザー名>
password=<パスワード or PAT>
EOS
```

※パスワードには PAT(パーソナルアクセストークン) を指定する方がおすすめです。

上記の設定を行うことで次回以降はパスワード入力を抑制することが可能になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/83badcf9-1b37-f3bf-9c88-ca264cb2b7b4.png)

無事に保存されればキーチェインには上記のような画像ように保存されていると思います。

ちなみに Windows の場合は以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/1e40c5bb-3bee-6e3d-cb8d-68ec06dfd6c1.png)

Windows の場合はパスワードに PAT を指定した場合はユーザー名に『Personal Access Token』と表示されるようです。

正常に登録されているかどうかを確かめる方法は

```sh
git credential-manager-core get
protocol=https　← 入力
host=github.com　← 入力
// 空白の改行を入れる
```

と入力すると

```sh
protocol=https
host=github.com
username=<ユーザー名>
password=<パスワード>
```

という感じで表示されるはずです。

以下に上記をまとめたシェルスクリプトを記載しておきます。

```sh
#!/bin/sh

# 引数
# $1 = GitHub のアカウント名（またはメールアドレス）
# $2 = GitHub の PAT (repo, workflow, admin:repo_hook)

security list-keychains -d user -s ~/Library/Keychains/login.keychain-db

git credential-manager-core store << EOS
protocol=https
host=github.com
username=$1
password=$2
EOS
```

上記のコードを `Store-GitHub-Credential.sh` というファイルを作成してコピペしてもらって以下のようにコマンドを叩いてもらえばよいかと。

```sh
./Store-GitHub-Credential.sh <ユーザー名> <パスワード>
```

# さいごに
git の認証にはかなりてこずりました。
特に macOS の場合はキーチェインの知識がかなり必要なため、それを知っていないと遠回りを常にしている感じです。
まぁ、事前の知識はしっかりと持っておかないといけないということですね。
ReScript & React で Hello World を表示する

##前提条件
ReScript & React の実行には Node.js version >= 10 が必要です。

##Reactアプリケーションの作成
```SH:SH
npx create-react-app sample
cd sample
```
Reactアプリケーションを作成します。[^create-react-app][^sample]
`npx create-react-app sample`の実行には時間がかかります。
実行終了まで待って、sampleディレクトリに移動します。

##ReScriptのインストール
```SH:SH
npm install rescript --save-dev
``` 
ReScriptをインストールします。[^rescript-install]
sampleディレクトリで実行します。

##rescript-reactのインストール
```SH:SH
npm install @rescript/react --save
```
rescript-reactをインストールします。[^rescript-react-install]
sampleディレクトリで実行します。

##React & Rescript設定ファイルの作成
sampleディレクトリに以下の内容の`bsconfig.json`を作成します。[^bsconfig.json][^suffix]

```JSON:bsconfig.json
{
  "name": "sample",
  "version": "0.0.1",
  "sources": {
    "dir" : "src",
    "subdirs" : true
  },
  "package-specs": {
    "module": "es6",
    "in-source": true
  },
  "suffix": ".js",
  "reason": { "react-jsx": 3},
  "bs-dependencies": [
    "@rescript/react"
  ],
  "warnings": {
    "error" : "+101"
  }
}
```

##App.resの作成
sample/srcディレクトリに以下の内容のApp.resを作成します。[^App.js]

```ReScript:src/App.res
@react.component
let make = () => {
  <div>{React.string("Hello World")}</div>
}
```

##ReScriptをJavaScriptに変換
```SH:SH
npx rescript
```
sampleディレクトリで実行します。
App.resの内容が変換され、App.jsに保存されます。

##index.jsの修正
```JavaScript:src/index.js
// 修正前
import App from './App';

// 修正後
import { make as App } from './App';
```
sample/srcディレクトリにあるindex.jsに上記の修正を加えます。

##実行
```SH:SH
npm start
```
sampleディレクトリで実行します。
しばらくするとWebブラウザが起ち上がり、Hello Worldが表示されます。[^npm-start]
`npm start`を実行したターミナルは何もできなくなっています。Ctrl+Cを入力すると制御が戻ります。

##この後
1.`App.res`にReScriptを記述する
2.`npx rescript`でReScriptをJavaScriptに変換する
3.`npm start`で内容を確認する
でいろいろと試すことができます。

##おまけ ： index.js をReScriptで書く
sample/srcディレクトリに以下の内容のindex.resを作成します。[^index.js]

```ReScript:src/index.res
switch(ReactDOM.querySelector("#root")){
| Some(root) => ReactDOM.render(<App />, root)
| None => ()
}
```
```SH:SH
npx rescript
npm start
```
で動作が確認できます。

[^create-react-app]: https://create-react-app.dev/docs/getting-started を参照
[^sample]: "sample"はプロジェクト名です。好きな名前を付けることができます。プロジェクト名でディレクトリが作成され、その配下に必要なファイルが設置されます。
[^rescript-install]: https://rescript-lang.org/docs/manual/latest/installation#integrate-into-an-existing-js-project を参照
[^rescript-react-install]: https://rescript-lang.org/docs/react/latest/installation を参照
[^bsconfig.json]: https://rescript-lang.org/docs/manual/latest/installation#integrate-into-an-existing-js-project と https://rescript-lang.org/docs/react/latest/installation を参照
[^suffix]: "suffix"は".bs.js"にするのが一般的なようです。その場合は後の例のApp.resはApp.bs.jsに変換されます。
[^App.js]: https://rescript-lang.org/docs/react/latest/installation を参照
[^npm-start]: 起ち上がったWebブラウザが http://localhsot:3000 にアクセスします。
[^index.js]: https://rescript-lang.org/docs/react/latest/rendering-elements#rendering-elements-to-the-dom を参照
Dockerを使ったLaravelにログイン機能を追加する

## ログイン機能

Laravelにてログイン機能を追加しようと思っていて
「laravel ログイン機能」と検索すると
dockerを利用していない場合の、追加方法が出てきたりするので、以下のサイトを参考にさせていただきました！

https://qiita.com/mumucochimu/items/3d4ff8fa8fcb9826339f

また、以下のコードの意味がよく分からなかったため
```
% docker-compose exec app bash
```

こちらの記事も参考にさせていただきました！

https://qiita.com/tsuboyataiki/items/90dbe94553d3dea39b19


出先のwi-fiを利用して、npm install を使用としたら
エラーが起きてしまいました。

https://qiita.com/tenten0213/items/7ca15ce8b54acc3b5719

これはプロキシ環境下において、設定を変更する必要があったため
上記サイトを3上にさせていただきました。

ちなみに、プロキシについてよく理解していなかったので
以下のサイトも参考にさせていただきました！

https://cybersecurity-jp.com/column/32171

簡単に言うと、自分のデバイスをネットに繋ぐ際の仲介サーバーです。
プロキシサーバーによって安全にネットを利用することができるといっても過言ではないでしょう。


### ログイン画面の追加方法
「laravel ログイン機能」と検索すると、ログイン機能を導入するためのコードは載っているのですが
どうやって、ブラウザ上で実装するかが載っていませんでした。

そこで、簡単に紹介していこうと思います。

上記サイトらを見て、諸々インストールすると
``` Web.php
Auth::routes();

Route::get('/home', [HomeController::class, 'index'])->name('home');
```
こんなコードが追加されているはずです。

これは、homeという名前を使うことで、ログイン画面を導くことができるよ。という意味なので

例えば、index.phpにログインリンクを追加したいとすると

```index.php
<a href="{{ route('home') }}">ログイン</a>
```
こう追加すれば
↓↓↓ログインリンクが追加され
![スクリーンショット 2022-02-16 13.00.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525372/3bde1292-4361-851b-964d-15b7cd2fd599.png)
↓↓↓

![スクリーンショット 2022-02-16 13.00.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525372/60177194-3838-9da5-0dda-9e56d7fba87b.png)
ログイン画面が出てきます。

### 今の悩み
ログインしようとしても、そもそも登録していないので
ログインできない。

では、登録しようと実行してみたのですが
![スクリーンショット 2022-02-16 13.02.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525372/4cdff1e9-2535-5701-6c7f-4b0fca994e02.png)

以下のようなエラーが出てしまいました。

![スクリーンショット 2022-02-16 13.02.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525372/3022a9ba-f7c1-5ef6-e025-35b204530d6d.png)

おそらく、登録情報を保存するデータベース（テーブル）が設定されていないよ。
ということだと思います。

ますはエラーコードで検索してみて
ダメならば、テーブルを作成する方法を調べてみたいと思います。

### 最後に

最近、エラーに3日間くらいハマっていたおかげか
エラーに対しての対処法がスラスラ思い浮かぶようになりました。

エラーが1番成長させてくれるのかもしれないなと思った、今日この頃でした。

### 追記（2022/02/20）
その後、多くのエラーに見舞われ
DBやDockerなどの知識が増えて、全体像がわかってきたので追記します。

まず、上記を参考に
ユーザー認証機能をインストールすると

ログイン画面がブラウザに出てこないと思います。
これがルーティングがされてないからなんですね。

なので、まずルーティングをします。

### ルーティング

```web.php
//view('welcome')になっているところをauth.loginに変更します。
Route::get('/', function () {
    return view('auth.login');
});
```

これは、localhostにアクセスされたら
元々設定されている初期画面を表してくれ。という設定を
ログイン画面を表示してくれと指示した感じです。

### マイグレーションもするよ

ルーティングができて、「ログインしちゃうぞっ！」と思って
ぽちぽちするとエラーが出てくるはずです。

これは、まだデータベースにテーブルが作成されていないからです。

どういうことかと言うと、
データベースにこんな情報登録するよ
という枠組みを用意できていないのです。

簡単に言うと、エクセルやスプレッドシートの項目を書いてすら
いないので、まず、どんな項目で登録するか教えてくれ
ってことなのです。

今回は、パッケージをインストール時点で
データベースのテーブルであるuser_table.phpという
マイグレーションファイルがあるので

そちらを、現在使用しているDockerに繋ぎます。

その方法は簡単で
``` command
./vender/bin/sail artisan migrate
```
でできちゃいます。

すると、データベースとの連結ができて
登録情報が保存ができるので完成です★
Ethernautに挑戦してみた

#Ethernautに挑戦してみた
本記事はEthernautの勉強会に参加した感想やまとめの備忘録のような記事です。
2月15日(火) 18:00~19:00に[Blockbase(株)](https://www.block-base.co/)でCryptoZombiesを修了したレベルの人向けに開かれたSolidityのコードの脆弱性に関する勉強会に参加しました。勉強会で用いた資料がEthernautです。勉強会はEthernautのやり方の説明、実際の問題を参加者で考える形式で行われました。Ethernautの問題については1~３までを勉強会で進め、記事では問題1と２についてまとめました。問題3のCoin Flipについては自分の理解が足りてないため、後ほどまとめようと思ってます。勉強会に参加することは初めてでしたが、様々な方の意見が参考になり一人で勉強するよりタメになることが多いと感じました。また、いつの日かに勉強会を開くらしいので興味があれば勉強会に参加してみてください。


####Ethernautとは
Ethernautはスマートコントラクトの脆弱性をsolidityのソースコードから見つけ、その脆弱性をついた攻撃をするハッキングのゲームです。Ethernautは[ここから](https://ethernaut.openzeppelin.com/)でアクセスできます。以下から実際に問題を解くまでの流れを自分なりにまとめました。


## 1. Fallback
Fallbackでは以下の条件 1.「契約書の所有権を主張する」、2.「契約書の残高を 0 にする」を満たせばクリアできます。言い換えるとコントラクトのオーナーのアドレスを自分のアカウントアドレスに置き換え、コントラクト内の残高を全額引き出す攻撃をします。
コントラクトの[ソース](https://ethernaut.openzeppelin.com/level/0x9CB391dbcD447E645D6Cb55dE6ca23164130D008)を見ると、receive関数内の
```require(msg.value > 0 && contributions[msg.sender] > 0);```を満たした状態でreceive関数（Fallback関数)を呼び出すことでオーナーの所有権を主張できると考えられます。
先程の条件の```contributions[msg.sender] > 0);```の部分を満たすためにはcontribute関数を実行した後、recive関数(Fallback)関数を呼び出します。このようにすることで1.「契約書の所有権を主張する」を満たせます。
次にオーナーのアドレスが満たされた後widthdraw関数を実行するとコントラクト内の残高を全額引き出せ、コントラクトの残高を０にすることができます。つまり2.「契約書の残高を 0 にする」を満たせ、問題をクリアできます。



## 2. Fallout
2.Falloutではコントラクトの所有権を主張することで問題を解けます。[ソース](https://ethernaut.openzeppelin.com/level/0x5732B2F88cbd19B6f01E3a96e9f0D90B917281E5)見てコンストラクターの名前がFal1outとなっていることに気づければ簡単にオーナーの所有権を取得できます。Fal1out関数を実行すると簡単にオーナーをトランザクション送信者のアカウントアドレスに書き換えられ、問題をクリアできます。


## 3. Coin Flip

この問題については後ほど深く理解してからまとめます。
rails consoleでActiveRecordの検索メソッドを実行するときに注意するべきこと



前提知識
-

ActiveRecordの検索メソッドは、`DBアクセスの有無`という点で大きく分けると以下の２種類がある。

- DBアクセスを行うメソッド
  - `ActiveRecord::FinderMethods`のメソッド
     - `find, find_by, take, first, last` など
     - すぐにクエリを発行し、データベースにアクセスし、レコード(Modelのインスタンス or インスタンスの配列)を返す。
- DBアクセスを行わず`ActiveRecord::Relation`のオブジェクトを返すメソッド
  - `all, where, limit, eager_load, preload, joins`など 


問題
-
上記の通り`all`や`where`はそれ単体ではDBへのアクセスは発生しない。
そこで実際に`rails console`で`where`を実行してみる。

```ruby
pry(main)> User.where(id: 1)
  User Load (3.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1
=> #<User:0x000055e9e1dd7e00
 id: 1,
 last_name: "田中",
 first_name: "太郎",
 created_at: Wed, 09 Feb 2022 17:57:33 JST +09:00,
 updated_at: Wed, 09 Feb 2022 17:57:33 JST +09:00 >
```
むむ、DBへのアクセスは発生しないはずだけど、明らかにDBからデータを取得してますね。(田中太郎さんのデータを取得している）

ログをみてもやはりSQLが発行してDBアクセスが発生していることがわかります。

```log/development.log
  User Load (3.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1
```

一見すると矛盾しているように見えますね。
なぜDBにアクセスが発生しないはずの`where`でDBアクセスが発生しているのか？

:::note info
ActiveRecord::Relation を返す他のメソッド( all, preload など)も上記と同じ挙動になります。
:::

原因
-

上記の問題は、railsコンソールの仕様が原因となっています。
railsコンソールにおいて、`User.where(id: 1)`は以下のような流れで処理されます。

- コンソールで`User.where(id: 1)`を実行
- `ActiveRecord::Relation`オブジェクトが帰ってくる
- コンソールはオブジェクトを画面に表示するため`#inspect`を呼ぶ
- `ActiveRecord::Relation`オブジェクトはDBにアクセスしにいく

つまり`rails console`では、オブジェクトを画面に表示するために式に`inspect`が実行されているんですね。
その時に、`ActiveRecord::Relation`が評価されDBアクセスが発生してしまいます。


まとめ
-

- `rails console`では、画面表示のために`inspect`が実行されており、それが原因で`where`や`all`でもDBアクセスが発生している。
- それを知らないと、`all`や`where`はDBアクセスしないという情報と、`rails console`での実行結果が矛盾しているように見え混乱を招く。
- なので、内部的に`inspect`を実行するという作りになっていることを知っておこう！


追記
-
行末にセミコロンをつけると実際の挙動になるようです。
```ruby
 User.where(id: 1); # DBアクセスなし

User.find(1); # DBアクセスあり
User Load (1.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
```



参考
-
https://qiita.com/ykamez/items/0c81a33ec1b90219d541

https://qiita.com/wakasa51/items/3fe880d0e8e656044778
Watson Discoveryの歴史をまとめてみた

本記事の内容は 2021/12末時点の情報です。

# Watson Discoveryとは
Watson Discoveryの概要についてはこちらの記事がとても参考になります。
[Watson Discoveryの概要まとめてみた](https://qiita.com/riina_hoiz/items/24674c216b0fe92577d4)

# Watson Discoveryの歴史
Watson Discoveryには大きく「検索」機能と「テキスト分析またはマイニング」機能があります。
また、提供形態としてIBM CloudとCloud Pak for Data(CP4D)があります。

それぞれ今までどういう製品を経由して、今の状態になったのか、少し歴史を紐解いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/0229d3eb-b966-e950-d2f8-9f9dbc351b8a.png)

※ WEXAC : Watson Explorer Analytical Component
※ WEXFC : Watson Explorer Foundational Component
※ WEX DAE : Watson Explorer Deep Analytical Edition
※ WD : Watson Discovery
※ CP4D : Cloud Pak for Data
※ RT : Relevancy Training
※ SDU : Smart Document Understanding

はじまりは、1998年にIBMの東京基礎研究所が開発した**TAKMI**(Text Analysis and Knowledge Mining）というテキスト・マイニング技術です。
これが後に、DiscoveryのContent Miningのベースとなります。<br>
一方、検索機能は IBM OmniFind Enterprise Editionという製品がありました。
しかし、2012年にIBMがvivisimo（企業向け検索エンジンを提供していた会社）を買収し、InforSphere Data Explorerという名前で検索を担う製品を発表しました。<br>
これらの製品が**Watson Explorer**という共通の名のもの統合されたのが、2014年です。
Watson Explorereという名前は統一されたものの、中は2つの異なる製品が含まれていました。
テキスト・マイニングがメインのWatson Explorer Analytical Component。
（厳密には、検索機能はあります。おそらくOmniFindベースのもの？）
検索がメインのWatson Explorer Foundational Component。
（こちらが、vivisimoベース）
Watson ExplorerのEditionによってどちらの製品が利用できるかが異なります。
異なる製品のため、インストール方法も異なればサポートされるOSなども異なっていました。<br>
その後、2018年に検索＆テキスト・マイニングを提供する新しい製品**oneWEX**が登場しました。
このoneWEXが、今のDiscoveryのContent Miningに似ています。<br>
一方で、2016年に大量のデータを検索し、適切な意思決定を支援するサービスとして**Watson Discovery**がIBM Cloudで登場しました。（この時期、他にもWatson APIが多く登場しましたね）
IBM CloudのDiscoveryは、年々様々な機能が追加され拡張を続けます。<br>
そして、2019年にIBM Cloudで提供していたWatson DiscoveryとoneWEXの一部の機能が統合され、**Watson Discovery for CP4D**が誕生しました。
その後、製品は機能拡張を続け現在も日々拡張されています。<br>
Watson Discovery for CP4Dが登場したことで、IBM CloudのWatson Discoveryにも変化がありました。
IBM CloudのWatson Discoveryには検索機能のみで、CP4DのWatson Discoveryには検索機能もContent Miningもあります。
この違いを吸収するために、IBM CloudのWatson DiscoveryにもContent Mining機能が使えるようになりました。
これが、2020年に登場したPremiumプラン（有料）です。
ここで、APIのバージョンがV1とV2に分かれました。<br>
この変化に伴い、現在、V1のWatson Discovery(LiteプランやAdvancedプラン）は新規に作成することはできず、V2のインスタンスのみ作成できる状態となっています。

ふぅ。といった感じで今のWatson Discoveryがあります。

# Watson Discoveryの提供形態
上記の歴史的背景があり、現在では以下のような提供形態となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/51edb0bd-4c8d-ae3e-06d9-81f45d5a608f.png)

# 参考情報
IBM CloudのそれぞれのプランとCP4Dでは若干提供される機能が異なりますので、詳しくは製品マニュアルを参考にしてください。

https://www.ibm.com/jp-ja/cloud/watson-discovery/pricing

https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-pricing-plans

https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-version-choose

# お断り
このサイトの掲載内容は私自身の見解であり、必ずしも所属会社の立場、戦略、意見を代表するものではありません。 記事は執筆時点の情報を元に書いているため、必ずしも最新情報であるとはかぎりません。 記事の内容の正確性には責任を負いません。自己責任で実行してください。
ネットワーク内の行方不明のデバイスのIPを特定する #備忘録

固定しているはずなのに、何らかのタイミングでデバイスのIPが変わってしまうことありませんか？
または、新しい製品のIPがわからない、なんてことはありませんか？

デバイスの管理画面等にアクセスするのにIPアドレスが必要な場合に、IPアドレスが行方不明になると、**ぴえん**ですよね。


以下の通りで、ネットワーク内のIPアドレスとMACアドレスの一覧を取得できます。

```
arp -a
```

しかし、IPアドレスとMACアドレスはHuman-readableではないので、これだけでは嬉しくありません。

新しい製品のIPがわからない、という場合は
/etc/hostsに登録されていない謎のデバイスをピックアップしたりしてもいいかもしれません。

```
arp -a | grep "?"
```

これで行方不明のデバイスが絞れてきましたが、依然MACアドレスだけなのでわかりにくいです。


# MACアドレスの先頭はベンダーに固有

あとは、製品のMACアドレスをもとに絞ればいいのですが、製品の箱とか本体を見るのも面倒ですよね。

同じデバイスは似たMACアドレスを持っている（前半分は少なくとも同一メーカなので一致）ので、既存のデバイスと同種または同じメーカのデバイスを接続したときは、既知のMACアドレス（冒頭のコマンドで得られる）と先頭が共通しているやつをgrepで見つけると楽ですね。

```
arp -a | grep "既存のMACアドレスの先頭を切り取ったやつ"
```

これは特に、ネットワーク内に１億台同じメーカのプリンタを設置するときとかに役立ちますね。
また、逆の考えをすれば、１億台同じメーカを設置したあとに、１台別のメーカのプリンタ設置したときとかに、わざわざMACアドレス調べなくても特定できますね。(なんか一台だけMACアドレスがめっちゃ違うぞ！みたいに)


それでは、素晴らしいネットワークライフを！ごきげんよう！
40 代おっさん GASの関数(関数リテラル,アロー関数)について学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 関数

関数とは
一連の処置をまとめたもの

定義方法
・function文による関数の宣言
<https://qiita.com/kou1121/items/f7be2dc115b84a42f296>
・関数リテラル
。アロー関数

### 関数リテラル

構文

```javascript
function ( 仮引数1, 仮引数2, ...){
  //処理
};
```

関数宣言とほとんど同じですが、関数名を記述していない。
無名関数などと言われる。

関数式の最期にセミコロンが必要となる。

お試し

```javascript
const toshiki_ = function() {
  console.log('利樹大好き');
};

function saytoshiki() {
  toshiki_();
  console.log('利樹もパパ大好き');
}
```

### アロー関数

関数リテラルを短縮したもの

構文

```javascript
(仮引数1, 仮引数2, ...) => {
  //処理
}
```

お試し

```javascript
const toshiki_ = () => {
  console.log('利樹大好き');
};

function saytoshiki() {
  toshiki_();
  console.log('利樹もパパ大好き');
}
```

仮引数が一つの場合はもっと簡略化できる。

構文

```javascript
仮引数1 => {
  //処理
}
```

さらにステートメントが一つの場合は、もっと簡略化

```javascript
(仮引数1, 仮引数2, ...) => ステートメント
```

わらにステートメントが一つかつreturn文である場合は

```javascript
(仮引数1, 仮引数2, ...) => ステートメント
```

お試し

```javascript
function toshiki() {
  console.log(`利樹のBMI: ${bmi_(18,100)}`);
}

const bmi_=(weight,height) => weight/(height/100)/(height/100);
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
JavaSprictの型について

# JavaSprictのデータ構造。

## JavaScriptの型について
JavaScriptにはオブジェクト型とプリミティブ型の2種類が存在する。

- オブジェクト型（構造型）　　　　　値：mutable        属性：プロパティやメソッドを持つ。
- プリミティブ型（データ型）　　　　値：immutable   属性：プロパティやメソッドを持たない。　

プリミティブ型は真偽値や数値などの基本的な型のことです。プリミティブ型の値は、一度作成したらその値を変更することができません。この独特な特徴をimmutableと言います。
オブジェクト型は、複数のプリミティブ型の値またはオブジェクトからなる集合体です。オブジェクトは、一度作成した後も、その値自体を変更することができます。この独特な特性をmutaleと言います。　　

## オブジェクト型
オブジェクト型は以下のものが含まれます。

- プリミティブ型以外のデータ
- Object(オブジェクト)
- Array(配列)
- Function(関数）
- StringやNumberなどのオブジェクト
- Date
- 正規表現
- JSON

プリミティブ型以外ではないものは、全てオブジェクト型になります。

```sample.js
console.log(typeof ["pokemon"]);
console.log(typeof { name: "pokemon" });
console.log(typeof function() {});

//=> object 
//=> object
//=> function
```
一つ注意なのが、配列とオブジェクトがどちらもobjectと判定されているように、全てのオブジェクトの種類を判定することはできません。そのため、基本的にはtypeof演算子は、プリミティブ型かオブジェクト型かを判別するために使われます。

## プリミティブ型
プリミティブ型は以下のものが含まれます。

- Boolean型
- Number型
- BigInt型
- String型
- Symbol型
- String型
- Null型
- Undefined型

こちらもtypeofで確認していきます。

```sample.js
console.log(typeof "Pokemon"); 
console.log(typeof false); 

//=> "string"
//=> "boolean"
```
それぞれの型の定義するにリテラルを使用します。リテラルとは、プログラム上で数値や文字列など、データ型の値を直接記述できるように構文として定義されたものです。Symbol型とUndefined型以外のプリミティブ型には、リテラルが用意されています。

### undefined型
undefinedは、宣言のみが行われた変数、あるいは引数が存在しない仮引数に自動的に割り当てられるプリミティブ値のこと。

###Boolean型
booleanはtrueかfalseの値のみを取れる論理データ型です。例えば、JavaScriptではbooleanによる条件がコードの部分を実行するかや繰り返しなどを決定します。

```boolean.js
console.log(typeof true)
// => true
```

###Number型
Number型とは、数値を扱うためのデータ型です。JavaScriptのNumber型では、整数も小数も同じNumber型として扱われます。Number型には、10や-7などの数値リテラルと1.4や5.4e3などの浮動小数点リテラルがあります。

```number.js
console.log(typeof 111)
// => number
```


### BigInt型
BigInt型とは、Number型で取り扱うことのできない大きな数値を扱うためのデータ型です。ES2020で追加されました。Number型との互換性はなく、相互に代入や計算・等価比較などは行うことができません。

###Symbol型
Symbol型とは、「シンボル値」という固有の識別子を表現する値で、任意の不変な値のデータ型です。
Symbol()関数を呼び出すことで同的に生成されます。同じシンボル値を後から生成することはできません。オブジェクトのプロパティキーとして使用することができます。

###String型
テキストを表す連続した文字である文字列を扱うためのデータ型です。"Pokemon"のように囲んだ範囲が文字列リテラルとなります。

```string.js
console.log(typeof "pokemon")
//=> string
```

### Null型
Null型とは、値が存在しないことを意味するデータ型です。
nullリテラルであるnullは、プリミティブ値nullを返します。

```null.js
console.log(typeof null);
//=>object
```
##まとめ
オブジェクト型とプリミティブ型について書いてみました。改善点や修正点がありましたらご指摘、アドバイスいただけると幸いです。
よろしくお願い致します。
CoreMLって速いの？　PytorchMobileと推論時間を比較する

#比べてみました
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/36591f74-e733-1fe6-edbb-322c31fda3ce.png", width=400>

#CoreMLに変換できないモデルもiOSで実行したい

Pytorchで書かれたモデルには、CoreMLToolが対応していないオペレーションがあって、CoreMLに変換するのが難しいものもあると思います。
そんな時、TorchScriptをiOSで実行することで、iOSでモデルを動かせたりします。

CoreMLはニューラルエンジンが使えたり、デバイスに最適化されているようですが、実行速度はどれくらい違うのでしょうか？

#Yolov5で比較

PytorchMobileはこちらを使用

https://github.com/pytorch/ios-demo-app

CoreMLはこちらを使用

https://github.com/john-rocky/CoreML-YOLOv5

画像は記事の最初の画像です。
入力画像のリサイズから、NMS処理までの時間を計測しました。

#結果

torch:
0.91秒

coreml:
0.23秒

やはり速いCoreML。
ただし、CoreMLは初期化に数秒かかりますが、torchScriptはほとんどかかりません。
また、torchも1秒以下で推論はできています。
処理速度がシビアに要求されないケースでは、CoreML変換が難しいモデルをtorchMobileで実行するのは選択肢になり得るのではないでしょうか。

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
RailsアプリにBasic認証を実装する

## Basic認証とは

HTTP通信に元々備えられているユーザー認証の仕組み。
あるアプリケーションに利用可能なユーザー名とパスワードをあらかじめ設定しておき、ユーザーが利用しようとした際設定していたユーザー名とパスワードを入力させてログインできるようにする機能。要するに個別のパスワード設定ではなく全員に共通したパスワードでログインさせるようなこと。Railsで作成したアプリにBasic認証を導入するのは比較的簡単にできるようなので試してみたいと思います。

## Basic認証を実装するメソッド

Railsにはbasic認証を実装する’authenticate_or_request_with_http_basic’というメソッドが用意されているので、それを使ってbasic認証を実装してみたいと思います。

ベーシック認証が成功したらトップページに

![スクリーンショット 2022-02-16 10.50.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623433/43f6b856-fbf1-2b93-afcb-922df2f95051.png)

と表示されるようにします。

### authenticate_or_request_with_http_basicの記述

authenticate_or_request_with_http_basicメソッドはコントローラーに記述し、各アクションを実行する前のbefore_actionとして実装します。

```ruby
class ApplicationController < ActionController::Base
  before_action :basic_authentication
  
  private
  
  def basic_authentication
    authenticate_or_request_with_http_basic do |user_name, password|
      user_name == 'hoge' && password == 'huga'
    end
  end
end
```

localhost:3000にアクセスしてみます。すると、
![スクリーンショット 2022-02-16 11.02.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623433/f9de64b3-3ab4-50d3-2df1-dd05dd42ff3e.png)


このような画面が表示され、ユーザー名とパスワードの入力を求められます。



ユーザー名とパスワードを入力してログインボタンを押すと...

![スクリーンショット 2022-02-16 10.50.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623433/43f6b856-fbf1-2b93-afcb-922df2f95051.png)

認証に成功し、トップページが表示されました！めちゃくちゃ簡単！

## 認証範囲を限定することもできる
先ほどの例では全てのアクションにBasic認証が効く設定にしましたが、ある特定の範囲（ページ）に効果を限定することができます。「このページは誰でも見れていいけど、ここから先は特定の人にしか見せたくない」ような場合に有効かと思います。

・indexページ
![スクリーンショット 2022-02-16 11.42.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623433/cd9bc213-8773-282d-a4d0-241c9c4b4457.png)

・showページ
![スクリーンショット 2022-02-16 11.46.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623433/0524ba4b-4550-5c80-57ae-1561e09b2502.png)

・tasks_controller.rb編集

```tasks_controller.rb
class TasksController < ApplicationController
  before_action :basic_authentication, only: :show # showアクションにだけベーシック認証をかける
  
  def index; end
  
  def show; end
  
end
```

このように実装すると、showアクションにだけベーシック認証をかけられるようになります。
Autoresizing MaskになっているとAutolayoutが効かない

Autolayoutで左右の制約を設定したが、Viewの幅が制約通りにリサイズされず、小さいデバイスだと画面からはみ出してしまった。
原因を探っていくと、インスペクターで該当ViewのLayout設定が`Autoresizing Mask`になっていたところを、`Inferred(Constraints)`にすると、意図通りに表示されるようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37598/977ce0d7-cb39-3a22-b8cd-13cecb3453bb.png)

Webで漁っても解決策に行き着かなかったが、これは常識の範囲なのだろうか。
pandasのgroupbyに関する基本の処理について

#1. この記事について

メモ的な形でpandasのgroupbyの**基本的な操作**のおさらいをします.

#2. 課題設定 :
以下のdataframe ``a``に対して,操作Aの操作を加えてdataframeを作成せよ:

```python
import pandas as pd
a = pd.DataFrame([["a",1,2,"A"],["a",2,4,"A"],["b",3,6,"B"]],columns = ["w","x","y","z"])
```

- 操作A :
    - wの値が同じものに関して,
        1. xに関しては合計を
        2. yに対しては平均と分散を  
        3. zに対してはそのままの値を 
        4. wのの長さを加えて集約せよ.

# 3. データ確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/c0c63445-8831-ed97-cc61-36da889568bb.png)
# 4. 問題理解

- まず,``z``は``w``ごとに値が異なるためそれぞれの集約として考えることができる.
- すなわち,基本的に以下の操作で完結する:

```python
a.groupby(["w","z"]).hogehoge
```

# 5. 答えの例
以下の操作を加えることで,操作が完結する:

```python
# 1. xの合計
q1 = a.groupby(["w","z"])["x"].sum().reset_index().rename(columns={"x":"x_sum"})

# 2. yの平均と分散
q2a = a.groupby(["w","z"])["y"].mean().reset_index().rename(columns={"y":"y_mean"})
q2b = a.groupby(["w","z"])["y"].std().reset_index().rename(columns={"y":"y_std"}).fillna(0)
q2 = pd.merge(q2a,q2b)

# 3. それぞれの長さ
q3 = a.groupby(["w","z"]).size().reset_index().rename(columns = {0:"length"})

# マージを行う
res_df = q1
lst = [q2,q3]
for i in lst:
    res_df = pd.merge(res_df,i)
res_df.head()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417525/5c6b4f66-3f71-4a56-07d1-b1f6d2282970.png)
【Excel】セルの先頭に空白を表示させたい

◆はじめに
この記事は自身が忘れないようにするための、作業用memoとなります。
分かりづらい表現があっても悪しからず・・・


◆利用環境
・Windows10
・Excel2016


◆問題点
Execelの先頭に空白を手動で入れたくない

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/b1d4d6de-192d-3884-6b6c-471ace1463bf.png)

→共通資料だと人によって半角・全角の差があり、統一が難しくて管理が面倒
 いちいち変なセルを修正しないといけないし周知もしきれない・・・

個人的には列を分けたくなるが、会社のやり方はそうそう変えられない・・・


◆解決案
・字下げしたいセルを選択し、「ホーム」タブ > 「設置」 > 「インシデントを増やす」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/9107f21f-f4ef-b7e1-9a1b-e00c4ee9ac5c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/4e083cc8-1b30-424e-0386-70d9c4e5acd7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/7a25b0f5-d8e9-c2a0-fb3d-6ca67a1c44bd.png)

これで空白を入れなくても字下げしてくれる。
全半角の修正等も不要になる。
めちゃくちゃ嬉しいですな。


◆便利機能
さらに、字下げを一文字分だけでなく、二文字分、三文字分・・・と変更することもできる

変更したいセルを選択し、右クリック > 「セルの書式設定」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/14c6c801-23bf-1c0a-a608-5abf5467b617.png)

「配置」タブ > 「文字の配置」 > 「インシデント」で数値を上げ下げする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523520/19f7d841-2364-970a-43e7-ea0f4fc796d5.png)

これで数値に紐づいた文字数分だけ字下げすることができる。
あまりやりたくはないが、一行の中で複数項目を入れる場合には活用できるだろう。

.
.
.


以上、セルの先頭を字下げする方法を記載した。
Excelって便利ですな・・・
そして会社って面倒なことが好きですな・・・


おわり
jetson nano install memo

# environemnt
確認方法：https://www.fabshop.jp/jetson-nano-jtop/

H/W:
jetbot@jetbot-desktop:~$ cat /etc/nv_tegra_release # R32 (release), REVISION: 6.1, GCID: 27863751, BOARD: t210ref, EABI: aarch64, DATE: Mon Jul 26 19:20:30 UTC 2021
OS :
Linux jetbot-desktop 4.9.253-tegra #1 SMP PREEMPT Mon Jul 26 12:13:06 PDT 2021 aarch64 aarch64 aarch64 GNU/Linux
CPU : aarh64 rel 4.9.253-tegra(ARM v8)
libRealSense: 

https://qiita.com/y4su0/items/292fda9704e0de8d59c6

# nano editor
sudo apt install nano

# pip3
sudo apt-get install python3-pip

# TELNET
https://blackbird-blog.com/ubuntu-telnet-setup

#設定、自動ログイン、IPアドレス固定
https://qiita.com/mmt/items/35e034bc8cd0a1a661bc

# VNC
つながるけど、なんか重いな。
https://qiita.com/iwatake2222/items/a3bd8d0527dec431ef0f

win10 : UltraVNC

jetson nano のスタートアップ時のアプリ登録はこれ。http://fanblogs.jp/nikmaniphonelife/archive/176/0

#libRealsense

これは駄目。
https://qiita.com/karaage0703/items/39040f23cbb0611c0a0e

こっち (branch 59/ver2.50.0)
https://github.com/IntelRealSense/librealsense/blob/master/doc/installation_jetson.md

# git clone 

バージョンを意識してリポジトリを取得する。
git clone --depth=1 -b v2.50.0 git://github.com/Inte
lRealSense/librealsense.git

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/19f1e70d-8d94-4b9f-4e74-4613b90ebdad.png)

# CMAKE-CUDA-COMPILER
cmake で次のエラーとなる。

-- Info: Building with CUDA requires CMake v3.8+
-- The CUDA compiler identification is unknown
CMake Error at CMake/cuda_config.cmake:3 (project):
  No CMAKE_CUDA_COMPILER could be found.

~~jetpackにCUDA-COMPILERある。
sudo apt install nvidia-jetpack~~


PATHの問題だった。
https://github.com/jetsonhacks/buildLibrealsense2TX/issues/13

export CUDA_HOME=/usr/local/cuda

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64

export PATH=$PATH:$CUDA_HOME/bin

# make 
make -j$(($(nproc)-1))

# conda はインストールできない？ -> archiconda3 が使える

https://forums.developer.nvidia.com/t/anaconda-for-jetson-nano/74286/11

wget --quiet -O archiconda.sh https://github.com/Archiconda/build-tools/releases/download/0.2.3/Archiconda3-0.2.3-Linux-aarch64.sh && \
    sh archiconda.sh -b -p $HOME/archiconda3 && \
    rm archiconda.sh


export PATH=$HOME/archiconda3/bin:$PATH
conda config --add channels gaiar && \
conda config --add channels conda-forge && \
conda config --add channels c4aarch64 && \
conda update -n base --all && \
conda install -y python=3.6.7 libiconv && \
conda install -y conda-build && \
conda install -y anaconda-client
rubyにおける：：（ダブルコロン、コロンコロン）スコープ演算子

rubyではスコープ演算子というのがあります。::っていうやつです。
これを使うと、クラスやモジュールで定義されている定数を外部から参照することができます

```
module Test
  HOGE=20
  FUGA=30
end

class Hogehoge
  hoge = Test::HOGE
  p hoge
end
=> 20
```
こうすることによってmoduleで定義されている定数を参照することができるんです。

今回はメモ書き程度に終わらせようとおもいます
以上です。何か間違いがございましたら、ご教示いただけますと幸いです。
40 代おっさん GASの関数(function文による関数の宣言)を学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 関数

関数とは
一連の処置をまとめたもの

定義方法
・function文による関数の宣言
・関数リテラル
。アロー関数

### 関数の宣言

構文

```javascript
function 関数名() {
  //処理
}
```

お試し

```javascript
function toshikidaisuki() {
  console.log('利樹大好き');
}

function toshikimikan() {
  console.log('利樹はみかんが好き');
}
```

こうするとデバックの横に関数名が表記されていると思います。

これで関数は出来たので別の関数で呼び出しを行えます。

お試し

```javascript
function myFunction() {
  toshikidaisuki();
  toshikimikan();
}
```

このように別ファイルから呼び出しも可能

関数を表示する必要がないときアンカースコアを付けると見えなくなる。
プライベート関数
こうすると別のファイルからは呼び出せなくなる。(作ったファイルからは呼び出せる）

### 引数と戻り値

呼び出した関数に渡す値を<font color="Red">引数</font>
呼び出した関数から受け取る値を<font color="Red">戻り値</font>

構文

```javascript
function 関数名(仮引数1, 仮引数2, ...) {
  //処理
  return 戻り値;
}
```

お試し

```javascript
function toshiki() {
  console.log(`利樹のBMI: ${bmi_(18,100)}`);
}

function bmi_(weight,height) {
  return weight/(height/100)/(height/100);
}
```

### デフォルト引数と残余引数

javascriptでは渡す仮引数の数と、それを受け取る仮引数の数は一致してなくても良い
引数が渡されていない場合に値を持つようにできる。
そのことをデフォルト引数と言う

構文

```javascript
function 関す名(仮引数, 仮引数 = 値, ...) {
  //処理
}
```

引数を配列として渡す方法もある。
それを残余引数と言う

```javascript
function 関す名(..., ...仮引数) {
  //処理
```

お試し

```javascript
function toshiki() {
  family_('パパ', 'ママ', '利樹', 'アッキー', 'アッキーママ');
}

function family_(father, mother, child, ...sister) {
  console.log(father, mother, child);
  console.log(sister);
}
```

### 値渡しと参照渡し

引数の渡し方は2種類ある。

値渡し
数値、文字列、真偽値などのプリミティブ値を引数に指定した場合は、値を複製して関数に渡す。

参照渡し
オブジェクトや配列を引数に指定した場合は、オブジェクトや配列のメモリ上のアドレスを渡す。

お試し

```javascript
function myFunction() {
  const x = 100;
  console.log(`funcl_(x)の値： ${funcl_(x)}`);
  console.log(`xの値： ${x}`);
}

function funcl_(y) {
  y += 10;
  return y;
}
```

＊このように、参照渡しと値渡しを気にしないとえらい目にあいます。

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
fbxをインポートした時に出てくる黒帯付きのあれはプレハブでありプレハブではないという話（Unity）

# 結論

　[Model Prefab](https://docs.unity3d.com/Packages/com.unity.formats.fbx@4.1/manual/prefabs.html)

# 本文

　Unityで3Dファイルを扱う人なら誰もがこのようなアイコンを見たことがあると思います。プレハブに黒い帯がついたようなものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/816f619a-aa5c-3352-1ed2-cc2659c55bc7.png)

　**これ、プレハブじゃないの？**

　......と思ったので調べてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/148491c0-4d6f-0d09-c548-f0b89541a3b9.png)

　これが正しいプレハブのアイコンです。

# Unpackはできる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/446210af-77d5-8100-61ca-2e290aff4539.png)

　プレハブ解除はできます。このあたりはプレハブっぽいです。これを行うとただのゲームオブジェクトになります。

# 編集はできない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/d58d0002-3fc4-e68f-2296-f8610b65dbb0.png)

　普通のプレハブを編集するようにアセットをダブルクリックすると、なぜか「3Dビューア」が開きます。（※Windows の場合。Mac だとどうなんでしょう？）このあたりはプレハブとは違います。

# Variantは作れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/9db3ad81-0106-117e-fd37-0441ae9abd95.png)

　バリアントは作れます。このあたりはプレハブっぽいです。

# Variantの変更を反映することができない

　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288125/1f002e9c-b841-7bf0-7c5d-d010fcfe377e.png)

　バリアントの変更は、本来親のプレハブに反映させることができますが、親のプレハブが fbx である場合は不可能なようです。バリアント自体のパラメータを変えることはもちろん可能です。

# 結局何か

　調べてみると、これは [Model Prefab](https://docs.unity3d.com/Packages/com.unity.formats.fbx@4.1/manual/prefabs.html) というもので、（fbx に限らず）3Dモデルをインポートする時はこれが作成されるようです。要は中身を変更できないプレハブです。3Dモデル（のデータ）自体を頻繁にいじることはあまりないですし、もしそうしたい時でもバリアントを介してできるので（作業性的にもそうした方がいい気がします）、**実際知らなくても何も不都合のない知識ではありますが**、こういうことがわかるとスッキリしますね。

　この件はあまり調べても日本語でも英語でもクリティカルな情報が出てこなかったので（「fbx import unity prefab」とかで調べてやっと公式ドキュメントがヒットしたような気がします）、かなりささいなことですが記事にさせていただきました。
【Kotlin】ExposedでデフォルトのDBとは別のDBを扱う

## 概要

KotlinのORMフレームワークである[Exposed](https://github.com/JetBrains/Exposed)でデフォルトのDBとは別のDBを扱う方法です。
ちょいハマりしたので、備忘録として残しておきます。

## 結論

デフォルトDBを設定する方法と複数DB扱う方法は[公式のWiki](https://github.com/JetBrains/Exposed/wiki/Transactions#working-with-a-multiple-databases)に方法が書いてあります。

## 方法

```kotlin
// デフォルトのコネクション設定
val defaultDb = connect("jdbc:foo;", "org.foo.Driver", "fooUser", "")
TransactionManager.defaultDatabase = defaultDb

transaction {
   ...
}

// デフォルト以外のコネクション設定
val otherDb = connect("jdbc:bar;", "org.bar.Driver", "barUser", "")

transaction(otherDb) {
   ...
}
```

## 参考文献

- [Working with a multiple databases](https://github.com/JetBrains/Exposed/wiki/Transactions#working-with-a-multiple-databases)
激安リフロー炉の改造を改造してみた件

# 激安リフロー炉T-962とその改造
中国製の激安リフロー炉T-962というのがあって、3万円くらいで買えてしまいます。とはいえ標準だと制御が甘くてあまりうまくリフローでできないようです。そこで熱電対を追加して改造ファームウエアを書き込んで使っている例が紹介されています。私はこちらの記事を参考に改造してみました。

https://blog.vivita.io/entry/2019/09/24/113438

この改造をして、ソースコード内の温度プロフィルを調整することで、それなりにリフローはできるようになったのですが、どうも温度が上がりきらないことがときどきあったり、また炉内で温度が不均一なようで、特に端のほうでは半田が融けていないことがたびたびあります。

# 制御アルゴリズムの変更

まあこんなものかなあ、と思っていたのですが、改めて[改造ファームウエアのソースコード](https://github.com/UnifiedEngineering/T-962-improvements)を読んでみると、温度の制御がちょっとマズい（というか改善の余地がある）のではないかと思えてきました。このファームウエアでは、10秒ごとに目標温度を指定してそれに向けてPID制御する、という動作をします。つまり仮にその10秒間のうちに目標温度に到達しなくても、次のステップへ進んでしまうわけです。これだと、ヒーターの性能が足りずに温度が上がりきらないことは十分起こり得て、実際の「ときどき半田が融けない」という現象とも符合します。

一般にリフロー炉の温度制御は、以下のように行います（共晶半田の場合。温度の数値は部品によって異なるので一例）。
1. 150度ｰ200度で100秒保つ（予熱）
2. 220度以上まで加熱し、最高温度260度を10秒以内保つ（220度以上の時間は150秒以内）
3. 冷却

![ReflowProfile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/5e4b025f-d625-9f68-2469-a80773c74d7f.png)
（リフロープロファイルの例：[エイブリック（株）のWebページ](https://www.ablic.com/jp/semicon/support/package/solder-temp-profile/)より）

そこで、このような制御ができるように、リフローの温度プロファイルを、「目標温度、判定温度、保持時間」の3つの数値の組みで指定するようにしました。
- 目標温度：この温度になるようにヒータ・ファンを制御する
- 判定温度：この温度に到達したら保持モードに入る（温度制御は続ける） 
- 保持時間：保持モードに入ったあとで制御を続ける時間。この時間が過ぎたら、次の目標温度の制御へ移る

これに向けてソースコード（特にreflow.c）を書き換えました。なお制御値の上限と下限を指定しているのですが、どうもコンパイラのバグなのか、その値がうまく内部の変数に反映できないようでした。具体的には最大値を0xffff（65535）と指定しているのに、内部では503という半端な値となってしまいます。どうもこの値を使っているようで、オリジナルの改造ファームウエアのreflow.cでは、PID制御の制御値(out)から248を引く、という謎のマジックナンバーが出てきます（503-248=255）。またPID制御の理屈から言えば、実際の温度が目標温度よりも高い場合は制御値は負となり、ヒータを停めてファンを回すはずですが、制御値の最小値が0に設定されていて、「制御量が248以下のときはヒータを停めてファンをまわす」という謎の式になっています（つまり制御量=248がニュートラル）。

このあたりがどうも気持ち悪かったので、制御アルゴリズムも、本来のPID制御の制御値を使うように書き直しました。制御値が正のときはヒータをON（制御値に比例、最大255）でファンをOFF、負のときはファンをON（制御値（の絶対値）に比例、最大255）でヒータをOFF、としました。本来であれば制御値とヒータとファンの制御パラメータ（PWMデューティ比）との係数は異なるはずですが、とりあえずは同じ比例係数にしました。

# 実際のリフロー動作

まず、以下のパラメータで制御をしてみました。
- 目標温度=190、判定温度=150、保持時間=100
- 目標温度=260、判定温度=250、保持時間=10
- 目標温度=50、判定温度=80、保持時間=20
あわせて、炉内にダミー基板を中央と端においてそこに熱電対を固定して、その温度もあわせて記録しました。

![T260.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/fe7e753d-7b1d-953d-3016-25c3fd9dda2a.png)

そのときの温度カーブが上図です（同時に計測できないので、2回（A/B）に分けて計測しているのでグラフの左右の位置はずれています）。
システムが持っている熱電対の温度（制御A/B）はほぼ指定通りになっていますが、基板表面温度が加熱中は高めに出る傾向があり、特にピーク温度は目標温度の260度を大きく超えて280度以上まであがってしまっています。
システムの熱電対は炉の上の方にあるので、基板温度とはずれていて時間遅れもあるだろうことは予想していたのですが、この温度差はけっこう問題です。

そこでピークの目標温度を240度に変更して、同様の制御をして温度を計測してみました。

![T240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/d2aa7863-3600-38e9-54a5-43df40f0d321.png)

そのときの温度カーブが上図です（同様に2回（A/B）に分けて計測しているのでグラフの左右の位置はずれています）。基板温度が炉内の中央と端で5度位のずれはありますが、255−260度で収まっていそうです。また予熱時間やピーク温度付近の時間も問題なさそうです。

実際にクリームはんだを塗ってと部品を載せてのリフローをした結果は、追って報告したいと思います。

ソースコードはこちらですが、実は手元のT-962は液晶モニタが故障してしまって表示されないため、画面表示関連は一切手を加えていません。また複数プロファイルの切り替えも未実装です。どなたか、実装していただけるとうれしいです。

https://github.com/akita11/T-962-improvements/