OmniAICreator/Qiita-1.07M huggingface dataset:
レガシーで押しにくいラジオボタンを押しやすくするスクリプト

# はじめに
会社で答えなきゃいけないアンケートがあったんですが、アンケートシステムがレガシーだったんですね。質問に回答するのにマウスの正確な操作を求められて、いらいらMaxでした。

ということで、レガシーなシステムのラジオボタンを勝手に改善します。


# 困っていること
ラジオボタンにラベル属性が付いてなく、ラジオの○の部分だけが押せる状態だった。4択アンケートに50問くらい回答しないといけないのに、ミリ単位でマウスを絶妙に合わせる作業をする必要があった。


# 改善してみる
JavaScriptを書いてこの状況を改善します。
たった10行でラジオボタンを押しやすくなりました。

:warning:私の困っていたサイトでは、ラジオボタンの上位タグがtdだったためtdにイベントを差し込みました。元のHTMLの構造に左右されるのでHTMLの構造をハックしたうえで適切にスクリプトを書き換えてお使いください。

レガシーなHTMLのサンプルがないと試せないので、あえて作ってここに置いときました。ご自由にお使いください。

https://kanaxx.github.io/bookmarklet/radio/index.html

## コード
コードはたった10行です。
Chrome DevToolのコンソールにスクリプトを貼り付けるだけで動きます。準備や予備知識は必要ないですね。

頑張ればもっと短く書けると思います。マウスオーバーで色を付ける必要もなければ2行短くなります。

```javascript:radio.js
for( const r of document.querySelectorAll('input[type="radio"]') ){
  //ここはparentでいいのかはHTMLの構造による。parentNode.parentNodeのほうがいいこともある。
  const td = r.parentNode;
  
  td.addEventListener('click', function(){ r.click(); });
  td.addEventListener('mouseover',function(){td.style.backgroundColor='#5F6F94'});
  td.addEventListener('mouseleave',function(){td.style.backgroundColor='#FFFFFF'});
}   

```

やってることは、これだけです。

1. ドキュメント全体から、`<input type="radio">`を探し
1. radioの一つ上の親要素の`onclick`にイベントに、radioのクリックを設定する
1. `mouseover`イベントと`mouseleave`イベントに色を設定する




## システム提供側が考慮するのが前提
昔のサービスやシステムだとラジオボタンやチェックボックスのユーザ側の操作性を考慮していない場合が多いです。作るときにちゃんと考慮してくれれば、こんなスクリプトの出番はありません。

```html:押しやすいラジオの書き方
<!-- IDとラベルとforを付けるんだ -->
<input type="radio" name="radio1" value="1" id="radio1"><label for="radio1">はい</label>
<input type="radio" name="radio1" value="2" id="radio2"><label for="radio2">いいえ</label>
<input type="radio" name="radio1" value="3" id="radio3"><label for="radio3">どちらでもない</label>
```

こっちのほうがシンプルですね。thanks @rl5j3 
```html:押しやすいラジオの書き方（その２）
<!-- ラベルで囲むんだ -->
<label><input type="radio" name="radio1" value="1">はい</label>
<label><input type="radio" name="radio1" value="2">いいえ</label>
<label><input type="radio" name="radio1" value="3">どちらでもない</label>
```


ラジオとチェックボックスを〇と□をマウスで直撃させるのはやめましょう。
【Webプライバシー】HTMLの中心で愛を叫んでも、漏れない

# 概要
- **Shadow DOM**で、一応見えなくなるよ
- **別オリジンのページをiframe**内にロードすると、一応見えなくなるよ
- 弱点の対策と、レイアウト調整が面倒だよ


# 背景
ユーザ（Webブラウズしている人）には見せたいが、他には漏らしたくない情報があるとします。この情報を見せようと、素直に**DOMに追加すると、同じページの他のスクリプトに丸見え**で、漏れてしまいます。

### 自作Webサイトの場合
この場合、情報を漏らさないスクリプトのみを選べるため、理論上は機密が保たれます。

フィクションで「理論上」はだいたいフラグですが、現実でも様々な地雷が埋まっており、理論通りにするのは言うほど簡単ではありません。

