OmniAICreator/Qiita-1.07M huggingface dataset:
sketchupでruby その15

# 概要

sketchupでrubyやってみた。
translation使ってみた。

# 写真

![ido.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0ef8bda8-7430-28dd-86fe-e898388f2c66.png)


# サンプルコード

```
def ido
   model = Sketchup.active_model
   entities = model.active_entities
   unit = 10
   p = Array.new
   p[0] = ORIGIN
   p[1] = [unit, 0, 0]
   p[2] = [unit, unit, 0]
   p[3] = [0, unit, 0]
   group = entities.add_group
   face = group.entities.add_face p
   face.reverse! if face.normal.z < 0
   face.pushpull unit
   trans = Geom::Transformation.translation [10, 0, 0]
   group.transform! trans
end



```


以上。
sketchupでruby その14

# 概要

sketchupでrubyやってみた。
scaling使ってみた。

# 写真

![bai.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/c21150c5-8872-1b0c-6deb-9586b3f66dd7.png)


# サンプルコード

```
def bai
   model = Sketchup.active_model
   entities = model.active_entities
   unit = 10
   p = Array.new
   p[0] = ORIGIN
   p[1] = [unit, 0, 0]
   p[2] = [unit, unit, 0]
   p[3] = [0, unit, 0]
   group = entities.add_group
   face = group.entities.add_face p
   face.reverse! if face.normal.z < 0
   face.pushpull unit
   scale = Geom::Transformation.scaling Geom::Point3d.new(0, 0, 0), 2, 2, 2
   group.transform! scale
end


```


以上。
Amazon Linux 上でGitlabを更新する際のTips

## TL;DR
- GitlabのRPM追加スクリプト（`script.rpm.sh`）に変更が入り、AmazonLinux2はel/7（CentOS 7）ベースと判定されるようになった
- 新規インストールの場合は問題ないが、既存更新の場合は一度最新の `script.rpm.sh` を実行する必要がある
- テストが通っている声明はでているものの、Amazon Linux2は公式サポート外のOSとなっている

以下、もうちょっとだけ詳しい話を書きます。

## Gitlabの公式サポートからel/6はなくなっている
これはまぁそりゃそうだろと思うんですが、el/6、つまりCentOS6のラインはGitlabの公式サポートからは外れています。そりゃあそうです。

以下のGitlabのRPM一覧ページを見ても、el/6は１３．６．７を最後にパッケージのリリースがありません。

- https://packages.gitlab.com/app/gitlab/gitlab-ce/search?dist=el%2F6&filter=rpms&page=3&q=-13.

というわけで、最新版をelのラインで利用しようとする場合には、最低でも`el/7`のラインを利用しないといけません。

## AmazonLinux2はGitlabのインストールスクリプトでは`el/6`として扱われてきた
これまで、AmazonLinux2上でyumパッケージとしてgitlabを利用しようとした場合、以下のスクリプトを用いてrpmレポジトリを追加する必要がありました。

- https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh

現在のスクリプトでは問題ありませんが、過去のスクリプトでは上記の条件分岐に於いてAmazonLinux2が`el/6`相当と判断されるという問題があり（修正はおそらく[2021年2月](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5902#note_506571451)）、少なくとも２０２０年以前にGitlabをインストールしていたばあいは、el/6のレポジトリを参照する設定となっていると思われます。

## 修正方法は最新のrpm追加スクリプトを走らせるだけ
修正は実はそこまで大変ではなく、上記で書いた[script.rpm.sh](https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh) をもう一度実行すればそれで問題ありません。

あとは`yum`コマンドで最新パッケージが利用できるようになります

## 一応、公式にはAmazonLinux2は未サポート
これで一応動くようにはなりますが、公式の声明からもAmazonLinux2はサポート対象OS外です。

- https://docs.gitlab.com/omnibus/update/#gitlab-137-and-later-unavailable-on-amazon-linux-2

ちゃんと動かすなら、以下の公式サポートOSから選ぶのが無難そうですね

- https://docs.gitlab.com/ee/install/requirements.html#supported-linux-distributions
pythonでgnuradio その6

# 概要

pythonでgnuradioやってみた。
AM変調を録音。
信号は、440ｈｚのサイン波、搬送波は、5KHZ。

# サンプルコード

```
from gnuradio import gr, blocks, analog

class my_top_block(gr.top_block):
	def __init__(self):
		gr.top_block.__init__(self)
		samp_rate = 32000
		self.blocks_wavfile_sink_0 = blocks.wavfile_sink('a2.wav', 1, samp_rate, 8)
		self.blocks_multiply_xx_0 = blocks.multiply_vcc(1)
		self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((0.3, ))
		self.blocks_head_0 = blocks.head(gr.sizeof_gr_complex*1, 64000)
		self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
		self.blocks_add_const_vxx_0 = blocks.add_const_vcc((1, ))
		self.analog_sig_source_x_1 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, 5000, 1, 0)
		self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, 440, 1, 0)
		self.connect((self.analog_sig_source_x_0, 0), (self.blocks_add_const_vxx_0, 0))
		self.connect((self.analog_sig_source_x_1, 0), (self.blocks_multiply_xx_0, 1))
		self.connect((self.blocks_add_const_vxx_0, 0), (self.blocks_multiply_xx_0, 0))
		self.connect((self.blocks_complex_to_real_0, 0), (self.blocks_multiply_const_vxx_0, 0))
		self.connect((self.blocks_head_0, 0), (self.blocks_complex_to_real_0, 0))
		self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_wavfile_sink_0, 0))
		self.connect((self.blocks_multiply_xx_0, 0), (self.blocks_head_0, 0))

if __name__ == '__main__':
	try:
		my_top_block().run()
	except KeyboardInterrupt:
		pass


```

以上。
AWSでエラー【Redirecting to /bin/systemctl start mysqld.service】sudo service mysqld start 実行時

タイトルの通りのエラーが発生し、mysqlが起動できない

# 問題を探す

## 1. 別のDBがインストールされている？
確か、mariaというDBが最初から入っている、と聞いたことがあるので、もしかしたらそれかもしれない。下記実行。

```
$ yum list installed | grep mariadb
```

何も表示されない。問題はここじゃない。

## 2. そもそもmysql はインストールされているよね？
```
mysqld --version *実行

mysql  Ver 8.0.24 for Linux on x86_64 (MySQL Community Server - GPL) *結果
```

mysql 8.0.** は確かに存在している。

## 3. インスタンス起動時は自動起動するようにしてみる

```
$ sudo systemctl start mysqld.service
$ sudo systemctl enable mysqld.service
```

これで起動してないだろうか。

再度、下記実行

```
sudo service mysqld start

Redirecting to /bin/systemctl start mysqld.service
```

結果は変わらず。


## mysql のステータス確認

下記実行。

```
systemctl status mysqld.service
```

結果:

```
mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2020-06-04 06:12:59 UTC; 6min ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 11780 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 11854 (mysqld)
   Status: "Server is operational"
   CGroup: /system.slice/mysqld.service
           └─11854 /usr/sbin/mysqld
```

「Active: active (running)」だから、起動しているのでは？

じゃあ、`Redirecting to /bin/systemctl start mysqld.service` ってなんだ？？

## 結論
`Redirecting to /bin/systemctl start mysqld.service`はエラーじゃないっぽい。
winユーザーがnodeをインストールするまで　Chocolatey & nvm

#はじめに#
windows10でnodeを入れた記事になります。


nodeを入れるにあたり、色々調べつつ何とかインスコできたので
その手順を公開しておく！

手探りでインストールしたため不正確な部分があるかもしれませんが
誰かの役に立てば幸いです。

#nodeインストールまでの流れ#

**Chocolatey → nvm → node**
この順番で進めていく

Chocolateyから直接nodeをインストール出来るようですが
バージョンマネージャ(nvm)を噛ませて、複数バージョン使える状態の方が良いそうだ。


##Chocolateyのインストール##
PowerShellから以下コマンドを実行

```powershell
iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex
```
<br>
しばらく時間がかかるので放置。

完了すると以下のような文言が出ます。

```
~（省略）~
 first prior to using choco.
Ensuring Chocolatey commands are on the path
Ensuring chocolatey.nupkg is in the lib folder
```

途中でWarningみたいなのが出ますが、放っておけば大丈夫でした。

##nvmのインストール##
続いてnvmのインストール

PowerShellで以下コマンドを実行

```powershell
choco install nvm
```

<br>
途中で下のような文言が出てきます。

```
Do you want to run the script?([Y]es/[A]ll - yes to all/[N]o/[P]rint):
```

スクリプトを実行していいか聞かれているので、「y」を入力してEnter

###インストール出来ているか確認###
nvmのインストール後にPowerShellを開き直し、以下コマンド

```powershell
nvm
```
<br>
下の画像のような感じで出れば大丈夫です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100934/d72cc9f1-4390-a4a6-4e46-3f8ad301225e.png)

