OmniAICreator/Qiita-1.07M huggingface dataset:
AWS S3を使って画像を保存する

# 初めまして
私は、現在オリアプを製作し、herokuを使ってデプロイし、画像はAWS S3を使って保存することをしました。
今回は、AWSアカウント登録、IAMユーザー設定後からの備忘録になります。

# S3を何故使うのか

* herokuでデプロイをし、再度デプロイすると画像が消えてしまう
* herokuの仕様で24時間に１回自動で再起動され消えてしまう
* インフラやクラウドについても理解を深めたい

以上の３点のことから「S3」を使うことを決めました！


# 保存先の作成（バケット作成）

①AWS　「S3」のホームページでバケットを作成します。
②バケット名「任意でおk」、リージョン「東京を選択」

アクセス許可ですが、
③パブリックのアクセスを全てブロックのチェックを外します。
④新規のパブリックバケットポリシー〜、あらゆるパブリックバケットポリシ〜のチェックを外す。
⑤そうすると、下の欄に「警告マークとともにチェック欄」が出てくるのでチェックを入れます。
⑥バケット作成をクリック

この作業によってファイルのアップロードができる様になります！

# バケットポリシーの設定をします

①AWS　「S3」のホームページで先ほど作成したバケットを選択します。
②アクセス許可をクリックします。
③画面を少しスクロールすると「バケットポリシー」という画面が出てくるので、「編集する」をクリックします。
④コードブロック内に下記を入力します。

```
{
   "Version": "2012-10-17",
   "Id": "Policy1544152951996",
   "Statement": [
       {
           "Sid": "Stmt1544152948221",
           "Effect": "Allow",
           "Principal": {
               "AWS": "ご自身のユーザーのARN"
           },
           "Action": "s3:*",
           "Resource": "arn:aws:s3:::作成したバケット名"
       }
   ]
}
```

⑤変更の保存をクリックすると完了です。

# S3の設定

Ruby on rails Gemfileの一番下に

```
gem "aws-sdk-s3", require: false
```

上記を追記し、bundle installをします。

# ローカル環境で画像の保存先をS3に変更します。

```
config/environments/development.rb

config.active_storage.service = :local
↓変更する
config.active_storage.service = :amazon
```
この作業により、画像の指定先がlocalからS3へ変更されます。



storage.ymlにバケット名とリージョン名を記述します。

```
config/storage.yml
test:
 service: Disk
 root: <%= Rails.root.join("tmp/storage") %>

local:
 service: Disk
 root: <%= Rails.root.join("storage") %>

amazon:
 service: S3
 region: ap-northeast-1　←　日本に住んでる方はこちらを選択しているはずです
 bucket: ←は自分のバケット名を記入
 access_key_id: <%= S3のアクセスキー環境変数 %>
 secret_access_key:  <%= S3のシークレットアクセスキー環境変数] %>

```

気をつけていただきたいのは、必ずをアクセスキー、シークレットキーは環境変数にしてからデプロイする様にしてください。
秘密情報の漏洩になるのでご注意を！

# 本番環境で画像の保存先をS3します。

```
config/environments/production.rb

config.active_storage.service = :local
↓に変更
config.active_storage.servise = :amazon
```
ローカルの時と同じです！

herokuでも環境変数を使える様にします。

ターミナルでアクセスキー、シークレットキーをherokuに上げます。

```
heroku config:set 変数名="アクセスキーの値"

heroku config:set 変数名="シークレットキーの値"
```

これで本番環境でも使用することができます。

# セキュリティ対策として

「git-secrets」というツールを使用して、誤ってAWSの秘密情報をpushしない様設定することもできます。

```
ホームディレクトリにて
brew install git-secrets

開発中のアプリにて
git secrets --install　←これでgit-secretsを使用できます
git secrets --register-aws --global　←AWS関連の秘密情報を一括で設定できます。
```

またGitHub Desktopを使用している場合


```
GitHub Desktopにも適応されます
sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets

今後全てのリポジトリに適応したい場合
git secrets --install ~/.git-templates/git-secrets
git config --global init.templatedir '~/.git-templates/git-secrets'
```

# 最後に
初めてクラウドを使ってみた感想は、意外と簡単に実装することができました。
複雑だなと感じた点は、セキュリティ面です。
今後開発していく上、セキュリティやクラウド、インフラは絶対に必要な知識の為、実装をしていく中でどんどん吸収していきたいと思います。

読んでいただきありがとうございました！
[DataGrid,DataGridView等]ソートの落とし穴と対処

