OmniAICreator/Qiita-1.07M huggingface dataset:
RaspbeeryPiからのセンサーデータの可視化(SORACOM Lagoon編)

#**目的**
RaspberryPiで取得したセンサーデータをSORACOM Harvestに送信し、soracom Lagoonで照会する

#**参照**
こちらをみながら進めました
SORACOM公式サイト：[Getting started with SORACOM Lagoon](https://dev.soracom.io/jp/start/lagoon-dashboards/)

[早速、SORACOM Lagoonで遊んでみた](https://qiita.com/koshin/items/35e71387ef5091d99dae)


#**前提**
温湿度データ取得、SORACOM Harvestへのデータ転送については以下参照。
[RaspberryPiでDHT11センサーから温湿度データを取得](https://qiita.com/mahko2/items/6f3755c40d130ffa5136)

[RaspbeeryPiからのセンサーデータの可視化(SORACOM Harvest編)](https://qiita.com/mahko2/items/f3c0875c2f5f17ab78ff)


#**SORACOM Lagoonの設定**

メニューから「ダッシュボード作成・共有」を選択
![キャプチャ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/a09130c4-414e-8a70-7611-8c2f91b77db1.png)

開始ボタン押下
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/fa54ec75-1e7e-b5a5-e115-be093a4dcd17.png)

パスワードを設定し、アクセス
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/6b7ac57b-b0ce-2d8d-4667-c00a2e61ca07.png)

![キャプチャ4.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/e634f562-8eb1-b26a-6e94-881f4b84e7b8.png)

![キャプチャ5.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/1df881ef-5d25-a090-9c6c-cac03b473952.png)

![キャプチャ6.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/a7958008-e696-a3ee-db1b-be95cb29ff6f.png)

この画面でパネル選択やら詳細設定を(操作方法についてはSORACOM公式を参照)
![キャプチャ7.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/8dbf392c-0e4f-347d-ab1c-c4933e90159b.png)

#**ダッシュボード照会**
![キャプチャ8.PNG](https://qiita-image-store.s3.amazonaws.com/0/22526/1e42690d-d9e8-4fb1-5584-fcb99272010c.png)
Lambda (Python) から特定のログストリームにログを書こうとして苦戦した2つのポイント

Lambda (Python) から指定のログストリームにログを書こうとして苦戦したのでメモ。

今日使い始めたばかりなので間違ってる点があるかもしれません。もし間違っていたら教えてくださいm(_ _)m

# 苦戦ポイント1 -put_log_events()の使い方-

結論から言って次のようにする必要があります。

```py

      logs_client = boto3.client('logs')

      res = logs_client.describe_log_streams(
          logGroupName='(ロググループ名)',
          logStreamNamePrefix='(ログストリーム名)',
      )
      seq_token = res['logStreams'][0]['uploadSequenceToken']

      res = logs_client.put_log_events(
          logGroupName='(ロググループ名)',
          logStreamName='(ログストリーム名)',
          logEvents=[
              {
                  'timestamp': int(time.time()) * 1000,
                  'message': '%s backed up successfully' % (message)
              },
          ],
          sequenceToken=seq_token
      )
```

注意する点が2点ほどあります。

### timestampの指定
まず1点目、timestampはUNIX時間に1000を掛けたものを**整数**で指定しましょう。つまり単位が**ミリ秒**です。

### sequenceToken
2点目、ログを書き出すput_log_events()にはsequenceTokenというパラメータが必要になります。
ログストリームへの初回の書き込みなら（多分）いらないのですが、2回目以降は必要になります。

上記コードではsequenceTokenをdescribe_log_streams()から取得していますが、put_log_events()のレスポンスの中にもありますのでそれを使ってもいいです。

# 苦戦ポイント2 -IAM ポリシー-

結論から言って次のようにする必要があります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
            ],
            "Resource": [
                "arn:aws:logs:*:*:/aws/lambda/(Lambda関数名☆ワイルドカード可☆)",
                "arn:aws:logs:*:*:log-group:(ロググループ名):log-stream:(ログストリーム名)"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:DescribeLogStreams"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ],
            "Effect": "Allow"
        }
    ]
}
```

ポリシーについて先に説明させていただきますと、最初のCreateLogGroup, CreateLogStream, PutLogEventsはCloudWatch Logsにログを書き出す（ログストリームの作成も）時に必要です。

最初のResource内の1つ目　（```"arn:aws:logs:*:*:/aws/lambda/(Lambda関数名☆ワイルドカード可☆)"```）は、Lambdaからprint()やloggerを使った時、自動でCloudWatch Logsに送られるのでその時用です。

その上での注意する点はResourceの指定です。

### Resource指定

最初のResource内の2つ目（```arn:aws:logs:*:*:log-group:(ロググループ名):log-stream:(ログストリーム名)```）は今回の問題である特定のログストリームに書くときのArn指定です。
自分は最初間違えて```arn:aws:logs:*:*:(ロググループ名)/(ログストリーム名)```とかやってました。

前述のdescribe_log_streamsのためにlogs:DescribeLogStreamsをarn:aws:logs:*:*:*に対して設定するのも忘れないでください。
Postfixのセットアップ方法

# インストール
```
# su -

# uname -a;date;id

# cd /var/tmp
# rpm -aq > /var/tmp/postgix_before_yyyymmdd.log
# rpm -aq | grep postfix
# rpm -Uvh postfix-2.10.3-5.mga5.x86_64.rpm

# rpm -aq > /var/tmp/postfix_after_yyyymmdd.log
```

# 初期設定
```
# cd /etc/postfix
# cp -p main.cf main.cf_yyyymmdd
# vi main.cf
# cat main.cf
# diff main.cf main.cf_yyyymmdd

# cp -p master.cf master.cf_yyyymmdd
# vi master.cf
# cat master.cf
# diff master.cf master.cf_yyyymmdd

# cp -p transport transport_yyyymmmdd
# vi transport
# cat transport
# diff transport transport_yyyymmmdd

# systemctl restart postfix
# systemctl status postfix
```
Swift - プロトコルが型になるとき

@koher さんの記事、[なぜSwiftのプロトコルはジェネリクスをサポートしないのか]における議論は改めて記事にするだけの価値があるのでそうすることにします。

[なぜSwiftのプロトコルはジェネリクスをサポートしないのか]: https://qiita.com/koher/items/b21879a31210f7408502#comment-90a37cf39b4509a2c819

## 君の型は?

まずは以下のコードをご覧ください。

```swift
import Foundation

protocol Animal {
    var binomen:String { get }
    init()
}
struct Cat: Animal {
    let binomen = "Felis silvestris catus"
    let theYoung = "kitten"
}
struct Dog: Animal {
    let binomen = "Canis lupus familiaris"
    let theYoung = "puppy"
}

var pet:Animal = (arc4random() & 1 == 1) ? Cat() : Dog()
```

* Q0: このコードは動きますか?
  * A0: 動く
  * A1: (type mismatchで動かない) 

正解はA0、きちんと動きます。PlaygroundsなりREPLで確認してみてください。で、本題です。

* Q1: `pet`の型は?
  * A0: `Cat`か`Dog`か動的に決まる
  * A1: 何らかの型に静的に決まる

正解はA1。そして型の名は`Cat`でも`Dog`でもない`Animal`です。

![](https://camo.qiitausercontent.com/3a19e7a0f046655765c07dd43ea4489ca424e3aa/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f31393232372f63363962636138302d396466302d333264622d313938342d3765346133356262303166302e706e67)

Playgroundの型インスペクターを見てももろそう書いてありますし、`.binomen`にアクセスできても`.theYoung`にはアクセスできません。どちらにも`.theYoung`は存在していますが`Animal`には知る由もないのです。

```swift
let 🐱 = Cat()
🐱.theYoung // "kitten"
let 🐶 = Dog()
🐶.theYoung // "puppy"
```

ならば

```swift
pet = Animal()
```

も動きそうなものですが、`protocol type 'Animal' cannot be instantiated`と怒られてしまいます。あくまで具現化(instantiation)は`struct`か`enum`か`class`で、`protocol`は本来の「規約」として使えということですね。

そのことがわかれば、Swiftの総称型(generics)の設計もわかります。

## 全ての定数(`let`)と変数(`var`)の型はコンパイル時に静的に決まる

ほんと、これだけです。なぜ

```swift
func ditto<T>(x:T)->T { return x }
```

がOKなのに

```swift

