OmniAICreator/Qiita-1.07M huggingface dataset:
Excel VBAでの最終行・最終列の取得方法

Excel VBAでコードを書いていくときにシートの最終行を取得して
処理を行い時があると思います。

今回はシートの最終行を取得するコードについて書いていきます。

最終行を取得する場面としては
例えば、
*1.csvファイルに対して、データの件数分繰り返し処理を行いたい場合
2.シート上の範囲を選択し、その範囲に対して処理を行いたい場合*
等が挙げられると思います。

その他、最終行を取得したい方も参考にしていただけると幸いです。

さて、最終行を取得するコードですが、以下のようにコーディングすることで取得することが出来ます。

```
Cells(1, 1).End(xlDown).Row
```

ExcelのショートカットキーでいうとCtrl + ↓の操作と同じことをしています。

このコードではA列の先頭行から下へ向かって値の入っているセルの行数を取得するコードになっています。
このコードは一点気を付けなければいけないことがあります。
上から下へ向かって行数を数えるため、途中に空白行があった場合は
その空白行の上のセルを最終行として認識してしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031387/2f1e944a-b3ec-8128-6446-1d87faa8a539.png)

※上記のケースだとA列の最終行は5行目となってしまいます。



そのため私は以下の方法で最終行を取得することがほとんどです。

```
Cells(Rows.Count, 1).End(xlUp).Row
```

この方法が先ほどのコードと違う点は、シートの最終行から上へ向かって、値が入っているセルを探すという方法です。

こちらはExcelのショートカットキーでいうとCtrl + ↑の操作と同じことをしています。
そのため、途中に空白行があったとしてもA列の一番下の行数を取得することが出来ます。

個人的には先ほども書きましたが、こちらの方を常に使用するくらいお勧めします。

さて、最終行の取得について、ダラダラと書いていきましたが、ここまで読んでくれた方の中には
最終行だけではなく、最終列の取得についても知りたいと思っている方もいると思います。

同じように最終列を取得する方法はあります。

```
Cells(1, 1).End(xlToRight).Column
```

そしてこちらも最終行取得の際と同じように先頭列からカウントしていくのか最終列の二通りがあります。
上記のものは先頭列から取得する方法になります。

そして最終列からカウントしていくコードは以下のようになっています。

```
Cells(1, Columns.Count).End(xlToLeft).Column
```

原理は同じです。

ただ、最終列の取得に関しては、どちらの方法を採るのかは場合によって使い分けています。
その理由は最終列の取得をするケースとしては、
特定の列を一行分コピーして別シートへ転記をするようなことが多いです。
このような場合だとだいたいのケースがA列にヘッダー情報が入っている場合が多いです。
（CSVファイル等)
そのため、先頭列から右へ向かって最終列のカウントしたとしてもA列はヘッダー部なので
空白であることが考えにくいです。
であれば、先頭列からカウントして問題ないです。

このように最終列の取得に関しては場合によって分けています。

ちなみに、余談ですが、エクセルのシートの最終行と最終列は以下のようになっています。
最終行：1048576行
最終列：XFD列


ExcelVBAは、同じことをするにしても色々なコーディングがあり、
書き方によって数分かかるものも少しの工夫で数秒で終わるようにコーディングできます。

最終列・最終列の取得もなるべく先頭からカウントすることで処理にかかる時間を僅かですが、抑えることが出来ます。
ただ、最終行の取得に関して一番下から上へ向かって取得することをお勧めします・・・
（三度目の主張）
IPアドレス 基礎

#【IPアドレス 基礎】

LPICでIPアドレスについて学びましたが、基本情報技術者試験でもネットワークに関する知識が問われるので復習しました。

##グローバルIPアドレス、プライベートIPアドレス

<strong>グローバルIPアドレス</strong>は、インターネットに接続する端末に割り当てられるIPアドレスであり、世界でー意に割り当てられる。

<strong>プライベートIPアドレス</strong>は、社内ネットワークなどに接続する端末に割り当てられるIPアドレスであり、直接インターネットに接続することはできない。

##NAT （NetworkAddress Translation）

<strong>NAT</strong>は、プライベートIPアドレスをグローバルIPアドレスに変換する。

##サブネットマスク

<strong>サブネットマスク</strong>は、IPアドレスをネットワークアドレスとホストアドレスに分割し、複数のより小さいネットワークを形成するために用いられる。

##例

<strong>問</strong>

次のIPアドレスとサブネットマスクをもつPCのネットワークアドレスはいくらか。

IPアドレス　10.170.70.19
サブネットマスク　255.255.255.240

<strong>答え</strong>

IPアドレスがどのネットワークに属しているか否かを判断するには、
IPアドレスとサブネットマスクをAND演算する。

10.170.70.19を2進数で表現すると、
00001010 10101010 01000110 00010011

同様に255.255.255.240も2進数で表現すると、
11111111 11111111 11111111 11110000

以下、AND演算の結果は下位4ビットが0
それ以外（28ビット）は元のビット列である。
00001010 10101010 01000110 00010000

ネットワークアドレスは、これを10進数で表現した 10.170.70.16 になる。
PowerAutomateでSharePointのユーザー列からUPN(ユーザープリンシパル)を取得

覚え書きです。

#状況
- 例：タスクを管理するSharePointリストに「担当者」のようなユーザー列を作成し、PowerAutomateにて①リストへの登録をトリガー→②担当者のメンショントークン取得→③フローボットからTeamsチャネルへ投稿(担当者にメンション)といったフローを想定。
- メンショントークンの取得にはUPNが必要ですが、組織によってはUPN=Emailではなく、Emailを設定しても動きません。
※UPN＝AzureAD/M365のログインID。
※連絡用メールアドレスを企業ドメインのものに設定しているなど、M365のログインIDとOutlookメールアドレスが異なる場合です。


#対応方法
ユーザー.Claimsから関数を使用してUPNを取り出します。
Claimsの例
```i:0#.f|membership|************@********.onmicrosoft.com```

①まずユーザーのClaims変数にユーザー.Claimsを変数にセット
②次に以下の関数でUPNを取り出し
|以降の文字を取り出す処理です。

```JavaScript:UPN取り出し
substring(variables('ユーザーのClaims'),add(lastIndexOf(variables('ユーザーのClaims'),'|'),1))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/749cccbd-440b-8267-4358-3519b7890cdc.png)
数式バーが小さいと思ったら全てのPowerAutomate設定を表示→プレビュー機能を
Onに
コントローラについて

#目次
<b>①コントローラとは</b>
<b>②コントローラの作成方法</b>
<b>③コントローラの削除方法</b>
<b>④コントローラの処理のカテゴリー</b>

##①コントローラとは
MVCモデルの役割の一つ。リクエストに対する処理をまとめて用意しておき、ルーティングからリクエストを受け取って処理を行った後、クライアントにレスポンスを返す。またレスポンスに必要となるデータがあれば、他の役割と連携してデータを取得したり受け渡しを行い、レスポンスを完成させる。

##②コントローラの作成方法

```
rails g controller コントローラ名
#コントローラを作成、コントローラは複数形
```


##③コントローラの削除方法
```
rails d controller コントローラ名
#コントローラを削除、コントローラは複数形
```

##④コントローラの処理のカテゴリー
コントローラはリクエストに対応する処理を記述する場所。リクエストの処理はアクションと呼ばれ、主に7つのアクションがある。

|アクション名|何に対応するか|
|:--|:---:|--:|
|index|一覧表示ページを表示するリクエストに対応|
|new|新規投稿のページを表示するリクエストに対応|
|create|データの投稿を行うリクエストに対応|
|show|詳細ページを表示するリクエストに対応|
|edit|編集ページを表示するリクエストに対応|
|update|データの更新をおこなうリクエストに対応|
|destory|データの削除をおこなうリクエストに対応|
[jQuery] を使う準備をする

#CDNを利用してjQueryを読み込む
今回はGoogleが提供しているCDNを読み込みます。
[Googleが提供しているCDN](https://developers.google.com/speed/libraries/#jquery) を開き、利用したいjQUeryのバージョンのコードをコピーしてHTMLの `head` 内に貼り付けます。
（今回は `v3.X` の最新版を利用してみました。）

#jQueryのコードを記述するファイルを読み込む
jQueryは、.js形式のファイルにコードを書きます。 HTMLファイルで、 `<script src="ファイルのURL"></script>` を追記します。 `<script>` はbody閉じタグ直前に書くことで、WEBページの表示速度をより早めることが出来ます。
今回ファイルのURLは `script.js` にしました。
ファイルのURLを間違えないように注意しましょう。

```:html
<body>

  <script src="script.js"></script>
