OmniAICreator/Qiita-1.07M huggingface dataset:
pyenv　の導入の巻

#目的
Pythonの2系と3系を使って開発を進めたい

#目標
pyenv を導入して、2系と3系を切り替えて使う
今回は、GCP CentOS7 にはデフォルトでpython2 系が入っているため、pyenv へ python 3 を導入する

#作業
##ライブラリの更新
`sudo yum -y update`

##git と pyenv 前提ソフトの導入
`sudo yum -y install gcc wget curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf bzip2 bzip2-devel libbz2-dev openssl openssl-devel readline readline-devel`


##git を導入
下のサイトを参照
https://qiita.com/hatakkkk/items/c06dd493d0fc96f7468d

```ruby:これを入力するんだ
wget https://www.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz

tar vfx git-2.9.5.tar.gz

cd git-2.9.5

make configure

./configure --prefix=/usr

make all

sudo make install

```


##pyenv の導入
https://github.com/pyenv/pyenv-installer


```ruby:下のコマンドを入力するんだ
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
source .bash_profile
```

導入できたか確認する
`pyenv -v`
>pyenv 1.2.6

pyenv を更新する
`pyenv update`

一旦、VM の再起動
`sodo reboot`

python の導入可能ver を確認する
`pyenv install --list`

今回は、3.6.6 を導入
`pyenv install 3.6.6`

pyenv のリフレッシュ
`pyenv rehash`

現行のpython ver を表示
`python --version`
>Python 2.7.5

3.代を使いたいので、導入した　python 3.6.6 へ変更する。
`pyenv global 3.6.6`

再度、python ver を確認
`python --version`
>Python 3.6.6

これで完了！
お疲れ様でした。

#Tips

warning 出た
>
Downloading Python-3.6.6.tar.xz...
-> https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz
Installing Python-3.6.6...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
WARNING: The Python sqlite3 extension was not compiled. Missing the SQLite3 lib?
Installed Python-3.6.6 to /home/h1d34h4t/.pyenv/versions/3.6.6


必要なものをインストールして完了。
`sudo yum -y install bzip2 bzip2-devel libbz2-dev openssl openssl-devel readline readline-devel`
ディレクトリ(フォルダ)を作成するプログラム

#開発環境
OS : Microsoft Windows10 (64bit)
IDE : Microsoft Visual Studio 2012

#ディレクトリ(フォルダ)を作成するプログラム
初めに新しいプロジェクトからC#を選択をして、コンソールアプリケーションを選択します。
次にプロジェクトの名前を入力します。今回はtest5と言う名前にして、右下のOKをクリックします。
↓画像の用になります。
![今日の日付２.png](https://qiita-image-store.s3.amazonaws.com/0/249265/3d787a7e-14e0-000a-f55f-5a49e0995ca6.png)

#ソースコード
```

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test5
{
    class Program
    {
        static void Main()
        {
            string path = @"C:\Users\honka-1\Desktop\new\test";

            Directory.CreateDirectory(path);

            Console.WriteLine("フォルダを作成しました");
            Console.ReadKey();
        }
    }
}
```
実行結果↓
![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/249265/a5aa993b-060a-3ad2-1d5d-c655d9a61c2b.png)
これだけだと本当にファイルが作られてかわからないので、実際ファイルを作ったファイル名かパスで確認で、検索がめんどくさい場合は次に書くソースを実行してもらうと確認出来ます。

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = @"C:\Users\honka-1\Desktop\new\test";

            if (Directory.Exists(path))
            {
                Console.WriteLine("存在します");
            }
            else
            {
                Console.WriteLine("存在しません");
            }

            Console.ReadKey();
        }
    }
}

```
↓実行結果
![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/249265/055b053f-c30f-7f31-73e3-e6b42d868cf1.png)
実行結果みてもらうとファイルきちんとあれば画像のようになります。
ファイル作成指定ソースの場所がstring path = @"C:\Users\honka-1\Desktop\new\test";この場所になります。
\の最後の場所でファイル名を決めます。
AzureでMeCab×Python

https://akamist.com/blog/archives/2376 をAzure用に焼きなおしたような記事です

# やること
* AzureでMeCab突っ込んでPythonからつかえるようにする
* MeCabにユーザ辞書を食わせる

# MeCabインストール
```bash
sudo apt install aptitude
sudo aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
pip install mecab-python3
```

# ユーザ辞書インストール
ここでは，mecab-ipadic-NEologdというのをつかいます．新語に強いらしい．
まずは，https://github.com/neologd/mecab-ipadic-neologd/tree/master/seedにアクセス．
ここで，mecab-user-dict-seed.(8ケタの日付).csv.xzとなっているファイルがあるはずです．これをつかいます．

```bash
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
xz -dkv mecab-ipadic-neologd/seed/mecab-user-dict-seed.(8ケタの日付).csv.xz
/usr/lib/mecab/mecab-dict-index -d /usr/share/mecab/dic/ipadic -u mecab-user-dict-seed.20180709.dic -f utf-8 -t utf-8 mecab-ipadic-neologd/seed/mecab-user-dict-seed.(8ケタの日付).csv
sudo cp -p ./mecab-user-dict-seed.(8ケタの日付).dic /usr/share/mecab/dic/
```


これでMeCabがつかえるはずです．
DatadogでRDS(Oracle)のテーブルスペースを監視するには

#やりたい事
DatadogでRDS(Oracle)のテーブルスペースを監視したい！（タイトルのまんま）

#やってみた環境
EC2 (Amazon Linux AMI 2018.03.0)
RDS (Oracle Standard Edition Two 12.1.0.2.v11)

#やってみた大まかな流れ
- EC2へDatadog Agentをインストール
- EC2へOracle Instant Clientをインストール
- Oracle Instant Clientの設定
- RDSへDatadog用（メトリクス取得用）のユーザー作成と権限を付与
- Datadog Agentのconfigファイルを作成

#つまづいたところ
基本的な手順は[公式サイト](https://docs.datadoghq.com/integrations/oracle/)に掲載されているのでその内容通りに進めていったところ、
監視用ユーザーに権限を付与するところでエラーとなりどうやってメトリクスを取得できるようにするかハマりました.....

####エラーが発生したところ
```
GRANT SELECT ON gv_$sysmetric TO datadog;
```
※監視用に作成したユーザー名が「datadog」

#解決した方法
とりあえず監視用ユーザーが動的パフォーマンスビュー（V$SYSMETRICなど）を
参照できる用になればいけるはず！ということで以下の権限付与を実行し実現しました。

####動的パフォーマンスビュー参照権限を付与したコマンド
```
GRANT SELECT_CATALOG_ROLE TO datadog;
```

上記の大まか流れをもう少し詳しく記述した手順が以下の手順となります。
参考になれば幸いです (・∀・)


#設定手順
##EC2へDatadog Agentをインストール
Datadogの公式サイトからAmazon Linuxへのインストールコマンドを取得して実行します。
（DD_API_KEY=~~~~~~~~~ ってコマンド）

##EC2へOracle Instant Clientをインストール　[(参考サイト)](https://dev.classmethod.jp/cloud/aws/install-oracle-instant-client-into-amazon-linux/)
Oracle Instant Clientのrpmをサイトからダウンロードします。
今回ダウンロードしたのは以下の2ファイル。
- oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
- oracle-instantclient12.1-sqlplus-12.1.0.2.0-1.x86_64.rpm

##ダウンロードしたrpmファイルをEC2へアップロードします。
```
scp -i ~/<pemファイル保存場所パス>/<pemファイル名> ~/<rpmファイル保存場所パス>/oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm ec2-user@<EC2 IP address>:<EC2の保存先パス>
scp -i ~/<pemファイル保存場所パス>/<pemファイル名> ~/<rpmファイル保存場所パス>/oracle-instantclient12.1-sqlplus-12.1.0.2.0-1.x86_64.rpm ec2-user@<EC2 IP address>:<EC2の保存先パス>
```

##rpmファイルをインストールします。
```
yum install oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm 
yum install oracle-instantclient12.1-sqlplus-12.1.0.2.0-1.x86_64.rpm
```

##Oracle Instant Clientの設定
```
sh -c "echo /usr/lib/oracle/12.1/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
```

##RDSへDatadog用（メトリクス取得用）のユーザー作成と権限を付与
###RDSへ接続
```
sqlplus64 '<user name>@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<RDSエンドポイント>) (PORT=1521))(CONNECT_DATA=(SID=ORCL)))'
```
※SIDはデフォルト値で作成した場合のものです

###ユーザー作成
```
CREATE USER <user name> IDENTIFIED BY <password>;
```

###権限付与
```
GRANT CONNECT TO <user name>;
GRANT SELECT ON sys.dba_data_files TO <user name>;
GRANT SELECT_CATALOG_ROLE TO <user name>;
```

##監視の設定
テーブルスペースのメトリクスが取れるようになっているのでDatadogで監視設定をして完！

最後まで読んで頂きありがとうございました。　(・ω・)ノシ
チョイ技(その他)

#目的
・ちょっとした技を記載
・カテゴリーごとに記載していく

##Excel
###テキストの文字列(箇条書き)を結合したセルに貼り付ける方法
1. 箇条書きのテキストをコピーする
2. 結合していないセルに貼り付ける(テキストのみ保持)
3. 貼り付けたセルをコピー
4. 貼り付けたいセルの頭で右クリック
5. 貼り付けのオプション(数式)を選択
6. END

###ENDモードというかっこいいものを見つけた。
キーボードのEndボタンを押すと件のENDモードというものになる。
機能としては。十字方向キーを押すと【Ctrl + 十字方向】と同じ挙動をするとのこと。
一回押すと元に戻るため使いづらい。

##Thunderbird
###容量確保術
 
* 原因
アドレスのほうにあるフォルダはサーバーを使用しているようなので容量が少ない。

* 対策
ローカルフォルダのほうにそっくりそのままファイルを作って移動。

* 注意
試してないのでわからないが、ローカルファイルに入れたものは同期できないと思います。
LINE の Messaging API アプリで通知対象のユーザーを追加するには？

# 前置き
Node.js + Express ベース
チュートリアルなど記事で既出ではあるが、ピンポイントにユーザー追加したい場合のTips

# LINE のプッシュ通知のユーザーを追加するには
今の所、Webhookで取れるイベントオブジェクトからuserIdを取るしかない気がする

# userIdを取得して使えるようになるまでの流れ
1. Webhookアプリを用意する
1. アプリケーションを公開する(Heroku, IBM Cloudなど)
1. アプリケーションのURLをLINEのチャネルページのWebhookに登録する（この時、接続確認ボタンでWebhookが使えることを確認すること）
1. 以下のSnippetの場合は、コンソールログに吐き出されるので、idを通知先に加えておく

# Snippet

```js
// app.js

