OmniAICreator/Qiita-1.07M huggingface dataset:
AWS 使い捨て Linux

ちょこっと EC2 を作って使い捨てしたい時のメモ。

## SSH key pair の作成

鍵を作る

    export AWS_PROFILE=exampleprofile
    aws ec2 create-key-pair --key-name trash --query 'KeyMaterial' --output text > trash.pem
    chmod 400 trash.pem

## CloudFormation ファイルを作る

trash.yaml という名前のファイルを作る。

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  Trash:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro # インスタンスの種類
      ImageId: ami-02892a4ea9bfa2192 # Amazon Linux 2 64-bit x86
      KeyName: trash
      SecurityGroups:
      - Ref: TrashSecurityGroup
      UserData: # 最初からパッケージを更新しておく
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          yum update -y
          
  TrashSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Redmine security
      SecurityGroupIngress:
      - CidrIp: 0.0.0.0/0 # ご自宅の IP。自宅からしか見えないように。
        FromPort: '22' # SSH のために開けるポート
        ToPort: '22'
        IpProtocol: tcp
        
Outputs:
  PublicIP: # 作った　IP アドレスを表示
    Value: !GetAtt Trash.PublicIp
```

## CloudFormation で EC2 を作る

    aws cloudformation create-stack --stack-name trash --template-body file://trash.yaml

様子見
    
    aws cloudformation describe-stack-events --stack-name trash | jq '.StackEvents[] | .EventId'

終わるまで待つ

    aws cloudformation wait stack-create-complete --stack-name trash

しばらく待って出来上がった IP を確認

    aws cloudformation describe-stacks --stack-name trash | jq -r '.Stacks[].Outputs[].OutputValue'

返ってきた IP の ec2-user ユーザにログインする。

    ssh -i trash.pem ec2-user@13.114.8.76

## 削除

    aws cloudformation delete-stack --stack-name trash
    aws ec2 delete-key-pair --key-name trash
    rm trash.pem

## おまけ Node のインストール

https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
. ~/.nvm/nvm.sh
nvm install 12.13.1
nvm use 12.13.1
IBM Cloud CodeEngine(Node.js) + Slackで単語帳作成アプリを作ってみる

#はじめに
IT企業に入社して半年が経ちました。
新入社員は新しく知ることや覚えることが山のようにあります。社内で飛び交うIT用語もその一つです。
社内会議やお客様とのミーティングで知らないIT用語が出てくるたびにコツコツ調べてメモしていましたが、同期と協力して、より充実した単語帳を作ることにしました。
初めはエクセルに書き込む形式にしましたが、少々不便を感じていました。手順は、ブラウザからクラウド上にある共有のエクセルを開いて、調べた単語とその意味を入力するというものです。書き込まれる量が多くなると全体として見づらく、単語が探しにくくもなってきます。
そこで、これらの不便を解消する単語帳作成アプリを考えることにしました。


#単語帳作成アプリのアイデア
単語とその意味の入力手順を簡略化し、見やすい単語帳にするために、社内のコミュニケーションツールであるSlackを活用できないかと思いつきました。
テレワーク中、ミーティング外での会話は主にSlackで行うため、Slackアプリは開いていることが多く、チャット形式で単語を登録することができればとても便利です。
Slackのチャット欄に単語とその意味を入力するだけで、自動的に整理された単語帳の形にする仕組みを考えました。

#アイデアのアーキテクチャ
![box-image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1396951/83eb3e58-404c-a4cd-792b-2494c1cc9126.png)
####単語登録の仕組み
① ユーザーは調べた単語とその意味をSlackの単語登録チャンネルに入力
② Slackアプリが単語とその意味が入力されたメッセージを検知すると、CodeEngineにWebhookする
③ 単語登録アプリはデータベースに単語とその意味を登録

####単語参照の仕組み
④ ユーザーはブラウザから単語表示アプリ(単語帳サイト)にアクセス
⑤ 単語表示アプリはデータベースを参照し、サイトに単語とその意味を表示

####アプリ開発/デプロイの流れ
❶ 開発者はgithub上にコードを管理
❷ CodeEngineはGithubからソースコードを取得
❸ CodeEngineの内部でコンテナイメージを作成
❹コンテナイメージをCodeEngineにデプロイ

#IBM CodeEngineとは
今回、アプリをCodeEngineで動かすことにしました。
Code Engine とは、以下の機能を備えるフルマネージド・ランタイムサービスです。
・インフラ管理·クラスタ管理なしに、コードを瞬時にデプロイできます
・あらゆるコンテナ、ソースコード、サーバーレス機能、バッチジョブを実行できます
・ゼロ·スケールによって真の意味でコードが実行されているときだけのお支払い

2021年4月からIBMが提供を開始しており、様々なメディアに取り上げられています。
【公式サイト】
https://www.ibm.com/jp-ja/cloud/code-engine
【他サイト】
https://news.mynavi.jp/itsearch/article/cloud/5623
https://it.impress.co.jp/articles/-/21695

#おわりに
今後実際にアプリを開発していくにあたり、単語とその意味を参照する仕組みを工夫していきたいと思います。例えば以下のような機能です。
#####単語検索機能
単語帳を参照するサイトで、単語を検索できる機能を実装したいと思います。
検索単語を含めたクエリとしてDB2に送信し、単語あるいは意味に検索単語が含まれているタプルを返り値としてブラウザに表示します。
複数の単語の検索結果テーブルそれぞれから同じタプルを省けば、複数単語の検索結果を表示することも可能だと考えています。
また、単語の先頭文字1文字を格納するカラムを作成すれば、頭文字による単語の分類が可能になります。
（ただし、ユーザの負担が増えてしまいますが...)
#####Slackからの参照
ブラウザからだけでなく、Slackから登録済みの単語とその意味を参照できるようにする機能があると便利です。
Slack内に検索コマンドを設定することで、コマンドとともに入力された検索単語を検索クエリに含めてDB2へ送信、受信した検索結果をAPIによりSlackチャンネルへ投稿することで実現できると考えます。
STM8のソフトウェアシリアルでHello Worldと出力 9600bps TX PD0


目的
つくれそうだから作ってみた。

x ALレジスターが1個だからたぶん遅い
x 遅い、遅い、遅すぎる　論理値104us stm32->96us stm8->82us
x 6805みたいな、アーキテクチャで汎用レジスターがない
x メモリアクセスのコストが高い
x よつてゴミである?

![o_con28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f6b58c49-8a4c-33f6-daa0-538fb516928e.jpeg)



```c++


//104 9600
//208 4800
//416 2400
//832 1200

//#define UART_DELAY 1000 //  1/1000 ok
//#define UART_DELAY 833  //  1/1200 ok
//#define UART_DELAY 416  //  1/2400 ok
//#define UART_DELAY 186  //  1/4800 ok 173-200
#define UART_DELAY 82     //  1/9600 ok 81-84

#define PD_ODR *(volatile uint8_t *)0x500F

#define  on1()   PD_ODR=0b00000001
#define  off1()  PD_ODR=0b00000000

//仮想シリアルへの一文字出力 9600bps
int pc_putc1(char ch) {

  on1();
  off1(); //START
  delayMicroseconds(UART_DELAY);

  if( ch & 0b00000001){
    on1();  /*ビットが1*/   
  } else {
    off1(); /*ビットが0*/ 
  }//end if
  delayMicroseconds(UART_DELAY);//0

  if( ch & 0b00000010){
    on1();  /*ビットが1*/   
  } else {
    off1(); /*ビットが0*/
  }//end if
  delayMicroseconds(UART_DELAY);//1

  if( ch & 0b00000100){
    on1();  /*ビットが1*/  
  } else {
    off1(); /*ビットが0*/
  }//end if
  delayMicroseconds(UART_DELAY);//2

  if( ch & 0b00001000){
    on1();  /*ビットが1*/   
  } else {
    off1(); /*ビットが0*/ 
  }//end if
  delayMicroseconds(UART_DELAY);//3

///44444444444444444444444444
  if( ch & 0b00010000){
    on1();  /*ビットが1*/ 
  } else {
    off1(); /*ビットが0*/ 
  }//end if
  delayMicroseconds(UART_DELAY);//4

  if( ch & 0b00100000){
    on1();  /*ビットが1*/   
  } else {
    off1(); /*ビットが0*/ 
  }//end if
  delayMicroseconds(UART_DELAY);//5

  if( ch & 0b01000000){
    on1();  /*ビットが1*/   
  } else {
    off1(); /*ビットが0*/
  }//end if
  delayMicroseconds(UART_DELAY);//6

  if( ch & 0b10000000){
    on1();  /*ビットが1*/  
  } else {
    off1(); /*ビットが0*/
  }//end if
  delayMicroseconds(UART_DELAY);//7

  on1(); //Stop
  delayMicroseconds(UART_DELAY);

}

void setup() {

  //仮想シリアルの出力ポート

  //ポートをhiにする 初期化
  pinMode(PD0, OUTPUT);
  on1();

}//setup

char *ss1; //文字のポインター
int  ii;   //ループカウンター