</body>
```

#js形式のファイルにコードを書いていく
jQueryはHTMLの中身を操作するので、HTMLの読み込みをしてからjQueryの操作を開始します。 そのためにreadyイベントを使用し、 `$(document).ready()` の中身にjQueryの処理を書いていきます。 この構文の省略形は、 `$(function(){ });` と書くので今回は省略形で書いていきます。

```:script.js
$(function(){
　　処理
});
```

処理の中に実行したい処理を書いていきましょう。
【CSS】背景色を斜めに切り替える

## `transform: skew`を使う

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="Lvbqwx" data-user="n_ninja" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/n_ninja/pen/Lvbqwx">
  斜め切り替えの背景</a> by sanagi (<a href="https://codepen.io/n_ninja">@n_ninja</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


他にも`clip-path`を使う方法もあるみたいだけど、より複雑な形を作りたいとき向けな気がしたので、これが一番手っ取り早いかも？
GCP サービスアカウントキーが発行されているサービスアカウント一覧の取得方法

[gcloud alpha asset list](https://cloud.google.com/sdk/gcloud/reference/alpha/asset/list)コマンドを使えば取得が出来る


### 組織単位で取得
```
gcloud alpha asset list --organization='組織ID' --asset-types='iam.googleapis.com/ServiceAccountKey' --content-type='resource' --filter="resource.data.keyType=USER_MANAGED"
```

### プロジェクト単位で取得
```
gcloud alpha asset list --project='プロジェクトID' --asset-types='iam.googleapis.com/ServiceAccountKey' --content-type='resource' --filter="resource.data.keyType=USER_MANAGED"
```
これまでの(LPC1114を用いた) IchigoJam と IchigoJam R 両対応のマシン語

先日、[こどもパソコン IchigoJam](https://ichigojam.net/) の新製品の IchigoJam R が発表されました。

[IchigoJam R ＆ IchigoSand 発表、HHKB他USBキーボード対応するRISC-V版、Zen言語でかんたんマシン語両対応 zen4ij #IchigoJam #riscv #zen / 福野泰介の一日一創 / Create every day by Taisuke Fukuno](https://fukuno.jig.jp/3077)

※IchigoJamはjig.jpの登録商標です。

さて、この IchigoJam R 、これまでの IchigoJam とはCPUの種類が違うため、これまでのマシン語が使えないようです。
上記の記事の「両対応」は「同じソースコードからそれぞれのマシン語を生成できる」という意味で、
同じマシン語を両方で使えるわけではありません。

しかし、動く機種を限ってしまうというのは不便ですので、なるべく避けたいです。
そこで、同じマシン語を同じ位置から実行することで、両方で動くようにできる方法を考えました。

# 両対応のマシン語

結論からいえば、例えば

```
00101111 10110111
11100xxx xxxxxxxx
```

というマシン語が使えることがわかりました。

これまでの IchigoJam では、1行目は`R7 - #B7`を、2行目は`GOTO n11`を表します。
![これまでの IchigoJam のマシン語 (一部)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/0661a329-9da1-7fd8-e493-5d108fbd524b.png)
([Cortex-M0 Armマシン語表 （asm15表記、抜粋）](https://mikecat.github.io/asm15/armasm.html) より抜粋)
1行目は比較命令なのでフラグレジスタの値が破壊されますが、他の汎用レジスタ(PCは除く)の値には影響を与えず、
2行目の`GOTO`で(命令が対応する範囲の)任意の場所に制御を移すことができます。

一方、IchigoJam R では、この2行で`R31 = n32` (`lui`) を表します。
![IchigoJam R のマシン語 (一部)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/9c2880b0-6f47-2726-da0a-e3e5b5f475d6.png)
([RV32C RISC-Vマシン語表 （asm15r、抜粋）](https://mikecat.github.io/asm15/rvasm.html) より抜粋)
したがって、レジスタ`R31`の値が破壊されますが、他の汎用レジスタの値には影響を与えず、
次の命令に進むことができます。
[The RISC-V Instruction Set Manual, Volume I: User-Level ISA, Document Version 20191213](https://riscv.org/technical/specifications/) の Chapter 25 RISC-V Assembly Programmer's Handbook を参照すると、
このレジスタ`R31`にあたる`x31`は Temporaries かつ Saver が Caller となっているため、
マシン語を呼び出してすぐ保存するべきような重要な情報は入っていないと考えられ、
この処理により破壊してしまってもまあ大丈夫でしょう。

したがって、このマシン語により、データの破壊を最小限にしつつ、これまでの IchigoJam では処理をジャンプさせ、 
IchigoJam R では処理をジャンプさせない、ということが可能になります。
あとは、分岐後にそれぞれの仕様に沿ったマシン語を配置すればいいでしょう。

# 組み込み例

以下のコードでは、これまでの IchigoJam ではマシン語が0を返して「イママデノ ヤツ」を出力する一方、
IchigoJam R ではマシン語が1を返して「アタラシイ ヤツ」を出力します。

```
10 ' CPU ｦ ﾊﾝﾍﾞﾂ ｽﾙ
20 POKE#700,`10110111,`00101111 :' R7 - #B7
30 POKE#702,`00000001,`11100000 :' GOTO @TRAD
40 POKE#704,`00000101,`01000101 :' R10 = 1
50 POKE#706,`10000010,`10000000 :' RET
60 ' @TRAD
70 POKE#708,`00000000,`00100000 :' R0 = 0
80 POKE#70A,`01110000,`01000111 :' RET
90 IF USR(#700,0) ?"ｱﾀﾗｼｲ ﾔﾂ" ELSE ?"ｲﾏﾏﾃﾞﾉ ﾔﾂ"
```

![実行結果 (これまでの IchigoJam)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/a6129983-09fc-0e38-bc03-1207b2d3e73a.png)
![実行結果(IchigoJam R)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/e122bd02-6828-ba44-1bbe-9371c0a14d2f.png)


# 結論

これまでの IchigoJam ではジャンプするが IchigoJam R ではジャンプしない命令を用いることで、
マシン語がどっちのCPUで実行されているかを判別し、
それぞれにあった処理に分岐させることができることがわかりました。
埋め込み実験用記事

[検知されないリンク](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8)

[検知されるリンク](https://gyoubumasataka.github.io/sidecode_hub/redirect.html?https://gyoubumasataka.github.io/sidecode_hub/ExportedTest.html)
テーブルの内容を修正する方法

# rails db:rollbackの手順

マイグレーションを差し戻して、テーブルの内容を修正する。

必要な手順は以下の3ステップ

>ステップ１　`ロールバック`
>>ステップ２　`migrationファイルの修正`
>>>ステップ３　`再度migrationを実行`


# ステップ１
## rails db:rollbackコマンド


```:ターミナル
% rails db:rollback
```

`rails db:rollback`
カラム名を誤ってしまった場合などに、モデルに紐づくテーブルを作り直したいときに用いられるターミナルコマンド

>例: nameをnemeにしてしまった等

`「差し戻す」`と表現される


実行すると以下のような表示が出て差し戻される。

```:ターミナル
== 20200315054113 CreatePosts: reverting ======================================
-- drop_table(:posts)
   -> 0.1939s
== 20200315054113 CreatePosts: reverted (0.2332s) =============================
```

### rails db:migrate:statusコマンドとは？
補足情報として
`rails db:migrate:status`というコマンドで状態を確認出来る。

```:ターミナル
% rails db:migrate:status
```

- マイグレーションファイルの状況
 - up = 実行済み
 - down = 適応されていない

```:ターミナル
database: first_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190820071210  Create posts
```

**downの表記がされていれば差し戻されている**

```:ターミナル
database: first_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
  down    20190820071210  Create posts
```



# ステップ２
## migrationファイルの修正


```ruby:db/migrate/20XXXXXXXXXXXX_create_変更前.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.text :memo
      t.timestamps
    end
  end
end
```

`t.text :memo`を`t.text :content`へ変更

```ruby:db/migrate/20XXXXXXXXXXXX_create_変更後.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.text :content
      t.timestamps
    end
  end
end
```

### カラム名と型とは？
補足情報として、カラム名と型とは何のことなのか解説

```ruby:カラム名と型
t.text :memo
```
t.に続くのがカラムの型
その右側にシンボルで記載されるものがカラム名



# ステップ３
## 再度migrationを実行
`修正したマイグレーションを実行`します。

```:ターミナル
% rails db:migrate
```



# 以上の修正が反映されているか確認して終了です
Chromium OSをVMwareにインストールしてみた

## 概要

`Chromium OS`は、`Chromebook`にインストールされている`Chrome OS`のオープンソース版です。
`Chromium OS`を`VMware Player`や`ESXi`にインストールし、動かしてみました。

## 準備

- `VMware Player`、または、`ESXi`
- Googleアカウント

## 手順

### Chromium OSをダウンロード

1. [Neverware社](https://www.neverware.com/)から`CloudReady`をダウンロードします。
1. `CLOUDREADY EDITIONS`メニューから`HOME`をクリックします。
1. `Where can I find VM images?`とあるので、`Download VM images →`リンクをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/e1830a65-a902-d864-c71a-0ae7676d8c9c.png)

1. `Download CloudReady Image For VMware`というブログのページが開くので、`Download v83 (64bit) CloudReady: Home Edition OVA file`リンクをクリックします。
1. `OVA`ファイル(`CloudReady-Home-v83-x64.ova`)をダウンロードします。

## VMware Player/ESXiで仮想マシンを起動

1. `VMWare Player`を開きます。
1. `仮想マシンを開く`をクリックします。
1. ダウンロードした`OVA`ファイルを選択し、`開く`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/dd8dddf2-0018-c485-0fdc-14796f76dc51.png)

1. `インポート`ボタンをクリックします。

## Chromium OSをセットアップ

1. `Chromium OS`のセットアップ画面が表示されます。
1. `English (United States)`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/1a02d2a6-3def-aa5d-e3ff-559b8135dfe3.png)

1. 言語を`日本語`、キーボードを`日本語`に変更し、`OK`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/fda29e14-79fb-1dab-da5d-e207a190f358.png)

1. `続行`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/2d572ec2-0a2f-f40e-9948-a6938906dc10.png)

1. `VMware Player`、または、`ESXi`から有線LANに接続できるはずなので、`Ethernet`が`接続済み`と表示されていることを確認し、`次へ`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/9fc6fb44-32dc-ee75-f2d2-ce060546d331.png)

1. `Send metrics to help improve CloudReady`にチェックが付いている場合は、`CloudReady`の改善を手助けするため、メトリクス情報が送信されます。
1. `CONTINUE`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/56bc0efc-c9bd-cb6d-7903-6ee9239308ed.png)

