OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】debugの設定: launch.json, console

# NOTE

新規のターミナルで開かれるのがウザすぎたので設定し直しました。

## launch.jsonの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/14a803c6-a42c-a58b-3136-8a0df93834b6.png)

`create a launch.json file`を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/55ce957c-9891-23d4-88a5-6497a1f7a9f7.png)

デバッグしたい環境を指定することで、.vscode下に自動でlaunch.json作成してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/d49f034d-ae3c-7a72-0548-bd938e1c6f65.png)

## launch.jsonのconsole設定

[公式](https://code.visualstudio.com/docs/editor/debugging)では3つの設定ができるらしい。

>Many debuggers support some of the following attributes:
- console - what kind of console to use, for example, internalConsole, integratedTerminal, or externalTerminal

---
`DEBUG CONSOLE`に結果が表示される。

```json
"console": "internalConsole"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/2766c8f2-e68e-0dd8-af5e-e7d282edf190.png)

---
デフォルトの`TERMINAL`に結果が表示される。
デバッグする度に新規ターミナルが開かれる。
既存ターミナルにつづけて結果を表示する方法はわからない。。。誰か教えて下さい。

```json
"console": "integratedTerminal"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/ac250332-a0f3-43d9-6450-24f0e18c15a8.png)

---
デフォルトの`TERMINAL`が別Windowで開かれる。

```json
"console": "externalTerminal"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561377/e2e95d79-6644-16cd-c792-3de9cf96e2b8.png)
---
Facebook for Developers から Messenger Plugin を使ってみる！

## 初めに
<font color="orange">⚠️</font>自分で学んだことをメモとしてまとめています．
<font color="orange">⚠️</font>実装が終了するまで．最後にTodoを表示します．

[こちら](https://developers.facebook.com/docs/messenger-platform/getting-started/sample-apps/original-coast-clothing) を参照しております．

## 目的
完全なMessengerアプリを自身のサーバー上で実行したいです．
ドキュメントを読んだ経験が少ないので，自分の知見を向上させるための備忘録です．

## Messengerアプリをデプロイするための条件

- Facebookページ
- Facebook開発者アカウント
- Facebookアプリ

## ページとアプリを設定する

### 各種情報の取得

> このセクションの目的は、Messengerアプリがメッセージを正常に送受信するために必要なすべてのアクセストークンとIDを収集することです。

とあります．
必要なアクセストークンは以下です．

```
PAGE_ID=
APP_ID=
PAGE_ACCESS_TOKEN=
APP_SECRET=
```

実際に取得してみましょう！
各アプリページに遷移します．
メニューバーをみましょう．

- PAGE_ID
 - プロダクトの[＋]を選択し，Messengerを選択します．
 - アクセストークンにて新しいページを選択します．
 - ページが追加されるとページのIDが表示されています．(※2)
- APP_ID
 - ベーシックを選択します．
 - ページ上部に表示されます.(※1)
- PAGE_ACCESS_TOKEN
 - アクセストークンにてトークンを生成を選択します．
 - モーダルウィンドウで表示されます．(※2)
- APP_SECRET
 - ベーシックを選択します．
 - ページ上部に表示されます.(※1)

※1.アプリメニューバー → 設定 → ベーシック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751101/54b85157-8e68-fd77-5023-3fb0cb998af2.png)

※2.アクセストークン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751101/89833d79-4468-7fc3-26b5-8e8a4f25f498.png)

PAGE_ACCESS_TOKENとPAGE_IDに関しては
[アクセストークンデバッガー](https://developers.facebook.com/tools/debug/accesstoken/)にて，ページトークンを入力して，取得することも可能です．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751101/f10b7b21-aa6c-24f6-0ab5-15e9228615a7.png)

## ローカル環境で実行する

私はbash環境で確認をしました．

- node.jsのversion確認

```
$ node -v
v14.15.0 //こちらで実行します．
```


- ローカルマシンにこのリポジトリのクローンを複製

```
git clone https://github.com/fbsamples/original-coast-clothing.git //original-coast-clothingリポジトリの複製
cd original-coast-clothing // ディレクトリ移動
```

- コードの依存関係をインストール

```
yarn install
```

こちらで私はyarnがinstallされていなくて怒られてしまいました．
同じだ〜💦という方は こちら（まだ用意できていません🙇‍♂️） を確認してください．

##### ローカルトンネルを使用して受信メッセージを取得する

メッセージを受信するには、Facebookサーバーからの受信Webhooksを取得できることが前提となります．
公式ページにあるように`Localtunnel`を使用します．

- ローカルトンネルのインストール

```
npm install -g localtunnel
```

- <font color='orange'>新しいターミナルタブ</font>を開き、好きなポートを指定してローカルサーバーへのトンネルをリクエスト

```
lt --port 3000
```

このコマンドを叩くと，URLが取得され，そちらを後の`.env`ファイルの`APP_URL`変数に設定します．
このコマンドを実行するたびに，新しいアドレスが提供されるため，このウィンドウは開いたままにしましょう．

##### WebhooksとMessengerプロフィールを設定する

- 最初のターミナルで，提供されているテンプレートを使用して，すべての環境値を入力

```
mv .sample.env .env
```

( Todo mvコマンドでやっていること ! )
`.env` ファイルを編集して先に取得した値を全て追加しましょう．
`VERYFY_TOKEN` には任意の値を設定してください．

- ビルトインウェブサーバーを使用してローカルでアプリを実行

```
node app.js
```

私はこれで，ブラウザから `http://localhost:3000` にアクセスできました．


# Todo
### テストアプリを設定する
### コードを変更する
### Herokuにアプリをデプロイする
### CLIでHerokuアプリを作成します
### 環境変数(Config Vars)を設定します
### WebhooksとMessengerプロフィールを設定します
### テストアプリを設定します
### トラブルシューティング
### ローカルでアプリを再実行する
### その他の問題
エンジニアからPMになって1年、学んだこと・大変だったこと・行った対策をまとめてみた

エンジニア上がりのPMしてます@nnn194naです
PL/PMを経験して1年がたったので、学んだこと・大変だったこと・対策をまとめてみました

# 経歴
Android/iOS/ちょっとだけ組み込み PG -> SE -> PL -> PM

プログラミングの限界を感じ且つプログラムでは解決できないところへの不満からPLへジョブチェンジ。
PLの実績(プロジェクトで最後まで生き残ったこと)が評価されPMを任されることに。

# PMの印象
* 最初
    * 
PLより裁量権があって責任もあって大変だけどぶっちゃけ上の人に謝ればいいんでしょ
* 今
    * つらい
    * 技術を知らないPMが意外と多い

# PMのやってること
・プロジェクトの進捗管理
・予算/収支管理
・レビュー
・メンバの管理
・他部署及び他チームとの調整

# こんなに大変
> ・プロジェクトの進捗管理

今までエンジニアとして開発しか見ていなかったので気づかなかったが、複数バージョンが走ると辛い。
PLでは今動いているプロジェクトと次に動くプロジェクトを見ていたが、
PMになってからはもう少し先のプロジェクトと上期後期全体のプロジェクトを知る必要があった。
(ぶっちゃけ今どのバージョンの話をしてるかわからなくなるときがあった)

> ・予算/収支管理

純粋に桁が大きくて怖いし片手間でやると後ろの数字が全部ずれて辛かった。

> ・レビュー

承認するとなると、大きなバグとか出したら怒られると思って細かく見てしまって他の仕事が追いつかなくなる。
SE感覚で見てると他タスクが回らなくなる。

> ・メンバの管理
> ・他部署及び他チームとの調整

人間関係が一番辛い(現在進行形)。
PLまでは下のメンバとPMにとしか話さなかったので気づかなかったが、
企画開発含め、他チームと話すと価値観や視座、知識が全然違うことに気づき何て言ったら伝わるかとても悩んだ。

# どうしたか
> ・プロジェクトの進捗管理

スケジュールをちゃんとredmineなりスプレッドシートなりでしっかり管理した。
メンバには期日を守るよう徹底した。

> ・予算/収支管理

とりあえず場数を踏んでお金になれる。

> ・レビュー

メンバを信用することを覚えた。
ある程度任せないと自分がパンクしてしまう。

> ・メンバの管理

どんなスキル・人柄のメンバがきても大丈夫なようにルールやredmineやbacklog等のプロジェクト管理ツールのチケットや依頼内容のフォーマットを作成。
ただルール塗れになっているのでそこはどう改善するか模索中…

> ・他部署及び他チームとの調整

* 価値観や視座、知識が違うから話にならないという姿勢になるのではなく、相手に合わせた会話をする。
    * ex) WEB開発の人にAndroid/iOSの話をするときに、Android/iOSの専門用語をわかるでしょベースで話さないとか、エンジニアならこの温度感わかるでしょ！って内容もちゃんとエンジニア以外の人でもわかる内容にしてこれくらい重要なんだ！っていうのを説明してた