//無限ループ
void loop() {

  ss1="Hello World !\r\n";
  ii=0; //ループカウンター
  while(ss1[ii]!=0){

    //一文字出力
    pc_putc1(ss1[ii]);ii++;

  } //while

  //1秒の待ち
  delay(1000);

}//loop



```
Railsで遷移元のURLを取得する

## はじめに
開発ですぐに忘れそうなことを、簡単に再度調べられるようにするための備忘録です。

## やりたいこと
元々いたページのパスをコントローラー側で受け取る。

具体例）
Blogのshow画面から、Contactのnew/createを呼び出して、
Blogのshow画面にリダイレクト。

## 方法

```ruby
before_url = request.referer
```
を用いる。

ちなみに、遷移後の現在のURLを取得したい場合は、

```ruby
## pathの取得
current_url = request.path

## urlの取得
current_url = request.url
```

のどちらかを用いる。
（pathの取得で良いのか、urlが必要なのかは、用途に応じて使い分ける。）

## 補足
request.refererを用いた時のrequest specでは、
HTTPヘッダを明記する必要があるため、

```ruby

let(:headers) { { HTTP_REFERER: xxx_url } }

it "リクエストが成功する" do
  post xxx_url, params: params, headers: headers
  expect(response.status).to eq 302
end

```

のような形で、書くと良い。
Optunaの内部ではなにが起きているか 全体概要編

# はじめに
自分自身よく利用することがあるoptunaですが、内部でなにが起きているのか実際に自分でコードを書いて理解してみたのでそれをまとめようと思います。
特に今回は、全体図を掴むことを目的としているので、optuna自体のコードまでは触れられていません。次回に持ち越したいと思います。
そのまま動かすことができる[コード](https://github.com/takassh/simple-tpe)もあります。それも触ってみてください。optunaとの比較もでき、完全に一致していることが確認できると思います。
なおバージョンは[v2.9.1](https://github.com/optuna/optuna/tree/release-v2.9.1)を参考にしています。

# optunaとは
[Preferred Networks](https://www.preferred.jp/en/projects/optuna/)社が提供しているハイパーパラメータ最適化ライブラリでTPEというアルゴリズムを採用したものです。
TPEの上位概念はベイズ最適化で、同じような概念ではGP-EIがあります。TPEもGP-EIもベイズ最適化の一種となります。
[A hyperparameter optimization framework](https://github.com/optuna/optuna)

# 参考
[ハイパーパラメーター最適化フレームワークOptunaの実装解説](https://cyberagent.ai/optuna-from-scratch)
[Optuna(TPE)のアルゴリズム理解](https://qiita.com/nabenabe0928/items/708d221dbccebf31f01c)
[機械学習におけるハイパーパラメータ最適化の理論と実践](https://logmi.jp/tech/articles/322678)


# 最適化の概要
optunaがTPEという仕組みでハイパーパラメータを最適化していることはわかったと思うのですが、実際にそれがどのような機構なのか説明しようと思います。

まず、全体図から確認していきます。これはハイパーパラメータの最適化全般に言えることだと思います。(手書きですみません)

![全体図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372622/2b8aeb75-afab-c95f-b3ec-e965492d8376.jpeg)

まず、図の左下にあるように通常通りモデルを学習し切ります(全エポック分)。すると、損失(Loss)が出力できると思います。
その後、なにかしらの最適化アルゴリズムを介して、次に学習するときはどんなハイパーパラメータにすれば良いか出力します。その値を再びモデルの学習に利用し、また損失が出力されます。この循環を繰り返していきます。

# ベイズ最適化の概要
ハイパーパラメータの最適化の全体像がわかったところで、今度はTPEやGP-EIが属するベイズ最適化の枠組みについて考えてみます。

![ベイズ最適化.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372622/023bf479-3fec-9dc2-fe8d-4ffed640ce9c.jpeg)

まず、与えられた数個の損失からハイパーパラメータの定義域全体にわたる損失を予測します。これは実際の損失を表す関数を代理するようなもので、**代理関数**と呼ばれます。
その関数を使って、今度は次のハイパーパラメータをどこにするか決定できる関数を作成します。これは**獲得関数**と呼ばれます。

この代理関数と獲得関数の作り方の違いによってGP-EIとTPE(optuna)は大別できると思います。

### ベイズ最適化の概要(補足)
これは補足なので読み飛ばしても大丈夫です。
そもそもなぜハイパーパラメータの最適化が難しいのかというと、ほとんどの場合、図の左下のモデルの学習に多大な時間がかかってしまうからです。
もし時間がかからない場合は、細かな粒度のグリッドサーチやランダムサーチで全通りに近い回数を試して最適なものを選択すれば良いことになります。
時間が無限であればこのようなアルゴリズムは必要ないですが、限られた時間で、限られた個数の損失しか得られない状況で最善を尽くすためになんとかしようとしているところが僕は面白いと思いました。

# 最後に
またこの続きを書いていこうと思います。
Vue.jsのローディング中に、テンプレートを見せたくない！

Vue.jsのローディング中、`{{text}}`⇦まま表示されてしまう問題を解決します！

**結論: v-cloakにstyleを設定する**
htmlのcssをゴニョゴニョすればいい感じでできます！

やり方👇
---
```javascript:main.js
const App = {
  data() {
    return {
      text: "aaaa"
    }
  }
}
```

```diff_html:index.html
-<div id="app">
-    <p>{{text}}</p>
-</div>
+<div id="app" v-cloak>
+    <p>{{text}}</p>
+</div>
```

```diff_css:styles.css
+[v-cloak] {
+  display: none;
+}
```
CakePHPでWarning: file_put_contents() [function.file-put-contents]: Only 0 of 1209 bytes written, possibly out of free disk space in…という警告が出た場合の対処

# 出力していたエラー
```
Warning: file_put_contents() [function.file-put-contents]: Only 0 of 1209 bytes written, possibly out of free disk space in [FileLog.phpのディレクトリパス]
Warning (512): _cake_core_ cache was unable to write 'cake_dev_ja' to File cache [CORE/Cake/Cache/Cache.php, line 327]
```

# 結論
容量がいっぱいなのでキャッシュが書き込めない状態です。
いらないファイルを削除する必要があります。

# バージョン
CentOS 6.6
Apache 2.2.15
PHP 7.3.15
CakePHP 2.10.20

# 削除するファイルの候補
- キャッシュ、アクセスログ、エラーログ
`app/tmp/`以下にあるキャッシュやログが不要であれば削除します。

- Rewritelog
開発環境だといつの間にか肥大しているようなので削除候補でしょうか。
ファイルパスは`/tmp/httpd.rewrite.log`です。
【kaggle】Titanicから学ぶテーブルデータコンペの進め方　～⑤アンサンブル～

#はじめに
アンサンブル学習は、複数の機械学習モデルを組み合わせることで性能の高い予測値を獲得する手法です。基本的に精度向上が望めるのでこの手法を使うのは一般的です。アンサンブルでは多様性が重要になるので得意分野の異なるモデルを組み合わせたり、似たようなモデルでもハイパーパラメータや特徴量を変えたりします。バギング、ブースティング、スタッキングなどの手法がありますが、まずは基本となる提出ファイル結果の多数決でアンサンブルを実施します。

#多数決によるアンサンブル
これまで作成したランダムフォレストと2種類のLightGBMによる提出ファイルを利用します。それぞれスコアは0.79186, 0.77751, 0.76315です。

- submission_rf_0.79186.csv
- submission_lightgbm_0.77751.csv
- submission_lightgbm_0.76315.csv

LightGBMのベースラインモデルでは0.77033を記録していますが、間違えてLightGBMのスコア0.76315を使ってしまいました。

次に、類似していないもの同士でアンサンブルするために相関係数が低い結果を選択していきます。今回使う結果は3つですが選択肢が多いに越したことはありません。

```python
import pandas as pd
import numpy as np
import os

# RandomForestの予測結果
rf = pd.read_csv("/kaggle/input/titanic-submit-files/submission_rf_0.79186.csv")

# LightGBMの予測結果
lightgbm = pd.read_csv("../input/titanic-submit-files/submission_lightgbm_0.77751.csv")
base_lightgbm = pd.read_csv("../input/titanic-submit-files/submission_lightgbm_0.76315.csv")

df = pd.DataFrame({"rf":rf["Survived"],
                  "lightgbm":lightgbm["Survived"],
                  "base_lightgbm":base_lightgbm["Survived"]})
# 相関行列
df.corr()
```
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835792/add74cd9-b548-2d7a-8be1-af005822b5fc.png">

0.95を超えないことが1つの基準になるようです。クリアしているのですべてをアンサンブルに採用します。

多数決で予測値を決定します。3ファイルの予測値部分を合計し、合計が2以上の場合は全体としての予測値を1とします。

```python
# 予測値の多数決
sum_pred = rf["Survived"] + lightgbm["Survived"] + base_lightgbm["Survived"]
pred = np.where(sum_pred >= 2, 1, 0)
 