[本記事は、自分サイトのこの記事と同一内容です。](https://hagiayato.github.io/my-site/jekyll/update/2021/02/07/DataGridSort.html)
# はじめに
Microsoft提供のフレームワークには、DataGrid(wpf),DataGridView(.net)等のコントロールがあります。
これはデータを表形式で表示・編集できる、とても便利なものです。
そんなDataGrid,DataGridViewのソートには、データ型による落とし穴があります。

# 落とし穴
下記のような、ファイル一覧をDataGridViewで表示するアプリケーションがあります。
ファイルサイズは、表記を分かりやすい単位に変換して表示しております。
参考：[【C#】容量を表すバイト単位の数値を単位付きの読みやすい文字列に変換する関数](https://baba-s.hatenablog.com/entry/2018/12/25/154000)
![2021-01-31SortBefore.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/98768cca-6314-ea27-7579-de81d4f2533e.jpeg)
ここでファイルサイズで昇順ソートをかけてみると、上から
「file2⇒file3⇒file1」の順になるべきです。
しかし実際は
「file1⇒file2⇒file3」という順になるのです…!
![2021-01-31SortAfter.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/fdb117a0-4b50-9f15-d6af-d199a0a46ec8.jpeg)
### なぜこうなるの?
その原因は、ソートの仕様にあります。

実は、ファイルサイズを表記を分かりやすい単位に変換すると変換後のデータは文字列になります。
そしてその状態でDataGridViewに表示するということは、DataGridViewに文字列としてデータが入るのです。
なのでファイルサイズでソートをかけた際、文字列としてソートが行われます。

文字列としてソートをすると、先頭の1文字から順番に並び替えが行われるため、
本当は一番サイズが大きい1.87MBが、先頭になります。
***※バグではありません。***

この事象は、数値を文字列に変換した際だけでなく日付を文字列に変換して表示した場合も同じことが起きます。Excelのフィルタでで文字列をソートした場合も同じです。
(となると、この落とし穴は.netあるあるかもしれません)
# 対処法
対処法は、下記2つのことを行うことです。

### 1. 非表示列として、元データを追加
文字列に変換する前の元データ(数値、日付等)を非表示列の列としてDataGrid,DataGridViewに追加します。
非表示列なので、ユーザからの見た目は変わりません。

### 2. 文字列データをソートする際、元データ列でソートする
文字列データをソートする際に、元データ列でソートを書けるようにコードを書きます。

```cs
        /// <summary>
        /// 列ヘッダクリック時処理(カスタムソート用)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            // クリックした列を判別
            switch (e.ColumnIndex)
            {
                case 4:
                    // ファイルサイズ(文字)列
                    // 現在のファイルサイズ(文字)列の並びを取得
                    SortOrder mode = dataGridView1.Columns[4].HeaderCell.SortGlyphDirection == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
                    ListSortDirection direction = mode == SortOrder.Ascending ? ListSortDirection.Ascending : ListSortDirection.Descending;
                    // ファイルサイズ(数値)列基準でソートを実施
                    dataGridView1.Sort(dataGridView1.Columns[3], direction);
                    dataGridView1.Columns[4].HeaderCell.SortGlyphDirection = mode;
                    break;
                default:
                    // それ以外の列の場合は、ファイルサイズ(文字)列のソート順表記消去
                    dataGridView1.Columns[4].HeaderCell.SortGlyphDirection = SortOrder.None;
                    return;
            }
        }
```
処理の流れ
列ヘッダをクリック⇒その列か判別：ファイルサイズ(文字列データ)列の場合⇒
現在の並び順を取得⇒その反対順で***元データ基準ソート***⇒
ファイルサイズ(文字列データ)列の並び順更新

ソートをこのように実装したうえで、ファイルサイズで昇順ソートをかけてみると、上から
「file2⇒file3⇒file1」の順になります。
![2021-01-31SortAfter2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/cbdf53a6-d10b-6130-6b7e-aea675240049.jpeg)
本来のファイルサイズ順でソートができました。

今回はDataGridViewを例にしましたが、DataGrid等でも同じ方法で対処可能です。

# まとめ
DataGrid,DataGridViewをソートする際には、データ型に注意してください。
また、どうしても数値を文字列で表示したい場合は上記方法で本来のサイズでのソートを実装しましょう。
Go: gorm で MariaDB のデータを読む (Read)

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.go
├── go.mod
├── go.sum
└── gorm_read.go
```

```go:gorm_read.go
// ----------------------------------------------------------------
//	gorm_read.go
//
//					Feb/26/2023
// ----------------------------------------------------------------
package main

import (
	"fmt"
	"os"
	"gorm.io/gorm"
	"gorm.io/driver/mysql"
)

type City struct {
	Id           string
	Name         string
	Population   int
	Date_mod     string
}

// ----------------------------------------------------------------
func main() {
	fmt.Fprintln (os.Stderr,"*** 開始 ***")

	host,user,password,data_base := config_mariadb_proc()
	dsn := user + ":" + password + "@tcp(" + host + ":3306)/" + data_base + "?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
		}
	cities := []City{}

	db.Find(&cities)

	llx := len(cities)
	fmt.Println(llx)

	for it := 0; it < llx; it++{
		unit_aa := cities[it]
		fmt.Printf("%s\t",unit_aa.Id)
		fmt.Printf("%s\t",unit_aa.Name)
		fmt.Printf("%d\t",unit_aa.Population)
		fmt.Printf("%s\n",unit_aa.Date_mod)
	}

	fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

// ----------------------------------------------------------------
```

.env
config_mariadb.go
はこちら
[Go: gorm で MariaDB のバージョンを表示](https://qiita.com/ekzemplaro/items/3f174eff33ada20dab5f)

実行の準備

```bash
go mod init read
go mod tidy
```

実行

```bash
go run gorm_read.go config_mariadb.go
```

## MariaDB
テーブル定義は次のようになっています。

```text
mysql> show columns from city.cities;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id         | varchar(10) | YES  |     | NULL    |       |
| name       | varchar(20) | YES  |     | NULL    |       |
| population | int         | YES  |     | NULL    |       |
| date_mod   | date        | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+
```

## 確認したバージョン

```text
$ go version
go version go1.20.1 linux/amd64
```
Firestore .modifed called after .added on addSnapshotListener 2回呼ばれる問題

問題の原因はこれだった。

> ドキュメントにタイムスタンプを付けると、onSnaphotが2回起動します
https://www.fixes.pub/program/77981.html

```swift
firebase.firestore.FieldValue.serverTimestamp()
```

またFirestoreの仕様として、1回の保存でも複数回のsnapshotが流れることがあるそうだ。
https://zenn.dev/ioridev/articles/bdf5fbd43f4705

## どういうシーンで置きたか
投稿をFireStoreに保存した時に、ホームの投稿一覧を更新したいみたいな処理をしたとき、`addSnapshotListener`の`.added`の後に`.modefied`が呼ばれた。

```swift
func setPostsListener() {
		self.postsListener = self.db.collection("posts")
			.order(by: "createTime", descending: true)
			.addSnapshotListener({ (querySnapshot, error) in
				if let error = error {
					print("Error while getting collection: \(error)")
				} else {
					guard let snapshot = querySnapshot else { return } // ここ if let error とまとめたほうが綺麗
					snapshot.documentChanges.forEach { diff in
						if (diff.type == .added) {
							print("New post")
							let post = Story(document: diff.document)
							self.posts.append(post)
						}
						if (diff.type == .modified) {
							print("Modified post")
						}
						if (diff.type == .removed) {
							print("Removed post")
						}
					}
					self.collectionView.reloadData()
				}
			})
		
    }
```
Macのターミナルなどで使う ls コマンドについての備忘録

## ls

`ls -- ディレクトリ内のコンテンツをリスト表示する`

```zsh
ls      # 現在のディレクトリ内のコンテンツを表示
ls -l   # 各コンテンツの詳細情報も表示
ls -a   # 隠しコンテンツも表示
ls −la  # 隠しコンテンツも含め現在のディレクトリ内のすべてのコンテンツの詳細情報を表示する

ls -r   # ソート逆順表示
ls -t   # 最終更新時刻が新しい順に表示
ls -G   # カラー表示

ls -altr -G # 更新日時が古い順に、現在のディレクトリ内のすべてのコンテンツおｗ，隠しコンテンツを含めて、カラー表示する
```

`~/.zshrc` に以下の様に記載をして、lsコマンドを上書きして、`ls` と入力すると自動で `ls -altr -G` の結果が得られて、便利かもしれません。

```zsh
alias ls='ls -al -G'
```
MINTIAの空き箱を使ってLEDライトにする

何となく、Mintiaの空き箱を再利用したく成ったのでLEDライトにしてみました。

箱の中に入れるには高さ5mm以下にする必要があるので、ボタン電池ホルダーとLED（5mmしか家に無かった）は削っています。

#### 各部品

ボタン電池：直列繋ぎで６V
LED：並列繋ぎで１つ恐らく３Vの20mAくらい
抵抗：150Ω＝（6V-3V）/0.02A

### 回路図

![mintia2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015539/6386aa81-8f9c-4ed7-c436-e19a01ac954a.png)



### 詰め込み画像

スイッチが真ん中から動かないようにグルーガンを使って空きスペースを埋めました。
![mintia.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015539/74cd4545-c799-b87e-a193-437bbb447485.png)

### Pythonでコーディングしてみる。

回路図もプログラミングの一種だと思っていますが、規約違反にならないように念のためPythonで今回のLEDライトの動作をプログラミングしてみます。

下のコードを実行すると、何かキーを押すたびに電圧が0.3V下がって行き2Vを切ると終了するように成っています。

キー入力：トグルスイッチ
RESISTOR：抵抗値
LED_AMPERE：LEDのアンペア
INPUT_VOLT：電池の電圧
BATTERY_NUM：電池の個数
としています。

```python:led_light.py

INPUT_VOLT = 3
BATTERY_NUM = 2
LED_AMPERE = 0.02
RESISTOR = 150


def _light(volt: float, resistor: int) -> float:
    v: float = volt - (LED_AMPERE * resistor)
    for i in range(1, 4):
        print(f"  LED{i}: {v:.2f}V")
    return v


try:
    volt = INPUT_VOLT*BATTERY_NUM
    while True:
        input(f"スイッチON: 入力電圧: {volt:.2f}")
        v = _light(volt, RESISTOR)
        if v < 2.0:
            input("LED 消灯")
            break
        volt -= 0.3

except KeyboardInterrupt:
    print("終了")
```

結果

```bash
$ python3 led_light.py
スイッチON: 入力電圧: 6.00
  LED1: 3.00V
  LED2: 3.00V
  LED3: 3.00V
スイッチON: 入力電圧: 5.70
  LED1: 2.70V
  LED2: 2.70V
  LED3: 2.70V
スイッチON: 入力電圧: 5.40
  LED1: 2.40V
  LED2: 2.40V
  LED3: 2.40V
スイッチON: 入力電圧: 5.10
  LED1: 2.10V
  LED2: 2.10V
  LED3: 2.10V
スイッチON: 入力電圧: 4.80
  LED1: 1.80V
  LED2: 1.80V
  LED3: 1.80V
LED 消灯
```
ROSノードをPython3で動かす

# はじめに
最近ROS Melodicを触っています．
ROS1ではPython2が標準になっていて，普段Python3を使っている身からするとやりにくいです．
（サポートも切れていて時流に沿ってないですしね）

しかし，ROS1でしかサポートされていないノードも多々あると思うので，
ROS1が避けられないこともあるかと思います．
（OpenVSLAMなど ← develop版ではROS2をサポートとしているようですが）

そこで，ROS本体はPython2で動かしつつ，ROSノードはPython3で動かす方法を取りました．
備忘録的に残しておきます．  

ROSをPython3用にビルドする方法も探すと出てきますが，
時間がかかったりうまくいかなかったりするのでこの方法が簡単です．

# 環境構築
### ROSインストール
以下を実行してROSをインストールします．
（[ROS Wiki](http://wiki.ros.org/melodic/Installation/Ubuntu)の通りです）

```bash
ROSのインストール準備
$ apt-get update
$ apt-get install -y dirmngr gnupg2
$ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
$ echo "deb http://packages.ros.org/ros/ubuntu bionic main" > /etc/apt/sources.list.d/ros1-latest.list

ROSのインストール（Desktop Fullをインストールしています）
$ apt-get install -y ros-melodic-desktop-full
$ apt-get install -y -essential python-rosdep python-rosinstall python-vcstools

rosdep初期化＆更新
$ rosdep init
$ rosdep update --rosdistro melodic
```

### Python×ROS
Python自体の環境構築は省きますが，ビルドインのPythonでも問題ありませんし，pyenvなどの仮想環境でもOKです．
PythonにROSのコマンドをインストールします．
catkin_toolsはpipでインストールすると使うに際エラーが出るので，gitから直接インストールします．

```bash
$ pip install trollius rosdep rospkg rosinstall_generator rosinstall wstool vcstools catkin_pkg
$ pip install git+https://github.com/catkin/catkin_tools
```

### Catkinワークスペースの作成
Catkinワークスペースを作る際に使用したいPythonを指定します．

```bash
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws
$ catkin_make -DPYTHON_EXECUTABLE={Pythonのパス}
$ source devel/setup.sh

ex)
$ catkin_make -DPYTHON_EXECUTABLE=~/.anyenv/envs/pyenv/versions/3.9.1/bin/python
```

Dockerfileの場合は，ここはentrypointにしておくと良いです．
（sourceの部分はbashrcに書くようにするなど工夫する）

# 開発
rosrunで実行すると，Python3で実行したいノードはPython2から起動されますが，
\#!（シバン）を書いておくことでPython3でノードを実行することができます．

```python
#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def talker():
    rospy.init_node('talker')
    word = rospy.get_param("~content", "default")
    pub = rospy.Publisher('chatter', String, queue_size=10)

    r = rospy.Rate(1) # 10hz
    while not rospy.is_shutdown():
        str = "send: %s" % word
        rospy.loginfo(str)
        pub.publish(str)
        r.sleep()

if __name__ == '__main__':
    try:
        talker()
    except rospy.ROSInterruptException:
        pass
```

# まとめ
ROSノードをPython3で実行するための環境構築に関して書きました．
特にしがらみがないのであればROS2を選択するのがベターな気がします．
Dockerを扱う際のコマンドまとめ（ケースごと）

*徐々にデータを追加していきます*

## 環境
- MacOSX 10.15.3
- [docker desktop](https://www.docker.com/products/docker-desktop) 2.2.x

## Dockerそのものがわからんとき

| command | meaning | note |
|:-----------------:|:------------------:|:------------------:|
| docker --help | dockerコマンドの内容 | |

## 削除したいとき
| command | meaning | note |
|:-----------------:|:------------------:|:------------------:|:------------------:|
| docker image rm <image id> | 指定した<image id>を削除する | 複数の<image id>を指定可能(docker image rm <image id> <image id>) , docker rmi <image id>はエイリアス|


## 一括削除したいとき
| command | meaning | parent command | note |
|:-----------------:|:------------------:|:------------------:|:------------------:|
| [docker system prune --all](https://docs.docker.com/engine/reference/commandline/system_prune/) | 使用されていない Container, Network, Image, Volumeが削除されます | [docker system](https://docs.docker.com/engine/reference/commandline/system) | |
| [docker image prune](https://docs.docker.com/engine/reference/commandline/image_prune/) | 使用されていないImageが削除されます（なにかの都合で残ってしまったデータ、何にも紐付かないデータなどは削除されません） | [docker image](https://docs.docker.com/engine/reference/commandline/image/) | |
| [docker image prune --all](https://docs.docker.com/engine/reference/commandline/image_prune/) | 使用されていないImageが削除されます| [docker image](https://docs.docker.com/engine/reference/commandline/image/) | |
| [docker image rm $(docker images -q)](https://docs.docker.com/engine/reference/commandline/system_prune/) | 使用されていないImageが削除されます | [docker image](https://docs.docker.com/engine/reference/commandline/image/) | |


## イメージをビルドしたりし直したりするとき
| command | meaning | parent command | note |
|:-----------------:|:------------------:|:------------------:|:------------------:|
| [docker-compose build](https://docs.docker.com/compose/reference/up/) | Docker imageをフォアグラウンドでビルドします。 |  | |
| [docker-compose up -d](https://docs.docker.com/compose/reference/up/) | Docker imageが見つからない場合のみビルドしてから起動します。 |  | |
| [docker-compose up -d --build](https://docs.docker.com/compose/reference/up/) | Docker imageビルドしてから起動します。 |  | |


## 動かしたいとき
| command | meaning | parent command | note |
|:-----------------:|:------------------:|:------------------:|:------------------:|
| [docker-compose up -d](https://docs.docker.com/compose/reference/up/) | Docker imageをバックグラウンドでビルドします。イメージが見つからないときはビルドしてから動かします |  | |


## その他覚えておくと良さそうなワード

| word | domain | meaning | examples | note |
|:-----------------:|:------------------:|:------------------:|:------------------:|:------------------:|
| prune | 操作系コマンド | 使われていない対象を一括削除する | docker system prune, docker image prune | |
| -q  | オプション | 表示するデータを絞る | docker images -q, docker image rm $(docker images -q) | |
【PHPのユーザー定義関数について】（初学者向け）

####【目次】
①PHPとは
②ユーザー定義関数とは
③PHPのユーザー定義関数について

####【①PHPとは】
プログラミング言語の1つで、ウェブ系のプログラムを作る際によく使用されるスクリプト言語です。
<dl>
  <dt>スクリプト言語とは</dt>
  <dd>概要：可読性が高く比較的簡単に書きやすい言語の総称です</dd>
  <dd>例：Ruby、JavaScript など</dd>
<dd>対比：コンパイラ言語・インタプリタ言語・LL言語 など</dd>

####【②ユーザー定義関数とは】
######■ユーザ定義関数
プログラミングの分野で出てくる関数の分類のひとつで自身でプログラミングして作成した関数のことを指します。
（後述のBの関数）


######■そもそも関数とは
関数は「何かを入れると何かを計算して何かを返してくれるプログラムの部品」です。
一般的には、入力を受けて処理を行い、その結果として出力があります。
**※イメージ例**
自動販売機で「お金を入れてボタンを押す（入力）」と自動販売機で処理がなされ、「ジュースが出てくる（出力）」ような処理をまとめたもの


######■関数には2種類ある
A．最初から用意されている関数
B．自分で作った関数

「A．最初から用意されている関数」
プログラミング言語などの仕様にあらかじめ用意され、標準で使用できる関数のこと。
組み込み関数 （built-in function）と呼ばれています。 

「B．自分で作った関数」
Aに対して実際に自分でプログラミングした関数でどんな処理をするか自分で決めて作成します。
**これをユーザ定義関数(user-defined function)と呼びます。**
自作関数と呼ばれる場合もあります。


####【③PHPのユーザー定義関数について】
PHPのユーザー定義関数は次のような書き方で定義します。
>ｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰ
function 関数名(引数) {
  // この中に処理内容を書いていく
  // 処理１
  // 処理２
  // ...
}
ｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰ

関数にも名前を付けることができ、function というキーワードに続いて関数名を書き、その後ろに ( ) カッコを書きます。
カッコの中には「引数」を指定します。そしてさらにその次に { 〜 } 波カッコを書きます。
波カッコの開始から終了までを「ブロック」といい、ブロック内に処理の内容を書いていきます。
※引数とは、この関数の中で使うことができるデータに名前をつけたものです。

####※参考資料URL
https://www.php.net/manual/ja/functions.user-defined.php
https://newmonz.jp/lesson/php-basic/chapter-9
https://wa3.i-3-i.info/index.html
Laravel Mixで圧縮時にconsole.logを削除してconsole.errorを残す


下記をwebpack.mix.jsに追記すると、production用 (`NODE_ENV=production`) にビルドするだけで`pure_funcs`で指定している`console.debug`と`console.log`を削除してくれる。

```js
if (mix.inProduction()) {
    mix.options({
        terser: {
            terserOptions: {
                compress: {
                    // Drop these function calls. Keep console.error and etc.
                    pure_funcs: [
                        'console.debug',
                        'console.log'
                    ]
                }
            }
        }
    });
}
```
上記設定だと、`console.wanr`と`console.error`は削除されずに残る。

`console.*`をすべて削除したい場合は`pure_funcs`を使う代わりに下記でOK。

```js
if (mix.inProduction()) {
    mix.options({
        terser: {
            terserOptions: {
                compress: {
                    drop_console: true // This drops all console.* calls
                }
            }
        }
    });
}

```

Laravel Mix 5.0.9で確認。



参考: https://github.com/webpack-contrib/terser-webpack-plugin/issues/57
Amazon Route53(Hosted Zone)とDNSフェイルオーバー概要

* Amazon Route53 Hosted ZoneとDNSフェールオーバーの概要を備忘録として、メモする。

## Amazon Route53

* AWSが提供するDNSサービス。

### Amazon Route53 Hosted Zone 

* Hosted Zone = ネームサーバー
* 提供機能
  * **ドメイン名のリソースレコード管理**
        * Public Hosted Zone:インターネット上に公開されたDNSドメインのレコードを管理する。
        * Private Hosted Zone:VPCに閉じたプライベートネットワークのDNSドメインのレコードを管理する。
  * **トラフィックルーティング**
        * DNS応答をカスタマイズすることで、クライアントからのトラフィックに応じてルーティングする機能。
        * レコード作成時に、Amazon Route53がクエリに応答する方法を決定するポリシーを選択する。
            * シンプル、加重、フェイルオーバー、複数回答などから選択。
  * **ヘルスチェックとDNSフェイルオーバー**
        * ヘルスチェックの結果に基づいて、利用可能なリソースのみ応答する機能。
        * 障害発生時に、S3でホスティングしているソーリーページを表示するなど。

#### 関連用語

* **ホスト名**

  * サーバーや端末に設定された名前。一意に識別されることを想定していない相対的な名前。

* **FQDN**

  * サブドメインからトップレベルドメインまで完全に指定されたホスト名。特定のドメイン名空間でノードを一意に識別可能な名前。

* **DNS**

  * FQDNをキーに対応するIPアドレスを取得する仕組み。
        * DNSから情報取得することを名前解決と呼ぶ。
        * 各ネームサーバーが管理する名前空間をゾーンと呼ぶ。

* **DNSサーバー**

  * 以下の4機能を持つ実装。
        * ネームサーバー：ルートを起点にFQDNを探索できるように構成された分散データベース。それらを構成する一つ一つのネームサーバー
        * フルサービスリソルバー：ルートから順にネームサーバーを問い合わせ、得られた結果を問い合わせ元に返却する。
        * スタブリソルバー：OSに組み込まれたDNSクライアント実装。
        * フォワーダー：受け取った問い合わせをルールに基づいて中継する。

  



## DNSフェールオーバー

* ヘルスチェックリクエストを送信し、エンドポイントのリソースの正常性をチェックする。チェック結果に応じて、DNSクエリへの応答を行う。

  * リクエスト失敗回数(正常性評価の指標)やヘルスチェック間隔などの設定が可能。

    

  * よく見る構成

  ![dns_fail_over.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/d1606157-fc51-f7b3-e341-226ab7e35a2e.png)


## 参考情報

* [Amazon Route 53 Hosted Zone](https://d1.awsstatic.com/webinars/jp/pdf/services/20191105_AWS_Blackbelt_Route53_Hosted_Zone_A.pdf)

* [Amazon Route53の説明とRoute53とEC2との関連について](https://www.acrovision.jp/service/aws/?p=2298)

* [Amazon Route 53 ヘルスチェックの作成と DNS フェイルオーバーの設定](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/dns-failover.html)
サーバー基礎知識①　〜サーバーの種類〜

#webサーバー
HTMLやCSSや画像ファイルが保存されている。

#メールサーバー
メール送受信専用のサーバー。
その中でも、
送信専用のサーバー、`SMTPサーバー`と、
受信専用のサーバー、`POPサーバー`がある。

#データベースサーバー
データベース管理システムが働いているサーバー。
データベースを搭載して、データが格納されている。

#DNSサーバー
IPアドレスとドメインを結び付けるためのサーバー。

#FTPサーバー
webサーバーにファイルを送受信するために使用するサーバー。
「ファイル転送プロトコル」とも呼ばれる。

#SSHサーバー
クライアント情報を暗号化するサーバー。
ActiveStorageのバリデーションとシードデータの用意

##したいこと

ActiveStorageを使って投稿機能を実装している状態で、ファイルの添付を必須にするバリデーションをかけ、それに対応したseedデータの用意したい。
<br>

##前提

- Userと１対多の関係にあるPostモデルがある
- PostにActiveStorageでファイルが紐づけられている



駆け足で説明すると

```:ターミナル
//UserとPostモデルを作成
$ rails g model User name:string 
$ rails g model Post body:text
```

 ※ActiveStorageで追加したいファイル用のカラムは作らなくて大丈夫です。
<br>
マイグレーションファイルを編集

```ruby:db/migrate/xxxxx_create_posts.rb
class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.text :body
      #外部キーを追加
      t.references :user, foreign_key: true

      t.timestamps
    end
  end
end

```

```:ターミナル
$ rails db:migrate
```

<br>
アソシエーションの記述

```ruby:/user.rb
class User < ApplicationRecord
  has_many :posts, dependent: :destroy
end
```


```ruby:/post.rb
class Post < ApplicationRecord
  belongs_to :user
end
```

<br>
ActiveStorageを導入

```:ターミナル
$ rails active_storage:install
$ rails db:migrate
```

Postモデルに画像を１つ添付する設定

```ruby:/post.rb
class Post < ApplicationRecord
  belongs_to :user
  #追記
  has_one_attached :image
end
```

`:image`の部分はファイルの呼び名で自由に指定してよい

**参考**

- [【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1#%E4%B8%80%E5%AF%BE%E5%A4%9A%E3%81%BE%E3%81%A8%E3%82%81)
- [Railsの外部キー制約とreference型について](https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47#%E3%81%BE%E3%81%A8%E3%82%81)
- [【Rails 5.2】 Active Storageの使い方](https://qiita.com/hmmrjn/items/7cc5e5348755c517458a)


<br>

##postモデルに画像をの添付を必須にするバリデーションをつける


今回はactivestorage-validatorというgemを使います。
https://github.com/aki77/activestorage-validator

<br>
Gemfileを編集

```ruby:/Gemfile
  gem 'activestorage-validator'
```

```:ターミナル
$ bundle
```

Postモデルに追記

```ruby:/post.rb
class Post < ApplicationRecord

  has_one_attached :image
  belongs_to :user
  
  #追記
  validates :image, presence: true, blob: {content_type: :image}
end
```
エラーメッセージは`@post.errors.full_messages`に格納されているので

```erb:
   <ul>
     <% @post.errors.full_messages.each do |message| %>
       <li><%= message %></li>
     <% end %>
   </ul>
```

のように書くと表示させることができます。

<br>

##seedデータを用意する

まず画像データを`app/assets/images/`に用意します。

[WSL(Windows Subsystem for Linux)で画像を用意したい](https://qiita.com/waynejsk/items/3e3ce540503ef6bfd18d)

<br>
次にseedを書いていきます。ここハマりました、ポイントとしては

- 一度インスタンスを作成してからattachする
- createではなくnewとsaveを使う

```ruby:/seed
User.Create!(name: "tony")

post = Post.new(
  user_id: 1,
  body: "foo"
)
post.image.attach(io: File.open("app/assets/images/sample.jpg"), filename: "sample.jpg", content_type: 'image/jpg')
post.save!

```

**参考**

[【Rails6】seedファイルに画像を追加する(ActiveStorage使用)](https://qiita.com/saya9875/items/c9bc319fc448959c2c92)
[Active Storage 3.3 Attaching File/IO Objects](https://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-file-io-objects)

以上です。
Vuetify、Bootstrapは時代遅れ！？Vue.jsで「Buefy」を使ってローディング画面をたったの２０秒で実装する方法！！

皆さん処理を行っているときにローディング画面出したいなと思ったことありませんか？

これを１から自分で作るってなると中々時間のかかるものです。

そこで出てくるのが僕のおすすめする「Buefy」。

Vue.jsには「Vuetify」というプラグインがあったり、皆さんの知ってる「Bootstrap」があったりします。

ただ、これらを入れたときに他のレイアウトが崩れる経験で頭を抱えている人もいるでしょう。（自分がそうだった）

これを解決してくれるのが、CSSフレームワーク「Buefy」。

フレームワークなので自分で実装して使いやすいようにするといった点では、Vue.jsを勉強し始めたひとにとっては少し物足りない感覚が出てくると思うのですが、僕は断然「Buefy」をおススメします！！

必要な機能だけそろってる。

なので、レイアウトが崩れない。

とりあえずBuefyの魅力を語るのはこの辺にしておいて、まずはこちらの記事[初心者必見！サイト制作は楽してなんぼ。CSSフレームワークBuefyの紹介！！](https://qiita.com/akki-memo/items/278ff2982961274955c4)でBuefyのパッケージをインストールしてください。

ものの数分で終わります。

そしたら、こちらの[公式ドキュメント](https://buefy.org/documentation/loading)を開いてください。

ソースコードにはいろいろと書いてありますが、ぶっちゃけ必要な部分は、以下だけです。

```
<b-loading :is-full-page="isFullPage" v-model="isLoading" :can-cancel="true"></b-loading>
```

``isFullPage``：全画面にローディングを適用（true or false）
ほとんどの場合は、全画面でOKです。

``v-model``：これでローディングを開始したり、止めたりします。(true or false)

``can-cancel``：ローディング画面が出てきたときに、どこかしらクリックするとローディングを止めれるか（true：止めれる false:止めれない）

本当にこれだけで実装できます。

一応実装例を載せておきますね。

```App.vue
<template>
  <div class="loading">
    <b-loading
      v-model="isLoading"
      :is-full-page="true"
      :can-cancel="false"
      style="background-color: rgba(255, 255, 255, 1)"
    ></b-loading>
    <button @click="isLoading = true">ローディング開始</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isLoading: false
    }
  }
}
</script>
```

ちなみに``style="background-color: rgba(255, 255, 255, 1)"``は、デフォルトでは画面が少し透けるので、真っ白にしたかったらこのstyleを付けてあげてください。

めちゃめちゃ簡単でしょ？

皆さんガンガンBuefyを使ってください！

以上、「初心者必見！Vue.jsでローディング画面をたったの２０秒で実装する方法！！」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも毎日初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
overleafでbibtexを使う

overleafのファイルを置く場所にbibファイルを用意します．
英語の論文を参考文献に入れるのであれば，google scholarでその論文を調べ，import into bibtexのところをクリックします．
![スクリーンショット 2021-01-31 13.40.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351794/cffc0714-8010-7909-0f35-dc535a6e97ca.png)
リンク先のテキストをcommand + Aで全文選択し，command + Cでコピー，bibファイルにcommand + Vでペーストします．
![スクリーンショット 2021-01-31 13.39.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351794/015fc6f2-4451-66d6-58af-2f869aad54fc.png)

```ruby:本文の文書ファイルの形式[1]
\documentclass{...}
\begin{document}