let ditto<T>:(T)->T = { $0 }
```

はNGなのか。まさにこれが理由です。`T`に何が入るのかは、コンパイル時に決まってなければならないから。実行時に決まる言語であれば

```javascript
// ECMAScript
const ditto = (x)=>x
```

と書けるのとそこが大いに異なります。`Type<T>`がOKで`Protocol<T>`がNGなのもそれ。その悩みを解決したのが`associatedtype`で、Protocolでは

```swift
protocol Sequence {
  associatedtype Element
}
```

として`Element`という型が内包されていることを強制した上で、

```swift
struct Array<Element> : Sequence {
  //...
}
```

とすることで確実に型が静的に決まるようにしているわけです。さらに今では

```swift
// Element が Numeric の場合のみ.sum()できるように
extension Array where Element:Numeric {
    func sum()->Element {
        return self.reduce(0, +)
    }
}
```

というように拡張の範囲を限定できたりもします。

## まとめ

というわけでまとめます。

* Swiftの定数と変数の型は100%静的。例外はストロングゼロ
* プロトコル(`protocol`)も実は型を持っているが、その型は間接的にそれに準拠(conform)した型(`struct`, `enum` or `class`)を具現化(instantiate)する時にだけかいま見える
* 「いろいろ入る型」は`enum`を使えば実現可能(例:[swift-sion])
* 「なんでも入る型」として`Any`も用意されているが、それをいかに使わせないかが工夫のしどころ

[swift-sion]: https://github.com/dankogai/swift-sion

このあたりの感覚は、実際に自分で型を作るとよくわかります。楽しいぞい。

Dan the Safe, Fast and Expressive

## 追記:`Any`の正体

コメントの議論にもありますが、これはやはり特記しておくべきですね。実は「何でも入る」型である`Any`もプロトコル型です。実際明示的に`Any`をプロトコルとして使うことも可能ですし…

```swift
struct Whatever:Any {} // no error
```

REPLで`Any.self`を覗いてみて見るとはっきりとそれがわかります。

```swift
1> Any.self
$R0: Any.Protocol = Any
```

つまり

```swift
protocol Any {}
```

で、全ての型宣言の裏では…

```swift
struct S {/*…*/}
enum E {/*…*/}
class C {/*…*/}
```

暗黙的に`Any`プロトコルに準拠している…

```swift
struct S:Any {/*…*/}
enum E:Any {/*…*/}
class C:Any {/*…*/}
```

というわけなのです。
Linuxでデバイス情報を取得する

環境変えて動かなかったときとかこういうのあると楽ですよね。

# 筆者環境
- Ubuntu18.04

上記環境で動作するのを確認しました、デフォルトで入っていないコマンドがあったら各自でインストールしてください。

# ディストリビューション
```shell-session
$ cat /etc/lsb-release
```
# マザーボード
```shell-session
$ dmidecode -t baseboard | grep -e "Manufacturer" -e "Product Name"
```

# CPU
```shell-session
$ cat /proc/cpuinfo | grep -e "processor" -e "model name"
```

# メモリ
```shell-session
$ cat /proc/meminfo | grep "Mem"
```

# オーディオ
```shell-session
$ lspci | grep "Audio device"
```

# イーサネット
```shell-session
$ lspci | grep "Ethernet controller"
```

# GPU
```shell-session
$ lspci | grep "VGA"
```
wemos注意点

#概要
wemos d1　r1 の注意点。

#ディジタル出力端子
使える端子は，IO0, IO2, IO4, IO5, IO12, IO13, IO14, IO15, IO16 の9本です。
IO2 には LED が接続されています。
HIGH で 3.3V 出力，LOW で 0V 出力です。
ドライブ可能な電流（流出・流入）は１端子あたり 12mA です。

#ディジタル入力端子
ディジタル出力と同様に，IO0, IO2, IO4, IO5, IO12, IO13, IO14, IO15, IO16 の9本が使えます。
IO2 には LED が接続され，IO13 は 10kΩ でプルアップ，IO15 は 10kΩ でプルダウンされているため注意が必要です。
INPUT, INPUT_PULLUP が使えますが，IO16 のみ INPUT, INPUT_PULLDOWN_16 のみが使えます。
入力電圧が約 2.5V 以上（3.3V 以下）で HIGH となり，約 0.8V 以下で LOW となります。

#アナログ出力端子
いわゆる PWM 出力です。
上述のディジタル入出力端子（9本）のいずれも使用（同時使用）できます。
analogWrite() に与えるデューティー比は，0〜1023 の整数で与えます。
PWM 周波数は約 1kHz（996.8Hz 前後）です。
デューティー比 0 を指定すると PWM モードが解除されます。
analogWriteFreq(4000) とすれば 4kHz になりますが，周波数を高くしすぎると，デューティー比の 0 近くと 1023 近くで挙動がおかしくなるようです。

#サーボ制御信号の出力端子
50Hz の PWM 信号です。
上述のディジタル入出力端子（9本）のいずれも使用（同時使用）できます。
パルス幅は 1500µs が中点で，544〜2400µs が可変範囲となっています。

#アナログ入力端子
TOUT がアナログ入力端子で，1チャネルのみになります。
analogRead(0) または analogRead(A0) で，10bit の非負整数として電圧を取得できます。
220K　+　100K　で分圧し、100K側でADCに接続されてます。
測定範囲は 0〜1V です。
入力電圧が飽和（1V 以上）の場合は 1024 が返されるようです。
3.3V * 100k　/　(100k　+　220k) = 1.031V

#ウォッチドッグタイマ（WDT）
プログラムが暴走するなどした場合に，自動的にリセットがかかる安全装置で，標準的な Arduino にはない機能です。
プロセッサ内部にタイマーがあり，
(1) loop() の終了・再呼出時，
(2) delay() の実行時，
(3) yield() の実行時にタイマが 0 に戻されますが，タイマが 3s を超えてしまうと，ESP8266 が強制的にリセットされます。
したがって，loop() の内部に while や for などで長時間実行される部分や入力待ちがある場合は注意が必要です。
適宜，delay() や yield() を入れてください。
delay(0) でもオーケーです。
一方，delayMicroseconds() ではリセットされません。

#WiFi 関連の機能
WiFi や TCP/IP 関連の機能（HTTP リクエストの処理など）は，WDT リセットと同様に，
(1) loop() の終了・再呼出時，
(2) delay() の実行時，
(3) yield() の実行時に，併せて実行されます。
したがって，WiFi や TCP/IP の応答性を確保するには，プログラム構造を工夫したり，適宜 delay() や yield() を呼び出すようにしてください。

#電源電圧 3.3V
プログラミングではなくハードウェア的な注意点ですが，ESP8266の電源電圧および IO の入出力電圧は 3.3V です。
5V 系のデバイスと接続する場合は注意が必要です。
降圧させるなら抵抗器２本による分圧回路，昇圧させるならトランジスタスイッチまたはレベル変換 IC を使うとよいです。
ディジタル出力端子あたり最大 12mA までドライブ（流出・流入）できます。
LED を接続するなら順方向電圧の低いもの（2V 程度のもの）を選び，数百 Ω（1kΩ でもよい）の抵抗器を直列に入れるとよいです。
スイッチ入力等に使うプルアップ抵抗，プルダウン抵抗は 10kΩ でよいです。

#ピン

|nano|GPIO|pinの名前|デジタル出力|デジタル入力|割り込み|アナログ出力|アナログ入力|備考|
|:--|:---|:---|:---|:---|:---|:--|:--|:--|
|D8|GPIO0	|IO0	|〇	|〇	|〇|〇	|-	|起動時に使用|
|D1|GPIO1	|TXD	|〇	|〇	|〇|〇	|-	|書き込みに使用|
|D9|GPIO2	|IO2	|〇	|〇	|〇|〇	|-	|起動時に使用|
|D0|GPIO3	|RXD	|〇	|〇	|〇|〇	|-	|書き込みに使用|
|D3|GPIO4	|IO4	|〇	|〇	|〇|〇	|-	|-|
|D4|GPIO5	|IO5	|〇	|〇	|〇|〇	|-	|-|
|D6, D12|GPIO12	|IO12	|〇	|〇	|〇|〇	|-	|-|
|D7, D11|GPIO13	|IO13	|〇	|〇	|〇|〇	|-	|-|
|D5, D13|GPIO14	|IO14	|〇	|〇	|〇|〇	|-	|-|
|D10|GPIO15	|IO15	|〇	|〇	|〇|〇	|-	|起動時に使用|
|D2|GPIO16	|IO16	|〇	|〇　	|-|〇	|-	|-|
|A0|A0	|TOUT	|-	|-	|-|-	|〇	|-|

#timer
Hardware Timer0 is used by WiFi Functions. 
We can use only Timer1. Use of timer instead of Ticker gives advantage of precision timing and You can get timer interrupt in micro seconds.

#CPU周波数
ESP8266のCPU周波数は標準で80MHzで、160MHzに変更でき、その方法は system_update_cpu_freq(160);
で160MHzに変更できます。

32ビットRISC CPU: Tensilica Xtensa LX106 running at 80 MHz*
命令RAM 64KiB、データRAM 96KiB
外部QSPIフラッシュメモリ - 512 KiB～4 MiB*（16MiBまでサポート）
IEEE 802.11 b/g/n Wi-Fi
統合された送受信スイッチ、バラン、LNA、パワーアンプ、インピーダンス整合回路
WEPもしくはWPA/WPA2による認証およびオープンネットワーク
16ピンのGPIO
SPI, I²C,
DMA付きのI²S（GPIOとピン共用）
専用のピン上のUARTとGPIO2で有効化できる送信専用UART
10ビットADC 1基


以上。
homebrewで特定のformulaをbrew upgrade対象外にする

## 動機

*『 `brew upgrade` したいけど、特定のformulaだけバージョンを固定したい！！』*

・・・あると思います。

## brew pin

`brew pin` というコマンドを使うと `brew upgrade` の対象外とすることができます。

```console
$ brew pin --help
brew pin formulae:
    Pin the specified formulae, preventing them from being upgraded when
    issuing the brew upgrade formulae command. See also unpin.