ensemble = pd.DataFrame({"PassengerId": rf["PassengerId"], "Survived":pred})
ensemble.to_csv("ensembele_rf_lgbm_lgbm.csv", index=False)
```
最終的なアンサンブルの結果は0.77990となったので、ランダムフォレスト単体より劣る結果となってしまいました。原因と対策をまとめます。

#今後の課題
- 決定木系モデルのみを使用したので多様性に欠けた
- モデルを大量に作成して選択肢を増やす
- 予測値の相関係数が低い(r<0.9)結果を選抜する
- 0.76315のスコアを出した単体LightGBMの精度が低い
- 予測クラスではなく予測確率を使うことで丸め込まれたデータより多くの情報量を活用する
パワポ―ポイントでワンクリックでマクロを実行する方法

<h3>0.はじめに

パワポ―ポイントでマクロを作成し**「いや～業務がはかどるわー」**と満足したのもつかの間、
頻繁に使うようになると**「いちいちマクロを呼び出す作業が面倒だな～」**と、さらに楽がしたくなりますよね。
できれば図形や文字を挿入するかの如く、ワンクリックで実行したいところです。

しかし、エクセルと違って、パワーポイントはマクロ実行ボタンを簡単に作成する機能がありません。
そこでパワーポイントで近い機能を実装する手段をご紹介したいと思います。
いくつか手は考えられるのですが、今回は最も簡単な *<font color="blue">リボンにマクロを登録する* という手段をご紹介します。

## 1.手順
①まずはリボン上で右クリック →　`リボンのユーザー設定`を選択します

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/ab2a7408-33f5-8c3a-557a-e7a3fba9295e.png)

② **`コマンドの選択`** から**`マクロ`**を選択します
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/5b973569-1663-b783-e2d4-dfcf817a3323.png)

③マクロを追加したいタブを選択し、**`新しいグループ`**をクリックして、新しいグルーを作成します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/e1e76b75-2f91-2572-3de1-7c110d0e0d49.png)

④追加されたグループを選択し、**`名前の変更`**をクリックし、任意の名前に変更します。
 **マクロ**などの名前にしておくとわかり易いと思います。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/43da3692-85fb-b265-d634-70aee2fb1713.png)

⑤リボンに追加したいマクロを選択　→　追加先のタブ、グループを選択　→　**`追加`**をクリック
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/9b7c4656-950f-03ab-b3bc-46e8d3d56f16.png)

⑥今回はホームタブのマクロというグループに、マクロを登録したのですが、↓の図のように
　問題なく登録できました。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/824754/444c965e-241f-9b09-6429-0cbd000d4924.png)


## 2.おわりに
これで作業終了です。小難しい作業なしにマクロがワンクリックで実行できるようになりました。
より使い勝手よくカスタママイズ性の高い手法もありますので、またの機会に紹介できればと思います。
VSCodeでGitのコミットメッセージを書きやすくする拡張機能

# VSCodeのソース管理でGitのコミットメッセージを書く時の不満点

VSCodeでGitのコミットを行う時、コミットメッセージの入力はどうしていますか？
普通に下画像の、ソース管理のコミットメッセージ入力欄で書いているという方が多いのではないでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/13b97053-bde5-30af-b19c-e13ca2975c1f.png)

この入力欄に、私は以下のような不満を感じていました。

## 入力欄が狭い

このVSCodeのソース管理機能が表示される左側のペインは、通常それほどの幅は取っていないと思います。しかし、通常取っている幅だと日本語にして20文字程度しか入らず、コミットメッセージを書くにはさすがに狭すぎます。
そのため、コミットメッセージを書くたびに左側のペインを広げたり狭めたりする必要があります。
また、改行すると行が追加されていきますが、行数が多くなっても最大5行ほどしか同時に表示できません。縦も横も窮屈です。

## 入力欄のフォントがプロポーショナルフォント

入力欄のフォントがプロポーショナルフォントであるため、文字種によっては入力した桁数がどのくらいなのか視覚的にわからなくなります。
1行の桁数が多くなってコミットメッセージとして推奨されている文字数を超えると一応警告を出してくれるのですが、日本語も1文字1桁と計算してしまうので、通常1文字でアルファベット2桁分の幅を取る日本語のコミットメッセージだと全く用をなしていない状態です。

# Commit Message Editor 拡張機能

そこでなにか良い拡張機能はないかと探したところ、その名も [Commit Message Editor](https://marketplace.visualstudio.com/items?itemName=adam-bender.commit-message-editor&ssr=false#overview) という拡張機能を見つけました。

Commit Message Editor 拡張機能をインストールすると、ソース管理のコミットメッセージのところに下のようなペンのアイコンが追加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/e3705429-0d4c-e8d9-f961-55b5c7bb3c8f.png)

これを押すとエディタ領域に以下のようなコミットメッセージの入力欄が現れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/16f701af-f269-c12a-ddbb-70ff38ef8393.png)

この入力欄にメッセージを入力して、「Save」ボタンを押すと通常のソース管理のメッセージ入力欄に内容が反映されるので、そのままチェックアイコンを押すなりしてコミットすればOKです。

## Commit Message Editor の良いところ

### コミットメッセージ入力欄が広い

まずはこれにつきます。エディタ領域で入力できるため、当然横幅は十分に確保されますし、縦も10行分[^1]あるので、広々としたエリアで入力できます。

[^1]: 設定(commit-message-editor.view.visibleLines)で変更可能。

### 固定幅フォントを使える

デフォルトではプロポーショナルフォントなのですが、設定[^2]を変更することで等幅フォントでメッセージを入力できるようになります。

### ルーラーが付く

設定で固定幅フォントにすると、コミットメッセージの1行の長さの目安となるルーラーが付きます。上で記載した画像でも2本縦線が入っているのが確認できると思います。
この2つのルーラーは、1行目の要約行の目安とされる50桁と、3行目以降のコミットメッセージ本文の目安とされる72桁に設置されているので、適切な1行の長さのコミットメッセージを作成しやすくなります。

### コミットメッセージのテンプレートが使える

コミットメッセージのテンプレートを設定することができ、「Load template」を押すと下画像のようにコミットメッセージのテンプレートが挿入されます。（画像の物はデフォルトで設定されているテンプレート。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22414/1a5e11bb-6fe5-3c28-fc36-e58aadac60e6.png)

プロジェクトでコミットメッセージの体裁が決められている場合等、便利だと思います。

[^2]: commit-message-editor.view.useMonospaceEditor
Stripe.js ElementsがCordovaでロードされない時

# はじめに
Webで動いてるStripe.jsとStripe ElementsがCordovaのビルド後に動かなかった時のメモ。
※Cordova iosでのみ動作確認済み

- Cordova 10.0.0
- Stripe JS SDK v3 

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [何がおかしかったか](#1-何がおかしかったか)
1. [追加したコード](#2-追加したコード)
1. [参考文献](#3-参考文献)

<!-- 各チャプター -->
#1. 何がおかしかったか

この画面でStripe Elementsを使っていて、Cordovaでビルドした後Elementsがロードされていない感じでCard Number、Expiration、CVCが入力できなかった。

![Screen Shot 2021-09-30 at 14.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2106354/2f83802f-c3ee-f1fd-3a84-36d6b117f2a7.png)


#2. 追加したコード
Cordovaの設定ファイルconfig.xmlの`<platform name="ios">`内に以下のコードを追加したらWebと同様に動くようになった。

```xml:config.xml
<allow-navigation href="http://*/*" />
<allow-navigation href="https://*/*" />
```

Stripe ElementsのURLを読むのにパーミションが問題だったみたい。。

#3. 参考文献
- [Stripe in wkwebview open a browser page loading script](https://stackoverflow.com/questions/63742455/stripe-in-wkwebview-open-a-browser-page-loading-script)
- [Stripe.js と Stripe Elements](https://stripe.com/docs/stripe-js)
WebMidi.jsを使ってみた

Web MIDI APIのライブラリ[WebMidi.js](https://github.com/djipco/webmidi)を使ってみました。指を離したときに音が急に切れるのでプツプツという音がしますが許してください。ブラウザではMIDIキーボードも使えるのかと感動しました。

```index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/webmidi"></script>
</head>
<body>
<script>
const audioCtx = new AudioContext();

const A4_FREQ = 440;
const A4_NUMBER = 69;

function note2Freq(note){
  const { number } = note;
  const dif = number - A4_NUMBER;
  const freq = Math.pow(2, dif / 12) * A4_FREQ;
  return freq;
}

WebMidi.enable(err=>{
  if(err){
    alert("Web MIDI APIは使えません。");
    return;
  }

  const sourceNodeBuffer = [];

  WebMidi.inputs[0].addListener('noteon', "all", e=>{
    const sourceNode = audioCtx.createOscillator();
    sourceNode.connect(audioCtx.destination);
    sourceNode.note = e.note;
    sourceNode.frequency.value = note2Freq(e.note);
    sourceNode.start();
    sourceNodeBuffer.push(sourceNode);
  });

  WebMidi.inputs[0].addListener('noteoff', "all", e=>{
    const sourceNode = sourceNodeBuffer.find(
      node => (
        node.note.number === e.note.number &&
        node.note.name   === e.note.name   &&
        node.note.octave === e.note.octave
      )
    );
    sourceNode.stop();
    sourceNode.disconnect();
    const index = sourceNodeBuffer.indexOf(sourceNode);
    sourceNodeBuffer.splice(index, 1);
  });
});
</script>
</body>
```
Raspberry Pi で Grove の 温湿度モジュールを使う

次のページを参考にしました。
[Grove - Temperature&Humidity Sensor Pro(DHT22)](https://wiki.seeedstudio.com/Grove-Temperature_and_Humidity_Sensor_Pro/)

実行時の様子
![IMG_20210930_155528.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/6cd1f29c-b6f3-e4ec-ea48-fde1b02dfb51.jpeg)

必要なライブラリーのインストール

```bash
curl -sL https://github.com/Seeed-Studio/grove.py/raw/master/install.sh | sudo bash -s -
```

プログラム

```py:dht_simpleread.py
#! /usr/bin/python3
import time
import seeed_dht