* 意見を押し付けない、押し付けられても改善策を一緒に考える
    * 文化の違いで片付けられてしまうものも今の時代にあってないと思ったら一緒に考える

* 苦手な人とも仕事をちゃんとする
    * 正直エンジニアのときはコードと向き合ってればいいやで苦手な人とか一線を引いてたところある

* アンガーマネジメント
    * 人間どうしてもいらっとしてしまう、感情を殺すために心がけた

当たり前のことだけどすごく重要。

# 最後に
自分なりのPMというものをまとめてみました。
ぶっちゃけどうしたかの内容については今も完全にできてるわけではない。(人間だもの)

プロジェクトマネジメントについてまだまだ勉強中なのでお手柔らかにお願いします。
gulp-postcss の autoprefixer エラーの解決方法

## エラーの発生状況

`gulp-postcss` で `autoprefixer` のバージョン `v10` 以上を利用するとエラーが発生。

```
Error: PostCSS plugin autoprefixer requires PostCSS 8.
```

## エラーの原因

* `autoprefixer` のバージョン `v10` 以上は `postcss` のバージョン `v8` 以上が必要なため
* `gulp-postcss` が依存している `postcss` のバージョンが `v7` のため

## エラーの解決方法

エラーメッセージを確認するとURLが表示されています。

```
Migration guide for end-users:
https://github.com/postcss/postcss/wiki/PostCSS-8-for-end-users
```

リンクをクリックすると [PostCSS 8 for end users](https://github.com/postcss/postcss/wiki/PostCSS-8-for-end-users) というページが表示され、様々な利用シーンでの解決方法が記載されています。

![gulp-postcss-autoprefixer-error_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/ec7ed466-9be5-8147-ab34-fed8c07efdc6.png)

Gulp の場合は以下となります。

![gulp-postcss-autoprefixer-error_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/a8268230-7499-1241-b282-ef0ac263f5b9.png)

この記述によると

1. `gulp-postcss` のバージョンを `v9` 以上にする
2. `postcss` をインストールする

というわけで、指示どおりインストールします。

```
npm i gulp-postcss@9.0.0 postcss -D
```

これでエラーが表示されなくなりました:blush:
Nginx で Laravel を動かす

まず、
/var/www/html 以下に Laravel のプロジェクトを作成します。

例えば
/var/www/html/helloworld というプロジェクトだとすると、
/var/www/html/helloworld/public を Nginx の root にします。

```text:/etc/nginx/sites-available/default
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html/helloworld/public;
        index index.html index.htm index.php;

        server_name _;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }

}
```

設定ファイルが正しいか確認

```text
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Nginx の再起動

```bash
sudo systemctl restart nginx
```

次のバージョンで確認しました。

```text
$ nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
```
HTMLの主な要素〜初心者だった自分に向けて〜　その③テキストコンテンツ

#HTML・テキストコンテンツ
###はじめに
その①「HTMLの主な要素〜初心者だった自分に向けて〜　[その①メタデータ系](https://qiita.com/syun02051/items/013bb352bec614123b23)」はこちら

その②「HTMLの主な要素〜初心者だった自分に向けて〜　[その②セクショニングと、主な区分化要素](https://qiita.com/syun02051/items/7650b11e991feacf0356)」はこちら


今回の記事にはHTMLの中のテキスト要素、タグについてまとめてあります。

<br>
##div要素 `<div>`
この要素はコンテンツを分割するための要素で、その範囲がブロックレベル要素であることだけを表します。他に適切な要素がない場合や、`class`や`id`を使用してスタイル付けをしやすくしたい場合に使用します。<br>この要素の中には、ブロックレベル要素でもインライン要素でも自由に入れることができます。

_記述例_

```html:HTML
<div class="warning">
    <img src="/media/examples/frower.jpg"
         alt="花の画像">
    <p>花はとてもきれいです</p>
</div>
~~~


```css:CSS

.warning {
    border: 10px ridge #f00;
    background-color: #ff0;
    padding: .5rem;
    display: flex;
    flex-direction: column;
}

.warning img {
    width: 100%;
}

.warning p {
    font: small-caps bold 1.2rem sans-serif;
    text-align: center;
}
~~~

##hr要素 `<hr>`
この要素は、文章中で話題の変更やテーマの区切りとして横線を表示させるための要素です。<br>
_使用例_

```html:HTML
<p>ぼくは先輩に尋ねた。「hr要素ってなんですか？」。すると先輩は「ヘアラインだ」と答えた。
そしてこう続けた。「ヘアラインが後退する前に嫁をもらったほうがいいという警告のために使用する要素なんだよ」。
ぼくは、「ヘアラインなら"hr"ではなく"hl"じゃないのか？」と疑問に思ったが細かいことを気にするとヘアラインが
後退しそうなので考えるのをやめた。</p>
<hr>
<p>翌週の水曜日、ぼくは先輩の家を尋ねた。釣りにいく約束をしていたからだ。
しかし、何度チャイムをならしても先輩は出てこなかった。帰ろうとした時、後ろから先輩の声が聞こえた。
「約束は明日だろ」。
ぼくは照れ笑いを浮かべながら、「じゃあ、また明日」。と言い残すとそそくさとその場を立ち去った。</p>
~~~

##ul要素 `<ul>`、ol要素 `<ol>`
ul要素は、箇条書きのような形式で順序なしのリストを表す要素です。行頭は○印がデフォルトで、CSSの`list-style-type`で変更できます。
ol要素は逆に、順序付のリストを表します。行頭は１から順の数字になります。
##li要素 `<li>`
リスト内の１項目を表します。<br>この要素は`<ul>`、`<ol>`、`<menu>`のいずれかの子要素として配置する必要があります。

_記述例_

```html:HTML
<p>りんごの品種リスト<p/>

<ul>
    <li>ふじ</li>
    <li>紅玉</li>
    <li>ジョナゴールド</li>
    <li>王林</li>
</ul>
~~~

##p要素 `<p>`
テキストの段落を表す要素です。<br>画像やフォームなどの関連する情報を構造的にまとめることもできます。空の`<p>`要素を使って段落間を空けることは読み上げアプリなど動きを阻害することがあるので推奨されません。段落間を空けたいときはCSSの`margin`などを使用するのが一般的です。<br>また、改行のためにこの要素で区切ることもよくありません。`<br>`をいれることによって同じテキスト内での改行を行うことができます。

_記述例_

```html:HTML
<p>こんにちは、田中です。ご無沙汰しております。<br>
今回こうして手紙を送ったのは、結婚の報告がしたかったからです。いまぼくは幸せです。</p>
~~~
UTF-8 BOMについて

<p>エンコードのUTF-8はBOM付とBOM無しがあるらしく、BOMの有無が原因で実行結果が異なる場合もあるようです。<br>
ここで学習のおさらいとして、表層的な知識をまとめてみました。</p>

<h2>BOMとはなんぞや？</h2>
<p>BOMは「Byte Order Mark」の略で、Unicode（統一文字コード）の符号化形式で符号化したテキストの先頭に付与される数バイトのデータです。<br>
ちなみに、Unicodeとは「文字セット（符号化文字集合）」と呼ばれるもので、使用する文字の定義です。<br>
このUnicodeの各文字に番号を割り当てるのが、「UTF-8」を始めとする「文字コード（符号化形式）」になります。</p>
<p>BOMをさらに詳しく説明すると、例えば「あ」という文字をコンピューター上で送る場合、</p>
<ul>
<li>01111000</li>
<li>11001100</li>
<li>11100001</li>
<li>11100010</li>
</ul>
<p>という4つの組み合わせのデータで「あ」を表すとします。（2進数のデータは適当です）<br>
この場合上記の4つのデータを送る、あるいは受け取る順番というものがあります。<br>
例えばリストの上から順番に送るのか、反対に逆から送るのか、この送る順番を表すものが「Byte Order Mark」になります。</p>
<p>このBOMの有無によって、どの種類の符号化形式を採用しているのかを判別しています。</p>

<h2>BOMを付与する一般的なケース</h2>
<p>Windowsアプリケーション（excelやメモ帳など）は、BOM付でなければunicodeなどの符号化形式を判断できない場合があります。<br>
その結果、BOMがついていないデータにも係わらず、BOMがついているとアプリケーションに判断されて文字化け等を起こしてしまう場合があります。</p>
<p>なぜMicrosoftがBOM付きを推奨するのかは私にもわかりません。</p>
<p>※現在はBOM無しにも対応していきているようです。（2021/2/15 現在)</p>

<h2>BOMを付与しないケース</h2>
<p>反対にBOMを付与すべきでないケースは、Webページとして使用されるHTMLファイルなどです。（BOM無しのUTF-8をUTF-8Nとも呼びます）<br>
これはWebページを動的に処理するPHPなどのプログラムが、BOM付のテキストファイルを正常に処理することができないからです。</p>

<p>ちなみに本来「UTF-8」は、「ISO（国際標準化機構）」によりデータの読み書きの順番が決まっているので、BOMをつける必要はありません。<br>
しかしWindows等ではBOM付きのファイルとして認識されることが多いので、BOMをつけておいた方が無難です。</P>

