OmniAICreator/Qiita-1.07M huggingface dataset:
#toio を捕まえるゲームを #toioDo で作ってみた【 #GWアドベントカレンダー 2021/5/6 】

この記事は、[2021年の GWアドベントカレンダー](https://gw-advent.9wick.com/calendars/2021/103) 5/6の分の記事です。

## はじめに
今回の記事の内容は、[2021年5月4日に toio の非公式ユーザコミュニティで開催したもくもく会](https://toiotomo.connpass.com/event/211167/)に参加して、以下の 2つの話を見聞きしたことがきかっけとなり、イベント後にふと思いついた「toio​ を捕まえるゲーム」の話です。

- 【聞いた内容 2つ】
   - 簡易マットの上に簡易カードを置いて、簡易カードに触れたら特定の地点にたどり着いたことを判定をする仕組み
   - クリアケースで簡易マットを挟み込んで保護

出来上がった内容（動かしている様子）は、以下のとおりです。

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

## 仕組み・プログラムの概要
今回 toio本体以外に利用しているのは、以下のものです。
　・toio専用の簡易マット
　・toio専用の簡易カード （＋ 持ち手になる細長い何か）
　・クリアファイル

toio専用の簡易カードに、持ち手になる細長い紙をテープで貼り付けたものを作り、それを手持ちで動かしています。上にのせた動画の画面外では、このようになっています。
![手持ち.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e0085153-a72b-dbf7-0e87-54846dac497a.jpeg)
また、toio専用の簡易マットはクリアファイルで挟み込んでおり、簡易マットとクリアファイルの間に持ち手をつけた専用カードを差し込んでいます。

なお、今回は自宅にあるクリアファイルの最大サイズが A4サイズだったため、簡易マットの半分だけを挟み込む形にして、挟み込んだ半分のエリアのみを toio を動作させる範囲として使っています。
ちなみに以下の記事に書いているのですが、toio と組み合わせて使われた実績がある A3サイズのクリアケースが 2種類、冒頭で書いたもくもく会の中で紹介されていました。
　●#toio に関するノウハウのメモと余談（2021/5/4開催のもくもく会でのメモ）【 #GWアドベントカレンダー 2021/5/5 】 - 技術とエンタメと、その他・・・
　　https://yo-to.hatenablog.com/entry/20210504/1620111222

そして、この仕組みのプログラムの部分は toio Do を使ったビジュアルプログラミングです。全部で 11個のブロックで構成されています。 
![toioを捕まえるゲーム.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/8fc0b321-8aba-2666-016b-4511c72bbb5d.jpeg)

## プログラムの補足
上で掲載したプログラムの内容について、少し補足します。

プログラムは処理的には大きく 2つの固まりに分かれます。

固まりの 1つ目は、簡易マットの上で toio を動きまわらせる処理に関わる部分です。
![プログラム1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/03e4867b-7958-07df-1f29-c90e2d2f19e7.jpeg)
この処理は、toio がマットに触れたことをトリガーに、その後 toio がマットに触れている状態である間はずっと実行されます。実行される処理は、特定の絶対位置座標に移動をする処理で、座標は移動を行うごとに乱数で設定されます。

記事の上のほうで書いた通り、今回用いたクリアファイルのサイズの関係で簡易マットの半分のエリアのみを使って動かしているため、乱数で生成する x座標と y座標はその半分のエリア内におさまるように上限と下限を決めています。

固まりの 2つ目は、toio が簡易カードの上に来た時に実行される処理です。ゲームの内容的には toio が捕まった時の処理ということになります。
![プログラム2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/707ee707-0a8d-bd77-aaed-228c901bb9d0.jpeg)
今回使った簡易カードは「％」に該当するものであるため、ここでの処理のトリガーは「％ に触れたとき」としています。別の簡易カードを用いた場合は、この部分をその簡易カードの内容に合わせて変更してください。

そして、ここで行う処理は「音声合成で "捕まっちゃった" としゃべる」・「toio の動きを止める」という 2つです。これらを同時に並列で動かすために、「％ に触れたとき」を 2つ並べた下に 2つの処理をそれぞれ配置しています。
今日の数学： 2021C37を4で割った余りを求めよ


#問題

${}\_{2021}C\_{37}$を4で割った余りを求めよ。

#解答

$(1+x)^{2021}$を展開して、$x^{37}=x^{2^{5}}x^{2^{2}}x^{2^{0}}$の係数を求める。

```math
\begin{align}
(1+x)^4&=1+4x+6x^2+4x^3+x^4\equiv 1+2x^2+x^4\equiv (1+x^2)^2\\
(1+x)^{2^2}&\equiv (1+x^{2})^2\\
(1+x)^{2^3}&\equiv (1+x^{2})^{2^2}\equiv (1+x^{2^2})^2\\
(1+x)^{2^{n+1}}&\equiv (1+x^{2^n})^2\\
(1+x)^{2021}&=(1+x)^{2^{10}}(1+x)^{2^9}(1+x)^{2^8}(1+x)^{2^7}(1+x)^{2^6}(1+x)^{2^5}(1+x)^{2^2}(1+x)^{2^0}\\
&\equiv(1+x^{2^9})^2(1+x^{2^8})^2(1+x^{2^7})^2(1+x^{2^6})^2
(1+x^{2^5})^2(1+x^{2^4})^2(1+x^{2})^2(1+x)\\
&\equiv (\cdots)(1+2x^{2^5}+x^{2^6})(1+2x^{2^4}+x^{2^5})
(1+2x^{2}+x^{2^2})(1+x^{2^0})\\
{}_{2021}C_{37}&\equiv2+1\equiv3
\end{align}
```

#補足

- YouTubeで見かけた問題。東大?
- 誘導がついていたが、理解するのが面倒だったので、一刀両断してみた。
- ちょっと趣旨が違うかも。
[やってみた]EeePC 901-Xを遠隔操作「TeamViewer」

## 背景

お出かけの際は妻の持ち物であるSurface Pro 3を持ち歩いていました。
が、先日、タイプカバーキーボードが無反応に。
タイプカバーキーボードが故障かと思い新しいものを買いましたが、結局無反応．．．
デバイスマネージャにもでてきませんので、本体のコネクタ側の故障な気がします。
そうなると単なる重たいタブレット端末。
とても持ち歩く気になりません。
かといって新しいPCを購入するのもちょっと負けた気がします。
ということで、久々に懐かしのネットブック EeePC 901-Xを引っ張り出してきました。
こいつには軽量OSのLubuntuをインストールしています。
こいつは初めてノートPCの基板をはんだ付け加工をして、SSD換装後にも本体にあるディスクアクセスランプが点灯するように加工した、とても愛着のあるマシンです。
ただ、キーボードが小さすぎるのでパンチミスが多いのが難点です。
であれば、リモートアクセスして、いつもの使い慣れたキーボードで操作できれば．．．
ということで、リモートアプセスのアプリとして以前Androidのリモート操作で使用したTeamViewerをインストールして、母艦であるMac miniで操作できるようにしてみます。

## 32bit? 64bit?

わかっているのですが一応チェック。
インストール媒体が32bitと64bitがあるので。

```
$ getconf LONG_BIT
32
```

はい、予想通り、32bitでした。
そりゃそうでしょう、2008年のモデルです。
今から10年以上も前のPCです。
それでも愛着があるので処分できません．．．

## TeamViewer ダウンロード

[公式サイト](https://www.teamviewer.com/en/download/linux/)からDebian 32bitのリンクを調べ、wgetで媒体を取得します。

```
$ wget https://download.teamviewer.com/download/linux/teamviewer_i386.deb
```

## TeamViewer インストール

ダウンロードした媒体を使ってインストールしていきます。
もちろん、媒体のあるpathで実行です。

```
$ sugo apt-get install ./teamviewer_i386.deb
```

## TeamViewerの起動と接続

アプリが[インターネット]-[TeamViewer]とインストールされているのでクリックして起動します。

TeamViewerライセンス契約に同意します。
次に、「遠隔操作を受ける許可」として「使用中のID」と「パスワード」が表示されます。
これを母艦であるMac miniのTeamViewerに入力します。

すると、母艦のMac miniのモニターにEeePC 901-Xのモニターがそっくりそのまま映し出されます。
これでちょっと使いにくいEeePC 901-Xのキーボードを使わずに操作できます。

## おわりに

今回は母艦のMac miniにTeamViewerがインストールされていたのでそちらの手順は割愛しました。
このTeamViewer、色々なOSに対応しています。
うちにある色々なPCやスマホ、タブレットにインストールしておけば母艦から遠隔操作できます。
難点は各デバイスの使用中のIDとパスワードを見なければならないこと。
それさえ我慢できればかなり便利なアプリです。
UnityのTriLibで悩んだテクスチャの挙動について

現在、Unityで独自のVRMビューアを開発中なのだが、利用しようとして試している機能で悩んで原因がわかってきたので簡単にまとめてみた。

動的にFbxやObjを読み込めるアセット「TriLb2」というのがある。
[TriLib2 - unity Asset Store](https://assetstore.unity.com/packages/tools/modeling/trilib-2-model-loading-package-157548)

※参考記事
https://qiita.com/jyouryuusui/items/5d0f041fc635295640c8

# やろうとしたこと

 自作アプリの特徴として、VRMの他にVRMに取り付けたい小物も読み込めるようにして、動的にVRMに色々パーツを付けてポージングして遊べるようにしたい。
　そこで3Dモデルの動的読み込みで有名なTriLib2の力を借りようと考えて導入した次第。


# 発覚した問題

今までVRoid作成時に作った小物Fbxを試しに読み込ませてテストしようとしたら・・・テクスチャやマテリアルが表示されないのだ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/f9a5567f-ee35-dae5-696c-0b734ef93be6.png)

試しに、アビス・ホライズン開発チームが公開しているFbxを読み込ませてみると正常に表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/ab3c6e95-d49b-e075-5d30-0558dd2933aa.png)

　最初はTriLib2の利用の仕方、コーディング方法でミスがあるのかと思ったが、他所様のFbxが正常に読み込めるので、TriLib2の利用の仕方にミスはない模様。

# ファイル・フォルダの構成を確認

TriLib2に読み込ませるのにfbx単体ではダメ？明示的にフォルダを構成しなければいけないのか？と思って逸仙のFbxに倣ってフォルダを構成し、Zip圧縮してみたがやはりダメ。

逸仙のFbxのフォルダ構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/805ca4b9-4bdb-e7cd-2a57-bbab4064a089.png)

これを真似たが別にフォルダ構成が重要とかそういうわけではないと察した。


# Blenderで設定を確認

　Blenderで各設定を見直してみた。

アビス・ホライズン逸仙のFbx=プリンシプルBSDF
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/d3d1f795-bc05-daa6-efc7-c952163607d0.png)