sensor = seeed_dht.DHT("22", 16)
	
while True:
	humi, temp = sensor.read()
	if not humi is None:
		print('DHT{0}, humidity {1:.1f}%, temperature {2:.1f}*'.format(s
ensor.dht_type, humi, temp))
	else:
		print('DHT{0}, humidity & temperature: {1}'.format(sensor.dht_ty
pe, temp))
	time.sleep(2)
#
```

実行結果

```text
$ ./dht_simpleread.py 
DHT22, humidity 68.3%, temperature 26.6*
DHT22, humidity 68.3%, temperature 26.6*
DHT22, humidity 70.1%, temperature 26.6*
DHT22, humidity 83.5%, temperature 26.8*
DHT22, humidity 85.0%, temperature 26.8*
DHT22, humidity 89.1%, temperature 27.0*
DHT22, humidity 88.6%, temperature 27.1*
DHT22, humidity 77.7%, temperature 27.2*
DHT22, humidity 76.6%, temperature 27.3*
```
Flutterで@2x,@3xの画像がうまく表示されない！


ドキュメントに書いてるのは

```
.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.
```
だから

```
assets/xxx.png
assets/2x/xxx.png
```
これはうまくいく。でも例えばフォルダ分けすると

```
assets/image/xxx.png
assets/2x/image/xxx.png
```
これはうまくいかない。そうだよ。
もうわかっちゃったよね

```
assets/image/xxx.png
assets/image/2x/xxx.png
```
だし

```
assets/images/icon/xxx.png
assets/images/icon/2x/xxx.png
```
こうじゃないとね
勘違いしないでよね！って感じ

[出典](https://flutter.dev/docs/development/ui/assets-and-images#resolution-aware)
markdownのコードに半角円マークを表示したいだけ

結論は、HTMLで書いた・・・😢

# 通常表示の場合は簡単

```
&yen;
```

&yen;

# インラインコードの場合

### 成功

```
<code>&yen;</code>
```

<code>&yen;</code>

### 失敗1

```
`\`
```

`\`

### 失敗2

```
`&yen;`
```

`&yen;`

# コードの場合

### 成功

```
<pre><code>C:&yen;Windows</code></pre>
```

<pre><code>C:&yen;Windows</code></pre>

### 失敗

<pre><code>```
C:\Windows
```</code></pre>

```
C:\Windows
```
【AWS】PythonでAppSync（GraphQL）を叩く

#やりたいこと

とりあえずAppSync上にGraphQL APIは構築したが、まずはローカルで試してみたいorデータを一括登録したいという場合があると思いますので、boto3を使ってローカル環境でAPIを叩けるようなコードを作成しました。
ぜひ、ご活用ください。

#ソースコード

```python
from requests_aws4auth import AWS4Auth
from gql import gql, Client
from gql.transport.requests import RequestsHTTPTransport
import pprint
import openpyxl
import sys
import json
import random
args = sys.argv

#一時的な利用なのでソースコード内に記述していますが、なるべく環境変数にしましょう。※補足参照
auth = AWS4Auth(
    "アクセスキー",
    "シークレットアクセスキー",
    "リージョン",
    "appsync",
)
headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
}

#graphqlのURL
transport = RequestsHTTPTransport(
    url="https://xxxx.appsync-api.ap-northeast-1.amazonaws.com/graphql",
    use_json=True,
    headers=headers,
    auth=auth
)
client = Client(transport=transport, fetch_schema_from_transport=True)


def create_data(params):
    create = """
  mutation CreateData(
    $input: CreateDataInput!
    $condition: ModelDataConditionInput
  ) {
    createData(input: $input, condition: $condition) {
      id
      ...
      }
    }
  }
        """
    try:
        resp = client.execute(
            gql(create), variable_values=json.dumps({"input": params}))
    except:
        pprint.pprint(resp)

def main();
    params = {
      id: 12345,
      ...
    }
    create_data(params)

if __name__ == "__main__":
    main()

```

#補足
boto3を利用する際の認証情報に関しては以下をご参考ください。
公式：https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html

Qiita：https://qiita.com/tsukamoto/items/00ec8ef7e9a4ce4fb0e9
Pythonのリスト内包表記をそろそろ書けるようになろう

`names = [user.get('name') for user in users if user.get('age') > 18]`
これを見ると、__ムカつきを覚える人__が対象です。

リスト内包表記の書き方を解説します。

## いつ使う：既存の配列から新たな配列を作る
まず、どんな実装をするときにリスト内包表記を使うか考えましょう。
ずばり、「既存の配列から新たな配列を作るとき」です。
リスト内包表記を使わないサンプルコードを見ていきましょう。
ユーザー情報のリストからユーザー名のみを抽出してユーザー名のリストを作成するコードです。

```py
users = [{'name': 'masaki', 'age': 20}, {'name': 'hiroshi', 'age': 24}]
names = [] # =====ここから=====
for user in users:
    names.append(user.get('name')) # =====ここまで=====
```

サンプルコードでここから～ここまで と書いているところが、リスト内包表記を使うと一行になります。

```py
users = [{'name': 'masaki', 'age': 20}, {'name': 'hiroshi', 'age': 24}]
names = [user.get('name') for user in users]
```

こんな感じで、一行にできました。
リスト内包表記を書くときのポイントは、`for user in users`の部分から書き始めることです。

```py
# forを回したい対象は -> users
[for user in users]
```

ここまでは普通のfor文の書き出しと一緒です。

```py
# forを回したい対象は -> users
[user.get('name') for user in users]
```

そして、userに何をしたいか、対象の処理を書けば良いだけ。
コードの前から見ていくと何をしているのか分かりにくくなってしまいます。

なので、慣れないうちは__for文から__見る・書くことをオススメします。

# ifがつくパターン
`names = [user.get('name') for user in users if user.get('age') > 18]`
そして、先ほどのコードにプラスして条件が書かれることもあります。
こちらの条件は、条件がtrueであれば配列に追加することになります。

```py
users = [{'name': 'masaki', 'age': 20}, {'name': 'hiroshi', 'age': 24}, {'name': 'satoru', 'age': 15}]
names = [user.get('name') for user in users if user.get('age') > 18]
print(names)  # -> ['masaki', 'hiroshi']
```

こちらも先ほどと同じ。
順序だてて書いていきましょう。

```py
[user.get('name') for user in users]
```

このコードに、条件を追加するだけです。

```py
[user.get('name') for user in users if user.get('age') > 18]
```

以下の手順で書いていきましょう。

1. for in の部分を書く
1. user.get('name')の、何をリストに入れたいかを書く
1. リストに入れる際に条件があればif文を書く


少しでも苦手意識が無くなれば幸いです。
pandasのdatetime計算でハマった件

本記事は私がハマった２件を検証した内容となっておりますが、初歩的ミスだったので
最終的に「そうだよねー」となる結論になっております。

## 1. datetimeの差分を取得する際
取り扱ってる研究用時間データはまぁまぁ膨大なので仮の日付を用いてかつ以下のように記述してあります(※再現性重視)

```python:test.py
import pandas as pd

a = '2200/04/01 23:00:05'
b = '2200/04/08 23:00:00'

df = pd.DataFrame([a,b],index=['A', 'B'], columns=['date'])
df['date'] = pd.to_datetime(df['date'])
B,A = df['date'].max(), df['date'].min()

(B - A).days #result: 6 
```
あれ。4/8 と4/1って日の差が1週間だから`result: 7`が出力されて欲しかったんだけど... ん？と思い検証。

### 1.の修正
結論としては`「秒単位で計算してるっぽい」`
だって計算結果表示したらこうだもの。

```python
(B - A)  #result: Timedelta('6 days 23:59:55')
```

勝手にday属性だけ取得して減算してると思ってました...
そりゃもっと正確な値を出してきますよねーって感じでした。

```python:modify.py
(B.day - A.day) #result: 7
```

## 2. DataFrameから特定期間を抽出する際

```python:テストデータ作成
test_dates = []
for d in range(1,11):
    for h in range(24):
        test_dates.append(f'2200/01/{d} {h}:00')

date_df = pd.DataFrame(test_dates, columns=['date'])
date_df['date'] = pd.to_datetime(date_df['date'])