<h2>まとめ</h2>
<ul>
<li>Windowsで文字化けしたらBOMをつけてみよう！<br>
特にWebページをWindowsで作る際は、charasetの指定を忘れないようにしよう！</li>
<li>Linux・UnixなどでWebページを作る際は、BOMをつけようないようにしよう！</li>
</ul>

<h3>参考記事</h3>
<a href="https://at.sachi-web.com/blog-entry-1080.html">ウェブ制作：「UTF-8」の「BOM」って何？付けた方がいいの？</a>
<a href="https://qiita.com/JINr/items/255429d6174fad76b9b7">UTF-8 BOM付き・BOM無しでハマった</a>
<a href="https://uxmilk.jp/48923">UTF-8のBOM付き・BOM無しの違いと確認方法</a>
デプロイしたアプリにBasic認証を導入

# はじめまして
私は、Herokuでアプリをデプロイした後に公開を制限する為にBasic認証を導入しました。
備忘録として残したいと思います。

# Basic認証とは

HTTP通信の規格に備えつけられているユーザー認証の仕組みです。
サーバーとの通信が可能なユーザーとパスワードを予め設定しておき、それに一致したユーザーのみがWebアプリケーションを利用できるようになります。


# 導入

ターミナルで環境変数を設定します。

```terminal
% vim ~/.zshrc
#iを押してインサートモードにします。

export BASIC_AUTH_USER='********'
export BASIC_AUTH_PASSWORD='*****'

「escキー」「:wq」で保存して終了します。

% source ~/.zshrc
#パスを通します。
```

#Railsアプリケーション側で設定します。

```ruby
app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :basic_auth


  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]  # 環境変数を読み込む記述に変更
    end
  end
end

```

#Heroku上にも環境変数を設定します。

先ほどローカルで設定した環境変数をherokuにも設定します。

```terminal

% heroku config:set BASIC_AUTH_USER="********"
% heroku config:set BASIC_AUTH_PASSWORD="**********"
```

これで設定は完了です！

# 最後に

今回はBasic認証について勉強しました！手軽に通信に制限をかけれますが、絶対安全という訳ではないみたいです。
理由としては、「Base64エンコード」だからです。（データを64種類の文字列だけで表現するエンコーディング方式）
簡単にデコードすることも可能らしいです。
よりセキュリティを安全に使う為には、SSLやTLSも使って暗号化すると強化することができるみたいです。
herokuであればSSLになっているので問題ないと思いますが。

セキュリティに関しても勉強続けていきたいと思います。

ここまで読んでいただきありがとうございました！
HTTPメソッドについて[get,post,put,delete]

#HTTPメソッドとは
HTTPメソッドは、クライアントが行いたい処理をサーバに伝えるという役割です。

今回は４つ説明します。

#GET
何かしらデータ(=リソース)を取得するときに利用するHTTPメソッドです。

#POST
クライアントからサーバーにデータを送信するときに使います。

#PUT
POSTと同様にクライアントからサーバーにデータを送信するときに使います。
ですが、既存データの「更新」で使われるのが多いです。

#DELETE
既存データを削除したいときに使います。

#まとめ
HTTPメソッドは、クライアントが行いたい処理をサーバに伝えるという役割
wed開発で使用頻度が高いのはGET,POST,PUT,DELETE
シェルスクリプトでリトライ処理

# リトライ処理とは

常に成功するとは限らない処理に対して、時間間隔を開けてもう一度同じ処理を実行する試み。時間をずらせば、成功する可能性がある処理について行われる。

リトライ処理が必要とされる例としては次の通り。

* なんらかのAPIが、時間単位でのリクエスト数の制限を掛けているとき
* リソース不足で処理が中断される場合があるが、リソース不足をリクエスト元から観測できないとき


## 実際の利用事例

* BigQuery の `bq load` を並列処理させていたが、 RateLimited にひっかかるので時間をおいてリトライしたい
* スクレイピングのコードを動かしていたがネットワークが安定しないため、成功する場合と失敗する場合があったため、成功するまでリトライしたい


# コード

コンソールが色制御に対応していれば、

```shell
#!/bin/sh
set -eu

ESC=$(printf '\033')
TAB=$(printf '\011')
RED="${ESC}[31m"
GREEN="${ESC}[32m"
YELLOW="${ESC}[33m"
NORMAL="${ESC}[0m"

retryable() {
    (
        i=0 MAX_RETRY=10
        COMMAND="$@"
        while [ $((i+=1)) -le $MAX_RETRY ]; do
            eval "$COMMAND" && printf "[${GREEN}success${NORMAL} $i/$MAX_RETRY]${TAB}$COMMAND\n" && break
            printf "[${RED}retry${NORMAL} $i/$MAX_RETRY]${TAB}$COMMAND\n"
            sleep 1
        done
        return $?
    )
}

# 使い方(retryable の後ろにコマンドを書く)
retryable printf "hello world"
```

# 表示例

![スクリーンショット 2021-02-15 16.24.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38967/80742e93-9ca1-00ec-bd3a-d5ba1b09ba86.png)
【Ruby on Rails】rollbackする理由がわからないとき

## rollbackしてしまう
Ruby on Railsでアプリを作成していて、rails consoleで対話式でデータを投入しようとした。そのときに、rollbackしてしまい、データを作成することができない課題にぶつかった。

```
irb(main):010:0> CompanyAdmin.create(id:1, email: "sample@gmail.com", company_id: 1, first_name: "gorira")
```
このような形で、CompanyAdminのデータを自分で作ろうとしていた。
しかし、下記のようにrollbackしてしまう。
![スクリーンショット 2021-02-15 16.18.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/17685575-0ff4-337a-2fa0-cd63257932c2.png)

## やったこと
```
CompanyAdmin.createでデータを作成するときの記述を変更した。
```
CompanyAdmin.create!(............)
```
やったこととしてはcreateのあとに！をつけただけ。
これで、なぜrollbackするのかのエラー文を吐き出してくれる。

![スクリーンショット 2021-02-15 16.22.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628093/43d19037-0c1a-ea74-2f7f-56c649d7ec73.png)

するとこんな文言がでてきた。
```バリデーションに失敗しました:Passwordは必須項目です。```

passwordが必須だったみたい。

これで,passwordを追記したらデータを作成することができました。
Mac M1チップにpython環境を構築してみた

Mac初心者がM1チップに**homebrewーpyenvーpython**の環境を構築してみました。
###homebrewをインストールする
Rosettaを使用します。
Finderでターミナル.appを右クリックして、情報見るをクリック。
Rosettaを使用して開くにチェックを入れる。
その後ターミナルを開いて

```terminal:Terminal.app
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