\bibliographystyle{plain}
\bibliography{myrefs}

\end{documents}
```

コンパイルしてもメインのtexファイルで引用していないものは出力の参考文献欄に載りません．

###参考文献
[1] 奥村晴彦, 黒木裕介. 「[改訂第8版] LATEX2ε美文書作成入門」 (技術評論社，2020年), pp.184.
setTimeout(..., 0)の本当の挙動を知っていますか？

ChromiumのGoogle Groupsを眺めていたらsetTimeout()の実装で面白いものをみつけた．

# Intent to Ship: Remove clamping of setTimeout(..., 0)

> **Summary**
> 
> Calls to setTimeout(..., 0) were previously clamped to a 1 ms timeout for historical reason: https://bugs.chromium.org/p/chromium/issues/detail?id=402694, This is very old, http://trac.webkit.org/changeset/17156 appeared to add it (10/20/06).
>
> This is actually a bug since there's no 1ms clamp in the spec, and which will cause scheduling error, e.g.
>
> setTimeout(()=> console.log('1ms timeout'), 1);
> 
> setTimeout(()=> console.log('0ms timeout'), 0);
>
> Outputs:
>
> Chrome 87:  1ms timeout, 0ms timeout
> 
> Moreover, 1ms clamp may bring performance penalty.

出典) https://groups.google.com/a/chromium.org/g/blink-dev/c/HKPTp7C1LwY/m/kIbTxKSPAwAJ

# 要約すると...

`setTimeout(..., 0)`は**歴史的理由**によって，1msのタイムアウトを含んでいるという．このポストではChromeに変更が加えられ，1msのタイムアウトを取り除く実装になったことがアナウンスされている．

歴史的な理由は，`setTimeout(..., 0)`によるCPUの過剰な使用を避けるためだという．

# 実装の確認

1msの前は10msのタイムアウトが入っていたよう．tはミリ秒をあらわす．

> Honor tiny timer intervals for JS timeouts as they are nested until a cutoff point is reached.
>
> At that point clamp to 10ms to prevent excessive CPU usage.

出典) http://trac.webkit.org/changeset/17156/webkit

変更前

```c++:trunk/WebCore/bindings/js/kjs_window.cpp(L1857)
// Use a minimum interval of 10 ms to match other browsers.
double interval = t <= 10 ? 0.010 : t * 0.001;
```

変更後

```c++:trunk/WebCore/bindings/js/kjs_window.cpp(L1865)
// Use a minimum interval of 10 ms to match other browsers, but only once we've
// nested enough to notice that we're repeating.
double interval = max(0.001, t * 0.001);
if (interval < cMinimumTimerInterval && nestLevel >= cMaxTimerNestingLevel)
    interval = cMinimumTimerInterval;