date_df
```

|date|
|:--|
|2200/01/01 00:00|
|2200/01/01 01:00|
|...|
|2200/01/10 22:00|
|2200/01/10 23:00|


1/1から1/8のデータを取得したい場合
こんな書き方で期間を抽出するんですが、この時起きた問題

```python:件のコード
date_df[(datetime.datetime(2200,1,1) <= date_df['date'])&(date_df['date'] <= datetime.datetime(2200,1,8))]
```

|date|
|:--|
|2200/01/01 00:00|
|2200/01/01 01:00|
|...|
|2200/01/07 23:00|
|2200/01/08 00:00|

となってしまう問題
 (~~空白はpep8に則っていないけれど見やすさ重視~~)

直感的にはこう書きそうなものなんだけれど、1/8のデータが欠けてしまっている。

### 2.の修正
`datetime.datetime(2200,01,09)`と記述するとそりゃ省略されてるのは`00:00`となっている様子。
つまり`<= datetime.datetime(2020,01,09)` は `<= 2200/01/09 00:00`ということらしい。
そりゃそうなりますよね。

```python:modify.py
start_date = datetime.datetime(2200,1,1)

#case 1:愚直に 次の日の24時ギリギリまで取得
end_date = datetime.datetime(2200,1,9)
date_df[(start_date <= date_df['date'])&(date_df['date'] < end_date)]

#case 2: 一日分追加っていう明示的なやり方？(case 1 の方が楽ですね)
end_date = datetime.datetime(2200,1,8)
one_day = datetime.timedelta(days=1)
date_df[(start_date <= date_df['date'])&(date_df['date'] < end_date + one_day)]

```

## 参考記事
- https://pg-chain.com/python-datetime-timedelta#toc4
- https://note.nkmk.me/python-pandas-query/
useEffect 第二引数のすすめ

#1. はじめに
　アプリで値の更新を行おうと思った際、これまではif文で特定の条件下で値の更新を行うようにコードを書いていました。例えば他の値が変更された時にもう一方の値を更新したい時などは、コンポーネントの再描写前と現在の値を比較し異なるときのみ一方の値の更新を行うようにコードを書いていました。そうすると結構コードの量が増えてしまいますし、何より管理が大変です。
　それがuseEffectを使うとこんなに簡単に書けました。せっかくなので記事にしようと思います。

#2. useEffectの使い方
　まずはインポートの仕方です。こうやって呼び出します。

```javascript
import { useEffect } from 'react';
```
　useEffect関数はコンポーネントの中に記述し、第一引数に関数を受け取ります。第一引数に受け取った関数はコンポーネントが描写されるたびに実行されます。
　下記のコードではAppコンポーネントが描写されるタイミングでtextの中身が変わります。もちろん、コンポーネントが再描写される際にもuseEffectの中の関数は実行されます。

```javascript
import React, { useState, useEffect } from "react";

function App() {
  const [text, setText] = useState("");
  useEffect(() => {
    setText("毎回起動する");
  });
  return <div className="App">{text}</div>;
}

export default App;
```
　しかし、上記の書き方では描写の度に関数が実行されてしまいます。そこで、useEffectの第一引数の関数を任意のタイミングで実行させたいのですが、それには第二引数を用います。useEffectの第二引数には配列を受け取り、この配列の中身が変化した時とコンポーネントの初回読込時のみ第一引数の関数を実行するようになります。
　コンポーネントの初回読み込み時のみ第一引数の関数を実行させるには第二引数の空の配列を渡します。

```javascript
import React, { useState, useEffect } from "react";

function App() {
  const [text, setText] = useState("");
  useEffect(() => {
    setText("初回のみ起動する");
  }, []);
  return <div className="App">{text}</div>;
}

export default App;
```
　任意のタイミング、例えば下記のようにcountの値が変更された時のみtextの値を更新する場合は第二引数の配列にcountを記述します。

```javascript
import React, { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");
  useEffect(() => {
    setText("count変更時のみ起動する、count:" + count);
  }, [count]);
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>count++</button>
      {text}
    </div>
  );
}

export default App;
```
　上記のような使い方をすることで任意のタイミングでtextの中身を更新できます。今回のcountはstateで定義していますが、通常の変数で定義するとコンポーネントの再描写が行われないためうまくいきません。配列の中身はstateで定義するのが無難だと思われます。

#3. おわりに
　いかがだったでしょうか。かなり簡単な使い方にはなりますが、useEffectを使いこなせば強力な武器になると思われます。この記事を読んでる皆さんもこれを機に私と同様に No Code, No UseEffect を掲げましょう。
ダッシュボードを「表示」できるSalesforceのTableau CRMのライセンスは？


見るだけのライセンスの話。

できそうなことが回答されている。
[Hi Trailblazers, is anyone aware of a license for Tableau CRM in Salesforce where you can just 'View' a Dashboard?](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Ci1Q3SAJ)

Analyticsライセンスを使用してカスタム権限セットを作成し、ユーザーがダッシュボードのみを表示するように制限できます。アプリを共有している間は、必ず「閲覧者」権限のみをユーザーに付与してください。

よく分からん。

結局、正規のライセンスがないとみることもできないようです。
困ったなぁ。見るだけのユーザは安価なライセンスで勘弁してほしい。
VSCode おすすめ ショートカットキー (Windows)

最新版は以下の場所に書きました。
https://pakhuncho.github.io/pakhuncho-blog/vscode-shortcut-list.html

VSCode使う機会が増えてきたので整理しておく。
これまでAtomをメインに使ってきたので、[Atomのショートカットキー](https://qiita.com/HyunwookPark/items/2bd5393fcadac82a88d1)と同じのが多いのは助かる。

中でも個人的に利用頻度高いものには★マークをつけた。

# メニュー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/53165633-162e-629d-8f8a-151710400cde.png)

## エクスプローラーを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/e94854d2-c6a5-c82b-2d24-fe45af15b0a9.png)

`Ctrl` + `Shift` + `E`

## 検索を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/7f611023-caec-fd65-7e44-3bc5a9da1a3f.png)

`Ctrl` + `Shift` + `F`

## ソース管理を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/22d8b46e-5b62-482a-e689-5377e572f148.png)

`Ctrl` + `Shift` + `G`

## 実行とデバッグを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/6dfd9f8a-acfa-9a1b-e900-72ebabd5b0e4.png)

`Ctrl` + `Shift` + `D`

## 拡張機能を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/9789bc40-97e7-f50d-b7e8-93997a921eda.png)

`Ctrl` + `Shift` + `X`

# 編集

## 該当行と同じ行をつくる ★

↑・↓どちらを押しても下にコピーされる。複数行まるごとコピーできる。

- `Alt` + `Shift` + `↑`
- `Alt` + `Shift` + `↓`

## 行削除 ★

`Ctrl` + `Shift` + `K`

## 行を上下にずらす ★

- `Alt` + `↑`
- `Alt` + `↓`

## コメント

該当行をコメントにする。
プログラムの種類に合わせたコメントにしてくれるのが嬉しい。
（pythonなら#、javaなら//）

`Ctrl` + `/`

# 選択

## 同じ単語を選択 ★

`Ctrl` + `D`

## 単語ごとに選択

- `Ctrl` + `Shift` + `←`
- `Ctrl` + `Shift` + `→`

## 行の先頭・末尾まで選択 ★

`Shift` + `HOME`
`Shift` + `END`

## 矩形選択

- `Ctrl` + `Shift` + `Alt` + `↑`
- `Ctrl` + `Shift` + `Alt` + `↓`

# タブ

## タブ移動 ★

- `Ctrl` + `PageUp`
- `Ctrl` + `PageDown`

## タブを選択して移動

Windowsの`Alt` + `Tab`みたいに使える。

- `Ctrl` + `Tab`
- `Ctrl` + `Shift` + `Tab`・・・逆順

## タブを閉じる ★

`Ctrl` + `W`

## タブを全部閉じる

`Ctrl` + `K`→ `W`

## 閉じたタブを再度開く

`Ctrl` + `Shift` + `T`

## エディタを分割表示する

`Ctrl` + <code>&yen;</code>

## タブを分割した先に移動

`Ctrl` + `Alt` + `→`
`Ctrl` + `Alt` + `←`

# 検索

## ファイル内を検索

`Ctrl` + `F`

## フォルダ・ワークスペース内を検索

`Ctrl` + `Shift` + `F`

## ファイル名でエディタを開く ★

`Ctrl` + `P`

# プレビュー

## MARKDOWNプレビュー ★

- `Ctrl` + `Shift` + `V`・・・別タブとして表示
- `Ctrl` + `K`→ `V`・・・分割して表示

# サイドバー

## サイドバーの開閉

`Ctrl` + `B`

# ターミナル

## 新しいターミナルを開く ★

`Ctrl` + `Shift` + `@`

# 設定

## 設定を開く

`Ctrl` + `,`

## キーボード ショートカット

`Ctrl` + `K` → `Ctrl` + `S`

# フォーカス

## ターミナルにフォーカス

`Ctrl` + `@`

## エディタにフォーカス

`Ctrl` + `1`

# エディタ

## コードフォーマット

`Shift` + `Alt` + `F`

# ターミナル

## クリップボードの内容を貼り付け

`Ctrl` + `Shift` + `V`

## コマンドパレットを開く ★

表示 > コマンドパレット

`Ctrl` + `Shift` + `P`
vscodeでjavascriptデバッグ方法(chrome)

vscodeでjavascriptデバッグ方法(chrome)の備忘録。

まず、2つのvscodeの拡張機能をインストールする。
・debugger for chrome
・Live Server

以下サンプルファイル

```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DEBUG</title>
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="javascriptdebug.js"></script>
</body>
</html>
```

```javascript:javascriptdebug.js
$(function(){

console.log('debugging!');

});
```

index.htmlの画面を右クリックして「open with Live Server」をクリックする。
(簡易webサーバー起動)

lanch.jsonファイルの設定を行う。

```json:lanch.json
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "localhost に対して Chrome を起動",
            "url": "http://localhost:5500/",
            "webRoot": "${workspaceFolder}"
        }
    ]