##nodeのインストール##

今回は14.4.0をインストールします

```powershell
nvm install 14.4.0
```

***利用可能なバージョン***
以下のコマンドでバージョンの一覧が見れる

```powershell
nvm list available
```

###インストール出来ているか確認###
インスコ出来ていれば、以下のコマンドでnodeのバージョンが表示できます。

```
node -v
```

<br>
ここまで出来たらnodeのインストールは完了です！

#おまけ#
せっかくなので、nodeを対話モードで実行してみる

##nodeコマンド##
以下実行

```
node
```

<br>
↓のように「**>**」が出てきて、jsを一行づつ実行できる状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100934/433a4716-cf75-d708-2aa0-37e8eb58a118.png)


##nodeでHello World##
以下のコマンドを1行づつ実行します

```
> const hoge = 'Hello World';
> hoge
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100934/f209ffda-e82f-7c16-1a8e-0d532c7f104c.png)
[Rails6]Production環境でrails db:reset ,db:dropができない時

今回は下記を参考にさせていただきました。

https://qiita.com/Esfahan/items/75ade0233fe02ab04381

## はじめに
Railsアプリの本番環境で`rails db:reset`を実行した所以下のエラーが出ました。

```
$ rails db:migrate:reset RAILS_ENV=production
rails aborted!
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments
(See full trace by running task with --trace)
``` 
## 原因
Rails5からはproduction環境で破壊的処理(内容は以下に記述)をすることができなくなっている。

```
db:drop
db:drop:all
db:reset
db:purge
db:purge:all
db:purge:test
db:schema:load
```

## 解決方法
ヒントはエラーメッセージに記載されている。

```
$ rails db:migrate:reset RAILS_ENV=production
rails aborted!
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1 ←ここ
```

環境変数として`DISABLE_DATABASE_ENVIRONMENT_CHECK=1`を指定することでコマンドを実行することができます。

```
$ rails db:migrate:reset RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1
Dropped database 'hogehoge_production'
Created database 'hogehoge_production'
== 20210311185651 DeviseCreateUsers: migrating ================================
```

以上です。
[AWS]ssh: connect to host xxx.xxx.xxx.xxx port 22: Operation timed outを解消

今回はこちらの記事を参考にさせていただきました。

https://qiita.com/tkmd35/items/2cbb08cd64e6fa748294

## エラー内容
EC2でSSH接続をしようとした所エラー発生

```
ssh: connect to host xxx.xxx.xxx.xxx port 22: Operation timed out
```
## 結論
元々作業していた所からコワーキングスペースに移動した為エラーが起きた。
要するにEC2インスタンスのセキュリティグループ、SSH接続設定と自分の接続元（IPアドレス）に問題があった。
具体的にはEC2のインスタンスのセキュリティのインバウンドルールのSSH接続のソースを「マイIP」に設定した。これにより、設定した作業場所じゃないとSSH接続ができなくなってしまう。
コワーキングスペースに移動すると接続元のIPアドレスが変わってしまった為、接続元が許可されずエラーになった。

## 解決方法
1. AWSのサービス検索欄から「EC2」を検索
1. 「セキュリティグループ」を選択
1. 該当EC2インスタンスにチェック
1. インバウンドルールから「インバウンドルールを編集」を選択
1. タイプSSHのソースで「マイIP」を選び直す。※推奨  
もしくは「任意の場所」にを選ぶ 
1. ルールを保存をクリック

こうすると、作業場所のIPアドレスからのSSH接続を許可したことになります。

```
$ ssh -i .ssh/ファイル名.pem ec2-user@xxx.xxx.xxx.xxxa #EC2インスタンスのパブリックIP
```

なぜ「マイIP」が推奨かというと万が一SSHキーが流出し時の危険性を考えるとこちらの方がセキュアだからです。
毎回接続元を変えなければならないのは面倒ですが、もし流出してしまった場合はAWSから高額請求がくることがあるのでここで保険を打っておいた方が無難ですね。
【Clip Studio】ベジェ曲線と発光

環境メモ
⭐️Mac Book Pro(macOS Catalina)
⭐️CLIP STUDIO PAINT PRO version 1.10.6(体験版）


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🌈CLIP STUDIO PAINT🌈<br>初めて💎クリスタ💎やってみた💕とっても楽しい😍<br>ツールを覚えるまで時間かかりそうだけど、デジタルイラストの塗りにチャレンジしてみよぉ😊<a href="https://t.co/eOQhf2e2Co">https://t.co/eOQhf2e2Co</a><a href="https://twitter.com/hashtag/clipstudio?src=hash&amp;ref_src=twsrc%5Etfw">#clipstudio</a> <a href="https://t.co/3Od4hiO7I5">pic.twitter.com/3Od4hiO7I5</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1386379717809344512?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

完成内容
![キラキラ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/fa0abdc2-5f2c-2cb1-b478-1d9dc8f8ba89.jpeg)

# ベジェ曲線で描く
新規ベクターレイヤーを作成する
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/495c4f63-2411-a59f-99b4-c288c7834542.png)

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/9a9f2bfe-1707-7a31-c2f7-3e6b2efc8f56.png)

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/40475020-47f4-b7ea-0911-ecdcfda9bd04.png)

「図形」から「ベジェ曲線」を選択し、曲線を描く
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/3abff8f3-34e2-8e3b-e343-054e13276bb5.png)

# 「ベジェ曲線」を選択するには
「①操作」から「②オブジェクト」を選択すると、「ベジェ曲線」が選択できる
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/8358ac04-45a1-bde7-1b56-6717087fe2a0.png)

#「ベジェ曲線」にグラデーションを塗る
「①グラデーション」を選択し、グラデーションを作る
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/7f3ed8fb-28fb-1d61-fc46-088d2b4e6137.png)

「レイヤー」-「レイヤー設定」-「下のレイヤーでクリッピング」すると、「ベジェ曲線」にグラデーションができる
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/ecb615a6-e593-c28c-6711-8e7148c4bf8e.png)

グラデーションができる
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/99f24416-6410-1131-e103-21f08ef8d37c.png)

# 発光させる
「①合成モード」「②加算（発光）」
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/73e85faf-f05b-5ac7-3190-2aae2ee2d6bd.png)

「レイヤー」-「ラスタライズ」
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/0cd2ae2d-2f49-13c4-699e-8b68497c9780.png)

「フィルター」-「ぼかし」-「ガウスぼかし」
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/738cf297-1d67-8f34-f7dd-671d0291e65b.png)

ぼかす範囲を「180」ぐらいに設定
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/0aaaacb6-d860-ee5b-689b-cdf20649ce16.png)

完成！！
![完成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/de5ec82e-a6a6-4740-59f3-57d79cf82cc2.png)
Docker ComposeでWordPressのテーマ開発環境を一瞬で作成する

# きっかけ
WordPressでテーマ開発をする際、
用意された環境が本番環境しかないときがあります。
そんなとき、Dockerでローカル環境のWordPress検証環境をすぐに作れるようにしたく、
用意することにしました。

# 環境
- Mac、WindowsどちらでもOK
- `Docker`、`Docker Compose`両方をインストール済

# ディレクトリ構成
WordPressのローカル検証環境を立ち上げられば良いので、シンプルな構成にします。
まずはプロジェクト用の適当なフォルダを用意します。
（ここでは`wordpress-docker`という名前にしました。）

```
 wordpress-docker/
  └─docker-compose.yml
