OmniAICreator/Qiita-1.07M huggingface dataset:
REAPERで時間ソートしてラベル付け

#はじめに
REAPERでアイテムの名前を一括で変えるスクリプトはもとからあったので使っていたのですが、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/02754ae6-3c3a-b2db-dbc6-8416ef2e5171.png)

トラックが分かれていると、それぞれのトラックごとに名前を流し込む感じだった。
一つのトラックでわけたものならよかったけど・・・

気づいた時にはトラック分けてしまっていた。

ので、
時間順で名前を流し込むようなスクリプトを書いてみた。

(あと、あまりに数が多いと文字オーバーしてるみたいで途中までしかうまくいかなかった）

# 全体の流れ
1.選択アイテム数を得る
2.選択アイテムを得る
3.カレントテイクを得る
4.カレントテイクの開始時刻とテイクを得る
5.時間で並び替える（ソート）
6.ダイアログで、リネーム用の文字を得る
7.ボタンが押されたらリネームする

#入力ダイアログ

Python tkinterを使いました。
こんな画面がでます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/daa40dd0-4fd7-b7e1-d03e-632a1f98a9b1.png)

#ソース

```tatLable.py
RPR_ClearConsole()

#Get Selected Items
itemNum = RPR_CountSelectedMediaItems(0)

itemList = []

for itemidx in range(itemNum):
  mediaItem = RPR_GetSelectedMediaItem(0,itemidx)
  itemList.append(mediaItem)
  
# Sort Items
dict = {}  
 
for item in itemList:
  currentTakeId = RPR_GetMediaItemInfo_Value(item, "I_CURTAKE")
  startTime = RPR_GetMediaItemInfo_Value(item, "D_POSITION")
  currentTake = RPR_GetMediaItemTake(item,int(currentTakeId))
  
  retval, tk, parmname, stringNeedBig,setnewvalue = RPR_GetSetMediaItemTakeInfo_String(currentTake, "P_NAME", "", False)
 
  dict[startTime] = currentTake
  #RPR_ShowConsoleMsg(str(startTime) + ",")
#RPR_ShowConsoleMsg(str(startTime) + "\n")
  
# Sort Start Time    
sortedList = sorted(dict.items(), key=lambda x: x[0], reverse=False)

for item in sortedList:
  retval, tk, parmname, stringNeedBig,setnewvalue = RPR_GetSetMediaItemTakeInfo_String(item[1], "P_NAME", "", False)
  RPR_ShowConsoleMsg(stringNeedBig + ",")
  
# Dialog
import tkinter
root = tkinter.Tk()
root.title("Rename Item with CSV")
root.geometry("400x200")

label = tkinter.Label(root, text="Names(separated by \",\")")
label.grid()

txtbox = tkinter.Entry()
txtbox.grid()

def clicked():
  nameList = txtbox.get().split(',')
  
  index = 0
  length = len(nameList)
  for item in sortedList:
    
    if index <= length :
      newName = nameList[index]
      retval, tk, parmname, stringNeedBig,setnewvalue = RPR_GetSetMediaItemTakeInfo_String(item[1], "P_NAME", newName, True) 
      index += 1
     
  root.destroy()

button = tkinter.Button(root, text = "OK", command= clicked)
button.grid()

root.mainloop()
```
#まとめ

時間ソートもなんとかできることがわかった。
簡単なGUIも使えるのが分かったので、いろいろはかどりそう。


# 使い方書いてないじゃないか！（　20210414 追記）
久しぶりに大量に名前をつけて保存したい機会がきたのでここをみて、実行しても動きませんでした・・・

pythonのスクリプトを動かすとかのところまでは一緒なので、以下の順で

- reapackを入れる
https://reapack.com/repos

- swsを入れる
https://www.standingwaterstudios.com/

これで動くはず。

1.リージョンを選択し、　
2. aaa,bbb,ccc, といったカンマ区切りの文字列をテキスト入力（ペースト）して
3. OKを押す

※トラック名を空にしておく必要があるかも（トラック名がリージョンに付与される場合があるようなので）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/eb816395-bf1f-ab5a-6423-60624d116525.png)

あとは、こんな感じの設定で出力すると　リージョン名（アイテム名）でファイルが保存できます。
Pythonで毎日AtCoder #21

