OmniAICreator/Qiita-1.07M huggingface dataset:
golang EchoでPOSTされたデータを確認する方法

golang + Echoで実装されたWebサーバにてPOSTされたデータを確認する方法です。

# 前提条件
- golang
 - 1.12
- WebFramework
 - https://github.com/labstack/echo
 - v4.1.10

# Body Dump Middlewareを利用する
https://echo.labstack.com/middleware/body-dump

Usageで提示されているコードにはrequestを出力する処理がないのでFprintfでos.Stderrに出力します。

```golang

e := echo.New()
e.Use(middleware.BodyDump(func(c echo.Context, reqBody, resBody []byte) {
    fmt.Fprintf(os.Stderr, "Request: %v\n", string(reqBody))
}))
```

# Skipperで出力を制御する


前述のコードではリクエストされたデータを毎回出力してしまうので、任意のタイミングで出力できるようにSkipperを利用します。Skipperはmiddleware.goで以下のように定義されており、trueを返却した際には当該middlewareは処理を行わずスキップされます。

https://github.com/labstack/echo/blob/master/middleware/middleware.go

```golang

// Skipper defines a function to skip middleware. Returning true skips processing
// the middleware.
Skipper func(echo.Context) bool
```

Skipperを使った実装例です。ヘッダーで`X-Debug`を受け取った場合のみ出力するようにしてみました。エントリーポイント毎にdumpするしないを変更したり、再度のbuildが必要になる何らかの実装をするよりも楽だと思います。

```golang

e.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{
    Skipper: func(c echo.Context) bool {
        if c.Request().Header.Get("X-Debug") == "" {
            return true
        }
        return false
    },
    Handler: func(c echo.Context, reqBody, resBody []byte) {
        fmt.Fprintf(os.Stderr, "Request: %+v\n", string(reqBody))
    },
}))
```

# 実装例

最小限の実装をおこなったmain.goの全体です。

```golang

package main

import (
    "fmt"
    "net/http"
    "os"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func dumpHandler(c echo.Context, reqBody, resBody []byte) {
    fmt.Fprintf(os.Stdout, "Request: %+v\n", string(reqBody))
}

func main() {
    e := echo.New()

    e.HideBanner = true
    e.HidePort = true

    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    e.Use(middleware.BodyDumpWithConfig(middleware.BodyDumpConfig{
        Skipper: func(c echo.Context) bool {
            if c.Request().Header.Get("X-Debug") == "" {
                return true
            }
            return false
        },
        Handler: dumpHandler,
    }))

    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!\n")
    })

    e.Logger.Fatal(e.Start(":1323"))
}
```

# 最後に

REST APIの提供をしていると「リクエストするとエラーになる」との問い合わせを受けることが多々あります。リクエストされたJSONを簡易に確認できる手段を用意しておくと調査が楽になると思います。
VSCodeのRemote Developmentを使ってリモートのRuby(Sinatra)をデバッグする

ISUCON9予選おつかれさまでした。惨敗しました。せっかくなので今回の開発環境を備忘録で残しておきます。

## Remote Development