自作のVRoid用小物のFbx=MToon_universioned
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/bf7fc03d-881f-dd4b-a207-b8f2df8d4c81.png)

シェーダーが明らかに違う。
そこで試しに自作の小物FbxのシェーダーをプリンシプルBSDFに設定し直して、TriLib2で読み込ませてみた。
（本当はマテリアルの設定も怪しいが後でそこは変更しなくても今回の問題には影響なかったのでスルーした）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/e2d81974-4184-063f-f05e-6b006560cb4c.png)

正常に表示されるようになった！Asset Unloaderでもマテリアルの画像のサムネイルが認識されるようになっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/55feaf5f-ee6e-09df-7106-42700dcb2fcd.png)

上図のうち、要素1の「base_color_texture」にあたる部分がいままではサムネの色がなくブランクだった。


# 結論

　TriLib2はVRoid/VRMのMToonシェーダーには対応していないことがわかった。TriLib2で動的にFbxやObjなどを読み込ませたかったから、VRoid用だとしてもプリンシプルBSDFなどの一般的なシェーダーにする必要ありそうだ。

　ただVRoidにMToon以外のシェーダーを設定した3Dモデルを寄り添わせると雰囲気が違ってくる。テクスチャの雰囲気がMToonとそれ以外では違うのだ。ゲームなどでの利用では作風の問題にも影響してくる可能性がある。
　もちろん動的にゲーム中に3Dモデルを読み込ませるなんて、よほどのことだろう。自分はその「よほど」の特殊事例なだけかもしれない。

　あと、VRoidSDKをプロジェクトに導入していると、TriLib2はnewtonsoft.JSON.dllが競合するのでビルド時にエラーが出るので要注意。（自分はまだ解決に至っていないが、VRoidSDKがアプリに不要だとわかったので削除して事なきを得た。）
django復習(matplot)