```

# 開発用の空テーマをダウンロード
開発用の空テーマを用意します。
[underscores.me](https://underscores.me/) というサイトから空テーマを取得することができます。
今回は、`original-theme` という名前のテーマを作成したいので、
`original-theme`と入力してダウンロードします。
![original.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111785/93e6fa8c-0f97-4285-9977-bd555d6a6862.png)
このフォルダはWordPressコンテナの`wp-content/themes`にマウントしたいので、
ダウンロードしたら、`wordpress-docker`ディレクトリに配置します。

```
 wordpress-docker/
  ├─original-theme/
  │  ├─inc
  │  ├─js
  │  ├─languages
  │  ├─...
  │  
  └─docker-compose.yml
```

# docker-compose.yml作成
`wordpress-docker` ディレクトリ配下に、`docker-compose.yml`を作成します。

```yml:docker-compose.yml
version: '3'

services:
  db:
    image: mysql:5.7
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: rootwordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    volumes:
      - db-data:/var/lib/mysql


  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./original-theme:/var/www/html/wp-content/themes/original-theme

  phpmyadmin:
    depends_on:
      - db
    image: phpmyadmin/phpmyadmin
    ports:
      - "8081:80"

volumes:
  db-data: {}
```

# Docker起動
Docker Composeを使って立ち上げます。

```shell
$ docker-compose up -d
```

# アクセスする
WordPressコンテナはポート`8001`で動かしているので、
[http://localhost:8001](http://localhost:8001)にアクセスします。
WordPressのインストール画面が表示されれば成功です。
![wordpress.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111785/5abeeecc-fc35-d381-83bc-2857d10f6333.png)
あとは、手順に沿えばWordPressのインストールは完了です。

phpMyAdminのコンテナもポート`8081`で追加しているので、
データベースには[http://localhost:8081](http://localhost:8081)でアクセスできます。

# 作成した空テンプレートを有効化する
先ほど作成した空テーマ `original-theme` を有効化します。
![test.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111785/cf4b232d-e541-0072-f22a-6e12e088146a.png)
これでローカル環境でテーマ開発がいくらでもできますね！
また `wordpress-docker` ディレクトリをGitで管理するようにしてしまえば、
複数人で開発するときにも便利です。
草野球の出欠確認Webアプリを作ろう！　part.1

これから作っていく簡単なWebアプリの作成メモ（自分の備忘）です。
自分用なのであまり凝りすぎないように書いていきたい。

##環境などメモ
・WSLのUbuntu（20.04.2 LTS (Focal Fossa)）
・Ruby on Rails（ruby 3.0.1p64 / Rails 6.1.3.1）
・PostgreSQL（psql (PostgreSQL) 12.6 (Ubuntu 12.6-0ubuntu0.20.04.1)）

##今回やったこと

###環境構築
####DB関連
以下の記事を参考にした。
[Windows10のWSL(Ubuntu)にPostgreSQLをインストールしたときのメモ](https://qiita.com/syutaro/items/d08c5c7cc24cddf7694c)

####Rails環境構築
以下の記事を参考にした。
[[Rails] Windows10 で WSL を使って Rails 環境を構築したときのメモ](https://qiita.com/ksh-fthr/items/64a4e86c8bad08322c94)

※Yarnをインストールしないとエラーになったのでバージョンによっては注意が必要。
[Rails6 開発時につまづきそうな webpacker, yarn 関係のエラーと解決方法](https://qiita.com/NaokiIshimura/items/8203f74f8dfd5f6b87a0)


####Rails初期セットアップ
以下は前述の手順と被りもあるが一応書いておく。

```bash
$ bundle install
$ rails new SampleApp
$ bin/rails db:create
$ bin/rails db:migrate
$ bin/rails s
```

###機能作成
####Userモデルの作成

以下の記事を参考にした。
[Rails「ユーザーのモデルを作成する」](https://qiita.com/macotok/items/a17a4b0d22db4e885678#validation%E3%81%A8%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA)

####Userコントローラーの作成
以下の記事をコントローラー生成時に参考にした。
[Rails generate の使い方とコントローラーやモデルの命名規則](https://qiita.com/higeaaa/items/96c708d01a3dbb161f20)

```bash
$ rails g controller Users index show new create edit update delete
```

ルートファイルを編集した。

```ruby:routes.rb
Rails.application.routes.draw do
  # ルート
  root "users#index"

  # Users
  resources :users
end
```

viewsにユーザー一覧を追加した。

```erb:users/index.html.erb
<h1>メンバーの一覧</h1>
<% if @users.empty? %>
  <div><%= "表示できるメンバーがいません。" %></div>
<% else %>
  <table align="center">
    <thead>
      <tr>
        <th>ユーザー名</th>
        <th>メールアドレス</th>
      </tr>
    </thead>
    <tbody>
      <% @users.each do |lst| %>
        <tr>
          <td><%= lst.name %></td>
          <td><%= lst.email %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
<% end %>
```

コントローラーのindexアクションにUserモデルの値を渡すよう編集する。

```ruby:controllers/users_controller.rb
def index
  @users = User.all
end
```

※初回動作確認時にrails serverは再起動しておくといいかも（bycryptのbundleのタイミング次第ではエラーになる）

このあと、コンソール経由でユーザーを登録して動作確認した。

```bash
$ rails c
$ User.new(name:"admin",email:"admin@example.com",password:"administrator",password_confirmation:"administrator").save
```

![ユーザー一覧の試作１](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534558/e1f269f1-88f5-8518-01e3-e66149b74bb6.png)

テーブルのデザインが気に入らなかったので、Webから適当に探してきて試す（以下を参照）。
[【コピペOK】CSSだけで実装できるおしゃれテーブルデザイン10つ](https://webliker.info/75964/)

![ユーザー一覧の試作２](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534558/db3aa533-8bc7-3dad-f214-a235d873bb3f.png)
↑こんなふうになった。（テーブルサイズは画面幅の7割）




今回はここまで。
[次回の記事>>](https://qiita.com/tomodachi_uec/items/9ed563516f4d0435c385)
[Chapter-10]https化によるNginxの設定

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
今回はNginxの設定をしていきます。
※これでhttps化完了です
画像なしで説明しますのであしからず。
少しだけrailsのファイルの設定もしていきます。

## Nginxとは
HTTPおよび、HTTPSでのアクセスに使われる軽量サーバーのことでWebサーバーとしての基本的な機能を持っています。

https://ryusou.dev/posts/at191OlUj

## Nginxの設定
以下のファイルを編集します
`/etc/nginx/nginx.conf`
httpでアクセスされたものをhttpsへリダイレクトする記述へ変更します。

```:EC2サーバー環境
$ sudo vim /etc/nginx/nginx.conf
server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  www.hogehoge.com; #ドメイン名に変更
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
}

```
ドメイン名を記述したら:wqで保存します。

次にRailsアプリに移動します。
そして`/config/environments/production.rb`ファイルを編集します

```:EC2サーバー環境
$ sudo vim /config/environments/production.rb
```

```:/config/environments/production.rb
config.force_ssl = true
```
これをすることで常時SSL化対応となります。

## NginxとUnicornの再起動
Nginxの再起動

```:EC2サーバー環境
$ sudo service nginx restart
```

次にUnicornを再起動させます。
まずUnicornの起動を確認

```:EC2サーバー環境
$ ps -ef | grep unicorn | grep -v grep