// LINE から来たEvent オブジェクトをハンドリングし、
// 中にあるidを抜き取る
function handleWebhookEvent(event) {
// ユーザーがbotをフォローしたタイミングでこのifに入る
    if( event.type === 'follow') {
      console.log('[Follow]: ', event.source.userId);
    }
    return Promise.resolve(null);
}

function webhook(req, res, next) {
  console.log("Received Event from LINE");
  Promise.all(req.body.events.map(handleWebhookEvent))
  .then((result) => res.json(result))
  .catch((err) => {
    console.error(err);
    res.status(500).end();
  });
}

app.post('/callback', webhook);
```
# 補足
- 今回はFollowのイベントのみ取っているが、メッセージ投稿などのイベントでも取れるので、もうフォローした後でも取得は可能
- Webhookアプリと通知アプリが一体化している場合、userIdの配列を用意し、取れたidがもしリストに入っていなければ、追加するといった実装がいいだろう
- Webhookアプリと通知アプリが別れている場合、通知アプリの方でRESTのAPIを用意し、Webhookでid取れた時点でそのAPIをコールする形がいいかもしれない
- クラウドサービス上にアプリをデプロイする手順は参考Linkにて

# 参考Link
[Herokuでサンプルボットを作成する](https://github.com/line/line-bot-sdk-nodejs/tree/master/examples/echo-bot)
[IBM Cloud(旧Bluemix)にExpressをデプロイする方法](https://qiita.com/ys22_/items/d34bf16593f08747e110)
GCP に git インストール　の巻

#目的
git を導入して、開発を高速化する

#目標
まっさらの環境へgit を導入する
git のver を表示する

#作業

```ruby:これを入力するんだ
sudo yum -y install gcc wget curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker autoconf

wget https://www.kernel.org/pub/software/scm/git/git-2.9.5.tar.gz

tar vfx git-2.9.5.tar.gz

cd git-2.9.5

make configure

./configure --prefix=/usr

make all

sudo make install

```

最後にバージョンが出力されるか確認する
`git --version`
>git version 2.9.5

お疲れ様です。
【Swift4】UIViewControllerで横スライドのアニメーション遷移（オリジナルアニメーション）

下記リンクを参考に実装していてちょっとハマったので備忘録として残しておきます。

[UIViewControllerAnimatedTransitioningを使って画面遷移アニメーションを作る](http://qiita.com/kitoko552/items/4c0e411ff6224090db87)


実装内容はリンクのものを参考にしています。
が、自作アニメーションをうまく連携してくれない。

なんでだ。。。


答えはUIViewControllerTransitioningDelegateプロトコルの該当メソッドがオプショナルになっており、実装しろエラーが発生しないため検知するのが遅くなった。という状況でした。

下記に修正版を貼り付けておきます。

リンク元

```SecondViewController.swift
...

// MARK: - UIViewControllerTransitioningDelegate

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        kAnimator.presenting = true // 遷移してくるときにtrueにする

        return kAnimator
    }

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        kAnimator.presenting = false // 遷移元に戻るときにfalseにする

        return kAnimator
    }
}
```


修正版

``` SecondViewController.swift
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        kAnimator.presenting = true // 遷移してくるときにtrueにする
        // この画面に遷移してくるときに呼ばれるメソッド
        return kAnimator
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        kAnimator.presenting = false // 遷移元に戻るときにfalseにする
        // この画面から遷移元に戻るときに呼ばれるメソッド
        return kAnimator
    }
```


プロトコルを実装する際は定義情報を確認してメソッドにあった実装を心がけよう。うん。
【Lua】覚書 Serial Debugger/Socket Debugger向けLua script

久々にSerial Debugger/Socket Debuggerを使いました。
ちょっとしたプロトコルを実装したかったのでLua scriptを書きました。
SerialDebugger-v1_18B
SocketDebuggerFree-v1_17
ではLua 5.1が使えるようです。

覚書。

##配列ではなくテーブル
Luaには配列がありません。テーブルを使います。
テーブルというくらいなんで名前でアクセスしたりいろいろ出来るようです。
Serial Debugger/Socket Debuggerで使うコレクションは単純な配列のほうが扱いやすいのですが。

高機能と思いきやテーブルの結合が出来ません。
単純にはforでぶん回して追加していくみたいです。



```lua

--空のテーブルを割り当て
table = {}

--要素の割り当て
table[1] = 1