とりあえずdjangoの復習用に適当にテーブルを作成。
投入データは下記から取得。
[日本政府が出してるっぽいデータ](https://www.e-stat.go.jp/stat-search/files?page=1&layout=datalist&toukei=00200521&tstat=000001011777&cycle=0&tclass1=000001094741)


```
from django.db import models
from datetime import datetime


# 人口テーブル
class Population(models.Model):
    prefectures_code = models.CharField(max_length=10,verbose_name="都道府県コード", null=False) 
    prefectures = models.CharField(max_length=10,verbose_name="都道府県", null=False) 
    era =  models.CharField(max_length=500, verbose_name="元号", null=False)
    jp_calendar =  models.CharField(max_length=500, verbose_name="和暦", null=False)
    year =  models.CharField(max_length=500, verbose_name="西暦", null=False)
    population =  models.CharField(max_length=500, verbose_name="人口", null=False)
    man =  models.CharField(max_length=500, verbose_name="男", null=False)
    woman =  models.CharField(max_length=500, verbose_name="女", null=False)
    create_date = models.DateTimeField(default=datetime.now, null=True, verbose_name="登録日")

    def __str__(self):
        return self.prefectures
```

適当すぎて人口の数値部分も文字列で作成。
問題ないかと思いそのまま続行した結果、色々被害続出。
[その辺の話](https://qiita.com/my1gmai9/items/c89461dc217328be0636)

文字列の問題は置いといて、今回はmatplotで県ごとの人口をグラフにした時のメモ。

適当に作ったらY軸に1e6となってしまった。


![新しいビットマップ イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1377400/53978a7a-8151-11af-248f-20fe4993d7e0.jpeg)


分かりにくい。
調べてみるといい記事が見つかった。
[MatplotlibのY軸の目盛りを指数表記（10のN乗表記）に変更する](https://qiita.com/Fortinbras/items/50500423888ef21429be#ex3y%E8%BB%B8%E3%81%AE%E7%9B%AE%E7%9B%9B%E3%82%8A%E3%82%9210%E3%81%AE%E3%81%B9%E3%81%8D%E4%B9%97%E8%A1%A8%E8%A8%98%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
![新しいビットマップ イメージ2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1377400/3773f47a-3550-7845-2a39-44687df39d9a.jpeg)


ex3)Y軸の目盛りを10のべき乗表記に変更するを真似するといい具合に動いた。



でもまだ10の6乗と言われてもピンとこないので万人単位で固定しようと下記を真似したが、動かない。
[ex4)Y軸の目盛りを1×10^6から1×10^4に変更する](https://qiita.com/Fortinbras/items/50500423888ef21429be#ex4y%E8%BB%B8%E3%81%AE%E7%9B%AE%E7%9B%9B%E3%82%8A%E3%82%921106%E3%81%8B%E3%82%891104%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)

ScalarFormatterの中身を見て確認すると自分の環境だと下記のオーバーライドしてるメソッドが違った。
（記事の）_set_orderOfMagnitude
（自分の）_set_order_of_magnitude
なので_set_orderOfMagnitudeの部分を_set_order_of_magnitudeに書き換えたらうまく動きました。
![新しいビットマップ イメージ3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1377400/e8c8d0fc-4387-faad-cc48-af111d0d973f.jpeg)
JavaScriptの条件分岐switchについて

JavaScriptのswitchは同値演算子(===)に特化した条件分岐です。
同値演算子とは等値演算子(==)よりも厳密に比較したい時に使われます。

switchの構文は次のように書きます。

```
   switch(式){
   case 値1:
   // 「式 === 値1」である時に実行したい処理を書く
   break;//ここでswitch文を抜ける意味
   case 値2:
   // 「式 === 値２」であると時に実行したい処理を書く
   break;//ここでswitch文を抜ける意味
   default:
   // 式の値がすべての値に合致しない時に実行したい処理を書く
   break;
 }
```

次に例文を書いてみます。

```javascript
var n = 1;
switch(n) {
  case 1:
  console.log('数値は1です');
  break;
  case 2:
  console.log('数値は2です');
  break;
  case 3:
  console.log('数値は3です');
  break;
  default:
  console.log('範囲外です');
  break;
}
```

これを実行すると

![df517c8aef1853b55b69112287b4191b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1301666/0fcbf644-c34d-01da-57c2-fceada593c25.png)

のように出力されました。
この場合変数nに１が代入されcase1に当てはまるので'数値は1です'が実行されました。
次にどれにも当てはまらない4を代入してみます。

```javascript
var n = 4;
switch(n) {
  case 1:
  console.log('数値は1です');
  break;
  case 2:
  console.log('数値は2です');
  break;
  case 3:
  console.log('数値は3です');
  break;
  default:
  console.log('範囲外です');
  break;
}
```

実行結果

![e513753045a1a9d0221000a4fdcb4cb8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1301666/b763ccf9-7561-634f-f3af-a467ab4afbd0.png)

case1,2,3どれも当てはまらないのでdefaultが実行されました。
画像ファイルをドラッグ＆ドロップでブラウザのアプリケーションに取り込ませる方法

画像ファイルをドラッグ＆ドロップでブラウザのアプリケーションに取り込ませる方法を調べました。

例えば、以下のような写真をカレンダー形式で管理するアプリケーションを作るとして、画像ファイルをドラッグ＆ドロップで表示できれば便利かと思います。
![スクリーンショット 2021-05-04 2.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569762/5861eddd-78a3-98aa-cd43-c9c90c327e56.png)

JavaScriptだけを使った簡易な実装方法と、PHPを使ったきちんとした（つもりの）実装方法の２パターンを書きます。

## 1.JavaScriptだけで実装

```HTML:calender.html
<table>
    <tr>
        <td id="box1">ボックス1</td>
        <td id="box2">ボックス2</td>
    </tr>
</table>
```

```JavaScript:drag_drop.js
$(function () {
    $("td").on('dragover', function (e) {
        e.stopPropagation();
        e.preventDefault();
    });

    $("td").on('drop', function (e) {
        e.stopPropagation();
        e.preventDefault();

        var boxid = $(this).attr("id");
        var items  = e.originalEvent.dataTransfer.items;
        var file = items[0].getAsFile();
        var reader = new FileReader();
        reader.readAsDataURL(file);

        reader.onloadend = function() {
            $("#" + boxid).append("<img src=" + reader.result + " width=130>");
        };
    });
});
```

このコードでたしかに画像をブラウザに表示させることはできるのですが、画像を保存できないため、実用上はあまり意味がないものです。

aタグに画像を挿入し、aタグのDownload属性を使ってダウンロードフォルダに格納することも試したのですが、使い勝手はあんまり良くなかったです。

## 2.PHPを使って実装

```HTML:calender.html
<table>
    <tr>
        <td id="box1"> ボックス1 <?php if ($box == "box1") { print("<img src=\"" . $data . "\" width=130>"); } ?></td>
        <td id="box2"> ボックス2 <?php if ($box == "box2") { print("<img src=\"" . $data . "\" width=130>"); } ?></td>
    </tr>
</table>
```

```JavaScript:drag_drop.js
$(function () {
    $("td").on('dragover', function (e) {
        e.stopPropagation();
        e.preventDefault();
    });

    $("td").on('drop', function (e) {
        e.stopPropagation();
        e.preventDefault();

        var boxid = $(this).attr("id");
        var items  = e.originalEvent.dataTransfer.items;
        var file = items[0].getAsFile();
        var reader = new FileReader();
        reader.readAsDataURL(file);

        reader.onloadend = function() {
            $("#" + boxid).append("<form id=\"upload" + boxid + "\" action=\"calender.php\" method=\"POST\"></form>")
            $("#upload" + boxid).append("<input type=\"hidden\" name=\"day\" value=\"" + boxid + "\">");
            $("#upload" + boxid).append("<input type=\"hidden\" name=\"data\" value=\"" + reader.result + "\">");
            var form = $("#upload" + boxid);
            form.submit();
        };
    });
});
```

```PHP:calender.php
function get_post_data($key) {
    $str = '';
    if (isset($_POST[$key]) === TRUE) {
        $str = $_POST[$key];
    }
    return $str;
}

$box = "";
$data = "";

if ($_SERVER['REQUEST_METHOD'] === "POST") {
    $box = get_post_data('box');
    $data = get_post_data('data');
}

include_once "calender.html";
```

これで画像をブラウザに表示させることができます。

あとは画像データのDBへの出し入れと、ブラウザへの描画の部分を修正すれば、意図した通り画像ファイルの取り込みをドラッグ＆ドロップで実現できます。
IP制限のかかったサイトにiPhoneのブラウザから接続するためのProxyをMac上で立てる

※前回の記事の延長
https://qiita.com/taaaaho/items/2f744c5a3bbe838f5137

前回はMacからProxy経由で接続する方法を記載した。
今回はiPhoneからMacを経由して接続する方法を記載していく。

## やりたいこと
- IP制限のかかったサイトに接続するProxyをMac上で立てる
- IP制限がかかっているサイトにiPhoneからアクセスすることが目的


## 解決方法
- MacのWebserver機能とSocksでアクセスできるようにする


## 手順
### 1. MacでWebserver機能を有効化する
```
$sudo apachectl start
```

ブラウザ上でlocalhostにアクセスして`It works!` が表示されることを確認する。

※DocumentRootはMacの以下の階層
`/Library/WebServer/Documents`


### 2. MacのIPアドレスをネットワーク設定から確認

下の画像の赤枠の部分。
ここで確認したIPアドレスを次のステップで活用する。

![Screen Shot 2021-05-04 at 20.42.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245027/d88b6582-72f7-cdfb-744e-adc7ffaf15ad.png)


###3. iPhoneからMac経由でアクセスするための接続ファイルを作成
```socks.pac
function FindProxyForURL(url, host) {
    return "SOCKS [確認したIPアドレス]:10080";
}
```

作成したファイルは先ほどのDocumentRoot以下に配置する
`/Library/WebServer/Documents/socks.pac`


### 4.iPhoneで接続しているwifiの設定画面を開いてProxyを設定
wifi設定画面の一番したのProxy設定を選択して開く。
Automaticを指定してURLに先ほど配置した `socks.pac`が読み込まれるようにパスを記載。

```Automatic.URL
http://[MacのIPアドレス]/socks.pac
```

### 5.完了
設定自体はこれで完了でiPhoneのアクセスが全てMac上で起動しているProxy経由になる。


## Proxy設定有無の確認
ブラウザ上で以下のリンクを開いてロケーションなどを確認して判別する
https://api.ip2geo.pl/json/
【rails】validateをかけてみた。

# バリデーションを設定
```
class User < ApplicationRecord

    #ハイフンあり、7桁の整数
    VALID_ZIPCODE_REGEX = /\A\d{3}[-]\d{4}\z/
    #メールアドレス
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    #電話番号 ハイフンあり、整数
    VALID_PHONE_REGEX = /\A[0-9-]+\z/

    validates :first_name, presence: true, length: { maximum: 10 } # 存在する、かつ、10文字以下。
    validates :last_name, presence: true, length: { maximum: 10 }
    validates :zipcode, presence: true, format: {with: VALID_ZIPCODE_REGEX }
    validates :prefecture, presence: true, length: { maximum: 5 }
    validates :municipality, presence: true, length: { maximum: 10 }
    validates :address, presence: true, length: { maximum: 10 }
    validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }
    validates :phone_number, presence: true, length: { maximum: 15 }, format: { with: VALID_PHONE_REGEX }
    validates :password, presence: true, length: { minimum: 6, maximum: 15 }

    belongs_to :user_classification
    has_secure_password
end
```

#苦戦したところ
電話番号の`/\A[0-9-]+\z/` について、"9"の後の"-"によって、
0~9の数字と、"-"はOKになる。

ハイフンをどこに入れても許可する設定が中々分からなくて苦労した。
コールバック関数とは

##コールバック関数とは
**関数の引数に渡された関数のことをコールバック関数といいます。**
呼び出された関数が逆に関数を呼び出す側になるのでコールバックと言います。
実際にコードをみてみましょう。

```javascript
// ②confirmed関数が呼び出される
function confirmed(fn) {
  if(window.confirm("OKを押して下さい")) {
// ③引数で受け取った関数を呼び出す
    fn()
  }
};
// ①confiremed関数を呼び出す
confirmed(function () {
  console.log("OKを押しました");
});
```
このコードを実行してみます。

![スクリーンショット 2021-05-04 19.14.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185431/95d0ce4b-107d-0ac5-7530-8110e6c1f8b2.png)

![スクリーンショット 2021-05-04 19.16.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185431/1f64a5ad-5af9-580d-22b7-acc73cfa9353.png)

ポップアップでOKを押してくださいと出てきます。
OKを押し、コンソールを確認するとOKを押しましたと表示されています。

処理を追ってみます。
まず最初にconfirmed関数を呼び出します。
この時、confirmed関数に対し引数で関数を受け渡しています。
**JavaScriptでは関数もオブジェクトの一つであるため、関数を引数として指定することも可能です。**
呼び出されたconfirmed関数は処理を実行します。
処理を実行するのでブラウザ上にポップアップでOKを押してくださいが表示されます。
ユーザーがOKを押下すると、呼び出された側であったはずのconfirmed関数が**引数で受け取った関数を呼び出しています。**
その結果console.log("OKを押しました")の処理が実行されるので、コンソールにOKを押しましたと表示されます。
最初は呼び出された側であったconfirmed関数が処理を実行した後、逆に関数を呼び出す側になったと思います。
これがコールバック関数です。

##コールバック関数が主に使われるケース
非同期処理を行う時に使用する事が多いです。

非同期処理というのは、**誰かに仕事を任せる事で自分は別の仕事を進める事ができます。**（つまり同時に複数処理を行える。）
この場合コールバック関数は、**非同期処理でお願いした仕事が終わった後に、特定の処理を指定する時に使われます。**

実際にsetTimeout関数を使用した例をみてみましょう。

**setTimeout( コールバック関数 , 時間の指定 )**

第一引数にコールバック関数、第二引数に時間の指定をする事ができます。
setTimeoutは時間を指定し、一定時間後に一度だけコールバック関数を実行する事ができます。


```javascript
const Bye = function(){
  console.log('さよなら！');
}

console.log('おはよう！')

setTimeout(Bye, 3000);

console.log('調子はどう?');

>> おはよう!
>> 調子はどう?
// 3秒後にByeが実行される
>> さよなら!
```


##まとめ
コールバック関数は**関数の引数に渡された関数のことを指します。**
非同期処理で使用する場合、**お願いした仕事（非同期処理）が終わった後に、別の処理を指定する際にコールバック関数が使われます。**
IP制限のかかったサイトに自端末のブラウザから接続するためのProxyをMac上で立てる

## やりたいこと
- IP制限のかかったサイトに接続するProxyをMac上で立てる
- IP制限がかかっているサイトにアクセスすることが目的

イメージとしては下の図のような感じ

![Screen Shot 2021-05-04 at 20.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245027/057adba9-a440-1ca8-6616-3fb0a087be8e.png)

ただ、今回の場合は踏み台サーバーを経由して多段SSHでの接続を行うため、実際はこんな感じのをやりたい。

![Screen Shot 2021-05-04 at 20.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245027/1c058366-03f8-4f22-b9f0-7218330a92a2.png)


## 手順
### 単純な自端末 -> GCEへのProxy
1つだけサーバーを経由する場合はシンプルに通常のSSHにオプション加えるだけ。

```bash
ssh -i 秘密鍵 ユーザー名@サーバーIP -N -D 10080
```

このコマンドでバックグラウンドでProxyが立ち上がる。
以下のコマンドでProxy経由と通常の通信の検証が行える

```
# 通常の通信
curl https://api.ip2geo.pl/json/

# Proxy経由の通信
curl --proxy socks5://localhost:10080 https://api.ip2geo.pl/json/
```

それぞれ繋ぎ先にもよるがロケーションなどが変わった結果が返ってくることでProxyが正常に立ち上がっていることが確認できる。

ブラウザなどを経由してアクセスする場合はNetworkの設定にProxyを挟む必要がある。
ネットワークのAdvanceの設定からProxiesを選択し、 `SOCKS Proxy`にチェックをつけてSSHのオプションで指定したポートを経由するようにする。

![Screen Shot 2021-05-04 at 20.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245027/5f13d971-0650-22ad-3b22-7e7f36436a18.png)

これでSSHで接続するサーバー経由で全ての通信が行われるようになる。


### 多段SSH 自端末 -> GCE -> EC2へのProxy
踏み台サーバーが増えても基本的にやることは同じ。
多段SSHの接続方法を知っていたら同様にオプションを最後に付与してあげるだけ。

```
ssh -i [EC2の秘密鍵] -o ProxyCommand='ssh -i [GCEの秘密鍵] GCEユーザー@GCEのIPアドレス -W %h:%p' EC2のユーザー@EC2のIPアドレス -N -D 10080
```

## 参考
- https://www.rhoboro.com/2019/02/15/gce-ssh-proxy.html
- https://www.wakuwakubank.com/posts/681-ssh-portforward-multistage/
VBScriptで配列の重複を削除する関数を作成してみた

EXcel VBAやVBScriptで配列の重複を削除する必要があり下記関数を作成しました。

辞書型を使うことで，重複文字列を除外しています。

``` VB
Function DeleteDupulicate(RamArray)
    Set Dic = CreateObject("Scripting.Dictionary")
    On Error Resume Next
    For i = 0 To UBound(RamArray)
        Dic.Add RamArray(i), RamArray(i)
    Next
    DeleteDupulicate = Dic.Keys
End Function
```
Nuxt.jsでi18n対応

Nuxt.js簡単にサイト構築ができてとても便利ですね。
今回はNuxt.jsでi18n対応をやりましたのでその手順を記載します。

##i18n対応とは

国際化対応とも言われる。
ソフトウェアやインターネットサイトを複数の言語で使用、閲覧可能な状態にすること。
「Internationalization」の省略表記で、最初と末尾の文字、及びその間の文字数を記載して「i18n」と呼ぶらしい。

今回はnuxt-i18nのパッケージを使用。


##nuxt-i18nのインストール

i18n対応可能とするパッケージ`nuxt-i18n`をインストール

~~~bash
yarn add nuxt-i18n
~~~

`package.json`に追加されていることを確認

~~~json
"dependencies": {
    ...
    "nuxt-i18n": "^6.26.0"
}
~~~

##言語翻訳ファイルの作成

`./locales/[laguage]` 配下に言語ファイルを作成
以下は、`./locales/ja/index.json`の作成例
※必要に応じて、他言語のファイルも作成

~~~json:./locales/ja/index.json
{
    "welcome": "ようこそ！"
}
~~~

##nuxt.config.jsファイルの設定

`nuxt.config.js`ファイルの`mudules`の箇所に以下の文言を追加

~~~javascript:./nuxt.config.js
modules: [
    [
      'nuxt-i18n', 
      {
        // 使用する言語の設定
        locales: [
          { code: 'ja', name: 'Japanese', iso: 'ja_JP', file: 'ja/index.json' },
          { code: 'en', name: 'English', iso: 'en-US', file: 'en/index.json' }
        ],
        defaultLocale: 'ja', // デフォルトの言語
        langDir: 'locales/', // 翻訳ファイルのディレクトリパス
        strategy: 'prefix_and_default', // URLに言語のプレフィックスを追加するかの指定
        vueI18n: {
          // 翻訳ファイルが見つからなかった場合の言語を指定
          fallbackLocale: 'ja'
        },
        vueI18nLoader: true,
        lazy: true
      }
    ]
  ],
~~~

##Vueファイル内での使用

コンテンツ部となるVueファイル内で、jsonのキー情報を埋め込む
`$t('key-name')`を指定することで、翻訳ファイルのキーと一致させることが可能

~~~vue:./pages/index.vue
<v-card-text>
    <p>{{ $t('welcome')}}</p>
    ...
</v-card>
~~~

##言語切替ボタンの追加

言語切替ボタンを追加するには`nuxt-link`を使用する
v-btnを使用してボタン表示（UIフレームワークとしてvuetifyを使用）

~~~vue:./pages/index.vue
<nuxt-link :to="switchLocalePath('ja')"><v-btn color="primary">Japanese</v-btn></nuxt-link>
<nuxt-link :to="switchLocalePath('en')"><v-btn color="primary">English</v-btn></nuxt-link>
~~~

##実行確認

一連の修正を実施して動作確認

~~~bash
npm run dev
~~~

####実際表示された画面

真ん中の部分の「Japanese」及び「English」のボタンで言語切替が可能となりました。
※ボタンすぐ上の「welcome！」の箇所が多言語対応されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/194056/abe2555a-5a1c-1833-9687-1a0701092199.png)


##最後に

UIフレームワークとしてVuetifyを使用しましたが、そもそもVuetifyがi18n対応済でvue-i18nとは連携可能とことです。

この辺り、もう少し深堀りすることでもっと効率の良いやり方があるかも知れません。
また分かり次第、投稿したいと思います。

https://vuetifyjs.com/ja/features/internationalization/
SSD + XFS のメモ

https://chiadecentral.com/chia-blockchain-ssd-buying-guide/

https://www.phoronix.com/scan.php?page=article&item=linux-58-filesystems&num=4

SSD(NVMe)では XFS が性能いいっぽいらしい

## CRC

XFS では crc のための領域があるが, off にできる.
ECC つきメモリを使っているなら, `-m crc=0` で off にするといくらか領域を節約できるやも.

## TRIM

https://wiki.archlinux.jp/index.php/%E3%82%BD%E3%83%AA%E3%83%83%E3%83%89%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%89%E3%83%A9%E3%82%A4%E3%83%96#XFS

XFS でも TRIM 対応している.

ファイル削除時に TRIM を走らせるなら, ページ先頭の chia decentral のサイトにあるように `discard` つきでマウントする.
(ただしファイル削除が頻繁にあるとパフォーマンスが落ちるであろう)
Let's Encrypt に登録してあるメールアドレスを調べる

こちらのページにあることを別の環境で確認しました。
[Let's Encryptに登録したメールアドレスを確認する方法と変更する方法おご教授いただきたいです。](https://teratail.com/questions/254030)

Arch Linux
Ubuntu 20.04
Ubuntu 21.04
で確認しました。

```py:get_email.py
#! /usr/bin/python3
#
#	get_email.py
#
#					May/05/2021
# ------------------------------------------------------------------
import sys
from acme.client import ClientV2
from acme.client import ClientNetwork
from acme import messages
import josepy as jose
from glob import glob
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")

folder='/etc/letsencrypt/accounts/acme-v02.api.letsencrypt.org/directory/*'
#
try:
	file_in = glob(folder + '/private_key.json')[0]
	fp_in = open(file_in, 'rb')
	json_str = fp_in.read()
	fp_in.close()
	key = jose.JWK.json_loads(json_str)
except Exception as ee:
	sys.stderr.write("*** error *** private_key.json ***\n")
	sys.stderr.write(str(ee) + "\n")
	sys.stderr.write("Usage: sudo ./get_email.py\n")
	exit(1)
#
try:
	file_in = glob(folder + '/regr.json')[0]
	fp_in = open(file_in, 'r')
	json_str = fp_in.read()
	fp_in.close()
	regr = messages.RegistrationResource.json_loads(json_str)
except Exception as ee:
	sys.stderr.write("*** error *** regr.json ***\n")
	sys.stderr.write(str (ee))
	sys.stderr.write("Usage: sudo ./get_email.py\n")
	exit(1)
#
net = ClientNetwork(key)
directory = messages.Directory.from_json(net.get("https://acme-v02.api.letsencrypt.org/directory").json())
client = ClientV2(directory, net)

client.net.account = regr
resp = client._post(regr.uri, None)

print(resp.json()['contact'])

sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ sudo ./get_email.py 
*** 開始 ***
['mailto:hello@example.com']
*** 終了 ***
```
[Django]   (fields.W340) null has no effect on ManyToManyField.

# Warning

```
model name:  (fields.W340) null has no effect on ManyToManyField.
```

> null has no effect since there is no way to require a relationship at the database level.

https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ManyToManyField


ManyToManyの実態は、リレーションテーブルなので、そのレコードの中でnullを許容するということが物理的にできないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64293/ebab6e7a-3f5b-4da9-af6c-3e8a1a3fbde3.png)
https://stackoverflow.com/questions/49677910/filter-data-from-two-tables-having-many-to-many-relation-django

# 解決策

```python

field_name = models.ManyToManyField(ModelName, blank=True, null=True, related_name='n')
↓
field_name = models.ManyToManyField(ModelName, blank=True, related_name='n')
```
Docker コンテナのライフサイクル（メモ）


ざっくりとしたコンテナのライフサイクルは、
作成(create)→起動(start)→停止(stop)→破棄(rm)となります。

##コンテナの作成・起動
```
docker run (オプション) イメージ (引数)
```

イメージをダウンロードする`docker pull`、コンテナを作成する`docker create`、コンテナを起動する`docker start`、これらの動きをまとめて実行してくれるのが`docker run`。
`docker run`コマンドはコンテナの作成・起動、イメージがない場合はイメージのダウンロードも行ってくれます。

##コンテナの停止

```
docker stop コンテナ名
```
##コンテナの削除

```
docker rm コンテナ名
```
【kotlinx-metadata】引数/型引数のnullabilityを取得する

# やること
以下のクラスのコンストラクタの引数について、それぞれの型/型引数の`nullability`を取得します。

```kotlin
data class Foo(val nonNullList: List<Any>, val nullableList: List<Any?>, val starList: List<*>?)
```

# やり方
ソースコード全体は以下の通りです。
細かい部分はコメントに記述してあります。

```kotlin
import kotlinx.metadata.Flag
import kotlinx.metadata.KmClass
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.KmType
import kotlinx.metadata.jvm.KotlinClassHeader
import kotlinx.metadata.jvm.KotlinClassMetadata

data class Foo(val nonNullList: List<Any>, val nullableList: List<Any?>, val starList: List<*>?)

fun Metadata.toKotlinClassHeader() = KotlinClassHeader(
    this.kind,
    this.metadataVersion,
    this.data1,
    this.data2,
    this.extraString,
    this.packageName,
    this.extraInt
)

val KmType.isNullable: Boolean get() = Flag.Type.IS_NULLABLE(flags)

fun main() {
    // メタデータ取得 -> クラス情報に変換 -> 対象となるコンストラクタを取得
    val metadata: KotlinClassMetadata.Class = (Foo::class.java.annotations.first { it is Metadata } as Metadata)
        .toKotlinClassHeader()
        .let { KotlinClassMetadata.read(it) as KotlinClassMetadata.Class }
    val kmClass: KmClass = metadata.toKmClass()
    val constructor: KmConstructor = kmClass.constructors.single()

    // コンストラクタの引数の型情報、typeプロパティは引数がvarargだった場合nullになる
    val parameterTypes: List<KmType?> = constructor.valueParameters.map { it.type }
    // 引数のnullability確認（今回はvararg引数が無いため強制アンラップ）
    println(parameterTypes.map { it!!.isNullable }) // -> [false, false, true]
    // 型引数情報、argumentsは型引数一覧で、今回の処理対象はListで型引数は1つなためsingle()している
    val typeParameters: List<KmType?> = parameterTypes.map { it!!.arguments.single().type }
    // 型引数のnullability確認、指定がスタープロジェクションだった場合nullになる
    println(typeParameters.map { it?.isNullable }) // -> [false, true, null]
}
```

# 参考にさせて頂いた内容
https://github.com/ZacSweers/MoshiX/blob/d18e87e73d69fee81bbfb1aa5d10b4b620e3ed61/moshi-metadata-reflect/src/main/kotlin/dev/zacsweers/moshix/reflect/KtTypes.kt#L35
Ruby 問題② ハッシュの基礎について

##はじめに##
GWも絶賛学習中！
本日もよろしくお願い致します。

##問題##

複数のユーザ情報をハッシュとして持つ変数user_dateがあります。

```ruby.rb
user_data = [
 {user: {profile: {name: 'Sugano'}}},
 {user: {profile: {name: 'Sakamoto'}}},
 {user: {profile: {name: 'Okamoto'}}},
]
```

このデータの名前だけを出力するように記述してください。
出力結果は以下の通りです。

```ruby.rb
Sugano
Sakamoto
Okamoto
```

##ヒント##

・配列とハッシュを組み合わせ
・名前を配列から取り出している（each文）
・２重にされています

##解答##

```ruby.rb
user_data.each do |u|
  puts u[:user][:profile][:name]
end
```

##解説##

ハッシュから特定のキーを取り出す場合は　**ハッシュ[取得したい値のキー]**で取り出す事が可能です。

今回は2重になっていました。
userの中にprofileがあり、その中にnameがあります。

奥底にある:nameを取り出すためには**ハッシュ[取得したい値のキー][取得したい値のキー]**
で取り出すため、

```.rb
ハッシュ[:user][::profile][:name]
```
となります。

また配列の中にハッシュがあるため余計なものを取り除かなければなりません。
1度問題のまま取り除いたらどうなるか検証してみます。

```.rb
user_data = [
 {user: {profile: {name: 'Sugano'}}},
 {user: {profile: {name: 'Sakamoto'}}},
 {user: {profile: {name: 'Okamoto'}}},
]
puts user_data[0]
#添字で呼び出す事で配列[0]に入っているデータが取得できる
{:user=>{:profile=>{:name=>"Sugano"}}}

#問題のように3人のnameだけを取り出す場合は下記のようになる
puts user_data[0][:user][:profile][:name]
puts user_data[1][:user][:profile][:name]
puts user_data[2][:user][:profile][:name]

Sugano
Sakamoto
Okamoto
```

３人を呼び出すには同じ記述をしなければいけないのでeach文で呼び出すと簡潔に記述する事ができます

```.rb
変数.each do |ブロック変数|
ブロック変数 = [][][]
```
解答では

```.rb
user_data.each do |u|
  puts u[:user][:profile][:name]
end
```
となります。
AWS サブネットを作成する

##はじめに
VPCを作成した際の備忘録として

##サブネットとは
サブネットは最初にVPCによって作られているCIDRブロックを分割したネットワーク群のことです。サブネットは、VPCの上限を超えなければ、いくらでも作ることが可能。

サブネットには、主に<strong>パブリックサブネット</strong>と<strong>プライベートサブネット</strong>があります。
パブリックネットは字のごとく、外のネットワークと直接繋がっているサブネットで、
プライベートサブネットとは、直接は外のネットワークに繋ぐことのできないサブネットになります。

外部から攻撃を受ける可能性も高いので、可能な限りプライベートサブネットにリソースを置くことが好ましいようです。

##サブネットの作成

[![Image from Gyazo](https://i.gyazo.com/99c9c9db39657fac7a2cc29dca2bc8b5.png)](https://gyazo.com/99c9c9db39657fac7a2cc29dca2bc8b5)

VPCの画面からサブネットを選択します。

[![Image from Gyazo](https://i.gyazo.com/dd2d4ff8db7ab6a1cd3abb2f2d5150ee.png)](https://gyazo.com/dd2d4ff8db7ab6a1cd3abb2f2d5150ee)

サブネットの一覧が表示されました。デフォルトのサブネットが3つ表示されています。
サブネットの作成をクリックしてください。

[![Image from Gyazo](https://i.gyazo.com/ac56eeabf8b9856d43c7c5a91d788257.png)](https://gyazo.com/ac56eeabf8b9856d43c7c5a91d788257)

VPCを選択してください。

[![Image from Gyazo](https://i.gyazo.com/8d7034dde1578703b1a4b8abc2770ca1.png)](https://gyazo.com/8d7034dde1578703b1a4b8abc2770ca1)

選択すると、設定ができるようになります。
任意の名前をつけましょう。

[![Image from Gyazo](https://i.gyazo.com/23160058c77c32b4210e921e2db3dce5.png)](https://gyazo.com/23160058c77c32b4210e921e2db3dce5)

次にアベイラビリティーゾーンを選択します。今回はap-northeast-1aを選択します。
アベイラビリティーゾーンとはリージョン内にあるデータセンターのことを言います。AZと略されます。

[![Image from Gyazo](https://i.gyazo.com/eba0d95e4f000a4495608dbc21894f33.png)](https://gyazo.com/eba0d95e4f000a4495608dbc21894f33)

次にIPv4 CIDR ブロックを設定します。
今回は10.0.10./24に設定しました。
使用するVPCのCIDRの範囲内でCIDRを指定する必要があります。たとえばVPCのCIDRが10.0.0.0/16である場合、10.0.0.0/24などのCIDRを指定します。

[![Image from Gyazo](https://i.gyazo.com/1cf454f94acd357c1bf2bcf689e1fc53.png)](https://gyazo.com/1cf454f94acd357c1bf2bcf689e1fc53)

サブネットを作成をクリックしましょう。

[![Image from Gyazo](https://i.gyazo.com/f523269af8a369a1796cd6bc3f246831.png)](https://gyazo.com/f523269af8a369a1796cd6bc3f246831)

サブネットが作成できました。
>参考サイト
[AWS　VPC の作成と設定](https://docs.aws.amazon.com/ja_jp/directoryservice/latest/admin-guide/gsg_create_vpc.html)
[Qiita 0から始めるAWS入門①：VPC編](https://qiita.com/hiroshik1985/items/9de2dd02c9c2f6911f3b)
[[初心者向け]VPC作成からEC2インスタンス起動までを構成図見ながらやってみる（その1）](https://dev.classmethod.jp/articles/creation_vpc_ec2_for_beginner_1/)
[AWSのVPCって何？メリットや使えるシーンなど徹底解説！](https://techplay.jp/column/541#:~:text=%E3%81%A6%E3%81%84%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,%E3%82%B5%E3%83%96%E3%83%8D%E3%83%83%E3%83%88,%E3%81%A8%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88%E3%82%B5%E3%83%96%E3%83%8D%E3%83%83%E3%83%88%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)
Vue.js~イベント処理~

#概要

フォームの入力の読み取り、送信するまでのプログラムについての記事です。
v-on,v-modelについて主に取り上げています。


#イベント発生
今回のフォームの実装では、ユーザーが入力して送信ボタンを押すのがイベント発生となります。
イベントを設定します。

#HTML

```index.html
<form @submit.prevent ="addItem">
  <input type="text" v-model="newItem">
   <input type="submit" value="add">
 </form>
```
イベントはsubmitです。
イベント処理を実装するのはv-onです。(上記では@sbmit)となっています。

更に今回のイベントは、ユーザーからの入力内容を受け取り反映したいので、input type="text"から値を受け取ります。

#v-model

```
v-model="データオブジェクトプロパティ"
```

#v-on

```
v-on="...." (@イベント名="")
```
sbmitされたときのメソッドを指定します。今回は、addItemです。
更に今回はボタンタグにsubmitを使用しています。それにより、ページ変移が起きてしまうのでpreventDefaultメソッドを使用します。

```index.html
@submit.prevent
```
と記述します。

#Vue

つづいて、Vueの実装内容です。

```index.js
data:{
  newItem:'',
  lists:[
    'list1',
    'list2',
    'list3'
   ]
},
```

#双方向データバインディング
先程、v-modelで指定したプロパティはnewItemです。
現在こちらのプロパティは空に設定しています。こちらに文字列を入れてみました。
すると、テキストボックスに初期値が反映されていました。
これは、双方向データバインディングといいます。Vue.jsのフォーム開発で大切になります。
データオブジェクトからテキストボックスの反映はもちろん。テキストボックスからの反映も可能にします。(データオブジェクトとテンプレート状態を同期する)

ちなみに、v-modelを利用した場合はテキストボックスでHTMLから指定されたValue属性は無効になります。

```index.js
methods:{
 addItem: function() {
   this.lists.push(this.newItem);
   this.newItem = '';
  }
}
```
次に送信されたときの処理についてです。methodsというキーでイベントオブジェクトを作ります。
先程のHTMLで指定したaddItemで処理を書いていきます。
今回の処理内容は、submitしたときにlistsという配列にプッシュします。
data内のlistにはthisでアクセスすることが出来ます。this.lists.pushとすることで追加することが出来ます。何をプッシュするのかv-modelで取得したプロパティですね。
値を送信した後に値がテキストボックスからなくなるようにthis.newItem = ''空文字にします。
VS CodeでApache RoyaleのWebアプリをデバッグする

# はじめに

Visual Studio Code（VS Code）を使って、Apache RoyaleのWebアプリをデバッグします。

## VS Codeでのデバッグイメージ

![Screenshot from 2021-05-04 19-18-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102121/69092070-7b8c-41fc-d4c4-2575fbc0a18b.png)

## 試した環境/バージョン

- VS Code 1.60.2
- Windows 10
- Apache Royale 0.9.8

# 事前準備

以下を実施していること

- [Apache RoyaleでHelloWorldアプリを作る](https://qiita.com/lune1122/items/4aed6ea07987219545b9)

VS Codeに以下の拡張機能をインストールしていること

- [ActionScript & MXML](https://marketplace.visualstudio.com/items?itemName=bowlerhatllc.vscode-as3mxml)

# アプリのデバッグ

## asconfig.jsonの作成

```asconfig.json
{
    "config": "flex",
    "compilerOptions": {
        "source-map": true
    },
    "files": [
        "src/Main.mxml"
    ]
}
```

## .vscode\launch.jsonの作成

```　.vscode\launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-chrome",
            "request": "launch",
            "name": "Launch Chrome",
            "file": "${workspaceRoot}/bin/js-debug/index.html",
            "timeout": 30000
        }
    ]
}
```

## デバッグ

VS CodeでMain.mxml等があるフォルダーを開く

右下の「No SDK」をクリックして、Apache Royaleのフォルダー（apache-royale-0.9.8-bin-js）を選択してSDKのリストに追加する

再度、右下の「No SDK」をクリックして、追加したSDKを選択する

Ctrl + Shift + Enter を押下する

Quick Compileによりコンパイルが行われて、アプリがデバッグで起動する

※VS Codeのキーボードショートカットの設定で、Ctrl + Shift + Enterを別のキーに変更すると楽かもしれません。（個人的にはF6に変更しています）

## 補足：Quick Compileについて

ActionScript & MXMLの拡張機能による機能です。
コンパイルに関する情報をVS Codeのメモリに保持することで、2回目以降のコンパイルを通常よりも速く行うための機能のようです。
2倍ぐらい速くなっているように思います。

とりあえず今回はここまで
JDLA　E資格の概要

#E資格?


AIの勉強をするために、何から始めればよいか困ってしまうので、JDLAが運営しているE資格取得を目指してみることにした。G検定はざっくりした初心者用の試験であるのに対して、E資格は、AIエンジニアとしての技能認定試験の意味合いが強い資格試験になっている。

<font color="blue">ディープラーニングの理論を理解し、適切な手法を選択して実装する能力や知識を有しているかを認定する。</font>


https://www.jdla.org/certificate/engineer/


#E資格の出題範囲：シラバス


|大項目|中項目|小項目|キーワード|
|:----|:----|:----|:----|
|応用数学|線形代数|特異値分解| |
| |確率統計|一般的な確率分布|ベルヌーイの分布、マルチヌーイの分布、ガウス分布|
| | |ベイズ則| |
| |情報理論| | |
|機械学習|機械学習の基礎|学習アルゴリズム|タスクT、性能指標P、経験E|
| | |納六、過剰適合、過小適合| |
| | |ハイパーパラメータ| |
| | |検証集合|学習データ、検証データ、テストデータ、ホールドアウト法、k-分割交差検証法|
| | |最尤推定|条件付き対数尤度と平均二乗誤差|
| | |教師有学習アルゴリズム|ロジスティック回帰、サポートベクトルマシン、最近近傍、k近傍法|
| | |教師無学習アルゴリズム|主成分分析、k平均クラスタリング|
| | |確率的勾配降下法| |
| | |深層学習の発展を促す課題|次元の呪い|
| |実用的な方法論|性能指標| |
| | |ハイパーパラメータの選択|手動でのハイパーパラメータ調整、グリッドサーチ、ランダムサーチ、モデルに基づくハイパーパラメータの最適化|
|深層学習|順伝搬型ネットワーク| | |
| |深層モデルのための正則化| | |
| |深層モデルのための最適化| | |
| |畳み込みネットワーク| | |
| |回帰結合型ニューラルネットワークと再帰的ネットワーク| | |
| |生成モデル| | |
| |強化学習| | |
| |深層学習の適応方法| | |
|開発・運用環境|ミドルウェア| | |
| |軽量化・高速化技術| | |
【Nuxt.js】自動ルーティング設定

# はじめに

nuxt では vue-router を自分で設定する必要がないです！
pages ディレクトリ配下に作った vueファイルに対して、自動的にルーティングが行えるように色々やってくれるようなので、ドキュメント見ながら簡単にまとめたいと思います。



# 自動的にルーティングを生成

下記のような `.vue` ファイルを `pages/` 配下に作成すると、、 

```
pages/
--| product/
-----| index.vue
-----| name.vue
--| index.vue
```

自動的に以下が生成されます

``` .js
router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'product',
      path: '/product',
      component: 'pages/product/index.vue'
    },
    {
      name: 'product-name',
      path: '/product/name',
      component: 'pages/product/name.vue'
    }
  ]
}
```
ここで定義されているルートは、こんな意味です。

```
{
    name: 'product',
    path: '/product',   //このパスにアクセスしたら
    component: 'pages/product/index.vue'   //このコンポーネントを呼ぶ
}
```

# 動的な場合

Qiitaなどの記事を API から取得する場合、記事の名前や記事IDのようなものがURIに入ることになります。そうなると、ルートの名前を決定することができないので、動的に設定する必要があります。

その場合は、アンダーバーをファイル名の頭に付けます。

```
pages/
--| article/
-----| _articleid.vue
```

下記が生成されます

```
{
    name: 'articleid',
    path: '/article/:articleid',
    component: 'pages/article/_articleid.vue'
}
```

これにより、`https://itblog.com/article/943095435` このようなURIで記事にアクセスできます。

### 記事IDを取得する

動的な記事ページ `article/_articleid.vue` があるとします。この articleid にアクセスするには、 `this.$route.params.articleid` でいけるみたいです。


# URIを指定してページ遷移するには

`NuxtLink` コンポーネントを使ってください。

```.html
<template>
  <NuxtLink to="/article">記事一覧</NuxtLink>
</template>
```

# さいごに

vue はポートフォリオつくる際に触りましたが、nuxt は初。何が便利なんだろうってところから一つ一つ理解。

Nuxt に用意された router プロパティで色々カスタマイズできるみたいです。

https://ja.nuxtjs.org/docs/2.x/features/file-system-routing/#router-%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3


# 参考文献
- [Nuxt.js 公式 - ルーティングの基礎](https://ja.nuxtjs.org/docs/2.x/features/file-system-routing/#%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E5%9F%BA%E7%A4%8E)
brew install gcc でつまづいた

ターミナルで、以下のように入力すると

```
brew install gcc
```

次のようなエラーが出る。

```
Searching for similarly named formulae...
Error: No similarly named formulae found.
Error: No available formula or cask with the name "gcc".
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.
```

この通りにbranchを切り替えると解決する
https://github.com/Homebrew/discussions/discussions/708
オリジナルアプリの要件定義(仮)

今日から、オリジナルアプリ(名前は未定)を作成しようと思う。
そのため要件定義をしようと思うので、未経験の人は参考程度にどうぞ。
ちなみに、私も未経験だ！

## 要件定義の項目

- アプリの名前
- アプリの概要
- 制作背景
- ペルソナ
- 必要機能
- 使用ツールと使用言語
- 目標制作期間と実際の制作期間
- 参考アプリケーション(あれば)

私は未経験で、実務での要件定義をしたことはないので、「とりあえずこれくらいは載せた方がいい」と思ったものを選びました。
また、「目標制作期間と実際の制作期間」については、Read.Meに記載する

## アプリの名前
未定
つのるん(募るん)みたいにしようと考えています。
## アプリ概要
参加者を募るためのアプリケーション
タイトル・内容・時間などを入力し参加者を募ることができる
## 制作背景
ポートフォリオを充実させるため。
## ペルソナ
#### 場面
社内ツールを想定。主にPCで使用する。
勉強会でも遊びでも。
#### 人物
年齢：２０〜４０代、幅広く
性別：どちらも
職業：PCをよく使う職業
#### 何の課題を解決できるか
LINEなどのチャットツールでも募ることはできるものの、人数制限など細かいことは自分で確認する必要がある。
主催者側の負担が大きいため、その負担を減らすべく作成。
社内のコミュニケーションにも一役買ってもらう。例えば、「野球しませんか」で募る→Aさんが参加する→Aさんは野球に興味があるということがわかる→話が広がる。
## 必要機能
#### ユーザー管理機能
ユーザー名・メールアドレス・パスワードを使って新規登録
メールアドレス・パスワードを使ってログイン
#### ユーザー情報編集機能
ユーザーの写真・名前を変更できるようにする
#### グループ作成・削除機能
グループタイトル・人数制限・日時・詳細・タグ・準備するものを入力してグループを作成できる
削除ボタンを押せばグループは削除される
#### グループ参加・辞退機能
グループ詳細画面から参加辞退ができる
#### タグ機能
グループ作成時にタグをつける。「途中参加OK」「リモートで」など。
チェックボックスを使う。
#### コメント機能
グループに対して質問などをする
#### メール機能→ユーザー間チャット機能に変更
１対１で話し合える場を設ける。
##### 変更の理由
個人的な意見だが「メール」は少しばかり堅い印象がある。
社内ツールを想定しているので、少しばかりは堅苦しくても良いのだが、連絡の取りやすさなどからもチャットの方がよいと思いました。
## 使用ツールと使用言語
#### 使用ツール
Git/GitHub
Trello
VSCode
Ruby on Rails
heroku
#### 使用言語
HTML
CSS
JavaScript
MySQL
Ruby
## 目標制作期間
全体の目標：１ヶ月間
--各機能の目標実装期間
ユーザー管理機能：1日
ユーザー情報編集機能：1日
グループ作成・削除機能：3日
グループ参加・辞退機能：3日
タグ機能：3日
--各テストの目標実装期間
ユーザー単体：1日
グループ単体：1日
グループ参加単体：1日
新規登録結合：1日
ログイン結合：1日
ログアウト結合：1日
グループ作成結合：1日
グループ削除結合：1日
グループ参加結合：1日
グループ辞退結合：1日

#　おしまい
本当はもっと、細かいところまで決めていくんだと思います。が、未経験がそんな細かいところまで気にしていたら、アプリ作り出す前にモチベーションが消えます。
つまりは、目指すところを重要視しましょう。要件定義とか詳細設計とかの仕事につきたいなら、その辺を全力で。
もしくは、勉強したいところを全力で。

※この要件定義はいずれ編集されます。
【Python】VS Code Run Without Debugging on macOS

# Code の Python プログラム 実行
以下のような方法があります．

1. .ipynb ファイルを Jupyter Notebook 風に実行する
1. Interactive cell を別タブで開く（# %% とスクリプトに書いて shift+Enter or ctrl+Enter）
1. ドラッグで選択して shift+Enter
1. Run メニューに有るコマンドを実行する．

Jupyter Notebook からの移行は１が便利です．最近使っているのは２です．３はあまり使っていません．

今回は４についての記事です．

# もとのコマンドがうまく動かない

^ + F5 と書いてあるのですがうまく動きません．BetterTouchToolでも解決を試みましたがよくわかりません．
実行環境：macOS 10.15.4，Code Version: 1.55.2, Python 3.8.6.


# 解決方法

システム環境設定＞キーボード＞ショートカット（「ショートカット」で検索）＞アプリケーション

と入ります．＋で Visual Studio Code (Finder では Code) にショートカット

```
Run Without Debugging
```

を追加し，⌘Rを紐付けます．これで完了です．
AWS VPCを作成する

##はじめに
AWSの基本サービスVPCの作成方法を備忘録として

##VPCとは
Amazonが提供している仮想ネットワークサービスでVirtual Private Cloudの略です。
リージョンという国や地域単位でデータセンターをグループ化したものを選択して作成します。
今回は東京リージョンを選択して作成します。

今回は作成方法をメインに解説していきます。

##VPCを作成する

[![Image from Gyazo](https://i.gyazo.com/b8c1040b0e9e25d0145d526e7c8fbb1f.png)](https://gyazo.com/b8c1040b0e9e25d0145d526e7c8fbb1f)
VPCを入力して、VPCをクリックします。

[![Image from Gyazo](https://i.gyazo.com/7dcd137b55db666e3e6f9968cd99ce71.png)](https://gyazo.com/7dcd137b55db666e3e6f9968cd99ce71)

VPCのページが表示されました。

[![Image from Gyazo](https://i.gyazo.com/4e67c642ce3760d1b778436a395a2b0c.png)](https://gyazo.com/4e67c642ce3760d1b778436a395a2b0c)
VPCをクリックします。

[![Image from Gyazo](https://i.gyazo.com/43c7f08d1e21c1295f2ffa0bb5f6f1fb.png)](https://gyazo.com/43c7f08d1e21c1295f2ffa0bb5f6f1fb)

VPCの一覧が表示されます。デフォルトのVPCが表示されています。
それでは自分でVPCを作っていきます。
VPCを作成をクリックしてください。

[![Image from Gyazo](https://i.gyazo.com/84d158a1dd651ad575cd5e8b4b2c1ab0.png)](https://gyazo.com/84d158a1dd651ad575cd5e8b4b2c1ab0)

作成画面に移動しました。

[![Image from Gyazo](https://i.gyazo.com/d190393f94e25b2dcf2f6c506bcf616e.png)](https://gyazo.com/d190393f94e25b2dcf2f6c506bcf616e)

任意のVPC名を記入して、
「IPv4 CIDR ブロック」に今回AWSで構築するシステムに割り当てることが可能な以下の範囲内で、/16〜/28のネットマスクCIDRブロックを入力します。
CIDRブロックを今回は10.0.0.0/16に設定。
IPv6CIDRブロックはなし。
テナンシーは、ライセンスやセキュリティ要件でハードウェアを専有したい場合のみ、「専有オプション」を指定します。
テナンシーはデフォルトのままで作成します。

####IPv6 CIDR ブロック
>Amazon 提供の IPv6 CIDR ブロックを VPC に関連付けることができます。Amazon は固定サイズ (/56) の IPv6 CIDR ブロックを提供しているため、IPv6 アドレスの範囲をお客様ご自身で選択することはできません。代わりに、お客様ご自身の IPv6 CIDR を AWS にインポートした場合、アドレスプールから IPv6 CIDR ブロックを指定できます。

####テナンシー
> インスタンスは、シングルテナントの専用ハードウェアの VPC で実行できます。起動時に指定されたテナンシー属性にかかわらず、この VPC で起動されたインスタンスが専有テナントインスタンスであるようにするには、[専有] を選択します。この VPC で起動されたインスタンスが起動時に指定されたテナンシー属性を使用するようにするには、[デフォルト] を選択します。

[![Image from Gyazo](https://i.gyazo.com/7b9d547303f24bb9b1f27d0bc9024b8f.png)](https://gyazo.com/7b9d547303f24bb9b1f27d0bc9024b8f)

VPCを作成をクリックします。

[![Image from Gyazo](https://i.gyazo.com/a9d53030be7a95d51e1f2350fdef8699.png)](https://gyazo.com/a9d53030be7a95d51e1f2350fdef8699)

VPCが作成されました。

お疲れ様でした。
次はサブネットを作成します。


>参考サイト
[AWS　VPC の作成と設定](https://docs.aws.amazon.com/ja_jp/directoryservice/latest/admin-guide/gsg_create_vpc.html)
[Qiita 0から始めるAWS入門①：VPC編](https://qiita.com/hiroshik1985/items/9de2dd02c9c2f6911f3b)
[[初心者向け]VPC作成からEC2インスタンス起動までを構成図見ながらやってみる（その1）](https://dev.classmethod.jp/articles/creation_vpc_ec2_for_beginner_1/)
【解消】プルリクエストでコンフリクトが発生してしまう

※備忘録です。
コンフリクト解消にかなり手こずってしまったため、手順を記録しておきます。

◆実現したいこと
・プルリクエストをコンフリクトなく実行できるようにしたい

◆現状
・プルリクエストを実行すると、コンフリクトを解消してくださいと怒られてしまう。

◆原因
・正しいブランチに正しい順序でプルリクエストできていなかった。
・間違った状態でコマンドを実行しすぎてしまい、gitの状態がぐちゃぐちゃになってしまった。

◆解決方針
・Gitをぐちゃぐちゃになる前に戻す
・コンフリクトを手動で修正する

◆解決手順
・現状のブランチの状況を確認する 
>$ git branch

・gitの状態をある特定の場所まで戻す
>$ git reset --hard URL

※URLには、戻したいgitバージョンのURLを貼る。URLはgithubから確認できる

・特定の場所まで戻れたら、いらなくなったコミットを削除する
>$ git revert URL

※git logでもURLを確認できる

----- ここまでで、ぐちゃぐちゃになってしまったものを、整えることができた。
----- ここからは、コンフリクトの解消へ進む

・本流へ移動
>$ git checkout [main] ※[]の中には、使っている名称を入力する

・ローカルリポジトリにブランチをマージする
>$ git pull

・新しく本流からブランチを切り出す
>$ git checkout -b [feature/test-solve-conflict]　

※[]の中には、自分で決めたブランチ名を入力する
※新しく本流からブランチを切り出す理由は、問題をシンプルにしたかったから。本流のリポジトリでは、チーム開発の進み具合によっては更新が進み、コンフリクトが積み重なってしまう可能性がある。それを避けるため、コミットする前に最新版をgit pullして、古いブランチをそのまま使うのではなく、新しいブランチを切り出して使う。

・コミットを書き換える
>$ git merge --squash [feature/test] 

※[]の中には、もともと使っていたブランチを入力する。

-----　ここでコンフリクトを手動解消

・改めてプルリクエストを行う
>$ git add *
$ git commit
$ git push origin feature/test-solve-conflict

コンフリクトを正しく手動修正できていれば、コンフリクトすることなくプルリクエストができるはず。

以上
第30回　JSTQB認定テスト技術者資格 Foundation Level　を受験する

#【前回の顛末】

以前、記事を書いたまま、合否を載せずにいた、28回目のJSTQBは落ちました。。。。
第28回　JSTQB認定テスト技術者資格 Foundation Level　を受験してみた
https://qiita.com/Ashi_mo/items/e3731284a1e9ed7a96a5
自分の記事をチラッと読んで、ああ、こんなこともあったなぁと。
第29回はですね、主催者が大幅に受験者数を減らしたようで、全然申し込みに間に合わなかったです。見に行ったら受付終了してた温度感。

なので第30回こそは受験するぞと。（合格するぞじゃない。残念ながら。）
申し込み開始はいつなのかなぁと緊急事態宣言真っ只中のゴールデンウィークにWebサイトを見に行ったら。
http://juse.or.jp/sqip/qualification/jstqb/foundation.html
申込期間：2021年5月7日（金）15：00 ～ 6月22日（火）15：00（予定）

え。
三日後じゃん。
そして試験は三ヶ月後（8月22日）か。。。。
いまQAの仕事をちょっと離れているので、自分の本職の試験は10月と2022年の2月に受けるため、8月受験はタイミング的にも狙える。

申し込んでみよう。高いけど。

#【前回の教訓】
前回受験してみて分かったこと。

<ol>
<li>「ソフトウェアテスト教科書 JSTQB Foundation 第4版 シラバス2018対応」
https://www.shoeisha.co.jp/book/detail/9784798161235
を暗記すれば受かる。</li>
<li>上記の書籍のサンプル問題どおりの出題のされ方をする。</li>
<li>ひっかけ的な問題がない。まっとうなことを聞かれるので、普通に答えれば良い。</li>
</ol>

落ちたのにえらそうなことを書いていますが、試験直前から一ヶ月集中して試験勉強をやり続ければ100%受かります。
わずかな期間ではありましたが、QAの仕事に少し携わったので、どうしてもこういう試験に合格して証明したい。性格ですね。

当時自分が作った単語帳やテキストを一式倉庫から引っ張り出してみました。
どう見ても当時の実務と結びつかないけど、QAとしてまず受ける試験がJSTQBのFoundationだというのであれば、受験しましょう。そして合格しましょう。

前回の反省点。3ヶ月前から始めて1ヶ月で受験できるレベルまで知識を揃えたあと、やる気が下がって残り2ヶ月何もしなかったこと。それは落ちますね。

なので、2021年8月の受験は、7月22日に試験勉強を開始しようと思います。
試験によっては半年かけるなんていうこともありますが、JSTQBのFoundationは短期決戦。
なぜなら、カタカナが多くて似た言葉も多くて、理解している暇はないから。
受かればよい。ただそれだけのために一ヶ月頑張ろうと思います。

試験が終わったら、合否がどっちであれ、知識がすべて抜け落ちる自信がある。
なのになぜ受けるんだろう。
受験しなければ気がすまないこの性分を、ビジネスの新しいひらめきに是非活かしたい。。。。。
AWS Iot EduKit Lチカを消灯できるようにしてみた

Lチカは止めたら消灯するでしょと思われた方、AWS IoT EduKit の[Lチカ](https://edukit.workshop.aws/jp/blinky-hello-world.html)は違うんです。はい、いつ止めてもLEDが点灯したままになります。

AWS IoT EduKit のLチカは、[M5Stack Core2 ESP32 IoT Development Kit for AWS](https://ssci.to/Core2_for_AWS) の左右にあるLEDを交互に点灯させることによって、点滅が実現されています。このため、点滅を止めると、片側のLEDがつきっぱなしになるというわけです。

[AWS IoT EduKitの説明](https://edukit.workshop.aws/jp/blinky-hello-world/blinking-the-leds.html#ledの点滅)では、「点滅を一時停止する(pause the blinking)」といっているだけですので、決して間違ってはいません。いつとめても片側のLEDがつきっぱなしでも、Lチカは止まっているのですから。でも、何かが違います。

なので、一時停止時に両側のLEDが消灯するように直してみました！

# AWS IoT EduKit の Lチカの動き
AWS IoT EduKit の Lチカは、

  1. サブスクライブしているMQTTトピックを受信すると、左右にあるLEDを交互に点灯
  1. もう一度トピックを受信すると、一時停止
  1. 1.に戻る

のように動きます。交互に点灯しているのを一時停止するだけですので、片側のLEDはつきっぱなしになります。これを、タスクの処理で表すと、

- LED点滅タスクで、
  1. サスペンド
  1. 両側のLEDを消灯(※)
  1. 左右のLEDを交互に点灯（これを永久に続ける）

- MQTTタスクで、サブスクライブしているMQTTトピックを受信した時、
  1. LED点滅タスクがサスペンドしている時、LED点滅タスクをレジューム
  1. それ以外の時、LED点滅タスクをサスペンド

となります（※印の処理が必要なのかは謎です）。タスクの起床から見たい方は、[AWS Iot EduKit Lチカの処理](https://qiita.com/tosihr/items/d62962bd11abaac59e4a) をご覧いただければと思います。

# 一時停止時に両側のLEDが消灯するようにするには

MQTTタスクでLED点滅タスクをサスペンドするのをやめて、LED点滅タスクで消灯してからサスペンドするようにします。

MQTTタスクでは、サブスクライブしているMQTTトピックを受信したときに、iot_subscribe_callback_handler() がコールされます。LEDが点滅している時に、LED点滅タスクをサスペンドするのではなく、通知を送信するだけにします。

```diff:main.c&#058;&#058;iot_subscribe_callback_handler()
--- 変更前
+++ 変更後
@@ -117,7 +117,7 @@ void iot_subscribe_callback_handler(AWS_IoT_Client *pClient, char *topicName, ui
         if (blinkState == eSuspended){
             vTaskResume(xBlink);
         } else{
-            vTaskSuspend(xBlink);
+            xTaskNotifyGive(xBlink);
         }
     }
 }
```

LED点滅タスクでは、その処理関数 blink_task() で通知を受け取ったら、消灯して自分でサスペンドするようにします。

```diff:blink.c&#058;&#058;blink_task()
--- 変更前
+++ 変更後
@@ -35,6 +35,12 @@ void blink_task(void *arg) {
         Core2ForAWS_Sk6812_Show();
 
         while (1) {      
+            if (ulTaskNotifyTake(pdTRUE, 0)) {
+                // Clear LED and suspend blinking
+                Core2ForAWS_Sk6812_Clear();
+                Core2ForAWS_Sk6812_Show();
+                vTaskSuspend( NULL );
+            }
             Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0x000000);
             Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0xffffff);
             Core2ForAWS_Sk6812_Show();
```
変更前のソースは、https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/blob/master/Blinky-Hello-World/main にあります(2021年4月6日の更新版にて)。

# まとめ
ということで、AWS IoT EduKit のLチカを消灯できるようにしてみました。結果は単純なのですが、[ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/index.html) やら [FreeRTOS](https://www.freertos.org/) やらを調べて、ここまでが結構長かったです。おかげで、取っ付きづらかった AWS IoT EduKit のソースコードに少し慣れてきました。LEDがつきっぱなしで、同じように困っていた方の参考になればうれしいです。
Qiitaでの簡単なMarkdown表形式

#はじめに

Markdownで表形式を作ろうとしたが、はっきり言って、|||で表を作るのは普通に手間。

何か便利な方法がないかと探すと、やっぱり自動で変換してくれる便利なツールが公開されていた。

https://markdown-convert.com/ja


# MarkdownConvert

表を作るとき、一旦Excelで表を作り、その表を、「MarkdownConvert」へコピペすると、自動でMarkdown表記へ変換してくれる。
そして、それをQiitaへ張り付ければ完了である。
下記の表が一瞬で出来上がった。

|A|B|C|
|:----|:----|:----|
|ナス|イチゴ|チンジャオロース|
|キャベツ太郎|かば焼き太郎|ぶどう|
[SQL] LeetCodeの無料問題集を活用して、SQLを使いこなし（6）

#Q182 Duplicate Emails
![Q182.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/0a1bcc92-89b2-18fb-e617-c8cedb5974c3.png)

##質問
重複なメールアドレスを探します。

##Code書き方のHint
count関数とhavingを組み合わせて、重複のデータが探せます。
※WHEREはCOUNT関数と一緒に使えない。

SELECT 列名　FROM テーブル名
GROUP BY 列名
HAVING COUNT(列名)>1;



##Code
```SQL
SELECT Email FROM Person
GROUP BY Email
HAVING COUNT(Email)>1;
```


##Result
![Q182_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/640e12df-0372-ff23-aadb-b0d4af95c906.png)