```

注意点としては、"url"と"webRoot"はこのままの設定で。

javascriptファイルにブレークポイントを設定し、「デバッグ開始」を押すと
ブレークポイントで停止した。

あと、docker環境でもこの設定でできた。
Google Colabを快適に使うための設定、メモ

# はじめに

Pythonの実行環境構築はJupyter labやVScode、docker、GCPのAI Platformなど色々使ってきましたが、一周回ってGoogle Colab Proが構築の楽さと費用面から良いなあと感じているこの頃。

特に自分のメインの学習内容が、画像データなのでGPUが使えることはマストなのです。

GCPのAI platformは一々立ち上げて、終了してってやるのがめんどくさい。

Google Colabならブラウザで立ち上げるだけで楽ちんです。

と、散々褒めちぎってますが、不便な部分（90分制限、12時間制限など）があるのも確かです。

なんとか快適に画像分類などのタスクを行えないか試行錯誤して今の形に落ち着いたのでメモ。

# Google Driveと連携する
元となる画像データなどは全てGoogle Driveにアップロードしておきます。

左のフォルダマークをクリックして上部の一番右のアイコンをクリックすればDriveと連携できます。

以下は連携済みの様子。
![スクリーンショット 2021-09-30 15.31.53（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890361/5bc5290e-0344-7a29-a654-ad262814dca4.png)

`drive`フォルダの中に`MyDrive`というフォルダがありここから、GoogleDrive上のデータにアクセスできます。

# データをcontent直下にコピーする
`MyDrive`上から画像データを持ってきてndarray形式にしたり、データセットを作ってもいいですが、めちゃくちゃ遅いです。
そのため`drive`の上の階層のcontent直下にデータをコピーすることでで読み込み速度を速くします。

使うものはフォルダのコピーや移動、削除を行える`shutil`というライブラリを使います。

```python
import shutil
shutil.copytree(data_path, '/content/datasets')
```
datapathはコピーしたい元データのパス
第二引数にコピー先のパスを指定して使用します。

# 90分制限に対応する
[コチラ](https://qiita.com/okateru/items/4b7dd3f36bdee3805249)の記事に詳しく書いています。

要は自動的にマウスが動く仕組みならなんでもいいと思います（）

# 12時間（proなら24時間）制限に対応する
これは強制的にストップしてしまうのでどうしようもないです。
従って、途中から学習が再開できる仕組みを整えればokです。

TensorFlowであればcallbackのModelCheckpointを設定しておけばいいですね。

```python:参考
filepath = '/content/drive/MyDrive/checkpoint/epoch_{epoch:02d}-loss_{val_loss:.2f}-psnr_{val_psnr:.4f}-ssim_{val_ssim:.4f}.h5'

checkpoint = tf.keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, 
                                                save_best_only=False, save_weights_only=False, mode='auto', period=100)
```

モデルの保存もGoogleDrive上に保存するようにします。
またモデルのパスにはエポック数や評価指標の値を含むようにします。

![スクリーンショット 2021-09-30 15.48.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890361/54405146-4b1a-a61a-8954-0bb7eed0c711.png)

こんな感じで指定のエポックごとにモデルが保存されていきます。

もし学習が途中で止まったらここからload_modelすればokです。

# その他便利なコマンドなど

```python
gpu_info = !nvidia-smi
gpu_info = '\n'.join(gpu_info)
print(gpu_info)
```
上記コマンドで割り当てられているGPUの種類が確認できます。

```python
def set_seed(seed=46):
    os.environ['TF_DETERMINISTIC_OPS'] = '1'
    tf.random.set_seed(seed)
```
学習の再現性担保のため乱数シードの設定はマストです。
いちいち環境変数とTensorFlowのシード設定を書くのが面倒なので関数化しています。

その他、自分の設定は以下です。
![スクリーンショット 2021-09-30 15.54.21（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890361/d3793131-5ac2-5145-5f1b-968fe4229f89.png)

Jupyter Labをメインで使ってたので、予測をTabキーを押して表示するのに慣れているので「コード入力時の候補を自動的に表示する」はオフにしています。

# まとめ

上記設定というか、やり方でかなり快適に学習を行えるようになりました。これで月額1000円ほどはもはや無料では（？）

Colab Proから抜け出せそうにないですね。Pro+にアップグレードも検討中です。

Colabユーザーの参考になれば幸いです。
【情報求む】FragmentShaderの演算精度でハマった話（Android Chrome93）

こんにちは。つんあーです。


あんまり意識していなかったのですが、シェーダを書く時って頭に演算精度を示す**精度修飾子**を記載しますよね。

```frag.glsl
#version 300 es
precision mediump int; <- これ
precision mediump float; <- これ
```

精度には三段階あります。
- `precision lowp float`
- `precision mediump float`
- `precision highp float`


頂点シェーダでは自動的に`highp`が選択されるそうなので、
今回の話はフラグメントシェーダーに限った話になります。



## Android Chrome93で起こったこと

↓`highp`の場合

```frag.glsl
#version 300 es
precision highp int;
precision highp float;

out vec4 color;
...

void main() {
  
  int num = 2000 + 2001;
  // => 4001
  // ↑当然の結果

}

```


↓`mediump`の場合

```frag.glsl
#version 300 es
precision mediump int;
precision mediump float;

out vec4 color;
...

void main() {
  
  int num = 2000 + 2001;
  // => 4000
  // ﾌｧｯ！？

}

