OmniAICreator/Qiita-1.07M huggingface dataset:
devise_parameter_sanitizerメソッドが訳わかってないのでここにアウトプットしてみる

Railsで写経をしていた際に出てきたメソッドで「何これ」となったので、もう一度復習してみて、それをアウトプットと忘備録として書いてみようと思います。

###devise_parameter_sanitizerとは
devise_parameter_sanitizerはdeviseというgemに用意されているメソッドで
ユーザー管理機能を実装する際に、ログインや新規登録などのリクエストからパラメーター(名前やメールなど)を取得するメソッドであるということです。



###パラメーターについて
パラメーターとはリクエストに含まれる外部から渡されるデータで、
コントローラーで処理されて、モデルを通じてテーブルのカラムにデータとして登録されます。
ブラウザの入力欄などから入力して送られてくるデータといったところでしょうか…


フォームにデータを入力してそれをリクエストとして送信するためには下記のような記述を書いてみます。

```ruby:index.html
#これは送り手側の話
<%= form_with url:”URL”, method: :post, local: true do |form| %>
<%= form.text_field :content %>
<% end %>
```

フォームに入力させてURLにデータを送るものだと思っています。
2行目の":content"の部分がparamsとなり、"params[:content]"として
外部からコントローラーへ渡されるデータになります。

今のは送る側の話でしたが、受け手側に関しても考えてみようと思います。
受け手側は指定したキー(カラム名)を持つパラメーターのみを受け取れるように制限することができます。
これをストロングパラメーターと呼びます。
記述としては下記の通りになります。

```players_controller.rb
#こちらは受け手側の話
params.require(:player).permit(:name, :age)
```

上記の記述ではPlayerモデルの"name"というキー(カラム)と"age"というキー(カラム)のデータのみをリクエストから受け取るということとなります。requireでカラムがあるテーブルを指定します。
リクエストの中に"name"や"age"というキーの他にも仮に"height"や"speed","defence"のデータが入っていれば、それらは受け取らないということになります。


###devise_parameter_sanitizerメソッドに戻ります。
どのように記述するかは下記の通りになります。

```application_controller.rb
#deviseの場合
devise_parameter_sanitizer.permit(:sign_up, keys: [:email])
```
devise_parameter_sanitizerはdeviseのメソッドになるので、モデルはdeviseによって作成されているUserモデルになりますので上記のrequireは記述しません。
サインアップする際に取得するパラメーター(データ)は"email"という意味になります。


このdevise_parameter_sanitizerでコードを書いてみて思ったことは、deviseのgemはログイン機能を実装する上でかなり便利だなということです。一からログイン機能を作らなくても新規登録、ログインの有無ができる訳です。
devise_parameter_sanitizerに必要な情報(カラム)を入れてあげることで、あとはdeviseがある程度やってくれるため、まだ訳わかってないところですが、非常に便利なメソッドだなと感じています。

###最後に
この記事を書いたものの、まだ自分でもわかっていないところがあります。この認識がおかしいと思われるところがあればいっていただけるとありがたいです。よろしくお願いします。

#####参考した記事
Railsのrequire/permitメソッドの使い方を現役エンジニアが解説【初心者向け】
https://techacademy.jp/magazine/22078
htmlタグ取り(sed) 英語(65)

htmlファイルからtxtファイルを生成する方法を試している。

 <この項は書きかけです。順次追記します。>


Delete html tags using sed/grep/awk
https://unix.stackexchange.com/questions/359980/delete-html-tags-using-sed-grep-awk
rmtag.sed 

```sed:rmtag.sed
sed -e 's/<[^>]*>//g' index.* > indexall.txt
```

上記でうまくいかなかったのは、２行にまたがるタグ。
うまく取れなかった。

こんな感じ。

```txt:intexall.txt
	<section id="c188278" class="g-padding-top-5 g-padding-bottom-5
	    ">
```

改行を取ってから処理すればうまくいくかも。

bashで変数内の改行コードを除去する
https://hacknote.jp/archives/12122/

シェルスクリプトでの改行文字の削除にハマる
https://hacolab.hatenablog.com/entry/2019/07/29/235312

```tr:rmreturn.tr
tr -d '\n' < infile > outfile
```

なんとかうまくいきそう。


```sh:bat.sh
#!/bin/sh
# https://unix.stackexchange.com/questions/359980/delete-html-tags-using-sed-grep-awk
# https://hacolab.hatenablog.com/entry/2019/07/29/235312
# https://qiita.com/kaizen_nagoya/items/ad4f75b391ff95e72634

_LISPDIRS=`find . -maxdepth 1 -mindepth 1 -type d`

for _DIRS in ${_LISPDIRS}; do
    echo -e "\n-- ${_DIRS} --"
    cd $_DIRS
    tr -d '\n' < index.* >> /tmp/web/indexall.txt
    cd ../
done
sed -e 's/<[^>]*>//g' /tmp/web/indexall.txt > index.txt
 ```
これではまだ駄目だった。

【シェルスクリプト】ファイルやディレクトリの有無を確認する方法色々
https://www.server-memo.net/shellscript/file_check.html

```shell-session:docker/bash
# ./bat.sh
-e 
-- ./www.xxx.com --

./bat.sh: 11: ./bat.sh: cannot open index.*: No such file
# ls 
  index.html  
```

```sh:bat.sh
#!/bin/sh
# https://unix.stackexchange.com/questions/359980/delete-html-tags-using-sed-grep-awk
# https://hacolab.hatenablog.com/entry/2019/07/29/235312
# https://qiita.com/kaizen_nagoya/items/ad4f75b391ff95e72634

_LISPDIRS=`find . -maxdepth 1 -mindepth 1 -type d`

for _DIRS in ${_LISPDIRS}; do
    echo -e "\n-- ${_DIRS} --"
    cd $_DIRS
    if [-e index.* ] then
      tr -d '\n' < index.html >> /tmp/web/indexall.txt
    fi
    cd ../
done
sed -e 's/<[^>]*>//g' /tmp/web/indexall.txt > index.txt
```


```shell-session:docker/bash
# ./bat.sh
./bat.sh: 13: ./bat.sh: Syntax error: "fi" unexpected (expecting "then")
```
 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
 
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.

'
/etc/hostsファイルを分割する

[hosts — / etc / hostsファイルが別の構成ファイルを参照している](https://www.it-swarm-ja.tech/ja/hosts/etc-hosts%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E5%88%A5%E3%81%AE%E6%A7%8B%E6%88%90%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%8F%82%E7%85%A7%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B/956718537/)
から思いついたネタ

`logrotate.d`、`rsyslog.d`、`/etc/udev/rules.d/`等々
`.d`のディレクトリにファイルを分割する機能がある。
`/etc/hosts`にはそもそも機能が無いので外側から作ってみる。
要は`cat /etc/hosts.d/* > /etc/hosts`である。



```pl:/usr/sbin/hosts-include
#!/usr/bin/perl

my $hosts = '/etc/hosts';
my $dir   = '/etc/hosts.d';

my @list;
opendir( my $dh, $dir ) or die "Can't open directory $dir: $!";
foreach my $file ( sort readdir $dh ) {
    next if -d $file;
    open my $rfh, "<", "$dir/$file" or die "Can't open file $file: $!";
    while ( my $line = <$rfh> ) {
        chomp $line;
        push @list, $line;
    }
}
closedir($dh);

if ( scalar(@list) == 0 ) {
    die "$dir is empty";
}

open my $wfh, ">", "$hosts.tmp" or die "Can't write $hosts.tmp: $!";
foreach my $line (@list) {
    print $wfh "$line\n";
}
close $wfh;
rename "$hosts.tmp", $hosts;
```

## 使い方

```
# mkdir /etc/hosts.d
# cp -a /etc/hosts /etc/hosts.d/00-base
# cat /etc/hosts.d/01-sample
192.168.1.10    example.com
# /usr/sbin/hosts-include
# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.10    example.com
```

## 使いみちとか

- アプリ毎にhostsを用意できる。
- 重複したらどうする？
- ACL抜けてるのに後から気づいた。`getfacl /etc/hosts`
vim-plug でRuby on Rails関連PluginをInstallしてみた

# 概要
普段、Ruby on Rails開発でVSCodeを使っているが、無性にVimが使いたくなったので
いくつかのVim Plugin Managerから`vim-plug`を選択、 
pluginをインストールしてみた。

# ローカル環境
* macOS Catalina 10.15.7

# インストール手順
### vim-plug ダウンロード
```
$ curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```

### .vimrc に以下Pluginを追記
ファイルツリー表示Pluginと rails関連Pluginを記述

```
# .vimrc ファイルツリー、rails関連プラグイン
call plug#begin()
Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }
Plug 'tpope/vim-rails'
Plug 'tpope/vim-endwise'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
call plug#end()

map <C-n> :NERDTreeToggle<CR>　←←ファイルツリーの表示・非表示を＜Ctrl + n＞にマッピング
```

### vim起動し、.vimrc上のPluginをインストール
vim起動し、`:PlugInstall`を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532385/a6677578-5f7e-b30f-caa2-d84c1ddd20c8.png)
「到達できないコード」とは？

