OmniAICreator/Qiita-1.07M huggingface dataset:
MATLABからCOTOHA APIをコールしてみた

# はじめに

めっきりご無沙汰していました。変わらずテキスト解析に従事した日々を過ごしていましたが、この度[【Qiita x COTOHA APIプレゼント企画】COTOHA APIで、テキスト解析をしてみよう！](https://zine.qiita.com/event/collaboration-cotoha-api/?utm_source=qiita&utm_medium=banner)という記事を見つけたので久しぶりに投稿してみます。
COTOHA APIとは何か？については、[公式のページ](https://api.ce-cotoha.com/contents/index.html)からご確認ください。何やら色々とできそうで、見るからに楽しそう！

# やったこと

ということで、今日は、このCOTOHA APIの使い方を紹介したいと思います。過去の記事なんかを見ているとPythonからコールしている例が多いですが、私は普段MATLABを使用しているので、MATLABからよんでみます。
一度コツをつかんでしまえば簡単なのですが、最初は何かとコードの書き方に迷ったので、少しでも他のMATLABユーザーさんのお役に立てたら嬉しいです。

# 手順

### COTOHA API for Developersに無料登録

こちらは[公式ページ](https://zine.qiita.com/event/collaboration-cotoha-api/?utm_source=qiita&utm_medium=banner)のSTEP1と同じです。
アカウントを作成後、COTOHA API Portalのアカウントホームで、こんな感じでURLやIDなどが確認できればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521542/22ca8516-6045-2e28-8f53-493dd9de5d3d.png)

### アクセストークンを取得する

こちらの[公式リファレンス](https://api.ce-cotoha.com/contents/reference/accesstoken.html)のやり方に従って、アクセストークンを取得します。MATLABコードは下記。clientidとclientsecretには、ご自身のものを入れてくださいね。

```MATLAB:getAccessToken
clientid = 'input_your_Client_ID';
clientsecret = 'input_your_Client_secret';

url = 'https://api.ce-cotoha.com/v1/oauth/accesstokens';
options = weboptions('RequestMethod','post', 'MediaType','application/json');
Body = struct('grantType', 'client_credentials', ... 
          'clientId', clientid, ...
          'clientSecret', clientsecret);
response = webwrite(url, Body, options);
```

すると、responseの中に、アクセストークンを含んだレスポンスが格納されます。

```MATLAB
>> response

response = 

  フィールドをもつ struct:

    access_token: 'your_access_token'
      token_type: 'bearer'
      expires_in: '86399'
           scope: ''
       issued_at: '1581567299154'
```

### 「構文解析」のAPIをたたいてみる

こちらの[公式リファレンス](https://api.ce-cotoha.com/contents/reference/apireference.html)のやり方に沿って、試しに構文解析をしてみます。MATLABコードは下記。sentenceに、解析したい文字列を入れてくださいね。

```MATLAB:parsing
sentence = '私は母と焼き肉を食べた';

baseurl = 'https://api.ce-cotoha.com/api/dev/';
accesstoken = response.access_token;
Header = {'Content-Type', 'application/json;charset=UTF-8'; 'Authorization', ['Bearer ' accesstoken]};
Body = struct('sentence', sentence, ... 
          'type', 'default');
      
options = weboptions('RequestMethod','post', 'MediaType','application/json','HeaderFields', Header);
response2 = webwrite([baseurl 'nlp/v1/parse'], Body, options);
```

### 結果を確認

上のコードを実行すると、response2に結果が返ってきますので、公式リファレンスの説明と照らし合わせながら結果を確認してみましょう。
色々と階層があって、パッと一覧させることが難しいのですが、粗方こんな感じで結果が見れます。すごーい！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521542/64a2bd86-6e9b-73b7-dcff-c9f8bc222b54.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521542/0012d206-9798-7729-945c-f5bbebd51b76.png)

# おわりに
今日はひとまず「構文解析」までですが、この要領で、他のAPIも使えるはずです。
返ってきた結果の理解や処理にはまたひと手間必要そうですが、MATLABの可視化機能やテキスト解析機能と組み合わせて、何か面白いことができないかな～なんて思います。
namespaceをURLに反映させたくない。

namespaceやってると、管理上分けてるだけなのにいらんもんがURLに出てくる。
例えば管理者(admin)とユーザー(public)の画面を分けていたりすると

```
namespace :public do
 resources :posts, only: [:index]
end
```
```
public_posts GET    /public/posts(.:format)        public/posts#index
```

こうなる。/publicがどう考えても邪魔。
ので、root.rbを書き換える。

```
scope module: "public" do
　resources :posts, only: [:index]
end
```

```
 posts GET    /posts(.:format)      public/posts#index
```

スッキリ！
pythonのパッケージにパッチを当てた記録

# 俺は悪い子なんだ
**注: この記事はそれなりにニッチです**

使っているpythonパッケージに無い機能が欲しくてたまらなかった。
時に研究者は他人の使わないような物を用意せねばならぬのだ。
しかし、その機能はニッチなもで[^douki]プルリクしたって受け取られるわけがないのだ。
だからパッチを作成した。

# 自前patch？gitじゃ駄目なん？
ご存知の通り、UNIX系にはpatchというコマンドがある。これを用いる。
gitでいいけど、**論文に「変な変更はしてないぽよ。差分はここだけぽよ。」って書きたかった(重要)。**

# 作成手順
git diffをすることによって自分やった変更を出力できる。
だから、patchの作成のためだけにgitを使う。歴史を巻き戻せるのも良い。
というわけで、結局gitは使うのだけれどね。

まず、編集するために、使っているパッケージのソースコードの元に飛かねばならなかった。
仮想環境だろうがどこだろうが、ワンライナーで行ける。下記のhogeを書き換えて飛んでいった。

```bash
cd $(python -c "import hoge as target; from pathlib import Path; print(Path(target.__file__).parent)")
```
で、編集する前に、一応git管理しておく。

```bash
git init
git add *
git commit
git branch patch
git checkout patch
vim hoge.py
```

git add *はキャッシュまで含んでしまうかもなので、まぁ、そこは適切に。
僕はvimmerなのでvimで編集しているが、もちろんvimじゃなくていい。変更し終わったらdiffする。

```bash
mkdir ~/warui_patch
git diff > ~/warui_patch/complex.patch
```

これでパッチの作成は終了だ。

# ソースコード
以下、さっきのパッチをパッケージに当てるためのシェルスクリプトだ。
下記ではmneパッケージに、さっき作成したcomplex.patchを当てている。
オプションをいくつかつけている。

- -R: パッチを戻す
- -p: 該当のパッケージのパスを表示する
- -h: ヘルプ

この、該当のパッケージのパスを表示するのは、僕が何か編集したい時に

```bash
cd $(sh ./patcher -p)
```
として、該当パッケージのもとにひとっ飛びできるようにするためのオプションだ。
当然仮想環境でも鉄の意志で飛んでいくぞ。

```bash
#!/usr/bin/env sh
OPT=$1
PACKAGE='mne'
PATCH='complex.patch'

make_python_path_code () {
  echo "import $PACKAGE; from pathlib import Path; print(Path($1.__file__).parent)"
}

make_python_path () {
  echo "$(python -c "$(make_python_path_code $1)")/"
}

patch_python () {
  patch $OPT -u -p 1 -d $(make_python_path $1) < $2
}

if [ "$1" = "-h" ]; then
  echo Patch script for python.
  echo ========================
  echo -h: Show this message
  echo -R: Reverse patch
  echo -p: Print script dir
  exit
fi
if [ "$1" = "-p" ]; then
  echo $(make_python_path $PACKAGE)
  exit
fi
patch_python $PACKAGE $PATCH
```

# 感想
研究のためとはいえ、本当はパッケージの書き換えなんか、やりたくない。
辛い…(´・ω・｀)


[^douki]: 脳波をWavelet変換して複素数から絶対値の平均を算出し、脳内での脳波の大きさを推定したかったが、俺は絶対値の平均じゃなくて複素数が欲しかったのだ。平均しないぶんだけ、計算コストはヤバくなる。
Githubに草が生えなくて困った話


全然草が生えなくて困ったので記事にしてみました。

# TL;DR
- Githubでリポジトリを作成してからcloneしたらおきた
- githubのpublic emailの設定をしていなかったらusers.noreply.github.comになってた
- githubのアカウントの設定なおした
- リポジトリのautherを変更した
- 草生えた


## 初めに
先週4日間ほどまとまった休みが取れたので、久しぶりに自主開発でもしようと思い、githubでリポジトリを作りました。
そのあとSource Treeでローカルにクローンして環境構築の過程でコミットを重ねていたのですが、どうにも草が生えません。

### 確認したこと

- githubのメールアドレス
    - settings/Emails の **Primary email address** はログイン時に使用しているものが設定されていた。
- ローカルのメールアドレスもgithubと同じものが設定されていた。
- 基本的にはローカルのメールアドレスとユーザー名がコミッターとしてリポジトリの変更履歴に残る。
- initial commitのコミッター名は **Googlesensei@users.noreply.github.com** このような形式になっていた。

### 調べてみると

> If you enabled email address privacy, then the commit author email address cannot be changed and is <username>@users.noreply.github.com by default. In the upper-right corner of any page, click your profile photo, then click Settings. In the left sidebar, click Emails.

どうやら **public email address** として登録が済んでいない場合、デフォルトでgithubドメインのメールアドレスを利用した形式で登録されるらしい。
なので、いくらコミットしてもgithub側では同一人物として見られていなかった。

```
リポジトリの製作者：Googlesensei@users.noreply.github.com
リポジトリの変更者：Googlesensei@example.com(仮)
```

### 変更してみると
github/settings/Profile の **Public email** にローカルのメールアドレスと同じものを登録し、テストコミットをしてみるたけど、それでもまだ草は生えなかった。

ここで気になっていたの initial commit の作者 **Googlesensei@users.noreply.github.com** だ。
source treeからは変更できないのでCLIで変更し、リモートへプッシュ。

### 草生えた


というわけでようやく環境構築も済ませることが出来たのでこれからガシガシコード書いていきたいと思います。
githubに草を生やすことが目的ではないですが、自分の行動履歴のようなものにもなるので、ちゃんとコーディングしたなら生えてほしいですもんね。

### 草生えてなかったｗ：追記

どうやら草を生やす要件の一つに、デフォルトブランチにコミットをすることが必要条件がありました。
かくしてデフォルトブランチをdevelopに変更することで草が見事に生えました(生えてなかった日のも生えました)

## 参考
[githubのサポートページ](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/setting-your-commit-email-address)
[GitのCommitユーザを修正する方法](https://qiita.com/y10exxx/items/dcea0e39788d649ca8ba)
FluentDをMacでセットアップして、CloudWatchLogsへログ転送するまで

## はじめに

実務で、ローカルで稼働しているMac miniが複数台あるので、それをCloudWatchLogsへ集約したいという要望があったので、勉強がてらFluentDを使った時の備忘録的なアレです

色々、試行錯誤しながら試したので、同じくハマっている人の助けになればと思います


## 失敗パターン

td-agentを使って、CloudWatchLogsに転送させる設定をしようとしたが、ripperが足りない?せいか、以下のエラーが発生して、td-agent内包のRubyを使っているため、これ以上は自力解決が難しいと思い、断念

```ruby

`require': cannot load such file -- ripper (LoadError)
```

### やったこと

1. FluentD公式から、MacOS向けのtd-agent.dmgをDLして、セットアップ
https://docs.fluentd.org/installation/install-by-dmg

2. CloudWatchLogsに飛ばすためのPluginは、ここからDL
https://github.com/fluent-plugins-nursery/fluent-plugin-cloudwatch-logs

README.md通りに、`gem install fluent-plugin-cloudwatch-logs` を実行しても、td-agent自体が、そのものに内包されているRuby(2.4)を使用してるっぽいので、エラーになる

```ruby
Starting td-agent: 2018-05-31 01:27:51 +0000 [error]: fluent/supervisor.rb:373:rescue in main_process: config error file="/etc/td-agent/td-agent.conf" error="Unknown output plugin 'cloudwatch_logs'. Run 'gem search -rd fluent-plugin' to find plugins"
td-agent    
```

3. td-agentを使っている場合は、td-agent-gemを使用して、インストールする

インストールコマンド
`/opt/td-agent/usr/sbin/td-agent-gem install <プラグイン>`

インストール済みリストを取得
`/opt/td-agent/usr/sbin/td-agent-gem list`


### 参考にしたリンク

https://qiita.com/nkg/items/cbf72adb436456804d76


## 成功パターン

td-agentだと、内包されているRubyを使う方法だったので、すでにインストールされてるRubyを使う方法を採用しました
下記を実行すると、CloudWatchLogsへ、自動的にログストリームが作成され、ログが出力されるようになりました

### やったこと

- gem版のFluentDをインストール→セットアップ

```bash
# FluentDのインストール
$gem install fluentd -N

# セットアップ
$ fluentd --setup ./fluent`
```

https://docs.fluentd.org/installation/install-by-gem

- gemを使って、CloudWatchLogs-Pluginをインストール

```bash

# fluentd-cloudwatch-logs-pluginをインストール
gem install fluent-plugin-cloudwatch-logs
```

- fluentd.confファイルを編集

```
<source>
  @type tail
  path ./logs/logger.log
  tag sample
  <parse>
    @type multiline
    format_firstline /\[(\d{4}-\d{2}-\d{2}T\d{1,2}:\d{1,2}:\d{1,2}.\d{1,3})\]/
    format1 /^\[(?<logtime>\d{4}-\d{2}-\d{2}T\d{1,2}:\d{1,2}:\d{1,2}.\d{1,3})\] \[(?<lebel>.*)\] (?<hoge>.*) - \[(?<title>.*)\] (?<message>.*)/
  </parse>
</source>

<match sample>
 @type cloudwatch_logs
 log_group_name test
 auto_create_stream true
 use_tag_as_stream true
</match>
```

- IAM User Policyの設定

```json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:*",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:logs:us-east-1:*:*",
        "arn:aws:s3:::*"
      ]
    }
  ]
}
```

- AWSのアクセスキーとシークレットキーを環境変数に登録

```
export AWS_REGION=us-east-1
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"
```


- fluentdを起動&停止

    - 起動
    `fluentd -c ./fluent/fluent.conf -o  ~/Desktop/tmp/fluentd.log -vv &`

    - 停止
    `pkill -f fluentd`


## まとめ

初めてFluentDを使って、ログの収集を行いましたが、ドキュメントがかなり充実していたので、ハマりはしたものの設定ファイルを作る等は、そこまで苦労しませんでした。
いろんなPluginがあるので、まだまだ色々できそうな気がしています。
また、FluentDとtd-agentでの挙動が違ったりする場合があるので、調査の時には注意が必要かなと思いました。
sqlalchemyでparent idを取得する方法

# parent_idを自動で採番したい
データベースにおいてデータの親子関係の情報を入れたい場合に必要になります。
例えば、あるホテルに複数の部屋が紐づいている場合やあるサービスに複数のプランが紐づいている場合などです。

重要なポイントは以下の2点です。
1. 子データの格納前に親データのIDを取得する必要がある
2. 子データの格納でエラーとなった場合は親データの格納前までロールバックする必要がある

# sqlalchemyの場合はsession.flush()を使う

```
session.add(parent_record) # トランザクションの登録
session.fluhs() # DBへの登録（保存はされない）
parent_id = parent_record.id # 親IDの取得
```
session.add(record)の時点では親データのIDがふられていないため、取得できません。
session.flush()することで親IDがふられ、取得できるようになります。

# session.commit()を使わない理由
```
session.add(parent_record)
session.commit() # DBへの登録（保存はされる）
parent_id = parent_record.id # 親IDの取得
```
session.commit()でデータベースに格納でき、親IDが振られるため取得することができます。
ただし、重要ポイント2で言及しているロールバックができなくなってしまうため、子データで格納に失敗すると、親データだけ格納されている状況が発生してしまい、子データの登録時に手間がかかってしまいます。（手動で親IDを付与するなど）
できれば親データと子データは同じセッションでコミットした方がインサートが効率的になります。
SSLを適用しているWebサイトなのに、アドレスバーに『保護されていない通信』と表示された

本日（2020/02/13）、チームメンバーから「SSLの更新忘れてました。。。」と相談を受けました。
理由を伺うと、「アドレスバーに『保護されていない通信』と表示されている」とのこと。
私もSSL更新のサポートしていたので、漏れていないはずだと思い調査しました。

## まず結論

予想通り Chrome のバージョンアップの影響でした。
以前から予告されていましたが、TLS 1.0/1.1 を無効化するための経過措置のようです。

https://forest.watch.impress.co.jp/docs/news/1210387.html

上記ページでは Chrome 79 から影響が出るような表記でしたが、私の環境では Chrome 79 は問題なく Chrome 80 で影響が出ました。

## 問題の切り分け

自分のPCで調査したところ、アドレスバーに『保護されていない通信』と表示はされず。
また、証明書の期限もゆうに半年以上残っていることを確認しました。
私が使用しているのは、Vivaldi というブラウザで、社内でも私しか使用していません。

チームメンバーに確認したところ、「Chrome を使用している。さっき気がついた」とのことでした。

まさかとは思い該当URLのTLSバージョンを確認したところ、1.0 しか有効になっていませんでした。。。


## SSL/TLS の調査を行うには

下記のWebサイトで、URLを入力すると簡単に調べられます。

https://www.ssllabs.com/ssltest/index.html

Protocols の欄に TLS のバージョンが表示されます。


## 解決方法

速やかにTLS 1.2 にバージョンを上げてください。
方法はレンタルサーバー業者やミドルウェアの関係でいろんなケースがあると思われるので、ケースバイケースになるかと思われます。

## 放置したらどうなる？

ChromeではHTTPSで接続しているのに、全画面で警告表示され正常にWebサイトが閲覧できなくなります。（予定）

こんな感じになるらしいです。
https://forest.watch.impress.co.jp/img/wf/docs/1210/387/html/image2.jpg.html

これはかなりまずいです。。。


## 最後に

個人的には、すべてのWebサイトをSSL/TLSにする必要はないと思っているんですが。。。
Google 様には従うしかなさそうです。
vue.js で サイト完成後にやっておきたいテスト

まぁ、重い。ページがすごく重い。
他の人の作ったvue.jsサイトを見ると 9点とかもある。

重い場合はCSSを別読み込みにするといいかも。
これで 80点以上に上がる。

```vue.blade.php

<script type="text/javascript">
    // 非同期でfontawesomeを読み込む
    (function() {
        var css = document.createElement('link'); css.href = 'https://use.fontawesome.com/releases/v5.11.2/css/all.css'; css.rel = 'stylesheet'; css.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(css);
        var css2 = document.createElement('link'); css2.href = '/css/app.css'; css2.rel = 'stylesheet'; css2.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(css2);
        var css3 = document.createElement('link'); css3.href = '/css/lightbox.css'; css3.rel = 'stylesheet'; css3.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(css3);

    })();
</script>

```

ページスピードテスト
https://developers.google.com/speed/pagespeed/insights/


サーチコンソール
https://search.google.com/search-console/about?hl=ja

・サイトマップは登録してる？
・インデックスされるURLをテストするとちゃんとタイトルタグは変更されてる？

モバイルフレンドリー
https://search.google.com/test/mobile-friendly

・エラー出てない？
・インデックスされるURLをテストするとちゃんとタイトルタグは変更されてる？


テストマイサイト
https://www.thinkwithgoogle.com/intl/ja-jp/feature/testmysite/

すべてやっておきましょう。




```webpack.min.js

mix.js('resources/js/app.js','public/js') .version()
   .sass('resources/sass/app.scss','public/css')
   .sass('resources/sass/lightbox.scss','public/css');
                                                

```

こんな感じで version(); をつけておく。
じゃないとnpm run prod するたびにユーザー側にキャッシュが残り、ハードリロードしない限り更新されないというバグになるので。
Nuxt generate(SSR)で静的なのに動的コンテンツを入れた時に辛いこと

# Nuxt generate(SSR)で静的なのに動的コンテンツを入れた時に辛いこと

静的が安い！速い！上手い！

そう思いつつ、静的なコンテンツでありAPIベースなコンテンツを作成し始めた。  

と思ったら問題発生！

## @nuxtjs/proxyが使えない問題

CORSが辛い。
ローカルではCORSをいじる
本番はURLをサーバー側で許可してもらうなど
まだ、いい対策が見つからず

## asyncData使えない問題

こんな感じで書いてAPIを取得するが、これがgenerate時しか取得してくれない問題が発生

```html
<script type="ts">
async asyncData({ $axios }) {
  const data = await $axios.$get('https://api~')
  return {
    lists: data
  }
}
</script>
```

これはcreatedを使うことで解決しました。

```html
<script type="ts">
lists: any = []
async created () {
  const data = await $axios.$get('https://api~')
  this.lists = data
}
</script>
```

## methodsを使うとDOMの不一致になる問題

基本的にプリレンダリング型のSSRだとmethodsを使ったDOM操作はエラーになる。  
でもDOM操作したい！！

ということで登場するのが、client-onlyタグ！

```html
<template>
 <div>
  <client-only>
    <list :lists="lists" />
  </client-only>
 </div>
</template>
```

そもそもSSRなのにSSR回避するのはどうかと思うが...

APIで取得した値をシャッフルしたいんじゃ！

## computedでfor文のシャッフルするとobjectの中身がランダムにされる問題

これは消耗しました。

シャッフルの処理はあっているのに、なぜ他のリストにも影響が出てかつ、
画像とタイトルの不一致が起こるんだ...

そこでmethodsを使うことにSSR、、、

こうすることで初期レンダリングは遅くなるものの、DOMは更新することが可能になります。

```html
<template>
 <div>
  <client-only>
    <list :lists="shuffleList" />
  </client-only>
  </div>
</template>

<script type="ts">
...
lists: any = []
shuffleList: any = []
async created () {
  const data = await $axios.$get('https://api~')
  this.lists = data
  this.shuffleList = this.shuffle(this.lists)
}
shuffle (list) {
  for (let i = list.length - 1; i > 0; i--) {
    const r = Math.floor(Math.random() * (i + 1))
    const tmp = list[i]
    list[i] = list[r]
    list[r] = tmp
  }
  return list
}
</script>
```

## iOS Safariで自動的に電話番号がリンクになるのでDOMが不一致になる問題

これはmeta情報にformat-detectionを入れることで回避することができます。

```html
{ name: 'format-detection', content: 'telephone=no' }
```

入れないと何も表示されないのでご注意！

## まとめ

プリレンダリングSSRは安い！速い！上手い！ということで辛いこともありますが、対応するとメリットが多いと思います！
チュートリアルでありがちなテキストが少しずつ表示されていくUILabelを実装する方法

うまく表現できませんが、チュートリアルなんかでよく、「カタカタカタカタ」と少しずつテキストが表示されていくシーンがあるじゃないですか！（伝わってください）

今回はそれを実装しました。
~~既存のライブラリで存在していたら教えてください~~

少しずつテキストを表示して、表示中にタップされたらテキストを全部まとめて表示するUILabelを実装しました。


```swift:

// テキストを表示中を表すフラグと、早く表示するためのフラグです
fileprivate var isPlaying = true
fileprivate var isFast = false

fileprivate var tutorialLbl: UILable!

override func viewDidLoad() {
    super.viewDidLoad()
    
    // タップを検知
    self.singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.singleTap(_:)))
    self.view.addGestureRecognizer(self.singleTapGesture)
}

// 画面をタップした際に発火する関数
@objc func singleTap(_ sender: UITapGestureRecognizer){
        
    // 一度タップされていてテキストがカタカタと表示中のとき、表示速度を早めるフラグを立てる
    if self.isPlaying {
        self.isFast = true
        return
    }
    self.isPlaying = true
    
    // このメソッドはよしなに
    showTutorial()
}

fileprivate func showTutorial() {
    // ラベルをテキトーに作成
    self.tutorialLbl = UILabel()
    self.tutorialLbl.frame = CGRect(x: 0, y: self.view.bounds.maxY - 200, width: self.view.bounds.width, height: 200)
    self.view.addSubview(self.tutorialLbl)

    let text = "アイウエオかきくけこさしすせそ"

    // ここで表示
    self.showTextDynamically(label: self.tutorialLbl, text: Array(text), idx: 0)
}

fileprivate func showTextDynamically(label: UILabel, text: [Character], idx: Int) {
    var waitTime = 0.0
    // 表示速度を早めるフラグが立っていないとき、0.1秒間に一文字表示するよう待ち時間を設定
    if !self.isFast {
        waitTime = 0.1
    }
    // テキストを表示しきったときリターン
    if text.count == idx {
        self.isPlaying = false
        self.isFast = false
        return
    }
    if label.text == nil {
        label.text = ""
    }
    // 0.1秒遅延して再帰する
    DispatchQueue.main.asyncAfter(deadline: .now() + waitTime) {
        // テキストをlabelに追加する
        let c = text[idx]
        label.text! += String(c)
        self.showTextDynamically(label: label, text: text, idx: idx + 1)
    }
}
```



こういうのってtimerを使うのが一般的なんでしょうか。
NuxtとVueを基礎から学びなおすために。Vue Schoolのすすめ

#TL;DR
[Vue School](https://vueschool.io/)に登録してみたら、VueとNuxtの理解が深まった。

※この記事は下書き保存したまま数ヶ月忘れてたので
書き直してはいますが一部でタイムラインの矛盾があるかもしれません。

#経緯
[Nuxtでポートフォリオを作り直していた際](https://qiita.com/webiscuit/items/a93d0eaa051e062b5640)に
よく考えたら今までは完全静的サイトの構築でNuxtメインが多かったので
実は細かい部分の知識がポロポロ漏れているのでは。。。
と思い直して、きっちり基礎から学び直しながら進めることにしました。

ちょうどVueのページ開いたら[Vue School](https://vueschool.io/)の40%オフセールの広告があったので（Black Fridayでした）
何も考えずに誘導されてさくっと登録（笑）

結論から言うと、登録してよかったです！

##良かった点

###◎実際の開発に近い形で学べる
フォーラムやブログを構築しつつ進んでいくので、実際のアプリ構築で必要な工程を順に学べます。
実際にこれを見ながら、進行中のポートフォリオサイトも構成の甘かった点など少し調整入れています。

###◎各レッスンが短め
コースの中でレッスンが機能ごとに細かく分けられているので
既に知ってる部分については、スキップしたり再生速度を速めたりもできるので楽。

###◎Nuxtの学習にも最適
「Vue School」ですが、VueのコースだけでなくNuxtに関連するコースもあります。

###◎実装ファイルが用意されている
また、コースごとにボイラープレートなども用意されてたりするので、実際のファイルを見ながら進められます。
私はよくやるのですが、タイプミスとかでどうしてもうまくいかないときにコピペもできます（笑）
後からも見直しやすいです。

###◎字幕がついてる
英語のコースではあるのですが、英語字幕がついていますし、再生速度の調整も可能です。

###◎ユーザーの声が結構反映されている
レッスンにコメントが残せるのですが、たとえば字幕つけてくれとかファイル提供してくれとか
そういったレスに対してしっかり対応しているようです。

##残念だった点

少しマイナスかな？というのが、動画の英語音声がとても訛っていること。。
最初無料コースを見て問題なさそうだなと思って
マスターコースを見たら突然訛りのある人になったのでぎょっとしました。。

ただ内容は問題ないですし、再生速度の変更や字幕の表示も出来るので、逆に良かったかもしれないです。

##Vue Schoolのすすめ

一部で無料コースもありますし、Nuxtのドキュメントからもリンクが貼られていたりします。
コースの種類も多様で、ピンポイントで不足している知識が学習出来ますし、とてもおすすめです。
個人的には、「[The View.js Master Class](https://vueschool.io/courses/the-vuejs-master-class)」や「[Async Data with Nuxt.js](https://vueschool.io/courses/async-data-with-nuxtjs)」あたりが参考になりました。

##これから

フリーランスで主に一人で活動しているため、知識がランダムになりがちです…。
まだまだ個人的には漏れている知識があると認識しているので
引き続き[Vue School](https://vueschool.io/)やドキュメントなどで学習続けたいと思います。
Material-UI Pickers×Moment.jsをReact(TypeScript)で使う際のtips

業務でMaterial-UI PickersをMoment.jsで使いたいと思った際に
[マテリアルUI](https://material-ui.com/components/pickers/)のサイトはあてにならなかったので参考になればと思います。
##環境/パッケージのversion
react　16.12.0
typescript　3.7.3
moment　2.24.0
@material-ui/pickers　3.2.10
@date-io/moment　1.3.13

material-ui-pickers v3ではdate-io系のversionは1.x.xを使わないとうまくいかないみたいなので`1.3.13`いれてます。
最初これよく読まなかったので、エラーがでまくりで死にそうでした
[Material-UI Pickersサイト](https://material-ui-pickers.dev/getting-started/installation)

##実装
実装の詳細について書いていきます。
###全体
これで一つのコンポネントです

```tsx
import React, { FC } from 'react'
import MomentUtils from '@date-io/moment';
import {
  MuiPickersUtilsProvider,
  KeyboardTimePicker,
  KeyboardDatePicker,
} from '@material-ui/pickers'
import moment, { Moment } from 'moment'

const DatePicker: FC = () => {
  const [selectedDate, setSelectedDate] = React.useState<Moment | null>(
    moment()
  );

  const handleDateChange = (date: Moment | null) => {
    setSelectedDate(date)
  };

  return (
    <MuiPickersUtilsProvider utils={MomentUtils}>
      <KeyboardDatePicker
        disableToolbar
        variant="inline"
        format="YYYY/MM/DD"
        value={selectedDate}
        onChange={handleDateChange}
      />
      <KeyboardTimePicker
        value={selectedDate}
        onChange={handleDateChange}
      />
    </MuiPickersUtilsProvider>
  )
}

export default DatePicker
```

###import

```tsx
import React, { FC } from 'react'
import MomentUtils from '@date-io/moment'
import {
  MuiPickersUtilsProvider,
  KeyboardTimePicker,
  KeyboardDatePicker,
} from '@material-ui/pickers'
import moment, { Moment } from 'moment'
```

- `React, { FC }`　FunctionCompornentをいれてます。
-  `MomentUtils` アダプターです。こちらいれないとMomentのオブジェクトを日付と認識してくれません。
-  `MuiPickersUtilsProvider`こいつでかこってあげないとMomentUtilsを反映できません。
- `KeyboardTimePicker` `KeyboardDatePicker`　keybordでも日付を操作したいので。
- `moment` これがないと日時を簡単に扱えません。
- `Moment` momentの型interfaceです。typescriptでは定義してあげないと怒られます。


###state
stateで行き交うデータは全てMoment型なのを注意してください。

```tsx
const [selectedDate, setSelectedDate] = React.useState<Moment | null>(
  moment()
);
```
初期stateに`moment()`で現在時刻をsetします。
`useState<Moment | null>`で型をMoment型にしてあげないとエラーがでます。

```tsx
const handleDateChange = (date: Moment | null) => {
  setSelectedDate(date)
};
```
メゾットに関してもpickerから引数で渡されるdateの型はMomentなので定義してあげましょう。

###render
```jsx
return (
    <MuiPickersUtilsProvider utils={MomentUtils}>
      <KeyboardDatePicker
        disableToolbar
        variant="inline"
        format="YYYY/MM/DD"
        value={selectedDate}
        onChange={handleDateChange}
      />
      <KeyboardTimePicker
        value={selectedDate}
        onChange={handleDateChange}
      />
    </MuiPickersUtilsProvider>
  )
```

`<MuiPickersUtilsProvider utils={MomentUtils}>`　これで囲わないと正しくMomentに変換できずにエラーがでます。`utils`内にアダプタ名を記述します。

ここで地味につまずいたのは`format`で、全部大文字にしないと正しく表示されないので大文字で。
多分Momentが大文字しか認識しないのかと。

##まとめ
@date-ioのversionミスしたりstateの型を`Date`でやってしまったりとなかなかつまずいたので、参考になれば幸いです。
Muiは日本語のtipsが少ないからハマったら長い。。。
改善、修正点ございましたら気軽にコメントくださいませ。
Windowsのクリップボード系アプリなら[Clibor]が便利

クリップボード管理のアプリは作業する時にはあると便利ですよね。

windowsで個人的におすすめなのは**Clibor**です。

## [Clibor](https://www.vector.co.jp/soft/winnt/util/se472890.html)

初回は起動すると、２回目以降はスタートアップでタスクトレイに常駐します。

コピペして

<img width="103" alt="2020-02-13 114554.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/59333a2d-873f-c2bc-5f9d-1d056a2783a6.png">

デフォルトでは``Ctrl``キーの２度押しで起動します。

<img width="152" alt="コメント 2020-02-13 114640.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/cc5ad49e-8288-9fff-bd16-13faa1f57d97.png">

クリップボードの履歴が一覧で表示されます。
現在は最大10,000件まで履歴管理できるようです。

よく使う定型文を保存できるのも便利です。

<img width="214" alt="コメント 2020-02-13 114658.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/16c70c5a-2997-3f4b-ee59-122e29d28060.png">
Axiosで特定のヘッダしか取れない場合の対処法（response.headersにlocation等が入らない場合）

## 概要

Axios使用時に、`response.headers` で `content-type` 等、特定のヘッダしか取れない場合にそれ以外をとれるようにする。

## 対応

サーバのレスポンスヘッダに↓を追加する。

```text
Access-Control-Expose-Headers: *
```

## 参考

* [Axios get access to response header fields
](https://stackoverflow.com/questions/37897523/axios-get-access-to-response-header-fields/37931084#37931084)
pairとmapを使いこなす練習　ABC152　D問題

#Atcorder152 D問題
手も足も出なかった問題...
***pair***と***map***を使えば一気に分かりやすくなった！
https://atcoder.jp/contests/abc152/tasks/abc152_d


```c++
#include<bits/stdc++.h>
#define rep(i,n) for(int i=0; i<(n); i++)
using namespace std;
using ll = long long;
const ll INF = 1e9 + 7;
typedef pair<int,int> P;// pair型は２つの値の組を表せる

P f(int x){
    int a=x%10; //下一桁
    int b =0;   //上一桁
    while(x){
        b=x;
        x/=10;
    }
    return P(a,b);
}

int main(){
    int n; cin >> n;
    map<P,int> freq; //連想配列の時に用いられる
    for (int i=1; i<=n; i++){
        P p=f(i);
        freq[p]++;
    }
    
    ll ans=0;
    for (int i=1; i<=n; i++){
        P p=f(i);
        P q(p.second,p.first);
        ans+=freq[q]; //A.firstとB.second, A.secondとB.firstが一致しているのか確認
    }
    cout << ans << endl;
    return 0;
}
```
Java Integerの比較（==）が正しく動作しない

# 現象

```java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); // 「2 10000000 10000000」が入ってくる
        int n = sc.nextInt();
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < n; i++) list.add(sc.nextInt());

        for (int i = 0; i < n-1; i++) {
            if (list.get(i) == list.get(i+1)) {
                System.out.println("等しい");
                return;
            }
        }
        System.out.println("等しくない");
    }
}
```

`list.get(i)`には10000000、`list.get(i+1)`にもおなじ10000000のはずなのに結果が「等しくない」が出力されてしまいました。なぜ？？

# プリミティブ型は`==`、オブジェクト型は`equals`

Integerはオブジェクト型のため、`==`で比較する場合、同一のインスタンスかどうかを確認することになるため、「等しくない」になってしまうようです。

```java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); // 「2 10000000 10000000」が入ってくる
        int n = sc.nextInt();
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < n; i++) list.add(sc.nextInt());

        for (int i = 0; i < n-1; i++) {
            if (list.get(i).equals(list.get(i+1))) {
                System.out.println("等しい");
                return;
            }
        }
        System.out.println("等しくない");
    }
}

// 結果
// 等しい
```

結論、数を比較する際は、プリミティブ型は`==`、オブジェクト型は`equals`を使いように注意しないとでしたー。
AWS S3にAngularのプロジェクトを配置して公開する(初心者向け)

S3×Angularということで、S3にAngularのプロジェクトを置いて、ホスティングする方法です。

セキュリティ周りに関しては説明していません。とにかく公開したい人向けです。
***
# S3のバケットを作る
### 用語
> バケット…フォルダの一つ上の概念容量無制限のハードディスクみたいなもの。バケット名は世界中で一意である。
***
### バケット作成手順1(バケット名を決める)
世界で一つだけのバケット名を決めてください。
![](https://i.imgur.com/hxY2Fp4.png)
***
### バケット作成手順2(オプションの設定)
今回はそのまま「次へ」を押下してください。
![](https://i.imgur.com/Bgja0nc.png)
***
### バケット作成手順3(アクセス許可の設定)
ここでは、アップロードされるファイルに対するアクセスに誰をブロックするかを指定します。今回はひとまずすべてのチェックを外します。
![](https://i.imgur.com/89ulsTS.png)
***
### バケット作成手順4(確認)
確認画面が表示されるので「バケットを作成」を押下するとバケットが作られます。
![](https://i.imgur.com/FXwUvP2.png)
***
#### 【Tips】AWS CLIを使うと
AWS CLIを使えば

```
aws s3 ls
```
で作ったバケットを確認できます。
***
# 作ったバケットにAngularの資材を配置する
```
ng build
```
コマンドをAngularのプロジェクト配下で実行すると`/dist`ディレクトリにコンパイルされたファイルが生成されます。

これを上記で作ったS3のバケットにアップロードします。方法は2つ。
***
### 【方法1】GUIで！
先ほど作成したバケットに下記の通りドラッグアンドドロップなどでdist/プロジェクト名フォルダ内
を全選択してアップロードします。

![](https://i.imgur.com/1toNh0W.png)

「アップロード」を押下します
![](https://i.imgur.com/z5k5yfT.png)

![](https://i.imgur.com/42tm8cw.png)
***
### 【方法2】CUIで！
```shell=
aws s3 sync dist/Angularのプロジェクト名 s3://作成したバケット名
> 例：aws s3 sync dist/Angular-With-S3 s3://angular-s3-trial
```
![](https://i.imgur.com/5mbJghI.png)
***
## ホスティング(公開するため)の設定をする
***
### 設定1(ホスティングの設定)
バケットを選択するとサイドバーが出現するので「プロパティ」をクリック

![](https://i.imgur.com/cgnojME.png)

「Static website hosting」からホスティングのための設定をします。
![](https://i.imgur.com/lDINLt2.png)
![](https://i.imgur.com/H1uVUoz.png)
***
### 設定2(バケットポリシーの設定)
続いて、バケットポリシーを設定します。
アクセス権限タブ > バケットポリシーに下記の内容を貼り付けて保存します。

```json
{
   "Version":"2012-10-17",
   "Statement":[{
    "Sid":"PublicReadForGetBucketObjects",
         "Effect":"Allow",
      "Principal": "*",
       "Action":["s3:GetObject"],
       "Resource":["arn:aws:s3:::【ここをバケット名に置換】/*"
       ]
     }
   ]
}
```

![](https://i.imgur.com/BgtWTMs.png)

保存を押すと全世界に公開されます。

`http://{バケット名}.s3-website-ap-northeast-1.amazonaws.com/`を開いてみてください！
![](https://i.imgur.com/y7LA5Tr.png)
***
## (CLIでアップロードした場合のみ)ContentTypeを指定
ここで一度、公開されたサイトを開いてみます。
![](https://i.imgur.com/q55sOZh.png)

真っ白な画面が表示されます。
![](https://i.imgur.com/nITis3X.png)
***
コンソールを見てみると、いくつかのjsが、ただのテキストファイル` text/plain `として読み込まれています。
S3上でjsファイルにContentTypeを定義する必要があります。
![](https://i.imgur.com/vLKEqZu.png)
***
コンソールでエラーが出ているファイルを選択します。
![](https://i.imgur.com/EvV2MOF.png)

プロパティから
![](https://i.imgur.com/gquw53Y.png)

メタデータを選択し、
![](https://i.imgur.com/hfDAeuh.png)
![](https://i.imgur.com/qqC8aic.png)

`text/plain`から`text/javascript`に書き換えます(チェックボックスを入れて編集できます)

> 同様にエラーが出ているJavaScriptファイルに対応していきます。
![](https://i.imgur.com/tIi6WIZ.png)
***
## 全て対応したら再度読み込んでみましょう
キャッシュが残っていると再発する場合があるので、キャッシュを削除して再読み込みしてみましょう。

【Tips】Chromeの場合、`Ctrl + F5`でキャッシュを削除して再読み込みしてくれます。
![](https://i.imgur.com/F59UdSn.png)
横3列のリストをキレイに並べる小技


## 問題
![qiita20200213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409408/be32362f-3f16-d067-bc9e-ef2f8b73a4a5.png)
Webサイトを作っているとこんな感じの横3列のリストを作りたい状況が結構あります。
しかし、フレックスボックスで 

```
justify-content:space-between;
```
を使ってに並べると

![qiita20200213-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409408/380eda7a-94f1-b117-61dc-6e5e2634da85.png)
このように10と11の間に隙間が空いてしまいます。

## 対策
```
.hoge::after{
  content: "";
  width: 30%;
}
```
このように疑似要素で11の後にリストをもう1つ追加してやればいい。
widthの数値はリストの幅と同じにする。
Q. リストが12個になった時 次の行にはみ出たりしないの？
A. 疑似要素は高さ0なので見た目上は何の影響もない。

## 完成版のコード例
```
<div class="inner">
  <ul class="list_anchor">
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
    <li><a href="#">6</a></li>
    <li><a href="#">7</a></li>
    <li><a href="#">8</a></li>
    <li><a href="#">9</a></li>
    <li><a href="#">10</a></li>
    <li><a href="#">11</a></li>
  </ul>
</div>
```
```
.inner {
  width: 90%;
  margin: 0 auto;
  padding: 1em 0;
}
.list_anchor{
  display: -webkit-box;
  display: flex;
  -webkit-justify-content: space-between;
  justify-content: space-between;
  -webkit-flex-wrap: wrap;
  flex-wrap:         wrap;
}
.list_anchor::after{
  content: "";
  width: 30%;
}
.list_anchor li{
  width: 30%;
  margin-bottom: 1em;
}
.list_anchor li a{
  display: block;
  line-height: 1;
  position: relative;
  color: #0063cc;
  background: #dff0ff;
  text-decoration: none;
  padding: 10px 15px;
  font-weight: 500;
}
.list_anchor li a::after{
  content: "";
  width: 0;
  height: 0;
  border-top: 4px solid #0063cc;
  border-right: 3px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 3px solid transparent;
  position: absolute;
  right: 10px;
  top: calc(50%);
}
```

https://jsfiddle.net/sphenisc/fgLxyhwu/14/
Lookerで1つのModelから複数のリソースにクエリを投げる方法

### "簡単だけど通常の使い方と違う"というハードル
* Googleで調べにくい
* Lookerの人に聞いても、「できますよ」という回答が返ってくる

### 前提
* Lookerからの接続先はBigQueryを想定

### やり方
* LookerのサービスアカウントにBigQuery側の権限を与える
    * もちろんクエリを投げたい複数のリソースへのアクセス権限が必要
* Modelで指定するConnectionはなんでも良い
    * ModelにConnection側の権限はちゃんと与えてあげることを忘れずに
* viewで指定するテーブル名は、ちゃんとリソース名から書く
    * 省略すると、Modelで指定したConnection名が接頭句として追加される ≒ 別のリソースにあるデータセット/テーブルの指定がうまくいかない
    * ここがわかりづらい

### 疑問/不安
* 通常の使い方だと1コネクション1リソースを前提としてるけど、それを乗り越えてしまうとどんなデメリットがあるのか把握しきれていない
    * 多分権限周りなんだろうけど…
selenium php-webdriver update

```
$composer update 
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Package facebook/webdriver is abandoned, you should avoid using it. Use php-webdriver/webdriver instead.
Generating autoload files
```


version 1.8.0 から名前が facebook/php-webdriver から php-webdriver/webdriverに変わりました
jsonを書き換えます

```composer.json
"require": {
-    "facebook/webdriver": "^1.7.1",
+    "php-webdriver/webdriver": "^1.8.0",
}
```

アップデートすれば新しいバージョンが入ります

```
$ composer update 
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 2 installs, 1 update, 1 removal
  - Removing facebook/webdriver (1.7.1)
  - Updating symfony/process (v4.4.4 => v5.0.4): Downloading (100%)         
  - Installing symfony/polyfill-mbstring (v1.13.1): Downloading (100%)         
  - Installing php-webdriver/webdriver (1.8.0): Downloading (100%)         
php-webdriver/webdriver suggests installing ext-SimpleXML (For Firefox profile creation)
Writing lock file
Generating autoload files
```

github php-webdriver
https://github.com/php-webdriver/php-webdriver
見事なグラフィックスを作成するのに役立つ10の基本設計原則

>「デザインには3つの回答があります。はい、いいえ、WOW！ワオが目指すものです。」—ミルトン・グレイザー

グラフィックデザインは、ブランド構築と同時に、スキルセットを紹介する上で重要な役割を果たします。

ブランディングとデザインは切っても切れない経験ですが、新しい課題に着手する前にグラフィックデザインの基礎を理解することが重要です。

クライアントと仕事をするとき、強い第一印象を与える機会は1つだけです。
あなたの設計要素の知識とアプリケーションの経験をさまざまなソーシャルメディアグラフィックス、WebおよびアプリのUI、ビデオ、バナー、広告などのプロジェクトに活用してみるが良い。

もちろん、デザイナーとして、線の外に絵を描いたり、楽しんだりすることを心配しないでください！実際、凡例や反復的なデザイン構造から引き離すために、線の外側を頻繁に色付けする必要がありますが、初心者はまずそれらの規定された線が何であるかを知る必要があります。

それでは、見事なグラフィックスを作成するのに役立つ10の基本設計原則を理解しましょう。

## 01. バランス

バランスは、全体的な設計に安定性と構造を与えます。それをよりよく理解するには、各デザイン要素の背後に重みがあると考えてください。

形状、テキストボックス、画像はデザインを構成する要素であるため、これらの各要素が持つ視覚的な重みに精通することが重要です。

これは、要素が常に均等に分散される必要があることや、要素が同じサイズである必要があることを意味するものではありません。バランスは対称または非対称です。

対称バランスとは、要素の重量がデザインの両側で均等に分割される場合です。一方、非対称バランスとは、スケール、コントラスト、色を使用してデザインの流れを実現することです。

## 02.近接

近接性は、類似または関連する要素間の関係を作成するのに役立ちます。これらの要素はグループ化する必要はなく、代わりにフォント、色、サイズなどで視覚的に接続する必要があります。

## 03.アライメント

配置は、設計要素とのシームレスな視覚的接続を作成する上で極めて重要な役割を果たします。乱雑に配置された要素を排除することにより、テキスト、画像、図形、ブロックに順序付けられた外観を与えます。

## 04.視覚的階層

簡単に言えば、デザインで最も重要な要素またはメッセージに視覚的な重みを追加すると、階層が形成されます。それはさまざまな方法で実現できます。タイトルを強調表示するために、より大きなまたは太いフォントを使用します。キーメッセージを他のデザイン要素よりも高く配置します。関連性の低い画像や小さい画像よりも大きく、詳細でカラフルなビジュアルにフォーカスを追加します。

## 05.繰り返し

繰り返しは、特にブランディングに関しては、基本的な設計要素です。ロゴやカラーパレットなどの一貫した要素を結び付けることで、リズムを作り出し、デザイン全体を強化し、ブランドやデザインを視聴者がすぐに認識できるようにします。

## 06.コントラスト

コントラストは、2つの対向する設計要素に違いがある場合に発生します。コントラストの最も一般的なタイプは、暗いvs明るい、現代的なvs昔ながらの、大きいvs小さいなどです。コントラストは視聴者の注意を主要な要素に導き、それぞれの側面が読みやすいようにします。

## 07.カラー

色は基本的な重要なデザインであり、デザインの全体的な雰囲気を決定します。

選択する色はブランドとその色調を表しているため、選択するパレットに注意してください。グラフィックデザイナーとして、色の理論の基本的な知識を身に付けることは常に役立ちます。たとえば、ゴールドとニュートラルシェードは洗練された全体的な感触を呼び起こし、明るい色は幸福を表し、青は落ち着きをもたらします。

カラーパレットは、コントラストとして、または要素を補完するために使用することもできます。

## 08.ネガティブスペース

色、画像、形の重要性について説明しましたが、空白のままになっているスペースについてはどうですか？これは「負の空間」と呼ばれ、簡単な言葉では、要素の間または要素の周囲の領域を意味します。ネガティブスペースは、クリエイティブに使用する場合、形状を作成し、デザインの重要なコンポーネントを強調するのに役立ちます。

## 09.タイポグラフィ

>「言葉には意味があり、タイプには精神がある」— Paula Scher。

タイポグラフィはデザインの重要な柱の1つであり、スタイリスティックに、またはカスタマイズされて実行されたときに、ブランドやアートワークに関するボリュームを語ります。デザインコンセプトを紹介するために必要なのは「タイプ」だけです。

## 10.ルール

デザインの基礎を理解した熟練したグラフィックデザイナーになったら、次はそれらのルールを破るときです。そして、それによって、私は、ピクセル化された画像や判読できないフォントタイプを使用するつもりはありません。通信することを選択することは何であれ、妥協しないでください。



これらの原則は、一部の人がより注意深くなり、新しいデザインの心のスナップショット（つまずく）を撮る必要があるかもしれませんが、強力なビジュアルとコンテンツによって優れたブランドを作りたい人にとっては重要な原則です。
Git,GitHubを使おう

<h2>まずは前置き。これは自分への自戒でもある。</h2>
<p>ろくにコード管理をしてこなかったのを今更ながらまぁまぁ後悔しています。
gitやってなかった自分への戒めも込めて残しておこうと思います。</p>

<h3>事前にやっておくこと（その1）<br></h3>
<p>偉大なる先人たちがいらっしゃるため、以下2点は割愛致しまする。<br>(リンクは貼っておきますので参照ください。)
</p>
<li>[Gitのインストール](https://git-scm.com/downloads)
　→ ターミナルはGitBushを使用します。<br>

<li>[githubアカウントの所持](https://github.co.jp/)
  → まぁ、そりゃやってありますよね。。

<h3>事前にやっておくこと(その2)</h3>
<p>これは自分のやり方残しておこうと思います。</p>
<li>｜gitへの登録作業<br>
1.ユーザー名(githubでのユーザー名)

```
git config —global user.name "****"
```

2.email(githubでのemailアドレス)

```
git config —global user.email "****"
```

3.エディタの登録作業(ここではvscodeを指定)

```
git config —global core.editor "code —wait"
```
と入力


<h3>ローカルレポジトリを作成する</h3>
<p>1.GitBushを起動後、git管理するディレクトリまで移動</p>
<p>2.コマンド「git init」を入力</p>

```
git init
```

<p>3.コマンド「git add ***」を入力。<br>(***の部分にはファイル名やフォルダ名などを入力する。以下のコマンドは管理するフォルダ内、全てを対象にする。)</p>

```
git add .
もしくは
git add hoge.txt
```

<p>4.隠しフォルダとして”.git”が同一階層に作成されていることを確認<p/>

<h3>コミットする</h3>
<p>1.コマンド「git commit」を入力する。<br>
</p>
<p>2.エディタが開くので変更内容を入力する。</p>
<p>3.入力が終わったらエディタを保存して閉じる。</p>
<p>4.コマンド「git status」を入力して、「nothing to commit~」的な内容が返ってくればコミットは無事終了です。</p>


```
git commit
(エディタが開きます)

git commit -m "Hello Github"
```


<h3>リモートレポジトリを作成する</h3>
<p>1.githubページへ移動、ログインする。</p>

<p>2.「New repository」を選択する。</p>

<p>3.必要項目を入力。最後に「Create repository」を押すと新規作成されます。※repositorynameとプライベートorパブリックを選択すればあとは好きに選んでください。</p>

<p>4.画像のような状態になったら[HTTPS]を選択して、右側のコピーアイコンを押す。</p>
<img width="900" alt="2020-02-13 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493685/5e0189fe-3888-2001-cdd6-45400ce22fe4.png">


さぁ、もうちょっと

<h3>ローカルリポジトリの編集内容をリモートリポジトリへプッシュする</h3>
<p>一度、`git status`でcommitされているか確認

```
On branch master
nothing to commit, working tree clean
```
これが返ってくれば大丈夫です。
では、いよいよpushします。

```
git remote add orijin <githubでコピーしたやつ貼り付け>

git remote 
<add時のリモートリポジトリ名が返ってくる>

git push -u origin master
 * [new branch]      master -> master
 ↑こんな内容が返ってくればOK
```

<h3>Githubのリモートレポジトリで確認</h3>
確認できたでしょうか？
ひとまずはここまでで終了です。
Microsoft IoT in Action Tokyo 参加レポート

#はじめに
マイクロソフト主催IoT in Action Tokyoに出展・参加してきたので、そのメモです。
何かの参考になればと思いまして。
[公式サイト](https://iotinactionevents.com/ja/event/tokyo)はこちらになるので、正確な情報はこちらを参照して下さい。
（＊追記　公式サイトに当日のスライドが追加されたみたいです。良かったらどうぞ）

#アジェンダ
* 基調講演
* ビジネス変革の実現
* スケーラブルでリピータブルなソリューションを創り出すインテリジェントエッジの構築
* 昼食
* IoTの可能性を引き出す最新テクノロジー
* 魅力的なイノベーション実現のためのIoTセキュリティ開発
* パートナー企業様によるIoT活用事例
* 休憩
* Mixed Realityで実現するビジネス変革
* Co-sellを加速させるマイクロソフトリソースとプログラム
* マッチメイキング

#入口
会場は東京コンファレンスセンター有明なので、こんな感じ。
![DSC_0070_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/2c8d4259-9825-1e51-01a6-65966df39867.jpeg)

#出展
出展ブースになります。一応、書いておく。
PLCのデータをクラウドに簡単接続、簡単"見える化"
クラウドでのデータ連携により遠隔地での設備管理や異常時のアラート通知を実現する製造業向けIoTソリューションのご紹介
![DSC_0072_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/8100d301-f396-342f-a7ef-ea45ff719f31.jpeg)


#会場の雰囲気
こんな感じでした。
展示コーナーやサテライトでもセッションをオンラインで流してたので、ライブ感が不要ならそっちのほうがスライドが良く見えました。あまり目が良くないので後ろの方の席になると結構キツイ。。。
![DSC_0073.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/79304c60-fd8f-f7e0-0923-af1580ea03db.jpeg)

#講演(ほんの一部)
###基調講演
・マイクロソフトと一緒に取り組んでいるIoTソリューションなどの紹介
・株式会社オカムラの方も話してたけど、以下に関連の記事を見つけました
https://japan.zdnet.com/article/35149063/
https://cloud.watch.impress.co.jp/docs/event/1234406.html
・オフィス空間のデジタルツインの話とか
・自分のコンディションに合わせて、働く場所を選択する働き方の話とか
・OfficeとしてのIoTプラットフォーム構想とかの話

###Mixed Realityで実現するビジネス変革
・全世界の労働人口のうち、パソコンが普及して恩恵を受けた仕事とそうでない仕事の話
・HoloLensなどはその両手を使って仕事をする必要がある人のスタイルを変えていくという位置づけ
・HoloLens2の話もあったけど、視野角は２倍になったってよりは、ちゃんと自分の視野角が保たれているという感覚だそう（ただし、個人の感想です）
・コールセンターの今後の働き方の話もあって、今までの真っ白なオフィスで人がずらっと並んで電話を取るイメージから、地方でも他の作業をしながらでも両手を使いながら対応できるイメージ動画あり
（感想）ますます働き方が時間と場所から解放されていくなぁって印象を受けました。まぁ、そのボーダーレス感の是非はともかく。

#昼食
マイクロソフトのイベントだとだいたいお弁当がついてます。
ごちそうさまでした。写真撮り忘れた。。。

#まとめ
セッションをしっかり聞くというよりは、参加者と話していることが多かったので、セッションまとめは全然です(笑)
ですが、いろんな人と話をして議論するには良い機会だったと思います。
あと、マッチングイベントの後にALGYAN主催Azure Sphere技術セミナーにも行ってきたので、一日中マイクロソフトな一日でした（運営の人に話を聞いたら、ちょうどその日にぶつけたらしかったです。参加しやすいように）
docker-composeで環境変数を設定する

# 概要
docker-composeに環境変数を動的にセットしたかったので調べる。

# docker-compose
記載方法については、以下で行けるようです。
※ デフォルト値の記載は、 `バージョン：2.1以上` で対応しているようです

```yml:docker-compose.yml
version: '2.1'
services:
    httpd:
        image: php:5.6-apache
        ports:
            - "80:80"
        environment:
            ACCESS_KEY_ID: ${ACCESS_KEY_ID:-default}
            SECRET_ACCESS_KEY: ${SECRET_ACCESS_KEY:-default}
```
※ version2系の制約があったので、下記のように記載していまが2.1以上であれば特に問題ないようです

# 使い方
下記のようにして、コードを変更しなくても、環境変数を変えることが可能なようです。

```bash:ターミナル
$ export ACCESS_KEY_ID=xxxxxxxxxxx
$ export SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxx
$ docker-compose up -d
```

# 参考サイト
- [Compose file version 3 reference](https://docs.docker.com/compose/compose-file/#variable-substitution)

以上
データベース設計　基礎用語　2

#はじめに
データベース設計を学んでいく上で、用語等を中心に整理していきます。
[データベース設計 基礎用語 1 はこちらをクリック願います。](https://qiita.com/raigakun/items/a4ca99b8e224e9491011)
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご教授願います。

#制約とは

- 特定のデータの保存を許さないバリデーション
 - 例）同じメールアドレスの登録をできないようにする。
 - 例）名前のデータが空のユーザーを保存できないようにする。

###制約の種類

- ① NOT NULL制約
- ② 一意性制約
- ③ 主キー制約
- ④ 外部キー制約

####① NOT NULL制約
- カラムに設定する制約
- カラムの値にNULLを入れることができなくなる。
- 絶対に値が必要のあるカラムに対して使う制約。
 - Rails マイグレファイルへ記述することでNOT NULL制約を設定できる。
          - 例） null: false 

####② 一意性制約
- カラムに設定する制約
- 一意性とはユニークで他とは違うという意味
- 一意性制約を設定したカラムには同じ値を設定できなくなる。
  - 例）メールアドレス登録で、同じアドレスが登録できないようにする等
- Rails マイグレファイルへ記述することで、一意性制約をかけることができる。
  - 例） add_index :テーブル名, :カラム名, unique: true


####③ 主キー制約
- レコードが必ず主キーを持っていなくてはいけないことを保証する制約
- 主キー出る属性値が必ず存在してかつ重複していないことを保証する制約
- 主キーに対して、NOT NULL制約と一意性制約の両方を設定すると同じ意味
- Railsでテーブルを作成する時は、主キー制約は元々実装されている。
  - また、主キーはidカラムとして自動で作成される。= idカラムの値は重複しないようにできている。


####④ 外部キー制約
- 外部キーに対応するレコードが必ず存在することを保証する制約
  - 外部キーのカラム（student_id)に値(3)があっても、その値(3)を主キーとして持つ他のテーブル(studentテーブル)のレコードがないとダメ。
       - 例）student_idが３のレコードを保存するために、studentテーブルにidが３のレコードが存在しないといけない。
- Railsではマイグレファイルで外部キーとなるカラムを追加する時に記述ことで外部キー制約を設定する。
  - 例） foreign_key: true



#インデックスでデータの検索を高速化
##インデックスとは
- データ検索を高速化
- カラムに対して設定する、設定したカラムでの検索が高速になる。
- インデックスをカラムに設定することを、［インデックスを貼る］という。

###デメリット
- 全てのカラムにインデックスを貼ることはよくない。
    - 理由１：データを保存・更新する速度が遅くなる（処理が遅くなる）。
    - 理由２：データベースの容量を使う。
   
##インデックスの貼り方
####テーブル内の1つのカラムにインデックスを貼る
- Rails マイグレファイルへ記述する。
  - 例） add_index :テーブル名, :カラム名

####複数のカラムに対してインデックスを貼る
- Rails マイグレファイルへ記述する。
  - 例） add_index :テーブル名, [カラム名, :カラム名] 

#正規化について
###正規化とは
- データベースのデータ構造をより効率的で重複や無駄のないシンプルな構造にするための手順
- 正規化を行ったあとのデータベースは、正規形と呼ばれる。
- 正規化を行っていなければ、非正規形と呼ばれる。
- 正規化には順番がある。
　

① 非正規　→　第一正規形
② 第一正規形　→　第二正規形
③ 第二正規形　→　第三正規形

以降もあるが、パフォーマンス低下の可能性もあるため、多くは第三正規形までのようです。
　→　テーブルがどんどんと小さなテーブルが増えていく　
　　→　SQLの検索実行回数が増える。
　　　→　**当初の目的を見失う。**

#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
Rails　コーティング規約について　3

# はじめに
Ruby、Railsの基礎を学習中の方に向けて記載致します。
[Rubyのコーティング規約はコチラをクリック願います。](https://qiita.com/raigakun/items/9db169935baa654af90d)
[Railsのコーティング規約 2 はコチラをクリック願います。]
(https://qiita.com/raigakun/items/265046a9fe78debfbd42)
私自身これからチーム開発を行う上で大事にしたい。知っておきたいことをOutputします。

#ActiveRecord Queries
####"sexy" validations を利用する。
利用はしていたが、名称は知りませんでした・・・


```
# 悪い例
validates_presence_of :name

# 良い例
validates :name, presence: true
```

#Mailers
####view で email へのリンクを記載する際には、_pathでなく_urlを利用する。
_url が生成するURLはホスト名を含むが、_pathメソッドのそれは含まない為のようです。

```qiita.rb
# 悪い例
詳細は下記のリンクをご参照ください。
= link_to 'こちらをクリック', course_path(@course)

# 良い例
詳細は下記のリンクをご参照ください。
= link_to 'こちらをクリック', course_url(@course)
```

#さいごに
コーティング規約については毎日更新します。
皆様の復習等にご活用頂けますと幸いです。
【PHPUnit】Test code or tested code did not (only) close its own output buffers【laravel】

## 概要
laravelでHTTPテストを行うとリスキーなテストという判定を受けることがある

```bash:黄色で言われるのでドキッとする
Test code or tested code did not (only) close its own output buffers

OK, but incomplete, skipped, or risky tests!
Tests: 12, Assertions: 18, Risky: 1.
```

## 環境

laravel 6.7.0
PHPUnit 8.5.0

## 原因

`@section` ディレクティブに文字列以外が入っているため。
第二引数には文字列以外を入れるとエラーになる。

```blade:XXX.blade.php
@section('title', $title)
```

例えばこのように動的プロパティで求めた値を入れていて、 `null` が入ってしまっていたりする。

```blade:XXX.blade.php
@section('name', $user->name)
```

## 解決

### @endsectionで囲む

```blade:XXX.blade.php
@section('name')
	{{ $user->name}}
@endsection
```

記述が長くなるので少し嫌ですね。

### 空文字にしてしまう

```blade:XXX.blade.php
@section('name', $user->name ?? '')
```

こちらの方がスッキリします。
【rails tutorial 3.4.4】ローカル環境でテストコードを通す方法

railsチュートリアルをローカル環境で開発時に、
ルーティング、コントローラ、ビュー、テストにコードを正しく記述しているにも関わらず、テストが通らずエラーで解決に非常に時間がかかりました。
開発環境はvagrantで、テキストエディタはVScodeを使っています。

#エラー文
テスト実行時のエラーは以下になります。
DEPRECATION WARNING: You didn't set `secret_key_base`. Read the upgrade documentation to learn more about this new config option. (called from block in <class:StaticPagesControllerTest> at /vagrant/re_learn/test/controllers/static_pages_controller_test.rb:23)
ERROR["test_should_get_help", StaticPagesControllerTest, 0.29687339199881535]
 test_should_get_help#StaticPagesControllerTest (0.30s)
RuntimeError:         RuntimeError: Missing `secret_key_base` for 'test' environment, set this value in `config/secrets.yml`
            test/controllers/static_pages_controller_test.rb:23:in `block in <class:StaticPagesControllerTest>'

#原因
・minitestのGemを入れてなかった
・railsのバージョン5.2未満だった

#説明
・テスト実行時はrspecやminitestなどをよく使いますが、勘違いしてrspecのGemを入れていたため、正常に動作しなかったです。
（当然ですねｗ）

・railsはバージョンが5.1から5.2にアップグレードする際に、大きな変更があったようで、secret_key_baseという秘密鍵の要求が必須だったものがなくなったようです。
つまり5.1系だと秘密鍵を要求されエラーになります。
railsチュートリアルで推奨されているバージョンが5.1.6なので~~（私含め初学者の方が）~~陥りやすい点かと思います。

※補足
herokuでデプロイ時にはrailsバージョンを5.1にした方がいい場合があるので、デプロイ時のみバージョンを下げるもしくは、発生するエラーに対処する必要があるかもしれません。

#対策
・minitestのGemを追加

/Gemfile

```
group :test do
  gem 'rails-controller-testing', '1.0.2'
  gem 'minitest',                 '5.10.3'
  gem 'minitest-reporters',       '1.1.14'
  gem 'guard',                    '2.13.0'
  gem 'guard-minitest',           '2.4.4'
end
```

bandle installを実行

```
$ bundle install
```




・railsのバージョンを5.2以上に変更

config.load_defaults を5.2にする。

```/config/application.rb
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module アプリ名
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2
    # config.active_record.sqlite3.represent_boolean_as_integer = true
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end

```


アプリで使っているrailsのバージョンを確認

```
bundle exec rails -v
=> Rails 5.1.6
```

Gemfile内のrailsのバージョンを5.2以上にして,
bundle updateを実行

```
gem 'rails',        '~> 5.2.0'
```

```
$ bundle update rails
```

バージョンを確認すると

```
$ rails -v
=> Rails 5.2.4.1
```

これでテストを実行すると、正常に動作しました。

#まとめ
・機能面でのエラーがあったらその使いたい機能は何であるか認識することと、それがGemfileにあるか確認する。
・railsのバージョンは慎重に扱う。
・railsはシステムの脆弱性の改善を施してから、バージョンアップしていることが多いのでバージョンを下げる行為はなるべく避けた方が良い。
・Gemfileに書いたことはbundle installによってGemfile.lockに反映される。それを読み込んで処理等が実行される。

##参考
・https://discuss.circleci.com/t/missing-secret-key-base-for-test-environment-set-this-value-in-config-secrets-yml/5179/2
🍰【CakePHP2】Error: Call to a member function dispatchMethod() on nullは環境設定で修正

## 環境
PHP 7.2.21
CakePHP 2.10.18

## やりたいこと
下記のエラーを修正

```sh
Error: Call to a member function dispatchMethod() on null
#0 （Modelのファイルパス）(223): Model->__call('makeRoleTargetJ...', Array)
#1 [internal function]: （対象のModel名）->__construct(Array)
#2 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Utility/ClassRegistry.php(169): ReflectionClass->newInstance(Array)
#3 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Console/Shell.php(316): ClassRegistry::init('（対象のModel名）')
#4 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Console/Shell.php(269): Shell->loadModel('（対象のModel名）')
#5 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Console/Shell.php(228): Shell->_loadModels()
#6 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Console/ShellDispatcher.php(221): Shell->initialize()
#7 /（CakePHPディレクトリ）/Vendor/cakephp/cakephp/lib/Cake/Console/ShellDispatcher.php(66): ShellDispatcher->dispatch()
#8 /（CakePHPディレクトリ）/（Projectディレクトリ）/Console/cake.php(48): ShellDispatcher::run(Array)
#9 {main}
```

## やったこと
env.phpの環境変数を確認して修正する
ModelやControllerは悪くなかった