VSCode 1.35.0からstable版でも使えるようになりました。今回は[Remote SSH]([https://code.visualstudio.com/blogs/2019/07/25/remote-ssh](https://code.visualstudio.com/blogs/2019/07/25/remote-ssh)) を使ってSSHでリモートサーバー内のファイルをVSCodeから直接編集します。また ruby-debug-ideを使ってステップ実行できるようにします。

## Remote SSH でサーバー内のファイルを編集する

### 1. Remote SSH Extensionをダウンロード
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh


### 2. ~/.ssh/configの設定
例えばこんな感じにします

```
Host s1
  User isucon
  HostName xxx.xxx.xxx.xxx
    
Host s2
  User isucon
  HostName xxx.xxx.xxx.xxx
    
Host s3
  User isucon
HostName xxx.xxx.xxx.xxx
```

### 3. Remote SSHでログインする
コマンドパレットから `Remote-SSH: Connect to Host` を選択、リモートのサーバーを選択するとエディタが開きます。開いたら任意のフォルダを開きます。(今回は~/isucari/webappにします)

<img width="1024" alt="web_rb_—_webapp__SSH__s1__and_Extension__Remote_-_SSH_—_isucon9q_and_____zsh_.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28262/85564a5b-cab3-401e-5794-637291f7dde4.png">

開けました。ターミナル、エディタ、Gitが扱えるのでこれでも大体操作できます。

## Ruby(Sinatra)でruby-debug-ideを使ってステップ実行なデバッグを行う
ついでにステップ実行できるデバッグ環境を作ります。

### 1. Gemfileにgemを追加

```
group :development do
  gem 'ruby-debug-ide'
  gem 'debase'
end
```

bundle installをお忘れずに。

### 2. VSCodeの Ruby Extensionをリモートにインストール
VSCodeのRemote Developmentではリモートの環境にExtensionを入れることになるのでそうします。ダウンロードしたらVSCodeの再起動が必要です。
https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby

### 3. 構成の追加でrdebug-ide環境を構築
デバッグ > 構成の追加 > Ruby > Listen for rdebug-ide の順に選択していくと、開いているフォルダの直下に `.vscode/launch.json` が作成されます。出来たlaunch.jsonにuseBundleのオプションを追加します。

※ Ruby Extensionを入れていないと構成の追加でRubyが選択できません。

```diff

{
  // IntelliSense を使用して利用可能な属性を学べます。
  // 既存の属性の説明をホバーして表示します。
  // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for rdebug-ide",
      "type": "Ruby",
      "request": "attach",
      "remoteHost": "127.0.0.1",
      "remotePort": "1234",
-     "remoteWorkspaceRoot": "${workspaceRoot}"
+     "remoteWorkspaceRoot": "${workspaceRoot}",
+     "useBundle": true
    }
  ]
}
```

### 3. rdebug-ide を使ってSinatraを起動する

VSCodeのDebugを実行し、以下のコマンドを実行する。

```
cd /home/isucon/isucari/webapp/ruby
bundle exec rdebug-ide --host 127.0.0.1 --port 1234  -- ~/local/ruby/bin/bundle exec rackup -p 8000
```

 <img width="1026" alt="web_rb_—_webapp__SSH__s1__and_Extension__Remote_-_SSH_—_isucon9q_and_____zsh_-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28262/88391770-ee8d-5e53-8424-a6c5adeba957.png">

うまくいくと上の図のようにfooterの色が変化します。

※ 今回は前段のnginxがupstreamの8000ポートにリクエストを渡すので8000ポートでsinatraを起動しています。

### 4. ステップ実行する

任意の止めたい場所にブレイクポイントを入れ、該当箇所が通るようなコードを実行します。

<img width="1153" alt="web_rb_—_webapp__SSH__s1__and_Extension__Remote_-_SSH_—_isucon9q.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28262/9fd1c2cc-439c-6547-66ec-d87f8a734765.png">

ブレイクポイントで処理が止まり、変数の確認やコードの実行、ステップ実行が可能になります。

## おわりに

VSCode便利すぎて最近RubyMineからVSCode一本にしようかなと考えたりしてます。来年こそはISUCONなんとかしたい。
ASP.net 

#ASP.net とは？

Microsoftが提供しているフレームワーク

# ASP.net Core 

適宜バージョンアップ

# EntityFramework 

端的に言うと
「.NET Framework」のコンポーネント

利点：オブジェクト操作をSQLなどのDB操作に自動変換してくれる。

# Code First

「Plain Old CLR Object」 
データ構造を定義したクラスを元にEntity Frameworkが自動でテーブルを生成してくれる優れもの

```C#:Person.cs
public class Person 
{
  public string id;
  public string name;
  public string age;
  public string gender;
}
```

上記の様にデータ構造を記述したファイル（Model）を作成することでDBのテーブルを作成してくれる。（※テーブル作成にはマイグレーションの実施が必須）
Salesforceで全角・半角の変換メソッド

Salesforceでの半角・全角の変換について、色々と調べたのでまとめておきます。

#既存情報で見つけた手法
少し古い記事ですが、下記リンクの記事でMapを使用して、半角→全角、全角→全角の変換を行うメソッドが紹介されていました。
https://salesforce.oikeru.com/entry/to_full_width

このコードをコピペすれば簡単にできるのですが、あまりスッキリとした感じではないので、もっとコンパクトにまとまらないかなとその他の情報を調べてみました。

#結論
Unicodeのコードポイントを利用した下記のメソッドで半角・全角の変換が出来ました。

```
public class ReplaceChar {
    
  /** 半角アルファベットを全角アルファベットに変換するメソッド */
    public static String repleceAlphabetHalfToFull(String str) {

        List<Integer> codePointList = new List<Integer>();

        for (integer i = 0; i < str.length(); i++) {
            // 文字のコードポイント取得
            Integer codePoint = str.codePointAt(i);

            if (65 <= codePoint && codePoint <= 90) {
            // 半角アルファベット大文字は全角大文字に変換してリストに追加
                codePoint += 65248;
                codePointList.add(codePoint);
            } else if (97 <= codePoint && codePoint <= 122) {
            // 半角アルファベット小文字は全角小文字に変換してリストに追加
                codePoint += 65248;
                codePointList.add(codePoint);
            } else {
            // 半角アルファベット以外はそのままリストに追加
                codePointList.add(codePoint);
            }
        }

        return String.fromCharArray(codePointList);
    }
}
```

上記メソッドで半角→全角の変換ができます。
全角→全角の変換はコードポイントの範囲を変更して、65248を引くだけで行えます。
Mapを作るメソッドよりはスッキリした作りだと思います。
また、半角・全角のアルファベットだけでなく数字や記号にも柔軟に対応できそうです。
Salesforceにおいて、全角・半角の変換は使用画面が限れれると思いますが、必要であればぜひ使用してみてください。

#おまけ
###Salesforceにおける半角・全角の取り扱いについて
　Salesforceでは、SOQLやApexによってアルファベットの小文字/大文字、半角/全角などの取り扱いが違います。
詳しいことは下記リンクを参考に。

[リンク]https://www.terrasky.co.jp/blog/2014/140204_001333.php

　一例を上げると、Mapのgetメソッドやcontainskeyメソッドでは全角と半角が区別されるため、Map内のキーと引数で渡す値が一致しない場合、期待した値が取り出せません。

###どんな場面で使用するか
　Salesforceでは、各項目に入力される値は柔軟に制限できるため、入力の際に半角に制限するなどシステムの設計をしておけば上記のメソッドは必要ないと思います。
　しかし、要件次第ではそのような設計ができなかったり、すでに入力されたデータがあって一致していない場合などに、このメソッドを使用するだけで入力された値に関係なく処理を行えるので、そのようなときに使用できるのではないかと思います。
複数の図形にテキストを流し込むExcelマクロ

##これは
Excelで資料を作成するときに便利かもしれない、ちょっとしたマクロです。

何かを図解する資料を作ろうとしたとき、
図形を挿入して、右クリックで「テキストの編集」を選んで、、、
というのを繰り返すのが煩わしくなったのです。

そこで、先に図形だけ配置しておいて、
テキストは後からマクロで一気に流し込むことにしました。

[以前作った図形の位置調整マクロ](https://qiita.com/jinoji/items/497007ccbae88ec1432c) を応用する形で作りました。
そちらと併用するとより便利かもしれません。
資料を作るときだけでなく、あとで修正したりするときにも重宝します。

##動作のイメージ
1. 図形を選択した状態でマクロを実行します。
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164214/906cf8e7-eb28-00a7-10e8-ca6159ad5fd5.png)

2. 流し込む文字列をセル範囲で指定します。
![pic2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164214/d5800fba-99fb-33cf-6486-b68c6bc923c0.png)

3. こうなります。
![pic3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164214/a3983e52-f927-7e62-8590-38134d6f50e8.png)


##コード
```vb
Sub 図形に文字列を流し込む()
    On Error Resume Next
    Dim shp As ShapeRange, rng As Range
    With ActiveWindow
        Set shp = .Selection.ShapeRange
        If shp Is Nothing Then If MsgBox("図形を選択した状態で実行してください") = vbOK Then Exit Sub
        Set rng = Application.InputBox("流し込む文字列を指定", "セル範囲選択", .RangeSelection.Address, , , , , 8)
        If rng Is Nothing Then Exit Sub
    End With
    Dim c As Range, i
    For Each c In rng
        i = i + 1
        If i > shp.Count Then Exit Sub
        shp(i).TextFrame.Characters.Text = c.Value
    Next
End Sub

```
Windows 10上でHyper-Vを使ってminishiftをセットアップ

minishiftをWindows 10でセットアップする必要があったので書いておきます。
Windowsでのminishiftはvirtualboxでやっている例が多いのですがその場合Hyper-Vを無効にしなければいけなく、他のHyper-Vを使うツールが使えなく不便です。そしてHyper-V使ってminishiftは日本語情報が少ないので書いておきました。と言ってもそんなには難しくはないです。（２０１９年９月５日現在）

今回やるのは
-minishiftのダウンロード、パスの設定
-Hyper-Vの有効化および設定
　有効化は再起動が必要な場合があります。
　設定は、Hyper-V administratorグループへのユーザーの追加、仮装スイッチの追加です。
minishiftの起動

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/6cd9c921-a5d8-c1cd-687a-13e1a45c687d.png)


-minishiftのダウンロード、パスの設定
　minishiftはこちらからダウンロードしてください。
https://github.com/minishift/minishift/releases
Windows版はminishift-1.34.1-windows-amd64.zipですね。
ダウンロードしたファイルを解凍、任意の場所においてください。（ここでは C:\minishift 配下）
次に以下のようにパスを追加します。
コントロールパネルを開いて システムとセキュリティー->システム-> システムの詳細設定で環境変数をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/bf0b3679-b86c-0221-8a57-312c66e1c058.png)

システム環境変数のPathを選択編集をクリックして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/1ae6e660-70f7-78ae-93e8-32b3a9a54d11.png)
以下のように”C:\minishift”を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/73589616-9d28-d61f-d84d-6ac4ecbb5136.png)
OKをクリックして追加するとPower Shellでminishiftが起動できるか確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/30fb1924-b30c-be96-45c4-d0bd0fd3e21b.png)


-Hyper-Vの設定
コンピューターの管理を起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/392980dc-a0d7-149a-6b36-978b36472d45.png)

Hype-V Administratorを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/c7e0231f-665b-58d9-6a11-be4a61f93a05.png)

ユーザー（ここではosonoi)を登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/4960c4fb-0118-d178-2f21-5d660bd5562c.png)

次に仮想スイッチの追加です。Hyper-Vマネージャーを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/cb9e926d-3740-4bb3-04f0-8c41ae3c2dac.png)

右の項目から仮想スイッチマネージャーを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/b8d95917-f2ae-1a3f-f424-b64d2aaa1872.png)

"External VM Switch"を以下のように追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/af6d4d65-36fa-62ee-ff93-8d2e90d856d6.png)

以上で準備は完了です。
パワーシェルから以下のコマンドでminishiftを起動してください。

minishift start --hyperv-virtual-switch "External VM Switch" 


問題なく起動するとURLが表示されるのでブラウザーでアクセスしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59741/8e08f207-37c4-b811-69e9-8e47055590ed.png)
Photonに接続する

##はじめに
この記事は参考記事のほぼ丸パクリです。アウトプットになります。

##Photonとは
マルチプレイ用のサーバーで、インターネットを通してサーバーに接続します。
今回はUnityで行います。

##Photonのユーザー登録からAppID取得までの流れ

１．下記のリンクからユーザー登録を行ってください。
https://dashboard.photonengine.com/ja-JP/account/SignUp

２．新しくアプリを作成するを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/f8b40a9a-01a4-6076-98f4-c78e3f23cb94.png)

３．必須項目を入力して作成するを押す(Photonの種別はPhoton Realtime）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/a38a1d3f-0b5d-d939-eeb6-d189e82fbf47.png)

４．アプリケーションIDが取得されたのでコピーする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/10e35bdc-829f-177a-d3fe-de4df0c1273a.png)


##Photon Unity Networking 無料版の操作手順
１．Photon Unity Networking 無料版をインストール&インポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/ebf9f409-146e-f2fd-8b7e-d915dd822c2e.png)