```

# 余談

Slackのtimesでつぶやいたら @malillu さんから`setInterval()` のネストは4msかかると教えてもらった．

> Timers can be nested; after five such nested timers, however, the interval is forced to be **at least four milliseconds**.

出典) http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#timers

参考) [setTimeout(...,0)などの使いドコロ - Qiita](https://qiita.com/jkr_2255/items/17693ab77beea71a871c)

↓setTimeout()なにもわからん．

[setTimeout仕様クイズ | クイズメーカー - こたえてあそぶ・つくってあそぶ・クイズのプラットフォームサービス](https://quiz-maker.site/quiz/play/JHWqig20210105134949)
複数銘柄の米国株価をPython pandasで一度に取得する

前回、銘柄名を指定して米国株価を取得しましたが、この方法では１つの銘柄しか取得できませんでした。

そこで今回は複数銘柄の株価一度に取得してみました。

#流れ
1.取得したい銘柄をCSVファイルに記載
2.CSVをjupyterフォルダに配置
3.銘柄毎にpandas datareaderで株価を取得

#詳細
**1.取得したい銘柄をCSVファイルに記載**
　ここではファイル名をtest_sp500.csvとします。

|Symbol|Name|Sector|
|------|----|------|
|AAPL|Apple Inc.|	Information Technology
|AMZN|	Amazon.com Inc|	Consumer Discretionary
|FB|	Facebook, Inc.|	Information Technology
|NFLX|	Netflix Inc.|	Information Technology
|MSFT|	Microsoft Corp.|	Information Technology
|V|	Visa Inc.|	Information Technology

**2.CSVをjupyterフォルダに配置**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696523/da5f41e8-86bc-b03d-aa14-12933da77e66.png)

**3.銘柄毎にpandas datareaderで株価を取得**

```python
import pandas as pd
import pandas_datareader.data as pdr
import datetime
from tqdm import tqdm