1. Googleアカウントの`メールアドレス`を入力し、`次へ`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/95a5419c-2b9e-209c-7e9b-ae9cdc0ffe97.png)

1. Googleアカウントの`パスワード`を入力し、`次へ`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/2de9fd4a-f8d6-6f28-ef39-3b7de665bbc0.png)

1. Googleアカウントで２段階認証を有効にしている場合、Gmailアプリにメッセージが届くので確認し、`はい`をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/f2976088-515f-d344-ab54-09c31427b7e2.png)

1. これで設定完了となります。`利用を開始`ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/03e310ba-516e-a4e4-27ea-45fc1310c853.png)

1. 次の画面で表示されるダイアログボックスの右上の`X`印をクリックしてください。あるいは、`GET STARTED`ボタンをクリックすると、次の画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/cde1d6e2-e68e-f31a-5133-32e5a27507a0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332590/c8f09cfb-dbd0-d1df-4ef5-60bd15bcc30c.png)

1. 以上です。
IntteliJベースのIDEのターミナルをGit BashやPowerShellに変更する方法

# この記事のターゲット
- Windows
- IntteliJ ベースIDE
    - IntelliJ IDEA, PyCharm, WebStorm, PHPStorm, CLion, RubyMine, Rider, GoLand etc...

# やり方
```
[メニューバー] → [File] → [Settings] → [Tools] → [Terminal] → [Shell path]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542505/93d86e1a-d157-154b-5a11-f0ad746bfc96.png)
ここを変更すると起動するターミナルを変更することができます。

## **Shell path**の変更
変更したいターミナルに合わせて、以下の通り変更してください。
なお、パスは環境によって異なることがあります。
普通にコマンドでの指定でも問題なく動作します。

### コマンドプロンプト
```cmd
C:\Windows\System32\cmd.exe
```
```cmd
cmd
```

### GitBash
```cmd
C:\\Program Files\\Git\\bin\\bash.exe
```

### PowerShell
```cmd
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
```
```cmd
powershell
```

# Motivation
私は普段 Mac、Windows、Ubuntu を気分で使い分けて開発しています。
中でもMacとUbuntuが多いので、 UNIX コマンドに慣れ親しんでいます。
Windows で IntteliJ の Terminal を起動したら、コマンドプロンプトが立ち上がってクソほど腹が立ったので "Terminal" で起動するターミナルを変更しました。

# Future
- WSLを起動できるようにしたい
toio SDK for UnityでMMLを再生する

# 概要
[toio SDK for Unity](https://github.com/morikatron/toio-sdk-for-unity/)のMIDI note number再生機能で、MML（Music Macro Langauge）を再生しました。

## GitHub repository
https://github.com/zurachu/toio-mml/

## WebGL sample
toioキューブ実機が必要です。
３台まで接続可能にしています（当方2台しか持っていないので3台は動作未確認）
https://zurachu.github.io/toio-karuta/

Google Chrome推奨、あと別タブに切り替えるとパフォーマンスが落ちて発音のタイミングがズレズレになるので注意です。

## 動画（Twitter）
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/toio?src=hash&amp;ref_src=twsrc%5Etfw">#toio</a> でmml再生するやつ、Qiita用に再収録。 <a href="https://t.co/5fMeVUGt5P">pic.twitter.com/5fMeVUGt5P</a></p>&mdash; ヅラChu (@zurachu) <a href="https://twitter.com/zurachu/status/1353684979180466178?ref_src=twsrc%5Etfw">January 25, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 技術情報
## MMLのパース
C#で書かれたMMLPlayer（パーサ）を教えていただいたので、こちらを利用しました。
https://github.com/Enichan/textplayer

Unity projectのAssets内に入れたら、問題なくビルド通ります。

TextPlayer.MML.MMLPlayerを継承したclassを作成して、PlayNote()をoverrideし、受け取ったNoteからCube.SoundOperationに変換してtoioキューブに再生指示を出します。

```ToioCubeMmlPlayer.cs
public class ToioCubeMmlPlayer : MMLPlayer
{
    // （中略）

    protected override void PlayNote(Note note, int channel, TimeSpan time)
    {
        var durationMs = (int)note.Length.TotalMilliseconds;
        var volume = (byte)(note.Volume * 255);
        var noteNumber = (byte)(noteMap[note.Type] + note.Octave * noteNumberPerOctave);
        if (note.Sharp)
        {
            noteNumber++;
        }

        var operations = new Cube.SoundOperation[]
        {
            new Cube.SoundOperation(durationMs: durationMs, volume: volume, note_number: noteNumber)
        };

        cube.PlaySound(1, operations);
    }
}
```

[Cube.SoundOperationの同時指定数は最大59](https://toio.github.io/toio-spec/docs/ble_sound#operation-%E3%81%AE%E6%95%B0)ですが、MMLPlayerによって、必要なタイミングで１音の指定が送られる→1音ぶんのCube.SoundOperationを送る、で良くなっているので、Operationの最大数を考慮する必要は無いです。
また、所謂[「テンポずれ」問題](https://ja.wikipedia.org/wiki/Music_Macro_Language#%E3%80%8C%E3%83%86%E3%83%B3%E3%83%9D%E3%81%9A%E3%82%8C%E3%80%8D%E5%AF%BE%E7%AD%96)も起こらないです。
一方で、都度toioキューブと通信を行うため、同時に他の通信を行うとラグが出る可能性はあります。
【24＿集合場所問題】コマ大数学科

# 【24＿集合場所問題】コマ大数学科

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/c0e95130-669e-71d2-522a-934f80816a29.png)

```latex
  
\begin{tikzpicture}
    % 碁盤の目(格子状)を描く
    \foreach \x in {0,1,...,8}
    {
      \draw (\x,0)--(\x,8);
      \draw (0,\x)--(8,\x);
      \node at (\x,0)[below]{\x};
      \node at (0,\x)[left]{\x};
    }
    % それぞれの位置を定義
    \filldraw [fill=cyan] (1,2.5) circle (0.1) node [right]{1人};
    \filldraw [fill=red] (3,7.5) circle (0.1) node [right]{5人};
    \filldraw [fill=green] (5,3.5) circle (0.1) node [right]{2人};
    \filldraw [fill=green] (6,5.5) circle (0.1) node [right]{2人};
    \filldraw [fill=yellow] (7,1.5) circle (0.1) node [right]{3人};
  \end{tikzpicture}
```
はじめてのCorvusSKK チートシート

CorvusSKKに入門してみた．日本語入力でEnterを押す回数が減ったので良さそう．

# 使い方

## 入力方法

漢字練習 → `KanjiRensyuu`

新しい → `AtaraShii`

おまけ → `omake`

使い方 → `Tukaikata`

勝った → `KaTta`

## カタカナ入力

日本語入力ONの状態で q を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/2f6edbab-b0ba-3ae5-a5f0-5501b3998d9a.png)

# カスタマイズ

## Ctrl+Spaceによる切り替え

IMEのONとOFFは同一キーバインドにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/d62579d6-2308-f0ae-5bd4-40de745d5185.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/6fa2d7e0-d272-3fd6-4369-49be634cec14.png)

## 初期入力をASCIIに

ターミナルでの操作が頻繁なのでASCIIをデフォルトに設定した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/d98a83b6-5536-a1b5-7cb9-42b36b7ceee1.png)

# ▽と▼を表示

入力時に表示したい場合にチェックを入れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/c4610ae8-067b-b95f-f5f9-17fb0823047c.png)

# カンマとピリオドの変更

更新を忘れずに押す．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/c169b2fd-f518-1b98-5ffc-27a0e0b76e6c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/db745444-f3b8-c44c-c7b0-65dd3526918a.png)
【23＿くりこみ】コマ大数学科

【23＿くりこみ】コマ大数学科

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/755ad145-aefd-eacb-20ca-3760de91437f.png)

```latex
\begin{tikzpicture}
    % 長方形
    \filldraw [fill=black!50!white] (-2,-2) rectangle (0,0); 
    % 線を描く
    \draw [very thick](-2,0)--(0,0)--(0,-2);
    % 板を積み重ねていく
    \foreach \x/\y in {0.2/0.3,0.5/0.6,0.9/0.9,1.3/1.2,2/1.5}
    {\filldraw [fill=yellow!50!white] ({-1.5+\x},{\y-0.3}) rectangle ++(2,0.3); }
    % 1枚分を判断する線
    \draw [dashed] (0,0)--(0,2);
    \node at (-1,-1)[fill=white]{机};
  \end{tikzpicture}
