OmniAICreator/Qiita-1.07M huggingface dataset:
「新・明解Pythonで学ぶアルゴリズムとデータ構造」で勉強日記#1

[「新・明解pythonで学ぶアルゴリズムとデータ構造」](https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%9F%B4%E7%94%B0%E6%9C%9B%E6%B4%8B/dp/4815603197/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1BG3JS7CKMZA0&keywords=Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0&qid=1644336329&sprefix=python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0%2Caps%2C212&sr=8-2)にてプログラミングをどう攻略していけばいいのか悪戦苦闘中。

手助けをしてくれる人がいるのならお金を出してでも所望したい気分デスネ。

さて、今日から、上記の本にて学んだことをまとめておきます。
本来はド頭からやるべきですが、なんとなく繰り返し処理からでいいかなーと思ったので、ここからスタートします。もし振り返ってめっちゃ重要なこと書いてある―！って思ったら追加編集しようと思います。


繰り返しについての部分からになります。（P14の2-1）

以下はすべて同様の処理を別表記にしているみたいですね。

#1からnまでの総和を求める。
最初のお題でありがちなやつですね。（総和をどこで使うのかよくわかってない( ;∀;)）
ここではwhile文とfor文それぞれの表記をしてくれています。

```python:list1-7
#1からnまでの総和を求める。while文

print('1からnまでの総和を求めます')
n = int(input('nの値:'))

sum = 0
i = 1

while i <= n:
    sum += i
    i += 1
    
print(f'1から{n}までの総和は{sum}です。')
```

```python:list1-8
#for 文

print('1からnまでの総和を求めます')
n = int(input('nの値:'))

sum = 0
for i in range(1, n + 1):
    sum += i
        
print(f'1から{n}までの総和は{sum}です。')
```
for文にすると簡潔に書けますね…。正直while文の存在意義はどこにあるのか初学者の私には見当もついてないです。
実はラスボス戦で効いてくるポジションなのかな？
わかる方がいればコメントください。


そして、おまけでガウスの法則版を載せます。

```python:EX16
#ガウスの法則
print('1からnまでの総和を求めます')
n = int(input('nの値:'))

sum = n * (n + 1)//2
        
print(f'1から{n}までの総和は{sum}です。')
```

今回学びになった点は、数学の偉大さですね。

なんちゃって理系なので、ガウスの法則とか覚えてなかった…。

内容薄いですが、ありがとうございました！
Javaのパッケージについてまとめてみた

Javaのパッケージについてとりあえずまとめてみようと思います。
packageは見たことあると思います。
初めてプログラミング学習をしたときに見る、classの先頭についている

```
package 'HogeHoge'
```

のようなやつです。

今回はこれが一体何なのか調べてみたので初心者ながらまとめてみようと思います。

パッケージというのは、

```
ソースの処理は違うが、役割は同じものをまとめたもの
```

です。
よくあるものとして、
「複数のクラスが一つになって行う処理をまとめて管理できるようにしたい」
といったものがあります。
小さいアプリケーションであればいいのですが、Javaを使っていくということは大規模なものを作っていきます。
クラスの数も100以上になっていくでしょう。
そんなときに継承を點せまくってみたらあっという間にスパゲッティな状態になります。

そうならないために、Javaのpackageは役に立つのです。

#やり方

packageを宣言するには、まずpackage文というものを作り作成していきます。
まず最初に、packageを作るときの命名の基礎について話していきたいと思います。

##命名のやり方

packageを命名するときは、そのパッケージの位置から逆に書いていきます。
どういうことかというと、
そのpackageを宣言しているファイルの位置が、上から見て4番目であれば

```
package宣言したいクラスのファイル.その上.その上.その上
```

のように宣言します。
そして、そのpackageを格納するファイルは、必ずpackageで指定したパスの中に入れないといけません。

ちなみに、、

#追加で知っておいたほうがいいimport文について

importというのは、クラスの処理を別のクラスで使いたい時にimport文を使えばそのクラスを呼び出すことができます。
実は、import文を使わなくても実は呼び出すことができます。

その方法は、そのクラスのパスを

```
class sample {
  public static void main(String[] args){
    //クラスのパスを指定する。
  	java.time.LocalDate ld = java.time.LocalDate.now();
    System.out.println(ld);
  }
}
```

上記のコードのように、クラスのパスを指定してあげればいいです。ただ、これだといちいち指定してあげなければいけないので、非常に面倒くさいです。それにタイピングをミスってエラーのもとになります。
そんな時にimport文で宣言します。

```
import java.time.LocalDate;

class sample {
  public static void main(String[] args){
    //クラスのパスを指定する。
  	LocalDate ld = LocalDate.now();
    System.out.println(ld);
  }
}
```

こうすることで、このクラスが書いてあるファイルのなかで何回でも使い回すことができます。

そして、import文の書き方を紹介していきたいと思います。

import文を書くときに二種類書き方があります。

・パッケージに含まれるうちの一つのクラスを指定する場合。
・パッケージに含まれるすべてのクラスを指定する場合。

では、前者の書き方から紹介していきたいと思います。

##パッケージに含まれるうちの一つのクラスを指定するやり方

これは単純に、ドメイン(そのクラスの所在地)から逆の順番で指定して上げればいいだけです。先程出した例で、`import java.time.LocalDate;`のように指定してあゲレば大丈夫です。

次に、packageのすべてのクラスを指定するやり方を消化しいます。

#packageに含まれるすべてのクラスを指定する場合

その場合は、指定しているpackageのあとに、*をつけるだけです。
例えば、先程例に出したコード(import java.time.LocalDate;)で、timeパッケージのすべてのクラスを指定したい場合は

```
import java.time.*;
```

と指定します。

とりあえず以上になります。

指摘点などあれば、コメントなどに書いていただけると嬉しいです。
生医科学専攻の大学生がTECHCAMPをやった訳　〜第一章〜

今週は、生医科学専攻の大学生が、TECHCAMP転職コースを受けた理由について説明します❗️

学生でプログラミングを習いたい人、TECHCAMP転職コースを考えている人、などの役に立てたらと思います。

第一章は、TECHCAMP転職コースを決断するまでの流れ。
第二章は、実際やってみて、TECHCAMP転職コースのメリットデメリット。

5分で読めるよう、簡潔に書きます🙂👀。

1. プログラミングを始めたきっかけ
-----------------------------------------------------------------------

・楽しかったから：
講義で初めて触れたとき、楽しくて興味湧いて何時間もできたから

