OmniAICreator/Qiita-1.07M huggingface dataset:
Crowdworks の募集中の案件数を取得 (Beautifulsoup4)

Selenium と Beautifulsoup4 のサンプルとして、CrowdWorks の募集中の案件数を取得してみました。
次のページをスクレイピングします。
[システム開発 の仕事・依頼を探す](https://crowdworks.jp/public/jobs/group/development/u/professionals?order=new)
![crowdworks_sep0201.png](https://qiita-image-store.s3.amazonaws.com/0/179446/d9ff27c6-a3f4-511a-9c32-0c505a2f2d7d.png)

```py:crowdworks_development.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	crowdworks_development.py
#
#					Sep/02/2018
#
# ------------------------------------------------------------------
import sys
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
#
from bs4 import BeautifulSoup
#
# ------------------------------------------------------------------
def file_write_proc(file_name,str_out):
	fp_out = open(file_name,mode='w',encoding='utf-8')
	fp_out.write(str_out)
	fp_out.close()
#
# ------------------------------------------------------------------
def page_ready_wait_proc(driver):
	WebDriverWait(driver, 10).until(
		EC.presence_of_element_located((By.CLASS_NAME,'result_count'))
		)
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
url_target = "https://crowdworks.jp/public/jobs/group/development/u/professionals?order=new"
file_html = "tmp001.html"
#
#
options = Options()
options.add_argument('-headless')
driver = Firefox(executable_path='/usr/bin/geckodriver', firefox_options=options)
ttx = 100
wait = WebDriverWait(driver, timeout=ttx)
driver.get(url_target)
#
idx="filter_hide_expired"
box_check = driver.find_element_by_id(idx)
box_check.click()
#
idx="filter_hide_budget_pending"
box_check = driver.find_element_by_id(idx)
box_check.click()
#
page_ready_wait_proc(driver)
html = driver.page_source
#
driver.quit()
#
file_write_proc(file_html,html)
#
soup = BeautifulSoup(html, "html.parser")
ccx=soup.find(class_="result_count")
ccy=ccx.find("span")
count=ccy.get_text()
sys.stderr.write("count = " + count + "\n")
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./crowdworks_development.py
*** 開始 ***
count = 182
*** 終了 ***
```
RSpecコマンドのオプションまとめ

## はじめに
RSpecコマンドのオプションを調べてみました。
本記事は`rspec --help`の内容がベースです。

## 対象バージョン
RSpec 3.8

## コマンドの使い方
```sh
$ rspec [オプション] [ファイル名かディレクトリ名] 
```

## オプション

|オプション|機能|
|---|---|
|`-I パス`|`$LOAD_PATH`に追加するパスを指定する（複数指定可）|
|`-r`, `--require パス`|コマンドライン上で`require`ができる|
|`-O`, `--options パス`|カスタムオプションファイルのパスを指定する|
|`--order タイプ[:シード値]`|テストの実行順序を指定できる（省略時は`[defined]`）<br>**タイプ**<br>`[defined]`定義された順序で実行<br>`[rand]`ランダムで実行<br>`[random]`ランダムと同じ<br>`[random:シード値]`ランダムを発生させる元となる値を指定<br>例）`--order random:123`|
|`--seed シード値`|「`--order rand:シード値`」で実行した結果と同じ|
|`--bisect[=verbose]`|エラーを最小で再現できるケースに分離するためにテストを繰り返し実行する<br>「`=verbose`」オプションをつけると詳細を表示する|
|`--[no-]fail-fast[=カウント数]`|テストが失敗した時点でテストを停止<br>「`--fail-fast=3`」で3回目の失敗で停止<br>「`--no-fail-fast`」で失敗してもテストを継続|
|`--failure-exit-code コード`|エラー時の終了コードを指定できる|
|`-X`, `--[no-]drb`|DRb経由でテストを実行する<br>（DRbは「distributed Ruby」の略）|
|`--drb-port ポート番号`|DRbサーバに接続するためのポート番号|

### 出力
|オプション|機能|
|---|---|
|`-f`, `--format 形式`|出力する形式を指定する（省略時は`progress`）<br>**形式**<br>`[p]rogress `ひとつのテスト結果を1文字で表示<br>`[d]ocumentation`テスト名を表示<br>`[h]tml`<br>`[j]son`<br>カスタムフォーマットの場合はそのクラス名
|`-o`, `--out ファイル名`|テスト結果を標準出力ではなく指定されたファイルに出力する<br>フォーマットが指定されていない場合は、<br>デフォルトの`progress`形式で出力する|
|`--deprecation-out `ファイル名|廃止予定についての警告をファイルに出力する|
|`-b`, `--backtrace`|全てのバックトレースを表示する|
|`--force-color`, `--force-colour`|出力先がTTYでない場合もカラーで出力する|
|`--no-color`, `--no-colour`|出力先がTTYであってもカラーで出力しない|
|`-p`, `--[no-]profile [件数]`|最も遅いテストをリストアップする（デフォルト10件）|
|`--dry-run`|テストを実行しない|
|`-w`, `--warnings`|Rubyの警告を有効にした状態で実行する|

### フィルタ・タグ
行番号でテストを指定できる。

```sh
$ rspec path/to/a_spec.rb:37:87
```

角括弧での指定もできる（下記は、ひとつめのグループの５番目と６番目のテストを実行）。

```sh
$ rspec path/to/a_spec.rb[1:5,1:6]
```

|オプション|機能|
|---|---|
|`--only-failures`|失敗したテストのみ実行する<br>（`spec_helper.rb`に設定を入れる必要あり）|
|`-n`, `--next-failure`|失敗したテストのみ実行し、ひとつめのエラーで中止する<br>エラーをひとつずつ修正していくのに便利<br>（「`--[only-failures --fail-fast --order defined`」と同じ）|
|`-P`, `--pattern パターン`|指定したパスのパターンに該当するファイルのテストを実行する<br>（デフォルト: `spec/**/*_spec.rb`）|
|`--exclude-pattern パターン`|一致しないパターンを実行する（「`--pattern`」の逆）|
|`-e`, `--example 文字列`|テスト名に、指定された文字列を含むテストを実行する|
|`-t`, `--tag タグ[:値]`|指定したタグのテストを実行する（値の指定も可能）<br>タグの前に~をつけると指定タグ以外を実行できる<br>例） `~slow`|
|`--default-path パス`|RSpecがテストを探すパスを指定できる<br>`/spec`がデフォルトであるが、変更ができる|

### ユーティリティ
|オプション|機能|
|---|---|
|`-v`, `--version`|バージョンを表示|
|`-h`, `--help`|ヘルプを表示|
|`--init`|`.rspec`と`spec/spec_helper.rb`を生成する<br>Railsの場合は、`rails g rspec:install`で<br>これらのファイル（さらに`rails_helper.rb`）を生成する|

## 参考URL
https://relishapp.com/rspec/rspec-core/v/3-8/docs
Tomcat8 から useBodyEncodingForURI の内容が変わっている？

**Tomcat7からTomcat8に移行した時のメモ**

## Tomcat8 から useBodyEncodingForURI の内容が変わっている？

Tomcat7 の時にGETのクエリパラメータに日本語を含んでいた場合、文字化けしていたのですが、
server.xml を useBodyEncodingForURI="true" とするのには影響範囲が大きすぎたので、
以前は下記のように、問題のあるアプリを個別に修正していました。

```java
String param = new String(parameter.getBytes("ISO_8859_1"));
```

しかし、Tomcat8 からは、上記対応をしていると文字化けしていまい、むしろ対応が不要になっています。

Tomcat7: http://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html
Tomcat8: http://tomcat.apache.org/tomcat-8.0-doc/config/ajp.html

ドキュメントを見比べてみると、`URIEncoding`の説明が違う。

### Tomcat7

> This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

> GET時のリクエストパラメタのURIエンコードを指定します。 URIEncodingが指定されていない場合は、 **ISO-8859-1** が使用されます。

### Tomcat8

> This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless the org.apache.catalina.STRICT_SERVLET_COMPLIANCE system property is set to true in which case ISO-8859-1 will be used.

> GET時のリクエストパラメタのURIエンコードを指定します。 URIEncodingが指定されていない場合は、 **UTF-8** が使用されます。
> ただし、システムプロパティ org.apache.catalina.STRICT_SERVLET_COMPLIANCE を trueにすると **ISO-8859-1** が使用されます。

URIEncodingを指定していない時の動作が変わっている。

# 対応

試しにシステムプロパティ`org.apache.catalina.STRICT_SERVLET_COMPLIANCE`を`true`にしてみようと思いましたが、
`org.apache.catalina.STRICT_SERVLET_COMPLIANCE`は、Tomcatのバージョン変化による差を解消するためのオプションみたいで、
影響範囲が広すぎるので、`URIEncoding`に Tomcat7のデフォルトである、`ISO-8859-1`を指定することにしました。

* URIEncoding="ISO-8859-1"を追加

```xml:conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
           redirectPort="8443"
           URIEncoding="ISO-8859-1" />
```
Google Cloud Functions を Serverless Framework で使う

Google Cloud Functionsを使うにあたって、
AWS Lambdaでよくあるデプロイや管理周りを楽にしてくれるフレームワークを探していました。
そこで、現時点で使えそうな「Serverless Framework」を試してみた記事です。
（個人的にAWSだとChaliceがお気に入りです）

結論としては、できないことがいくつかあり、まだ本格的に使うか悩んでいます。

**※この記事は2018/9/2時点に記載しており、それ以降にできることが増えてる可能性があります。**

## サンプル
https://github.com/suzukenz/sandbox/tree/master/cloud-function-sls-trial

npm scriptでserverlessコマンドを色々使えるようにしているので
package.jsonを見るとなんとなくできることがわかるかと思います。

## Serverless Frameworkの使い方

### Quick Start
利用自体は[Serverless Framework公式のQuick Start](https://serverless.com/framework/docs/providers/google/guide/quick-start/)に沿っていけば簡単に開始できます。

1. npmで`serverless`をインストール
2. `serverless create`コマンドでワークスペースを作成
2. GCPの`credential`を取得(`Service account key`)  
※ドキュメントにはOwner権限で作れと書いてますが、Editor権限でも大丈夫でした。
3. `serverless.yml`に`project名`と`credential(key.json)`のパスを記載
4. あとは`serverless deploy`コマンドでデプロイ

という流れです。

### 気をつける点

#### Regionについて
regionの指定については、

1. `serverless.yml`の　`provider => region`に書く方法
2. `deploy`コマンドの`--region`オプションに指定する方法

の２つありますが、後者で行う方がよさそうです。
最初、ymlだけにリージョンを書いてみたら、デプロイ後のエンドポイント表示がおかしくなりました。

例：ymlにだけ書いてコマンドのregionオプションを指定しなかった場合。実際は東京リージョンにデプロイされてるのにこのように表示された。

```
Deployed functions
first
  https://us-central1-kj-poc.cloudfunctions.net/http
```

#### Function名の変更について
デプロイされるCloud Functionの名前は`serverless.yml`に定義しますが、その変更は一度アンデプロイしてからでないとうまくいきませんでした。
ymlの中身だけ変えたら、古い名前のFunctionが消えるだけで終わりました。

具体的には以下の`hello`の部分がfunction名になり、変更時にはundeployが必要。

```yaml
functions:
  hello:
    handler: helloworld
    events:
      - http: path
```


#### CLIで使えるコマンドについて
`serverless help`コマンドでヘルプを参照できますが、Google Cloudではまだ使えないコマンドが結構ありました。（deploy list や deploy functionなど）
使えるコマンドについては[公式のGCP向けリファレンス](https://serverless.com/framework/docs/providers/google/cli-reference/)を読んだ方が良さそうです。

## 試してみて良かった点

### デプロイ、アンデプロイが楽
デプロイが簡単なのはもちろんですが、削除も簡単な点が良いです。
自分で考えると結構面倒ですが、しっかり全て消してくれます。

## できないこと （できてほしいこと）
使うに踏み切れずにいる、微妙な点です。

### Local実行ができない
公式のリファレンスにも記載があり、`invoke local`コマンドは用意されているように見えるのですが、動作しませんでした。

[こちらにissueもあがっており](https://github.com/serverless/serverless/issues/4826)今はできなさそうと諦めました。

### 環境変数設定ができない
Cloud Functionに対する環境変数の設定ができません。
新しい機能なので仕方ないのかもしれませんが。

[こちらはプルリクエストがあがっています](https://github.com/serverless/serverless-google-cloudfunctions/pull/117)。

### Function単位でのデプロイができない
AWSのCLIリファレンスを見るとできるようなので、要望度は低いですが、できてほしい・・・。
デプロイコマンドを打つ度に全部のアップデートはしたくない時があります。

## 終わりに

できない点の記載の方が多くなりましたが、とはいえ自分でガリガリとデプロイの
仕組みを書くのもなあという感じで、冒頭にも書きましたが本格的に使うかはまだ悩んでいます。

この記事は自分へのメモ用でもあるので、今後できることが増えないかトレースしてみます。

// または、他におすすめなライブラリ、方法があったら教えていただけると助かります。
初めてionicを使ってみる

# 基本環境を構築する
- install nvm
 - https://github.com/creationix/nvm

```
  curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
  vi ~/.bash_profile 
  nvm --version
```

- install node and npm
 - https://nodejs.org/ja

```
nvm ls-remote
nvm install v10.9.0
$ node -v
v10.9.0
$ npm -v
6.2.0

```

- install ionic & cordavo

```
npm i -g ionic cordova

$ ionic --version
4.1.1
$ cordova --version
8.0.0
```


# Android SDKの環境変数を設定

```
export ANDROID_HOME=~/Library/Android/sdk
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
export PATH=$PATH:~/Library/Android/sdk/platform-tools:~/Library/Android/sdk/tools
export PATH=$PATH:"/Applications/Android Studio.app/Contents/gradle/gradle-4.1/bin/"
```

# プロジェクトを作成

```
$ ionic start hello_world blank
```

# Androidアプリを作成

```
$  ionic cordova run android
```
Tomcat 8 でTomcat自体が出力するログのフォーマット

**Tomcat7からTomcat8に移行した時のメモ**

## 変更点

* Tomcat 7 + Java 6 でのログ内容

```:catalina.out
2015/01/16 9:26:31 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します
```

* Tomcat 8 + Java 7 でのログ内容

```:catalina.out
16-Jan-2015 9:26:31.518 INFO [main] org.apache.catalina.core.StandardService.startInternal サービス Catalina を起動します
```

2行だったものが1行に変更されている。

## 2行に戻す
これを元の2行に戻すには、conf/logging.propertiesの以下の箇所を

```properties:conf/logging.properties
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
```
以下に変えることでTomcat 7と同じ2行になる。(OneLineFormatter -> SimpleFormatter)

```properties:conf/logging.properties
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
```

これで以下のように2行表示になる。

```:catalina.out
1 15, 2015 12:06:25 午後 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します
```

### よく見ると日付のフォーマットも変わっている

今までは`java.util.logging.SimpleFormatter`で保持している`format`で処理されていたが、
Java 7から`sun.util.logging.LoggingSupport`の`getSimpleFormat`で取得したフォーマットが使われる。

Tomcatのconf/logging.propertiesに以下を追加することでJava 6 の時と同じ内容が得られる。

```properties:conf/logging.properties
java.util.logging.SimpleFormatter.format = %1$tY/%1$tm/%1$td %1$tk:%1$tM:%1$tS %2$s%n%4$s: %5$s%6$s%n
```

やっとTomcat 7 + Java 6と同じになった。

```:catalina.out
2015/01/16 9:26:31 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します
```

## 補足情報

日付書式確認用ソース

```java
package jp.kajiken.format;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

public class TestFormat {

	public static void main(String[] args) {
		// テストする日付
		Calendar cal = new GregorianCalendar(2015, 0, 2, 8, 50, 59);
		Date dat = new Date(cal.getTimeInMillis());

		// Java6
		System.out.print(new MessageFormat("{0,date} {0,time}").format(new Object[]{dat}));
		System.out.println(" org.apache.catalina.core.StandardService startInternal");
		System.out.println("情報: サービス Catalina を起動します");
		System.out.println("---");

		// Java7
		System.setProperty("java.util.logging.SimpleFormatter.format",
				"%1$tY/%1$tm/%1$td %1$tk:%1$tM:%1$tS %2$s%n%4$s: %5$s%6$s%n");
		LogRecord log = new LogRecord(Level.INFO, "サービス Catalina を起動します");
		log.setSourceClassName("org.apache.catalina.core.StandardService");
		log.setSourceMethodName("startInternal");
		log.setMillis(dat.getTime());
		SimpleFormatter sf = new SimpleFormatter();
		System.out.println(sf.format(log));
	}
}
```

実行結果

```:stdout
2015/01/02 8:50:59 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します
---
2015/01/02 8:50:59 org.apache.catalina.core.StandardService startInternal
情報: サービス Catalina を起動します
```

無事に移行前の状態を再現できました。
なぜこんなことをしているのかと言うと、この文字列を使って処理している既存スクリプトがあったのですよ…
git rebase -iでgitのコミットをまとめる



いけてないログがあるときなどログをまとめたい時

##手順
1. git rebase -i  HEAD~
2. どれをまとめるか変更
3. (コンフリクトしてたら)コンフリクト解消
4. PUSHする


##git rebase -i でまとめる

```bash
$ git rebase -i [commitID]
```

これで指定したCommitIDの１つ後のところまで表示。
まとめたいコミットの１つ前を指定する。

```bash
$ git rebase -i HEAD~~
```

-i以下の`~`の数でまとめるログの数
git rebase -i HEAD~2
という書き方でも可能

##いい感じにまとめる

```bash
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
```
のようなメッセージが出るので
消したいコミットログのpickをfに変更する

p,pick そのコミットを使用
r,reword コミットのメッセージのみ変更。ログは残る
e,edit コミットを修正する
s,suash １つ前のコミットにまとめる。ログは書き直す
f,fixup １つ前のコミットにまとめる。ログはその前のに合わせる。

基本は、複数のをまとめたいのでfixupとコメントを編集するeditを多く使用しています。

こんな感じ

```
  r 71a335aad hoge
  f 6e51e52fb iranai mes
  f 596d7eec7 iranai mes
```

コンフリクトがあれば解消し、コメントに沿ってaddしてから　git rebase --continue を行う

失敗した時はgit rebase --abortを行う

```bash
$ git rebase --abort
```

##PUSHを行う
git logなどで変更した後のコミットログを確認してPUSHします。
そのままではpushできないので
ブランチを削除して再度あげるか push -fでpushする

ブランチ消してあげる場合

```bash
$ git push origin :<対象ブランチ> // リモートブランチの削除
$ git push
```

push -fであげる場合

```bash
$ git push -f ブランチ
```

first commitを含む場合はエラーが出るので

```
git rebase -i --root
```

でできる
yukicorder No.3　ビットすごろくをpython3で解いてみた

# 1.はじめに
yukicorderというサイトで競技プログラミングの勉強をしているのですが、はじめて幅優先探索を使って解く問題を解くにあたり、理解するのがやや難しく、解くのに時間がかかりました。
そこで、解法の整理も兼ねて、解説します。
処理の遷移がわかるスライドも作りましたので、よければご覧ください。
参考になれば幸いです。

# 2.参考
問題：https://yukicoder.me/problems/no/3
コード：https://github.com/tagfa/yukicorder/blob/master/No3.py
解説スライド：https://www.slideshare.net/fatag1/yukicorder-no3

# 3.コード
```No3.py
import queue
#移動するマス数を求める関数
def calcpop(num):
    return bin(num).count("1")

N=int(input())
q=queue.Queue()
q.put(1)

masu =[]
masu=[-1]*(N+10)
masu[1]=1

while q.empty()==False:

    curpos=q.get()
    popcnt=calcpop(curpos)
    if (curpos-popcnt>0 and masu[curpos-popcnt]==-1):
        masu[curpos-popcnt]=masu[curpos]+1
        q.put(curpos-popcnt)
    if (curpos+popcnt<=N and masu[curpos+popcnt]==-1):
        masu[curpos+popcnt]=masu[curpos]+1
        q.put(curpos+popcnt)

print(masu[N])
```

# 4.解説
## 4-1.処理概要
1. キューから値を取り出し、現在のマス目とする。
2. 現在のマス目を2進数に変換し、1のビット数だけ前後のマスを参照。
3. 未更新だった場合、
   1. 現在のマスの内容に1を足した数で更新。
   2. 参照マスをキューに入れる。
4. キューの中身が空であれば、処理終了

## 4-2.コード解説
[masu]というlistを用意します。
この[masu]は、indexがマス目の番号、値がそのマスへの最短移動数を保持します。
例えば、
`masu[5]=4`
であれば、5マス目の最短移動数は4であるということを表します。
そして、このマスを-1で初期化しておきます。
この-1という値は、未探索のマスであるということを表します。
最短移動数としてとりえない値、つまり0や、極端に大きな値などであればなんでもいいのですが、問題文より
>到達できない場合は-1

ですので、-1で初期化しておくと、出力時に余計な変換をせずに済みます。

次にキューを作成し、初期位置の「1」を入れておきます。

キューから値を取り出し、これを現在のマス目(`curpos`)とし、2進数に変換したときの1の数を数えます。(`popcnt`)
ここでは、標準ライブラリの`bin()`で2進数に変換し、`count()`で1の数を数えています。

そして、求まった1の数だけ前後のマスを参照します。
前のマスの場合、0より大きい、かつ未到達の場合にマスの値を更新します。
後ろのマスの場合、N以下で、かつ未到達の場合にマスの値を更新します。
問題文
 > 1未満とN+1以上のマスには移動することは出来ない

より、「0より大きい」、「N以下で」という条件を導き出しました
この前後のマス目は、次に進めるマス目となりますので、現在の移動数+1の値で更新します。
更新できた場合、次のマス目から探索をするため、Queue(`q`)に次のマス目をputします。
この段階でキューの中身が空であれば、次のマス目がない、つまり探索できるところはすべて探索したということなので、探索処理を終了します。
この探索処理が終わると、`masu[N]`に最短移動数が格納されていますので、`masu[N]`の中身を標準出力に出力して、おしまいです。
到達できなかった場合は-1を出力する必要がありますが、初期値として-1を格納していますので、そのまま出力してしまって問題ありません。
Sigfoxネットワーク品質指標 - Link Quality -

#Link Qualityとは
Sigfoxネットワークは、デバイスから送信された信号を複数のゲートウェイで受信可能です。そのため、Sigfoxネットワークでのネットワーク品質を評価する指標として、ゲートウェイでの受信レベルと受信局数による**Link Quality**が定義されています。
[Radio Configuration](https://qiita.com/ghibi/items/ac9a1642b2feca8f9eb7)によりLQIの計算方法が異なりますが、日本国内（RC3）では下記の条件に基づきLQIが決定されます。

|RSSI|受信局数|Link Quality||
|:---|:---:|:---|:---:|
|-122dBm ≦ RSSI|3|EXCELLENT|![EXCELLENT.png](https://qiita-image-store.s3.amazonaws.com/0/172313/18277e97-0234-3df0-ecab-c61b0ac373ef.png)|
|-135dBm ≦ RSSI < -122dBm|3|GOOD|![GOOD.png](https://qiita-image-store.s3.amazonaws.com/0/172313/6aa2f25a-1fbe-fd3f-b2ab-6fed6dc3369d.png)|
|-122dBm ≦ RSSI|1 or 2|GOOD|![GOOD.png](https://qiita-image-store.s3.amazonaws.com/0/172313/6aa2f25a-1fbe-fd3f-b2ab-6fed6dc3369d.png)|
|-135dBm ≦ RSSI < -122dBm|1 or 2|AVERAGE|![AVERAGE.png](https://qiita-image-store.s3.amazonaws.com/0/172313/3aef34db-3332-5958-6d35-78d4eae58aec.png)|
|RSSI < -135dBm|any|LIMIT|![LIMIT.png](https://qiita-image-store.s3.amazonaws.com/0/172313/d9fa40e3-89d4-418f-1808-a5978fde95c8.png)|

このLink Qualityは、Deviceのメッセージビューで確認できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/172313/3082dede-d66f-bac1-eb5d-e27e87ddf3a9.png)

#日本以外でのLQI
日本（RC3）以外の国のLQI定義は、大きく2つに分かれています。
RC1,RC3,RC5では、上記の通りとなっていますが、RC2,RC4では、下記の条件になります。

**LQI for RC2,RC4**

|RSSI|受信局数|Link Quality||
|:---|:---:|:---|:---:|
|-114dBm ≦ RSSI|3|EXCELLENT|![EXCELLENT.png](https://qiita-image-store.s3.amazonaws.com/0/172313/18277e97-0234-3df0-ecab-c61b0ac373ef.png)|
|-127dBm ≦ RSSI < -114dBm|3|GOOD|![GOOD.png](https://qiita-image-store.s3.amazonaws.com/0/172313/6aa2f25a-1fbe-fd3f-b2ab-6fed6dc3369d.png)|
|-114dBm ≦ RSSI|1 or 2|GOOD|![GOOD.png](https://qiita-image-store.s3.amazonaws.com/0/172313/6aa2f25a-1fbe-fd3f-b2ab-6fed6dc3369d.png)|
|-127dBm ≦ RSSI < -114dBm|1 or 2|AVERAGE|![AVERAGE.png](https://qiita-image-store.s3.amazonaws.com/0/172313/3aef34db-3332-5958-6d35-78d4eae58aec.png)|
|RSSI < -127dBm|any|LIMIT|![LIMIT.png](https://qiita-image-store.s3.amazonaws.com/0/172313/d9fa40e3-89d4-418f-1808-a5978fde95c8.png)|

おそらく、RC2とRC4はデータレートが100bpsではなく600bpsであることから、受信品質にマージンを設けているものと思われます。

[Sigfox Japan KCCS](https://qiita.com/organizations/sigfox)
macのキー入力速度を爆速にする

# macのキー入力の速度を変更する。
### いつも忘れるのでメモ
- キー入力時のイライラを感じなくなる。
- 設定はターミナルから下記のコマンドを実行してください。
- ちなみに設定のに反映には再起動が必要です。
    - ん?High Sierraだと即時反映されました。

###　繰り返しの認識までの時間
```bash:確認
defaults read -g InitialKeyRepeat
```
```bash:設定
defaults write -g InitialKeyRepeat -int 13
```

### 繰り返しの速度
```bash:確認
defaults read -g KeyRepeat
```

```bash:設定
defaults write -g KeyRepeat -int 1
```
StackOverflowError（無限ループ）


技術書に無限ループになってしまうからそれはだめだと書いてあり、実際どのようにしたら無限ループになるのかを調べました。

```java
public static void add(){
    add();
}
```

簡単に書くと、こうすると無限ループになります。
関数を宣言して、その内側でおなじ関数を呼ぶ。
すると，add()がadd()を呼び続けるため無限ループになる。

eclipse上だと、java.lang.StackOverflowError
というエラー文が出て終了します。

つまり、stack領域がいっぱいになってあふれたということでエラーになります。

Java Platform, Standard Edition 7　API 仕様によると、
アプリケーションでの再帰の回数が多すぎてスタックオーバーフローが起こる場合にスローされます。

ということだそうです。
自分の場合勝手にとまりましたが、とまらなかったら、ctrl + c か ctrl + z か　Escキー
が有効だそうです。
Pythonista Help(clipboard)

英語がわからないので機械翻訳しました。

[clipboard — Copy and paste — Pythonista Documentation](http://omz-software.com/pythonista/docs/ios/clipboard.html#module-clipboard)
# clipboard — Copy and paste
クリップボードモジュールは、iOSのテキストクリップボード（a.k.a.ペーストボード）を読み書きするための2つの単純な関数を定義しています。

例:

```python
# クリップボードを大文字/小文字に変換する
import clipboard
text = clipboard.get()
if text == '':
    print('No text in clipboard')
else:
    uppercase = text.upper()
    if uppercase != text:
        new_clip = uppercase
    else:
        #already uppercase, convert to lowercase
        new_clip = text.lower()
    clipboard.set(new_clip)
    print(new_clip)
```

# clipboardモジュールの関数:

`clipboard.get()`

- クリップボードの内容をUnicode文字列として返します。

`clipboard.set(string)`

- クリップボードの内容を新しい文字列またはUnicode文字列に設定します。

`clipboard.get_image(idx=0)`

- クリップボードから画像をPIL画像として返します。
- クリップボードに複数の画像がある場合、idxパラメータを使用して、指定されたインデックスで画像を取得できます。インデックスが> =クリップボード内のイメージの数である場合、Noneが返されます。

`clipboard.set_image(image、format = 'png'、jpeg_quality = 0.75)`

- 指定したPIL画像をクリップボードに保存します。  
- formatパラメータは 'png'または 'jpeg'です。  
- formatが 'png'の場合、jpeg_qualityは無視されます。それ以外の場合は、0.0〜1.0の間のfloatになります。
[構想]郵便受けポストに郵送物があるか無いかを遠隔で知る

## 概要
・[起案理由]マンションの郵便受けポストに郵送物があるかないかを遠隔で知りたい

・[デバイス]ラズパイ+3G+SORACOM AIR SIM +カメラ+LEDライト+単３電池駆動
上記を郵便受けポストに入れて
「１６時に起動してLEDライト点灯させ撮影しFTPサーバへ送信したら寝る」
・[AWS EC2]FTPサーバで画像GETして二値化処理をかける。
郵送物が映ってたらSNSでメール発砲。

## 10月ごろ実装してJAWSUGやソラコムユーザ会で発表できたら良いなぁ
rails のtransaction処理

#transaction 処理
不可分の一連の処理作業です。

#単一モデルにおける実装
処理に制約をつけて、わざとロールバックさせられる環境を作ります。

```User.rb

validates_presence_of :username
#usernameを必須にする

```

実際のロジックはこんな感じです。

```
#コンソール
User.transaction do
  user1 = User.new(username: "ttm", age: 25)
  user1.save!
  user2 = User.new(username: nil, age: 26)
  user2.save!
end
```
saveではダメです。transactionは例外処理に反応してロールバックするので、！をつけて例外を起こさせるようにします。


#複数モデルにまたがる実装
新しいモデルと制約を課します。

```Book.rb

validates_presence_of :title
#titleを必須にする

```
ロジックは下の感じ。

```
#コンソール

ActiveRecord::Base.transaction do
 user = User.new(username: "ttm", age: 25)
 user.save!
 book = Book.new(title: nil)
 book.save!
end

```

より良いシステムを作るには必要そうなので、是非覚えておきたいです。
Spring BootでThymeleafのDialectを追加する方法

# 環境

Spring Boot 2.0

# デフォルトで使えるDialect

- Java8TimeDialect

spring-boot-starter-thymeleafの依存性として入っていて、かつAuto Configurationクラス内で追加されているので、何もしないでも使うことができます。

# 依存性を追加するだけでOKなDialect

- SpringSecurityDialect
- LayoutDialect
- DataAttributeDialect

上記の3つはAuto Configuration対象になっているため、依存性を追加するだけで使うことが出来ます。

ここらへんを読んでみてください。

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java#L297

# その他のDialect（自作のDialectなど）

上記以外のDialectについては、適当にJava Configクラスを作成してDialectをBean定義すればOKです。

```java
@Configuration
public class ThymeleafDialectConfig {

    @Bean
    public FooDialect fooDialect() {
        return new FooDialect();
    }

    @Bean
    public BarDialect barDialect() {
        return new BarDialect();
    }
}
```

Bean定義すれば、Auto Configurationクラスによって使われます。

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java#L143

# やってはいけなくはないけど・・・

`SpringTemplateEngine` を自分でBean定義してもいいのですが、Auto Configurationクラスで定義している `SpringTemplateEngine` のBeanが無効化されてしまいますので、なるべくやらないようにしましょう。

```java:これはなるべくしない
@Configuration
public class ThymeleafDialectConfig {
    
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        ...
        engine.addDialect(new SpringSecurityDialect());
        engine.addDialect(new LayoutDialect());
        engine.addDialect(new DataAttributeDialect());
        engine.addDialect(new FooDialect());
        engine.addDialect(new BarDialect());
        return engine;
    }
}
```
vs2010でmanaged directx その11

#概要
c#で、3Dやりたかった。
フォントを表示してみた。

#写真

![image](https://qiita-image-store.s3.amazonaws.com/0/18104/c24ba4a1-5346-74e6-7429-4f9e7d4e9634.png)



#サンプルコード

```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        private Device device = null;
        private Microsoft.DirectX.Direct3D.Font font;
        private String info;
        public Form1()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);
            info = string.Format("あす");
            System.Drawing.Font winFont = new System.Drawing.Font("MS ゴシック", 50, FontStyle.Regular);
            font = new Microsoft.DirectX.Direct3D.Font(device, winFont);
            font.PreloadText(info);
        }
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            device.Clear(ClearFlags.Target, Color.DarkBlue, 1.0f, 0);
            device.BeginScene();
            device.SetTransform(TransformType.World, Matrix.Identity);
            font.DrawText(null, info, 50, 50, Color.Red);
            device.EndScene();
            device.Present();
            this.Invalidate();
        }
    }
}


```

以上。
TeamViewer13による会議の開催／参加方法

# TeamViewer13による会議の開催／参加方法
## 前書き
・本ページは、TeamViewer13を利用して主催者PCの画面を共有した会議ミーティングを行うための、最小手順を記載したものです。

・本ページで説明しているTeamViewerのバージョンは以下です。
Version 13.2.14327
>※TeamViewerを持っていない、Versionが極端に古い場合は、こちらを参考にインストールしてください。
>https://teamviewer-howto.com/?page_id=4

・TeamViewerへのアカウント作成やログインは不要です。

・趣味で使っているため、非商用(無償利用)を想定して記載しています。


## 会議の主な流れ
１、主催者が会議を開く
２、主催者が参加者へ会議IDを伝える
３、参加者が会議IDを入力する


以下、詳細です。

---

#### １、主催者が会議を開く
1-1 TeamViewerを起動する


1-2 ①「会議アイコン」をクリックし、②「名前」を入力する
![qiita_teamviewer_02.png](https://qiita-image-store.s3.amazonaws.com/0/238650/4b2e70bf-8f5d-e3f0-a862-5a7d3951479c.png)
  ※「名前」は他のメンバーへ表示される名称です


1-3 プレゼンテーションボタンをクリックして会議が開始する
![qiita_teamviewer_03.png](https://qiita-image-store.s3.amazonaws.com/0/238650/59241d2b-ff80-b608-2e82-92f64446a713.png)


1-4 画面内に別途表示された部分から「会議ID」をコピーする
![qiita_teamviewer_04.png](https://qiita-image-store.s3.amazonaws.com/0/238650/2ab5d490-68f8-3166-4145-72f66ae47d05.png)

---
### ２、主催者が参加者へ会議IDを伝える
2-1 メールやチャット等を利用し参加者のみへ伝えます
  ※会議IDを知っているだけで会議へ参加できるので不要な方へは伝えないよう注意！

---
### ３、参加者が会議IDを入力する
3-1 会議の主催者から「会議ID」を教えてもらう

3-2 TeamViewerを起動する

3-3 ①「会議アイコン」をクリックし、②「名前」を入力する
![qiita_teamviewer_15.png](https://qiita-image-store.s3.amazonaws.com/0/238650/280bc3bc-dd69-70cb-c35d-3b516b6cf659.png)
  ※「名前」は他のメンバーへ表示される名称です

3-4 ①「会議ID」を入力し、②「ミーティングに参加をクリック」して会議へ参加する
![qiita_teamviewer_16.png](https://qiita-image-store.s3.amazonaws.com/0/238650/2f5a86d5-8047-c89d-45dd-b8fff1be0750.png)

---

細かい使い方に関しては以下のURLを参考にしてみてください。
TeamViewerさんで各種手順書を作成されてますのでとても助かりました。

#### 参考URL
TeamViewerとは
https://teamviewer-howto.com/?page_id=6

TeamViewerのダウンロード・インストール
https://teamviewer-howto.com/?page_id=4

会議ミーティングを開催　※本ページはこちらを参照しました
https://teamviewer-howto.com/?page_id=274


以上です。
TeraTermのブロードキャストコマンドについて + α

# 概要

TeraTermのブロードキャストコマンドという便利な機能を知りましたので、その備忘録として記事を作成しました。
ブロードキャストコマンドの他にもいくつか知見が得られたので＋αとして追記しています。

**環境**

* Windows 10 Professional
* TeraTerm 4.100

**参考**

* [Tera Term Pro コマンドライン] (https://ttssh2.osdn.jp/manual/ja/commandline/teraterm.html)
* [TeraTerm Macro コマンドライン] (https://ttssh2.osdn.jp/manual/ja/macro/commandline.html)

# ブロードキャストコマンド

ブロードキャストコマンドを使えば、複数のターミナルで同じ操作を同時に行うことができます。
どれか1つのターミナルで、メニューバーの"Control" -> "Broadcast command"を実行し、ブロードキャストしたいターミナルを一覧から選択します。
この例では3つのターミナルを起動し、すべてにブロードキャストする様子をgifにしました。

![ttl2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/e4bfef5d-a81f-7adf-159e-6f4781926971.png)

実行したいコマンドをコマンド欄に入力すると選択したターミナルにブロードキャストされます。
コマンド欄ではカーソルが点滅しているだけですが、実際にはキーボードから"date"、"ls -laF"、"clear"と3つのコマンドを入力しています。

![sd2.gif](https://qiita-image-store.s3.amazonaws.com/0/22772/8bb8d783-cafd-ca0e-7315-b49669983a49.gif)

# TeraTerm Macroで自動ログイン

TeraTerm Macroと秘密鍵を使ってAWSのEC2に自動ログインする方法です。
下記の方法でショートカットアイコンを作成しておけば、アイコンクリックで自動的にログインできます。

## ショートカットアイコンの作成

ttpmacro.exeのショートカットアイコンを作成し、そのアイコンのリンク先を以下のように設定します。

```text
path\to\ttpmacro.exe /V path\to\aws.ttl {ec2のpublic ip address}
                        ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
                        param1          param2
```

* /V はオプションで、起動時にMACROを隠します。
* 以降はttpmacro.exeに渡されるパラメータになります。
    * ”aws.ttl”はマクロファイルで、マクロファイルの中ではparam1としてファイル名を参照できます。
    * ログインしたいEC2のpublic ip addressを指定します。これはparam2として参照できます。

## マクロファイル(ttl)の作成

先に拡張子ttlをttpmacro.exeに関連づけておく必要があります。

![ttl0.png](https://qiita-image-store.s3.amazonaws.com/0/22772/705e311f-256f-d3d5-7438-25ab8f123d41.png)

```text:aws.ttl
HOSTADDR = param2
USERNAME = 'ec2-user'
TIMEOUT = 30
KEY_FILE = 'path\to\aws-key.pem'
INI_FILE = 'path\to\teraterm.ini'
sprintf2 LOG_FILE 'path\to\%s.log' param2

sprintf2 COMMAND '%s /ssh /2 /auth=publickey /user=%s /keyfile=%s /F=%s /TIMEOUT=%d /L=%s' HOSTADDR USERNAME KEY_FILE INI_FILE TIMEOUT LOG_FILE

connect COMMAND

end
```

* param2には、ショートカットアイコンの部分で触れたようにEC2インスタンスのpublic ip addressが格納されています。
* KEY_FILEには、EC2インスタンスに紐づけたキーペアの秘密鍵ファイルを指定します。
* INI_FILEには、TeraTermの設定ファイルを指定します。（オプション）
* 操作をログファイルに記録したい場合はLOG_FILEにログファイルの保存先とファイル名を指定します。（オプション）
    * この例ではEC2インスタンスのpublic ip addressをファイル名に指定しています。

# ローカルPCからscpでファイル転送

転送したいファイルが1つだけの場合、そのファイルをターミナルへドラッグ&ドロップするだけでscpで転送することができます。
AWS LambdaでCognitoユーザ一覧を取得

意外と情報がなくて手こずったので備忘録。

# とりあえず全ユーザを取得したい場合
フィルタや属性の指定は不要なので、以下のようなロジックを書けばOK。（Serverless Frameworkで開発することを前提としてます。）

ちなみに引数としてUserPoolIdをもらう前提で書いてます。

```py
import json
from datetime import datetime
import os
import boto3

cognito_client = boto3.client('cognito-idp')

def list_users(event, context):
    
    if 'UserPoolId' not in event:
        raise KeyError("UserPoolId does not exist.")
    
    response = cognito_client.list_users(
        UserPoolId = event['UserPoolId']
    )

    return json.dumps(response, default=support_datetime_default)

def support_datetime_default(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(repr(obj) + " is not JSON serializable")
```

support_datetime_default関数を利用することで、response内に存在する「datetime.datetime・・・」という厄介でそのままJSON化できない値をJSON化可能な文字列に変換してくれます。

serverless.ymlはこんな感じ。引数でアクセスに必要なキーを取得し、かつIAM Roleを割り当てるので、これなら機密情報は何も載りません。

```yml
service: lambda-cognito-user-manager

provider:
  name: aws
  runtime: python3.6
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "cognito-idp:ListUsers"
      Resource: "arn:aws:cognito-idp:*"

functions:
  cognito-manager:
    handler: handler.list_users
    memorySize: 128
    timeout: 
```

# 実行してみる
引数には以下を渡します。

```json
{
  "UserPoolId": "us-east-1_XXXXXXXXXXX"
}
```

無事、値が取れました。

```json
{
  "Users": [
    {
      "Username": "admin",
      "Attributes": [
        {
          "Name": "sub",
          "Value": "00000000-0000-0000-XXXX-XXXXXXXXXXXX"
        },
        {
          "Name": "email_verified",
          "Value": "false"
        },
        {
          "Name": "email",
          "Value": "xxxxxx@xxx.com"
        }
      ],
      "UserCreateDate": "2018-09-01T07:07:28.497000+00:00",
      "UserLastModifiedDate": "2018-09-01T07:09:20.934000+00:00",
      "Enabled": true,
      "UserStatus": "CONFIRMED"
    }
  ],
  "ResponseMetadata": {
    "RequestId": "XXXXXXXX-xxxx-xxxx-0000-XXXXXXXXXX",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "date": "Sun, 02 Sep 2018 08:37:00 GMT",
      "content-type": "application/x-amz-json-1.1",
      "content-length": "312",
      "connection": "keep-alive",
      "x-amzn-requestid": "XXXXXXXX-xxxx-xxxx-0000-XXXXXXXXXX"
    },
    "RetryAttempts": 0
  }
}
```

# その他注意点など
Limitに60までしか指定できないとか、それ以上を取得する場合はどうするかとか、、、その辺はこちらの記事が参考になりそう。

[[Boto3]ListUsersAPIでCognitoのユーザーを検索する](https://qiita.com/motchi0214/items/6d525688b1595336107f)
JavaScriptに集合演算がない…だと…？！

# はじめに
JavaScriptやTypeScriptで集合演算をしようと思って調べてみると、ES6以降`Set`は導入されているものの、これらの演算はbuilt-inで実装されていないようでした。
これっていうイディオムないんかと調べてみても、for文でどうのこうのとか、lodashを使いましょうとか、とてもじゃないですが納得できない…。
自分の中で、まぁこれなら許せるかという書き方について備忘しておきます。

## Union(和集合)
```javascript
const x = new Set([1, 2, 3]);
const y = new Set([2, 3, 4]);
const union = new Set([...x, ...y]); //1, 2, 3, 4
```
配列としてひっつけて、`Set`にいれなおしてるだけです。

## Intersection(積集合)
```javascript
const x = new Set([1, 2, 3]);
const y = new Set([2, 3, 4]);
const intersection = new Set([...x].filter(e => (y.has(e)))); //2, 3
```
配列に倒してfilterして、`Set`にいれなおす。

## Difference(差集合)
```javascript
const x = new Set([1, 2, 3]);
const y = new Set([2, 3, 4]);
const difference = new Set([...x].filter(e => (!y.has(e)))); //1
```
積集合とほぼ同じです。filterの条件が積のときと逆です。

## Product(直積集合)
```javascript
const x = new Set([1, 2, 3]);
const y = new Set([2, 3, 4]);
const product = new Set(
    [...x]
        .map(e0 => (y.map(e1 => ([e0, e1]))))
        .reduce((acc, e) => ([...acc, ...e]), []));
```
`map`で組み合わせを作って、`reduce`でフラット化しています。

## おまけ
上記でも使っていますが、`Array`と`Set`の相互変換です。

```javascript
const a = new Set([1, 2, 3]) // array to set
const b = [...a] //set to array
```

## さいごに
タプルもないんか…。
[AWS×ServerlessFramework] AWSLambda(Node.js)をTypeScriptで書いてデプロイする

# はじめに

最近はAWSLambdaをデプロイするにあたって、ServerlessFrameworkやAWS SAMを利用することが多いと思います。
簡単なソースコードならコンソール画面からインラインで実装すればいいですが(Cloud9で書けるようになったので、かなり書きやすくなりましたね)、複数のLambdaを管理する必要がある場合は、フレームワーク等を利用することで管理コストを削減できます。個々のLambdaをZipに固めてアップロードするわけにもいきませんからね…

そんなときにJavaScriptで書いているソースコードをTypeScriptで書けたらいいのになーとか思っていると、「ServerlessFrameworkにもTypeScriptのプラグインありますよ」という情報を手に入れたので、本格導入する前に個人で試してみました。

## ServerlessFrameworkのインストール

下記コマンドでインストールします

```console
$ npm i -g serverless
```

## プロジェクトの作成

TypeScriptで書いたソースコードでデプロイするためには、もちろんですがTypeScriptをJavaScriptにコンパイルしなければなりません。
そのために `serverless-webpack` というプラグインをインストールする必要があります。
本来であれば上記のプラグインをインストールしてWebpackの設定をしてなどしなくてはいけないのですが、ServerlessFrameworkがテンプレートを用意してくれています。

```console
$ sls create -t aws-nodejs-typescript -p serverless-typescript
```

`serverless-typescript` というディレクトリにプロジェクトが用意されています。ディレクトリに移動してパッケージをインストールします。

```console
$ cd serverless-typescript
$ npm i
```

## 内容の確認

デフォルトではAPIGateway経由でレスポンスを返すようになっています。

```ts:handler.ts
import { APIGatewayEvent, Callback, Context, Handler } from 'aws-lambda';

export const hello: Handler = (event: APIGatewayEvent, context: Context, cb: Callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  cb(null, response);
};
```

```yml:serverless.yml
service:
  name: serverless-typescript

# Add the serverless-webpack plugin
plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs8.10

functions:
  hello:
    handler: index.hello
    events:
      - http:
          method: get
          path: hello
```

`aws-lambda` というパッケージの中に、Lambdaが受け取るEventの型宣言が書いてあります。
なので `event` の型宣言をLambdaのトリガーごとに書き換える必要があります。

## デプロイ

デプロイするのは普段どおりです

```console
$ sls deploy

(省略)

Service Information
service: serverless-typescript
stage: dev
region: us-east-1
stack: serverless-typescript-dev
api keys:
  None
endpoints:
  GET - https://xxxxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/hello
functions:
  hello: serverless-typescript-dev-hello

```

## 確認する

デプロイ時に確認できるAPIGatewayのエンドポイントにブラウザからアクセスすると、メッセージとAPIGatewayからLambdaに渡されている `event` の中身がJSON文字列として表示されます。

## さいごに

こうして、AWSLambdaのNode.jsをTypeScriptで書くことができるようになりました。
やっぱりTypeScriptで書くことができるのっていいですねー(適当)
これから本格的に導入していこうと思います。これでLambdaライフがより一層快適なものになりますね！

ではまた！
railsのactionmailerでメール通知機能を作る

# やりたいこと

* controllerから呼び出してactionmailerでメール送信

# 全体像

![memo-55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193389/04e6aea5-1c68-7d40-6a03-05cf584b1cf1.jpeg)

## 初期設定

- application_mailerにてmailアドレスなどの設定
- （gmail使う場合）gmailの設定

## mailerの作成

- `rails generate mailer`コマンドでmailer作成
- viewにテキスト本文作成
- メソッドを呼び出す

# mailerの作成方法

```
$ bin/rails generate mailer UserMailer
```

```ruby:app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: "from@example.com"
  layout 'mailer'
end
```
```ruby:app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
end
```

mailerはcontrollerと似ていて上記コマンドでview（メール文面）もテストも生成される。このmailerで使えるオプションは下記に

https://railsguides.jp/action_mailer_basics.html#action-mailer%E3%81%AE%E5%85%A8%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89

ちなみにbin/railsコマンドについても調べてみた。

https://teratail.com/questions/211337

>Railsはプロジェクトルートの bin ディレクトリにある rails ファイル（実行可能ファイル）を優先的に起動する仕様になっているからです。

https://qiita.com/jnchito/items/c5a0848144203dce6e26

railsコマンドだとbin/を付ける必要がなくてrakeコマンドだとある。

# configの設定

## configの記述箇所

cofig/environments/○○.rbで書くかconfig/initializers/の２パターンある。

cofig/environments/○○.rbはそのfileの環境にのみ適用したい時、config/initializers/はどの環境でも使いたいときに使用する。

```ruby:config/environments/development.rb
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  address: 'smtp.gmail.com',
  domain: 'gmail.com',
  port: 587,
  user_name: 'Gmail のメールアドレス',
  password: 'Gmail のパスワード',
  authentication: 'plain',
  enable_starttls_auto: true
}
```

## smtpモードでの設定情報

* address => SMTPサーバーのホスト名
* port => SMTPサーバーのポート番号
* domain => 使うgmailアカウントのドメイン。もし無料アカウントから転送で使っていたら無料アカウントのドメイン（gmailなど）。有料だった場合独自ドメイン。
* user_name => メール送信に使用するgmailのアカウント
* password => メール送信に使用するgmailのパスワード
* authentication => 認証方法
* enable_starttls_auto => メールの送信にTLS認証を使用するか

引用：https://qiita.com/Yama-to/items/823baf26bba3193712ea

パスワードは下記の方法でアプリパスワードを取得しないといけない

https://support.google.com/mail/answer/185833?hl=ja

# メール本文をmailerviewで作成

app/views/user_mailer/ディレクトリでmailerでセットされたインスタンス変数名.html.erbというファイルを作成するとメール本文を編集できる。.text.erbで作るとテキストメールになる。

# gmailの設定

gmailから送信する場合以下の作業をしないといけない

* ２段階認証を有効にする
* アプリパスワードの設定
  * 端末は適当で良し
* 転送の設定をしている場合、設定のアカウントをちゃんと変更しておく

# controllerの記述

```ruby:app/controllers/post_controller.rb
NotificationMailer.send_oubo_notification("なんか引数あったらここに").deliver_later
```

# 細かい注意点

* actionmailerはactivejpbで非同期で行なわれるのでユーザーは完了を待たなくていい。
* mailのpreviewがみれる（ https://railsguides.jp/action_mailer_basics.html#%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%AE%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC ）
tf.keras.layers配下pool関連サブクラス

## pooling関連sub-class一覧

1. AveragePooling1D
* AveragePooling2D
* AveragePooling3D
* AvgPool1D
* AvgPool2D
* AvgPool3D
* GlobalAveragePooling1D
* GlobalAveragePooling2D
* GlobalAveragePooling3D
* GlobalAvgPool1D
* GlobalAvgPool2D
* GlobalAvgPool3D
* GlobalMaxPool1D
* GlobalMaxPool2D
* GlobalMaxPool3D
* GlobalMaxPooling1D
* GlobalMaxPooling2D
* GlobalMaxPooling3D
* MaxPool1D
* MaxPool2D
* MaxPool3D
* MaxPooling1D
* MaxPooling2D
* MaxPooling3D

よく見ると、名前にパタンがありそう。整理してみた。
## class名の構造
![tf.keras.layers2.png](https://qiita-image-store.s3.amazonaws.com/0/32912/92ca2ed8-611b-072e-4c1f-10f2a8695730.png)


* 名前は４層に分けられる
* 最後１D、２D、３Dは入力データの構造を指す
* ３層のPoolとPoolingは同じ意味、ただの別名
* ２層のAveとAverageも同じ意味
* 存在しない組み合わせ（AvgPoolingとAveragePool）ある

## おまけ
そもそもpoolってなんだっけ？[[2]](https://qiita.com/FukuharaYohei/items/73cce8f5707a353e3c3a)
![tf.keras.layers (1).png](https://qiita-image-store.s3.amazonaws.com/0/32912/fd8c4352-6b2d-52e8-48da-70c7cb9a0dc7.png)

じゃ、Globalとは？[[3]](https://qiita.com/mine820/items/1e49bca6d215ce88594a)
![tf.keras.layers-3.png](https://qiita-image-store.s3.amazonaws.com/0/32912/2b44f44e-6f7a-9944-d34c-06cf7e7a13c2.png)

念のため、Avgは平均、Maxは最大を求めるのこと

#### 参考
1. https://www.tensorflow.org/api_docs/python/tf/keras/layers
2. https://qiita.com/FukuharaYohei/items/73cce8f5707a353e3c3a
3. https://qiita.com/mine820/items/1e49bca6d215ce88594a
仮引数と実引数


# 概要
引数には
仮引数と実引数という言葉があります。

仮引数
-
関数を定義しているところに書いてある
呼び出される側

実引数
-
関数を呼び出しているところに書いてある
呼び出す側


という違いがあります。


```java
public static int add(int x,int y){//1　仮引数
   return x + y;
}

public static void main(String[]args){
  int x = 10;
  int y = 20;
  add(x,y);//2　実引数
}
```

1. `仮引数`でこういうことをするよ、というのを定義しておきます。
2. `実引数`で実際に呼び出して使用します。

https://qiita.com/hp_kj/items/9ffe03bf2919c99b964a
コメント欄にて、引数について教えていただいたきました。
調べてまとめました。
Docker導入

# 前提
- Docker初心者が導入から使用までをまとめます
- 環境
    - Windows10 64bit 
 

# Doker for Windows のインストール
- [こちら](https://docs.docker.com/docker-for-windows/)からダウントード
- 完了すると鯨の可愛いショートカットが作成される

# コンテナの作成
- とりあえず以下のコマンドでバージョン等を確認

```
$ docker info
```

- ここではubuntuの環境作成を目指す
    - 以下のコマンドでイメージを取得

```
$ docker run -it ubuntu bash
```
- run
    - ローカルでイメージを探してコンテナを起動。イメージがない場合はインターネットからイメージが取得される。
- -i
    - Dockerコンテナ内の標準出力とホスト側の出力をつなげる
- -t
    - ホスト側の入力とコンテナの標準出力をつなげる
- ubuntu
    - イメージ名
- bash
    - 起動時に指定するコマンド
    - この場合は省略してもbashが指定される
        - bashを指定するのは指定するのは、ログインシェルとしてbashを起動するため(自信無し…)
- 起動するとubuntuの環境が開く
- 終了する場合はexit または ctrl D

# コンテナ一覧を表示
全てのコンテナを表示

```
$ docker ps -a
```

```
CONTAINER ID  IMAGE   COMMAND   CREATED        STATUS                    PORTS       NAMES
0b037c67233a  ubuntu  "bash"    4 minutes ago  Exited (0) 3 minutes ago        　　　kind_chatterjee
```
- オプションを指定しないと実行中のコンテナしか表示されない
- 今回は起動時にnameを指定しなかったためランダムにNAMESはランダムに生成されている

# イメージ一覧を取得

```
$ docker image
```

```
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              16508e5c265d        10 days ago         84.1MB
```

# コンテナを起動

```
docker start  [コンテナID or コンテナ名]
```

# コンテナを停止
```
docker stop [コンテナID　or コンテナ名]
```

# コンテナを削除
```
docker rm [コンテナID　or コンテナ名]
```

#「Kitematic」によるコンテナの管理
- Kitematic(カイトマチック)はGUIでローカルの管理を行えるツール
- Dockerのアイコンを右クリック→Kitematicを指定するとダウンロードのサイトが表示されるのでそこからダウンロード
- C:\Program Files\Docker\Kitematicにダウンロードしたzipファイルを解凍
- 今後はDockerのアイコンを右クリック→Kitematicから起動できる
- 左側にローカルのコンテナが表示される
<img width="1128" alt="Kitematic.png" src="https://qiita-image-store.s3.amazonaws.com/0/269592/87a91a3f-e24e-c607-f990-ef6f21bfdb55.png">

- 選択するとログが表示される。起動・停止もこちらで操作可。
Atomでsassを使いたいと思ったのでその方法をまとめました。

# Atomにsassを導入してみた。

以前はcould9でsassを使っていたけど、いつも使ってるエディタのatomに導入しようと思った為。

## 導入方法

導入には「nodo.js」と「node-sass」のインストールが必要です。
Atomには、パッケージで「sass-autocompile」があるのでそのインストールまでまとめていきます。

## nodo.jsのインストール
公式サイト：https://nodejs.org/ja/

 公式サイトからインストールします。

ターミナルで`node-v`を打ちインストールされてるか確認。
`npm -v`も同時にインストールされてるのでこちらも一応こちらも確認。

```
node -v
 v8.11.4
npm -v
 5.6.0
```
よしよし、インストール出来てますね。

## node-sassをインストールする

次にnode-sassをインストールするためターミナルに
 `npm install -g node-sass`を打ち込む。

```
npm install -g node-sass
 ```

しかしエラーが出てインストールされてません・・・。
![スクリーンショット 2018-09-02 14.48.16.png](https://qiita-image-store.s3.amazonaws.com/0/250487/a3721eec-5583-2ad7-b260-3ac016e58edb.png)


エラーはアクセス権限がありません的な事が書かれてる。

下記のサイトを元にエラーを解決していく。
参照：http://codetofly.com/others/nodejs-node-sass-install/
参照：https://qiita.com/okoysm/items/ced3c3de30af1035242d

 - まずは`npm config get prefix`で確認して見る。
 
```
npm config get prefix
 ```


すると結果がこちら

```
/user/local
 ```

npmフォルダのオーナーを自分のユーザー名に変更して、内包されているフォルダなどのパーミッションもこれで変えるため下記のコマンドを打つ。

```
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
```

もう一度インストールを試みる。

```
npm install -g node-sass
 ```


無事、インストール出来ました！！！

確認で`node-sass -v`でインストールが出来たか見てみる。

```
node-sass -v
```
![スクリーンショット 2018-09-02 16.26.46.png](https://qiita-image-store.s3.amazonaws.com/0/250487/5db16e1b-8a7b-e727-dac9-4f43b9ff879a.png)

うん！無事にインストール出来ました！

補足：Finderから/user/localに移動したかったが、見つからない〜と思ってましたが、
Finderのメニューから「移動」→「フォルダに移動」を選択。
/user/lodalを入力すると移動できました(^^)
参照：http://d.hatena.ne.jp/testnoda/20120515/1337069061

## atomでパッケージをインストール

Atomを開いて、環境設定のインストールから`sass-autocompile`をインストールする。
![スクリーンショット 2018-09-02 16.30.56.png](https://qiita-image-store.s3.amazonaws.com/0/250487/4e5c04ae-1e6b-7e51-e7fc-996da5e4e1d8.png)



同じく環境設定のパッケージに追加されて入れば成功です！！
![スクリーンショット 2018-09-02 16.32.16.png](https://qiita-image-store.s3.amazonaws.com/0/250487/651c5134-293b-89dc-70c9-db3a463bd309.png)

実際は、エラーのところですごく時間を使ってしまいましたが、同じエラーの人がいたので同じように実行していけばすんなりいけました(^O^)


導入を考えてる人は参考にして下さい。お疲れ様でした！！！
【PHP】 GETを使った受け渡しの備忘録03

https://goo.gl/MoabjU
の続きです。

## select要素について

select要素のname属性と、その中にあるoption要素のvalue属性の組み合わせがあパラメータになる。
`?name=popo&nenrei=14&jusho=tokyo`

```index.php
<p>住所:
  <select name="jusho">
    <option value="">選択してください</option>
    <option value="tokyo">東京</option>
    <option value="osaka">大阪</option>
    <option value="fukuoka">福岡</option>
    <option value="sonota">その他</option>
  </select>
</p>
```

## 三項演算子について
[条件]?値:値2
[条件] なら 値 そうでなければ 値2

```index.php
<?php
	if (isset($_GET['name'])) {
		$name = htmlspecialchars($_GET['name']);
	} else {
		$name = '<script>alert("あああ")</script>';
	}
	if (isset($_GET['nenrei'])) {
		$nenrei = htmlspecialchars($_GET['nenrei']);
	} else {
		$nenrei = '年齢がないよ';
	}
	if (isset($_GET['jusho'])) {
		$jusho = htmlspecialchars($_GET['jusho']);
	} else {
		$jusho = '住所がないよ';
	}
?>
```
長々しいif文を下記のように修正

```index.php
<?php
	$name = isset($_GET['name'])?htmlspecialchars($_GET['name']):'名前がないよ';
	$nenrei = isset($_GET['nenrei'])?htmlspecialchars($_GET['nenrei']):'年齢がないよ';
	$jusho = isset($_GET['jusho'])?htmlspecialchars($_GET['jusho']):'住所がないよ';
	$seibetu = isset($_GET['seibetu'])?htmlspecialchars($_GET['seibetu']):'性別が入力されてないよ';
```

## raidoボタン
type="text"とかだとvalueがからでもurlに表示されるが、type="radio"だと属性が表示されずに、エラーとなってしまう。

<img width="919" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/179505/65da46b7-f1fa-6587-34d6-558b59862462.png">

下記のように修正

```index.php
<?php
	$name = isset($_GET['name'])?htmlspecialchars($_GET['name']):'名前がないよ';
	$nenrei = isset($_GET['nenrei'])?htmlspecialchars($_GET['nenrei']):'年齢がないよ';
	$jusho = isset($_GET['jusho'])?htmlspecialchars($_GET['jusho']):'住所がないよ';
	$seibetu = isset($_GET['seibetu'])?htmlspecialchars($_GET['seibetu']):'性別が入力されてないよ';
	if (!isset($_GET['seibetu'])) {	
		$seibetu = '性別がないよ';
	} elseif ($_GET['seibetu'] == 'm') {
		$seibetu = '男';
	} else {
		$seibetu = '女';
	}
?>
```

<img width="622" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/179505/1684d595-ff79-7c1c-9c84-4454f9e5bbd1.png">

### 参考文献
WEBデザイナー・HTMLコーダーのための実践PHP入門 (1) メールフォームを自作する
https://www.udemy.com/phpbasics01/
ECにおけるデータベース構築と業務活用に至るまでの手順を考える

ECモールの運営企業で働いてるが、今業務の中で『データ活用』が大きな問題となっている。既存のシステム構成では業務の様々な部分に大きなボトルネックを生んでいる。
理想的なデータベース構成を考える上で、以下の本を読みながら自分なりにイチからECモールにおけるデータベースの最適解を考えてみたいと思う。

※参照「データマネジメント業務改善の正攻法」

#データマネジメントについて
###定義
>　「データを経営資源、あるいは組織の資産として設計・登録・更新・活用することと一連の行為をより安全にかつ効果的に実施するための一連の活動」

###目的
>　「データ活用を通じて**競争優位を実現すること**」

データを感覚的に捉えて使っているが、きちんと何の目的で使うべきなのかは考えておくべきだと改め感じた。　

#最初にやること
##Asis(現状)データの可視化

これは本当に大事だと直感でわかる。とにかく見えていない情報は多い。単純に必要なデータが足りていないというのもあるが、みんな勝手にデータを作ってはその場限りで、共有もしないし次への積み重ねもなく自由に保管・破棄している。

これでは正しい意思決定なぞできるはずもない。。。。社内の皆が持っているデータの集約・整理は非常に大事だ。

#実際の解決方法

実現手順を色々考えてみた。

##1. 社内データの集約
###1.1 社内データの現状　
今社内のデータは様々な方法でみんなよく言えば自由に悪く言えば全く統率されない形で管理されている。そもそも持ち方もフォーマットも自由だが、見たらこんな感じだった。
　　・Excel
　　・スプレッドシート
　　・Tableauサーバー
　　・Accessとか
　　・csv

###1.2 方法検討
これらをカバーできるのはやはり・・・Tableauしかない。**色々なタイプのデータ形式をインポートできるからだ。**Tableauでデータソースを作り定期更新されるようにして、元々のスプレッドシートやExcelの更新方法は変えないで運用する。
これしかないなと結論付ける。

###1.3 やってみた
集めてみたら思った通り滅茶苦茶笑。あと足りない情報も多い。不足情報が何なのか整理しておくことも重要だと改めて実感。データソース作成による基盤整理を進める上でこの辺の追加情報がちゃんと使えるように想定して作らないと駄目だなと思った。

##2. データソースの作成
###2.1 社内データの現状　
じゃあTableau Desktopで繋げてそのままデータソース化しようと思ったところ。。。まあ当然バラバラなので無理笑。ETL的なものがいる。

###2.2 Tableau Prepによるクリーニング
色々方法はエンジニアの人たちと相談したのだが、処理を作る上でまずお試しで状況を見たりする上でそこで登場するのがこれ。
データのクリーニングやディメンション整理及びフォーマットの合わせもソフトウェア側で容易に実施することができる。これでデータをある程度奇麗にすることができる。そしてデータソースを作ってTableauサーバーに上げて活用するという流れになる。
※実際業務はここまでしか実施できていない。。

##3. 可視化社内活用
###3.1  ダッシュボード(DB)要件定義
ここで社内で実際にどうやってデータ活用しているのかをヒアリングに入る。主にマーケティング部門・営業側(弊社はB(弊社) to B(店舗) to C(顧客)という図式)その他経営企画等の要望や用途を聞く。

###3.2  Tableau Desktopによるダッシュボード作成
皆が見れるダッシュボードを作る。そのうえで意識することは以下。

**日々自己担当業務の状況を把握し、データによる意思決定ができること**
　
大まかに言える範囲で実際に作っているものを挙げると

>・経営状況DB
　全体もしくは各フィルタリングにより担当業務の関連流通・コスト・収益・費用対効果が見れるもの

>・新規ユーザーDB
　モールにおける新規ユーザー獲得数及びパフォーマンス(次月RR(リターンレート)等)が追えること

※所感
これで思ったのがやはりTableauによるビュー化できるのが自分だけだと大変だなということ。今後これも追加してほしいとか色々な要望が現場から上がることも容易に想像できるのでチューニングも必須。
今社内ではTableauがちゃんと使えるのが自分だけなので、データスチュワードの育成とTableau社内教育も大事だなと痛切に感じる。
データガバナンスか。。。どうやって組織作りしていこうと悩む

---

一旦今回は手順だけ考えたが問題は多いため、各視点で色々データ構築を考え今後記事化していきたいと思う。
・MSMを考える
・データガバナンスの体制作り
centos7で 時刻がずれていた時の対処法

1. nptコマンドをインストールする
  
  yum intall npt


2.同期にする

sudo ntpdate ntp.nict.jp

3.サーバーにnptが入っているかを確認
　nptd --version


参照
http://wp-e.org/2014/03/31/1586/


https://qiita.com/yoshikyoto/items/cc7320863fb96ba53ffa
Windows 10で一発でCTRLとCAP LOCKを切り替える


#概要

以下のファイルをダウンロードして、実行する。
システムに、、、と聞かれるけど、YESで

https://gist.github.com/tksmiura/29c25e48280a7e91bde0645e1f699858


#内容

レジストリを追加して、普段使わないと思われる右CTRLキーとCAP LOCKを入れ替えます。
もっとも、今使っているSurface Goのタイプカバー(JIS)に右CTRLはないですが、、、

PC変えるたびに設定に苦労するので、gistに上げておきます。

```ctrl.reg
﻿Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1d,e0,3a,00,3a,00,1d,e0,00,00,00,00
```