ryogo    11658     1  0  4月24 ?      00:00:02 unicorn_rails master -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
ryogo    11662 11658  0  4月24 ?      00:00:02 unicorn_rails worker[0] -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
ryogo    11663 11658  0  4月24 ?      00:00:02 unicorn_rails worker[1] -c /var/www/rails/travelour/config/unicorn.conf.rb -D -E production
```

表示されたUnicornの番号をkillします。
1行目の11658のみkillすれば良いです

```:EC2サーバー環境
$ kill 11658
```
Unicornを再度起動させます。

```:EC2サーバー環境
$ bundle exec unicorn_rails -c /var/www/rails/アプリ名/config/unicorn.conf.rb -D -E production
```
これでhttpsでドメインにアクセスできるようになります。

```:EC2サーバー環境
https://www.hogehoge.com
```

## 参考
https://qiita.com/Yuki_Nagaoka/items/55ed1610cfc1f59398b1
ORM

### O/Rマッピングとは
　O/Rマッピングは、「オブジェクト」と「リレーショナルデータベース」をマッピングすることを意味します。
　O/Rとは、「Object/Relational」の略で、オブジェクトとリレーショナルデータベースのデータの間をマッピングする技術です。データベースのテーブルにあるデータをプログラミング言語のオブジェクトに変換したり、逆にプログラミング言語のオブジェクトをデータベースのテーブルデータに変換したりする機能を提供します。
　また、従来のJDBCを利用した開発ではデータベースにアクセスする際、SQL文などを直接ソースコードに埋め込むことがほとんどです。そのため、テーブル構造の変更が発生した場合埋め込んだソースコードを修正しなければならないのでSQL文がソースコードの様々な場所に記述されていると、修正漏れや修正間違いといった問題を常に意識しながら開発しなければなりません。
　そして、これらの問題を解決するために考えられたのがO/Rマッピングです。

### O/Rマッピングの基本的な流れ
  O/Rマッピングの機能は個々のソフトウェアによって異なりますが、基本的には以下のような機能を提供します。
1.コネクション管理機能
　データベースとの接続やコネクションプーリングが管理できるようになる。
2.自動マッピング機能
 XMLファイルなどの外部ファイルにオブジェクトの属性名とテーブルの列名に関するマッピング定義を設定することによって自動的にマッピング処理を行ってくれます。
3.マッピングファイル、DTO、DAOの自動生成機能
　O/Rマッピングツールの提供する自動生成ツールによってマッピングファイル、DTO、DAOといったファイルを自動で作成してくれます。
4.接続情報の管理機能
　JDBCドライバやデータベースの接続情報を、O/Rマッピングツール側で管理してくれます。
5.キャッシュ機能
　一度取得した検索結果をメモリ上に保持しておいて、同じ検索処理が行われた場合は、メモリ上にある検索結果を返します。これによって、データベースへのアクセスを減らし、パフォーマンスがあがります

　一般的な「O/Rマッピング」は以下のような流れで処理を行います。
1.データベースの接続情報をXMLファイルに定義（データベース設定ファイル）
2.クラスのフィールドとテーブルカラムの対応付けをXMLファイルに定義（マッピングファイル）
3.O/Rマッピングフレームワークがデータベース設定ファイルとマッピングファイルを読み込んで自動的にマッピング処理を行う
4.O/Rマッピングフレームワークがクラスのフィールドとテーブルカラムのマッピングを処理する
5.アプリケーションからO/Rマッピングフレームワークの提供するAPIを用いてデータベースへアクセスし、検索、登録、削除、更新処理を行います。


![ORM.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310302/ba3a7a9e-5c51-fac8-8a0e-24539d23495e.jpeg)
Qiitaでのマークダウン記法を解説します

Qiitaで記事を書くときにはマークダウン記法を使います。
※CSSは使えません

##マークダウン記法とは
マークダウン記法とは、マークアップ言語（HTMLなど）を簡略化したものであり、記述も少なくシンプルなので、誰でも簡単に使うことができるのです。
## Qiitaで活用するマークダウン記法の書き方
### 見出しの書き方
シャープと半角スペースで見出しを記述します。
h1〜h6のような見出しの重要度は、シャープの数で対応しています。

```
# h1見出し
## h2見出し
### h3見出し 
        (...続く)
```

__`実例`__
># h1見出し
>## h2見出し
>### h3見出し

## 文字の装飾
### 背景灰色・黒文字
```
`aaa`
```
「`aaa`」
### 文字の強調(Strong)
__ か ** で囲むとHTMLのstrongタグになります。

```
_aaa_
**<font color="red">bbb</font>**
```
_aaa_
**<font color="red">bbb</font>**


## 水平線の書き方

アンダースコア、アスタリスク、ハイフンなどを3つ以上連続して記述することで水平線を表示します。
※連続するハイフンなどの間にはスペースがあっても良い

```
___
***
---
```

「`実例`」

___
***
---

## テーブルの書き方

```
|a  |b  |c  |
|---|---|---|
|1  |2  |3  |
|4  |5  |6  |
```

「`実例`」

|a  |b  |c  |
|---|---|---|
|1  |2  |3  |
|4  |5  |6  |

## Qiitaで初めて記述時の注意点
* CSSは使えない
* タグでの記述可能(style属性は使えない）
* 改行が必要なタグがある


___
この記事は、随時更新していきます
[Chapter-9]https化によるRoute53の設定

| タイトル |
|:-|
|  [[Chapter-1]VPCの設定](https://qiita.com/Jackson123/items/c7b0a7a6ae659fe48a3b) |
|  [[Chapter-2]EC2の設定](https://qiita.com/Jackson123/items/53cc698b1b7cfdbfe368) |
| [[Chapter-3]EC2のサーバー環境構築](https://qiita.com/Jackson123/items/821d89184d87b6020df5)  |
|  [[Chapter-4]EC2にRailsアプリの配置](https://qiita.com/Jackson123/items/e91eec2f76774717bdee) |
|  [[Chapter-5]ロードバランサー(ELB)の作成](https://qiita.com/Jackson123/items/a739525d0084747405d7) |
| [[Chapter-6]ACM(AWS Certificate Manager)でSSL証明書を取得](https://qiita.com/Jackson123/items/eb586c33fe3c5b7d9dad)  |
|  [[Chapter-7]Route53の設定](https://qiita.com/Jackson123/items/6b41ebde0eec072a283e) |
|  [[Chapter-8]https化に向けたロードバランサーの設定](https://qiita.com/Jackson123/items/d6819d3dbf304aebd459) |
|  [[Chapter-9]https化によるRoute53の設定](https://qiita.com/Jackson123/items/9ceae188a53f646e55e9) |
|  [[Chapter-10]https化によるNginxの設定](https://qiita.com/Jackson123/items/255263a260f7a833bf1d) |
## はじめに
今回はhttps化によるRoute53の設定をしていきたいと思います。
画像なしで説明しますのであしからず。
また今回はアプリを既にEC2に上げている(HTTPで)、ACM（AWS Certificate Manager）でSSL証明書を取得している、ロードバランサーでHTTPSのアクセス許可をしている前提とします。
まだ設定されていないという方は以前のチャプターをご覧ください。

## Route53で作成したホストゾーンのレコードからタイプAの編集
※ちなみにレコードタイプAとは「Address」頭文字。ドメインに対するIPv4アドレスを登録している。

サービス検索欄から「Route53」と入力し検索します。
「ホストゾーン」を選択して作成済みの「ドメイン名」を選択します。

その中の「タイプA」の「www.ドメイン名」のレコードにチェックを入れて「レコードを編集」をクリックします。

以下のように項目を修正します
名前：「www.ドメイン名」
レコードタイプ：「A-IPv4アドレス」
**エイリアス** ：　バーをクリックして有効にする
**トラフィックのルーティング先** ：「Application Load Balancer と Classic Load Balancerへのエイリアス」→「アジアパシフィック(東京)[ap-northeast-1]」→「アプリ名-ELBを選択」

「保存」を選択
## 参考
https://qiita.com/yuta-38/items/7ac74a4be398a0483f36
【Mac】Jupyter Notebookをディレクトリ指定で開くアプリのための４行

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 　Jupyter Notebookを一発で開きたい。すぐ使いたい。

##やること
Jupyter Notebookを開く時、一度ターミナルを開く必要があります。
またディレクトリを指定して開くこともできますが、その場合はディレクトリも入力する必要があります。
これをクリック一発で行えるアプリをデスクトップに作成します。

## 環境

- Mac
- automator

## オートメーターを使って作ります
![ssg5 242.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/ed11390a-f80b-47ef-db5c-d41aecf73e2f.png)
① 検索ウィンドウに「automator」と入力し、automatorを開く。
② メニューの「新規」から「アプリケーション」を選択。
③ 検索窓に「a」と打ち込んで「アップルスクリプトをを実行」を選択。
④ スクリプトを下記のように上書きする。

```applescript:applescript
on run {input, parameters}	
	tell application "Terminal"
		delay 0.1
		do script "jupyter notebook /<デフォルトで開きたいパス名>"
	end tell