```
アプリケーションの作成〜立ち上げ

#アプリケーション作成の流れ
<b>①アプリケーションを保存するためのディレクトリを作成</b>
<b>②新規のrailsアプリケーションを作成</b>
<b>③データベースを作成</b>
<b>④アプリのケーションの立ち上げ</b>

###①アプリケーションを保存するためのディレクトリを作成
ホームディレクトリから新規フォルダで適当な名前のディレクトリを作成する

###②新規のrailsアプリケーションを作成
```
cd ①のディレクトリ
#①のディレクトリに移動する

rails railsのバージョン　new Career_up -d mysql
#railsのバージョンを指定して、Career_upを作成

cd Career_up
#Career_upのディレクトリに移動する

pwd
#現在のディレクトリに移動
```

###③データベースを作成

```
rails db:create
#データベースを作成する
```


###④アプリのケーションの立ち上げ

```
cd Career_up
#Career_upのディレクトリに移動する

rails s
#Career_upのディレクトリ上記のコマンドを打つ
```

以上です
【021_等分】コマ大数学科

# 【021_等分】コマ大数学科

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/0131b000-e3ec-a7ea-3780-0f2778e5977c.png)

```LaTeX
    \begin{tikzpicture}
      \filldraw [fill=yellow!50!white](0,0) circle (0.5);
      \filldraw [fill=yellow!50!white](1,0) circle (0.5);
      \filldraw [fill=yellow!50!white](2,0) circle (0.5);
      \filldraw [fill=yellow!50!white] (1,1) circle (0.5);
      \filldraw [fill=yellow!50!white] (2,1) circle (0.5);
      \fill (0,0) circle (0.05) node at(0,0) [below left]{P};
      \node at (0,3){(1)};
    \end{tikzpicture}
  \hspace{3cm}
  \begin{tikzpicture}
    \filldraw [fill=cyan!50!white] (0,0) rectangle (5,1);
    \filldraw [fill=cyan!50!white] (2,0) rectangle (3,3);
    \filldraw [fill=cyan!50!white] (1,1) rectangle (4,2);
    \filldraw [fill=cyan!50!white] (1,0) rectangle (2,1);
    \filldraw [fill=cyan!50!white] (2,1) rectangle (3,2);
    \filldraw [fill=cyan!50!white] (4,0) rectangle (5,1);
    \node at (0,3){(2)};
    \fill (0,0) circle (0.05) node at (0,0) [below left]{P};
  \end{tikzpicture}