--末尾に要素を追加
--#tableは table.lengthみたいなものらしい
table[#table + 1] = 2

--初期値で宣言したりもできる
table2 = { 1, 2, 3}

--table と table2の結合を単純にやるとこんな感じ
for key = 1, #table2 do
    table[#table + 1] = table2[key]
end 

```

正にやりたかった 「..」 でのテーブル結合はここで紹介されています。
http://hevohevo.hatenablog.com/entry/2014/02/03/214843

##チェックサム計算

```lua

--byte配列を走査してチェックサムを付加して返す
function SetChecksum(a)

    chk_sum = 0
    --テーブルの開始インデックスは1です
    --#(テーブル変数)で要素数を取得できます
    for key = 1,#a do
        --チェックサム計算
        chk_sum = chk_sum + hoge(a[key])
        key = key + 1
    end
    --要素の追加は追加したいインデックスに値を詰めるだけ
    --テーブル末尾への追加は↓でOK
    a[#a+1] = GetChecksum(chk_sum)

    return a
end

```

##現在の日付文字列の取得 (秒まで)
日付を取得する王道はos.dateの様です。

```
    datetable = os.date("*t")
    datestr = string.format("%04d",datetable["year"]) 
        .. string.format("%02d",datetable["month"])
        .. string.format("%02d",datetable["day"])
        .. string.format("%02d",datetable["hour"])
        .. string.format("%02d",datetable["min"])
        .. string.format("%02d",datetable["sec"])
```

##ミリ秒を測る

os.date()では秒単位までしか取れません。
Serial Debugger/Socket Debuggerで時間を測るようなときはミリ秒単位で取れないと意味無いケースが多いと思います。
時間を計るだけなら以下でミリ秒まで計れます。単位は秒なので0.001刻みです。

```lua

starttime = os.clock()
--何か処理
elapsedtime = os.clock() - starttime

```

##ASCII文字列とbyte配列の相互変換

```lua

function ConvertStringToByteArray(data)
    t = {}
    for i=1, string.len(data) do
       t[i] = data:byte(i)
    end
    return t
end

function ConvertByteArrayToString(data)
    rtnStr = ""
    for key = 1, #data do
        rtnStr = rtnStr .. string.char(data[key]) 
    end
    return rtnStr
end
```
AWS CloudFrontのアクセスログを確認する

S3にログファイルを保存し、Athenaで検索します。

## S3にログ用bucketを用意する

ログファイルを保存するbucketを作成します。
ここでは`test-logs`とします。
さらにこのbucketの中に、`test1`というフォルダを作って、ここに保存することにします。

## CloudFrontの設定でログ出力をOnにする

ログを出したいCloudFrontのGeneralタブでEditボタンを押し、以下のように設定します。

| 項目 | 値 |
|:---|:---|
| Logging         | On |
| Bucket for Logs | test-logs.s3.amazonaws.com(選択肢に出るはず) |
| Log Prefix | test1/ |

SaveするとS3の該当フォルダにログファイルが保存され始めます。

## Athenaで見る

ログファイルは複数ファイルに分かれ、gzで圧縮されているので、ダウンロードして見るのはなかなかめんどうなので、Athenaでテーブルを作って見てみます。

クエリエディタでクエリを書くところに以下を書き、実行します。
(下から2行目の`LOCATION`にログが保存されている場所を書きます。)

```
CREATE EXTERNAL TABLE IF NOT EXISTS default.cloudfront_logs (
  `date` DATE,
  time STRING,
  location STRING,
  bytes BIGINT,
  requestip STRING,
  method STRING,
  host STRING,
  uri STRING,
  status INT,
  referrer STRING,
  useragent STRING,
  querystring STRING,
  cookie STRING,
  resulttype STRING,
  requestid STRING,
  hostheader STRING,
  requestprotocol STRING,
  requestbytes BIGINT,
  timetaken FLOAT,
  xforwardedfor STRING,
  sslprotocol STRING,
  sslcipher STRING,
  responseresulttype STRING,
  httpversion STRING,
  filestatus STRING,
  encryptedfields INT
)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t'
LOCATION 's3://test-logs/test1/'
TBLPROPERTIES ( 'skip.header.line.count'='2' )
```

これでdefaultデータベースにcloudfront_logsというテーブルができたので、あとはSQLで好きなようにSELECTできます。
例えば

```
SELECT requestip, COUNT(*) AS num FROM cloudfront_logs WHERE uri LIKE '/contents/hoge/%' GROUP BY requestip ORDER BY requestip
```
などなど。

Athenaの料金は実行するクエリに対して発生し、『スキャンされたデータ 1 TB あたり 5 USD』ということなので、ログが大量になったら少し心配ですが、ちょっとログ出して確認したい時とかにはいいのではと思います。

### 参考
[アクセスログの設定および使用](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html)
[Amazon CloudFront ログのクエリ](https://docs.aws.amazon.com/ja_jp/athena/latest/ug/cloudfront-logs.html)
[料金](https://aws.amazon.com/jp/athena/pricing/)
ofxHttpUtilsでAPIを叩きまくってたら強制クローズされた

#急なconnection reset by peer
ハマったのでメモ。

5分に1回APIを叩いてweb上からxmlを引っ張り、情報を更新するということをやろうとしていたのだが、数時間ほど立つと***「connection reset by peer」***というログと共に接続が遮断されて復帰できなくなった。

ofxHttpUtilsではデフォルトでクッキーを送信する仕様になっており、request情報が蓄積され上限を超えてしまうことが原因だったよう。これを切ることで回避した。

具体的にはofxHttpUtilsコンストラクタ内のsendCookiesをfalseするだけ。
ついでにresponseが失敗したときに成功するまで無限に呼びに行くようになっているため、上限を設定しておく。

##ofxHttpUtils.cpp
```C++
ofxHttpUtils::ofxHttpUtils(){
    timeoutSeconds = 2;
    maxRetries = 3; //3回まで呼びに行ってそれでも無理なら諦める
    nbOfTries = 0;
    verbose = true;
    sendCookies = false; //こいつをfalseにしておく
    //start();
　　　　　　　//省略~~
}
```

##参考
https://qiita.com/you-me/items/d9b148036ebd4e2667d7
IE11対応必要事項

LPの受託開発をしていて、IE対応について調べたことをまとめた。
自分のメモ用。随時更新。

#IE11が対応していないこと
## CSS
- flex box(特定の条件下で壊れる)
    - [参考](https://qiita.com/hashrock/items/189db03021b0f565ae27#7-flex-basis%E3%81%8Cborder-box%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%AA%E3%81%84)

## JS
- ES6の表記
    - arrow function, `${}`, etc. 
        - [参考](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)
        - Babelを使えばこういうこといちいち個別対応する必要なさそう。

# その他注意事項
- 適用されるフォントが変わるので、テキストボックスのハードコーディングは避ける
【小ネタ】S3で404ページを全て特定のドキュメントにリダイレクトしたい

S3でウェブサイトホスティングする際に、存在しないドキュメントへのアクセスを全て特定のパスにリダイレクトしたいケースがあったのでその時のメモ。

ルーティングルール等は公式ドキュメントが詳しい
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/how-to-page-redirect.html

## 実際の設定

xml形式で、リダイレクトルールを設定する。

### サンプル

例)存在しないドキュメントへのリクエストは、全てhogeにリダイレクトする。　※hoge/index.htmlを設置する。

```
<RoutingRules>
  <RoutingRule>
    <Condition>   
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>      
      <ReplaceKeyPrefixWith>hoge</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>
```

![A9F2128A-0064-4A7F-86F0-C5029933E9A4.png](https://qiita-image-store.s3.amazonaws.com/0/40850/5d26583b-09c8-066d-26e2-88ec819aeace.png)

### 動作イメージ
存在しないパスへのリクエスト `https://hogehoge.com/abc.jpg`
↓
301リダイレクト
↓
`https://hogehoge.com/hoge/`が表示される
MNCTF 2018 WritesUp

毎年開催されているマクニカさんのCTFに今年は会場で参加できなったかたので後から解いてみました。
MNCTF
http://mnctf.info/mnctf2018/
**注意　FLAGを白文字で記載していますので、MNCTFに挑戦される方はご注意ください**

#練習問題
　回答をそのまま入力するだけ
　**FLAG**
  <font color="White">MNCTF2018</font>
#新人奮闘I
 与えられたマルウェアのSHA256を答える問題。Windows標準だと以下のコマンドで調査可能
 certutil -hashfile <検査するファイル名> SHA256
**FLAG**
  <font color="White">f24f5629be2e0f821adb36fe4d47407937f5a318bf96ae3655b628f833040f29</font>
#新人奮闘II
 先ほどのマルウェアをより詳しく調査する。MD5、SHA1はSHA256と同じくcertutilコマンドで調査可能。importされている関数、DLLに関してはIDAPro等で読み込ませれば確認できる。
全てを正しく入力すると以下の様に答えが出てくる。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/156890/fb36b80b-a0f2-a65d-809b-85405fe05889.png)
**FLAG**
  <font color="White">d56d9a6036bd18ee98878eb74ae8d663</font>

#新人奮闘III
先ほどのマルウェア内で、実行されるコマンドを確認する。
IDAProで逆アセンブラすると以下の部分でコマンド実行されているのが確認できる。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/156890/25319bfb-225f-59cd-fa57-07b98937f70d.png)
**FLAG**
  <font color="White">cmd /c net user /add /domain vpnadmin P@ssw0rD1!</font>

#新人奮闘IV
新人奮闘IIIで得た情報を元にログを調査する。
Ⅲからvpnadminという名前のユーザが追加されたことが分かるので該当ユーザのログイン時刻を調査することで回答できる
**FLAG**
  <font color="White">2018/07/13 15:01</font>

#新人奮闘V
新人奮闘IVでvpnadminでログインしてきたIPアドレスが分かるので、そこからwhois等で国が分かる。
**FLAG**
  <font color="White">韓国</font>

#種類特定
pcapファイルを渡されて、wiresharkで中を見てみると明らかに怪しい通信が
通信先ホスト　kp.mnctfmnctfmnctff.com
GET　/images/GnBKaYOtPriW2Gg_2FSL_2/FHKd8Kd5bkW6W/x7j_2FKi/KiqHM_2Fh7GsRCwLf5ChDFa/F2mTob6Gr4/taMEy1pRTdVV2fsR_/2BNvWB7fYock/a7HKjH1Fytf/2yr_2FPVRYv2t_/2FRMCh_2BE_2By_2Bwn6G/GlWu_2FELxZZWd5F/1pmIiRnJqqmRnj7/syJhI_2BUbG/xA.gif
上記の内容を検索してみると、packettotalで解析した結果が出て来るので、MaliciousActivityタブを参照するとマルウェアの種類が特定できる。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/156890/604bced5-5c1c-3e7c-25a9-bea989237603.png)

**FLAG**
  <font color="White">Ursnif</font>