```

pinを解除するには `brew unpin` すればOKです。

```console
$ brew unpin --help
brew unpin formulae:
    Unpin formulae, allowing them to be upgraded by brew upgrade formulae.
    See also pin.
```

## 実践例

Terraformの特定のバージョンにバグがあるため v0.11.3 に固定したい、ということがあったので `brew pin` を実際に試してみました。

まず現状のバージョンを確認します。

```console
$ terraform -v
Terraform v0.11.3

Your version of Terraform is out of date! The latest version
is 0.11.7. You can update by downloading from www.terraform.io/downloads.html
```

upgrade対象外にするべく `brew pin` を実行します。

```console
$ brew pin terraform
```

`brew info` して pinned になったことを確認します。

ここでは `[pinned at 0.11.7]` と出ていますが、upgrade対象外となるため v0.11.3 からupgradeされることはありません。

```console
$ brew info terraform
terraform: stable 0.11.7 (bottled), HEAD [pinned at 0.11.7]
Tool to build, change, and version infrastructure
https://www.terraform.io/
Conflicts with:
  tfenv (because tfenv symlinks terraform binaries)
/usr/local/Cellar/terraform/0.11.3 (7 files, 79.9MB) *
  Poured from bottle on 2018-03-20 at 18:49:55
/usr/local/Cellar/terraform/0.11.4 (7 files, 80.2MB)
  Poured from bottle on 2018-03-20 at 18:56:15
/usr/local/Cellar/terraform/0.11.5 (7 files, 80.2MB)
  Poured from bottle on 2018-03-22 at 11:20:46
/usr/local/Cellar/terraform/0.11.7 (6 files, 80.2MB)
  Poured from bottle on 2018-04-17 at 18:13:05
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/terraform.rb
==> Dependencies
Build: go ✘, gox ✘
==> Options
--HEAD
	Install HEAD version
```

`brew upgrade` してterraformがupgradeされるか確認してみます。

```console
$ brew upgrade
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
amtk
==> Updated Formulae
packer ✔         ansiweather      charm            fakeroot         fwup             grpc             nifi             pulseaudio       util-linux
sphinx-doc ✔     bareos-client    cockroach        file-roller      gitlab-runner    mutt             npth             tepl             vala
xonsh ✔          binaryen         conjure-up       folly            gnome-latex      neomutt          overmind         tiger-vnc        webpack

==> Upgrading 37 outdated packages, with result:
vim 8.0.1600 -> 8.1.0150, ...（中略）... , packer 1.2.1 -> 1.2.5
```

upgrade対象から確かに外れました！やったぜ！
【備忘録】AWSとはなんぞや【初心者】

こんにちはtsuttieです(*'▽')
今回はAWSについて記載します。
由来とかの要点まとめていければと思います。
(ほとんど公式の引用になりそうな予感・・・)

AWS？
amazon・・・？


#1. AWSってどんなサービス

[AWS](https://aws.amazon.com/jp/s/dm/landing-page/start-your-free-trial-c/)のサイトには以下のように記載されています。
`アマゾン ウェブ サービス（AWS）は、米アマゾン・ドット・コムを支えてきた技術がベースとなるクラウドサービスです。`

あ、やっぱりamazon発祥。そりゃそうですよね・・・(笑)
調べてみたところ、amazon社内のビジネス課題を解決するために生まれ、それを公開したのが始まりとのこと。
参考：[クラウドサービスとは](http://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/service/13.html)

そんなAWSですが、めちゃくちゃたくさんのサービスを展開しています。
[S3](https://aws.amazon.com/jp/s3/)、[EC2](https://aws.amazon.com/jp/ec2/?p=tile)に始まりなんと、その数100以上・・・全部把握するのは厳しいですね。把握してる間に次のサービス展開するでしょうし・・・

下記、[公式](https://aws.amazon.com/jp/s/dm/landing-page/start-your-free-trial-c/)引用。
`AWS では現在 100 以上のサービスを展開し、企業で必要な IT リソースを網羅しています。そのサービスは、コンピュート、ストレージ、ネットワーキング、データベースのみならず、データ分析（アナリティクス）、アプリケーション サービス、展開、管理、デベロッパー、モバイル、IoT、人工知能（AI）、セキュリティ、ハイブリッド、エンタープライス・アプリケーションなど、多岐にわたっています。`

名前を見てるだけでも種類の多さがわかってしまいます。


#2. なぜAWSなのか

機能がたくさんあって便利なのは十分わかったので、次はアプリケーション(Webサイト)の運営などを[クラウド](https://aws.amazon.com/jp/cloud/)で行う人が多いのは何故なのか、その利点について調べてみました。
参考：[amazonクラウド、AWSとは？何ができるかデメリット含めわかりやすく説明](https://capsulecloud.io/about/aws)

1. 初期コストが低い
2. セキュリティ評価が高い
3. すぐに始めることが出来る
4. 拡張性がある。簡単に容量の調整を行うことが出来る
5. ハードウェアを最新に保つことが出来る
6. 負担軽減により人的リソース不足を解消できる


おぉ・・・いいとこ尽くし。
そりゃみんな使うわけですね。

逆にデメリットとしては以下のような点があげられています。

1. サービスが多すぎてどうしたらいいのか、どれを使うべきかわからなくなる
2. 使った分だけになるので、コストが変動してしまう
3. トラブル時の対応スキルが必要になる(これは[オンプレミス](https://www.idcf.jp/words/on-premises.html)サーバーも？)

まあ、仕方なくない？くらいのデメリットしか出てこないですね。
これだけ良いことづくしだと「インフラ」と言われるのも納得です。


#3. 代表的なサービス・・・？

AWSの代表的なサービスについてまとめたいと思い、調べたり、周りの利用者の方に質問をしてみたりしたところ、十人十色な回答が返ってきました。ある人は[S3](https://aws.amazon.com/jp/s3/)、ある人は[EC2](https://aws.amazon.com/jp/ec2/?p=tile)、[RDS](https://aws.amazon.com/jp/rds/?p=tile)、[Amazon CloudWatch](https://aws.amazon.com/jp/cloudwatch/?p=tile)と利用者の用途に応じて使うサービスが異なるため一概にこれが一番と決めることはできないような回答でした。(とはいっても上記は有名どころだと認識はしていますが・・・)
代表的なサービス、というかサービスについては今後まとめていければと思います。(願望)

#4. まとめ

今回はAWSとは・・・ということについて簡単にまとめてみました。
要するにすごく便利なクラウドサービスってことですね。(ざっくりしすぎ・・・)
今後、サービスについても詳しく勉強していけたらいいな。と思わせてくれるAWSでした。

何かご指摘等ありましたら、コメントいただければ幸いです。
よろしくお願いします。('◇')ゞ
【備忘録】jinja2のselectフィルターを使ってAnsibleの変数を出力する方法

selectフィルターを使ってリストから指定の文字列だけ出力する方法。
jinja2やansibleのドキュメントだと調べるのが大変に感じたので備忘録として残しておきます。

```
test01.yml

- name: practice filter
  hosts: localhost  
  gather_facts: False  

  vars:
    test_servers:      
      - server1
      - server2
      - server3
      - server4  

  tasks:    
    - name: extract only server1
      vars:
        v: "{{ test_servers|select('equalto', 'server1')|list }}"
    　debug: var=v

```

出力結果
```
ok: [localhost] => {
    "v": [
        "server1"
    ]
}
```



selectフィルターは'equalto'などの変数 ＋ listとセットで使ってあげないと、ジェネレーターを返してきてしまいます。

<h2>セットで使ってないPlaybook </h2>
```
test01.yml

- name: practice filter
  hosts: localhost  
  gather_facts: False  

  vars:
    test_servers:      
      - server1
      - server2
      - server3
      - server4  


  tasks:    
    - name: extract only server1
      vars:
        v: "{{ test_servers|select('server1') }}"
    　debug: var=v