df = pd.read_csv('test_sp500.csv')

end = datetime.date.today()
start = end - datetime.timedelta(days=3)
stock = {} #株価を格納する辞書
error_symbols = [] #エラー用

for s in tqdm(df['Symbol']):
    try:
        stock[s] = pdr.DataReader(s,"yahoo",start, end)
    except:
        error_symbols.append(s)
```

取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696523/5e3fd7da-7b37-b3bf-17ae-b3579a192681.png)
AtCoder備忘録

#備忘録

#C問題
-[C - ABC Tournament](https://atcoder.jp/contests/abc188/tasks/abc188_c)
    - ヒント：分割すれば個々の結果を求める必要は無い

-[C - 1-SAT](https://atcoder.jp/contests/abc187/tasks/abc187_c)

-[C - Unlucky 7](https://atcoder.jp/contests/abc186/tasks/abc186_c)
    - 関数を用いれば任意の進数に変換できる
【Flutter】園児でもタイトルの中央寄せできるもん📛

# まえがき
[Flutter title中央寄せ🔍]で検索して一番上にでる記事の方法で実装したときにハマっちゃった💦

だから今後はITお兄ちゃん達に悲しい思いをしてほしくないということでこの記事をかくね:relaxed:


# いいやりかた⭕️

たぶんこの方法が一番いいとおもうの📛

centerTitle:trueを指定する

```main.dart
appBar: AppBar(
  centerTitle: true, // 中央寄せにするパラメーター
  title: Text(
    "たいとる"
  ),
),
```

これのいいところは戻るボタンが左側に来ても中央寄せがくずれないことなの:point_up:

:point_down:うごきはこんな感じ:point_down:

![good-title.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692320/548fa0c8-c87f-fa66-90cb-c7d2693cce6a.gif)



# よくないやりかた❌

Centerをつかう

```main.dart
appBar: AppBar(
  title: new Center(child: new Text("たいとる", textAlign: TextAlign.center))
),
```

これでだいじょぶなときもあるけど
戻るボタンが左側に来たときに正確な中央寄せにならなくなっちゃうんだ😢

:point_down:うごきはこんな感じ:point_down:
![bad-title.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692320/96c2e03b-6d39-9d1a-3644-70af7ae1a6ab.gif)


# おしまい

Flutterべんきょうちゅう！
要望とか訂正事項があったら[園児ニアのTwitter](https://twitter.com/enzi__nia)に連絡くれたらうれしいな

最後までみてくれて
ありがと。おにいちゃん📛
【Laravel初心者】コントローラー作成からルーティングまで

Laravel初学者です。
オリジナルアプリを作成しているのでその過程を記事にしています。

理解が曖昧なところも多いため、ご指摘等ありましたらご連絡いただければ幸いです。

前回は[モデル作成とマイグレーションまでの流れ](https://qiita.com/mumucochimu/items/35ebe809c60ec95702fe)を行なったので
今回はコントローラー作成からルーティングまでを行います。

## 環境

|                | Version     |
|:---------------|------------:|
| PHP            | 7.4.14      |
| Laravel        | 8.24.0      |
| mysql          | 8.0.23      |
| docker         | 20.10.2     |
| docker-compose | 1.27.4      |


## コントローラー作成

まずターミナルでそのプロジェクトのディレクトリまで移動します。
（私の場合はdockerなのでdockerコンテナ内です。)

そしてコントローラー作成のためのコマンドを入力します。

```PHP:ターミナル
php artisan make:controller <コントローラー名>
```

私の場合はGameコントローラーを作成したいので

```PHP:ターミナル
php artisan make:controller GameController
```

と入力しました。

```PHP
Controller created successfully.
```

と出力されれば成功です。

`app/Controllers`配下に`GameController.php`が生成されます。


## CRUDについて

CRUDとは

- C(Create)：生成
- R(Read)：読み取り
- U(Update)：更新
- D(Delete)：削除

の頭文字をとったものでデータの取り扱いの基本処理のことです。

LaravelのCRUDについては[こちらの記事](https://qiita.com/zaburo/items/9fefa3f6834b2e79b734)を参考に学びました。

>| アクション | 動作                            |
>|------- | ------------------------------- |
>| index  | 一覧表示                         |
>| create | 入力画面の生成とstoreへのデータの送信 |
>| store  | 情報を受け取り保存（一覧へリダイレクト）   |
>| edit   | 編集画面を表示し、updateにデータを送る |
>| update | editから送られたデータを受け取り更新する |
>| show   | 詳細表示                         |

とのこと。
Railsと似てるので私は分かりやすかったです。


## ルーティング

最初にみたいくつかの記事や技術書だとルーティングの記述は

```PHP:routes/web.php
Route::get('/sample', [SampleController::class, 'index'])->name('sample.index');
```

このような書き方でした。
`/sample`にアクセスがあった時、`Samplecontrollerのindexアクション`が`get`で動くという意味です。このルーティングを呼び出す時はnameの`sample.index`で指定します。

分かるけど、Railsみたいに

```Ruby:Rails
resources :samples, only: :index
```

とできたら楽なのになと思っていたら
[こちらの記事](https://qiita.com/sympe/items/9297f41d5f7a9d91aa11)にありました。ありがとうございます。

```PHP:routes/web.php
Route::resource('/hoge', App\Http\Controllers\HogeController::class);
```

上記のように書くことでCRUDルーティングを一度に行えます。

```PHP:routes/web.php
Route::resource('/hoge', App\Http\Controllers\HogeController::class)->only(['index']);
```

上記のように書くことでindexアクションだけにすることもできます。
無駄なものはない方がいいので必要なものだけにしましょう。

ルーティングの一覧は

```PHP
php artisan route:list
```

で確認することができます。
Linux远程连接

### 查看Linux网卡信息命令
```$ ifconfig [网卡名]```

### 主机SSH服务命令
- 启动SSH服务 ```$ sudo service ssh start```
- 停止SSH服务 ```$ sudo service ssh stop```
- 重启SSH服务 ```$ sudo service ssh restart```
- 查看SSH状态 ```$ sudo service ssh status```

### 远程连接Linux
```$ ssh [用户名]@[主机ip地址]```
サーバとは?

# 初めに
「サーバ」という単語はよく聞くが、皆が同じ意味で使用しているように思えなかった。
このため、初学者が検索して学んだことまとめた。

# サーバとは？
サーバ (***server***) は、広義としてサービスを提供するもののことを指す。
コンピューター(***HardWare***) に対してもプログラム (***SoftWare***) に対してでも同一単語が用いられることがある。

# 何をするのか
要求に対して、それに応じた返答を返す。
要求が「誰から」「どのようなもの」であるか、「返答」を「どのように」返すのかはものによって異なる。
広義で考えると漠然としていて「サーバ」が取り留めもないように思えるのも正しいと思える。
<img width="250" alt="server.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192737/a7b3cc07-34f3-df10-8451-7eccd9455563.png">


# どんなものがあるのか
簡単に機能別と状態別に分類できる。

# 機能別
サーバはサービス(要求に対して返答する行為)がある。
サービスはその目的に応じて、様々な機能を有する。
代表的なものを以下に挙げた。

|サーバ名|役割|
|---|---|
|Webサーバ|オブジェクトの表示提供|
|APサーバ|アプリケーションの実行|
|DBサーバ|データの運用、管理|
|プロキシサーバ|通信の中継|
|ファイルサーバ|ファイルの共有|
|メールサーバ|メールの配送|
|DNSサーバ|インターネット関係の何か|
|FTPサーバ|ファイルの通信|
|SIPサーバ|IP電話システムの管理|

サービスに応じて名称が異なるので、当然、非常に多くの名称がある。

# 状態別
サーバは広義としてその状態(環境)を指定しないので、物理的なものを指す場合とSW(機能)ブロックを指す場合がある。
サーバそのものの状態に応じて名称が分かれている。
・物理サーバ (***HardWare***) 
・仮想サーバ (***SoftWare***)

## 物理サーバ
物理的に存在するコンピューターのことを指す。
物理的な筐体があり、クライアントPCと同様にCPUや、メモリ、ストレージ、電源などが組み込まれる。
PCと部品(名称)は概念として基本的に同じであるが、スペックや構成が異なる。

## 仮想サーバ
物理的に存在するコンピューター上に、サーバが動作可能な環境をプログラムで構築したもののことを指す。

# まとめ
サーバには多数の種類がある。
「サーバ」という単語で会話する際は、実際に何を指しているのか注意する。

メモ：バックエンドのサーバで使用される言語は以下が代表的であるらしい。

|言語|種類|
|---|---|
|PHP|インタプリタ言語|
|Java|コンパイラ言語|
|Ruby|インタプリタ言語|
|Perl|コンパイラ言語|
|Python|インタプリタ言語|
|JavaScript (Node.js)|インタプリタ言語|


# 自身の関連記事

https://qiita.com/flcn-x/items/9b8c3e5657124b68139c

https://qiita.com/flcn-x/items/3b15fcae62df2e6b6667
pythonの自作Exceptionで変数を含むエラー内容を出力する

# はじめに
pythonで『例外クラスを自作する方法』、『**例外ごとに定型(変数を含む)のエラー内容**を返す方法』を調べたので、ここに整理しようと思います。

### ゴール
4桁の数字を与えて、それが正しい月日の表現になっているかチェックするコードを作りました。
4桁の数字ではなかったり、実在しない月日(13月など)になっている場合にエラー内容を出力することが目的です。
※ 今回は1月~12月の全てが31日まであることとしています（そこは今回は重要ではないので）

```bash:出力結果
###正しい月日を指定した場合
$ python main.py 0101
指定した日付は01月01日です。
$ python main.py 1231
指定した日付は12月31日です。

