OmniAICreator/Qiita-1.07M huggingface dataset:
Hashクラスにおける要素の削除メソッド

#背景

Ruby技術者認定試験に向け、[Ruby技術者認定試験公式ガイド](https://www.amazon.co.jp/RUBY%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93-%E5%85%AC%E5%BC%8F%E3%82%AC%E3%82%A4%E3%83%89-ITpro-BOOKs-%E4%BC%8A%E8%97%A4%E5%BF%A0%E3%83%86%E3%82%AF%E3%83%8E%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BA/dp/4822234304/ref=sr_1_1?ie=UTF8&qid=1519637097&sr=8-1&keywords=Ruby%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93%E5%85%AC%E5%BC%8F%E3%82%AC%E3%82%A4%E3%83%89)を使ってお勉強をせっせとしていたところ、ある問題で「むむっ」と詰まってしまい、リファレンスをめちゃくちゃ調べた（当社比）のでメモ的な感じで書いていく。

プログラムの実行環境はRuby2.4.0/Ubuntu 16.04 LTSです。

#ハマった問題

自分がハマったのはこんな問題でした。著作権の都合上、問題文を変えてます。ザックリと言うと、

- こんな出力になるのはどんな時か。当てはまるコードを入れてね。

```ruby:main.rb
hs = {:Tom => 2000, :John => 3000}
#ここにコードを書く
p hs

#出力
# {}
```
選択肢は省きますが、この場合、正解になりうるメソッドは

- delete_if（ブロックを評価して真の場合に要素を削除）
- clear（ハッシュの全内容を削除）

です。ここまでは説明を読んで「ほー」となったのですが、問題はここからです。

- reject（ブロックを評価した値が真の場合、値の要素を削除）は、非破壊的メソッドなのでhs自体に影響を及ぼさないため不正解　←？？
- reject!（rejectの破壊的メソッド）にすれば正解。

どういうことなんだろう。rejectは上辺だけ変えて本質は変えてない？（哲学）なんのこっちゃとなったので[Rubyリファレンスマニュアル](https://docs.ruby-lang.org/ja/)のお力を借りてみた。リファレンスマニュアルによるとrejectの仕様は次のような記述になっています。

>self を複製して、ブロックを評価した値が真になる要素を削除したハッシュを返します。 

#ということは

つまり、

```ruby:main.rb
hs = {:Tom => 2000, :John => 3000}
p hs.reject { |value, key|  true} #rejectしたのを見る
p hs #もっかい見る
```
とすると、出力は

```
{}
{:Tom => 2000, :John => 3000}
```
となります。破壊的メソッドと非破壊的メソッドの本質なのですが、
非破壊的メソッドでは、実行した段階で参照したオブジェクトとは違う新しいオブジェクトが生成され、その中に変更後の値が入ります。つまり、main.rbの２行目で表示しているのは、hsに変更を施したものを入れた**別のハッシュ**です。リファレンスに基づくと「self（自分自身）を複製したハッシュを、値を変更した後のハッシュに置き換える」ということです。当然、３行目で参照しているのはhsそのものなので、変更されてないありのままのハッシュが表示されるわけです。対して、破壊的メソッドでは

```ruby:main.rb
hs = {:Tom => 2000, :John => 3000}
p hs.reject! { |value, key|  true} #reject!
p hs #もっかい見る
```
とすると、出力は

```
{}
{}
```

になります。破壊的メソッドはオブジェクトそのものを変えてしまうので名前の通り
「破壊的」ですね。めっちゃ基本の復習でした。

こんな感じで``delete_if``や``clear``のほかに``reject!``がハッシュの要素を削除するメソッドとして使えることがわかりました。コードに何気なく書いてありますが``delete_if``や``reject!``で全要素を削除するには評価条件を無理やり全部trueにしておきます。

何か間違いや誤字脱字などがありましたら指摘をよろしくお願いします。初めての投稿（カミングアウト）なので至らない点が無数あると思います。

ここまで読んでいただきありがとうございました。

#参考・引用

- [Hashクラスの組み込みライブラリ - Rubyリファレンスマニュアル](https://docs.ruby-lang.org/ja/2.4.0/class/Hash.html)
- [Ruby技術者認定試験公式ガイド(Amazon)](https://www.amazon.co.jp/RUBY%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93-%E5%85%AC%E5%BC%8F%E3%82%AC%E3%82%A4%E3%83%89-ITpro-BOOKs-%E4%BC%8A%E8%97%A4%E5%BF%A0%E3%83%86%E3%82%AF%E3%83%8E%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BA/dp/4822234304/ref=sr_1_2?ie=UTF8&qid=1519643226&sr=8-2&keywords=ruby%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93)
PythonでTkinterがインポートできないと怒られた

# 環境
Ubuntu 16.04.4 LTS (VirtualBoxゲストOS)
Python 3.5.2

# やろうとしたこと
PythonでTkinterを使い、デスクトップアプリを作ろうとした。

# ソースコード

``` Python3:HIee.py
#!/usr/bin/env python3
# -*- coding: utf8 -*-
import sys
import Tkinter

root = Tkinter.Tk()
root.mainloop()
```
# 実行

``` bash:bash
$ python3 HIee.py
```

# 実行した結果

```
Traceback (most recent call last):
  File "HIee.py", line 4, in <module>
    import Tkinter
ImportError: No module named 'Tkinter'
```
Tkinterモジュールが見つからないのか、ふむふむ。
というわけで、Tkモジュールをインストールした。

# Tkモジュールのインストール

``` bash:bash
$ sudo apt-get install python3-tk
$ sudo apt-get install tk-dev
```

この状態で再実行してみる。

あれ？？？さっきとエラーメッセージ変わってない(汗)
仕方がないので、あちこち検索してみた。

# エラーの原因
モジュール名がまちがっていた。
以下のように、`Tkinter`ではなく、頭のTが小文字で正しくは`tkinter`と書かないといけなかった。

``` Python3:HIee.py
#!/usr/bin/env python3
# -*- coding: utf8 -*-
import sys
import Tkinter
     ↓
import tkinter

root = Tkinter.Tk()
     ↓
root = tkinter.Tk()
root.mainloop()
```
Xamarin.Forms で Nuget のカレンダーを使う（１）

初投稿です。Xamarin.Forms を使って何でもいいからスマフォアプリが作りたくて勉強中。

# 今回やりたいこと
Xamarin.Forms でカレンダーの表示・利用。
ただ Android の CalendarView みたいなものがないので、どうすればいいのか…と思案。調べてもなかなか出てきません。各ネイティブ層で別々に作るか、それらしいのを自力で作るしかないのかと思ったところで、Nuget に有志が作ってくれたパッケージがあることを知り、それを試してみることにしました。

Android/iPhone 両方で作りたいのですが、今は iMac 環境が無いのでとりあえず Android 環境でのみ確認しておきます。

使うのは Nuget にあった XamForms.Controls.Calendar です。

# 環境
* Visual Studio 2017 v15.5.5
* .NET Framework 4.7
* Xamarin.Forms 2.5
* Android Emulator x86 (v6.0 API23)

# 事前準備
1. [ツール]->[ソリューションのパッケージの管理] を開く
2. 今回は XamForms.Controls.Calendar v1.1.1 を選択
![xamarin_nuget_calendar.png](https://qiita-image-store.s3.amazonaws.com/0/233922/de35dae9-5d62-c6a1-cd40-f92a3389587a.png)
3. 「インストール」ボタンを押下してインストール

# 基本表示

カレンダーを貼り付けたい XAML の ContextPage に以下文を追加します。

```xml:Sample.xaml
xmlns:controls="clr-namespace:XamForms.Controls;assembly=XamForms.Controls.Calendar"
```
5. カレンダーを貼り付けたい XAML に以下文を追加

```xml:Sample.xaml
            <controls:Calendar Padding="10,0,10,0" StartDay="Sunday" 
                               SelectedBorderWidth="4" DisabledBorderColor="Black" />
```

cs ソースは変更なし。
単純にカレンダーを表示させるだけならこれで OK です。
![xamarin_calendar_def.png](https://qiita-image-store.s3.amazonaws.com/0/233922/8c53b79f-eed9-a7fb-1553-06a67db3848f.png)

# 属性

XamForms.Controls.Calendar は結構属性が多いです。
以下は一例。どっかに API ないのかしら…

| 属性 | 概要 | 指定文字 |
|:-:|:-:|:-:|
| TitleLabelTextColor | 年月表示の色を指定する | 色 |
| TitleLabelFormat | 年月表示のフォーマットを指定する | e.g.) "YYYY年 MM月" |
| StartDay | 開始曜日の指定 | 曜日 |
| SelectedBorderWidth | 選択した日の枠の太さ | 数字 |
| Padding | 前後左右の余白 | 左幅,上幅,右幅,下幅, |
| DatesTextColor | 年月に該当する日々の色を指定する | 色 |

取り合えずデフォルトでは <b>2 2018</b> みたいな感じでダサいので、 <b>TitleLabelFormat 属性</b>でいいフォーマットにしておいたほうが良さそうです。

```xml:Sample4.xaml
            <controls:Calendar Padding="10,0,10,0" StartDay="Sunday" 
                               SelectedBorderWidth="4" DisabledBorderColor="Black"
                               TitleLabelFormat="yyyy年MM月" />
```

# 画面遷移と土日祝日の設定

続きを書きました。
<a href="https://qiita.com/loveloveoita/items/642000ecd0d979ada963">Xamarin.Forms で Nuget のカレンダーを使う（２）</a>


# リンク

基本的な使い方は本家参照。
https://github.com/rebeccaXam/XamForms.Controls.Calendar
MongoDB一覧取得で閲覧数とかのカウントを取りたい時

　かなり放置していましたが更新します。以前の記事はMongoDB3.4でして、現在は3.6を利用しています。今回の記事はバージョンの差異による問題は無いかと思います。

# 一覧にcountを出したい
　PHPだとMySQL使ってましたが、１対多のテーブル構造でGroupByからのCountで件数を表示していました。Mongoでも似たことをやりたかったのですが、調べるのに苦労したので備忘としてメモしておきます。

|タイトル|質問|回答数|
|---|---|---|
|ほげ|ほげほげ|2|
|ふが|ふがふが|5|
|ぬが|ぬがぬが|0|

こんな表を作りたい時のクエリです。

データ構造は例えば以下のパターンで考える
課題コレクション（kadais）
no(課題No＝オブジェクトIDでも良い)
title(課題のタイトル)
question(課題の問題)

回答コレクション(kaitous)
kadai_no(回答の対象になった課題のNo)
answer(問題に対する回答)


データの入れ方等は本筋ではないので割愛
※ちなみにRobo 3T使ってます。

```
db.getCollection('kadais').insert([
    { 'no': 1, 'title': 'ほげ', 'question': 'ほげほげ' },
    { 'no': 2, 'title': 'ふが', 'question': 'ふがふが' },
    { 'no': 3, 'title': 'ぬが', 'question': 'ぬがぬが' },
]);
db.getCollection('kaitous').insert([
    { 'kadai_no': 1, 'answer': 'あ' }, { 'kadai_no': 1, 'answer': 'い' },
    { 'kadai_no': 2, 'answer': 'う' }, { 'kadai_no': 2, 'answer': 'え' }, { 'kadai_no': 2, 'answer': 'お' }, { 'kadai_no': 2, 'answer': 'か' },
    
]);
```

そしてSQLで言うところのJoinをして$sizeを使う

```
db.getCollection('kadais').aggregate([
    {
        "$lookup": {
            "from": "kaitous",
            "localField": "no",
            "foreignField": "kadai_no",
            "as": "kaitous"
        }
    },
    {
        "$project": {
            "no": "$no",
            "title": "$title",
            "question": "$question",
            "count": { "$size": "$kaitous" },
        }
    }
])
```

これで欲しかったものが取得できる。





# ちょっと捻って正解数を出したいなって時
※簡略化のため、課題の問題に関係なくanswerが「あ」のものを正解とします。

```
db.getCollection('kadais').aggregate([
    {
        "$lookup": {
            "from": "kaitous",
            "localField": "no",
            "foreignField": "kadai_no",
            "as": "kaitous"
        }
    },
    {
        "$unwind": {
            "path": "$kaitous",
            "preserveNullAndEmptyArrays": true
        }
    },
    {
        "$project": {
            "no": "$no",
            "title": "$title",
            "question": "$question",
            "seikai": {
                "$size": {
                    "$filter": {
                        "input": ["$kaitous"],
                        "as": "kaitou",
                        "cond": { "$eq": [ "$$kaitou.answer", "あ" ] }
                    }
                }
            }
        }
    },
    {
        "$group": {
            "_id": {
                "_id": "$_id",
                "no": "$no",
                "title": "$title",
                "question": "$question",
            },
            "seikai": {
                "$sum": "$seikai"
            }
        }
    },
    {
        "$project": {
            "no": "$_id.no",
            "title": "$_id.title",
            "question": "$_id.question",
            "seikai": "$seikai",
        }
    }
])
```

こんな感じ

unwindに「"preserveNullAndEmptyArrays": true」を付けるとOuterJoin的なものになります。
デフォルトはInnerJoin的なものになってます。

あとは、filterつかってカウントの和を求めて正解数としています。
$cond～ifとかで何とかする手もありそうです。
最適解かは別として、使い方のメモ的な位置付けとしてご理解ください。

# おわりに
　如何でしょうか。Aggregateは色々出来すぎて探すのが大変でした。また時間を見つけて投稿出来れば思っています。間違え等あればご指摘をお願い致します。
CO2センサを部屋につけてログを取る


# ざっくり言うと
・部屋のCO2濃度があがると集中力が落ちて眠気を感じるらしい。
・CO2-miniって製品つかうと簡単にRaspberry PiからCO2濃度が取得できる。
・USB接続で、はんだ付けもブレッドボードも要らないのでお手軽。


# 背景
・一人暮らし始めてからすぐ眠くなったり気が付いたら何もしないで時間がたってることが増えた。
・CO2濃度が高いと集中力が落ちて眠気を感じるらしいので測ってみたい


# 使ったもの
 Raspberry Pi
 [CO2-mini(商品リンク)](https://www.amazon.co.jp/dp/B00I3XJ9LM)

# CO2濃度を読み取る
　Raspberry PiにUSBで接続してこちらのPythonモジュールつかえば簡単に読めます。
　[Github heinemml/CO2Meter](https://github.com/heinemml/CO2Meter)
　
まずはpipでインストール

```
sudo pip3 install git+https://github.com/heinemml/CO2Meter
```
サンプルスクリプトを参考に読み込み
なぜかサンプルと同じ2秒の待ち時間ではうまくいかなかったので10秒待ってます。

```python:show_CO2.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from CO2Meter import *
from time import sleep

# CO2meterが認識されているデバイスを設定
# 他にUSBデバイス挿してると末尾が1とか2とかになってるかもしれません。
sensor = CO2Meter("/dev/hidraw0")
# ちょっと待つ
sleep(10)
# CO2濃度を取得(単位はppm)
data = sensor.get_co2()
# 表示
print("CO2: {}ppm".format(data["co2"]))
```

実行結果

```
$ sudo python3 show_CO2.py
CO2: 936ppm
```

# CO2濃度を定期的に測る
上の表示用プログラムをちょっと修正

```python:CO2_logger.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from CO2Meter import *
from time import sleep
from datetime import datetime
import csv


# CO2meterが認識されているデバイスを設定
sensor = CO2Meter("/dev/hidraw0")
# ちょっと待つ
sleep(10)
# CO2濃度を取得(単位はppm)
data = sensor.get_co2()
# 現在日時と時刻を取得
time = datetime.now()
# ファイル名を作成
filename = time.strftime('%y%m%d.csv')
# ファイルに結果を追記
with open(filename, 'a') as f:
    writer = csv.writer(f, lineterminator='\n')
    row = [time.strftime('%H:%M:%S'),data["co2"]]
    writer.writerow(row)

```

1分周期で動くようにcrontab設定

```
* * * * * sudo python3 ~/CO2_logger.py
```

# 結果
　締め切っていると1時間くらいで1200ppmまで上がることが分かった。
  窓開けっぱなしじゃないとどうにもならない。引っ越ししたい。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/98679/a8185a79-2c3e-5d47-23cf-bdddf5e8df28.png)



# 補足
Windows向けのCO2-mini用データロギングソフトが[ここ(リンク有)](https://www.co2meter.com/collections/desktop/products/co2mini-co2-indoor-air-quality-monitor)にあるので、とりあえず動かしたい方はこちらからどうぞ。



# 参考資料
[チームラボオフィスの空気環境(CO2)を測定して改善している話](http://ch.nicovideo.jp/tks/blomaga/ar932992 "チームラボオフィスの空気環境(CO2)を測定して改善している話")
[CO2モニタリングのためにセンサーをHackした話](http://r-kurain.hatenablog.com/entry/2016/01/26/164648 )
[Reverse-Engineering a low-cost USB CO₂ monitor](https://hackaday.io/project/5301-reverse-engineering-a-low-cost-usb-co-monitor Reverse-Engineering a low-cost USB CO₂ monitor)
[Github heinemml/CO2Meter](https://github.com/heinemml/CO2Meter)
<a>タグについて調べてみた

#きっかけ
ここのところ、画面の実装をしていてaタグではまることが多くて辛いです。disableってつけて見た目もdisableっぽくなってるのになぜかクリックするとリンク先へ飛んでいけてしまうという事件やdownloadタグがブラウザによって挙動が変わるという事件を経て、きちんと調べようと誓いました。

#調査について
[こちら](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a)を参考にしました。参考というかこちらのページをまとめました。

#使用可能な属性
##グローバル属性
グローバル属性とは全てのHTML要素で共通の属性です。例えばhiddenとかidとか。個人的にはでしょうねって感想です。

##download属性
指定されたURLへ移動するのではなく、ダウンロードするようブラウザへ示す属性です。ファイルとかダウンロードさせたいときに便利じゃん!って飛びついたんですがこいつがなかなか曲者です。ブラウザで挙動が違います。まずInternet Explorerは未対応です。~~これだからIEはダメ。~~あと、edgeでもダウンロードができないというバグが報告されているようです。クロスブラウザ対応が必要な場合はこのタグ使わない方がいいかもしれません。

##href
ハイパーリンクのリンク対象をURLまたはURLフラグメントで表します。aタグはリンクさせたいときに使うんだよ、って研修で習った気がします。

##hreflang,ping,referrerpolicy
初めまして、不勉強で知りませんでした。ただ、使う機会はあまり多くない気がします。referrerpolicyは実験段階だから製品内では使うなとのことです。

##rel
対象オブジェクトとリンクオブジェクトとの関係を示す属性です。特にコメントはないです。

##target
リンク先を表示する場所を示す属性です。
_selfは遷移元のページに表示します。デフォルトです。
_blankは新しいブラウジングコンテキストに表示します。
_parentは親コンテキストに表示します
_topはトップレベルのコンテキストに表示します。

##type
リンク先のURLのMIMEタイプの形式を表すメディアタイプを指定します。純粋に助言的なもので組み込まれている機能はないそうなので、気にしなくていいと思います。

#感想
感想というよりはあれなんですが、**aタグにはdisable属性がない**んですよ。衝撃的でしたね。ぶっちゃけdisableがないと知ったのがこの記事を書こうと思った一番の動機です。aタグに活性・非活性つけたければJavaScriptを使いましょうってことなんでしょうね。
Linuxよく使うコマンド

- Linuxで（個人的にですが😣）使用頻度の高いコマンドをまとめます

###ファイルの操作

| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|ls [オプション][ファイル]|ファイル・ディレクトリの参照<br>　-a　隠しファイルの表示<br>　-l　Long形式で出力<br>　-t　最終修正時間で並び替え<br>　-r　逆順|
|cp [オプション] コピー元 コピー先|ファイルのコピー<br>　-i　処理を行うときに確認<br>　-R　ディレクトリを対象<br>　-p　元ファイルの情報を保持
|mv [オプション] 移動元 移動先|ファイルの移動<br>　-i　処理を行うときに確認<br>　-f　強制的に処理を実行|
|-rm [オプション] ファイル|ファイルの削除<br>　-i　処理を行うときに確認<br>　-f　強制的に処理を実行<br>　-r　ディレクトリを対象<br>　-v　削除したファイル名を表示|

###ディレクトリの操作
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|pwd|現在のディレクトリを表示|
|cd [ディレクトリ]|ディレクトリの変更|
|mkdir [オプション] ディレクトリ|ディレクトリの作成<br>　-p　指定されたディレクトリの上位ディレクトリも作成する|
|rmdir [オプション] ディレクトリ|ディレクトリの削除<br>　-p　空の上位ディレクトリも削除|

###ファイルの中身の操作
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|cat [オプション] ファイル|ファイルの中身の表示<br>　-n　行数を表示|
|less [オプション] ファイル|ページャ。jで下に移動。kで上に移動<br>qで終了<br>　-N　行番号を表示|
|head [オプション] ファイル|ファイルの先頭10行を表示|
|tail [オプション] ファイル|ファイルの末尾10行を表示<br>　-f　末尾をリアルタイムに更新|

###ファイルの検索
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|find パス -name ファイル名|ファイルの検索|
|which コマンド名|コマンドのパスを表示|
|grep [オプション] 検索条件 [ファイル名]|ファイルの中からデータを検索<br>　-a　文字列を検索パターンとして扱う<br>　-i　大文字小文字の区別を行わない<br>　-v　検索パターンとマッチしなかった行を選択|

###ファイルの比較
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|diff ファイル1 ファイル2|ファイルの比較|
|cmp ファイル1 ファイル2|ファイルの比較|

###OSの操作
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|uname [オプション]|システム情報の表示<br>　-m　コンピュータの種類を表示<br>　-n　ネットワークホスト名を表示<br>　-r　カーネルのリリース番号を表示<br>　-s　カーネルの名称を表示<br>　-a　全て表示|
|df [オプション]|ディスクの使用状況の表示<br>　-h　ディスクサイズを表示<br>　-T　ファイルシステムの表示|
|fdisk [オプション] [デバイスファイル]|パーティションの作成<br>　-l　パーティション情報を表示|
|mkfs [オプション] パーティション|パーティションのフォーマット<br>　-t　ファイルシステムの種類を指定<br>　-c　壊れている箇所の検知|
|vmstat [オプション] [時間間隔 [回数]]|メモリやCPUの負荷率や使用状況の表示<br>　-d　ディスクに関する統計を表示<br>　-p　指定したパーティションの統計を表示<br>　-S　指定した単位で容量を表示|
|jobs|ジョブの稼働状況の表示|
|kill ジョブ番号|プロセスおよびジョブの強制終了|

###ネットワーク関連
| コマンド       |説明＆オプション  |
|:-----------------|:------------------|
|ifconfig|TCP/IPのアドレス情報の表示|
|ping 宛先|宛先にパケットを送付|
|traceroute 宛先|宛先までのルートの表示|
|route|ルーティングテーブルの表示|
The Things Network




The Things Network にアクセス
[The Things Network](https://www.thethingsnetwork.org/)


![Kobito.xmwRo9.png](https://qiita-image-store.s3.amazonaws.com/0/49910/9d40e1d6-3b95-b32b-fea1-c1ebea4372d7.png "Kobito.xmwRo9.png")


## 日本語化

右上の自分のアイコンをクリック＞ドロップダウンからCONSOLEを選択する。
![スクリーンショット 2018-02-26 20.08.04.png](https://qiita-image-store.s3.amazonaws.com/0/49910/476d579a-c498-f985-9fca-222cbd013b85.png "スクリーンショット 2018-02-26 20.08.04.png")

再度、右上の自分のアイコンをクリック＞ドロップダウンからSETTINGを選択する。
![スクリーンショット 2018-02-26 20.10.19.png](https://qiita-image-store.s3.amazonaws.com/0/49910/5c37e751-46c7-6b6e-4898-680778abffb1.png "スクリーンショット 2018-02-26 20.10.19.png")


Handlerから日本に近そうなttn-handler-asia-seを選択する。
![Kobito.DcVCWa.png](https://qiita-image-store.s3.amazonaws.com/0/49910/17057699-4112-0c47-3903-b3297775c1c3.png "Kobito.DcVCWa.png")


Languageから日本を選択する。
![Kobito.2eiJwS.png](https://qiita-image-store.s3.amazonaws.com/0/49910/fce1ec21-9a7b-6707-c196-a23b93906060.png "Kobito.2eiJwS.png")

上記終わればSAVEボタンを押す。

メニュー等が日本語化される。



## ゲートウェイの登録

右上のメニューからゲートウェイを選択する。


ゲートウェイを登録をクリック

![Kobito.JOh8wQ.png](https://qiita-image-store.s3.amazonaws.com/0/49910/e173a7c4-a7f5-0aac-fb9a-161c3f27fa9a.png "Kobito.JOh8wQ.png")


![The Things Network Console.png](https://qiita-image-store.s3.amazonaws.com/0/49910/dcd416e0-bee3-f22d-6091-907b3ff9c733.png "The Things Network Console.png")


### ゲートウェイID


### 記述
ゲートウェイのメモ的記述

### 周波数計画
日本で使用可能な範囲、Asia 920-923MHzを選択します。

### Router
初期設定で選択したものがデフォルトで表示されてます。
そのままttn-router-asia-seのままで

### 場所
ゲートウェイとなる機器を配置する場所を地図から選択します。


### アンテナ代替え

インドアかアウトドアかを選択する。




## アプリケーション追加



### 

![Kobito.RnLrKq.png](https://qiita-image-store.s3.amazonaws.com/0/49910/ea90c1a8-5e96-859b-7620-3085550e379a.png "Kobito.RnLrKq.png")




## デバイスの登録

アプリケーション一覧から登録したアプリケーションを選択するとアプリケーションの情報が表示される。


![スクリーンショット 2018-02-26 20.39.25.png](https://qiita-image-store.s3.amazonaws.com/0/49910/b6a21ec4-b853-7b0e-3234-caed1301de14.png "スクリーンショット 2018-02-26 20.39.25.png")




![スクリーンショット 2018-02-26 20.41.23.png](https://qiita-image-store.s3.amazonaws.com/0/49910/cae17ab1-c7c7-80f2-0a32-7f4a72cb10a5.png "スクリーンショット 2018-02-26 20.41.23.png")


![スクリーンショット 2018-02-26 20.45.06.png](https://qiita-image-store.s3.amazonaws.com/0/49910/f5e79fbf-fd82-8d95-ae73-982dbf3b6452.png "スクリーンショット 2018-02-26 20.45.06.png")


### デバイスID
任意のデバイス名を入力する。

### デバイスEUI
入力欄の左側のボタンをクリックして自動生成を行う。
![スクリーンショット 2018-02-26 20.53.41.png](https://qiita-image-store.s3.amazonaws.com/0/49910/9039738e-d398-bd40-8d6c-2018fb98847d.png "スクリーンショット 2018-02-26 20.53.41.png")


### App Key
自動生成されるのでそのまま何もしない。

### App EUI
AppEUIが表示されている。


登録が終わるとデバイスが追加されている。以下のような画面が表示される。

![スクリーンショット 2018-02-26 20.55.48.png](https://qiita-image-store.s3.amazonaws.com/0/49910/5156ca01-0937-4701-e313-d43bff1ce627.png "スクリーンショット 2018-02-26 20.55.48.png")



### アクティベーション方法
アクティベーション方法は右上の設定ボタンを押す事が変更画面に切り替わり変更できる。
【やってみた】Azure Active DirectoryでTwitterのシングルサインオン(SSO)を実装してみる

##Azure Active Directoryを使った、Twitterのwebアプリへのシングルサインオンの実装方法をご紹介致します。

「いちいちアカウントとパスワード入れるのめんどくさいなぁ。」そんなことを思った経験はないでしょうか。まぁ最近だったらブラウザにパスワード記憶させればいいし、、、。まぁその通りです。ただし、ブラウザにパスワードを記憶させることができない環境（ゴリゴリにネットワークを閉じた社内の環境など）ではブラウザにパスワードを残すことはできません。そこで役に立つのがシングルサインオンです。

シングルサインオン（SSO）とは、1つのIDとパスワードで認証を行い、複数のWebサービスやクラウドサービスにアクセスする仕組みです。

実はこのシングルサインオンは別に新しいサービスではなく、十数年前からオンプレミス環境では構築されていました。最近はこのシングルサインオンという機能をクラウド上で実装し、オンプレにあるアプリだけではなく、SNSなどのネット上のサービスにも一つのIDでパスワード認証を行えるようになりました。

今回このブログでは、Azure Active DirectoryでTwitterのシングルサインオンを実装する方法をご紹介致します。


##シングルサインオンでTwitterにログインする方法
>①Azure Active Directoryにユーザの追加
>②AADの管理するアプリケーションにTwitterを追加
>③ユーザーの資格情報に、Twitterのログイン名とパスワードを追加
>④Azure AD アクセス パネルからAADに登録したログイン名でサインインし、Twitterにログインする

以上の方法を行い、実際にシングルサインオンが実現できるのか、実証実験をしてみます。

##実験①：規定ブラウザ(Chrome)でログインする
実験方法
Azure AD アクセス パネルに表示されているTwitterのロゴボタンをクリックすることで、シングルサインオンが可能かどうか実験

結果
Azure AD アクセス パネルにはサインインすることができ、正しくTwitterがアプリとして表示されていた。
![20180226_SSO実験_4.PNG](https://qiita-image-store.s3.amazonaws.com/0/149921/da722da9-7939-44a2-a832-bfbde07e65f5.png)

Twitterのロゴボタンをクリックしシングルサインオンができるか確認した所、ユーザーの資格情報に登録したTwitterの認証情報でログインされず、別のツイッターアカウントでログインされてしまった。

考察
ブラウザにパスワードが保存されログイン維持を実行している場合、シングルサインオンよりもブラウザに残っているキャッシュが優先されてしまうということが分かった。したがって次はプライベートモードでシングルサインオンを試みる。

##実験②：シークレットモードでログインしてみる
実験方法
規定ブラウザ（Chrome）をシークレットモードで起動し、Azure AD アクセス パネルからTwitterロゴをクリックしてシングルサインオンが可能かどうか実験

結果
シークレットモードでは、シングルサインオンに必要な拡張機能がインストールできず、シングルサインオンは失敗。
![20180226_SSO実験.PNG](https://qiita-image-store.s3.amazonaws.com/0/149921/8b776ba7-e849-0829-061e-519d701a7e9c.png)


考察
Chromeの拡張機能の一部はシークレットモードでは機能しないということが判明しました。したがってシングルサインオンをTwitterで実装するには、対象のwebサイトのパスワードが保存されていない、ブラウザを使用することが必要である。そこで、実験用のブラウザ（FireFox）をインストールして、実験してみる。

##実験③
新しくPCにインストールしたFirefoxで、実験①、②と同じ手順で実証実験を行う。

結果
成功！！
ユーザの資格情報に入力したツイッターアカウントにシングルサインインできました。
しかし、Twitterの仕様だと思うのですが、セキュリティのため、1回目にログインする際に登録した電話番号を入れなくてはいけませんでした。。（結局SSOできてないじゃん。笑）
![20180226_SSO実験_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/149921/5c1abb3b-076b-e566-ce00-74c142833994.png)


##まとめ
これまでオンプレミスで管理していたシングルサインオンですが、クラウドと統合したAAD環境を作ることで、多くのSNSにシングルサインオンできるということが分かりました。ただし一方で、セキュリティの観点から、初回ログイン時に電話番号を入力するなどの仕様もあり、IDとパスワードだけ知っていればログインするということはできない様です。まぁそれも踏まえ、ほんの数分でADの構築から、シングルサインオンを実現できるAzureは大変魅力的であると感じました。

##参考URL
Azure AD アクセス パネル
https://myapps.microsoft.com

開発者のための Azure Active Directory
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/active-directory-developers-guide

Azure Active Directoryで簡単認証～自前でユーザー管理しよう Nativeアプリ 前編～
https://blog.nextscape.net/archives/Date/2015/06/azuread05
Basic Git commands

#Basic Git commands


| Command          | Use               |
|:-----------------|:------------------|
| git clone URL    |Download a copy a remote repository |
| git init         |Convert current directory into a new Git repository |
| git status       |Get a status report your repository |
| git add --all    |Add all changed and new files to the staging area of your repository|
| git commit -m "message"|Commit all staged files to your repository|
| git log          |Review a repository's history|
| git log --oneline|View a condensed history of your project|
| git branch --list|List all local branches|
| git branch --all |List local and remove branches|
| git branch --remotes|List all remote branches|
| git checkout --track remote_name/branch|Create a copy of a remote branch for local use|
| git checkout branch| Switch to a different local branch |
|git checkout -b branch branch_parent|Create a new branch from a specified branch|
|git add filename(s)|Stage only the specified file so that it is ready to be committed|
|git add --patch filename|Stage only portions of a file so that they are ready to be commiitted|
|git reset HEAD filename|Remove proposed file changes from the staging area|
|git commit --amend|Update the previous commit with changes currently staged, and supply a new commit message|
|git show commit|Log details for a single commit|
|git tag tag commit|Add a tag to a commit object|
|git tag|List all tags|
|git show tag|Log detail for the commit where the tag was applied|
|git remote add remote_name URL|Create a new reference to a new remote repository|
|git push|Upload changes for the current branch to a remote repository|
|git remote --verbose|List the fetch and push URLs for all available remotes|
|git push --set-upstream remote_name branch_local branch_remote|Push a copy of your local branch to the remote server|
|git merge branch|Incorporate the commits currently stored in another branch into the current one|
|git push --delete remote_name branch_remote|Remove named branch from the remote server|
|git reset --hard HEAD -- filename|restore file|
|git reset --hard HEAD| restore in the previous commit|
Javaで三項演算子はどこまで許されるか


# はじめに

この記事ではJavaに限った話をします。

先日、以下の記事を書きました(タイトル変更してます)。

- [Javaではif (isAdmin == true)というコードを書いてはいけない - Qiita](https://qiita.com/ikemo/items/4f56a283f9e27cf98d81)

この記事で、以下のように三項演算子を良い例として挙げました。

```java
String userType = isAdmin ? "管理者" : "一般";
```

しかし、三項演算子は読みにくいという反応が結構ありました。あくまでシンプルな例として挙げたつもりだったのですが、説明不足だったので、別途記事を書きます。

**三項演算子を使っていいのは、単純なもののみ**に限られるのが自分の中での結論です。

# 三項演算子とは

三項演算子(ternary operator)は以下のような形をしています。

```
<条件式> ? <trueのときの値> : <falseのときの値>
```

どの書き方ならよいかの話をする前に、自分が「どこまでならよい」と感じているのか、その例を書きます。

```java
/*
 * 白(ほぼ問題なし)
 */
String userType = isAdmin ? "管理者" : "一般";

String userType = user.isAdmin() ? "管理者" : "一般";

UserType userType = user.isAdmin() ? UserType.ADMIN : UserType.NORMAL;

String userName = user.isAdmin() ? "管理者" : user.getName();

/*
 * 白に近いグレー
 */
return user.getType() == UserType.GUEST ? "ゲストユーザ" : user.getName();

/*
 * 黒に近いグレー
 */
String userName = user.getType() == UserType.GUEST ? "ゲストユーザ" : user.getName();

/*
 * 黒(アウト)
 */
String userName = user.getType() == UserType.GUEST ? "ゲスト" : user.getType() == UserType.ADMIN ? "管理者" : user.getName() + "さん";
```

# 何が基準か

三項演算子の定義に戻ります。

```
<条件式> ? <trueのときの値> : <falseのときの値>
```

先程の例で、どのようなパターンが良いのか、悪いのかは、以下のように分類できます。

- 白(ほぼ問題なし)
  - 条件式
    - boolean変数
    - booleanを返すメソッド
  - true/falseのときの値
    - 定数
    - enum
    - getterなど単純な呼び出し
- グレー
  - 条件式に `==` や `!=` での比較が入る
- 黒(アウト)
  - ネストしている
  - true/falseのときの値が、単純な呼び出し以外

三項演算子が嫌われがちなのは、どこまでが条件式なのか、どこまでがtrueのときの値なのか、頭の中で字句解析、文法解析するコストが高いからです。また、 `==` や `!=` での比較が入るとよくないのは、代入の `=` と見間違えて、一瞬混乱するからです。

なので、単純な書き方以外は避けるようにしています。

# どのように書くべきか

以下のように書くこともできますが、後ろ向きな解決案なので、自分は好きではありません。

```java
String userName; // ここでの初期化は無駄なのでしない

if (user.getType() == UserType.GUEST) {
    userName = "ゲスト";
} else if (user.userType() == UserType.ADMIN) {
    userName = "管理者";
} else {
    userName = user.getName() + "さん";
}
```

自分なら以下のように、メソッドを作ります。この場合はUserクラスのメソッドとして実装できますが。

なお、今回は元の条件式と合わせるためにif文にしましたが、enumの場合はswitch文を使うことが多いです。

```java
private String getName(User user) {
    if (user.getType() = UserType.GUEST) {
        return "ゲスト";
    } else if (user.getType() == UserType.ADMIN) {
        return "管理者";
    } else {
        return user.getName() + "さん";
    }
}

// 呼び出し元
String userName = getName(user);
```

# おわりに

自分が思っていたより、読みにくくなるパターンのほうが多かったです。三項演算子を禁止するのはやりすぎだと思いますが、単純なもの以外は使わないくらいでいいと思います。
Go言語の開発環境構築（Mac + SublimeText3）

## はじめに
自分がやった方法をメモしておく。環境は以下。

* macOS High Sierra version 10.13.3
* homebrew:1.5.4 

## Goのインストール
homebrewから素直に落とす。以上。

```sh
brew install go
```

## 初期設定

Goの作業場所として**`$GOPATH`**を設定する必要がある。
公式の標準としては`$HOME/go`らしいが、別にどこでもいい。

ただ、**途中で変えるのはあまり良くない**らしいので気をつける。

自分は標準で構わないのでPATHの設定をする。
bashを使ってる人は下記を`~/.bash_profile`に追記。

```sh
export GOPATH=${HOME}/go
export PATH=$GOPATH/bin:$PATH
```

ターミナルを再起動する。

## 作業ディレクトリの作成

Goのルールに従って標準のディレクトリを作成する。

```sh
mkdir $GOPATH
cd $GOPATH
mkdir src pkg bin
```

構造はこんな感じになる。

```
go
├── bin
├── pkg
└── src
```

それぞれのディレクトリの役割として、

* bin:実行ファイルを置く
* pkg:パッケージを置く
* src:ソースファイルを置く

となっている。

## とりあえず書いてみる

ひとまず動くか確認。src配下に`hello.go`を作成し、下記のコードを書く。

```golang
package main

import "fmt"

func main() {
	fmt.Printf("Hello, world.\n")
}
```

実行して動くか確認。Goの実行は`run`コマンドで行う。

```sh
cd $GOPATH/src
go run hello.go
```

`Hello, world.`が表示されたらおっけー。
このファイルはもういらないので消しておく。

## Sublime用プラグインの導入

下記記事の通りにやってみる。
[Sublime Text(Atom)で快適なgolangの開発環境](https://qiita.com/69guitar1015/items/f69d004976de4272b65f)

依存パッケージを`go get`でインストールする。
このコマンドはどこで実行しても良い。

```
go get golang.org/x/tools/cmd/goimports
go get github.com/golang/lint/golint
```

これらは`$GOPATH/src`配下に展開される。

次にSublime TextのPackage Controlで`GoSublime`をインストールする。
インストール後、Package Settings -> GoSublime -> Segttings-Userを開き、下記の設定をコピペで貼り付ける。

```json
{
  "fmt_cmd": ["goimports"],
  "comp_lint_enabled": false,
  "on_save": [
    {
      "cmd": "gs9o_open",
      "args": {
        "run": ["sh", "go build . errors && go vet && golint"],
        "focus_view": false
      }
    }]
}
```

コードを書いて保存するとエラーチェックとフォーマットが走る。
補完も一応効いてるっぽい。

## 開発の流れ
公式にGo言語における様々なルールが書いてあるので、ここを参考に。
[How to Write Go Code](https://golang.org/doc/code.html)

基本的に自分の開発ディレクトリはsrc配下にgithubのURLで作る。
例えばこんな感じ↓

```sh
mkdir -p $GOPATH/src/github.com/[githubのユーザ名]
```

なので、`hello`というプロジェクトで開発したいなーと思ったら、

```sh
mkdir -p $GOPATH/src/github.com/[githubのユーザ名]/hello
```

みたいな感じでディレクトリを切って開発していけばよい。
自分のGoディレクトリに移動するのがダルいので、以下のようにエイリアスを貼ると良いかも。

```sh
alias gogo="cd $GOPATH/src/github.com/[githubのユーザ名]"
```

Goのルールに従うと便利になる的な話が公式に書いてあるが、疲れたので次回。

## おわりに
続きをそのうち書くかもしれない。
Gitlab Pagesにgzip済ファイルをデプロイする

# はじめに
Gitlab Pagesに大きなファイルをデプロイしたい場合、基本的には設定の`Maximum size of pages`を大きくすれば問題ありません。ただそうは言ってもその分サーバの容量は食ってしまうので、数GBのコンテンツをデプロイしたいようなケースでなんとか圧縮できないかやってみました。

動作確認したバージョンはGitLab Community Edition 10.4.2になります。

# Support for statically compressed gzip content-encoding
この[MR](https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/25)の通り、ブラウザがgzip圧縮をサポートしている場合、Gitlab Pagesは事前にgzip圧縮されたファイルを返すことができます。
例えば

```
index.html
index.html.gz
```

という構成になっているとき、gzipサポートされたブラウザでアクセスすれば`index.html`ではなく`index.html.gz`が表示され、gzipがサポートされていなければ`index.html`が表示されます。
つまりgzipサポートされたブラウザからアクセスする限りにおいては`index.html`は空でもよい、ということになります。
ただし`index.html`が不要というわけではなく、存在しない場合は404エラーとなります。

# `.gitlab-ci.yml`

というわけで以下のような`.gitlab-ci.yml`でGitlab PagesをデプロイすればOKです。
`find ...`にてデプロイする全コンテンツをgzip圧縮し、ダミーの空ファイルを生成しています。

```yaml
pages:
  script:
    - mkdir -p public
    - touch public/large.html
    - find public/* -type f | xargs -I {} sh -c "gzip {}; touch {}"
  artifacts:
    paths:
      - public
```

単に空ファイルにするのではなくエラーメッセージ的なものを入れておいた方が後々混乱しにくいでしょう。
（下記の通り`curl`で取りに行くと空ファイルが返ってきてびっくりするかもしれません）

# `curl`/`wget`での取得
gzip非対応のブラウザというのはもはや想定しなくていい気がしますが、`curl`/`wget`はデフォルトではgzipを受け取りません。そのため以下のように`Accept-Encoding:gzip`ヘッダを明示的に付けるか直接`.gz`ファイルを取りに行く必要があります。

```shell-session
> wget --header="Accept-Encoding:gzip" -O index.html.gz http://.../index.html
> curl -H "Accept-Encoding:gzip" -o index.html.gz http://.../index.html
```

```shell-session
> wget -O index.html.gz http://.../index.html.gz
> curl -o index.html.gz http://.../index.html.gz
```
log4netログレベルによる出力状況

log4netを導入後、ログレベルの設定によってどのようにログが出るのか時々忘れることが分かったので備忘録として下記のように残した。

## ログレベルによるログの出力状況
|ログレベル |       出力されるログ | 
|:-----------------|------------------:|
| DEBUG             |              すべて| 
| INFO|            FATAL・ERROR・WARN・INFO|
| WARN|              WARN・ERROR・FATAL| 
| ERROR|                ERROR・FATAL|
| FATAL|                FATAL| 

今更なんですが、Traceログがlog4netにはないんですね。

## 参考資料
- [log4net で ログレベル を 動的に 取得、設定 する 方法
](https://garafu.blogspot.jp/2014/05/log4net_27.html)
- [ログレベル利用規則(log4net)](http://kurusugawa.jp/2009/04/24/log-level-rule/)
VBAを1週間使ってみて非常に使いづらかった点

# VBAでコードを書いてみて使いづらかった点

業務で最も使うといっても過言ではないエクセル。

そのエクセルを扱えるVBAはプログラマーから過小評価されている言語じゃないか！？

そんなことを思い、1週間ほど本気で学んでみました。
その結果, 評判通りVBAは非常に使いづらかったです。


以下、VBAの弱点を3点挙げます。

<h3>1.配列が扱いづらい</h3>
<p>
配列のインデックスが1から始まる。
Rangeのインデックスが1から始まる。
Pushが定義されてない。Pushするには都度配列の長さを拡張して再定義が必要。
Shift,UnShiftも定義されていない。</p>

<h3>2.引数に関数を受け取れない</h3>
<p>VBAでは引数に関数を受け取る事ができない。
VBAの配列にselectが無かったので定義しようとしたが、関数を渡せない事に気が付き断念。</p>

<h3>3.エラー処理が難しい</h3>
<p>Try catch finally の仕組みが存在せず、エラー時の処理が難しい。</p>

# 総評

綺麗なプログラムを書くにはなかなかハードルの高い言語だと思いました。

ただ汚くても動くものを作るには効果が高いので、
ちょろちょろっと扱えるようになるには便利だと思います。

# 追記
指摘いただいたので以下修正しました。
配列のインデックスが1から始まるは勘違いで、Rangeから取得した値を配列に格納した結果としてIndexが1からとなります。
AWS Lambdaてナニ？

# 1. AWS Lambdaとは
amazon aws上で提供されている、サーバーレスのAPI実行環境。
自前のサーバーをたてる必要なく、lambda上でコードが実行される。
awsの別のサービスのイベントを検知し、自動でコードを実行するといった、イベントの発生をトリガーとした運用を行える。

# 2. lambdaの特徴
   - インフラ周りの管理が不要
自身で一からサーバー環境を構築する必要が無い。
インフラ周りはすべてlambdaがハンドリングして管理するため、インフラ管理の工数も大幅に削減できる。
また、開発者がビジネスロジックの開発に集中できる利点が生まれる。

   - 実行環境のオートスケール
例えば、運用を続けるうちにリクエスト数が増大してきた場合、負荷に耐えうる最適なパフォーマンスにlambdaがオートスケールしてくれる。
サーバーリソースの管理も意識する必要がない。

   - ほぼ全てのAWSサービスに対するイベントハンドリング及び操作
lambdaの機能のみで、ほぼ全てのAWSサービス（イベントソース）からのイベントをキャッチし、対応する処理を実行できる。

# 3. lambdaの料金体系
・lambdaファンクションに対するリクエスト回数
・lambdaファンクションのメモリに応じた実行時間

上記二点に対して課金が発生する。
100万リクエスト辺り0.02ドル、1GBのファンクションを0.1秒実行で0.00001667ドルらしい。
無料利用枠は、月に100万リクエスト・40万GBのコンピューティング時間となっている。（1年経過後も継続）
https://aws.amazon.com/jp/lambda/pricing/

# 4. lambdaにおける開発
### 4.1 開発言語			
	・Node.js [Javascript] 		
	・Python		
	・Java [Java8互換]		
	・C# [.net core]		
			
	サードパーティーライブラリ等の組み込みも可能。		
			
### 4.2 開発環境			
lambdaが提供しているブラウザベースのコードエディタが利用可能。
オンプレ上で記述したテキストファイルをZIPに圧縮し、アップロードも可能。

# 5. lambdaの仕組み
lambdaファンクションと呼ばれる単位で実行される関数を作成する。
1ファンクション＝1機能が原則。

### 機能例.
・amazon s3にファイルが投入されたら、ファイルのメタデータを抜き出して加工する	
→ DBに格納し、ファイル検索のためのインデックスとしての活用を図る	
・s3に投入されたファイルを検知し、SNSと連携してファイルの追加を通知する
→ ユーザーに対して即座に通知ができる	

lambdaファンクションには、ファンクション毎に実行メモリ量を割り当てる。処理の複雑さ等によって割り当て量が柔軟に設定可能。
また、ファンクション毎のタイムアウト時間の設定も必要。
ファンクションに対して紐付けるawsサービスの指定も行う。(イベントソース)

イベントソースからは、発生したイベントの詳細をJSONとして送られる。
s3であれば、以下のような情報が含まれる。

・PUTされたバケット名
・PUTされたオブジェクトの詳細(キー・サイズ・タグなど)
・イベント発生時刻  etc...

また、ファンクション毎にIAMロールを指定し、イベントソースに対する詳細なアクセス権の設定が可能。
lambdaファンクションそのものの実行モニタリングも自動で行われる。

・リクエスト数
・遅延率
・可用性・エラー率
(CloudWatchへ保存され、CloudWatchのコンソール上で閲覧可能)

# 6. ユーザーアプリケーションからの利用
awsのサービスに対する処理だけでなく、独自のユーザーアプリケーションからの利用も可能。
lambda経由でs3に対してファイルを投入する、lambda経由でec2に対する処理を実行する、
lambda経由でs3のファイル情報を取得するなど、
awsの各種サービスに対する処理をlambdaに対するリクエストのみで完結させられる点がメリット。（SDK等使わない）

尚、上記の使い方の場合、lambdaに加えてamazon api gatewayを併せて利用する必要がある。
(AWS上のコード等を、RESTAPIとして外部に公開してアクセスできるようにするサービス）
![fsathon-lambda01.png](https://qiita-image-store.s3.amazonaws.com/0/239292/2347b085-bd0a-5771-3d31-6dda489519af.png)
windows10でtensorflow-gpuをインストール(Anaconda環境)

#はじめに
　今使っているパソコンはryzen7というCPUを使っていてグラフィック機能が付いていないため、GTX1060 3gbを流用していました。
　このGPUまあまあ有能であり、機械学習は自分の専門分野(化学)に役立つのでは？？？と思っていたことと、GTX1060はCUDAに対応しているみたいなのでとりあえず環境構築をしてみることにしました。

#パソコン環境
Windows10
Ubuntu16.04 （デュアルブート）
gtx1060 3gb
ryzen7 1700

#Tensorflowのwindowsサポート
　Tensorflowは2016/9/26からwindowsのサポートを始めたらしく、tensorflowはlinuxで環境構築する記事が多く見られます。https://developers.googleblog.com/2016/11/tensorflow-0-12-adds-support-for-windows.html
自分もそれにならってUbuntuを入れてみたのですが、まあよくわからない...そこで今回はwindows10に導入することにしました

#Anacondaでtensorflow-gpu
　機械学習を勉強するにつれ、pythonで必要なモジュールが多すぎて手に負えなくなってきたためAnacondaを利用し始めることにしました。そこで、windows10でAnacondaのプロンプトを用いてtensorflow-gpuを導入しているサイトを探したら以下のサイトを見つけました。

[Windows 10のAnaconda環境でtensorflow-gpuをインストールする手順とか](http://suechan.hateblo.jp/entry/2017/12/23/235835)

自分と環境がそっくりなことと、tensorflow-gpuだけでなくtensorflowも入れて、GPUとCPUで処理して実際に処理時間を比較しているのでとても分かりやすかったです。また、バージョンも最新に更新してあるのでこの記事でほとんど済みました。

ここで、最後に仮想環境をpython2.7や3.5も追加しておくと、自分のような初心者でサイトや本に書いてあることがよくわかっていなくて、コードをコピペして動かしてみたいなどと思った時に便利です。

```
conda create -n py35 python=3.5
```

または

```
conda create -n py27 python=2.7
```

で作成できます。

---
作った仮想環境は

```
activate py35
```

でアクティベートでき、

```python
conda info -e
```

で、確認できます。また、削除は

```
conda remove -n py35 --all
```

で、できるのでとりあえず試してみるといいと思います。

https://qiita.com/supersaiakujin/items/50def6f33b79f9a61b18
正則表現 括弧でグループ

置換前
abc12fa
abc23fb
abc45fc
abc67fd
abc78fe
abc32ff

以下に変更したい（fの前gを追加したい）
abc12gfa
abc23gfb
abc45gfc
abc67gfd
abc78gfe
abc32gff


括弧でグループして、置換後は

$1→一番目の括弧

$2→二番目の括弧

$3→三番目の括弧（置換後に$3がなければ、置換対象、下図ようにgfに置換）

$4→四番目の括弧


![image](https://qiita-image-store.s3.amazonaws.com/0/197416/076bd004-c2a4-031c-4032-034f634e7bdd.png)
CentOS 7 ネットワーク設定

# 動作確認環境
- 仮想環境 VMware Workstation Player 14.1.1
- OS Windows 10 Pro 64bit

#仮想環境
- OS CentOS 7.4 (1708) minimalインストール
- メモリ 2GB
- HDD 250GB

# ネットワーク設定
**自動接続**
OS起動時に自動的にネットワークに接続するため、コマンドを実行する。

````
nmcli con mod eth0 connection.autoconnect yes
```` 

**IPアドレスをDHCP設定する場合**

````
nmcli con mod eth0 ipv4.method auto
````

**IPアドレスを手動設定する場合**

- IPアドレス 192.168.1.10
- ゲートウェイ 192.168.1.1
- DNS 8.8.8.8

````
nmcli con mod eth0 ipv4.method manual ipv4.addresses 192.168.1.10/24 ipv4.gateway 192.168.1.1 ipv4.dns 8.8.8.8
````

手動設定時には、DHCPでのDNSサーバの設定を無効にするため、コマンドを実行する。

````
nmcli con mod eth0 ipv4.ignore-auto-dns yes
````
`NetworkManager`を再起動する。

````
systemctl restart NetworkManager
````

DNSサーバが設定されていることを、`resolv.conf`ファイルで確認する。

````
vi /etc/resolv.conf
````

```` /etc/resolv.conf
# Generated by NetworkManager
nameserver 8.8.8.8
````

**ホストの名前を変更する**
以下のコマンドでホストの名前を変更する。

````
nmcli general hostname [ホスト名]
````

`systemd-hostnamed`を再起動して適用させる。

````
systemctl restart systemd-hostnamed
````

---
[目次](https://qiita.com/knutpb1205/items/3ece0cab588afdb13f02)
WIP：Ansibleで勉強会用の環境を構築する方法備忘録

勉強会を開催するにあたってどうしても事前の環境構築などが必要になり、ansibleを使ってみようと。

どこぞの環境に接続して実行するわけではなくローカルでの実行を前提にしています。

# モジュールについて

ansibleでは各モジュールというものが提供されているらしい

例えばpostgresqlを扱うための`postgresql_db`モジュールなど

# ダウンタイムについて
taskで再起動する場合は当然ながらダウンタイムがある

# 自分自身を指定する方
オプションで`--connection=local`を指定する

```
$ ansible-playbook --connection=local main.yml
```

# sudoが必要なtaskを実行する方法

* `become`を記述する。`sudo`は非推奨になったらしいので使わない
* オプションに`--ask-become-pass`を使うとパスワードをきいてくる。事前に登録することもできるらしく理想的だけど暗号化とかめんどくさそうなのでとりあえず今回はこれで

```yml:main.yml
---
- hosts: localhost
  become: yes
```

```
$ ansible-playbook main.yml --connection=local --ask-become-pass
```



# 参考にしたWebページ

* [Qiita - Ansible ～shellモジュール～](https://qiita.com/moiwasaki/items/bc3ce9da7f4aa2a80d61)
Spring Data JPA と QueryDSL を組み合わせた際の LocalDate 型のパラメーターの表示のされ方について

# 概要

QueryDSL を使用してクエリを構築していますが、先日 IntelliJ IDEA 上に表示されたコンソールをみてびっくりしたので備忘録です。
なんと、LocalDate 型 のプロパティについては、UTC+9 にてパラメーターがバインドされているのです。
通常の、Spring Data JPA にて生成されたクエリについては、特段問題なくパラメーターがバインドされているようでした。

* コンソール上の SQL

```.sql

select 
  o.id,
  o.order_id
  o.purchase_date 
from customer_order o
where o.purchase_date = '11/01/2020 09:00:00.000' 
  and o.order_id = 1
```

# 動作について

上記は (おそらく SpyLogger が) コンソール上で表示している値が UTC+9 で表示されているだけのようでした。
tail にて mysql 上のログを監視した結果、日付がバインドされていない動作になっておりました。

* MySQL 上で記録されたログ

```.sql
select 
  o.id,
  o.order_id, 
  o.purchase_date
from customer_order o
where o.purchase_date = '2020-11-01' 
and o.order_id = 1
```

## 補足

上記のコンソール上の SQL において、パラメーターは MM/dd/yyyy HH:00:00.000 の形式にて出力されています。(11/01/2020 09:00:00.000)
Spring Data JPA にて生成されるクエリの場合においても、コンソール上に出力される日付の形式は、上記の形式で yyyy-MM-dd HH:00:00 にて出力されませんでした。

なお、QueryDSL については、Spring Data JPA とは異なる JSR310 のパーサーを独自で実装していますので、パラメータには時刻秒が付加されていないようでした。

```JSR310LocalDateType.java
package com.querydsl.sql.types;

public class JSR310LocalDateType extends AbstractJSR310DateTimeType<LocalDate> {

    public JSR310LocalDateType() {
        super(Types.DATE);
    }

    public JSR310LocalDateType(int type) {
        super(type);
    }

    @Override
    public void setValue(PreparedStatement st, int startIndex, LocalDate value) throws SQLException {
        Instant i = value.atStartOfDay(ZoneOffset.UTC).toInstant();
        st.setDate(startIndex, new Date(i.toEpochMilli()), utc());
    }
}
```

上記の実装になっているので、utc() メソッドと使用している JDBC のドライバ (PreparedStatement の実装) の相性が悪いのか、
と思いとても焦りました。

また、Spring Data JPA がクエリを構築する場合、規定のパーサでは、LocalDate 型についても、'2018-05-01 00:00:00'　と、LocalDateTime の形式でパラメーターがバインドされて SQL が実行されました。

* Spring Data JPA にてクエリが構築されて実行される SQL

```.sql

select 
  o.id,
  o.order_id
  o.purchase_date 
from customer_order o
where o.purchase_date = '2020-11-01 00:00:00' 
  and o.order_id = 1
```
Embulkの設定情報（環境変数版）

## 概要
Embulkで処理を作成する際、DB接続情報などの環境によって変更したい設定をどう定義すればいいか調べた内容をメモしておきます。

## 環境変数を利用する
Embulkの場合、環境変数が利用可能なので下記のように環境変数を使う方がシンプルな感じがします。

## ファイル構成
```:ファイル一覧
~/
| # 設定情報
├ secrets.sh
└ opt
  | # bundle plugin.
  ├ bundle
  │ ├ .bundle
  │ ├ .ruby-version
  │ ├ Gemfile
  │ ├ Gemfile.lock
  │ ├ embulk
  │ └ jruby
  |
  | # 処理内容
  └ users.yml.liquid
```

## 設定情報
設定ファイルを作ってみる。

```sh:~/secrets.sh
#!/bin/bash

## TreasureData Settings
export TREASURE_DATA_API_KEY=XXXXXXXXXXXXXXX

## MySQL Settings
export MYSQL_HOST=127.0.0.1
export MYSQL_USER=hoge
export MYSQL_PASSWORD=test

## PostgreSQL Settings
export POSTGRES_HOST=127.0.0.1
export POSTGRES_USER=hoge
export POSTGRES_PASSWORD=test
```

## 処理に組み込んでみる
実際に、上記設定を組み込んで実行してみる。

```liquid:~/opt/users.yml.liquid
in:
  type: mysql
  host: {{ env.MYSQL_HOST }}
  user: {{ env.MYSQL_USER }}
  password: {{ env.MYSQL_PASSWORD }}
  database: hoge_db
  query: |
    SELECT
      id, name, created_at
    FROM
      users
    WHERE
      deleted_at IS NULL
    LIMIT
      5
    ;
out:
  type: file
  path_prefix: "./users_"
  file_ext: csv
  formatter:
    type: csv
    delimiter: ","
    newline: CRLF
    newline_in_field: LF
    charset: UTF-8
    quote_policy: MINIMAL
    quote: '"'
    escape: "\\"
    null_string: "\\N"
    default_timezone: 'Asia/Tokyo'
```

## プレビュー
```sh:ターミナル
$ source ~/secrets.sh; embulk preview -b bundle users.yml.liquid
```

## 実行
```sh:ターミナル
$ source ~/secrets.sh; embulk run -b bundle users.yml.liquid
```

## .bashrcに定義する
.bashrcか.bash_profileに下記を追記しておけば、ログイン時に環境変数を反映可能。

```bash:~/.bashrc
# Embulk Settings.
source ~/secrets.sh
```

## まとめ
サブディレクトリを作成して、各処理をフォルダに分けても特に問題ないので、liquidより使いやすいかもしれませんが、secrets.shを実行せずに、うっかりembulkを実行してしまう場合もありそうですね。

## 参考サイト
- [Embulkにdotenvで設定した環境変数を使う](https://qiita.com/inouet/items/f79d6f99ec316e3b514b)
- [EmbulkでMySQLのデータをElasticsearch5に転送する](https://qiita.com/Esfahan/items/c2a22da5d57bfa1d4cc4)
- [シェル変数と環境変数の違いをコマンドラインで確認する](https://qiita.com/kure/items/f76d8242b97280a247a1)
- [コマンドでの環境変数の受け渡し](https://qiita.com/reflet/items/2caf9dbf0e3f775276ec)
openCVで読み込んだ画像をmatplotlibで表示する方法

# openCVで読み込んだ画像をmatplotlibで表示する方法
*先輩の写真を使って画像認識の勉強をしようとぽちぽちしていたらつまずいたところを備忘録として書いておきます。*



さて、opencvで読み込んだ画像はBGRフォーマットになっていますがmatplotlibではRGBフォーマットで読み込まれるためmatplotlibに渡す前にRGBに変更してあげる必要があります。

```python

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('./monkey.jpg')
```

 これはopencvで取り込んだ画像の１ピクセルにおける色を青、緑、赤の値で表しています。（BGR）

```python

plt.imshow(img)
plt.show()
```

![blue_monkey.png](https://qiita-image-store.s3.amazonaws.com/0/189118/ff56e970-cf01-02c1-be44-64a7e44bab94.png)

BGRの画像をRGBのmatplotlibで表示しようとしたので先輩の顔が真っ青になってしまいました。これではかわいそうです。

##RGBへの変換
先輩を元気にするために色を変換してあげましょう。

```python
#このcvtColorで変換ができます
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

plt.imshow(img)
plt.show()
```
![fine_monkey.png](https://qiita-image-store.s3.amazonaws.com/0/189118/ccc3363e-a716-85d1-f351-276a5a9b56d2.png)

これでやっと先輩が元気になりました！焼肉が美味しそうですね。

##参考
[[Python]PythonでOpenCVを使う (基本編)](https://qiita.com/supersaiakujin/items/54a4671142d80ca962ec)
[画像処理入門講座 : OpenCVとPythonで始める画像処理](http://postd.cc/image-processing-101/)
javascriptのspread operatorのいいサンプルを見つけた

いいサンプルを見つけた
https://daveceddia.com/immutable-updates-react-redux/

```js
// For arrays:
let nums = [1, 2, 3];
let newNums = [...nums]; // => [1, 2, 3]
nums === newNums // => false! not the same array

// For objects:
let person = {
  name: "Liz",
  age: 32
}
let newPerson = {...person};
person === newPerson // => false! not the same object

// Internals are left alone:
let company = {
  name: "Foo Corp",
  people: [
    {name: "Joe"},
    {name: "Alice"}
  ]
}
let newCompany = {...company};
newCompany === company // => false! not the same object
newCompany.people === company.people // => true!

let liz = {
  name: "Liz",
  age: 32,
  location: {
    city: "Portland",
    state: "Oregon"
  },
  pets: [
    {type: "cat", name: "Redux"}
  ]
}

// Make Liz one year older, while leaving everything
// else the same:
let olderLiz = {
  ...liz,
  age: 33
}
```
Qiitaの記事に動画を埋め込めないか色々試してみる

#名前の通り埋め込めないか色々試して見ます

####まずはTwitter

「ツイートをサイトに埋め込む」のコードをそのまま書いてみる

```html
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">て〜す〜と〜 <a href="https://t.co/eXXw5vwjlW">pic.twitter.com/eXXw5vwjlW</a></p>&mdash; 納豆うまい＠昼寝神 (@nattouumainemui) <a href="https://twitter.com/nattouumainemui/status/968060134713733120?ref_src=twsrc%5Etfw">2018年2月26日</a></blockquote>
+<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```
**結果**

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">て〜す〜と〜 <a href="https://t.co/eXXw5vwjlW">pic.twitter.com/eXXw5vwjlW</a></p>&mdash; 納豆うまい＠昼寝神 (@nattouumainemui) <a href="https://twitter.com/nattouumainemui/status/968060134713733120?ref_src=twsrc%5Etfw">2018年2月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

編集しているところから見ると↓こう

<img width="499" alt="スクリーンショット 2018-02-26 19.02.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/237205/05e03e52-8bd7-a207-93e3-c5b575f93e14.png">
プレビューがちょっと違う・・・

ちなみに画像なしのツイートだと


```html
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">て〜す〜と〜（２回目）</p>&mdash; 納豆うまい＠昼寝神 (@nattouumainemui) <a href="https://twitter.com/nattouumainemui/status/968062593435713541?ref_src=twsrc%5Etfw">2018年2月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```
**結果**
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">て〜す〜と〜（２回目）</p>&mdash; 納豆うまい＠昼寝神 (@nattouumainemui) <a href="https://twitter.com/nattouumainemui/status/968062593435713541?ref_src=twsrc%5Etfw">2018年2月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


####次にできたら嬉しいYoutube

共有>右下の埋め込むをそのまま書いてみた

```html
<iframe width="560" height="315" src="https://www.youtube.com/embed/pKV47FuePU0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
```

**結果**

<iframe width="560" height="315" src="https://www.youtube.com/embed/pKV47FuePU0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

あれ・・・何も表示されなかった・・・

####こうなったら直接動画をアップロード
右上にある「添付する画像を画像を選択またはドラッグ&ドロップ」
**結果**

`![undefined]()`

あっ・・・はい

#最後に
これで動画が埋め込めた、やったぜ！
ただ、Youtubeから簡単に埋め込めたらいいのになぁ・・・
~~Twitterのプレビューが違うのはどうにかしてほしい、焦る~~
Microsoft Translator テキスト API の使い方 (go)

Microsoft Translator テキスト API の使用例です。
日本語から、ドイツ語への翻訳です。

```go:translation.go
// ------------------------------------------------------------------
//
//	main_get_token.go
//
//					Feb/26/2018
//
// ------------------------------------------------------------------
package main
import (
	"fmt"
	"os"
	"log"
	"io/ioutil"
	"net/http"
)

// ------------------------------------------------------------------
func translate_proc(token string,text_in string) string {
	rvalue := ""

	url_bb := "https://api.microsofttranslator.com/v2/http.svc/Translate?text="

	url_bb += text_in + "&to=de" + "&category=generalnn"

	req, _ := http.NewRequest("GET", url_bb, nil)

	req.Header.Set("Authorization", "Bearer " + token)

	client := new(http.Client)
	resp, err := client.Do(req)


	if err != nil {
		log.Fatalln(err)
		fmt.Printf("%s", err)
		os.Exit(1) 
	} else {
		defer resp.Body.Close()
		contents, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
			}

		rvalue := string(contents)
		fmt.Printf("%s\n", rvalue)
		}

	return rvalue
}

// ------------------------------------------------------------------
func main() {
	fmt.Fprintf (os.Stderr,"*** 開始 ***\n")

	token := get_token_proc ()

//	fmt.Fprintf(os.Stderr,"%s\n", token)

	text_in := "今日はいい天気です。"
	fmt.Printf ("%s\n",text_in)

	result := translate_proc(token,text_in)
	fmt.Printf ("%s\n",result)

	fmt.Fprintf (os.Stderr,"*** 終了 ***\n")
}

// ------------------------------------------------------------------
```

```go:get_token.go
// ----------------------------------------------------------------
/*
	get_token.go

					Feb/26/2018
*/
// ----------------------------------------------------------------
package main
import (
	"fmt"
	"os"
	"log"
	"io/ioutil"
	"net/http"
)

// ----------------------------------------------------------------
func get_token_proc () string {

	token := ""

	key1 := "e968e25ffc2146f00000000000000aaa"
	url := "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Set("Ocp-Apim-Subscription-Key", key1)

	client := new(http.Client)
	resp, err := client.Do(req)

	if err != nil {
		log.Fatalln(err)
		fmt.Printf("%s", err)
		os.Exit(1) 
	} else {
		defer resp.Body.Close()
		contents, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("%s", err)
			os.Exit(1)
			}
		token = string(contents)
//		fmt.Printf("%s\n", token)

	}

	return token
}

// ----------------------------------------------------------------
```

```text:Makefile
translation: translation.go get_token.go
	go build translation.go get_token.go
clean:
	rm -f translation
```

python3 の例はこちら
[Microsoft Translator テキスト API の使い方 (python3)](https://qiita.com/ekzemplaro/items/23b82bdff02eda738f7a)
正規表現の検索文字列(memo)

| 書き方       |       意味 |
|:--------------|:---------|
|A+	|1個以上のA（可能な限り長く）
|A*	|0個以上のA（可能な限り長く）
|A+?	|1個以上のA（可能な限り短く）
|A*?	|0個以上のA（可能な限り短く）
|A?	|0または1個のA
|A{3}	|3個のA
|A{3,}	|3個以上のA
|A{3,5}	|3～5個のA
|A|B	|AまたはB
|ABC|DEF	|ABCまたはDEF
|[ABC]	|A,B,Cのいずれか1文字
|[A-C]	|A～Cのいずれか1文字
|[^ABC]	|A,B,C以外のいずれか1文字
|.	|任意の1文字
|.+	|任意の1以上の文字
|^A	|Aで始まる文字列
|A$	|Aで終わる文字列
|A.+B	|『A（任意の文字列）B』（可能な限り長く）
|A.+?B	|『A（任意の文字列）B』（可能な限り短く）
|A[^\/]+B|『A（『/』を含まない文字列）B』


元
https://crocro.com/write/manga_javascript/wiki.cgi?p=regexp