```

出力結果
```
ok: [localhost] => {
    "v": "<generator object_select_or_reject at 0x7fc94963740>"
}
```


後日リスト全体をマッチさせたい場合の書き方について編集予定。

coming soon.
Microsoft Flow でExcel帳票を出力・・・めっちゃ苦労したからみんなに共有　その１

# 今回の投稿背景
とあるお客様の要望で、カスタムリストのレコード単位でExcel帳票ファイルを作成したいというご要望がありんす

# とりあえず作ってみた
## 結論
そのままじゃ使えねぇｗｗｗｗｗｗ

## Why?
Microsoft FlowのExcelコネクタは、既存のExcelファイルに何らかのアクションを行う前提のものであり
そもそもファイルを作るなんて芸当ができませんですしおすし。

# じゃあどうすればいいのさ！！！
## 結論
既存のExcelファイルの既存テーブルにとりあえずレコードぶち込んでそれコピーしたらよくね？
そして、コピー終わったらそのレコード消したらいいじゃまいか！

## テンプレートファイルの作成
1. いわゆる印刷したりする帳票用のワークシートと、テーブル用のワークシートを作成
2. テーブル名は半角英数字で宣言
3. カラム名も半角英数字で宣言
4. 帳票用のワークシートは、テーブルの1レコード目の内容を参照するように作成
5. これをテンプレート格納用のShared Documentに格納

## Flowの作成
1.Excelの"Add a row into a table"アクションを使用して、テンプレート用のファイルや対象レコードのパラメタを指定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/b433a87a-f24e-8ca2-9c8a-11912a9f7f77.png)

2.SharePointのファイルのコピーアクションを使用して、テンプレートファイルをコピー

![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/f48734ee-a7f5-9226-45e1-0d14425bf293.png)

3.Excelの"Delete a row"で特定のレコードを削除

![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/72e8bb6b-2311-1d87-be88-c5bbab4e617d.png)

# やってみた
だめだった。

## 何が起こった！？
コピー先のファイルのレコードに何も入ってない！！
なぜだ！
結果を確認したけど出力は問題ないと出ているのに！！

## どうする！？
次回、解決策を投稿します！
お楽しみに！！
AlibabaCloudのRAMユーザーを作ってみる

# はじめに
今回は、AlibabaCloudのRAMユーザーを作ってみます。

# コンソールから作成してみます
## RAM(Resource Access Managment)を選択

![9423eb6b.png](https://qiita-image-store.s3.amazonaws.com/0/241104/fa896f5a-28fe-669e-1bd7-d600a9cc360f.png)

## ユーザータブから新規作成

![e0e69ec9.png](https://qiita-image-store.s3.amazonaws.com/0/241104/9919dbe3-7615-c6ad-54f6-f663ab089a94.png)

![f7a633fa.png](https://qiita-image-store.s3.amazonaws.com/0/241104/3e61e5b5-cc27-af53-fad3-9cf3b40a394e.png)

## ユーザーが作成されました。

![6db45669.png](https://qiita-image-store.s3.amazonaws.com/0/241104/01afa9fc-19f4-09d4-3e46-e9d7b58e74dd.png)

## コンソールでログインをできるように有効化
作成した
**shinya-furuwata**
でAlibabaCloudコンソールにログインできるようにします。

![26e58487.png](https://qiita-image-store.s3.amazonaws.com/0/241104/f313924c-e0fe-d41f-adcb-9fc467174082.png)

![db79186f.png](https://qiita-image-store.s3.amazonaws.com/0/241104/65b18ba6-bf3e-ca0c-b2fb-40d5c2e3a3f6.png)

![e1e94ea1.png](https://qiita-image-store.s3.amazonaws.com/0/241104/df8f0d2b-b66a-8631-6c87-dc5dca1393c2.png)

## ログインのURLを確認して開く

![a27a8609.png](https://qiita-image-store.s3.amazonaws.com/0/241104/9906671a-4345-0e63-90fe-f4ab36732047.png)

RAMユーザー名/パスワードを入力

![6e78bac6.png](https://qiita-image-store.s3.amazonaws.com/0/241104/9184aa98-aaca-76a4-37ea-04c896a1da0b.png)

パスワード変更が求められるので、新規に入力
![c74d22da.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a537dcfc-424d-bb9f-d56a-2e7f4d7bb22a.png)

![c6094668.png](https://qiita-image-store.s3.amazonaws.com/0/241104/90ce2001-f8a9-651a-4d34-084a2dd796e5.png)

で、ログインできました。

## RAMを見ようとすると

![911b24d5.png](https://qiita-image-store.s3.amazonaws.com/0/241104/3694cc25-3f0a-09b0-6d12-777cdb768574.png)

「権限がありません」となります。

# ユーザーに権限を付与します。

こちらは、Alibaba Cloud アカウントでの操作となります。
雑といいますか、適当に
**AdministratorAccess**
を付与してます。

![25fe3975.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ec37a364-1659-014b-8ca6-d177cd53b4c2.png)

![c4ac7bf2.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a6ab3bb8-7ae4-ddcb-f2e9-349109882c00.png)

# 画面をリロードすると、エラーがなく閲覧できるようになります。

こちらは、shinya-furuwata RAMユーザーでの操作です。

![a92cefd8.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ce111a05-fadb-bbbf-189c-d8e5edad0513.png)

# まとめ
ユーザー作成→権限付与→ユーザー情報引き渡し
の流れになるかと思います。
今回は雑に、**AdministratorAccess**しました。
これだとshinya-furuwataユーザー情報が漏洩と
rootアカウント漏洩とあまり大差がないので、
権限周りについては別の機会に今度触れたいと思います。
UserDefaultsの使い方

# UserDefaultsの使い方
UserDefaultsを使うとiOSでアプリ設定などを手軽に永続化することができます。

## 保存
```swift
//  インスタンスの生成
let userDefaults = UserDefaults.standard

//  保存
userDeafaults.standard.set("保存する内容", forKey: "key01")
userDeafaults.standard.set(100, forKey: "key02")
```

## 読み込み
```swift
//  読み込み
let val1 = UserDeafaults.standard.object(forKey: "key01")
let val2 = UserDeafaults.standard.integer(forKey: "key02")
```

## 削除
```swift
UserDeafaults.standard.removeObject(forKey: "key01")
UserDeafaults.standard.removeObject(forKey: "key02")
```
forを無理やりforeachにする

他人が書いたコードを読んでいる途中、こんなコードがあった。
同じ処理を5回繰り返す。

```c#

foreach(var i in Enumerable.Range(1, 5)) {
    //処理
}
```
「forを使うやつはアレ」的なコメントがあった。

でも、そのアレな俺が書くと下記。

```c#

for(int i = 0; i < 5; i++) {
    //処理
}
```

なんでforを使うとアレなんでしょ？
[OF] プリンタ制御


#自己紹介
社会人3年目を迎えたエンジニアです。
そろそろ自分に「初心者」っていうレッテルが取れ始めて「初心者なんで多めに見てね」スタンスが通用しなくなってきたことを感じる日々を送っています。

ものすごい久しぶりの投稿になります。
前回投稿からすでに一年以上空いてますが、その間で色々学ばさせていただいたことが多く、ここに書けそうなことをちょいちょいっとまとめていけたらなと思います。


#本題
はい、今回は需要があるかどうかとても怪しいのですが、openframeworksでプリンタの制御をしようというものです。
実際僕がこのケースに出くわしているので多少の需要はあるでしょう、きっと。....きっと。

どのようなケースに遭遇したかといいますと
「体験者に応じて画像を生成して、その画像を全て自動で印刷させる」というものでした。
unityには有料でプリンタ制御できるアセットがあったりと別にOFでやらなくてもよかったのですが、
僕個人は一番OFが慣れ親しんでるものだったので、どうせなら自作でアドオンを作ってみようと思いました。


んで、作ってみました。

###**[ofxPrinter](https://github.com/Iwanaka/ofxPrinter "ofxPrinter")**###

実を言うと、中身見ればわかっちゃうのですがコアな部分ほぼPowershellで書いて、それをOFからsystem関数で呼んでるだけです。
Example見てもらえればある程度使い方わかりますでしょうか？不明であればコメントください。あとプルリクも大歓迎です。
駄目だしとかめっちゃしてください笑

##使い方
```ruby:ofApp.cpp

#印刷情報を持つ構造体
OFX_PRINTER p;

p.printerName = ""; #使用するプリンタの名前を入力

p.paperSize = ""; #使用する紙のサイズを入力
p.color = false; #白黒かカラーかを選択 falseの場合は白黒
p.fitToPaper = false; #ページの隅に画像を合わせるか選択
p.landscape = false; #縦印刷か横印刷か選ぶ falseの場合は縦 trueは横
p.margin = ofVec4f(50.f, 50.f, 50.f, 50.f); #ページの余白を入力 fitToPaperがtrueの場合は無視されます

#印刷
printer.printOut("画像ファイルのパス", p);

```

Exampleでは[ofxImGui](https://github.com/jvcleave/ofxImGui "ofxImGui")を用いてGuiでプリンターや紙サイズなど選べて印刷できるようにもなっているので、よければビルドして試してみてください。


#終わりに
今回初めて自身のアドオンをGithub様で公開してqiita様で広報という事をしました。
今年中にあと２つか３つくらい需要のありそうなOFのアドオンを制作して、同じような形でまたここに書いていこうと思います。

ではまた次回！読んでいただきありがとうございました。
Iron.ioを使用してバックグラウンドジョブからメールを送信

##バックグラウンドジョブからユーザーにメールを送りたいと思ったことはありませんか？

ユーザーを、あなたのシステムがメールプロバイダーにリクエストを終わるまで待たせるのは良くありません。また、ハンドシェイクして、メールが送信完了になるまで待足せるのも良くないです。

早くて簡単に「Sendgrid」,「[Iron Worker](https://www.iron.io/worker?utm_source=qiita)」、「Ruby」を使用してメールを送信しましょう。
「Iron Worker」はDockerを元にしていますので、あなたの好きなプログラミング言語を使用できます。この事は、他のバックグラウンドサービスと比べた場合の優位点になります。

* 新しいディレクトリーにアプリを作りましょう。
Gemfileに下記を追加して下さい。

```Ruby
source 'https://rubygems.org'
gem 'sendgrid-ruby'
gem 'iron_worker', '>= 3.0.0'
```

* 「send_email.rb」ファイルを作成して下さい。このファイルは、メールを送ります。

私たちはIron CLIを使用したアプローチをしますが、もしかするとあなたはIron Ruby Gemを使用したアプローチを望むかもしれません。

```Ruby
require_relative 'bundle/bundler/setup'
require 'iron_worker'
require 'sendgrid-ruby'
include SendGrid