を実行（[homebrew公式HPから](https://brew.sh/index_ja.html))。

brew doctorでインストールできているかを確認。

```terminal:Terminal.app
＄ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: "config" scripts exist outside your system or Homebrew directories.
`./configure` scripts often look for *-config scripts to determine if
software packages are installed, and which additional flags to use when
compiling and linking.
```
Warningが出ていますが、とりあえずは大丈夫でした。

###pyenvのインストール
次にpyenvをインストールします。

```terminal:Terminal.app
$ brew install pyenv
```

インストールしたらPathを通します。
シェルがzshなので、``.zshrc``で

```terminal:Terminal.app
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(pyenv init -)"' >> ~/.zshrc
```
openコマンドで.zshrcを開いて確認することもできます。

```terminal:Terminal.app
$ open ~/.zshrc
```

完了したらpyenv install --listで使えるバージョンを確認します。

```terminal:Terminal.app
$ pyenv install --list
```

###pythonのインストール
今回は python 3.8.7 をインストールしました。

```terminal:Terminal.app
$ pyenv install 3.8.7
```
インストールしたpython3.8.7を常時使うようにします

```terminal:Terminal.app
$ pyenv global 3.8.7
$ python --version
Python 2.7.16
```
普通にやってもうまくいかなかったので、

```terminal:Terminal.app
$ eval "$(pyenv init -)"
$ python --version
Python 3.8.7
```

これでpythonをインストールすることができました。

###Jupyter Notebookを起動
anacondaはインストールしていませんが、

```terminal:Terminal.app
% jupyter notebook
```

でJuypter Notebookを起動できます。
終了するときは、`ctrl + c`で。

これでひとまず、pythonを使える環境ができました。

###参考記事
[MacOSとHomebrewとpyenvで快適python環境を。](https://qiita.com/crankcube/items/15f06b32ec56736fc43a)
[pyenvを使ってMacにPythonの環境を構築する](https://qiita.com/1000ch/items/93841f76ea52551b6a97)
[M1チップ搭載のMacBookAirにHomebrewをインストールする【2020年12月~](https://www.oyoshi.work/entry/m1-mac-homebrew-install/#3_Rosetta_2)
[Macのzshでpyenvが「command not found: pyenv」](https://techium.hatenablog.com/entry/2016/08/30/010150)
[Jenkins] Unityに内包するファイルを非エンジニアが更新するJenkins設計について

#はじめに
アプリの起動画面にて、通信が発生しない状態で表示をしなくてはならないものがある場合、
Unityに予め内包しておく必要があるデータがあるとします。
このデータはプランナー側で管理しており、編集したタイミングでエンジニアがGithubにPushするというフローでした。
この`エンジニアがGithubにPushするというフロー`というのがめんどいね。ということで自動化した感じの忘却録です。
プランナーは毎回エンジニアに依頼を出していましたが、プランナーで完結します。

前提としての細かいフローは下記

* 編集データはDB管理である。
* プランナー側で該当データをEXCELで管理
* EXCELデータをDBに反映する
* データはjson形式でUnity側(アプリ内包)に保存される
* 編集したよ！の連絡を受けてエンジニアがJson形式で吐き出してデータ上書き後、GithubにPushする
* 反映するbrunchは一定(developのみ)ではなく開発Versionによって変更される
* Jenkinsで予め設定しておいたビルドで自動的にPullするので勝手に内包される

## DBからJson形式の書き出し
この部分はエンジニアがsshしたあとにコマンドを叩いてはDB → Jsonを生成していました。
この部分をファイル化してShellで叩いて吐き出すようにします。

## サーバー上にあるJsonファイルをJenkinsマシン(ローカル)へ
サーバー上でpushすれば良いのですが、Jenkinsのパラメータビルドでブランチ指定をしたいので、JenkinsマシンにJsonファイルを反映してPushするようにします。

## Jenkins側の設定の詳細について

### TARGET_BUILD_BRANCH設定
`ビルドのパラメータ化`の文字列に`TARGET_BUILD_BRANCH`変数を設定。
これは`ビルド`する際に必ず設定する

### 該当のリポジトリ設定
`ソースコード管理`でリポジトリの設定をする。
`ビルドするブランチ -> ブランチ指定子` は`*/${TARGET_BUILD_BRANCH}`で指定出来るようにする。
ビルドする際に、まず現状のブランチを最新にする必要があるので設定は必要です。
追加処理で`Advanced clone behaviours`を付けます。

### シェルの実行
```
git clean -df;
git reset --hard origin/${TARGET_BUILD_BRANCH};
git checkout ${TARGET_BUILD_BRANCH};
git pull;
```
上記、`ビルド -> シェルの実行`ではまず、現状のコードを最新にします。

```
ssh -i .ssh/id_rsa atsutama@atsutama.com "cd /home/atsutama; php json_export.php"
```
そのあとに、sshした際の処理を書きます。(上記はサンプルです。)
sshの続きでDBからjsonを吐き出すphpファイルを実行させます。
これで`atsutama`直下に該当のjsonファイルが完成しています。
PHP内の処理はDBにアクセスし、該当のMSTデータを取得、`json_encode` → `file_put_contents`で吐き出してます。

### 該当Jsonファイルをローカルのファイルと同機

```
eval `ssh-agent`
ssh-add ~/.ssh/id_rsa

# rsync
rsync -avz --delete -e ssh -i .ssh/id_rsa atsutama@atsutama.com:/home/atsutama/sample.json ローカルの反映したいディレクトリ/sample.json
```
Jenkinsマシンのサーバー上で生成したJsonファイルを同期させます。

### GitHubへPush
```
git add sample.json;
git commit --allow-empty -m "json update from Jenkins";
git push;
```
DB編集後のjsonファイルとローカルにあるjsonファイルに差異があれば、修正がPushされるはずです。
`--allow-empty`を付ける理由は編集がもしなかった場合にJobを実行するとErrorになるので空コミットOKにしています。

あとは、別JobでUnityをビルドすればJsonファイルがPullされるのでアプリに反映されます。
【C#】デバッグの基本

マイクロソフトのサイトにはデバッグの基礎が詳細に書かれています。

https://docs.microsoft.com/ja-jp/visualstudio/debugger/?view=vs-2019

日本語訳
![1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/3b7b9717-cbc0-d44d-2249-4fdf68838159.png)



英語訳
![1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/d54e574c-5e47-defe-ab06-2f7cbc60b4e0.png)



しかし、初めてデバッグする方には少々情報過多になっておりさらに日本語訳が分かりづらいといった問題があるので、情報を絞り最低限必要なものを和訳しました。


■デバッガーとは

https://docs.microsoft.com/ja-jp/visualstudio/debugger/what-is-debugging?view=vs-2019

 

アプリを開発する過程でデバッグは必要な作業です。デバッグはバグつまりプログラムの誤りを取り除く作業のことです。

 

デバッグにはVisual Studioデバッガーというツールを使用します。ここではまず使用方法を説明する前にデバッガーとデバッグおよびデバッグ＆リリースモードの用語について述べます。

 

デバッグ：ソースコードからバグをなくすこと。バグとは予期していない間違いのこと。
デバッガー：デバッグするための特別な開発ツールのこと
デバッグモード：デバッガー機能をONにしてアプリケーションを実行すること。
![1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/e908d9eb-6637-6b2c-59fc-284a1b49ee79.png)
一方で、リリースモードとは最終リリースの配布で使用する実行ファイルを作ることです。
![1-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/f9163912-4148-cfd2-30bf-1b07d6e8c891.png)
■デッバガーの使用

Visual Studioによって提供されているデッバガーについて述べます。
Visual Studioでデッバガーというバグをなくすためのツールを使用する際、さまざまな機能が提供されます。
例えばソースコードで設定した変数の値を確認したり、どういったパスでソースコードを読み取っているかなどです。

１．デッバガーを使用するためには、Visual Studio上でデバッグモードにする必要があります。

ここで説明されるデバッガーの機能はC#, C++ ,Visual Basic, JavaScriptといったVisual Studioがサポートしているプログラミング言語で有効である。
![1-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/7d5beb4c-a16f-127f-cfef-5a016af449fc.png)

２．ブレークポイントの設定(F9)とデッバガーのスタート(F5)
デバッグするためには、ソースコードにブレークポイントと呼ばれる設定をし、F5キーを押すします。
ブレークポイントは、変数やメモリの挙動などを確認するためにソードコードで疑わしい行に置く赤い点のことです。
アプリがまだ実行されていない場合、F5 キーを押すとデバッガーが起動し、最初のブレークポイントで停止します。
ブレークポイントはコードを１行ずつ調べることができる優れた機能になります。

実際にソースコードを開き、行番号の左側をクリックするとブレークポイントを置けるようになります。またはF9を押してもブレークポイントを置けます。
![1-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/37f668de-6055-e583-4577-433e78516ef1.png)

３．ステップイン(F11)

アプリの実行をソースコードの１ステートメント(1行)ずつ進めていく方法である。ステップインとも呼ばれます。F11キーを押すとステップインによるデバッグが始まります。F11からアプリを開始すればデバッガーは実行される最初のステートメントで停止します。ブレークポイントを置きそこからステップインによるデバッグを始めることも可能です。
![1-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/206bca60-5fa1-6c38-9c92-f84b52fbe85e.png)

黄色の矢印はデバッガーが一時停止しているいステートメントを表しています。

デバッガーの一時停止によってアプリの実行も同じポイントで中断されます (このステートメントつまりこの行でのメソッドまだ実行されていません)。
メソッド上でステップインするとそのメソッドを呼び出している関数まで移動できます。

４．ステップオーバー

前節のステップインではメソッドの呼び出し先まで移動する方法でしたが、スキップしたい場合はステップオーバーによるデバッグをします。
F10を押すとステップオーバーによるデバッグが始まります。関心のないコードをスキップすることが可能になります。
最後に：ステップ実行をやめる
ステップ実行をやめて、通常の実行に戻すには
![1-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408792/ba496e69-e6ec-3199-622b-5b5409511110.png)
続行ボタンをクリックしてください。これで次のブレークポイントまで一気にコードが進みます。

 

 ■まとめ

Visual Studioにおけるデバッグの基礎事項を説明しました。初学者はデバッグの開始(F5)、ブレークポイント(F9)、ステップイン(F11)、ステップオーバー(F10)をまずは知ってください。
TeraTermでNiceHashOSとSSH通信がしたい。

自分用の忘備録

マイニングリグの健康状態を確認したいのでssh通信したい。
試しにTera Termでログインを試みたが、まあできないですね。
英文で紹介されていたページを元にガチャガチャやったら通信できました。

まず。
初期状態ではSSH通信できない。(当たり前か)
鍵を設定して初めて通信できる。

NiceHashOSはTiny Core Linuxというディストリビューションをベースに作られているらしい。
Tiny Core Linuxは起動時にUSBメモリなど外部記憶装置からOSをすべてメインメモリにコピーして動かすようだ。つまり起動後に変更した内容は基本的に保存されない。(なんかコマンド打てば保存できるっぽい？)
つまりOSを保存してる外部記憶装置内のファイルに手を加える必要がある。

NiceHashOSの設定はドライブ直下の"configuration.txt"に変更を加える。
(WiFiのssidやpassを設定するのもここ。あと頑張ればグラボのOC設定とかもいじれるっぽい)

以下手順

<前準備>
下記をダウンロード、インストール
・PuTTY Key Generator(鍵つくるやつ)
https://www.puttygen.com/
・Tera Term(通信するやつ)
https://ja.osdn.net/projects/ttssh2/

1.PuTTY Key Generator起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104038/29567229-d117-2af0-c4fc-3f277e1aae61.png)

2."Generate"ボタンを押下後マウスをガチャガチャ動かす。（ポインター位置で疑似乱数生成？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104038/551c843d-f315-8272-5881-22675119cb1b.png)

↑こんな感じでステータスバーが右端へいくまでマウス動かす。

3."Public key for pasting into OpenSSH authorized_keys file:"の中身、"ssh-rsa"からはじまる文字列をリグのファイルのssh欄に張り付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104038/639cb3a5-8841-17a2-5c0f-ead8049e4cf4.png)

```TEXT:configuration.txt
{
    "access": {
        "ssh": {
            "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAvYKUlnWcrXONhcENZgPp79HPUYwOEEhvUwmcR1JVpMoVYq1X9VryGG297kNld9xiCQPx7Oh0gp8OLwAySZ15OmrzTyAK3cvj3tQdiHIBkPMhfo6Wud4N3/BF7jVmsQ11RrlC3Sn8LMWjdp+x+nr8yi9Mx6Q5nYnMkYiN7rb32ri9YnA3qayPQpuBmeGW1/NNJ14v1Fpo4NkFGboBJVDxVu0Vd+Pu+ftyAztMsyJFkjPAqRTGyIti36OJAdAETdfvBQmKy4JA/uqw1D7upLikJrY+fcUP+ssNJVbr7fOX6HX/y0BRQKZSpNG8k85kZ1k8ZvtrpcnTpP/tVhKhCdiqJQ== rsa-key-20210215"
　　　　　　　　　　　↑こんな風に突っ込む
    ～省略～
}
```

4.PuTTY Key GeneratorのAction内、Save private keyでppkファイルを忘れず作成する。

5.設定出来たらこのコンフィグファイル使って起動。

6.TeraTermで"新しい接続"、IPアドレス指定でOK。"ユーザ名"に"nhos"、パスフレーズは空欄でいい。認証方式がプレインパスワードになっているので"RSA/DSA/ECDSA/ED25519鍵を使う"に切り替えて、先ほど作成したppkファイルを指定してOK。

　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104038/04231c87-ab13-384d-e868-4e38be758b02.png)


接続できました。
CTRL + Cでコマンドラインに遷移できます。
お疲れさまでした。
高位合成言語アセンブラを作る。 その20

# 概要

高位合成言語アセンブラを作る。
俺言語から、verilogコードを生成する。

# コードを投入。

```
10 ?="helloworld"
20 #=20

```

# 生成したコード

```
module ore(input clk, input rst, output reg [7:0] out);
	reg [7:0] pc;
	reg [7:0] mod;
	always @(posedge clk)
	begin
		if (!rst)
		begin
			pc <= 10;
			mod <= 0;
		end
		else
		begin
			case (pc)
			10:
			begin
				out <= "h";
				pc <= 11;
			end
			11:
			begin
				out <= "e";
				pc <= 12;
			end
			12:
			begin
				out <= "l";
				pc <= 13;
			end
			13:
			begin
				out <= "l";
				pc <= 14;
			end
			14:
			begin
				out <= "o";
				pc <= 15;
			end
			15:
			begin
				out <= "w";
				pc <= 16;
			end
			16:
			begin
				out <= "o";
				pc <= 17;
			end
			17:
			begin
				out <= "r";
				pc <= 18;
			end
			18:
			begin
				out <= "l";
				pc <= 19;
			end
			19:
			begin
				out <= "d";
				pc <= 20;
			end
			20:
			begin
				pc <= 20;
			end
  			endcase
		end
	end
endmodule
module test;
	reg clk,
		rst;
	wire [7:0] out;
	ore u(.clk(clk), .rst(rst), .out(out));
	initial
	begin
		clk = 0;
		rst = 1;
		$monitor("%s", out);
		#2
			rst = 0;
		#2
			rst = 1;
		#2500
			$finish;
	end
	always
		#1
			clk = ~clk;
endmodule


```

# 成果物

https://embed.plnkr.co/plunk/vzlruJuWcR5Aebtp

以上。
Azure Static Web Appsのアプリケーション設定の辛み

Azure Static Web Appsのアプリケーション設定は新しい環境ができる、
つまりProduction環境のGitHubブランチに対してpull requestを作成した際、
新しく作成された環境にアプリケーション設定が値ごとコピーされる

ゆえに例えば、関数がログを書き込む先のApplication InsightsをProduction環境とStaging環境で分けたい、
といったことをシームレスにするのは難しい
これを解決するためには各システム環境ごとにStatic Web Appを作成することをお勧めする


## 動作確認  
pull request作成⇒merge⇒pull request再作成でアプリケーション設定の値がどうなるか確認する

1. GitHubにstagingブランチがあり、mainブランチへpull requestを作成している状態
  - Static Appに存在する環境  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/e3b103ab-6d9a-3d0f-af56-6c78995de034.png)
  - Prodution環境のアプリケーション設定  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/00af4fe2-cc39-d40b-be28-2311cf3f1dec.png)
  - Staging環境のアプリケーション設定<br>手動で値を変更しています  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/929c276a-e7a4-42a9-5c5e-24dc04205bca.png)


