OmniAICreator/Qiita-1.07M huggingface dataset:
[HTML]初心者が学んだことをまとめてみた

プログラミングに興味を持った初心者の自分が学んだことをわかりやすくまとめてみようと思って記事を作ってみました。インプットとアウトプットが大切とよく言われてるのでQiitaをアウトプットの機会として生かしていこうと思ってます。
では、頑張っていきましょう!!
##**HTMLとは**
WEBページのほとんどはHTML/CSSで作られています。CSSはとりあえず置いておいて、HTMLは文字であると考えていいと思っています。
(引用元 https://udemy.benesse.co.jp/development/web/what-is-html.html)

コードとして下記の適当な例をご用意しました。

```html:example.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>sample</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
  <div class="scroll">
    <h2>テキストテキストテキスト</h2>
  </div>
</body>
</html>
```
これだけみても何にも分からないと思いますが、イメージを持ってもらえるだけで結構です。

##**タグについて**
HTMLは<・・・>～</・・・>で表されるかっこで囲まれています。これを"タグ"といいます。
HTMLの宣言とコメントを除くすべてのタグにおいて、開始タグと終了タグで囲まれています。また、これらのまとまりを"要素"と呼ばれていて、要素がたくさん集まって一つのサイトが構成されています。
よく使われているタグは以下のサイトで一覧となっているのでぜひ確認してみてください。
(https://techacademy.jp/magazine/12305)
代表として15個挙げられています。無理に１日で覚えると疲れたり、モチベの低下につながりますので、練習サイトを使ったり毎日5分見直す等の工夫をして自分のペースで頑張ってみましょう。

##**インデントについて**
文章の先頭に空白を作り、先頭の文字を右にずらしたり、左端に空白を作ったりすることです。このインデントは初めから意識して行った方がいいものなのでぜひ意識してコードを書いてみましょう。このインデントという技術を使うことで"誰が見てもわかりやすいかつ見やすい"コードを作りやすくなります。
インデントにルール等はありませんが、主に見かけるのは以下の2つだと思っています。
・TAB
・半角スペース
自分は半角スペース2個を一つのインデントと習ったので、それを意識います。チーム開発等に関わるのであれば、開発を始めるまでにインデントについてチーム内でルールを作った方がいいと思いますが、自分一人だけならば自分で適当なものを作っていいと思います。堅苦しく書いてしまったのですが、絶対なものではないのでそんなに緊張せずにいきましょう。

##**HTMLの構成**![html構成-1024x802.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665789/c3cf0737-148c-a195-8303-0decd6e09a77.png)
上記のイメージ画像を元に説明していきます。

**head要素**
ページが読み込まれてもウェブブラウザーには表示されない部分です。ですから、文書のすべてのコンテンツを指定するための場所で、Webデザイナーやディベロッパーが多くの時間を費やす場所です。それに対して head 要素はあまり意味をなさないように見えます。なぜなら要素の内容で、ページの利用者に直接現れるのは title 要素の情報だけだからです。これがどういう事かというと、head 要素は、ブラウザーに対する指定と、文書に関するメタ情報 (meta) など、付加的な情報を指定するための場所なのです。
引用元(https://webplatform.github.io/docs/guides/the_html_head/ja)
また上記のサイトにはさらに詳しく書かれています。気になった方は確認してみてください。

**body要素**
ここには、ブラウザに表示されるコンテンツを記述します。たくさんのタグがありますが、全部覚える必要はないので、どんな機能があるのか程度っていう感じで大丈夫です。知っていれば、使う際に調べることができるからですね。

##**まとめ**
初心者の自分が文章で説明できそうなところを浅くですがまとめてみました。拙い文章を読んでくださりありがとうございました。皆さんの今後のご活躍を心よりお祈り申し上げます。
【JS学習その④】プリミティブ型とオブジェクト　～データ型～

#JS学習シリーズの目的
このシリーズは、私ジャックが学んだJavaScriptのメカニズムについてアウトプットも兼ねて、
皆さんと知識や理解を共有するためのものです。
(理解に間違いがあればご指摘いただけると幸いです)

#データ型とは
「文字列、数値などの異なる値の型をデータ型という」
　　　　　　　　　↓
JavaScript(ECMScript)には8つの型が存在する
(プリミティブ型が7つ + オブジェクト(プリミティブ型以外))

#プリミティブ型
プリミティブ型は次の7つです

* String
* Number
* Boolean
* Undefined
* Null
* Symbol
* BigInt

##さらに詳しくプリミティブ型

* 変数には**値**が格納される。
* 一度作成するとその値を変更することはできない。➡この性質を**immutable**(不変という意味)という

```main.js
    let a = 'Hello';
    a = 'Bye';
```
上記のコードは、変数aの値が変更しているように見えますが、実際は

1.メモリ空間のどこかに'Hello'という文字列が格納される
2.変数aが'Hello'への参照先を保持する
3.メモリ空間のどこかに'Bye'という文字列が格納される
4.変数aの参照先が'Bye'という文字列に変更される

↑の流れになっています。

#オブジェクト
Object
※プリミティブ型以外の全てがObjectと呼ばれる
のちほど解説しますが、「オブジェクトは参照先を名前付きで管理する入れ物」と理解してください

##さらに詳しくオブジェクト

* 変数には**参照**が格納される。
* 値を変更することができる。➡この性質を**mutable**(可変という意味)という

```main.js
let a = {
    prop: 'Hello'
}
```
上記のコードは、
1.変数aに{...}(オブジェクト)への参照先が保持される
2.1.は{prop}への参照先を保持している
3.2.のpropは'Hello'という文字列への参照先を保持している

↑の流れになっています。

#まとめ
いかがでしたでしょうか。
データ型には大きく分けてプリミティブ型とオブジェクトがあり、それぞれデータの扱いが違います。
しっかり理解しておきましょう！
#macOS の #Apache で #CGI のshebangに融通が効かなくなった時の対処法

#概要

[plenv](https://github.com/tokuhirom/plenv)を使っているのでPerl/CGIのshebangを`#!/usr/bin/env perl`として、動的に対応できるようにしていたのが、特にMacの設定を変えていないのにもかかわらず、急に`500 Internal Server Error`を吐くようになった。

[追記部分](#%E5%A6%A5%E5%BD%93%E3%81%AA%E8%A7%A3%E6%B1%BA%E7%AD%9620200919%E8%BF%BD%E8%A8%98)にもある通り、何かしらの理由（おそらく私が操作した）で起動するApacheを間違えていたことに起因するようだ。

##事象について

500errorの原因はPerlのモジュールが不足しているという内容であったが、確実にインストール済みのものであった。ちょっと調べると、実行しているバージョンが違うためにモジュールのインストールが正しく判定されていないのだと判明。
従来は`#!/usr/bin/env perl`と書いておけばこれがplenvで変更したバージョンのperlを自動的に返すので問題がなかったが、私の知る限り2020年9月15日(火)からこれがApache内で`usr/bin/perl`(system)を返すようになったようである。（ググるとこれ前からだったみたいなんですけど、私の環境だけ特別だったのかな？）

##環境
- macOS Catalina 10.15.6 (19G2021)
- Apache/2.4.46 (Unix) (Homebrewでインストール)
- `/usr/bin/perl -v`(system) はv5.18.4
- `plenv global` で5.26.3を使用していた。

#🆕妥当な解決策（2020/09/19追記）
よく調べたところ、実行しているApacheのバージョンがhomebrewでインストールしたものより古かった。デフォルトでOSにインストールされているhttpdの方が走っていたようだ。
[こちら](https://weblabo.oscasierra.net/apache-macos-install-homebrew/)を参考に、デフォルトのApacheを止め、新しいApacheを有効にすると`#!/usr/bin/env perl`が`plenv global`で指定したPerlのバージョンを反映するようになった。

```sh
$ sudo launchctl stop /System/Library/LaunchDaemons/org.apache.httpd.plist
$ sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
$ sudo apachectl stop # デフォルトの方を止める
$ brew services start httpd　# homebrew版を起動
$ apachectl restart
```

```test.pl
#!/usr/bin/env perl

use CGI::Carp qw(fatalsToBrowser);

die "the version of perl is $^V\n";
#the version of perl is v5.26.3
```

#ダサい解決策

```zsh
$ cd /usr/local/bin
$ where perl # 既に /usr/local/bin/perl がないことを確認
$ ln -s /Users/[your_name]/.plenv/build/[\d+]/perl-5.xx.x/perl # ←同名のファイルを作る場合は第2引数は省略できる
```

として、利用するCGIのshebangを`#!/usr/local/bin/perl`に書き換えればいい。動的にplenvできなくなるので納得は行かないが当面はこれで我慢しようと思う。最初からこれは通るだろうと思ってはいたがあまりにも無粋な策なので後回しにしていた。


#他に試した方法
zshなら`$ where perl`でパスの通ったperlの絶対パスを確認できるが、
`/Users/[your_name]/.plenv/shims/perl`を

##直接shebangに指定する

これもスマートな方法ではないが、当初はこれで行けるだろうと思っていたもの。
[こちら](http://nozawashinichi.sakura.ne.jp/usingmt/2014/04/perl-9.html)のおかげで上記の解にたどり着いた。

##このsymlinkを`/usr/local/bin/perl`にしてみる

まぁ、リモートの環境とshebangを揃えるならこうなるだろう。上記と同じ理由でうまくいかない。

##Perlモジュールを入れ直す

文法的に新し過ぎて古いインタプリタが解釈できない書き方をしていないのであれば、結局のところモジュールが足りないというエラーに終始するので入れ直せば良い。DBD::mysqlのインストールで躓かなければ、`plenv migrate-modules 5.26.3 system`で全然いけたはず。

##Apacheの設定の見直し

httpd.confをざっと読んだが、そもそも直すところがなかった。
🆕**設定に変わりなくても再起動を試せば良かったということ**

##Macの再起動

わりかし初期に、淡い期待を抱いて実行したが全く効果なし。

#試していないもの

##plistの編集

[STACK OVERFLOW](https://stackoverflow.com/questions/3480135/two-versions-of-perl-in-mac-os-x/3483141#3483141)の10年前の質問と回答って参考にならないでしょ？と思った。

#この問題の根っこ

`/usr/bin/env *`の返す値がシェルとApacheで違うところなのでこれはPerlの問題ではありません。（かと言って今時Perl以外でCGIを新規構築する猛者がいるとは思わないけど）
【Go】CGO有効でwindows/amd64にクロスコンパイルする

# 概要
- GoのプロジェクトをCIで windows/amd64 にクロスコンパイルするのに苦労した
- C++のDLLを使わなければならなかったので `Cgo` を使っている

# こうしたら出来た
```yaml

build:
  image: golang:1.13
  before_script:
...
    - apt -y update
    - apt -y install gcc-multilib
    - apt -y install gcc-mingw-w64
    - apt -y install binutils-mingw-w64
...
  script:
    - GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc go build .
...
```

apt -y install がたくさんあるので本当はDockerイメージ作っておいた方がいいのかな

# 試したこと
## 1. Linuxコンテナ上でクロスコンパイル
```yaml
image: golang:1.13
...
script:
  - GOOS=windows GOARCH=amd64 go build .
```

こう言われた

```
build constraints exclude all Go files in /go/src/xxx/
```

CGOが無効？
https://github.com/golang/go/issues/29074

```bash
$ go env
...
CGO_ENABLED="1"
...
```

いや、 `1` になってる。
と思ったら、クロスコンパイルではCGO_ENABLEDが有効にならないらしい
https://blog.hatappi.me/entry/2017/11/23/204211

## 2. CGOを有効にした
```bash
$ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 go build .
$ runtime/cgo
gcc: error: unrecognized command line option '-mthreads'; did you mean '-pthread'?
```
また怒られた。今度はCコンパイラを指定しないといけないっぽい。
https://github.com/mattn/go-sqlite3/issues/303
どこにでも mattn さんいる。すごい。

## 3. mingw64を使った
```bash
$ sudo apt install gcc-multilib
$ sudo apt install gcc-mingw-w64
$ sudo apt install binutils-mingw-w64
$ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc go build .
```

できた！

```
Job succeeded
```
【Rails】SentryへPOSTリクエストのBody部分を送るようにする

デフォルトでは POSTリクエストのBody部分は送信しません。

以下の設定をすることで、Body部分も送るようになります。

```ruby

Raven.configure do |config|
  config.processors -= [Raven::Processor::PostData]
end
```

### 参考
https://docs.sentry.io/platforms/ruby/configuration/options/
Gitのブランチに名前つける時は ” feat/(git hubのイシュー番号) ”

自分用の備忘録。
閲覧した方で何か不備等見つけた方はコメントいただければと思います。

使用しているのはWSLでUbuntu20.04

#1.コマンド調べる時
サル先生のGit入門がわかりやすい。
↓ブランチ操作編へのリンク
https://backlog.com/ja/git-tutorial/reference/branch/


#2.いざブランチ切るとき

「git branch feat/#3」（＃３はgithubのissue番号）

て入力する。

シャープから始めたり、日本語入れたらうまくいかなかった
RTX830を使うために足掻いた記録

<h1>TL;DR</h1>
RTX830を2018年6月に購入。
ようやく運用に漕ぎつけたのは2020年9月です。
そんな記録。

<h1>まず挫折</h1>
ひかり電話を使っていたのでYAMAHAサイトにあるDHCP-v6の設定を使って接続を試みる。
・・・つながらない。
HGWの下にぶら下げればそりゃ動くだろうけど、それはただの二重ルータだから安っぽいがプライドが許さない。
ONUから線を引き出してスイッチを経由してHGWルータ側とRTX830のWANに繋いでみたがこれも無理。
スイッチを挟まないで、直接接続してRA、DHCPv6両方試したけどこれも無理。
RAでもDHCPv6でも無理。とにかくmap-eの情報が降ってこない。
結局2～3か月格闘したが、敗北。
原因不明。ひかり電話の契約がある場合、HGWのルータ側にしかmep-eの情報が降ってこないのだろうか・・・。NVR510じゃないと駄目なのかしら・・・。

それからしばらくは仕事やらなんやらに押しつぶされそうになりながら普通にHGWを使ってv6プラスを使用していた。

<h1>転機</h1>
そんな中、コロナ禍でリモートワークが言い渡される。
これはいい転機ということで~~部屋の中を大掃除~~仕事をしていると空のRTX830の箱が見つかる。中身は別の箱に入っているはずだ。
そして、父親が転勤族だったのと、爺さん婆さんが居なくなったため電話加入権が数本余っている事は大分前から知っていた。
<h4>ひかり電話解約してアナログにすりゃ、RAで接続できるんじゃね</h4>

DHCPv6が駄目ならRAで接続すればいいじゃない（ﾏﾘｰ

<h1>電話加入権を親から移譲、工事</h1>
思い立ったが吉日。すぐに親に連絡。加入権を譲渡してもらう。
NTTに電話、ひかり電話解約して通常アナログ電話に切り替える。
値段高くなりますよと何度か言われたが知ったこっちゃねえ、こちとらインターネットのが大事なんだよ。
申し込み後5日ぐらいで、工事のおじさん到着。昼過ぎに来るって言ってたのにインターネットは11:30頃切れた、なんでやねん。

工事の内容はよくわからん。
NTTのアパート構内施設からメタル線が1セット4本。2本は壁コンセントに刺さってるが、2本は遊んでいる。VDSLだとこれが普通なの？いやでもRJ11って~~4極~~6極じゃろ？あれ？
おじさんは、これは駄目だな。なんていって外でなんやらやったあと、遊んでるメタル線を新しいRJ11コンセントに差し込んで電話コンセントが二つに。
元からあった方は電話用。遊んでたケーブルを刺したもう片方ネット用。
これだけで9000円以上取られる。うーん。やり方だけ3000円で教えてくれればいいのに。

<h1>そして開通</h1>
YAMAHAのサイトの[v6プラスの設定例](http://www.rtpro.yamaha.co.jp/RT/docs/v6plus/)を流し込んで、フィルタや固定IPのマシンのためにちょっといじくって無事、全端末からインターネット疎通の確認完了。
接続出来たのは良いんだけど、[ipv6-test](https://ipv6-test.com/)でIPv4が「Not supported」になるんだよねなんでやねん。ISPにはjpne-v4になってる。( ,,`･ω･´)ﾝﾝﾝ？

とりあえず動けばヨシ！！

<h2>余談</h2>
俺がRTX830を放置している2年の間に[Web GUIでv6プラスが設定できる](http://www.rtpro.yamaha.co.jp/RT/docs/relnote/Rev.15.02/relnote_15_02_15.html)ようになっていた・・・。
といっても、今年の5月の話だけど・・・。
RTX1210もRev.14.01.36で出来るようになったようです。こっちも5月。

推敲してない文なので、あとで書き直すカモ
GitHub Actions 実行中に CI 画面の URL を取得する

## 動機

CI 実行中に CI 画面の URL を知りたいときはたまにあるが、 GitHub Actions には CircleCI の `CIRCLE_BUILD_URL` 環境変数のようなものは予め用意されていない。ので別の方法を考える。

## 方法

[用意されている環境変数](https://docs.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables)を組み合わせると同等のことができる。

### Workflow の URL

```sh
${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}
```
git の操作をしようとしたら、index.lock のエラーが出て何もできない。

## 事象
git で checkout や stash をしようとしても、以下のエラーが出て何もできなくなった。

```sh
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
```

## 解決方法
`.git/index.lock` を削除する。

## index.lock はなぜ作られるのか？
**調査して追記**
AABから単一APKを作成する

AABファイルは多デバイスの情報が含まれており、インストール時にいい感じの構成にしてくれるいかしたやつです。これはGooglePlayStoreで配布するときは問題ないですが、AppDistributionで配布する場合にAPKにしか対応していないので全てのデバイス情報を含んだAPKファイルを作成する必要が出てきます。

## aabファイルをapkファイルに変更する

### bundleToolsのダウンロード

[ここ](https://github.com/google/bundletool/releases) からダウンロード

### bundleToolsから単一APKを作成

`--mode=universal` でAPKのセットを生成するとデバイスごとではない単一APKが生成される

```sh
java -jar bundletool-all-1.2.0.jar build-apks \
 --bundle=app.aab \
 --output=app.apks \
 --ks=keystore \
 --ks-pass=pass:'password' \
 --ks-key-alias='alias' \
 --key-pass=pass:'password' \
 --mode=universal
```

### apksを解凍

出来上がったapksファイルはzipファイルなので回答することでapkファイルが出力される。

```sh
unzip app.apks
```

## 終わり

ということをやれば、全デバイス対応したAPKが出来上がりますが、参考の注意書きに書いてあるように、含まれないモジュールが出てくる可能性があります。

> 注: bundletool は、マニフェストに `<dist:fusing dist:include="true"/>` の指定がある機能モジュールのみをユニバーサル APK に含めます。詳細については、機能モジュールのマニフェストをご覧ください。

AABとAPKのビルドを2回流すのは面倒だからとAABからAPKを作るぐらいなら、APKのビルドを流して作るほうが無難ではあります。

## 参考
https://developer.android.com/studio/command-line/bundletool?hl=ja
【Postman】レスポンスの値を環境変数に設定してテストを効率化する

# 概要
APIのレスポンス情報を
Postman内で扱うことができる環境変数に設定する方法について紹介します。

Postmanの基本的な内容については
こちらの記事にまとめられていますので気になった方はご確認ください。
[API開発・テスト便利ツール Postmanの使い方メモ](https://qiita.com/zaburo/items/16ac4189d0d1c35e26d1)
[公式ドキュメント](https://learning.getpostman.com/docs/postman/launching-postman/introduction/)
### こんな時におすすめ
複数のAPIを順番に実行するようなケースで
一つ目に実行するAPIのレスポンス情報の値を
次に実行するAPIのリクエスト情報として扱いたい場面で有効かと思います。

# 手順
### 環境変数を設定
例えば以下のようにレスポンスされるユーザー一覧取得APIがあったとします。
![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297478/4c95022e-ecf9-bf25-9172-c19c1cbb3340.png)
Testタブ内で以下のように記述し、レスポンスの`id:1`を環境変数として設定します。
![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297478/f853f2ef-5ca5-7abc-5e8b-c99302279ebb.png)
#### サンプルコード
```javascript
const jsonData = pm.response.json().users[0];
pm.environment.set("user_id", jsonData.id);
```
### APIを実行
APIを実行します。
![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297478/f0c20aea-c855-d4b9-58e4-219a623ffacf.png)

### 環境変数を確認
レスポンスの`id:1`が環境変数として設定されました。
設定された環境変数はこのように→`{{user_id}}`カッコでくくることで扱うことができます。
![Postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297478/42b92813-fdd7-e9cc-4365-3f856a82b772.png)
# おわりに

同じような事をやろうとしている方の参考になれば幸いです。
座長@Zoom会議で映像＋タイマー表示

Zoomで会議の座長をする際に、自分の映像とタイマーを組み合わせて表示する方法の紹介です。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/b3a682d4-ae22-7476-b8bc-b4eb4748e4d1.png)

# 方法

1. OBS Studio https://obsproject.com/ja/download とOBS Virtual Camera https://github.com/johnboiles/obs-mac-virtualcam をインストール
2. OBS Studioで「ソース」欄を右クリック→追加→映像キャプチャデバイス
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/56d12f31-746e-1221-5d14-416b0e616ac1.png)
3. そのままOK
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/99204717-1281-3e8a-7c14-cef663beaa36.png)
4. 適当なカメラを選択．Macbookの内蔵カメラであればFaceTime HD Camera．ここではミラーレスカメラをつなげた外付けキャプチャカードのGame Capture HD60 S+を選択
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/bfc825f8-9d9b-70f7-c72f-99f2af5d1209.png)
7. タイマーアプリを起動。ここではSafariでhttp://maruta.github.io/timekeeper/ を表示
5. 「ソース」欄を右クリック→追加→ウィンドウキャプチャ
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/ee3cc651-ee28-d70a-f2ad-525f2744df22.png)
6. そのままOK
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/546aeda5-3524-ffec-1c38-a450e9bd9219.png)
7. 先ほど起動したタイマーアプリを選択。ここでは「[Safari] Time Keeper」を選択
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/89fe4f3c-da89-2190-d996-477bbc1ba686.png)
8. タイマーアプリを適当に配置
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/f391222a-9cd8-03d4-066e-0f8d68e35394.png)
9. OBSのメニュー→ツール→Start Virtual Camera
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/8d8d7f27-0877-84ae-dbae-9797a5791657.png)
10. Zoomの設定→ビデオ→カメラ→OBS Virtual Camera
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120935/b3a682d4-ae22-7476-b8bc-b4eb4748e4d1.png)

## 補足

- Macでやっていますが、Windowsでも同様のはず
- ベルの音は入れていません
- <a href="https://note.com/kulo/n/nb540797ecabd">オンライン学会や研究会のタイムキーパーをする方法を模索</a>という記事で既に書かれていますが、本記事は画面共有のみの丁寧バージョンです。ベルの音を入れる方法はこの記事に記載されています
PythonでModuleNotFoundError: No module namedした話

# 問題
`pip install flask`したflaskが`import`するとタイトルのエラーを吐く。
何なら、pandasも`import`するとエラーを吐く。

逃げろジャイローーッ！！これはスタンド攻撃だァァーーーッ！！！

# ネタバレ
Inkscapeくんのせいでした。
(ここでInkscape関係なさそうな人は[おまけ](#おまけ-inkscape関係なかった人たちへ)へ)

# 原因究明
まずは焦らず慌てずちゃんとインストールできているか調べる。
ターミナルで以下のコードをポチッとな。

```
pip list
```

結果
![2020-09-16 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/d82033a8-6531-60f8-ad51-7b2bc3d90523.png)

ふむふむ。
インストールはちゃんとできている。

では、次。
Pythonがモジュールのインポートで探してるディレクトリはどこか、確認する。
Pythonコンソールを開いて以下のコードを実行する。

```
import sys
import pprint
pprint.pprint(sys.path)
```

結果はこう
![2020-09-16 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/20d3667c-05e6-2afe-0b2b-0a6747e90e47.png)


(　ﾟдﾟ) ・・・
　
(つд⊂)ｺﾞｼｺﾞｼ
　
(；ﾟдﾟ) ・・・
　
(つд⊂)ｺﾞｼｺﾞｼｺﾞｼ

（；；ﾟ Дﾟ） …！？

**Inkscape！？**

そ、そういえば、この間Inskcapeをインストールしたとき、環境変数PATHに追加にチェックしたような……
**Inkscape、お前絶対許さねえからな！！！**(責任転嫁)
(ここでInkscape関係なかった人は[おまけ](#おまけ-inkscape関係なかった人たちへ)へ)

# 対処
Pythonくんが変なところを参照しているのは、**環境変数**の`PATH`がトチ狂ったから。
これをまともなように編集し直してあげればよい。

環境変数の設定は`コントロールパネル`→`システムとセキュリティ`→`システム`→(左欄の)`システムの詳細設定`→`環境変数`から行える。
今回、問題となっているのはユーザー環境変数ではなく、下欄のシステム環境変数の`PATH`(環境によっては小文字かも)。
これを選択して編集。
Inkscapeなんたらってなっているパスを消す。
![2020-09-16 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/c0fb636c-0b16-378c-0ee1-cca9049a2474.png)

消したら保存して再起動。
チェックしてみると…
![2020-09-16 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629180/59199d34-bcbb-cc64-bb4a-b5dee85e13b9.png)

ktkr～～～～～～！！！！！
一件落着。

# まとめ
変なものをホイホイと環境変数`PATH`に追加しない！

# おまけ (Inkscape関係なかった人たちへ)
[原因究明](#原因究明)の項のモジュールをインストールできているかの確認をまずしてほしい。
インストールがミスっているならもう1回インストール、できていたならば次のコードを。

```
pip show [importできなくて困ってるモジュール名]
```

このコードはモジュールの場所を教えてくれる。
そして、Pythonコンソールを開いてPythonがどこを参照してインポートしようとしているかの確認する。
手順は[原因究明](#原因究明)にある(コンソールで、`sys`をなんたらってやつ)。

Pythonの参照先とモジュールの場所は一致しているだろうか。おそらく一致していないと思う。
であれば、[対処](#対処)の項の環境変数の設定の仕方を参考に、Pythonがインストールされたフォルダを環境変数`PATH`に追加する。
Pythonのインストールフォルダは人によって違うだろうが、筆者の環境では`C:\Users\[筆者の名前]\AppData\Local\Programs\Python\Python38`にあった。

見つからない場合は、スタートメニューからPythonを探して、右クリックメニューの`その他`→`ファイルの場所を開く`、
開いたフォルダで選択されているもの(おそらくPythonのショートカット)の右クリックメニューから`ファイルの場所を開く`。
これでpythonがインストールされたフォルダにたどり着く。

そもそもスタートメニューにPythonがないって人は諦めてPythonを再インストールしよう。
その際、インストール画面をじっくり見て、`環境変数PATHに追加`にチェックを入れること。
そうすれば解決するはずだ。

それでは、よいPythonライフを！
備忘録(CSVファイル読み込み時のUnicodeDecodeError対策）

**pythonで自動化とかできるんでしょ～？よろしく～、って言われたので頑張る記録　その1**

<details><summary>**～～結論だけ先に書いておく～～**</summary>
open(CSVファイル,encoding =文字コード）で指定する時、
　文字コードには「CSVファイルに使われている文字コード」を使えば大丈夫。
　今回は日本語を含むファイルだったのでShift-jisで指定が必要だった。
</details>

<details><summary>**～～どうでもいい日記～～**</summary> 社内のソフトでデータをCSVに出力する
→担当者がいい感じにエクセルファイル上で成形する
→エクセルファイルをメールで先方に送る
pythonを使って上記作業をうまいこと自動化するように言われたのでゼロスタートで頑張ることになった。
pythonについては完全に素人だが、VBAの知識が多少あるなら何とかなるらしい。本当かよ。
**～～ここまで日記～～**</details>


**～～主題～～**
**・CSVファイルを読み込んだらUnicodeDecodeErrorが出たので直したい**


**～～ここから状況説明～～**
Google Colaboratoryを使ってpythonの基本機能を確認から開始した。
適当なCSVファイルをグーグルドライブ直下に置く。
google Colaboratoryから新しいNotebookを作成する。
csvを読み込んで出力するサンプルプログラムを試す。
Ref：https://note.com/092i034i/n/n76f2c2de197

```python:test
import csv　#これを書いておくとCSVファイルが扱えるっぽい

csvfile = open('/content/drive/My Drive/test.csv') #csvファイルをpythonの変数csvfileに取り込んだ
reader = csv.DictReader(csvfile) #csvfileの情報を何らかの形でreaderという変数に放り込んだ

for row in reader: #まだ良く分かってない。繰り返し処理っぽいけど・・・。

 print(row) #変数rowの中身を出力するやつ
```
しかし、コンパイルが通らない。エラーが出る。

```python:error-message
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-30-e6400dcd8fdb> in <module>()
      4 reader = csv.DictReader(csvfile)
      5 
----> 6 for row in reader:
      7  print(row)
```

英語の成績が致命を通り越して落命レベルであり、スマブラの「Break the target！」のアナウンスさえ異界の言語と思っていた身としては、この時点で既に気分がどんよりしてきているが、まあ一個ずつ取り組むしか無い。

見たところ、変数readerの中身をrowに代入するときのデコード（復号化）に失敗しているのだが、
csvfile=open(test.csv)の処理では何もエラーが出ていない。

`この結果から考えたプログラム処理の流れ
1.ドライブ上のCSVファイルをエンコード（暗号化）してpythonの変数csvfileに取り込む
2.変数csvfileの中身を、エンコードされたままcsv.dictreaderという法則で変数Readerに代入
3.変数readerの中身を復号化して変数row に移し替える（ここで復号に失敗してエラーが出た）
4.変数Rowの中身を1行目から最後まで出力する
`

よってreaderの中身をrowに移すときの復号方式に何か問題がある・・・と、思っていたのだが、
エラーメッセージをネットで調べるとどうも違うらしい。

`正しい処理の流れっぽいもの
1.ドライブ上のCSVファイルは日本語を含むのでShift-jisでエンコードされていた
2.しかし、特に何も指定がないと、pythonはCSVファイルの中身をUTF-8でエンコードして変数csvfileに取り込む
3.この時、変数csvfileの中身は「Shift-jisのファイルをUTF-8で無理矢理エンコードした文字化け状態」になっている
4.しかし、なぜかこの状態でもcsv.dictreaderという法則で変数csvfileから変数Readerに代入することはできる
5.変数readerの中身を復号化して変数row に移し替える（ここでデコードできないことで初めて文字化けが分かるらしい）
6.変数Rowの中身を1行目から最後まで出力する
`

何故csv.dictreaderではOKなのか分からないが、
直したらコンパイルが通ってしまったのでひとまずはそういうものだと割り切ることにする。

**エンコードの時点で問題が発生していても、pythonの処理でそれが発覚するのはデコード時らしい。**
これは多分、俺のエンコード・デコードに関する知識が不十分なせいで意味が分からない点なんだけど・・・メインの自動化の話からは逸れるので今回は追うのを諦める。


しかし、初日が終わってまだCSVファイルの読み取りしか出来ていないが本当に大丈夫か。
俺がオリマーならホコタテ星から出られず土に還るペースだぞ。
VBAの知識あれば大丈夫って本当に本当か。不安。


```python:補足：直したらコンパイルが通ったときのコード
import csv

csvfile = open('/content/drive/My Drive/test.csv',encoding="shift-jis")  #日本語csvファイルをshift-jisで取り込み
reader = csv.DictReader(csvfile)

for row in reader:
 print(row) 
```
Firebase Storageの複数ファイルをダウンロード＆アップロード

# はじめに

Firebaseのプロジェクトを作り直した際、元のプロジェクトから新しいプロジェクトへStorageの中身を全てコピーする必要がありました。調べたけど複数ファイルを一括で扱う方法が見つからなかったので、forEachで１ファイルずつ処理しました。

# Google Cloud Storageからのダウンロード

Storage直下にあるファイルをローカルのworkディレクトリへダウンロードします。

```javascript:download-storage.js
const admin = require('firebase-admin');

const serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  storageBucket: "<BUCKET_NAME>.appspot.com"
});

const bucket = admin.storage().bucket();

async function main() { 
  const files = await bucket.getFiles();
  files[0].forEach((file) => {
    const filePath = `./work/${file.name}`;
    console.log(filePath);
    file.download({destination: filePath});
  });
}

main().then();
```

# Google Cloud Storageへのアップロード

ローカルのworkディレクトリにあるファイルをStorage直下へアップロードします。

```javascript:upload-storage.js
const fs = require('fs');
const admin = require('firebase-admin');

const serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  storageBucket: "<BUCKET_NAME>.appspot.com"
});

const bucket = admin.storage().bucket();

async function main() {
  const files = await fs.readdirSync('./work');
  files.forEach((file) => {
    const filePath = `./work/${file}`;
    console.log(filePath);
    bucket.upload(filePath);
  });
}

main().then();
```
機械学習とA-frameの連動方法

# A-frameで3Dが簡単につくれることを知った

**「3Dなんて僕にはまだ無理無理」**

そんな風に思っていたのですが、
**初心者でも、簡単に、**WEB上で3Dをつくれることを、つい先日知りました。

それが**A-frame**　サイトは[こちら](https://aframe.io/ "こちら")

WEBサイト上にこんなものを簡単に表示させることができます。

<img width="500" alt="image10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664861/90cbc6fd-44d1-d553-e742-4ecddc7468b1.png">


# じゃあ、この物体動かしてみよう

それぞれのものを動かすのも簡単です。animationを追加すれば、すぐに動かせます。

```javascript
<a-box position="-1 1.6 -5" animation="property: position; to: 1 8 -10; dur: 2000; easing: linear; loop: true" color="tomato"></a-box>
```

こんなものを一行加えるだけで、animationが動きます。


# じゃあ、teachable Machineと連動させて動かすには？

if文の中にif文書いたり複雑なことをやろうとしてなかなかうまくいかなかったんですが、
関数をつくることが、なんとかできました。


```javascript
const imageModelURL = 'teachableMachineから取得したURL';

            async function main() {
                // カメラからの映像取得
                const stream = await navigator.mediaDevices.getUserMedia({
                    audio: false,
                    video: true,
                });
                // html内のidがvideoのdomを取得
                const video = document.getElementById('video');
                // videoにカメラ映像を適用
                video.srcObject = stream;

                // 自作モデルのロード
                classifier = ml5.imageClassifier(
                    imageModelURL + 'model.json',
                    video,
                    modelLoaded
                );
                // モデルのロード完了時に実行される
                function modelLoaded() {
                    console.log('Model Loaded!');
                }
                // 繰り返し検出処理
                classifier.classify(onDetect);
                function onDetect(err, results) {
                    console.log(results);
                    if (results[0]) {
                        console.log(results[0].label);
                        if (results[0].label === '動画から取得した情報') {
                            //  "取得情報"を検出すると、上にanimatinが動く関数
                            move();
                        }
                    }
                    classifier.classify(onDetect);   
                }
                //  対象とする物体にanimationを追加。
                function move() {
                    cylinder.setAttribute('animation', 'property: position; to: 0 5 -3; dur: 2000; easing: linear; loop: true');
                }
            }
            main();

```
【Wordpress】Smart Custom Fields(SCF)で繰り返しのカスタムフィールドをコード定義＆REST API出力する

#やりたいこと
SCFの繰り返しのフィールドをコードで管理し、更にAPIで出力する

#やりかた
##コード定義
https://2inc.org/blog/2015/03/12/4670/

```php:functions.php
function my_register_fields( $settings, $type, $id, $meta_type ) {
	// 特定のタイプにだけ、このカスタムフィールドを表示する場合下記をコメントアウト
	//if($type !== 'post'){
    //    return $settings;
	//} 

	// SCF::add_setting( 'ユニークなID', 'メタボックスのタイトル' );
	$Setting = SCF::add_setting( 'id-1', 'functions.php から追加 その1' );
	
	// $Setting->add_group( 'ユニークなID', 繰り返し可能か, カスタムフィールドの配列 );
	$Setting->add_group( 'group-name-1', true, array(
		array(
			'name'  => 'field-1',
			'label' => 'テストフィールド',
			'type'  => 'text',
		),
		array(
			'name'    => 'field-2',
			'label'   => 'テストフィール2',
			'type'    => 'text',
			'default' => 2,
		),
	) );
	
	$settings[] = $Setting;
	return $settings;
}
add_filter( 'smart-cf-register-fields', 'my_register_fields', 10, 4 );
```

`add_group`の際に第２引数に`true`を設定

##API出力
`add_group`の際に指定したユニークなIDを使う

```php:functions.php

function rest_scf_add_field()
{
    register_rest_field(
        'post', // 追加する投稿タイプ(カスタム投稿なら、その投稿タイプを指定する),
        'scf', // 追加するフィールド名
        [
            'get_callback' => function(){
                return SCF::get('group-name-1'); // add_groupで指定したID
            },
            'update_callback' => null,
            'schema' => null,
        ],
    );

}
```

出力イメージ(２回繰り返している)

```
- scf
    - 0
        - field-1
            - ほげ
        - field-2
            - ほげ2
    - 1
        - field-1
            - ほげ
        - field-2
            - ほげ2
```



ちなみに、Smart Custom Fields API で調べると下記が一番に出てくるけど
構造の使いみちが限定的な形なので、そのまま繰り返すフィールドの塊でとったほうが良いと思う

https://yamashitive.com/281/
上記記事だと下記のような感じ
この形が良い場合は、参考にしてください

```
- scf
    - field-1
        - ほげ
        - ほげ２
    - field-2
        - ほげ
        - ほげ２
```
Python を学習するなら　無料クラウドサービス　『python anywhere』 が最適！ （2020年9月）

Python 初学者必見🔰

Pythonの無料クラウドサービス『python anywhere』は、

環境構築不要！！

最速！！

5分でデプロイ可能！！

その場で、
Webアプリケーションを作成することができます:airplane:
ブログサイトや、ToDoリスト、プレビューサイトなど💪

公式サイト　➡️ https://www.pythonanywhere.com/

![A935E5DD-C714-401A-9F51-666E27306A5D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/06821b8e-d9bb-c30c-de22-0bdab37b860a.jpeg)
　　　　　　　　　　　　　　　　　　　　　　　　　　（2020年9月現在）

⬇️
デプロイ方法は、近日公開🌐　👉(part2へ)　https://qiita.com/iwasaki-hub/items/241ede0367d0d9a4a9d7　
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　（公開ページ）
　必要スキル　:snake:  Django（web フレームワーク）
　　　　　　　:whale2: 基本的なコマンド（ls,cd,mkdirなど）
nannouでスケッチを動画として書き出す

# はじめに
nannou は Rustのクリエイティブコーディングライブラリです。
今回の記事ではそのスケッチを動画に書き出す方法を備忘録として書いておきます。
###  環境
nannou : 0.14.1
Linux


# 概要
1. nannouのAPIでフレームをキャプチャする
2. png形式で保存
3. ffmpegでmp4に変換

# フレームをキャプチャしてpngで保存
以下のようなコードで `./cap/プロジェクト名/フレーム数.png` でpngで書き出せる。

```Rust
fn captured_frame_path(app: &App, frame: &Frame) -> std::path::PathBuf {
    app.project_path()
        .expect("failed to locate `project_path`")
        .join("./cap/")
        .join(app.exe_name().unwrap())
        .join(format!("{:04}", frame.nth()))
        .with_extension("png")
}

fn view(app: &App, model: &Model, frame: Frame){
    let file_path = captured_frame_path(app, &frame);
    app.main_window().capture_frame(file_path);
}
```

# ffmpegでmp4に変換

ffmpegはクロスプラットフォームの録画とか変換用のツールです。
[公式サイト](https://ffmpeg.org/)やGoogle検索を頼りにインストールしてください。



```sh
cd cap/プロジェクト名 # 先程のキャプチャしたpngのあるフォルダへ移動
ffmpeg -framerate 30 -i %04d.png -vcodec libx264 -pix_fmt yuv420p -r 60 out.mp4     
```
を行うことで、`out.mp4` という動画ファイルが完成します。

# ツイッターに上げるなら
ツイッターでの動画の規約は以下

>■動画の形式
>スマートフォンのアプリではMP4とMOVの動画形式をサポート。ブラウザではMP4（H264形式、AACオーディオ）をサポートしています。
>
>■動画のサイズ（容量）
>アップロードできるサイズは最大512MBです。
>
>■動画の時間
>アップロードできる動画の長さは2分20秒間以内です。
>
>■ブラウザでアップできる動画の解像度と縦横比
>最小解像度: 32 x 32
>最大解像度: 1920 x 1200、または1200 x 1900
>縦横比: 1:2.39～2.39:1の範囲
>最大フレームレート: 40fps
>最大ビットレート: 25Mbps
ドライブレコーダ（組込みシステム開発）ー午後

応用情報技術者平成29年秋期 午後7

ファイル：2017h29a_ap_pm_qs.pdf

参照：
https://www.ap-siken.com/kakomon/29_aki/pm07.html

メモも簡単に記載します。
詳細の分析は、上記リンクをご参照くだいますようよろしくお願いします。

**１、〔レコーダの基本動作〕について，本文中のaに入れる適切な字句を答えよ。**
２次電池の役割は何ですかね。
・ファイル保存の中断を防止するためです：
　　動画ファイルの生成または追記の途中で電源断が生じると、動画ファイルが破損してしまう恐れがあります。30秒間の電力を供給可能な二次電池を用意する理由は、動画ファイルの保存中に電源断が生じても動画ファイルの保存動作を維持するためです。

・なぜ、衝撃センサからの割込みを禁止するか？
　　動画ファイルの保存中に再度衝撃を受けるとその時点から20秒間の画像を追記する仕様のためです。二次電池により担保される電力供給時間は30秒間なので、再衝撃による割込みを許すと動画ファイルの保存時間の合計が30秒を超えてしまい、保存動作中に電力供給が途絶えてしまう恐れがあります。

衝撃検出（私の答え）
→
動画ファイルを保存（参考答え）

私は、衝撃検出した時、電源が続けて、動画ファイルを保存しつつ、破損は発生しないようにするだが、
やっぱり、直接に、「ファイルを保存」を答えないと、いけないですね。


＜＜レコーダの基本動作＞＞
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/4b6f5dbf-166f-8eac-683b-63e699a0de3f.png)
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/a6ceccfd-4cab-ac3c-fb56-65f9ab187259.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/01f79190-a0e2-b6dc-6bce-faf25caf4eb4.png)


**２、〔記録バッファ〕について，記録バッファの容量を求める式を，カメラが1秒間に撮影するフレーム数F及びGPS情報を含む1フレームの画像データのバイト数Nを使って答えよ。**

ポイントとしては、「
　　記録バッファには，衝撃検出直前の10秒間分の画像データが書き込まれる。さらに，動画ファイルの保存の処理遅れを考慮して，10.5秒間分の画像データを書き込むことができる容量とする。
」
ですね。

後は、１フレームはNバイトので、
Fフレームは、F×Nで、
10.5秒と掛けると
10.5FNですね。

**３、〔保存タスクの動作〕について，(1)，(2)に答えよ。**
（１）、図2中のb～dに入れるイベントを，本文中のイベントを用いて答えよ。
bは、衝撃検出後データ保存の（１）によると、衝撃イベントですね。
cは、衝撃検出後データ保存の（３）によると、画像格納イベント　ですね。
dは、衝撃検出後データ保存の（３）によると、タイマ満了イベント　ですね。

＜＜図２＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/5af5c0ef-f8fd-ee5c-e58d-97a7d3266bcf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/a205d2bf-7fb9-72b0-fd67-fc92c3ae99ea.png)


（２）、本文中のe，fに入れる適切な数値を答えよ。
eとfは、動画ファイルの保存ですね。
仕様は、
　・①衝撃割り込みから１０秒間保存。保存所要時間は、１００ミリ秒
　・②保存した以降２０秒、動画ファイルに追記
　・③仮に、上記二つのいずれか保存の途中で、再度衝撃割り込みと、その時点から２０秒、動画ファイルに追記
です。

言い方が結構分かりにくいですね。
衝撃検出前データ保存は、１００ミリ秒だけが必要ですね。この時は、既にバッファに１０秒動画データがありましたので、１００ミリ秒の保存の後は、そのタイムは何のため、リセットされるよね。

では、何のためでしょうか。
上記の②ですね。つまり、保存してから、２０秒間、動画ファイルも保存したいので、２０秒のタイマを設定する。
eは２０秒。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/63690a09-883d-461c-cfc0-8ab1339f8d20.png)


fは、ちょっと理解しやいですね。
新しい衝撃が来ると、上記③で、２０秒にタイマをリセットするよね。
fは２０秒。



＜＜動画ファイルの保存＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/c5f76dbf-195a-684f-c048-1b496d628457.png)


**４、現在のレコーダの設計では，電源投入後に衝撃を検出しても，動画ファイルをSDに保存しないことがある。どのような場合にこのようなことが起きるのか。40字以内で述べよ。ここで， SDには十分な空き容量があり，ハードウェアに故障はないものとする。**


動画ファイルの保存　によると、システム時刻が設定されないと、動画ファイルを保存しないという仕様です。
システム時刻は、制御装置がGPSモジュールにより取得した最初のGPS情報（時刻含む）で設定されます。
その後は、１時間ごと補正のため、再設定をする。

そうすると、最初のGPS情報（時刻含む）でシステム時刻を設定できない場合、動画ファイルを保存できないです。


起動後の初回GPS情報取得ができなく、システム時刻設定できない場合（私の答え）
→
電源投入後、システム時刻の設定が完了するまでの間に衝撃を検出した場合（参照答え）
v-data-table（Vuetify）をTypescriptで書き直す

# Vuetify.ts
VuetifyはTypescript対応がされていますが、
公式ドキュメントのコンポーネントリストでTypescriptのサンプルコードがないため、
v-data-tableを例にTypescriptに変更した際の備忘録です。

公式ドキュメント
https://vuetifyjs.com/en/components/data-tables/

#Javascript

``` sample.vue
//表示部分
<template>
  <v-container>
    <v-row>
      <v-data-table
        :headers="headers1"
        :items="items1"
        :items-per-page="5"
        class="elevation-1"
      ></v-data-table>
    <v-row>
      <v-col cols=3></v-col>
    </v-row>
      <v-data-table
        :headers="headers2"
        :items="items2"
        :items-per-page="5"
        class="elevation-1"
      ></v-data-table>
    </v-row>
  </v-container>
</template>

//スクリプト
<script>
  export default class hoge {
    export default {
      data() {
        return {
          headers1: [...],
          headers2: [...],
          items1: [...],
          items2: [...],
        }
      }
    }
  }
</script>

```

それぞれの詳細が知りたい場合は、
公式ドキュメントからGitHubに公開されているコードを確認してください。

また、公式ドキュメントのAPIリファレンスを見ると、
headers 部分についてはjavascript でも、
下記のようになることを期待されています。

``` header_example.js
{
  text: string
  value: string
  align?: 'start' | 'center' | 'end'
  sortable?: boolean
  filterable?: boolean
  groupable?: boolean
  divider?: boolean
  class?: string | string[]
  width?: string | number
  filter?: (value: any, search: string, item: any) => boolean
  sort?: (a: any, b: any) => number
}
```
したがって、こちらをTypescriptに書き直す必要があります（嘘）。



#Typescriptに書き直す
主に"#スクリプト"以下について、
headers と、 items という、
interfaceやtypeを構造体のような役割のあるモジュールで定義してあげる必要があります。

ただ、
headerについては自分で定義してもよいのですが、
VuetifyでTypescript用にDataTableHeadeインターフェースが用意されているので、こちらを利用したほうが楽です。

``` index.d.ts

export interface DataTableHeader<T extends any = any> {
  text: string
  value: string
  align?: 'start' | 'center' | 'end'
  sortable?: boolean
  filterable?: boolean
  groupable?: boolean
  divider?: boolean
  class?: string | string[]
  width?: string | number
  filter?: (value: any, search: string | null, item: any) => boolean
  sort?: DataTableCompareFunction<T>
}
```

この辺を踏まえて書き直すと下記のようになります。

```sample.vue
//表示部分
<template>
  <v-container>
    <v-row>
      <v-data-table
        :headers="headers1"
        :items="items1"
        :items-per-page="5"
        class="elevation-1"
      ></v-data-table>
    <v-row>
      <v-col cols=3></v-col>
    </v-row>
      <v-data-table
        :headers="headers2"
        :items="items2"
        :items-per-page="5"
        class="elevation-1"
      ></v-data-table>
    </v-row>
  </v-container>
</template>

<script lang="ts">
  export default class hoge {
    //ヘッダー部
    headers1: DataTableHeader[]=[...,...,]
    headers2: DataTableHeader[]=[...,...,]
    
    //アイテム部
    items1: item[]=[...,...,]
    items2: item[]=[...,...,]
  }
  
  //アイテムインターフェース作成部
  export interface item<T extends any = any>{
    xx :string;
    yy :string;
    zz? :string;
    …
  }
</script>
```

以上です。
「input type=time」と「input type=text + timepicker」での動作の違い

# やりたこと
せっかくHTMLのデフォルトで「input type=time」が準備されているのだから、できれば使いたい。
input type=text + timepickerとの動作の違いを確認する。

# 結論
input type=text + timepickerの方が以下の観点で良い。

* 「input type=time」はブラウザによって描画・挙動が違う（参照サイト確認）
* リクエストの内容は同じなのでどちらでもよい

# 環境
* jQuery3.5.1
* timepicker1.13.14
* Chrome85.0.4183.83

# 実装

```xxx.html
<input type="time" class="ddd" name="bbb" value="12:30">
<input type="text" class="aaa" name="ddd" value="11:30">
<script type="text/javascript">
$(function () {
    $('.text').timepicker({'timeFormat': 'H:i'});
});
```

### 表示（左：time,右：text(timepicker)）
何もCSSを当てていない状態。
Chromeの場合は、timeには時計のアイコンが表示される。
個人的にはどっちでもいいかなという感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691945/6c4436b4-2c7d-d92a-9f85-79976f3558df.png)

### timeの選択画面
時分を別々で選ぶのって面倒くさくない？
1分単位で選ばせたい場合はこっちの方がいい場合あるのか。
今回は30分単位で選択させたかったのだが、そもそも[step](https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/time#Using_the_step_attribute)がうまく効かなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691945/1885b553-ba9a-63f1-f664-20fcf6341b09.png)

### text(timepicker)の選択画面
１クリックで選択できる。
ただ1分単位とかになると少しスクロールが面倒くさいかも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691945/132db3e4-1bcd-3a63-0476-3d0f394513f3.png)

### POSTデータ
どちらも同じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691945/2f6ee5fe-3a41-0ad7-0720-a74de7daff77.png)

# 参照
https://b-risk.jp/blog/2019/09/input-date-form/#link04
[VB.NET] 暗黙のFormオブジェクト～My.Forms

# My.Formsの謎に迫る

まず、VB.NET の WinForms プロジェクトを作成し、下記のようなコードを記述します。
（Form1 には、Button1 と Button2 の2つのボタンがあり、デザイナで Click イベントハンドラを設定しています）

```vb
Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Test.HelloWorldA(Me)
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Test.HelloWorldB()
    End Sub

End Class

Public Class Test
    Public Shared Sub HelloWorldA(frm As Form1)
        frm.Text = "Hello World! A"
    End Sub

    Public Shared Sub HelloWorldB()
        Form1.Text = "Hello World! B"
    End Sub

End Class
```

HelloWorldB メソッドでは Form1 のインスタンスを渡しておらず、何故かインスタンスが作成されていないForm1.Text プロパティに対して直接アクセスしてるように見えます。

一見コンパイルエラーになるように見えますが、奇妙な事に実際はこのコードはコンパイルエラーにもならないし、Button1 をクリックすると "Hello World! A"、Button2 をクリックすると "Hello World! B" にフォームのタイトルが切り替わります。

VisualStudioで、HelloWorldB の Form1 にマウスカーソルを当てると、下記のように表示されます。
![VisualStudio表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519547/5b71b780-0eb9-4d55-06e3-6f6cf0204ad3.jpeg)

ちなみに、ILSpy でC#にデコンパイルすると、下記のようになります。
![decomp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519547/76a66edc-f3d2-1403-a340-e92a2eda9497.jpeg)

WindowsApp1.My という名前空間と、その中に、My〇〇 というクラスが作成され、
MyProject クラスの中に Forms という静的プロパティがあり、その中に Form1 プロパティがあります。
C#の HelloWorldB メソッドのコードを見ると、

```cs
MyProject.Forms.Form1.Text = "Hello World! B";
```

となっています。VB.NET が勝手に My.MyProject.Forms にフォームのインスタンスを作成していて、
[フォームクラス名.プロパティ]
 と記述すると、My.MyProject.Forms を省略し、そこにアクセスしたものと解釈してくれる訳ですね。~~まったく余計な事しやがって。~~

関連ドキュメントを漁ったら、下記のものが見つかりました。他にも色々な My オブジェクトがあるようですね。英語苦手な人は Google 翻訳通してください。
[My.Forms Object](https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/objects/my-forms-object)
[My.Internals: Examining the Visual Basic My Feature](https://docs.microsoft.com/en-us/previous-versions/ms379610(v=vs.80)?redirectedfrom=MSDN#vbmy_topic3)
[Objects implicitly instantiated in vb.net?](https://stackoverflow.com/questions/20076969/objects-implicitly-instantiated-in-vb-net)

# My.Formsの問題点
VB.NET はデフォルトのプロジェクト設定だと Form から直接起動され、この場合は My.Forms のインスタンスが使用されますが、これをC#のように Main メソッドを作成し、プロジェクト設定のスタートアップオブジェクトを変更して、Main メソッドから起動してフォームを作成したとします。

```vb
Public Class Program

    <STAThread>
    Shared Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1)
    End Sub

End Class
```
これで Form1 の Button2 をクリックした場合どうなるかというと、フォームのタイトルは "Hello World! B" に設定されません。
Main メソッドで作成した Form1 と、MyProject.Forms.Form1 の Form1 のインスタンスは別物であり、現在画面に表示されているのは Main メソッドで作成した Form1 です。MyProject.Forms.Form1 の Text プロパティを更新した所で、当然フォームのタイトルは変わらないという訳ですね。

.NET開発の主流は C# で、VB.NET は開発も止まるみたいですし今後無くなっていくとは思いますが、既存の VB.NET のコードを C# に移植する際、My.Forms のような暗黙のオブジェクトはC#には無い要素なので、もし参照している箇所があったりするとハマりどころになる場合があるので注意が必要です。
railsのバージョン指定について

#該当箇所
現場で使えるRuby on Rails5 速習実践ガイドChapter3-1-3

```
$ rails _5.2.1_ new taskleaf -d postgresql
```


でバージョン指定してアプリを作成したのにサーバを起動するとrails のバージョンが5.2.4.4になってしまいました。


#期待する動作
GemfileとGemfile.lockのバージョンを一致させて、サーバを起動するとrails のバージョンが5.2.1になること



#取り組んだこと
バージョンはGemfile.lockに記述されているため、見てみるとやはりrails のバージョンが5.2.4.4になっていました。それに対し、Gemfileは

```ruby:Gemfile
gem 'rails', '~> 5.2.1'
```

とあり、なんでGemfileとGemfile.lockでバージョンが違うんだろう？と思いました。

調べていくうちに、原因はGemfileの中のgem ‘rails’, ‘~> 5.2.1’の部分だとわかりました。
`gem ‘rails’, ‘~> 5.2.1’`は`gem ‘rails’, ‘>= 5.2.1’, < 5.3.0'`を表すためGemfile.lockのバージョンが5.2.4.4になってしまっていたのです。
Gemfile.lockも5.2.1にするためにはGemfileで`gem ‘rails’, ‘5.2.1’`でがっちり指定する必要がありました。

```ruby:Gemfile
gem 'rails', '5.2.1'
```

に修正して、

```
$ bundle update
```

これで正しくバージョンが指定されました！
Flutter TextFieldの装飾

Flutter で 「入力欄にボーダー設定したいけど、どうするんだろう」 と調べた時に、あまりに基本的な事すぎて？しばらく見つけられなかったので備忘録を兼ねたメモです。

## スクリーンショット
ボーダーとかアイコンを設定するとスクリーンショットにあるような入力欄が作れます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39953/41dac5c9-1a59-eb0f-07a8-27023f89ab3f.png" width=50%>

## ソースコード

TextField に InputDecoration で設定しています。

``` Dart
class MyWidget extends StatelessWidget {
  const MyWidget({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Container(
            padding: const EdgeInsets.all(30),
            child: Form(
              child: Column(
                children: [
                  const Text('テキスト入力の装飾'),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      labelText: 'デフォルト',
                    ),
                  ),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'ボーダーあり',
                    ),
                  ),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'アイコンあり',
                      icon: Icon(Icons.send),
                    ),
                  ),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'エラーあり',
                      errorText: 'ここにエラーメッセージ',
                    ),
                  ),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'Prefix, Suffix',
                      prefix: Text('Prefix'),
                      suffix: Text('Suffix'),
                    ),
                  ),
                  const SizedBox(height: 20),
                  TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'Prefix, Suffix アイコン',
                      prefixIcon: Icon(Icons.face),
                      suffixIcon: Icon(Icons.face_outlined),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
```
rails new アプリ名でアプリが作成されない

#該当箇所
Railsチュートリアル第3章
`$ rails _6.0.3_ new sample_app`
を実行すると、エラーが起こりアプリが作成されない。

#期待する動作
`$ rails _6.0.3_ new sample_app`コマンドが正常に動作し、アプリが作成されること。

#取り組んだこと

```
$ rails _6.0.3_ new sample_app

Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
```

Yarnがインストールされていないようです。Yarnをインストールしてくださいと言われました。
なので、HomebrewのbrewコマンドでYarnをインストールします。

```
 $ brew install yarn

 bash: brew: command not found
```

次は、brewコマンドなんてないよと言われました。
ということはHomebrewがないのだと思い、Homebrewをインストールします。

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

　Warning: /home/linuxbrew/.linuxbrew/bin is not in your PATH.
```

PATHが通っていませんよ、と言われました。
なので、PATHを通らせます。

```
$ echo 'export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"' >>  ~/.bashrc
source ~/.bashrc
```

これでHomebrewがインストールされYarnもインストールされました。

```
$ rails _6.0.3_ new sample_app
```

ちゃんとアプリが作成されました！！

#結論
`$ rails new アプリ名`コマンドでアプリを作成するためには、Yarnをインストールする必要がある。
また、Yarnをインストールするためにはnpmでインストールする方法などもありますが、Homebrewでインストールできる。

#参考
https://qiita.com/jun3030/items/afcd3287285a57b32ccb
VSCode + Vetur で Typescript の Paths が解決できない。

# 参照エラーとともにVetur(xxxx)が発生

過去に動いていたのに環境を変更したら、

```
Vetur(2339)
Vetur(2306)
Vetur(2307) …etc
```

が発生するようになった。※インテリセンスが効かない

Git-hubのIssueで議論されていますが、
解決部分を見つけるのが大変なので、
よくありそうな解決方法をまとめました。
https://github.com/vuejs/vetur/issues/762

## 1.tsconfig.json を 確認する。
パスの設定がされていること。

```
    "paths": {
      "@/*": [
        "src/*"
      ]
```

## 2.ファイルの拡張子が「.vue」になっていることを確認する。
単一ファイルコンポーネントで構成する際は、.vueとする必要があります。
（単純にファイル作成時に拡張子を忘れるケースがあった、とのこと）

## 3.ワークスペースのルートディレクトリにtsconfig.jsonがあることを確認する。
VSCodeのVeturはワークスペースのルートディレクトリから順に解決するため、  
作業ディレクトリ直下にtsconfig.jsonがあるようにすると手っ取り早いです。

例えば、
- ワークスペースにtsconfig.jsonがあるディレクトリを追加する
- プロジェクトをフォルダやワークスペースから開きなおし、tsconfig.jsonがあるディレクトリをルートにする。

以上です。
登記簿謄本 履歴事項全部証明書をネットでもらおう

履歴事項全部証明書、登記簿謄本をネットから取得しよう

https://www.touki-kyoutaku-online.moj.go.jp/

かんたん証明書請求をクリック

左上からログイン

納付者に
カブシキガイシャジシャメイ

と入力




処理状況照会で 納付という赤いボタンを押す
(取得可能情報の納付ボタン)が表示されるまで10分ほどかかる。

すると銀行の画面に飛べるので、そこから振り込みをして完了。
Laravel getFormattedDueDateAttributeでTrailing data のエラーが出た場合

#初めに
仕事でLaravelの知識が必要となり、下記リンクの良さげなチュートリアルをやっていまた。
https://www.hypertextcandy.com/laravel-tutorial-todo-app-list-tasks

チュートリアル通りにやっていてもエラーってやっぱり起きるのですよね〜。。。

#環境
チュートリアルが2018年のものだったので、少し古めのv6でやってみた（**この時、もっと詳しく年代別のバージョンを調べていれば**・・・:persevere:）

```console
$ php artisan --version
Laravel Framework 6.18.40
```

#問題の箇所
上記リンク先のチュートリアルである**「日付の表示形式を変更する」**の部分

```php:Task.php
// この行を追加
use Carbon\Carbon;

class Task extends Model
{
    /* 中略 */

    /**
     * 整形した期限日
     * @return string
     */
    public function getFormattedDueDateAttribute()
    {
        return Carbon::createFromFormat('Y-m-d', $this->attributes['due_date'])
            ->format('Y/m/d');
    }
}
```

Carbon ライブラリを使って期限日の値の形式を変更して返す部分で、以下のようなエラーが！

```
Carbon\Exceptions\InvalidFormatException
Trailing data (View: /Users/***/resources/views/tasks/index.blade.php)
```

全てコピペし直したりしたので、どう考えてもスペルミスではない。とすると、、、

#バージョンによる違いでした。。

https://stackoverflow.com/questions/50208932/laravel-model-trailing-data-when-save-the-model

上記stackoverflowで見た回答を試すとエラーは解消された。。。
**おそらくv5とv6の違いなのでしょう。**

```php:Task.php
  /**
     * 整形した期限日
     * @return string
     */
   public function getFormattedDueDateAttribute()
    {
        // createFromFormatの中を 'Y-m-d H:i:s'に変更する
        return Carbon::createFromFormat('Y-m-d H:i:s', $this->attributes['due_date'])
        ->format('Y/m/d');
    }
```

と言うか、[チュートリアルのページ](https://www.hypertextcandy.com/laravel-tutorial-todo-app-list-tasks)をよく見ると、以下のようなコメントもありました:joy:

>お世話になります。
Laravel6.14.0です。
後半の「日付の表示形式を変更する」の項で、getFormattedDueDateAttributeを追加し、テンプレートの修正をしてブラウザを再読み込みしたところ、「trailing error」が出ました。
createFromFormat内を('Y-m-d H:i:s' , ......)と修正したところ、解決しました。
念のため、お知らせしておきます。
現場で使えるRuby on Rails5速習実践ガイド　まとめ


現場で使えるRuby on Rails5速習実践ガイド一冊を一通り習い終えたので、なるほど！と思ったことをメモしました。

#用語整理
__rbenv:__

Rubyのバージョン管理を簡単にしてくれるツール。
開発においてプロジェクトに合わせてバージョンを使い分ける必要があるため、バージョン管理は重要。動作の速さやBundlerによるgem管理の使い勝手の良さが評価されている。

rbenvのインストールにはHomebrewが便利で、Homebrewの利用にはXcodeが必要。
つまり、Xcode -> Homebrew -> rbenvの順でインストールを行う。


__RDB:__

 Relational DataBaseの略。
データを表で管理してわかりやすく関連性を示すデータベースのこと。
普段使うMysqlやPostgresqlなども含まれる。

__アセットパイプライン:__

記述したCSSやJavaScriptをブラウザにとって最適な形にする処理のこと。
production環境では処理速度や通信量を重視する点からアセットの連結・最小化が行われるのに対し、devlopment環境ではデバックのしやすさを追求するためアセットの連結・最小化が行われない。

```ruby:app/views/layouts/application.html.slim
    = stylesheet_link_tag    'application', media: 'all'
    = javascript_include_tag 'application'
```

共通ビューでのヘルパーメソッドstylesheet_link_tag, javascript_include_tagの記述によってブラウザがCSSやJavaScriptのアセットを読み込んでいる。

__Yarn:__

JavaScriptのパッケージマネージャ(RailsでいうGemのパッケージマネージャはBundler)のこと。
RailsがサポートするWebpack,Vue.js,React.jsなどのフロントエンドのモジュールをRailsから管理する役割を担っている。

Yarnはデフォルトで入っていないため、自分でインストールしなければいけない。

__Webpacker:__
Railsのgemの一つで、Webpackを使ったアセットの管理を簡単にする。
WebpackerはYarnをインストールしていなければ使えない。


#〇〇と△△の違い
__*＜renderとredirect_toの違い＞*__
`render`はアクション直後にviewを返すのに対し、`redirect_to`はアクション後に別のURLへとブラウザがリクエストし直す。
アクション内でrenderやredirect_toを記述しなくてもviewが表示されるのはRailsが勝手にアクション名と同じ名前のviewを返してくれるからである。

__*＜saveとsave!の違い＞*__
`save`メソッドは検証エラーがあればfalseを返し、そのエラーの中身はerrorsメソッドで見ることができる。
`save!`メソッドは検証エラーがあればfalseでなく例外を発生させるため、絶対保存できるはず！という時に使うのが妥当。
つまり、if文の分岐処理として使う場合はエラーでなくtrueかfalseを返したいため、!はつけない。

__*＜findとfind_byの違い＞*__
`find`メソッドはデータがない時にエラー`ActiveRecord::RecordNotFound`を発生する。
`find_by`メソッドはデータがない時にnilを返す。

よってログイン処理ではログインしていない状態、すなわちsession[:user_id]がない時にエラーでなくnilを返したいのでfind_byメソッドを使う。

#その他のメモ



##ルーティングについて
URLとHTTPメソッドの組み合わせからコントローラのアクションを繋げる役目だけでなく、
一つのルートはrails routesと打った時に出てくるPrefix部分に記述されているURLパターン名を用いてURLを簡単に作成するためのヘルパーメソッドを作り出している
link_toメソッドの第2引数の`(URLパターン名)_path`はルーティングで生成されたURLヘルパーメソッドである。

##マイグレーションについて
マイグレーションファイルはバージョンの上げる記述だけでなく、上げ下げどちらの記述もしたほうがいい。
`change`メソッドではバージョンを上げるコードだけの記述から、Railsが勝手にバージョンを下げるロールバック処理も行ってくれるようになっている。
`$ rails db:migrate:redo`コマンドはバージョンを一回下げてまた戻す処理をしてくれるためロールバックができるか確認することができる。これを常に確認する癖をつけておいたほうがチーム開発では特にトラブルへの対応が楽になる。


##Cookieの仕組みについて
まず、ブラウザの初めてのリクエストに対して、サーバはCookie情報を含めたレスポンスを返すことでブラウザはサーバのドメイン情報とそのCookie情報を保存する。
次回以降、サーバはブラウザからのリクエストに含まれるCookie情報から以前の情報を取得して更新する。更新したCookie情報はブラウザに渡され保存される。
この繰り返しでブラウザ側で情報を更新し続けている。


#学び終えた全体の感想
とにかくRailsが勝手にやってくれていることが多いな！というのが印象的でした。便利であるからこそその裏側は知っておくべきだと改めて感じました。また、学んでいてRuby on Railsの勉強というよりRuby on Railsによる開発の勉強というような感覚でした。実践的な開発の流れであったり仕組みが細かく記述されていたためとても勉強になりました。基礎学習としておすすめです！
Node.jsの特徴

#プログラミング勉強日記
2020年9月16日
JSには色々なフレームワークがあって、開発の用途によって使用するフレームワークが違うと思うので、まとめてみようと思う。[Reactについて](https://qiita.com/mzmz__02/items/18f04f8e4ec84f1cc1af)と[Angularについて](https://qiita.com/mzmz__02/items/929beb891c194c9d0f43)、[Vue.jsについて](https://qiita.com/mzmz__02/items/0753cb65d7853cd60825)、[Next.jsについて](https://qiita.com/mzmz__02/items/d68667e281927a5f3e0d)、[Riot.jsについて](https://qiita.com/mzmz__02/items/969135ea1e86c83dded0)まとめたので、今回はNode.jsについてまとめる。


#Node.jsとは
　Node.js(読み方：ノードジェーエス)は、2009年に作成されたGoogle Chromeのために開発されたもので、JSアプリケーションのプラットフォーム。なので、ライブラリでもフレームワークでもない。
　サーバーサイドJavaScriptで、PHPやRuby、Python、Javaと同様にサーバで動作を行う。軽量で効率よく作業できるので人気のJSライブラリ。


#特徴

 - 大規模開発に向いている(大量接続を同時処理できる)
 - C10K問題を解決できる
 - フロントエンドのJSでも処理上の互換性がない

##大規模開発に向いている(大量接続を同時処理できる)
　軽量であるので、リアルタイムで複数人が使用する場合でも動作がもたつかない。Webアプリやスマホアプリの作成もNode.jsはしやすく、複数人が同時に接続する場合でも処理のパフォーマンスは落ちにくい。
　つまり、多くのアクセスがあるアプリに向いている。

##C10K問題を解決する
　サーバへの接続台数が1万台以上になると処理が遅くなってしまうのがC10K問題であり、この問題をNode.jsを使うだけで解決できるので、技術液なことに時間やコストを割かなくていい。

##フロントエンドのJSでも処理上の互換性がない
　Node.jsとフロントエンドのJavaScriptには、同じJSでも処理上の互換性がない。ただ、JSなのでプログラミング言語の基礎的な書き方や知識は活かせる。


#参考文献
[「.js」選びに迷った時に役立つ！人気のJavaScriptライブラリ＆フレームワークまとめ！](https://career.levtech.jp/guide/knowhow/article/387/)
[初めてでもわかる！Node.jsの特徴やできることとは？](https://www.webstaff.jp/guide/trend/nodejs%E3%81%AE%E7%89%B9%E5%BE%B4/)