・やったら得するって思ったから：
AI時代・エンジニアの不足・技術者強し(最近思った）

・時間や場所を選ばずできちゃう：
バイト先が電車+徒歩で20分以上かかることが嫌だった。
電車だから時間的縛りがあるし、帰省したらバイトできないし、、、それがすごい嫌だった。

・コードは世界共通語：
これは大きい。
海外で働きたいから、海外でも通用する技術が手に入るのは魅力だった！


⇨⇨⇨
この観点から、専攻とは関係ないけど、本格的にプログラミングの勉強を始めました❗️
高額だけど、大きな挑戦だけど、やりたいからやった、それだけです。

プログラミング学習しようかなって迷っている方、課金するのどうしようって悩んでる方、
メリットとデメリットを天秤にかけて考えてみて👏🏻🍀。


2.TECHCAMP転職コースを選んだのはなぜ？
--------------

[TECHCAMPを選んだ理由]
・スクール大手で、信頼度が高かったから
・多くの情報集めの結果、一番評価高かったから
・（本田圭佑さんがここを選んでいたから）

[転職コース(自分のペースで学べる教養コースでなく）を選んだ理由]
・やるなら一度にやりたかったから
・厳しい方がやる気出るから

教養コースと転職コースの違いはこちらから
→https://dkssksk.com/tech-camp-liberal-arts-job-change-difference/



⇨⇨⇨
こうして、大学2年の冬、TECHCAMP転職コースに通う決断をしました。

家族にも、友達にも相談せずに、自分で決めました。
大学の費用が高いのに、自分のやりたいことにさらに親に負担をかけるのは絶対嫌で、勝手に決めました。全く自慢じゃないけど、全部自分のお金。(車買えます😅笑）

それでも全然後悔ないのは、

TECHCAMPで学習でき、プログラミングが楽しく続けられたから。
自分がやりたいことに対して、自分の力で行動し、完走できた経験を得られたから。



3.将来の夢
--------------

今の夢は、プログラミング技術を持ったエンジニアになること。そして、技術蓄えて、海外でエンジニアとして働くこと！
今の目標は、継続的な学習をすること。


4.最後に
--------------

ここまで読んでいただきありがとうございました。
私もプログラミングを勉強する時や、スクールを決める時は多くの方の意見を参考にしました。その時のように、この記事が多くの方の参考になれたら嬉しいです😊。

これが聞きたい、とかあったらコメントください🙏🏻🌞
Safariのブックマークツールバーにfaviconが表示されていない。

#Safariのブックマークって文字だけで視認性が悪くない？

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128851/f563b15c-905f-36fb-c079-36e8ef6763ef.png)

そうだ、こんな時のemojiだ。

![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128851/589f585f-9ecd-95cd-e83d-54f6073cbfe2.png)

めでたしめでたし。
電流計をスピードメーターとして動かしてみる

書泉や東急ハンズで販売されていた電流計を速度計とみなして動かしてみます。
電流計を速度計と変える事で、そのまま速度計を動かすことが出来ます。
##速度計
速度計や電流計は、電流制御の為、抵抗を挟むことで電圧に応じてメーターが動くようになります。
![DSC_0905.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a0f72a24-a468-2c58-6c8c-372e2023e209.jpeg)
##ステーの製作
ステーを3Dプリンターで製作しました。
![DSC_0911 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/048e93bb-c77f-0613-30b9-c0190571f776.jpeg)
##組立
製作したステーにメーターを取り付けました。
##ハーネスの製作
電流計とマイコンをつなぐハーネスを製作します。
![DSC_0527 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e80b9633-cad9-a10d-85a8-7919ef40bde1.jpeg)
#マイコンの準備
今回はESP32を使用します。
ESP32には2つのDACがあり、DACと無線機能が使えるから選択しましたが
メータを3種類使用する際にはPWMに変更しています。
このため通常の使用であればPWMやAnalogWriteが使える普通のマイコンの方が良いといえます。
#制御抵抗の追加
ESP32のDACと速度計の間に、抵抗を挟みます。
電流は2.5~5mA程度のようです。
3.3Vから2.5mAを生成するには1.32kΩ、５ｍＡは0.66kΩとなります。
この為メータに合わせて、１～２ＫΩ程度の可変抵抗を使用します。
なお、抵抗値は確定していない為、可変抵抗を入れることをお勧めします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d699c3e7-f7d7-e340-e561-c2d4f30eb732.png)

#プログラム
下記プログラムはESP32のdacWriteを使用したものです。

```
/*
   Copyright (c) 2018, circuits4you.com
   All rights reserved.

   ESP32 DAC - Digital To Analog Conversion Example
*/

#define DAC1 26
int Value = 255; //255= 3.3V 128=1.65V

void setup() {
  Serial.begin(115200);
}

void loop() { // Generate a Sine wave
  dacWrite(DAC1, 255);
}
```
#可変抵抗を調整する
なおプログラムを動かす前に、可変抵抗を最大にしておきます。
これはメータの針が振りきれることを防ぐためです。
可変抵抗を調整して最大出力の状態と表示する最大値を一致させます。
今回は、120Km/hを最大として設定しています。
OSINT Tip: How to download Tiktok videos

#紹介
Tiktokは若年層に人気のSNSです。

TwitterやFacebookと違って、Tiktokで主体となるものはユーザーが投稿する動画です。

もちろん動画を通じてコメントを投稿できるし、友達とプライベートに会話することも可能。

OSINTでTiktok調査をするとき、必ず動画をダウンロードしたいところですが、通常ではブラウザではダウンロード
ができません。

アプリではダウンロードできますが、時間制限や、背景に文字が写っていたりと、アプリ側で強制的に制限が
かかってしまいます。

今回は、それら制限なしに動画をダウンロードできる方法をご紹介します。

注)PC専用。今回ご紹介する方法は携帯端末ではできません。


#環境

Macbook Pro
Google Chrome

#方法

1:まずはTiktokのページにアクセス。
事前にアカウントを作成しておくように。
https://www.tiktok.com

2:適当に動画をクリック。

3:動画を読み込んだら右クリックして「検証」をクリック。
そうすると、HTMLの<video src>欄の、**v16-webapp.tiktok.com** が見えるはず。

![スクリーンショット 2022-02-07 21.11.17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/d4dd05b0-618f-29eb-ae16-581bdcf7b507.jpeg)

ここを右クリックして「新しいタブで開く」で移動。

4:「名前をつけて動画を保存」でダウンロードできる。

#感想

アプリの時間制限でイライラしてたからやっと解放された〜
HaskellでFlappy Bird 作ってみた


![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597046/ae875b7d-87b2-25a0-fbbc-626455ca2571.gif)

#はじめに

Haskellの練習がてらプラッピーバードを作ってみました。
モナドでかっこよくできたら良かったのですが、まだモナドを使いこなせるレベルではなかったです。
Haskellの練習をしたい人の参考になれば幸いです。


#プログラムの良くない点

良くない点はたくさんあると思いますが、個人的にだめだと思っている点をメモしておこうと思います。

###1.何回もループしていると画面がカクつく
これは推測ですが、ガベージコレクタが動くときに画面描写用のスレッドがそちらに回されることで描写が遅くなっているのではないかと思います。なのでコンパイルプラグを変えればなにか変わるのかもしれません。

###2.スコアの保存方法が良くないと思う
最高スコアを保存するようにしているのですが、整数を直接ファイルに書き込んでおりどうなのかと思っています。


#遊び方
1. stackのインストール
https://qiita.com/usamik26/items/672ed3c4451402bfc275

2. ダウンロードと実行

```bash
$ git https://github.com/Kohei-Wada/bird.git
$ cd bird
$ stack run 
```
3. マウスをクリックすると羽ばたきます


#参考
グラフィックライブラリはこの記事を参考にしました。
https://qiita.com/lotz/items/eb73e62a64bc208c2dd6

素材はここから借りました。
https://github.com/Rydgel/flappy-haskell
Twitter API(v1) 経由でスレッドを作成する際の挙動

# API 経由でのスレッド作成方法

まず、「API 経由でスレッドを作成する」という用途で用意された API エンドポイントはなかった。

[php - Twitter api - is it possible to post a thread? - Stack Overflow](https://stackoverflow.com/questions/51563995/twitter-api-is-it-possible-to-post-a-thread)

リプライを利用して実現する。エンドポイントは、 [POST statuses/update](https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update)。

PHP のライブラリである [TwitterOAuth](https://twitteroauth.com/) を利用すると、以下のようになる。

```
$statues = $connection->post(
            "statuses/update",
            [
                "status" => $message,
                "in_reply_to_status_id" => $tweet_id
            ]
        );
```

"in_reply_to_status_id" には、リプライ元のツイートの ID を指定する。 ID はツイートを表示した際の URL で確認できる。下記であれば ID は 20。

[jack⚡️さんはTwitterを使っています 「just setting up my twttr」 / Twitter](https://twitter.com/Jack/status/20)

# メンションのありなしによる挙動の違い

なお、 `$message` に指定するメッセージにおいて、 `@someone` (メンション) をつけるか否かで挙動が変化することを確認した。

スレッドとして表示されるのはどちらも同じであるが、フォローするユーザのタイムラインに現れるかどうかが異なる。

スレッドを利用する場合はユーザのタイムラインに表示されたほうがいいケースが多いと思うので、メンションなしでツイートするとよい。

## メンション付きの場合

ユーザのタイムラインには現れない。

## メンションなしの場合

ユーザのタイムラインに現れる。
Salesforceのダッシュボードを自動翻訳するコツ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2262/df8f7860-5014-1a1e-f4f0-680542dd6e46.png)

## 背景
Salesforceアプリのホームページに表示されているダッシュボードを自動的に翻訳するのは可能かどうかを検証してみました。
## アイデア
ダッシュボードを翻訳するのは画面全体を翻訳するということなので、Webページあるいはコンポーネント全体を翻訳するという選択肢があります。
全ページの単語を検出し、取得　→　翻訳APIに投げて　→　翻訳結果を再度画面にレンダーリングするということができるかもしれませんけど、時間かかるし面倒なので今回はやりません。
## Google翻訳
今回使ってるのはGoogle翻訳です。Google翻訳にはGoogle翻訳APIがありますが残念ながらAPIにはページ全体の自動翻訳機能がありません。
Google翻訳では以下のようにWebページ全体を自動翻訳するボタンを配置することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2262/47e1ab8a-3c72-7e3d-c083-d69c54b508e7.png)
しかしどうしても言語選択は手動で行うし、上記の画像のようにダサいバナーwも表示されてしまうので、少し改善する必要があります。
## 課題
第一のアイデアを検証してみましたが、Salesforceアプリページの画面全体を自動翻訳させることは不可能でした。

- LWCで実装するとしたら、まず外部スクリプトをダウンロードし静的リソースとして扱わない必要があります。しかしそれを実装しても[LWCのロッカーSafety](https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/security_code.htm)に引っかかってしまって `window` オブジェクトの下をアクセスすることができませんでした orz
- Visualforceで実装したら、VFページのコンポーネントは `iframe`に包み込んでるので画面全体の制御は `parent`を使わないといけないですが、`parent`の直下をアクセスしようとすると `cross-origin`のエラーが出てしまいましたのでアクセス不可になってました。

## 課題の解消
どうしても画面全体を自動翻訳ができないなら、コンポーネント内にチャートを手動で表示させて自動翻訳を行うしかりませんね。

## さあ、実装しよう
- まずはVisualforceにチャートを追加します。「[analytics:reportChart](https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_compref_analytics_reportChart.htm)」のタグでこんな感じで追加できます

```html
<analytics:reportChart reportId="00O2r0000013tzPEAQ" size="large" showRefreshButton="false" hideOnError="false">
    </analytics:reportChart>
```

- 自動で翻訳するということで、日本語環境のユーザは翻訳しないというフィルタリングをしないといけません。Apex上ではこんな感じでユーザの環境の言語を取得することができました。

```apex
User u = [SELECT toLabel(LanguageLocaleKey) FROM User WHERE Id = :UserInfo.getUserId()];
language = u.LanguageLocaleKey;
```

- その後Google翻訳の枠を用意

```html
<div id="google_translate_element"></div>
```

- 英語環境であれば翻訳開始し、Google翻訳の選択ボックスを自動的に英語選んでその後Google翻訳のバナーと選択ボックスを非表示させます

```javascript
<script type="text/javascript">
  function googleTranslateElementInit() {
    if ('{!language}' == 'English') {
      new google.translate.TranslateElement(
        {
          pageLanguage: 'ja',               // Webサイトの言語
          includedLanguages: 'en', // 翻訳する言語
        }, 'google_translate_element');
      setTimeout(function () {
        var select = document.querySelector('select.goog-te-combo');
        select.value = "en";
        select.dispatchEvent(new Event('change'));
      }, 2000)
      setTimeout(function () {
        const el = document.querySelector('#google_translate_element');
        el.style.display = 'none';
      }, 2500);
    }
  }
</script>
```

- Google翻訳のスクリプトを落として上記の関数をコールバックとして設定します

```html
<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
```
- 最後にバナーを非表示するためのCSSを追加します

```css
.goog-te-banner-frame.skiptranslate {
  display: none;
}
```

##感想
現状はこんなに苦労して実現することができましたが、将来的にGoogle翻訳APIにWebページの翻訳の機能をすごく期待してます。
DeepRacer 報酬関数について

# はじめに
DeepRacerでタイム向上を狙う上で最も重要となるのが報酬関数になると思います。
初期状態だと下記のように「track_width(トラックの幅)」と「distance_from_center(車体の中心とトラックの中心の距離)」しか使用していなく、これだけではコースアウトばかりでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239199/9767f8d0-2a76-7177-ca15-05d10f6f042f.png)