1. pull requestをmergeしたあとの状態
  - Static Appに存在する環境  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/2356702f-38f9-a25e-5c83-b8068e3f8444.png)
  - Prodution環境のアプリケーション設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/cdb70fe3-39c6-dbe0-a5b2-2f0e5f454c7a.png)

1. 再度stagingブランチからmainブランチへpull requestを作成している状態
  - Static Appに存在する環境  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/b6f5cd97-61c5-c1cc-c35a-0d98dd41f772.png)
  - Prodution環境のアプリケーション設定  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/e4de2dfc-49ad-860d-f189-62bb1037d602.png)
  - Staging環境のアプリケーション設定<br>**Production環境の値がコピーされてしまう**  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481044/f1d4aa25-2b45-ff3a-5916-68e3ed977a83.png)
[Vue.js] 共通SCSSファイルをグローバルで読み込む方法：こまけぇこたぁいいんだよ ─ のんびりVue.js超入門［第9回］

![vue_article.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593842/342b04a5-561b-8074-e100-23f4e8e2ff61.png)

[Vue.js] 共通SCSSファイルをグローバルで読み込む方法：こまけぇこたぁいいんだよ ─ のんびりVue.js超入門［第9回］
https://myscreate.com/vue-common-scss/
[Vue.js] SPAを最速で作成！ついでにhistoryモードでGithub Pagesへデプロイ：こまけぇこたぁいいんだよ ─ のんびりVue.js超入門［第10回］

![vue_article-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593842/d29900f1-ca87-49a2-bbed-fa24976877c4.png)

[Vue.js] SPAを最速で作成！ついでにhistoryモードでGithub Pagesへデプロイ：こまけぇこたぁいいんだよ ─ のんびりVue.js超入門［第10回］
https://myscreate.com/komakee-vue-spa/
Optional Chaining のエラーを更にもう一度整理

これまで、
https://qiita.com/terukazu/items/d0ac760425a715649d92
https://qiita.com/terukazu/items/73d32b7907cc76328fb9
と、気になった内容とか調べていて、ようやく、頭の情報が整理されてきたので、再度トライ。

## ```vue-cli-service build``` でエラーが発生しない

ts-loader が解釈できているんだから、エラーが発生しないのは当然。


## ```vue-cli-service build``` で生成し、ブラウザで確認してもエラーが発生しない

ブラウザがOptional Chainingをサポートしているならば、エラーする理由がない。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Optional_chaining


## storybook を開始するとエラーが発生する

### 発生時のローダー設定

```
File was processed with these loaders:
 * ./node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/ts-loader/index.js
 * ./node_modules/vue-loader/lib/index.js
```

ローダーは逆順に実行される。
https://webpack.js.org/concepts/loaders/#loader-features


### エラー回避

tsconfig.json の target を "ES6" にするとエラーは発生しない。

tsconfig.json の "target" を "esnext" や "es2020" を設定していても、"esnext"  というパラメータ自体にエラーが発生していない事を考えると、後段の vue-docgen-loader がエラー発生元の可能性が高い。

### storybook の公式見解

下記のチケットで発見。
https://github.com/storybookjs/storybook/issues/11515#issuecomment-657681163

ここで気になる記述が。。。。

> "I've found the culprit,"
>> 犯人見つけた。

これは良いとして、問題は次の一文

> "it looks like the "target": "esnext" doesn't support optional chaining anymore :/"
>> 「"taget" : "esnext"」 は Optional Chaining をサポートしなくたったみたい。

そして。。。