from = Email.new(email: IronWorker.payload["from"])
to = Email.new(email: IronWorker.payload["to"])
subject = IronWorker.payload["subject"]
content = Content.new(type: 'text/plain', value: IronWorker.payload["body"])

mail = Mail.new(from, subject, to, content)
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code
puts response.body
puts response.headers
```

* 「payload.json」ファイルを作成して下さい。このファイルはメールを送る時にRubyが使用するデータになります。

```Json
{
  "from": "test@example.com",
  "to": "you@example.com",
  "subject": "It works!",
  "body": "Hello from IronWorker"
}
```

* Dockerの依存関係をインストールし、コードを圧縮して「Iron.io」へアップロードします。

注意；この記事ではIronのRubyベースのDocker　イメージを使用しますが、あなた独自のDockerイメージも使用出来ます。

```
> docker run --rm -v "$PWD":/worker -w /worker iron/ruby:dev bundle install --standalone --clean
> zip -r email_worker.zip .
> iron worker upload -e SENDGRID_API_KEY=YOUR_SENDGRID_API_KEY --name email_worker --zip email_worker.zip iron/ruby ruby send_email.rb
```

「Iron.io」へ圧縮したファイルをアップロード終えたら、いつでもあなたの好きな時にメールを送る事が出来ます。

* Iron　CLIを使用してメールを送って見ましょう。

```
> iron worker queue --payload-file payload.json --wait email_worker
```

下記のような結果がコンソールに出力されたら成功です。
<img width="1415" alt="Iron_CLI_output.png" src="https://qiita-image-store.s3.amazonaws.com/0/272363/c577ab5d-ab75-06cd-851f-67728ed9f875.png">


## まとめ
Iron.io ワーカーを使用する事で、バックグラウンドジョブを簡単に実行出来ます。
プログラミング言語に関係無く使用出来、オートスケールアップなどインフラを気にせずに使用出来ます。
そして、全てのクラウドとオンプレミス導入に対応していますので、ベンダーロックインを回避出来ます。
git revertの基本的な使い方

# revertコマンドとは

すでにpushされているcommitを打ち消す(もとに戻す)コマンドの事。
取り消したいコミットを打ち消すようなコミットを新しく作成する。

# 使い方

1回revertするたびに自動的にcommitされる。
実行したときに、コミットメッセージを編集するためのエディタが起動する。

```
$ git revert <commit ID>
```
※ ```<commit ID>``` には、commitのハッシュ値を指定する。git logを叩くと出力される値。

## commitせずにrevert

commitしない方法は、-nを指定する。
複数のcommitを戻して、1つのcommitとしてpushする場合に便利。

```
$ git revert <commit ID> -n
```


## コミットメッセージを編集しない場合

コミットメッセージを編集しなくていいときは `--no-edit` を使用する。

```
$ git revert --no-edit <commit ID>
```

その場合は、

```
This reverts commit <commit ID>.
```
というようなメッセージが設定されてcommitされる。

# 雑感

めったに使用することはないので、毎回忘れてしまうのでメモ書き。
Gitで管理しているディレクトリの大文字/小文字を変更する方法

# この文章は？
Macのファイルシステムではファイル名やディレクトリ名の大文字小文字を区別してないらしく、Gitでディレクトリ名を

```bash
git mv  Objective-C/ objective-c/
```
で
Objective-C ->  objective-c
に変えようとした場合


```bash
fatal: renaming
```
と言れてリネームできなかったので、その際の解決策を書く。

# 解決策
一度別の名前にリネームして

```bash
git mv  Objective-C/ _Objective-C/
```

目的の名前にもう一度リネームする

```bash
git mv  _Objective-C/ objective-c/
```
これだとうまくいく。
[python] あなたは本当に python（cpython）を理解しているのか


以下のコードの実行結果に「`当たり前でしょう`」と思う方にはすみません。:bow: 
スキップしてください。

```py
class WTF:
  pass

WTF() == WTF()
# False
WTF() is WTF() 
# False

id(WTF()) == id(WTF())
# True
```


「`どうして`」と思う方は、下記のデバッグコード入りのソースを見て頂ければわかるようになると思います。

```py
class WTF(object):
  def __init__(self): print("I ")
  def __del__(self): print("D ")

WTF() is WTF()
# I I D D

id(WTF()) == id(WTF())
# I D I D    
```

    

理由の詳細な説明は [こちら](https://github.com/satwikkansal/wtfpython#-deep-down-were-all-the-same-) をご参照ください。


# 参考

https://github.com/satwikkansal/wtfpython#-deep-down-were-all-the-same-
gem dotenv-railsを使うにあたって躓いた事

まず何が躓いたってドキュメント通りにやっても上手くいかない。
原因はドキュメントを補完するように、どっかの記事を見ながらそのまま進めた事にあった。
じっくりしっかりドキュメントを見ながらしてたら、それだけでいけてた。
問題のコードは

```ini
.env
twitter_dev_account-API-KEY=
twitter_dev_account-API-SECRET=
```

ドキュメントのこの部分

```ini
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
```

要は.envファイルはハイフンは使ってはいけないってことでした。
バックグラウンドジョブをIron.ioとHerokuで10分かからず実装！

Herokuはコンテナを使用したデプロイを認めています。そして、[Iron's Worker](https://iron.io/worker?utm_source=qiita)は、
バックグラウンドジョブの運用とスケーリングを楽にします。
HerokuとIronは相互運用抜群です。Herokuはアプリケーションを構築運用を楽にできます。そして、Ironはワークロードをスケーリングすることが上手です。

シンプルなPythonアプリをHerokuにデプロイして、[Iron Worker](https://www.iron.io/worker?utm_source=qiita)にバックグラウンドジョブを書いて見ます。

##ステップ

* ドッカー化されたwebアプリをHerokuにアップ
* 新しいプロジェクトをIron上に作成
* Iron Workerを使用してバックグラウンドワーカー作成
* Herokuのアプリからワーカーを実行

下記のコマンドを実行して、
簡単な「Hello World」プロジェクトをgitクローンして、Herokuへデプロイします。

```
> git clone https://github.com/heroku/alpinehelloworld.git
> cd alpinehelloworld
> heroku create
> heroku plugins:install heroku-container-registry
> heroku container:login
> heroku container:push web
> heroku open
```

ブラウザー上に「Hello World」と表示されれば、Heroku上にちゃんとデプロイされました。

##　Iron workerを作成しましょう。

「worker.py」(実際はemailworker.py、imageprocessor.pyなど実際にバックグラウンドワーカーが実行する名前をつけます。)ファイルを作成します。
ここでは「Hello from IronWorker」を出力するようにします。

```
> cd webapp
> echo "print 'Hello from IronWorker'" > worker.py
```

Ironのクレデンシャルjsonを手に入れます。

[Iron.io](https://www.iron.io/?utm_source=qiita)へログインして、プロジェクトを作成しjsonファイルをコピーして、あなたのアプリのrootディレクトリーにおいて下さい。

```
> cp iron.json webapp/
```

ローカルでIronワーカーを起動しテストして下さい。

```
> cd ..
> docker run --rm -v "$PWD":/worker -w /worker iron/python:2 python worker.py
```

ワーカーとコンフィグjsonファイルを圧縮して、Iron.ioへアップロードします。

```Python
> cd webapp
> zip -r worker.zip worker.py iron.json
> iron worker upload --zip worker.zip --name worker iron/python:2 python worker.py
```

アップロードが完了したら、コマンドラインからワーカーを起動します。

```Python
> iron worker queue --wait worker

```

クライアントライブラリーを使用して、あなたのサイトに誰かが訪れた時に自動的にワーカーを起動しバックグラウンドジョブを実行するようにしましょう。
まず、「requirements.txt」ファイルに「iron-worker python client library 」を追加します（これはpipに必須の依存関係と認識させるためです。）。

```Python
> cd webapp
> echo "iron-worker" >> requirements.txt
```

「app.py」ファイルを下記のコードに変更します。

```Python
import os

from flask import Flask
from iron_worker import *

app = Flask(__name__)

@app.route('/')
def hello():
    task = IronWorker()
    task.queue(code_name="worker")
    return 'Hello world!'

if __name__ == '__main__':
    app.run(host='0.0.0.0')