cf.
https://docs.microsoft.com/ja-jp/visualstudio/ide/reference/remove-unreachable-code?view=vs-2019

実行されないコードのこと
「現状削除しても構わない部分」とも言える

Gitを使ってるなら、当該行を削除して、その旨と、本来の用途をコメントに付けておく。
Railsのバージョンを指定してアプリを作成する

#やりたいこと
Railsのバージョンを指定して新規アプリを作成をしたい

#開発環境
* Windows10
* AWS Cloud9

#問題の背景
教材の学習をする時に、以前Cloud9にインストールしていたRailsのバージョン(-v6)と教材のバージョン(-v5)が違ってるせいでエラーか発生し、学習が行き詰る事があった。
**バージョンの違いが原因で起こるエラーを回避して学習したかった。**

#解決方法
* 教材と同じRailsのバージョン(-v5)をインストールする
* rails new 〇〇 でアプリを作成する時に教材と同じRailsバージョン(-v5)を指定する

下記のコマンドで行いました。<br>

```
cd ~/environment ↵
```
```
gem install rails -v 5 ↵
```
```
rails _5_ new ○○ ↵
```

これでRails(-v6)がインストールされていても、Rails(-v5)で新規○○アプリ作成が出来ました。


#解決のキーワード
```
gem install rails -v △
```
コマンドでバージョン△を指定してrailsをinstall出来る。
バージョンを指定してアプリを作成する時は

```
rails _△_ new 
```
コマンドで作成する。
Nuxt.js2.14+@nuxtjs/vuetify 1.11.2でブレイクポイント設定をカスタマイズ

#前置き

これまでずっとGoogleAppsScript上でのみjavascriptを扱ってきた初心者ですが、今年の夏からFirebase+nuxt.js+Vuetifyでウェブアプリの作成を目指して勉強しています。
GASしか知らないために、いろいろと勉強することが多すぎて大変なのですが、特にVuetifyに関するネット記事はGASに関する記事と比べてあまり多くなくて困っているところです。（英語もほとんど読めないので・・・）

今回は**レスポンシブデザインにおけるブレイクポイントをカスタマイズする方法**が確立できましたので備忘録を兼ねて投稿してみたいと思います。（Qiita初投稿です！）

https://v2.vuetifyjs.com/ja/customization/breakpoints/
上記の公式ガイドの「使い方」のところに「独自のブレークポイントで閾値をピクセル数で定義できます」とあり、方法も説明されていますが簡素な記述のためそのまま使える情報ではありませんでした。
それで、タイトルに記載したとおり、バージョン指定のNuxt+Vuetifyしかも@nuxtjs/vuetifyの場合という限定された環境でのお話にはなりますが、私のような初心者の方々に参考になればと思います。（よく理解できているから投稿しているのではなく、結果として望み通りにできたのでその時の設定内容を投稿するというスタンスです。）

今回の環境は下記です。
Windows10 / VScode / node.js 10.22.0

```json:package.json
"dependencies": {
    "@nuxtjs/axios": "^5.12.2",
    "core-js": "^3.6.5",
    "firebase": "^8.0.0",
    "firebase-tools": "^8.14.1",
    "nuxt": "^2.14.6",
    "save": "^2.4.0",
    "vuexfire": "^3.2.4"
  },
  "devDependencies": {
    "@nuxtjs/vuetify": "^1.11.2",
    "eslint-config-prettier": "^6.12.0",
    "eslint-plugin-prettier": "^3.1.4",
    "prettier": "^2.1.2"
  }
```

#本題

##やりたかったこと
Vuetifyのブレイクポイントの初期値はけっこうざっくりしているので、iPhone,iPad縦,iPad横でデザインを切り替えるために、

  xs: 0,
  sm: 420px,
  md: 840px,
  lg: 1260px,
  xl: 1680px

という形で独自の数値でブレイクポイントを設定したいと思いました。そのために必要なことは以下の３つでした。

##Step1 : assetsフォルダ内のvariables.scssに下記内容を記載する

```scss:assets/variables.scss
  @import '~vuetify/src/styles/styles.sass';

  $grid-breakpoints: map-merge($grid-breakpoints, (
    xs: 0,
    sm: 420px,
    md: 840px,
    lg: 1260px,
    xl: 1680px
  ))
```

##Step2 : pluginsフォルダにjsファイルを下記内容で新規作成する
例ではvuetify.jsという名称にしています任意で名前を決めることができます。


```js:plugins/vuetify.js
import Vuetify from 'vuetify/lib'

export default new Vuetify({
  breakpoint: {
    thresholds: {
      xs: 0,
      sm: 420,
      md: 840,
      lg: 1260,
      xl: 1680,
    },
    scrollBarWidth: 24,
  },
})
```

##Step3 : nuxt.config.js内のpluginsにパスを記入し、Step2で作成したファイルを読み込む

```js:nuxt.config.js
  plugins: [
    '~/plugins/vuetify.js',
  ],
```

私の環境ではすでにplugins内に、
    '~/plugins/firebase.js',
    '~/plugins/firebase.auth.js',
が存在していましたので、3行目に追加する形で、
'~/plugins/vuetify.js',を記入しました。

それで私の場合の最終結果はこうでした。

```js:nuxt.config.js
  plugins: [
    '~/plugins/firebase.js',
    '~/plugins/firebase.auth.js',
    '~/plugins/vuetify.js',
  ],
```

#まとめ
以上の手順を踏むと、独自の数値がブレイクポイントに反映されるようになりました。

なおstep1に出てくるvariables.scssに書き込むとCSSを独自に設定できるという情報はネットにもたくさん出てきました。ですが今回のようにVuetifyにデフォルトで設定されている特殊な数値に手を加えたい場合には、variables.scssに書き込むだけでなく、Step2と3が必要でした。

ネットでこのあたりのことを調べると、下記のＱＡがよくヒットします。
https://www.366service.com/jp/qa/e9b29ca348c2d046abf87b6cd7baf757
このベストアンサーは詳しい人が見れば、どうすればよいのかすぐに分かるのでしょうけど、私のような初心者で、なおかつ環境が少し違ったこともあり、すぐに役立つ情報ではありませんでした。とはいえこれをヒントに試行錯誤し、やりたかったことがなんとか自分の環境で実現できましたので、上記ＱＡには感謝しています。

もっと勉強してnuxtやvuetifyを使いこなせるようになりたいです。そしてQiitaにはいつもお世話になっていますので、貴重な情報を共有して下さる皆様方にも感謝しています。

今回の件について、どんなことでも構いませんので、先輩方の知見の中から"知っておくとためになりそうな情報"がもしありましたら、教えていただけるなら幸いです。

【Vuetify公式ガイド】
https://v2.vuetifyjs.com/ja/

【検索用キーワード】
$vuetify.breakpoint
BreakPoints
ブレークポイント
新しいコードの記述で感じたこと

### Vuejsを初めて、コードの記述が変わり
省略した記述にも慣れてきました。
<h1>jqueryにも出てくるthisの使い方</h1>
methodsで指定した関数を引数で返す。
基礎さえあれば、慣れそうです。
### 
```javascript
sampleCode({
    el: '#app',
    data: {
      message:'Hello world'
    },
    methods:{
    sayWords: function(){
        this.message = 'Hi'
        return 'Hey'
       }
     }
  })
```
<h1>タグ内のidに、v-on・v-bindを使う</h1>
Html・CSSで、複雑だったコードがすっきりしました。
### 該当するソースコード
```javascript
<div id="sampleCode">
    <div v-html="html"></div>
    <a:[attribute]="url">調べる</a>
    <br>
    <a v-bind="snsObject">Twitter</a>
 </div>

```
<h1>JavaScriptの処理方法</h1>
```javascript
url:'https://www.google.co.jp/',
        attribute:'href',
        snsObject:{
            href:'https://twitter.com'
```
### Vuejsのフレームワークを使って、コードを書くのが簡単になりました。
jqueryを使ったコーディング学習はあまりなく、基本的なJavaScriptでした。
より直感的に書けるフレームワークを学習の中心するといいでしょう。
メモ：三角関数と双曲線関数を変わった座標系で考える

オイラーの公式より、三角関数と双曲線関数を

```math
\begin{eqnarray}
\cos{\theta_c} & = & \frac{e^{i \theta_c} + e^{- i \theta_c} }{2} = \frac{e^{\theta_h} + e^{- \theta_h} }{2} = \cosh{\theta_h} = x\\
i \sin{\theta_c} & = & \frac{e^{i \theta_c} - e^{- i \theta_c} }{2} = \frac{e^{\theta_h} - e^{- \theta_h} }{2} = \sinh{\theta_h} = y\\
\end{eqnarray}
```

として

```math
\begin{eqnarray}
X & = & x^2 \\
Y & = & y^2 \\
x & = & \pm \sqrt{X} \\
y & = & \pm \sqrt{Y} \\
\end{eqnarray}
```

となる $XY$ 平面を考えます。この平面では