※PUN 2では以降の手順ができません。

２．AppIDを入れてSetup Projectボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/c9d823c9-92d9-287a-542a-611f90e4f908.png)

成功するとDoneの文字が出るので、出たはCloseを押して閉じる。

３．PhotoServerSettingsで黄色の設定にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/83dce91c-419d-1a28-dccb-ff947515537d.png)

##スクリプト作成と実行

以下のスクリプトを入れる。これは参考サイトのほぼ引用になります。

~~~C#
public class NetWork_01 : MonoBehaviour {

	void Start() {
        // Photonに接続する(引数でゲームのバージョンを指定できる)
        PhotonNetwork.ConnectUsingSettings(null);
    }
 
    // ロビーに入ると呼ばれる
    void OnJoinedLobby() {
        Debug.Log("ロビーに入りました。");
 
        // ルームに入室する
        PhotonNetwork.JoinRandomRoom();
    }
 
    // ルームに入室すると呼ばれる
    void OnJoinedRoom() {
        Debug.Log("ルームへ入室しました。");
    }
 
    // ルームの入室に失敗すると呼ばれる
    void OnPhotonRandomJoinFailed() {
        Debug.Log("ルームの入室に失敗しました。");
 
        // ルームがないと入室に失敗するため、その時は自分で作る
        // 引数でルーム名を指定できる
        PhotonNetwork.CreateRoom("myRoomName");
    }
}
~~~

このスクリプトをヒエラキーのオブジェクトにアタッチして再生ボタンを押してみる。

コンソールで以下の表示が出れば成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307841/26f155cc-44af-420d-dff6-d9c98df4c1fe.png)


##おわりに
Photonの参考サイトはいくつかあるが、違うソフトをインポートしてしまったが為にそれなりに時間がかかた。Pun2の設定項目はPhoton Unity Networkingとかなり似ている。公式はPUN 2を推奨しているようなので、使う機会があれば是非ためしておきたい。


##参考サイト
TechPin：https://tech.pjin.jp/blog/2016/07/20/unity_pun_1/
AWS AppSyncでリソースへのアクセス制限を実現する

# 概要

AWS AppSyncはAWS上にGraphQLサーバーを構築することができるマネージドサービスです。
APIを作る場合、「リソースの作成・編集・削除は、そのリソースを作成したユーザーしか許可しない」というような認可の仕組みが必要になります。

今回はAWS AppSyncをGraphQLサーバーとして使う場合の認可の実装方法をまとめてみたいと思います。
なお、AWS AppSyncのデータソースにはAWSのNoSQLデータベースであるAmazon DynamoDBを使います。

# DynamoDBのスキーマ設計だけで実現できるパターン

Amazon DynamoDBはNoSQLデータベースで、テーブルのデータはあらかじめ設定したハッシュキーと任意で設定できるソートキーを使ったシンプルなクエリしかできません。

そのDynamoDBの設計によってアクセスできるリソースを制限することができます。

例として、`User`と`Post`というモデルを持つアプリケーションを考えます。
`User`は`Post`を複数作成することができます。

**`User`モデルが持つ情報**

|属性|役割|
|----|----|
|id|ユーザーごとに一意なID|
|name|ユーザー名|

**`Post`モデルが持つ情報**

|属性|役割|
|----|----|
|id|投稿ごとに一意なID|
|content|投稿の本文|
|userId|投稿したユーザーのID|

これをAmazon DynamoDBに格納するとき、以下のような2つのテーブルを設計したとします。

**`UserTable`**

|属性|型|テーブル|
|----|----|----|
|id|String|Hash Key|
|name|String||

**`PostTable`**

|属性|型|テーブル|
|----|----|----|
|id|String|Hash Key|
|content|String||
|userId|String||

これに対して、「あるユーザーの投稿を取得したい」というアクセスパターンを実現するには、以下のようなGSIを作成します。

**`PostTable`**

|属性|型|テーブル|userId-index|
|----|----|----|----|
|id|String|Hash Key||
|content|String|||
|userId|String||Hash Key|

これで、`PostTable`に対して、`userId = ?`という検索が行えるようになりました。

AWS AppSyncでDynamoDBをデータソースにしたリゾルバーを作るとき、以下のようにリクエストマッピングテンプレートで指定することでインデックスに対してクエリを行うことができます。

```text:リクエストマッピングテンプレート
{
  "version": "2017-02-28",
  "operation": "Query",
  "index": "userId-index", ## インデックス名を指定
  "query": {
    "expression": "userId = :userId",
    "expressionValues": {
      ":userId" : $util.dynamodb.toDynamoDBJson($ctx.identity.sub), ## セッション中のユーザーIDを取得
    },
  },
}
```

リゾルバーで使える`$ctx`変数には、セッション中のユーザーの情報が含まれています。
AWS AppSyncの認証モードを`Cognito User Pools`にしている場合は、`$ctx.identity.sub`でCognitoユーザープールでのユーザーIDを取得することができます。
今回の例では、`Post`の保存時に`userId`属性にこの`$ctx.identity.sub`をリゾルバーでセットしている前提になります。

こうすることで、シンプルにユーザーのリソースに対するアクセス制限を実現できました。

一人のユーザーに結びつくようなモデルを扱う場合、テーブルのハッシュキーを`userId`にすると扱いやすくなることが多い印象です。

# レスポンスマッピングテンプレートで認可を制御するパターン

「データソースから取ってきたデータによって、それをセッション中のユーザーが見られるかどうかが決まる」というケースは、このレスポンスマッピングテンプレートで制御するパターンが適用できるかもしれません。

先ほどと同じモデルを想定して、以下の例を考えます。

`Post`は、基本的には作成したユーザーしか閲覧できない。しかし、`Post`に`public: true`という属性がセットされている場合は、作成者以外のユーザーでも閲覧することができる。

この場合、セッション中のユーザーが要求した`Post`にアクセスできるかどうかは、実際にDynamoDBからデータを取ってきてから決まります。
リクエストマッピングテンプレートはデータソースにデータを取得するための命令を書くので、まだデータソースからデータは得られていません。

そこで、レスポンスマッピングテンプレートを使います。
`Post`をIDで指定して1件取得する`getPost`というGraphQLクエリのリゾルバーは、以下のように実装することができます。

```text:リクエストマッピングテンプレート
{
  "version": "2017-02-28",
  "operation": "GetItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($ctx.args.id),
  },
}
```

```text:レスポンスマッピングテンプレート
## 該当するアイテムが見つからなかった場合
#if(!$ctx.result)
  null
#end

## セッション中のユーザーのものではない and アイテムのpublic属性がセットされていなかった場合
#if($ctx.result.userId != $ctx.identity.sub && !$ctx.result.public)
  $util.unauthorized()
#end

$util.toJson($ctx.result)
```

# まとめ

他のデータソースにデータを取得して、それを使って認可を行うにはパイプラインリゾルバーが使えます。
パイプラインリゾルバーを使った認可の方法はまた別の記事でまとめたいと思います。
Python 環境構築（Mac）

2019.09.08 作成。