#標的攻撃I
渡されたExcelファイルを「マクロの実行を無効化した」状態で開き、開発者ツールでマクロを確認する。
マクロ内を確認すると、アプリケーションを実行したユーザ名とC6~C11セルに書かれた内容が一致するなら実行すると記載があるのでC6~C11セルを確認して回答する
**FLAG**
  <font color="White">Take Teshigawara</font>

#標的攻撃Ⅱ
マクロ内に通信先が記載されているので、そのまま記載。
**FLAG**
 <font color="White">https[:]//gist.githubusercontent.com/Sh1n0g1/3a240ce15fe7f26263ddf1877e5acc38/raw/d1d74601e5f4c94c958130accb16add9bb16e33d/cert</font>

#標的攻撃Ⅲ
標的攻撃Ⅱで通信先が分かるので、内容をダウンロードして、コマンドプロンプトでマクロ内で実行されるコマンドでexeを生成して、certutilコマンドで確認する。

**FLAG**
  <font color="White">c4f069d079330cd46e51f9469c27015ed34c6371481df83a323bc098f3b53382</font>

#標的攻撃IV
標的攻撃Ⅲで生成したファイルを実行し、wiresharkで通信をキャプチャするとどこに通信したかを確認する。
**FLAG**
  <font color="White">https[:]//shinobotps1.com/download_get.php</font>

#感想
今年は一つの問題が次の問題につながっていく内容になっており、実際の標的型攻撃の調査やマルウェア解析がどのように行っているかを簡単では体験できるので面白い内容になったのではないかと思う。
残り3問はまだ解けていないので、余裕がある時に再度挑戦したい
~~クロスワードパズルがなくなったのは寂しい~~
Laravel 5.6 Laravel Homesteadを試してみた！！

勉強会でLaravelがいいよと聞いたので、開発環境を構築してみようと思いました。
基本は、Homesteadのマニュアル通りで構築ができました。
ハマったところを自分用のメモとして、残します。

##環境
Macbook pro 
OS High Sierra

##Homesteadについて
githubに公開してあるファイルをcloneして、yamlファイルを編集しました。
**DHCP**を有効にするために、以下のファイルを追加しました。
（外部からアクセスするようにするため）

```
networks:
    - type: "public_network"
      bridge: "en1: Wi-Fi (AirPort)"
```
あと、sitesの項目を編集しています。

変更前

```
sites:
    - map: homestead.test
      to: /home/vagrant/code/
```

変更後

```
sites:
    - map: homestead.test
      to: /home/vagrant/code/laravel/public
```
これは、laravelのrootであるpublicのindex.phpを見るように変更します。
最終的に、**Homestead.yaml**全体は、以下のようになります。

```yaml:Homestead.yaml
---
ip: "192.168.10.10"
memory: 2048
cpus: 1
provider: virtualbox

networks:
    - type: "public_network"
      bridge: "en1: Wi-Fi (AirPort)"

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: ~/code
      to: /home/vagrant/code/

sites:
    - map: homestead.test
      to: /home/vagrant/code/laravel/public

databases:
    - homestead

# blackfire:
#     - id: foo
#       token: bar
#       client-id: foo
#       client-token: bar

# ports:
#     - send: 50000
#       to: 5000
#     - send: 7777
#       to: 777
#       protocol: udp
```
**vagrant up**をしたとき、```homestead-7: Which interface should the network bridge to? ```について聞かれます。
その際は、1(natを選択)を入力して```enter```を押します。

##Laravelのプロジェクトを作成
開発環境に```vgarant ssh```で入ってlaravelのプロジェクトを作成します。

```
sudo composer create-project laravel/laravel /home/vagrant/code/laravel
```

##確認

作成したプロジェクトを```http://192.168.10.10```で確認してみてください。

##ドメインでアクセス
Macの```/etc/hosts```に以下を追記します。

```
192.168.10.10  homestead.test
```
ブラウザで```http://homestead.test```でアクセスできるようになります。

参考元
https://readouble.com/laravel/5.6/ja/homestead.html

##感想
laravelの開発環境が簡単に構築できるのは、魅力的です。
ただ、以下、疑問が残りました。

・マニュアル通りにvagrantでboxをaddしたあと、gitからファイルをcloneします。
その後、vagrant upしたのですが、laravelのプロジェクトが作成されていませんでした。
そのため、sshでログインし、composerでプロジェクトを作成しました。
このへんが、マニュアル通りに進まなかったので、ハマりました。
CentOS6にNode.js 8を入れてみる

#前書き
新しいNode.jsが使いたくば、CentOSの6を使うんじゃない、の突っ込みはごもっとも。

でも、AWS使ってたりすると、兼ね合いでNode.js8系を使ってみたくなったり。

# インストール。

## パッケージ入手

```
# curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
```

どうも、ローカルのrpmデータベースをいじってるみたい。

## 展開
なんと下記のコマンドで入ってしまいます。

```
# sudo yum -y install nodejs
```

##確認
下記にびっくり。

```
# node -v
v8.11.3
```
【Ruby】モジュール関数を理解する

#概要
Rubyにおけるモジュール関数とは何かサンプルコードと共に簡単にまとめました。

#モジュール関数とは？
モジュール関数の主な特徴は以下の２つです。

- __モジュール内に`private`で定義されたインスタンスメソッドである。__
- __モジュールの特異メソッドである。__

モジュール関数としてセットすることで、__「レシーバを全く取らない」__か、__「モジュールをレシーバとする」__場合にのみメソッドの実行が可能となります。
つまり、モジュール関数として定義されたメソッドはオブジェクトの状態に左右されず__関数的__に呼び出しを行うことができるようになります。
#モジュール関数の定義方法
モジュールに定義したメソッドをモジュール関数化するには以下のように記述します。

```ruby
#定義方法1
module Module1 #モジュールを定義する。
  def hello(name)
    puts "Hello #{name}"
  end
  module_function :hello #メソッドをモジュール関数とする。
end
```
複数のメソッドを同時にモジュール関数化する場合には以下のように記載することも可能です。

```ruby

module Module1 #モジュールを定義する。

  module_function #これ以下に定義されたメソッドをモジュール関数とする。

  def hello(name)
    puts "Hello #{name}"
  end

  def good_morning(name)
    puts "Good Morning #{name}"
  end
end
```
#モジュール関数の呼び出し方法
モジュール関数として定義されたメソッドを呼び出すには以下の２方法があります。

- __モジュールから直接呼び出す。__
- __includeして使用する。__

呼び出しの際には以下のように記述できます。

```ruby
###モジュールの定義###

module Module1 #モジュールを定義する。
  def hello(name)
    puts "Hello #{name}"
  end
  module_function :hello #メソッドをモジュール関数とする。
end

###モジュール関数の呼び出し###

#モジュールから直接呼び出す。
Module1.hello('Ben') #=> Hello Ben

#includeする。
include Module1
hello("Doug")

```
通常のミックスインしたモジュールからの呼び出しを試みると以下のようにエラーが発生してしまいます。

```ruby
class Obj
  include Module1
end
obj = Obj.new.hello('Matt') #=> private method `hello' called for #<Obj:0x00007fde68127700> (NoMethodError)
```

#モジュール関数の実例（Mathモジュール)

Rubyの組み込みモジュールであるMathモジュールでは全てのメソッドがモジュール関数として定義されています。
よって上記で実践したようなメソッドの呼び出しが可能です。

```ruby
#モジュールから直接呼び出す。
p Math.sqrt(2) #=> 1.4142135623730951

#includeする。
include Math
p sqrt(2) #=> 1.4142135623730951

```

#参考
[Rubyリファレンス(module_function)](https://ref.xaio.jp/ruby/classes/module/module_function)
[Rubyリファレンスマニュアル(module_function)](https://docs.ruby-lang.org/ja/1.9.3/class/Module.html#I_MODULE_FUNCTION)
コンパイル時の条件により変数宣言の型を変える

# TL;DR

コンパイル時に決まる条件`C`の真偽値により、型`A`か型`B`を選択して、その型の変数を宣言したい。疑似コードで書くとこんな感じ。

```cpp
if (C){
  A x;
}else{
  B x;
}

// 以降xを使う
```

これを実現するには`std::conditional`を使って

```cpp
typename std::conditional<C, A, B>::type x
```

とする。

# 利用例

乱数生成エンジンとして、32ビット版の`std::mt19937`と、64ビット版の`std::mt19937_64`が用意されている。テンプレートで`uint32_t`が指定されたか`uint64_t`が指定されたかにより、それらを同じ変数名で宣言したい。こんな時、`std::is_same`を使って、

```cpp
typename std::conditional<std::is_same<INT, uint32_t>::value, std::mt19937, std::mt19937_64>::type m;
```

と書ける。`typename`はコンパイラにこれが型だと教える。

例えば、こんな感じにラップできる。

```cpp:test.cpp
#include <iostream>
#include <random>