end run
```

⑤ 最後に名前をつけてデスクトップ等に保存する。

## 実行
アプリアイコンを押して実行します。
初回起動時のみ、ダイアログボックスが出ますが、２回目以降は１発で起動できるようになります。
コンフィグでパスを設定するとディレクトリ移動に制限が出るらしいので、その点でこの方法が便利かもしれません。


## 参考
こちらの記事を参考にしました。

- [MacでワンクリックでJupyter Notebookを起動させる方法]
(https://qiita.com/rebellious-wimp/items/f227424c518691c5ae26)
- [Automatorで簡単にコマンド実行アプリを作る]
(https://book.mynavi.jp/macfan/detail_summary/id=42064)
openfoamの演習問題出展はどこから？

Onion Salad - OpenFOAMチュートリアルドキュメント作成プロジェクト（https://sites.google.com/site/freshtamanegi/home）のtutorialを調べており
なかなかズバリのファイルがなく、一番近いファイルがOpenFOAM extensions（https://sourceforge.net/projects/openfoam-extend/files/foam-extend-3.1/）
のファイルが一番近かった。(tutlialだけ抽出。![Something went wrong]()　）

fileは、読めるかわかりません。^^;

本日は、ここまで。m(__)M
google map javascriptをtailwindcssで表示する

##google map apiの導入法

①google cloud platformに登録

②api keyを取得してscriptタグに埋め込む

③tailwind cssでサイズを指定する

##widthとheightを指定する

````~blade.php
<div class="w-full h-full" id="map">

</div>
````

これでは表示されません。

##対策
````~blade.php
<div class="w-full h-screen" id="map">

</div>
````
これで無事divタグの中に表示されるようになりました。

※api keyを埋め込んだままgitにpushするとアプリによっては情報漏洩で
 悪用されるリスクがあるので注意です。
Java専が初めてSwift UIで作ったアプリと感想

#筆者のスペック

- 業務内容は主にJavaでバックエンド
- フロントエンド自体、あまり経験なし
- 他にもC++, Node.jsを少し触った
- 趣味は麻雀とかポーカー

---

#やったこと
SwiftUIを使ってポーカー支援アプリを作る

##想定状況 (結構ニッチ)
残りチップが少ない時、少しずつベットするのではなくオールイン戦略が有効となる
このような場面での正しい判断を提供するアプリ

##公開について
App storeへの公開に必要なライセンス料や審査がネックなので、手元の実機でのみ楽しんでいます

--- 
#アプリ内容
1.自分のポジションを選ぶ
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/cfab65df-c967-d352-cd8e-7fc7cbe474a2.png" border="10">

2.自分のスタック/アンティを入力
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/e2c4c5ee-dae2-89f0-e926-c173098619c9.png">

3.すると、オールイン or フォールドを教えてくれる
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/5e06929d-1918-5da6-cf1f-1e1e1880567a.png">

---
#ロジック
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/7af7d493-731c-bb07-8203-b86c636b13cf.png">

パワーナンバー表といい、今回のアプリで行なっている計算はここから算出している
> 有効M値<パワーナンバー表であればオールイン
有効M値>パワーナンバー表であればフォールド
(M値=スタック/ポット額 
 ポット額=SB+BB+全員のアンティ)
参考：https://note.com/croizz/n/n2a87e73f3482

---
#感想
- MVCとMVVMモデルの違い
- XcodeのPreview機能の便利さ
- SwiftUIのデフォルトモジュールの有能さ

---
##MVCとMVVMモデルの違い
当初MVCモデルをイメージして実装を行っていたが、
各種サンプルコードがMVVMで実装されていたためハマった

###MVC
<img width="400" alt="MVCモデル" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F15902%2F545594a8-9bd1-b137-6ac0-c67519fda69f.jpeg?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=61ab2742168ca3318e2d0b9fa7c858eb">

###MVVM
<img width="400" alt="MVCモデル" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F15902%2Fb3caa541-155f-4abd-746c-9f035217df48.jpeg?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=744e51abd8ed4a0758a2a5fb372f8689">

####参考
https://qiita.com/shinkuFencer/items/f2651073fb71416b6cd7

---

##XcodeのPreview機能の便利さ
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/d8f92868-a873-d5fd-0fb0-23f1755e9c83.png">

- 作成したソースをリアルタイムでPreview側で動かすことができる
- Preview側を修正することができ、リアルタイムでソースに反映される

⇨いちいちデプロイして、修正を確認する必要がなく、効率◎

---

##SwiftUIのデフォルトモジュールの有能さ
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260518/78284f1a-ecc6-31ae-1573-0d0d9e3e9e1e.png">

- 機能的でシンプルでおしゃれ
- Apple製品のあらゆるデバイスに対応
- Xcodeから文字通りモジュールとして挿入することができる

---

#まとめ
・モデルや文法など、Javaとは結構勝手が違う
　（Swiftの関数定義は慣れないが、デフォルトでnilを許容しない機構は非常に良い）
・提供元が一元化されていることにより、各開発フェーズでの連携が非常にスムーズ
　（eclipseみたいに色んなプラグインやソフトに惑わされることがない）
・App storeへの登録料（＄99）を値下げしてください。。。
【Giit】まだMergeしてないのに、Already up to date.の対処法

<h2>症状</h2>
ブランチで変更したファイルを切り出したブランチからマスターブランチにマージしようとしたら、エラーが表示されて、マージできませんでした。

```terminal:ターミナル
git merge 
Already up to date.
```

翻訳すると、「すでに最新です。」
merge先がすでに最新であるという意味だと推察します。

<h2>解決方法</h2>
masterブランチに移動後に、mergeし直したら解決しました。
merge文の使い方の理解が浅かったようです。

git mergeを使用する際は、masterブランチに移動しないといけないようです。

```
#ヴランチをマスターに変更
git checkout master

#firstbranchを指定して、マスターにマージする
git merge firstbranch
```
consoleで見るとプロパティが明らかに存在するのにundefinedが返される場合[chrome]

###なんで明らかに存在するって断言できるの？

```javascript:sample.js
    console.log(userData.fav);  //{word:[...]}
    console.log(userData.fav.word); //undefined

```
あれ...存在しているはずじゃん？？

###原因
Chromeのconsoleはどうやらconsoleの▶を開いて詳細を確認しようとした時点での状態を表示するようです。つまり実際にはuserData.favは{}であるのにも関わらず、その0.00001s後にwordプロパティが追加された場合consoleを確認するときにはすでにプロパティが存在しています。
つまり
console.log(userData.fav);を「実行した」とき、プロパティは存在しない。
↓
console.log(userData.fav.word);を「実行した」とき、プロパティは存在しないのでundefinedを返す
↓
開発者がconsoleを開いてconsole.log(userData.fav);の表示結果を「確認する」とき、すでにプロパティwordが追加されたのでconsoleに表示される。

なのでPCがプロパティを追加するのよりも先にconsole画面で表示させれば{}と表示されるはずです。
ちなみに▶をクリックして展開する必要のないundefinedのような文字列は一度表示されたら変更されることはありませんが▶{__ ob __: Observer}のように展開する必要があるものは中身を確認した時点の状態を返すようです。
Adobe Target RecommendationsのDesign記法について(応用編)

こちらは以下の記事の続き(応用編)になります。

https://qiita.com/manji6/items/d0c4c1fbea98ef83f85f

Adobe Target Recommendationsの基本的な使い方を知りたい方は是非上で確認してください。
応用編ではこんな書き方出来ますよーというややマニアックな使い方についてご紹介します。
(一部基本編で使っていた機能になりますが…解説編ということで。)

## 事前に定義されている変数について
Adobe Target側から事前に以下の変数が定義されているので、必要に応じて利用可能です。

| 変数内容 | 変数値 | 詳細 |
| ---- | --- | --- |
| Criteria 名称 | $algorithm.name | Criteria設定画面の "Criteria Name" 値 |
| Criteria Display Title | $criteria.title | Criteria設定画面の "Display Title" 値 |
| Criteria 集計期間 | $algorithm.dayCount | Criteria設定画面の Data Rangeを日数に変換した値 |
| レコメンド結果商品配列 | $entities | レコメンド結果の商品情報配列 |
| Profile値 | $user.プロファイル名 | Profile機能で設定したカスタムプロファイル値 |

## Template内で変数を利用したい
これは基本編でも使っていたのですが…使いまわししたいような値や変更することが考えられる値などは変数化すると便利です。

記述方法

```
#set($変数名 = "値")
```

例

```
#set($countLoop = 5)
#set($priceSuffix = " 円")
```

## $entity.valueのドット表記部分を削りたい
普通に$entity.valueのデータを出力すると 500.00 というような表現になってしまいます。
日本円ではこの記述方法だと使いにくいので…この".00"部分を取り除く方法は以下のようにします。

記述方法(仮に1商品目の価格データを出す場合)

```
$entity1.value.split(".00").get(0)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/6ca29dda-6e57-77d4-62c2-327ecff23100.png)
上が普通に表示した場合、下が上の記述方法で出力した場合です。