- [安全なウェブサイトの作り方](https://www.ipa.go.jp/security/vuln/websecurity.html)
- [Web Security Cheat Sheet](https://infosec.mozilla.org/guidelines/web_security.html)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)

スクリプトを選べない例外として、クロム拡張などのブラウザ拡張機能があります。変な拡張機能を使って漏れたら自己責任という見方もありますが、そう単純ではありません。

SNSサービスの場合、漏れる情報はユーザ個人だけでなく、共有する他ユーザの情報も混ざっています。**あるユーザのミスで、何の落ち度もない知り合いのユーザの情報が漏れる**様では、安心してサービスを利用できません。

このため、SNSサービスの場合は機密を守る対策が必要になります。もちろん、SNSサービス以外も機密を守る対策をする方が良いです。

### クロム拡張の場合
クロム拡張の場合、事態はより複雑です。ページ本体に寄生する形になるため、他のスクリプトを選べません。

特に、私のクロム拡張の様に任意のWebページで動かす場合、悪意を持ったスクリプトも混ざってくる事を覚悟しなければなりません。

https://worth-hole.com/posts/summary/


# 機密を守る道具とその弱点
## Shadow DOM
### Shadow DOMとは？
一言で言うと、DOMの一部を秘密にする機能です。

https://developer.mozilla.org/ja/docs/Web/Web_Components/Using_shadow_DOM

2つのモードがあり、それぞれ機密性が異なります。

| mode | 概要 | 特徴 |
| --- | --- | --- |
| open | かくれんぼレベル | getElement～では見つからないが、親要素.shadowRoot で見つかる |
| closed | スパイレベル | 親要素.shadowRootでもnullが返る |


### Shadow DOMで残るリスク
Shadow DOM(closed)さえ使えば、誰でも簡単にスネークできると思ったら、大間違いです。このままでは~~段ボールは~~穴だらけです。

#### JavaScript言語によるリスク
JavaScriptはプロトタイプの操作により、同種のオブジェクト全てを好きに改造できるので、悪用すると…

```
const originalFunc = Element.prototype.attachShadow;
Element.prototype.attachShadow = () => {
    return originalFunc( { mode: "open" } );
};
```

前もって、この仕込みを他のスクリプトが行っていると、[closedのつもりがopenのまま](https://blog.revillweb.com/open-vs-closed-shadow-dom-9f3d7427d1af)という事になります。

幸いなことに、クロム拡張のJavaScript環境は、同一ページの他のスクリプトから隔離されており、変数やプロトタイプは全て別扱いです。このため、**クロム拡張でattachShadowする限り、このリスクは管理可能**です。

#### うっかりや好奇心のリスク
クロム拡張なら安心してShadow DOMで機密を扱えると思ったら、大甘です。

DOM自体から漏れなくても、スクリプト本体が、エラーメッセージなどでうっかり漏らすリスクがあります。

好奇心の強いユーザが開発者ツールで、スクリプトが持っている機密をDOMなどに書き出してしまうかもしれません。

つまり、**他にどんなスクリプトが動いているか分からないページ（≒[コンテンツスクリプト](https://qiita.com/sakaimo/items/416f36db1aa982d8d00c#content-scripts)）で機密を扱うこと自体がリスク**です。


## iframeに別オリジンのページ
### オリジンとは？
Web上での、情報を遮断する壁の様なものです。
- 同一オリジン内だと、自由に情報交換可能
- 別オリジンとは、明示的な許可が無いと情報交換不可

https://qiita.com/tkek321/items/bd36b1541d22c8645eb9

クロム拡張だと、コンテンツスクリプトは閲覧中のページのオリジンで、それ以外のスクリプトはクロム拡張独自のオリジンで動作します。つまり、機密情報を持つ**クロム拡張独自のページを作ってコンテンツスクリプトでiframe内にロード**すれば、コンテンツスクリプトは直接機密情報を持たずに済みます。

### iframeに別オリジンのページで残るリスク
自分のスクリプトがiframe内にロードできるという事は、同じページの他のスクリプトからもロード可能という事になります。対策をしないと、クリックジャッキングの餌食です。

https://qiita.com/gotchane/items/4d31b01381f47100de7f

対策には色々ありますが、ロード時のパラメタなどで、**正規の呼び出しかをチェック**するのが、一番シンプルでしょう。

### iframeに別オリジンページだとレイアウト調整が面倒
同一DOM内だと、CSSを用いてレイアウトやサイズの調整が容易です。しかし、別オリジンページのiframeだと、情報が遮断されるため、これらの調整を自分でやる必要があります。

ちょっとした調整なら、iframe-resizerを使うのも手です。

https://github.com/davidjbradshaw/iframe-resizer

私のクロム拡張の場合、状況に応じて双方向にサイズ情報をやり取りする必要があったので、iframe-resizerでは機能不足でした。独自に[chrome.runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime/#method-connect)でサイズ情報のやり取り用チャンネルを作ることで対応しました。
numpy配列からｎ番目に小さい値まで取得

結構よく出会うシチュエーションですがいつもどうするか迷うのでメモします．timeitで時間を測りましたが参考程度です．

## 環境
Ubuntu 20.04 on win
python 3.10.4
numpy 1.21.6

## 準備
適当な配列を用意する．
```py
np.random.seed(0)
a = np.random.randn(1000, 100, 100)
```

## sort + partition
コメントで教えてもらった方法．partitionは小さい方からn番目のもので仕切る．無駄が少ない．

```py
n = 1000
a_minima = np.sort(np.partition(a.ravel(), n)[:n]); a_minima
```
timeit出力
```py
159 ms ± 18 ms per loop (mean ± std. dev. of 3 runs, 4 loops each)
```

## argsort

インデックスが必要な場合．丸ごとソートするので無駄が多いのと，配列が大きいと終わらない．  

```py
n = 1000
idx = np.unravel_index( np.argsort(a=a, axis=None), a.shape)
a_minima = a[idx][:n]
```
timeit出力

```
3.47 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
```

## forループ＋argmin

原始的な方法．ｎが小さくないと使えない．  

```py
n = 1000
a_minima = []
for _ in range(n):
    idx = np.unravel_index( np.argmin(a=a, axis=None), a.shape )
    a_minima.append( a[idx] )
    a[idx] = np.Inf
```
timeit出力

```
10.1 s ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
```

## argwhere＋argsort

現実には配列の取りうる値の範囲に見当がつくことも多いので，適当なｘについてそれより小さい要素のみ抜き出し，配列サイズを小さくしてから上記の処理を行う．argwhereのアウトプットをそのままインデックスとして使えないのが歯がゆい．  

```py
threshold = ( np.max(a) - np.min(a) ) / 5 + np.min(a) # 小さい方から２０％
idx = np.transpose( np.argwhere(a < threshold) )
a_minima = a[idx[0], idx[1], idx[2]]
a_minima_sorted = a_minima[ np.argsort(a_minima) ]
```
timeit出力
```
6.8 ms ± 13.5 ms per loop (mean ± std. dev. of 3 runs, 3 loops each)
```

※追記訂正：argwhereではなくnonzeroを使って同じことができ，かつ返り値をそのままインデックス配列として使える．インデックスが不要ならargsortではなくsortで．
```py
idx = np.nonzero(a < threshold)
idx_to_sort = np.argsort(a[idx])
a_minima = a[idx_to_sort]
```
## 最小値とそのインデックスだけ知りたい

最小値だけでよいなら以下のように．
```py
idx = np.unravel_index( np.argmin(a), a.shape)
a_min = a[idx]
```
ruby「インスタンスメソッドとクラスメソッドの使いわけ」と「アクセサメソッドの使い分け」

# どうもaono1234と申します。記事がいいなと思ったらtwitterのフォローもお待ちしております‼
https://twitter.com/takeshi_program
___
# はじめに
著者自身も初学者なので本内容を鵜呑みにせず参考程度に読んで頂けるとありがたいです。😉
___
![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/92d8ce09-2868-c8fa-5a6e-678cd3244749.png)
___
![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/f21fff5a-980a-fd75-314f-f87a910d3ba3.png)
クラスとはインスタンスの設計書にあたるものです。
___
![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/851818ff-47d0-5dd9-7b11-2ad63cde7444.png)
インスタンス(オブジェクト)は設計書をもとに作ったものです。
そのため、クラスが車の設計書であればインスタンスが車にあたります。
___
![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/a6e44923-ca70-21c8-66bb-7783faf629f3.png)
インスタンスにさせたい作業のことをインスタンスメソッドといいます。
インスタンスが車ならば、「走る」、「ワイパーを動かす」「給油する」など車が持つ機能や作業がインスタンスメソッドにあたります。
___
![スライド6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/7041d1bb-7564-1503-944b-a3b8471f0e8b.png)
クラスメソッドは
「大きなくくりでは車に関わるメソッドだが、
車というインスタンスに持たせるには、違和感があるものがクラスメソッド」という風に捉えています。
___
例えば「今年度の車の生産数を出す」、「車1台あたりの生産時間を出す」、「クレームがあった車の工場を特定する」というメソッド達は大きなくくりでは車に関わるメソッドです。
しかし、車インスタンスに持たせてしまうと違和感がありませんか？そういった場合はクラスメソッドとします。
___
# まとめ
![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/7fb677aa-0463-6569-3bc1-b50a710db621.png)
___
![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/df4962c2-cb95-9ed6-3009-5751234cca3c.png)
アクセサメソッドにはゲッター・セッターの2種類が存在し、アクセサメソッドを使ってインスタンスのプロパティ取得/変更ができます。
rubyには3種類のメソッドが用意されており、それぞれどういう時に使うか一例を示してます。
___
![スライド13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534058/b827093c-3a18-3694-892f-924ae52df123.png)
LPC812の素にLチカを書き込む(どうやったか、おぼえていない)


x mbed2リビジョン144
x リビジョンを変更できる人むけ


目的
秋月で売っている素のLPC812に書き込んで遊ぶ


1.組む
2.P0_12は、グランド
3.BINをHEXに変換
4.書き込む
5.はずす
6.P0_12を開放
7.つなげる
8.おわり



```c++


#include "mbed.h"

//DigitalOut myled(LED1);
//DigitalOut myled(D13);
DigitalOut myled(P0_7);

int main() {
    while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }
}



```


![o_con743.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/950bcf13-258d-1021-fe67-a9ebd1b856f4.jpeg)


![o_con744.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/aca724eb-f6d5-7862-ea64-fc3d82bfa09e.jpeg)


![LPC812.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f51883cd-4c80-7586-40d5-899c94271790.jpeg)


![o_con745.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/52719c8f-f0ed-7ab2-e937-1d96c912d3d6.jpeg)


![o_con746.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/12586b34-ac21-9127-06d1-ab1410b12ace.jpeg)


![o_cop117.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/50bc929c-34ff-ca35-31df-a64bf64665ff.jpeg)



![o_con833.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/edda47e5-87f1-2367-99c6-50e9b87479df.jpeg)







-23-
Macの拡張ディスプレイとしてiPadを使う

Sidecar機能を使って、iPadを追加ディスプレイとして利用します。
ワイヤレスで接続できるため、iPadを手元に置いておくだけで、簡単に利用することが出来ます。

### 準備
- 同じAppleIDで、MacとiPadの両方にサインインする
- Macの近くにiPadを設置する
- WiFi、BluetoothをONにする

### ワイヤレスで接続
Macの「システム環境設定」から、「ディスプレイ」を開きます。
「ディスプレイを追加」の項目から、対象にするiPadを選択します。

しばらくすると、iPadが追加ディスプレイとして認識されて、利用可能となります。

普通のディスプレイに繋いだ時と同様に「ディスプレイ設定」から、ミラーリングや拡張ディスプレイが選択可能となります。

### 有線接続
MacとiPadをケーブルで接続します。
有線接続の場合は、WiFi、BluetoothがOFFでも利用可能です。

iPad側で「このコンピューターを信頼しますか？」と表示された場合は「信頼」を選択します。

ワイヤレス接続と同様に、Macの「システム環境設定」から、「ディスプレイ」を開きます。
「ディスプレイを追加」の項目から、対象にするiPadを選択します。

しばらくすると、iPadが追加ディスプレイとして認識されて、利用可能となります。

### 最後に
Sidecarがサポートされていない端末では、残念ながら利用出来ません。
Apple公式にシステム条件が詳しく記載されていますので、ご確認ください。

[Sidecar のシステム条件](https://support.apple.com/ja-jp/HT210380#systemrequirements)


##### 記事投稿時のOSバージョン
- Mac: macOS Monterey 12.5.1
- iPad: iPadOS 15.6.1
numpyでargsortの逆操作を行う配列を (sort1回のみで) 簡潔に得る

表題のとおりです．

以下のように行うとsortは一回で済み，for文を使う必要もないです．

```python
import numpy as np

# 配列を定義
size = 1 << 20
x = np.random.random(size)

# sortを行う
order = np.argsort(x)

# 逆操作を得る (以下2行)
order_inv = np.zeros_like(order)
order_inv[order] = np.arange(size)

# 検証
np.allclose(x, x[order][order_inv])
>>> True
```
Flowでリストビューから選択されている複数のidを取得する

元の質問 : [リストビューに複数レコードをフローに渡したい](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000JdLwY)


 One caveat to Matt's suggestion:  **your list button must be configured to "Display in existing window without sidebar or header" for this to work.**   This is exactly how the setup is shown in the screenshot on the page above, but pointing it out here to avoid others wasted time from overlooking that part of the button setting. 

[How can I pass selected records from a listview into a flow?](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000A8UjOSAV)

私の設定では「 現在のウィンドウにサイドバーなしで表示 」を指定していて機能しませんでした。

上記に書いていある「現在のウィンドウにサイドバーおよびヘッダーなしで表示」ではなんと機能します。

いやぁ、こんなにユーザに優しいフローは涙が出ます。おそらく今後は使うことを避けたくなります。どこにこんなことが書いてあるんだろう？。フローが嫌いな私に対する嫌がらせとしか思えません。

Salesforceを使えば使うほどフローと英語はどんどん嫌いになっていきます。

この設定をしなくても問題ない場合もあるみたいですが、何が違うか分かりませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6088da80-03a8-2fee-0507-8667745765aa.png)

ただ、以下のようにも投稿されているのがちょっと不思議です。私もVisualforceを使って選択されているIdを取得していますが、別にこの設定にしなくても大丈夫なんですがね。

>本番ではご教授頂いた内容での実装を予定しておりますが、Visualforceを使用したパターンでの実装方法でも同様の動作が確認できましたので、その際参考にしたリンクを添付いたします。

https://creativecontentlabtokyo.com/tips-how-to-execute-the-flow-with-listview-selected-items-as-a-parameter/

しかし私の環境ではこの設定をしなくても機能しているんですよねぇ。何が違うかさっぱり分かりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9e0a78c4-ba89-45c7-8c9b-8772d407328b.png)
「エンジニアリングマネージャーのしごと」を読んで、マネージャーの楽しさを学ぶ

[Best Qiita賞という社内賞](https://qiita.com/cold-wisteria/items/be3ec7f417a199a619cd) を頂いたので、書籍を購入しましたという読書感想文です。


[O'Reilly Japan - エンジニアリングマネージャーのしごと](https://www.oreilly.co.jp/books/9784873119946/)
[エンジニアリングマネージャーのしごと ―チームが必要とするマネージャーになる方法 | James Stanier, 吉羽 龍太郎, 永瀬 美穂, 原田 騎郎, 竹葉 美沙 |本 | 通販 | Amazon](https://www.amazon.co.jp/dp/4873119944)

![](https://images-fe.ssl-images-amazon.com/images/I/51mllWSxrpL._SX218_BO1,204,203,200_QL40_ML2_.jpg)

結果、エンジニアリングマネージャーだけではなく、エンジニアリングマネージャーと協力するメンバー視点でも改めて整理整頓ができる本でした。1on1は大事。


## 学び

[インポスター症候群 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%9D%E3%82%B9%E3%82%BF%E3%83%BC%E7%97%87%E5%80%99%E7%BE%A4)
> 自分の達成を内面的に肯定できず、自分は詐欺師であると感じる傾向

に向き合うこと。

### 新人マネージャーがやること
- アイスブレイク ... 1on1でそのまま使えそう
    - 今週はどんな感じですか
    - 今取り掛かっているのはどんな作業ですか
    - 最近リリースした中で、心から満足しているもの
    - チームは主に何を担当していると思いますか
    - チームメンバーはどうですか
    - ここで働いて気に入っていることはなんですか
        - 反対に気に入らないことはありますか
    - はっきりとは言いにくいことがあるとしたらなんですか
    - 手助けしてほしいことがあるとしたらなんですか
- 1on1の設定
- 自分のスナップショット
- そして一旦落ち着くこと

### 自分を管理する
- マネージャーは自分自身を整理する
    - カレンダー
    - TODOリスト
    - メール

### 個人とかかわる
- マネージャーのアウトプット = あなたのチームのアウトプット + あなたが影響を与えた他のチームのアウトプット
- 上司との関係も大事

### 1on1 ほか
- [伽藍とバザール - Wikipedia](https://ja.wikipedia.org/wiki/%E4%BC%BD%E8%97%8D%E3%81%A8%E3%83%90%E3%82%B6%E3%83%BC%E3%83%AB)
- [Linux用語事典 [伽藍とバザール]](https://atmarkit.itmedia.co.jp/aig/03linux/candb.html)
- 評価面談
- ゲームオーバー
    - アメリカのテック業界での年間離職率は13.2パー
    - 人は必ず去ってゆく
- 友人を作る
- 人間って難しい
    - ダニング=クルーガー効果
    - [「完全に理解した」](https://zenn.dev/e99h2121/articles/c11daf42169beb)
- ライトニングトーク

## 参考: セッション資料

ちょうど開催されたセッション資料。副教材に。

https://twitter.com/miua/status/1567176253169610752?s=20

https://www.youtube.com/watch?v=k_FkG_BI6fA

https://www.ryuzee.com/contents/blog/14574

https://iucstscui.hatenablog.com/entry/2022/09/09/235344

## 参考: その他

[ドラッカーの「マネジメント」を読み直して永遠の「管理職vs専門職」問題を考えた - Qiita](https://qiita.com/e99h2121/items/48ff1d5d2675def03bd6)

以上メモ式ですが、参考になればさいわいです。
このサイトって写真綺麗だな、どんなカメラ使ってるんだろう？

参考にしたのは以下のサイトです。

https://news.mynavi.jp/techplus/article/natonakucommand-21/2

sipsコマンドで写真画像データに含まれているメタデータをいろいろ見られるようです。

加工ソフトによってはデータは消えますが、残っている場合もかなりあるようです。

コマンドラインが面倒くさい方はフリーや有料のソフトなどがあるようです。

ファイルの詳細を確認する。

`sips -g all （ファイル名）`


これを応用して、

`sips -g model *.{jpg,jpeg};`


これで一括で出てきます。

CLIでもうちょっとなんとかなると思うのですが、時間がなかったのでEXCELに持っていき不要な行を削除して機種だけをcountして傾向が出ます。

ライキング上位のサイトでは、XperiaとiPhoneのProバージョンが使われているのがよくわかりました。

この方法で焦点距離も見たかったのですがちょっとわかりませんでした。
Python,Ruby,PHP,Java,JavaScript,Perlのfor文の比較 | プログラミング言語比較


<a href="https://qiita.com/yuki_kimoto/items/f9c2454e7f9130ddb003">Qiita > プログラミング言語の比較</a>

プログラミング言語Python,Ruby,PHP,Java,JavaScript,Perlのfor文の比較

# Python

https://qiita.com/Morio/items/e8aed85346c0055beea7

# Ruby

https://qiita.com/Morio/items/3ac5cac9ace7e9ddbdb4

# PHP

https://qiita.com/miriwo/items/d1b5d5ece4f16c7b5985

# Java

https://qiita.com/Co_Pilot/items/7c59410cd90be4cf06d8

# JavaScript

https://qiita.com/w-tdon/items/f3ecb29dc9350f2f2e8d

# Perl

https://perlzemi.com/blog/20080327120662.html
C言語とJavaの環境構築

*Ubuntu22.04*環境下における、*C*と*Java*の環境構築について備忘録。


# C言語

コンパイラの*clang*と*gcc*のインストールだけなので、

```
sudo apt install clang gcc
```

で良いです。

# Java

*Eclipse*は、好みの問題で今の所、使いません。
```
sudo apt install default-jdk
```

で良いです。*JDK*についてバージョンを選択したい場合は、

[Java Downloads | Oracle](https://www.oracle.com/java/technologies/downloads/)

から選択して落としてください。当方、まだ初学者なので、そんなJDKを選ぶような状態ではないです。の場合は、上述のコマンドでよいでしょう。

以上です。
SPSS Modeler ノードリファレンス 5-16 因子分析(主成分分析)

# 5-16 因子分析(主成分)ノード[モデル作成タブ]
<img width="200" alt="194_161因子分析" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f5b86a82-f4fd-1b0e-d8d0-3c91d7bbec14.png">


## 1.ノードの目的
主成分分析は、いくつかのフィールド（列）を縮約して合成変数を作ります。極端に列が多い実験系のデータでは変数削減を目的とした特徴量として利用されます。

## 2.解説動画（60秒）

<iframe width="560" height="315" src="https://www.youtube.com/embed/9fhXrQFO-2Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## 3.クイックスタート

39フィールドのデータを主成分分析で6フィールドに縮約します。
＊サンプルデータ（CSV）は[5.参考情報]からダウンロードできます。
![スクリーンショット 2022-08-31 11.32.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b8ed1b37-b44d-eaf7-0f9a-494c4b876793.png)

[可変長ファイル]ノードから[因子分析]ノードに接続します。
<img width="450" alt=2022-06-27 14.12.30 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f1b9282e-4f9b-0a70-2211-60a58380869e.png">

[可変長ファイル]ノードを編集します。[データ型]タブで[値の読み込み]ボタンを押してデータタイプを確定します。[ロール]では全てのフィールドを[入力]のままにします。
![スクリーンショット 2022-08-31 11.35.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/16a82c9c-9575-6c11-8638-1201b50fd76f.png)

[因子分析]ノードを編集します。[抽出方法]は[主成分分析]にします。
![スクリーンショット 2022-08-31 11.40.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/33fea117-6dd0-d891-fec7-adf0c498501b.png)

[エキスパート]タブを以下のように設定にします。
![スクリーンショット 2022-08-31 11.40.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1eae5f35-cd07-604c-6a9f-d8bff6d57118.png)

[因子分析]ノードを実行してテーブルを接続します。
![スクリーンショット 2022-08-31 11.46.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f77f1ea4-480f-6adb-868d-6dca9dd24739.png)

[テーブル]を実行します。第1から第6主成分までが追加されました。
![スクリーンショット 2022-08-31 11.47.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d019e698-110b-c034-7db5-03a9867cc43c.png)

## 4.Tips

#### 抽出した主成分の評価

今回のデータでは39あるフィールドを第1主成分のみで20.57%情報を縮約できています。以下第6主成分までの累積で85.16%の情報をカバーしていることがわかります。
![スクリーンショット 2022-08-31 11.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/d64cca8b-f86b-dee5-0e60-befbf5622500.png)

例えば第1主成分がどのように計算されたかはナゲットに表示されます。
![スクリーンショット 2022-08-31 12.04.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cf7c8b49-b61b-8168-c49d-374a073d47e3.png)

どのフィールドが主成分に効いたかは以下の成分行列で理解できます。
![スクリーンショット 2022-08-31 11.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/db18ea5a-00de-1504-6b4b-dcff4ca8c318.png)

## 5.参考情報

#### 主成分分析でフィールドの縮約を解説した記事

https://www.ibm.com/blogs/solutions/jp-ja/modeler-tips-15/

#### 利用データ

右クリックでリンク先を保存してください。

https://raw.githubusercontent.com/yoichiro0903n/blue/main/pca.csv

#### ノードのヘルプ

https://www.ibm.com/docs/ja/spss-modeler/18.3.0?topic=models-pcafactor-node

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee
スプレッド構文（配列のコピーについて）

# スプレッド構文（配列のコピーについて）

Jsの配列のコピーは、「`=`」でコピーすると参照元が変化してしまうので、スプレッド構文（`...arr1`みたいな感じ）でコピーする。

```js
const arr1 = [10, 20]

const arr2 = arr1;
arr2[0] = 100;
console.log(arr2);  // => [100, 20]

console.log(arr1);  // => [100, 20]  (*arr2のみ変更したつもりが、参照元のarr1も変更されてしまっている。。。。)
```

これをなくすために、スプレッド構文を使用し、配列をコピーすることで、参照元のarr1には影響を及ぼさないようになる。
（＊ただし、下記の@shiracamusさんのご意見より、浅いコピー(shallow copy)で、多次元配列やオブジェクトには影響してしまうので、注意が必要です。
また、shallow copyについては、下記の記事が参考になりましたので、ぜひご参考までにお読みいただけると幸いです。
https://medium-company.com/%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%82%B3%E3%83%94%E3%83%BC%E3%81%A8%E3%82%B7%E3%83%A3%E3%83%AD%E3%83%BC%E3%82%B3%E3%83%94%E3%83%BC%E3%81%AE%E9%81%95%E3%81%84/ ）

```
const arr1 = [10, 20]

const arr2 = [...arr1];  // ←先ほどのconst arr2 = arr1;部分をスプレッド構文に変更。
arr2[0] = 100;
console.log(arr2);  // => [100, 20]

console.log(arr1);  // => [10, 20]  (*arr2の配列の中身を変更しても、arr1には影響を及ぼさない。)
```
2022/9/12主にITとかセキュリティの記事

ランサムウェア攻撃に最も有効な対策「ペネトレーションテスト」とは？(9/9)
https://news.mynavi.jp/techplus/article/20220909-2450246/

なぜ日本が標的に？ ロシア系のサイバー攻撃集団「Killnet」の目的とは(9/9)
https://news.biglobe.ne.jp/it/0909/aab_220909_0812683056.html

フィッシングメールと思い込んで「本物の警告メール」を見逃す失態にヒヤリ(9/9)
https://ascii.jp/elem/000/004/104/4104208/?topnew=1

｢サイバー防衛人材｣育成拠点に 久里浜の陸自通信学校(9/9)
https://www.townnews.co.jp/0502/2022/09/09/641243.html

河野デジタル相、緊急対応「直轄チーム」　外部から招集(9/9)
https://www.nikkei.com/article/DGXZQOUA097JB0Z00C22A9000000/

シスコの複数製品に重要な脆弱性、アップデートを(9/10)
https://news.biglobe.ne.jp/it/0910/mnn_220910_0098209835.html

ルーターやiOS、Androidなどに対する12の脆弱性がアクティブに悪用されている(9/10)
https://www.itmedia.co.jp/enterprise/articles/2209/10/news028.html

Windows 11で不要なデータを削除して空き容量を確保する方法(9/10)
https://ascii.jp/elem/000/004/105/4105014/?rss

Dockerのlocalhostがどっかいった話し(9/8)
https://qiita.com/Bee2papa/items/6c269697e3f3263de07e
Salesforce：全角数字を半角数字に変換する

Visualforceにて入力された値など、
全角数字を半角数字に変換する必要がある場合に使用するメソッドを作った。


### 構成
①入力値がNULLの場合はそのままreturn　
　※呼び出し元でエラーを検知
②入力値がすべて半角数字の場合はそのままreturn
③全角数字（Key）と半角数字（Value）をセットにしたMapを作成
④入力値に全角数字（Key）が含まれていたら半角数字（Value）に変換する
　※０～９までをループで変換実施
⑤出来上がった文字列をreturn！:kissing_cat:　

### 実装

```apex:sample.cls
private String convertFullNumber(String inputNumber){
        if(String.isEmpty(inputNumber)) return '';
        
        if (Pattern.matches('[0-9]+', inputNumber))  return inputNumber;
        
        Map<String, String> convertNumberMap = new Map<String, String>();
        convertNumberMap.put( '０',  '0' );
        convertNumberMap.put( '１',  '1' );
        convertNumberMap.put( '２',  '2' );
        convertNumberMap.put( '３',  '3' );
        convertNumberMap.put( '４',  '4' );
        convertNumberMap.put( '５',  '5' );
        convertNumberMap.put( '６',  '6' );
        convertNumberMap.put( '７',  '7' );
        convertNumberMap.put( '８',  '8' );
        convertNumberMap.put( '９',  '9' );
        
        for (String full : convertNumberMap.keySet()) {
            if (inputNumber.contains(full)) {
                inputNumber = inputNumber.replaceAll(full, convertNumberMap.get(full));
            }
        }
       
        return inputNumber;
    }
```

<br>
<br>

Salesforce関係ない気がするｗ　
ほぼjava？

まぁただのチートシートなのである。少しでも時短！（　＾ω＾）
useHistoryとは何か

はじめに
--
reactに初めて触ったときは一目見ると何をしているかわからない記述がたくさんありました。（どの言語でもですが)
一つ一つ調べて自分の言葉でアウトプットすると理解度が深まると思ったので簡単なことでもqiitaに残そうと思います。

useHistoryとは
--
react-router-domをimportすると使用できるようになります。
簡単にまとめると、指定したリンクに飛ばしたい時に使用します。

単純に文字をクリックしたらリンクを飛ばしたいというだけであれば、
下記のように、"Sign Up now!"をクリックすれば指定した"/signup"に移動できる"Link"タグを使用すればOKです。

~~~react
                <Link to="/signup" className={classes.link}>
                  Sign Up now!
                </Link>
                <Link to="/password/reset" className={classes.link}>
                  パスワードを忘れた場合はこちら
                </Link>
~~~

https://v5.reactrouter.com/web/api/Link

ではuseHistoryは、どんな時に使用するのでしょうか？
それは関数の中の処理の一つとしてリンクに移動したい時などです。

useHistoryの使用例
--
基本、useHistoryはpushメソッドを使って引数に移動したいurlを記述して使用します。
(他に使い方があるのか調べましたが見つかりませんでした）

例として、僕がポートフォリオ用に実装しているコードをそのまま貼り付けます。
(不要な情報が多くてすみません。)

これはhandleSubmitがクリックされたらパスワードを変更のapi通信を行う関数なのですが、
もしapi通信が成功してステータス200を返したら
① "パスワード変更に成功しました。新しいパスワードでログインをしてください。"というalertが表示される
②alertが表示された後に"history.push("/signin")"で指定したサインインのページに推移する

~~~react
  import { useHistory } from "react-router-dom"

 ~~諸々省略してます~~
  //ここでusehistoryをhistoryに代入
  const history = useHistory()

  const handleSubmit = async (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault()

    const data = createFormData()

    try {
      const res = await RedirectForgetCurrentUserPassword(data)
      console.log(res)

      if (res.status === 200) {

        alert(
          "パスワード変更に成功しました。\n新しいパスワードでログインをしてください。"
          )

        //ここでpushメソッドを使って引数にurlを指定している。
        history.push("/signin")

        console.log("changed Password successfully!")
      } else {
        setAlertMessageOpen(true)
      }
    } catch (err) {
      console.log(err)
      setAlertMessageOpen(true)
    }
  }
~~~

このようにuseHistoryを使用することで、関数の中の処理の一つとしてリンクに飛ぶことができるようになります！

https://v5.reactrouter.com/web/api/Router/history-object

終わりに
--
Reactの"use~"という名前の機能が多く、頭が混乱することもありますが、個別に調べると理解しやすいですね。
(useHistoryが簡単なだけかもしれませんが)
この調子でReactの機能を少しづつアウトプットしていきます。
VisualStudioでLAPACKを使うならOpenBLAS


## 概要


- Windows ＆ Visual Studio環境でのC++の開発においてLAPACKを使いたいときは、OpenBLASが簡単です。
- OpenBLASという名前ですが、LAPACKの関数も実装されています。
- 公式のgithubでコンパイル済みbinaryも配布されているので、ダウンロードして配置するだけで使えます。つまりインストール不要。

## 個人的な背景

Windows上でのアプリ開発にてLAPACKを使いたい場合、ソースを持ってきてコンパイルするにしても、面倒だなあという印象がありました。Visual Studioを使う場合には、FORTRANが使えなかったり、C系列の派生ソースを持ってきてもコンパイルが上手くいかなかったりしました。結局Intel MKLを使いたいだけのためにIntelコンパイラを導入するのが楽ですが、Visual Studioのエディタの動きがますます遅くなったり、ノートPCに入れるには容量が大きかったりします。

そんなとき、金子邦彦先生の以下のWebページを見つけました。

[https://www.kkaneko.jp/tools/win/openblasvc.html](https://www.kkaneko.jp/tools/win/openblasvc.html)

え？OpenBLASって名前なのにLAPACKも入ってるの？

OpenBLASの公式サイトや公式githubを見てみると、

[https://www.openblas.net/](https://www.openblas.net/)

[https://github.com/xianyi/OpenBLAS/](https://github.com/xianyi/OpenBLAS/)

確かにLAPACKの実装も含まれている様子。

ただし、LAPACKも使えるようにソースからコンパイルするにはFORTRANコンパイラも必要なようです。Windows + Visual Studio環境だとFORTRANコンパイラの利用は難しいです。ですが、OpenBLAS公式がコンパイル済みのbinalyも配布してくれており、Visual Studioでリンクできる`lib`と`dll`も配布されています。しかもLAPACKも含まれています。これは嬉しい！

## 使い方（簡単に）

インストールも必要ありません。公式からbinaryをダウンロードして解凍し、Visual Studioのプロジェクトのプロパティーを設定するだけです。
### ダウンロード

まず、OpenBLAS公式のgithubの[Release](https://github.com/xianyi/OpenBLAS/releases)から`OpenBLAS-0.3.21-x64.zip`をダウンロードします（バージョンやx86など、環境に合わせて適宜読み替えてください）。

解凍すると、`bin`, `include`, `lib`の三つのディレクトリが入っています。これらを適当な場所におきましょう。例として、Visual Studioのソリューション・プロジェクト名を`MyApp`とします。`OpenBLAS-0.3.21-x64`ディレクトリを次のように配置することにします。
```
repos
|-- MyApp
|   |-- MyApp.sln
|   |-- MyApp.vcxproj
|   |-- sources
|       |-- ...
|-- OpenBLAS-0.3.21-x64
    |-- bin
    |-- include
    |-- lib
```

### Visual Studioの設定

次に、Visual Studioを立ち上げ、MyAppプロジェクトのプロパティーを設定します。

1. Visual Studioのメニューから「プロジェクト」→「プロパティ」を選択して「MyAppプロパティ ページ」というウィンドウを開きます。
1. 「構成プロパティー」→「VC++ ディレクトリ」→「インクルードディレクトリ」に`../OpenBLAS-0.3.21-x64/include`を追加します。（「構成プロパティ」→「C/C++」→「全般」→「追加のインクルードディレクトリ」で可）
1. 「構成プロパティー」→「VC++ ディレクトリ」→「ライブラリディレクトリ」に`../OpenBLAS-0.3.21-x64/lib`を追加します。（「構成プロパティ」→「リンカー」→「全般」→「追加のライブラリディレクトリ」でも可）
1. 「構成プロパティ」→「リンカー」→「入力」→「追加の依存ファイル」に`libopenblas.lib`を追加します。
1. (これは無くてもいいかも)「構成プロパティー」→「VC++ ディレクトリ」→「実行可能ファイルディレクトリ」に`../OpenBLAS-0.3.21-x64/bin`を追加します。

すでに別の内容が設定されているときは、セミコロン`;`区切りで追加します。

### DLLの配置

自作のアプリ`MyApp.exe`の実行時にはOpenBLASのDLLを読み込む必要があります。次のどちらかの方法で設定してください。

- Windowsの環境変数の`Path`項目に、`OpenBLAS-0.3.21-x64/bin`のフルパスを登録してください。フルパスなので、`c:\...\...\...\OpenBLAS-0.3.21-x64\bin`などとなるでしょう。
- `OpenBLAS-0.3.21-x64/bin`の中にある`libopenblas.dll`だけを、MyAppの実行ファイルと同じ場所にコピーします。デフォルトだと`MyApp/x64/Release/`になると思います。自作のアプリ`MyApp.exe`を配布する場合にも、`libopenblas.dll`を同梱すればユーザーに環境変数の設定をしてもらう必要はありません。

これで、LAPACKを利用するプロジェクトのコンパイルが通るようになり、実行もできると思います。


## 感想

ありがとう OpenBLAS。ありがとう、金子邦彦先生。
Linux nmap、ulimit、lastコマンドについて（自分用メモ

●nmapコマンド
指定したホストの開いているポートをネットワーク経由で確認（ポートスキャン）できる。ホストにログインせずに、外部からアクセス可能なポートを調査。

nmap 対象ホスト

TCPやUDPなどスキャンで利用するプロトコルを指定したり、オプションによってリモートホストのOS識別を試みたり、対象ポート範囲の指定を行うことができる。

「netstat」や「lsof」コマンドでも空いているポートは確認できるが、これらで表示できるのはローカルホストの情報だけ。「nmap」コマンドはリモートホストの情報も確認できる。「nmap localhost」とすればローカルホストのポートスキャンも可能


●ulimitコマンド
ユーザやシェルが利用するリソースを制限するコマンド。
ユーザーの誤操作やプログラムのバグ、悪意のあるユーザーによるリソースの消費などを回避する為などに使用される。

ulimit [オプション] [制限値]

オプション
・-a リソースの制限値を全て表示(all)
・-c コアファイルのサイズを制限(core)
・-f 出力ファイルのサイズを制限(file)
・-u ユーザ1人が起動できるプロセス数を制限(user process)
・-v シェルが利用できる仮想メモリを制限(virtual memory)

※csh・tcsh を使っている場合は、limit コマンドを使用する


●SUIDやSGIDが設定されていると、一般ユーザーでもroot権限でファイルを実行できる場合がある。root権限を不正に操作されるとセキュリティ上問題がある。そこで、システム管理者は、ファイルを検索する「find」コマンドに「-perm」オプションを付けて、SUID/SGIDが設定されたファイルを検索し、把握する必要がある。

■findコマンドの書式
find [検索場所] -perm -[モード]
　[モード]で指定されている許可属性ビットのすべてが、ファイルでも立っていたら真
find [検索場所] -perm +[モード]
　[モード]で指定されている許可属性ビットのどれか一つが、ファイルでも立っていたら真

例）
・find / -perm -u+s -uid 0
・find / -perm -4000 -uid 0

SUIDが設定されたモードを数字表現で表すと「4000」、記号表現では「u+s」。
また、「-uid」で所有権を持つユーザIDを、「-gid」で所有権を持つグループIDを指定して検索できる。rootユーザはユーザID、グループIDともに「0」。

●lastコマンド
「/var/log/wtmp」ファイルを参照し、最近ログインしたユーザの一覧を表示するコマンド。「/var/log/wtmp」はユーザのログイン/ログアウト情報が記録されているバイナリファイル

●「w」、「who」コマンド
「/var/run/utmp」ファイルを参照し、現在システムにログインしているユーザーの情報を表示。「/var/run/utmp」ファイルはログイン中のユーザの情報が格納されているバイナリファイル。

「w」コマンドは、「who」コマンドの情報にプラスして、システムの情報やユーザが何をしているのか、まで表示
素数p=x+y (x,yともに1以上)とすると gcd(x,y)=1 らしい

# gcd(x,y)=1 の図を作る

まず、試しに以下の方法

```python:gifビットマップ用512x512
from math import gcd  # python 3.5 以上

width = 512
bitmap = [int(gcd(x, y) == 1)
          for y in range(1, 1 + width)
          for x in range(1, 1 + width)]
```

で得た情報から画像を作ります（白は $gcd(x,y)\ne 1$、青は $gcd(x,y)=1$ のドット）
![sample-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/5200cb0f-9ab1-5f30-b8bb-7ba7e33555c2.gif)
$x$ 方向は右で、$y$ 方向は下、画像の座標は左上が $(1, 1)$ です。また、$gcd(x,y)=gcd(y,x)$ で対称です。

# 左下方向から右上方向への途切れない斜め線を探す

上の図で、$n=x+y$ としたとき、$gcd(x,y)=1$ しかないものを探して赤ドットに変更すると
![sample-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/d27ea231-dc16-4d4a-ec4a-29810153bc23.gif)
となりました。$n$ を探すプログラム

```python:検索
from math import gcd  # Python 3.5 以上

width = 512

m = ''
for x in range(1, 1 + width * 2):
    u = x
    v = 1
    while u >= v:
        if gcd(u, v) != 1:
            break
        u -= 1
        v += 1
    if u >= v:
        continue
    m += f'{x+1},'
    if len(m) >= 72:
        print(m)
        m = ''
if m:
    print(m)
```

```console:実行結果
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,
103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,
197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,
307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,
419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,
523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,
643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,
761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,
883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,
1019,1021,
```

が得られたので、これを Mathematica で

```Mathematica:
Table[Prime[n], {n, 172}] == {
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,
103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,
197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,
307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,
419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,
523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,
643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,
761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,
883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,
1019,1021
}
```

を実行すると True が返ってきました。

~~何でそうなるのかは分かりませんし、どの範囲まで通用するのかも分かりません。~~

$gcd(x,y)=m$ で $m\ne1$ なら

```math:
p = x + y = m (s + t) = m s + m t \\
x = m s \\
y = m t \\
```

の場合が存在するので、$p$ は合成数か…
正規表現 備忘録

# よく使用する正規表現
`//`：構文の最初と終わり
`[]`：[]で囲まれた文字のうちいずれか１つにマッチする
`[a-z]`：aからｚのいずれか１つにマッチ
`\d`：数字にマッチ
` [ぁ-んァ-ヶ一-龥々ー]`：かな/カナ漢字のいずれかにマッチ
`\s　` :スペースと全角スペース(\sの後ろに全角スペースを入れる)にマッチ

`/i`：大文字・小文字を区別しない
`\A`：\の直後においた文字が先頭にある文字列にマッチ
`\z`：\の直前においた文字が末尾にある文字列にマッチ

`.`:ハイフンやピリオドなど含めたすべての英数字において、1文字マッチする
`*?`:直前の1文字が0回以上続く文字列をチェックし、?の直後の文字が出た段階でその１文字を返す
`+`:直前の文字が１回以上の繰り返しにマッチ
`{n}`：直前の文字がn回以上出現するものにマッチ
`{n,m}`：直前の文字が少なくともn回、多くてもm回出現するものにマッチ
`?=`:?後に設定した文字が続く文字列にマッチ
Electron超概略


Electron を触る前に概略を知っておけば用語が理解しやすいです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/5afd373d-506d-1064-5137-aba377444195.png" width=500px>

| 用語               | 説明                                                                                                                                                                       |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| レンダラープロセス | オモテの見える部<br>HTML等で記述する部分                                                                                                                                   |
| メインプロセス     | Node.js で記述する部分<br>オモテから見たときのバックエンドの部分にあたる                                                                                                   |
| ContextBridge      | レンダラープロセスから直接メインプロセスを操作させないための仕組み<br>セキュリティ向上のための仕組みで、このワンクッションを挟むことで OS にイタズラされないようにしている |
対数関数を使ったイージング等のチューニング

# はじめに

ゲーム制作で簡単なアニメーションを実装する際にイージングが便利でよく使いますよね！

私もよく以下のページとにらめっこしてハマりそうなプリセットを使ったり

https://easings.net/ja

自分でイージング関数を実装したりしています。

さて、今回は高校数学でも習う対数関数「$logx$」を使ったちょっとしたイージングのチューニング小ネタを紹介します。

# 対数関数

対数について軽く復習しましょう。

ある数 $x$ を $b^p$ と表した際に、この$p$を「底$b$とする$x$の対数」と呼び
```math
log_{b}x
```
と表しました。

なので、このような対数があった場合、以下のような数式も成り立ちました。

```math
b^{log_bx}=x
```

# 冪関数

続いて冪関数についても軽く見ていきます。
(指数関数ではなく冪関数にしているのは、今回の話題においてこれが都合がいいからです)

```math
x^a
```

さて、ここで注目したいのが  
少なくとも実数の範囲では

- $x$ が $0$ のとき $a\neq0$ ならば、いかなる値だとしても $0^{a}$ は $0$ になります
- 同様に、$x$ が $1$ のとき $a$ がいかなる値だとしても $1^{a}$ は $1$ になります

つまり
冪関数は、$a\neq0$ ならば絶対に$(0, 0)$と$(1, 1)$を通ることが分かります。

# 任意な点を通る なめらかな曲線

ここで

```math
x^{log_ab}
```
という関数を考えてみます。

$a$, $b$をそれぞれ

- $0 < a < 1$
- $0 < b < 1$

の範囲とした場合

この関数は、先ほどまで見てきた対数関数、冪関数の性質から
以下の三点をとおる`なめらかな曲線`であることがわかります。
※a,bが同じ値の場合、直線になる

- $(0, 0)$
- $(a, b)$ (任意の点)
- $(1, 1)$

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/fdd6dc60-b35f-b6ef-6ba4-6004d923429a.png" width="400">

# イージング関数等と組み合わせる

先ほど考えた$x^{log_ab}$という関数。いったい何が嬉しかったのかという

イージング関数自体が
時間軸$t$において始点を$t=0$、終点を$t=1$とした場合
$0$～$1$の範囲での変化とみることができるので
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/896b277d-ec9c-0acb-f868-efdbe2fb5dd8.png" width="400">

この$t$に$x^{log_ab}$を適用することで、イージング関数を

**任意の点を通る**くらいに**いい感じ**に**歪ませる**ことができます。

## 例1 イージング関数
例えば、上記の`easeInSine`の例でいえば、
だいたい$t=0.6$の時に$0.4$くらいの値を通っていますが
もう少し早く$t=0.5$くらいの時には$0.4$くらいの値を通ってほしいと思ったとします。

それであれば$t$を$t^{log_{0.5}0.6}$にしてしまえばいいのです！

```javascript:疑似コード
// easeInSine(t); を以下のように修正
easeInSine(pow(t, log(0.6, 0.5))); 
```
※log(a, b)をbを底とした対数関数とする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/d9988d8b-14ba-239e-d3f1-6670baa12541.png" width="400">


## 例2 三角関数

sin関数なんかも歪ませちゃえます。
最大値に到達する時間をもう少し早めてみます。(※減少速度が下がることに注意)

```javascript:疑似コード
// sin(t * PI); を以下のように修正
sin(pow(t, log(0.5, 0.4)) * PI); 
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104703/238dd541-807c-de77-74b3-963c10f0b3b8.png" width="400">

---

このように、対数関数と冪関数の関係を上手く活用した$x^{log_ab}$を挟むことで、任意の点$(a, b)$をとおるように、他の関数を歪ませることができます。

ゲーム制作では、細かい動きの調整をする機会が多いと思うので、似たようなイージングはあるのだけど、ちょっと理想のタイミングとずれてるなと思った時とかに、いい感じに歪ませることでそれっぽい動きができあがるかもしれません！

# おまけ 底を指定する対数関数の実装
なお、プログラミング言語によっては、組み込みで用意されてる`log`関数が底の指定ができないこともあると思います。(一般的には底は`e`？)
その場合は自分で底を指定する対数関数の実装が必要になりますが、
こちらは、高校数学でも習った以下の式により簡単に実装できます。

```math
log_ax=\frac{log_bx}{log_ba}
```

```javascript:疑似コード
// aを底とする対数関数
log(x) / log(a)
```

# まとめ

- 対数関数と冪関数の関係を利用した$x^{log_ab}$は任意の点$(a, b)$を通るなめらかな曲線
  ※($0 < a,b < 1$)
- イージング関数等に上記関数を適用することで任意の点をとおるように歪ませることができる
- アニメーション変化の細かいチューニングで活用できる
AirDropでMacに転送したファイルの保存先を変更する

## やりたいこと

　画像や動画ファイルなどをiPhoneからMacBookにAirDropで転送する際、デフォルトの保存先は Downloads/ フォルダとなっている。これを変更したい。
　具体例としては、iPhoneの空き容量確保のために大量のスクショ画像や録画・動画をMacに移動するケース。サイズが大きいなどの理由により、Mac側でTimeMachineのバックアップ対象から除外したい。そこで、TimeMachineで除外設定したフォルダへすぐさま退避しておきたい。

## アイデア
　残念ながら保存先の変更自体はどうしてもできないらしく、一度は必ず Downloads/ に保存される。そこで代替策として、転送完了後すぐさま別のフォルダに移動する。
　そのためにMacの標準的な仕組みであるAutomatorとフォルダアクションを使う。
この基本的なアイデアだけで予備知識なしでGUI操作して作ると、ハマって30分ほど試行錯誤したのでTIPSとして残しておく。

## 注意点：期待しない動作・ハマったこと
　フォルダアクションはファイル書き出しが瞬時に終わることを前提としているのか、Downloads/ へファイル保存が完了する前に移動し始めるようで、移動先フォルダに中途半端な空ファイルだけ作られ、実体はDownloads/ にできる。移動先フォルダの空ファイルを削除しようとすると、プログラム（フォルダアクション？）がつかんだままになる。

この問題を解決するのが、後述する手順に「★重要」と書いている部分。

## 確認した動作環境
* macOS Catalina バージョン 10.15.7
* iPhone 7 iOS 15.7

## 1. 準備：ワークフローを作成する
1. Automator起動し新規ワークフローを作成
1. ワークフローの種別としてフォルダアクションを選択
1. 「フォルダアクションは、次の場所に追加されたファイルやフォルダを受け取る」の箇所で、Downloadsを選択
1. そのフローの下に「Finderにフィルタを適用」を追加
1. 種類がイメージである、あるいはムービーであるものを対象とする
1. オプションで「ワークフローの実行時にこのアクションを表示」にチェック ←★重要
1. そのフローの下に「Finder項目を移動」を追加
1. 保存先フォルダを任意に選択
1. ワークフローを保存

これで自動的にフォルダアクションが設定され、AirDropやその他の方法でDownloadsにファイルが追加された際に、自動的に起動されて動作する。

## 2. 保存と移動
1. AirDropなどでDownloads/にファイルを送信する
1. （先に作成したフォルダアクションが自動実行される）
1. 「Finder項目にフィルタを適用」ダイアログが表示されるが、まずは何もしない。送信側で送信が完了、すなわち受信側でDownloadsフォルダへのファイル保存が完了するまで待つ（※１）。ちなみにこのダイアログは上記手順のフィルターのオプションで設定したもの。ファイル数が50以上など多い場合は2回表示される場合がある。
1. 送信／が完了しファイルが一式作成されたら、表示ダイアログの「続ける」ボタンを押す（※２）。

これで、移動先フォルダにファイルが移動される

※１）ファイル名が半透明の状態は書き出し途中を意味する。
※２）これが早すぎると、冒頭に書いた期待しない状況が発生する。

## 補足
　フォルダアクションを作成する前から既にDownloads/内に画像や動画ファイルがある場合、それらは移動対象とならない。フィルターがファイルをつかみ、それらのみ移動する模様。
　ダイアログが複数回に分けて表示される場合、それぞれが分担してつかんでいるらしく、「続ける」ボタンを押すと、その担当分だけ移動される。

## フォルダアクションを無効化する方法
1. ダウンロードフォルダを右クリックし、「フォルダアクション設定」
1. Downloadsを選択し、当該フォルダアクションを削除

## おわりに
Automatorが識別するファイル種別で切り替えられるので、必要に応じて切り替えると応用が効く。うっとうしい時は無効化するとOK
’data-*’表現をよく見るから調べると「データ属性」って言うらしい

# ‘data-*’の正体

HTML要素に追加情報を格納できるHTML属性

# 使用例

## ‘data-*’属性がない時
```
<article id="electric-cars">
    ...
</article>
```
**電気自動車の記事が書かれてる**という情報が分かりそうです。

## ‘data-*’属性がある時
```
<article
  id="electric-cars"
  data-columns="3"
  data-index-number="12314"
  data-parent="cars">
    ...
</article>
```
‘data-*’属性を加える事で、**3つのトピックが用意されている**・**この記事は12314個目**・**電気自動車以外の車の記事もあるかもしれない**。
これらの情報が追加で分かりました。
# ‘data-*’属性を使うと何が嬉しいの？
JavaScriptでおこなうデータ取得がシンプルになります。
実際に下記で確認してみます。

## ‘data-*’属性がない時
```
const article = document.getElementById('electric-cars');

article.getAttribute('columns'); // "3"
article.getAttribute('indexNumber'); // "12314"
article.getAttribute('parent'); // "cars"
```
getAttribute()を何度も呼び出しています。
少しカッコ悪さを感じてしまいますね…。

## ‘data-*’属性がある時
```
const article = document.getElementById('electric-cars');

article.dataset.columns // "3"
article.dataset.indexNumber // "12314"
article.dataset.parent // "cars"
```
可読性が上がった気がします。

# 参考リンク🙏🏻
https://developer.mozilla.org/ja/docs/Learn/HTML/Howto/Use_data_attributes
困ったときはGit Reflogに頼る

SourceTreeなどGit関連のツールはいっぱいあると思いますが
その際にマージミス、リセットミスなどまぁやらかしてしまうことは何回かあります。

その時にGit Reflogコマンドをよく使うので、備忘録として残しておきます。

## git reflogとは
自分がGitを使用した操作のログを確認することができるコマンド。
どちらかというと、操作をやる前に戻すと言った場合に利用する。

そのため、マージミスやブランチを間違えて削除してしまった…など、大きな操作ミスなどのリカバリ策としてよく利用する。

このコマンドを実行すると、以下のようにログが出力される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565426/da98fa24-b646-6848-13de-9a336cc9c356.png)

## 時間をさかのぼりたい
下記のようなコマンドで、時間を表示してログをさかのぼることができます。
`git reflog --date=default`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565426/e03778ad-b58a-11c0-4d6e-e26dca214029.png)

## 戻し方
以下のように、作業ディレクトリも元に戻したいのでhardリセットを行い
操作を戻していく。

### 操作の順番で戻したい場合
タイミングの場所を指定する。
例：`git reset --hard HEAD@{1}`
### 時間で指定したい場合
時間を指定する。
例：`git reset --hard HEAD@{Sun Oct 20 14:23:22 2019 +0900}`
chmodでファイルの実行権限を変更

# ファイルの権限を実行可能に変更する

## 1. ファイルのあるディレクトリまで移動
```termianl
$ cd script/shell
```

## 2. 権限変更（実行権限を付与）
```terminal
$ chmod 755 sample02.sh
```

:::note
ちなみに`+x`でも可能で、`755`と同じ結果になる。
```terminal
$ chmod +x sample02.py
```
:::

## 3. 権限確認

```terminal
$ ls -l
```

```terminal:例
 ~/プロジェクト名/リポジトリ名/script/shell (feature/sample *)$ ls -l | grep sample
-rw-r--r--  1 username  staff  1121 May 15 16:20 sample01.sh
-rwxr-xr-x  1 username  staff  1246 Jul 21 17:55 sample02.sh
-rw-r--r--  1 username  staff  1126 May 16 16:38 sample03.sh
```

:::note
`$ chmod 755 ファイル名`としたことで権限が実行可能に変更された。
:::

## 詳細

```terminal
-rwxr-xr-x  1 username  staff  1246 Jul 21 17:55 sample02.sh
```

左から

|記号  |意味  |
|---|---|
|-  |ファイル  |
|rwx  |所有者(u)が、読み込み(r)、書き込み(w)、実行(x)が可能  |
|r-x  |グループ(g)が、読み込み(r)、実行(x)が可能  |
|r-x  |その他(o)が、読み込み(r)、実行(x)が可能  |


- **数字の意味**
    - 4・・・読み込み(r)
    - 2・・・書き込み(w)
    - 1・・・実行(x)


- すなわち`-rwxr-xr-x`は、755となる	
    - `rwx`	→　7
    - `r-x`	→　5
    - `r-x`	→　5


:::note
ちなみに、今回実行権限の修正を加えなかったファイルの`-rw-r--r--`は644となるのが理解できる。また、777に変更すれば全て実行可能となる。
:::


---

先頭記号の意味は以下の通り

|種別  |意味  |
|---|---|
|-  |ファイル  |
|d  |ディレクトリ  |
|l  |シンボリック  |
Azureのリソースを半自動でTerraformにリバースするシェルを書いてみた


Azureのリソースを半自動でTerraformのリソース定義にリバースするシェルを書いてみました。
日本語の記事はZennに記載してます。ツール本体についてはGithubをご覧ください。

[https://zenn.dev/soil/articles/azure-terracotta](https://zenn.dev/soil/articles/azure-terracotta)

# Gitリポジトリ
[https://github.com/takker-hero-se/terracotta](https://github.com/takker-hero-se/terracotta)
PCで使う一般的な記号をまとめてみた

# はじめに
Power Platformを中心に登壇することが増えてきましたが、「**ぶっちゃけPC記号わからん**」って問題を感じてきたため、自分なりにまとめてみました。

:::note warn
お断り
いくつかのサイトを拝見してまとめた結果です。
JIS日本語通用名称ではなく、一般的な読み方を採用し、まとめた結果です

登壇している方のお言葉遣いを参考にし、この呼び名で使いたいと感じたものを採用しています
:::

**一般的な読み方**特化の記事です。

## この記事の対象者
 - 勉強会などで登壇するが、PC記号の名称が正直曖昧な方
 - エンジニア含むIT初心者
 - とりあえずそれっぽい言い方をしたい方

## パソコン記号　一般的な読み方 一覧
|記号|一般的な読み方
|---|---
| |スペース
|！|エクスクラメーションマーク、ビックリマーク、感嘆符
|"|ダブルクォーテーション
|＃|シャープ、ハッシュタグ、イゲタ、ナンバーサイン、番号記号、ナンバー記号、No、パウンドサイン（ポンド）
|$|ドルマーク、ダラー、ダラス、ドル
|%|パーセント
|&|アンパサンド、アンド
|'|シングルクォーテーション、クォート、アポストロフィー
|`|バッククオート
|(|[左]パーレン、ヒダリカッコ、カッコ（開く）、マルカッコ（開く）
|)|[右]パーレン、ミギカッコ、カッコ（閉じ）、マルカッコ（閉じ）
|[|[左]ブラケット、角カッコ（開く）、大カッコ（開く）
|]|[右]ブラケット、角カッコ（閉じ）、大カッコ（閉じ）
|{|[左]カーリーブラケット、ブレイス、中カッコ（開く）
|}|[右]カーリーブラケット、ブレイス、中カッコ（閉じ）
|=|イコール
|-|ハイフン、マイナス、ひく
|~|チルダ
|^|キャロット、ハット、カレット
|\| |パイプ、パイプライン、たて棒、縦線  - パイプラインについては、演算子の要素と処理の要素が含まれますので、使用するシーンに応じて適切な表現が必要とのことです
|\|\||二重縦線、双柱（そうちゅう）
|¥ |円マーク、円、円記号
|\\ |バックスラッシュ
|@|アットマーク
|*|アスタリスク、アステリ、アステ、ホシジルシ、かける
|+|プラス、たす
|/|スラッシュ、わる
|,|カンマ、コンマ
|.|ピリオド、ドット
|:|コロン
|;|セミコロン
|<|[左]アングルブラケット、レスザン、レフトアングル、カギカッコ（開く）、小なり（記号）
|>|右アングルブラケット、グレーターザン、ライトアングル、カギカッコ（閉じ）、大なり（記号）
|?|クエスチョンマーク、疑問符
|_|アンダースコア、アンダーバー
|￣|オーバーライン * 全角文字

## 最後に
今回まとめた内容で登壇の言い回しはなるべく統一しようかと思ってます！
noteで活動履歴をまとめているのでよかったら見てくださいね🐟✨

**変なカッコしてます。変装が趣味になってきました**

https://note.com/bonito_vba_gas

## おすすめの勉強会

https://kimamani.connpass.com/

https://powerautomatedesktop.connpass.com/

https://rpacommunity.connpass.com/

https://akiika-yuruyuru.connpass.com/

どこかしらで登壇予定です。よろしくお願いします🙇
toPromiseの代替手段はlastValueFromで問題ないのか

# はじめに
toPromiseはRxJS7で非推奨となりRxJS8で使用できなくなることが予定されています。
今後はtoPromiseの代わりにlastValueFromを利用するべきという記事が多くありますが、本当に同じことができるのかを検証してみました。

# 結論
　　**多くのケースでは問題ないが全く同義ではない**


下記公式ドキュメントでもこう記載されています。
[RxJS Conversion to Promises](https://rxjs.dev/deprecations/to-promise)
> The lastValueFrom is almost exactly the same as toPromise()

almost（ほぼ）ということで異なる挙動をするケースがあるのでこの記事ではその説明をしていきます。

# toPromise終了に向けて追加された2つのFunction
lastValueFromとtoPromiseの違いの前にまずtoPromiseの終了に向けて追加された2つのFunctionを説明します。
## fistValueFrom
firstValueFromはtoPromise同様にObservableなオブジェクトをPromiseに変換する機能を持ったFunctionです。
firstValueFromでは引数とした受け取ったObservableが最初にnextした値をresolveして返してくれます。
```
firstValueFrom(from([1, 2, 3])).then((value) => {
  console.log(value);
});

// expected output: 1
```
Angularなどを利用している場合、stateをobservableな値で持っている場合も多くそれをasync awaitで同期処理のように書きたい場合などで非常に便利な関数です。

## lastValueFrom
lastValueFromもObservableなオブジェクトをPromiseに変換する機能を持ったFunctionですが、firstValueFromとは異なり最後にnextした値をresolveして返してくれます。
```
lastValueFrom(from([1, 2, 3])).then((value) => {
  console.log(value);
});

// expected output: 3
```

# toPromiseとそれぞれの関数の違い
それでは本題のtoPromiseとの違いについて説明します。
## firstValueFromとの違い
これは明らかですね。
toPromiseでresolveされるのは最後にnextされた値ですが、firstValueFromでresolveされるのは最初にnextされた値です。
```
firstValueFrom(from([1, 2, 3])).then((value) => {
  console.log(value);
});
// expected output: 1

from([1, 2, 3]).toPromise().then((value) => {
  console.log(value);
});
// expected output: 3
```

ただし、BehaviorSubjectなどで最新値をお取得したい場合などの処理は少し簡略化して書くことができるようになってます。
```
from([1, 2, 3]).pipe(first()).toPromise().then((value) => {
  console.log(value);
});
// expected output: 1

firstValueFrom(from([1, 2, 3])).then((value) => {
  console.log(value);
});
// expected output: 1
```
上記の2つは同義です。

## lastValueFromとの違い
lastValueFromもtoPromiseも最後にnextした値をresolveするという点では同じなので一見同じ処理に見えますが異なる動きをするケースがあります。
それは

　**値がnextされずにcompleteされた場合**

です。
```
lastValueFrom(EMPTY).then((value) => {
  console.log(value);
}).catch((error) => {
  console.log('error');
});
// expected output: 'error'

EMPTY.toPromise().then((value) => {
  console.log(value);
}).catch((error) => {
  console.log('error');
});
// expected output: undefined
```
toPromiseでは仮にそのオブジェクトが何もnextせずにcompleteしてもundefinedでresolveしてくれますが、lastValueFromでは値がnextされなかった場合はerrorとして返してしまいます。
したがって、toPromiseを副作用なしで代替しようとすると下記のようになります。
```
lastValueFrom(
  EMPTY.pipe(
    last(),
    catchError((error) => {
      if (error instanceof EmptyError) {
        return of(undefined);
      } else {
        throw error;
      }
    })
  )
)
```

# まとめ
toPromiseはRxJS8で削除予定となりますが、移行の際には意味合いをきちんと理解して移行するのが無難かと思います。
最後に紹介したlastをpipeするパターンで書き換えればおそらく互換性を維持して書き換えることが出来ますが、せっかくfirstValueFromなどの便利なFunctionも追加されているのでこれを機に書き換えていくことを強くお勧めします。

# 参考
- [firstValueFrom](https://rxjs.dev/api/index/function/firstValueFrom)
- [lastValueFrom](https://rxjs.dev/api/index/function/lastValueFrom)
- [Conversion to Promises](https://rxjs.dev/deprecations/to-promise)
コンテナイメージを利用した簡単なLambdaを作成する

コンテナイメージを使用したLambdaを作る必要があったので、pythonで簡単なHello worldを表示させるだけのLambdaの作り方をメモ。

# 0．作成手順
１．各ファイルの準備
２．ECRリポジトリの作成
３．ECRへイメージをプッシュ
４．Lambda関数の作成
５．Lambda関数のテスト

# 1．各ファイルの準備
Dockerfileとpython処理を記述したapp.pyを準備して同じディレクトリに置く。

app.pyにはHello worldを返すだけの処理を記述。
```python:app.py
def handler(event, context):
    return 'Hello world!'
```

Dockerfileはドキュメント：[Lambda コンテナイメージの作成](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html#images-create-1)を参考に作成。
```Dockerfile:Dockerfile
FROM public.ecr.aws/lambda/python:3.8

COPY app.py ${LAMBDA_TASK_ROOT}

# この例ではrequirements.txtは必要ないので下2行はコメントアウト
#COPY requirements.txt  .
#RUN  pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

CMD [ "app.handler" ] 
```

# 2．ECRリポジトリの作成
AWSマネジメントコンソールでリポジトリを作成する。
リポジトリ名を入れるだけで作成可能。
この例ではリポジトリ名をhello-testで作成。
![01_リポジトリ作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402694/1b0e64c6-db29-ff4c-cbd9-7685deeeffad.png)

# 3．ECRへイメージをプッシュ
作成したECRリポジトリの画面＞プッシュコマンドの表示ボタンから表示されるコマンドをコピーして実行すればOK。

(1) docker login（東京リージョンの例）
```
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com
```

(2) docker build
```
$ docker build -t hello-test .
```

(3) イメージにタグを付与
```
docker tag hello-test:latest {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-test:latest
```

(4) ECRにイメージをプッシュ
```
docker push {AWSaccountID}.dkr.ecr.ap-northeast-1.amazonaws.com/hello-test:latest
```
※タグは後々のことを考えるとlatestから変えた方がよいかも。。。

# 4．Lambda関数の作成
マネジメントコンソールのLambda＞関数＞関数の作成で、コンテナイメージを選択。
関数名とコンテナイメージURIを入力して作成できる。
![03_lambda作成画面_入力済み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402694/6afe20d7-0326-e563-57d5-fb316b212b2c.png)
関数を作成すると、イメージ欄にイメージURIが表示される。
![04_lambda概要画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402694/a1baf92d-0688-d892-1cff-c2bde89936f0.png)

# 5．Lambda関数のテスト
テストの実行結果。"Hello world!"が表示されている。
![05_テスト実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1402694/75ac4afc-5a32-9448-47eb-74d2620d6830.png)
IoT あるじゃん　ALGYAN x STM x mROS-base 世界初！mROS 2ハンズオンを受講したよ

2022年10月1日に横浜の岩崎学園　情報科学専門学校さんで行われた __ALGYAN x STM x mROS-base世界初！mROS 2ハンズオン__ を受講しました。
# mROS2とは？
ROSはPub/Sub通信という、出版者、購読者という役割で動くシステムになります。
今まで中心となるシステムにはLinuxが稼働している必要がありましたが
mROS2を要約するなら
Linuxが稼働していないマイコンにおいて動作するROSといえます。
https://www.stmcu.jp/design/thirdparty/os/91883/
現在対応しているのはLANが搭載されているマイコンボードとなりSTM32やGR-MANGOがサポートされています。
# シラバス
https://docs.google.com/document/d/14tb6riEkbYYiEMxBEIIdI4j2KYm1JenvI23AvOBuCHU/edit#
# アーカイブ映像
https://www.youtube.com/watch?v=Hjo1ZfefjL4
# 使用機材
- STマイクロエレクトロニクス　STM32H743
- Raspberry Pi 4B（ROS 2ホスト環境として利用）
- 習環境イメージ書込み済みのmicroSDカード（ROS 2環境込み）
- 電源アダプター
- Groveモジュール各種
- USB-microUSBケーブル
- LANケーブル
![IMG_4276.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/3558cb8e-1718-d84b-f89c-00fcf84b3d81.jpeg)
## Hello World！
シラバス通りに進めていけば一通りの動作が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c268ccdc-7a92-0203-cdae-2409141923e8.png)
## STMマイコンから turtlesim をいごかしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c02620b6-9c50-c9b8-7f03-729c2925dee7.png)
# ROSとmROS
ROSは敷居が高く入りずらいという印象が強かったと思います。
今回のmROS2はマイコンボードにLAN端子が必要と言う事で敷居がさらに高いと言えますが
多角的な運用を行いたい方はmROS2を試してみてはいかがでしょうか？