template <class INT>
struct Hoge {
  typename std::conditional<std::is_same<INT, uint32_t>::value, std::mt19937, std::mt19937_64>::type m;
  INT operator()() {
    return m();
  }
};

int main() {
  Hoge<uint32_t> h32; // 32ビット乱数 
  Hoge<uint64_t> h64; // 64ビット乱数
  for (int i = 0; i < 10; i++) {
    std::cout << h32() << " " << h64() << std::endl;
  }
}
```

```shell-session
$ g++ test.cpp
$ ./a.out
3499211612 14514284786278117030
581869302 4620546740167642908
3890346734 13109570281517897720
3586334585 17462938647148434322
545404204 355488278567739596
4161255391 7469126240319926998
3922919429 4635995468481642529
949333985 418970542659199878
2715962298 9604170989252516556
1323567403 6358044926049913402
```


# この記事について

上記のようなことをやりたくて結構調べたんだけれど、どうしてもやりかたがわからなくて最後は同僚さんに聞いて教えてもらった(他にもやり方があるっぽい)。似たようなことで苦労する人がいるかもしれないので検索にかかるようにしておきます[^1]。

[^1]: 調べ方として「コンパイル時　条件分岐 変数宣言」とか「コンパイル時　型 切り替え」みたいなキーワードで調べたんだけど、そうすると`constexpr if`とか`std::is_same`とかは出てきたんだけど、`std::conditional`にたどり着かなかった。`std::conditional`を知らない状態からこのキーワードにたどり着くにはどういうキーワードでググればよかったんですかね？
[AWS] SwitchRoleで擬似セッションタイムアウト（要MFA）

# 関連記事
1. [[AWS] IAMユーザーを擬似セッションタイムアウト（要MFA）](https://qiita.com/n-ishida/items/bf83b5b4d01138fb8d11)

# 目的
IAMロールにはセッション期間の設定があり、デフォルトでは１時間でセッションが切れます。
マネジメントコンソールで `SwitchRole` した場合にもその時間でセッション切れが発生しますが、セッションが切れると再ロードを促され、いくらでも延長が可能です。[^1]
[^1]: 開いている画面によってはセッション延長に未対応のところもあるようです。
つまり実質的には無期限になっています。

[関連記事1](https://qiita.com/n-ishida/items/bf83b5b4d01138fb8d11) と同様、ログインしっぱなしを防止したいケースもあると思います。それほど多くはないと思いますが。
ということで、擬似的にセッションタイムアウトさせてみます。



# 方法
[関連記事1](https://qiita.com/n-ishida/items/bf83b5b4d01138fb8d11) と基本は一緒。
SwitchRole先のIAMロールに、ログインから一定時間経過後に全ての権限を禁止（Deny）するポリシーを付与します。
そうするとSwitch元のログインから一定時間後に、Switch先での権限がDenyになります。
尚、MFA必須です。他にログイン時間を基準にする方法がないので。

図にすると、こうです。
![Untitled (1).png](https://qiita-image-store.s3.amazonaws.com/0/193715/92a86a80-1b0b-db90-e7a4-97d478ea1e18.png)



# ポリシー例

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "NumericGreaterThanIfExists": {
          "aws:MultiFactorAuthAge": "3600"
        }
      }
    }
  ]
}
```

* `"aws:MultiFactorAuthAge"` は秒数です。  
  このポリシー例の場合は 3600秒 = １時間。
* MFAなしでログインした場合は、"常に全てDeny"になります。  
  そもそもSwitch不可にしたほうがよさそう。


# 注意事項
* 「最後の操作から一定時間経過後」ではありません。  
  何か作業途中であろうと、ログインから一定時間で権限が剥奪されます。
VS CodeのターミナルをAnacondaに変える

#VS Code内蔵ターミナルが使いたい
備忘録です。
Anacondaでpythonをまとめてインストールしたので、「VS Codeでコーディング、Anaconda Promptで実行」と２ウィンドウでやっていましたが、VS Code内で実行もできるようにするという話です。

#やること
1. Pathの追加
2. バッチファイル作成
3. VS Code内の設定
4. 再起動

#1.Pathの追加
ユーザー環境変数のPathに
```C:\Users\(ユーザー名)\AppData\Local\Continuum\anaconda3```
```C:\Users\(ユーザー名)\AppData\Local\Continuum\anaconda3\Scripts```
の２つを追加します。Anacondaのインストール先に指定した場所です。

#2.バッチファイル作成
C:\Users\(ユーザー名)\AppData\Local\Continuum\anaconda3\envsの下にAnaconda3.batという名前でバッチファイルを作成しました。名前は何でもいいです。

```Anaconda3.bat
%windir%\system32\cmd.exe "/K" C:\Users\(ユーザー名)\AppData\Local\Continuum\anaconda3\Scripts\activate.bat C:\Users\(ユーザー名)\AppData\Local\Continuum\anaconda3\envs\Anaconda3
```

#3.VS Code内の設定
VS Codeを立ち上げます。メニューの「ファイル ＞ 基本設定 ＞ 設定」にて
ユーザー設定に```"terminal.integrated.shell.windows": "C:\\Users\￥(ユーザー名)\\AppData\\Local\\Continuum\\anaconda3\\envs\\Anaconda3.bat",```を追加します。

```json:ユーザー設定
{
    "python.pythonPath": "C:\\Users\\(ユーザー名)\\AppData\\Local\\Continuum\\anaconda3\\pythonw.exe",
    "editor.renderWhitespace": "all",
    "terminal.integrated.shell.windows": "C:\\Users\\(ユーザー名)\\AppData\\Local\\Continuum\\anaconda3\\envs\\Anaconda3.bat",
}
```

#4.再起動
VS Codeを再起動します。「設定変わったけど、OK?」と聞かれるのでAllowしてあげます。
これで完成です。"Ctrl + @"でターミナルを起動するとpythonプログラムが実行できるようになっているはずです。
ついでに言うと、普通のコマンドプロンプトでもpythonが実行できるようになります。（自分はAnacondaでpythonもインストールしたので、これをやるまでAnaconda Promptでしか実行出来ませんでした）
Ruby on Rails | rails console で直接ファイルを require する方法

`/path/to/rails-application/some/file.rb` を `require` したい。

# 絶対パス指定

`Rails.root` から読む。

```rb
require "#{Rails.root}/some/file"

# => true
```

# 相対パス指定

相対パス指定だと、Railsアプリケーションのトップディレクトリを基準に読めた。

```rb
require_relative "some/file"

# => true
```

## エラー例 

`require` で相対パスから読もうとすると、 `./` を付けない時にエラーになるので注意。

```rb
require "some/file"

LoadError: cannot load such file -- some/file
```

( なんでだよ！ と思ったが、この書き方だと多分、インストール済みの ruby gem などだけから読もうとする気がする)


## 補足

ちなみに実際に rails console を起動したディレクトリと、相対パス指定した時の基準ディレクトリは関係ない様子。

カレントパスの確認はたぶんこいつ。

```rb
Dir.pwd

# => "/path/to/rails-application"
```

# 環境

- pry-rails (0.3.6)
- rails (5.1.5)
- ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin16]
 
# 参考