###誤った月日を指定した場合
$ python main.py 12345
[12345]は4桁の数字ではありません。例：1月2日なら0102の形式で指定してください。
$ python main.py 1301
[13]は月ではありません。01~12の値を指定してください。
$ python main.py 0132
[32]は日ではありません。01~31の値を指定してください。
```

# 自作の例外クラス
まず例外クラスを準備します。
今回は
・４桁の数字でない場合
・月が01-12でない場合
・日が01-31でない場合
の３つのパターンを用意しますが、いずれもエラー内容とエラーになった部分(引数)を出力したいので、`MyException`クラスを用意して例外インスタンス生成に属性として引数を格納するようにしています。

[\_\_str\_\_関数](https://docs.python.org/ja/3/reference/datamodel.html#object.__str__)はインスタンスにstrやprintが適用されたときにstringオブジェクトを返す特殊メソッドで、これをoverrideしてエラーメッセージを返すようにしています。

```python:Exception
class MyException(Exception):
    def __init__(self, arg=""):
        self.arg = arg

class InvalidInputException(MyException):
    def __str__(self):
        return (
            f"[{self.arg}]は4桁の数字ではありません。例：1月2日なら0102の形式で指定してください。"
        )

class InvalidMonthException(MyException):
    def __str__(self):
        return (
            f"[{self.arg}]は月ではありません。01~12の値を指定してください。"
        )

class InvalidDayException(MyException):
    def __str__(self):
        return (
            f"[{self.arg}]は日ではありません。01~31の値を指定してください。"
        )
```

（参考: [8.3. 例外を処理する](https://docs.python.org/ja/3/tutorial/errors.html#handling-exceptions)）
ちなみに、例外インスタンスでは`__str__`関数はインスタンスの引数を直接印字できるよう実装されているそうです。
> except 節では、例外名の後に変数を指定することができます。この変数は例外インスタンスに結び付けられており、 instance.args に例外インスタンス生成時の引数が入っています。例外インスタンスには __str__() が定義されており、 .args を参照しなくても引数を直接印字できるように利便性が図られています。必要なら、例外を送出する前にインスタンス化して、任意の属性を追加できます。


# メイン処理
ポイントは`try~except`の箇所かと思います。
Exceptionごとに定型のメッセージを出力するのは共通なので、Exceptionごとに補足時の処理を実装するよりも簡潔になります。
また、もし他の箇所でこれらのExceptionが使われる場合も同じように書けるので、メンテしやすいのかなと思います。


```python
import re
import sys
def main():
    # 引数が4桁の数字であるかチェック
    arg = sys.argv[1]
    check_arg(arg)

    # 引数を2桁ごとに分けて、月日であるかチェック
    month = arg[0:2]
    day = arg[2:4]
    check_month(month)
    check_day(day)

    print(f"指定した日付は{month}月{day}日です。")