[『直感 Deep Learning』のリポジトリ](https://github.com/oreilly-japan/deep-learning-with-keras-ja)で環境構築しようとしたが上手くいかなかったのでメモ。

結果から言うとかなり面倒だった。



## 予備知識

Mac 使用、homebrew 使用。

- pyenv : python のバージョンを自由に切り替える
- pyenv-virtualenv : python の仮想環境を構築する

Python はバージョン2と3で使い分ける事が多いので、環境の切り替えが重要らしい。



## インストール

まずは pyenv, pyenv-virtualenv（そして python）をインストールする。

```sh
$ brew install pyenv
$ brew install pyenv-virtualenv
$ pyenv install 3.6.0
$ pyenv rehash
$ pyenv local 3.6.0
```

local のバージョンを設定すると、.python-version という設定ファイルが生成される。



ただ、pyenv をインストールしただけでは使えるようにならない。PATH を通す必要がある。

また、pyenv-virtualenv をインストールすると、

```sh
To enable auto-activation add to your profile:
  if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
```

と言われる。これは仮想環境の起動を簡略化できる記述らしい。（本来、virtualenv では仮想環境の起動に `$ pyenv activate` が必要とのこと。）

 というわけで、~/.bash_profile を更新する。

```shell:.bash_profile

# pyenv の設定
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# pyenv の auto-activation を有効化する
if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi
```

.bash_profile を更新したら、適用もしておく。

```sh
$ source ~/.bash_profile
```



 

## 仮想環境の構築

準備ができたので、python の仮想環境を構築する。コマンドは `$ pyenv virtualenv {バージョン} {環境名}` 。


```sh
$ pyenv virtualenv 3.6.0 env_python3.6
Requirement already satisfied: setuptools in /Users/xxx/.pyenv/versions/3.6.0/envs/python3.6/lib/python3.6/site-packages
Requirement already satisfied: pip in /Users/xxx/.pyenv/versions/3.6.0/envs/python3.6/lib/python3.6/site-packages
```

作られた環境は、バージョン一覧で確認できる。

```sh
$ pyenv versions
  system
* 3.6.0 (set by /Users/xxx/git/deep-learning-with-keras-ja/.python-version)
  3.6.0/envs/python3.6
  python3.6
```

一覧を見ると、pyenv でインストールしたバージョンと、virtualenvで構築した環境（python3.6）が並んでいる。

最後、カレントディレクトリで構築した環境（python3.6）を使用するように設定。

```sh
$ pyenv local python3.6
(python3.6) ~/git/deep-learning-with-keras-ja (master)
$ python -V
Python 3.6.0
$ pip -V
pip 9.0.1 from /Users/xxx/.pyenv/versions/3.6.0/envs/python3.6/lib/python3.6/site-packages (python 3.6)
```
先頭に仮想環境の名前が表示されるようになった。

他のディレクトリでは元の Python 2.7.10 が使われている。

```sh
(python3.6) ~/git/deep-learning-with-keras-ja (master)
> cd ..
~/git
> python -V
Python 2.7.10
```

local だけでなく grobal 設定もあるようだが、今は必要ないので環境構築は一旦これで完了。
mapについて自分用にまとめておく

最近競技プログラミング問題を解いているのだけど、焦っているとifやforで書きがちになるので、真の意味でmapやfilterも使える状態になっていないと気づきました。
そういった訳でよく使うJSとPythonのコードを自分用にまとめておきます。

まずはmapの基礎おさらい

```Javascript:Javascript
var numArray = [1,2,3];
var newArray = numArray.map(x => x*3);

console.log(newArray);//[2,4,6]
```

Python

```py:Python3

numList = [1,2,3]
newList = map(str, numList)
print(list(newList))
#['1','2','3']
```

Pythonはmap関数の結果はリストにならないため、list()関数でリスト化など施す必要があります。
だからたとえば数値計算を施したいとき、

```py:Python3
numList = [1,2,3]
print(map(lambda x: x*3, numList))
#<map object at 0x10aaadf28>

```
これだとmapのイテレータ（直接値が操作できない状態）が返ってくるため、

```py:Python3
numList = [1,2,3]
print(list(map(lambda x: x*3, numList)))
#[3,6,9]
```

という具合にlist関数を通さないと、値が直接演算されません。


JSばかり弄っているとPythonの値の扱い方をうっかり忘れがちなので、気をつけたい……。
Jenkinsで複数GKEに並列でシェル実行する時にdockerで実行しないと危ない

# 要約

1. Kubernetesへ、Jenkins（not Jenkins X）でデプロイするときのお話
2. 何も気にせずに、シェル実行のjobを並列して実行すると  
  <font color="Red">Kubernetesのcontextがjobをまたいで切り替わって、誤デプロイしちゃう時がある</font>
3. シェル実行で、dockerをそれぞれ起動すれば、解決したよ。

# 目的・背景

1. JenkinsでKubernetesにシェルスクリプトでデプロイしたい
2. 1つのJenkinsサーバーから、環境別のKubernetesへデプロイしたい
3. Jenkinsのjob毎に、Kuberenetesのcontextを分けたい
4. Jenkinsの実行環境自体も管理したい
5. Jobを並列実行して、効率的にデプロイしたい

# やったこと

## dockerfile

```dockerfile
# google-cloud-sdkだと、デフォルトpython3.5だったので、3.7がほしかった。（※1）
FROM python:3.7

# timezone
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

# google-cloud-sdk
RUN pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib pandas \
    && curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz  \
    && mkdir -p /usr/local/gcloud \
    && tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
    && /usr/local/gcloud/google-cloud-sdk/install.sh

# gcloudのコマンドのPATHを通す
ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin

# helmもほしい。
RUN curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
RUN helm init -c

# kubectlももちろんほしい。
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl \
    && chmod +x ./kubectl \
    && mv ./kubectl /usr/local/bin/kubectl

CMD ["/bin/sh"]
```

```bash
docker build -t jkkitakita/gcloud-sdk-python37-helm:latest .
docker push jkkitakita/gcloud-sdk-python37-helm:latest
```
https://cloud.docker.com/repository/docker/jkkitakita/gcloud-sdk-python37-helm

## jenkins

1. ビルド並列設定の変更
    - 「Manage Jenkins」->「Configure System」->「Maven Project Configuration」->「# of executors」
    - 1を2以上に変更
2. フリースタイルプロジェクトのjobを作成
3. シェルスクリプトを追加（※2）
    - `GCLOUD_SERVICE_KEY`は、外から適切なcredentialsのkeyを渡してあげる
    - `ENV`はJenkinsのJobの引数で渡してあげる

```bash
#!/bin/bash

export IMAGE="jkkitakita/gcloud-sdk-python37-helm:latest"

docker run \
    -v $WORKSPACE:/workspace \
    -w /workspace \
    -e GCLOUD_SERVICE_KEY=${GCLOUD_SERVICE_KEY} \
    $IMAGE /bin/bash -ex ./deploy.sh -e ${ENV}
```

もちろんこれでpipelineを設定してもokだと思います。

# さいごに

あまり

- Kubernetes
- Jenkins（not Jenkins X)
- シェル実行（not Jenkins pipeline（※3））