```math
X 軸 \begin{cases}
X \ge 0 \cdots \left( x\ は実数 \right)　\\
X \lt 0 \cdots \left( x\ は虚数 \right)　\\
\end{cases}
\\
Y 軸 \begin{cases}
Y \ge 0 \cdots \left( y\ は実数 \right)　\\
Y \lt 0 \cdots \left( y\ は虚数 \right)　\\
\end{cases}
```

を意味します。双曲線関数は

```math
x^2 - y^2 = 1
```

だから、$X,Y$ に置き換えると

```math
\begin{eqnarray}
X - Y & = & 1 \\
Y & = & X - 1 \\
\end{eqnarray}
```

となって、$XY$ 平面では直線になります。平面の象限ごとに、三角関数と双曲線関数にある指数関数 $e^z$ の指数部 $z$ は

```math
z \begin{cases}
第一象限\left( x\ は実数, y\ は実数 \right)： 実数 \left( 双曲線関数に対応 \right) \\
第二象限\left( x\ は虚数, y\ は実数 \right)： なし \\
第三象限\left( x\ は虚数, y\ は虚数 \right)： 複素数 \left( y^2 - x^2 = 1\ の双曲線 \right) \\
第四象限\left( x\ は実数, y\ は虚数 \right)： 虚数 \left( 三角関数に対応 \right) \\
\end{cases}
```

に対応する。

---

整理できてスッキリした。
[人狼ゲームにぴったり] Discordの通話転送ボットをdiscord.jsで作りたい💭

こんにちは、最近友人に誘われ `Among Us` にハマっています。流行っていますよね。

オンラインで人狼のようなゲームを行う際、Discordでボイスチャットを行いながらすることが多いのですが、「追放」や「無残な姿で発見された」後には会議に参加できない特性がつきものです。

- ボイスチャットに残ってその後ゲームの様子を黙って聞く
- 別のボイスチャットに移って脱落者同士で「騙されたー！！」や「もっとできたな～」などお話しする

脱落した際はどちらかの選択を迫られることになります。

どちらも満たしたいという欲張り精神の元、『Discordのボイスチャットが別チャンネルに転送できたら様子をうかがいながらもっと楽しめるのでは？？』と考え、作成することにしました。

※ 後述しますが、問題としてAudioStreamの合成ができていないので複数人で同時にしゃべった時に音声が途切れることがあり、解決策募集中です。

# 完成イメージ
![rendering_image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/347998/a49503d3-a8ca-ca20-69d9-b8e9226f0faf.gif)

このイメージを元に、開発していきます。


# 開発環境
- Node.js `12.18.4`
- discord.js `12.3.1`