```

単純な足し算ですが、結果が正しくありません。

もちろん、PC(Mac)のChromeではこういったことは起こりませんでした。

**今のところ、原因はよくわかっていません。**

### じゃあ`highp`で書けばいいんじゃね？という話

まあそうといえばそうなんですが。
GLSL3.0は一応、`highp`が標準とされたようです。

なので大方問題はないと思うのですが。。。
とはいえ、GLSL2.0以前の潮流なのか多くのサイトで「highpの実装具合や実行の確実性は環境に左右される」といった記載がされているのと、
これはどこかで聞いたのですがhighpが実装されていない環境の場合は自動的にmediumpが選択されるらしいので、**自分の知らないところで不具合が出てるかも**と思うとちょっとソワソワしますね。

そもそも、フラグメントシェーダの実行結果を数字でみるのってちょっと面倒なので、もし不具合が起こっていた場合の原因追及もなかなかしんどそう。


あと、ぶっちゃけエンジニア感情論的に気持ち悪いですよね。



## この後の動き


もう少し詳しく調べつつ、再現に条件があるのかどうかなどを調べてみようかなと思います。
あととりあえず、Android Chromeの不具合報告にでも送っておこうかな...
Xcode(12)アイコン早見表

#
![xcode早見表.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/b579c3cb-d1b0-1878-e320-406d56f5da2e.jpeg)

Xcodeの各アイコンの機能をまとめました。
まだ全部を覚えられていない初心者向けです。
BizRobo!初見あるある：あれ、ステップが実行されない。。

## はじめに

あえて記事やハウツーとしては取り上げられないが、多くの人がつまづく些細なことを挙げていきます。

## あるある
### :thumbsdown: ボタンをクリックしたのに反応しない。

ロボットを作ったときには動いたのに、開き直したら「Click 検索」を押しても検索ページに移動しない。？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/1339b187-6935-bcad-1b97-36d84be02217.png)<details><summary>実際のところは？</summary><div>「Click 検索」が `青色` で表示されているときにはまだその命令は実行されておらず、その次のステップに移動することにより処理が実行されます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/51a6a74f-1222-6339-1008-aae35ac85696.png)
</div></details>


### :thumbsdown: ファイル読込でPDFを指定しても「アクションを選択」プルダウンが表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/d0df8c0c-cd55-a5cf-9029-ddf86d0f2219.png)<details><summary>実際のところは？</summary><div>「Click 検索」が `青色` で表示されているときにはまだその命令は実行されておらず、その次のステップに移動することにより処理が実行されます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/3dafba97-a81c-d5c6-6cb0-10bbf82955db.png)

</div></details>

## ステップ実行とは

Design Studioの場合少しわかりにくさを感じるかもしれませんが、ロボットの処理を構成する `ステップ` の状態はよく見ると以下のように3色の色分けにより状態が判断できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/ca66710a-7fbf-b1b2-5843-f183d7f5f55d.png)
- 緑：実行済み
- 青：実行前（カレントステップ）
- 灰色：未実行

なので、ステップを実行するというのは、ステップの色を`緑`にすると言い換えることができます。
上の例で行くと、ステップが実行されたのは1つ目の「Do Nothing」だけで、「Load File」を実行するためには、2つ目の「Do Nothing」をクリックして「Load File」のステップを`緑`に変えてあげる必要があります。

もし初学者の方がDesign Studioを触っていて、「あれ、処理が実行されないな？」と思ったらステップの色を確認してみてください！！！:sunglasses:

## 追伸
一方でDAは色分けではなくガイド線の挿入により現在位置を表示する形式なのでわかりやすいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1524794/bd99dee9-2db5-86c5-e82c-5a85c5b596b4.png)
composer requireで「xxx.php does not comply with psr-4 autoloading standard」が発生した

先日からLaravelで開発していたところ、ある時点を境に

```
xxx.php does not comply with psr-4 autoloading standard. Skipping.
```
のエラーが大量に発生した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505734/80244526-a2c7-23dd-e404-778ac704074b.png)

Symfonyは触っていないので、何が問題なのかと調べること1日…… 最初はnamespaceかと思ったけど、問題は自分が起こしたものではなくsymfonyのautoloading側の問題でした。

議論の全貌は以下↓
https://github.com/symfony/symfony/issues/43212

# 結論
composer2を使用しているのであれば、

```
composer update
```
をすれば直ります。

1を使用しているのであれば

```
composer clear-cache
composer update
```
これでも直らない場合は、vendor/ディレクトリの内容を削除して再度実行、それでもできない場合はcomposer2へのアップグレードを検討してください。 という旨が上記のリンクに示されています。

原因はどうやら運営がsymfonyの一部を修正した際に、競合が起きた模様… 明日は我が身…気をつけないと。
【PowerPoint】仕事が捗るショートカット集

#はじめに
今回は「仕事が捗るショートカット集」をテーマに、PowerPointのショートカットをいくつか紹介しようと思います。前回の「【Excel】仕事が捗るショートカット集」のPowerPoint版です。
資料作成などを通して私が便利だなと感じたものを、私の独断と偏見でいくつか紹介します。
使用環境はWindows10になります。

#対象読者
・PowerPoint初心者
・PowerPointで資料作成をする人

#ショートカット集
###基本ショートカット11選
おそらく誰もが知っているであろうショートカット（Excelとほとんど同じ）です。

|No.  |コマンド  |操作キー  |
|---|---|---|
|1  |コピー  |Ctrl + C  |
|2  |切り取り  |Ctrl + X  |
|3  |貼り付け  |Ctrl + V  |
|4  |上書き保存  |Ctrl + S  |
|5  |全選択  |Ctrl + A  |
|6  |元に戻す  |Ctrl + Z  |
|7  |直前の操作を繰り返す  |Ctrl + Y  |
|8  |検索  |Ctrl + F  |
|9  |オブジェクトの複製  |Ctrl + D  |
|10 |プレゼンテーションの新規作成  |Ctrl + N  |
|11 |プレゼンテーションを閉じる  |Ctrl + Q  |

###応用ショートカット10選（資料作成編）
ここからは知らなかったというショートカットもあるのではないでしょうか。
以下のショートカットを知っているだけで、資料作成の効率が大きく上がります。

|No.  |コマンド  |操作キー  |
|---|---|---|
|1  |グリッドの表示/非表示  |Shift + F9  |
|2  |拡大・縮小  |Ctrl + マウスをスクロール / Alt + W + Q  |
|3  |オブジェクトを一つ背面に移動  |Shift + Ctrl + [  |
|4  |オブジェクトを最背面に移動  |Alt + H + G + K  |
|5  |大文字と小文字を切り替える  |Shift + F3  |
|6  |グループ化の解除  |Shift + Ctrl + G  |
|7  |段落のレベルを上下する  |Alt + Shift + 矢印  |
|8  |段落を揃える（中央or両端or左or右）  |Ctrl + E or J or L or R  |
|9  |フォントのサイズを変更する  |Shift + Ctrl + > or <  |
|10  |オブジェクトを左右or上下中央揃えにする  |Alt + H + G + A + C or M |

###応用ショートカット9選（プレゼンテーション編）★
ここでは、プレゼンテーションの際のショートカットを紹介します。

|No.  |コマンド  |操作キー  |
|---|---|---|
|1  |先頭のスライドからプレゼン開始  |F5  |
|2  |途中のスライドからプレゼン開始  |shift + F5  | 
|3  |指定したスライドの表示  |数字キー（スライド番号） + Enter  |
|4  |スライドに蛍光ペンで書き込み  |Ctrl + I  |
|5  |スライドの書き込みを消す（すべて消す）  |Ctrl + E （Eのみ） |
|6  |レーザポインタを出す  |Ctrl + 左クリック  |
|7  |画面を真っ暗にする  |B  |
|8  |BGMを大きくする  |Alt + ↑  |
|9  |先頭のスライドに戻る  |左クリックと右クリックを同時に長押し  |

※またF1でショートカット一覧を見ることも可能です。
いくつかポイントを記載します。
#####No.4 スライドに蛍光ペンで書き込み : Ctrl + I
こちらのショートカットを使うことで、スライドの伝えたい部分を強調したり、目線を集めることができます。

#####No.6 レーザポインタを出す : Ctrl + 左クリック
こちらのショートカットを使うことで、聞き手の目線を集めることができます。マウスカーソルよりも見やすいので積極的に使っていくと良いと思います。

#####No.7 画面を真っ暗にする : B
こちらのショートカットを使うことで、聞き手にスライドではなく、話に集中してもらうことができます。
適度に使用することで、強調したいポイントを示したり、聞き手への理解を促すことにつながると思います。

★ PowerPointは資料を作成するだけでなく、作成物をプレゼンテーションすることが多くあると思います。プレゼンテーションの際もショートカットを駆使することで、より聞き手の理解を促したり、聞き手を引き付けることができて効果的だと言えます。

#まとめ
今回はPowerPointの便利なショートカット集を記事にしました。Excelに続きPowerPointもショートカットを知ることで資料作成の生産性をぐっと高めてくれます。またショートカットは生産性を高めるだけなく、作成物を聞き手に伝えることにも大きな効果があると思います。何のために使うかを考えると覚えも早くなるのではないでしょうか。みなさんどんどん使いこなしていきましょう。筆者自身も頑張ります！
Autonomous Data Guardで東京、大阪リージョン間のフェイルオーバーをやってみた

#はじめに
**Oracle Autonomous Databaseで**先日Cross-region Autonomous Data Guardができるようになったので、東京・大阪リージョン間で手動フェイルオーバーをやってみました。本記事ではOCI CLIを使用して行います。

Autonomous Data Guardの概要については、[こちらの記事](https://oracle-japan.github.io/ocitutorials/database/adb212-audg/)を参考にしてください。

#前提条件
- ADBインスタンスが構成済みであること

- OCI CLIが使用でき、コンパートメント内のリソース操作が可能であること
詳しいやり方は[こちらの記事](https://oracle-japan.github.io/ocitutorials/database/adb501-ocicli/)を参考にしてください。

#Autonomous Data Guardの有効化
OCIコンソールから有効化します。有効化する際にスタンバイADBを置くリージョンを選択できます。
![validation.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/5ba9f037-b364-a46f-6000-51009b49cdcb.jpeg)

プライマリADBが東京リージョンにある場合、スタンバイADBは東京・大阪・ソウルから選択可能です。
このうち、大阪・ソウルに置いた場合、Cross-Regionとなります。

今回はプライマリ：東京、スタンバイ：大阪で構成します。
プライマリADBである、ATPpriのAutonomous Data Guardを有効化すると、自動で大阪リージョンにATPpri_RemoteというADBインスタンスが作成されます。
![ATPpri.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/e7e6c196-7379-e83a-3377-3dae4d940d0b.jpeg)
![ATPpri_remote.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/c59d5591-385f-71f6-0cee-aeb03d870ed2.jpeg)

#CLIを使った手動フェイルオーバー
まずはCLIから現在のコンパートメント内のリソースにアクセスできるか確認してみます。

```
oci db autonomous-database list
```

正しく設定されていれば、現在のコンパートメント内のADBの情報がJSON形式で出力されるはずです。
もし以下のようなエラーが出力されたら、APIに問題があると思われるので設定を見直すか、回避策として[インスタンスプリンシパルを使用してインスタンスからAPI/CLIを利用する](https://docs.oracle.com/ja-jp/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm)ことを推奨します。

```
ServiceError:
{
    "code": "NotAuthorizedOrNotFound",
    "message": "Authorization failed or requested resource not found.",
    "opc-request-id": "E3DB6EE9CCC84BD782C646D7CA52A516/52257E727158FDED7A9D592C796F0006/0501B025885EF0BFBAF0D90E5753DAAB",
    "status": 404
}
```

CLIが正しく使用できることを確認したら、さっそく手動フェイルオーバーをしてみます。
フェイルオーバー自体は一つのコマンドで可能です。

```
oci db autonomous-database fail-over --autonomous-database-id <スタンバイADBのOCID> --peer-db-id <プライマリADBのOCID> --region <スタンバイADBのリージョン>
```

今回はプライマリ：東京、スタンバイ：大阪なので、regionパラメータはap-osaka-1になります。

実行すると、以下のようにスタンバイADBのステータスがロール変更進行中となります。
![rolechange.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/6d712c3c-6b33-c6b7-c279-0afe9f512649.jpeg)

また作業リクエストに"Failover Autonomous Database"が追加されます。
![作業リクエスト.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/1dab435c-e8d3-d244-ab1c-64b44e55ab09.jpeg)

データ量に依存しますが、数分程度でフェイルオーバーは完了します。

まずスタンバイADBであった大阪リージョンのADBインスタンスのロールがプライマリに変わります。
![afterfailove_osaka.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/3dce538c-c792-25dd-08b2-344856fc4902.jpeg)

続いてプライマリADBであった東京リージョンのADBインスタンスのステータスがプロビジョニング中に変わります。
![afterfailove_tokyo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/5f64dc9d-2e7c-dc6e-0d6a-f7ee40ee3637.jpeg)

しばらく経つと東京リージョンのADBインスタンスが使用可能になり、ロールがスタンバイに変わります。

これでフェイルオーバー完了です。

なお、再度プライマリを東京に戻したい場合はスイッチオーバーをします。OCIコンソールからでも操作可能ですが、CLIでは以下のコマンドになります。

```
oci db autonomous-database switchover --autonomous-database-id <スタンバイADBのOCID> --peer-db-id <プライマリのOCID>
```

この際はregionパラメータは必要ありません。
繰り返し処理

繰り返し処理とは同じ処理を何度も繰り返す処理。繰り返し処理を行うメソッドはtimesメソッドとeachメソッドがある。

timesメソッドは指定した回数だけ同じ処理を繰り返してくれる。

処理の回数.times do
　繰り返したい処理
end

で使用できる。例えば
```
3.times do
   puts = “こんにちわ”