- [ruby - How can I require libraries in your Rails directory from the console? - Stack Overflow](https://stackoverflow.com/questions/4609577/how-can-i-require-libraries-in-your-rails-directory-from-the-console)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
(Clovaに喋らすメソッド編)Lambdaで使える、Clova(CEK)のSDK作ってみた

# はじめに

|No,|タイトル|
|-----------------|------------------|
|1|[(インストールから、ハンドラー作成編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/1b919b923246e69fe86e)|
|2<<今ここ|[(Clovaに喋らすメソッド編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/26c7e977079ddb04336c)|
|3|[(スロット、セッション情報取得編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/6e84cd0ff8fad28b3fe9)|

前回は、ハンドラの登録実践しました。
canHandle内でリクエストを判断して、handlerでCEKに返す処理を実行しました。
今回はそのhandler内でClovaに喋らす内容を定義する方法を紹介します。

# LaunchRequestHandler

今回は前回紹介した`SampleIntentHandler`にて説明をします。

```js:index.js
const SampleIntentHandler = {
  canHandle: function(handlerInput){
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "SampleIntent";
    // return handlerInput.requestEnvelope.isMatch('sampleIntent');
  },
  handle: function(handlerInput){
    var msg = "";
    return handlerInput.responseBuilder.speak(msg).reprompt(msg).getResponse();
  }
}
```

前回、`canHandle`と`handler`についての説明はしたので省きます。
このSampleIntentHandlerが実行された場合、Clovaは以下のように喋りユーザーに再度応答を求めます、（つまりスキルを終了しません)

```
SampleIntentが呼ばれた時に返します。
```

また、ユーザーがしばらく応答をしなかった時再度Clovaが喋る内容が以下になります。

```
ユーザーがしばらく応答をしなかった時に再度Clovaが喋ります。
```

# speak(msg)

Clovaが喋るテキストを引数に与えます。
上記ですと、`msg`変数に値します。
後述するrepromptがない場合、Clovaは発話した後にスキルを終了します。

# reprompt(msg)

このメソッドを使用した場合、Clovaは発話した後にユーザーの応答を求めます。
つまり、スキルを終了しません。
また、この引数に指定したテキストはユーザーが数秒間応答がなかった時に再度Clovaが喋る内容になります。

# audioPlay(url)

speakメソッドでは、引数にテキストを指定しましたが、このメソッドでは流したい音声のURLを指定します。

```
const URL = "https://audio.....";
return handlerInput.responseBuilder.audioPlay(URL);
```

# audioPlayReprompt(url)

repromptメソッドでは、引数にテキストを指定しましたが、このメソッドでは流したい音声のURLを指定します。

```
const URL = "https://audio.....";
return handlerInput.responseBuilder.audioPlay(URL).audioPlayReprompt(URL);
```

# 合わせて利用する

この`speak`,`reprompt`,`audioPlay`,`audioPlayReprompt`はそれぞれ繋げて利用することが可能です。

例

```js
const audioStart = "オーディオを流します。";
const audioStop = "オーディオを止めます。";
const URL = "https://audio.....";
return handlerInput.responseBuilder
  .speak(audioStart)
  .audioPlay(URL)
  .speak(audioStop)
```

この例ですと、Clovaは以下のように喋ります。

```
オーディオを流します。
（オーディオ再生)
オーディオを止めます。
```
(スロット、セッション情報取得編)Lambdaで使える、Clova(CEK)のSDK作ってみた

# はじめに

|No,|タイトル|
|-----------------|------------------|
|1|[(インストールから、ハンドラー作成編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/1b919b923246e69fe86e)|
|2|[(Clovaに喋らすメソッド編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/26c7e977079ddb04336c)|
|3<<今ここ|[(スロット、セッション情報取得編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/6e84cd0ff8fad28b3fe9)|

前回は、Clovaに喋らすテキストの定義方法を説明しました。
今回はスロットとセッション情報の取得を実践してみたいと思います。

# スロットの取得

`Fruit`という名前のスロットがあったときの取得方法は以下になります。

```js
var value = handlerInput.requestEnvelope.request.intent.slots.Fruit.value;
```

または、以下でも取得できます。

```js
var slots = handlerInput.requestEnvelope.getSlot();
var value = slots.Fruit;
```

# セッション情報(sessionAttributes)

## そもそもsessionAttributesとは

1回のスキル起動中に保存しておきたい値を置いておくオブジェクトです。
これだと想像が難しいので例で説明します。

例えば、カフェでコーヒーを頼むスキルがあったとします。
以下のような会話が想定されます。

```
ユーザー: 「Clova, カフェスキルを起動して」

Clova: 「いらっしゃいませ。頼みたいメニューをおっしゃてください。」

ユーザー: 「コーヒー」 << ここでコーヒーを発言している

Clova: 「コーヒーですね。何杯頼みますか？」

ユーザー: 「２杯」 << ここではコーヒーを言っていないのでスロットとして取得できない。

Clova: 「コーヒーを２杯ですね。ただいまお持ちいたしますので少々お待ちください。」
```

ここで、この会話の中に、もし`sessionAttributes`が存在しなかったら成り立たない部分があります。
それは、`「コーヒーを２杯ですね。」`の部分です。
なぜ成り立たないかというと、「２杯」の部分はスロットで取得できますが「コーヒー」の部分はスロットで取得できません。
ユーザーの2回目の発話の`「コーヒー」`で`sessionAttribute`に`コーヒー`という値を保存します。
これにより、3回目以降の会話でも`コーヒー`を頼もうとしていることを取得できるのです。


## 取得

以下でsessionAttributesのオブジェクトを取得することができます。

```js
var attributes = handlerInput.sessionAttributeManager.getSessionAttributes();
console.log(attributes);
// 例
// {
//   key: "value"
// }
```

## 保存

CEK側にsessionAttributesを返したい場合は以下になります。

```js
var attributes = {
  key: "value"
}
handlerInput.sessionAttributeManager.setSessionAttributes(attributes);
```
(インストールから、ハンドラー作成編)Lambdaで使える、Clova(CEK)のSDKを作ってみた

# はじめに
|No,|タイトル|
|-----------------|------------------|
|1<<今ここ|[(インストールから、ハンドラー作成編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/1b919b923246e69fe86e)|
|2|[(Clovaに喋らすメソッド編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/26c7e977079ddb04336c)|
|3|[(スロット、セッション情報取得編)Lambdaで使える、Clova(CEK)のSDK作ってみた](https://qiita.com/imajoriri/items/6e84cd0ff8fad28b3fe9)|

Alexaスキル開発でおなじみの`ask-sdk`とほぼ同じコードで動くSDKを作ってみました。
その紹介記事です。

CEKとLambdaのひも付けなどは、[ここ](https://qiita.com/imajoriri/items/357026af6b0de0dfe330)で説明しています。よかったらどうぞ。

# リポジトリ

[npm](https://www.npmjs.com/package/love-clova)
[GitHub](https://github.com/imajoriri/love-clova/wiki)

# install

```
$ npm install love-clova
```

# ファイル自動作成

indexファイルを作成するコマンド。ここはお好みでやってください。

```
$ node ./node_modules/.bin/clova-init

// もしくは、以下は個人的なディレクトリ構成を作成してくれる
$ node ./node_modules/.bin/init-original
```

# Hnadler（ハンドラー）とは

何かのイベントが発生した時に実行される処理のことです。
Clovaスキルでは、イベントをインテント（もしくはリクエストタイプ）で判断します。
例えば`SampleIntent`が発生した場合は`SmapleIntentHandler`が実行されます。

# ハンドラーの作成

上で説明した`SampleIntentHandler`を実際に作成してみます。

```js
const SampleIntentHandler = {
  canHandle: function(handlerInput){
    return handlerInput.requestEnvelope.request.type === "IntentRequest"
      && handlerInput.requestEnvelope.request.intent.name === "SampleIntent";
    // return handlerInput.requestEnvelope.isMatch('sampleIntent');
  },
  handle: function(handlerInput){
    var msg = "";
    return handlerInput.responseBuilder.speak(msg).reprompt(msg).getResponse();
  }
}
```

コードの中の詳しい説明は後ほどします。
このままでは、`SmapleIntent`をトリガーとして実行はできないので、できるように紐付けを行います

# ハンドラーの登録

`addRequestHandlers()`の引数にハンドラーを登録するだけです。

```js
exports.handler = clova.extensionBuilders
  .addRequestHandlers(SampleIntentHandler)
  .lambda()
```

次にSmapleIntentHandlerの中身をみていきます。

# canHandleメソッド

このハンドラーのトリガーか？を判断するメソッドです。
このメソッドの戻り値がtrueの場合、ハンドラーが1回だけ実行されます。

これらより、LuanchRequestがきた時は

```js:LaunchRequest
return handlerInput.requestEnvelope.request.type === "LaunchRequest"
```

SampleIntentの時は

```js:sampleIntent
return handlerInput.requestEnvelope.request.type === "IntentRequest"
  && handlerInput.requestEnvelope.request.intent.name === "SampleIntent";
```

それぞれ`true`になります。

# handleメソッド

canHandleがtrueを返した場合実行されるメソッドです。
スロット値や、sessionAttributesを取得し、Clovaに喋らす内容を構成します。

スロットやsessionAttributesの取得メソッドなども用意しているので、次回紹介します。

次回 >> [(Clovaに喋らすメソッド編)Lambdaで使える、Clova(CEK)のSDK]()
h2oのmrubyハンドラで`/robots.txt`を出し分ける

[諸処の事情](https://getshifter.io)で、本番とは違うドメインで起動して操作しているWordPressなどがGoogleなどにインデックスされてイヤン、ということもあるでしょう。

いちいちrobotsを切り替えながら操作するのも手間なので、[h2o](https://h2o.examp1e.net)に組み込まれているmrubyで出力をコントロールした。

```ruby:robots.rb
# デフォルトのDisallowルール
robots = <<EOL
User-Agent: *
Disallow: /
EOL

lambda do |env|
  # /robots.txt以外のリクエストはすぐ処理をh2oに返す
  unless env["PATH_INFO"] == '/robots.txt'
    return [399, {}, []]
  end

  # 任意の条件で、これまた処理をh2oに返す。これはフラグファイル有無での例
  # 環境変数で判断とかでもよい
  if File.exist?('/path/to/flagfile')
    return [399, {}, []]
  end

  # Cookieに`wordpress_logged_in_*` => WordPressにログイン済みっぽいとして扱う
  if env["HTTP_COOKIE"]
    cookies = env["HTTP_COOKIE"].split
    if cookies.select {|a| a.match(/^wordpress_logged_in_/)}.any?
      # カスタマイズしたときのプレビューが出来ないと不便なので、ユーザ定義のrobots.txtを見せる
      return [399, {}, []]
    end
  end

  # これまでの条件にマッチしなければ、デフォルトのDisallowルールを適用
  return [200, {'Content-Type' => 'text/plain;charset=utf-8'}, [robots]]
end
```

rackベースなのでやりやすい。
Terraformではresource名にはdev/prodなどを入れなくてよさそう

# 環境ごとのリソース名の切り替え

- Terraformで環境ごとのリソース名の切り替えをする際は、[Terraform 環境周りTips](https://qiita.com/mafuyuk/items/2d9f8dc2292135c93b51) にあるように `workspace` サブコマンドを使えばよい
- でも、その場合同じリソース名をprod/devで指定すると重複してしまうのではないかと危惧していた

## 構想

以下のようなリソースを作るべきかとちょっと迷った

```ruby
resource "aws_iam_role" "hoge-role-${terraform.env}" { # <-- ${terraform.env}でリソース名切り替え
  name   = "hoge-role-${terraform.env}"
  path   = "/${terraform.env}/hoge/"
  assume_role_policy = <<EOF
{
...
}
EOF
}
```

## 関連するStackOverflowやGitHubのトピック

- [hashicorp/terraform - Can't use programmatic resource names #571](https://github.com/hashicorp/terraform/issues/571)
- [StackOverflow - Referring to resources named with variables in Terraform](https://stackoverflow.com/questions/38619691/referring-to-resources-named-with-variables-in-terraform)

>The names in Terraform are just logical for the purposes of referring to them. You want to parameterize the values inside the resource, and not the name itself, so this is by design.
>
>Multiple environments are supported by using different variable and state files.

しかし、上記の記事にあるようにTerraformでリソース名に[文字列補間](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%88%97%E8%A3%9C%E9%96%93)できないのは仕様で、やる必要がないようだ。

同じリソース名を参照していたとしてもworkspaceが異なれば実際のARNは異なるのだろう（たぶん）
VSCodeで新規作成ファイルのデフォルト言語を指定する

とあるところ向けに書いたものを再編集しておきます

VSCodeでデフォルトの新規作成時には`プレーンテキスト`になっていますよね。
メモや議事録などドキュメントとしてMarkdownをよく使う自分としては、
いちいち画面右下から設定するか、`Cmd + K → M`でこの画面を出して設定するのが本当に面倒です。

<img width="449" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/30278/2778edae-db01-9955-b582-1bcc24849d50.png">

なので、**もういっそのことMarkdownをデフォルトにします。**

`設定アイコン → ユーザー設定` を編集するか、
`~/Library/Application Support/Code/User/settings.json` を編集します。

```json
{
  //settings.json
  "files.defaultLanguage": "markdown"
}
```

<img width="329" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/30278/3d1ea57d-c7af-d945-0a9b-6919764f70e4.png">

ヤッターこれでMarkdownすらすら書けるよ

`files.defaultLanguage` を各自好みの言語にしておけば幸せになれますね。
おわり。
【Rails】どうしてredirect_to @userでユーザーページにリダイレクトできるのか

#詰まった点

RailsTutorial[7.4.1 登録フォームの完成]をやっている際、```redirect_to @user```でユーザーページにリダイレクトできるロジックがわからなかった。

Railsチュートリアル内にて、```redirect_to @user```のコードが```redirect_to user_url(@user)```のコードと等価という記載があった。

```user_url```の名前付きパスの後の```(@user)```がどうしてくっついているのかが見当がつかなかった。```redirect_to URL```という文法がある以上、```redirect_to user_url(@user)```ではなく、```redirect_to user_url```でもいい気がした。

#どうして```redirect_to @user```でユーザーページにリダイレクトできるのか

概して、```user_url```は```/users/:id```みたいなURLになっていることが多い。

```redirect_to user_url```では```:id```の部分に何が入るのかわからないためエラーとなる。
この```:id```の部分に何が入るかを指定するのが```(@user)```の部分であり、引数に```@user```と指定することでその変数に格納されたレコードに該当するページへのURLとなる。

おそらく、ここでの```@user```はインスタンス変数ではないと推察され、```:id```を入れるためにあるものであると考えられる。

#参考文献
[【Rails】redirect_to @userでユーザーページにリダイレクトできるロジックを知りたい](https://teratail.com/questions/136365#reply-206636)
開発中アプリがインストールできなくなる現象

# 現象
- 開発中のアプリがPlayプロテクトに有害なアプリとして認定されたことでアプリがインストールできなくなった？
- adb経由ではインストールできるが、Webページからダウンロードしたものはインストールできない。
- Webページからダウンロードしたものをインストールしようとすると、「インストールされません」と出てインストールできない。

# 前提
- アプリをインストールする場合は上書きではなく、アンインストール後、再度インストールします

# 原因
Playプロテクトを無効化することでインストールできることを確認しました。
そのため、Playプロテクトがインストールできない原因と判断しました。
次の2点を根拠に原因とするには弱い気もしますが、最も可能性の高い原因と思っています。

- Playプロテクトのダイアログが出たこと
- ダイアログが表示されるようになってからインストールできない現象を確認したこと

他に情報をお持ちの方は教えていただけると嬉しいです。

---

以下は原因調査で確認した内容です。

# 原因調査
## 複数ユーザにインストールされているから？
使用した端末では複数ユーザの設定はされておらず、所有者のみある状態です。
そのため、他のユーザにもインストールされていて、端末から完全にアンインストールされた状態ではないために発生したというわけではありませんでした。

## パーミッションの問題？
[こちら](http://nobollel-tech.hatenablog.com/entry/2016/08/10/154255)にあるように、adb経由であればエラーが出るとのことなので、adbからインストールを試しました。
しかし、なんのエラーもなくSuccessのみ表示され何事もなくインストールされました。

## 署名に使用したキーストアが異なっている？
開発段階なので、開発者が各々キーストアを作成していました。
そのため、共通のキーストアを作成し、今後はそれを使用してAPKを作成するようにしました。
APKの署名に使用したキーストアと前述した共通のキーストアを比較しましたが、同一のものであることが確認できました。

## Playプロテクト？
最初に現象を確認した担当者から聴取したところ、インストールしようとしたときにPlayプロテクトのダイアログが表示され、「OK」を押したとのこと。
ユーザーに対して有害なアプリとして認定された？ためインストールできない可能性があるかもしれません。
しかし、調べても有害認定の基準は不明。
[ヘルプページ](https://support.google.com/android/answer/2812853?hl=ja)からガイドライン、ポリシーを確認しましたが、開発中のアプリには該当しないため問題はありません。
別端末で確認したところ、Playプロテクトのダイアログが表示されました。
ダイアログによると「提供元不明」が理由として挙げられていますが、提供元不明のアプリのインストールを許可するように設定しています。
ダイアログの「OK」を押さず、「インストール」を押すことでインストールできましたが、アンインストールすると次回からはPlayプロテクトのダイアログが出ることもなく、「インストールされません」と出てインストールできなくなりました。

## Webページの問題？
インストールするWebページの問題の可能性はあるかもしれませんが、これに関しては私では確認できないのでこの点については調査できず。
サーバとの通信で[問題](https://developer.android.com/training/articles/security-ssl?hl=ja)が発生することが多々あったこともあり、可能性としては捨て切れていません。
Pythonでプログラミングを始めよう!  〜環境構築編(Mac)〜

#前提
・Homebrewがインストールしてあること。
　　まだの方は下記を参考にしてください。
 [　　・Homebrewインストール](https://hajipro.com/unix/mac-homebrew)
・インストール済みの場合はbrewを最新の状態にしてください。

```
brew update
```
#Pythonのバージョンを確認しよう。
MacOSではデフォルトでPythonがすでにインストールされています。
まずは、インストール済みのPythonのバージョンを確認してみましょう。

ターミナルを開いて、下記のコードを実行します。
[・ターミナルの開き方](https://syncer.jp/mac-terminal)

```
python --version
```

すると、バージョン情報が表示され「Python 2.7.10」がインストール済であることが確認できます。

Python2系でも良いのですが、今回は最新のPython3系を使いたいので早速Python3をインストールしていきます。
まずは、Pyenv,Pyenv-Virtualenvをインストールしましょう。

#そもそもPyenvって？
一つのパソコン上で、複数のPythonの仮想実行環境を構築し、自由にバージョン切り替えを
出来るようにする為のツールです。

#Pyenv,Pyenv-Virtualenvのインストール
下記を実行し、Pyenv,Pyenv-Virtualenvをインストールします。

```
brew install pyenv pyenv-virtualenv
```

インストールが完了したら、PATHを通します。
.bash_profileを開きましょう。

```
vi ~/.bash_profile
```

.bash_profileを開いたら末尾に下記を入力します。

vi の操作がわからない方は[こちら](http://feb19.jp/blog/archives/000226.php)をご覧ください

```sh
export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
    export PATH=${PYENV_ROOT}/bin:$PATH
    eval "$(pyenv init -)"
    eval "$(pyenv virtualenv-init -)"
fi
```

最後に設定した内容を反映します。

```
source ~/.bash_profile
```

[pyenvのコマンドはこちらを参考にしてください。](https://github.com/pyenv/pyenv/blob/master/COMMANDS.md)

#Python3のインストール
Pythonをインストールする準備が整ったので、Pythonをインストールしていきます。

まずは、インストール出来るバージョン一覧を確認します。

```
pyenv install --list
```

バージョンが3.6.4のPythonをインストールします。

```
pyenv install 3.6.4
```

インストールされているバージョンを一覧で確認します。

```
pyenv versions
```

こんな感じで表示出来ていればOKです！

```
$ pyenv versions
* system (set by /root/.pyenv/version)
  3.6.4
```
※印がついているものが現在適用中のバージョンになります.

#バージョンを切り替えてみよう。

##globalコマンドを使用して、バージョンを切り替える。
全体でバージョンを切り替えるにはglobalコマンドを使用します。

```
pyenv global 3.6.4
python --version
```
Python 3.6.4と表示されれば、インストールと反映は完了になります。

※バージョンが3.6.4 と表示されない場合は、もう一度下記の実行を行ってみてください。

```
source ~/.bash_profile
```

##localコマンドを使用して、バージョンを切り替える
特定のディレクトリ配下のみバージョンを切り替える場合は、localコマンドを使用します。

任意のバージョンに切り替える為、他のバージョンをあらかじめインストールしておきましょう。

```
cd TARGET_DIR
pyenv local 任意のバージョン
python --version
```

#Pyenv-Virtualenvの使い方まとめ
プロジェクト毎に仮想環境を切り替えたい場合にPyenv-Virtualenvを使用します。

バージョンを指定して、仮想環境を作成する

```
pyenv virtualenv 3.6.4 sandbox
                 　　　　　　　　　　　　-------
                       任意の名前
```

作成済みの仮想環境を確認

```
pyenv virtualenvs
```
作成した、仮想環境を反映する場合は、バージョン切り替えとおなじようにすれば反映することが出来ます。
ofxTweenzor を使用する際のメモリリーク対策

#removeAllTweensではメモリを解放してくれない。
調子に乗ってaddしまくるとメモリリークを引き起こす危険があるので、Tweenzor.cpp内のremoveAll系の関数内で、vectorをswapしてメモリを解放する記述を足してやる。

##Tweenzor.cpp
```c++

void Tweenzor::removeAllTweens() {
	for(unsigned int i = 0; i < __instance->_events.size(); i++) {
		__instance->_events[i].destroy();
		__instance->_events[i] = NULL;
	}
	
	__instance->_events.clear();
	__instance->_tweens.clear();
    
    __instance->_tweens.swap(__instance->_tweens); //こいつを追加してvectorのメモリを解放
	
	cout << "Tweenzor :: removeAllTweens : " << __instance->_tweens.empty() << endl;
}
```

```c++

void Tweenzor::removeAllListeners() {
	__instance->_events.clear();
    
    __instance->_events.swap(__instance->_events); //こいつを追加してvectorのメモリを解放
}

```
Node.jsインストール


```
curl --silent --location https://rpm.nodesource.com/setup_16.x | sudo bash -
yum install nodejs
````

【備考】以前のやり方

```
yum install nodejs npm --enablerepo=epel
```

#Expressの導入

```
npm install -g express
```

#Expressの利用
画面にejsを利用

```
express -e ディレクトリ名 -t ejs
cd ディレクトリ名 && npm install
npm install  
```
Lambdaでヘルスチェックするコードのメモ

完全自分用メモですよ。

```
# -*- coding: utf-8 -*-
 
import commands
import os
import boto3
 
print('Loading function')

## SNS送信関数
def sendmsg():
    TOPIC_ARN = u'arn:aws:sns:ap-northeast-1:＊＊＊＊＊＊'
 
    msg = "Please check for https://www.example.com/"
    subject = u'Site is down！!'
    client = boto3.client('sns')
 
    request = {
        'TopicArn': TOPIC_ARN,
        'Message': msg,
        'Subject': subject
    }
 
    response = client.publish(**request)

#Linuxのコマンド実行関数
def _(cmd):
    return commands.getoutput(cmd)
 
def lambda_handler(event, context):
    #ヘルスチェックで問題がない場合に表示する文字列
    ok_string = "ok"
     
    #ヘルスチェックで問題がある場合に表示する文字列
    ng_string = "ng"
     
    #実行するcurlコマンド
    curl_cmd = 'curl -LI https://www.example.com/ -o /dev/null -w \'%{http_code}\\n\' -s'

    #curlコマンドの実行
    response = _(curl_cmd)
     
    #レスポンスのログへの記録
    print("----------response body start.----------")
    print(response)
    print("----------response body end.------------")
     
    #ステータスコードの判定
    if response == ("200"):
        print("Status is 200")
        return {"result": ok_string}
    else:
        print("Status is not 200")
        sendmsg()
        return {"result": ng_string}
```
ProtocolBuffersとサブモジュールを使った通信・パースの仕組み

## ProtocolBuffersとは
ProtocolBuffersとは、簡単にいうと、言語や型定義が異なるアプリ（swift,java,kotlin)とサーバー(Railsなど）間の通信を、より簡単に、意思疎通ロスなく、便利にしてくれる仕組み、概念、ツール。

Googleが提唱したらしく、swiftでいうと、Himotokiライブラリなどを使って、サーバー側からJSONで送られてきたデータを、都度都度、型やmapなどを考えながら、手でコードを書いていかなければならない。そのコードや型が間違っていたらswiftだとアプリ落ちてしまうし。

そもそも、サーバー側とhttpで通信させないのは、当時スマートフォンなどPC以外のデバイスで、サーバーから送られてきたhttpなどのデータをブラウザを使って、形式通りにパースして表示させようにも、スペックが足りなくて重い。それほどブラウザという仕組みはW3Cなどの機関によって、がっちり固められて複雑で重い。

そのため、アプリという、もっとデータ→画面表示の部分を、俺たちで自由にやって、かつサクサク動くようにしようぜってのが、アプリの考え方。現代ではデバイスの性能が上がってきたので、Webアプリをブラウザで使う形でも問題なくなってきたが、元を辿ると、モバイルデバイス⇄サーバー間の通信形式がhttpでなく、JSON+アプリといった形なのはそういう理由。

### 型変換などの手書きしていたコードも自動生成？
サーバーサイドとのやり取りするデータ・型は、口頭で話し合うか、ドキュメントにまとめて、フロント（アプリ側）と共有しなければいけない。

それをみながら、ここではこのかたで、とHimotoki（デコード）を手動で書かなければいけなかった。

ProtocolBuffersを使うとそれが自動生成されるっぽい。なんかbinaryっぽい。

## サブモジュールとは
サブモジュールはgitの仕組みであり、gitの各リポジトリ同士をハッシュキーによって、結びつけ、共有する仕組み。

アプリのリポジトリには、サブモジュールのリポジトリのハッシュ値のみの記載があり、それぞれ別リポジトリからデータをダウンロードしてくる。

サブモジュールのリポジトリが更新されると、それと紐づけられているiOS, Android, サーバー側のリポジトリは、そのハッシュ値を更新してコミットするだけで、最新版のサブモジュール（今回の場合はProtocolBuffers）のデータを正確に更新・同期でき、iOS, Android, サーバー間で、ドキュメントの作成や口頭での確認などなく、同じパースの仕組みを共有できる。

ドキュメントをオンラインで共有することの違いとしては、サブモジュールの仕組みを使った方が、色々とプログラムでのやり取りが便利だからだ。


## 参考URL
https://qiita.com/aiueo4u/items/54dc5dd8c4772253634c#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95-for-ruby