> So this is a tsconfig.json configuration issue, not a storybook issue?
>> それに、 tsconfig.json の設定の話だから、storybook 関係なくね？

として結論付けしている。

#### マジか？！

まず、これを見て吃驚仰天之助だったので。。。

> "it looks like the "target": "esnext" doesn't support optional chaining anymore :/"
>> 「"taget" : "esnext"」 は Optional Chaining をサポートしなくたったみたい。

改めて、公式サイトで調べてみる。

> ESNext という特別な値は TypeScript がサポートしている最新のターゲットバージョンを参照します。 
https://www.typescriptlang.org/ja/tsconfig

で、現時点の最新版のECMAScriptの「ECMA-262 11th Edition / June 2020」内の「12.3.9　Optional Chains」にてサポートしている記述がある。
https://www.ecma-international.org/wp-content/uploads/ECMA-262.pdf

となると、サポートしなくなったのは ECMAScript ではなく、何なんだろうか？
ちなみに、この発言は、コントリビュータさんじゃなさそう。

そして、次の発言はコントリビュータさんですね。
> So this is a tsconfig.json configuration issue, not a storybook issue?
>> それに、 tsconfig.json の設定の話だから、storybook 関係なくね？

というのが、storybookの公式見解のようですね。

#### 結論

「動けば良い」と考えるなら、```tsconfig.json``` で ```"target": "es2018"```にすれば良い。（"ES6"でも良いが、対象のプラットフォームによりますな）
「原因を知りたい」と考えるなら　storybook のソースコードを見るしかないかない。
【Rails】gem wheneverによる本番環境のバッチ処理

##はじめに

今回が初投稿となります。
学習した内容をアウトプットしようと思いアカウントを作成したのですが、インプットに夢中になり全然アウトプットできていませんでした。。。
この投稿をきっかけに定期的にアウトプットしていきたいと思います。
初学者ですので間違い等あるかもしれません。
その際は、お手数ですがご指摘お願いします。

##環境
 - Ruby 2.6.3
 - Rails 5.2.4
 - 本番環境 Nginx／Puma／Linux(CentOS)／AWS EC2／MySQL<br>
※ Dockerは使っていませんので注意

##目的
 - 本番環境でcounter_cacheのカウント修正を定時処理として行いたかった。（本記事ではcounter_cacheについては触れませんし、実行する処理も適当なものにしています）

##目次
 - wheneverの導入
 - 自動化したい処理を記述
 - 設定ファイルの作成
 - 自動化した処理の確認
 - 設定を本番環境に変更する
 - 本番環境で処理を確認する

##wheneverの導入

```ruby:Gemfile
gem 'whenever', require: false
```

``bundle install --path vendor/bundle``を実行。

#自動化したい処理を記述
``app/lib``の配下に``batch``ディレクトリを作成し、その中に任意のファイルを作成して自動化したい処理を記述する。
ファイル名（``hoge.rb``の部分）は何でもいいです。

```ruby:lib/batch/hoge.rb
class Batch::Hoge
  def self.fuga
    p "処理を実行しました"
  end
end
```

``lib``以下をロード対象とするために``config/application.rb``に下記2行を追加。

```ruby:config/application.rb

class Application < Rails::Application
  config.autoload_paths += Dir["#{config.root}/lib"]  # 追加
  config.eager_load_paths += Dir["#{config.root}/lib/**/"]  # 追加
end

```

実行されるか確認。

```
$ bundle exec rails runner Batch::Hoge.fuga
Running via Spring preloader in process [プロセスID]
"処理を実行しました"
```

##設定ファイルの作成
``bundle exec wheneverize . ``で設定ファイルを作成。

```
$ bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized! 
```

作成された``config/schedule.rb``に設定を記述。
まずは開発環境で処理が実行されるか確認するために``development``を指定し、実行頻度を1分にしています。

```ruby:config/schedule.rb
require File.expand_path(File.dirname(__FILE__) + "/environment")  # rootパス取得
set :environment, :development  # 実行環境の指定
set :output, "#{Rails.root}/log/cron.log"  # ログファイルの出力先
set :runner_command, "rails runner"

every 1.minute do
  runner "Batch::Hoge.fuga"
end
```

##自動化した処理の確認

```
# 設定内容が問題ないか確認
bundle exec whenever
```

```
# crontabに反映する
$ bundle exec whenever --update-crontab
```

```
# crontabに反映した内容の確認
$ crontab  -l
```

```
# crontabに反映した内容を削除
$ bundle exec whenever --clear-crontab
```

##設定を本番環境に変更する
問題がないことを確認したら設定を本番環境に変更する。

```ruby:config/schedule.rb
require File.expand_path(File.dirname(__FILE__) + "/environment")
set :environment, :production  # 本番環境に変更
set :output, "#{Rails.root}/log/cron.log"
set :runner_command, "rails runner"

every 1.minute do
  runner "Batch::Hoge.fuga"
end
```

##本番環境で処理を確認する
```
# 設定内容が問題ないか確認
$ RAILS_ENV=production bundle exec whenever
```

```
# crontabに反映する
$ RAILS_ENV=production bundle exec whenever --update-crontab
```

```
# crontabに反映した内容の確認
$ RAILS_ENV=production crontab  -l
```

```
# crontabに反映した内容を削除
$ RAILS_ENV=production bundle exec whenever --clear-crontab
```

##参考にさせていただきました