end 
```
とすると

こんにちは
こんにちは
こんにちは

と出力される。

変数を|変数|で定義でき||で囲まれた変数をブロック変数という。ブロック変数はメソッド内でしか使用できず0から始まるブロック変数である。
```
3.times do |i|
  puts  “#{ i }回目”
end
```
と記述すると

1回目
2回目
3回目

と出力される。


eachメソッドとは配列やハッシュの要素の回数だけ繰り返し処理を行いたいときにtimesメソッドよりもシンプルに記述ができるもの。

配列またはハッシュ.each do |変数|

で使用できる。例えば配列の場合
```
animals = [“イヌ”,”サル”,キジ”]
animals.each do |member|
   puts  “member”
end
```
と記述すると

イヌ
サル
キジ

と出力される。ハッシュの場合は
```
student = {name :”Taro”,height : 170 ,gender :”men”}
student.each do | key,value |
   puts  “#{key} : #{value}”
end
```
と記述すると

name : Taro
height : 170
gender : men

と出力される。

配列とハッシュが組み合わさった場合
```
students = [
{ name :“Taro”,height :”170”},
{ name :”Rika”,height :”160”}
```
上記のコードからnameを出力したい場合

students.each do |student|
  puts  “#{student[:name]”
end

と記述すると

Taro
Rika

と出力される。
kotlinでfocus search returned a view that wasn't able to take focus!と表示された場合の対処法


実務で以下のエラーに遭遇したので対処法を記載します。

`focus search returned a view that wasn't able to take focus!`　-> フォーカス検索では、フォーカスが取れていないビューが返されました。というエラー内容が表示されてます。

その場合は該当のViewに`isFocusable = false`を追加してあげればエラー回避できます。
【Vue.js】ToDoリストを作成しよう

#はじめに
こんにちは。
Vue.jsでToDoアプリを作成する手順を解説していきます！

<br>

##雛形の作成
まずはVueインスタンスとルートテンプレートを準備します。

```html:HTML
<div id="app">
  <h2>ToDoリスト</h2>
  <form>
    <input type="text">
    <button>追加</button>
  </form>
</div>
```

```javascript:Vue.js
var app = new Vue({
  el:'#app'
})
```

<img width="300" alt="ToDo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/af9779e8-20c3-23f7-20e4-cc9b0f8c5bd5.png">



##テキストボックスと追加ボタンの編集
次に、入力したテキストを双方向データバインディングする処理と、追加ボタンをクリックしたらイベントが発火する処理を記述します。

```html:HTML
<div id="app">
  <h2>ToDoリスト</h2>
  <form v-on:submit.prevent>
    <input type="text" v-model="newItem">
    <button v-on:click="addItem">追加</button>
  </form>
  <pre> {{ $data }} </pre>
</div>
```

```javascript:Vue.js
var app = new Vue({
  el:'#app',
  data: {
    newItem: ''
  },
  methods: {
    addItem: function(event){
      
    }
  }
})
```
dataオプションに空のプロパティのnewItemを作成。（ここに入力したテキストが入る）
テンプレート側では、テキストボックスのinputとnewItemを双方向データバインディングするためにv-modelディレクティブを使用。

追加ボタンのクリックで、methodsオプションのaddItemの処理が発火する。submitエラー防止のため、formタグに上記のように記述しておく。

動作確認のためpreタグでdataを参照しておく。

<br>

##タスクの追加
タスクを追加してリスト表示する処理を記述します。

```html:HTML
<ul>
  <li v-for="todo in todos">
    <span> {{ todo.item }} </span>
  </li>
</ul>
```

```javascript:Vue.js
data: {
  newItem: '',
  todos: []
},
methods: {
  addItem: function(event){
    if(this.newItem == '') return;
    let todo = {
      item: this.newItem
    };
    this.todos.push(todo);
    this.newItem = '';
  }
}
```
addItem内に、入力したタスクを配列todosに追加する処理、タスクの追加後に入力欄を空にする処理、なにも入力されていない状態で追加ボタンをクリックしても処理を行わない記述をそれぞれ入力。

<img width="400" alt="ToDo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/3c56a429-4257-ec28-98dc-c5d82feeaae8.png">

##タスクの完了・未完了の表示
チェックボックスでタスクの完了・未完了を表示する。

```html:HTML
<li v-for="todo in todos">
  <input type="checkbox" v-model="todo.isDone">
  <span> {{ todo.item }} </span>
</li>
```

```javascript:Vue.js
let todo = {
  item: this.newItem,
  isDone: false
};
```
リスト表示させるタスクの前にチェックボックスを配置。
todoの中に、isDoneの初期値をfalseで定義しておき、チェックされると真偽値がtrueになるように双方向データバインディングする。

<img width="400" alt="ToDo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/1be17686-e9bf-97a0-dac3-a5aae821a145.png">

##タスクの削除
削除ボタンでタスクの削除を行う処理を記述します。

```html:HTML
<li v-for="(todo,index) in todos">
  <input type="checkbox" v-model="todo.isDone">
  <span> {{ todo.item }} </span>
  <button v-on:click="deleteItem(index)">削除</button>
</li>
```

```javascript:Vue.js
methods: {
  addItem: function(event){
    if(this.newItem == '') return;
    let todo = {
      item: this.newItem,
      isDone: false
    };
    this.todos.push(todo);
    this.newItem = '';
  },
  deleteItem: function(index){
    this.todos.splice(index,1)
  }
}
```
リスト表示させるタスクの後に削除ボタンを配置。
削除ボタンをクリックしたらdeleteItemの処理を実行し、タスクの削除を行う。タスクとクリックした削除ボタンが連動するように、引数indexをとって、liタグを上記のように変更する。


<img width="400" alt="ToDo" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/87a627e1-171e-e8aa-9326-c04b4ae863bd.png">


#最後に
ここまでToDoアプリの作成についてまとめました。
ただアプリを作るより、言語化してアウトプットしたほうが身につきやすい感覚があるのでこれからも続けていきます！

誤りや感想があればコメントいただけると幸いです！
【AWS】PythonでExcelからDynamoDBへデータを一括登録する

#やりたいこと

以下のようなエクセルのデータをDynamoDBにpythonを使って一括登録していきます。
![スクリーンショット 2021-09-30 15.29.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/726987/db3e6dad-98eb-b864-9ec8-7296b4ff45e8.png)

#プログラム

AWSのライブラリ（boto3）とopenpyxlを使います。

```python
import boto3
import json
import openpyxl
import datetime
import uuid

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table("Demo-table")
dt_now = datetime.datetime.now()

print(dt_now)
wb = openpyxl.load_workbook("サンプルデータ.xlsx")

#シート名
ws = wb["フルーツ"]
#セルの範囲
rng = ws["A2:C4"]

with table.batch_writer() as batch:
    for row in rng:
        item = {
            "id": row[0].value,
            "name": row[1].value,
            "price": row[2].value,
        }
        print(item)
        batch.put_item(item)

```

#まとめ

アプリ開発などでサンプルデータを大量投入したい場合に便利です。
例えば、以下のサイトで疑似個人情報をランダム生成してエクセルにエクスポートできるので、こちらと組み合わせると大量に個人情報を一括登録できます。
https://hogehoge.tk/personal/generator/

ぜひご活用ください！