しかし報酬関数について調べても関数1つ1つに対して詳細に記載があるページは少なかったです。。。
[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/deepracer/latest/developerguide/deepracer-reward-function-input.html#reward-function-input-all_wheels_on_track)に記載がありましたがすぐにコーディング出来る程の記載はありませんでした。



そこで報酬関数について自分で調べて検証をした結果をここにまとめていこうと考えました。

そもそもDeepRacerってなに？どうやって始めるの？という方は、同じ会社の先輩が記事にまとめているのでそちらをご覧ください。
https://qiita.com/toma_shohei/items/be1ff2549c99f026829b
https://qiita.com/toma_shohei/items/a79abd8d71a2e284273f

# 報酬関数リスト
調査・検証が出来次第、詳細記事を書いて下記リストにリンクをつけていければと考えています。
更新まで少々お待ちください。。。
まずは比較の基準として報酬関数無しでモデルを作成して検証してみました。

- [報酬関数無し](https://qiita.com/trente_saito/items/6e7902e43cd500d75a05)
- all_wheels_on_track [Boolean]
    - 車両のすべてのホイールがトラック内にあるかを示します。
- x [float]、y [float]
    - シミュレーション環境の左下隅を原点として車両の座標を示します。
- closest_objects [int,int]
    - 車両に最も近い2つの障害物の位置(x,y)
- closest_waypoints [int,int]
    - 車両に最も近い2つのウェイポイントの位置(x,y)
- distance_from_center [float]
    - 車両の中心とトラックの中心との距離
- is_crashed [Boolean]
    
- is_left_of_center [Boolean]
    - 車両がトラックの中心より左側にある場合はTrue、右側にある場合はFalseを返すフラグです。
- is_offtrack [Boolean]
    
- is_reversed [Boolean]
    
- heading [float]
    
- objects_distance [float]
    
- objects_heading [float]
    
- objects_left_of_center [Boolean]
    
- objects_location [float,float]
    
- objects_speed [float]
    
- progress [float]
    
- speed [float]
    
- steering_angle [float]
    
- steps [int]
    
- track_length [float]
    
- track_width [float]
    
- waypoints [float,float]
DeepRacer 報酬関数無しで学習→評価をするとどうなるのか

# はじめに
報酬関数の比較をするうえで元となるデータが必要でした。
色々調べても報酬関数無しの評価データはさすがに見つかりませんでした。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239199/a886a437-43ae-b5e6-b209-ce2cd679c045.png)

DeepRacerはどんなに報酬関数を作りこんでも、報酬関数無しでも1時間$3.5の料金がかかるのであまり無駄な学習・評価したくないものですよね。。。

# 報酬関数無しでモデル作成

という事で自分で検証してみます！
報酬関数はどんな走りをしても同じ値が返るようにしてモデルを作成し、1時間の学習→評価をしました。

```
def reward_function(params):
    reward = 1e-3
    return float(reward)
```

# 報酬関数無しの結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239199/7c20ec33-0dcc-7c5d-f787-533decaeba1b.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2239199/3b1e9cb1-a6dd-d313-9c22-ad194f2ebe10.png)

結果はもちろん完走など出来ず、毎回大きなカーブを曲がり切れずにコースアウトをしていました。
しかしどんな走りをしても同じ報酬なのに一応コースに沿って走ろうとはしてくれるんだなーという発見もありました。

という事でコースにもよりますが今回のコースだと何もしなくても29％は走ってくれるという結果を今後の報酬関数の実装をする上での一つの判断基準としていきたいと思います！
【Laravel】戻るボタンの実装（メモ）

https://kaiblo.com/%e3%80%90laravel%e3%80%91%e6%88%bb%e3%82%8b%e3%83%9c%e3%82%bf%e3%83%b3%e3%81%ae%e5%ae%9f%e8%a3%85%ef%bc%88%e3%83%a1%e3%83%a2%ef%bc%89/

こちらに移動しました。
カスタムフィールドで数値を3桁区切りでカンマを自動でつける

カスタムフィールドで金額を入力する項目を出力する際に、自動で3桁区切りでカンマをつけたいことがあったのでメモ
。

PHPの``number_format();``を使用する

```php
<?php
$price = number_format(get_field('フィールド名'));
$minute = get_field('フィールド名');
echo "¥{$price} / {$minute}min";
?>
```
参考記事 → https://www.web-myoko.net/blog/wordpress/comma-separated-number-advanced-custom-fields-wordpress/
Qt Creatorでデザインモードにできない

# QtQuickでデザインモードにできない  

QtWidgetではデザインモードが開けるのに，QtQucikではデザインモードが開けない

# 解決方法

QmlDesignerがデフォルトでは無効化されているのでHelp->About PluginからQMLDesignerを有効にして再起動する．
内包表記覚え書き

メモ程度に
基本的には`[ 式 for 変数 in 入力したいデータ(イテラブルなオブジェクト)]`の形式をとる。(少しmap関数っぽい)
# リスト内包表記
リストを生成する際に用いる内包表記、
形式は`[ 式 for 変数 in イテラブルなオブジェクト]`

```python:例
# [1,2,3,4,5]を作成したい場合
# appendを使った場合
li = []
for i in range(1,6):
    li.append(i)
# 内包表記を使った場合
li = [i for i in range(1,6)]
# データを式に代入することも出来る
li = [i*2 for i in range(1,6)]
print(li)
# [2,4,6,8,10]
```
また`if`などの条件式も用いることが出来る
## ifを用いた内包表記
式の部分へ`if`を書くかと思いきや、for節の後に置くことになる。

```python:例
li = [ i for i in range(1,6) if i%2 == 0]
print(li)
# [2,4]
```
しかし`else`を含む条件を書きたい場合は位置が変わる。(リストに入力される式へ配置する)
`[ i if節 else節 for 変数 in イテラブルなオブジェクト]`

```python:例
li = [i if i%2 == 0 else i*2 for i in range(1,6)]
print(li)
# [2, 2, 6, 4, 10]
```
どうやらifを含むと内包表記の特徴である処理速度が若干落ちるらしい
# 辞書における内包表記
辞書でもリスト内包表記の様に生成できる。
形式は`{ key:value for 変数 in イテラブルなオブジェクト}`

```python:例
# { "No1":"A", "No2":"B", "No3":"B" }を作りたい場合
#単純に代入していく時は
key = ["No1","No2","No3"]
val = ["A","B","C"]
dic = {}
for i in range(len(key)):
    dic[key[i]] = val[i]
# zipを使う場合
key = ["No1","No2","No3"]
val = ["A","B","C"]
dic = dict(zip(key,val))
# 内包表記
key = ["No1","No2","No3"]
val = ["A","B","C"]
dic = {i:j for i,j in zip(key,val)}
```
例によって条件式も使える
## 辞書内包表記におけるif節
`if`のみであればリスト内包表記と同様にfor節の後ろへ

```python:ifのみ
dic = {i:j for i,j in zip(key,val) if j == "A" or i == "No3"}
print(dic)
# {'No1': 'A', 'No3': 'C'}
```
`else`を含む場合は`key:val`の各々の後方に記述する
`{i if節 else:j if節 else for i,j in zip(key,val)}`

```python:例
li = {"No"+str(i) if i%2 == 0 else str(i) + " is odd" :i if i%2 == 1 else "even" for i in range(1,6)}
print(li)
# {'1 is odd': 1, 'No2': 'even', '3 is odd': 3, 'No4': 'even', '5 is odd': 5}
```
# elifを用いたい場合
条件式をif節、elifの数だけ書いてしまえば良い。
`[i if節 else 前述のelseの結果へのif節 else ... for i in イテラブルなオブジェクト]`

```python:例
# これをしたい場合
alpha_li = ["A","B","C","D"]
li = []
for i in alpha_li:
    if i == "A":
        li.append("red")
    elif i == "B":
        li.append("blue")
    else:
        li.append("yellow")
# li = ["red","blue","yellow","yellow"]
# これを内包表記で書いた場合
alpha_li = ["A","B","C","D"]
li = ["red" if i=="A" else "blue" if i=="B" else "yellow" for i in alpha_li]
# i=="A"の場合はredに、違う場合はblueに
    # i=="B"の場合は前述のblueがそのまま出力、違う場合はyellowが
```
# 多重配列を作りたい場合
内包表記内に内包表記を書けばOK
`[[i for i in イテラブルなオブジェクト] for k in イテラブルなオブジェクト]`

```python:例
# [[A,B,C],[A,B,C],[A,B,C]]を作りたい場合
li  = [[i for i in ["A","B","C"]] for k in range(3)]
```
# 多次元配列を一次元に
多次元配列を一次元に整形する

```python:例
# [[1,2,3],[4,5,6],[7,8,9]] を [1,2,3,4,5,6,7,8,9]に
multi_li = [[1,2,3],[4,5,6],[7,8,9]]
li = [i for first in multi_li for i in first]
print(li)
# [1,2,3,4,5,6,7,8,9]
# 内包表記は基本的に後ろへかかっていく
# firstには[1,2,3]や[4,5,6]などがそれぞれループで入り、それをiへループで分解している
```
# 参考
[pythonの内包表記を少し詳しく](https://qiita.com/y__sama/items/a2c458de97c4aa5a98e7)
PowerApps（フロー）を使った外形監視をやってみる

# やりたいこと
外形監視を手軽に実現したい。
流行り？のノーコード/ローコードでやってみたい。

# 実現方法
ノーコード/ローコードのツールとしてPower Appsを使うことにします。
（プレミアムプランのコネクタが使える環境です）

作るのはとても簡単。
１）繰り返しアクションをトリガー（1時間ごととか）にしてフローを作成
２）HTTPコネクタを使って監視対象のURLにリクエスト
３）２）の結果を判定してNGの場合にTeamsなり各種webhookなりに通知する

めちゃくちゃ簡単。
。。。
と思ってました。

通知テストのためにフローの2）で404ステータスになるようにURLを書き換えてみました。
すると、フローの実行が中断されてしまい、３）の判定に進めません。
中断されてると後続のアクションで何をしようとしてもそこまで進まないのがフローの仕様。

それでも後続アクションでHTTPステータスを取得しようとしたらなんとかならないかとか、色々試してみましたがやはり中断は中断。
後続処理は動いてくれません。

しかし、ありました！
直前のHTTPコネクタがエラーはいても判定アクションを動かす方法、ありました！

まずは全体像を。
![スクリーンショット 2022-02-07 18.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72763/9dda5ba5-bda7-9653-505b-4e7371728485.png)

ここで「条件」コネクタの右上にある三点リーダーをクリックしてメニューを表示して「実行条件の構成」というのを開きます。
![スクリーンショット 2022-02-07 18.38.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72763/9768472f-c57e-0769-337d-6e6ccbb91f53.png)

するとこのアクションよりも前に実行されたアクションに対して「成功しました」のときだけに動くようになっていました。
ここで「失敗しました」にもチェックを入れることで、HTTPアクションが失敗していてもこの条件アクションが実行されるようになります。
![スクリーンショット 2022-02-07 18.39.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72763/f3ccf876-3393-12c9-dd1d-04c5ff49b7d8.png)

あとは条件コネクタでHTTPステータスなり、本文の一部なりを判定して外形監視の成否を決めてあげればよいです。

この状態でHTTPコネクタが404のステータスになり、「失敗」の状態になった場合に想定通り通知が行えることの確認が取れました。

# 結論
Power Appsのフローを使って、ノーコードで外形監視を実現することができました。
注意点として、HTTPコネクタの後続アクションはHTTPコネクタが失敗したときにも実行されるように「実行条件の構成」を変更する必要がありました。
【Serializer】ActiveRecordを継承していないモデルのJSONレスポンスを整形したい

###返したいレスポンス

**本のタグ一覧API**

```json
{
  "book_tags": [
    {
      "id": 1,
      "name": "芥川賞受賞"
    },
    {
      "id": 2,
      "name": "ベストセラー"
    },
    {
      "id": 3,
      "name": "映画化決定"
    }
  ]
}
```

ActiveRecordを継承していないBookTagモデルのJSONは整形しないとこうなる。

```json
{
  {
    "id": 1,
    "name": "芥川賞受賞"
  },
  {
    "id": 2,
    "name": "ベストセラー"
  },
  {
    "id": 3,
    "name": "映画化決定"
  }
}
```


###Serializerを使わずにコントローラーでJSONを整形


```ruby
class BookTagsController < Api::ApplicationController
  def index
    tags = Tag.all
    hash = { "book_tags" => tags }
    json_str = JSON.pretty_generate(hash)
    render json: json_str
  end
end
```

###最終形態
もっと簡単に書けた。

```ruby
class BookTagsController < Api::ApplicationController
  def index
    tags = Tag.all
    render json: { book_tags: tags }
  end
end
```


##参考

https://docs.ruby-lang.org/ja/latest/method/JSON/m/pretty_generate.html
Googleフォントを使うと犯罪になる

`<link href="https://fonts.googleapis.com">`って書くと罰金取られます。

以下は[German Court Rules Websites Embedding Google Fonts Violates GDPR](https://thehackernews.com/2022/01/german-court-rules-websites-embedding.html)というニュースの紹介です。


# German Court Rules Websites Embedding Google Fonts Violates GDPR

ドイツのミュンヘン地方裁判所は、あるWebサイトの運営者が、ユーザの個人情報を本人の同意なしにフォントライブラリを経由してGoogleに提供したとして、100ユーロの賠償を命じました。

Webサイトが原告のIPアドレスをGoogleに無断で提供したことは、ユーザのプライバシー権の侵害に当たると判断しました。
さらに、Webサイトの運営者は収集した情報をその他のデータと突き合わせることで『IPアドレスの向こう側にいる人物』を特定することができる、とも付け加えました。

[判決文](https://rewis.io/urteile/urteil/lhm-20-01-2022-3-o-1749320/)には、"plaintiff's loss of control over a personal data to Google,"`原告はGoogleに個人情報の制御を奪われた`と書かれています。


Goole Fontsは、Googleが提供する[フォント埋め込みサービス](https://fonts.google.com/about)ライブラリで、開発者はスタイルシートを埋め込むだけでAndroidアプリやWebサイトでフォントを使用可能になります。
2022年1月時点では1358ものフォントが存在し、[5010万以上のWebサイト](https://trends.builtwith.com/websitelist/Google-Font-API)で利用されています。

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/7d5038aa-c585-067c-22e3-6e8643a34895.jpeg)

EUの一般データ保護規則(GDPR)では、IPアドレス、広告用のID、Cookieのような個人を特定できる情報(PII)について、事業者はこれらの情報を処理する前にユーザの明確な許可を得なければならないと義務付けられています。

判決にはこのようなことも書かれています。
『被告は、Googleサーバへの接続を確立することなく、Webサイト利用者のIPアドレスをGoogleに送信することなしにGoogle Fontsを使用することも可能である』
すなわち、Webサイトはフォントをサイト側で保持することを要求しています。

裁判所は、フォントライブラリの埋め込みによるGoogleへのIPアドレス開示を停止するようWebサイトに命じ、またWebサイトの運営企業に対し、どのような個人情報を保存・使用しているかを当事者に共有するように求めました。

また数週間前にはオーストリア共和国データ保護機関(DSB)が、NetDoktorという健康情報WebサイトがGoogle Analyticsを利用して閲覧者の情報を不正にGoogleに提供することは[GDPR違反に当たる](https://www.wired.com/story/google-analytics-europe-austria-privacy-shield/)との[判決を下して](https://noyb.eu/en/austrian-dsb-eu-us-data-transfers-google-analytics-illegal)います。


# 感想

おい誰だよ[海外はこんな不当な解釈しない](https://www.hacker.or.jp/coinhiveopinion/)とか言ってた奴は。

この話題、2018年には[早々と議論が始まっていた](https://github.com/google/fonts/issues/1495)のですが、Google側がろくな対応をしないまま数年間だらだら引き延ばしたせいで、ついに法的な結論が出てしまったようです。
世界中から賠償取り放題ですね。

ただまあ地裁でスットコドッコイな判決が出ることはままあることなので、今後最終的にどうなるかは継続して見ないとわかりません。

他に情報を送っているとかならまだしも、さすがにIPアドレスだけで同意取れとか言われても困りますよね。
この主張が通ってしまえば、今度は私は`hoge.example.com`へのIPアドレス送信に同意したのであってCloudflareへのIPアドレス送信に同意したわけじゃない！なんて主張することもできるわけですよ。
すなわち世界中のソーシャルボタンやらCDNやらSXGやらは全滅です。
たいへん困ったことになってしまいますね。

いややっぱSXGは滅んでいいや。
Windowsブートマネージャーの再構築

# 状況と環境
WindowsとArchlinuxをデュアルブートしようと作業中、間違えてEFIパーティションをフォーマットしてしまった。ブートローダーが消えてしまったので当然OSを起動することはできず、しかしWindows内に入っていたデータは残っているはずなのでWindows再インストールは避ける方向で修復をしたい。  

インストールメディアを作りたいが肝心のWindowsが眠りから帰ってこないので友達にPCを借りて作成することに。

|||
|:-:|:-:|
| PC | HP spectre13 x360 (2019) |
| 起動モード | UEFI |
| ディスク | GPT |
| Secure Boot | ON |

:::note warn
注意
8GB以上のUSBメモリまたはCD等および、Windowsを使用できるPCが別で必要です。
:::

# Windowsインストールディスクの作成
Windowsのインストールメディアを作成します。
ブラウザで"Windows インストールメディア"とかで検索してツールをダウンロードする。

[Windows 用のインストールメディアを作成する](https://support.microsoft.com/ja-jp/Windows/Windows-%E7%94%A8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB-%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-99a58364-8c02-206f-aa6f-40c3b507420d)

ツールを起動し指示に従いインストールメディアを作成する。

# 修復作業
インストールメディアをPCに挿して電源を入れる。
1. 言語やキーボードの種類を選び次へを押す
2. 左下の"コンピュータを修復する"を押す
3. "トラブルシューティング"を選択
4. "コマンドプロンプト"を選択

コマンドプロンプトにて以下のコマンドを実行する

```
diskpart
list disk
sel disk ?
```

`?`は`list disk` でディスク番号とサイズ、空き容量などが表示されるのでそこから指定したいディスクを推測し`?`と置き換えてください。

```
list vol
sel vol ?
format fs=fat32 quick
exit
```

`list vol`でボリュームリストを表示し、リストの中からEFIシステムパーティションの番号を`?`と置き換えてください。[^1]  
`format fs=fat32 quick`でEFIシステムパーティションをフォーマットする。

[^1]: EFIシステムパーティションはファルシステムが`FAT32`であることが特徴である。

```
bootrec /RebuildBcd
bootrec /fixmbr
```
`bootrec`コマンドでBCDを再構築する。  
`bootrec /RebuildBcd`実行時に"ブート一覧に追加しますか？"と聞かれるので"Y"を入力します。

# 最後に
これで再構築は完了したので、シャットダウンしてインストールメディアを抜き、Windowsが起動すれば成功です。

```
exit
```

# 参考サイト
https://itojisan.xyz/trouble/17752/

https://www.dell.com/support/kbdoc/ja-jp/000124331/%E3%83%8F%E3%82%A6%E3%83%84%E3%83%BC-repair-windows-7-8-8-1-%E3%81%8A%E3%82%88%E3%81%B3-10-dell-pc-%E7%94%A8%E3%81%AE-efi
MongoDBにNode.jsで接続するときの認証について

# やりたいこと

DockerでNodeのコンテナを作成し、MongoDBのコンテナにアクセスしたい。しかし、接続ができない（認証が失敗する）ときがあるので、方法として3種類紹介したいと思います。
Node.js初心者なので書き方がよくなかったり、こんな方法使わんだろと思うかもしれません。ぜひ教えていただきたいです。

# 実装について

node: Node.jsのコンテナでMongoDBのコンテナにアクセスしていろいろしたい
mongodb: mongoのコンテナでデータベースサーバ

一応、docker-composeファイルを載せておきます。

```yml:docker-compose.yml
version: "3.8"

services:

  mongodb:
    container_name: "mongodb"
    hostname: "mongodb"
    image: mongo:5.0.5
    restart: always
    ports:
      - 27017:27017
    volumes:
      - ./mongodb_db:/data/db
      - ./mongodb_configdb:/data/configdb
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: password

  node:
    container_name: "node"
    hostname: "node"
    image: node:17.3
    tty: true
    restart: always
    ports:
      - 3000:3000
    volumes:
      - ./node_src:/src
    working_dir: "/src/"
```

# 認証方法について

## 1つ目の方法

uriに、ログインするユーザとそのパスワードを載せて、接続する時に認証する方法。
Dockerを使わず、ローカルで実行するとき（localhostのデータベースに接続するとき）、以下の方法で接続できます。

```javascript:find_data.js
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb://root:password@localhost:27017";

.....

MongoClient.connect(uri, (err, client) => {
  .....
  collection.find(query).toArray((err, result) => {
    .....
  }
}
```

## 2つ目の方法

uriに、ログインするユーザとそのパスワードを載せて、インスタンスを作成する際に認証する方法。
私がみた`insertOne()`の[公式のサンプルコード](https://docs.mongodb.com/drivers/node/current/usage-examples/insertOne/)ではこの方法が使われていました。

```javascript:/src/insert_data.js
import { MongoClient } from "mongodb";
const uri = "mongodb://root:password@mongodb:27017";
const client = new MongoClient(uri);

.....

await client.connect();
const database = client.db("insertDB");
const haiku = database.collection("haiku");
const result = await haiku.insertOne(doc);

.....
```

## 3つ目の方法

optionsにログインするユーザとパスワードを入れて、接続する時に認証する方法。
optionsについて詳しく知りたい人は[こちらへ](https://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html)

```javascript:/src/find_data.js
const uri = "mongodb://mongodb:27017",
const options = {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  auth: {
    username: "root",
    password: "password"
  }
}

.....

MongoClient.connect(uri, options,  (err, client) => {
  .....
  collection.find(query).toArray((err, result) => {
    .....
  }
}
```

# さいごに

方法は3つだけでなく、他にもあると思います。
認証方法がたくさんあって難しい。。。
Azure SQLServerで、php /var/www/artisan migrate 時に "Could not find stored procedure 'sp_msforeachtable'."  が出た場合の対処

Azure 使うなら SQL Server使うでしょ、ということでSQL Server と Laravelを組み合わせて使うと、 ``artisan migrate``実行時にエラーが発生。つらい。


```sh
[2022-02-07 06:54:34] local.ERROR: SQLSTATE[42000]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Could not find stored procedure 'sp_msforeachtable'. (SQL: EXEC sp_msforeachtable 'DROP TABLE ?') {"exception":"[object] (Illuminate\\Database\\QueryException(code: 42000): SQLSTATE[42000]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Could not find stored procedure 'sp_msforeachtable'. (SQL: EXEC sp_msforeachtable 'DROP TABLE ?') at /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php:703)
[stacktrace]
#0 /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php(663): Illuminate\\Database\\Connection->runQueryCallback('EXEC sp_msforea...', Array, Object(Closure))
#1 /var/www/vendor/laravel/framework/src/Illuminate/Database/Connection.php(493): Illuminate\\Database\\Connection->run('EXEC sp_msforea...', Array, Object(Closure))
```


どうやら、AzureのSQLServerには ``sp_msforeahtable``が存在しないらしいです。
Stackoverflowさんもそうおっしゃっております。なんてこった。

>  Deploy database to Azure SQL fails, sp_MSforeachtable not found
https://stackoverflow.com/questions/46651612/deploy-database-to-azure-sql-fails-sp-msforeachtable-not-found


が、そこはStackoverflowさんということで、解法も載っていました。

あわてず、以下記載のSQLを実行して``create``。

https://gist.github.com/metaskills/893599


無事解決。
100日でSQLの達人になる@LeetCode! Day6 <mod() or %>

##620. Not Boring Movies （問題レベル: Easy）
今日の問題はこれ。
IDが奇数かつ、降順にリストアップするという問題。

全体のクエリ構造は非常に簡単だが、奇数の判定と降順のクエリを忘れていた。

ポイントは

```:MySQL 
mod(ID,2) = 1
```
とMySQLではmod関数が使えるが、SQL Serverでは、次のように記載しないと駄目。

```:SQLServer 
ID % 2 = 1
```

また、降順のコマンドは

```:SQLServer 
order by rating desc
```

descendingとフルスペルしては駄目！また、記載する順も重要。
昨日早速サボってしまったため、今日は二つ投稿した。

* [LeetCode](https://leetcode.com/)の問題は、MS SQL Serverで解いています。
PHPでGoogle Identity Platformにログアウト

厳密にはPHPというより、どうやってサーバサイドでログアウトをするかになる。

PythonのSDKではrevoke_refresh_tokensというものが提供されており、これを呼び出すとリフレッシュトークンが無効になる。さらにトークンも無効になる。
https://firebase.google.com/docs/reference/admin/python/firebase_admin.auth#revoke_refresh_tokens

処理の中身を見ていくとsetAccountInfoでvalidSinceを更新している。
validSinceは記載の通りタイムスタンプ。

```
validSince:string
Timestamp in seconds for valid login token.
```

Firebase Admin SDK for PHPでは指定できなさそう
https://firebase-php.readthedocs.io/en/stable/user-management.html

実際呼び出してみると、他の値をsetAccountInfoで更新したのと同じレスポンスが返ってくるが、トークンは無効になっていた。

```
{
"kind": "identitytoolkit#SetAccountInfoResponse",
"localId": "～～～",
"email": "～～～",
"idToken": "～～～",
"providerUserInfo":[
{"providerId": "password", "federatedId": "～～～", "email": "～～～",…}
],
"passwordHash": "～～～",
"emailVerified": false
}
```

挙動としてはそれっぽくなるが、複数で同一ログインした場合、すべてのアクセストークンが無効になるようだし、これが正しいのかわからない。

クライアント側でログアウトは処理した方が良さそう。
MSGからPDFへ - MSGファイルを添付ファイル付きのPDFに変換する

<p>MSGからPDFへの添付ファイル変換ブログ。</p>
<p>自動化されたソリューションは、MSGをPDFに変換する最も簡単な方法です。時間とお金の両方を節約できます。データを失うリスクがないので安全です。このプロフェッショナルガイドを使用すると、MSGファイルをPDFドキュメントに簡単に変換できます。</p>
<p>そこにある最も信頼できるソリューションの1つは <a href="https://www.mailsware.com/jp/msg-converter.html"><b>MSGコンバータソフトウェア。</b></a>です。 MSGファイルをPDFに変換するとき、すべての添付ファイルが保持されます。 使いやすいユーティリティインターフェイスが用意されています。 また、MicrosoftのWindowsオペレーティングシステムの任意のバージョンで実行することもできます。 ...</p>
<p>コンバージョンに関しては、専門的なソリューションが最善の選択肢です</p>
<h2>自動化されたソリューションを使用して、添付ファイル付きのMSGをPDFに直接変換します</h2>
<p>複数のMSGファイルをPDFドキュメントに変換できます。</p>
<p>Outlookがなくても、MSGをPDFに変換できます。</p>
<p>OutlookおよびExchangeMSGファイルを移動できます。</p>
<p>Convert.msgto.pdfをバッチで簡単に。</p>
<p>あなたは多くの時間を節約し、このように働くことができるでしょう。</p>
<p>[名前を付けて保存]ボタンをクリックして、OutlookメッセージをPDFファイルに変換します。</p>
<p>ほんの数秒で、いくつかのMSGファイルをPDFに変換するにはどうすればよいですか？</p>
<h2<添付ファイルを含むMSGファイルをPDFに変換する方法のステップバイステップの説明を以下に示します。</h2>
<p>MSGからPDFへのコンバーターは最初のステップです。</p>
<p>[フォルダの選択]タブに入ります。ソフトウェアパネルで、MSGファイルを追加できます。</p>
<p>フォルダ内の.msgファイルの場所を確認してください。</p>
<p>電子メールと添付ファイルのプレビューを取得するには、電子メールをクリックします。</p>
<p>改心する時が来ました！保存オプションのドロップダウンメニューからPDFを選択します。</p>
<p>ファイル名とファイルを保存する場所を選択します。</p>
<p>結果を変換して評価する時が来ました。</p>
<p>この方法を使用すると、マルチMSGからPDFへの変換が簡単になります。サンプルアプリケーションは、上記のプロセスを示すために使用されます。 25.msgファイルのみをPDFに変換できます。 MSGからPDFへの一括変換の場合は、製品のライセンスバージョンをアクティブ化します。</p>
<p>インスタントMSGからPDFへの変換ソリューションその結果、ユーザーは、電子メールのプロパティを維持しながら、必要な数のMSGファイルをPDFに移動できます。複数のユーザーのプロライセンスが含まれています。完全に無料で使用できますが、ユーティリティにはいくつかの制限があります。高度なセキュリティはユーザーにとって重要な問題であり、プログラムはその懸念に対処します。 Outlook.msgからPDFへの変換には、技術的な専門知識は必要ありません。変換されるデータの精度を維持しながら、時間とお金を節約します。</p>
<p>これまでのところ、英語以外のテキストのMSGメッセージをPDF形式に変換できるツールは他にありません。これは、英語以外のテキストメールを簡単に変換できることを意味します（MSG UNICODEコンテンツ）。アラビア語、日本語、ロシア語、スウェーデン語、ヘブライ語、中国語、韓国語はすべてこのプログラムでサポートされています。</p>
<h3>考えたことのないサプライズファクター</h3>
<p><b>すべてのデータを維持しながら、MSGをPDFに変換することが可能です。</b></p>
<p>もちろん、それは本当です。複数のMSGファイルを1つのPDFドキュメントに結合できます。添付ファイルは、変換プロセスに含まれる場合があります。</p>
<p><b>選択したMSGファイルからPDFを作成します</b></p>
<p>信頼できる方法を使用して、多数のMSGファイルをPDFに変換することが可能です。高度なアルゴリズムを使用して構築されており、さまざまな方法で消費者に利益をもたらします。</p>
<p><b>OutlookMSGファイルのプレビューを確認する</b></p>
<p>電子メールを変換する前に、電子メールの内容を確認する必要がある場合があります。 MSGをPDFに変換する前に、プログラムは電子メールのプレビューを提供します。</p>
<p><b>MS Outlookをインストールせずに、操作を完了することができます</b></p>
<p>スタンドアロンプ​​ログラムでは、Outlookをインストールする必要はありません。この機能を使用して、複数のOutlook電子メールをYahooアカウントに直接転送できます。</p>
<p><b>変換プロセス中のデータの整合性を確保する</b></p>
<p>MSGからPDFへのコンバーターの使用は簡単なプロセスです。フォルダ構造、bb、cc、to、from、signatureなどの電子メール属性を正確に保持します。</p>
<h3>結論</h3>
<p>MSGからPDFへのコンバーターを使用して、Outlookのメッセージと添付ファイルをPDFファイルに変換できます。制限はなく、エラーもありません。上記にリンクされているブログ投稿では、多数のMSGファイルをPDFに変換するための、シンプルで信頼性が高く、プロフェッショナルな方法が説明されています。</p>
CASB とは

## 勉強前イメージ

テレビに入れるカードみたいな名前してるね

## 調査

### CASB とは

Cloud Access Security Broker の略で、キャスビーと呼ばれています。
アメリカのガートナー社によって提唱された考え方で、
ユーザとクラウドの間にコントロールポイントを設置し、クラウドサービスの利用を可視化・制御して管理を行うものになります。
CASBを経由してクラウドサービスを使用することでセキュリティの担保ができるようになります。
[shadow IT](https://qiita.com/miyuki_samitani/items/e731054526ca7e845c29) と呼ばれる、社員が独自にサービスの導入を行うことが顕著化しており、
利便性をそのままにサービスの制御を行うことができるものです。
また通信の制御管理ができるところで次世代のファイアウォールと似たようなところがありますが、
`クラウドサービス` 単位での制御ができるというのが特徴になります。

### CASBの機能

大きく以下の4つの機能があり、この機能を使用することでセキュリティ対策が可能になります。

- 可視化・分析

クラウドサービスとの通信を経由させることでユーザの行動の可視化が可能です。
クラウドサービスごとやユーザごとに細かい管理を行うことができます。
また、上記にも記載したshadow IT を防止することができ、セキュリティリスクを下げることができます。

- コンプライアンス

企業のポリシー、ルール等も存在するところがあり
それに沿うように対処ができるのも特徴です。
また、クラウドサービスごとにセキュリティ能力をチェックして危険度を表示するので
それを元に管理することも可能です。

- データのセキュリティ

CASBを使用することでデータの暗号化や改ざん検知を行うことができます。
また、データの公開範囲も一元的に管理ができます。

- 脅威防御

世の中には安全なクラウドサービスだけではないため、
クラウドサービスへのアクセス自体も制限したりすることができます。

## 勉強後イメージ

クラウドサービスごとに制御できるって
CASBにクラウドサービスっていう登録がされてるってことかな？

## 参考

- [CASB（Cloud Access Security Broker）とは？仕組みやメリット、次世代FWとの違いまで徹底解説](https://cybersecurity-jp.com/column/36027)
- [CASBとは何か？基本を解説【2021年版】](https://products.nvc.co.jp/forcepoint/blog/what-is-casb)
100日でSQLの達人になる@LeetCode! Day5 <not where where but where and >

##181. Employees Earning More Than Their Managers （問題レベル: Easy）
今日の問題はこれ。
IDと給料と自分の上司のIDの入ったテーブルから上司よりも給料の良い職員をリストアップするという問題。

自分自身のテーブルを結合するのだが、```where```句を2つ使った冗長なクエリを書いてしまった。

ポイントは一つの```where```句に条件を```and```足すだった。
この問題はもう一度復習しよう。

* [LeetCode](https://leetcode.com/)の問題は、MS SQL Serverで解いています。
Arch Linux に QEMU の環境を生やす

1. qemu と virt-manager をインストールする
    
    ```bash
    sudo pacman -Syu qemu virt-manager
    ```
1.  libvirtd の有効化&ユーザの登録
    
    ```bash
    sudo systemctl enable --now libvirtd
    sudo usermod -aG libvirt user
    ```
1. NAT を有効化する
    標準で用意されている defalut 定義ファイルを使います
    dnsmasq に依存しているので先にインストールしておきます
    ```bash
    yay -S dnsmasq
    virsh net-define /etc/libvirt/qemu/networks/default.xml
    sudo virsh net-start default
    sudo virsh net-autostart default
    ```
    `ip a` を叩いて `virbr0` が生成されていたら成功です
1. Windows 向けの virtio ドライバをダウンロードしてくる
    パフォーマンス改善のために準仮想化に対応した virtio を使います
    しかし，Windows にはドライバが標準装備されていないため別途ダウンロードしてきます
    https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md
    \# 配信元のサーバーの通信がかなり遅いので一度ダウンロードしたら手元に持っておくことをオススメします…
Amazon SESを使うことで通常のGmailで独自ドメインを利用する -受信編-

# この記事について
準備編の続き
https://qiita.com/Sand-River/items/4c0dbb16b70e11ec594a

# 受信のための設定

https://docs.aws.amazon.com/ja_jp/ses/latest/dg/receiving-email-setting-up.html

前提として準備編でドメインの検証が完了していること。

## DNS定義

利用するドメインのMXレコードとして以下の値を設定する。
10 inbound-smtp._regionInboundUrl_.amazonaws.com

例）バージニア北部（us-east-1）だと
`10 inbound-smtp.us-east-1.amazonaws.com`


## 受信用S3の作成と設定
受信したメールを直接SNSやLambdaに渡す事もできるが、SNSだとサイズの制限（150KB）があったりLambda一発だとロストの心配があったりするので、一旦S3に蓄積する。

https://docs.aws.amazon.com/ja_jp/ses/latest/dg/receiving-email-action-sns.html
> 重要
Amazon SNS の通知を通じて E メールを受信することを選択した場合、E メールの最大サイズ (ヘッダーを含む) は 150 KB です。それよりも大きいメールはバウンスします。このサイズよりも大きい E メールが予想される場合は、代わりに Amazon S3 バケットに E メールを保存してください。

とりあえずデフォルト設定でS3を作成。バケット名は mail._domain_name_ とかでええんじゃないかと（適当）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/79a06517-91b8-5cb0-af95-2ed26c326a50.png)

作成したバケットを選択し、アクセス許可のタグからバケットポリシーを編集する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/8d48c807-1aa4-333d-07fc-04bd53081201.png)


バケット名（mail.domain_name）, AWSのアカウントID（111122223333）の部分は環境に合わせて書き換え。
（ポリシーを書く度に思うんだけど、自分のアカウントIDを指す変数が欲しいなぁ……） 

```
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AllowSESPuts",
      "Effect":"Allow",
      "Principal":{
        "Service":"ses.amazonaws.com"
      },
      "Action":"s3:PutObject",
      "Resource":"arn:aws:s3:::mail.domain_name/*",
      "Condition":{
        "StringEquals":{
          "AWS:SourceAccount":"111122223333"
        }
      }
    }
  ]
}
```

## SESの設定

::: note info
最終的には転送処理を作成するつもりだが、一旦はS3への格納のみ実施
:::

SESのEmail receivingから「Create rule set」を選択。
（ちなみに、東京リージョンなど、SESが受信に対応していないリージョンで作業を進めていると、ここで「Email receiving」が表示されていないことに気づき愕然とする）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/3a875e27-f514-db67-126d-c3c090676638.png)

ルール名を適当に決める。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/558f98c8-f072-c1c7-adca-16c46f331994.png)

作成したルールセットの詳細画面が開くので、さらに「Create rule」。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/9bdcb93f-d64f-83c6-6cdb-d9c975ef24fb.png)

ルール名を入力。（その他のオプションはデフォルトのまま）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/a302d76e-5c7a-9dc5-e374-9558148b5fcf.png)

ルール適用する条件を設定できるが、とりあえずオプションなので何もせずにNext。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/000e67a9-1019-da48-11db-baaa80a1ac9d.png)

Actionで「Deliver to Amazon S3 bucket」を選択し、先程作成したS3 Bucketを選択。
それ以外はデフォルトのまま。
Nextすると確認画面が表示されるので、問題なければ「Create rule」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/dd17d5f4-36a7-db2f-ec6b-660fc86f0071.png)

ルールが作成され、Enabledになっていることを確認。
問題なければ「Set as active」を押してルールセット自体をInactiveからActiveにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/3425c19b-b361-c2f5-8929-5c18be6152e5.png)

## 確認
今回セットアップしたドメインあてにメールを送信するとメッセージIDをオブジェクト名としたオブジェクトがS3バケットに作成されていることが確認できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554633/24e8e008-5b7c-8722-cb83-890f09d1d457.png)


# 送信編に続く
Googleドライブの「リンクを知っている全員」になっちゃっているファイルを特定する方法

エンタメ系企業の社内もろもろを担当しているakibinです。

最近、[Sunny Day Service - イン・ザ・サン・アゲイン](https://www.youtube.com/watch?v=O2TkwZ3iQLE)にハマってます。まだまだ知らない名曲があるなーこんちくしょう。

# やりたかったこと
Googleドライブの共有ドライブは、ちゃんと設計しないとファイル共有がカオス状態になりやすいですよね。

特に「リンクを知っている全員」で不特定多数にリンクを共有したい場合、専用の共有ドライブを作成して以下のチェックを入れる、それ以外の共有ドライブはチェックを外して共有をコントロールするのが理想ですが、これを考えないで運用するとカオスになります…
![スクリーンショット 2022-02-07 11.11.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/8b060596-e87c-6149-acb4-976a07a43e1b.png)

そんなカオスな状況を打開すべく、「リンクを知っている全員」になっちゃっているファイルを特定して諸々整理できないかと動き出しました。

# 管理コンソールから確認
管理者にて監査ログからフィルタリングして「リンクを知っている全員」になっちゃっているファイルを特定可能です。
[管理コンソール > レポート > 監査ログ > ドライブ]で設定画面を開き、[公開設定 > リンクを知っている全員]でフィルタリング実施
<img width="300" alt="alt" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/8a17a706-a93c-cab4-6d7c-0944cb5a6ee5.png">


ただ、**監査ログは6ヶ月しか保存されない**ので、それ以前に[リンクを知っている全員]されちゃったファイルは特定できず…そこでGASを使用して共有状況を一覧化することに、それが以下です。

# GASで「リンクを知っている全員」になっちゃっているファイルを特定
[google-drive-permission-search](https://techracho.bpsinc.jp/morimorihoge/2014_10_02/19117)や[Google Drive Permissions Auditor（アドオン）](https://workspace.google.com/marketplace/app/drive_permissions_auditor/370134017754)を試してみましたが、google-drive-permission-searchはうまく動かないし、Google Drive Permissions Auditorは問い合わせしても回答ないし…と思いつつ調べていたら以下の記事を見つけました。

[GASを使ってGoogle Drive内のフォルダ、ファイルの権限をチェックする](https://qiita.com/goofmint/items/614ab76aaf807a66bf10)

ありがたかった…ホント**これをちょっとカスタムしたら特定のフォルダ（ドライブ）の中のファイルを再帰的に一覧化して「リンクを知っている全員」になっちゃっているファイルを特定できました！**

**コードは2行更新、1行追加しただけ**でした…転記するのは申し訳ないレベルなので基本のコードは↑を参照してもらい、更新箇所は以下です。

#### 【更新１】フォルダIDを検索したいフォルダ（ディレクトリ）のIDに更新
```js
// フォルダIDを更新
function permissionCheker(prefix = null, id = '******') {
```

フォルダIDはURLの以下です。
![スクリーンショット 2022-02-07 16.44.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/c03f5cca-59d2-8e92-9db1-88b3205bcb17.png)

#### 【更新２】ユーザ指定して共有しているファイルのみを該当にしている以下コードをコメントアウト
以下コードをコメントアウトすることで、すべてのファイルの共有状況が確認可能です。

```js
  // if (editors.length === 0) return;
```

#### 【追加１】最後の方に共有権限を取得、出力するコードを追加
```js
// スプレッドシートの5列目にファイルの共有権限を出力
  sheet.getRange(rowIndex, 5).setValue(obj.getSharingAccess());
```

## GASを実行してみると
再帰的にファイルパス、ファイル名とその共有状況が取得できました！
![スクリーンショット 2022-02-07 17.49.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504009/982683ca-aca5-8da2-6736-58c73e552359.png)

共有状況のステータスの見方は以下です。

| ステータス | 意味 |
|:-----------|:------------|
| PRIVATE       | ユーザだけ or 他ユーザを指定して共有        |
| DOMAIN_WITH_LINK     | ドメイン（@hoge.co.jp）ユーザはリンクを知っていればアクセス可能      |
| **ANYONE_WITH_LINK**       | リンクを知っていれば誰でもアクセス可能        |

今回、共有状況を確認するためのメソッド（SharingAccess）を確認させてもらった、また他の情報を取得するためのメソッド確認は以下記事が一覧になっておりわかりやすかったです！

[初心者でもわかるGoogle Apps Script活用のススメ](https://for-dummies.net/gas-noobs/gas-japanese-reference-for-drives/)

# こちらもチェックお願いします！
[Twitterアカウント](https://twitter.com/akibinmusic)
[Youtubeチャンネル](https://www.youtube.com/channel/UC-JOpwEnJn3gCrUA4NdCYgg)
pythonのpyenvでBUILD FAILD

###環境
windows10 20H2 19042 1466
Linux(Devian)

###該当エラー

```terminal
(ユーザー名)@XXX:~$ pyenv install 3.10.2
Downloading Python-3.10.2.tar.xz...
-> https://www.python.org/ftp/python/3.10.2/Python-3.10.2.tar.xz
Installing Python-3.10.2...
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?

Please consult to the Wiki page to fix the problem.
https://github.com/pyenv/pyenv/wiki/Common-build-problems


BUILD FAILED (Debian GNU/Linux 9 using python-build 2.2.4-1-4-g1e79a522)

Inspect or clean up the working tree at /tmp/python-build.20220207141603.8256
Results logged to /tmp/python-build.20220207141603.8256.log

///以下略
```

###試行錯誤

とりあえずまずは普通にインストールしてみたら、上記のようなBUILD FAILED エラーが出る。
なので別のバージョンで確認してみた。

```terminal
（ユーザー名)@XXX:~$ pyenv install 3.6.2
Downloading Python-3.6.2.tar.xz...
-> https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz
Installing Python-3.6.2...
Installed Python-3.6.2 to /home/testuser/.pyenv/versions/3.6.2
```

最新の3.10.X系以上ではだめだったけど、それ以下のバージョンはインストールできました。

何とか最新バージョンを入れることはできないか確とググってみると、下のようなサイトを発見。

<a link="https://qiita.com/kzrashi/items/80ff82d4330d51a398dc">参考サイト</a>、<a link="https://child-programmer.com/pe-bs-2021/">参考サイト</a>、<a link="https://it-jog.com/py/intro/pyenvsetting">参考サイト</a>

###解決策

まず、terminalでPATHの設定と再起動をやってみます。

```echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile ```
```echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile```
```echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile```
```exec $SHELL -l```

実行した後```[プロセスが完了しました]```と表示さえれば処理はちゃんと適用しました。

```pyenv version```で確認してみると

```terminal
(.venv) XXX@XXX:~/project1$ pyenv versions
  system
  3.8.2
  3.6.2 //ちゃんと入ってる
```

最新バージョンはなぜか入らない・・・
Promiseのループ処理と終わってから何かする

調べてみたらこういう書き方もあるようだ。


https://qiita.com/saka212/items/ff61a6de9c3e19810c5d

```js
        const items = [1, 2, 3];
        const boxes = [1, 2, 3];

        var myPromise = Promise.resolve();
        for (const item_id of items) {
              myPromise = myPromise.then(update.bind(this, item_id));
        }
        for (const box_id of boxes) {
              myPromise = myPromise.then(edit.bind(this, box_id));
        }
        myPromise.then(function(){
            return new Promise(function (resolve, reject) {
                alert("end");
                resolve();
            });
        })


```
MAMPでPHPのエラーをブラウザ表示させるには


![PHPのエラー箇所をブラウザ表示させるには.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/f184cffd-7da1-1d40-a936-82a05a13a817.png)



https://tomosta.jp/blog/mamp-display-errors/
PowerVS IBM i 日記(42): 簡単安価にPowerVSとオンプレをつなぐVPN as a Service(VPNaaS)

# 簡単安価にPowerVSとオンプレをつなぐVPN as a Service(VPNaaS)

PowerVS で面倒だったのは、PowerVSがあるエリア/ネットワークが通常の IBM Cloud の IaaS のあるところと違う点でした。
すでに、IBM Cloud をお使いのお客様は、無料の ダイレクトリンクで通常の IBM Cloud の IaaS と PowerVSを接続できますが、PowerVS IBM i を使うために IBM Cloud を始めたいというお客様にはネットワークの構築が負担になっていました。

なんと新サービス VPNaaS は「接続コストは従来の1/10以下（月額4000～5000円）」なのだそうです。
自分でテストして投稿しようと思っていましたが、グズグズしているより玉川さんの記事があるので、そちらを紹介した方が有益のようです。

* [Power Systems Virtual ServerにVPNaaSで接続する](https://qiita.com/y_tama/items/5e0ff7f50731d88a1c04)
* [Power Virtual Serverで「VPN as a Service」の提供開始　～IPsec VPNをサービス化、接続コストは従来の1/10以下（月額4000～5000円）と破壊的なインパクト](https://www.imagazine.co.jp/pvs-vpnaas/)



---
2022/02/07 作成

---
当日記のIndexは[こちら](https://qiita.com/6onoda/items/f146c78c0c1bbe905a42)です。

---
許可の無い転載を禁じます。
この記事は筆者の個人的な責任で無保証で提供しています。
当記事に関してIBMやビジネスパートナーに問い合わせることは、固くお断りします。
【RSpec】インスタンス変数よりletを使う理由

そういえばRSpecではインスタンス変数使ってるのほとんど見かけたことないなと思ったことがきっかけで調べた。
その中でももっともらしいなと感じた理由のみ抜粋。

##インスタンス変数よりletを使う理由
（詳しいことは参考記事に）

- typoにすぐ気づける 

letはtypoした場合```undefined local variable or method```のエラーがでる。
インスタンス変数の場合```nil```と評価されるため、インスタンス変数をtypoしたことにすぐには気づけない可能性がある。

####ちなみに
**let!** は即時にデータ作成される。
**let** は呼ばれて初めてデータ作成される。（遅延評価）
テストによって意図的に**let**を使って、呼ばれるまでデータ作成を行わない遅延評価を使うほうがいい場合もある。
「**let!**と**let**は使い分けずに、**let!**のみを使用したほうがよい」みたいな意見も見たことがあるけど、
脳死せずにそのときは何がベストなのかを考えて使い分けたい。


##参考

https://qiita.com/jnchito/items/cdd9eef2ed193267c651
Vue.js 入門（第３回） - メソッド（methods） -

# はじめに

`Vue.js`に少し触れてみたので、その内容を「**Vue.js入門**」として、数回にわけて書いていこうと思います。
今回の３回目では「**メソッド（methods）**」を紹介します。
前の記事は以下を参照してください。

+ [Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -](https://qiita.com/yasushi-jp/items/b5226a5379b3539da81b "Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -")
+ [Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -](https://qiita.com/yasushi-jp/items/5f4e6c6a5eb0284cab15 "Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -")

※ここではVue.jsの**2.x系（2.6.14）**を使用しています。**3.x系**では書き方が異なるので注意してください。

# 1. メソッド（methods）

`methods`オプションを指定することで、`v-on`のイベントハンドラとして呼び出されるメソッドを定義することができます。

### 1.1. jsの作成
```js:js/main.js
var vm = new Vue({
  el: '#app',
  data: {                       // （１）
    items: ['HTML', 'CSS', 'JavaScript'],
    input: ''
  },
  methods: {                    // （２）
    addItem: function(item) {   // （３）
      this.items.push(item)     // （４）
      this.input = ''           // （５）
    }
  }
});
```
（１）dataとして`items`変数と`input`変数を定義します。ここで、`items`変数は`['HTML', 'CSS', 'JavaScript']`と配列を定義しています。
（２）`methods`でメソッドを定義します。
（３）`addItem`という名前のメソッドを定義します。
（４）引数の`item`を`items`変数の配列に追加します。
（５）`input`変数に空文字を設定します。


### 1.2. HTMLの作成
```html:index.html
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <title>Vue.js(method)</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
  </head>
  <body>
    <div id="app">
      <input type="text" v-model="input">                             <!-- （１）-->
      <button type="button" v-on:click="addItem(input)">追加</button> <!-- （２）-->
      <ul>
        <li v-for="item in items">  <!-- （３）-->
          <span>{{ item }}</span>
        </li>
      </ul>
    </div>
    <script src="js/main.js"></script>
  </body>
</html>
```

（１）`v-model="input"`で入力された内容と`input`変数を紐付けます。
（２）`v-on:click="addItem(input)"`で、「追加」ボタン押下時に`addItem`メソッドを呼び出すようにします。
（３）`v-for="item in items"`で`items`変数の配列から１件ずつ`item`変数に格納し、繰り返し処理を行います。`items`変数の配列の一覧を表示させます。


### 1.3. 動作確認
`index.html`を開くと、以下が表示されます。
初期表示として、テキスト入力欄に`input`変数の初期値（空文字）が表示されます。一覧には`items`の配列の内容（HTML、CSS、JavaScript）が表示されます。
![3-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/c37f2193-1d59-1b1c-ffaa-ac0684617a8c.png)


テキスト入力欄に入力し（ここでは「Vue.js」）、「追加」ボタンを押します。
![3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/eec91733-acbf-4899-4339-93cd29cb95ef.png)


すると入力した内容が一覧に追加されます。（入力欄はクリアされます。）
![3-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/2343de8b-496e-2144-6a64-b632406dcea5.png)

# 参考
+ [Vue.js](https://jp.vuejs.org/ "Vue.js")
+ [とほほのVue.js入門](https://www.tohoho-web.com/ex/vuejs.html "とほほのVue.js入門")

# リンク
+ [Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -](https://qiita.com/yasushi-jp/items/b5226a5379b3539da81b "Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -")
+ [Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -](https://qiita.com/yasushi-jp/items/5f4e6c6a5eb0284cab15 "Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -")
+  [Vue.js 入門（第４回【最終回】） - ToDoリストを作ってみる -](https://qiita.com/yasushi-jp/items/4416390dde26153073bd "Vue.js 入門（第４回【最終回】） - ToDoリストを作ってみる -")