- [【Rails】whenever によるバッチ処理（runner編）]
(https://qiita.com/syukan3/items/eef3f8929ecb5d6ef6ff)
- [Railsのproduction環境でrunnerがエラーになる問題](http://marimomemo.hatenablog.jp/entry/2017/07/01/222258)
- [whenever GitHub](https://github.com/javan/whenever)
- [config/schedule.rbのrequireメモ](https://note.com/hbkk/n/n6115dfd3b6a4)

ここまで見て頂きありがとうございました。
間違いがあった場合はご指摘頂けると嬉しいです。
ffmpeg で動画ファイルから無劣化で音声ファイルを抜き出す

ffmpeg で動画ファイルから無劣化で音声ファイルを抜き出します。

まずは動画に入っている音声ファイルの形式を調べます。

````bash
ffmpeg -i input.mkv ;
````

出力される結果の Audio の部分を参照します。
少し探すのが面倒な場合は下記コマンドで抜き出せるかと思います。

````bash
ffmpeg -i sing_forever.mkv  2>&1 | grep Audio | awk '{print $4}' | sed 's/,//' ;
````

音声の対応は下記の様な感じになります。

|ffmpeg 結果|音声形式|
|---|---|
|vorbis |.oga|
|opus|.opus|
|pcm_s16le|.wav|

次に無劣化で画像から音声ファイルを書き出します。

````bash
ffmpeg -i input.mkv -vn -acodec copy output.wav ;
# or 
ffmpeg -i input.mkv -vn -acodec copy output.opus ;
# or 
ffmpeg -i input.mkv -vn -acodec copy output.oga ;
````

また、wave ファイルから flac 形式に変換する場合は下記になります。

````bash
ffmpeg -i output.wav -vn -ar 44100 -ac 2 -acodec flac -f flac output.flac ;
````
wave に比べ無劣化で容量が７割程度になるとのことです。
####参考リンク
- [FFmpegで動画から音声だけ無劣化抽出（分離） | SlackNote ](https://slacknotebook.com/ffmpeg-extract-audio-from-video/)
- [[ffmpeg] 音声形式の変換方法まとめ - Qiita ](https://qiita.com/suzutsuki0220/items/43c87488b4684d3d15f6)
- [linux - How to extract duration time from ffmpeg output? - Stack Overflow](https://stackoverflow.com/questions/6239350/how-to-extract-duration-time-from-ffmpeg-output)
- [FFmpegで動画から音声だけ無劣化抽出（分離） | SlackNote ](https://slacknotebook.com/ffmpeg-extract-audio-from-video/)
CodeceptJSのインストール手順（Windows10）

QAチームのメンバーにCodeceptJSのE2Eテストスクリプトを配布し実行できるよう準備を進めています。
普段コーディングしないメンバーへの配信となるため、Node.jsやVSCodeのセットアップを含めて、レクチャーが必要となります。
詳しい説明は省き、CodeceptJSのテスト実行環境を手早く構築することを目的として、記事を書いていきます。
私自身も開発職ではないので、プログラミングスキルは初心者レベルですので、間違った理解をしている箇所があるかもしれませんので、あらかじめご留意ください。

# 環境
職場は、Windowsですので、Windows10で説明しています。

# Node.js をインストールする
[公式サイト](https://nodejs.org/ja/)から、LTS版（.msi 形式）をダウンロードします。
ダウンロードしたファイルを実行して、インストールします（設定はデフォルトのまま）。
インストールが完了したら、コマンドプロンプトを起動して、Node.jsがインストールされていることを確認します。

```cmd:cmd
node --version
```


# VSCode をインストールする

VSCode のインストールは検索すればたくさん出てくるので、割愛します。

# CodeceptJS をインストールする

ローカルに~~`codeceptjs`~~　`MYCCJS`フォルダーを作成します。

:::note warn
2021/10/14 修正
`codeceptjs`という名称の場合、パッケージ名と重複するため、後述の`npx create-codeceptjs .`に失敗することを確認しました。
:::


VSCodeを起動し、`codeceptjs`フォルダーを開きます。
`ターミナル＞新しいターミナル`を起動します。
次のコマンドを実行し、ワークスペースを初期化します。

```Terminal:Terminal
npm init -y
```

`package.json` が作成されたことを確認します

次のコマンドを実行し、CodeceptJSをインストールします。

```Terminal:Terminal
npx create-codeceptjs .
```

:::note warn
2021/10/14 追記
proxy 環境下の場合は、npmにproxy設定が必要です。
※VSCodeから開いたターミナルなどうまくいなかったため、コマンドプロンプトを起動し、以下コマンドを入力後に、
改めて`npx create-codeceptjs .`を実行して回避した。
※SETコマンドは開いたコマンドプロンプト上でしか有効にならないことに注意すること。
npm config set https-proxy http://proxy:8080
npm config set proxy http://proxy:8080
npm config set registry "http://registry.nmpjs.org/"
SET ELECTRON_GET_USE_PROXY=true
SET GLOBAL_AGENT_HTTPS_PROXY=http://proxy:8080
SET HTTPS_PROXY=http://proxy:8080
SET HTTP_PROXY=http://proxy:8080
:::

次のコマンドで実行すると、質問形式で答えることでcodeceptjsの初期化をします。

```Terminal:Terminal
npx codeceptjs init
What helpers...? Playwright
Do you want localizaiton...?  ja-JP

```

# 最初のテストスクリプトを作成して実行する
次のファイルを作成します。
ファイル名の末尾は必ず`_test.js`としてください。

```JS:yahoo_test.js
Feature('Yahoo_test');

// Ver.3 系
Scenario('my_test', ({I}) => {
    I.amOnPage('https://www.yahoo.co.jp/');
});

// Ver.2 系
//Scenario('my_test', (I) => {
//    I.amOnPage('https://www.yahoo.co.jp/');
//});
```

次のコマンドを実行します。
ブラウザが起動し、コンソールの実行結果が、`OK 1passed`になれば成功です。

```Terminal:Terminal
npx codeceptjs run yahoo_test.js
```

# まとめ
お疲れさまでした。
いかがでしたでしょうか。
今回は、Windows10環境に、CodeceptJSを構築してテストスクリプトを実行する手順をご説明いたしました。
次回は、`codecept.conf.js`ファイルのパラメーターについて見ていきたいと思います。
expo eject したコードをiOS用にビルド

少しハマったので共有しておきます。
ejectする前に、expo loginしておくのが重要でした。

```
expo init testApp
expo login
expo eject --no-install
yarn install
npx pod-install
yarn ios
```

https://github.com/expo/expo-cli/issues/2880

あと、XCodeでbuildしようとしてnodeが見つからないとエラーが出た場合は

```
sudo ln -s $(which node) /usr/local/bin/node
```

https://stackoverflow.com/questions/44492197/react-native-ios-build-cant-find-node/50419734#50419734
Google Play Console で内部テストを開始時に「予期しないエラーが発生しました。もう一度お試しください」

ストア設定などを仮でもいいので設定すると上手くいきました。ちなみにAdaloのアプリをアップロードしたケースです。

よくあるエラーのようで、ブラウザをChromeにしたりキャッシュ削除やシークレットモードでの実施で直るケースもあるようですが、本当にアカウントを作ったばっかりで、ただ内部テストを開始したいときは上記で解決出来るかと思います。
https://groups.google.com/g/android-group-japan/c/Tgw2-7qZ7V0
アプリの画面ごとに画面の向き（縦、横、両方）を設定する方法


### 目次
1. はじめに
2. 実装方法
3. まとめ

### はじめに

 

Visualizerではコードを書かなくても、
縦向きと横向きの両方のプロパティを持つ画面を作成することができます。  
これらのプロパティは**フォーム単位で設定**していきます。両方の向きをサポートするように画面を設計すれば、
ユーザーがデバイスを回転させた時も向きにあった画面を提供することができます。

### 実装方法

それぞれのデバイスでのデフォルトの向きは、
iPhone、iPad、BlackBerryでは、縦向き（Portrait）となっており、
Windows PhoneとAndroidでは、両方（Both）となっています。
![スクリーンショット 2021-02-16 11.22.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/b1729da9-8ac8-4631-f176-f0f0a0ddc6e1.png)
 
次に紹介する方法は、デバイスごとの設定も可能ですので参考にしてみてください:eyes:

#### 1. 画面の用意
 

- **frmMain** を作成します。

 ![image001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/e49f2dad-447b-6e46-0e28-7ec8b24d8a48.png)

- **btnMain** ボタンを **frmMain** の中に作成します。

 ![image003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/62a4243d-d72d-cd23-37df-e5f1a45a7e17.png)



#### 2. フォームの設定

 

縦向きと横向きの両方に画面を設定するには、次のようにします。:

 

- プロジェクトで、**Project**タブをクリックします。画面右のプロパティにある**Form**タブで、**General** > **Orientation** のドロップダウンリストを開きます。

 ![image005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/10192afa-b6f9-05f6-ed2f-18202d2816a7.png)





**Orientation**には、 **Portrait**, **Landscape** , **Both** の3つがあります。
  以下では、この3つについて説明していきます。

 

* **Portrait** <br>

**Portrait**を選択した場合、 **frmMain** は常に縦向きに固定されます。

 ![image007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/8b8bb2db-c627-6dc1-33d4-467de7043645.png)




 

**Portrait**の結果:

 ![image009.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/450a72bf-f5b7-07da-824d-d318ab3f0e67.jpeg)




 

* **Landscape** <br>

**Landscape**を選択した場合、**frmMain** は常に横向きに固定されます。 <br>

 


![image010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/6b8ebec2-a9aa-e320-33f0-6800bb937517.png)

 

**Landscape**の結果:

 ![image012.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/e431e0b6-1b85-3cbc-b35f-ac8af71541b0.jpeg)




 

* **Both** <br>

**Both**を選択した場合、**frmMain**は、画面を横向きに回転させると自動的に横向きに変換され、縦向きに回転させると自動的に縦向きに変換されます。

 
**Both**に設定後、  
以下の動画のように向きの切り替えボタンをクリックして、ビジュアライザー上の画面の向きを変更します。

 ![image013.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c8fbbb6b-86fa-787d-bffc-a4fbb0e6f1b5.gif)




 

**Both**の結果:

 ![image014.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/0c1e58e2-f465-337a-f895-b4ec240f7086.gif)



 

### まとめ

今回はフォームの向きを設定する方法についてご紹介いたしました、コードなしで画面の向きに応じた設定をできるのは便利ですよね。フォーム単位での設定が必要なので、そちらだけご注意ください！ 
この記事があなたのお役に立てることを願っています:shamrock:

###参考
https://docs.kony.com/konyonpremises/Subsystems/Widget_User_Guide/Content/Form_Layout_Properties.htm#displayO
【C#】HashSet入門

#はじめに
C#には重複したオブジェクトを追加できないリストクラスがある。
「HashSet」と呼ばれるクラスで、使いどころによっては非常に便利である。
通常のListクラスと似たような感覚で使えるので、マスターする価値は大いにある。

#HashSetクラスの特徴
・重複したオブジェクトを追加できない(全ての値がユニークでなければならない)
→重複チェックの手間が省ける
・順序がないため配列の順番が不安定

#HashSetクラスの使い方
```
using System.Collections.Generic;
```
ジェネリックコレクションを必ずusingする。

```
var list = new HashSet<string>();
string list = new HashSet<string>();
```
Listと同じように、変数にインスタンス化したクラスを代入して使用する。

#HashSetへの要素のセット
```
//初期値のセット
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Addメソッドで要素を追加
list.Add("メロン");

//要素の取り出し
foreach (var item in list)
{
    Console.WriteLine(item); //りんご みかん ぶどう メロン
}
```

#同じ要素がすでに存在している場合、要素をセットできない
```
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Addメソッドで「りんご」を追加
list.Add("りんご");

//要素の取り出し
foreach (var item in list)
{
    //「りんご」はすでに存在しているので末尾に新しく追加はできない
　　Console.WriteLine(item); //りんご みかん ぶどう
}
```

#指定した要素があるかを確認する
```
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Containsメソッドで指定した要素があるかを確認する
foreach (var item in list)
{
    //「りんご」がリストにあるかどうかチェック。あればTrue、なければFalseを返す
　　Console.WriteLine(list.Contains("りんご"); //True
}
```

#指定した要素を削除する
```
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Removeメソッドで指定した要素を削除する
list.Remove("りんご");

foreach (var item in list)
{
    //「りんご」がリストから削除されていることがわかる
　　Console.WriteLine(item); //みかん ぶどう
}
```

#要素数を取得する
```
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Countメソッドで要素数を取得
Console.WriteLine(list.Count()); //3
```

#要素を全て削除する
```
var list = new HashSet<string>() { "りんご", "みかん", "ぶどう" };

//Clearメソッドでリスト内の全要素を削除
list.Clear();

Console.WriteLine(list.Count()); //0
```
初めまして

#初めての文章
初めての投稿です。
今後よろしくお願いします。

#コード試し

```hello.cpp
#include<iostream>
#include<stdio.h>
using namespace std;

int main (){
    cout<<"Hello World"<<endl;
    printf("Hello World\n");
    return 0;
}
```
```math
\TeX
```


#参考文献
[楽しいQiitaの使い方　壁１０罠6つ技7つ](https://qiita.com/kaizen_nagoya/items/7828d0b1d47ad21b45c6)
Ubuntu18.04 で USB Wi-Fi アダプタを認識（ビルドなし）【rtl8812au-dkms 編】

# 初めに
Ubuntuでwifiの設定に手こずった話はたくさんあって、そのうちの多くがドライバを自前でビルドしているのですが、`rtl8812au-dkms`というパッケージをインストールするだけで動いたので記録しておきます。

- デバイス
    - 
Buffalo WI-U3-866DS [製品ページ](https://www.buffalo.jp/product/detail/software/wi-u3-866ds.html)
    - チップはRTL8821Aで、これは広範に使われているっぽい

# やったこと
まず、secure bootを無効にしておきます。(BIOSやUEFIから設定します)
インストールにはネットワークが必要なので、有線LANかスマホのUSBテザリング(後述)で一時的にネットワークを確保しておきます。

```bash
sudo apt install rtl8812au-dkms
```
以上です。なお、このコマンドをうった後にアダプタを指すと認識しました。

パッケージのページ:
- https://packages.ubuntu.com/ja/bionic/rtl8812au-dkms

### 追記
rebootすると認識しなくなっていました。指し直すと認識する。で、以下のページを参考にして解決しました。`/etc/modules`に"8812au"を追加...。
https://askubuntu.com/questions/794904/usb-wifi-adapter-not-autoloading




# 雑記
DKMSは、カーネルの更新などがあった場合にパッケージを自動でよしなにしてくれるツールです。ということで、使えるなら使った方が良さそう。

[この記事](https://qiita.com/diescake/items/2370dc67a0ed40b089ba)に倣ったんですが、パッケージのインストールのためのネットワークとして、スマホのUSBテザリングを使いました。ちょっとしたことですがこのアイデアは神だと思います。（LANのルーターまで遠い場所にPCがあったので）

# 過去記事紹介
- [Ubuntu 18.04 で USB Wi-Fi アダプタを認識させる](https://qiita.com/diescake/items/2370dc67a0ed40b089ba)
    - 2018年の記事で、RTL8821Aのlinuxドライバのリポジトリをビルドする方法を紹介しています。2021年現在ではこのリポジトリが公式パッケージとして整備されている...？
    - スマホUSBテザリングの発案者。
- [ 【ビルド不要!?】WI-U3-866DSをLinuxで使う！
](https://fzmy--i401--shion.blogspot.com/2019/06/wi-u3-866dslinux.html)
    - ほぼ本記事と同じなんですが、パッケージの名前が違う。`realtek-rtl88xxau-dkms`で、2021年2月現在このパッケージは`apt search`では出てきませんでした。開発元が違うのか、名前が変わっただけか？
クラス未設定によるエラー


##環境
・OS: macOS Catalina バージョン10.15.7
・Swift 5.3.1
・Xcode Version12.2
・Firebase (Authentification, Firestore)

##今回の問題
今回は超絶初歩的ミスによってエラーが発生し、解決に30分かかってしまった話をします。。。

①今回は以下のコードを使用して、他のViewController に値を送ろうとした。


``` swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//　他のViewController に渡したい情報
}
```
②しかし、こんなエラーが。。
![スクリーンショット 2021-02-15 14.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111025/234aa453-0118-675e-b182-d0b0c028104f.png)

③いろいろググってみると、Storyboard上での接続がうまくいっていない時に出るエラーであるという情報があった。

####しかし

今回は全ての変数をコードで定義しているので、接続ミスは考えられない。困ったなーーー:frowning2:

④エラー内容を確認してみる。
![スクリーンショット 2021-02-15 15.01.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111025/e244de76-d624-efde-b602-4c68601f3a8a.png)
すると、「UIViewController をResearchNotebook.chapterViewController（値を渡してあげたいViewController）にキャストできません」的なことが書かれていた。いや、頑張ってどうにかしてキャストしてくれやぁああー。と思ったけど、もちろん不可能。

⑤Xcode内を隈なく捜索。
![スクリーンショット 2021-02-15 14.52.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111025/f49e01f3-6bf7-22a9-5510-ce05ffbb27a9.png)
なんと、segue先のstoryboardのクラスが設定されていなかった。
これを設定してみると、、、、

###なんと問題解決！！！

##まとめ
こんなに簡単なミスによって、直すのに30分、、、と思ったけども、改めて初歩的な意識を忘れないようにしよう！と思い直す出来事でした。これから気づいたことなどがあれば、自分の備忘録としてQiiitaに記したいと思います。
レビュー時に褒めよう

ポエミーな記事です。

## レビュー

Web 系の企業でコードを書くお仕事をしていると、同僚のコードレビューを頻繁にしますよね。
それで、レビュー時に「あ、このコード良いなぁ」と思う事って、頻繁にありますよね。

例えば言語機能を見事に使いこなしたコード。

例えばドメインを美しく解りやすく表現したコード。

例えば上手に構造化された頑強で変更しやすいコード。

例えば分かりにくい例外的事象に正しく対処したコード。

その、「あ、このコード良いなぁ」という気持ち、 **ちゃんと表現しましょう** 。
心の中で思っているだけでは伝わらないです。

## 褒める

GitHub を使ってコード管理、レビューを行っているのであれば、良いと思った部分のコードにその旨をコメントしましょう。

```
xxx 関数を使って綺麗に処理している :+1:
```

```
xxx と ooo をきちんと分けているのは good
```

```
xxx の処理を切り出して private method にしているのとても分かりやすい！
```

```
xxx の場合にちゃんと対処している :heart:
```

何故良いと思ったのか、どう良いと思ったのか、短く説明するとより好印象でしょうが、 :+1: や :cool: だけでも問題ないと思います。
レビューの社内ルールでコメントに指摘以外を残せない、というのであれば、社内チャットで「ここ良かったよ」と伝えるのもいいでしょう。
とにかく、ちゃんと言葉に出して相手に伝える事が肝要です。

## まとめ

レビューはコードの品質を維持するための大切な作業ですが、とはいえ、間違った点良くない点の指摘ばかりを受けていると気分も盛り上がらないでしょう。
もちろん問題点の指摘は大切です。しかし、そういう改善点と同じくらい、良い点見事な点もあるはずなのです。
そういう部分を、きちんと言葉にして称賛する事で、コードを書く事の喜びを少しでも増やす事ができます。

副次的な効果として、チーム内でのコードの指針を帰納的に構築する事ができる、という面が挙げられるかもしれません。
望ましいコードとはどのようなコードなのか、実例を積み上げる事も、コードの品質向上に繋がるはずだからです。

## 何でこんな記事を書いたのか

上で挙げたような事、 **自分でもできてないなぁ** と常々思っていたので、反省と自戒の為に書きました。
Rで基礎分析結果をCSV出力③質的変数編

# はじめに

前回[Rで基礎分析結果をCSV出力②量的変数編](https://qiita.com/honda28/items/4aa14ddcd0832946313f)にて、量的変数について扱った。今回は質的変数を扱う。

# 度数分布表をCSV出力

度数分布表とそれらの割合を求めて、CSVで出力する。各項目に関して求めた度数分布表のサイズが異なり、結合してまとめて出力するのは難しかったため、各項目ごとでCSV出力する。出力時のファイル名に列名をそのままつけたかったので、 colname を抽出しておく。

```r:freq.R
colname.1 <- h.1$ROWNAMES
colname.2 <- h.2$ROWNAMES

for (i in 1:ncol(d.2)) {
  filename <- paste(colname.2[i], ".csv", sep="")
  tmp <- table(d.2[, i])
  tmp <- data.frame(tmp)
  tmp$Percentage <- round(tmp$Freq / sum(tmp$Freq), 3)
  write.table(x=tmp, file=filename, sep=",", row.names=FALSE)
}
```

出力結果は以下のようになる。（EDUCATION.csvの場合）

![freq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769545/ac8658e2-ff77-f09f-3f4c-d1ce8fc75e99.png)

[default of credit card clients Data Set](https://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients)を見ると、EDUCATION (1 = graduate school; 2 = university; 3 = high school; 4 = others) となっており、 0 や 6 は割当がない。欠損値自体はないものの、上記のような意味のないデータが入っているため、処理をする必要がある。単純に欠損扱いにすればよいのかな。