```

## Herokuにコードをデプロイして見ましょう。

```
> heroku container:push web
> heroku open
```

ブラウザーに「Hello World」が表示されましたでしょうか？
[Iron.io](https://www.iron.io/worker?utm_source=qiita)のダッシュボードに行き、
該当のプロジェクトを開くと、下記の画像のように、既にバックグラウンドジョブが実行され「Hello from IronWorker!」と表示されます。
<img width="715" alt="hello_world_heroku.png" src="https://qiita-image-store.s3.amazonaws.com/0/272363/8998e317-0cb4-4773-985b-968efe1fcc66.png">


##まとめ
[Iron.io](https://www.iron.io/worker?utm_source=qiita)は、ほぼ全ての言語のライブラリーとREST APIを提供しています。
Iron.ioは独自のオートスケーリングアルゴリズムを使用していますので、１プロセスが次の１分で１,０００プロセスに増えたとしても対応出来ます。
そして、異なるクラウドベンダー、オンプレミス導入に対応していますので、あなたのデータ、ビジネスを簡単に移動出来ます。
commit rebase -I HEAD^^^の使い方

[参考](https://qiita.com/numa08/items/b676e38e3dbabfd39d18)
[参考２](https://backlog.com/ja/git-tutorial/stepup/stepup7_6.html0)
HEAD^^^の^の数で何個前までのコミットを含めるか決める。

```
#pick ${HASH} [WIP]テキストの最大文字数は140文字である
- pick ${HASH} テキストの最大文字数を設定した
pick ${HASH} 入力された文字数を画面に反映する
+ f ${HASH} テキストの最大文字数を設定した
pick ${HASH} 入力された文字数を画面に反映する
```

fixup ${HASH} テキストの最大文字数を設定した
とpickの部分をfixupに変えることで１つ目のコミットが融合され、コミットメッセージが消される

編集画面でfixupに書き換えたら→EXIT→enter

最後にgit push -f
で。
【Swift4】UITableViewで一番下までスクロールしたことを検知し、イベント発火させる手法

日本語でぐぐったらこれじゃないって検索結果がでたので。
英語でぐぐったらいい感じの記事があった。
https://stackoverflow.com/questions/46208539/how-to-determine-if-the-last-cell-of-a-uitableview-is-visible-on-the-screen?noredirect=1&lq=1

下記の通り

```
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        guard let lastCell = tableView.cellForRow(at: IndexPath(row: tableView.numberOfRows(inSection: 0)-1, section: 0)) else {
            return
        }
        // ここでリフレッシュのメソッドを呼ぶ
    }
```

リフレッシュメソッドを呼ぶタイミングが一番下についてからだとちょっと遅く感じるかもしれない
このようにすると、付く前に呼ばれる
また、lastCellが不要な場合はそもそも宣言しなくてよい

```
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        // 下から５件くらいになったらリフレッシュ
        guard tableView.cellForRow(at: IndexPath(row: tableView.numberOfRows(inSection: 0)-5, section: 0)) != nil else {
            return
        }
        // ここでリフレッシュのメソッドを呼ぶ
    }
```
BigQueryのLEFT JOINでイコール条件が必要でハマったときの解決策

月初からの積み上げデータを作る際にBigQueryのJOINルールでハマったのでその解決策を共有します

日次の仮想テーブル（[BigQueryで日次の仮想テーブルを作る](https://qiita.com/ryoichi-u/items/91e16ee53ccfad010ff7)）を作って月初からその日までの情報をjoinしてcountすることで積み上げグラフを作ろうとしていました。しかし、下記のエラーが...


```
LEFT OUTER JOIN cannot be used without a condition 
that is an equality of fields from both sides of the join
```

BigQueryではLEFT,OUTER JOINをするときにはイコールで条件を結ばないといけない

## 解決策

月次積み上げなのでmonthは等しいので（少し無駄になるが）monthの条件も付けてJOINさせる

##  Before（エラーになるもの）
```SQL
SELECT t1.date, count(u.id)
FROM   
(
  SELECT 
    DATE_SUB(CURRENT_DATE(), INTERVAL  n day) as date 
    FROM UNNEST(GENERATE_ARRAY(1, 365)) AS n ORDER BY n  
)  AS t1
LEFT JOIN `users` AS u 
  ON u.date BETWEEN DATE_TRUNC(t1.date, MONTH) AND  t1.date  -- 月初から指定日
WHERE
  u.city_id in (....)
GROUP BY 
  t1.date
```

## After

```SQL
SELECT t1.date, count(u.id)
FROM   
  (
    SELECT 
      DATE_SUB(CURRENT_DATE(), INTERVAL  n day) as date 
      , DATE_TRUNC(DATE_SUB(CURRENT_DATE(), INTERVAL  n day), MONTH)  as month -- LEFT JOINのイコール条件作るため
    FROM UNNEST(GENERATE_ARRAY(1, 365)) AS n ORDER BY n  
  )  AS t1
LEFT JOIN `users` AS u 
    ON  DATE_TRUNC(u.date, MONTH)  = t1.month -- LEFT JOINのイコール条件作るため
    AND u.date BETWEEN DATE_TRUNC(t1.date, MONTH)  AND  t1.date  -- 月初から指定日
WHERE
  u.city_id in (....)
GROUP BY 
  t1.date
```
Golangでグラフを描く

## はじめに
golangでグラフを描く時，つまづいたので備忘録として残しておきます．
どうやら`gonum plot`が便利らしい．
しかし，古い記事だと`go get`の場所が[google code](https://code.google.com/archive/p/plotinum/)を参照しているようだ．
現在は，`github`に移行しているので以下を実行．

```
go get gonum.org/v1/plot/...
```

## 二つのデータ群をplot
`(8.0, 2.0)`と`(3.0, 6.0)`を軸にそれぞれclass1,class2として100個,ガウス分布に従って，学習データを生成したものを`plot`する．
以下がそのコードである．図の生成から`plot`まで，コメント文を参照してください．

```golang
package main