```
Ｅ検定個人勉強用

目次

 - [目次](#目次)
     - [始めに](#始めに)
     - [内容](#内容)
         - [Python基礎文法](#Python基礎文法)
            - [変数](#変数)
            - [データの型](#データの型)
            - [制御文](#制御文)


# 始めに
私は2017年院卒でメーカーに入社しました。
毎日日経新聞を読んでいたところＡＩやＩｏＴに興味を持つ。
とんとん拍子で話が進み会社の金でＥ検定講座を受講中。
全体像が把握できないので文章に起こすことにしました。
あくまで個人ノートという位置づけ。

# 内容

## Python基礎文法
機械学習を行う上で大事なPython基礎文法  

### 変数
数学でいうところのｘにあたる。
代入が可能。

```
x = 10
print(x)
```
計算とかもできる

```
x = 10
y = 2000 + x
```

### データの型

int : 整数　・・・　そのまんま整数
float : 小数　・・・　小数点のやつ
・・・・・数学的な演算ができる
str : 文字列
・・・・・連結可能　
ex)

```
"Tennis" + "したい"
```

基本のデータ型はたくさんある
【リスト】順番大事なデータの集まり[1,2,3]
【辞書】キーバリューのデータ｛"テニス":"したい"｝
【タプル】組み{1991,2010}
【セット】値の重複だめ{"テニス","バレー","卓球"}

異なるデータの型は計算不可

ただ、変換してくっつけることは可能

```
str(2012) + "2013" #2012を文字列の型に変換
```

データの型を確認したいときは以下のコード

```
print(tipe(y))
```

### リスト
リスト・・・順番をつけてまとめたデータ型
国語（１）、算数（２）、、、

リストの作成方法は以下の通り

```
subject_name = ["フェデラー","メドベージェフ","ナダル","錦織"] #リスト型変数の宣言
print(subject_name)
print(type(subject_name))
```

リストの参照は以下で可能

```
print(subject_name[1]) #フェデラーを表示
print(subject_name[0:2]) #フェデラー、メドベージェフを表示
```

ここに選手を追加したい場合は

```
subject_name.append("マレー") #マレーを追加
```

ちなみに複数の選手を追加したい場合は

```
subject_name.extend(["ロディック","チチパス"] #2人の選手を追加
```

でも急に推しが出てくる時もある。。。
そんな時は

```
subject_name.insert(3,"ジョコビッチ") #3番目にジョコを追加
```

時には推しではなくなることも

```
subject_name.remove("ジョコビッチ")
```

ランキング上位も変動は激しい

```
subject_name[3] = "アガシ"
```

### 辞書
辞書：値（バリュー）に名前（キー）をつけてまとめたデータ型

辞書の作成 テニス好き度

```
tennis_dict = {"フェデラー":100,"メドベ":200,"ナダル":100}
```

追加したいとき！

```
tennis_dict["ロディック"] = 120
```

引退した選手の削除

```
tennis_dict.pop("ロディック")
```
Lua on RTX1210 (5) - DDNS(NoIP)更新

## 検証環境

```console
RTX1210 BootROM Ver. 1.04
RTX1210 FlashROM Table Ver. 1.00
RTX1210 Rev.14.01.38 (Fri Jul 10 09:41:02 2020)
```

## 経緯

非法人NURO回線では、YAMAHA謹製のネットボランチサービスを頼れない。
[No-IP](https://www.noip.com) は無料かつ[RESTで更新できる](https://www.noip.com/integrate/request) DDNSなので使ってみる。可用性がどの程度かは知らない。

## 前提

- [`strict.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/eef507defcc27f68fe40)
- [`slack.lua` 、 `json.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/8ba4257727387d8efe79)

## `update_ddns.lua`

```update_ddns.lua
--
-- update_ddns.lua
-- DDNS update via No-IP
--

require "strict"
local slack = require "slack"

local inet_url = os.getenv("INET_URL") or "http://inet-ip.info/ip"
local noip_url = os.getenv("NOIP_URL") or "http://dynupdate.no-ip.com/nic/update"
local noip_hostname = os.getenv("NOIP_HOSTNAME") or "example.ddns.net"
local noip_name = os.getenv("NOIP_NAME") or "example@example.com"
local noip_password = os.getenv("NOIP_PASSWORD") or "xxxxxxxx"

local function log(priority, message)
  if priority == "DEBUG" then
    rt.syslog("notice", message)
  else
    rt.syslog("info", message)
    slack.post(priority, message)
  end
end

local function get_remote_ip()
  local request_inet = {
    url = inet_url,
    method = "GET"
  }
  local response_inet = rt.httprequest(request_inet)
  if response_inet.rtn1 then
    local ip_address = response_inet.body
    log("DEBUG", "(update_ddns.lua) Global IP Address from inet-ip.info: " .. ip_address)
    return ip_address
  else
    log("ERROR", "(update_ddns.lua) Failed to fetch Global IP Address.")
  end
end

local function update_ddns(ip_address)
  local request_noip = {
    url = $[[${noip_url}?hostname=${noip_hostname}&myip={ip_address}]],
    method = "GET",
    auth_type = "basic",
    auth_name = noip_name,
    auth_pass = noip_password
  }
  local response_noip = rt.httprequest(request_noip)
  if response_noip.code == 200 then
    log("INFO", "(update_ddns.lua) Successfully updated: dynupdate.no-ip.com -> " .. response_noip.body)
  else
    log("ERROR", "(update_ddns.lua) Failed to update DDNS.")
  end
end

local current_ip = os.getenv("GLOBAL_IP")
local remote_ip = get_remote_ip()

if remote_ip then
  if current_ip then
    if current_ip ~= remote_ip then
      update_ddns(remote_ip)
    else
      log("DEBUG", "(update_ddns.lua) No need to update.")
    end
  else
    log("INFO", "(update_ddns.lua) GLOBAL_IP was not set.")
  end
  rt.command("set GLOBAL_IP=" .. remote_ip)
end
```

[No-IP](https://www.noip.com)の情報を下記のようにして環境変数に設定。

```console
set NOIP_URL="http://dynupdate.no-ip.com/nic/update"
set NOIP_HOSTNAME="example.ddns.net"
set NOIP_NAME="example@example.com"
set NOIP_PASSWORD="xxxxxxxx"
```

RESTでグローバルIPを取得できるサービスはいくつかあるが、[inet-ip.info](http://inet-ip.info) が一番安定しているように思う。

## スケジュール

NUROは滅多にIPアドレスが変わらないので毎時で十分。

```console
schedule at 3 */* *:00 * * lua /lua/update_ddns.lua
```

あとは拠点間なりリモートアクセスなり煮なり焼くなり。

## 所感

良い意味で[Luaの言語仕様](https://ja.wikipedia.org/wiki/Lua)が乏しいおかげで全くの未経験でもだいたいやりたいことができた。
勘所を掴んでるうちにWiresharkやVLCへ組み込んでみよう。
きっとgit使えないとbad②

#はじめに
昨日に引き続き、gitの基本的なコマンドを覚え書きのつもりで紹介します。

↓昨日の投稿
[きっとgit使えないとbad
](https://qiita.com/TerToEer_sho/items/8e5f9294c8d0cf936207)

##ローカルでブランチを切ってマージするまで

###ローカルブランチを作成

```bash
% git branch ブランチ名
```

###ローカルでブランチを切り替える

```bash
% git checkout ブランチ名 
```

###ローカルでブランチを作成し、切り替える（上２つを同時に行う感じ）
```bash
% git checkout -b ブランチ名 
```
間違えてマスターにコミットしないためには、こっちの方が使い勝手がいいかな…

###マスターに切り替える
```bash
% git checkout master
```

###全て(ローカル・リモート)のブランチを一覧表示
```bash
% git branch -a
```

###ローカルのブランチをリモートにプッシュ

```bash
% git push -u origin ローカルのブランチ名
```

###ブランチをマージする
```bash
% git merge ブランチ名
```
##その他使いそうなコマンド
###ブランチの削除

```bash
% git branch -d ブランチ名
```

###ブランチ名の変更
```bash

% git branch -m 古いブランチ名 新しいブランチ名
```

###変更点の表示
```bash
% git diff
```

##終わりに
`-d`みたいにオプションが多い印象です。何かの頭文字として覚えられればいいのだが…
udemy 英語速読・記憶講座のレビュー

プログラミングの学習の上でどうしても避けては通れないのが英語。
最新の文献や、分からないことを調べたい時に欲しい情報が英語でしかない、、、そんな経験ありませんか？

Udemyで英語学習における講座を受講したので、そのレビューを書きたいと思います！
「全世界で３万人が受講！ 英語速読・記憶講座」
https://www.udemy.com/course/superlearning-speed-reading-memory-techniques_jp/

こちらの講座の目的は英語の長文を早く読むこと、そしてその内容をしっかり頭に入れることです。

講座の初めの部分ではなぜ英語を学びたいか3-5個、紙になどに書き出すことを求めます。
目標を明確化することで英語学習へのモチベーションを高めるためです。

講座の動画で解説されるテクニックは
・ポイントの周辺を一つの塊として理解する
・読みながらポイント毎に単語を画像や映像のイメージと結びつけること
・それらのポイントとポイントを結びつける

これらは人の記憶しやすいメカニズムに沿って説明されています。
人は電話番号など10桁の数字を一気に覚えることは難しいですが、080-1234-5678
など、いくつかに分解して、それを繋げることで覚えやすくなるという性質があります。

他には、文字の羅列を見るよりも、1-2秒画像をみただけで情報を多く人は理解することが出来ます。
これは人は視覚からくる情報を記憶しやすいからです。
理想的には、視覚のみならず、その単語から匂いや感覚、昔の自分の個人的な記憶や経験と結びつけるとより鮮明に記憶へ印象付けるが出来ます。
これを応用して、読みながら節目毎に「bird」という単語が出てきたら。頭の中に鳥の画像を思い浮かべるなどして読み進めます。
最初は読みながら脳みその普段使ってない部分を同時に使うことで疲れてきますが、その分、より深く内容を理解できることを実感できるはずです！

講座の動画は2時間と短めで、テクニックを解説するだけです。
つまり、それらのテクニックは知ったからといってすぐに使えるようにはなりません。
そのために以下のリンクのスケジュールを参考にじっくり毎日練習して初めてその術を習得出来ます。
http://www.keytostudy.com/examplary-training-schedule/

また他には、TED動画の視聴も役に立つからということで紹介されています。
・脳の「作業記憶野」による認識とは？
https://www.youtube.com/watch?v=UWKvpFZJwcE

・誰でもできる記憶の偉業
https://www.ted.com/talks/joshua_foer_feats_of_memory_anyone_can_do#t-178

・早く言語を習得する方法
https://www.youtube.com/watch?v=HZqUeWshwMs

・記憶を身につける方法
https://www.youtube.com/watch?v=9ebJlcZMx3c
Lua on RTX1210 (4) - ハードウェア監視

## 検証環境

```console
RTX1210 BootROM Ver. 1.04
RTX1210 FlashROM Table Ver. 1.00
RTX1210 Rev.14.01.38 (Fri Jul 10 09:41:02 2020)
```

## 前提

- [`strict.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/eef507defcc27f68fe40)
- [`slack.lua` 、 `json.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/8ba4257727387d8efe79)

## 注意事項

このスクリプトだけは **Shift-JIS** で保存しなければならない。
`pattern = "筐体内温度%(℃%): (%d+)"` が拾えない、Slackへのペイロードが空になるなどの不具合が起きる。

## `monitor_hardware.lua`

```monitor_hardware.lua
--
-- monitor_hardware.lua (Shift-JIS)
-- Hardware monitoring
--

require "strict"
local slack = require "slack"

local idle_time = 43200 -- = 60 * 60 * 12 [s]

local function log(priority, message)
  if priority == "DEBUG" then
    rt.syslog("notice", message)
  else
    rt.syslog("info", message)
    slack.post(priority, message)
  end
end

local resource_table = {
  cpu_5sec = { index = 1, pattern = "(%d+)%%%(5sec%)", name = "CPU(5sec)", unit = "%" }, -- (1)
  cpu_1min = { index = 2, pattern = "(%d+)%%%(1min%)", name = "CPU(1min)", unit = "%" },
  cpu_5min = { index = 3, pattern = "(%d+)%%%(5min%)", name = "CPU(5min)", unit = "%" },
  memory = { index = 4, pattern = "(%d+)%% used", name = "Memory", unit = "%" },
  packet_small = { index = 5, pattern = "(%d+)%%%(small%)", name = "Packet Buffer(small)", unit = "%" },
  packet_middle = { index = 6, pattern = "(%d+)%%%(middle%)", name = "Packet Buffer(middle)", unit = "%" },
  packet_large = { index = 7, pattern = "(%d+)%%%(large%)", name = "Packet Buffer(large)", unit = "%" },
  packet_huge = { index = 8, pattern = "(%d+)%%%(huge%)", name = "Packet Buffer(huge)", unit = "%" },
  temp = { index = 9, pattern = "筐体内温度%(℃%): (%d+)", name = "Temperature", unit = "C" }
}

local function rt_res_status()
  local cmd = "show environment"
  local rtn, str = rt.command(cmd)
  local rtn_table = {}
  local rtn_message = ""
  if rtn and str then
    for k, v in pairs(resource_table) do
      local value = str:match(v.pattern)
      if value then
        rtn_table[v.index] = v.name .. ": " .. value .. v.unit
      end
    end
    for i, v in ipairs(rtn_table) do
      rtn_message = rtn_message .. " " .. v
    end
    return rtn, rtn_message
  end
end

while true do
  local rtn, rtn_message = rt_res_status()
  if rtn then
    print(rtn_message) -- for DEBUG
    log("info", "(monitor_hardware.lua) " .. rtn_message)
  else
    log("info", "(monitor_hardware.lua) Failed to get environment information.")
  end
	rt.sleep(idle_time)
end
```

(1): `pairs()` が順序保証しないことに気づくまでしばらくハマった。

## スケジュール

起動時に実行するよう設定。

```console
schedule at 2 startup * lua /lua/monitor_hardware.lua
```

## 最終回予告

No-IP DDNSを定時更新してみる。
Lua on RTX1210 (3) - ログイン監視

## 検証環境

```console
RTX1210 BootROM Ver. 1.04
RTX1210 FlashROM Table Ver. 1.00
RTX1210 Rev.14.01.38 (Fri Jul 10 09:41:02 2020)
```

## 経緯

Lua on RTX1210して遊ぼうと思ったのは[河野哲治氏のコラム](https://router-switch-jirei.jp/archives/2157)を読んだのがきっかけ。
Lua未経験だったので、自分の理解のために写経を始めるうちに、Slack投稿などを外部化してこんなシリーズ投稿が生まれた。

## 前提

- [`strict.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/eef507defcc27f68fe40)
- [`slack.lua` 、 `json.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/8ba4257727387d8efe79)

## `watch_login.lua`

```watch_login.lua
--
-- watch_login.lua
-- Login monitoring
--

require "strict"
local slack = require "slack"

ptn = "Log%l%l%l* "

local function log(priority, message)
  if priority == "DEBUG" then
    rt.syslog("notice", message)
  else
    rt.syslog("info", message)
    slack.post(priority, message)
  end
end

local function find_string(syslog_message)
  if string.find(syslog_message, "succeeded") ~= nil then
    return "INFO", "Login Succeeded."
  end
  if string.find(syslog_message, "failed") ~= nil then
    return "WARN", "Login Failed."
  end
  if string.find(syslog_message, "Logout") ~= nil then
    return "INFO", "Logout."
  end
  if string.find(syslog_message, "restricted") ~= nil then
    return "ERROR", "Login Restricted."
  end
end

while true do
  local rtn, str = rt.syslogwatch(ptn, 1)
  if rtn and str then
    rt.syslog("debug", "(watch_login.lua) Found log: " .. str[1])
    local priority, message = find_string(str[1])
    if message then
      log("INFO", "(watch_login.lua) " .. message)
    else
      log("INFO", "(watch_login.lua) Found: " .. str[1]) -- (1)
    end
  end
end
```

(1): どうも `"Log%l%l%l* "` ではログファイルのローテートなども拾ってしまうらしく、不意に `message` が `nil` になる。

## スケジュール

```console
schedule at 1 startup * lua /lua/watch_login.lua
```

こんな感じで、起動時に実行されるように設定。

## 次回予告

CPUの使用率や筐体内温度を監視してみる。
Lua on RTX1210 (2) - Slack投稿

## 検証環境

```console
RTX1210 BootROM Ver. 1.04
RTX1210 FlashROM Table Ver. 1.00
RTX1210 Rev.14.01.38 (Fri Jul 10 09:41:02 2020)
```

## 経緯

[`rt.syslog()`](http://www.rtpro.yamaha.co.jp/RT/docs/lua/rt_api.html#rt_syslog) には半角で最大231文字、全角で最大115文字の制限もあるし、そもそもsyslogを読みにいくのが面倒なので、Slackに投稿できるようにする。

## 前提

- [`strict.lua` の導入が終わっている](https://qiita.com/shin-sforzando/items/eef507defcc27f68fe40)

## `json.lua`

**Special thanks, rxi!**
[GitHub - rxi/json](https://github.com/rxi/json.lua) からPure Luaで書かれたJSONライブラリ(MITライセンス)を使わせていただく。

## `slack.lua`

```slack.lua
--
-- slack.lua
--

require "strict"
json = require("json")

local slack = {
  -- Slack Incoming Webhook URL
  url = os.getenv("SLACK_URL"),
  -- Slack Channel Name
  channel = os.getenv("SLACK_CHANNEL"),
  -- Slack User Name
  username = os.getenv("SLACK_USERNAME")
}

local function get_log_level_color(log_level)
  if log_level == "INFO" then
    return "#14dc3c"
  elseif log_level == "ERROR" then
    return "#dc143c"
  elseif log_level == "WARN" then
    return "#dcdc14"
  elseif log_level == "DEBUG" then
    return "#148cdc"
  else
    return "#e3e3e3"
  end
end

local function post(log_level, message)
  local log_level = string.upper(log_level)
  local color_rgb = get_log_level_color(log_level)
  local payload = {
    channel = slack.channel,
    username = slack.username,
    color = color_rgb,
    icon_emoji = ":globe_with_meridians:",
    attachments = {
      {
        color = color_rgb,
        text = $[[*${log_level}* ${message}]] -- (1)
      }
    }
  }
  local request_slack = {
    url = slack.url,
    method = "POST",
    content_type = "application/json;charset=UTF-8",
    post_text = json.encode(payload)
  }
  rt.syslog("notice", "(slack.lua) DEBUG: " .. request_slack.post_text) -- for DEBUG
  local response_slack = rt.httprequest(request_slack)
  if response_slack.code == 200 then
    rt.syslog("info", "(slack.lua) Successfully posted: " .. message)
  else
    rt.syslog("info", "(slack.lua) Failed to post: " .. message)
    if response_slack.body then
      rt.syslog("info", "(slack.lua) Posting Error: " .. response_slack.body)
    end
  end
end

return { post = post }
```

(1): こういった[式展開](http://www.rtpro.yamaha.co.jp/RT/docs/lua/tutorial/syntax.html)の書き方はRT_LUA専用らしく、それほど便利さも感じないので多用しないほうがいいかも。

Slack側でIncoming Webhookを有効化し、環境変数に設定する。

```console
set SLACK_URL="https://hooks.slack.com/services/xxxxxxxx/xxxxxxxx"
set SLACK_CHANNEL="#yyyyyyyy"
set SLACK_USERNAME="zzzzzzzz"
```

## 次回予告

`strict.lua` と `slack.lua` を使って、ログインの監視などをやっていく。
pramasについて

#目次
<b>①paramsとは何か</b>
<b>②値はどのように送られてくるのか？</b>
<b>③どのように取り出すのか</b>
<b>④まとめ</b>




###①paramsとは何か
送られてきた値を受け取るためのメソッドのこと

###②値はどのように送られてくるのか？
以下のコードはブラウザから入力されたデータを受け取るためのコードです。


```
  def create
    Peroson.create(human_params)
  end

  def human_params
    params.require(:human).permit(:text).merge(user_id:current_user.id)
  end
```

投稿作業を行った後、ターミナルを見てみると

```
 Parameters: {"authenticity_token"=>"MgJJR92h/eFO7aQ+4YMt4y2tY6kPAxD1KaiVccrRxcuK4342o8v7bNpMV0SQgmmIZW8WZA4ik/UwxLVLyT5NSA==", "human"=>{ "text"=>"おはよう"}, "commit"=>"SEND", "id"=>"14"}

```
といったものが表示されています。
Parametersにハッシュの形でいろいろ格納されてデータが送られてきます。

###③<b>どのように受け取るのか</b>
②の"human"=>{ "text"=>"おはよう"}, "commit"=>"SEND", "id"=>"14"}の「おはよう」を取り出すときは

```
human(params[:text])
```
というように記述するとParametersのハッシュから「おはよう」を取り出すことができる。

###④まとめ
クライアントサイドから送られてきた値はParametersというハッシュに格納されたデータが送られてくる。その送られてきたデータをハッシュから取り出してデータを受け取るメソッドがparamsです。
Githubでプッシュしたリモートブランチ名を変更する

リモートにプッシュしたブランチ名が後々イケてない事に気づいた、、、
恥ずかしい、、どうすれば、、、
そんな時の対策！！


## 手順の流れ
  1. ローカルのブランチ名を変更する
  1. リモートの変更前ブランチを削除
  1. 1で変更したローカルブランチをリモートにプッシュ

  ※この記事では変更前ブランチ名 > 変更後ブランチ名 に変更する

## 1. ローカルのブランチ名を変更する
```
$　git branch -m 変更前ブランチ名　変更後ブランチ名
```
※この時点ではローカルのみ変更されている
## 2. リモートの変更前ブランチを削除
```
  $ git push origin :変更前ブランチ名
```

## 3. 1で変更したローカルブランチをリモートにプッシュ

```
git push origin 変更後ブランチ名
```

これでローカルもリモートも恥ずかしい履歴がスッキリ！！
Lua on RTX1210 (1) - タイプミスを防ぐ

## 検証環境

```console
RTX1210 BootROM Ver. 1.04
RTX1210 FlashROM Table Ver. 1.00
RTX1210 Rev.14.01.38 (Fri Jul 10 09:41:02 2020)
```

## 経緯

[YAMAHA RTX1210](https://network.yamaha.com/products/routers/rtx1210/index)があったので、[Lua](http://www.rtpro.yamaha.co.jp/RT/docs/lua/)で遊んでみる。

## `strict.lua`

Lua初心者なのでYAMAHA公式サイトから[strict.lua](http://www.rtpro.yamaha.co.jp/RT/docs/lua/tutorial/strict_lua.html) をもらってくる。
これによって未初期化グローバル変数への誤った参照や代入を防ぐことができる。
以後、きちんとスコープを意識して `local` 変数を使わなければいけなくなる。

```strict.lua
--
-- strict.lua
-- checks uses of undeclared global variables
-- All global variables must be 'declared' through a regular assignment
-- (even assigning nil will do) in a main chunk before being used
-- anywhere or assigned to inside a function.
--

local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget

local mt = getmetatable(_G)
if mt == nil then
  mt = {}
  setmetatable(_G, mt)
end

mt.__declared = {}

local function what ()
  local d = getinfo(3, "S")
  return d and d.what or "C"
end

mt.__newindex = function (t, n, v)
  if not mt.__declared[n] then
    local w = what()
    if w ~= "main" and w ~= "C" then
      error("assign to undeclared variable '"..n.."'", 2)
    end
    mt.__declared[n] = true
  end
  rawset(t, n, v)
end

mt.__index = function (t, n)
  if not mt.__declared[n] and what() ~= "C" then
    error("variable '"..n.."' is not declared", 2)
  end
  return rawget(t, n)
end
```

USBなりSFTPなりで転送する。
ごちゃごちゃしないよう、 `/lua` 以下に保存することにした。
その場合、 `PWD` と `LUA_PATH` の指定は下記のようになる。

```console
set PWD="/lua"
set LUA_PATH="./\?.lua;"
console character ja.utf8
```

ついでにコンソールの文字コードも設定した。
`luac -p /lua/strict.lua` のようにして構文解析するとデバッグが捗る。

## 次回予告

syslogの限界を感じたので、Slackへのカジュアルな投稿を試してみる。
WordPressで投稿者アーカイブ、ユーザー情報APIを無効化する

TL;DR
-

パーマリンク設定及び``/wp-sitemap.xml``のサイトマップから投稿者アーカイブを除去
さらに``?author=``のURLパラメータ付与によるユーザー名による投稿の検索も無効化し
``/wp-json/wp/v2/users/``のリクエストも無効化します。

```php
add_filter('wp_sitemaps_users_pre_url_list',function(){return [];});
add_filter('wp_sitemaps_users_pre_max_num_pages',function(){return 0;});
add_filter('author_rewrite_rules',function(){return [];});
add_filter('query_vars',function($vars){return array_diff($vars,['author','author_name']);});
add_filter('rest_prepare_user',function(){return new WP_REST_Response(['message'=>'404 not found')],404);});
```
Unity公式のLocalizationを軽めに使う

# 概要

LocalizationというpackageがUnity公式で提供されています（preview）
まだ情報が少なかったため、とりあえず軽くプロジェクトに入れてみる方法をメモしておきます
導入などは[公式](https://docs.unity3d.com/Packages/com.unity.localization@0.9/manual/index.html)がわかりやすいです

# 環境

Unity2020.2.1f1
Localization 0.9.0-preview

# 軽く使ってみる

uGUIのTextをローカライズするだけだったらInspectorからLocalizeStringEventをアタッチして、表示する文字を選択するだけです
今回は動的に変更したい時にどうするかをメインに記載します
※StringだけでSpriteなどには触れません

```c#
var tableName = "TableName";// 作成したテーブル名を設定
var key = "FOO_KEY";// 取得したい文字のキー

var stringTable = await new LocalizedStringTable {TableReference = tableName}.GetTable().Task;
var stringResult = GetEntry(key).GetLocalizedString();
```

裏でアセットをロードしたりするためかawait必須になっています
StringTableはSerializeFieldでInspectorから指定できるため、awaitを回避できますが、毎回指定するのは面倒です

# 細かいところは無視して使う例

まずはコードだけ

```c#
public static class Localize
{
    private static StringTable StringTable;
    
    public static async UniTaskVoid LoadStringTableAsync()
    {
        StringTable = await new LocalizedStringTable {TableReference = "StringTable"}.GetTable().Task;
    }

    public static string GetLocalizedString(string key)
    {
        return StringTable.GetEntry(key).GetLocalizedString();
    }
}
```

使い方は下記です
とりあえず入れてみようという気になって知見が増えると嬉しいです

```c#
// アプリ起動時や言語選択時にロードしておく
// キャンセルなどはうまいことやる
await Localize.LoadStringTableAsync();

// 下記でよしなに取得できる
Localize.GetLocalizedString("BAR_KEY");
```
初学者からの統計学10冊（社会科学向き）

# はじめに

千葉大学・株式会社Nospareの[川久保](https://sites.google.com/site/ykawakubostat/)です．
今回は，初学者レベルから学部上級レベルの統計学関連の教科書を，順を追って紹介していきます．普段，経済学をはじめとする社会科学（経済学・経営学や政治学など）を学ぶ学生に教えているので，タイトルに「社会科学向き」と入れてみましたが，これから紹介する多くの本は，他の応用でも役に立つものが多いはずです．

# 入門書
### [大屋幸輔『コア・テキスト統計学』](https://www.amazon.co.jp/dp/4883843076/ref=cm_sw_em_r_mt_dp_RKQdGbB450EPD)
厳密さと初学者に対する分かりやすさのバランスのとれた本です．演習問題を集めた[副読本](https://www.amazon.co.jp/dp/4883841820/ref=cm_sw_em_r_mt_dp_UXQdGbF3GJJ2Y)もあるので，こちらと併せて学習すると効果的だと思います．

### [久保川達也・国友直人『統計学』](https://www.amazon.co.jp/dp/4130629212/ref=cm_sw_em_r_mt_dp_VPQdGbG1C8531)
入門書としては，やや硬派な教科書ですが，しっかり学びたい人にはお勧めの教科書です．「1.記述統計」「2.確率」「3.推測統計」と標準的な構成をしている中，最後の第4部では社会・経済データとして標本調査や時系列分析の話題にも触れているのも本書の特徴です．


# 数理統計学

### [久保川達也『現代数理統計学の基礎』](https://www.amazon.co.jp/dp/4320111664/ref=cm_sw_em_r_mt_dp_WPQdGbV28H603)
分布論，統計的推測決定理論，線形モデルといったトピックを，数学的に学んでいきます．統計学の応用に関心がある場合，数理統計学を必ず学習しなければいけないわけではありませんが，数理統計の理解を深めると読める本の幅が広がります．数学的には，学部教養レベルの微分・積分と線形代数の知識があれば十分です．逆に文系の学生（昔の私です）からすると「数理統計を学びながら，重積分や行列演算のテクニックを磨いていく」ぐらいの気持ちで勉強するといいと思います．最後の2章では，計算統計や確率過程といった現代的な話題にも触れています．

### [竹村彰通『現代数理統計学』](https://www.amazon.co.jp/dp/4780608600/ref=cm_sw_em_r_mt_dp_ZPQdGb95J5BBF)
硬派な教科書ですが，丁寧に学習したい人向けの教科書です．昨年，新装改訂版が出版されました．

# R入門

### [今井耕介『社会科学のためのデータ分析入門』（上](https://www.amazon.co.jp/dp/400061245X/ref=cm_sw_em_r_mt_dp_OSQdGbCAX7YZR?_encoding=UTF8&psc=1)・[下巻）](https://www.amazon.co.jp/dp/4000612468/ref=cm_sw_em_r_mt_dp_LTQdGbZP87GMW)
今井先生著"[Quantitative Social Sciences (QSS)](https://www.amazon.co.jp/dp/B01M34JHIM/ref=cm_sw_em_r_mt_dp_Le4dGbXP3H78M)"の訳本です．
Rの入門書としても最適ですが，社会科学のデータ解析例が豊富で，計量社会科学・計量政治学に関心がある人にとっても面白い内容です．

# 計量経済学

### [浅野皙・中村二朗『計量経済学』](https://www.amazon.co.jp/dp/4641163367/ref=cm_sw_em_r_mt_dp_hUQdGb2GVCNQ8)
経済学をデータ分析により実証していくための方法論が計量経済学で，基本的には使う統計学のツールは回帰分析です．多くの計量経済学の入門書が行列表記を避けている一方，行列を用いながらも平易に解説している数少ない本です．

### [西山慶彦・新谷元嗣・川口大司・奥井亮『計量経済学』](https://www.amazon.co.jp/dp/4641053855/ref=cm_sw_em_r_mt_dp_0UQdGb4JXQ9QR)
「1.基礎編」（回帰モデルの基礎），「2.ミクロ編」（操作変数法やパネルデータ分析など），「3.マクロ編」（主に時系列解析）と分かれていて，計量経済学の広範なトピックが1冊にまとまっています．実証例も豊富です．


# その他の話題

### [小西貞則・越智義道・大森裕浩『計算統計学の方法』](https://www.amazon.co.jp/dp/4254127855/ref=cm_sw_em_r_mt_dp_vVQdGb5GS81XZ)
ブートストラップ，EMアルゴリズム，MCMC（マルコフ連鎖モンテカルロ）法という3つの計算統計の代表的な手法についてまとめられた本です．

### [小西貞則『多変量解析入門』](https://www.amazon.co.jp/dp/4000056530/ref=cm_sw_em_r_mt_dp_kWQdGb9S9ST9W)
計量経済学では主に回帰分析が用いられますが，回帰分析以外にも様々な多変量解析の手法があります．非線形回帰，判別分析，主成分分析といった様々な多変量解析の方法論がまとまった本です．

### [土屋隆裕『概説 標本調査法』](https://www.amazon.co.jp/dp/425412791X/ref=cm_sw_em_r_mt_dp_UWQdGb429V7SA)
多くのデータ解析ではランダムサンプルを暗に仮定していますが，実際の標本調査の現場では層化抽出法をはじめとする複雑なサンプリングが行われています．これは母集団における様々な集団をくまなく調査するために，あえてバイアスをかけてサンプリングを行っていると見ることができます．そのようなサンプリングの手法や，そのデザインの下でとられたデータに対する解析法などをこの本で学習できます．


# 終わりに
株式会社Nospareには，統計学の様々な分野を専門とする研究者が所属しております．統計アドバイザリーやビジネスデータの分析につきましては[株式会社Nospare](https://bit.ly/38WtGZH) までお問い合わせください．
<a href="https://bit.ly/38WtGZH">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1023506/d5c625c0-d6f4-680b-d702-3c40f11d6c39.jpeg" alt="株式会社Nospare" width=400>
</a>
ProgateでHTML,CSSを学んでみた（4日目）

#概要
Web開発に興味が出てきたのでとりあえず一通り必要そうなものを触ってみることにしました。
ただ触るだけだと忘れてしまいそうなのでメモとして学んだことを書いてみます。
ここにあるコードはほぼ全てProgateで出てきたものです。

##フッターの構造
フッターの左側にロゴ、右側にリストがある。
<a ref="https://qiita.com/kfuku1634_dev/items/731e98be8ff6bedc04a7">ProgateでHTML,CSSを学んでみた（3日目）</a>で\<li>にCSSで要素を追加した。
なので、このままではフッターにも上記と同じCSSが適用されてしまう。
これを回避するには以下のように書く。

```hoge.css
    .header-list li{
        float: left;
        padding: 33px 20px;
    }

```

##mainの構造

###文中の一部にCSSを適用させる
一部にCSSを適用させるには以下のようにspan要素で囲む

```hoge.html
    <h1>
        ようこそ<span>Progate</span>へ
    <\h1>
```

```hoge.css
    span{
        color:#ff0000;
    }
```

###ブロック要素、インライン要素について
HTMLには改行される要素と改行されない要素がある。
改行が入って、幅いっぱいに広がる要素をブロック要素という。
改行されない要素をインライン要素という。

###枠線をつける
枠線をつけるには以下のようにborder要素を追加する。
border: [太さ]　[種類]　[色];
```hoge.css
    .hoge1{
        border:5px solid red;
    }
```
下にのみ線をつけたい場合はborder-bottmoのように書く。
つけたい方向によってboder-top、border-right、border-leftが使える。

```hoge.css
    .hoge2{
        border-bottom: 1px solid #333;
    }
```

###paddingとmargin
paddingはborderの内側に空白を作る。
marginはborderの外側に空白を作る。
marginもboderの書き方と同様。
2021年データ分析に関するビジネストレンド--人工知能

##概要
　ビッグデータは情報通信技術の発展によって蓄積されてきたもので、自身の技術発展ロジックに従い、生産効率を向上させることからより高度な知能段階に成長して行きます。ありふれた収集端末は大量のデータを収集して、計算技術は絶えず進歩するにつれて、人々に強力なデータ分析能力を提供してくれました。本文では、データ分析における人工知能のビジネストレンドに対する影響を予測した。
##人工知能

　人工知能と機械学習はデータ分析とデータ管理を革新しています。同時に私達も使う時に安全性を高める措置を考えなければなりません。

　企業はすでに発生したことを報告するから能動的な状況分析に変化しています。ダッシュボードにおける、毎秒の状況を確認し、異常が発生した時に警報を出してくれます。

　最先端の神経ネットワークに基づくAIアルゴリズムのような解決策は、歴史的な傾向やモードから予測して、高精度な異常検出を提供します。このように、任意の予期せぬ事象が直ちに監視され、システムはユーザに通知します。
![network-698598_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/94287c81-0f4c-48e4-d114-ae98fb761665.jpeg)
AIがデータ分析で提供するもう一つの機能は高級な洞察機能です。基本的にはデータセットを自動的に全面的に分析することができます。分析するデータソースとアルゴリズムが注目すべき列/変数を選択するだけで、特に複雑な操作が必要がありません。そして、AIで増加、トレンド、予測、異常、仮設分析などの分析結果を得ます。
![ダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/e450b327-8633-fb5d-dd82-27e18471fe38.png)
　これにより、強力なIT知識がなくても、データ科学者はツールを通じて、業務ユーザーに高品質な見解と情報のより良い理解を提供でき、より多くの作業時間を節約することができます。

　時間の利得もAIヘルパーとして現れます。ツールはすでに人工知能機能を開発しました。これらの機能により、ユーザーは簡単なキーワードで問題を提出して、そしてAIは可能な最善の答えを生成します。

　ビジネス知能のもう一つの成長要因は、AIとの対決テストです。これは、CAPTCHA技術などのオンライン検証プロセスを代表として、対抗ネットワーク（GAN）と呼ばれる技術です。Battleが何度も発生すると、人工知能がよりスマートになります。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/a4fdc878-ae66-d537-d3ca-e690c7732a79.png)

　人々は様々な方法でAI技術を使っています。これで機械学習にどのような変化をもたらすのか、これが2021年、我々が注目すべきことでしょう。

元記事：https://jp.scrapestorm.com/tutorial/2021-data-analysis-business-trends-artificial-intelligence/
クロージャはlogを計算する関数を作ることで理解できる

```python:対数計算をする関数
>>> import math
>>> def log(底):                     # エンクロージャ。関数「log底」を返す関数
...     def log底(真数):              # クロージャ。返される関数
...         return math.log(真数, 底) # エンクロージャ内の変数「底」を、クロージャ内で利用する。
...     return log底
...
>>> log(2)(8)
3.0
```

# `log(2)(8) == 3` の解説
## 1. `log(2)`の呼び出し
まず`log(2)`が評価された時点で、エンクロージャ`log(底)`が呼び出される。
### 1-1. `def log底(真数): return math.log(真数, 2)`が実行される
エンクロージャ内で、クロージャの定義が実行される。この時、クロージャ内の変数はエンクロージャ内と共通であるため、
`底==2`が成立する。

### 1-2. `return log底`が実行される
エンクロージャ呼び出し`log(2)`の評価値は、`math.log(真数, 2)`を返却する関数そのものである

## 2. `log(2)(8)`の呼び出し
1-2節より、`log(2)`は「`math.log(真数, 2)`を返却する関数」として評価されるのだった。
故に、`log(2)`は`(lambda 真数: math.log(真数, 2))`と同じようなことをを意味するのだ。
`log(2)(8)` つまり `(lambda 真数: math.log(真数, 2))(8)`が呼び出されることで、`真数=8`が代入され、
`math.log(8, 2)`が実行されるのである。


# 演習. `x`を受け取り、`x`が`min`未満なら`min`、`max`超なら`max`、どちらでもないなら`x`を返却する関数`rerange(max,min)(x)`を作れ

## 1. `def rerange(max,min):`
まずは外側の関数(エンクロージャ)を定義します。

### 1-1. `def rerange_max_min(x):`
関数`rerange`内に別の関数`rerange_max_min`を作ります。`rerange_max_min`が関数内関数、より具体的に言うとクロージャです。
#### 1-1-1. `y = max if x>max else (min if x<min else x)`
今、`rerange_max_min`内部にいます。①
`rerange_max_min`は`rerange`内部にあります。②
①②より、今`rerange`内部にいます。
よって、引数`max`と`min`が有効です。
#### 1-1-2. `return y`
`rerange_max_min`の戻り値を宣言しました。
この瞬間、`rerange_max_min`は
`x`を引数として受け取り、`max if x>max else (min if x<min else x)`を返却する関数
となりました。

返却値`max if x>max else (min if x<min else x)`をよく見てみましょう。
変数は、`max`, `x`, `min`の3種類があります。
このうち、引数は`x`だけです。それ以外の2種類は、「引数ではない『謎』の変数」です。

『謎』解きは1-2節で行います

### 1-2. `return rerange_max_min`
`rerange`の戻り値を宣言しました。
この瞬間、`rerange`は
`min`,`max`を引数として受け取り、
(
　　`x`を引数として受け取り、`max if x>max else (min if x<min else x)`を返却する関数
)
を返す関数となりました。
1-1節で「『謎』の変数」といった`min`, `max`は、`rerange_max_min`より外側の関数`rerange`によって決まります。
故に、`rerange_max_min`だけに注目している限り「謎」の変数です。もっと視野を広げ、`rerange`全体まで見渡した今、謎が解けました。


```python
>>> def rerange(max, min=0):
...     def rerange_max_min(x):
...         y = max if x>max else (min if x<min else x)
...         return y
...     return rerange_max_min
...
>>> [rerange(4,2)(成分) for 成分 in range(6)]
[2, 2, 2, 3, 4, 4]
>>> [rerange(4)(成分) for 成分 in range(6)]
[0, 1, 2, 3, 4, 4]
>>>               
```
ElectronのcontextBridge.exposeInMainWorldの挙動

![](https://github.com/taktamur/scratch-electron/raw/main/ipc-js/20210124.png)

# 文章書くのがめんどくさいので箇条書き
- electronのipc通信を調べると、「セキュアな」という記事があった。
    - 古いやり方では、レンダープロセスからelectronの全機能にアクセスできて、セキュアではなかったらしい
    - contextBridge.exposeInMainWorldを使う事で、レンダープロセスからアクセスする範囲を限定する事で安全にしているらしい。
- contextBridge.exposeInMainWorldを使うことで、windowオブジェクトに関数を貼り付けて、レンダープロセスからはこのwindowオブジェクトに貼り付けた関数を使うのがセオリーらしい。


# 参考にした記事
- https://qiita.com/hibara/items/c59fb6924610fc22a9db
- https://zenn.dev/erukiti/articles/electron-ipc