OmniAICreator/Qiita-1.07M huggingface dataset:
Inside Windows / Windows Internals の邦訳版

# はじめに
**『Inside Windows (Windows Internals)』** の邦訳版は版数によってタイトルが異なるのでググラビリティが低いです。

# 一覧
オリジナルの方も改題してるんですけどね。

| タイトル | 言語 | 版数 | 対応 | ISBN-10<br>(Amazon) |
|:---|:---:|:---:|:---:|:---:|
| Inside Windows NT | 英語 | 1 | NT 3.x |[155615481X](https://www.amazon.co.jp/dp/155615481X/) |
| Inside Windows NT | 日本語 | 1 | NT 3.x |[4756102778](https://www.amazon.co.jp/dp/4756102778/) |
| Inside Windows NT 2nd Edition| 英語 |2 | NT 4.0 |[1572316772](https://www.amazon.co.jp/dp/157231852X/) |
| インサイド Windows NT 第2版 | 日本語 | 2 | NT 4.0 |[4891000309](https://www.amazon.co.jp/dp/4891000309/) |
| Inside Windows 2000 3rd Edition | 英語 | 3 | 2000 |[0735610215](https://www.amazon.co.jp/dp/0735610215/) |
| アーキテクチャ徹底解説 Windows 2000 <上> | 日本語 | 3 | 2000 |[4891001917](https://www.amazon.co.jp/dp/4891001917/) |
| アーキテクチャ徹底解説 Windows 2000 <下> | 日本語 | 3 | 2000 |[4891002174](https://www.amazon.co.jp/dp/4891002174/) |
| Windows Internals 4th Edition | 英語 | 4 | XP |[0735619174](https://www.amazon.co.jp/dp/0735619174/)|
| インサイド Windows 第4版 <上> | 日本語 | 4 | XP |[4891004738](https://www.amazon.co.jp/dp/4891004738/)|
| インサイド Windows 第4版 <下> | 日本語 | 4 | XP | [4891004746](https://www.amazon.co.jp/dp/4891004746/)|
| Windows Internals 5th Edition | 英語 | 5 | Vista | [0735625301](https://www.amazon.co.jp/dp/0735625301/)|
| Windows Internals Part 1 6th Edition | 英語 | 6 | 7 |[0735648735](https://www.amazon.co.jp/dp/0735648735/)|
| Windows Internals Part 2 6th Edition | 英語 | 6 | 7 |[0735665877](https://www.amazon.co.jp/dp/0735665877/)|
| [インサイド Windows 第6版 <上>](https://bookplus.nikkei.com/atcl/catalog/12/P94700/) | 日本語 | 6 | 7 |[4822294706](https://www.amazon.co.jp/dp/4822294706/) |
| [インサイド Windows 第6版 <下>](https://bookplus.nikkei.com/atcl/catalog/13/P94710/) | 日本語 | 6 | 7 |[4822294714](https://www.amazon.co.jp/dp/4822294714/) |
| [Windows Internals Part 1 7th Edition](https://www.pearson.com/en-ca/subject-catalog/p/windows-internals-part-1-system-architecture-processes-threads-memory-management-and-more/P200000000583/9780735684188) | 英語 | 7 | 10 |[0735684189](https://www.amazon.co.jp/dp/0735684189/) |
| [Windows Internals Part 2 7th Edition ](https://www.pearson.com/en-ca/subject-catalog/p/windows-internals-part-2/P200000000695/9780135462409) | 英語 | 7 | 10 | [0135462401](https://www.amazon.co.jp/dp/0135462401/) |
| [インサイド Windows 第7版 <上>](https://bookplus.nikkei.com/atcl/catalog/18/P53570/) | 日本語 | 7 | 10 | [4822253570](https://www.amazon.co.jp/dp/4822253570/) |
| [インサイド Windows 第7版 <下>](https://bookplus.nikkei.com/atcl/catalog/22/08/05/00304/) | 日本語 | 7 | 10 | [4296080202](https://www.amazon.co.jp/dp/4296080202/) |

# おわりに

2022/09 に『インサイド Windows 第7版 <下> (日本語版)』が出版されました。

**See also:**

 - [【本の特盛り】インサイドWindows - 仕事と生活と私――ITエンジニアの人生 (blogs.itmedia.co.jp)](https://blogs.itmedia.co.jp/yokoyamat/2021/02/windows.html)
 - [20年の歴史を誇るWindowsのバイブル、最新版がついに刊行 (ビジネス+IT)](https://www.sbbit.jp/article/cont1/94817)
 - [お待たせしました！　ITプロ必携の最新技術書『インサイドWindows 第7版 下』、その注目ポイントを紹介 (@IT)](https://atmarkit.itmedia.co.jp/ait/articles/2208/31/news007.html)
 - [Microsoft がひっそり出版部門を終了 (ITmedia PC USER)](https://www.itmedia.co.jp/pcuser/articles/1607/24/news021.html)
「引き継ぎ」という仕事は無い、かもしれない

QAに限らず、退職や異動などで人の入れ替えが発生したとき、一般的には「引き継ぎ」という業務が発生します。ただ、この「引き継ぎ」という言葉のニュアンスに引きずられて、しなくても良い心配をしてる人が、たまに居るなぁ、と感じています。


チームからAさんが抜ける、となったとき、チームの誰かがAさんの仕事を引き継ぐことになると思います。仮にBさんが引き継ぐとなったとき、よくある事例が、BさんをAさんのコピーにしようとすることです。

Bさんのほうがスキルも経験も豊富であれば、それも上手くいくでしょうが、そうでないときに、チーム内から不安の声が上がってきます。この不安は、多くの場合「BさんにAさんの代わりを務められるかどうか」というところから来ているように見えますが、これは正直、間違った不安だと思います。

本来は、「Aさんが抜けたあとで、どうやってチームとして価値を出すか」をゼロベースで考えるべきであり(どう再構築するかを考える)、「どうすれば、Aさんが居たときと同じ業務フローを保てるか」は必ずしも考える必要はありません。

Aさんが抜けることで、「このままだと、QAとして顧客に価値を提供できない」という不安は感じたなら、それは正しいと思いますが、「このままだと、現状維持できない」という不安は、不安になるべきピントがズレてると感じます。

##たとえばなし
プロスポーツの世界では、野球でもサッカーでもバスケでも、引退・トレード・ドラフトなどで、毎年人の入れ替わりが発生します。では、プロ野球の世界に「引き継ぎ」という概念はあるのでしょうか。

おそらく無いと思います。

代わりに存在するのは、チームのスクラップアンドビルドです。リソースは毎年異なって当たり前なので、「今年はこのリソースで、どう戦おうか」と、都度考えている、と思います。

優勝を目指す年もあるでしょうし、優勝は諦めて育成の年にすることもあるでしょう。
「ファンの期待を裏切らない(=顧客に価値を提供する)」という軸からぶれてはいけないと思いますが、どう戦うか、どこの順位を目指すか、ということは、毎年変わってるはずです。

日本ハムファイターズは、数年前にエースで4番でスーパースターの大谷翔平を失いましたが、その後、第二の大谷を育てているわけでも探しているわけでもなさそうです。大谷が抜けた状態のチームで、どうファンを喜ばせるか、どうすれば勝てるか、をゼロベースで考えているはずです。

***
ということで、今後、人員の入れ替えが発生したときは、「引き継ぎどうしよう」ではなく「どう再構築しよう」と、考えてはいかがでしょうか。

それでは！
MacでCTL+ALT+DELETEを押す方法(VirtualBox)

# はじめに

VirtualBoxにmetasploitable3(win)をインストール中にこの画面が出て大変困りました。

「CTL+OPTION+DELETE」「CTL+fn+OPTION+DELETE」を押しても、動かない。

ということで、調べてみました。

![Screen Shot 2021-12-07 at 15.53.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/15b75a9c-0105-2bd5-3b0e-25d1b1865554.png)


# やり方

ソフトウェアキーボードを幼いと反応しないみたいです。

メニューバーから
input > keyboard > insert CTL+ALT+DELETEをクリックする。

![Screen Shot 2021-12-07 at 15.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/aa5680ff-0ca8-eaa4-e305-45a51be33836.png)


以上
raspiでspotifyを聴く

## 定番のアプリ(raspotify)
raspiでspotifyを聴く時多分検索でヒットするのはraspotifyだと思います．
しかしカメラ触るためにcui版からdesktop版に変えた結果raspotifyではbluetoothのスピーカが使えなくなってしまいました．
オーディオ関係の大型アップデートがあったからみたいなのですがいまいち解決策がわからず，困ってしまったのですが，raspotifyの公式に
>
For desktop versions of Raspberry Pi OS (and/or systems with PulseAudio installed) spotifyd offers similar functionality, much better PulseAudio compatibility and is a better choice.

と書いてあったためspotifydを入れたところうまくいきました．

## 導入手順

https://github.com/Spotifyd/spotifyd/blob/master/docs/src/installation/Raspberry-Pi.md

https://spotifyd.github.io/spotifyd/installation/Raspberry-Pi.html

最新版が欲しい場合はwgetのリンクを書き換える

```zsh 
wget https://github.com/Spotifyd/spotifyd/releases/download/v0.3.2/spotifyd-linux-armhf-default.tar.gz
tar -xf spotifyd-linux-armhf-default.tar.gz 
./spotifyd --no-daemon
```
これで一応できる．

## settings
https://raw.githubusercontent.com/Spotifyd/spotifyd/master/contrib/spotifyd.service
を書き込む

```zsh
mkdir -p ~/.config/systemd/user/
nvim ~/.config/systemd/user/spotifyd.service
systemctl --user daemon-reload
```
次にconfig fileを作成．

```zsh
mkdir ~/.config/spotifyd/
nvim ~/.config/spotifyd/spotifyd.conf
```

(私のやつはこんなです．)

```toml
[global]
username = "spotifyのusername"
password = "spotifyのパスワード"
backend = "alsa"
device = "default" # Given by `aplay -L`
mixer = "PCM"
volume-controller = "alsa" # or alsa_linear, or softvol
#onevent = command_run_on_playback_event
device_name = "hello_spotifyd"
bitrate = 320
cache_path = "/home/pi/.cache/spotifyd"
volume-normalisation = false
normalisation-pregain = -10
```

その後

```zsh
systemctl --user start spotifyd.service
```
で起動．
起動時にも立ち上げたい場合は，

```zsh
sudo loginctl enable-linger pi
systemctl --user enable spotifyd.service
```
開始5分で打ち切り終了？エンジニアが面接で絶対にやってはいけないこと！3選

こんにちは。エンジニアリング マネジャーをしている今野です。
この記事は[リンクアンドモチベーション Advent Calendar 2021](https://qiita.com/advent-calendar/2021/mcs)の10日目の記事です。

## これはなにか

エンジニアにとって、いまや仕事探しの大航海時代ですね！
新たな挑戦のために仕事を探すのは、もはや日常的なことになってきました。
ただ、応募したら受けざるを得ないのが「面接」…正直、私も得意ではありません。

この記事は、面接を受けるのはちょっと苦手…と感じるエンジニアに向けて
**「やってはいけない回答」を個人的な経験から書き記したものです。**

私は ~~受けるのは苦手なのに~~ 面接担当として数百人の面談・面接に同席してきたので
面接官の目線も生かして、なにか少しでも参考になる情報をお伝えできたら嬉しいです。


## 解決したいテーマ

面接の場でお会いすると「技術力はあるけど、もう1つ要素があるといいな…」
「エンジニアではない社長の面接では魅力が伝わらないかも」と感じることがあります。

そんな**「エンジニアとしてスキルがあるのにもったいない！」**を今回の課題としています。
どんな場所であれ、同じエンジニアの仲間が活躍できたらやっぱり嬉しいですしね。


## 原因らしいこと

どうも対話がぎこちない場合、たいてい次のような問題がありそうです。

- 応募者は技術力を中心に判断されると考えている（と同時に会社の技術力を知りたい）
- 一方、対話する相手もやはり人間なので、技術力だけでは判断しきれない

このすれ違いが原因となっていることが多いように思います。
もちろん高い技術力は武器であり価値ですが、開発チームで成果を出すとなると
周囲とうまく情報伝達できるかという点も気になってきます。
やはり技術面の相性だけでは片付かなさそうです。


## 解決への戦略

さて、技術面以外とはなんでしょうか。コミュニケーション？
確かにそうなのですが、どことなく捉えどころがない感じがします。
そこで、下記のような戦略で対話することをオススメしたいです。

**戦略：「技術スキルでキャッチボールして、それ以外でエラーを出さない！」**

そう、抜群にコミュニケーション上手になる必要はありません。
技術力はアピールしつつ、それ以外で大きな失敗をしなければ勝ちというわけです。

以下では、特に代表的かつ致命的な回答例を、3つ記載してみました。
逆に言えばこの3つに適切に回答できれば、だいたいLGTMな印象です。
ポイントは、**目的志向、課題解決、行動力**の3点。さっそく見ていきましょう。


### Err 1. 「目的」を把握していないケース
> *「その開発は何のためにやったんですか？」*
> *→「リファクタしてパフォーマンスを上げました！」*

3人のレンガ積みの話は有名ですが、建築同様、システム開発には目的が欠かせません。
要求を忘れて開発していたら、望まれていないモンスターが生まれるリスクが高いお仕事。
そんなことが起こらぬよう、**ちゃんと目的に立ち返って開発に取り組むことができるか**
を相手に伝えておきたいところです。

さらに構造化するなら、「意義 > 目的 > 行動」の順で整理すると伝わりやすいですね。

> *【回答例】*
> （意義） ユーザー満足度が低い機能を調べてみたらシステムのレスポンスが重くて
> （目的） もっと快適に使えるよう、APIのパフォーマンス向上が必要でした。
> （行動） 実際にはループ処理のリファクタとか、キャッシュ機構を取り入れました。

### Err 2. 「課題解決」になっていないケース
> *「困難なことはなんでしたか？」*
> *→「納期ギリギリで鬼残業したことです！」*

どの企業も熾烈な競争のなかで、やりたいことは山積み。一方の開発リソースは不足がち。
限られた時間やリソースを生かしながら、システムを開発していく必要があります。
そんな中、力押しで乗り切った実績は、主体的に問題解決していないと映る恐れがあります。
**困難に対してどのように工夫したのか** を中心に伝えていきたいところです。

ちなみに、次の2つの合わせ技でお伝えすると、とてもチャーミングだと思います。
① 純粋に技術力を使った課題解決
② チームの協力やプロセスによる課題解決

> *【回答例】*
> リリース日が近くて日々残業するようなギリギリの状態だったんですが…
> 
> （①技術）フルスクラッチで開発しようとしていたライブラリを見直して
> 　評判も良いOSSに少し手を加えて開発することにしてみたんです。
> 
> （②チーム・プロセス）よく見るとチームの各自が同じ開発をするような無駄があって
> 　1日5分ですが朝のスタンドアップを提案してみたんです。


### Err 3. 「行動力」が伴わないケース
> *「勉強している技術はありますか？」*
> *→「〜を勉強しようと思ってます！」*

エンジニアにとって技術研鑽はやはり大事ですが、**わずかでも行動していること**が肝心です。
市場のニーズに応じて、機動的にシステムや組織を変更していくには大切なスキルだと思います。
興味を持ったら、チュートリアルを読むだけでも良いので手を付けたいところ。

なお、最新技術への関心も大事ですが（背伸びするくらいなら）
わずかでも実践的に学んでいる枯れた技術をお伝えするほうが、会話が弾むことと思います。

> *【回答例】*
> 目新しい内容とは言えないかもしれませんが
> Rails 6.0 の新たな機能を一つずつチェックして勉強中でした。


### Err＋α. 気をつけたいこと

回答からは少し外れますが、忘れてはいけないのは **「相手も人間」** ということです。
面接官も本当に5分で心が折れるので、次のような事は避けて温かく接してください(**祈り**)

* リモート面談で正面を見ず、横に向かって話す（けっこう凹みます）
* 対話しているときに、相槌や反応をまったくしない（寂しくなります）
* うつむきがちで表情や言葉をほとんど変えない（不安になります）


## まとめ

エンジニアが対話のなかで魅力を伝えられたら良いなぁ、という気持ちで
「面接でやってはいけない回答＋α」を書き起こしてみました。

ただ、何よりも大事なのは、等身大で対話をすることではないかと思います。
面接というものは、あくまでも相互のマッチングを測る出会いの場なので
一方的に見極めるための場ではない、というのが私の個人的な想いです。
（応募者も企業もどちらにとっても）

ちょっと対話が苦手だな、という方に少しでも得られるものがあれば幸いです！
SSSAPI を利用して、Kuso API をつくった + remix（おまけ） 

この記事は、[クソアプリカレンダー](https://qiita.com/advent-calendar/2021/kuso-app) の7日目の記事です！

# Kuso API　とは
誰でも使える、誰れかが自由にKuso なデータを追加した API です。
どんなデータが入ってくるわからないので、使い所は無いはずなのですが、クソアプリを作成している皆様にとっては、ご利用価値があるかもしれません。

こちらのjson APIが使えます。
https://api.sssapi.app/wAR1fWuTyRyQJxLPzpqQf

そんな未来のクソアプリ・クリエーターのために、クソデータなデータをどうぞ登録してください！

https://kuso-api.vercel.app/


# なぜ　Kuso　API　を使うべきか
remix でこのウェブサイトが作られていようと、APIには全く関係がありませんが、
それこそが、このAPIを使う理由です。

> This is an amazing API because this website is made with remixjs!
I just wanted to create app-based on remix :D

# なぜ　Kuso　API　をつくったか
Google Form + SpreadSheet を API 化できる SSAPI を利用すれば、ユーザーからデータを集めたAPIを作れるんじゃないかなと思ってつくってみました。+ create-remix したかっただけです。

https://sssapi.app/

# SSSAPI
SSSAPI は簡単に使えました。
自動更新というオプションがあるので、これを ON にすることで　Google Form のデータを自動でサイトに反映することができます。

 ![](https://storage.googleapis.com/zenn-user-upload/a5d27cd26df2-20211207.png)

## ちょっと工夫
google form が自動生成するシートのタイムスタンプのラベルが日本語だと「タイムスタンプ」となってしまうので、2行目以下を参照する別シートをつくりました。
別シートをSSSAPIと連携することで、ラベルを自分の好きなデーターにできます。

またタイムスタンプがデフォルトで unixtime になってしまったので、spreadsheet 上の「表示形式 > 数字」で表示を変えてたら、APIにも反映されました。


## SSSAPI アイデア
また今回は使っていないですが、SSSAPIに filter 機能があるので、「承認」などの列を連携させる別シートに作って、GoogleForm のデータを承認・非承認していけば、
ユーザーのデータが自動で反映はなく、承認したデータだけをフィルターしてAPIを使うなどができそうですね。


## remix
こんな感じでローダーで API 取得して SSR できるので楽ちんでした。

```routes/index.ts
export let loader: LoaderFunction = async (): Promise<IndexData> => {
  const res = await fetch("https://api.sssapi.app/wAR1fWuTyRyQJxLPzpqQf");

  const data = {
    items: await res.json(),
  };

  // https://remix.run/api/remix#json
  return data;
};
```

大したことやらなかったので、あまり解説することないです。
 remix 公式の [joke app](https://remix.run/docs/en/v1/tutorials/jokes) のチュートリアル以上のことは何もありません。

レポジトリは公開してあります。
https://github.com/yahsan2/kuso-api

# デザイン
Suffule という Webブラウザ上でテンプレートを組み合わせて、簡単なデザインが作れて、tailwind や bootstrap のHTMLをエクスポートできるサービスを使いました。

> Create tailwind templates in minutes

おしゃれっぽいデザインですが、テンプレのままです。

https://shuffle.dev


# 事前入力したURLを取得

Google Form はGETパラメーターで初期値として値を渡せます。

![capture](https://storage.googleapis.com/zenn-user-upload/dd90a52eb74c-20211207.png)

``` routes/index.tsx
<form action="https://docs.google.com/forms/d/e/1FAIpQLSdz5yYrR6vmUeUC_kUg7OmssOCVfxzsS3__GJ6gdWRrWsiL-w/viewform"
  target="blank"
>
  <div className="relative flex flex-wrap mb-6">
    <input
      className="relative mb-2 md:mb-0 w-full py-4 pl-4 text-sm border rounded"
      name="entry.1359096461"
      type="text"
      placeholder="にゃーん"
    />
    <span className="absolute top-0 left-0 ml-4 -mt-2 px-1 inline-block bg-white text-gray-500 text-xs">
      Title
    </span>
  </div>
```


## 終わりに
GoogleForm と SpreadSheet は何かと汎用性が高いので、何か遊びたいですね。
皆様も良いクソアプリライフを。
【React】フォームの回答欄の数を可変にする

#概要
こんにちは！今日はフォームの回答欄の数を可変にする方法をお伝えします。
具体的にいうと「回答を追加するボタン」を押すと回答欄が増えて、「回答を削除するボタン」を押すと回答欄が減るフォームです！
useStateなどreactの基本的な内容が分かっている人は、簡単に実装できると思います〜

#手順
##1.numOfFormを定義する。
（例）

```typescript
const [numOfForm, setNumOfForm] = useState(1);
```

このようにuseStateを用いて初期値が１のstateを作成します。
これが最初の回答欄の数になります。

##2.inputsを定義する。
（例）

```typescript
const inputs = Array(numOfForm).fill(null);
```

ここに入力されたデータを入れていくことになります。
すなわち最終的にユーザに入力してもらったデータはinputsに入ります！

##3.HTML(JSX)の記述
（例）

```react
return(
...
{Array(numOfForm)
            .fill(null)
            .map((_, i) => (
                    <input
                      key={i}
                      value={inputs[i]}
                      required={true}
                      onChange={(e) => inputs.splice(i, 1, e.target.value)}
                    />
))}
...
)
```

上記のようにして、map関数やfill関数を用いて、記述していきます。
まずnumOfFormの数だけnullが入っている配列を作成します。それにmapを適用してinputをnumOfFormの数だけ作っていきます。

##4.addAnswer,deleteAnswerを定義
（例）

```typescript
const addAnswer = () => {
    setNumOfForm(numOfForm + 1);
  };
  const deleteAnswer = () => {
    if (numOfForm === 1) {
      console.log("これ以上回答は削除できません");
    } else {
      setNumOfForm(numOfForm - 1);
    }
  };
```

このようにしてaddAnsewerではnumOfFormの数を増やし、deleteAnswerではnumOfFormの数を減らします。delteAnswerでは、numOfFormの数が0以下にならないようにif文を記述しています。
##5.フォームを増やすボタンの作成
（例）

```react
return(
...
<Button onClick={addAnswer}>回答を追加</Button>
<Button onClick={deleteAnswer}>回答を削除</Button>
...
)
```

これによりaddAnswerとdeleteAnswer関数が呼び出されるようになります。またnumOfFormはstateで管理しているため、numOfFormの値がsetされるたびに、JSXの再描画が行われます。これによりボタンを押すたびに、ページの見た目がしっかりと変わってくれます。

#余談
今回はフォームの回答欄が可変になるようにしました！
やや、mapやfillを使っているところが複雑ですが、ゆっくり読んでみてください！
自分は複数回答のクイズのフォームに使用しました。
[JavaScript] 配列要素の削除方法

JavaScriptにおける配列要素の削除についてまとめておく。
配列要素の追加については、前回作成した。（[配列要素の追加方法](https://qiita.com/s_ryota/items/831acfd53854922ed263)）
今回もサンプルの配列として、以下を定義しておく。

```javascript
const color = ["red", "white", "blue", "green"]
```

また、今回紹介するメソッドも配列（今回では配列color）そのものの要素を削除し、内容が変更されていまう***破壊的メソッド***であることに注意が必要である。

# 末尾の要素の削除
配列の末尾の要素を削除する場合は、```pop()```を使用する。返り値は、削除された末尾の要素。また、配列の要素数も1減る。

```javascript
const result  = color.pop();
console.log(color);    // [ 'red', 'white', 'blue' ]
console.log(result);    // green
console.log(color.length);    // 3
```

# 先頭の要素の削除
配列の先頭の要素を削除する場合は、```shift()```を使用する。返り値は、削除された先頭の要素。先頭の要素が削除されると、後ろの要素が1つずつ前にずらされ、配列の要素数も1減る。

```javascript
const result  = color.shift();
console.log(color);    //[ 'white', 'blue', 'green' ]
console.log(result);    // red
console.log(color.length);    // 3
```

###指定位置の要素を削除
配列の指定位置の要素を削除したい場合は、```splice()```を使用する。```splice()```の引数は以下となる。
***第一引数***：配列の要素の削除を行う位置（負の数で配列末尾から引いた位置も指定可）
***第二引数***：削除する要素数
返り値は、削除された要素の配列が返される。また、このメソッドも削除後、後ろの要素が1つずつ前にずらされ、要素数も1減る。例として、配列```color```の```"white", "blue"```を削除する場合以下のように書ける。

```javascript
const result  = color.splice(1,2);
console.log(color);    //[ 'red', 'green' ]
console.log(result);    // [ 'white', 'blue' ]
console.log(color.length);    // 2
```
PhpStrom(WebStorm)でgit pullできない(解決済み)

# PhpStrom(WebStorm)でgit pullできない症状と解決

## 症状

PhpStromのバージョンアップで、GitHubへのpull/pushができなくなってしまった。

### 詳細
pullすると "GitHubログイン" or "トークン" を使う選択肢がでる。
"GitHubログイン"を選ぶと連携を承認するページが開き、そこから承認を実行するもページが進まない。
ページが進まないので、PhpStromの処理が進まず、いつまでたってもpullが実行できない。

別のGitアプリを使うとpullできるので、Githubアカウント側に問題はない気がする。

調べた感じ、Githubの自分のアカウントと企業のリポジトリへ連携しているが、それをPhpStrom側に持ってくれなさそう。

## 解決

PhpStromでは、PhpStrom自体のGithub管理機能とバニラなGit機能を使うモードがあるみたい。
今回はGit単体では動いていたので、バニラなGit機能を使うようにする。

### 手順

1.メニューから設定を開く

![2021-12-07_15h31_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90529/cc93493e-0c29-fcc0-da49-61fb6681dea6.png)

2.設定の「Git」から「資格情報ヘルパー」のチェックを入れる

![2021-12-07_15h34_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90529/ad81111a-9775-2901-57b3-5cc74dc19ef1.png)



以上です。
クラウドサービスを持つお客様の関心事

### クラウドサービスを持つお客様の関心事
WEBサービスを開発・運用しているお客様との打ち合わせで、お客様がよく気にしているところ。
お客様から●●はどうなっていますか？と質問されるところ。
設計時て、自分の作業を明確にするのはもちろんなんだけど、
その設計でお客様の合意を得るには、お客様の質問に答えないとうまくいかない。
1年ほどお客様の打ち合わせに帯同して発見したことを纏めておく。
今まではプライベートクラウドの小規模サービスが多く(というかそもそも専門外だったし)、大規模なクラウドサービスはあまり経験が無かったため、お客様の関心事はとても興味深く勉強になると思った。

#### 1. 復旧できるか
* データ復旧してサービスの再起動したとき、復旧前に確定した情報を上書きしないか  
復旧というのは全てのデータを投入するわけではないようだ…。
* データをどうやったら復旧できるか。  
aurolaの●●テーブルを入れてdynamoの●●テーブルを××にして〰、  
環境変数▲を×してなど、具体的であればあるほどいいようだ。SQL文も要求されることもある。

#### 2. 安全に改修できるか
* 改修前と後で何が変わるのか。
* 改修前にできていたことができなくなったりしないか

#### 3. 運用しやすいか
* どこで障害が起きているか保守員が判別できるか？
* どこで判別できるか？どのデータを見ればよいか。

#### 4. 性能
* サービスが落ちたりしないか。

#### その他、お客様とお付き合いしたときの所感
* お客様は、すごい機能やソフトを入れたいわけではなくて、  
今動いているサービスを安全に更新することを重要視しているところがある
* 設計考慮漏れで起きる不具合は駄目なんだけど、  
次に対策ができること、データの復旧ができるなら、まあ良しとみてくれるようだ…
【SwiftUI】Viewの境界線を描くには

## [Q] SwiftUIでViewの境界線を描くには？

## [A] border を使います

```swift
  Text(“Hello, world!”)
    .border(Color.gray, width: 2)
```

以下は SwiftPlayground で実行できる簡単なサンプルです。

```swift
import SwiftUI
import PlaygroundSupport

struct Preview: View {
  var body: some View {
    Text(“Hello, world!”)
      .border(Color.gray, width: 2) // この行がポイント
  }
}

PlaygroundPage.current.setLiveView(Preview())
```

### 動作確認環境

2021/12/07 に確認しました。

- iPad Pro
- iPad OS 15.1
- Playgrounds 3.4.1(1302.34)

### 参考

- Apple Developer Documentation
  - [border](https://developer.apple.com/documentation/swiftui/view/border(_:width:))
BBS+ Signature Scheme理解メモ (1) - 署名・検証アルゴリズム

DID・VC界隈で最近話題のBBS+ Signature Schemeについて理解を深めるためのメモです。
BBS+について全部解説しようとすると1記事には収まらないため、複数回に分けて書くことにしました。
第1回はBBS+の概要、及び署名アルゴリズムの詳細について解説します。

## 概要
https://mattrglobal.github.io/bbs-signatures-spec/

BBS+ Signature Schemeはマルチメッセージに特化した署名スキームで、その最大の特徴は**ZKPによるメッセージの選択的開示のサポート**です。その性質から、検証可能クレデンシャル(VC)の署名形式として有用ではないかと注目を集めています。

### 選択的開示 (selective disclosure)
通常の署名形式では、署名はメッセージ全体に対して作成されます。検証者は、メッセージ全体を知らなければ、署名が正しいことを検証できません。

これに対し、*メッセージの一部だけを開示し、それが正しく署名されたメッセージの部分集合であることを証明する*ことを、メッセージの**選択的開示**と呼びます。BBS+の選択的開示アルゴリズムでは、検証者はメッセージ全てを知ることも、署名の値そのものを知ることもありません。その代わりに、検証者は対応するゼロ知識証明(ZKP)を検証することで、開示されたメッセージの正しさを判断することができます。

例として、学生証と学割キャンペーンの関係を考えてみましょう。

1. 大学は学生に対し、毎年デジタルな学生証を発行する。それは大学によってデジタルな署名がなされている。
1. 学割キャンペーンはサービスのユーザーに対し、特定の大学の学生であることの証明を要求する。
1. ユーザーは学割を適用してほしいが、必要以上の個人情報をサービスに渡したくはない。

この場合、学生証をそのままサービスに提示してしまうのが従来の署名検証の方法、一部の情報だけをサービスに提示し、それが学生証に由来することを証明するのが選択的開示、ということになります。


## 署名アルゴリズム
選択的開示のアルゴリズムの前に、今回はまずBBS+の署名がどのように生成されるのかをざっくり解説します。この署名生成アルゴリズムが選択的開示のZKPでどのように効いてくるのかについては次回以降に回したいと思います。

### 鍵生成
ある有限体上の楕円曲線の群構造$G_1$, $G_2$について、その位数が$r$であるとします。
また、$P_1$, $P_2$はそれぞれ$G_1$, $G_2$の生成元であるとします。

* 秘密鍵 $SK$ は $0 < SK < r$ であるようなランダムな整数です。
* 公開鍵 $w \in G_2$ を、$w = SK * P_2$ で定義します。

これに加えて、メッセージの個数が$L$であるとき、$L+1$個の$G_1$の元$h_i (i = 0, 1, ..., L)$を$w$から生成します。これらも公開鍵と呼びます。

* $h_i$は$w, i$から決定的に計算するため、$w$をshort form public keyと呼びます。
* $h_i$の具体的な計算にはhashを用いますが、本質ではないため詳細は省きます。$w$から有限個の$G_1$の元が生成できるという点が重要です。

### 署名の生成
L個のメッセージ$msg_1, msg_2, ..., msg_L$と鍵$SK, w, h_0, h_1, ..., h_L$から、次のように署名を生成します。

1. $0 < e, s < r$ を満たすランダムな整数 $e, s$ を定める。
1. $b = P_1 + h_0 * s + h_1 * msg_1 + ... + h_L * msg_L$ を計算する。
1. $A = b * (1 / (SK + e))$ を計算する。
1. $(A, e, s)$ の三組を署名とする。

乱数$s, e$はそれぞれソルトのように働きます。$b$はメッセージ・公開鍵・ソルトから計算できるダイジェスト値です。

### 署名の検証
署名を検証するためには、更に次の道具が必要です。

* 非退化双線型写像$E : G_1 \times G_2 \to GT$。$GT$は位数rの乗法群とする。

検証アルゴリズムは次のようになります。

1. 署名$(A, e, s)$、メッセージ$msg_1, ..., msg_L$、公開鍵$w, h_0, ..., h_L$ を入力とする。
1. $b = P_1 + h_0 * s + h_1 * msg_1 + ... + h_L * msg_L$ を計算する。
1. $C1 = E(A, w + P_2 * e)$とする。
1. $C2 = E(b, P_2)$とする。
1. $C1 = C2$であれば検証成功、そうでなければ検証失敗とする。

写像$E$の双線型性より、$A$が正しく生成されていれば $C_1 = E(A, w + P_2 * e) = E(b * (1 / (SK + e)), P_2 * (SK + e)) = E(b, P_2) = C2$ となるので、この検証過程が正しいことがわかります。

## 次回予告：ZKPによるメッセージの選択的開示
今回解説した署名の値$(A, e, s)$を直接検証するには、元の全メッセージを知っている必要があります。
学生証の例で言えば、学生証の保持者は自分の学生証の真贋を上記のアルゴリズムで検証することはできますが、選択的開示にはまた別のアルゴリズムが必要になります。

次回はこの選択的開示がゼロ知識証明(ZKP)でできること、その証明の構築には署名の値・全メッセージ・署名者の公開鍵さえ知っていれば良いことを示し、アルゴリズムの詳細を解説したいと思います。
翻訳QAでのテスト自動化の取り組み

# この記事について
本項目は翻訳QAにおけるテスト自動化について弊社で取り組んだ事例を紹介します。
海外配信を行っているアプリの品質管理担当者の参考になれば幸いです。
内容としてはGREE Tech Conference 2021で発表したものと同様ですので下記リンクもご参照ください。
[動画リンク（youtubeに飛びます）](https://www.youtube.com/watch?v=S-fzb97kUNY)

# 翻訳QAとは
弊社では誤表記や誤翻訳などにより、アプリをご利用いただいている海外のお客様に混乱をきたさないことを目的として**翻訳内容が正しいことを確認する翻訳QA**を実施しています。
対象としているアプリは海外で配信されている全タイトルで**主に3点の確認観点**で実施しています。

 - 該当の言語で表示されること
 - 内容の意味合いが間違っていないこと
 - 元の言語の表記が残っていないこと

上記は最低限の観点でありさらに深く確認する場合は「ネイティブから見て違和感のない表現になっていること」などのいわゆる**ローカライズ観点**が加わります。

# 自動化に取り組んでいる背景
翻訳QAで自動化に取り組んだ背景として、現行の翻訳QAフローの抱える課題が挙げられます。

現在の翻訳QAでは**作業者の目視**により確認行っており、作業者自身の経験や能力に依存する体制となっています。
現状はQA経験の長いメンバーをアサインしているため、品質リスクが高い状況ではないですが、先々の安定した運用を想定するといずれ直面する課題でした。

この課題に加えて、目視での作業であるがゆえに**作業者自身の工数を過大に必要としてしまう**点も課題として存在しています。
本来であれば別の業務に更なる工数をかけたいのですが、現状だと一定の工数をテスト実施業務にあてる必要があるため、テスト工数の削減は急務でした。

そこで、翻訳QA業務にテスト自動化を導入することにより、品質面の安定化および必要な工数の最小化を画策しました。

# 翻訳QAでのテスト自動化
#### 自動化の着眼点
今回は**フォーマット**に着目して自動化を推進しました。

弊社における翻訳業務フローは下記のようになっており、完全に一から文章を作成するケースもありますが、お知らせの文章をはじめとして、担当者は文章を作成する際に過去の同フォーマットの文章をベースとして作成することがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321384/fedbde36-bbbd-0def-9b0a-03a6b630d4bb.png)


現在の翻訳QAでは文章全てを目視で確認していますが、過去フォーマットから作成するということは変更を加えていない箇所があるということです。
そこで過去のフォーマットを用いて、検証対象の文章との差分を自動で抽出するシステムを構築しました。

#### 自動化システムの実装
翻訳QAで実装した自動化システムには2つの要素があります。

1.フォーマットの識別
弊社では翻訳時に用いられるフォーマットが同じ画面においても複数存在しました。
そこで**どのフォーマットと照合すべきか**を決定するために、検証対象とする文章に該当するフォーマットを識別するシステムを構築しました。

2.変更箇所の抽出&比較
照合するフォーマットを識別した後に**そのフォーマット内でどの部分を変更しているか**を抽出します。
そして抽出された変更箇所を自動で突き合わせるシステムを構築しました。
このような工程を踏むことで変更された箇所のテストが自動化できると同時に、**変更されていない箇所のテストが不要**となりテストの効率化につながります。

これらの要素を用いて翻訳QAのテスト自動化システムを実装しました。


# 自動化の効果と今後の展望
#### 自動化による効果
上記の自動化を実際の業務へ導入することで、変更のない箇所の確認工数が大幅に削減し、加えてデータベースとの照合が容易になったことで**一部の翻訳QA業務の工数を50%削減**することに成功できています。
また目視ではなくなったため、導入前の状態である「全ての文章を目視で確認」という方法より品質リスクが明らかに下がっており、実際に大きな障害も発生しておりません。

#### 今後の展望
今後の展望として**他の検証における自動化の導入**が挙げられます。
今回の取り組みはお知らせ関連など、一部の業務のみへの適用でとどまっているため、他の箇所の翻訳QAでも適用できないかは検討していく予定です。

加えて**別の観点からの自動化の検討**も展望として挙げられます。
今回は同一フォーマットを利用しているという観点からのテスト自動化を推進しましたが、実施時の作業方法に着目した自動化なども検討していきたいと考えております。
WPF で Aero Snap を無効化

#概要
AeroSnap をどうしても消したかったの！😣
ちょっといじくったら Windows Forms でも使えそう？

#こんな感じ (適当に変えてね)
``` xml:MainWindow.xaml
<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" 
        WindowStyle="None">
    <WindowChrome.WindowChrome>
        <WindowChrome CaptionHeight="0" ResizeBorderThickness="0"/>
    </WindowChrome.WindowChrome>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="45"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button x:Name="CloseButton" Background="Transparent" Content="&#xE8BB;" 
                FontFamily="Segoe MDL2 Assets" FontSize="8.5" 
                BorderThickness="0" RenderOptions.EdgeMode="Aliased"
                Grid.Column = "1"/>
        <Grid Grid.Row="1" Grid.ColumnSpan="2"/>
        <Canvas x:Name="DragHandle" Background="Transparent"/>
    </Grid>
</Window>
```

``` cs:MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace WpfApp2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int GWL_STYLE           = -16;
        int WS_OVERLAPPEDWINDOW = 0;
        int WS_THICKFRAME       = 0x00040000;

        [DllImport("user32")]
        private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwLong);

        public MainWindow()
        {
            InitializeComponent();
            
            this.CloseButton.Click                      
                += CloseButton_Click;                       //ウィンドウ閉じるボタン

            this.DragHandle.PreviewMouseLeftButtonDown  
                += DragHandle_PreviewMouseLeftButtonDown;   //ドラッグ移動

            
            this.Loaded += MainWindow_Loaded; //ウィンドウがロードされたら
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
            => SetWindowLong(
                    new WindowInteropHelper(this).Handle,
                    GWL_STYLE,
                    WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME);

        private void CloseButton_Click(object sender, RoutedEventArgs e)
            => this.Close();

        private void DragHandle_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            => this.DragMove();

    }
}

```

#試せ
``` cs:MainWindow.xaml.cs
this.Loaded += MainWindow_Loaded; //ウィンドウがロードされたら
```

(多分)32行目の、上のやつコメントアウトしたりしなかったりして違いを確かめよう！

ウィンドウをドラッグで移動させてマウスカーソルが画面端でごっつんこしなかったら成功！

(コピペしてもうまく動かなかったらごめんなさい僕は動いたんです😥)
【LeetCode】アルゴリズム体操 1920. Build Array from Permutation

# <a href="https://leetcode.com/problems/build-array-from-permutation/">LeetCode - Build Array from Permutation</a>

#### 問題文
> Given a zero-based permutation nums (0-indexed), build an array ans of the same length where ans[i] = nums[nums[i]] for each 0 <= i < nums.length and return it.

> A zero-based permutation nums is an array of distinct integers from 0 to nums.length - 1 (inclusive).


#### だいたいの日本語訳
引数：`int[] nums`
戻り値：int型の配列

与えられた配列（nums）と同じ要素数の配列（ans）を返してほしいんだけど、`ans[i] = nums[nums[i]]`みたいなかんじでお願い。
numsは0から配列の要素数-1までの数値がシャッフルされたものやで。

## この問題は簡単すぎた
```java:Solution.java
class Solution {
    public int[] buildArray(int[] nums) {
        int[] ans = new int[nums.length];
        
        for (int i = 0; i < nums.length; i++) {
            ans[i] = nums[nums[i]];
        }
        
        return ans;
    }
}
```

## 実行結果

|Title             |RunTime |Memory   |
|------------------|--------|---------|
|この問題は簡単すぎた|1ms     |40MB     |

## ひとこと
己の心がやられないようにEasyから取り組んでますが、さすがに簡単すぎました。
Ubuntu に gh コマンド (GitHub CLI) をインストールする

GitHub CLI である gh コマンドをインストールする手順です。

https://cli.github.com/

## gh コマンドのインストール

[公式のインストール手順](https://github.com/cli/cli/blob/trunk/docs/install_linux.md)を参考にインストールします。

```bash
type -p curl >/dev/null || sudo apt install curl -y
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
```

gh を起動してみます。

```
❯ gh --version
gh version 2.17.0 (2022-10-04)
https://github.com/cli/cli/releases/tag/v2.17.0

```

## gh コマンドの使い方

gh コマンドの簡単な使い方をご紹介します。

まずは、 login の認証を行います。

```bash
❯ gh auth login
```

リポジトリをクローンする。

```bash
❯ gh repo clone cli/cli
```

### gh コマンド を補完する (completion)

サブコマンドの補完が利いて便利です。
bash の場合、下記を .bashrc に追記すればOKです。
(zsh, fish, PowerShell にも対応してます）

```
eval "$(gh completion -s bash)"
```
```gh <Tab><Tab>``` にてサブコマンドが表示されます。

```
❯ gh
alias       (Create command shortcuts)
api         (Make an authenticated GitHub API request)
auth        (Authenticate gh and git with GitHub)
browse      (Open the repository in the browser)
co          (Alias for pr checkout)
codespace   (Connect to and manage codespaces)
completion  (Generate shell completion scripts)
config      (Manage configuration for gh)
extension   (Manage gh extensions)
gist        (Manage gists)
gpg-key     (Manage GPG keys)
help        (Help about any command)
issue       (Manage issues)
label       (Manage labels)
pr          (Manage pull requests)
release     (Manage releases)
repo        (Manage repositories)
run         (View details about workflow runs)
search      (Search for repositories, issues, and pull requests)
secret      (Manage GitHub secrets)
ssh-key     (Manage SSH keys)
status      (Print information about relevant issues, pull requests, and notifications acr…)
workflow    (View details about GitHub Actions workflows)

```

## 参考
* https://github.com/cli/cli
* https://cli.github.com/manual/
* https://cli.github.com/manual/gh_completion
M5Stackを使ったBLEスキャナーを作る

# はじめに
この記事は[TDU CPSLab Advent Calendar 2021](https://adventar.org/calendars/6489)の5日目の記事です。
大遅刻してしまいました。ごめんなさい。orz


# なにやるの？
M5Stack(esp32)でBLEを使ってRSSI取りたいと思います。
esp32でBluetoothを使う時には一般的には[ESP32_BLE_Arduino](https://github.com/nkolban/ESP32_BLE_Arduino)を使います。
このソースを読むのはとても勉強になるのでお勧めです。

# どうしてやるの？
研究でBLEを使った接近判定をしてみたかったので・・・・

# ソースコード
名前をもつBLEデバイスが周囲に存在しているときにシリアルでRSSIを出すソースがこちらになります。


```cpp:main.cpp
#include <M5Stack.h>
#include <BLEDevice.h>

BLEScan* pBLEScan;

class testAdvertisedCallBacks: public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice){
    int rssi = advertisedDevice.getRSSI();
    if(advertisedDevice.haveName()){
      Serial.println("Show DeviceName");
      Serial.println(advertisedDevice.getName().c_str());
      Serial.println(rssi);
      Serial.println();
    }
  };
};

void setup() {
  M5.begin();
  M5.Lcd.setTextSize(3);
  M5.Lcd.println("GW");
  BLEDevice::init("M5Stack-GW");
  pBLEScan = BLEDevice::getScan(); //scan object 
  pBLEScan->setAdvertisedDeviceCallbacks(new testAdvertisedCallBacks());
  pBLEScan->setActiveScan(true);
}

void loop() {
  BLEScanResults foundDevices = pBLEScan->start(10,false);
  Serial.println("Devices Founded!");
  Serial.println(foundDevices.getCount());
  Serial.println("scan done!");
  delay(2000);
}
```

# ビーコンについて
BLEビーコンについては[こちらのサンプル](https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/examples/BLE_server/BLE_server.ino)を使わせていただきます・・・
デバイス名が"Long name works now"になります
# 動作結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238493/f0f6f44a-5b1f-b454-63d8-495861099405.png)



# おわりに
まーじで記事を書く余裕がない・・・　
あんまりM5を使ったBLEの記事は少なかったので書いてみました! よければ参考にしてみてください
git diff -I<regex> --ignore-matching-lines=<regex>

# gitバージョン確認

git 2.30か2.31あたりで実装されたオプションのようです。

# なんぞこれ？

diff の -I, --ignore-matchin-lines=<regex> と同様らしいです。
たとえばgitのソース(私が持ってきたのは以下のミラーです)で、

https://github.com/git/git

こちらには、git diffじゃなくて、diffのサンプルとして、htmlドキュメントインストール用にこんなスクリプトがあります。
(Documentation/install-webdoc.sh 抜粋)

``` sh:
T="$1"

for h in \
	*.txt *.html \
	howto/*.txt howto/*.html \
	technical/*.txt technical/*.html \
	RelNotes/*.txt *.css
do
	if test ! -f "$h"
	then
		: did not match
	elif test -f "$T/$h" &&
		$DIFF -u -I'^Last updated ' "$T/$h" "$h"
	then
		:; # up to date
	else
		echo >&2 "# install $h $T/$h"
		rm -f "$T/$h"
		mkdir -p $(dirname "$T/$h")
		cp "$h" "$T/$h"
	fi
done
```
ターゲットフォルダ($T)と手元のファイルを比較して、違いがあれば
コピーしますが、しかし、

``` sh:
$DIFF -u -I'^Last updated ' "$T/$h" "$h"
```

にあるように違いが '^Last updated ' の辺りだけであれば、変更なしとしてコピーはしないというものです。

この場合、実際に違うのは '^Last updated ' の次の行の日付の部分なのですが、diffの -I の場合はぢつはハンク単位でのマッチングということでこの記述でOKらしいです。diffの場合は。大事なので2度言っておきます。

参考にさせてもらったのはこちら

https://qiita.com/dalance/items/d9ff4142fd49d15269a9

# 使ってみた

さて、 `git diff -I` ( `git diff --ignore-matching-lines` ) の場合ですけども、ぱっと思いつくのは、

git statusで「Changes not staged for commit」なファイルのうち、上記のような更新日付だけしか違わないようなファイル(ここではhtmlファイル)は git restore (git checkout) しちゃいたい。

上記diffで手元のhtmlと、インストール先のhtmlでやったことを、
カレントディレクトリとそのサブフォルダに対して、
作業ツリーのhtmlとHEADの対応するhtmlとの間で行います。

```sh:restore-htmls.sh
#!/bin/sh
git ls-files -m | while read line; do
    if test -e ${line} &&
	    git diff --quiet -I"^ [12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9] [012][0-9]:[0-5][0-9]:[0-5][0-9] JST" -- ${line} &&
	    ! git diff --quiet -- ${line}
    then
	git restore -- ${line}
    fi
done
```

`git ls-files -m` は「Changes not staged for commit」なファイルのリストを得ます。この場合は現在のディレクトリとそのサブディレクトリの中全部から探してきてリストします。この時点ではhtml以外のファイルもリストされています。

`! git diff --quiet -- ${line}` 普通にdiff取って違いがあるかどうか一応確認しています。

`git diff --quiet -I"^ [12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9] [012][0-9]:[0-5][0-9]:[0-5][0-9] JST" -- ${line}` 指定の正規表現の行だけ無視すれば違いが無い(この行以外に違いが無い)のであれば、そのファイルは編集前の状態に戻しちゃって構わないので `git restore -- ${line}` します。

git diffのオプションで差分アルゴリズム等をチューニングすればdiffと同様の記述でいけるのかもしれませんが、手元で試した時はdiffと同じファイルを扱っていても、git diff -Iの場合はこのようにマッチする行を厳密に指定する必要がありました。

# -I --ignore-matching-lines の効果
正規表現に合致した行は違いと見なさない訳ですが、当該部分の差分出力自体が無くなる訳ではなくて、当該部分の差分出力は依然として行われます。単に exitcodeにカウントされるかしないかだけです。ここでは差分出力そのものは不要なので --quiet を指定しています。

# --quiet

今回は差分出力そのものは必要ないので --quiet を指定します。 --quiet を指定すると --exit-code を指定したのと同じ効果もあります。

もし、 --quiet を外すのなら、必ず --exit-code を記述してください。そうしないと、git diffは差分ありなしではなく、gitコマンドの実行の成否(そしてそれはほとんどの場合、成功==0)を返してきます。しばらくハマっておりました。
saas-resources-loaderで各scssにグローバル変数を読み込ませる

# 対象者

webpack、sass-loaderを使っている人。
色んな場所のscssにグローバル変数やmixinを導入したいけどいちいちimportするのが面倒な人。
**特に、vueの単一ファイルコンポーネント全部のstyleにグローバル変数を効かせたい人。**

#インストールされているもののバージョン 

私がやったのはこのバージョンだったよ、というだけなので注意。

**・webpack^5.65.0**
・webpack-cli^4.9.1
・style-loader^3.3.1
・css-loader^6.5.1
**・sass-loader^12.3.0**
**・sass-resources-loader^2.2.4**
・その他vue-loaderとかts-loaderとか

太字がこの記事の本質部分。
sass-resources-loaderを使うと、sass, scssをコンパイルするときに`options.resources`で指定したファイルを読み込んでくれるらしい。

[本家のgithub](https://github.com/shakacode/sass-resources-loader)には

>Supports Webpack 4

書かれていたが、webpack5でもいけたよということを報告したいがためにこの記事を書いた。

# コード

``` webpack.config.js
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
  mode: 'development',
  devtool: 'inline-source-map',
  entry: './src/js/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist/js'),
　　publicPath: ''
  },
  module: {
    rules: [
      /*
        vueとかtsとかcssとかの情報がこの辺に入る
      */
      {
        test: /\.scss/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader',
          {
            loader: 'sass-resources-loader',
            options: {
              resources: [
                path.resolve(__dirname, 'src/style/global.scss')
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
  ]
};
```

#ファイル構成

```
root/
  ┣ index.html
  ┣ dist/js/bundle.js
  ┣ src/
      ┠ js
          ├ index.ts
          └ その他jsとかtsとかvueとかのファイル
      ┗ style
          ├ global.scss
          └ style.scss
  ┣ webpack.config.js
  ┣ package.json
  ┣ package-lock.json
  ┗ node_modules/
```

#備考
`test: /\scss/`の欄にsaas-resources-loaderのことを書いておけば.vueファイルの中のscssにも適用してくれるので、`test: /\vue/`のところに重ねて書く必要はない。

#参考ページ
[webpack/sass-loaderでimport毎に共通ファイルを読み込ませる](https://qiita.com/8845musign/items/409f8f6f42947885c657)
本当はこんな風にsaas-loaderのoptions.dataで追記させたかったけど、上手くいかなかった。

[shakacode/sass-resources-loader - GitHub](https://github.com/shakacode/sass-resources-loader)
本家のGitHubページ。

[Vueで共通のSCSS(SASS)をwebpack(3系と4系)で読み込む方法](https://www.mk-engineer.com/posts/vue-sass-global)
webpack3, 4で試しているページ。5でもいけた。
GECのタスク説明

文法誤り訂正（Grrammtical Error Correction: GEC）は専門外だったので特段何も気にしてなかったけれど。学生の原稿チェックしてたら、

> 文法誤り訂正とは、学習者が書いた文に含まれる誤りを訂正するタスクである。

という１文で始まる原稿ばかりで、「いやちょっと待て:raised_hand:」ってなったので。
とりあえず、

- そもそもそれ、やってること本当に「文法」誤り訂正なの？？？　なんかもう「文法」の枠超えていない？？？
- なんでこんなド最初の分野解説から「入力は『文』」って言い切るの？？？

と、ツッコミ入れたら、研究会中にいい議論できたのでメモ。

先に結論を書いておくと、上の１文は ↓ を圧縮した表現だと判明。

> 自然言語処理の分野において、文法誤り訂正は一般的に、計算機が非母語話者が書いた文を入力として受け取り、その文に含まれる文法誤りを訂正し、出力するタスクとみなされている。何を文法誤りとするかは分野や立場により一貫しないため、自然言語処理の分野では基本的に、コーパスのアノテーションの定義に従う。また文単位の処理であるのは、アノテーションされた文法誤りを計算機が自動訂正する上で、文内の情報を超えて文外の情報を参照しないといけない状況がほとんど存在しないためである。

この定義 ↑ を、圧縮して１文で書いたのが最初に示したもの。

うん。たしかにそうなる。そうなるけど。めっちゃ内輪ネタじゃん......
「形態素解析とは、文を単語に分割して品詞を付与するタスクである」を国際会議に持っていけないくらい内輪ネタじゃん......

でまあ、横でサーベイしてるのを見てたから、↓ 読み直しに行ったら、

https://www.ai-gakkai.or.jp/resource/my-bookmark/my-bookmark_vol33-no6/

> あらためて説明する必要はないかもしれないが、念のため最初に文法誤り訂正のタスクについて説明しておく。
> 一般的な文法誤り訂正では、非母語話者が書く文を入力として受け取り、その文に含まれる誤りを訂正した文を出力する。

って、こっちでもド最初に書いてあるし。なんなら引用元 ↓ のp.60あたりの定義読みにいっても、

http://www.coronasha.co.jp/np/isbn/9784339027617/

こっちでも文法誤り訂正の入力は「文」って~~言い切ってるし。~~[^1]
[^1]: p.60 周りしか見ていなかったが、ここで言及されているのは「訳文を対象とした文法誤り訂正」なので、入力は文単位。ただし「言語処理における文法誤り訂正」は、訳文を対象とする場合と、自由記述文章を対象とする場合の２種類に大別できるとあり、後者は入力を文書単位に設定しているため「言い切って」はいない。（2021/12/08 訂正） 
（え？　マジでそんな局所的にタスク定義しちゃうの？？？）
ってなるワリに、「文法誤り」が何から何までの範囲を指すのか、その明確な定義もないし......

で、こういう時はなるべく原点回帰の気持ちで、いそいそ田中本を取り出すのだけど。

https://www.coronasha.co.jp/np/isbn/9784885521607/

ここでは７章「文書処理」に登場しているので、入力は文ではないし。誤りもtypoのような入力誤り（slip）と、母語などの書き手の知識に起因する認知誤り（mistake）があって。認知誤りの下に、語形成、文法、運用、実世界との対応 があるので、少なくとも90年代は最初に出した1文のような認識ではなかったことが判明。
個人的に「文法」って言われたら統語論とか生成文法とか、そこら辺のイメージで、田中本と一致。

で、頭抱えて今度は言語処理学事典のp.622「文法性（Grammticality）」読みにいく。

https://www.kyoritsu-pub.co.jp/bookdetail/9784320122383

ここでやっと納得できたのは、Grammatical かどうかって、非文かどうか（文法の本とか読んでて「＊」や「？」が頭に付くやつ）の判断だと判明。
なら、英語でGrammatical Error Correctionで定着してるのも納得。
要は読んだときに自分が首かしげるかどうかなので。
英語ネイティブからしたら、Grammatical Errorとして扱ってる範囲、結構裾野広くてもいい、と。
またここでも文法性は、音韻論、形態論、統語論、意味論の4分野で解説されていて。統語的文法性は狭義であるとも解説されてて納得。

で、ここら辺の背景持って議論した末、やっと最初に上げていた1文、実はその下に書いた長い説明をギュッと圧縮したものだとコンセンサス取れて、マジかよ......となった次第。

GEC分野にいたらなんとなくわかってるんだろうけど。客観から見たら、いやいやいや、君たちなんでこぞってこの文から書き出してるの！？　ってなるんだけど。
原稿に書ける量も限られてるし......藪蛇チックなほぼ裏話だし......
しょうがない、と片すこともできるけど。
お願いだから、誰でもいいから、ジャーナルか書籍で、このお気持ちちゃんと書いて引用されるようになってくださいの思いで、初めてQiita記事書いてみた。

あと、意味わからずの丸のみコピペ、やめて。
自分が何やってるのかくらい、ちゃんと批判的に見て、疑問に思ったら調べて。最近の原稿読んでも書いてないからって、そこでそういうものなんだっていう丸のみ思考放棄はしないでほしい。
「自分をマネージャーとして一番成長させてくれたのは育児だった」

育休中に一気読みしてしまった本。

https://www.amazon.co.jp/%E7%94%B3%E3%81%97%E8%A8%B3%E3%81%AA%E3%81%84%E3%80%81%E5%BE%A1%E7%A4%BE%E3%82%92%E3%81%A4%E3%81%B6%E3%81%97%E3%81%9F%E3%81%AE%E3%81%AF%E7%A7%81%E3%81%A7%E3%81%99%E3%80%82-%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%BB%E3%83%95%E3%82%A7%E3%83%A9%E3%83%B3/dp/4479794336/ref=asc_df_4479794336/?tag=jpgo-22&linkCode=df0&hvadid=295641556548&hvpos=&hvnetw=g&hvrand=7847974672282305723&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009129&hvtargid=pla-523953887893&psc=1

業績評価の現実とか、インセンティブの考え方に違和感を感じている人は読んだら共感できる部分があるかもしれません。

何より、一番印象に残った一文は、

<FONT COLOR=red><B>「自分をマネージャーとして一番成長させてくれたのは育児だった」</B></FONT>

マネージャーとしてはどうかは分かりませんが、
確かに仕事を進める上で、育児により変わった点はあります。


###タスクは分解⇒作業化

子の発熱などで突発的に仕事ができなくなる事はやはりありました。
数時間後の自分が当たり前に業務できる、ということが非現実的になったのです。

ただ、皆忙しいので、人のタスクをマルっと引き取る余裕はありません。

その結果、前倒しで業務を進める癖がついたのと同時に、
自分で不要に仕事をため込むのをやめました。
自分のチームメンバーにタスクを分解して作業化して渡すようにしたことで、
私がいないことががボトルネックにならないようにしたのです。

###日中が勝負
顧客や営業との打ち合わせは100%日中に設定されるので、
なかなか長時間集中して手を動かすことができません。

そのため、出産前はよく「定時後にじっくりやろう」カードを使っていました。

皆が帰った20時以降が勝負、とまで思っていました。

今は残業できないが故、忙しい日中でも最大限の成果を出すしかありません。
腹が決まれば、忙しい日中は集中できな～い、という考えは消え去りました。

###リスクヘッジは念入りに
なぜなら、退勤後にトラブルが起きないようにするためです。
トラブルは大体夕方に起きるのですが、17時～18時半は育児の黄金タイムです。

**鬼のように忙しいです。**

幼児2人をみながら、スマホのTeamsやSlack上で対応するには限界があります。

そのため、トラブルの元となる、
**ミスコミュニケーション、記述の曖昧さ、バッファのなさ**
これを徹底的に排除するようにしました。

###さいごに
1歳と3歳のママですが、子供は本当にかわいいです。
でもテストエンジニアとしてのキャリアもあきらめたくありません。
両方バランスをとって、自分が後悔しない生き方をしたいなと思います。
Flask入門②～htmlの扱い～

##はじめに
前回の続きで、今回はhtmlを扱います。
(どこまでできるかな)

https://qiita.com/dem_kk/private/54cee6c7038c9a735c3b

##環境
* windows10
* flask2.0.2
* python3.8.10

##コード内でのhtml設定
###文字の大きさ変更
```python:flask1.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return '<h1>Hello world</h1>' #メインタイトル

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/68328c95-a9cf-bd58-3ff3-f89b1aca09d9.png)
h1タグで設定したことで、文字が大きく表示されました。h3にすると小さくなったのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/dc00f1de-bbf7-053b-809e-d9e839ea0d18.png)

###装飾
色を変更してみた。

```python:flask2.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask

app = Flask(__name__)

#色を指定
@app.route('/')
def index():
    return '<h1><font color="darkgreen">Python</font><br></h1>'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/82ab1718-1025-097d-e539-cd02de841b25.png)

なんとなくpythonっぽい色(?)になりました。

##htmlファイルの読み込み
pyファイルにhtmlタグを書き込むのはカスタマイズ性に欠けるので、htmlファイルから読み込む練習をしました。
下記のようなファイル階層にしています(templatesはこの名前にしないとエラーが発生する)。

```html
directory/
|__flask3.py
|__templates/
      |__index.html
```
###htmlファイル
今回の練習でhtmlを初めて扱いました。これも今後勉強が必要だなあ・・・

```html:index.html
<!DOCTYPE html>
<html lang=”ja”>
<head>
<meta charset=”UTF-8″>
</head>
<body>
<title>Flask練習</title>

<span style="text-decoration: underline;"><font color="red"><h2>ショートケーキ</h2><font></span>

<p><font color="black">スポンジとクリームが層になり、上にイチゴが乗ったケーキを指すことが多いです。<br/>
ただし一般的な定義はないそうです。なのでこれがショートケーキだ主張すれば、何でも該当します(極端に言えば)
<font></p>

<span style="text-decoration: underline;"><font color="khaki"><h2>チーズケーキ</h2><font></span>

<p><font color="black">チーズを使ったケーキです。<br/>
チーズケーキは種類があり、スフレチーズケーキ、ベイクドチーズケーキ、レアチーズケーキに大別されます。<br/>
<font></p>

<span style="text-decoration: underline;"><font color="peru"><h2>ロールケーキ</h2><font></span>

<p><font color="black">スポンジ生地にクリームやフルーツを置いて巻いたものです。<br/>
スポンジの外側にクリームがあるもの、ないもの両方存在します。<br/>
<font></p>

</body>
</html>
```

###flaskの利用
htmlファイルを読み込みます。

```python:flask3.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html') #htmlファイルの表示

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/2199e525-615b-598d-3828-4448bf111fc1.png)

実行するとちゃんと項目ごとに色分けされて表示されました。

##まとめ
* htmlファイルを読み込んで表示できた。

次回は画像の読み込みを練習します。
四則演算のみを用いて4つの数字で１０を作ることはできますか。

電車の広告で見かけたので解いてみた。
逆ポーランド記法を用いた。
簡易な電卓機能を作れるかを試すような問題だった。
例は1,3,3,7の場合。

```ruby
class Calculator
  OPERATORS = %w[+ - * /]

  def exec
    answer_formulas = []
    OPERATORS.each do |l|
      first_ope = l
      OPERATORS.each do |m|
        second_ope = m
        OPERATORS.each do |n|
          third_ope = n
          [1.0, 3.0, 3.0, 7.0, first_ope, second_ope, third_ope].permutation.to_a.each do |formula|
            result = _calc(formula.dup)
            if result == 10.0
              answer_formulas << formula
            end
          end
        end
      end
    end
    p answer_formulas.uniq
    p answer_formulas.uniq.count
  end

  private

  def _calc(formula)
    stack = []
    while formula.size > 0
      item = formula.shift
      if OPERATORS.include? item
        if stack.size < 2 || OPERATORS.include?(stack[-1]) || OPERATORS.include?(stack[-2])
          stack.unshift "failure"
          break
        end

        case item
        when '+'
          right = stack.pop
          left = stack.pop
          stack << left + right
        when '-'
          right = stack.pop
          left = stack.pop
          stack << left - right
        when '*'
          right = stack.pop
          left = stack.pop
          stack << left * right
        when '/'
          right = stack.pop
          left = stack.pop
          stack << left / right
        end
      else
        stack << item
      end
    end
    stack[0]
  end
end

Calculator.new.exec
```
【Unity】VRoid Studio産VRMアバターにBlinker.csをアタッチしても「まばたき」しない問題の解決法

<b>答え</b>：まばたきさせたいVRMのInspectorウィンドウを開き，Animatorコンポーネントの「Update Mode」を「<b>Animate Physics</b>」に変更する（デフォルトではNormalになっている）．
![mabatakiInspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/a31d1dcf-d6d0-8fbf-2c62-0fa176d7754d.png)
こうすることでAnimatorControllerのupdateに依存しなくなる（ので，Animation ClipとBlendShapeを同時に使えるようになる？　よくわかってないけど動いたのでヨシ）．


<b>結果</b>
まばたきがあるだけで存在感がグッと増してかわいい．
![finalmabataki2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/97cb5fbf-9ca7-89bc-98db-c4a818c8f5a6.png)
curl: (77) Problem with the SSL CA cert (path? access rights?)が出た時の対処法

[**セゾン情報システムズ Advent Calendar 2021**](https://qiita.com/advent-calendar/2021/sisco) 8日目を担当します。

Azure Site Recoveryを使ったAzure VMのDR構成を試している際に、ASRログ(/var/log/AzureRcmCli.log)にcurlのエラーが出力しうまくいきませんでした。
ググると色々出てきますが、私がやった環境での対処方法を残しておきます。

# 環境
Red Hat Enterprise Linux 6.10

# エラーメッセージ
```
curl: (77) Problem with the SSL CA cert (path? access rights?)
```

# 対応
* CA証明書がサーバーにインストールされているかを確認します。

```
# ls -l /etc/pki/tls/certs/ca-bundle.crt
```

* ca-bundle.crtが存在していなかったため新規で用意します。なぜなかったのかは不明。。
* 以下サーバーよりCA証明書をダウンロードします。
https://curl.haxx.se/ca/cacert.pem

* Azure VMに配置します。

```
# mv cacert.pem /etc/pki/tls/certs/ca-bundle.crt
```

* ASRジョブリランして問題なければOKです。

以上
Vue 3のCompositional APIでRefをComponentに渡す方法

## 目的
Compositional APIのrefを別Componentに渡すこと。

## 背景
React・VueでFormを作る時に、ごちゃごちゃ防止として以下のHTMLを一つのComponentにまとめたい。

```html
<div class="some-class">
 <title>Some Title</title>
 <input type="text" />
</div>
 ```

ただ、Componentにrefを渡さなければいけず、ここでややこしくなります。

React.jsだと、forwardRefという関数を使うと、簡単にクリアできますが、Vue 3はそうでもないのです。

ここで、JavaScriptの魔法を使って、解決法を解説します。


## InputのComponentを作る

このように作ります。

```vue:BaseInput.vue

<template>
  <div>
    <label :for="name">{{ title }}</label>
    <input :type="type" ref="ref" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  props: {
    type: { type: String, required: true },
    name: { type: String, required: true },
    title: { type: String, required: true },
    inputRef: { required: true },
  },
  setup() {},
});
</script>

```

## FormのComponentも作ろう

```vue:NewPost.vue

<template>
  <form @submit="handleSubmit">
    <BaseInput title="Title" name="title" :inputRef="titleRef" type="text" />
    <button type="submit">Submit</button>
  </form>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import BaseInput from "./UI/BaseInput.vue";

export default defineComponent({
  components: {
    BaseInput,
  },
  setup() {
    const titleRef = ref<HTMLInputElement>();

    const handleSubmit = (event: Event) => {
      event.preventDefault();
      if (titleRef.value) {
        console.log(titleRef.value.value);
      }
    };

    return {
      handleSubmit,
    };
  },
});
</script>

```

## JS魔法：渡したいrefを関数に包む

JavaScriptの信者じゃなければ納得はいかんと思います。

NewPost.vueのsetupがreturnするObjectに、titleRefを返す関数を入れるのです。

```javascript
    return {
      titleRef: () => titleRef,
      handleSubmit,
    };
```

ここでBaseInput.vueに戻って、この関数を実行した上でTemplateに渡します。

setupにpropsを入れます。

```vue:BaseInput.vue

<template>
  <div>
    <label :for="name">{{ title }}</label>
    <input :type="type" ref="ref" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  props: {
    type: { type: String, required: true },
    name: { type: String, required: true },
    title: { type: String, required: true },
    inputRef: { type: Function, required: true },
  },
  setup(props) {
    return {
      ref: props.inputRef(),
    } 
  },
});
</script>

```

## まとめ

これでCompositional APIのrefを渡してスッキリしたFormを作れます！

本当は、ReactみたいにちゃんとしたforwardRef機能をつけてほしいところですね。
【Rails】配列をキーでsortしたい


配列をpriceの昇順でsortしたいとき

```ruby
array = [
 {'id'=> 1, 'price'=> 300}, 
 {'id'=> 2, 'price'=> 100}
]
```

なんとなくキーを指定したらsortできたようなーと思ったけどできなかった。

```ruby
array.sort(:price)
#=>ArgumentError (wrong number of arguments (given 1, expected 0))
```

sort_byでブロックの中でキーを指定する。

```ruby
array.sort_by { |a| a['price'] }
#=> [{"id"=>2, "price"=>100}, {"id"=>1, "price"=>300}]
```


##参考

https://docs.ruby-lang.org/ja/latest/method/Array/i/sort.html
lwc跨page通信

LMS可以实现在同一页面下的各个组件的通信，但是却不能跨页面通信。因为lms的本质是跨越dom元素的通信。

如果想要实现不同page之间的通信。可以试试以下的方案


I was searching for a way how to communicate between multiple tabs or windows in a browser (on the same domain, not CORS) without leaving traces. There were several solutions:

using the window object
postMessage
cookies
localStoragelwc