の例がないので書いてみました。
[Jenkins x Kubernetesが簡単だと思ったら大変だった話](https://www.slideshare.net/YamamotoMasaki/jenkins-x-kubernetes)みたいにあるように
あまりGood Practiceとは言い難いですが
個人的にはまだまだ

- やっぱりJenkinsに慣れている
- Jenkinsfileとか書かずに、さくっとシェルで実行したい

みたいなニーズもあるような気がしました。
以上です。

# 参考

※1 [Python 3.7とgoogle cloud sdkが入ったDockerコンテナ](https://gadgeterkun.hatenablog.com/entry/20190822/1566477227)
※2 [Dockerを使ってJenkinsのジョブごとにテスト実行環境を分離する](https://orangain.hatenablog.com/entry/jenkins-docker)
※3 [JenkinsのビルドをDockerコンテナで実行する](https://rixwwd.hatenablog.jp/entry/2018/08/26/205905)
初心者の備忘録

初心者のメモ的なアレ

Sub テキストを読み込む処理()
    Dim buf As String, n As Long
'EOF (ファイル番号)、このファイル番号は重複を避けるために行うんだってさ
    Open "パス" For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            n = n + 1

            Cells(n, 1) = buf
        Loop
    Close #1
End Sub

Sub スペースで区切る()
    Dim i As Long, tmp As Variant
    m = Cells(Rows.Count, 1).End(xlUp).Row
    For i = 1 To m
        tmp = Split(Cells(i, 1), " ")
        Cells(i, 2) = tmp(0)
        Cells(i, 3) = tmp(1)
    Next i
End Sub
Goでログ出力/標準出力をテストする

Goのlogパッケージや標準出力内容の結果をテストをしたいときのメモ。

# ログ出力のテスト

Goのlogパッケージの`log.PrintXX`のログ出力先はデフォルトでは`os.Stderr`ですが、[log.SetOutput](https://golang.org/pkg/log/#SetOutput)によって出力先を変更することができます。

```go:log.SetOutput
func SetOutput(w io.Writer)
```

テストする関数は以下の通りです。

```go:trysail.go
type member int

const (
	mocho member = iota
	sora
	nansu
)

func printLog(m member) {
	switch m {
	case mocho:
		log.Print("(o・∇・o)終わりだよ〜")
	case sora:
		log.Print("(°Ｑ`)")
	case nansu:
		log.Print("(*>△<)<ナーンナーンっっ")
	}
}

```

引数によって出力するログの内容が変わる単純な関数です。

ではテストコードを書いてみましょう

```go:trysail_test.go
func Test_printLog(t *testing.T) {
	// ログの出力先をバッファに変更
	var buf bytes.Buffer
	log.SetOutput(&buf)
	// デフォルトだと日付が出力されてしまうので、フラグに0を設定する
	defaultFlags := log.Flags()
	log.SetFlags(0)
	// Test_printLogテスト終了時、変更した内容を戻す
	defer func() {
		log.SetOutput(os.Stderr)
		log.SetFlags(defaultFlags)
	}()
	t.Run("Mocho", func(t *testing.T) {
		// 次のテスト(Nansu)に影響がないように、Mochoテスト終了時にバッファの内容をクリアする
		defer func() {
			buf.Reset()
		}()

		printLog(mocho)

		expected := "(o・∇・o)終わりだよ〜"
		// 末尾に改行コードが入っているので除去する
		actual := strings.TrimRight(buf.String(), "\n")
		if actual != expected {
			t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
		}
	})
	t.Run("Nansu", func(t *testing.T) {
		defer func() {
			buf.Reset()
		}()

		printLog(nansu)

		expected := "(*>△<)<ナーンナーンっっ"
		actual := strings.TrimRight(buf.String(), "\n")
		if actual != expected {
			t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
		}
	})
}
```

# 標準出力のテスト

なんと、Go言語の標準出力や標準入力である`os.Stdout`や`os.Stderr`は`os.File`で上書きすることができます。マジかよ…

`os.File`を`bytes.Buffer`につなぐために`os.Pipe`を利用します。

テストする関数は以下の通りです。

```go:trysail.go
type member int

const (
	mocho member = iota
	sora
	nansu
)

func print(m member) {
	switch m {
	case mocho:
		fmt.Println("(o・∇・o)終わりだよ〜")
	case sora:
		fmt.Println("(°Ｑ`)")
	case nansu:
		fmt.Println("(*>△<)<ナーンナーンっっ")
	}
}

```

先ほどの関数の`fmt.Println`版です。
`fmt.Println`は`os.Stdout`に書き込むので、そちらを`bytes.Buffer`にPipeします。

```go
func Test_print(t *testing.T) {
	tmpStdout := os.Stdout
	defer func() {
		os.Stdout = tmpStdout
	}()
	t.Run("Mocho", func(t *testing.T) {
		r, w, _ := os.Pipe()
		os.Stdout = w

		print(mocho)
		w.Close() // クローズしないと永遠に読み込み待ち状態になるよ

		var buf bytes.Buffer
		buf.ReadFrom(r)

		expected := "(o・∇・o)終わりだよ〜"
		actual := strings.TrimRight(buf.String(), "\n")
		if actual != expected {
			t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
		}
	})
	t.Run("Nansu", func(t *testing.T) {
		r, w, _ := os.Pipe()
		os.Stdout = w

		print(nansu)
		w.Close()

		var buf bytes.Buffer
		buf.ReadFrom(r)

		expected := "(*>△<)<ナーンナーンっっ"
		actual := strings.TrimRight(buf.String(), "\n")
		if actual != expected {
			t.Fatalf("failed! actual = %s, expected = %s", actual, expected)
		}
	})
}
```

意外と簡単にできた。
(o・∇・o)終わりだよ〜
コードのみでView(四角)を作って画面に配置する(kotlin, 基本)

#はじめに
探せばすぐでてきそうなものなのになんかでてこなかったのでここに残しておきます！！
見た目の参考↓
<img width="835" alt="スクリーンショット 2019-09-08 22.53.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133940/20d50cba-073b-e8f5-b02e-81e78cc77e55.png">


#コード
```.kotlin
val sampleView = View(this);
sampleView.setBackgroundColor(Color.RED)

addContentView(sampleView, ViewGroup.LayoutParams(20, 40));

sampleView.setX(300.0F)
sampleView.setY(300.0F)

val sampleView1 = View(this);
sampleView1.setBackgroundColor(Color.BLUE)

sampleView1.setAlpha(0.3F);

addContentView(sampleView1, ViewGroup.LayoutParams(120, 140));

sampleView1.setX(100.0F)
sampleView1.setY(100.0F)
```

サイズの変更あとでしたいなって時↓

```.kotlin
sampleView1.layoutParams.width = 300;
sampleView1.layoutParams.height = 300;
```

#参考
http://atmarkplant.com/blackview-android/
https://www.javadrive.jp/android/textview/index4.html
https://qiita.com/titoi2/items/7bf271cd17beae74620b
[crowi]学科の情報共有wikiとしてcrowiを導入しよう

# 経緯
今の学科に入って1年経つけど、常日頃から「この情報あったらもっとうまいことやれたのにな」とか思わされることが多いので、とりあえず今年一年の内容をwikiにまとめようかなと思った次第です。だからちょくちょく更新していきたいな…(2019/9/7)

#そもそもmacでサーバーを立てて良かったのかな？
Linuxの方がサーバーとして有能らしい?ので、その上で立てるべきだったかな？その辺りの演習もできるしなあ

#herokuについて
crowiはサーバを立てる必要があるらしかったので、最初はcrowiのgithubとか見て奮闘しましたが、どうにもエラーが出るので、キャッシュカードの情報とか入れてheroku(サーバを立ててくれるサービス)を使ってデプロイしました。

#bonsaiについて
今ここで悩んでます。検索しようとするとエラー(error on searching!)が出ちゃうのでその解決法を探しています。元あったbonsaiを消して、新しいbonsaiをaddonに追加したらok！と思っていたら、そこからさらにinstallしないといけないっぽいことに気づきました

その後(以下のコマンドで)herokuのCUI(?)を入れて
`$ curl https://cli-assets.heroku.com/install.sh | sh`
その後`heroku login`でログイン
そして
` heroku addons:create bonsai`
みたいなことをしたら
`Error: Missing required flag:`
これですわ　キレそう
### 改善策
・まずgitにログインしてください
その後
` $ git init `
のコマンドを打つと良さそうです(意味はわかってない)

・要するにどのアプリケーションにaddonするの？って聞かれてたらしいので、
` heroku addons:create bonsai -a (アプリ名)`
とするとできました
ちなみにアプリ名は`heroku apps`で確認できます


#??
入れ直したけど治ってない…？そもそもindex-buildが終わらないんですが…
index-buildのボタン押して"now rebuild~~"って出たら終わってるらしい　それなのに検索機能動かん　わからん
ベイズで変化点検知する(ガンマ-ポアソン分布)

#概要
ガンマ-ポアソン分布を使ったベイジアンモデリングを組みたかったので、やってみた。
良い感じのカウントデータを探したが(ポアソン分布使いたかったので)、なかなか見つけられなかったので、
今回は、google trendで「米津玄師」の直近90日間の検索数のcsvを出力した。
https://trends.google.co.jp/trends/?geo=JP
出力データに対して、ベイジアンモデリングを行い、変化点検出を行った。

#直近90日の「米津玄師」検索数
2019年8月あたりから、検索数が増えている。
![yonezu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371779/aebfff25-e835-b1be-0134-d5ee8e963ea9.png)
#結果
pymc3のサンプリング結果。
![bayes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371779/5c219b33-3193-a861-217d-201e05b546a3.png)
可視化。ちゃんとトレンド検知できているよう。
![change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371779/2d95a117-c541-d74c-a44a-6b79ab75a831.png)

#コード
```python
import pandas as pd
import numpy as np
import pymc3 as pm
import matplotlib.pyplot as plt

#前処理
df = pd.read_csv("../desktop/yonezu.csv")
df["日"] = pd.to_datetime(df["日"])
df.index = df["日"]
df.drop(["日"], axis=1, inplace=True)

#モデリング
weeks = df.reset_index().index
with pm.Model() as model:
    switchpoint = pm.DiscreteUniform('sp', 
                                     lower=weeks.min(),
                                     upper=weeks.max())
    lambda1 = pm.Gamma('lambda1', alpha=1, beta=1)
    lambda2 = pm.Gamma('lambda2', alpha=1, beta=1)
    lambda_ = pm.math.switch(switchpoint>=weeks, lambda1, lambda2)
    k = pm.Poisson('k', lambda_, observed = df["米津玄師"].values)
with model:
    trace = pm.sample(10000)
burnin = 100
chain = trace[burnin:]

#出力
pm.traceplot(chain)
df["bayes"] = np.hstack([np.array([chain.lambda1.mean()] * int(chain.sp.mean())), np.array([chain.lambda2.mean()] * (df.index.size - int(chain.sp.mean())))])
df.plot(subplots=False, sharex=True, figsize=(10, 8), title="ベイズによる米津玄師の変化点検知")
```
#感想
変化点検知、実データ分析でかなり有用そうなので、もっと慣れたい。
もっと凝ったことをやりたい。
#参考
http://machine-learning.hatenablog.com/entry/2017/08/19/200841#f-d375c286
javascript ドットインストール復習　~ヘルスケアwebサービスを自分で作る医者の日記~

[ドットインストール](https://dotinstall.com/)
を復習中
最終回のソースコードをチラ見して、
できる限り再現するように書く。

シンプルなアプリだが、まずはこれをひとつ。

```javascript:main.js
 'use strict;'

 {
   const btn = document.getElementById('btn');
   btn.addEventListener('click', () => {
     const n = Math.random();
     if (n < 0.05 ) {
       btn.textContent = '小吉';
     }else if(n < 0.20 ){
       btn.textContent = '中吉';
     }else{
       btn.textContent =  '大吉';
     }
   });
 }
```
```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>おみくじ</title>
    <link rel="stylesheet" href="css/styles.css">
  </head>
  <body>
    <div id="btn">?</div>
<script src= "js/main.js">

</script>
  </body>
</html>
```
Pythonでスクレイピングしてニフティクラウドに格納

# ymlファイルの作成
まずは、NiftyCloudのAPIキーをコピペして、ymlファイルを作成します。

```yml:nifty_cloud.yml
APPLICATION_KEY: 'your_application_key'
CLIENT_KEY: 'your_client_key'
```

# ChromDriverをダウンロード
次に、[ここ](https://chromedriver.chromium.org/downloads)からChromDriverをインストールします。

# 今回スクレイピングするサイト
https://www.walkerplus.com/event_list/eg0135/
お祭りの情報をスクレイピングして、その情報をニフティクラウドに格納したいと思います。

# Pythonで走ろう！
上の2つのファイルはこれから走らせるコードと同じ作業ディレクトリに置きます。

```python:code.py
from py_nifty_cloud.nifty_cloud_request import NiftyCloudRequest
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from time import sleep
```
```python:code.py
driver_path = "/Users/＊＊＊＊＊＊＊＊/chromedriver"
driver = webdriver.Chrome(driver_path)
driver.get("https://www.walkerplus.com/event_list/eg0135/")
sleep(10)
```
お祭りの日付をスクレイピングします。
<img width="1260" alt="スクリーンショット 2019-09-08 21.37.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435522/925a2a29-540d-f161-ef20-271ac70e44ec.png">

サイトの中で、日付はここにありますね！
クラスの名前で指定して、日付の値を取得します。


```python:code.py
dates = driver.find_elements_by_class_name("m-mainlist-item-event__period")
date_list = []
for i in range(len(dates)):
    date = dates[i].text
    date_list.append(date)
print(date_list)
```
結果がこちら。

```python
['2019年9月27日(金)・28日(土)', '終了間近 2019年9月15日(日)', '2019年9月14日(土)～20日(金)', '2019年9月21日(土)～25日(水)', '終了間近 2019年9月14日(土)・15日(日)', '終了間近 2019年9月7日(土)・8日(日)', '終了間近 2019年9月14日(土)・15日(日)', '終了間近 2019年9月13日(金)', '2019年9月21日(土)・22日(日)', '終了間近 2019年9月7日(土)～9日(月)']
```

次は、お祭りの場所をスクレイピングします。同じようにクラスの名前を指定して、値を取得します。

```python:code.py
places = driver.find_elements_by_class_name("m-mainlist-item-event__place")
place_list = []
for i in range(len(places)):
    place = places[i].text
    place_list.append(place)
print(place_list)
```
```python
['武蔵総社 大國魂神社', '石清水八幡宮', '柞原八幡宮', '大原八幡宮', '山陽電車高砂駅南側一帯', '北澤八幡神社', '武蔵野八幡宮', '住吉大社', 'JR恵那駅前周辺', '山梨県上野原市上野原']
```

お祭りのタイトルもスクレイピングしちゃいます。

```python:code.py
titles = driver.find_elements_by_class_name("m-mainlist-item__ttl")
title_list = []
for i in range(len(titles)):
    title = titles[i].text
    title_list.append(title)
print(title_list)
```
```python
['大國魂神社くり祭', '勅祭 石清水祭', '柞原八幡宮 仲秋祭・浜の市', '大原八幡宮 放生会', 'たかさご万灯祭2019', '北澤八幡神社例大祭', '第47回 吉祥寺秋祭り', '住吉大社 観月祭', '2019 ENAみのじのみのり祭', '牛倉神社例大祭']
```
# ニフクラのデータストアに格納

```python:code.py
ncr = NiftyCloudRequest('./nifty_cloud.yml') #application keyとclient keyを書いた、ymlファイルを作成しておく。
path = '/classes/Festival'
method = 'POST'

#格納
for i in range(len(date_list)):
    values = {'date': date_list[i],'place': place_list[i],'title': title_list[i]}
    
    response = ncr.post(path=path, query=values)
print(response.status_code)
```
```
201
```

# ニフクラのデータストアを確認
<img width="964" alt="スクリーンショット 2019-09-08 21.35.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435522/a3227c85-e6b6-f319-185c-046253984cce.png">

お祭りの情報が格納できています！！
Visual Studio Code (VScode) においてEmmet でHTML5 を入れるときにlang=ja にする設定を入れる

# 概要
VSCode でHTML5 をEmmet で入れるとこうなる↓
![2019-09-08 21_25_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/ca96e886-6eb3-3227-7384-a04aac36ab27.png)
![2019-09-08 21_09_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/84afe19c-1e68-d598-712c-e5fc133563fd.png)
毎回`<html lang="ja">`に書き直していたんですが、めんどくさいので設定を変更しました。
めちゃめちゃニッチな話ですが...
# 変更方法
「File > Preferences > Settings」または「Ctrl + ,」を押下して設定画面を開く
![2019-09-08 21_27_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/763afc52-323c-48e4-36a6-7239ab52a1e7.png)
右上の「Open Settings (JSON)」をクリックする
![2019-09-08 21_38_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/0f2fabcf-07fe-b43b-bb5c-200c777951db.png)
`"emmet.variables": {"lang": "ja"}` を追記する
![2019-09-08 21_40_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/078d4081-234d-4e77-314e-3d9aea1bdfbe.png)
# 結果
こうなる
![2019-09-08 21_42_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/5353dc6f-1223-1275-7e04-26600b30ad09.png)
![2019-09-08 21_43_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/75dae1ca-fa64-70bf-bb8d-4f0aeeace89d.png)
Everyday Rails - RSpecによるRailsテスト入門を終了しました！

##感想
無事にEveryday Rails - RSpecによるRailsテスト入門を終えることができました。この本の説明がとても分かりやすく、進めていくのが楽しかったです。ただ、すべてを完全に理解したわけではないです。具体的には、モックとスタブのところがまだいまいちの状態です。モックとスタブ以降の章も全くの新しい知識だったので、バッチリとは言えない状態です。ただ、止まってる訳にはいかないので、今後必要になったらもう一度読み直しながら学習していくのがいいのかなと思います。とてもいい本だったので買ってよかったです！

##今後
学んだ知識を使って自分のアプリに生かしていく
アウトプットしていく
AndroidStudioのバージョン確認方法

1.ウィンドウ上部のHelpタブをクリック
2.Check for Updatesを選択
3.下記のような画面が表示される。
![AndroidStudioバージョン確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446126/1f6117cb-6ae5-3f66-99aa-aa6be874eea2.png)
渋野日向子プロのスイングを機械学習してみた

話題の渋野日向子プロのスイングを、TensorflowJS・Mobilenetで機械学習（転移学習）してみました。

##機械学習とは
ゴルフファンのために、「機械学習」について優しく説明します。
我々の目でゴルフスイングを見ると、「〇〇プロ」ってわかりますよね？これは、過去に自分が見た色んなプロのスイングを記憶していて、その特徴から「〇〇プロ」と判断しています。

同じく、色んなプロのスイング画像をコンピュータに記憶させ、人間の脳の構造に近い「ニューラルネット」という技術で特徴を分類・計算し、「〇〇プロ」と判断出来る頭脳をコンピューターで作成することが出来ます。この一連の作業を「機械学習」と言い、AI（人工知能）の基礎部分となります。車における自動運転で、カメラに映る映像から人や車、センターラインを見分ける技術と基本的には同じです。

おそらく、どんなに優秀なレッスンプロの目よりも正確にスイングを把握し、その相違まで示唆することが可能となります。ただし、矯正方法はレッスンプロのアドバイスを聞いて下さいね。

##転移学習
TensorFlowJSのサイトに、具体的な手口が記載されているので、これを改良。
[https://www.tensorflow.org/js/tutorials/transfer/image_classification?hl=ja](https://www.tensorflow.org/js/tutorials/transfer/image_classification?hl=ja)

サンプルではWebcamから転移学習する方法なので、これをmp4からの動画取り込みに変更。
videoタグに、src=""でmp4本体を記載し、await setupWebcam();をコメントアウト。）

あとは、3クラス分類になっている部分を、
「Shibuno」、「Not Shibuno」
の2クラスに変更。

あとはほぼ変更なしです。Youtubeから適当な動画を拾って、ブラウザで動画再生〜ポーズしながらバシバシとボタンを押して、時間を掛けて学習します。

##成果
ドライバーショット。右上に「Shibuno !」と表示されました。
![スクリーンショット 2019-09-08 20.30.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/530518e9-e9ec-3db8-7b79-7e26a943a338.png)
![スクリーンショット 2019-09-08 20.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/dd3c13c9-003b-1a39-d4e7-31277d8cba3b.png)
![スクリーンショット 2019-09-08 20.31.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/229ba999-1e9e-a4bb-bf88-ce2217c6f62f.png)

アイアンショットです。右上に「Shibuno !」と表示されました。
![スクリーンショット 2019-09-08 20.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/dd5a7b33-4731-f884-985b-51566db2b22a.png)

パッティングです。スイングを学習したので、パッティングは「Not Shibuno ><」となっています。
![スクリーンショット 2019-09-08 20.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/2d88b3ea-7f62-9ee9-3973-2d9d61341514.png)

原英莉花プロです。もちろん「Not Shibuno ><」。
![スクリーンショット 2019-09-08 20.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74852/5ab45a12-a94b-67e6-8804-523bab7ddc1e.png)

##何に使う？
自分自身のゴルフスイングを機械学習（AI化）させておけば、調子の悪い時、しっくり来ない時に、AIに尋ねてヒントをもらうことが出来るようになるかも知れません。
専属コーチがAIになる時代も、もうそこまで来ているのかも。

渋野プロのスイングはコンピュータに記憶されているので、調子が悪くなった時は、ぜひお尋ね下さい！！
TeraTermのバージョン確認方法

1.ウィンドウの”ヘルプ”タブをクリック
2."Tera Termについて"を選択
3.下記のような、情報画面が表示される。

![Localhost - kusamochi@localhost_~ VT 2019_09_08 21_16_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/446126/96db1f21-125b-64f6-83f5-1b1ed964edca.png)
9/8 Tech Expert (事前学習) day 9　/　配列オブジェクト

【学習アウトプット】

今日の目標(やること)
Ruby!!

#今日のまとめ
##配列オブジェクト
ハッシュと同じように、1つの変数でたくさんの情報を持つことのできる。
ハッシュがキーでオブジェクトを管理していたのに対して、配列は順番でオブジェクトを管理。
ハッシュは`{}`(中括弧)で囲んでいたのに対し、配列は`[]`(大括弧)で囲む。

##配列
データを入れるとそのデータに順番がつけられる。＝データと順番がひもづく。

##要素
配列の中のデータは要素とよぶ
配列に入れた順に1番目,2番目..と自動的に順番が割りあてられる。

##配列を作るもっとも簡単な方法
```rb
配列オブジェクト = []
```
これで何も入っていない空の箱の配列。

##配列オブジェクトに要素を追加
```rb
配列オブジェクト << 追加する要素
```
`<<`メソッドでは配列オブジェクトに最後の順番で追加される


##length
```rb
配列オブジェクト.length # => 配列オブジェクト内の要素の数をカウント
```
##posts
```rb
posts = []      # 複数のレビューを持つ配列オブジェクト
```


##〜独り言(まとめやら感想やら)〜
Tech解約まで後３−４日。
復習はその後にして、少しでも多く目を通しておこ。
テーブルデータのオプション項目の変換


# はじめに
テーブルデータの項目には、しばしば任意に入力する項目といったオプション項目があります。このようなオプション項目を変換する手法について書きたいと思います。

# 環境
- macOS Majave 10.14.6
- pandas 0.23.4

# 手順
## データの準備
下記のデータを準備します。

```python
import pandas as pd
import numpy as np


data = [['南', '北', '東'],
        ['南', '東', None],
        ['東', '北', '西'],
        ['南', None, None],
        ['北', '西', '東'],
        ['西', '東', '南']]

df = pd.DataFrame(data, columns=['項目1', '項目2', '項目3'])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/1065f5b2-90ba-8bfc-c621-30ced60cbef6.png)

例えば、自分の部屋のどの方角に窓があるといいですか？といったアンケートの回答だとしましょう。最大３つまで回答してください、とお願いした場合に表のようなデータになります。
決まった順序を設けていないので東西南北入り乱れたデータになりました。また、最大３つ、なのでNoneの部分もあります。

このテーブルをRandom ForestやLightGBMにかけようとすると、列自体に意味がないので、予測器がうまく解釈できません。

## データの変換
各行に東西南北があるか無いかの0-1データに変換します。選択項目の値を列にし、各行にその値があれば1、なければ0とします。

まず、Noneを選択項目の値の何かで埋め、重複を削除したものを列値とします。
この列値をもつ、元のデータと同じインデックスを持つデータフレームを作成します。

```python
cols = np.unique(df.fillna('北').values)  # cols = np.array(['南', '東', '北', '西'])
df_new = pd.DataFrame(data=0, index=df.index, columns=cols, dtype=np.int8)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/480ca138-a8a1-e2ca-2867-a921e36312e5.png)

元のデータのうち、新しい列値と一致する部分をTrue、しない部分をFalseに変換します。行方向に和をとれば、各行にその値があれば1、なければ0となります。これをすべての新しい列に対して実行すれば次のような表になります。

```python
for col in cols:
    dg = df == col
    df_new[col] = dg.sum(axis=1)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/64bfb9ce-1ddd-67d5-1b98-abf6205912c5.png)

これで予測器がデータを解釈できるようになりました。


# おわりに
最初からこうなるようにDB設計してくれれば(ry
[初心者向け]　rails カラムの追加・削除

意外と忘れがちなrailsのカラムの追加・削除をまとめました！
###新しいカラムの追加（基本）
```$rails g migration （行う処理＋テーブル名）(追加したいカラムとデータ型など)```
例）＄rails g migration AddColumnToUsers  name:string age:integer

###新しいカラムにインデックスを追加
```$rails g migration AddColumnToUsers name:string:index```

###カラムの削除
```$rails g migration RemoveNameFromUsers name:string```

###テーブルの作成と同時にカラムの作成
```$rails g migration CreateUsers name:string age:integer```
CakePHP3でポートフォリオを完成させるまでのメモ(20190908)

※2018年11月頃からプロゲート、ドットインストールを通じ、
HTML、CSS、PHP、MySQL、CakePHPを勉強。
現在はオンラインメンターに師事しつつ、就職時のポートフォリオ制作中。
※主に土日に集中的に制作作業。平日は不明点の整理と消化に充てる。
※このメモは、ポートフォリオ制作途中から、完成までの中での不明点、
解決策、今後の課題等を記載していく場所とします。

■環境(各ツールのver)
-
AWS Cloud9：無料枠
MySQL：ver5.7.26 
CakePHP：ver3.8.2
PHP：ver7.2.19

■やったこと
-
事前にER図、画面遷移図を作成。
DB設定
CakePHPにてBakeALLを実行。
Bake後のMVCの連携に気をつけつつ、自身の作品への完成を目指す。←イマココ


■MySQLのテーブルに対し事前に設定済みだったforeignkeyが削除できない
-
alter table users drop foreign key 'user_key';
と打つと
ERROR 1091 (42000): Can't DROP 'user_key'; check that column/key exists
のようにエラーが出た

■解消のしかた
-
show create table テーブル名
と実行すると下記の結果が出た

mysql> show create table ices \G
*************************** 1. row ***************************
       Table: ices
Create Table: CREATE TABLE `ices` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `manufacturer` varchar(50) NOT NULL,
  `ice_name` varchar(50) NOT NULL,
  `ice_fraver` varchar(50) NOT NULL,
  `price_no_tax` int(5) unsigned NOT NULL,
  `buy_year` int(4) unsigned NOT NULL,
  `buy_month` int(2) unsigned NOT NULL,
  `image_file` varchar(255) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  `simple_comment` varchar(20) NOT NULL,
  `desc_comment` varchar(100) NOT NULL,
  `repeat_rate` int(11) DEFAULT NULL,
  `stock_rate` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ices_ibfk_1` (`user_id`),
  CONSTRAINT `ices_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

※ices_ibfk_1がこのicesテーブルの外部制約の名前ということになるため

alter table ices drop foreign key ices_ibfk_1;
↑とうつと、

削除できた。

※作業中に気づいた内容の一部抜粋でした。
※ざっくりとなぐりがきのような形となったため、
今後充実させていきます。つたない記事ですみません。


■今後の課題/希望
-
・この記事はQiitaへの初投稿にはなるが、今後の投稿頻度をどうするか。
・昨日、そして本日の作業後、MVCへの理解は深まったが、具体的な各メソッドへの深堀をする必要がある。
・現在はCakePHPを中心にした制作だが、PHP/MySQLだけでフルスクラッチで何か制作をしたい。
・CakePHPでのフロント部分に対し、制作していく方法の確認。
・AWS Cloud9への画像投稿時のファイル容量の制限はどのくらいなのかを確認する。
・Twitterで流れてくる内容に機械語、基本情報、という単語が目に入るが並行して勉強できるか。

■最後にひとこと
-
プログラミング、やればやるほど楽しいですね(^^)b
Rails - Discardを使って論理削除を実装する方法

# Discardを使って論理削除を実装する方法

現在開発しているプロジェクトで論理削除を実装する必要があった為、discardというgemを利用して実装しました。

現在論理削除のgemにはparanoiaとDiscardというgemがあります。当初スターの数などでparanoiaを利用しとうかと検討したのですが、rails公式の非推奨やactive recordのコア部分を上書きしてしまう実装の為、今後のRailsバージョンアップの際や他のgemとのコンフリクトを懸念があり、discardを利用する事になりました。

discard -> https://github.com/jhawthorn/discard
paranoia -> https://github.com/rubysherpas/paranoia

実装に掛かった時間は30分程度で、非常に使いやすいgemでおすすめです。

#### プロジェクトの解説
`SurveyItem`と`SurveyItemOption`というモデルがあり、それぞれ`Survey`という親モデルに`belongs_to`しています。

#### Gemfile
`gem 'discard', '~> 1.0'`

#### Migration
論理削除が必要なモデルにdatetimeタイプの`discarded_at`というフィールドを追加します。論理削除する際、`model.discard`というメソッドを呼ぶことで`discarded_at`に論理削除した時間が入ります。元に戻す場合は`model.undiscard`でフィールドをnilにする事が出来ます。

```
  def up
    add_column :survey_items, :discarded_at, :datetime, after: :deleted
    add_index :survey_items, :discarded_at

    add_column :survey_item_options, :discarded_at, :datetime, after: :deleted
    add_index :survey_item_options, :discarded_at
  end

  def down
    remove_column :survey_items, :discarded_at
    remove_column :survey_item_options, :discarded_at
  end

```

#### Model

discard gemを使うため`include Discard::Model`をモデルincludeします。
論理削除されていないレコードだけをデフォルトで返すようにしたい為、`default_scope -> { kept }`を追加します。

```
class SurveyItem < ApplicationRecord
   include Discard::Model
   default_scope -> { kept }

   belongs_to :survey
end
```

```
class SurveyItemOption < ApplicationRecord
   include Discard::Model
   default_scope -> { kept }
   
   belongs_to :survey
end
```

実装はこれだけ終わりです。

#### テスト
テストはminitestを使用しています。

```

  def test_discard
    assert_equal([
      survey_items(:survey_item_1),
    ].sort,
    SurveyItem.all.sort,
    "Should list all records")

    assert_equal([
      survey_items(:survey_item_1),
    ].sort,
    SurveyItem.kept.sort,
    "Should list all records")

    survey_items(:survey_item_1).discard
    assert_equal([],
    SurveyItem.kept,
    "Should list all records")

    survey = surveys(:survey_1)
    assert_equal([],
      survey.survey_items,
      "Should have zero survey items")
  end

```

デフォルトで論理削除されていないレコードを返すようにしているため、親レコードを取得した際、論理削除された子レコードは除かれて取得されます。素敵！

```
project > survey = Survey.first
=> #<Survey id: 1, company_id: 6, name: "アンケート 1", deleted: false, created_at: "2019-08-25 06:00:10", updated_at: "2019-08-25 06:00:10">

まだdiscardされていない。(まだ論理削除されていない）
project > survey.survey_items.first
=> #<SurveyItem id: 1, survey_id: 1, question_order: 1, question_name: "test", question_text: nil, question_type: nil, answer_data_type: nil, deleted: false, discarded_at: nil, created_at: "2019-09-08 11:08:57", updated_at: "2019-09-08 11:15:22">

discardする（論理削除する）
project > survey.survey_items.first.discard
=> true

project > survey = Survey.first
=> #<Survey id: 1, company_id: 6, name: "アンケート 1", deleted: false, created_at: "2019-08-25 06:00:10", updated_at: "2019-08-25 06:00:10">

survey_itemsは空で返ってくる。
project > survey = survey.survey_items
=> #<ActiveRecord::Associations::CollectionProxy []>

```
Vagrantで仮想ファイルの作成

自分用のメモです。２つ目の言語を学ぶ際に仮想環境を設定した方がそれぞれの言語で環境を変えられるのでいいかなと思いこの記事を作成しました。

```
# ホームディレクトリに移動
cd

# 今後複数の仮想マシンを作ることを想定して、それらをまとめるフォルダ（MyVagrant）を作る
mkdir MyVagrant

# MyVagrantに移動する
cd MyVagrant

# 仮想マシンを作るフォルダを作る（MyCentOS）
# ２回目以降の場合、ここのフォルダ作成から始める。例えばscalaの環境を作りたいならScalaAppみたいな。
mkdir MyCentOS

# MyCentOSに移動する
cd MyCentOS

# 仮想マシン設定用のVagrantfileを作る
vagrant init bento/centos-6.8

# Vagrantfileを編集して仮想マシンのIPアドレスを192.168.33.10にする
# ２回目以降の場合はIPアドレスを変更して、ローカル環境内でIPが炙らないようにすればいい。
sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile

# 仮想マシンを起動する（少し時間かかります）
vagrant up

# 仮想マシンの状態を確認する
vagrant status

# ステータス確認でrunningにあっていれば、仮想環境内に接続する
vagrant ssh

# 仮想マシンを停止したい場合は以下を実行
vagrant suspend
```

なにか間違っていれば遠慮なく申し出てください。