import (
	"image/color"![plot.png](https://qiita-image-store.s3.amazonaws.com/0/123283/3a191005-7612-21c4-88ef-aa6b3f3c5e29.png)

	"math/rand"
	"time"

	"gonum.org/v1/plot"
	"gonum.org/v1/plot/plotter"
	"gonum.org/v1/plot/vg"
)

func main() {

	// 図の生成
	p, err := plot.New()
	if err != nil {
		panic(err)
	}
	//label
	p.Title.Text = "Points Example"
	p.X.Label.Text = "X"
	p.Y.Label.Text = "Y"

	// 補助線
	p.Add(plotter.NewGrid())

	//クラス1
	x1, y1 := 8.0, 2.0

	//クラス2
	x2, y2 := 3.0, 6.0

	//各クラスのサンプル
	n := 200

	// 散布図の作成
	plot1, err := plotter.NewScatter(randomPoints(n, x1, y1))
	if err != nil {
		panic(err)
	}

	plot2, err := plotter.NewScatter(randomPoints(n, x2, y2))
	if err != nil {
		panic(err)
	}

　   //色を指定する．
	plot1.GlyphStyle.Color = color.RGBA{R: 255, B: 128, A: 55}
	plot2.GlyphStyle.Color = color.RGBA{R: 155, B: 128, A: 255}

    //plot1,plot2をplot
	p.Add(plot1)
	p.Add(plot2)

    //label
	p.Legend.Add("class1", plot1)
	p.Legend.Add("class2", plot2)

	// 座標範囲
	p.X.Min = 0
	p.X.Max = 10
	p.Y.Min = 0
	p.Y.Max = 10

	// plot.pngに保存
	if err := p.Save(6*vg.Inch, 6*vg.Inch, "plot.png"); err != nil {
		panic(err)
	}

}

//ガウス分布
func random(axis float64) float64 {
	//分散
	dispersion := 1.0
	rand.Seed(time.Now().UnixNano())
	return rand.NormFloat64()*dispersion + axis
}

//学習データの生成
func randomPoints(n int, x, y float64) plotter.XYs {
	pts := make(plotter.XYs, n)
	for i := range pts {
		pts[i].X = random(x)
		pts[i].Y = random(y)
	}
	return pts
}

```

## 結果
![plot.png](https://qiita-image-store.s3.amazonaws.com/0/123283/e898fd29-1bde-ed02-2040-afe02898f60a.png)

実際にplotすることができた．

## 参考文献
[Go でグラフを plot するパッケージを試した](https://qiita.com/ikawaha/items/61dac34ebfe2f8fa5c61) 
[gonum](https://github.com/gonum/gonum)
はじめてのGAS - Slackにメッセージを送る

# 概要
今回はGoogle Apps ScriptでSlackへユーザーメッセージを投稿してみます。
ボットユーザーでメッセージを投稿する方法はまた異なりますのでご注意ください。

# Slackアプリの登録＆設定

### 1. Slackアプリ一覧画面を開きます

[Slack APIのページ](https://api.slack.com/)を開き、 右上の 「Your Apps」リンクを押します。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/87995/c1957c11-eca8-6ceb-9d9c-9d840d722140.png)

### 2. Slackアプリを作成します。

「Your Apps」の下にある「Create New App」ボタンを押します。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/87995/15eacb75-8896-f058-cb88-bf09e00e6aec.png)

アプリ名、動作させるワークスペースの欄を入力して「Create App」
アプリ名は後から変更出来ますが、ワークスペースは変更ができないので注意が必要です。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/87995/28f44078-14a9-aef9-764b-70e9d53b4637.png)

### 3. アプリに権限を追加します。

アプリが無事作成されると、アプリの管理画面が開きます。
左のメニューから「OAuth & Permissions」を選択し、Scopesというブロックまで下にスクロールします。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/87995/f9dce25d-dddd-ba3b-b4d3-7420fa270b4e.png)

セレクトボックスで`chat:write:user`を探して選択します。
キーボードで入力することで絞り込み（インクリメンタルサーチ）されます。
選択後は Save Changes ボタンを押すの忘れずに

![5.png](https://qiita-image-store.s3.amazonaws.com/0/87995/ec3e6339-1ea0-97ea-5a51-e1d9e6573981.png)

### 4. アプリをワークスペースにインストールします。

一番上までスクロールして、「Install App to Workspace」ボタンをおします。
完了すると、OAuth Access Token が発行されます。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/87995/3722adea-d260-4459-7efe-ff15fd7123fb.png)

# GASコード

GASプロジェクトを作成しコーディングしていきましょう。

```javascript
function testPost() {
  const app_auth_token = PropertiesService.getScriptProperties().getProperty('slack_app_auth_token');
  const channel = PropertiesService.getScriptProperties().getProperty('channel');
  
  const result = postMessageToSlackChannel(
    app_auth_token, 
    channel, 
    "It is sample message!!"
  );
  Logger.log(result);
}

/**
 * messageをSlackチャンネルにポストする関数
 */
function postMessageToSlackChannel(app_auth_token, channel, message){
  const payload = {
    "token" : app_auth_token,
    "channel" : channel,
    "text" : message
  };
  const options = {
    "method" : "post",
    'contentType': 'application/x-www-form-urlencoded',
    "payload" : payload
  };
  
  return UrlFetchApp.fetch("https://slack.com/api/chat.postMessage", options);
}
```

# 実行

`testPost`関数を実行すると、外部サービスに接続するための権限確認のダイアログが表示されます。

![7.png](https://qiita-image-store.s3.amazonaws.com/0/87995/7a976c6d-5e83-a46c-08c6-5cb2502946d6.png)

![8.png](https://qiita-image-store.s3.amazonaws.com/0/87995/b0e787ac-0ad0-d02c-2891-5c6b32fed0f4.png)

# 参考リンク

- [GAS - UrlFetchApp.fetch](https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app)
- [Slack - chat.postMessage](https://api.slack.com/methods/chat.postMessage)
[Literature Review] Intent Detection

## Introduction
When I worked on the project, I was required to acknowledge my understanding in Intent detection more, so I have decided to do some literature review and summarise this domain for further research purpose.
My initial touch point was "FastText" which is current state-of-the-art, so I would like to start analysing the paper named "Enriching Word Vectors with Subword Information" and "Bag of Tricks for Efficient Text Classification".

## Intent Detection
### FastText
Title: Enriching Word Vectors with Subword Information
Link: https://arxiv.org/pdf/1607.04606.pdf
Author: Piotr Bojanowski and Edouard Grave and Armand Joulin and Tomas Mikolov
Published Year: 2016

Title: Bag of Tricks for Efficient Text Classification
Link: https://arxiv.org/pdf/1607.01759.pdf
Author: Armand Joulin Edouard Grave Piotr Bojanowski Tomas Mikolov
Published Year: 2016

###
PowerShell 6系のタスクスケジューラの設定方法

## PowerShell 5系までのタスクスケジューラ

「PowerShell タスクスケジューラ」と検索するとおおむね以下の記事等がヒットするのではないでしょうか？
http://www.atmarkit.co.jp/ait/articles/1412/03/news125.html
.NET Coreである6系の「pwsh.exe」は、従来の「powershell.exe」とはディレクトリが違うのでメモ代わりに残しておきます

## PowerShell 6系の設定

* プログラム/スクリプト(P)

```
 "C:\Program Files\PowerShell\6.XXX.XXX\pwsh.exe"
```

xxxは各環境のバージョンに合わせてください

* 引数の追加

```
"C:\Users\xxx\xxx\xxx.ps1"
```

同じくxxxは各環境のバージョンに合わせてください。
ただし.ps1のコマンドレットファイルは**UTF-8**で作成してください。
PowerShell5系まではShiftJISがデフォルトだったのですが...
MySQL のデータを TimeMachine から復旧する

homebrew で入れた macOS の MySQL に入っている開発用のデータを誤って飛ばしてしまったので、Time Machine から復元した。

## 1. MySQL を止める

```console
$ brew services stop mysql
  or
$ mysql.server stop
```

## 2. TimeMachine から復元


* `/usr/local/var/mysql` ディレクトリが表示されている状態にする  
（terminal で`open /usr/local/var/mysql` とか)
* メニューバーの Time Machine アイコンから「Time Machine に入る」を選択
* 適当な日付まで、戻って mysql ディレクトリを選択した状態で、「復元」を押す
* 上書きするか聞いてくるので、上書きを選択

## 3. MySQL 再開

```console
$ brew services start mysql
  or
$ mysql.server start
```

## あとがき

今の macOS は直近のデータまでだったら外付けの Time Machine Backup HDD がなくても、手元のSSD とかにデータが残ってるので、ふとした瞬間のデータ復元がいつでもできて大変助かる。
一時停止機能の作成

**Time.timeScale**による一時停止機能。
アイテム画面の閲覧中などに使えるかもしれません。
使い勝手は良くないです。←

いや、正直アニメーションを個別に止めたりするほうがまだ楽な気がします・・・

注意点：**Update関数内のものは止まりません。**止めたいものは**FixedUpdate**内へ記述しましょう。

```Pause.cs
using UnityEngine;

public class Pause : MonoBehaviour {

    //どこからでもアクセスしたく、staticにしました
    public static bool isPaused;

    private void Update()
    {
        if(isPaused){
            Time.timeScale = 0f;
        }else{
            Time.timeScale = 1f;
        }
    }
}
```
Microsoft Translator API v3をGoogle Apps Script から使う方法

# 概要
Microsoft Translator API v2が2019年4月にCloseされ、v3に移行する必要があるようです。
いままでGASで動いていたv2のSlack翻訳botをv3にしたので、そのコードを晒しておきます。

### 関連記事
v1: https://qiita.com/kemayako/items/21fe36005e6e729aff77
v2(GAS): https://qiita.com/sosuke/items/ece4aee023fade0c2d23


# ソースコード
https://docs.microsoft.com/en-us/azure/cognitive-services/translator/migrate-to-v3 に従い、認証方法やレスポンスの構造(xml→json)をv2実装から変更しています。
↓の記事の内容から `translate()` の実装を以下のものと置き換えれば、そのまま動作するはずです。

https://qiita.com/sosuke/items/ece4aee023fade0c2d23

```js

var MS_API_TOKEN="鍵";
var PRIMARY_LANGUAGE="ja";
var SECONDARY_LANGUAGE="ko";

function translate_v3(text) {
  var detect_url = "https://api.cognitive.microsofttranslator.com/detect?api-version=3.0";
  var options = {
    "method": "post",
    "headers": {
      "Content-Type": "application/json",
      "Ocp-Apim-Subscription-Key": MS_API_TOKEN
    },
  };
  options["payload"] = JSON.stringify([{"text":text}]);
  var detect_resp_raw = UrlFetchApp.fetch(detect_url, options).getContentText("UTF-8");
  var detect_resp =  JSON.parse(detect_resp_raw);
  var language = detect_resp[0]["language"];
  
  var from = language;
  var to = PRIMARY_LANGUAGE;
  if (language.indexOf(PRIMARY_LANGUAGE) >= 0) {
    to = SECONDARY_LANGUAGE;
  }

  var translate_url = 'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&To='+to;
  options["payload"] = JSON.stringify([{"text":text}]);
  var translate_resp_raw = UrlFetchApp.fetch(translate_url, options).getContentText();
  var translate_resp =  JSON.parse(translate_resp_raw);
  return translate_resp[0]["translations"][0]["text"];

}
```


# Microsoft Translator API v3の所感

Microsoft Translator API v3に関するQiita記事はまだ無いようなので、多少所感を書いておきます。

v2からv3に上げたことで、翻訳の内容が変わり、
やや韓→日、日→韓の翻訳精度が上がったように思います。

例えば、
> 네, 알겠습니다.

という文は、v2の翻訳だと

> 私の、サー。

などという、「同音異義語間違え」「英語等の他の言語を経由した形跡」が見られましたが、
v3では、

> はい、わかりました。

と正確に訳されるようになりました。
その他、丁寧語の訳も正確に出るようになった気がします。
TPSカメラの作り方

<img width="773" alt="スクリーンショット 2018-07-17 16.37.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/256717/7249ef98-74fd-7a12-cc5f-4d0ddf3a7536.png">

空のオブジェクトを作成し、プレイヤー位置を常に追従させ、子オブジェクトにカメラを配置します。
カメラはプレイヤーから離れた位置へ（好みの場所で）。
また、**Mathf.Clamp**で、縦方向の回転角度を制限しています。




【参考】[Unityでカメラの向きを基準に移動する方法と、追従して回転できるカメラの実装](
http://tech.pjin.jp/blog/2016/11/04/unity_skill_5/)

```TpsCamera.cs
using UnityEngine;

public class TpsCamera : MonoBehaviour {

    [SerializeField] Transform Player;
    [SerializeField]float RotateSpeed;

    float yaw,pitch;
    
    private void Start()
    {
        RotateSpeed = 1;
    }

    void Update () {
        
        //プライヤー位置を追従する
        transform.position = new Vector3(Player.position.x, transform.position.y, Player.position.z); 

        yaw +=  Input.GetAxis("Mouse X")*RotateSpeed; //横回転入力
        pitch-=Input.GetAxis("Mouse Y")*RotateSpeed; //縦回転入力

        pitch = Mathf.Clamp(pitch, -80, 60); //縦回転角度制限する

        transform.eulerAngles = new Vector3(pitch, yaw, 0.0f); //回転の実行
	}
}
```
Podの使い方

毎回忘れてしまうので自分へのメモ用

#手順
①podinit
②Podfileの編集
③pod install
④xcworkspace（白いやつ）を開く
⑤ビルドする（ビルドしないとimportでエラーがでる）
⑥import

#intallとupdateの違い
pod install -> Podfile.lock を見てインストール
pod update -> Podfile に書いてある利用可能な最新バージョンをインストール


つまり、基本的にinstall、ライブラリのバージョンを更新したい時のみupdate。
ちなみにinstall時にPodfile.lockがない場合は新しく生成されるので、新規インストール時もinstallでよい。
Discordの投稿につけたリアクションを通知するボット

# どうして作ろうと思ったか
最近は友人とグループでDiscordを使って会話をすることが多く、わざわざ返事を書くほどでもないけど反応はしたいと言う気持ちでリアクションを使っていました。しかし、リアクションをされた側は通知がこないので

```
A「昨日の投稿見た？」
B「リアクションつけたよ」
Aが確認してから
A「本当だ、気づかなかった」
```

ということが何度かありました。そこで、**リアクションに通知がくればいいじゃないか**とBotを書いてみました。

# できないこと（追記）
コメントで@1ntegrale9のこの実装の弱点を教えてもらったのでここに追記しておきます。

以下に書く方法では**Botが起動してから受信したメッセージ以外に対して反応できません**(botにキャッシュされているメッセージにしか反応ができないようです)。つまり、Herokuのように1日に1回再起動するような仕様のPaaSを利用している場合あまり使えない実装となっております。

# 完成品
作り方も下に書いてありますが一応完成したものはここにDiscord-Reactorと言う名前で置いてあります

https://github.com/pineapplehunter/Discord-Reactor

一応`README.md`を見ればある程度分かるように書いたつもりですがわからないところがあれば、ここのコメントでもissueでも何でも質問してください。

# 作り方
## Botを作る
とりあえずまずBotがないといけないので私が以前書いた~~まあまあアクセスがあってビビってる~~下の記事を参考にBotを作って見てください。

[Pythonで簡単なDiscord Botの作り方](https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f)

Botが動くのを確認できたら次に進んでください

## リアクションに反応する
上の記事ではメッセージに反応するために

```py
@client.event
async def on_message(message):
```

のような関数を書きました。リアクションも似たようなものです。下のように書きます。

```py
@client.event
async def on_reaction_add(reaction, user):
```

ここの引数の説明を軽くすると

* reaction
  - `discord.Reaction`のクラス。リアクションの種類や`reaction.message`でリアクションがついたメッセージを参照できたりする。

* user
  - `discord.User`のクラス。リアクションをつけた人のデータ。

これを利用することでメッセージを投稿した人に「リアクションがつきました」と通知ができます！

## 実装
特に説明する要素がない気がするので最小限のコードだけ載せておきます。

```py
import discord

client = discord.Client()

@client.event
async def on_reaction_add(reaction, user):
    # author: リアクションがついたメッセージを書いた人
    author = reaction.message.author
    await client.send_message(author, f"{user} さんがリアクションをしました")


client.run("あなたのBotのトークン")
```
このコードを実行すると、誰かがあなたの投稿にリアクションをつけると通知がくるようになります。

# 最後に
このbotを入れてからTwitterの良いね感覚でリアクションが使えるのでかなり便利です。

~~このbotはできればPublicにして誰でも使えるようにしたかったのですが自分のサーバーがかなり貧弱なので諦めました。もし誰か強いサーバーが余ってる方がいましたらぜひやってくれると嬉しいです。~~
追記 2018/7/31
コメントでこの実装がサーバーに載せずらいことが分かりました。
ruby on rails 環境をセットアップするときの自分メモ

素のCentOSにRuby on Rails環境を作る時に毎回ググる項目のメモ

# 必要なyum
```
sudo yum install -y git gcc openssl-devel readline-devel zlib-devel mysql-devel
sudo yum install -y epel-release
sudo yum install -y nodejs --enablerepo=epel
```
* gitはrbenvのインストールに必要
* gcc〜zlib-develは2.4.1で必要でした。
* mysql-develはmysql2のgemを使わないなら不要。大体使うから入れておく。
* ~~nodejsはmigrateの時にRuntimeが無いと怒られる件に対応する。~~
  * ~~参考：https://qiita.com/azusanakano/items/771dc9919f347de061d7~~
  * nodeはyarnの部分でバージョンが古くて話にならないので、最新版を入れる手順を後述。

# rbenvのセットアップ
```
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
exec $SHELL -l
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install -v 2.4.1
rbenv rehash
rbenv global 2.4.1
```
* 2.4.1の部分はバージョンに応じて適宜書き換え
* 参考：https://qiita.com/inouet/items/478f4228dbbcd442bfe8

# rails環境構築で（よく忘れる）使うコマンド
* bundlerのインストール  

```
gem install bundler
```
* vendor/bundlerにbundle install  

```
bundle install --path vendor/bandler
```
  * 参考：https://qiita.com/osamtimizer/items/3a241f365c85356394a8

# yarnの導入

```
sudo yum remove nodejs npm #古いのが入っていれば削除
curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash -
sudo yum install -y nodejs
sudo npm install yarn -g
# webpacker 使っている場合 rails プロジェクト配下で
bundle exec rails webpacker:install
```

* 参考：
 * http://d.hatena.ne.jp/xlc/20170910/1505010764
 * https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora
 * [npm install で SSL Error になった時の対処法。](https://blog.yug1224.com/archives/563d9b67bf652a600632d01e)

## nodeのバージョンでエラーになるケースへの対応
* node-sassがnodejsのバージョン10.6でエラーになる
 * http://kongaribug.hatenablog.com/entry/2018/07/16/021827

### nを導入してバージョンを変えられるようにする

```
sudo npm install -g n
sudo n 9.11.2
```
  * 参考：https://github.com/tj/n

# mysqlコマンド
* ユーザーに権限追加  

```
grant all on *.* to 'username'@'192.168.33.%'
```
  * IP部分は適宜書き換え。例ではVirtualBoxのprivate_networkからの接続を許可するような設定
* DB作成  

```
CREATE DATABASE データベース名 CHARACTER SET UTF8
```
  * latin1でいつもイラッとするやつ
* 5.6系をインストールする  

```
sudo yum -y install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
sudo yum -y install mysql-community-server
```
  *　参考：https://weblabo.oscasierra.net/installing-mysql-rhel6-with-yum/

# その他エラー対処
## make: g++: コマンドが見つかりませんでした
```
sudo yum -y install gcc-c++
```
https://notsleeeping.com/archives/863
Rmarkdownお役立ち情報まとめ

# TL;DR

- Rmarkdownのチートシート的な記事
- 主にRmarkdownを使ってレポート等を執筆している学生向け
- 随時更新していきます
- 他に追加したいものがあったら修正リクエストお願いします

## 日本語文字化けしない設定

```markdown
---
title: "タイトル"
subtitle: "サブタイトル"
output:
  pdf_document: 
    latex_engine: lualatex 
documentclass: ltjsarticle
---
```



## 画像のサイズ指定

```markdown
![代替テキスト](画像ファイル名){width=幅の値 height=高さの値}
```

オススメの設定は↓

```markdown
![代替テキスト](画像ファイル名){width=10cm}
```

# 参考サイト

http://blog.k-sakabe.com/2016/07/12/latex%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B%E3%81%AB%E3%82%82%E5%AF%BE%E3%81%99%E3%82%8Bmarkdown%E4%B8%AD%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%B5%E3%82%A4%E3%82%BA%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95/
BigQueryで日次の仮想テーブルを作る


redashで可視化のため累積グラフを作るときに必要となったので、基準となる日ベースの仮想テーブルを作りました。

いろんな書き方がありそうですがありますが、思いついた書き方はこれ
スタンダードクエリを使っています

```SQL
-- 昨日から１年間分の日付仮想テーブル
SELECT 
  t1.date
FROM   
  (
    SELECT DATE_SUB(CURRENT_DATE(), INTERVAL n day) as date 
    FROM UNNEST(GENERATE_ARRAY(1, 365)) AS n ORDER BY n  -- 365日分
  )  AS t1
;
```

ここに `JOIN` させていく形で今まで作れていなかった各種テーブルが作れそう


----

#### 参考

[mysqlの同様の仮想テーブル作成](https://symfoware.blog.fc2.com/blog-entry-1713.html)