OmniAICreator/Qiita-1.07M huggingface dataset:
【Git】初学者向け　なんとなく使っているpushの挙動を確認してみた。

#はじめに
Gitでの共同開発の中でpushでミスった経験からしっかりpushの挙動を確認してみました。

#対象者
pushは使っているけど、実際にどんなことをしているのかあまりわかっていない方。

#実際に試した内容

testディレクトリに空のindex.htmlファイルがあるとする。

```
ローカルブランチは下記だとする。
master
hoge
fuga
```

hogeブランチにはindex.htmlに「hogehoge」と入力してコミット
fugaブランチにはindex.htmlに「fugafuga」と入力してコミット

###実験1
今いるブランチ以外のブランチをpushできるか？

```
master
*hoge
fuga
hogeブランチで
$ git push origin fuga を実行。
```

###検証結果
pushされたのは「fugafuga」と書かれたindex.html
つまり、hogeブランチでpushしたがfugaブランチの内容がpushされた。

###実験2
ローカルブランチ名以外でpushできるか？

```
次にfugaブランチに移動。
master
hoge
*fuga

$ git push origin hogehoge を実行。
```

###検証結果
```
$ git push origin hogehoge
error: src refspec hogehoge does not match any
error: failed to push some refs to リモートリポジトリ名
となった。
```

つまり存在しないブランチをpushしようとしたのでエラーが表示された。


#結論
以上の結果からpushの挙動は以下のこととなる。
・カレントブランチがどこにいても他のブランチの内容をpushできる。
・しかしローカルブランチ名が一致しないとエラーが返ってくる。
・どこのブランチでpushを実行するかは関係なく、ローカルブランチ名が存在すれば、そのローカルブランチがpushされる。

#補足

@yonceさんが書かれているこちらの記事が非常にわかりやすいので、ぜひ参考にしてみてください。
https://qiita.com/yonce/items/b09f35ab301befde7803


`$ git push origin master`　普段pushする時に使っていたこの書き方は
`$ git push origin <PUSHしたいローカルブランチ名>:<PUSH先リモートブランチ名>`の省略形だったんですね。
pushしたいローカルブランチ名とリモートブランチ名を一緒にする場合は省略できるんです。

反対に別名でpushしたい場合は、`:`の後を任意の名前にすればOKです。
最速の開発