# 実装
全体はこうなりました。[GitHub](https://github.com/suzukey/discord_transfer)
チャンネル選択などで大きくなってしまったので、転送のコアの部分だけここで紹介させていただきます。

転送元側のクライアントから音声を取得し、そのまま転送先のクライアントから送信しています。

```module/core.js
// 前略

// Streamにデータを流して初期化しないと正常に動作しないようです
this.connection.from.play(new Silence(), { type: "opus" })
this.connection.to.play(new Silence(), { type: "opus" })

this.connection.from.on("speaking", (user, speaking) => {
  // 転送元の誰かが発話した際のみ処理を行う
  if (speaking.bitfield !== 1) return
  const stream = this.connection.from.receiver.createStream(user.id)

  // TODO: ここで他のStreamと合成をしたい

  this.connection.to.play(stream, { type: "opus" })
})

// 後略
```

# まとめ
脱落後も様子をうかがいながらお話ができるボイスチャットが用意できました。
Discord.jsは初めてでBotのディレクトリ構成などがまだ整っていないのでこれから調整を行います。

また、現状の問題点としてAudioStreamが合成できずに複数人が発話した際は1枠を奪い合い、途切れ途切れになってしまうというものがあります。
こちらを解決しないことにはあまり使い勝手がいいと言えないので、どうにか解決していきたいと考えています。

- [marge-stream](https://www.npmjs.com/package/merge-stream)を用いた方法では、音声合成をしているわけではないので、音声が順番に繰り出されるのみで解決には至りませんでした。
- [WebAudioAPIを使用した方法](https://support.skyway.io/hc/ja/articles/360049696313-%E8%A4%87%E6%95%B0%E3%81%AE%E9%9F%B3%E5%A3%B0%E3%82%92%E5%90%88%E6%88%90%E3%81%97%E3%81%A6%E9%8C%B2%E9%9F%B3%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%81%8B-)も考えましたが、ブラウザを触っているわけではないので取り入れることが難しいと考えています。

解決策思いついた方いらっしゃいましたらコメントや[プルリクエスト](https://github.com/suzukey/discord_transfer/pulls)いただけると大変助かります🙏

皆さんもDiscord Botでよいゲームライフを！
【PHP初心者】三項演算子使う？使わない？

三項演算子を使ったほうがいいのかわからなかったので個人的な意見をまとめました。

まず、三項演算子についてかんたんに紹介します。
### 三項演算子 
~~~php
// $fuga = trueとなる。
$hoge = 20;
$fuga = $hoge > 0 ? true : false;

// 行っている処理は以下と同じ
$hoge = 20;
if ($hoge > 0) {
    $fuga = true;
} else {
    $fuga = false;
}
~~~

### 三項演算子は使うべき？
三項演算子は使う？使わない？の賛否両論があります。
個人的な意見としては、使って良いと思います。
ただチームでルールを決めてから使うべきです。

以下、使わないほうが良いパターンです。

### 三項演算子を使わないほうがいいパターン１
**三項演算子を積み重ねて使う**

~~~php
$hoge = 20;
$fuga = $hoge > 0 ? true : false ? "a" : "b";

// 上記の結果は"a"となります。
// 想像の結果とあっていたでしょうか？
~~~

評価順をまとめるとわかりやすくなります。

~~~php
$hoge = 20;
$fuga = ($hoge > 0 ? true : false) ? "a" : "b";

// 最初にカッコ内が評価され下記の式に書き換えられます。
$fuga = true ? "a" : "b";
~~~

結果分かりづらいので、使わない。


### 三項演算子を使わないほうがいいパターン2
**Null合体演算子やエルビス演算子と一緒に使う**

* Null合体演算子

~~~php
$hoge = null;
$fuga = $hoge ?? "fuga";

// $fugaは”fuga”となる。

// 行っている処理は下記同じ
$hoge = null;
if (isset($hoge)) {
    $fuga = $hoge;
} else {
    $fuga = "fuga";
}
~~~

* エルビス演算子

~~~php
$hoge = true;
$fuga = $hoge ?: false;

// $fugaはtrueになります。
~~~

三項演算子、Null合体演算子、エルビス演算子が混在した式を見ると一気に可読性が下がります。

### 結論
`$hoge ? $fuga : $piyo`の形でしか使わない。
使うとしてもチームでルールを決めてから使う。
可読性（個人差がある）が保てる範囲で使う。
AmazonEC2LinuxインスタンスにSSHアクセスできるユーザーを追加する

EC2でインスタンスを起動させる時に、デフォルトのシステムユーザーアカウントで起動しますが、複数ユーザーがアクセスする場合は、各ユーザーに個別のアカウントを使用することがセキュリティ上望ましいです。

#キーペアの用意
まず新しいユーザー用のキーペアを用意します。
EC2のダッシュボードの、▼ネットワーク＆セキュリティのキーペアで作成しておくのが管理も楽です。

![スクリーンショット 2020-11-02 11.22.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178483/e89bf4d7-c59f-13df-78d6-ab49664fcf40.png)

#パブリックキーの取得
ローカルにpemファイルでDLしたら、キーペアのパブリックキーを取得します。

```bash:
$ ssh-keygen -y -f /path_to_key_pair/my-key-pair.pem 
// 取得したpemのパスです。
```

コマンドがバブリックキーを返します。（後で使います。）

#ユーザーの追加
新しいユーザーを追加します。
SSHで接続したら、adduserコマンドでユーザーを追加し、新しいアカウントで設定をします。

```bash:
$ sudo adduser new_user
// new_userを新アカウント名に置き換える
```

```bash:
$ sudo su - newuser // newuserは任意のユーザー名
$ mkdir .ssh // .sshディレクトリを作成
$ chmod 700 .ssh // .sshディレクトリのパーミッションを変更
$ touch .ssh/authorized_keys //authorized_keysを作成　この名前にする決まり
$ chmod 600 .ssh/authorized_keys　//　authorized_keysのパーミッションを変更
```

先ほど取得したパブリックキーをauthoraized_keysにコピペします。

新しいユーザーでSSHできるか確認します。

```bash:
$ ssh -i /path_to_key_pair/my-key-pair.pem new_user@public_IPv4_DNS
// pemファイルのパス、新しいアカウント名、ec2のIPアドレスかDNSに置き換える
```

```bash:
Last login: Sun Nov  1 08:16:38 2020

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
```

無事新アカウントでSSH出来ました。

# パスワードなしでsudo権限渡す
作成したユーザーは現時点で`sudo`コマンドが使えません。

```bash:
$ sudo passwd new_user
```

でパスワードを設定しておきます。
`sudo`時にパスワード入力をすれば`sudo`コマンドが使えるようになります。

でもいちいち入力が面倒な場合は、パスワード入力不要なグループにユーザーを追加しておけば、上記の設定せずに`sudo`が可能になります。

```bash:
$ sudo visudo

#%wheel ALL=(ALL) ALL　←コメントアウトする。
%wheel ALL=(ALL) ALL
```

`visudo`の上記をコメントアウトしておいて、

```
$ sudo usermod -aG wheel new_user
```

`wheel`グループに新ユーザーを追加しておきます。
A5:SQL Mk-2 使い方

# はじめに
A5:SQL Mk-2 使い方に関する自分用健忘録


# データベースの接続文字列やファイルなどの確認
[データベース(D)] → [データベースの追加と削除(D)] → [修正(E)]


# CREATE文の作成方法
データベースツリー(F12)上でテーブルを選択して、右側のウィンドウのタブから
ソースを選択

# INSERT文の作成方法
データベースツリー(F12)上でテーブルを選択して右クリック
[アドオンメニュー(X)] → [インサート文を作る(1)]


# ACCESSのクエリーみたいなGUI
SQL編集画面
[SQL(S)] →　[クエリデザイナ(D)] or CTRL+D


# SQLの整形
SQL編集画面
[編集(E)] →　[SQLの整形(Q)] or CTRL+Q

# 接続文字列
### Excel
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=z:\Sample.xlsx;Extended Properties=Excel 12.0;
ネットワーク接続時にoneshot実行するsystemdのunitサンプル

```
[Unit]
Description=sample
Wants=network-online.target
After=network.target network-online.target

[Service]
Type=oneshot
ExecStart=-/usr/sbin/sample
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
```
Web記事の頻度辞書を作成するまで


#Web 記事一括保存

サブディレクトリに一括で処理するスクリプト
http://hico-horiuchi.hateblo.jp/entry/20130421/1366557696


Webサイトを一括ダウンロードするには　北浦訓行　2003/2/20
https://www.atmarkit.co.jp/flinux/rensai/linuxtips/407dlweball.html


wgetの使い方メモ - basic認証、robots.txt無視
https://qiita.com/inutty/items/917f42b0e9e9d643d59d

#タグ取り

C# HTMLタグを除去したい
https://teratail.com/questions/87807

Delete html tags using sed/grep/awk
https://unix.stackexchange.com/questions/359980/delete-html-tags-using-sed-grep-awk


```sed:rmtag.sed
sed -e 's/<[^>]*>//g' index.* >> /tmp/web/indexall.txt
```
#事例

https://www.vector.com/us/en-us/

#参考資料
Webサイトの丸ごとダウンロードツール「Cyotek WebCopy」がJavaScriptをサポートへ
https://forest.watch.impress.co.jp/docs/news/1194549.html

WeBoX v0.99M（07/02/12） インストールアプリ
気になるWebページを丸ごと保存・スクラップ
https://forest.watch.impress.co.jp/library/software/webox/
Azure App Service for Java の Configuration は System.getEnv() で取得する


Azure Web App のサービスで Javaベースのアプリを実行する際、Settings - Configuration から Application settings として　Name - Value の組み合わせで値を保存することができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/2ec8c815-4e88-a4ff-1769-62133fa66d91.png)

この値をアプリから取得するには System.getEnv() を利用する。

```java
String serviceName = System.getenv("KEY_NAME");
```

システムプロパティ(System.getProperty()で取得)ではなくて環境変数(System.getenv()で取得)としてセットされるのがポイント。


以上です。
AWS ソリューションアーキテクトアソシエイト持ちが AZ-900: Microsoft Azure Fundamentals に挑戦してみた

## 概要

AWS ソリューションアーキテクトアソシエイトを合格し、プロフェッショナルを目指して勉強中です。いろいろあって `AZ-900: Microsoft Azure Fundamentals` を受験して無事合格したのでその流れをまとめてみようかなと。

## 前提条件など
* 経歴等は[こちら](https://qiita.com/dmikita/items/93a3d93ac91fb3c58641)の記事を参照
* ソリューションアーキテクトアソシエイト取得後はプロフェッショナル目指して勉強していました。



## 資格取得のきっかけ

* AzureADなどが演習問題に出ておりこの辺わからないな・・・となりました。
* `Microsoft Azure Virtual Training Day : Fundamentals `というオンラインセミナーが開催されていたので参加してみました。在宅勤務だったので聞きながら仕事していました。
    * この時内容的にAWSの方と共通している部分が多々あったのでこのまま受けてみようかなと考えました。
* こちら参加するだけで受験料が免除されるということで AZ-900: Microsoft Azure Fundamentals を受けて見ました。
* 現在でも `Microsoft Azure Virtual Training Day : Fundamentals ` で調べてみると定期的に開催しているようで現在でも受けることができるようです。

## 勉強方法

### 勉強から受験の流れ
勉強時間としては1～2週間くらい、合計20時間くらい？(オンラインセミナーの時間は除きます)でした。(タダだからまあ)

1. `Microsoft Azure Virtual Training Day : Fundamentals `を受講
1. Qiitaで勉強した人などいないか調べてみる。
    * [こちら](https://qiita.com/gomasa/items/8279c389ee10f7226dc4)と[こちら](https://qiita.com/mnoda/items/76c21096bfdedaf319c8)の記事を参考にしました。
1. [Azureの基礎](https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/)を読みました。(実習は未実施)
    * `Azure Resource Manager での Azure リソースの管理と整理`と`Azure のコストを予測して支出を最適化する` については最後のまとめのみ
    * ここの内容を把握していれば問題はほとんど解けそうな感じでした
    * 一部画像が表示されていなかったりMarkDownの記述失敗しているなという箇所もありましたが・・・
1. Azureの基礎を読み進めながら [AWS サービスと Azure サービスの比較](https://docs.microsoft.com/ja-jp/azure/architecture/aws-professional/services)を読みAWSの各サービスとの対応を頭に入れました。
    * Azureの基礎の内容でもAWSだとこれかな？と考えながら読むと頭に入りやすかったです。

### 注意点
* 試験を予約する際無料のチケットを有効にするにはセミナーを申し込んだのと同じメールアドレスを使う必要があるので、有効にする際に入力するアドレスには注意
    * オンラインセミナーの申し込みは勤務先のアドレスで申し込んでいたので、最初わからず有効にできないとあわてました・・・
* 今のご時世なのか受験できる場所が相当限られていました・・・スケジュールには余裕をもって予約した方がよさそうです。
* 結構他の受験をしている人がいたのか受付が混んでいたので時間に余裕を持った方がよさそうです。

## 受験について
* 実際の試験ではAWSと違い、ラジオボタン、チェックボックスだけでなくサービス名がずらっと並んでいるところから選んだり、ドラッグドロップして正解を選んだりとバリエーションがあったのでちょっと驚きました。
* 合格ライン700点のところ746点とちょっとギリギリでした。Azureの基礎をもうちょっと読み込んでいればもっととれたかなと


## 最後に
* AWSを知っているとクラウドの基本的な部分は共通しているので比較的取りやすい資格のように思います。
* AWSとAzureを比較するとそれぞれの違いがわかってそこが結構面白かったです。
* ソリューションアーキテクトプロフェッショナルの方が一区切りしたらAzureを進めるかGCPもついでに挑戦してみるのもいいかもしれません。
【初心者でもわかる】横スクロールしたら背景が切れてしまう時の対策方法

# どうも7noteです。横スクロールした時に、背景色が切れてしまう問題の解決方法

どうも7noteです。
この記事は以下へ引っ越しました。

https://naruweb.com/coding/widebg/
Visionで顕著性分析。人の視線を集めるのはどこか。

#人は画像のどこをみているか。
Visionで、画像の中で人の視線を集めやすい部分を分析できます。
いろんな画像で分析してみました。

**　（１）人　／　（２）目立つ物体　　／　（３）人が見る確率が高いところ**
![pexels-truth-enock-4063607.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/fb5f4136-6b88-95c4-c2b7-1550f5aaca9f.jpeg)![Rects Mask Attention Objectneのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/6f5fe6af-d6ac-ba35-700d-617369f6cec6.png)![IMG_1553のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/d1d177e3-54be-0647-2cea-bf90cc28ac4f.png)
白い部分が顕著性マスクで、四角がその境界ボックス表現です。
画像はアップルの公式サンプルです。簡単に試せます。

##1,人の視線を集める可能性の高い部分を分析する。

```swift
let attentionRequest = VNGenerateAttentionBasedSaliencyImageRequest()
```

##2,目立つ物体を分析する。

```swift
let objectRequest = VNGenerateObjectnessBasedSaliencyImageRequest()
```

##実行

```swift
let requestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
try? requestHandler.perform([attentionRequest])
```

##結果処理

```swift
let observation = request.results?.first as? VNSaliencyImageObservation
let pixelBuffer = observation.pixelBuffer // 結果マスク画像のピクセルバッファー (68*68)
let salientObjects = observation.salientObjects　// 目立つオブジェクトのRectangleObservation
for object in salientObjects {
    let boundingBox = object.boundingBox //　個々のオブジェクトの境界ボックス 
}
```

##試してみた
**　（１）かぼちゃ　／　（２）目立つ物体　　／　（３）人が見る確率が高いところ**
![pexels-karolina-grabowska-5422694.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/7dcd87c8-b81e-451e-a323-78f4a6d333c4.jpeg)![Rects Mask Attention Objectne１のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/bcb0a6b6-c33f-623b-7c6e-31acbff1bf00.png)![IMG_1555のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/37c1de32-5d6e-7fe3-8224-5ec06299f35f.png)
**　（１）ろうそく　／　（２）目立つ物体　　／　（３）人が見る確率が高いところ**
![pexels-nick-bondarev-5017023.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/753e47eb-9a55-9cd7-afa6-b1a62dc6ee17.jpeg)![IMG_1556のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/0da24129-61be-674d-0a68-408c30648bee.png)![IMG_1557のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/17d4a73e-5eff-d06f-2d44-a4a9fe5e6092.png)
**　（１）わんちゃん　／　（２）目立つ物体　　／　（３）人が見る確率が高いところ**
![pexels-samson-katt-5257637.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/da1bfa0f-c52c-0f66-5bce-42480732fa41.jpeg)![IMG_1558のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/b267bf98-8bd0-7721-9b47-4afa9d4a21b3.png)![Rects Mask Attention Objectnessのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/126bb87e-4b36-6d13-cdba-ef7ec415e76a.png)

🐣
****
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Terraform(AWS)入門時にハマったとこ

# 前提
TerraformがAWSを始め､複数のクラウドをまとめてIaaCな管理できるすごいやつ､という認識程度
今回は API Gatewayと Lambdaを作成して紐付けるとこまでやった｡
その際にハマったことの覚書としてここに残しておきます
# ハマったこと一覧
## MalformedPolicyDocument: JSON strings must not have leading spaces
##### 状況：IAMのassume_role_policyをベタ書きしてapplyすると怒られる
##### 原因：assume_role_policyをインデントして整形すると怒られる｡
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123667/d60a0ed1-cccc-50b5-459e-10180257cb14.png" width="50%">

##### 対策：見た目はイケてないが､インデントなしでやろう

## Error Creating IAM Role {role_name} InvalidClientTokenId: The security token included in the request is invalid
##### 状況：IAMを作成すると怒られる｡
##### 原因：AWSのMFAを有効にした状態で､ ~/.aws/config に mfa_serial パラメータを追加せずに実行すると怒られる｡(aws-vaultを利用していた)
##### 対策：~/.aws/config に mfa_serialを追加しよう

## terraformにおけるsource と data の違い
- data はすでにクラウド上にあるリソースを参照する手段｡Readonlyなので､そのリソースを消したりできない
- source は書き換えもできる｡

他のプロジェクトなどと共有するもの→ data
このプロジェクト固有のもの→ source
Unity-Chan! のスクリプトを直す（2020年11月）

# 環境（主な部分）

いずれも執筆時点（2020-11-01）、一般的な方法で入手可能な最新版。

- Windows 10 Home 1909
- Unity 2020.1.11f1
    - Unity-Chan! Model (unity-chan!) v1.2.2
    - Visual Studio Code Editor (Unity Technologies) v1.2.3
- VS Code 1.50.1
    - C# (Microsoft) v1.23.4
    - Mono Debug (Microsoft) v0.16.2
    - Visual Studio IntelliCode (Microsoft) v1.2.10
    - Debugger for Unity (Unity Technologies) v2.7.5

# やったこと

## その１
`Assets\unity-chan!\Unity-chan! Model\Scripts\IdleChanger.cs` で

>'AnimatorStateInfo.nameHash' は旧形式です ('AnimatorStateInfo.nameHash has been deprecated. Use AnimatorStateInfo.fullPathHash instead.')

と言われる個所が４つあるので、書いてある通り、`nameHash` を `fullPathHash` に書き換え。

## その２
`Assets\unity-chan!\Unity-chan! Model\Scripts\UnityChanControlScriptWithRigidBody.cs` で

>'AnimatorStateInfo.nameHash' は旧形式です ('AnimatorStateInfo.nameHash has been deprecated. Use AnimatorStateInfo.fullPathHash instead.')

と言われる個所が５つあるので、書いてある通り、`nameHash` を `fullPathHash` に書き換え。

以上。
ReactのuseRefで親と子コンポーネントのDOMにアクセスする with TypeScript

`useRef`を使って親と子コンポーネントのDOMにアクセスした背景としては、各DOMの高さを取得したかったからです。
実装内容です。

- useRefで親と子コンポーネントのDOMにアクセス
- 各DOMの高さを取得
- 子コンポーネントのDOMにuseRefを渡すとき`forwardRef`を使用
- TypeScriptで実装

## useRefで親コンポーネントのDOMにアクセスする

- ページ全体の高さを取得してuseStateの`appHeight`に設定
- useRefを使用して、`<div>`のscrollHeightの値を取得
- `Header`コンポーネントにuseRefを渡して、`<header>`のclientHeightの値を取得
- useRefのGenericsにDOMの型を指定

``` javascript:親コンポーネント
import React, { FC, useEffect, useRef, useState } from 'react';

import Header from '@/components/header';

const Parent: FC = () => {
  const [appHeight, setAppHeight] = useState(0);

  const containerRef = useRef<HTMLDivElement>(null);
  const headerRef = useRef<HTMLHeadElement>(null);

  useEffect(() => {
    if (containerRef.current && headerRef.current) {
      setAppHeight(
        containerRef.current.scrollHeight + headerRef.current.clientHeight
      );
    }
  }, [setAppHeight]);

  return (
    <>
      <Header ref={headerRef} />
      <div ref={containerRef} />
    </>
  );
};

export default Parent;
```

## 子コンポーネントでforwardRefを使用してrefを受け取る

- ReactのAPIで`forwardRef`を使用して親コンポーネントに設定したuseRefを受け取る
- forwardRefは`forwardRef(props, ref)`の関数
- refの型はRefを使用してGenericsに受け取ったuseRefのDOMの型を指定
- forwardRefの型はGenericsでrefの型とpropsの型を指定

``` javascript:子コンポーネント
import React, { Ref, forwardRef } from 'react';

const Header = (props: Record<string, unknown>, ref: Ref<HTMLHeadElement>) => (
  <header ref={ref} />
);

const fowardHeader = forwardRef<HTMLHeadElement, Record<string, unknown>>(
  Header
);

export default fowardHeader;
```

以上になります。
AWS EC2においてポート80番でデプロイしたかった

# はじめに

Node.jsで作成したアプリケーションを、AWS EC2でデプロイしました。
ポート3000番ではデプロイできたものの、80番でデプロイすることができず色々と調べたので、
調べた内容や、解決方法について記します。

# 実行環境
- AWS EC2 (Amazon Linux2 AMI)
- Apache 2.4.46
- Node.js 12.19.0



# やりたかったこと

URLのポート番号表記を省略して、短いURLにしたかった。

`http://hogehoge:3000/` → `http://hogehoge`


https://www.google.com:443/ に接続したとき、
自動的にhttps://www.google.com/ にリダイレクトされることは知っていたので、*1
この応用で、3000ではなく80番ポートでデプロイすれば、

`http:[パブリックIPv4アドレス]:3000/` → `http:[パブリックIPv4アドレス]`

のようにポート番号の表記が省略され、URLを短くできると考えました。


> *1
ホスト名のあとには、ポート番号が続くことになっていますが、たいてい省略されます。省略されている場合、スキームのプロトコルのウェルノウンポートになります。HTTPならTCPポート番号80番にアクセスします。ポート番号を指定する場合は、「:」のあとにポート番号を指定します。
[URL ～Webサイト(Webページ)のアドレス～](https://www.n-study.com/tcp-ip/url/)

引用に対する補足：443番もHTTPSとして、HTTP 同様にふるまいます。

# 困ったこと & エラー文

以下の画像のようなインバウンドルールにおいて、Node.jsで作成したアプリケーションを
ポート番号3000で`node app.js`すると、以下URLでWeb上に公開できました。

`http:[パブリックIPv4アドレス]:3000/`

一方で、ソースコードで指定したポート番号を3000から80番に変えると、
`node app.js`の実行時に、以下のエラー文が返ってきました。

`Error: listen EACCES: permission denied 0.0.0.0:80`


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549712/2393b1b8-9fde-cc6b-4f6a-7cf29473e590.png)


# 解決方法

下記を参照して管理者権限で実行してみましたが、私の場合では別のエラーが発生しました。

```
$ sudo node app.js
sudo: node: command not found
```

> サーバー立ち上げ時に小さいポート番号を指定すると、このエラーが発生します。
一般的には、管理者権限を持っていない場合では、1024番以下のポート番号にてサーバーをlistenすることはできないとのことですので、
`sudo node app.js`
と、管理者権限で実行するようにしましょう。
[「listen EACCES 0.0.0.0:443」というエラーが出るとき](https://qiita.com/tomoya_ozawa/items/131c75bdfa08e12fc4ae)

　

このエラーは、さらに別の記事を参照して解決を図りました。

下で引用した記事内では、おおまかに分けて3つの解決策が提示されていましたが、
私はその中でwhichコマンドを利用し、問題を解決しました。

```
$ sudo `which node` app.js
```




> whichは指定したコマンドのパスを表示するコマンドで、Linuxでは$()で囲うとそのコマンドの出力結果をコマンドとして使えるという機能があるらしい。
[sudo nodeでcommand not foundが表示される件](https://penpen-dev.com/blog/sudo-node-commandnotfound/)

　

> sudoを付けずにnodeを実行するときちんと実行されるのに何故なんだ･･？
と思って調べてみたら、どうやら原因は「sudo付きでコマンド実行すると環境変数であるPATHがスーパーユーザーのものに変わるから」だった。
[sudo nodeでcommand not foundが表示される件](https://penpen-dev.com/blog/sudo-node-commandnotfound/)



# 参考

- [URL ～Webサイト(Webページ)のアドレス～](https://www.n-study.com/tcp-ip/url/)
- [「listen EACCES 0.0.0.0:443」というエラーが出るとき](https://qiita.com/tomoya_ozawa/items/131c75bdfa08e12fc4ae)
- [sudo nodeでcommand not foundが表示される件](https://penpen-dev.com/blog/sudo-node-commandnotfound/)
超入門 Laravel 環境構築

AWSでEC2インスタンス建てた後何をすればLaravelを使えるのか？

【環境】
apache2.4
ubuntu 18.04
php7.2
laravel7*



①サーバーアップデート
②apache2のインストール
③PHPのインストール
④サーバー再起動
⑤モジュール入れる
⑥パッケージ更新一色
⑦Composer インストール
⑧swapファイル作る
⑨ Laravelプロジェクト立ち上げ
⑩権限周り
１１apache設定変更
+α　SSLの有効化

①サーバーアップデート
---
```
sudo apt update
```

②apache2のインストール
---
```
sudo apt install apache2
```

③PHPのインストール
---
```
sudo apt install php7.2
```

④サーバー再起動
---
```
sudo service apache2 restart
```

⑤モジュール入れる
---

```
sudo apt install zip
sudo apt install unzip
sudo apt install php7.2-mbstring
sudo apt install php7.2-xml
sudo apt install php7.2-mysql
sudo apt install php7.2-bcmath
sudo apt install php7.2-curl

まとめた奴
sudo apt install -y zip unzip php7.2-mbstring php7.2-xml php7.2-mysql php7.2-bcmath php7.2-curl

```

⑥パッケージ更新一式
---
```
sudo apt update
sudo apt upgrade
sudo apt autoclean
sudo apt autoremove
```

⑦Composer インストール
---

```
sudo apt install composer
```

⑧swapファイル作る(3G分)低スペサーバー限定
---
```
無料枠だとLaravel重いからswapfile作って入れる！

sudo fallocate -l 3G /swapfile3
sudo chmod 600 /swapfile3
sudo mkswap /swapfile3
sudo swapon /swapfile3

※Laravel入れたらけしてもOK
sudo swapoff -v /swapfile3
sudo rm /swapfile3 
```
⑨ Laravelプロジェクト立ち上げ
---
```
cd /var/www
sudo composer create-project --prefer-dist laravel/laravel プロジェクト名
```

⑩権限周り
---
```
sudo chown -R ubuntu:www-data プロジェクト名
sudo find プロジェクト名 -type d -print | xargs -i chmod 750 {}
sudo find プロジェクト名 -type f -print | xargs -i chmod 640 {}
sudo chmod -R 770 プロジェクト名/storage/
sudo chmod -R 770 プロジェクト名/bootstrap/cache/
```

11 apache設定変更
---
①Apache2のドキュメントルート変更
②AllowOverride All変更奴
③RewriteEngine on
④サーバー再起動
⑤オーナー・パーミッションを調整


①Apache2のドキュメントルート
---

```
cd /etc/apache2/sites-available/
ls
000-default.conf  default-ssl.conf←この２つを変更する

```
一応記載
sudo vim  でファイル編集する際は "i"キーを押すと編集できる。
保存の際は "esc" → ":" → "wq" → エンタ-
※"wq"で保存できな買ったら "!wq"

```
000-default.conf開く
↓
sudo vim 000-default.conf

上の方にある
DocumentRoot /var/www/laravelプロジェクト名/public に変更
```

```
default-ssl.conf開く
↓
sudo vim default-ssl.conf


上の方にある
DocumentRoot /var/www/laravelプロジェクト名/public に変更
```

②AllowOverride All変更奴
---
```
cd /etc/apache2/
sudo vim apache2.conf ←変更してゆく
```
```
最下層から少し上がったとこに、似たようなのが複数あるから以下を追記

<Directory /var/www/laravelプロジェクト名/public> 
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>
```

③RewriteEngine on
----
```
sudo a2enmod rewrite
```
④サーバー再起動
----
```
 sudo service apache2 restart
```

これで完了！
webページをひらけばLaravelのWelcomeページ表示される！

+α SSLの有効化
---
```
しなくてもHTTP通信できる
sudo a2enmod ssl
sudo systemctl reload apache2
sudo a2ensite default-ssl
```
※GoogleChromeはデフォルトのSSLをセキュリティーガバ扱いしてるから、少しやることある
↓
https://qiita.com/Sub_Tanabe/items/f5fc04d1db57152f69bf
material ui + react-hook-form Ratingのvalueを所得してみた

formの値を所得する時react-hook-formという便利なライブラリが存在します。
しかし、UIライブラリを使用するとうまく反映されない時があります。
material uiのRatingを例に出して、その対処法をご紹介します。
今回は、UIライブラリを使った時の対処法についての紹介なので、基本的な使い方はある程度わかっているとして記事を書かせていただきます。


## react-hook-formの基本的なコード

以下のコードは、ボタンを押した時にデータをlogに表示させるだけのコードで
react-hook-formの初歩的な使い方です。
ベースはこのコードで書いていきます。

``` 
import React from 'react';
import { useForm } from 'react-hook-form';

const Form = () => {
  const { register, handleSubmit } = useForm()
  const submit = (data) => {
    console.table(data)
  }
  return (
    <form onSubmit={handleSubmit(submit)}>
      <input
        name="text"
        ref={register} />
    </form>
  );
}

export default Form;

```
## material uiの導入（registerを入れられる場合）
ここからmaterial uiを導入します。
が、まず使うUIにregisterに使用できるinnerRef または ref を公開しているかどうかを確認します。
公開している例で言うとmaterial ui のTextFieldです。この場合はinputRefを公開していて
その中に登録するためのregisterを入力します。

実装する場合は 

```
yarn add @material-ui/core 
か
npm install @material-ui/core
```
をしてインストールしてください。

```
import React from 'react';
import { useForm } from 'react-hook-form';
import TextField from '@material-ui/core/TextField'

const Form = () => {
  const { register, handleSubmit } = useForm()
  const submit = (data) => {
    console.table(data)
  }
  return (
    <form onSubmit={handleSubmit(submit)}>
      <TextField
        name="text"
        inputRef={register} />
    </form>
  );
}

export default Form;
```
## material uiの導入(registerを入れられない場合)
次はregisterに使用できるinnerRef または ref を公開していない例です。今回は例としてmaterial uiのRatingを使って実装します。
上と同様に実装する場合は

```
yarn add @material-ui/lab
または
npm install @material-ui/lab
```
をしてインストールしてください。

```
import Rating from "@material-ui/lab/Rating"
import {useForm ,Controller} from "react-hook-form"

const  Form=()=> {
  const {control,handleSubmit}=useForm()
  const sub=(data)=>{
    console.table(data)
  }

  return (
      <form onSubmit={handleSubmit(sub)}>
      <Controller
      name="reviews"
      control={control}
      defaultValue={2.5}
      precision={0.5}
      as={Rating}
      />
      <button>sub</button>
      </form>
  );
}

export default Form;

```

- material uiからRatingをreact-hook-formからはuseFormとControllerをインポートします。
- controlとhandleSubmitを定義します。
- formタグの中にControllerタグを配置してその中に以下の属性を追加していきます。
  * name : react-hook-formで登録のkeyとなるもの（ユニークなものにする）
  * control : ここにはreact-hook-formに登録するためのメソッドが入っておりほぼrefにはいってるregisterと思っていいと思う(registerと同じようにcontrolをuseFormから定義すれば良い)
  * defaultValue : 初期値
  * precision : 区切り値
  * as : ここにUIのライブラリ等を入れる

## まとめ
以上のように簡単にformの値を扱えるためreact-hook-formは優秀なあと思います。
またバリデーション等も充実していてエラー文を表示することも簡単なため是非使っていただきたいライブラリです。
今回はほぼreact-hook-formを使ったことがない人でもわかるようにとおもい作りました。
誰かのためになれば幸いです。

詳細は
https://react-hook-form.com/get-started
の記事に書かれているので詳しく知りたい方は↑
node.jsでneo4jのOGMを使う③メソッド一覧

#node
|メソッド|引数|戻り値|説明|
|-------------|---------------|---------------|---------------|
|id()||int|Node ID|
|identity()||Integer|internal ID as a Neo4j Integer
|properties()||Object|プロパティ取得|
|get(property, or = null) |String:プロパティ名|mixin|指定したプロパティ名の値取得|
|valueToJson(property, value)|||
| model()||model|ノードのモデル取得|
| labels()||Array|ノードのラベル取得
|setEager(key, value)||node|Set an eager value on the fly
|delete(to_depth) ||Depth to delete to (Defaults to 10)|グラフからノードを削除します
|relateTo(node, type, properties = {}, force_create = false) |||ノードにリレーションシップを設定
|detachFrom(other) |||別のノードとの関係を削除します
|toJson()||Promise|NodeをJSONオブジェクトで取得|
|update(properties)|properties|node|nodeのプロパティを更新|

#Relationship 
|メソッド|引数|戻り値|説明|
|-------------|---------------|---------------|---------------|
|id()||int|Node ID|
|identity()||Integer|internal ID as a Neo4j Integer
|properties()||Object|プロパティ取得|
|get(property, or = null) |String:プロパティ名|mixin|指定したプロパティ名の値取得|
|valueToJson(property, value)|||
| definition()||Definition|リレーションシップの定義取得|
| type()||type|リレーションシップのタイプ取得|
|startNode()||node|リレーションの開始node|
| endNode()||node|リレーションの終了ノード|
|otherNode()||node|サブジェクトの関係の反対側のノード取得（方向が入っている場合は終了ノード、それ以外は開始ノード）
|toJson()||Promise|リレーションシップをJSONオブジェクトで取得|
|update(properties)|properties|node|リレーションシップのプロパティを更新|
ESP32で床下点検車を作る

2019年の台風で自宅が床下浸水しました。
この時、水抜きと浸水確認のために床下に入ったのですが私の力では家全体を見る事ができませんでした。
この為、床下を撮影できる車を作る事にしました。
##・仕様を考える
まずは、モーターの仕様から9～12Vを選択することになります。
駆動輪はタイヤかキャタピラーになります。
カメラ：Wi-Fi対応のカメラとする
コントローラー：ESP32
照明：高輝度LED
ベースは、Aliexpress等で売っているSmart Tankにしました。
使用するESP32はNodeMCU ESP-32 MotorShield FULLを使います。
https://qiita.com/usashirou/items/4674ece87d452e71256c
##・CAD
###本体のみ（キャタピラなし）
![3D-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/139d6ccd-86e2-db05-6b79-9b8150c171d2.jpeg)
###WEBカメラを付けてみましょう
これまだ土台だけです・・・
![3D-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/02c6cd92-b3ac-ec06-11ac-764c4394a12c.jpeg)
Arduino用のカメラマウントも取り付け可能にしました。
##・製作
本体の板金は協和工業にお願いしました。
![DSC_0163 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b73d5b42-5f0c-7496-23e6-dda1adfb5e85.jpeg)
ベースとなるSmart Tankのキットとの比較です。
少し大きいです。
![DSC_0168 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/9bdae32a-0b19-0ab7-dd7a-15b7023b8087.jpeg)
##・組み立て
![DSC_0170 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/16992f10-e9e9-945a-0059-a704d18eb7b8.jpeg)
ベースが完成です。
次に高輝度LEDとカメラを搭載してみましょう。
###WEBカメラ
![DSC_0524 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/bd2d3129-393c-c995-771b-7099f36e91ce.jpeg)
###1080Pカメラ
![DSC_0522 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/15705e93-9181-4602-d8ad-6b2cfe3e2ac4.jpeg)
1080Pのカメラの方が良いですね
ちなみに、トップカバーは、3Dプリンタで製作しました。
Lidarは搭載しない予定でしたが激安Lidarがあったので搭載してみました。
##・部品の準備
電源は、12v9800mahをギボシでつなぎます。
高輝度LEDとスイッチも準備します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/da2e2d4c-42ec-535b-a70c-2d7af93966cb.jpeg" width="500" />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e78c8600-71b4-cb0b-df96-08bf28fd4b4f.jpeg" width="500" />
##・完成
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/028fd2ca-e83c-3387-5f95-dfa1a1ad15eb.jpeg" alt="ESP32床下点検車" />
###・LED点灯状態
高輝度LED明るいですね
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/878240cd-1dff-0482-d2fe-6f0e258070d2.jpeg" alt="ESP32床下点検車" />
【Android】ScrollView がトップに戻らない

# やりたいこと

ScrollView の中に RecyclerView を入れてスクロールできるようにしている画面があります。

```
 --------------------
| ScrollView         |
|  ----------------  |
| | RecyclerView   | |
| |                | |
```

RecyclerView の中身はユーザーの操作によって非同期的に変更されることがあり、変更される場合はトップまでスクロールを戻したい。

【2020/11/02 追記】

コメントでご指摘いただきましたが、上記のような場合 ScrollView がなくてもスクロールが機能するので不要でした。

そのうえで RecyclerView をトップまで戻す方法は下記にあるとおり `recyclerView.scrollToPosition(0)` で OK のようです。

# 試したこと

スクロールをトップまで戻すための方法はいろいろな記事で書かれています。

よく目にするのが以下の２つ。

```
scrollView.fullScroll(ScrollView.FOCUS_UP)
```

```
scrollView.scrollTo(0, 0)
```

しかし自分の環境ではどちらもうまく機能しませんでした。

# 結論

結果、次の方法で解決しました。

```
recyclerView.scrollToPosition(0)
```

RecyclerView の最初の要素までスクロールさせることができます。

~~上記ダメパターンがなぜ機能しなかったのか、、もしわかる方がいれば教えていただけると幸いです。~~ → コメントにて教えていただきました！
gTTS で日本語の発話 (テキストファイルの読み上げ）

こちらと同じことを gTTS で行ってみました。
[OpenJtalk で日本語の発話 (テキストファイルの読み上げ）](https://qiita.com/ekzemplaro/items/1d669ffa8915db110180)

```py:kusamakura02.py
#! /usr/bin/python
#
#	kusamakura02.py
#
#						Nov/01/2020
#
# --------------------------------------------------------------------
from gtts import gTTS
import sys
# --------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
file_in = sys.argv[1]
file_out = sys.argv[2]
#
fp_in = open(file_in,encoding='utf-8')
text_aa = fp_in.read()
fp_in.close()
#
tts = gTTS(text=text_aa, lang='ja')
tts.save(file_out)
sys.stderr.write("*** 終了 ***\n")
# --------------------------------------------------------------------
```

実行方法

```bash
./kusamakura02.py in01.txt out01.mp3
#
mpg321 out01.mp3
```
[aws] sqs メッセージの送受信

## 概要

業務でSQSを使用する機会があったため、その際に行った動作確認方法をまとめます。

## SQSとは

SQS(Amazon Simple Queue Service)はメッセージキューであり、データの送受信を仲介する役割を持つサービスです。
メッセージブローカとして有名な`RabbitMQ`とほぼ同じ機能を持っています。

SQSを使用する利点は以下の通りです。
https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html

* セキュリティ
    * AWS KMS で管理されたキーを使用してキューのメッセージのコンテンツを保護するため、重要なデータを送信することが可能
* 耐久性
    * メッセージの安全性を確保するため、 Amazon SQS 複数のサーバーに保存
* 可用性
    * 冗長なインフラストラクチャを使用して同時実行性が高いメッセージへのアクセスと、メッセージの作成と消費のための高い可用性
* スケーラビリティ
    * プロビジョニング指示を必要とせずに負荷の増大やスパイクに対応
* 信頼性
    * 複数のプロデューサーがメッセージを送信するのと同時に、複数のコンシューマーがメッセージを受信
* カスタマイズ
    * ユーザ側である程度カスタマイズすることが可能


## キューの作成

データの送受信を行う前に、キューを作成する必要があります。
AWS コンソール `サービス → sqs → キューの作成` の手順で作成します。

![スクリーンショット 2020-10-31 11.11.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497547/3920ff32-152a-14d1-2a8d-1801f4199a7c.png)

キューには`標準`と`FIFO`がありますが、動作確認を行うだけなので今回は標準とします。

## データの送信

データの送信方法は以下の通りです。
事前に`aws configure`を設定しておく必要があります。

```python
import boto3
import json

que_name = 'test_que'
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName=que_name)

def sqs_send_msg():

    msg = [{'Id': '1', 'MessageBody': json.dumps([{'result': "msg_1"}])}]
    response = queue.send_messages(Entries=msg)

    print(response)
    return response

sqs_send_msg()
```

## データの受信

sqsのurlを指定してsqsとの通信を行うことも可能です。
urlはAWSコンソール画面から確認できます。

```python
import boto3
import json

sqs = boto3.client('sqs')
queue_url = "https://sqs.ap-northeast-1.amazonaws.com/xxxxxxxxxxxx/test_que"

def sqs_receive_msg():
    msg = sqs.receive_message(QueueUrl=queue_url, MaxNumberOfMessages=10)
    print(msg)

sqs_receive_msg()
```
脱Excel Elastic Stack（docker-compose）でcsvログを分析・可視化 - LogstashのPipeline-to-Pipelineで複数のbeatからの入力を受け付ける

## はじめに

どうも！生産技術部で製品の検査工程を担当しているエンジニアです。[脱Excel Elastic Stack（docker-compose）でcsvログを分析・可視化 - Elastic Stack](https://qiita.com/TomoyukiSugiyama/items/619ab258ba230dfcf0a0)とはの続きになります。

## 対象読者
この記事では、Elastic Stackをそもそも知らない方、これから試そうと思っている方を対象としています。

## この記事の内容
Logstashの特定ポート（５０４４）で受け付け、複数のbeatからの入力を別のパイプラインに流しました。

GitLabに設定ファイル一式を置いておきましたので参考にしてください。
リポジトリはこちら -> [elastic-stack](https://gitlab.com/iyama_yuki/elastic-stack/-/tree/master/)

## Pipeline-to-Pipelineの設定
beats-serverパイプラインを用意し、5044番ポートで受けます。[source]がfilebeatかmetricbeatで分岐し、それぞれのパイプラインに流します。公式のドキュメントは[こちら](https://www.elastic.co/guide/en/logstash/current/pipeline-to-pipeline.html#distributor-pattern)です。sourceで判断していますが、公式通りにtypeで判断すれば良いと思います。

```yml:logstash/config/pipelines.yml
- pipeline.id: beats-server
  config.string: |
    input { beats { port => 5044 } }
    output {
        if [source] == 'filebeat' {
          pipeline { send_to => filebeatlog }
        } else if [source] == 'metricbeat' {
          pipeline { send_to => metricbeatlog }
        }
    }

- pipeline.id: filebeat-processing
  path.config: "/usr/share/logstash/pipeline/{input/filebeat_in,filter/filebeat_filter,output/filebeat_out}.cfg"
  pipeline.batch.size: 50
  pipeline.batch.delay: 50

- pipeline.id: metricbeat-processing
  path.config: "/usr/share/logstash/pipeline/{input/metricbeat_in,filter/metricbeat_filter,output/metricbeat_out}.cfg"
  pipeline.batch.size: 50
  pipeline.batch.delay: 50
```

## inputの設定
5044番ポートで受けていたものを、pipelineのアドレスで受けるように変更します。

```config:logstash/pipeline/input/filebeat_in.cfg
input {
#  beats {
#    port => 5044
#  }

  pipeline {
    address => filebeatlog
  }
}
```

## Beatsの設定（公式のやり方とは違う）
logstashでどこから来たのか識別するために、sourceフィールドを設定します。（公式に従ったtypeに設定が間違いないと思います。）[fields_under_root](https://www.elastic.co/guide/en/beats/filebeat/current/configuration-general-options.html#_fields_under_root)を設定することで、filebeatから出力する時に、トップレベルのフィールドにストアすることができます。この設定をしないと正しく動作しません。

```yml:beats/filebeat/config/filebeat.yml
  fields:
    source: 'filebeat'
  fields_under_root: true
```

## 最後に
これで、複雑なパイプラインも組むことができるようになりました。
今後は、metricbeatなどについて紹介したいと思います。
IntelliJ IDEA／AdoptOpenJDKのインストール＆KotlinでHello world出力

# 概要
* 統合開発環境のIntelliJ IDEA／AdoptOpenJDKのインストール／環境構築
* IntelliJ IDEA上で「Hello world」と出力するプログラムファイルをKotlinで書き実行

# 目的
* Kotlinでアプリケーションを開発する環境の構築
* Kotlinの学習

# 前提
* 使用PCはMac／MacOS
* Homebrewをインストール済
* JDKはAdoptOpenJDKを使用

# 手順
1. IntelliJ IDEAのインストール
2. AdoptOpenJDKのインストール
3. IntelliJ IDEAのセットアップ
4. プログラムの作成／実行

## 1. IntelliJ IDEAのインストール
1. [IntelliJ IDEA](https://www.jetbrains.com/ja-jp/idea/)のサイトへアクセス
2. ダウンロードボタンをクリックし、[ダウンロードページ](https://www.jetbrains.com/ja-jp/idea/download/#section=mac)へ遷移
3. 「コミュニティ」の方のダウンロードボタンをクリック
4. .dmgファイルのダウンロードが完了したら、ファイルを開き、表示される手順通りに進め、インストールを完了させる

## 2. AdoptOpenJDKのインストール
1. ターミナルを起動
2. 下記コマンドを実行し、インストールを完了させる

```shell:terminal
brew cask install adoptopenjdk
```

## 3. IntelliJ IDEAのセットアップ
※IntelliJ IDEAでAdoptOpenJDKを使うようにするためのセットアップ

1. IntelliJ IDEAを起動
2. 右下の「Configure」 > 「Structure for New Projects」をクリック
3. 「Platform Settings」の「SDKs」をクリック
4. 「+」(Add New SDK) > 「Add JDK」をクリックし、2でインストールしたAdoptOpenJDKのフォルダパス（※基本「/Library/Java/JavaVirtualMachines」配下にあるはず）を指定。SDKが追加される
5. 次いで、「Project Settings」の「Project」をクリック
6. 「Project SDK:」で3-4で追加されたSDKを指定し、右下の「OK」をクリック

## 4. プログラムの作成／実行
1. トップ画面の「+ New Project」をクリック
2. 「Java」を選択し、「Project SDK」は3-6で設定したSDKがセットされていることを確認
3. 「Additional Libraries and Frameworks:」は「Kotlin/JVM」にチェック
4. 右下の「Next」をクリック
5. 「Project Name:」と「Project location:」に任意の名前を入力（例：~/dev/kotlin/test 等）
6. 左上の「src」を選択し、右クリック。「New」 > 「Kotlin File/Class」をクリック。「Name」(ファイル名)に任意の名前（例：test 等）を入力し、「File」を選択したままでreturn。srcディレクトリ配下に.ktファイルが作成される
7. 作成された.ktファイルを開き、下記をコーディング
8. 右上の「▶」(Run TestKt)をクリックし、「Hello world」の出力を確認

```kotlin:test.kt
fun main() {
    println("Hello world")
}
```

# 参考
※以下、参考にさせていただきました。ありがとうございます。

* [IntelliJ IDEAでKotlinを始めてHello Worldする](https://qiita.com/suin/items/e941aa249c235350b8eb)
【R】 所定のフォルダからファイルを読み込む

#ファイルリスト取得/出力フォルダ設定
    input_path<-"c:/R/id/input/"
    file_list <- list.files(input_path,full.names=T)
    output_path<-"c:/R/id/output"

#データ読み込み/ファイル名を取得/ファイル書き出し
    for ( list in file_list) {
     csv<-read.csv(list)  
     # time列を読み込んで時間をファイル名にする
     name<-csv[1,"time"]
     name_char<-as.character(name)
     write.csv(csv,paste0(output_path,"/",name_char,".csv"))  
    }
HTML/CSS:立体的なカード状のデザイン

#【概要】

<b>1.[結論](#1結論)</b>

<b>2.[どのようにコーディングするか](#2どのようにコーディングするか)</b>

<b>3.[開発環境](#3開発環境)</b>

<b>[補足](#補足)</b>


#1.結論
CSSで、<b>`box-shadow`、 `border`、`margin`、`border-radius`</b>を使用する！

#2.どのようにコーディングするか

```html
<div class="card">
<div>
```

```css
  border: 1px solid #333333; /* ---❶*/
  margin: 5px 20px; /* ---❷*/
  border-radius: .10rem;　/* ---❸*/
  box-shadow: 20px -10px 25px 0 #d9d9d9;　/* ---❹*/
}
```
❶：border : [線幅] [線の種類] [色] ;と設定できます。線の種類は`dashed`は波線、`double`は二重線等々の指定ができます。色は`#333333`でも`rgba(0,0,0,0(➡︎透明度設定可能)`でも可能です。

❷：これはいわずもがなで、外側の余白指定です。複数のカードを用意するときはこれで間隔を空けます。

❸：`border-radius`はカードの四隅を丸くしてくれます。`margin`のように1つの数値だと四隅に同じ数値を適用しますし、`border-radius:10px 20px 30px 40px/20px 30px 40px 50px;`と書くと`/`を境目に前者は`水平方向の半径`、後者は`垂直方向の半径`を`左上・右上・左下・右下`という順で設定できます。`.10`は0.10を示しており、`rem`は`html`要素に対して大きさを変化させています。


❹：`box-shadow`は 要素に影をつけます。`box-shadow： 水平方向 垂直方向 [ぼかし] [影の広がり具合] [色] [inset];`となっています。最後の`inset`は内側に影をつける仕様です。

自分が作ったものは下記のようになります！
![スクリーンショット 2020-11-01 20.31.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686400/7a78fc77-f661-9c81-c1af-e0cfa28ad049.png)



#3.開発環境
HTML5
CSS3

#補足
レスポンシブ対応で、横幅が縮まった際にカードを2列から1列にした場合は`メディアクエリ`と`flex-wrap: wrap`を使用することで単一行または複数行に押し込むことができます。


```css
@media screen and (max-width: ***px) {
   flex-wrap: wrap;
}
```
</br>
また、`rem`と`em`の違いはこちらになります。
参考URL：
<a href="https://qiita.com/masarufuruya/items/bb40d7e39f56e6c25f0d">CSS3のremとemの違いについて</a>