OmniAICreator/Qiita-1.07M huggingface dataset:
初めてのJavaScript

#初めてのJavaScript
筆者はこれまでWebについてHTMLとCSSには触れてきましたが、JavaScriptをつかった動きの部分をやってきませんでした。
そんなJavaScript初心者の筆者が、初心者の目線で勉強方法をまとめてみました。
これからJavaScriptを勉強する同じ初心者の仲間の役に立てれば本望です。


##JavaScript学習の入り口として理解しやすい初心者本を紹介
JavaScriptを苦手とする人の多くには、そもそも記述されている構文について、読み方が分からない（何を書いているか分からない）という点が挙げられると思っています。
この本では特段難しいJavaScript文は出て来ません。
JavaScriptの基本構文を抑えつつ、その読み方のポイントを教えてくれます。

[スラスラ読める JavaScript ふりがなプログラミング](https://amzn.to/2r1XSik　"スラスラ読める JavaScript ふりがなプログラミング")

1週間もあれば、日中の合間で十分読み切ってしまえました。

また、読み進めながら自身のPCでも同じように動作確認をしていくと、内容をさらに理解しやすかったです。


##初心者として覚えておくべきJavaScriptの構文
下記は『1+1=2』というくらい当たり前に使われる構文です。
上記で紹介した本にももちろん出てきます。
この構文を知らないと有識者にはすごく不思議な顔をされるので覚えておくべきです。

```Javascript
console.log();
```

この構文自体はブラウザ上の表示物に対して動きをどうこうするものではなく、JavaScriptで書いたプログラムの処理の中で、指定した値を出力するためのメソッドです。

ブラウザに搭載されている「デベロッパーツール」（F12で起動する『開発モード』）のコンソールの箇所に、指定の値を出力（値を表示）させることができます。
「console.log('こんにちわ');」と記載すれば、コンソールに「こんにちわ」と表示されるわけです。


###「console.log();」の主な使い方
「console.log();」の主な使用方法としては、自分が書いたJavaScriptのプログラムが、どこまで処理が正しく書けているのかを確認する際に使用します。

処理の各部に「console.log();」を埋め込んで、表示され無くなる箇所、つまりプログラム記述が誤って処理が通らなくなっている箇所を見つけるときに使われます。

初心者がJavaScriptを勉強する際にも、自分が書いた処理の成否を確認する為に使いますし、ベテランでも、自分のプログラムのチェックで使うポピュラーな方法です。


##初心者として覚えておくべき用語
先程**『メソッド』**という言葉を使いましたが、単語の意味を理解できずに進めることは、勉強する中で辛いポイントの一つに感じます。
JavaScriptに関わらず、プログラム言語を勉強する際、様々なカタカナ単語が出てきます。
初心者がプログラムを勉強する際、単語が何を指しているのか分からず、プログラム言語を苦手に思ってしまう要因の一つだと思っています。

『メソッド』とは『方法』を意味し、プログラムにおいて「どういう方法で動くのか」が決まっている部分を指します。

先程の「console.log();」は「入力したデータが表示される」ように決まった方法で動作しています。


##チュートリアルを使って動くものを作ってみる
下記はプログラムの勉強サイト「ドットインストール」にあるJavaScriptの初心者向け講座です。

[ドットインストール：はじめてのJavaScript](https://dotinstall.com/lessons/basic_javascript_v4)

初心者向けに1本3分程の動画が計11本あり、動画を見ながらプログラムコードをまねていくことで、動くものが作れるようになっています。

先に紹介した『スラスラ読める JavaScript ふりがなプログラミング』を読み終えていれば、動画を通して、今現在自分が何を理解できていて、何がまだ分からない部分なのかを感じることができました。

動画を止めながら一緒にJavaScriptをプログラミングしていけば、1時間程で終わる内容です。


##JavaScriptで「どういう処理ができるのか」を知る
ひとえに、JavaScriptでWEB上の要素を動作させると言っても、細かなプログラムが記載されて動いています。

例えば『ページ上部へ戻るボタン』は、下記のような処理の要素があるかと思います。

>・ある程度ページをスクロールしたら表示される。
>　⇒高さを取得するメソッドを用いて、ページの特定の高さが条件で表示される。
>　⇒クラスを切り替えるメソッドで、非表示のクラスが外れて表示される。
>
>・ボタンを押すとスルスルと上部に戻っていく。
>　⇒アニメーションのメソッドを用いて、指定の速度で動作する。

このようにJavaScriptで「どういう処理ができるのか」、どういったメソッド等の機能が用意されているのかを知っておくことは重要になると考えます。

そこで下記の参考書を購入しました。

[JavaScript コードレシピ集](https://amzn.to/35cBNfM：JavaScript コードレシピ集)

この参考書は、JavaScriptに用意されている一つ一つの主だった機能がカテゴリ分けされてまとめられている参考書です。

先に挙げた「高さを取得する」「クラスを切り替える」といった処理ももちろん載っています。
JavaScriptを書いていく際、どういう処理機能を持たせれば思い通りにWEB上の要素を動かせるのかといった、予測がつけられるようになると考えました。

いきなり全部を覚えていくことは大変だとおもいますので、WEB上でよく見られるJavaScriptの動作につながるカテゴリを先に見るように使っており、これも例文をもとに自身でもコードを書いて動作を確認しながら進めます。

・chap1：javascriptの基礎
・chap2：真偽値や数値や文字列の扱い
・chap7：ユーザーアクションの取り扱い
・chap8：HTML要素の操作方法


JavaScriptを書き続けていくうちに何度も使うようなものはだんだん覚えてもいきます。

たとえ覚えられずとも知ってしまえば、必要な時に調べることができるようになると考えます。


##まとめ
・理解しやすい基礎
　[スラスラ読める JavaScript ふりがなプログラミング](https://amzn.to/2r1XSik　"スラスラ読める JavaScript ふりがなプログラミング")

・実際に動くものを作ってみて、面白さ、楽しさを知る。
　[ドットインストール：はじめてのJavaScript](https://dotinstall.com/lessons/basic_javascript_v4)

・javaScriptで何ができるのかを知る。
　[JavaScript コードレシピ集](https://amzn.to/35cBNfM：JavaScript コードレシピ集)

それでは皆さんも良きコーディングライフを。
Youtube動画をループ再生させる


## はじめに

パラメーターをつけることで出来ますが、
ちょっとしたコツがあります。

1つの動画をループする、というパラメーターはないので、実際に行うのは、
**同じ動画を2つ入れた再生リストをループで再生する**

ということになります。

## パラメーター

こちらをパラメーターとしてぶち込みます。
`?loop=1&playlist=VIDEO_ID`

実際に埋め込んでみるとこうですね、同じ動画IDをくりかえしていることがポイントです。

```HTML
<iframe width=”560″ height=”315″ src=”https://www.youtube.com/embed/SX_ViT4Ra7k?loop=1&playlist=SX_ViT4Ra7k”></iframe>
```


### 何をしているのか

まず、
`?loop`
で指定の動画でプレイリストを作り、その中でループさせます。
`playlist=VIDEO_ID`では、どの動画とループ再生を行うかを動画IDで指定します。

今回は同じ動画をループさせるので、同じIDを指定します。


## 無事ループしましたか？
現場では関連動画を出したくない。

背景として動画を使いたい。

など、多様な面で動画をループさせたいというニーズに出会うと思います。

ただ、このやり方は簡単ですが、プレイリストを作成してしまうので、同じ動画が2つ入っているプレイリストにアクセス出来てしまうので、あまりイケてる、とは言えないことになってしまいます。

JavaScriptを使えば、その辺も何とかなったりするらしいのですが、それはまた別の機会にでも･･･。
ボタンクリックでランダムでペンギンの画像が出るページを作る その１


概要は[こちら](https://qiita.com/xcx_04/items/332ab141de4aad6fc5c5)

# ローカル環境を作る
PHPはHTMLのように書いただけでは動きません。これはPHPがサーバー内でないと動かないサーバサイドのプログラミング言語だからです。
けどさすがに動きを確認しながら構築していきたいので、まずはXAMPPを使用して仮想サーバー環境…ローカル環境を作ります。

PHPはインストールして使うものらしいけど（よくわかってない）XAMPPにはPHPも含まれているので、これだけインストールすればOK。らしい。すごい。

インストールの仕方はたくさんの記事があるので割愛します。

### ローカル環境の見方
xamppフォルダの中にhtdocsというフォルダがあり、さらにその中にlocalhostフォルダがあります。
XAMMPを起動したあと、ブラウザのアドレスバーに`localhost`と入力すると、localhostフォルダの中のindex.phpを表示してくれます。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531501/3868155b-39f8-ed52-1902-4a33add02c39.png)

とりあえず中身全部消してphpでhelloを表示させてみたの図


# 指定したディレクトリを任意のURLで見れるようにする
localhostフォルダのindex.phpをlocalhostで見れるようになったものの、
テスト用、勉強用、ポートフォリオサイト用…とプロジェクトごとにディレクトリを分けて管理したいので、それぞれのディレクトリを任意のURLで見れるようにしていきます。

### 1. 設定を変える
`C:\xampp\apache\conf\extra\httpd-vhosts.conf`にある以下の記述のコメントアウト（##）を消します。

```
##NameVirtualHost *:80　//##を消す
```
### 2. ディレクトリを指定
そして下のほうに以下を記述。

```
<VirtualHost *:80>
    DocumentRoot "D:\Document\xampp\htdocs\penguin.com"　//任意のディレクトリパス
    ServerName penguin.local //任意のドメイン名
</VirtualHost>
```
（自分はDドライブに入れているのでパスがDからになっています）

自分はhttpdocsの直下をこのように分けて管理することにします。

httpdocs
　├ localhost    //テスト用
　└ penguin.com    //プロジェクト用

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531501/6e705271-79cb-5650-a19c-572f74850713.png)

任意のドメイン名をcom→localにする必要はありませんが、将来penguin.comというドメインを取ったとき、今見ているサイトがローカルなのかそうじゃないかを区別できるので個人的に変えています。

###3. hostsファイル編集
`C:\Windows\System32\Drivers\etc`の中にあるhostsを開いて、`vhosts.conf`に書いた任意のドメイン名を追加します。

```
127.0.0.1       penguin.local　//vhosts.confに書いた任意のドメイン名
```

### 4. 接続テスト
XAMPPを起動した後、アドレスバーに`penguin.local` をいれて接続してディレクトリの中身が表示されれば成功です。
2、3を追加していくことで、他のディレクトリも任意のURLで見れるようになります。

ローカル環境がhtdocsの直下しか使えないのは不便なので、設定しておくと管理も楽でオススメです✨


# 参考
https://qiita.com/nbkn/items/e72b283c54403a30b2e1
PulseAudioでHDMI/DisplayPort出力とヘッドホンジャックの自動切り替え

環境
OS: ArchLinux(5.3.11-arch1-1)
PulseAudio: 13.0-dirty

参考文献
pulseaudio: auto switch sink when headphones connected - Unix & Linux Stack Exchange
https://unix.stackexchange.com/questions/342556/pulseaudio-auto-switch-sink-when-headphones-connected

# acpidのインストール
acpidは様々なacpiイベントをフックするデーモン。
ヘッドホンジャックの挿抜イベントを補足するのに使用。

```sh
$ sudo pacman -S acpid
```

# ヘッドホン挿抜イベントをフック
まずはイベントファイルを作成

```conf:/etc/acpi/events/headphone-jack
event=jack/headphone
action=/etc/acpi/headphone-jack.sh %e
```

次にheadphone-jack.shを作成する。
予めaudio sink(オーディオ出力)の名前を調べる(ヘッドホンを挿した状態でないとanalog-stereoは出ないかもしれない)

```sh
$ pacmd list-sinks
2 sink(s) available.
    index: 6
	name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2>
	driver: <module-alsa-card.c>
	flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
--- 中略 ---

  * index: 19
	name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
	driver: <module-alsa-card.c>
	flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
--- 略 ---

```
それぞれのデバイスの`name: <〜〜>`の部分が重要。
それぞれの名前を以下のシェルスクリプトにあてはめる。

```sh:/etc/acpi/headphone-jack.sh
#!/bin/bash
set -e -u

if [ "$1" = "jack/headphone" -a "$2" = "HEADPHONE" ]; then
    case "$3" in
        plug)
            sink=alsa_output.pci-0000_00_1b.0.analog-stereo # ヘッドホン出力の名前
            ;;
        *)
            sink=alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2 # HDMI/DisplayPort出力の名前
            ;;
    esac
    for userdir in /run/user/*; do
        uid="$(basename $userdir)"
        user="$(id -un $uid)"
        if [ -f "$userdir/pulse/pid" ]; then
            PULSE_RUNTIME_PATH="$userdir/pulse" su "$user" -c "paswitch $sink"
        fi
    done
fi
```

忘れずに実行権限を付与する

```
$ sudo chmod 755 /etc/acpi/headphone-jack.sh
```

# paswitchのインストール
paswitchはサードパーティ製のsink切り替えツール。以下のコマンドでビルド&インストールする。

```
$ git clone https://www.tablix.org/~avian/git/paswitch.git
$ cd paswitch
$ make
$ sudo cp paswitch /usr/bin
$ sudo chmod 755 /usr/bin/paswitch
```

# acpidを有効化

```
$ sudo systemctl enable acpid
$ sudo systemctl start acpid
```

# 結果
ヘッドホン挿抜でsink切り替え成功！
PYTHONリリースどうするか？

さてさて、ＷＥＢアプリケーションの方は、完成に導くことができました。

し、しかしながら、今日は上司と話をしていて、pythonアプリをどうやって
リリースするか？

それにPYTHONって、会社のパソコンで使っていいの？

なんてことを聞かれました。


そもそも、今年の社長方針で、AIやりましょう！
みたいなことを言っていたのであるから、
当然のごとくpython前提でしょ！

なんて、勝手に思っていました。


という訳で、今日は社内のＡＩ開発の相談室にメールしました。

どうやら、ＡＷＳを使うのはアリっぽいです。


とりあえず、そういう場所へのデプロイを仲介してくれる方が
居るようなのですが、どう考えても
私のＦＬＡＳＫアプリをセッティングできるとは思えない。。。


いまのところローカルＰＣのポート開放で
運用を始めました。


この書き込みも、ほとんど独り言状態です。

まるで、ヒロシみたいです。


こないだ、ヒロシがＹＯＵＴＵＢＥで一人でバーベキューをしているのが
受けているという話を聞きました。

ただ、それだけです。

ひろしです。ひろしです。
transform内のtolowerの呼び出し方

## 概要
https://atcoder.jp/contests/abc011/tasks/abc011_2

上記の問題で下記のようなコードを書いた時に出た疑問解消。

```cpp
#include<bits/stdc++.h>

#define rep(i,n) for(int i = 0; i < (n); i++)

using namespace std;

int main(){
  
  string s;
  cin>>s;

  transform(s.begin(), s.end(), s.begin(), tolower);

  s[0]=toupper(s[0]);
  
  cout<<s<<endl;

  return 0;
}
```

## 起きた疑問

```cpp
transform(s.begin(), s.end(), s.begin(), tolower);
```
上記の箇所で下記のようなコンパイルエラーが発生する。

```
cannot determine which instance of overloaded function "tolower" is intended
```
になるが、下記のように修正すると通る。

```cpp
transform(s.begin(), s.end(), s.begin(), ::tolower);
```

この時呼ばれている`tolower`は実際何なのかについて調べたので復習の意味で記す。


## 結論

結論から言うと`::`をつけた時に呼ばれるtolowerは[こちらのtolower](https://ja.cppreference.com/w/c/string/byte/tolower)である。
グローバルなscopeにある`tolower`が呼ばれている。

## エラーになる理由

`using namespace std`としているので、`locale`と`cctype`の`std::tolower`がデフォルトスコープに含まれてしまっており、`tolower`とした時にどの関数を呼ぶべきかが一意に判別できずにエラーとなっている。
`::`をつけることでグローバルスコープにあるtolowerを一意に識別できている、というふうに動いているようだ。


## 参考URL
https://stackoverflow.com/questions/5539249/why-cant-transforms-begin-s-end-s-begin-tolower-be-complied-successfu
https://stackoverflow.com/questions/5270780/what-does-the-mean-in-tolower
https://qiita.com/_EnumHack/items/430da105a541f9ecd774
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11170167721
[python] WSLのpipenv install時になぜかWindows側のpythonが呼ばれる件

# 概要
- wslでリポジトリにpipenvをinstallしようとするとなぜかエラーが。。。
- どうやらwindows側のpythonを参照している模様
- pythonをフルパスで指定することでとりあえず対策完了

# 環境
- Windows10 1909
- wsl ubuntu 18.0LTS
- pyenv 1.2.13-35-g22c0202
- python 3.8.0
- pipenv 2018.11.26

# 現象
 python3.8になってから初めてWSLでプロジェクトにpipenv をinstallしようとしたら見慣れぬエラーが。。。:frowning2:

```python
user@***:~/prj$ pipenv --python 3.8
# ~~中略~~
'TypeError: write() takes exactly one argument (3 given)\n']
```
ログをちゃんと読んだところ、どうもwindows側のpythonを読んでる模様

```python
OSError: [Errno 8] Exec format error: '/mnt/c/Users/user/AppData/Local/Microsoft/WindowsApps/python.exe'
```
 一旦、pythonを3.7.4に差し戻してみたが変わらず。。。  
原因は、どうもこれっぽい[＃3488](https://github.com/pypa/pipenv/issues/3488)  
このissue、ステートはcloseですが根本的には解決されていないっぽいです。  
とりあえず急場しのぎ的な対策が載っていますので今回はそれで済ますことにしましょう

# 対策
やり方はいたってシンプル。installするpythonをバージョン指定ではなく、フルパスで直に指定します

```python
# 【方法１】バージョン指定していれる場合(例:3.7.4)
#  パスはフルパスで指定してください(~/.pyenv...は不可)
pipenv install --python=/home/ユーザー名/.pyenv/versions/3.7.4/bin/python

# 【方法２】globalなpythonを入れる場合(止めておいた方がいい？？)
pipenv install --python=$(which python)
```
ちょっと気になったのが、globalを切り替えたときにグローバルのpythonのファイル`/home/ユーザー名/.pyenv/shims/python`が差し変わるっぽいので、方法２だとpipenvが見てるpythonファイルが変わっていろいろ面倒なことになりそうという事。
やるなら方法１ですかねぇ(パス指定めんどくさい。。。:rolling_eyes:)
font-familyに指定するフォントの種類が多いのはなぜか

## font-familyとは？
フォントの種類を指定するプロパティです。

## なぜたくさん指定するの？
答えは
<b>OSに応じて用意されているフォントが異なるため</b>でした。
Mac用にHiragino Kaku Gothic ProN、Window用にMeiryo等
それぞのOSに応じた指定する必要がありました。

OSごとのフォントに関しては、以下を参考にさせて頂きました。
[各OSごとの標準システムフォント](https://qiita.com/babandoned/items/b09ea45f6633f30de43e)

## 最後に
ふぉんとに（本当に）！？と思ったらどんな初歩的なことでも
調べるこれが大事やなあと思いました。
（言いたいだけです笑）
Edgeでautocompleteが動作しないとき

# 事象

autocompleteが入力履歴をドロップダウンで表示してくれたけど、それを押してもformに反映されない

そんな時は以下が原因かも。

# 原因

formに同じname属性のinput or select フィールドが存在している。

```html
<input name="hoge" type="hidden" />
<input name="hoge" type="text" />
```

上記のような場合、hiddenの方だけがvalueが更新されて、autocompleteが反映されていないように見えます。
Edge独自のautocompleteスクリプト`Autoformfill_ContentScript.js`が「同じnameのinputは先に存在するものだけをvalue更新する」ことが原因です。

# 対策

- autocompleteを効かせたいinputフィールドを複数存在させない。
- autocompleteを効かせたいinputフィールドを効かせたくないフィールドより前に配置する。

同じnameのinputが存在する方がおかしいと思うので、前者の方が良いかも。

# 所感

ソース読むのめっちゃ大変だった。
minify化されててよくわからんかった。
初心者によるプログラミング学習ログ 163日目

# 100日チャレンジの163日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

163日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>163日目<br><br>今回もメンターさんのwebサイトコーディング課題<br><br>基本的に時間があんまりないんで、一日に１つのことしかできないけど、そのほうがいいのかもしれん<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアとつながりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1196519790908592128?ref_src=twsrc%5Etfw">November 18, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

課題をやっている間は、しばらく書くことないんですよね笑
AWSリージョン名を Asia Pacific (Tokyo) や US East (N. Virginia) 等の形で取得

タイトルの通りちょっと長い形のリージョン名が欲しいときは
SSM Parameter storeの以下のパスを参照すればよい。
`/aws/service/global-infrastructure/regions/${REGION}/longName`

- `${REGION}` には `ap-northeast-1`や`us-east-1` などが入る
- どこのリージョンからでも任意のリージョンの情報を取得できる

# 例: AWS CLI
```bash
$ aws ssm get-parameters \
  --name '/aws/service/global-infrastructure/regions/ap-northeast-1/longName' \
  --output json|jq .Parameters[].Value
"Asia Pacific (Tokyo)"
```


# 例: boto3
```python
import boto3

ssm = boto3.client('ssm')
res = ssm.get_parameters(
        Names = [
            '/aws/service/global-infrastructure/regions/ap-northeast-1/longName'
        ]
)
region = res['Parameters'][0]['Value']
print(region) # Asia Pacific (Tokyo)
```


# つかいどころ
Price List APIのフィルター条件で使いました。
知っているといつか役に立つ日が来るかもしれません。
ローカルのJupyter NotebookからBigQueryを使う


#はじめに
リソースをそこまで必要としない分析で、ローカルのJupyter NotebookからBigQueryデータを使いたい場合がよくある。そこで、ローカルのJupyter NotebookでBigQueryのクエリを書いて、そのままDataFrameに格納するための方法を紹介する。
・macOS Mojave
・Python3.7.3

#Python3の仮想環境を作る
適当なディレクトリ(ここでは`/Users/{username}/BigQueryLocal`)を作成して、virtualenvでEVN3という仮想環境を作り、ENV3を有効にする。

```
$ mkdir BigQueryLocal
$ cd BigQueryLocal
$ virtualenv -p python3.7 ENV3
$ source ENV3/bin/activate
```


#gcloudの認証
まず、以下のURLをクリックする。
https://cloud.google.com/docs/authentication/getting-started?hl=ja

上記のURLをクリックすると、以下の画面が現れるので、`[サービス アカウントキーの作成] ページに移動`をクリックする。
<img width="1429" alt="スクリーンショット 2019-11-19 20.45.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201533/0e2ad650-765e-d7de-c29c-9ee9fa7b25a6.png">

`サービス アカウントキーの作成`に移動して、サービスアカウントを`App Engine default service account`、キーのタイプを`JSON`にして、作成を押すと、JSONファイルがダウンロードされる。

<img width="1429" alt="スクリーンショット 2019-11-19 20.42.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201533/5dbb8c26-74a2-26d1-5617-cedbb97d6efd.png">

ダウンロードしたJSONのアカウントキー`{xxxxxxxxxx}.json`を`/Users/{username}/BigQueryLocal`の直下に配置して、以下を実行する。

```
$ export GOOGLE_APPLICATION_CREDENTIALS="/Users/{username}/BigQueryLocal/{xxxxxxxxxx}.json"
```


#Projectディレクトリを作成する
必ずしも必要ではないが、その後の見通しをよくするために、`TestProject`というディレクトリを作成して、移動する。

```
$ mkdir TestProject
$ cd TestProject
```


#必要パッケージをインストールする
最低限必要な以下のパッケージをpipでインストールする。

```
$ pip install google-cloud-bigquery
$ pip install jupyter
$ pip install pandas
```


#Jupyter Notebookを起動する
以下のコマンドでjupyter notebookを起動する。

```
$ jupyter notebook
```

起動したら、適当なnotebookを作成して、以下のモジュールのインポートとクライアント認証を行う。

```python
[1]
from google.cloud import bigquery
client = bigquery.Client()
```

ここでは、デフォルトで用意されている`bigquery-public-data.samples.natality`のデータを使う。
以下を実行すると、BigQueryデータをDataFrameで扱えるようになる。

```python
[2]
sql = """
SELECT
    plurality,
    COUNT(1) AS count,
    year
FROM
    `bigquery-public-data.samples.natality`
WHERE
    NOT IS_NAN(plurality) AND plurality > 1
GROUP BY
    plurality, year
ORDER BY
    count DESC
"""
df = client.query(sql).to_dataframe()
df.head()
```

実際には以下のような出力になり、DataFrameとして、出力されていることが確認できる。
<img width="1159" alt="jupyter_sample.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201533/df1e8d04-dc43-1431-ea4c-d95feac490ab.png">


次回以降は以下だけを実行すればいよい。

```
$ cd BigQueryLocal
$ source ENV3/bin/activate
$ export GOOGLE_APPLICATION_CREDENTIALS="/Users/{username}/BigQueryLocal/{xxxxxxxxxx}.json"
$ cd TestProject
$ jupyter notebook
```


#参考
virtualenvによる環境構築は、以下を参照。
https://cloud.google.com/python/setup?hl=ja

Jupyter NotebookでのBigQueryの使用方法は以下を参照。
https://cloud.google.com/bigquery/docs/visualize-jupyter?hl=ja
【SQL server】T-SQL 学習メモ / OPENJSON

#OPENJSON
・JSONテキスト　→　行と列のセットに変換できる
・返されたデータでSQLクエリを実行したり、行セットをテーブルに挿入できる。


```
DECLARE @menu NVARCHAR(MAX)

SET @menu'{"name": "coffee", "price": 300, "type": "hot"}';

SELECT *
FROM OPENJSON(@menu);
```

結果

|キー（Key) | value| 型|
|---|---|---|
|name  |coffee| 1| 
|price |300 | 2  | 
|type| hot|  1 |
Javaプログラミング　(クラスの構成)

#クラスの概念
Javaでは避けては通れないクラスについて概要について紹介します。変数と簡単な計算を知っていれば読めます。逆に深いことはこの記事では紹介しません。多分、こういう構成で書くのは珍しいんじゃないかしら？
##クラスとは
厳密なクラスの定義はほかの記事や書籍に譲るとして、クラスとはJavaを作るものです。実際にJavaのいろいろな機能はクラスで定義されています。そして、クラスを自分で作ることで、自分の思う機能を創ることが出来ます。

##クラスの構成
それではクラスを実際に構成してみましょう。ここではTestクラスを作ってみます。
クラスには変数とメソッドといわれる処理があります。Testクラスを日本語で作ってみましょう。


```java
public class Test{
/*
 *クラスの変数をここらへんで宣言
 */
/*
 *ここで、クラスのなかで実現したい処理'メソッド'を定義
 */
}

```

###クラスの変数
クラスの変数は次のように書きます。

```java
private int a = 4;
```
ここでは、aという整数型の変数に4を入れています。
変数には次の2つの命名ルールが使われることが多いです。
#####わかりやすい名前
変数の名前を書きます。Javaのルールではありませんが、変数名は処理や操作の内容を表すものを付けないといけません。ほかの人が見てもパッとわかる名前を付けましょう。
#####LowerCamel
また、一般に英単語をつなげたものがつけられがちですが、大文字、小文字はだいたい決まっています。一般に先頭の英単語は小文字で、2つ目以降は頭文字だけ大文字で書きます。
######例.変数名を二つの英単語 Java Qiitaでメソッド名を作る場合

正しい例
　　javaQiita, qiitaJava

悪い例
　　javaqiita, JavaQiita

ちなみに、privateというものはメソッドの説明のなかで一緒に説明します。

###クラスのメソッド
次にメソッドです。メソッドはこんな処理や行いたい変数の操作を書いています。
そして、最後に処理や操作の結果を返してくれます。
メソッドは次のような構成をしています。

```java
public 戻り値の型 メソッドの名前(引数の型 引数){
/*
*メソッドの中身
*メソッドで実現したい処理や操作を書きます。
*/

return 戻り値;
}
```
一つ一つ解説していきましょう
####戻り値、戻り値の型
メソッドが返してくれる結果を戻り値といいます。そして、メソッドは最初に戻り値はどんな型の値なのかを最初に書いています。
処理の最後に値を 

```java
return 戻り値;
```
と書きます。ちなみに、メソッドはこのreturnを実行したら、そこで終了します。
####メソッド名
メソッド名も変数と同様の命名ルールがあります。
####引数、引数の型
メソッドはなにか値をいれる場合もあります。例えばある数字を3倍する処理とか、ある数字にプラス4だけする処理とかです。このある数字を引数として入れるわけです。引数も変数と同様の命名規則を使います。

####アクセス指定子
ここで、アクセス指定子に触れましょう。変数の時に出てきたprivateとかメソッドやクラスのpublicがアクセス指定子です。これはその変数やメソッドに使うことができる範囲を指しています。
######public
 ほかのクラスからこのメソッドや変数を使うことができます。
######private
 自分のクラスの中からだけメソッドや変数使えます。
初学者はとりあえず、クラスやメソッドはpublicで変数はprivateとすると覚えてもいいでしょう。

###クラスの例
例えば、引数を3倍にして返すメソッドを作ります。

```java
public int multipleIntegerNumber(int num){
 num = 3*num;
 return num;  
}
```
##まとめ
ここでは、クラスの中身の書き方について紹介しました。
実際にクラスをどう使うかとかは次の記事で解説します。
クラスとインスタンス化(少々お待ちください。)
また、アクセス指定子に関係して
カプセル化とsetter, getter(少々お待ちください。)
仕事に効かせるテスト自動化

# みんなが求めていることは結局こういうことじゃない？
仕事に効く技術を求めているんじゃないの！だから記事を真剣に読む！と思う

## 自動化する動機

どこで自分は自動化するのか！？
↓
テストする量が膨大にあるからあるから一人ではしんどい。期限までに何とかしたい
かつ、1度すれば飽きるような似たテストを延々と繰り返す状況になるとき

## 自動化を魅力的だと思う理由
パソコンさえあれば、まるで自分が分身したかのようにテストを行えるんじゃないかと期待するから

## 計画
- まずは作業の工夫(短縮化) → 自動化も早くなる
- ここで、十分に間に合う範囲なら自動化は必要なし
- 今度は一人では間に合わないから、自分の分身を作りたい
- 自動化する

## 自動化のアイディア



### キャプチャ取得

```python:6step.py
# ALT + PRINTSCREEN
# ↓
# Windowsキー + PRINTSCREEN
```
- コマンドでキャプチャを取得する
- ペイントソフトを開く
- キャプチャを貼り付ける
- 画像として保存するために、保存場所を指定する
- 画像を保存する

```python:1step.py
# Windowsキー + PRINTSCREEN
```
※ピクチャのスクリーンショットにはいるので、5stepは省略可能


```python:実装例.py
# スクリーンショットを撮る
def screenshot():
    keyDown(Key.WIN)
    keyDown(Key.PRINTSCREEN)
    keyUp()

#main
screenshot()
```

How to send alt+printscreen command from sikuli?
https://answers.launchpad.net/sikuli/+question/208921
Key Constants
https://sikulix-2014.readthedocs.io/en/latest/keys.html
keyDown
https://sikulix-2014.readthedocs.io/en/latest/region.html#Region.keyDown

以降、更新予定
超絶性能劣化したSQLをチュウーニングした

# 始めに
超絶性能が劣化したSQLをチューニングした時の顛末を書いてみる

# データ構造
# 顛末
夜間バッチの運用試験を実施したら、バッチが2時間経過しても完了しなかった。
1か月前、同じテストを実施したときは10分程度で完了していたのに

# 調査
V$SQLからロングランしたSQLを特定した
ロングランしたSQLのデータ構造はデータ件数が1千万件のエンティティがA,B,C,Dと4つあり、リレーションは下の図のような感じになっている
 
![SQL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136860/dda6f6f5-9fe8-0bbb-0bc8-25fa94db87af.png)

SQL_IDから実行計画を取得し、1か月前の実行計画と比較したところ、A→Bのinner joinしている個所の結合がHashJoin結合から、NestedLoop結合に変化していた。
どうやら、Bのデータが1か月前のテスト時からデータ量が増えたため、OracleのオプティマイザがNestedLoop結合を選択するようにしたらしい。
AもBも大量のデータがあるので、NestedLoop結合はしてほしくないのに

# チューニング
A→BをinnerjoinしているサブクエリにUSE_HASH(A,B)のHint句をつけてバッチを実行したら、1か月前と同じ10分で処理が完了したよ

# おわりに
Oracle12cはNestedLoop結合を好んで用いる傾向があるので、大量のデータ同士をJoinするクエリが遅くなったら、まずは実行計画が変動していないか確認してみよう
買い物かごを一つにまとめるサービス作った


#完成したサービス
買い物カゴを一つにまとめよう 
[OneCart](https://onecart.info/)
![onecart_toppage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296715/db9d2285-b959-09db-39f3-7c6a6dfa832b.png)

よかったら使ってください。

#作ろうと思った経緯
よくネットで買い物をするのだが、気になった商品があったりするとブックマークで保存していた。しかし、これだとurlだけが残るだけで、ぱっと見で商品がわからないし、金額もわからない。
[pocket](https://getpocket.com/)みたいな感じで、URLを入力したら自動で作成されるような感じにしたかった。
よく使うAmazon,Yahooショッピング,zozoなどなど、いろんなサイトのカートをひとまとめにできたら楽だなと思ったから作った。

本当はメルカリのデータも取得したかったんですが、スクレイピングしようとすると403が返ってくるし、どうもメルカリさんはVPSサーバーのIPをブロックしているっぽい。プロキシサーバー使ったり、Seleniumやlaravelのdusk(本番環境で使えない)使ったりなんかはできると思うのですが、面倒なのでとりあえすパス。


#制作期間
これといって難しいものは特に使ってないので、だいたい5日間くらいで終わった。ロゴとサービス名を考えるのに一番時間がかかったかもしれない。結果的にすごく適当なロゴになってしまった。

#使ったもの
勉強ついでにGoで作ろうかと思ったけど、そこまで高速処理を求めてないし、短期間で素早く作りたかったので使い慣れているものでサクッと作った

laravel/vue.js/vuetify/vue router/vuex
laravelでSPA作る時によくある構成、認証はJWTを使用


スクレイピングにはgoutteを使用している
入力されたurlからogpを引っ張ってきてアイテムを作成している。


商品かどうかの判断は、まずOGPのtypeでざっくり判断し、ページから価格が取得できた場合には商品として判定している。精度はまぁまぁ。だんだんと上げていく予定。

OGPがちゃんと設定されていないサイトが多すぎる印象。しっかりしてくれ。


#今後
個人的に便利だなーって思う感じに仕上げていく予定。
カレンダー機能をつけていつ何を買ったかとか見れるようにしたい。
chromeの拡張機能でワンクリックでurl保存できるようにしたい。



#最後に
デザインのセンスが欲しい・・・

次はバイクのツーリング仲間を募集できるサイトを作ります。
HTMLの雛形

・testAppフォルダの作成（その他必要なファイルも作る。画像参照。）
　＜フォルダの階層＞
　　testApp
　　　/index.html(topページ)
　　　/css(スタイルシートのフォルダ)/style.css
　　　/js(javascriptが入るフォルダ)/test.js
　　　/images(画像が入るフォルダ)/img1.jpg

<img width="956" alt="スクリーンショット 2019-11-19 20.12.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420031/0be2915d-e042-25d4-4631-3ebe06d37dae.png">


```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet"  href="css/style.css">
    <title>タイトル</title>
    <script src="js/test.js"></script>
  </head>
    <body>
      <main>
        <p>Hello World</p>
      </main>
  </body>
</html>
```

```css:css/style.css
p{
  font-size: 30px;
  color: red;
}
```

```javascript:js/test.js
window.onload = function() {
  console.log("読み込み完了！")
}
```
・index.htmlをダブルクリック→「Hello World」が表示されれば読み込み完了。
・読み込んだ際文字が赤ければCSSの読み込み完了。
・ブラウザを「右クリック」→「検証」→「console」→「読み込み完了！」が表示されればJSファイルも問題なし。
　
<img width="1402" alt="スクリーンショット 2019-11-19 20.24.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420031/00068b07-ea0d-bdb7-aced-513c6b961149.png">
RailsでSchema migrations table does not exist yet.が出た。

こんにちは[@yukifreeworld12](https://twitter.com/yukifreeworld12)です。

##問題
railsで既にあるモデルにカラムを追加し、`rails db:migrate`したところ

```
$ rails db:migrate
== 20191119102845 AddImageToUsers: migrating ==================================
-- add_column(:users, :image, :string)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
```
そして確認したところテーブルが存在しないというエラー。

```
$ rails db:migrate:status
Schema migrations table does not exist yet.
```

##試したこと
ググって試したのは
`rails db:rollback`,
`bundle exec rake db:drop`,
`rails db:create`
などごちゃごちゃやっても効果なし


##解決
結果はカラムを追加する前に`git reset --hard HEAD`を行っていて変更をなかったことにしたけど、
migrationファイルは`rails db:migrate`していなかった為変更が反映されずそのまま残っていて、
また最初から始めた時にまたカラムを追加したせいでダブってrails aborted!とエラーが出ただけでした。

なので最初から`git reset --hard HEAD`した後に`rails db:migrate`で変更を加えれば良いだけでした。

##最後に
今日も見てくれてホンマありがとな!!
記事がええなと思ったらフォローといいねホンマよろしくな!!
(ジョーブログ風に)
Github Actions で C++ アプリの AARCH64 Linux ビルドを行う

# 背景

aarch64 対応な C++ プロジェクトを Github Actions(CI)で使いたい(CI ビルドしたい).

Github Actions 自体は, 現状 x86-64 Linux のみの対応のようです.

## native(エミュレータ) の方法

run-on-arch-action を使います.

https://github.com/uraimo/run-on-arch-action

中身としては, qemu で aarch64 環境を動かしています. 
最近は qemu も NEON 対応してきたので, Arm SVE(Scalable Vector Extension) 命令など, 特殊な命令セットを使わないのであれば aarch64 バイナリでユニットテストコードを動かすなども問題なくできるかと思われます.

qemu で動かす Ubuntu 環境はちょっと違いますのでご注意ください. gcc など開発系は入っていませんし, sudo などが使えません. apt でも `build-essential` package は用意されれていません.

## cross-compile の方法

apt で aarch64 gcc クロスコンパイラを入れるなどして, クロスコンパイラでやる手もあります.

## サンプル

embree-aarch64 https://github.com/lighttransport/embree-aarch64 を Github actions 対応しました.

https://github.com/lighttransport/embree-aarch64/actions
https://github.com/lighttransport/embree-aarch64/blob/master/.github/workflows/ccpp.yml

Embree のビルドが時間かかるので, cross-compile でも 1 時間, qemu aarch64 だと 3 時間くらいかかります.


```
name: BuildCI

on: [push, pull_request]

jobs:
  build-native-aarch64:

    runs-on: ubuntu-18.04
    name: Build on native aarch64

    steps:
    - uses: actions/checkout@v1
    - uses: uraimo/run-on-arch-action@v1.0.5
      id: aarch64-build-on-qemu-aarch64
      with:
        architecture: aarch64
        distribution: ubuntu18.04
        run: |
          apt-get update
          apt-get install -y cmake gcc g++
          ./scripts/bootstrap-aarch64-linux.sh
          cd build-aarch64
          make VERBOSE=1

  build-cross-aarch64:

    runs-on: ubuntu-18.04
    name: Build on cross aarch64

    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: CmakeAndBuild
        run: |
            sudo apt-get update
            sudo apt-get install -y build-essential
            sudo apt-get install -y gcc-8-aarch64-linux-gnu g++-8-aarch64-linux-gnu
            ./scripts/bootstrap-aarch64-gcc-cross-linux.sh
            cd build-aarch64-cross
            make VERBOSE=1
```

## その他

YAML, インデント間違えたりなどすると動かないので, ビルド構成を記述するには向かないきがしますね.
(インデントチェックしてくれる Github 上での yaml エディタは初回 workflow 作成時しか使えないっぽいようで辛い)

## TODO

* [ ] Test run を qemu aarch64 で行えるようにする.
* [ ] 自前 aarch64 環境を用意し, self-hosting でビルドできるようにする(A72 コアな ROCKPro64 発注中. 最近の 6~8 GB メモリ搭載高性能スマホに Termux 入れる手もあるかも?).
Nuxt.js IE11 で syntax error が発生する場合

## 解決法

`nuxt.config.js` (ts) に以下を追加

```javascript
  ...
  build: {
    // 特定の依存関係を Babel で変換したい場合、マッチする依存ファイル名の文字列または正規表現オブジェクトをここに書く
    transpile: [
      'helpful-decorators'
    ]
  }
  ...
```

今回は、 `helpful-decorators` というモジュール内で arrow function が使われていたことが原因だったので

`helpful-decorators` を `transpile` に追加

## transpile とは？

`node_modules` 下のモジュールに事前に Babel を通す機能

## それでも解決しない場合

上記の `transpile` でも解決しない場合があります

例えば `is-https` というモジュールはソース内で、デフォルト引数を使っています

この書き方は、 `transpile` で解決できないため （たぶんNuxtの仕様、未調査です🙏）

モジュールを `node_modules` から import するのではなく

`src` ディレクトリ下にモジュールの `index.js` ファイルを配置し、 `import` して使うことで強制的に Typescriptコンパイラ を通すことができます

**Typescriptコンパイラ はデフォルト引数を、IEで動作する記述に変更してくれる** ため、IE11で動作するようになります
Node（Express）でJWT

# はじめに
ユーザー認証を実装したい。
スマホアプリ向けのAPI作っているときにユーザー認証が必要となり、JWTが良さそうだったので採用した。

以下、注意点

* 本記事の目的はあくまでJWTの導入なので、脆弱性については触れていない。
* 入門者にわかりやすくするため、有識者には誤解される表現を使っている可能性がある。

## JWTとは
「Json Web Token」の略で、URLに埋め込めるJSON文字列のこと。
電子署名によってJSONが改ざんされていないかをチェックできるため、ユーザー認証などに使うことができる。
~~筆者は詳しく理解してないので、JWT使えばログイン機能作れる！、みたいに思っている。~~

## JWTのしくみ
1. クライアントは、認証情報（ユーザーIDとパスワード）をサーバに送る（いわゆるログイン処理）
2. サーバは、データベースに接続して認証情報が正しいか確認
3. ~~サーバは、ユーザーIDと有効期限といった情報を持つJSONを秘密鍵で暗号化し、JWTの形でクライアントに返す~~
3. サーバは、ユーザーIDと有効期限といった情報を持つJSONに秘密鍵で署名し、JWTの形でクライアントに返す
4. 以降、クライアントは、渡されたJWTを使ってサーバと通信する（いわゆるログイン状態）

JWTの有効期限が切れたら、再び１に戻って新しくJWTを発行する必要がある。

## コード

```:command
npm install jsonwebtoken
```

```js:index.js
var express = require("express");
var app = express();
var jwt = require("jsonwebtoken");

// 秘密鍵設定、本当は環境変数使うべき
app.set("superSecret", hogehoge);

var apiRoutes = express.Router();

// ユーザー情報、本当はデータベースにあるのをとってくるべき
var users = [
  {id: "user0", pass: "huga0"},
  {id: "user1", pass: "huga1"},
  {id: "user2", pass: "huga2"}
];

// クライアントから送られたIDとパスワード確認してtoken（jwt）発行
// "/api/authenticate"
apiRoutes.post("/authenticate", (req, res) =>{
  var post_id = req.body.postId;
  var post_pass = req.body.postPass;
  for (var i = 0; i < users.length; i++) {
    // IDとパスワードが正しかったらtoken発行
    if (post_id == users[i].id && post_pass == users[i].pass) {
      var token = jwt.sign(user_id, app.get("superSecret"), {algorithm: HS256, expiresIn: 120});
      res.json({
        success: true,
        msg: "Authentication successfully finished",
        token: token
      });
      return;
    }
  }
  // IDとパスワードが正しくなかった場合
  res.json({
    success: false,
    msg: "Authentication failed"
  });
});

// 一度クライアントに返したtokenが改ざんされずにクライアントから送られてきたか確認
apiRoutes.use((req, res, next) => {
  var token = req.body.token;
  // tokenがない場合、アクセスを拒否
  if (!token) {
    return res.status(403).send({
      success: false,
      msg: "No token provided"
    });
  }
  // tokenが改ざんされていないかチェック
  jwt.verify(token, app.get(superSecret), (err, decoded) => {
    // tokenが不正なものだった場合、アクセス拒否
    if (err) {
      console.log(err);
      return res.json({
        success: false,
        msg: "Invalid token"
      });
    }
    // 正しいtokenの場合、認証OKする
    req.decoded;
    next();
  });
});

// 認証後、これ以降のURIにアクセス可能となる
// "/api/private"
apiRoutes.get("/private", (req, res) => {
  res.json({
    msg: "Hello world!"
  });
});

app.use("/api", apiRoutes);
```

## 解説
```js
jwt.sing(user_id, app.get("superSecret"), {algorithm: HS256, expiresIn: 120});
```
- アルゴリズム
    - ``algorithm: HS256``　デフォルト値がこれになっており、記述しなくても問題ない
- 有効期限
    - ``expiresIn: 120``　120ミリ秒
    - ``expiresIn: 3h``　3時間
    - ``expiresIn: 2days``　2日

```js
apiRoutes.post("/authenticate", (req, res) => {...});
apiRoutes.get("/private", (req, res) => {...});
```
アクセスする際のURIは、``"/authenticate"``や``"/private"``ではなく、
``/api/authenticate``や``"/api/private"``となる。
理由は、コードの一番下で``app.use("/api", apiRoutes);``としているから。

## さいごに
脆弱性については今後別の記事でまとめる予定。
間違いなどあれば是非コメントにお願いします。

## 参考サイト
* https://www.npmjs.com/package/jsonwebtoken
VBAと共に去りぬ：第1話 Windows OSがある限りVBAがある その３

#VBA 導入のジレンマ
③自動化
自動化とは VBA を使って作業を自動化することである。以下三つの流れでそれを行う。
1　事前ネゴシエーション
2　開発と導入
3　運用

以下は全て蛇足である。
人に見せるようなものではなく考えを書きなぐったものなので自分も読み返して参考にならない、と思うくらいのものなので読む必要がないです。

自動化はあくまでも手段である。
ゴールは目標達成である。
その目標が例えば、「パワーポイント資料を10枚印刷すること」と定義づけられているのであれば、ちょっと間違っている。
SES系の運用業務の目標は、基本的にはお金をもらうことである。
お客さんにお金を払ってもらうことが目標と読み替えても良い。
ではお客様は何に対してお金を払うのか。
「満足」に対してである。


運用が開始された業務では通常、お金をもらうということは契約によって定義されているはずなので、後は成果物を提供することである。
成果物はサービス提供範囲や条件で細かく定義されていることが多いが、結局は「お客さんを満足させる」ことである。
それ以上でもそれ以下でもないと思う。
これはかなり消極的な目標設定であるが、運用業務の中ではひとつの真実だと思う。
積極的な目標設定の例は、沢山ある。
-　価値の創造
-　お客様を導く
-　ゲームチェンジ

ただ現実的にはSES系SIerのチームで上記を達成することは難しい場合が多い。
なぜならそれができる集団であればきっとスタートアップを作って IT サービスを使った事業会社を経営してるであろうから。
(まぁもう事業会社と it の会社を分けること自体ナンセンスで、この世の会社は全て it 企業であるが。)
まずは背伸びせずに、消極的な目標設定を達成してそれができた状態で積極的な目標設定を試みるという順番でいいのではないかと思う。
というか、それが運用系SIerの現実である。

めちゃくちゃ極端な例だけれど、プロジェクトメンバーの全員がサボって何の価値提供もしない状態であるが、めちゃくちゃ可愛い女の子がお客さん側の責任者のご機嫌を取り、お客さんがそれに満足しお金を払ってくれて契約も更新してくれれば、それでいいのである。
というか、その方が良いのである。

例えはよくないけれど、伝えたいことは、自動化は手段であって目的にはならないということである。
目的はあくまで顧客満足である。
(このケースでの自動化はプログラミングでなく女の子の配備である)
とりあえず今はそういうことにしておく。

では自動化はなぜ存在するかと言うと、顧客満足度を上げることに他ならない。
これを履き違えるとVBA導入のジレンマにハマる事になる。
自分たちの業務を楽にするという側面はもちろんあるけれど、それが目的にはならない。
目標を「自分の業務時間を圧縮し自由な時間を確保し新しい知識を身につけ転職もしくは副業するための時間を捻出する」と定義した場合は、自動化は自分のためのものになるが、「顧客満足度を上げる」と定義した場合は、自動化はみんなのためのものになる。

その先を描くなら間違いなく後者を目指すべきであるし、後者を目指しながら行う前者であれば無駄にはならない筈である。

自分の業務を自動化するプログラムの何が悪いのか?と思うかもしれないが、何も悪くない。
しかし問題は、他の人が使いづらい。
それだけである。
しかしそれがとても重要なのである。
UX、UIが騒がれて久しいが、UXとは顧客満足である。(直訳は顧客体験であるが)
要は技術偏重のマスターベーションを止めて本当の目的である顧客満足を見ろということである。そして、顕在化した顧客の課題を解決するだけの満足ではなくて内在する顧客の要求まで満たすような体験を提供しろ。というのがUXの広義な意味であると勝手に思っている。
また技術がコモディティ化して、ちょっとやそっとの技術では差別化できないというのも UX が騒がれている背景にある。
では自分だけのために作ったプログラミングはどうであるか。
これは点で駄目な場合が殆どである。
いや、自分の業務を楽にするという目的だけであるのなら良いのだが、チーム全体の効率を上げる、如いてはお客様を満足させる。という視点で考えるとダメなケースが多い。
例えば、自分だけの業務が自動化されたのならお客様にとっては「楽になったのだから、ひとり人を減らしてもいいよね」
と言うことに当然なるのである。
それだと別にもらえるお金は増えない。
自分たちで自分たちの仕事をなくしているだけである。
それはそれですごいことなのだが、運用チームとしてはそれだけでは駄目である。

ではどうすればいいか?
まず突破すべき3つのバリアについて説明する。
まず突破すべき、三つのバリアを意識し


Kさんへ　VBAのススメ　SES業界で働いてる人は特におすすめ
https://www.youtube.com/watch?v=_3Yh85wlvQs
VBAと共に去りぬ：第1話 Windows OSがある限りVBAがある その２

#まずやること
VBAで業務を自動化しよう。
しかし、自動化しようにも手順書や業務フローがない業務も沢山あるよね。
なので、アプローチの方法はこうです。
①フロー化
②文書化
③自動化

①フロー化について
これはPMを巻き込んでやろう。(Project Managerの事で、AMからPMまで死ぬまで働く。の略語ではないよ。)
絶対に巻き来ないとイケナイ。なぜならここでやりたい事はフローを書く事による「見える化」だけでなく、「要らない作業を減らす」事なんだ。
自動化する時に重要な事は、今やっている作業を全てプログラミング化することじゃなく、まずは、「してもしなくても良い作業を見つけ出し、金輪際それはしないと決定する」こと。
そして必要な作業だけを「業務フロー」として書き起こし、お客さんとも合意すること。(これは運用チーム独特かもね)
合意を取るときに(所謂、お客さんと握る。決してへんなものを握り合うわけじゃない)、身内の1番偉い人とお客様側の担当者に話を通さないといけないから、まず前者であろうPMを巻き込むんだ。

K北さんがこの“現場”に来た時、「さぁここに座ってこれをやってくれ」と言われた業務の束の中には、「何のためにやっているのか」僕らもお客さんも分からないものが実は結構あったりする。
要は「必要だと思い込んでやってるもの」だ。
それを愚直に文句を言わず行うのは作業者として美学を感じずには居られないが、上に物申すのが現代の正しい働き方だと思う。
煙草を咥えながら「あ？これやらないといけないんですか？まじだるいんですけど」と。
上の人がその要望に対して用件を聞き、素直に対応してくれないなら、そんな職場すぐ辞めても良いくらい。
なぜなら、こんだけ新しい技術がどんどん出てくる世の中で、意味のない仕事を社員にさせ続けるような企業は、大かれ早かれ淘汰されるから。
自分のキャリアにとってもよくないので、そうしよう。
ごめん煙草は冗談でした。
ジョイントを巻いて。が、正しいかな。

因みにここでのフロー化は「SES業界の運用チームが作る”業務フロー“」の事で、フローチャートの事ではないのでメカドック。
フローチャート化は②に含まれます。

②文書化
文書化は以下2つから成り立つ。
1 フローチャート化
2 各作業を言葉にする

1はVBAのコードをモジュール化する時に役立つ
2はVBAのコード内のコメントにそのまま対応するイメージ
これはこの前口頭で伝えた通りなんだけど、ちょっと文章にすると伝わりにくくてごめんなさい。

Kさんへ　VBAのススメ　SES業界で働いてる人は特におすすめ
https://www.youtube.com/watch?v=_3Yh85wlvQs
Rails + Turbolinks上のjs内でletを使うと怒られる(Identifier 'a' has already been declared)

## turbolinks × let の相性？

かなり時間を取られたのでメモ。
## 
```html:index.html.erb
<script>
  let a = "Hello";
</script>
```
このようにerbのscriptタグ内にletで変数宣言をすると、turbolinksでの一度訪れたページへの遷移の際
Chromeでは`Uncaught SyntaxError: Identifier 'a' has already been declared`のように怒られてしまいます。

どうやらletで宣言した変数はページ遷移しても保持されたままのようで、再度同じ名前の変数を宣言しようとするために起こるようです。
varを使えば問題なく動作します。

```html:index.html.erb
<script>
  var a = "Hello";
</script>
```
なぜこうなるのか、ご存知の方はコメントお待ちしております。
Excel 2列のデータを1列にして、値を交互に並べ替えたいとき

##やりたいこと
下記みたいなデータがあるとする

|No|A列|B列|
|:--|--:|--:|
|1|1|5|
|2|2|6|
|3|3|7|
|4|4|8|

こうしたい

|No|C列|
|:--|--:|
| 1| 1|
| 2| 2|
| 3| 3|
| 4| 4|
| 5| 5|
| 6| 6|
| 7| 7|
| 8| 8|

##解決方法
下記をC列にペーストして下にスライド。

```
=IF(MOD(ROW(),2)=1,INDIRECT("A"&INT(ROW()/2)+1),INDIRECT("B"&(ROW()/2)))
```

##解説
まず単純にIF分岐。`MOD(ROW(),2)`が1だったら`INDIRECT("A"&INT(ROW()/2)+1)`実行。
`MOD`は剰余を求めます。`ROW`は行番号を取得します。
上記を簡単に以下のように表にしてみると、奇数行は1,偶数行は0になります。

|No|=ROW()|=MOD(ROW(),2)|
|:--|--:|--:|
|1|1|1|
|2|2|0|
|3|3|1|
|4|4|0|

で、次に`INDIRECT`で指定しているセル名を求めている部分も表にすればわかりやすいです。

|No|=ROW()|=MOD(ROW(),2)|IF条件YESの場合(INT(ROW()/2)+1)|IF条件NOの場合=(ROW()/2)|
|:--|--:|--:|--:|--:|
|1|1|1|<font color="Red">1</font>|0|
|2|2|0|2|<font color="Red">1</font>|
|3|3|1|<font color="Red">2</font>|1|
|4|4|0|3|<font color="Red">2</font>|
|5|5|1|<font color="Red">3</font>|2|
|6|6|0|4|<font color="Red">3</font>|

上記により、奇数行の場合は`A1`セルを参照、偶数行の場合は`B1`セルを参照、`A2`、`B2`を参照するとなるわけですね。。
（赤文字部分を`INDIRECT`で参照している）
温度センサーをアップデート

## 温度センサーをアップデートした！（目的）

- DHT11からDHT22にアップデート<br>
  付け替えたら、そのまんま使える訳じゃなかったので、ご説明します。<br>
　前回の記事を見ていない人へ➡︎  [URL](https://qiita.com/arakaki08512/items/22ea1f7bdd6fe72c1209)<br>

参考資料[Raspberry Pi 3+DHT22 で気温を通知するLINEbotを作る②](https://qiita.com/zakopuro/items/ed6720f4c27773cb58c7)<br>
## 使用したもの

- [DHT22](http://akizukidenshi.com/catalog/g/gM-07002/)<br>
  その他は、以前と同じです。

## セットアップ
 [GitHub](https://github.com)にソースコードがあるので、引用してきます。<br>
  - まずは、RPi.GPIOはRaspberry PiのGPIOピン制御できるモジュールをインストール。<br>
  
  ```
$ sudo apt-get install python-rpi.gpio
  ```

  - ねんの為にパッケージもインストール。

```
$ sudo apt-get install build-essential python-dev
```
  - DHT22のライブラリをインストール

```
$ sudo git clone https://github.com/adafruit/Adafruit_Python_DHT.git
```

```
$ cd Adafruit_Python_DHT
```

```
$ sudo python setup.py install
```


## 回路図
- 前回と一緒です。そのまんま引用してすみません。<br>
  ***<font color="red">一つだけ注意があります。</font>***
 - 5Vを与えるとうまく起動しません。(なんでかは知りません）<br>
なので、***3.3V***電圧に変えてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413177/84349be8-bbb2-2d60-ca06-66c48c0ed5a3.png)

## プログラム(Python)

```python:
# coding: utf-8
import RPi.GPIO as GPIO
import time
import datetime
import MyPyDHT

# GBCMの番号で指定する事を宣言
GPIO.setmode(GPIO.BCM)
#BCMの17番ピンを出力に設定
DHT_PIN = 14 
GPIO.setup(DHT_PIN,GPIO.OUT)
HEATER_PIN = 17 
GPIO.setup(HEATER_PIN,GPIO.OUT) 
HotTemp = 10
ColdTemp = -1
sleepSecond = 0
try:
   while True:
       humidity, temperature = MyPyDHT.sensor_read(MyPyDHT.Sensor.DHT22, DHT_PIN)
       if humidity is not None and temperature is not None:
           tmp = temperature
           print(tmp)
           if tmp <= ColdTemp:
               # Heater running
               GPIO.output(HEATER_PIN,1)
               print("Heater ON")
               sleepSecond = 10
           elif tmp >= HotTemp:
               # Heater stop
               GPIO.output(HEATER_PIN,0)
               print("Heater OFF")
               sleepSecond = 10
           else :
               time.sleep(sleepSecond)
       time.sleep(5)
except KeyboardInterrupt:
       GPIO.cleanup()
```
***この前と、ちょっとだけ違います。少しだけなので***

## 動かない場合

<font color="red">***5V***を使用していませんか？<font>
<font color="blue">***3.3V***に差し替えてみてください！<font>
機械学習関連AWSソリューション簡易まとめ

## 目的

MLを利用した動画解析をしたいと思いました。
ですが往々にして、開発環境構築などの本質的ではない作業があります。
本質にフォーカスする時に便利なのがSaaSの存在です(MLaaSと呼びます)。
そのためまずはこれらのサービスの概要を理解したいと考えました。

---

## MLレベルについて

couseraのAndrew Ng先生のmachine leaning講座を修了しました(Stanford大学の修了証は少し嬉しかった)。
MLエンジニアになりたいと考えていますが、研究して人類未踏の領域を広げたいわけではありません。あくまでもMLは手段の一つと考えています。

---

## MLaaSの選定について

開発経験のあるAzure、AWSの2択でした。
Azureに関してはエンジニアからとても完成度の高いデモを見せてもいただいたこともあります(サッカーの試合でゴールシーン前後のキャプチャ、リアルタイム翻訳した字幕付与など)。
結局はできることは一緒かなと思い、すでに個人で契約していたAWSを利用することにしました。

---

## ソリューション一覧

AWSの`機械学習`カテゴリには以下のソリューションがあります(2019/11/07現在)。
SageMaker, Comprehend, Forecast, Lex, Machine Learning, Personalize, Polly, Rekognition, Textract, Transcribe, Translate, DeepLens, DeepRacer

それぞれ、概要を説明していきます。

---

## SageMaker

機械学習のワークフロー全体をカバーする完全マネージド型サービス

汎用的なMLプラットフォームのようです。ラベル付等をひとが一度行うと、性質が同じものをラベル付してくれるものを特にGround Truthと呼びます。
動画の解析もできるようです。

---

## Comprehend

テキスト内でインサイトや関係性を検出する自然言語処理 (NLP) サービス

動画で考えると、音声からテキストをおこして整合性のあるコンテキストすることができるかもしれません。

---

## Forecast

時系列データを用いた数値予測を行ってくれる完全マネジメントサービス

Amazon.comと同じロジックとのことです。
動画解析としては直接利用するケースが思いつきませんが、強いて言えば解析時間等は予測を立てたい部分かもしれません。

---

## Lex

音声やテキストを使用して、任意のアプリケーションに対話型インターフェイスを構築するサービス

Alexaはこの仕組みを利用しているようです。botを使ったサービスは最近いろいろあるのでイメージしやすいですね。動画観点では用途が思いつきませんでした。

---

## Machine Learning

汎用的なML実行ができるPFのようです。sagemakerの方が後発のサービスで、よりML研究者以外の利用を意識しているようです(流行りの既存モデルがすでにあったり、notebookがあったり等)。
モデル構築等重要な部分の違いがわからなかったので、実際に両者を使い比べて見たいと思いました。

---

## Personalize

アプリケーションを使用している顧客に対して開発者が個別のレコメンデーションを簡単に作成できるようにする機械学習サービス

Forecast同様、実際のamazonサービスで利用されています。レコメンドなどのUX向上は動画解析後の話になりそうですね。

---

## Polly

文章をリアルな音声に変換するサービス

動画解析として利用用途が思いつきませんでした。

---

## Rekognition

画像分析と動画分析を行うサービス

まさに、今回の用途に特化したサービスです。動画を与えるだけで良さそうなので、利用も簡単そうです。
こちらは実際に利用してみて、後日内容をまとめたいと思います。

---

## Textract

ドキュメントからテキストとデータを自動抽出するサービス
OCRはもちろんのこと、どのような種類のドキュメントでもテキスト化できるようです。解析後にワークロフーを定義できたりするようで、紙ベースの仕事を自動化できたりするかもしれません。
動画観点では利用用途が思いつきませんでした。

---

## Transcribe

音声をテキストに変換するサービス(自動音声認識: ASR)

動画の字幕を付与できたりするかもしれません。ただ独立して利用するよりかはRekognitionに組み込まれてほしい機能なので、Rekognitionを利用する際はこの観点に留意したいと思います。

---

## Translate

高速で高品質な言語翻訳を手ごろな価格で提供するニューラル機械翻訳サービス

動画字幕、音声の多言語対応で便利そうです。こちらもRekognitionに組み込まれてほしい機能なので、Rekognitionを利用する際はこの観点に留意したいと思います。

---

## DeepLens

深層学習対応のビデオカメラサービスとのことです。

内部ではRekognitionに繋がって、動画を解析してくれるみたいです。
ライブ動画等では検討する余地があるかもしれませんが、今回はアーカイブ動画をターゲットにしているため一旦保留です。

---

## DeepRacer

自動操縦のエンジンを提供するサービスです。

ラジコンに組み込み自走型のデバイスを作成したりできるようです。さらにレースの大会まで用意しているとのことです。
流石に動画解析の用途ではなさそうです。

---

# まとめ

動画解析観点で利用できそうなサービスは、sagemaker, machine learning, rekognitionですね。
とりあえずは簡単に利用できるrekognitionを利用して、どういったデータを出してくれるのか試してみたいと思います。
R　簡単な作業ディレクトリの設定方法（windows）

#WindowsではRの作業ディレクトリの設定が面倒
Rで作業する際には、データやスクリプトがあるフォルダを作業ディレクトリとして設定した方が何かと便利である（＝絶対パスで呼び出す必要がなくなる）。
Rstudioを利用している場合であれば、スクリプトを開くと自動で作業ディレクトリが設定される。
一方、デフォルトのGUI（Rgui.exe）を使う場合には、「ファイル」＞「ディレクトリの変更」から移動する、`setwd`にフォルダの絶対パスを渡す、`choose.dir`を使うなどの少々面倒な方法で設定するしかない。

```R:setwd.r
#パスを渡す場合
setwd("C:/Users/hoge/Documents")
#choose.dirを使う場合
setwd(choose.dir()) #このあとGUIで指定する
```
**もっと楽に作業ディレクトリを設定したい！**
※ 通常の設定方法については[こちらの記事](https://qiita.com/d-cassette/items/59bb6e4b9bbf8e53d2a9)や[こちらのページ](http://rplus.wb-nahce.info/rsemi_operation/rsemi_ope_changeDirectory.html)でくわしくまとめられています。


#指定のフォルダを作業ディレクトリとしてRを起動する方法
##①　Rdataファイルを使う
Rdataファイルをダブルクリックで開くと、その場所を作業ディレクトリとしてRが起動し、Rdataファイル内のデータが読み込まれる。
これを利用し、空のRdataファイルを配置することで指定のフォルダを作業ディレクトリにしてRを起動させる。

###1.　空のRdataファイルを作成する
- Rを起動する
- 適当なフォルダを作業ディレクトリに設定する
- 以下のコマンドを入力する

```R:make_Rdata.r
save(list = NULL, file = "dir.Rdata")
```
これで指定したフォルダに「dir.Rdata」が作成される。

###2.　作成された「dir.Rdata」を、自分が作業ディレクトリに指定したいフォルダに移動する

###3.　dir.Rdataをダブルクリックし、Rを起動する
こちらも`getwd`で確認すると、指定のフォルダが作業ディレクトリになっていることがわかる。

なお作業中のワークスペースを保存することでRdataファイルを作る手もあるが、これは個人的には非推奨。理由は、以前の作業におけるオブジェクトがそのまま引き継がれて混乱が起きるため（例えば、`d`や`i`などの名前がかぶりやすいオブジェクトは、上書きしない限り以前のものがそのまま呼び出される危険性がある）。
データ自体を明確に使いまわししたい時（例えば、一区切りした作業を再開したい時や再計算に時間がかかる時）以外は、スクリプトからオブジェクトを再生成した方が良いと思う。

##②　アドレスバーを使う
2020年3月4日更新：この方法だとバージョンアップグレードの際に混乱が起きるので、①の方をおすすめします。詳しくは後述。

###0.　Rgui.exeまでPathを通す
詳しいパスの通し方は[こちら](https://qiita.com/shuhey/items/7ee0d25f14a997c9e285)を参照。

- 自分の環境でRgui.exeが格納されているフォルダを確認し、フルパスをコピーする
 - インストール時に設定をいじっていないのであれば、「C:\Program Files\R\R-[バージョン名]\bin\x64」になっているはず
- 「スタート」＞「設定」で「設定の検索」から「環境変数を編集」を探す
- 「～のユーザー環境変数」の「Path」を選択し、「編集」をクリック
- 「新規」をクリックし、先ほどコピーしたフォルダのフルパスを追加する（元々入っていたパスを消さないように注意）

※**環境変数の変更は自己責任で。**他のユーザーも使えるようにするならシステム環境変数に追加する

設定はこれで完了。

###1.　作業ディレクトリとして指定したいフォルダをエクスプローラで開く

###2.　Alt+Dを押して、「Rgui」と入力してEnter
アドレスバーをクリックして「Rgui」でもOK。
目的のフォルダを作業ディレクトリとしてRguiが起動する。
`getwd`で確認すると、指定のフォルダが作業ディレクトリになっていることがわかる。
　参考：[エクスプローラから直接Powershellを起動する方法](https://kakesoba2626.wordpress.com/2016/11/01/%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%97%E3%83%AD%E3%83%BC%E3%83%A9%E3%81%8B%E3%82%89%E7%9B%B4%E6%8E%A5powershell%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

![rgui.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/ed32b0c5-7766-c6d0-7309-941cfdfb3360.gif)


**ただしこの方法を使った場合、新しいバージョンのRを入れたときには再度環境変数を変更する必要がある。**
**また前のバージョンのパスを残しておくと、そちらの「Rgui.exe」が呼び出されてしまうので注意。**
**（2020年3月4日追記）**

-----
これで指定したフォルダでRを楽々起動できるようになる（はず）

全然関係ないけど、Rguiで「全てのオブジェクトの消去」を選ぶと「本気ですか？」って聞いてくるの結構面白いと思う。
![honki2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535720/c82b5341-120c-f443-c3b1-f039f8907ac0.png)
Amazon API Gateway で作成された API に IAM 認証を有効にする

#API Gateway API の作成と事前準備#

API に IAM 認証をすることが目的なので、今回は一旦サンプルAPIで準備しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/3551a613-9b29-8f4c-fd41-e87755361fec.png)

テストしておく。
`{"type": "dog","price": 249.99}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/eaeb6cb7-00c3-1c8d-3e5b-5012e585f679.png)



#メソッドリクエストで認可を設定する#
[POST - メソッドリクエスト]で「認可」で「AWS_IAM」にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/c471bfad-3cc0-b12b-902a-4700eb448ec6.png)



#API 認可をポリシーで IAM グループに付与する#

検証のために、
`AmazonAPIGatewayInvokeFullAccess ポリシー`
をtest1にはアタッチし、test2にはアタッチしないようにします。

IAMグループ　test1
IAMユーザ　user1
ポリシー　AmazonAPIGatewayInvokeFullAccess　有

IAMグループ　test2
IAMユーザ　user2
ポリシー　AmazonAPIGatewayInvokeFullAccess　無



#API Gatewayをデプロイし、テストする#

API Gatewayをデプロイし、テストしていきます。

テストには、今回
　[Postman を使用して REST API を呼び出す](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html)
を利用していきますので、詳しい設定方法はドキュメントを確認！


1.IAMユーザ　user1　のアクセスキーシークレットキー
　→　権限があるためレスポンスが返ってくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/d476aa05-80dd-8668-91be-c0f08a6817bb.png)

2.IAMユーザ　user2　のアクセスキーシークレットキー
　→　権限がないためアクセスできない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/9fd53dc2-c799-5f46-0614-45e893ca6e2e.png)

3.空欄
　→　認証が必要とおこられる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/009892b5-2ec9-a834-3273-2a155087cb6d.png)


#リンク#
[API Gateway API に IAM 認証を有効化するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-authentication-api-gateway/)
Spring Data JDBCでInsertできなかった件のメモ

なんとなく復習してたSpring Data JDBCでハマったのでメモ。
（ベースにしたSpring bootがちょっと古いけど・・。）

##環境
* Spring boot 2.1.2
* Spring Data JDBC 1.0.4
* PostgreSQL 10.5

##やろうとしたこと
単に、Spring Data JDBCでテーブルにオブジェクトを保存（レコードをInsert）しようとしただけ

##ハマった原因
どうも、Spring Data JDBCは@IDをつけたフィールドがオブジェクト型の時はnullのときはInsert、nullじゃないときはupdateでSQLを発行するらしい。
テーブルのPKがAuto Generatedじゃないとだめよってことね。


参考
https://stackoverflow.com/questions/50371775/why-does-spring-data-jdbc-not-save-my-car-object


##サンプルコードで動かしてみる
オブジェクト

```Users.java
public class Users {
  @Id
  private Integer user_id;
  private String password;
  private String notes;
```

サービス

```SampleService.java
@Transactional
@Service
public class SampleService {
  @Autowired
  private UserRepository dao;
//略
//極めて雑なコードだけど・・
  public void add(Integer id) {
    LocalDateTime time = LocalDateTime.now();
    Users user = new Users(id, "password", time.toString());
    logger.info(user.toString());
    Users inserted = dao.save(user);
  }
```

テスト実行用

```SampleServiceTest.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleServiceTest {
  
  @Autowired
  private SampleService service;
  
//こちらを実行するとUpdate
  @Test
  public void test1() {
    service.add(3);
  }
  
//こちらを実行するとInsert
  @Test
  public void test2() {
    service.add(null);
  }
}
```

test1()実行時

```
2019-11-19 18:41:47.275  INFO 37316 --- [           main] org.example.test.service.SampleService   : userid: 3, note: 2019-11-19T18:41:47.274
```

そのときのPostgreのSQLトレース

```
2019-11-19 09:41:47.326 UTC [167] LOG:  execute <unnamed>: BEGIN
2019-11-19 09:41:47.334 UTC [167] LOG:  execute <unnamed>: UPDATE users SET user_id = $1, password = $2, notes = $3 WHERE user_id = $4
2019-11-19 09:41:47.334 UTC [167] DETAIL:  parameters: $1 = '3', $2 = 'password', $3 = '2019-11-19T18:41:47.274', $4 = '3'
```

test2()実行時

```
2019-11-19 18:41:47.355  INFO 37316 --- [           main] org.example.test.service.SampleService   : userid: null, note: 2019-11-19T18:41:47.355
```

そのときのPostgreのSQLトレース

```
2019-11-19 09:41:47.368 UTC [167] LOG:  execute <unnamed>: BEGIN
2019-11-19 09:41:47.368 UTC [167] LOG:  execute <unnamed>: INSERT INTO users (password, notes) VALUES ($1, $2)
	RETURNING *
2019-11-19 09:41:47.368 UTC [167] DETAIL:  parameters: $1 = 'password', $2 = '2019-11-19T18:41:47.355'
```


##さいごに
とりあえずDDLを変えるってのと、Spring bootのバージョンも上げてみようかな。
Postgre10だとAuto Generetedにできるのね。
https://qiita.com/nuko_yokohama/items/7d0d5525bcefaa3332ce

あ、PostgreSQLのSQLトレースの設定はこちらを参考にした。
https://www.kakiro-web.com/postgresql/postgresql-sql-log-system.html
応用カリキュラム javascript 01

####アラート表示 window.alert

```js
window.alert("aaa")
//  ポップアップウィンドウで表示
```

####コンソール表示 console.log

```js
console.log("aaa")
// ブラウザのコンソールで表示
```

####変数宣言 let 変数名

####定数宣言 const 変数名

```js
let aaa = "bbb"
console.log("aaa" + aaa);
// aaabbb
```

####条件分岐 if

```js
if (条件式1) {
 処理1
} else if (条件式2) {
 処理2
} else {
 処理3
}
```

####配列

rubyと似てる。

```js
宣言 let aaa = [1,2,3]
取得 aaa[1]
要素数取得 aaa.length
要素追加 aaa.push(5)
要素削除(最後の要素) aaa.pop()
要素削除(最初の要素) aaa.shift()
要素削除(インデックス,要素数) aaa.splice(n1,n2)
```

####オブジェクト

rubyのハッシュに近い？

```js
宣言 let aaa = { num: 1 };
取得 aaa.num
要素追加 aaa.num2= ,aaa["num2"]=
要素削除 delete.num2 , delete["num2"]
```

####算術演算子
+=が使える

####関数定義

```js
function 関数名(引数) {
  // 処理
}
```

※引数がなくとも、()は省略することができない。
※返り値は必ず、return明示

####無名関数

```js
let 変数名 = function() {
  // 処理
}
```

※関数式とすることで、何かに代入したり他の関数に渡しやすい
※コード実行時、先に読み込まれるわけではないので、無名関数の呼び出しは、
　無名関数定義の後でなければできない。
macOSに必須なアプリ(無料)

- Spectacle
- The Unarchiver
- Clipy
- CLCL Lite
- Turbo Boost Switcher
- intel Power Gadget
- Speedtest
- LINE
- Android File Transfer

ダウンロードリンク等はこちら
>https://entotsu44.hatenablog.com/entry/2019/09/14/060000