def check_arg(arg):
    if not re.match("^\d{4}$", arg):
        raise InvalidInputException(arg)

def check_month(month):
    if not re.match("^0[1-9]|1[0-2]$", month):
        raise InvalidMonthException(month)

def check_day(day):
    if not re.match("^0[1-9]|[12][0-9]|3[01]$", day):
        raise InvalidDayException(day)

if __name__ == "__main__":
    try:
        main()
    except(
        InvalidInputException,
        InvalidMonthException,
        InvalidDayException,
    ) as e:
        print(e)
```

# 参考
参考にさせていただきました
[Qiita: Pythonで例外を投げるときのベストプラクティス](https://qiita.com/hasoya/items/05d4e49d492869875cca)
[Python 入門: Python のユーザー定義例外クラス](https://python.keicode.com/lang/python-user-defined-exception.php)
[note: pythonでスマートに例外処理をする](https://note.com/yucco72/n/n444de1f6d53b)
【Ruby】送料無料メソッド

【コード】

```
product = 2000

def shopping (p)
 if p < 3000
    q = p + 500
    puts "送料込み#{q}円"
 else
    puts "送料無料#{p}円"
 end
end

shopping(product)
```

【出力】

```
送料込み2000円
```

【解説】
ネットショップでよく見かける、¥〇〇円以上で送料無料という仕組みをメソッドにしてみます。
今回は¥3000以上であれば送料が無料になるという設定です。


product(商品)という変数を定義して数値(値段)を代入します。
標準入力から値を取得する場合は、

```
product = gets.to_i
```
となります。

shoppingメソッドを定義して、実引数()にproductを入れ、仮引数(p)に渡します。

¥3000以上か、¥3000以下かの条件を判定したいので今回はif文を使いました。


```
if p < 3000
    q = p + 500
    puts "送料込み#{q}円"
```

今回の設定では、¥3000以上の場合は送料無料であるため、
¥3000円以下場合は、送料である500をを足し算して、変数qへ代入
文字列の中に#{q}と記述し、文章として出力します。


```
else
    puts "送料無料#{p}円"
```

ifの条件を満たさなかった場合、つまりproduct変数の値が3000以上の場合は、実引数pをそのままの値#{p}として文章に組み込んで出力します。


設定する値を操作したい場合は

```
if p < 3000
```
の3000の部分を設定したい値に変えると、その価格として設定することができます。

¥1500以上で送料無料としたい場合

```
if p < 1500
```
という感じです。
M1 Mac (Mac mini) に GitHub CLI をインストールする


## Homebrew のインストール

[Homebrew](https://brew.sh/index_ja) のインストール

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

## 環境変数を設定する

Homebrew のインストールをすると最後に以下のように表示される。
ここで `ユーザー名` はそれぞれ自分のユーザー名になっている。

```
==> Next steps:
- Add Homebrew to your PATH in /Users/ユーザー名/.zprofile:
    echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> /Users/ユーザー名/.zprofile
    eval $(/opt/homebrew/bin/brew shellenv)
- Run `brew help` to get started
- Further documentation: 
    https://docs.brew.sh
```

以下の部分のコマンドをシェルに貼り付けて実行する。(`ユーザー名`の部分は実行したユーザーの物になっているので実際の実行結果をそのまま貼り付けるだけで良い)

```
    echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> /Users/ユーザー名/.zprofile
    eval $(/opt/homebrew/bin/brew shellenv)
```

前者のコマンドで次回シェルを開くときに自動的に処理が行われるようして
後者のコマンドで今開いているシェルに対して処理を行う。

参考

https://zenn.dev/ress/articles/069baf1c305523dfca3d

## GitHub CLI をインストールする

```
brew install gh
```

## GitHub CLI で GitHub にログインする

```
gh auth login
```

を実行するとテキストベースでウィザードが出るので手順どおりに設定する。
ファイル監視シェル


#目的
夜間にバッチ処理を終えるとサーバをシャットダウンする要件があったので作成しました。
ファイル監視シェルで特定のファイルを監視しておき、夜間バッチの最後の処理で監視対象のファイルを更新することでバッチサーバをシャットダウンしています。

使い方によってはシャットダウンではなく、バッチ1が処理を終えるとバッチ2を起動するなどでも使えると思います。

#構築環境
OS:Amazon Linux2
shell:bash

#ファイル監視シェルの作成
##シェルファイルを作成
シェルファイルの配置先は極論、任意かもしれませんが、
特に要件がなければ以下で考えてます。

| シェルの用途 | 配置先 |
|-------|-------|
|一般ユーザーも使う| /usr/local/bin/|
|システム管理用| /usr/local/sbin/|
|特定のユーザーしか使わない| $HOME/bin/|

今回はログインユーザーのbinに配置します。

```
$ mkdir -p ~/bin/monitoring
$ vim ~/bin/monitoring/monitoring.sh
```

##ファイル監視シェルを実装
シェルでは、以下を任意に指定します。
①監視対象とするファイル
②監視間隔（秒）

監視対象ファイルの更新日付をチェックし、更新されればシャットダウンします。

監視対象ファイルが更新された際に実行するコマンドをshutdownコマンドはなく、
他バッチを実行するコマンドにすれば、バッチの連続実行にも使えそうです。
今回は設定値をシェルに埋めてますが、パラメータとして受け取れば、もっと可変的に使用出来ると思います。

```
#!/bin/sh

# 設定値■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# 監視間隔, 秒で指定
INTERVAL=1 
# 監視対象のファイルを指定
MONITORING_FILE=/home/ec2-user/monitoring/file.txt 
# 監視対象ファイルが更新された際に実行するコマンド
EXEC_COMMAND="sudo shutdown -h now" 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

last=`date -r ${MONITORING_FILE} +%s`
while true;
do
  sleep $INTERVAL
  current=`date -r ${MONITORING_FILE} +%s`
  if [ $last -ne $current ];
  then
    $EXEC_COMMAND
    exit 0
  fi
done

echo "end"
```

##実行権限を付与
ファイルを作成した段階では実行権限が無いため、実行権限を付与します。

```
$ chmod 755 ~/bin/monitoring/monitoring.sh
```

#監視対象のファイルを作成
任意の場所にシェルで監視するファイルを作成します。

```
$ mkdir ~/monitoring
$ touch ~/monitoring/file.txt
```


#systemdでシェルを自動起動するように設定
##サービスファイルを作成
systemdで管理するためにサービスファイルを作成します。

```
sudo vim /etc/systemd/system/monitoring.service
```

サービスファイルの詳細は以下の通り

```
[Unit]
Description=monitoring

[Service]
Type=simple
User=ec2-user
Restart=on-success
ExecStart=/home/ec2-user/bin/monitoring/monitoring.sh

[Install]
WantedBy=multi-user.target
```

##自動起動するように設定
```
$ sudo systemctl enable monitoring
```

##サービス起動
```
$ sudo systemctl start monitoring
```

##サービス起動を確認
runnning状態になっていれば起動OKです。

```
$ sudo systemctl status monitoring
● monitoring.service - monitoring
   Loaded: loaded (/etc/systemd/system/monitoring.service; enabled; vendor preset: disabled)
   Active: active (running) since 土 2021-08-07 06:31:52 UTC; 6s ago
 Main PID: 3855 (monitoring.sh)
   CGroup: /system.slice/monitoring.service
           ├─3855 /bin/sh /home/ec2-user/bin/monitoring/monitoring.sh
           └─3869 sleep 1