### はじめに
[前回](https://qiita.com/taxfree_python/items/80b68114296a3be48c68)
今日は麻雀で負けまくったので萎えています。
ABCのAを全部埋めます。

### #21
[問題]
(https://atcoder.jp/contests/arc015/tasks/arc015_2)
2WA

**考えたこと**
思考停止で場合分けしました。未満と以下、以上をしっかり確認して実装しないと痛い目をみます()。

```python
n = int(input())
temp = [list(map(float,input().split())) for _ in range(n)]
ans = [0] * 6
for i in temp:
    if i[0] >= 35: #猛暑日
        ans[0] += 1
    elif 30 <= i[0] < 35: #真夏日
        ans[1] += 1
    elif 25 <= i[0] < 30: #夏日
        ans[2] += 1
    if i[1] >= 25: #熱帯夜
        ans[3] += 1
    elif i[1] < 0 and i[0] >= 0: #冬日
        ans[4] += 1
    elif i[0] < 0: #真冬日
        ans[5] += 1

l = list(map(str,ans))
ans = ' '.join(l)
print(ans)
```

### まとめ
楽しかった数理の翼も終わってしまいました。学校の宿題します。では、また
これからはじめる、Gatsbyのインストールから静的サイトのビルドまで

Gatsbyは次のWordpressとも言われている、Reactベースのオープンソースフレームワーク。

超高速なWebサイトやブログ、アプリを簡単に作ることができ、今最も注目されているCMSツールでもあります。

ここではGatsbyをこれからはじめる人のために、インストール〜静的サイトのビルドまでをサクッと解説していきます。

## Node環境のインストール
まずは環境のチェック。nodeは11.10以降にする必要がある。

brew使ってたので、brewでnodeをアップデートする。

node入ってない人は[ここ](https://nodejs.org/en/)からダウンロードできる。

```
brew upgrade node

// nodeをインストールしてない場合
brew install node
```

インストールできたらnodeのバージョンチェック。

```
node -v
v13.11.0
```

## Gatsbyのインストール

```
npm install -g gatsby-cli
gatsby new gatsby-site
cd gatsby-site
gatsby develop
```

`http://localhost:8000`にアクセス。ページが表示されればOK。

<img width="763" alt="Home___Gatsby_Default_Starter.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549249/18dc30ad-969c-b89b-2a6f-81001d4a7ab8.png">



## 静的サイトのビルド（生成）
コマンドで自動的にファイルを作成してくれる。

```
gatsby build
```

ビルドすると、puglicフォルダに静的サイトが作成される。あとはサーバーにアップすればWebサイトを表示できる。


## Gatsbyのスターターライブラリを使ったインストール
Gatsbyはデフォルトだけでなく、ブログやWebサイト、ポートフォリオサイトなどのスターターライブラリがあり、効率よく開発をスタートできる。

スターターライブラリ
https://www.gatsbyjs.org/starters/?v=2

ブログを作りたい場合はこちら。

```
gatsby new gatsby-starter-blog https://github.com/gatsbyjs/gatsby-starter-blog
```


## Gatsbyのリソース
ドキュメントがしっかりしてるので、そこ見ればだいたいのことはわかる。

プラグインやライブラリなどもリンクされてるので、公式のリソース集はチェックしておきましょう。

最新情報はTwitterやRedditを活用。

- [公式サイトのリソース集](https://www.gatsbyjs.org/docs/awesome-gatsby-resources/)
- [RedditのGatsby板](https://www.reddit.com/r/gatsbyjs/)
- [TwitterのGatsbyアカウント](https://twitter.com/gatsbyjs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor)
大学がリモート授業をするなら画面にコメントを流すNicoNico SPEENYAはアリなんじゃないか

コロナ対策として、大学がリモートでの授業配信を進めていくらしいですね。
どういった形で配信されるのかはわかりませんが、大勢が聴講する授業では学生と講師間でのコミュニケーションが難しそうなので、コメントを打って意見や質問を共有できるといいんじゃないかと。
(最近はそういうのが当たり前にあるのかもしれないけど、特にどういうシステムが使われてるとかは知らない状態で書いてます)

そこで、Chrome Extensionでコメントを流せるNicoNico SPEENYAってあったよなと思い出して試してみたのでデプロイ方法とか書いておきます。
私は社畜なのでリモート会議ででもネタとして使わせていただこうと思います。

**NicoNico SPEENYA**
https://github.com/chimerast/niconico-speenya

# 前提
* gitが利用可能
* docker/docker-composeが利用可能

# ローカルでデプロイ

```
git clone https://github.com/chimerast/niconico-speenya.git
cd niconico-speenya
vi docker-compose.yml
```

```yaml:docker-compose.yml
version: "3"

services:
  nicosp:
    build: .
    restart: unless-stopped
    ports:
      - 2525:80
```
```
docker-compose up --build -d 
```
ブラウザで
http://localhost:2525

<img width="366" alt="2020-03-30_225503.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565369/706282d6-7ef8-9b1d-58b0-8e466c7d62d4.png">

```
./make-package.sh
cd dist
[root@localhost dist]# ls -l
合計 308
-rw-r--r-- 1 root root 314662  3月 30 23:08 extension.zip
```
できあがったファイルzipファイルを
chrome://extensions/
にドラッグアンドドロップしてインストール。
コメントサーバ側からコメントを入力するとChromeにコメントが流れる。
<img width="503" alt="2020-03-30_230205.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565369/4dd237dc-dbbf-be47-9448-ed0ae2e5e933.png">

コメントサーバをインターネットに公開しておいて、授業スライドをSharepointとかでWeb上で表示して画面共有しておけば、学生側がコメントを流せるというような使い方ができるんじゃないか。(認証がないとか、荒れるとかいう話は別にしておいて)


# インターネット公開

一応簡単にインターネット公開用設定も。
例によってリバースプロキシにぶら下げてLet's Encrypt対応。

```yaml:docker-compose.yml
version: "3"

services:
  nicosp:
    build: .
    restart: unless-stopped
    environment:
      TZ: Asia/Tokyo
      VIRTUAL_HOST: #あなたのドメイン名
      LETSENCRYPT_HOST: #あなたのドメイン名
      LETSENCRYPT_EMAIL: #メアド

  nginx-proxy:
    image: jwilder/nginx-proxy
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - /dockerdata/nginx-proxy/certs:/etc/nginx/certs:ro
      - /dockerdata/nginx-proxy/htpasswd:/etc/nginx/htpasswd
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro

  letsencrypt-nginx-proxy-companion:
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    volumes:
      - /home/web/wordpress/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy

networks:
  default:
    external:
      name: shared
```

Chrome extensionを公開したサーバに対応させる。

```
vi ./extension/scripts/content-script.js
--------------------
  const SERVER_URL = 'http://localhost:2525' #ここを公開したURLに書き換える。
--------------------
./make-package.sh
```
これで公開したコメントサーバから読み込むことができるはず。
オブジェクト指向プログラミングなremoveEventListenerの書き方

[記事](https://qiita.com/querykuma/items/63098e7ac67ab0f058d8)を書いたのにremoveEventListenerでまた躓いた。:confounded:

今回はオブジェクト指向プログラミング版。

# 失敗例

```javascript
class X {
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    document.addEventListener('click', (e) => this.click(e));
  }
  remove() {
    document.removeEventListener('click', (e) => this.click(e));
  }
}
var x = new X();
x.add();
x.remove();
```

`(()=>{}) === (()=>{})`や`(function(){}) === (function(){})`がfalseを返すのでremoveEventListenerに無名関数を使用できない。

addEventListenerで指定した関数と同じ関数をremoveEventListenerで指定できていないのでイベントリスナーを削除できない。

イベントリスナー関数に`this.click`を指定するとremoveEventListenerで削除できるが、thisがdocumentを指し、e.currentTargetもdocumentを指すので重複してしまう。

オブジェクト指向プログラミングでイベントリスナー関数は書けない？

ここで小一時間悩んだ。:thinking:

# 成功例1 (bind)

```javascript
class X {
  constructor() {
    this.event_listeners = {};
  }
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    this.event_listeners.click = this.click.bind(this);
    document.addEventListener('click', this.event_listeners.click);
  }
  remove() {
    document.removeEventListener('click', this.event_listeners.click);
  }
}
var x = new X();
x.add();
x.remove();
```

関数にthisをbind[^arrow]して、その関数を保存して書けばいいと思う。:blush:

# 成功例2 (handleEvent)

あらゆるイベントを捕捉する handleEvent() という特別な関数が存在した。[^handleEvent]

handleEventを使うとどうなるか。

```javascript
class X {
  click(e) {
    // thisがオブジェクトXを指すようにしたい
    console.log('click', this, e.currentTarget);
  }
  add() {
    document.addEventListener('click', this);
  }
  remove() {
    document.removeEventListener('click', this);
  }
  handleEvent(e) {
    if (e.type === 'click' && e.currentTarget === document) {
      this.click(e);
    }
  }
}
var x = new X();
x.add();
x.remove();
```
この方法でもイベントリスナーを削除できる :smile:

オブジェクト`x`のすべてのイベントが1つの関数`handleEvent`に集約されるので、オブジェクトのイベントが多くなったときデバッグしやすくなるかもしれない。



[^arrow]: `this.event_listeners.click = (e) => this.click(e)`と書いてもいい。addEventListenerがthisを書き変えるので`this.event_listeners.click = function (e) { this.click(e) }`とは書けない。

[^handleEvent]: [EventTarget.addEventListener() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener)
Git で困った時の対処法

# ブランチを間違えたとき

- 対処法：正しいブランチに修正を反映させる。

```bash
# 1. 作業していた内容を退避する。
$ git stash

# 2. 正しいブランチに切り替える。
$ git checkout [正しいブランチ名]

# 3. 退避した情報をもとに戻す。
$ git stash pop 
```

# コミットメッセージを間違えたとき

- 正しいコミットメッセージで上書きする。

```bash
$ git commit --amend -m [修正後のコミットメッセージ]
```


# `git add` し間違えたとき

- 間違えたファイルを `git add` する前の状態に戻す。

```bash
$ git rm --cached [間違えたファイル]
```

# コミットを間違えた場合

- コミットを取り消す。

```bash
# 直前のコミットを間違えた場合
$ git reset --hard HEAD^
# または
$ git reset --hard @^

# n個前のコミットを間違えた場合
$ git reset --hard HEAD~n
# 3個前のコミットを間違えた場合
$ git reset --hard HEAD~3

# Working Area の修正はそのままでコミットだけ取り消す場合
$ git reset --soft

# Working Area の修正も含めて完全にコミットを取り消す場合
$ git reset --hard
```

- コミットした内容を打ち消すコミットを行う。

```bash
$ git revert [打ち消すコミットのハッシュ値]
```

Good Git Life !!
【備忘】bcpコマンドでcsvインポート

業務で使うbcpコマンドの備忘。
試験用のデータをcsvファイルでインポートしたい時に、以下のコマンドを叩いた。
(DBはSQL Server)

【コマンド】
```$ bcp DB名.スキーマ名.テーブル名 in "CSVファイルパス" -S ホスト名 -U ユーザー名 -P パスワード -t , -c```

オプションの意味は
-t    ⇒文字列を何で区切るか。上記 -t ,だとカンマ区切り。
-c    ⇒ファイルの中身が文字列であることを表す。
heroku アプリを削除して新しく作成する。

```
heroku apps
```
で現在のappを確認する。（5つ以上は作れないみたい。）

```
heroku destroy --app "削除したいアプリの名前"
```
"削除したいアプリの名前"の名前に入力を求められるので入力する。

```
heroku login
heroku apps:create "作成したいアプリの名前"
```
 （作成したいアプリの名前に"_"が入っていてはいけないようだ。）



#参考
[heroku create のエラー](https://qiita.com/kota810/items/5a5fc228afb3065fed20)
[Python + HerokuでLINE BOTを作ってみた](https://qiita.com/shimajiri/items/cf7ccf69d184fdb2fb26#%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E7%99%BB%E9%8C%B2)
AWSのLambdaでタグのついているインスタンスの情報を辞書形式で取得する方法

EC2インスタンスを[自動起動](https://ponsuke-tarou.hatenablog.com/entry/2020/02/18/100804)したり[自動停止](https://ponsuke-tarou.hatenablog.com/entry/2020/03/30/000120)したりするLambdaをつくるときに使います。Lambdaをつくってもすぐに忘れるので残します。

# Lambda関数
- ランタイム : Python3.8

```py
# -*- coding: utf-8 -*-

from __future__ import print_function

import boto3

# インスタンスがあるリージョンを指定する
REGION_NAME = 'us-east-2'
# インスタンスの状態をリストで指定する
STATE_LIST = ['running','stopped']
# インスタンスにつけているタグの名前をリストで指定する
TAG_LIST = ['Name','AutoStop']

def get_instance_list(ec2):
    """
    タグとステータスを指定してインスタンスを取得する.
    """
    instances = ec2.describe_instances(
        Filters=[
            {'Name': 'instance-state-name', 'Values': STATE_LIST},
            {'Name': 'tag-key', 'Values': TAG_LIST}
        ]
    )['Reservations']

    if len(instances) != 0:
        instances = instances[0]['Instances']

    return instances

def lambda_handler(event, context):
    ec2 = boto3.client('ec2', REGION_NAME)

    instances = get_instance_list(ec2)
    print(instances)

    return 0
```

# 定数に設定する内容
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/31eb4686-c323-37b6-2f97-4492d03186a9.png)


# 関数を実行するための権限
上記の関数では `describe_instances` を使用するため、`ec2:DescribeInstances`をIAMのポリシーに設定する必要がある。

- 参考 : [タグを使って EC2 リソースへのアクセスを管理する IAM ポリシーを作成する](https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-ec2-resource-tags/)

```json:IAMポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        }
    ]
}
```


# 取得できるインスタンス情報
取得できる辞書形式のインスタンス情報は、[EC2 &mdash; Boto 3 Docs 1.12.31 documentation - describe_instances](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.describe_instances)の「Returns」に記載されている`Instances`キーの内容となる。
ViewModelProviderクラスを定義せずにViewModelを生成する

## はじめに
つい最近ViewModelを触り始めたのですが、当初は律儀にViewModelProvider(s)を使っていました。
しかし、fragment-ktxを使うことでかなり簡素にViewModelを生成出来たので自分用に纏めておきます。

## 実装

jvmTargetを1.8に指定し、`lifecycle-viewmodel-ktx`と`fragment-ktx`を追加する。

```gradle:build.gradle

android {
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
    implementation "androidx.fragment:fragment-ktx:1.2.3"
}

```

### 引数なしの場合
まずは引数なしのViewModelから。
とりあえず引数なしのViewModelを定義する。
initとhelloメソッド呼び出しのタイミングでそれぞれログを出力させる。

```kotlin:MainViewModle.kt
class MainViewModel : ViewModel() {
    init {
        Log.d("MainViewModel", "init")
    }

    fun hello() {
        Log.d("MainViewModel", "hello")
    }
}
```

1行サクッと書くだけでViewModelが取得できる。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    private val viewModel: MainViewModel by viewModels() // ← ここ！！

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.hello()
    }
}

```

initとhelloメソッド呼び出しのタイミングでそれぞれログが出力されているのがわかる。

```:log
2020-03-30 22:48:02.199 3963-3963/com.masaibar.viewmodelsample D/MainViewModel: init
2020-03-30 22:48:02.199 3963-3963/com.masaibar.viewmodelsample D/MainViewModel: hello
```

### 引数ありの場合
続いて引数ありの場合、先程のViewModelのコンストラクタを`userId`という引数を受け付けるように変更した。

```kotlin:MainViewModle.kt
class MainViewModel(
    private val userId: String
) : ViewModel() {
    init {
        Log.d("MainViewModel", "init, userId: $userId")
    }

    fun hello() {
        Log.d("MainViewModel", "hello, userId: $userId")
    }
}
```

今度は先程のように1行だけサクッとという訳にはいかないが
それでもViewModelProviderクラスを定義しなくてもこのように書くことが出来る。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {

    private val viewModel: MainViewModel by viewModels {
        object : ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                @Suppress("UNCHECKED_CAST")
                return MainViewModel("masaibar") as T
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.hello()
    }
}
```

initとhelloメソッド呼び出しのタイミングでそれぞれログが出力され`userId`が渡っていることが確認できる。

```:log
2020-03-30 22:58:52.525 4979-4979/? D/MainViewModel: init, userId: masaibar
2020-03-30 22:58:52.525 4979-4979/? D/MainViewModel: hello, userId: masaibar
```

## おわりに
Googleにはもう少しこれを推していって欲しいです。

参考：https://developer.android.com/kotlin/ktx?hl=ja#fragment
wordpressよく使う関数まとめ【随時更新】

自分のブログをwordpressでつくろうと思い、wordpressをいろいろいじってます。
その時に使うwordpressの予約関数(?)を備忘録的にまとめてみました。

**ページ読み込み系**

```matome.php
get_header() //ヘッダー 読み込み
get_gooter() //フッター読み込み
get_template_part('huga','hoge') //huga-hoge.php読み込み
```
Djangoで、WEBアプリケーションを作ってみた

#はじめに
本記事は、Djnagoで、WEBアプリケーションを作成したした際の備忘録として書いたものである。


#前提条件

* OS環境は、Virtualboxで稼働中のCentOS8.1です。以下、OS詳細情報となります。

```php
# cat /etc/centos-release
CentOS Linux release 8.1.1911 (Core)
```

* 本記事では、AdminLTEを用いたTOPページの作成及びログインユーザのみのアクセス制限をDjangoで実装した内容です。
それを全5章分の記事にまとめました。


#実施手順

* 本編

[①Django　環境構築](https://qiita.com/yes_dog/private/37e7819082b9ce683b46)
[②Django　環境設定&管理者サイト表示](https://qiita.com/yes_dog/private/3f105234be3772e02d28)
[③Django　アプリケーション設定](https://qiita.com/yes_dog/private/54187f8c67075e0e6b1f)
[④Django　デザイン設定](https://qiita.com/yes_dog/private/3a320f839ed327af3af5)
[⑤Django　ログイン機能の実装](https://qiita.com/yes_dog/private/ea63912731dafabfd35b)


完成イメージ図(gif)を下記に記載しときます。
![TOP2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252895/17d0b791-f4e3-4a49-58cd-97373c0a8785.gif)

* 番外編

[【番外編】Django　ログイン機能の実装(Classバージョン)](https://qiita.com/yes_dog/private/ae2fba1fc68d20bf9402)

#参考URL
[【Django】PDFからEXCELへ文字起しする業務改善アプリを作ってみよう！](https://www.techpit.jp/p/django-pdf-excel)
↑この記事には、大変お世話になりました！！


#最後に

Djangoは、色々用意されていて便利だが、それを理解するまでに少し時間がかかってしまった。
この記事は、そんな私が今後見返した時に思い出せるように書いたものなので、
みすぼらしい箇所がいくつかあると思いますがご了承ください(´;ω;｀)
mutationsについて学んだことの備忘録

# mutationsについて

Vuexはグローバル変数なので、状態を変えると、stateを使っている箇所全てに影響する。

例えばこの以下の部分はデータの追跡や予測をしにくくしている

```counter.js
this.$store.state.count++
```

これは、ぱっと見、データを変えているのか参照しているのかがわからない

mutationsを使わなくても、データを変えることはできけど
データの追跡や予測をしやすくするために、**mutationsでしかstateを変えないようにした方が良い**らしいです。

## mutationsの書き方

```counter.js
export default new Vuex.Store({
 state:{
  count:2
 }, 
 getters:{
  doubleCount: state => state.count * 2,
  tripleCount: state => state.count * 3
 },
//mutationsでしかstateを変えれないようにする
 mutations: {
//第一引数はstate,第二引数は適当でいいけど今回はnumber
   increment(state,number){
    state.count += number;
 },
   decrement(state,number){
    state.count -= number;
 }
});
```

double.countやtripleCountを使用している部分はどのように書くかというと

```Header.vue
<template>
  <div>
  <button @click="increment">*2</button>
  <button @click="decrement">-1</button>
 </div>
</template>
<script>
 export default {
  methods:{
   increment(){
　　　//mutationsを用いいない書き方だと、
     //this.$store.state.count++;
     //引数(今回は2)もとることができる
     this.$store.commit('increment',2);
     },
   decrement(){
     this.$store.commit('decrement',2);
   }
  }
 };
</script>

```


このように、stateを変える部分をこの場所一つに絞ることで、わかりやすくなります！
[C#]GeoTag(GPS情報)をjpgファイルに設定/取得するときのハマったメモ

**もくじ**
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f

**GeoTag関連**
- [GeoTag(GPS情報)をjpgファイルに設定/取得する](https://qiita.com/tera1707/items/0322a22517dfacee4133)
- [GeoTag(GPS情報)をjpgファイルに設定/取得するときのハマったメモ](https://qiita.com/tera1707/items/b245c4a264ed2bf50746)


# やりたいこと
UWPのAPI（`GeotagHelper.SetGeotagAsync()`）を使って、jpegファイルにGeoTagを付与したいのだが、あるjpegファイルだけ、なぜか`GeotagHelper.SetGeotagAsync()`を実行した際に例外が発生してしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/5d2e4034-e7d7-58e4-a1ef-193be947d774.png)

jpegファイルをちゃんとSetGeotagAsyncにセットしてやっているはずが、なんで例外になるのかさっぱりわからない。そのときに調べた(というかいろいろ試した)事のメモ。

# 結論(例外の原因)

原因は、GeoTag付与しようとしていたjpegファイルが、実はjpegファイルではなかったこと。
具体的には、そのjpegファイルを`System.Drawing.Bitmap`の`Save()`メソッドを使って作成していたが、Saveの引数に`System.Drawing.Imaging.ImageFormat.Jpeg`を指定してJpeg作成すべきが、`System.Drawing.Imaging.ImageFormat.Bmp`を指定して、ファイルの拡張子だけ`.jpeg`にしてjpegファイルにしていたことが原因。

Windowsでは、拡張子が`.bmp`のビットマップファイルの拡張子だけを`.jpeg`に変えてやると普通にjpegとしてペイントやその他アプリで開けるようになるが、`GeotagHelper.SetGeotagAsync()`的にはそれはダメで、拡張子だけではなく**生粋の**.jpgファイルでないと、ためした限り受け付けてくれないらしい。
(EXIFのデータを乗っける領域がbmpファイルの先頭部分には用意されてないからかも。)


# サンプル

```.cs
var cur = Directory.GetCurrentDirectory();      // exeのあるディレクトリ
var filepath = cur + @"\ginga.bmp";             // 元の画像
var filepath_out_jpg = cur + @"\ginga_out.jpg"; // jpgとして保存する画像
var filepath_out_bmp = cur + @"\ginga_out_fake.jpg"; // 実はbmpだけどjpgとして保存する画像

using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.ReadWrite))
using (var bmp = new System.Drawing.Bitmap(fs))
{
    // 元の画像を、jpgとbmpで保存し分ける
    bmp.Save(filepath_out_jpg, System.Drawing.Imaging.ImageFormat.Jpeg);
    bmp.Save(filepath_out_bmp, System.Drawing.Imaging.ImageFormat.Bmp);
}

// GPS値作成
BasicGeoposition bgps = new BasicGeoposition() { Latitude = 3.0, Longitude = 2.0, Altitude = 1.0 };
// GPS値をGeopointにセット
Geopoint gps = new Geopoint(bgps);

try
{
    // GPS値をjpgファイルに書き込み
    var stjpg = await Windows.Storage.StorageFile.GetFileFromPathAsync(filepath_out_jpg);
    await GeotagHelper.SetGeotagAsync(stjpg, gps);// →こっちは問題なくgeotag付与できる
    var stbmp = await Windows.Storage.StorageFile.GetFileFromPathAsync(filepath_out_bmp);
    await GeotagHelper.SetGeotagAsync(stbmp, gps);// →こっちは、拡張子はjpgだが実はbmpでjpgではないので、geotag付与時に例外発生
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
```
反変性インタフェースと共変性インタフェース　in C#

##はじめに
共変性，反変性インタフェースという言葉を知っていても知らなくても，このルールはよくよく考えればあたり前の話で，言葉を知らなくてもほとんどの人はその概念を理解しているのではないでしょうか．しかし職場の先輩などに言われて，言葉の意味を知っているのに言葉自体を知らずに悔しい思いをしないように，なるべく短くメモを残しておきました．
##準備1（暗黙的代入）
共変性，反変性は「ある型をもつ変数へ別の型をもつインタフェースを実装したオブジェクトが代入できるかどうかの性質」なのですが，実際にはインタフェースを実装したオブジェクトが変数に代入される場面で問題になるのではなく，メソッド呼び出し時の引数としての暗黙的代入でエラーになったりならなかったりします．
int func(int a);
というシグネチャを持つメソッドを呼び出すときに
func(5);
とすると暗黙的に
int a=5と同じことになります．これを，ここでは暗黙的代入とします．代入をメソッドへの引数の引き渡しと同じこととみなして，
本稿では共変性，反変性は「ある型の引数をとるメソッドに別の型をもつインタフェースを実装したオブジェクトが引数として引き渡せるかどうかの性質」として，C#のIComparerとIEnumeratorで実験してみます．

##準備2　親子クラス
AnimalとDogの２つのクラスが親子関係になっています．DogオブジェクトはAnimal変数に代入できますが，AnimalオブジェクトはDog変数に代入できません．

```
class Animal
    {
        public int id { get; set; }
        public int weight { get; set; }
    }
class Dog : Animal
    {
        public int speed { set; get; }
    }
Animal a =new Dog();//可能（アップキャスト）
//Dog d = new Animal();//コンパイルエラー（ダウンキャスト）
```
ここで，以下の実験のために2つの配列を用意しておきます．初期化子パラメータは適当です．

```
Dog[] ad = {
                new Dog(){id=1,weight=1,speed=10},
                new Dog(){id=2,weight=2,speed=9},
                new Dog(){id=3,weight=3,speed=8}
            };
Animal[] aa = {
                new Animal(){id=10,weight=3},
                new Animal(){id=20,weight=1},
                new Animal(){id=30,weight=2}
            };
```
## 反変性インタフェースの例 IComparer\<T>
前で用意した配列をソートするためIComparer\<T>を実装したクラスを作成します．

```
class Dcompare : IComparer<Dog>
{
        public int Compare(Dog x, Dog y)
        {
            return x.speed - y.speed;
        }
}
class Acompare : IComparer<Animal>
{
        public int Compare(Animal x, Animal y)
        {
            return x.weight - y.weight;
        }
}
```
この２つの比較クラスで，それぞれ親子クラスをたすき掛けでソートしてみるとどうなるでしょうか．

```
Array.Sort<Dog>(ad, new Dcompare());//speedでソート
Array.Sort<Dog>(ad, new Acompare());//weightでソート
//Array.Sort<Animal>(aa, new Dcompare());//compile error
```
本来Dog配列をソートするのにはDcompare()を使って，speedプロパティによって並べ替えられます（1行目）．しかし，上記例のとおりDcompare()が入るべきIComparer\<Dog>型引数位置にIComparer\<Animal>型を実装したオブジェクトを引き渡してweightプロパティで並び替えることもできます(2行目)．一方IComparer\<Animal>型が来るべき位置にIComparer\<Dog>型を引き渡せません(3行目)．2行目と3行目を暗黙的代入に書き換えると，それぞれ以下のようになります．

```
IComparer<Dog> x =  new Acompare();//可能（ダウンキャスト風）
IComparer<Animal> y =  new Dcompare();//コンパイルエラー（アップキャスト風）
```
これはAnimal型変数へDog型オブジェクトの代入が許されたアップキャストの逆の関係にみえます．この性質からIComparer\<T>は反変性インタフェースであると言われます．

## 共変性インタフェースの例 IEnumerable\<T>
共変性の性質をもつインタフェースの例としてIEnumerable\<T>があります．class Dogs: IEnumerable\<Dog>とclass Animals : IEnumerable\<Animal>の2種類のクラスがあるものとします．この2つの変数型とオブジェクト型を入れ替えて代入してみると，一方がエラーになります．

```
IEnumerable<Animal> ae = new Dogs();
//IEnumerable<Dog> de = new Animals();//compile error
```
これはAnimal型変数へDog型オブジェクトの代入が許されたアップキャストと同じ関係にみえます．この性質からIEnumerable\<T>は共変性インタフェースであると言われます．
一般的にIEnumerable\<T>はメソッドに代入されるのではなく，foreach 文のinの後に置かれます．しかし，foreachでの型不一致はコンパイルエラーではなくランタイム時のキャスト例外になります．この場合でもIEnumerable\<Dog>を置くべきところにIEnumerable\<Animal>を置けないという共変性ルールは同じです．

```
foreach (Animal a in new Dogs())
{
    Console.WriteLine(a.ToString());
}
foreach (Dog d in new Animals())//不正キャスト例外
{
    Console.WriteLine(d.ToString());
}
```
新人エンジニアへ伝えたい　～質問するときの心構え～


#いよいよ4月1日・・・！
新卒、あるいは既卒の未経験のエンジニアがデビューする時期になりました。
そんな皆さんに是非、事前に伝えたいことがあります。


#質問するときの心構え

プロジェクトに参画中、きっと先輩や上役にわからないところを質問したくなるシーンが必ずあります。

その時の振舞い方についてここに記したいと思います。

###①まず自力で起きている問題を特定する
全て完璧にとは言いませんが、ある程度特定しておくことによって回答する先輩方も理解がしやすいですし
自力で解決できないにしても考える力はつきます。
何より社会人ですから、ただ「わかんなーい」だけじゃ恥ずかしいですよね。

###②質問事項をタイプ別に分類
分からなくて質問したいことでも大きく3つに分けることができます。

◆聞かないと進められないこと
◆聞いたほうが効率がいいこと
◆自力で解決するべきこと

最初は難しいかもしれませんが、先輩方に質問する前に意識してみましょう。
出来るようになれば間違いなく効率よく仕事が進むはずです。

###③同じ間違いはしない
とはいっても人間ですから何度も失敗すると思います。
慣れないうちはとにかく全てメモする姿勢でいきましょう。
絶対忘れます(笑)
私がそうなのですが、聞きやすい先輩は無意識に同じことを何度も聞きがちです。要注意。

#そもそもなぜこの記事を書こうと思ったか
時期的なものも勿論あるのですが、明日で昨年夏から参画していたプロジェクトを退場することとなり
その時にお世話になった先輩から頂いたアドバイスを退場を機に共有したいと思ったからです。

比較的ドライなタイプの方だったので、メッセンジャーでこの長文が送られてきたときは良い意味でとても意外だったので嬉しかったことを今でもよく覚えています。

今では新天地で頑張っておられるとのこと。

もう連絡する手段がないのは名残おしいですが、頂いたアドバイスを胸に4月から新たな現場で頑張ります！
相手の音は聞こえるけれど、自分の音が相手に聞こえない

スカイプやスラックなどで相手の声は聞こえているけれど、こちらの声が通じない場合
→アプリがマイクにアクセスできるようにする　の設定がオフになっていたため。

windows10　の場合
設定→プライバシー→マイク→アプリがマイクにアクセスできるようにする　をオンにする
「テスターちゃん」で学ぶソフトウェアテスト④

#1. 「テスターちゃん」について
初心者(新人)向けに描かれたソフトウェアテストの漫画になります
たまたまJSTQBについて調べていた時に見付けたブログの記事がきっかけで読むようになりました
[JSTQBを取るメリット5選](http://testerchan.hatenadiary.com/entry/2018/02/15/001117)

今でも更新がある度にチェックしたり、書籍版を読み返したりしたり、とテスト関連の資料として活用しています
[Blog](http://testerchan.hatenadiary.com/)
[書籍版](https://books.rakuten.co.jp/rb/16202142/)

#2. LOG
[「テスターちゃん」で学ぶソフトウェアテスト①](https://qiita.com/156Musik/items/46111ec9cfae5f9aa88d)
[「テスターちゃん」で学ぶソフトウェアテスト②](https://qiita.com/156Musik/items/3c1a91126dc15bd2bf40)
[「テスターちゃん」で学ぶソフトウェアテスト③](https://qiita.com/156Musik/items/1a9450a15aa3607fe2d5)
「テスターちゃん」で学ぶソフトウェアテスト④ :point_left_tone1:イマココ
[「テスターちゃん」で学ぶソフトウェアテスト⑤](https://qiita.com/156Musik/items/b89e104010dfcced3fd0)
[「テスターちゃん」で学ぶソフトウェアテスト⑥](https://qiita.com/156Musik/items/ebb1d2339c3a256f8ec9)
[「テスターちゃん」で学ぶソフトウェアテスト⑦](https://qiita.com/156Musik/items/94a036beb46c2dc68a86)
[「テスターちゃん」で学ぶソフトウェアテスト⑧](https://qiita.com/156Musik/items/fb1aa75351660c1150f8)

#3. ふりかえりって大事

##3.1 ふりかえりって何？:thinking:
やったことをフィードバックして、次回への糧とすること
やらないと**3歩進んで2歩下がる**ようなことが起きることもある

##3.2 ふりかえりをやらないとどうなるの？

- やったことを忘れる
　⇒成功体験も失敗もフィードバック出来ない
　　**経験**や**わかったこと**が放置されてすっかり忘れる可能性もある

- チーム内の**気づき**が共有できない
　⇒場がないと共有されないことはよくある

##3.3 ふりかえりの大切な役割
- やったことをフィードバックする
- 効率よくみんなの気づきを共有・フィードバックする
- フィードバックから**これから取り組む課題**をはっきりさせる

次からこの**課題**に取り組むことで、悪かったことを直したり、新しいことに挑戦したりして、より一層成長できる
　⇒カイゼンを回すという言い方もする

逆にカイゼンしたいのにふりかえりをしないと、自分たちのどこがよくなかったのかわからないし、次はやったほうがいいこともわからないため、カイゼンが回らなくなる

ふりかえりがただの感想会にならないようにも気を付ける

-------------------------------------------------

なんとなくのふりかえり会をしないように気を付けるためには
:point_down_tone1:

#4. KTPのやり方

##4.1 KTPって何？:thinking:
**Keep**と**Problem**という面でふりかえり、**Try**で次につなげる
※ケプトと読む

> - Keep
 - これからも続けること
 - よかったこと
- Problem
 - 困ったこと
 - 問題点
- Try
 - 次試したいこと

##4.2 KPTの全体的な流れ
>
①前回の確認
　前回のTryはKeepになったか
②Keepを出す
③Problemを出す
④Tryを出す
⑤TryをActionに落とす

####全体ルールについて
①**当事者意識**が大切
②人の話を遮らない

##4.3 実際にやってみよう〜Keep編〜
- Keepから出していく
    - 時間的には１０〜１５分くらい
- **これからも続けること**や**よかったこと**を付箋に書く
    - 一つの付箋に一つのことを書くこと
-  最初は黙々タイム！個人でKeepを出してみる
    -  ここで他の人と話をすると人の意見に自分の考えが引っ張られてしまう
-  書き終わったらみんなで共有
    -  **声を出しながら**貼り出す
-  最後はグループ分けを行う
    -  自分たちがどこに注力しているかわかり易くなるため

##4.4 実際にやってみよう〜Problem編〜
- Keepと同じように黙々タイムをしてから貼り出す
- 貼り終わったらグルーピング
    - どんなところに問題意識が向いているのかわかる

【注意点】
>〜していない
〜過剰

これだとTryの時に反対にしただけの意見が出てしまう
具体的に書いた方がTryが考えや易くなる

>個人攻撃をしない
悪口を言わない

##4.5 実際にやってみよう〜Try編〜
- 時間的には１５分くらい
- **Keepをより良くすること**・**Problemをカイゼンすること**・**やってみたいこと**を出す
- 他の工程と同じように黙々タイムをしてから貼り付ける
- **Keepをより良くするTry**は忘れがちなので、これも意識すること
- Problem⇒Tryの場合は、原因を少し考えて解決するTryを出すほうかいいかも
    - 「〜してない」を「〜する」に変えるTryもいい、だけど…
    - **良いことを伸ばすTry**も必要⇒強みをより伸ばすことも考える
- Tryを出したら、どのTryに取り組むかを決める
    - 難しい＝効果があるではない
    - 最初のうちは**簡単に出来るけど、効果がありそうなもの**を１〜２つ選んでやってみる
    - この選んだTryが出来ると次回のKPT継続のモチベーションにもつながる

<font color="red">KPTは継続がとても大切</font>

<details><summary>優先順位について</summary>緊急度と重要度で優先順位をつけるのもアリ</details>

##4.6 実際にやってみよう〜2回目以降編〜
<font color="red">2回目からが大切</font>
　⇒1回だけだと真の効果を発揮しない

定期的の行なって**カイゼンを回す**ことが大事

【2回目からは…】
開始する前に**前回からの確認**を入れること
　⇒TryがKeepになっていたらKeep側に移す
　　続けていくといらないものも出てくるが、そういうものは外す
　　Keepで習慣化したものも外す

ProblemからTryへ
TryからKeepへ
そしてKeepから**そのチームのベストプラクティス**になっていく

まずはKPTを繰り返すことから初めていく
⇒いいチームの第一歩となるかもしれない
UiPath Orchestrator のAPIを呼び出すためにIISサーバにCORSの設定を追加する(IISでCORS対応)

## CORS(Cross Origin Resource Sharing)の概要

あるWEB上のサービスが、RESTのAPIを公開しているとします。
そして**自分のWEBアプリから、そのRESTサービスを呼び出したい**なんてときがあります。たとえば **UiPath Orchestrator APIを使ってロボット一覧を取得して、自分のWEBサイトに表示するとか**、そんな場合です。

しかしながら通常WEBブラウザはセキュリティの観点から「**WEBアプリ(Script)が他のサイトへHTTPアクセスするのを制限する**」という動きをします。いわゆる「同一オリジンポリシー(Same Origin Policy)」にしたがって動作するわけですが、従って通常このRESTサービスの呼び出しは遮断されてしまいます。

- 参考: [オリジン間リソース共有 (CORS)](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)

(ちなみに「オリジン」ってのは https://www.example.com:443/api/Account/Authenticate などにおける「https://www.example.com:443 」のことです。ここが異なるWEBサイトへの、Scriptをつかったアクセスを遮断するということですね)

![C001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73777/9fe73ab5-7cdc-e3f2-2866-4d4d8d5cf8f1.png)

さて、信頼関係があるサーバ間ではこの制約をこえて通信したいわけですが、そのためにブラウザは「**REST先が自分をOKって言ってくれれば、他のオリジン(Cross Origin)だけどアクセスを許可して、情報を共有しましょう(Resource Sharing)**」という機構を用いて通信をおこなう事ができます。この機構が Cross Origin Resource Sharing つまり**CORS**です。


「IIS上で動いているUiPath Orchestrator が公開しているRESTのAPI」をWEBアプリから呼び出そうとして、CORSの制限に引っかかってしまったので、今回は**IISにCORSの設定を追加**してみようと思います。

## やってみる

### 確認した環境

AWS上の Windows Server 2019 Detacenter 上のIIS

### ダウンロード・インストール

IIS上で稼働するモジュールをインストールします。
https://blogs.iis.net/iisteam/introducing-iis-cors-1-0 より64Bit版のインストーラ(``IISCORS_amd64.msi``)をダウンロード。
IISサーバ上でインストーラを起動します。手順は「install」をクリックするだけ。

![C002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73777/00b7c7e1-e4c7-5f22-307e-8494c35ae900.png)

### Web.Config に設定追加

メモ帳などで ``C:\Program Files (x86)\UiPath\Orchestrator\Web.config`` を開きます。
``<system.webServer>`` の項目を検索して、、、、下記を追加します。

```xml
<system.webServer>
  <cors enabled="true" failUnlistedOrigins="true">
      <add origin="*" >
          <allowHeaders allowAllRequestedHeaders="true" />
      </add>
  </cors>
...
</system.webServer>
```

画面で見るとこんな感じ。
![C003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73777/c125faf6-2fa5-ea33-21bf-ba3acad2aa5e.png)

上記は **任意のサイト(*)に対して、すべてのHTTPメソッドを許可する、というとっても緩めな設定にしていますが、実際は特定のオリジンや特定のHTTPメソッドのみ許可するなど、必要最低限のモノにすべきです。ご注意ください。**
この辺のConfigurationの方法は、 https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference ココに詳しく書いてありますので、熟読しましょう。


最後に、IISを再起動して、WEBアプリからリクエストしてみましょう。

![C004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73777/51c8943b-ebca-3159-8c8e-0f51942df11d.png)

詳細は割愛しますが、OPTIONSメソッド(CORSをチェックするために呼ばれたHTTPリクエスト)が正常処理され、つぎのRobots 一覧を取得するリクエストも正常終了(Response:200) していますね！


おつかれさまでしたー

### 関連リンク

- [IIS CORS Module を試してみた](https://blog.shibayan.jp/entry/20171218/1513583833)
- [IIS CORS module Configuration Reference](https://docs.microsoft.com/en-us/iis/extensions/cors-module/cors-module-configuration-reference)
- [CORSまとめ](https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34)
PWMで輝度制御（キーボード入力でコントロール）

PWM制御でLEDの輝度を変化させるプログラムを作成しました。

```python
#本プログラムはラズパイのターミナル上で実行してください。
#統合開発環境だとエラーになります。
import pigpio
import time
import readchar

gpio_pin0 = 18 #GPIO18でPWMを動かす
x=0 #LEDの初期輝度

pi = pigpio.pi()
pi.set_mode(gpio_pin0, pigpio.OUTPUT)

while 1:
    #100Hz,x*100000のところがDuty比です。これでx%になります。
    pi.hardware_PWM(gpio_pin0, 100, x*100000)
    
    #キーボードから入力を読み取ります。
    kb = readchar.readchar()
    print(kb)
    
    #uが入力されたら輝度を一段階上げます。
    if kb == 'u':
        x=x+1 
        print("brightness="+str(x))

    #dが入力されたら輝度を一段階下げます。
    elif kb== 'd':
        x=x-1 
        #xがマイナスになるとエラーでプログラムが止まります。。張り付きにする処理が必要です。
        print("brightness="+str(x))

    #qが入力されたらプログラムを終了します。
    elif kb == 'q':
        pi.set_mode(gpio_pin0, pigpio.INPUT)
        pi.stop()
        print("")
        break
```
↓動作させているところ
<blockquote class="twitter-tweet"><a href="https://t.co/1okaUUdWLc">pic.twitter.com/1okaUUdWLc</a> <a href="https://twitter.com/shi78ge/status/1244271756602294272?ref_src=twsrc%5Etfw">March 29, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##参考サイト
・pigpioによるPWM制御
https://qiita.com/s417-lama/items/0ef64a7af3fcf6a56cc5

・readcharの使い方
https://teratail.com/questions/100708
input()だと入力のあとenterを押さないと入力が反映されません。
readcharを使うとenterなしで連続入力ができます。
バンドサークル管理webアプリ製作日記 - ユースケース

## あらすじ

このシリーズでは、私の個人開発である**バンドサークル管理webアプリ**の
開発の内容をまとめていく。

[前回](https://qiita.com/RINYU_DRVO/items/d73c8c9c8732fbbd1a3f)は、この開発サイクルで解決する問題を提起した。

## この記事では

これから製作する**バンドサークル管理webアプリ**が、
`どんな場面で使用されるか（ユースケース)`考察していく。

## 解決すること

この開発の大きな目標は
`バンドサークルの運営を円滑にする`事だ。

そのためには、運営がめんどくさい、上手くいかない、
そんな**問題点**を解決する必要がある。

今回解決する課題は下記の2つ。

```
①誰がどのバンドに所属しているのか分からない。共有しにくい。
②ライブにバンドを登録するのがめんどくさい。
```

これを解決できる機能を持つアプリケーションが
これから作るものとなる。

そんなアプリケーションは、
一体どんな場面で使われるだろうか？

## ユースケース

私が考察したユースケースの概要は下記のような感じ。

```
課題①の解決
・バンドを結成した時に登録ができる。
・バンド一覧を見ることができる。登録順。
・バンド一覧からバンドを検索することができる。
・バンド詳細から所属メンバーを見ることができる。
・メンバーを登録できる。
・メンバーはバンドに加入希望を送ることができる。
・バンド管理者はメンバーからの加入希望を承認して登録することができる。
・メンバー詳細から所属ライブを見ることができる。
課題②の解決
・サークル管理者はライブを登録・設定することができる。
・バンドはライブにエントリーができる。
・管理者はライブにエントリーしたバンドを日程ごとに振り分けて登録することができる。
・管理者がライブの出演順や出演時間、リハ時間を設定できる
・ライブにどのバンドが何番目に出るか誰でもすぐ分かる
・ライブ一覧を見ることができる。登録順。
```

これにより、ユーザは**何ができれば**便利か
明確になった。
これは、より利用者に近い視点である。

これを詳細まで深堀りする。

図にしてみよう。

## Use Case Diagrams

> ユースケース図とは、「ユーザーの視点でシステムの利用例を表現する図解術」です。

下記の図のように、誰がどの機能を使うかまとめることが出来た。

![スクリーンショット 2020-03-30 21.24.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360072/342ceb37-41ed-1b30-64a7-9556f0a1466c.png)

また、下記のように表に起こすことで、
抜け漏れを防ぐことができる。

![スクリーンショット 2020-03-30 21.26.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360072/2f82f185-7e7b-d3d4-1db6-4d13d7b76375.png)

## まとめ

解決すべき課題から、ユーザがどんな機能を
どのように使えば、目的を満たすプロダクトになるかを
定義することができた。

次は、今回まとめたユースケースを実現するための機能を
**要件定義**として落とし込んでいく。

[バンドサークル管理webアプリ製作日記 - 要件定義](https://qiita.com/RINYU_DRVO/items/66ec54bee76a68cc0e09)

## バックナンバー

[バンドサークル管理webアプリ製作日記 - Introduction](https://qiita.com/RINYU_DRVO/items/d6f1e27749d01e2fdf75)
[バンドサークル管理webアプリ製作日記 - 問題提起](https://qiita.com/RINYU_DRVO/items/d73c8c9c8732fbbd1a3f)
[バンドサークル管理webアプリ製作日記 - 競合比較](https://qiita.com/RINYU_DRVO/items/849cf034095977b5f57e)

## 参考

[若手エンジニア必読！超絶分かるユースケース図－全知識と書き方５ステップ](https://it-koala.com/usecasediagrams-1832)
【MySQL】データのエクスポートとインポート

## エクスポート
ファイル名に現在時間をつけてエクスポート

```
mysqldump -h 【ホスト名】 -u 【ユーザー名】 -p 【DB名】 > 【ファイル名】_`date "+%Y%m%d-%H%M%S"`.sql
```


## インポート
```
mysql -h 【ホスト名】 -u 【ユーザー名】 -p 【DB名】 < 【ファイル名】_YYYYmmdd-HHMMSS.sql
```

または

```
mysql -h 【ホスト名】 -u 【ユーザー名】 -p 【DB名】
mysql > source 【ファイル名】_YYYYmmdd-HHMMSS.sql;
```

## その他
### 今どこのデータベースにつないでるか忘れたとき
```
SELECT database();
```
【Hack for Play】複数ラインの攻撃をしてみたいとき

この記事では、下図のような拡散攻撃的なやり方を紹介します。
<img width="277" alt="xx01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/ddd6d4d6-964a-aa81-7f08-133871b57183.png">
実際の練習用はこちら。
https://www.hackforplay.xyz/works/2myb7Aj95NlpDKQa3Vuy

それでは、
【参考】
【やり方】
【実践】
の順序で進めていきますね。

---

【参考】
参考になるのは、商人たちの、「しょうかん」するです。
<img width="725" alt="sy01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/a761d2ed-665b-bfa9-23f1-4ff44e4c5c9a.png">

---

【やり方】
攻撃させたいプレイヤーで、「こうげきするとき」で「もの」を選択します。
<img width="437" alt="pl01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/2c8fb6f8-5421-379a-8d32-a51e09eb155a.png">

下図は、新たに「しょうかん」を追加したスクリプトです。
商人とは違い、「しょうかん」するスクリプトに数値が追加されています。
(例として「ハート」をしょうかんしています)
<img width="431" alt="pl02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/2673d79b-1435-bca8-ee68-946e7ef85168.png">

この「しょうかん」では、オブジェクトのしょうかん位置を、主たるプレイヤーの相対パスで座標しています。(下図参照)
<img width="431" alt="スクリーンショット 2020-03-30 21.41.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/c6c7fe53-7c2e-4d6a-950f-506de04ae964.png">

ハックフォープレイでは、通常の位置取得は、左上からの絶対パスです。
<img width="223" alt="pl03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/a3251df8-7fb5-96ae-1e80-13851732575a.png">

そのため、「しょうかん」する際、座標に気をつけてスクリプトを設定すれば、下図のようになります。
<img width="404" alt="nn01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/b530f21e-8298-9246-129b-d7c2b49fdd8a.png">
<img width="110" alt="nn02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/77bcec1e-18b8-2766-5cb1-0e5fb86fa507.png">
<img width="117" alt="nn03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/0a4c5c33-04d9-2a9d-4ffb-485c2db60d4e.png">

おさらい
ハックフォープレイは、code9leapのように、左上からのパス指定になるので、
「しょうかん」する際の座標設定は、主たるプレイヤーの右向きをイメージして設定すると良いでしょう。

---

【実践】
<img width="515" alt="pl05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/7f5e3f21-bec4-f69d-a38f-7951ef508ae1.png">
<img width="277" alt="xx01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/c51dd304-7ac8-dd66-ed33-43032f356c07.png">

---

どうでしたか？
直近のアップデートで、アセットの名前指定がしやすくなったのもあり、
より華美な攻撃が実現しやすくなったと思います。

それでは最後に、この事例を体現していた息子yuckey氏の作品を紹介して締めたいと思います。

【総合ビーム.トルネード！、仲間も敵も、強敵も！】
https://www.hackforplay.xyz/works/TVYYiVqg5lFwzSNcbasY
<img width="662" alt="yc01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/90d4e6c4-d47d-bc4e-0ffa-9bbed1150f3f.png">

---

TANIさんにも紹介していただき、ありがとうございます。

ハックフォープレイ実況　みんなの作ったステージを、TANI がプレイします！
なんだこの新スキルはｗｗ【ハックフォープレイ実況】
https://youtu.be/64EAWLQgLPE
修正しやすいCSSプリプロセッサの書き方を考える

最近はcssを直接修正することがほぼなく、scssやstylusなどを使って修正をすることがほとんどで、色々なCSSプリプロセッサの機能を使って書くことがほとんどになりました。
その分生のcssを調整する時に感じなかった「こう書かれると困るなー」、「こう書いたけど見にくいなー」というのが色々出てきたので、覚書。

## &を使ってのネスト

デベロッパーツールから該当クラスをコピーしてエディターのプロジェクト内検索を行った際、以下のようにネストされると、検索結果に引っかからず目視で該当のクラスを探す必要が出てくるため、＆を使用してのネストの多用を避ける。
もしくは使用箇所をmodifireのみに限定する。


``` scss
// 検索に引っかからない。
.block {
  width: 600px;
  margin: 0 auto; 
  &__element {
     font-size: 16px;
     &--modifier1 {
       color: #ff0000;
     }
     &--modifier2 {
       color: #00ff00;
     }
  }
}

// 検索に引っかかる。
.block {
  width: 600px;
  margin: 0 auto;
}
.block__element {
  font-size: 16px;
}
.block__element--modifier1 {
  color: #ff0000;
}
.block__element--modifier2 {
  color: #00ff00;
}
```

## extend

該当の要素の修正を行った際、以下のように他箇所でextendされているのを気づかず対応した場合、他箇所に影響が出てしまう。
気づいたとしても対応する場合に新しいクラスを作成する必要が出てくるため、使用する場合は、mixinかプレースホルダセレクタ※を使用する。

``` scss
// 修正箇所
.block1 {
  width: 600px;
  margin: 0 auto; 
}

// 間に色々な記載

// 気づかず影響を受ける箇所
.block2 {
  @extend .block;
  backgroud: #000;
}

.block3 {
  @extend .block2;
  margin-bottom: 60px;
}
```

### ※プレースホルダーセレクタの書き方

``` scss

// プレースホルダーセレクタ、cssにはコンパイルされない
%extend-block {
  width: 600px;
  margin: 0 auto; 
}

// 他箇所の影響を考えずここだけ修正出来る。
.block1 {
  @extend %extend-block;
}

.block2 {
  @extend %extend-block;
  backgroud: #000;
}

.block3 {
  @extend %extend-block;
  backgroud: #000;
  margin-bottom: 60px;
}
```

## 演算
式だけ見ると、どういう風に計算されているか分からない場合があるため避ける。
使用する場合は、コメントアウトで補足を入れる。

``` scss
// 式が不明
.block1 {
  width: (690 / 750 * 100)vw;
}

// 式が分かる
.block1 {
 // デザイン上の要素の横幅 / デザイン幅 * 100 
  width: (690 / 750 * 100)vw;
}
```
vue-chartjsでデータの数に応じてグラフサイズを変える

## やりたいこと
1. Horizontal Barグラフでデータ数が増えたときに、ラベルが間引かれるのを防ぎたい。
2. さらに、Barが小さくなるのではなく、グラフの方が大きくなって欲しい。


## 1.に対する解決策
`autoSkip: false`を設定する。

```js
yAxes: [{
  ticks: {
    autoSkip: false,  //ラベルを間引かない
    fontSize: 10,
  },
}]
```

## 2.に対する解決策
基本的に`responsive: true, maintainAspectRatio: false`の2つを設定すれば実現可能。


しかし今回は開閉するパネル内にグラフを配置しており、パネルの開閉時にグラフの高さが0から増えないという現象に悩まされたので、明示的に高さを指定するようにする。

```js
data () {
  labels: this.label,
  datasets: [{
    data: this.value,
  }],
  return {
    options: {
      responsive: true,  //レスポンシブ
      maintainAspectRatio: true //縦横は固定
    },
  }
}

mounted () {
    this.$refs.canvas.height = this.value.length*17.5; //データ数に応じて高さ指定
    this.renderChart(this.data, this.options)
  },
```
emacs と vim の lsp をdocker で試す

# はじめに
[language server](https://code.visualstudio.com/api/language-extensions/language-server-extension-guide)(以下 lsp)の登場でどのエディタでも、統合環境のような高機能エディタとなることが可能になりました。
みんな大好き emacs や vim でも lsp をサポートし、言語ごとの設定が大分楽になり敷居が下がってきたんじゃないかなって思います。しかし、如何せん試してみるのも面倒だなーって思う人は結構いるはずです。試してみる気力があったらとっくに入門してますしね...。
そこで、今回は emacs と vim の lsp 設定が内包した docker を使ってみて最新エディタ気分を味わっていきたいと思います。

# emacs + lsp on docker
まず、emacs + lsp です。最近は spacemacs が流行っていますが今回は普通の emacs でやっていきます。最初に、以下のコードで emacs + lsp on docker のコードをローカルに落としてきます。

```sh
git clone https://github.com/emacs-lsp/lsp-docker.git
```

権限を与えて実行します。

```sh
cd lsp-docker
chmod u+x start-emacs.sh
./start-emacs.sh
```

立ち上がったら、パッケージのインストールを聞かれるので`y`で進んで行きます。

<img width="570" alt="スクリーンショット 2020-03-29 13.44.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488897/b1034939-07bd-4093-5fde-f2c61db1e3a7.png">

インストールが終わったら、`C-x C-f` で `Project` の適当な言語のファイルを開いて見ます（`C-x` は windows だと `Ctr+x`、mac だと `⌃+x` です）。
<img width="571" alt="スクリーンショット 2020-03-29 13.54.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488897/39030176-0c44-4c51-d5e4-7b7caf219a21.png">

ファイルが開けたら、適当に色々試して見ながらコーディングすると楽しいと思います。
補完が効いているのとかがよく分かると思います。
<img width="561" alt="スクリーンショット 2020-03-29 13.57.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488897/247f579e-7220-76e2-0b28-6727aa10550d.png">

ただ、定義ホバーがオンになっているせいかdockerとの相性なのか、少し重いですね...。
詳しい挙動やできることなどは以下を見ていただけると助かります。
https://github.com/emacs-lsp/lsp-mode


# vim + lsp on docker
次に vim + lsp です。こちらも流行りの neovim でなく普通の vim でやっていきます。今回も同じようにコードを落としてきます。今回は公式で用意されていなかったため自前で用意しました。

```sh
git clone https://github.com/komem3/vim-lsp-docker.git
```

Docker イメージをビルドします。

```sh
./build.sh
```

emacs + lsp のようなサンプルプロジェクトを用意するのが面倒だったため、引数にサンプルプロジェクトへのパスを指定して実行します。

```sh
vim-lsp-docker % PROJECT_DIR=~/Downloads/lsp-docker/demo-projects ./start.sh # PROJECT_DIR に lsp-docker/demo-projects へのパスを指定する
```


コンソールが開けたら、`Project`下の適当なファイルを vim コマンドで開いてみます。
(TypeScriptとC++はうまく動かせなかったので他の言語でおねがいします...)

```sh
vim Project/Javascript/hello-world.js 
```

こちらもファイルが開けたら適当にコーディングしてみると楽しいと思います。
vim の軽さをすごい感じます。
<img width="570" alt="スクリーンショット 2020-03-30 19.29.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488897/1847f5af-1152-4b2d-7713-651ecc179e51.png">

詳しい挙動やできることなどは以下を見ていただけると助かります。
https://github.com/prabirshrestha/vim-lsp

# 終わりに
お手軽に emacs や vim の lsp を試せるので、興味がある人は試してみてほしいなって思います。
また、今回使った emacs や vim の設定ファイルはどちらもとても短い記述内容になっているので、軽く見てみると簡単に設定できるもんだなぁって思うと思います。

- [emacsの設定](https://github.com/emacs-lsp/lsp-docker/blob/master/emacs.d/init.el)
- [vimの設定](https://github.com/komem3/vim-lsp-docker/blob/master/.vimrc)

今回の設定はどちらも最低限のものになっていますが、emacs や vim の魅力は高い拡張性や自分好みの設定にし放題なことのため、まだまだ力を温存しています。しかも最近は spacemacs とか neovim とか出てて楽しい界隈だなぁ。
ラズパイでLチカプログラム

初投稿です。
ラズパイでLチカプログラムを作成したので、投稿してみます。
使用しているのはmodel3Bです。

※この手の記事は探せばいくらでも出てきますので、本記事は自分自身の備忘録の意味合いが強いです。

```python
import RPi.GPIO as GPIO
import time

GPIO.setwarnings(False) #GPIO使用時に表示されるエラーを消すための記述
GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.OUT) #GPIO2を出力端子に設定

try: #try~exceptでひとかたまり
    while True:
        GPIO.output(2, GPIO.HIGH)
        time.sleep(1) #1秒休止
    
        GPIO.output(2, GPIO.LOW)
        time.sleep(1) #1秒休止

except KeyboardInterrupt: #キーボード入力により処理を抜ける
    pass #passをつけることで、抜けたあとの処理を指定せずスルーする

GPIO.cleanup() #GPIOピンの開放 つけていないと次実行した際にエラーになる
```
実際に光らせているところはこちら↓
<blockquote class="twitter-tweet"> <a href="https://t.co/7pnkOKMksP">pic.twitter.com/7pnkOKMksP</a> <a href="https://twitter.com/shi78ge/status/1242448818907410433?ref_src=twsrc%5Etfw">March 24, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

##参考サイト
[RaspberryPiでLEDライトを点滅する](http://www.ic.daito.ac.jp/~mizutani/raspi/blinkingLED.html)

GPIOのエラー処理↓
https://teratail.com/questions/173544

try~exceptの使い方
https://note.nkmk.me/python-try-except-else-finally/

以上
discord.js最新版での罠(私的メモ)

discord.jsが11.xから12.xにアップデートされたので自分が引っかかりまくった点をサクッと書いていきます

# Nodejsとdjsのバージョン
discord.js 12.xからはどうやらnodejs 12.xからじゃないと出来ないっぽくて見事にハマってました
自分はちょっと都合でnodejs8.10くらいを使ってまして、discord.jsを入れてbotを起動させようとしたら謎の場所でエラー吐いてまして…色々調べてたらバージョン関係で使えなかったことがわかって仕方なくnodejsとnpmを最新版にして使いました

# djsの仕様変更
色々と変わったので自分が知ってる限りの仕様変更部分をまとめます。

## xxxs系
xxxs系は`<client>.channels`や`<message>.guild.roles`などの複数の情報が入ってるやつです。
11.xでは`<client>.guilds.get('channelId')`などで出来たのですが、最新版になって`<client>.guilds.**cache**.get('channelId')`と、**cache**をつけないとArrayとして認識されなくなれました(xxxsはmanager系になってました、それでcacheにCollection系が移動されたんだと思います。)

## ボイス系
ボイス系は`<message>.member.voice`です
前のバージョンは`<message>.member.voiceChannel.join()`とかだったと思うんですけど、最新版だと`<message>.member.voice.channel.join()`になってます。
あとはモジュールの変更ですかね
旧モジュール: 
node-opus, ffmpeg-binaries
新モジュール: 
@discordjs/opus, ffmpeg-static
opusscriptはまだ使えるかは不明。

# 追記(2020/3/31)

## メッセージ関連
最新版djsになって、メッセージを送信する時のやつが完全に消えました

```js:12.xで消えたもの
const ch = <message>.channel;
ch.sendCode();
ch.sendEmbed();
ch.sendFile();
ch.sendFiles();
ch.sendMessage();
```

これは11.xでもDEPRECATEDが付いていたので多分知ってた人は知ってたと思います。

ついでに、基本メッセージ送信は`<message>.channel.send();`です、リプライは`<message>.reply();`です。

## message系に関して
embedの`RichEmbed`が`MessageEmbed`に変更されています。

自分的にはこれ使うよりオブジェクト型で書いた方が直感的かなーと思ってたりしてます

```js:embed-sample.js
<message>.channel.send({
  title: 'Hello',
  description: 'Discord.js!'
});
```

こんな感じの書き方があるのでぜひこの書き方をおすすめしたい

※ 4/5追記
`<message>.channel.fetchMessages()`は最新版では消えてます、多分`<message>.channel.messages.fetch()`に移動されてるのでmessages.fetch()の方を使いましょう。

# おわり
自分が見てきたとこだとこれくらいですかね、他にもあったような気がするので思い出したら追記しようと思います。

## 参考
[discord.js](https://discord.js.org)
[個人サイト/ブログ/Qiitaなど]ゆるふわにGoogle Analytics からSlackに通知したいと思ったら簡単だった

あなたの所有しているサイトやブログ、あるいはQiitaにGoogle Analyticsって入れてますか？
（実はQiitaにもGAを導入できると @sapi_kawahara に教えてくいただきました！）
多分、入れてる人は多いんじゃないかと思います。

ではそのレポート、どれぐらいの頻度で確認してますか？
サイトの運営規模にもよりますが、私は一週間スパンで知りたいと思っています。
**が、自分で都度見に行きたくはありません。** 忘れますよそんなの。面倒だし。

できればレポートの結果だけを文字（表）でサクッと見れたらとっても嬉しいなーと思いました。
でもそんな方法あるんでしょうか？

あるんだなこれが。

意外と **出来るって知ってさえいれば** 簡単（当社比）にできたので、参考になるリンクをばばっとまとめてみました。


## Google AnalyticsのレポートをGoogle Spreadsheet に落とす
Google同士なので連携するためのアドオンがあり、めっちゃ簡単にできます。

- [スプレッドシートでGoogle Analyticsの数値を毎日自動更新しよう - ペパボテックブログ](https://tech.pepabo.com/2017/06/01/analytics-spread-sheet-add-on/)

私は上記の記事を参考にしました。
また、レポートを作る段になって、MetricsとDimensionsがさっぱりわからなかったので以下の記事も参考にしました。

- [Googleアナリティクスの自動デイリーレポート＆よく使うMetrics一覧](https://tonari-it.com/analytics-metrics/)
- [記事別ページビューランキングを自動で取得＆よく使うDimensions一覧](https://tonari-it.com/analytics-pageviews-ranking/)

最終的に私が設定したレポートは以下です。

| Report Name | 人気記事 | ユーザー数とPV数 | 参照元 |
|:--|:--|:--|:--|
| View ID | --- (*1) | --- | ---- |
| Start Date | 7daysAgo | 7daysAgo | 7daysAgo |
| End Date | yesterday | yesterday | yesterday |
| Metrics | ga:pageviews | ga:users,ga:pageviews | ga:pageviews |
| Dimensions | ga:pageTitle | ga:date | ga:fullReferrer |
| Order | -ga:pageviews |  | -ga:pageviews |
| Filters |  |  |  |
| Segments |  |  |  |
| Limit | 1000 | 1000 | 1000 |

*1 自分がCreate Reportしたときに自動生成されたIDをいれる

Start Date を7daysAgoにすると直近1週間分からレポート生成、
Orderでソートです。

今回は週次でレポートを生成してほしいのでScheduled Reportで週次月曜日を選択しました。

## Spreadsheetの結果をSlackに通知したい
Spreadsheetの結果をSlackに通知するにはGoogle App Scriptを使えば簡単にできそうです。
私ははじめ、以下の記事を参考にしました。

- [Google Apps Scriptを使って、スプレッドシートの内容をSlackに通知する ｜ Tips Note by TAM](https://www.tam-tam.co.jp/tipsnote/javascript/post8499.html)

Slack通知の実際の処理はIncoming Webhookを使ったほうが簡単でした。

- [Slack での Incoming Webhook の利用 \| Slack](https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8#incoming-webhook-u12398u35373u23450)
- [Sending messages using Incoming Webhooks \| Slack](https://api.slack.com/messaging/webhooks#posting_with_webhooks)

![スクリーンショット_2020-03-30_21_36_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122390/0a7cb831-898e-f057-b4d5-e52971ff189c.png)


元のロジックの余計なところを取っ払ったり、レポートのフォーマットに併せて整形するのはお任せします。
スクリプトを実行してSheetからデータを引っ張ってくるとき、許可を求められるのですが、
私が試したときはその際にSSL証明書の切れたサイトにアクセスしたかのような警告画面が表示されましたが、
注意深く確認しながら許可します。

最終的に私のロジックはこのようになりました。

- [Google Analytics\(Sheet\) to Slack](https://gist.github.com/fruitriin/5d9ed625b8a2f3837a3ff6f9be6b59e2)


結果、このようなレポートがSlackから得られるようになります。
![スクリーンショット 2020-03-29 23.43.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122390/9b90632a-4964-b9db-e08a-cc621b559829.png)

最後に、GASもスケジュール実行するようにして完成です！

自分でサイトなどを持っている方は、是非自分のサイトのステータスを定点ウォッチに挑戦してみるのはいかがでしょうか。