## 正規表現を使って値の判定をしたい
ちょっと特殊な書き方にはなりますが、正規表現を使って値の判定をすることが可能です。

記述方法
(仮に$entity1.itemTitle という値に対して正規表現を使いたい場合)

```
#if($entity1.itemTitle.matches("正規表現文字列"))
  ## マッチした時の処理
#end
```


例([テスト]という文字列があるかどうかを判定)

```
#if($entity1.itemTitle.matches("^\[テスト\].*$"))
  <h2>テスト商品です</h2>
#end
```

これらのテクニック及びループ処理やIF文の判定を使うことで、ある程度のデザインカスタマイズがVelocity記法で記述した場合に可能になります。
今回説明した内容含めて以下のヘルプでも様々な例が記載されています。是非こちらも合わせてご確認下さい。

[Velocity を使用したデザインのカスタマイズ \| Adobe Target](https://experienceleague.adobe.com/docs/target/using/recommendations/recommendations-design/customizing-a-template.html?lang=ja#section_C431ACA940BC4210954C7AEFF6D03EA5)


是非Adobe Targetのレコメンデーション機能を使ってお手軽にレコメンド環境を導入してみてください！
Jenkinsのmaster slave構成をDockerで構築する

## はじめに

この記事は[Docker/Kubernetes実践コンテナ開発入門](https://www.amazon.co.jp/Docker-Kubernetes-%E5%AE%9F%E8%B7%B5%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80-%E5%B1%B1%E7%94%B0-%E6%98%8E%E6%86%B2-ebook/dp/B07GP1Q3VT/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=Docker%2FKubernetes%E5%AE%9F%E8%B7%B5%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80&qid=1619364316&sr=8-1)にて、
書籍通りに進めて詰まってしまった箇所の解決策を自分用にメモしています。

## 前提条件

一度Jenkinsのmasterノードをdockerで作成し、ssh公開鍵の作成は完了している。

## 用意するdocker-compose.yml

```yml
version: "3"
services:
  master:
    container_name: master
    image: jenkins/jenkins:latest
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
    links:
      - slave
  slave:
    container_name: slave
    image: jenkins/ssh-slave:latest
    environment:
    - JENKINS_SLAVE_SSH_PUBKEY=ssh-rsa AAAAB.......
```

※[Jenkinsのサイト](https://www.jenkins.io/blog/2018/12/10/the-official-Docker-image/)によると、 jenkinsciは開発が止まっているようです。。

## 実行

```sh
$docker-compose up -d #上記docker-compose.ymlを実行
Docker Compose is now in the Docker CLI, try `docker compose up`

Starting slave01 ... done
Starting master  ... done
```

無事実行できました！
ちなみに、jenkinsciのイメージでコンテナを作成すると、Jenkinsのpluginインストールでこけます。

## masterノードへslaveノードを登録する

ここも一山ありました。。
書籍通りに進めると、slaveノードに通信ができません。（java.IOExceptionが出ます）

解決策は、以下サイトに非常に丁寧に記載してくださっています。
[jenkinsのmaster/slave間のSSH接続でjavaがないと言われた時の対処法(docker)](https://qiita.com/michi-michi/items/b1835d6e89856643b65a)
VBA フォルダの更新日時を取得 その2

```
Sub test1()
    Dim fso As FileSystemObject
    Set fso = New FileSystemObject
    
'    フォルダ
    Dim fl1 As Folder
    Set fl1 = fso.GetFolder("C:\Windows")
    Dim d1 As Date
    d1 = fl1.DateLastModified
    With ActiveSheet
        .Range("A1") = fl1.Name
        .Range("B1") = d1
        .Range("C1") = Hour(d1) & ":" & Minute(d1)
    End With
    
'    ファイル
    Dim fl2 As File
    Set fl2 = fso.GetFile("C:\Users\user\Documents\222.txt")
    Dim d2 As Date
    d2 = fl2.DateLastModified
    With ActiveSheet
        .Range("A2") = fl2.Name
        .Range("B2") = d2
        .Range("C2") = Hour(d2) & ":" & Minute(d2)
    End With
    
    Set fso = Nothing
End Sub
Windows+Apache+perlで #!/usr/bin/perl なCGIを動かす

これまで、WindowsではActivePerlを使っていました。
でも今は Strawberry Perl のほうがいいみたいなので乗り換えました。

Perlのスクリプトのshebang行は通常
`#!/usr/bin/perl`
にしてますよね。Apacheはこれを読んで /usr/bin/perl を起動しようとするので、Windowsでもこのパスで perl.exe が起動するようにしないとCGIが動きません。

ActivePerlを使っていたときは、ActivePerlの bin フォルダにpathを通したうえで、ActivePerlの perl.exe を C:\usr\bin フォルダにコピーすればOKでした（コピーではなくシンボリックリンクでも良かったかも）。

しかし、Strawberry Perl ではそれではダメでした。C:\usr\bin に perl.exe をシンボリックリンクしてbash等から `/usr/bin/perl script.pl` を実行するとエラーなく動くのに、なぜかApacheでは 500 Internal Server Error になります。

で、いろいろ試行錯誤してたどり着いたのが、Apacheの`ScriptInterpreterSource`ディレクティブを使うことでした。これはCGIファイルのshebang行（スクリプト先頭の`#!`で始まる行）を無視して拡張子のみ（.pl や .cgi）でスクリプトファイルを関連付け実行できるというものです。httpd.conf で対象ディレクトリに `ScriptInterpreterSource registry` を記述してみたら、無事、Apacheで`#!/usr/bin/perl`なCGIが動くようになりました。

めでたしめでたし

…が、以下の謎があります。

- レジストリの設定も関連付けもしなくても動いちゃう。え？なんで？
- C:\usr\bin\perl はやっぱり無いとダメ。なんで？

ま、動いてるから、いっか…
REST API設計について学ぶ①

要件定義、設計のフェーズでAPIの設計がとても大事であると痛感しています。
きちんと学びたいと思い勉強中です。

間違い等あればご指摘いただけましたら幸いです。

## REST APIとは

私がプログラミングを学んでいて最初に認識したAPIというのは、例えばTwitterやAmazonなどそのサービスを外部から使うというようなものでした。
自身の作ったアプリにGoogleの検索バーを入れるとかそういうものだと思っていました。

で、実際に就職して初めて先輩と一緒にやった仕事がAPI連携設計で「ん？APIって私が思っているものと違うのかな」と混乱しました。

認識を確認するために読んだ記事が以下です。

[Web APIとは何なのか](https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02)
[リソース指向アーキテクチャ(ROA)とは何なのか](https://qiita.com/NagaokaKenichi/items/0f3a55e422d5cc9f1b9c)

>厳格な定義はないが、広義にはHTTPプロトコルを用いてネットワーク越しに呼び出すアプリケーション間、システム間のインターフェースのこと。

とあります。なるほど。
つまり「呼び出す側」と「呼ばれた側」がいてそこを繋ぐインターフェースはWebAPIというんだと分かりました。
APIのIはインターフェースですからね。接続とかやりとりするポイントっていう意味で考えれば納得できます。

なのでREST API設計では、HTTPメソッドはどれか、URIはどうするか、必要なパラメータは何か、どんなレスポンスが返ってくるかを考えることなのだと認識しました。


## 設計方法

参考：[WebAPIの設計](https://www.shoeisha.co.jp/book/detail/9784798167015)

めちゃくちゃ簡単なCRUDの例で考えます。
ショッピングサイトで考えてみましょう。

上記の書籍では
①各リソースの関係を考える
②アクション、パラメータ、レスポンスを考える
③リソースのパス(URI)を考える
④HTTPプロトコルで表す
というステップを紹介していました。

#### ①各リソースの関係を考える

`誰が、何を、どのように`する機能なのかを洗い出し、その機能のゴール=REST APIに置き換えるといいとのことでしたので、そうすると、下記のように考えればいいのでしょうか。

| 誰が    | 何を | どのように          |
|:------:|:----:|:----------------:|
| ユーザー | 商品 | 商品の一覧を取得する |
| ユーザー | 商品 | 商品の詳細を取得する |
| ユーザー | 商品 | 商品を追加、登録する |
| ユーザー | 商品 | 商品を編集、更新する |
| ユーザー | 商品 | 商品を削除する      |

この`どのように`の部分がAPIのゴールと考えます。
これを実現するにはどのようにしたらいいかを考えていきます。


#### ②アクション、パラメータ、レスポンスを考える

アクションも`どのように`で考えた部分ですね。
`取得`、`更新`、`追加`、`削除`の3つが出てきました。

パラメータは何を渡したら期待通りの出力がされるかを考えればいいのかなと思っています。
例えば、商品の詳細を取得したければその商品のIDが必要とか。
こちらは以前記事にまとめています。
[リクエストパラメータについて](https://qiita.com/mumucochimu/items/f005f46413a100d3dc75)

レスポンスは、何が返ってくれば`どのように`の要件が満たされるのかを考えればいいのかなと思っています。
例えば、商品の一覧を表示するゴールであればそのデータですね。

#### ③リソースのパス(URI)を考える

こちらはエンドポイントを考えることとほぼイコールであると考えています。
これはいろんな考え方があるので正解！っていうのはないみたいですが、一般的にこうするべきというのは様々な記事で紹介されていました。
私が参考にしたのは以下の記事です。
[RESTful APIのURI設計(エンドポイント設計)](https://qiita.com/NagaokaKenichi/items/6298eb8960570c7ad2e9)

ということで、今回の例でいうと

商品の一覧取得と商品の登録は`/products`としてみます。
商品の詳細取得と編集と削除はその商品を特定するべきなので`/products/{productID}`とします。


#### HTTPプロトコルで表す

こちらはつまり`GET`、`POST`、`PUT`、`PATCH`、`DELETE`のHTTPメソッドで表すということです。

一覧取得と詳細取得は取得なので`GET`ですね。
商品の登録は情報を送るので`POST`ですね。
削除は`DELETE`。
更新は場合によるのですが今回は`PATCH`にしておきます。

#### まとめ

ということで今回考えた設計でいうと以下のようになります。
レスポンスやパラメータは場合によって変わると思うのですが分かりやすく？しています。

| ゴール(機能の要件)  | パラメータ             | レスポンス    | URI                   |
|:----------------:|:-------------------:|:-----------:|:---------------------:|
| 商品の一覧を取得する |                     | 商品の一覧    | /products             |
| 商品の詳細を取得する | 商品のID             | 商品の詳細情報 | /products/{productID} |
| 商品を追加、登録する | 商品の登録情報         | 登録した情報   | /products             |
| 商品を編集、更新する | 商品の編集情報、商品のID | 更新した情報   | /products/{productID} |
| 商品を削除する      | 商品のID             |             | /products/{productID} |

このようにたくさんのAPIが繋がりあってサービスってできていくんですね。
確かにこれを間違えると開発大変そうです。

今回はここまでにします。
create-next-appでテンプレートのダウンロードが止まる場合の対応策

## 問題
create-next-appで以下のコマンドを実行した時、環境によってはコマンドの実行が進まず、プロジェクトが生成されないことがあった。
おそらく原因はProxy設定によってテンプレートのダウンロードが阻まれているため。

```sh
npx create-next-app --example with-typescript nextexp
```

これに対応する。

## 解決策

create-next-appのテンプレートは`--example`に入力するのと全く同じ名前でnext.jsのgithubのmasterブランチのexamplesに入っているので、それをダウンロードしてくればよい。

今回のコマンドで言えば具体的にはここ。

[vercel/next.js/tree/master/examples/with-typescript](https://github.com/vercel/next.js/tree/master/examples/with-typescript)

コマンドの実行が進まない原因自体はProxy設定によってテンプレートのダウンロードが阻まれているからだと考えられるが、最初に一回ダウンロードするだけのものなのでこれでよしとした。

以上
const、let等の変数宣言

#JavaScriptの変数について

##そもそも変数とは
変数とは<strong>値</strong>に<strong>名前</strong>をつける。
例えば、犬を飼っているとして、柴犬にポチと名前をつけるのと一緒です。
好きな名前をつけれるし、呼びやすいし愛着湧くでしょう。

##型の種類、`var let const`について

###var
- varは上書き可能
- varは再宣言可能

```javascript
var hoge01 = "hoge01変数";
console.log(hoge01);
}
```
consoleではこのように表示されます。
`hoge01変数`

```javascript
var hoge01 = "hoge01変数";

hoge01 = "hoge01変数を上書き";
console.log(hoge01);
}
```
consoleでは上書きされてこのように表示されます。
`hoge01変数上書き`

このように`var`で宣言すると、プロジェクトが大きくなると意図しないところで変数を上書きしてしまい
不具合の原因になります。


###let
- letは上書き可能
- letは再宣言不可能

```javascript
let hoge02 = "hoge02変数";

hoge02 = "hoge02変数を上書き";
console.log(hoge02);
```
こちらも`var`同様に上書きされコンソールにはこのように表示されます。
`hoge02変数を上書き`

```javascript
let hoge02 = "hoge02変数を再宣言";
```
let変数を再宣言しようとすると、コンソールにこのようなエラーが出ます
`Uncaught SyntaxError: Identifier 'hoge02' has already been declared`
もうすでにhoge02は宣言されているとエラーが出ます。
letだと再宣言されるとエラーが出るのでバグを未然に防げます

###const
- constは上書き不可
- constは再宣言不可

```javascript
const hoge03 = "hoge03変数";

hoge03 = "hoge変数を上書き";
console.log(hoge03);
```
const変数を上書きしようとするとコンソールにエラーが出ます。
`Uncaught TypeError: Assignment to constant variable.`

```javascript
const hoge03 = "hoge03変数";

const hoge03 = "hoge03を再宣言";
console.log(hoge03);
```
const変数を再宣言しようとするとlet同様にコンソールにエラーが出ます
`Uncaught SyntaxError: Identifier 'hoge03' has already been declared`

##変数宣言について
`型` `変数名` = `値`

##まとめ
varは再宣言、上書きなんでもできる。
便利だがプロジェクトが大きくなると不具合の原因になる可能性がある。
letは再宣言はできないが上書きが可能、なのでfor分の変数とかによく使われる。
constは上書き、再宣言共に不可能だが、constで定義した、配列、オブジェクトのプロパティは変更可能
なのでほとんどの宣言がconstでいいのかな。

最後まで読んでいただきありがとうございました。
【Unity】アスペクト比維持してUIのimageをCanvasにフィットさせる

# 「Canvasにフィットさせる」とは？
<img width="700" src="https://1.bp.blogspot.com/-AMMDgWfM8Vw/YIUgY7G9amI/AAAAAAAAARo/O4yEg6Dl0nwoTuNywin7W6NBaG1zMKYxACNcBGAsYHQ/w674-h403/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B%252830%2529.png">

imageのUIを、元の画像のアスペクト比そのまま、はみ出ないようにピッタリに、というイメージ。
Rect Transformを弄ってもできることはできるのだが、それだとimageがCanvasめいっぱい覆う感じになってしまうので、もう少し端に寄ってもらう方法とかないかな、と考えた次第。

# 1.環境について
Unityバージョン：2019.4.18f1
Visual Studio Community 2019バージョン：16.9.1

# 2.スクリプトですべて解決
色々とインスペクター弄るの面倒なので、アタッチして実行したら即完成するスクリプトを作った。

```c#:ImageSizeManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ImageSizeManager : MonoBehaviour
{
    private float scaleRate;
    // Start is called before the first frame update
    void Start()
    {
        this.GetComponent().preserveAspect = true;
        this.GetComponent().SetNativeSize();
        Vector2 CanvasSize = transform.root.GetComponent().sizeDelta;
        Vector2 ThisImageSize = this.GetComponent().sizeDelta;
        if(CanvasSize.x<CanvasSize.y)
        {
            scaleRate = CanvasSize.x / ThisImageSize.x;
        }
        else
        {
            scaleRate = CanvasSize.y / ThisImageSize.y;
        }
        this.GetComponent<RectTransform>().localScale = new Vector3(scaleRate, scaleRate, 1);
    }
}
```

# 3.応用編：Canvasピッタリ、から少し余裕を作りたい場合
<img width="表示幅" alt="ファイル名" src="https://1.bp.blogspot.com/-LEjKVeOmsIo/YIV6p92ZFZI/AAAAAAAAASI/YDUawRvZVR8ElDitwto5pRqtLNrh6D3owCNcBGAsYHQ/w674-h432/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B%252834%2529.png">

上の画像は、Canvasの上下左右に10ずつ離したPanelです。まぁキッチリカッチリではなく少し離す、というのは想定される事例です。

これに対応させる場合、若干スクリプトを弄らなければなりません。とはいえ、そこまで苦でもないのですが。

一つ前の項目で少し書いた通り、このスクリプトはCanvasの縦横サイズを参照するのが基本となってます。

よって、Canvasの縦横サイズから少しずらすのならば、ずらした分だけ調整すればいいだけです。具体的にはこんな感じ。

```c#:ImageSizeManager.cs
Vector2 CanvasSize = transform.root.GetComponent().sizeDelta+new Vector2(-20,-20);
```

スクリプトの12行目のココ。

これがCanvasを参照している部分なので、ここからずれる分を引き算なり足し算すれば大丈夫です。

画像の例だと、私は上下左右に10ずつ余白を作ったので、縦と横、一片の長さをもとのCanvasと比較すると、（ローカル座標で）20短くなっていることがわかります。

それを引き算してスクリプトを保存、完成形はこちら。

<img width="700" src="https://1.bp.blogspot.com/-RWqrNtdPxxQ/YIV_Uqz0KpI/AAAAAAAAASQ/Igx4D-1QqiAkSa3j-7tZoU1oxAYPm05HQCNcBGAsYHQ/w675-h430/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%2B%252838%2529.png">

以上です。
Ubuntu環境に間違えてfirewalldを入れないようにしよう。

##やらかし
やらかしました。
Ubuntuにはデフォルトでufwというファイヤウォール管理コマンドが用意されているのですが、
いままでCentOSを使っていた私はapt-getでfirewalldを入れてしまったのです。
##結果
その結果ufwとfirewalldが競合し全てのポートが閉じられてしまいました。
##対処
間違えて入れてしまったfirewalldをapt-get removeで削除しリブートした。
SQLの基本用語と主な命令文

###基本用語
表　テーブル
表の縦の列　カラム
横の行　レコード
データベースに送る命令　クエリ

###主な命令文
```sql
CREATE TABLE テーブル名(
  カラム名 データ型
  カラム名 データ型
  ...
);
```
テーブルを作成する
カラム名とそのカラムの値のデータ型を設定

```sql
INSERT INTO テーブル名 (カラム名, カラム名) VALUES 
  (カラムの値, カラムの値)
  (カラムの値, カラムの値)
  ...
```
テーブルにカラムの値を挿入する

```sql
SELECT 
  カラム名, カラム名 
FROM 
  テーブル名 
WHERE  
  カラムの値を条件をつける;
```
カラムの値を条件にして条件にあったカラムの値を抽出する

```sql
DELETE FROM テーブル名 WHERE カラムの値を基にした条件;
```
条件にあったカラムの値を削除

```sql
UPDATE テーブル名 SET　カラム名 = 更新したい値 WHERE レコードの位置;
```
レコードの位置に合わせてカラムの値を更新

```sql
ALTER TABLE テーブル名 ADD 追加したいカラム名 データ型;
```

CREATEの外でもカラムの追加ができる
   
まだ詳しいことがあるので頑張って理解したい。
【Vue.js】transition ラッパーは単一要素/コンポーネントで使うと言う話とか

Vue.js の`transition`について。
単一要素は`transition`で複数要素は`transition-group`と言う単純な覚え方ではアカンと思ったので、覚書。

## 前置き
`transition`は Vue.js で、
遷移とか移り変わりの表現をいい感じにしてくれるラッパーコンポーネントである。
要素のフェードイン / フェードアウトを簡単に実装する事が出来るので、そう言う例が多く見られるが、

https://jp.vuejs.org/v2/guide/transitions.html#%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B8%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%AF%E3%83%A9%E3%82%B9

要するにvueが用意してくれているトランジションクラス（v-enterとかv-leaveとか）を用いて、要素がDOMに追加、更新、削除される意図したタイミングでアニメーションを指定する事が出来る。

## 本題
`transition`でラップ出来るのは次のようなケース
・条件付きの描画 (v-if を使用)
・条件付きの表示 (v-show を利用)
・動的コンポーネント
・コンポーネントルートノード (Component root nodes)

で、これらは`単一要素/コンポーネント`である事が条件としてあると言う事。

```vuejs
<!-- これはダメ -->
<transition>
  <div v-if="show">message1</div>
  <div v-if="show">message2</div>
</transition>
```
対象が単一要素であれば良いので、これなら問題ない。
（まあ普通はこっちになると思うけど）

```vuejs
<!-- これは良い -->
<transition>
  <div v-if="show">
    <div>message1</div>
    <div>message2</div>
  </div>
</transition>
```

またパターンをifや動的プロパティで表現する時に複数要素を指定するのは問題ない。

```vuejs
<!-- これは良い -->
<transition>
  <button v-if="show === 'message1'" key="message1">
    message1
  </button>
  <button v-if="show === 'message2'" key="message2">
    message2
  </button>
  <button v-if="show === 'message3'" key="message3">
    message3
  </button>
</transition>
```
つまり、条件の単一要素と言うのは「独立したノード」又は「一度に1つのみ描画される複数ノード」であれと言う事。

また`transition-group`でも使う時に注意が必要な点がある。
ドキュメントにも重要であると書かれており、使う上で直ぐに気づくと思うが、`v-for`で回す要素を`span`でラップする形でDOMが形成される。

これはtag属性で指定する事でspan以外のタグを設定する事が出来るが、場合によってはコーディングに影響が出るので注意が必要。

```vuejs
<transition-group name="list" tag="p">
  <span v-for="item in items" v-bind:key="item" class="list-item">
    {{ item }}
  </span>
</transition-group>
```
AtCoder Heuristic Contest 002 参戦記

# AtCoder Heuristic Contest 002 参戦記

最初は一度出たタイルは2度と入れないだと問題を完全に勘違いしていて、Web版ビジュアライザに0点と言われて勘違いに気づいた(笑).

次にダイクストラ法風に heapq を使って、ある地点でのベストスコアを記録して、それ未満な枝をカットしながら探索したところ 4174074点. 残り2時間で30位だったのでやったーと思ったが、その後は6.3%しかスコアを伸ばせなかった.

最高スコアより低い枝もある程度枝刈りしないようにして点を伸ばしたのだが、本当は残り行ける数を評価しないとダメだったんだなあと思いました. 素直な BFS のほうが良かったかな.

```python
def main():
    from time import time
    from heapq import heappush, heappop

    start = time()

    si, sj = map(int, input().split())
    t = [list(map(int, input().split())) for _ in range(50)]
    p = [list(map(int, input().split())) for _ in range(50)]

    def is_time_ok():
        return time() - start < 1.95

    best_scores = [[-1] * 50 for _ in range(50)]
    best_score = 0
    best_result = ''
    q = [(si, sj, 0, '', set([t[si][sj]]))]
    while q and is_time_ok():
        i, j, score, result, used = heappop(q)
        if -score > best_score:
            best_result = result
        for di, dj, s in [(-1, 0, 'U'), (1, 0, 'D'), (0, -1, 'L'), (0, 1, 'R')]:
            ni, nj = i + di, j + dj
            if ni < 0 or ni > 49 or nj < 0 or nj > 49:
                continue
            if t[ni][nj] in used:
                continue
            nscore = score - p[ni][nj]
            bs = best_scores[ni][nj]
            if -nscore < bs - 135:
                continue
            best_scores[ni][nj] = max(bs, -nscore)
            nresult = result + s
            nused = used | set([t[ni][nj]])
            heappush(q, (ni, nj, nscore, nresult, nused))
    print(best_result)


main()
```