```
Linux的文件目录结构

- / 根目录
  - /dev 存放抽象硬件
  - /lib 存放系统库文件
  - /sbin 存放特权级二进制文件
  - /var 存放经常变化的文件
  - /home 普通用户目录
  - /etc 存放配置文件目录
  - /boot 存放内核与启动文件
  - /bin 存放二进制文件（可执行命令）
  - /usr 存放安装程序（软件默认目录）
  - /mnt 文件挂载目录（u盘、光驱）
  - /root 特权用户目录
  - /opt 大型软件存放目录（非强制）
Apple M1 CPUがなぜ速くなれたのか？

思いつきだが、CPUとOSの両方をリリースできた事にあるのかもしれない。
詳しく調査してないので、以下は、想像です。

CPUはIntelが主で,OSはWindowsが主流。メーカーが違うのでx86アーキテクチャの縛りの中でしかリリースできなかった。

なぜなら、費用対効果だろう。x86以外のCPUとなるとPowerPCなどでも対応を見送ってきたWindows。大規模OSでは、別アーキテクチャへの対応の費用対効果で見送ったのでは無いかと思う。

AMDが提供したx64アーキテクチャもx86の縛りの中での拡張というイメージ。

縛りの中で拡張するしかなかった。独占企業だし。

それがAppleはCPUもOSも提供できる事に強みがあったのかと。

Rosseta？という下駄を履かせ(=emulateし)てx86アーキテクチャ用アプリを動かした。ほぼOSへの組み込み?(RossetaはCPUへの組み込み?)で動かしたのだから、これは大変なブレイクするーなんじゃないかと思う。

正直、M1はx86よりずっと遅いと思ってた。再コンパイルなしに、iOSと同一アプリを動かすためにARMアーキテクチャに揃えたとばかり思っていたので、M1 CPUがベンチマークでよいスコアを残したのは意外だった。

今後は、脱x86, x86_64アーキテクチャーの動きが進むかもしれない。Armは低電力で高パフォーマンスを出せるなら、そちらに乗り換える動きも増えるかもしれない。

AppleがCPUを単体で販売するならまだしも、Appleは自社製品の中でしか提供しない恐れがある。そうすると開発の蓄積があるサムスン?やソフバンがARM社を譲渡したNVidia社が一気にCPU市場のマーケットの支配図を塗り替えるかもしれない。MicrosoftもArmには興味を持って、WindowIoTやノーマルWindowsをArmで動かす話もなくはないのではなかろうか。
injectメソッド（たたみ込み演算）を理解する

## 背景
- Railsで検索フォームを作っています
- お手本のコードに読み慣れないメソッドが多数だったので、勉強しながらノートにまとめてみました

▼環境
- Ruby 2.6.0

なお、この記事は以下の２つの記事を参考に学習したことをまとめたものです。

- [instance method Enumerable#inject](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html)
- [【Ruby入門】injectの使い方をわかりやすくまとめてみた！](https://www.sejuku.net/blog/19219)

## `inject`メソッドとは

たたみ込み演算ができるメソッドです。
基本の構文は下記の通り。

```
配列.inject {|初期値, 要素| ブロック処理 }
```
具体的なコードにすると、こうなります。

```Ruby
[1, 2, 3, 4, 5].inject {|result, item| result + item }
# => 15
```

この時、以下の計算がされています。

```sh
1 + 2 + 3 + 4 + 5
```

### 初期値の設定

`inject`には、初期値が設定できます。

```ruby
[1, 2, 3, 4, 5].inject(6) {|result, item| result + item }
# => 21
```

この時、以下の計算がされています。

```sh
6 + 1 + 2 + 3 + 4 + 5
```

### eachとの書き換え

`inject`メソッドは、下記のように`each`に書き換えることができます。

```Ruby
# これと
[1, 2, 3, 4, 5].inject(6) {|result, item| result + item }

# こちらの処理は同じ
result = 6
[1, 2, 3, 4, 5].each do |item|
  result = result + item
end
result
```

上記の通り、injectを使うとコードがコンパクトになりますが、[最初に紹介したこちらの記事](https://www.sejuku.net/blog/19219)でも言っている通り、

> ただ、何をやっているのかは、eachメソッドの方がわかりやすいです。
injectになれてきたら、injectを書いていきましょう。

...ので、当面はeachを使おうと思います。
ES6で追加されたループ処理メソッドをまとめる【reduce】




## reduceはどういうメソッドか？
reduceが、その他のループ処理メソッドと大きく異るのは、累積値を持てるところです。
その特性から、配列の要素を累積していき、1つの値にするする際に最適なメソッドです！

簡単な例だとこんな感じです↓

```js
//numbers配列の中身を合計していく処理

const numbers = [1,2,3,4,5];
let result = numbers.reduce(function(acc, num) {
 
  return acc + num;
 
},0)
 
console.log(result);

// 15 が出力されます
```

## 構文
それではreduceの構文と挙動について見ていきます。

```js
// 上と同じサンプルです。
const numbers = [1,2,3,4,5];

let result = numbers.reduce(function(acc, num) {
//reduce()の中でコールバック関数を書きます
//コールバック関数の引数には、(累積値,配列の各要素)を取ります

  return acc + num;
// 実行したい式

},0)
// 初期値(acc)の値をセット
```
この例だと、accは０から始まりループが終わるごとに returnされた結果がセットされていくことになります。
そしてaccは次回の処理に引き継がれていきます。

|  実行回数 |  acc  |
| ---- | ---- |
|  1回目  |  1  |
|  2回目  |  3  |
|  3回目  |  6  |


### いろんなサンプル


##### 配列が持つ要素の文字列合計を集約
```js
const animals = ["cat","dog","fish"];

let total = animals.reduce(function(acc, word) {
  return acc + word.length;
}, 0);
```

##### 累積値を配列にしてmapのような動きをさせる
```js
const primaryColors = [
  {color:"red"},
  {color:"yellow"},
  {color:"blue"}
];

primaryColors.reduce(function(acc, pc) {
  acc.push(pc.color);
  return acc
}, []);
```

##### プロパティを集約してみる
```js
const desks = [
  { type: 'sitting' },
  { type: 'standing' },
  { type: 'sitting' },
  { type: 'sitting' },
  { type: 'standing' }
];

let deskTypes = desks.reduce(function(acc, el) {
    if(el.type === "sitting"){
        acc.sitting +=1;
    }else{
        acc.standing +=1;
    }
    
    return acc;
}, { sitting: 0, standing: 0 });
```
webpackハンズオン

この記事は JSL (日本システム技研) Advent Calendar 2020 - Qiita 25日目の記事です。


## webpackとは
- JavaScriptファイルをひとつにまとめるツール
  - ローダーを使えば他のファイルもまとめることができる
- それぞれのファイルを束ねる(バンドルする)役割から、**モジュールバンドラー**とも呼ばれる
- 複数のJavaScriptコードの**依存関係**を自動で解析して、バンドルしてくれる

--- 
<b>メリット </b>  

- 自動的に依存関係を解決してくれる  
- リクエストの回数を抑える
  - 複数のファイルをひとつにバンドルすることで、リクエストを減らせる -> 転送効率上昇

> 前述の利点から、多くのJavaScriptフレームワークで採用されている。
　ex ... Angular、React、Vue.js   　
これらのフレームワークを学ぶ上で有用な前提知識を本記事で身につけましょう。👍



## ハンズオン準備

### 作業フォルダの作成
- 作業ディレクトリは`study-webpack`としてハンズオンを進めていく  

```
- study-webpack
|- ...
```

> ※後述の操作について、特別な指定が無い場合は`study-webpack`直下で実行しています  

### プロジェクトの作成

- 以下のコマンドを実行し、設定ファイル(package.json)を作成

```
> npm init -y
```

- webpack/webpack-cliをインストールする

```
> npm install --save-dev webpack@4.44.1 webpack-cli@3.3.12
```

### バンドル対象のファイルを準備

```
- study-webpack
|- dist
|   |- index.html <- index.jsを呼び出すhtmlファイル
|- src
    |- index.js  <- myutilモジュールを呼び出し実行するjsファイル
    |- myutil.js <- 三角形の面積を求める関数などを定義したjsファイル
```

以下、ソースコード 

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>webpackハンズオン</title>
</head>
<body>
  <p>Hello, webpack</p>
  <script src="./main.js"></script>
</body>
</html>
```

```javascript:index.js
var myutil = require('./myutil');

console.log(myutil.APP_NAME);
myutil.hello();
console.log(myutil.Figure.getTriangle(10, 5));
```

```javascript:myutil.js
const message = 'こんにちは、webpack！';
const APP_NAME = 'webpackハンズオン';

function hello() {
    console.log(message);
}
class Figure {
  static getTriangle(base, height) {
    return base * height / 2;
  }
}

module.exports = {
  message,
  APP_NAME,
  hello,
  Figure
};

```

> 上記ディレクトリ/ファイルが用意できたらバンドルを行う準備は完了です。👍

## バンドルの実行

- バンドル対象のファイルが準備できたので、以下のコマンドを実行

```
> ./node_modules/.bin/webpack
Hash: 419eec4e9cda32e1d2f8
Version: webpack 4.44.1
Time: 266ms
Built at: 2020-10-22 01:15:59
  Asset      Size  Chunks             Chunk Names
main.js  1.07 KiB       0  [emitted]  main
Entrypoint main = main.js

```

実行後、dist配下にmain.jsが作成されていることを確認する。   
![20201225002816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397734/18e2832f-abcc-5456-374b-074fe91f848f.png)


- index.htmlをブラウザで開く

```
>  open index.html
```

![20201225003018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397734/650c0128-c58d-cb54-9742-e9dd8b2c9307.png)



`Hello, webpack` の文言と、コンソールにログが出力されていればバンドルに成功。👍

> **main.js**は、index.jsとmyutil.jsがバンドルされて作成されたファイルのため、index.htmlは**main.js**の参照だけでindex.jsとmyutil.jsのプログラムを利用することができるようになりました。🎉


設定ファイル(webpack.config.js)を別途定義することによって、バンドルの仕方はいろいろ変更することもできるので、調べて試してみましょう。