# 素早く開発するコツ
無料で利用でき、特に小規模な開発やマークダウンを書く際は[Web版VsCode](https://vscode.dev)が役に立ちます。Chromebookと一緒に使うと相性がよく数秒から数分で目的を達成できることは非常に喜ばしいです。また、ネットが繋がらない環境でも使える点も非常に素晴らしいです。
![Web版のVsCodeスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556644/0c271e0a-ea39-4613-cd08-835d7d424359.png)

# メリット
1. 速く使える
1. Google AppsやNotionなどのWebアプリと相性がいい
1. 無料

# デメリット
1. 多くの言語はデバックできない
1. 日本語UIの非対応(実はGoogle翻訳が起動する場合日本語化します)
1. 中規模開発や大規模開発が苦手(中規模開発以上の場合インストール版やIDEを検討してみよう)
1. シェルが使えない

# 開発オススメの言語
以上を踏まえて以下の言語に特にオススメです。

- javascript
- html
- css
- markdown
- json
- google apps script(コードの検討)

# 使った感想
気がついたときに早く使えるので速度に関するイライラはなくなるが、機能制限や中規模から大規模開発の苦手さやできないこともあるのでその時に応じた使い分けすると非常に良い。
Open ZeppelinのContract Wizardの使い方

## Contract Wizard

[Contract Wizard](https://wizard.openzeppelin.com/#erc721)とは、ERC20、ERC721、ERC1155などのスマートコントラクトの機能をUI上で組み合わせて実装することができるサービスです。

EVMのスマートコントラクト開発言語であるSolidityのセキュアなライブラリ群を提供する[OpenZeppelin](https://openzeppelin.com/)が提供しています。

## Contract Wizardの使い方

[Contract Wizard](https://wizard.openzeppelin.com/#erc721)にアクセスします。

![Screen Shot 2022-01-31 at 23.28.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/b5d99a6a-3426-5be0-601d-5a24d401b52f.png)

Contract Wizardでは

- OpenZeppelinのコードを組み合わせて、ERC20、ERC721、ERC1155などのトークンの実装
- 実装したコードをコピー、ダウンロード、Remixへの連携する

を行うことができます。

今回はNFTの規格としてよく使われているERC721を実装してみましょう。実装するコントラクトのタイプは左上のタブから選択することができます。

## OpenZeppelinのコードを組み合わせてERC721の実装

### Setting

- name: コントラクトの名称です。
- symbol: コントラクトのシンボルです。
- baseURL: アセットのメタデータを管理するURLのベースです。

### info
Security Contactや、ライセンスの情報を載せることができます。

今回はContract Wizardの基本的な使い方についての記事ですので、詳細については割愛します。

Featuresについては後日作成予定の記事、Access Controlについては[こちらの記事](https://note.com/taijusanagi/n/nd4e52784d8c6)、Upgradabilityについては後日作成予定の記事に詳細があります。

チェックボックスによる設定で、コントラクトに実装する機能を選択することができます。

## コードのコピー、ダウンロード

右上のボタンからコードのコピーやダウンロードができます。

![Screen Shot 2022-01-31 at 23.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/b338772b-e6a7-46d2-b1fc-93e79d417050.png)

## Remix IDEとの連携
Contract Wizardで作成したコントラクトはRemix: Ethereum IDEと連携することですぐにデプロイすることができます。Remix: Ethereum IDEの詳しい使い方は[こちらの記事](https://qiita.com/taijusanagi/items/9ce63d64c9f5b4d6b66e)をご参照ください。
AWSロードマップ(EC2基本コンポーネント)

#目次
[1.はじめに](#1-はじめに)
[2.用語](#2-用語)
[3.ドローンでクラウドを利用](#3-ドローンでクラウドを利用)

#1. はじめに
ドローン✖︎クラウドの記事をよく見るけど、どうゆう仕組みで連携してるのか分からなかったので
[AWSロードマップ](https://qiita.com/KurokawaKouhei/items/4e9aa3b526f3f233bf85 "Qiita Home")で勉強をしたいと思います！
(まずはざっくり覚えて徐々に深堀していく、仕事でAWS少し触ったぐらい)

#2. 用語
![スクリーンショット 2022-01-31 21.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2181084/d7802fa3-901f-dbc7-098f-5ed8e98a75e4.png)

###EC2
- 仮装サーバー(1台のサーバーで複数のOSを動かし複数のサーバとして運用する仕組み)
- インスタンスという単位でサーバー環境を構築できる
    - アプリサーバー、データベースサーバーの二つが必要な場合2つのインスタンスを作成
- 構築にかかる時間を短縮、状況に合わせてスペックの変更がしやすい、従量課金制によりコストを抑えやすい

###AMI
- クラウドの仮想サーバーであるインスタンスの起動に必要な情報を提供
- 設定を保存
    - 例えは、ApacheをインストールしたWebサーバーをAMIに保存できる
- デフォルトで用意されたAMIを使う事もできる

###UserData
- 起動後にインスタンスにユーザーデーターを渡し一般的な自動設定タスク、スクリプトを実行可能
- ユーザーデータに機密な情報を格納したらあかん(パスワードやSSHキーとか)

###Instance MetaData
- インスタンスに関するデータで、実行中のインスタンスを設定または管理するために使用
    - インスタンスID, インスタンスタイプ、インスタンスが起動した利用可能ゾーンなどが取れる

###インスタンスタイプ
- m5a.2xlargeのような構成で
    - m = インスタンスファミリー
        - 汎用、コンピューティング最適化、メモリ最適化　、ストレージ最適化、高速コンピューティングの5種
    - 5 = 世代
        - 数字が大きい方が新しい世代で、新しい方が性能が高く安価になっていく傾向
    - a = 追加機能
        - CPUをAMD製に変更した場合、追加機能は「a」など
    - 2xlarge = サイズ
        - nano < micro < medium < small... < 2xlarge

###EBS
- EC2インスタンスに接続して使われるAWSのストレージサービス
- 高い可用性(長く稼働できる)、2つのディスクタイプ(SSD、HDD)から適するタイプを選べる

###EFS
- ファイルストレージサービス(linux)
- 同一リージョンからであれば異なるAZからでもアクセス可能
- 自動スケーリング(自動で容量を拡張可能)
- したい事にあわせてモード(パフォーマンスモード)を選べる
    - 汎用パフォーマンスモード、最大 I/O パフォーマンスモード

###FSx
EFSのWindows対応版。OSがWindowsのEC2で使用

###SSM
- AWSにおけるインフラ(サーバー、ストレージとか)の管理に使用することができるサービス
- EC2インスタンスパッチ管理やソフトのインストール状況の管理などができる

###Keypair
- 公開鍵暗号方式で用いる、公開鍵と秘密鍵の組のこと
    - 公開鍵で暗号化した情報を秘密鍵で復号して認証


#3. ドローンでクラウドを利用
EC2の特徴(サーバーのスペックを状況に合わせて変更可能)でドローンの使用を考えてみた。
(今は浅い情報かもですが、勉強して濃くしていきます)

22年にレベル4(人が居る場所で目視外飛行)が解禁になり物流で本格的にサービス開始されると思う。(なので各社実証実験をしてる)
その際に、気象情報/運行管理(色々なドローン、車ドローン)/映像を見れる管理webアプリなどが必要になりどれだけサービスが大きくなる(ドローンの飛行量とか)か分からんから、EC2でアプリを作れば後で柔軟に対応できそう
CI環境構築はまりごと

# Jenkinsポート周りの設定  
CI環境構築する上で地味にはまった個所を備忘録として残します。
(今後業務で複数のslavePCの設定をする予定なので。。。)

## 展開事項1  
### はまりごと  
Jenkinsマスタサーバの置き換える際に、localhostにつながらなくなった。  
### 原因  
ファイアウォールの詳細設定が必要だが、設定されていなかった。  
### 解決策  
[コントロールパネル]→[システムとセキュリティ]→[Windows Defender ファイアウォール]→[詳細設定]→[受信の規則]→[Jenkins]→[プログラム]に'java.exe'の絶対パスを設定する。  
![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355686/0c189722-6f9c-37cc-c7e6-df760d6131f3.png)

## 展開事項2  
### はまりごと    
slavePCからmasterPCにアクセスできない。  
### 原因  
ポートの設定  
### 解決策  
[ダッシュボード]→[グローバルセキュリティの設定]→[Agents]を'固定','5900'と設定  
![2022-01-31-22-25-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355686/6d90af6a-264a-1f4d-4784-d9c2e2bed176.png)

[ダッシュボード]→[設定]→[Jenkinsの位置]を'http://\<IPアドレス\>/'と設定  
![2022-01-31-23-13-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355686/0f872b1d-d71f-405f-38cc-9046d42e6b23.png)

[Jenkins]→[jenkins.xml]の--httpPortを'5900'と設定    
![2022-01-31-23-21-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355686/32a28658-cdc8-fcfe-d4bb-c3bba62d714f.png)

[コントロールパネル]→[システムとセキュリティ]→[Windows Defender ファイアウォール]→[詳細設定]→[受信の規則]→[Jenkins]のリモートアドレスにMasterサーバへのアクセスを許可するslaveサーバのIPアドレスを追加する。  
![2022-01-31-23-26-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355686/27ff6f07-84f3-9145-5785-bb04caf3c7f8.png)
pythonでdequeの中身を出力するには`*dq`とすればOK

pythonでdequeの中身を出力するには`*dq`とすればOK

```python:test.py
from collections import deque

L = deque()
L.append("a")
L.append("b")
L.append("c")

# deque 1つの場合
print(*(L))

L2 = deque()
L2.append("d")
L2.append("e")
L2.append("f")

# deque 2つ足す場合
print(*(L + L2))

# 上記だと、なぜか空白が一緒にprint()されるので、、、文字列にして空白を削除する
str = "".join(list(L + L2))
print(str)
```

実行

```
$ python test.py 
a b c
a b c d e f
abcdef
```

# 参考

https://note.nkmk.me/python-collections-deque/
foliumと日本の人口データを使ってコロプレスマップを作成してみた

## はじめに
以前の記事で`folium`を使ってコロプレスマップを作成できることはわかったので、今回は実際に日本の人口のデータを用いてコロプレスマップを作成してみました。

以下は以前`folium`を使ってコロプレスマップを作成してみた記事です。

https://qiita.com/zumi0/items/9b28789658e7fae08fbf

## foliumと日本の人口データを使ってコロプレスマップを作成してみた
### 使用したデータ
人口のデータはe-Statよりダウンロードしたものを整形して使用しました。

https://www.e-stat.go.jp/

またコロプレスマップに使用するデータは、以下のリポジトリに上がっている`japan.geojson`を使用させていただきました。

https://github.com/dataofjapan/land

### 実際のコード
```python
# ライブラリの読み込み
import folium
import geopandas as gpd
import pandas as pd

# 人口のデータの読み込み
df = pd.read_csv('./population.csv')
# カラムの型変換
df['population'] = df['population'].map(lambda x: int(x.replace(',','')))

# geojsonの読み込み
geojson_path = "https://raw.githubusercontent.com/dataofjapan/land/master/japan.geojson"
geojson = gpd.read_file(geojson_path)

# 元となる地図の作成
map = folium.Map(
    location=[36.288055, 138.097424],　　# 日本が地図の中心になるように設定、位置は長野県上田市
    tiles='cartodbpositron',
    zoom_start=4)

# 都道府県のデータを描画
folium.Choropleth(
    geo_data=geojson,
    name = 'choropleth',
    data = df,
    columns=['code', 'population'],
    key_on='feature.properties.id',
    fill_color='BuPu',
    fill_opacity=1,
).add_to(map)

map
```
## 結果
![スクリーンショット 2022-02-01 0.26.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/24fbef1c-14d1-1214-4282-3aa797c58de0.png)


## さいごに
今回はfoliumと日本の人口データを使ってコロプレスマップを作成してみました。簡単にできるので、興味のあるひとはぜひ試してみてください。
【TypeScript】TypeScriptとは

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## TypeScriptとは
TypeScriptは、JavaScriptを拡張して作られたプログラミング言語です。
Microsoftによって開発・発表されました。

## 特徴
TypeScriptには以下の特徴があり、大規模開発を効率的に行うことができます。

- JavaScriptとの互換性が高い
- 型定義が可能

### JavaScriptとの互換性が高い
TypeScriptはJavaScriptのスーパーセット（上位互換）であるため、JavaScriptの開発環境や実行環境があれば、すぐに導入することが可能です。

### 型定義が可能
TypeScriptでは変数の型定義が可能です。
型定義をすることで、コンパイルする時点でエラーが分かることや、可読性が高まり、大人数が開発に携わる環境で非常に便利です。
pythonのprint()で改行つけないためには`print("test", end='')`みたいにすればOK

pythonのprint()で改行つけないためには`print("test", end='')`みたいにすればOK

```python:test.py
print("test")
print("test", end='')
print("test", end='')
```

実行

```
$ python test.py
test
testtest
```

以上

# 参考

https://techacademy.jp/magazine/22292
[Go] Structs

# Structs とは

`Go` には関連する情報をまとめするため、 `structs` が使われる

# Defining and Declaring

```Go
package main

import "fmt"

type person struct {
	firstName string
	lastName  string
}

func main() {
	var aaa person
	fmt.Println(aaa) // The default value is a empty string.
	fmt.Printf("%+v\n", aaa) // Use the "%+v" can print the fields also.

    // Updating Struct Values
    aaa.firstName = "aaa"
    aaa.lastName = "player"
}
```

# Embedding Structs

`Structs` に `structs` も宣言できる

```Go
package main

import "fmt"

type contactInfo struct {
	email   string
	zipCode int
}

type person struct {
	firstName string
	lastName  string
	contact   contactInfo
}

func main() {
	aaa := person{
		firstName: "aaa",
		lastName:  "player",
		contact: contactInfo{
			email:   "aaa@mail.com",
			zipCode: 1234567,
		},
	}
	fmt.Println(aaa)
}
```

宣言するときに、 `contactInfo` だけを宣言すると

`contactInfo contactInfo` の書き方と同じになる

```Go
type contactInfo struct {
	email   string
	zipCode int
}

type person struct {
	firstName string
	lastName  string
	contactInfo
}
```

# Updating Struct Values

```Go
package main

import "fmt"

type player struct {
	name  string
	score int
}

func main() {
	a := player{"aaa", 0}
	fmt.Println(a)
	a.updateScore(1)
	fmt.Println(a)
}

func (p player) updateScore(s int) {
	p.score = s
}
```
```zsh:output
{aaa 0}
{aaa 0}
```

上記の`updateScore` functionを使っても`a`のスコアが更新できない

## Pass By Value

`Go`は`Pass By Value`なので、下記のように

|address|value|note|
|---|---|---|
|0001|{aaa 0} 元のa値|更新されなかった|
|0002|||
|0003|{aaa 0} コピーされた値|funcがこの値を更新した|

元の`a`のスコアが更新されなかった

## Pointer

|address|value|
|---|---|
|0001|{aaa 0}|

Turn ___address___ into **value** with `*address`

Turn **value** into ___address___ with `&value`

## Point Receiver

ReceiverのTypeに*を追加することで

`(p *player)`

宣言するtypeはstruct playerではなく、struct playerのaddressになる

そうすれば、struct `a`のaddressのvalueをpassでき

元の`a`の値を更新できるようになる

```Go
package main

import "fmt"

type player struct {
	name  string
	score int
}

func main() {
	a := player{"aaa", 0}
	fmt.Println(a)

	pointerA := &a // Turn value into address
	pointerA.updateScore(1)
	fmt.Println(a)
}

func (p *player) updateScore(s int) {
    // Turn value into address
	(*p).score = s
}
```

```zsh:output
{aaa 0}
{aaa 1}
```

ちなみに、

aのvalueをadressに転換しなくても、`Go`も処理してくれる

```Go
package main

import "fmt"

type player struct {
	name  string
	score int
}

func main() {
	a := player{"aaa", 0}
	fmt.Println(a)

	a.updateScore(1) // Use a, the player struct type
	fmt.Println(a)
}

func (p *player) updateScore(s int) {
	(*p).score = s
}
```

結果も同じ

```zsh:output
{aaa 0}
{aaa 1}
```
データサイエンス

自分用のメモです。

■AIとは何か？

・AI：Artificial Inteligence（人工知能）の略

・「人間と同様の知能を実現させようとする技術」と言われているが、厳密な定義は存在しない

・「機械学習」や「ディープラーニング」はAIの一種


■機械学習・ディープラーニングとは何か

・機械学習
　•AIの一種
　•データからパターンを学習し、タスクを実行するもの
　•主に人が特徴を定義（薔薇とは赤くて棘があって・・・）

・ディープラーニング
　•機械学習の一種と言われることが多い
　•人間の脳の神経細胞（ニューロン）を模した学習法から発展
　•主にコンピュータが特徴を自動定義


■機械学習は大きく3つ

・教師あり学習
　•答えあり学習
　•入力データと出力データがセット
　•未知の入力から出力を予測：回帰と分類

・教師なし学習
　•答えなし学習
　•入力データのみ
　•データの構造を把握：グループ分けやラベル付に利用

・強化学習
　•報酬を最大化できる一連の行動を学習
　•ボードゲームや歩行ロボットなど


■機械学習を活用する上での注意点

・機械学習はあくまでも「手段」
　•目的になってはいけない
　•課題解決をする上で「適切な」分析をする必要がある

・実際は前処理が大変
　•garbage in garbage out
　•生のデータって想像以上に汚い
　•そもそも必要なデータがないなんてことはザラ


■機械学習の概要まとめ

・AIが「人間と同様の知能を実現させようとする技術」だが、厳密な定義は存在しない

・「機械学習」や「ディープラーニング」はAIの一種

・機械学習は教師あり学習・教師なし学習・強化学習の3種類

・機械学習は手段であり、前処理が大変


■回帰分析の概要→教師あり学習に含まれる

・回帰モデル（連続値を扱い、予測する）

・機械学習としてのアプローチと統計解析としてのアプローチがある
　•機械学習：未知の入力データから出力データを予測する
　•統計解析：入力データと出力データの傾向を把握する

・プロットした散布図のデータから回帰直線を引き、「このような傾向があります」と言えるのが回帰分析

・用語の確認（部屋の広さから家賃を予測する例）
　•目的変数：予測したい変数（家賃）
　•説明変数（特徴量）：予測に使うための変数（部屋の広さ）
　•単回帰分析：説明変数が1つ
　•重回帰分析：説明変数が複数
AOJトライに関する知識知見の記録共有：ITP2_11_D

# タスク概要

Enumeration of Combinations

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP2_11_D
 
# コード実装例
TIPS

1. 例外処理含む評価パターンを追加

```Python
import pprint, sys, time
import itertools

def agg(lst):
    return sum([2**v for v in lst])

def core(arg, adv=True, n_ret=10):
    ret = []
    n = arg[0]
    k = arg[1] if len(arg) > 1 else int(n/2)
    
    if adv:
        ret = sorted([[agg(array), array] for array in itertools.combinations(range(n), k)], 
                key=lambda x: x[0])[:n_ret]
    else:
        for array in itertools.combinations(range(n), k):
            ret.append([agg(array), array])
        ret = sorted(ret, key=lambda x: x[0])[:n_ret]

    return ret

def app(*args):
    ret = []
    for arg in args:
        s = []
        for adv in [True, False]:
            st = time.time()
            try:
                r = core(arg, adv=adv)
            except Exception as e:
                r = e
            s.append([adv, round(time.time() - st, 6), r])
        ret.append([arg, s])
    return ret

print(sys.version)
pprint.pprint(app(
    # basic examples
    [5, 3],
    # additional examples
    [5],
    [20, 5],
    # exceptional examples
    "例外入力"
))
```

# 実行結果
各種補足情報出力（入力値FB、デバッグログ等）含む

```Python
3.8.10 
[GCC 9.3.0]
[[[5, 3],
  [[True,
    2.5e-05,
    [[7, (0, 1, 2)],
     [11, (0, 1, 3)],
     [13, (0, 2, 3)],
     [14, (1, 2, 3)],
     [19, (0, 1, 4)],
     [21, (0, 2, 4)],
     [22, (1, 2, 4)],
     [25, (0, 3, 4)],
     [26, (1, 3, 4)],
     [28, (2, 3, 4)]]],
   [False,
    9.2e-05,
    [[7, (0, 1, 2)],
     [11, (0, 1, 3)],
     [13, (0, 2, 3)],
     [14, (1, 2, 3)],
     [19, (0, 1, 4)],
     [21, (0, 2, 4)],
     [22, (1, 2, 4)],
     [25, (0, 3, 4)],
     [26, (1, 3, 4)],
     [28, (2, 3, 4)]]]]],
 [[5],
  [[True,
    1.8e-05,
    [[3, (0, 1)],
     [5, (0, 2)],
     [6, (1, 2)],
     [9, (0, 3)],
     [10, (1, 3)],
     [12, (2, 3)],
     [17, (0, 4)],
     [18, (1, 4)],
     [20, (2, 4)],
     [24, (3, 4)]]],
   [False,
    1e-05,
    [[3, (0, 1)],
     [5, (0, 2)],
     [6, (1, 2)],
     [9, (0, 3)],
     [10, (1, 3)],
     [12, (2, 3)],
     [17, (0, 4)],
     [18, (1, 4)],
     [20, (2, 4)],
     [24, (3, 4)]]]]],
 [[20, 5],
  [[True,
    0.03452,
    [[31, (0, 1, 2, 3, 4)],
     [47, (0, 1, 2, 3, 5)],
     [55, (0, 1, 2, 4, 5)],
     [59, (0, 1, 3, 4, 5)],
     [61, (0, 2, 3, 4, 5)],
     [62, (1, 2, 3, 4, 5)],
     [79, (0, 1, 2, 3, 6)],
     [87, (0, 1, 2, 4, 6)],
     [91, (0, 1, 3, 4, 6)],
     [93, (0, 2, 3, 4, 6)]]],
   [False,
    0.030134,
    [[31, (0, 1, 2, 3, 4)],
     [47, (0, 1, 2, 3, 5)],
     [55, (0, 1, 2, 4, 5)],
     [59, (0, 1, 3, 4, 5)],
     [61, (0, 2, 3, 4, 5)],
     [62, (1, 2, 3, 4, 5)],
     [79, (0, 1, 2, 3, 6)],
     [87, (0, 1, 2, 4, 6)],
     [91, (0, 1, 3, 4, 6)],
     [93, (0, 2, 3, 4, 6)]]]]],
 ['例外入力',
  [[True,
    1.6e-05,
    TypeError("'str' object cannot be interpreted as an integer")],
   [False,
    3e-06,
    TypeError("'str' object cannot be interpreted as an integer")]]]]
```

# 補遺
残課題（Pull Request絶賛募集中！）

1. 実行速度の改善（枝刈り、データ構造の見直し等）
1. コア関数の汎用化
srcset属性はIE11非対応……だけどsrcがフォールバックになるから使ってしまおう

## この記事の概要

「srcset属性使おうかなと思ったんですけど、IE11が非対応だから使えなくて……。」

という会話があったのですが、使っても良いのでは？と思ったので記事にしました。

## そもそも`srcset`とは

`img`要素や`picture`要素に対して、複数のソースを指定できるものです。

[MDN Docs](https://developer.mozilla.org/ja/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#how_do_you_create_responsive_images)よりコードを拝借しますが、以下のような書き方ができます。

```html
<img srcset="elva-fairy-320w.jpg 320w,
             elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="妖精の衣装を着たエルバ">
```

若干簡略化して説明すると

1. 色々なサイズの画像を用意し`srcset`に指定する
1. ウィンドウサイズがいくつのときは画像がどのサイズか、といった条件を`sizes`に指定する
1. 条件を満たす範囲で1番小さな画像が読み込まれる
1. モバイル画面に対して何千pxもあるような大きな画像を読み込まなくなってパフォーマンスアップ

といった具合で使えます。

どんな条件でどの画像が選ばれるかの説明は、以下の記事が分かりやすいと思います。

https://qiita.com/dowanna6/items/b9e132b4c56e67491027

## Can I use...

ここからがタイトルの内容です。
Can I use...を見てみましょう。

https://caniuse.com/srcset

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/0df33d57-a5f3-26cb-9af2-0ed474eb68e0.png)

はい、IEは非対応です。

ですが、`srcset`が非対応だからと言って`srcset`を指定した`img`要素がまるっと表示できない訳ではありません。[^1]
`img`の中の`srcset`は理解できないけど、`src`があればそちらを読みに行きます。

[^1]: `picture`要素は要素そのものがIEに非対応なので、駄目です。 https://caniuse.com/picture

まとめると以下の表のようになり「全員に不適切な読み込み速度を提供するくらいなら、一部の人[^2]だけにでも良い読み込み速度を提供した方が良い」と言えるのではないでしょうか。

[^2]: [Statcounter](https://gs.statcounter.com/browser-market-share/all/japan/#monthly-202012-202112)によれば2021年12月時点で、日本のIE以外利用者は98%程度でした。一部の人という言い回しも不適切ですが便宜上こう表現しています。

| | srcsetを使う場合 | srcsetを使わない場合 |
| --- | --- | --- |
| IE以外のブラウザを使っている人に | 最適な画像読み込みを提供できる | デバイスサイズなどに関係なく大きな画像を提供してしまう |
| IEを使っている人に | デバイスサイズなどに関係なく大きな画像を提供してしまう | デバイスサイズなどに関係なく大きな画像を提供してしまう |

## まとめ

- IE非対応の属性とは言え、img要素にsrcsetを使うのは（フォールバックが効くので）良いと思われる
- ただしpicture要素は要素そのものが非対応なので辞めておくかポリフィル利用を検討する方が安全そう
Elasticsearch::Modelのresultsとrecordsメソッドの違い

elasticsearchをなんとなく触っていたら、勘違いしてハマったので記事として残します。

## resultsとrecordsメソッドの違い
結論から書くとresultsメソッドはelasticsearchのドキュメントを返しますが、recordsメソッドはデータベースから取得したモデルインスタンスのコレクションを返します。

```
response = Article.search 'sample'

response.results.map { |r| r._source.title }
# => ["sample article 1", "sample article 2"]

response.records.to_a
# Article Load (0.3ms)  SELECT "articles".* FROM "articles" WHERE "articles"."id" IN (1, 2)
# => [#<Article id: 1, title: "sample article 1">, #<Article id: 2, title: "sample article 2">]
```
仮に```<Article id: 1, title: "sample article 1">```のレコードは削除したが、elasticsearchのドキュメントは削除していない状態だと、

```
response = Article.search 'sample'

response.results.map { |r| r._source.title }
# => ["sample article 1", "sample article 2"]

response.records.to_a
# Article Load (0.3ms)  SELECT "articles".* FROM "articles" WHERE "articles"."id" IN (1, 2)
# => [#<Article id: 2, title: "sample article 2">]
```

recordsメソッドではデータベースから取得した情報を返すので削除されたレコードは結果に返ってきませんが、
resultsメソッドだとelasticsearchのドキュメントを削除していないため削除されたレコードの結果も返ってきてしまいます。

ちなみに二つのメソッドの使い分けですが、基本的にはresultsメソッドを使ってモデルのメソッドにアクセスしたいときのみrecordsメソッドを使うとよさそうです。

## 参考
https://github.com/elastic/elasticsearch-rails/blob/main/elasticsearch-model/README.md
Google ColabからGithubを使ってみた

Google ColabでGitHubを使う方法
Gitコマンドについては[こちら](https://qiita.com/tuk19/items/fe5edeb35a6512465784)にまとめています。

# Google ドライブをマウント
1. Googleドライブをマウントする。
2. git管理したいディレクトリを作成し移動する。

```python:ディレクトリに移動
%cd 'gitを導入するディレクトリまでのパス'
```

# Git Cloneする
```python:Git_Clone
!git clone https://github.com/リポジトリ名.git
# Cloneしたディレクトリへ移動
%cd 'ディレクトリ名'
```

# ユーザ名とメールアドレスを設定
```python:設定
!git config --global user.email "メールアドレス"
!git config --global user.name "ユーザー名"
```

# ブランチ操作
```python:ブランチを切って移動
!git checkout -b develop
>> Switched to a new branch 'develop'
```

# ログの確認
```python:log
!git log
```

# コミットしてpush
```python:add~commit~push
!git add -A
!git commit -m "コミット名"
# ユーザー名とアクセストークンが必要
!git remote set-url origin https://ユーザー名:アクセストークン@github.com/リポジトリ名.git
!git push origin develop
```

# Reset
ブランチを切る前にmasterにpushしてしまったので。
本当はRevertのほうがいいけど、masterがごちゃごちゃすると嫌だなぁと思ってしまったためReset（自分しか使わないし）。
チームで開発するときはRevertしましょう。

```python:Reset
!git reset 戻したいcommitID --hard
!git push origin master -f
```

これでGit管理しながらGoogle ColabでAI開発ができるようになりました！

# weightが重すぎてpushできない問題
モデルのパラメータを保存したweightフォルダ内のファイルが400MBあり、Gitにpushできなかった。
すでにcommitしているので、とりあえず戻す。

```python:reset--soft
!git reset 戻したいcommitID --soft
```

commitを戻しただけでaddはされているので、weightフォルダのファイルをaddから除く。

```python:rm
!git rm --cached -r  取り除くファイルのパス
```

次回以降、git管理しないように.gitフォルダと同じ階層に.gitignoreファイルを作成。
今回はとりあえずweightフォルダ全てをgit管理からはずすようにする。

```python:gitignore
/weight
```

あとは通常通りcommitしてpushする。

```python:commit~push
!git commit -m "コミット名"
!git push origin develop
```


# 参考資料
[Google Colab上でGitHubからCloneして変更をPushするまでのまとめ](https://qiita.com/kurilab/items/f6f4374d7b1980060de7)
pixivの小説作品のURLからテキストを保存する

# どうして作ったの？

**※あくまでブラウザ内で確認するのが難しいテキスト情報を手元で確認するためのツールとしての利用を想定しています**

TRPGの一つ、CoC（コールオブクトゥルフ）を最近頻繁にプレイしていてページ内だけで確認するのが手間だな・・・と思ったので作りました
pixivで一般公開されている名作のシナリオのテキスト量は膨大で、数十ページにおよぶためpixivサイト内だけで情報を確認することは難しい！
ということでpixivの小説作品のURLから本文のテキストだけを抽出するコードを作ってみました

# 環境
* Google Colab

# ざっくりやってること
* seleniumを使って仮想ウェブブラウザを構築
* html内のタグ情報を使って本文のテキストを取得
* ページ遷移をさせつつ、リダイレクト後に同じページに飛ばされたらwhile文をbreakしてファイルを出力する

# ソース

## Colabへの環境構築

```shell
!pip install selenium
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
```

## ライブラリの読み込みと環境設定

```python
import urllib.request
from bs4 import BeautifulSoup
import time
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
```

## 関数

```python
def main(url):
  lists = []
  idx = 1
  while True:
    browser = webdriver.Chrome('chromedriver',options=options)
    search_url = f'{url}#{str(idx)}'
    res = browser.get(search_url)
    time.sleep(1)
    current_url = browser.current_url
    print(idx)
    print(search_url)
    print(current_url)
    # リダイレクトが発生した際に同じURLに転送された場合処理を終了する
    if search_url != current_url:
      if idx == 1:
        pass
      else:
        break
    source = browser.page_source.replace("<br>", "\n") # レイアウト上の改行要素を事前にテキスト用に変換しておく
    soup = BeautifulSoup(source, 'html.parser')
    sentences = soup.find_all('p', attrs={'class': 'sc-dIvrsQ leiCDy'})
    for sentence in sentences:
        # 文字部分のみを抽出する
        sentence = sentence.get_text().replace("\r", "").replace("\u3000", "")
        lists.append(sentence)
    idx += 1
  lists = '\n'.join(lists)
  return lists
```

## 呼び出し例

```python
url = 'https://www.pixiv.net/novel/show.php?id=16394819'
lists = main(url)
print(lists)
```
* このあとは好きにテキストファイルに保存するなりコピペするなりできます

## 終わりに

**良きCoCライフを！！！**

個人的にリダイレクトを待つコードの位置を間違えてリダイレクト前のURLを一生参照していたのが最初は何故か分かりませんでしたが気づいてしまったら綺麗に動いてくれて一安心
一応pixiv小説とかにも汎用性があるコードになっているはずですが、pixivさんのサイト仕様の変更に伴って利用できなくなると思うのでニーズがあれば更新いたします
データ分析未経験者が社内データ分析コンペに出場してわかったこと

# はじめに
昨年末から今年頭にかけ，会社でデータ分析推進部署主催の社内の実データを使ったデータ分析のコンペがあり，未経験ながらも興味があったので**本物のデータを使ってデータ分析を実体験できるチャンス**と捉えて参加しました．
コンペの振り返りと頭の整理のために**自分なりに理解したデータ活用・分析のイメージ**をまとめます．

注) 初心者が振り返りも含めて自分の言葉でまとめたものなので間違い等あるかと思います．何か問題点・間違い等ありましたらコメントいただけますようよろしくお願いします．

# 参加したデータ分析コンペの概要
データや評価内容の詳細は載せられませんが，当たり障りの無いレベルでざっくりと今回参加したコンペの概要をまとめます．

- **目的:**データ活用が可能な人材の育成 ＋ 社内業務へのフィードバック
- **参加者：**自分で参加したいと応募した人(データ分析・活用の経験問わず)
- **利用データ：**社内業務で収集した実データ(正解あり)
- **データ形式：**表形式データ
- **予測対象**:複数分類(グループ分け)
- **期間：**3週間
- **コンペ環境：**社内IT部門等の関係部署が協力して専用環境を構築

# わかったこと
今回参加したコンペは正解ありの教師あり学習で予測精度を競ったため，教師あり学習を前提にわかったことをまとめます．
  
### データ分析・活用とは？
ある定まったフォーマットのデータをインプットに欲しい結果を予測・判断できる数式的なもの(データ活用の世界ではモデルと言う)を作成し，必要なデータを準備すれば誰でも一定のレベルで今後の予測や判断ができるようにすること．

- **インプットと予測の例：**天気・温度・湿度・曜日 → 入場者 や 売上高 の予測 など
- **インプットと判断の例：**画像 → 文字の識別 や 偽札の判定 など

### データ分析コンペとは？
企業などがスポンサーになり，所有するデータと予測したい内容を提示して，予測に使える計算式を参加者に作成してもらい予測精度を競いあう大会．参加者が作成した計算式に予測したい内容をマスキングしたデータを投入し，予測結果の精度を競いあう．上位入賞者には賞金が支払われるものもあり．
有名なデータ分析コンペとして Kaggle がある．

### データ分析をする環境
データ分析はPythonを使うのが一般的．
PythonとVisualStudioCodeと関連する拡張機能をPCにそれぞれインストールして環境構築することもできる．処理速度はPCのスペックに依存するので大規模な分析には不向き．
GoogleはGoogleアカウントがあれば無料で利用できるブラウザベースのデータ分析環境を提供している．簡単な分析ではストレスなく利用できた．大規模な分析では？？？
データ分析コンペで有名なKaggleでは，Kaggle内にデータ分析環境があり利用可能．簡単な分析ではストレスなく利用できた．大規模な分析では？？？
AWSのSavgeMaker等のSaaSもあり．AWSの場合，利用するインスタンスを選択できるようなので必要に応じてリソースを選択することが可能．ただし，大規模リソースを利用すればその分コストは増加することにつながるのでリソースサイズの検討が必要になりそう．

### モデルの作り方
インプットデータの形式と予測したいものによって，この手法を使えばだいたいOK，という指針がある．
それぞれの手法はpythonのライブラリで提供されているので，作りたいモデルを指定して学習用データを動作パラメータを設定すれば予測するモデルを作成してくれる．
手法ごとにパラメータが違う．パラメータチューニングで予測精度が上がったり下がったりする．

### モデル学習用データの準備方法
コンペでは提供されたデータを学習用データ(参考書)と評価用データ(模擬試験)に分けて，学習用データで勉強→評価用データで正解率の確認をしてモデルの精度を上げていく．
学習用データ(参考書)と評価用データ(模擬試験)の準備方法にもいろいろあり，初めに比率で分けてそれを使い続けるホールドアウト法や，全データで学習用データ・評価用データの組み合わせを網羅する交差検証などの手法がある．

### 予測精度を上げるには？
インプットデータと結果の間で影響度が高いインプットがどれか？を見つけ出すのが重要．
インプットと結果の関係性を推測するのも重要．
物理現象が絡む場合は，データの物理現象の意味を知ることも必要．
インプットと結果は1:1の関係ではなく，N:1で関係しあっている場合が多いので，複合的に関係性を見つけ出す必要あり．
インプットのデータの特徴をより如実に表すようにインプットデータを加工する必要あり．
加工方法の例：対数をとる，平均値/中央値/標準偏差

# コンペの結果と感じたこと
今回のデータ分析コンペでは，インプットデータの加工はガイド通りの加工にとどまり，何種類かのデータ分析モデルを実装して精度比較をしましたが，ある一定の精度で頭打ちとなってしまいました．
コンペの上位者のコメントを聞くと，インプットデータと予測対象との関係性に着目してインプットデータの特徴を表すように加工することに注力したとのことで，やはりモデル作成の前の人間によるデータ分析や推論が重要であると実感しました．

# まとめ
データ分析を実際に手を動かして体験しながら学んだことで，実は手の届く世界の技術であることがわかり大変有意義な経験をすることができました．
とは言え，データ活用をがっつり使うには数学的知識や統計学の知識などの知識は弱いなということを実感したので，ちょっとずつでも勉強していきたいな．
あと，良いデータ活用をするには実際の業務背景や業務モデル，対象の物理現象などを理解しないといけないということも聞きましたが，ここらへんはシステム開発と一緒ですね．


最後に，このような機会を作ってくれたコンペ企画・運営をしていただいた方々，本当にありがとうございました．

###補足
2022年の目標である「外に発信をしよう」の第一歩として，初めての記事投稿をしてみました．自分で分かったつもりでいることでも，文章にまとめるのは難しいですね．
AWS ELB (Elastic Load Balancing)についてまじで簡単にまとめてみた

## はじめに
SAA対策の中で特に私がいつもつまずいてしまうところをまとめておく。

多分以下のような観点が特に自分は弱いと分析している。
- レジリエントアーキテクチャの 設計
- セキュアなアプリケーションと アーキテクチャの設計

ちょっとあまり理解できてなさそうなサービスをまとめておく。

まずはELBについて。

## Elastic Load Balancingについて
ELBと略される。
ELBは、受信した通信を指定した複数の宛先に自動的に負荷分散をしてくれるもの。
このELBを使用することによって、耐障害性を高めることができ、万が一システムに障害が発生したときにサービスへの影響を最小限に抑えることができる。

### ELBの特徴
```
- ロードバランサーにはDNS名のアクアセスポイントが付与される。
- ヘルスチェック機能がある。
- SSL/TLS通信の終端になる。
```

### ELBの種類
ELBには3つ種類がある。

①ALB Application Load Balancer
②NLB Network Load Balancer
③CLB Classic Load Balancer

③のCLBは古いタイプのロードバランサーらしく、現在は非推奨となっている。
基本的にはALBかNLBを選択することになる。

###  ALB
このALBはL7レイヤー(HTTP/HTTPS)の負荷分散に使用される。
SAAの試験では、よくこの「L7レイヤーで使用する・・・」みたいな問題が出題されている気がするので覚えておきたい。
主にこのALBはユーザーからのアクセスを受け付けて、配下のサービス(例えばEC2やLambda)に負荷分散するために使用される。

### NLB
NLBはL4レイヤー(TCP/UDP/TLS)の負荷分散に使用される。
基本的にはAWS内部で負荷分散が必要な際に使用され、ALBと組み合わせて使用されることもある。

NLBの特徴としてはこのようなものがある。
- 高可用性
- 高スループット
- 低レイテンシー
要するに、停止しづらく、処理可能なデータ量が多く、データの転送をするときに遅延が少ないということ。

NLBの特徴としては急激なアクセス増加でも自動的にスケーリングしてくれるためエラーは発生しない。
対して、ALBを使用していた場合は503エラーが出てサービス利用不可となる可能性もある。らしい。

##  ELBの特徴のヘルスチェックについて
```
- ロードバランサーにはDNS名のアクアセスポイントが付与される。
- ヘルスチェック機能がある。
- SSL/TLS通信の終端になる。
```
この3つの特徴の中の、ヘルスチェックについてまとめておく。

そもそもヘルスチェックとは、ELBで複数のEC2に負荷分散をするときにEC2が停止していたらどうだろう。
ELBのヘルスチェックは、このターゲットグループに所属している``EC2が正常に動いているかどうか``を確認してくれる機能。

### ヘルスチェックの流れ
ヘルスチェックは次のような流れで動いているらしい。(NLBの場合)

```
①NLBはターゲットグループに所属しているターゲット(EC2)にヘルスチェックのためのpingを実行する。

②ヘルスチェック３回連続失敗をすると、NLBはターゲットのステータスを「Unhealthy」に変更をする。そのあと、Unhealtyのターゲットにはアクセスを振り分けることはしない。(ちなみにヘルスチェックの回数は変更可能)

③サービス停止中のターゲットに対しても定期的にヘルスチェックしていく。

④サービス停止中のターゲットに対してpingが3回連続成功すると、NLBはターゲットのステータスを「Healthy」に戻し、アクセスの割り振りを再開する。
```

このような流れでヘルスチェックは行われている。
【C言語】Windowsでmakeを行う　初心者向け

# 自身の環境
- Windows10
- GNU make 3.81
- gcc 9.2.0

# はじめに
この記事はC言語を勉強しはじめたばかりの人にむけてコンパイルの手間を少しでも省けて学習に集中できるのではないかという思いで書いてます。

※gccでC言語の開発環境が構築済みであることが前提です。

# 1.GNU makeをインストールする
下記のサイトからインストーラーをダウンロードする
[Make for Windows ダウンロードサイト](http://gnuwin32.sourceforge.net/packages/make.htm)

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642219/72ee8487-acc4-9acb-6932-c2750ef9c56a.png)

上記画像の「Setup」をクリックすれば、ダウンロードできます。
ダウンロード後インストーラーを起動してインストールを行ってください。

※環境設定などの説明は省きます。

インストール後

コマンドプロンプトで「make -v」を入力し、下記のような結果になったら成功です。


```コマンドプロンプト
C:>make -v
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
これはフリーソフトウェアです. 利用許諾についてはソースを
ご覧ください.
商業性や特定の目的への適合性の如何に関わらず, 無保証です.

This program built for i386-pc-mingw32
```

# 2.プログラムを用意
テストプログラムを適当に用意します。

複数ファイルをコンパイルしたいので複数のファイルを用意します。

まずはmain関数です。

今回は別ファイルの関数を呼び出す処理です。
test_1,test_2,test_3の３つの関数を呼び出します。

```test.c
#include <stdio.h>
#include "test_Prot.h"

int main(void){

    printf("test make\n");

    test_1();
    test_2();
    test_3();

    return 0;
}
```

次にヘッダファイルを作成します。
さきほどのtest.cファイルですでにincludeされていたのはこのためです。

呼び出し関数のプロトタイプ宣言を行います。

```test_Prot.h
/* プロトタイプ宣言 */
void test_1(void);
void test_2(void);
void test_3(void);
```

各ファイルを作成し関数の中身を記載しておきましょう。

今回は簡単にテキストを表示するだけの処理です。

```test_1.c
#include <stdio.h>

void test_1(){

    printf("test_1\n");

    return;
}
```

上記の要領で「test_2.c」「test_3.c」を作成し処理を記載しましょう。


# Makefileを作成

拡張子がないファイルを用意してください。

例えば、上記で用意したtest.cをコピぺしてファイル名を変更して拡張子を消しても作れるます。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642219/50bd4d48-18e7-bf80-3cd6-cd8741a7c1cd.png)

ファイル名は[Makefile]にしてください。

Makefileの中身を記載します。
今回は初心者がすぐ使えることを目的としているためコンパイルオプションはなるべく設定せず簡略表記もしないよう記載します。


```Makefile.
CC := gcc

test:test.o test_1.o test_2.o test_3.o
	gcc -o test test.o test_1.o test_2.o test_3.o

test.o:test.c test_Prot.h
	gcc -c test.c

test_1.o:test_1.c
	gcc -c test_1.c

test_2.o:test_2.c
	gcc -c test_2.c

test_3.o:test_3.c
	gcc -c test_3.c
```

CC := はコンパイラーを指定するコンパイルオプションです。
gccを使用するためgccとなってます。

複数ファイルをコンパイルするときのコマンドをそのまま記載しているイメージで大丈夫です。

上の４行を簡単に説明すると

test:test.o test_1.o test_2.o test_3.o
__test.exeを作成するに必要なオブジェクトファイルは「test.o test_1.o test_2.o test_3.o」ですよ。__
	gcc -o test test.o test_1.o test_2.o test_3.o
__↑のコマンドでtest.exeを作成しますよ。__

test.o:test.c
__test.oを作成するのに必要なファイルはtest.cですよ。__
	gcc -c test.c
__↑コマンドでtest.oを作成しますよ。__


# makeを実行

ソースとMakefileが格納されているディレクトリに移動してmakeコマンドを実行します

```コマンドプロンプト.
C:\dir>make
gcc -c test.c
gcc -c test_1.c
gcc -c test_2.c
gcc -c test_3.c
gcc -o test test.o test_1.o test_2.o test_3.o
```

上記にような表示になるはずです。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642219/276b6d1a-d504-bb6f-d0e7-b95b1e24512e.png)

ディレクトリ内に各ソースファイルのオブジェクファイルとexeファイルが生成されていれば成功です。
※再度makeするにはソースファイルを更新する必要があります。

ついでにプログラムも実行して確認してみましょう。
記事通りに作成すると以下のように表示されます。

```コマンドプロンプト.
C:\dir>test
test make
test_1
test_2
test_3
```

以上
expectコマンドを使ったadduserの自動化


EC2のユーザデータでadduserコマンドを使いたいが対話モードで入力が必要。そこでexpectコマンドを使って自動で対話モード入力を行ってみることにした。expectコマンドを使ったスクリプト`script.sh`を作成する。`script.sh`を作成した後、chmodで実行権限を付与するのを忘れないこと。

```bash
chmod +x script.sh
./script.sh
```

`script.sh`の中身は以下の通り。以下の例ではユーザ名が「test123」、パスワードが「test」としている。パスワード入力後に少し待たないとうまくいかないので、`set timeout 3`を入れている。

```sh:script.sh
#!/bin/bash

expect -c "
spawn sudo adduser test123
expect \"New password:\"
send \"test\n\"
expect \"Retype new password:\"
send \"test\n\"
set timeout 3
expect \"Full Name []:\"
send \"\n\"
expect \"Room Number []:\"
send \"\n\"
expect \"Work Phone []:\"
send \"\n\"
expect \"Home Phone []:\"
send \"\n\"
expect \"Other []:\"
send \"\n\"
expect \"Is the information correct? \[Y\/n\]\"
send \"Y\n\"
interact
"
```
【ssh, git, windows10】ssh githubしたらエラーが出た。Bad owner or permissions on /Users/hoge/.ssh/config の解決方法

###ssh githubしたらエラーが出た

```gitbash:gitbash
ssh github
```

##結論
エクスプローラーで.sshフォルダを右クリック⇒プロパティ⇒セキュリティタブから
あーだこーだして解決

面倒くさい人はconfigを消してもエラーは無くなる。(本末転倒)

Mac, Linuxの人はchmod 600すれば良いと思う

##前提
・Windows10だからchmodできない
・ssh鍵作った
・.sshフォルダにconfig作った

:::note info
この記事の中に出てくる「C:\Users\hoge\.ssh\github」の
    hoge ⇒ 自分のWindowsユーザー名
    github ⇒ ssh鍵のファイル名
この記事の中に出てくるssh githubの
    github ⇒ configのHost
に置き換えてください
:::

```config:.ssh/config
Host github
    HostName github.com
    IdentityFile C:\Users\hoge\.ssh\github
    User git
```

##ssh githubするとエラー
```
ssh github

Bad owner or permissions on C:\\Users\\hoge/.ssh/config
```
#解決方法
### 1.エクスプローラーで.sshフォルダの前まで行き、.sshフォルダを右クリック ⇒ プロパティ
![explorer_WtygSY0vo2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/d8f26032-ec35-286c-e81b-7b957ee481f2.png)

:::note info
.sshフォルダがどこにあるか分からない人は、とりあえずCドライブ ⇒ ユーザー ⇒ hogeをチェック
:::

### 2.上　セキュリティタブ ⇒ 下 詳細設定をクリック
![Code_0GoK2wlhR4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/1465a010-1d70-f82f-79a9-7febc075c61b.png)

### 4.左下　継承の無効化をクリック
![explorer_YLaREob0Dd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/28be9e32-4355-db53-8c18-e9ed8fe7ae52.png)

### 5.継承の無効化を押すとワーニングが出るため、下の選択肢を選ぶ(継承された権限の削除とか書いてあると思う)
![chrome_3kAyKRqyne.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/1b5b1e50-f356-60dd-251e-7f6bbef60157.png)

### 6.アクセス許可エントリ: が空になる(なんか色々出てたユーザー一覧が空に)

### 7.継承の無効化の上にある、追加をクリック

### 8.上　青文字、プリンシパルの選択をクリック
![Code_fDOBrtfYJA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/dbb8cad0-12d9-b469-22b9-b5c29983dc31.png)

### 9.左下　詳細設定をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/19bca526-8c91-0084-9143-bffb9806cc42.png)

### 10.中央右　検索をクリックすると、下の検索結果にユーザー一覧が出る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/4a5ccb92-3328-f3e9-9eff-13cceff85ba0.png)

### 11.ユーザー一覧の中から自分のユーザー名を選ぶ。その後、OKですべてのウィンドウを閉じる

## ssh githubしてみる

```gitbash:gitbash
ssh github
Hi hoge! You've successfully authenticated, but GitHub does not provide shell access.
```

私の環境ではうまくいきました。

##補足
このままだと.sshフォルダにファイルの作成・ファイルの変更等が行えない。

6.のアクセス許可エントリにある、11.で追加したユーザーをダブルクリックすると、
8.のプリンシパルの選択～とかが出てくる。
右　青文字、高度のアクセス許可を表示する　をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159729/bb6e34d0-a1c1-e40d-8665-ca7c55ebf6d9.png)
ここでアクセス許可を設定できる。
デフォルトは読み取り・実行のみなので、
・ファイルの作成/データの書き込み
・フォルダーの作成/データの追加
・削除
など、最低限CRUDは追加したほうが良いと思います。
MacbookからWindowsにリモートデスクトップ接続する際の快適キーボード設定

# はじめに
自宅のMacbookから会社のWindowsPCにリモート接続して操作する環境で働くこととなりまして、
Macユーザーとして快適にキーボード操作するために試行錯誤した現在の結果を投稿させていただきます。

# 環境
- MacBook Air (Retina, 13-inch, 2020)
- macOS Big Sur バージョン11.6
- Amazon WorkspacesでWindos(デスクトップ)へリモート接続

# 事前準備
### [Autohotkey](https://www.autohotkey.com/)をWindows PCへインストール
Autohotkeyとは、ホットキーへの機能の割り当てなど常駐ソフトの作成に特化したスクリプトエンジンです。( [Autohotkey Wiki](http://ahkwiki.net/Top)より)
要するに、キーボード設定をあれこれいじることができます。

# 実現したい操作
- macのcontrol + A で行頭へカーソル移動(VSCodeのcursorHome)
- macのconrtol + E で行末へカーソル移動(VSCodeのcursorEnd)
- macのcontrol + D でDelete
- macのcontrol + K でカタカナ変換
- アクティブウィンドウを左寄せor右寄せする操作(Windowsのwindowsキー ＋ ← or →)

macで慣れてからwindows使おうとすると、上記のあたりの操作ができず非常にストレスでした。 特に行頭行末移動が必須だと思うのは私だけではないはず…！
というかwindowsユーザーの人はHomeキーやEndキーをそのまま使っているんだろうか。使いづらくないんだろうか。

# 行う設定
## Windows側
Autohotkeyにて以下のスクリプトを実行

```
#InstallKeybdHook
#UseHook

F1:: Send,#{Left}
F3:: Send,#{Right}

Alt & A:: Send,{Home}
Alt & E:: Send,{End}
Alt & K:: Send,{F7}
Alt & D:: Send,{Delete}
```
色々試行錯誤しましたが、上記に落ち着きました。
アクティブウィンドウを左寄せはF1, 右寄せはF3で行うようにしています(他にいいキーが無かった…)。
F2はWindowsでファイル名変更でよく使うので外しました。

ご自身でアレンジされる際は、[Autohotkeyのキーリスト](http://ahkwiki.net/KeyList)をご参照ください。

## mac側
システム環境設定 → キーボードから以下設定。
(macbook単体で使用するときはこの設定は戻さなければいけないのがネック。)

- F1, F2などのキーを標準のファンクションキーとして使用(これはF1, F3を使いやすくするためです)。
- 修飾キーから、control → option へ(optionキーがwindowsでAltとして認識されているため)。


# 以上！
これで個人的に最低限必要な設定はできました。

### 可能なら今後実現したいと思っていること
- 上述の通り、mac側の設定をwindows使用時とmac使用時とで変えなければいけないのを解消したい。
- macのcmd + shift + ← or → で行全体を選択する操作(VSCodeのcursorHomeSelectとcursorEndSelect)も実現したい。
gcloud auth application-default loginのプロジェクトID無い問題

## はじめに
小ネタですが「`gcloud auth application-default login`で生成したクレデンシャルにプロジェクトIDが無い問題」に対処する方法をまとめました。

##gcloud auth application-default login
手元の環境から直接GCP（Google Cloud）上のサービスに繋ぎ込む際のクレデンシャルとして、**サービスアカウントキーをコンソールからダウンロードする方法もありますが、セキュリティ上あまりオススメしません**。管理もタイヘンです。

```sh
gcloud auth application-default login
```

を実行し、生成された`application_default_credentials.json`をクレデンシャルとして使うのが多いかなと思います。
ざっくりとしたフローとしては、コマンドを叩くとブラウザが立ち上がり、Googleアカウントでの認証を求められ、認証通過後、OAuthの仕組みでアクセストークンが発行される流れです。

>User Account を使って Server Application が使うためのアクセストークンを取得する方法です。
ターミナル上で gcloud auth application-default login を実行することで行われます。

https://medium.com/google-cloud-jp/gcp-%E3%81%A8-oauth2-91476f2b3d7f

生成されたトークンは、

- Windowsの場合
    - `%APPDATA%/gcloud/application_default_credentials.json`
- macOS等の場合
    - `$HOME/.config/gcloud/application_default_credentials.json`

に配置されます。
Google CloudのSDKは、クレデンシャルを下記の順番で探します。

>1. 環境変数 GOOGLE_APPLICATION_CREDENTIALS が指定されていたら、そのファイルを service account の credentials として読んで使う
2. gcloud auth application-default login を実行して well_known_file が作成済みであれば、それを authorized user の credentials として読んで使う
3. GAE (Google App Engine) 上で実行されていれば、その built-in service account を使う
4. GCE (Google Compute Engine) 上で実行されていれば、その build-in service account を使う
ここまで該当がなければエラーとする
>
>※well_known_fileは前述のapplication_default_credentials.jsonのこと

https://dev.to/seizans/gcp-api--429k

上記の「2」が`gcloud auth application-default login`で発行したトークンに該当します。
つまり、`gcloud auth application-default login`で生成されたクレデンシャルは、**コード中で明示的に読み込まなくてもSDKが自動で見つけてくれます**。

## プロジェクトIDがない問題

ここまでは極めて一般的な話でした。ただし、この方法にも弱点があります。
生成された`application_default_credentials.json`には`project_id`がありません。

```sh
❯ cat ~/.config/gcloud/application_default_credentials.json
{
  "client_id": "...",
  "client_secret": "...",
  "quota_project_id": "...",
  "refresh_token": "...",
  "type": "authorized_user"
}
```

この状態でGCPのサービス、例えばFirestoreを呼び出してみます。

```go:実行コード
app, err := firebase.NewApp(ctx, nil)
if err != nil {
	log.Fatal(err)
}
client, err := app.Firestore(ctx)
if err != nil {
	log.Fatal(err)
}
iter := client.Collection("Foo").Documents(ctx)
snaps, err := iter.GetAll()
if err != nil {
	log.Fatal(err)
}
```

プロジェクトIDの指定がない！と怒られます。

```sh:結果
project id is required to access Firestore
```

解消する方法は主に３つあります。
まず１つ目はコード中でプロジェクトIDを明示的に与える方法です。

```go
conf := &firebase.Config{ProjectID: "my-project"}
app, err := firebase.NewApp(ctx, conf)
```
２つ目（非推奨。クレデンシャルは弄るべきでない）が`application_default_credentials.json`を直接編集するなりして`project_id`を追加する方法です。

```sh
❯ vi ~/.config/gcloud/application_default_credentials.json
{
  "client_id": "...",
  "client_secret": "...",
  "quota_project_id": "my-project",
  "project_id": "my-project",
  "refresh_token": "...",
  "type": "authorized_user"
}
```
３つ目は、これが最も推奨なのですが、`GOOGLE_CLOUD_PROJECT`環境変数にプロジェクトIDを設定する方法です。
これにより、SDKが対象とするプロジェクトIDとして自動で読み込んでくれます。

```sh
export GOOGLE_CLOUD_PROJECT="my-project"
```

https://github.com/GoogleCloudPlatform/nodejs-getting-started/issues/251

## おわりに

`gcloud auth application-default login`を使いつつ、`GOOGLE_CLOUD_PROJECT`環境変数にプロジェクトIDを指定する方法でローカル開発を進めるのが良さそうです。
Flickrの写真を使って写真の位置情報を可視化してみた

## はじめに
SNSにはたくさんの写真がアップロードされています。地図を使って可視化することが好きな僕は、アップロードされている写真の位置情報を使って地図に可視化できないかなと思いました。調べてみると位置情報の取得が簡単にできるサービスでFlickrというものがありました。今回はFlickrに投稿されている写真を使って、その写真の位置情報をもとに地図に可視化してみたいと思います。

## Flickrの写真を使って写真の位置情報を可視化してみた
### 実現したいこと
今回はFlickrのAPIを扱うPythonライブラいを使って写真の情報を取得し、そのデータをLeafletをPythonで使えるようにしたPythonライブラリの`folium`を使って可視化していこうと思います。地図上に写真の位置情報をもとにピンをたて、ピンには実際のその写真が見えるようにします。

### Flickrとは
Flickrとは、写真を共有することのできるサービスです。Instagramのようなサービスですね。今回はこのFlickrのAPIを使って写真の情報を取得しました。

Flickr APIの利用方法については、以下の記事を参考にしました。

http://ykubot.com/2017/11/05/flickr-api/

### 実際のコード
Flickr APIを利用して写真の情報を取得方法については、以下の記事と公式ドキュメントを参考にしました。

http://ykubot.com/2017/11/05/flickr-api/

https://www.flickr.com/services/api/

```python
# 必要なライブラリ
from flickrapi import FlickrAPI
import folium
import json
import pandas as pd

# Flickr APIを利用するための情報を記載
key = "XXXXXXXXXXXXXXXXXXX"
secret = "XXXXXXXXXXXXXXXXXX"


# Flickr APIを使って写真の情報を取得
# 今回は写真のタイトルに"fish"が関連しているものを５００件を上限に取得
# 位置情報は、extrasでgeoを指定
flickr = FlickrAPI(key, secret, format='parsed-json')

result  = flickr.photos.search(
    text = 'fish',
    per_page = 500,
    media = 'photos',
    sort = 'relevance',
    safe_seach = 1,
    extras = 'url_q, licence, geo'
)

photos = result['photos']['photo']

# 地図の中心を、写真に保存されている緯度経度の平均を出すため
lat_sum, lon_sum = 0,0

for photo in photos:
  lat_sum += float(photo['latitude'])
  lon_sum += float(photo['longitude'])

lat_mean = lat_sum / len(photos)
lon_mean = lon_sum / len(photos)

# 元となる地図を作成
map = folium.Map(location=[lat_mean, lon_mean], zoom_start=3)

# 写真に保存されている位置にピンをたて、そのピンに写真を載せる
for photo in photos:
  folium.Marker(
      location=[float(photo['latitude']), float(photo['longitude'])],
      popup="<p>{}<br /><img src='{}'</p>".format(photo['title'],photo['url_q'])
  ).add_to(map)

# 地図を描画
map
```

### 結果
ピンをプロットした地図は、以下のような感じです。
![スクリーンショット 2022-01-31 22.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/232c50b0-5235-db0b-b6bf-796ddc3d2583.png)

ピンをクリックすると写真が表示されます。
![スクリーンショット 2022-01-31 22.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/cd81f469-510f-9389-f1dd-e2495bb36738.png)

## さいごに
今回はFlickrに投稿されている写真の位置情報をもとに地図に可視化してみました。写真の位置情報の利用は色々な使い道があると思うので、今度は他の使い方を検討してみたいと思います。
【S/4HANA】App could not be opened because the SAP UI5 component of the application could not be loaded. 

# トラブル内容
当記事は、2022/1/31に遭遇した事象の解決方法です。

自社のSAP S/4HANA環境がオンプレ版2020→2021にアップグレードされました。
すると、FIori Launchpadでいつもは使えていたアプリが起動できなくなりました。

使おうとしたアプリケーション：[Migrate Your Data](https://fioriappslibrary.hana.ondemand.com/sap/fix/externalViewer/#/detail/Apps('F3473')/S21OP)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/861e1af1-4835-51fe-6131-5d3d4c71d39d.png)

表題のメッセージです。

`Copy`をクリックしてメモ帳に貼り付けるとこんなメッセージが。

```

Title: ErrorMessage: App could not be opened because the SAP UI5 component of the application could not be loaded.Details: 
{	info: "Failed to load UI5 component for navigation intent \"#DataMigration-manage\"",
	technicalMessage: "found in negative cache: 's4hana/lt/mc/Component.js' from /sap/bc/ui5_ui5/sap/lt_mc_pe_s1/~XXXXXXXXXXXXXXXXXXXXXXXXXXX~5/Component.js: 
	failed to load 's4hana/lt/mc/Component.js' from /sap/bc/ui5_ui5/sap/lt_mc_pe_s1/~XXXXXXXXXXXXXXXXXXXXXXXXXXX~5/Component.js: 403 - \nError: found in negative cache:
	以下略

```

# 環境
S/4HANA オンプレ版 2021

# 対処方法
## Step1
[Fiori App Library](https://fioriappslibrary.hana.ondemand.com/sap/fix/externalViewer/)で当該のアプリ（Migrate Your Data）のSAP UI5 ApplicationとOData Serviceを検索

SAP UI5 Application↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/49a80eb8-3838-f213-b79c-06702f6e4b37.png)

OData Service↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/a014893f-1bbf-5233-8d05-e51e5cc00162.png)

##Step2
TCode:SICFでICF (Internet Communication Framework)を有効化する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/7be5d667-7b5f-8229-a8d4-1f83e3a277bd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/d004061c-86ab-2d99-c3c5-5f92fe3be8a2.png)

わたしの場合は、Activateを押下しても、`You are not authorized to use function Activate`と表示されて実行できなかった。
おそらく、Tcode:SICFを実行できるだけではだめで、特別な権限オブジェクトが必要らしいです。
BASISに依頼して有効化してもらいました。

##Step3
TCODE:/n/iwfnd/maint_service で OData Serviceを有効化する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/2e048fe4-5241-76d9-9fb5-5dcc12170785.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/0018432f-8040-2214-83d0-8896353ad856.png)

ここもBasisにやってもらったので、自分に権限があったかどうかは不明。

##Step4
Migrate Your Dataが開けるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378457/0d432dda-c877-cf79-7843-96aba834c5ed.png)

めでたしめでたし。

#参考
https://launchpad.support.sap.com/#/notes/0002808615
https://fioriappslibrary.hana.ondemand.com/sap/fix/externalViewer/
useraddコマンドの暗号化パスワードを生成する方法

OpenSSLを使って暗号化されたパスワードを生成できる。

```bash
$ echo "password" | openssl passwd -1 -stdin
$1$igAT2WWL$KEd42pTcWqYFaP6IIrs6.1
```

useraddの-pオプションを使って、暗号化されたパスワードでユーザを作成

```bash
sudo useradd <username> -p $1$igAT2WWL$KEd42pTcWqYFaP6IIrs6.1
```
checkboxの値について~備忘録~

###経緯
laravelにおいて、formタグでviewのcheckboxからcontrollerに値を渡そうとしたとき、何もチェックを入れていないと、その渡した値がundefinedになってしまった。
checkbox以外で渡すときは値が入っていなくても、undefinedにはならずnullになっていたので不思議に思い、調べてみた。

###結果

答えはここにありました
参照元：https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/checkbox

```
<form>
  <div>
    <input type="checkbox" id="subscribeNews" name="subscribe" value="newsletter">
    <label for="subscribeNews">Subscribe to newsletter?</label>
  </div>
  <div>
    <button type="submit">Subscribe</button>
  </div>
</form>
```
上のようなcheckbox属性のformタグにおいて、チェックされたら値が送信される。チェックボックスにチェックが入っていない場合、値は全く送信されない。
値は何も送信されないので、リクエストの情報を渡した先でその値はnullではなく、undefinedになる。


nullとundefinedの違いとしては、どちらも値が存在しないが、概念があるかないか。

トイレでトイレットペーパーを切らしている状態がnull。
トイレットペーパーホルダーそのものがない状態がundefined。

という違いがあるとどこかで見た。
N予備プログラミング　〜冬コンテスト作品制作過程を晒してみる⑥〜

みなさんこんばんわ。

一月後半から、冬コンテスト作品作って今年こそ出品したい！と思って頑張ってきましたが、
１月３１日２１時現在、思い描いてたソフトになってません。。
とても悔しくて、全く諦めがついてませんが、記事を読んで参考にして頂いた方々に現時点で区切りのご報告です。


![スクリーンショット 2022-01-30 17.59.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/228bf52a-8939-1444-51a5-2cd417d6f1e4.png)
トップページ。夏作品VRCalc(covid19ワクチン検討リスクチェッカー)では、毎回各項目を入力する仕様だった。ユーザーを覚えるようにできた点では満足。

![スクリーンショット 2022-01-30 18.29.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/cc7e80ca-abd2-a305-2d61-6c5e7e00b3ba.png)
おなまえ（モジュール名dataset）展開画面。
しかしっ！！肝心の、最新のリスク状況を”計算する”ボタンを押しても！！うんともすんとも。。うごかにゃい。ぐすん（泣）
ワクチン摂取状況の部分は、だいたいねらった形にできたんですけどね。

![スクリーンショット 2022-01-31 20.30.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/3a0434b3-8cd0-5c9f-9079-6f9dceacf319.png)
F１２ボタンを押してコンソールをチェックしてみたところ。「HTMLからのvalueがnullですよ」とおこられてる。。

![スクリーンショット 2022-01-31 20.33.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345137/72f45ae3-b8d0-f0bb-979b-b688475198a8.png)
サーバーログにeRNumber.csvと見えるから、夏作品のvRCalc.jsからなんらかのデータは渡ってるっぽい。
けど、uuid型入力構文が不正です。とか、PromiseRejectionとか色々おこられてる。。

『予定調整くん』を改造して、npx webpackで前作vRCalc.jsをぶち込んだらうまくいくんじゃないか？と目論んでましたが。。そんなに甘くはなかったみたい。ウワァァァン！
2011年3月11日に起きた地震情報を可視化してみた

## はじめに
2022年1月22日に九州で大きな地震が発生しました。地震といえば、僕は2011年の東日本大震災を思い出します。今回は東日本大震災が発生した２０１１年３月１１日の地震情報を`folium`を使って可視化してみたいと思います。

## 2011年3月11日に起きた地震情報を可視化してみた
### 実現したいこと
LeafletをPythonで使えるようにしたPythonライブラリの`folium`を使って、震央の位置とマグニチュードを円の大きさで表現したいと思います。

### 使用するデータ
今回使用するデータは、気象庁が提供している震度データベース検索からダウンロードしたものを使わせていただきました。

https://www.data.jma.go.jp/svd/eqdb/data/shindo/index.html

ここから、2011年３月１１日に発生した最大震度１以上をどこかしらで観測した地震を集計しています。

### 実際のコード

```python
# 必要なライブラリ
import folium
import pandas as pd
import geopandas as gpd
import numpy as np
import datetime as dt
import re

# ダウンロードしたCSVを読み込む
# データの整形が必要なので、もろもろ修正していく
df_tmp = pd.read_csv('./earthquake.csv')

# マグニチュードが不明なところは除く
df_tmp = df_tmp[df_tmp['Magnitude'] != '不明']

# 使用するために空のデータフレームを作成しておく
df = pd.DataFrame(index=[], columns=['datetime','lat','lon','magnitude'])

# 緯度経度が六十進法で保存されるので、それを十進法に変更する関数を用意する
# 緯度
def Sixty2TenOfLat(row):
  lat_splited = re.split('\D+', row['lat'])
  lat = float(lat_splited[0]) + float(lat_splited[1]) / 60 + float(lat_splited[2]) / 60 / 60
  return lat

# 経度
def Sixty2TenOfLon(row):
  lon_splited = re.split('\D+', row['lon'])
  lon = float(lon_splited[0]) + float(lon_splited[1]) / 60 + float(lon_splited[2]) / 60 / 60
  return lon

# 緯度経度を六十進法から十進法に変更して、使用するデータフレームに格納
df['lat'] = df_tmp.apply(Sixty2TenOfLat, axis=1)
df['lon'] = df_tmp.apply(Sixty2TenOfLon, axis=1)

# マグニチュードは文字列で保存されていたので、`float`に変更して使用するデータフレームに格納
df['magnitude'] = df_tmp['Magnitude'].map(lambda x: float(x))

# 使用する元の地図を作成
# 地図の中心は、震央の緯度経度の平均にしている
map = folium.Map(location=[df['lat'].mean(), df['lon'].mean()], zoom_start=5, tiles='cartodbdark_matter')

# 震央の位置に、マグニチュードの大きさを円の大きさとして描画
# 円の半径は、描画の関係で大きくしている
for i, row in df.iterrows():
    folium.CircleMarker(
        location=[row['lat'], row['lon']],
        radius=row['magnitude']*5,
        color='#0000ff',
        fill_color='#000055'
    ).add_to(map)

# 地図を描画
map
```

### 実際の結果
![スクリーンショット 2022-01-31 21.26.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581736/536f2ceb-b956-c882-95b8-cbbf3f593e1b.png)

上記のコードを実行すると、このような結果が得られました。東北ではたくさんの地震が発生していることがわかります。僕もたくさんの地震が発生したのを直で経験していたので、すごく覚えています。

## さいごに
今回は気象庁のデータとLeafletをPythonで使えるようにしたPythonライブラリの`folium`を使って、2011年3月11日に起きた地震情報を可視化してみました。`folium`を使うと簡単に、インタラクティブな地図を描画することができます。