OmniAICreator/Qiita-1.07M huggingface dataset:
position: fixed指定したら横幅短くなったし、要素が隠れてしまった時の対処法

# 前提

- M2 Mac 12.5.1
- Node.js 16.17.1
- Next.js 12.3.1
- tailwind 3.1.8
- GoogleChrome 105.0.5195.125

SPAとかSSRとか関係なく、HTML/CSSの話なので環境が違っても役立つ話かと思います
ただし、`tailwind`を使用しているので、CSSの書き方は読み替えお願いします

https://tailwindcss.com/docs/installation

# 理想

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/241f1136-0c46-328f-0d1e-f1354898e1f5.png)

# 現実

`fixed`を指定したあとは...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/fad4ec69-bdff-94c6-fffb-66a6ce05cb11.png)

# やったこと

- ヘッダ部分に`position: fixed;`を追加

```diff_tsx
// navbar.tsx
import Link from 'next/link'

export const Navbar = (): JSX.Element => {
  return (
-    <header className="text-center bg-c1 text-c5 py-4">
+    <header className="fixed text-center bg-c1 text-c5 py-4">
      <div className="flex flex-wrap flex-row text-3xl justify-center">
        <Link href="#section-profile">
          <a className="px-3 hover:underline decoration-c2 hover:decoration-4">Profile</a>
        </Link>
// ...略...
      </div>
    </header>
  )
}
```

# 解決策

## 横幅が短くなってしまう

- `position: fixed;`を指定しているところに`width: 100%;`を追加

```diff_tsx
// navbar.tsx
import Link from 'next/link'

export const Navbar = (): JSX.Element => {
  return (
-    <header className="fixed text-center bg-c1 text-c5 py-4">
+    <header className="fixed w-full text-center bg-c1 text-c5 py-4">
      <div className="flex flex-wrap flex-row text-3xl justify-center">
        <Link href="#section-profile">
          <a className="px-3 hover:underline decoration-c2 hover:decoration-4">Profile</a>
        </Link>
// ...略...
      </div>
    </header>
  )
}
```

## 要素がヘッダーの下に隠れてしまう

- ヘッダーの高さ以上の十分な`padding`をとる

```diff_tsx
// index.tsx
// ...importは省略...

const Home: NextPageWithLayout = () => {
  return (
-    <div className="container text-center">
+    <div className="container text-center py-52 sm:py-40 md:py-20">
      <Head>
        <title>サンプル</title>
        <meta name="description" content="サンプル" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <h1 id="section-profile" className="text-3xl">
        Profile
      </h1>
      <div className="py-10">なまえ: じゅげむじゅげむ</div>
    </div>
  )
}
```

# 参考

https://teratail.com/questions/175904
Virtual Box上にKali Linuxをインストールする方法

[@ipusiron](https://twitter.com/ipusiron?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor) さん著の『[ハッキング・ラボのつくりかた](https://www.shoeisha.co.jp/book/detail/9784798155302)』及び『[ハッキング・ラボの構築で困ったら読む本](https://hack.booth.pm/items/1850777)』でVirtual Box上にKali Linuxの実験環境を構築した際に、書籍の記載内容から変わっていた点があったのでメモ書きとして記録する。
:warning:2022/09/23時点の情報を基に記載しています。そのため、現時点で相違がある可能性があります。その点を了承の上お読みください。

# 書籍の記載内容から変わっていた箇所
Kali LinuxのVirtual Box版のイメージをダウンロードして、Virtual Boxにインポートする方法手順。
書籍では、OVAファイルをインポートする記載となっていました。しかし、現在はダウンロードしたvboxファイルから仮想マシンを追加するというより簡単な方法でKali Linuxをインストールできるようになっています。

具体的な手順は:point_down:で紹介していきます。

# 検証環境
OS：Ubuntu 22.04
Virtual Box：6.1.38

:loudspeaker: Windows環境やMac環境でも大筋は変わらないと思います！

# Kali Linuxのインポート手順

１．[Kali Linuxの公式サイト](https://www.kali.org/get-kali/)へアクセス！
２．Prebuilt Virtual Machinesを選択して、仮想マシンイメージを取得するページへ移動
![Screenshot from 2022-09-23 19-16-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/9dc7ebbd-5485-adc9-6c5d-2ceddd1b5a7d.png)

３．Virtual box用のイメージをダウンロード
　　:mega: VMWare版の場合も入手可能です。今回の記事では触れません。
![Screenshot from 2022-09-23 19-16-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/5e6aec93-6a84-2e38-b1a7-00aa4dd3e988.png)


４．7Zipファイルがダウンロードされるので解凍する。
　　Linuxの場合は、p-7zipがおすすめ。
```bash:7zipファイルを解凍
$ sudo apt install p7zip-full
$ 7z x 解凍対象ファイル
```

　　Windows環境の場合は7Zipをインストールして解凍してください。

解凍すると、:point_down:の２つのファイルが得られる。
vboxファイルが、仮想マシンの設定ファイル。
vdiファイルが、仮想マシンがインストールされた仮想ハードディスク。
![Screenshot from 2022-09-23 19-25-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/42c77a2e-4f90-2c54-4f4a-9cd75ed43c45.png)

５．解凍してできたフォルダをVirtual Boxのデフォルトの仮想マシンフォルダへ移動
　　:mega: デフォルトの仮想マシンフォルダは、「ファイル　→　環境設定　→　一般　デフォルトの仮想マシンフォルダ」で確認できます。
６．仮想マシン設定ファイル（vboxファイル）を使用して仮想マシンを追加する。
「メニュー　仮想マシン　→　追加」により、５．で移動したvboxファイルを選択してKali Linuxの仮想マシンを作成する。
![Screenshot from 2022-09-23 19-27-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/901d53bc-d53d-66df-d644-c1ba950ab335.png)

![Screenshot from 2022-09-23 19-27-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793264/208be0a1-e56d-4793-98bc-bc5ee0deedce.png)

### 実験環境の仮想マシン（Kali Linux）環境をインポートすることができた:clap:！！

### この後の実験環境の整備方法は、書籍に従って行えば良い:thumbsup::exclamation::exclamation:
Python用標準入力チートシートまとめ

# はじめに
python用の標準入力でよく使うものを集めたチートシートです。
便利そうなものがあれば随時更新してゆきます。

# 標準入力のコーディングに必要な関数
### input()
入力で与えられるフォーマットを文字列で取得する
```
# 以下入力pを与えられるとすると
p

# pを取得してsに値を入れる
s = input()

# 出力
print(s)　
>>> p (str)
```
input関数で取得した時点ではstr(文字列)なので、計算などで使用する場合は型を変えてあげる必要があります。
```
# 入力
３

i = int(input()) # 3を取得してint(整数)に変更してiに値を入れる

print(s)　# 出力: ３ (int)

```
### split()
文字列を分割する関数です
```
# 以下入力　a　と　b　をスペースを挟んで与えられるとすると
a b

# a と　b　を取得して　s　にlist形式で入れる
s = input().split()

# 出力
print(s)
>>> ['a', 'b']
```
splitする数に合わせて変数を用意して直接変数に入れる方法もあります。

```
# 以下入力　a　と　b　をスペースを挟んで与えられるとすると
a b

# a と　b　を取得して　x と y　にそれぞれ値を入れる
x, y = input().split()

# 出力
print(x)
>>> a

print(y)
>>> b
```


### map()
第一引数に適用する関数、第二引数にリストなどのイテラブルオブジェクトを指定します。

イテラブルオブジェクトとはfor文などで要素を１つずつ取り出して処理できるようなオブジェクトのことを指します。（listやdictなど）
```
# 以下入力　１　と　２　をスペースを挟んで与えられるとすると
1 2

# 1 と　2　を取得して　x と y　にそれぞれ値を入れ、それぞれint型にする
x, y = map(int, input().split())

# 出力
print(x)
>>> a (int)

print(y)
>>> b (int)
```
### range()
0から連番を作成します
```
for i in range(3):
    print(i)

>>> 1
>>> 2
>>> 3
```
リストを生成することも可能です。
```
li = list(range(3))

print(li)
>>> [0,1,2]
```

# よくでる標準入力
よくでる標準入力をここにまとめます。

## 1行に１つの入力を整数で取得
```
# 以下入力　１を1行与えられるとすると
1

a = int(input())
print(a)
>>> a (int)
```
## 1行に複数ある入力を整数で取得
```
# 以下入力　１　と　２をスペースを挟んで1行で与えられるとする
1　２


# それぞれ変数に格納
a, b = int(input().split())
print(a)
>>> 1 (int)

print(b)
>>> 2 (int)


# リストで取得したい場合
li = int(input().split())
print(li)
>>> [1, 2]
```

## 複数行にわたって１行に1つの入力を整数でlist取得
### 行数が指定されている場合
```
# 以下入力　１~3を3行で与えられるとすると
1
2
3

# for文で３回入力を取得して整数に変換後、listにする
li = [int(input) for i in range(3)]

# print(li)
>>> [1, 2, 3]
```
### 行数が指定されていない(不明な)場合
```
# 以下入力　１~NをN行で与えられるとすると
1
2
3
...
N

while True:
	try:
		i = map(int, input())
		input_lines += i
	except EOFError:
		break

# print(li)
>>> [1, 2, 3]
```
:::note warn
補足
map()を使わずに i = int(input())としてもよさそうですが、繰り返しに使えないオブジェクト（ここでは整数）を繰り返し処理（ここでは +=）で使うことになり、TypeError: 'int' object is not iterable　が発生するので必ず map() を使いましょう。
:::

## 複数行にわたって１行に複数の入力を整数でlist取得
### 行数が指定されている場合
```
# 以下入力　１~６を3行で２つずつスペースを挟んで与えられるとすると
1　２
３　４
５　６


r = []

# for文で３回入力を取得して整数に変換後、listにし二次元配列で格納する
li = [r.append(list(map(int, input().split()))) for i in range(3)]

# print(r)
>>> [[1, 2], [3, 4], [5, 5]]
```
### 行数が指定されていない(不明な)場合
```
# 以下入力　１~NをN行で与えられるとすると
1 2
3 4
5 6
...
N N

while True:
	try:
		r.append(list(map(int, input().split())))
	except EOFError:
		break

# print(r)
>>> [[1, 2], [3, 4], [5, 6]... [N, N]]
```

# 最後に
もし他にも便利な取得方法などがあれば教えてください。
PostgreSQL環境構築

# PostgreSQL環境構築

## 概要

dockerを使って環境構築をします

## Dockerfileの準備

```Dockerfile
FROM postgres:latest

ENV POSTGRES_PASSWORD postgres

RUN apt-get update && \
    apt-get clean language-pack-ja  && \
    rm -fr /var/lib/apt/lists/*

# Time Zone
ENV TZ Asia/Tokyo

# Language
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG="ja_JP.UTF-8" \
    LANGUAGE="ja_JP:ja" \
    LC_ALL="ja_JP.UTF-8"
```

## docker-compose.ymlの用意

```yml
version: '3'
services:
  pgsql:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: pgsql
    tty: true
    volumes:
      - ./db:/var/lib/postgresql/data
    ports:
      - '25432:5432'
```

## ビルド

```docker-compose build```

## コンテナの起動

```docker-compose up -d```

## コンテナに入る

```docker exec -u postgres -it pgsql bash```

## クライアントの起動

```psql```

## 参考

[【PostgreSQLをインストール】Dockerを使って15分以内に作成する！ | Study Infra](https://study-infra.com/postgresql-install-docker/)
k3d を使ってローカル で k8s を試す

## 環境 

MacOS

## k3s とは

https://k3d.io/v5.4.6/

> k3dは、k3s（Rancher Labの最小Kubernetesディストリビューション）をdockerで実行するための軽量なラッパーです。
> k3dを使うと、Kubernetes上でのローカル開発など、シングルノードやマルチノードのk3sクラスタをDocker上で非常に簡単に作成することができます。


### k3s インストール

```bash
brew install k3d
```


### クラスタ作成

```
k3d cluster create mycluster
```

### クラスタ削除

```
k3d cluster delete mycluste
```

## kubectl 操作メモ


### コンテキストの一覧

```
kubectl config get-contexts
```

### コンテキストの切り替え

```
kubectl config use-context xxx
```

### ポートフォーワード

```
kubectl port-forward mypod 80:80
```


## NodePort を使ってアクセス

https://k3d.io/v5.4.6/usage/exposing_services/#2-via-nodeport
【Swift】Dateは扱いにくい！！

# はじめに
Dateは扱いにくい！！
こんなふうに使いたい！！！
```swift
Date(string: "2022/05/10 12:00:00")
```

# 実装
```swift
extension Date {
    init(string: String, format: String = "yyyy/MM/dd HH:mm:ss") {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        dateFormatter.locale = Locale.current
        dateFormatter.timeZone = TimeZone.current
        dateFormatter.calendar = Calendar(identifier: .gregorian)
        guard let date = dateFormatter.date(from: string) else {
            fatalError("The format is incorrect")
        }
        self.init(timeIntervalSince1970: date.timeIntervalSince1970)
    }
}
```

:::note warn
**注意**
`dateFormatter.calendar`を指定しないとユーザーの設定によって値が変わってしまう

https://qiita.com/SNQ-2001/items/38912a1f41129585cdba#comment-d114039a82f8abb99df9
:::

# おわり
`fatalError`で処理してるのは良くないかもしれないです。
おすすめの方法があればコメントで教えていただけると嬉しいです
PythonでEmbulkを動的に実行する

# はじめに
ETLツールの一種であるEmbulkでは、データ転送の処理をyamlで設定して実行します。
動的に処理内容を変更したい場合、yamlの一部を環境変数に置き換えることができます。

しかし、処理内容を実行ごとに変化させたい場合、環境変数で設定をするのは面倒です。例えば、出力するファイル名に実行時間を加えたい場合などには、環境変数を逐一変更することになります。
この記事では、Python用のテンプレートエンジンであるjinja2を使って、簡単にyamlの設定ファイルを動的生成する方法について紹介します。より作り込んだシステムが必要な場合には、Digdagなどのワークフローエンジンを使うことが良いです。

## そもそもEmbulkとは
EmbulkとはOSSのバッチ型のデータ転送ツールです。ストリーミングデータを対象にしたfluentdと対になるようなツールです。コンパクトながら、たくさんの入出力のデータソースに対応しておりとても便利です。

https://www.embulk.org/

日本人の古橋さんという方が主導で開発されているようです。とてもありがたいです。下のリンクはリリース時の記事です。

https://frsyuki.hatenablog.com/entry/2015/02/16/080150

簡単な使い方を紹介します。データ転送（ETL）の入力と出力の処理内容を、下のようにyamlで定義してコマンド実行します。例では、gzipで圧縮されたcsvを標準出力する処理を示しています。設定内容の補完機能があり、下のような設定を全て手入力で行う必要は無く、また、プレビュー機能やフィルター機能なども利用できます。
```処理内容.yml
in: # 入力データの内容（ETLのExtract部分）
  type: file
  path_prefix: ./try1/csv/sample_
  decoders:
  - {type: gzip}
  parser:
    charset: UTF-8
    newline: LF
    type: csv
    delimiter: ','
    quote: '"'
    escape: '"'
    null_string: 'NULL'
    trim_if_not_quoted: false
    skip_header_lines: 1
    allow_extra_columns: false
    allow_optional_columns: false
    columns:
    - {name: id, type: long}
    - {name: account, type: long}
    - {name: time, type: timestamp, format: '%Y-%m-%d %H:%M:%S'}
    - {name: purchase, type: timestamp, format: '%Y%m%d'}
    - {name: comment, type: string}
out: {type: stdout} # 出力データの内容（ETLのLoad部分）
```

# jinja2でyamlを動的に生成
前置きが長くなりましたが、jinja2でyamlを生成するコード例について紹介します。
以下では、テンプレートとなるyamlファイルをもとに、実行するyamlファイルを生成し、Embulkで実行しています。
具体的には、mysqlからデータを抽出し、gzip化されたcsvファイルを出力する処理を行っています。テンプレートエンジンを使うことで、ファイル名などの動的な設定を（簡単に！）できます。

```template.yml
# テンプレートのyamlファイル
in:
  type: mysql
  host: localhost
  user: <ユーザ名>
  password: <パスワード>
  database: sample
  table: user
  select: "id, name"
out:
  type: file
  path_prefix: ./data/sample_{{ start_time }} # 変数を入れたい箇所
  sequence_format: .
  file_ext: csv.gz
  formatter:
    type: csv
  encoders:
  - type: gzip
```
```execute_embulk.py
# Embulkを実行するためのPythonスクリプト
import datetime
import os

from jinja2 import Template # jinja2パッケージを使う!!

# 現在時刻の取得
dt_now = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')

# yamlテンプレートの取得
with open('template.yml') as f:
    template_yml = f.read()
teamplate = Template(source=template_yml)

# 変数の代入
new_yml = teamplate.render(start_time=dt_now)

# 実行するyamlファイルの作成
with open('config.yml', 'w') as f:
    f.write(new_yml)

# Embulkの実行
os.system('embulk run config.yml')
```

```config.yml
# Embulkで実行するyamlファイル（実行ごとに生成）
in:
  type: mysql
  host: localhost
  user: <ユーザ名>
  password: <パスワード>
  database: sample
  table: user
  select: "id, name"
out:
  type: file
  path_prefix: ./data/sample_20221002_162745 # 動的に変更した箇所
  sequence_format: .
  file_ext: csv.gz
  formatter:
    type: csv
  encoders:
  - type: gzip
```

# おわりに
今回はPythonのテンプレートエンジンであるjinja2を使って、yamlを動的に生成する方法について紹介しました。flaskでjinja2を使っていたのを思い出して使ってみましたが、簡単で結構便利です。Embulkに限らず、設定ファイルの管理などにも使えそうです。
まだ、Digdagなどのワークフローエンジンは使ったことがないので、そちらの方も試してみたいです。
【SQL】集計関数の結果をJOINする

現在エンジニアを目指してPHPを学習中です。
SQLで集計関数の結果をJOINして取得する方法を学んだので、メモです。

## 前提
以下の2つのテーブル（生徒、テスト結果）があったとして、
__各生徒の科目毎の平均点を算出した上で、生徒テーブルにJOINして取得したい__
というのが今回やりたいことです。
ちなみにMySQLは5.7.34
___
↓生徒テーブル
|id |名前 |出身|
|---|---|---|
|1|鈴木|東京|
|2|佐藤|東京|
|3|高橋|沖縄|


↓テスト結果テーブル（）
|生徒id |英語 |数学 | 
|---|---|---|
|1|60|30|
|2|20|100|
|3|80|70|
|1|70|30|
|1|90|50|
|3|100|80|

↓取得したいデータ
|id |名前 |出身 |英語平均 |数学平均 |
|---|---|---|---|---|
|1|鈴木|東京|||
|2|佐藤|東京|||
|3|高橋|沖縄|||

## 先に結論：「JOIN hoge ON」 のhogeに集計関数のSQLをはめる
色々調べた結果、今回は以下のSQLを流すことで希望のデータを取得できました。

```sql
SELECT * FROM 生徒 LEFT JOIN (SELECT 生徒id, AVG(英語), AVG(数学) FROM review GROUP BY 生徒id) AS avg ON 生徒.id = avg.生徒id
```

## 組み立ての順序
順を追って見ていきましょう
### ①まずは集計結果を取得するSQLを用意
はじめに、集計結果を取得する関数を用意します。集計関数は以下が代表的なものらしい。
（記載方法がわかりやすくなるよう、SELECTもつけてます）
```sql
SELECT COUNT(x) /* xの件数を取得 */
SELECT AVG(x) /* xの平均を取得 */
SELECT SUM(x) /* xの合計を取得 */
SELECT MIN(x) /* xのなかで最小値を取得 */
SELECT MAX(x) /* xのなかで最大値を取得 */
```
今回であれば、テスト結果テーブルから生徒ごとに英語・数学の平均点を取得したいです。
以下のSQLで、平均点を取得できます。
```sql
SELECT 生徒id, AVG(英語), AVG(数学) FROM テスト結果 GROUP BY 生徒ID
```

### ②JOIN元となるテーブルの関数を用意
今回は、生徒テーブルを基準に、平均点をJOINしたデータを出したいです。
なので以下。（WHERE句などついていても問題ありません）
```sql
SELECT * FROM 生徒　LEFT JOIN /**/ ON 生徒.id = テスト結果.生徒id
```

### ③2つのSQLをドッキング
②のSQLにおける`/**/`の部分に①を結合して完成です。
なお①の関数にはASで別名をつけます。今回は`avg`としました。
ONの部分も若干書き換わっているので注意です。
```sql
SELECT * FROM 生徒 LEFT JOIN (SELECT 生徒id, AVG(英語), AVG(数学) FROM review GROUP BY 生徒id) AS avg ON 生徒.id = avg.生徒id
```


## まとめ
今回の考え方ですが、
①の集計関数で新たなテーブルを作成し、③で生徒テーブルと新テーブル（avgと命名）を結合した
と考えるとわかりやすいかなと思います。
↓avg テーブル
|生徒id |英語平均 |数学平均 |
|---|---|---|
|1|||
|2|||
|3|||

そのため、①のSQLでは後々の結合に必要な生徒idも取得しておかないと、③でエラーになります。
↓以下はエラー
```sql
SELECT AVG(英語), AVG(数学) FROM テスト結果 GROUP BY 生徒ID
```

今回は以上です。SQL深めたい。。


※内容や考え方に間違い、補足等ありましたらぜひ教えていただけますと幸いです！
読み込んだファイル内にある数の最大値と最小値を求めるコード

# 読み込んだファイル内にある数字の最大値と最小値を求めるコード

```:最大最小.py
n = int(input("数はいくつですか？"))

f = open('1.txt')
list_str=f.read().split()
f.close()

min_val=int(list_str[0])
max_val=int(list_str[0])
for i in range(1,n):
    if min_val>int(list_str[i]):
        min_val = int(list_str[i])
    
    if max_val<int(list_str[i]):
        max_val = int(list_str[i])
        
print("最小値は"+str(min_val)+"です。")
print("最大値は"+str(max_val)+"です。")
```
### 用意するファイル例
![最大最小_5_1text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/c826850d-513c-6954-24f3-2063faf6423c.png)
### コード
![最大最小_1コード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/a65ed9c7-afae-11fe-ef4c-792752406457.png)
![最大最小_2打込.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/9b9a45a0-c3d9-153c-fd62-7f76961d6300.png)
![最大最小_3入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/7af18810-6989-122c-2f1b-12d0ea1d900a.png)
![最大最小_4結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2739883/329daec2-09fd-be92-d3bf-2c17643d25d7.png)


## 作りたいもの
* ファイル内にある数の個数を問う質問文
* ファイルを開いて読み込むコード
* 個数を入力したら計算して、解を表示させるコード

## 作りたいものに対応するコード
#### ファイル内にある数の個数を問う質問文
```Python
n = int(input("数はいくつですか？"))
```

#### ファイルを開いて読み込むコード
```Python
f = open('1.txt')
list_str=f.read().split()
f.close()
```

#### 個数を入力したら計算して、解を表示させるコード
```Python
min_val=int(list_str[0])
max_val=int(list_str[0])
for i in range(1,n):
    if min_val>int(list_str[i]):
        min_val = int(list_str[i])
    
    if max_val<int(list_str[i]):
        max_val = int(list_str[i])
        
print("最小値は"+str(min_val)+"です。")
print("最大値は"+str(max_val)+"です。")
```

# 感想
* 最小値や最大値を次々更新していくためにはどうすればいいのか考えるのに時間がかかった。
* 文字型と整数型をよく混同してしまうから、しっかり覚えたい。
Openmediavaultで「Performance Statistics」が機能しないバグの修正

**Openmediavaultで「Performance Statistics」が機能しないバグの修正**
フリーのNASプログラムのOpenmediavaultは、以下のパーフォマンスがグラフで表示される。
・CPU
・Disk I/O
・Disk Usage
・Load Average
・Memory Usage
・Network Interfaces
・Uptime 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/745702/fa387b29-7c8e-099f-44b8-06c100497e35.png)
これまで、Ver.5で運用していたが、最近、Ver.6にアップグレードしたところ、
「Performance Statistics」が全く動いていないことに気づいた。
いろいろ調べた結果、解決法がわかったので、記録として残しておく。
なお、現在使用しているOMVのバージョンは、6.0.42-2 (Shaitan)である。

**原因：**
スクリプト　./etc/init.d/rrdcached  が rrdcached　をロードしていない。

**解決法：**
./etc/init.d/rrdcached　の指定された行を、以下のように書き換え
「start_daemon」からでなく、直接「rrdcached」から起動させる。

```
Code：変更部分
start_daemon -p ${PIDFILE}　${DAEMON} ${RRDCACHED_OPTIONS}
　　を以下のように２行に分け、１行目をコメントアウトする。
# start_daemon -p ${PIDFILE} 
${DAEMON} ${RRDCACHED_OPTIONS}
```

:::note warn
注意：
スクリプト修正前に、オリジナルの./etc/init.d/rrdcachedのバックアップを必ず取っておいてください。
書き換え後に、再起動が必要です。
:::
参考
https://github.com/openmediavault/openmediavault/issues/1217
https://forum.openmediavault.org/index.php?thread/42038-omv6-performance-statistics-not-working/
Wordでフローチャートを書くな高校

※この記事には偏見が含まれます。
ご自分に合ったツールを使ってください。

# Wordでフローチャートを書くな高校
Wordでフローチャートを書くな高校
Wordでフローチャートを書くな高校

### おお　われらが　Wordでフローチャートを書くな高校

Wordでフローチャートを書こうとすると
コネクター線が　くっついてくれない
![コネクター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663038/7993e2e4-9ac2-2f58-f93b-08301691eae3.png)

（※ところで、Shiftを押しながら　動かすと
直線が書けたりするぜ）


![shift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663038/dfd937b3-fd30-63a5-bf61-a86f4510ab2a.png)

磁石のように　ぴったりと
コネクター線が　くっついてくれない

線をそろえる労力は

間違っている　間違っている

PowerPointのほうが書きやすい
（次点でExcel）

Wordでフローチャートを書くな高校
Wordでフローチャートを書くな高校

### もしもツールを選べるならば

もしもツールを選べるならば

[draw.io](https://app.diagrams.net/)
[PlantUML](https://plantuml.com/ja/)

だったらいいのにな

## draw.ioはWeb上で動く
draw.ioはWeb上で動く
![draw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663038/3cbef466-1772-dd3e-23a3-9af5b9a70111.png)

見よこのマス目

![masu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663038/898a9da4-a09f-32ee-5ec8-90e69583e710.png)

マス目に図形を添わせられるだけで
フローチャートは書きやすい

図形をそろえる労力は
間違っている　間違っている

PlantUMLはちょっと違う
タグうちゃ構造　生えてくる

![plant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663038/f4dfe6b2-5194-75d8-4746-1c1a7d3582ef.png)

直観操作的ではないので
上級者向けである

それでもWordよりはいい

オフラインでやりたいのなら
いざゆかん　VisualStudioCode　プラグイン

### どうしてもWordでなくてはならない

おお　クライアントが　言っている
我々も図形を愛したい
編集しないとならないと

共通言語がWordであるのだ

ゆえに
Wordでフローチャートを書かなくてはならない
Wordでフローチャートを書かなくてはならない

Wordでフローチャートを書かせるな
Wordでフローチャートを書かせるな高校

Microsoft 365でWeb版Visioでなんとか
なりませんか　なりませんか……。

ならないですか……。わかりました……。
……描画キャンバスを使ってください……。


### せめてパワポにして高校

あの
ふだんあんまりフローチャート書かず
個人でゲーム開発しようと思い立ったとか
そういう
そういう人は

ちょっとだけ図が欲しいとか、ちょっとだけとか、
そういうときは
Wordでいいのかな、って思ったときは

パワーポイントを試してみて高校
おお　パワーポイントを試してみて高校
【Linux】コマンド履歴からコマンドを実行する


# コマンド履歴からコマンドを実行する
以前に実行したコマンドを再度実行したい場合に、コマンド履歴を確認する事で楽に再実行する事が出来ます。
`historyコマンド`　または　`インクリメンタルサーチ`　を実行する事でコマンドの再実行を楽に行えます。

## historyコマンド

`historyコマンド`については、`historyコマンド`の結果を`grepコマンド`で絞って確認するのが定番だと思います。`historyコマンド`単体で叩いても、出力される結果が多いので目的のコマンドを探すのが大変です。
ある程度スペルが分かっている前提ですが、`historyコマンド | grep 対象文字列`で履歴を絞る事が可能です。

以下、実行例です。

```shell_session:コマンド実行
[root@localhost ~]# history | grep 'll'
   12  lsll
   13  ll
   18  history | grep 'll'
```

目的のコマンドが見つかった場合に、弄りたい場合はコピペして編集するとよいでしょう。
そのまま実行したい場合は、コマンドと一緒に表示されている番号と`!`を組み合わせて実行する事が出来ます。

以下、実行例です。

```shell_session:コマンド実行
[root@localhost ~]# history | grep 'cat'
   22  cat memo.txt
   26  cat -n  .bash_history
   27  history | grep 'cat'


# 26  cat -n  .bash_historyを実行
[root@localhost ~]# !26
cat -n  .bash_history
     1  cat -n .bash_history
　　　
     etc...
```

## インクリメンタルサーチ

<font color="Red">インクリメンタルサーチ</font color>でもほぼ同じような事が出来ます。私は普段、こちらを使用しています。
プロンプトで`Ctrl + r`を入力すると、インクリメンタルサーチを使用する事が出来ます。
以下のように、プロンプトが変更されます。

```shell_session:インクリメンタルサーチ
(reverse-i-search)`':
```

この状態でキーボードを入力すると検索が行われます。
cと入力すると、以前に実行したコマンドが表示されます。cat -n  .bash_historyを先程実行しているので、以下のように出力されました。さらにdを入力すると、cd /tmpと出力されました。

インクリメンタルサーチは、入力毎に履歴を検索する特徴があります。


```shell_session:インクリメンタルサーチ
#cと入力
(reverse-i-search)`c': cat -n  .bash_history
#次にdを入力
(reverse-i-search)`cd': cd /tmp
```

文字入力後に、再度`Ctrl + r`を実行すると1つ前の実行結果に移動します。
`Ctrl + r を実行する` or `文字を入力する` で目的のコマンド探す事が可能です。

目的のコマンドが見つかったら、`Enterキー`を入力するとコマンドが実行されます。
コマンドを編集したい場合は`Escキー`で検索結果をそのままで、元のプロンプトに戻れます。

また、インクリメンタルサーチから抜けたい場合は`Ctrl + g`でプロンプトに戻る事が可能です。

## 終わり
`historyコマンド`と`インクリメンタルサーチ`を記載しましたが、好みで使い分けすればよいと思います。
`$ git status -s`について

`$ git status`を使用すれば、現在編集中のファイルやインデックスされているファイルの一覧を確認することができる。  
このコマンドに`-s`オプションを付与すればより簡単にファイルの差分を確認することができるが、ファイルの前に文字が表示される。  
あまりこの意味に関して理解していなかったので調べてみた。  
※`-s`=`--short`  
![git-status.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953754/2bd5735d-c494-d5b0-d9fc-43cd81ee3635.png)




# 基本構造
変更があったファイの頭には1つか2つのアルファベットがつく。  
└**XYの構造**  

- X（右側）→ ステージ前の状態
- Y（左側）→ ステージ後、コミット前の状態

VSCodeの場合はわかりやすいように色分けしてくれる。  
└Y：緑、X：赤


# アルファベット一覧
| 文字 | 単語 | 意味 |
| -- | -- | -- |
| A | added | 新規ファイル |
| M | modified | 変更したファイル |
| D | deleted | 削除したファイル |
| R | renamed | 名前変更 |
| C | copied | コピー |
| U | unmerged | 未マージ |
| ? | untracked | 未追跡、gitが認識していない |
| ! | ignored | 無視 |



# 参照
- [git-status Documentation](https://git-scm.com/docs/git-status#_short_format)
- [git status -s(–short)オプションの使い方を実例で解説｜冒頭のアルファベットや記号A, M, D, ?, U, !, C, R, AD, AM, ??, MM, UUとは何か？意味は？](https://prograshi.com/general/git/git-status-s-short/)
VMware Cloud on AWS の設定状況を API Explorer で確認する

# はじめに
<!-- 発端や概要を記載 -->
VMware Cloud on AWS (VMC) では、さまざまな自動化と統合のニーズに対応可能な複数のツールと開発インターフェイスが提供されています。これらのツールは、手動タスクを自動化し、大規模で複雑な環境を管理する際に役立ちます。
今回は API Explorer を利用して、VMC の 組織（Org）の設定状況を確認してみます。


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [API Explorer](#api-explorer)
1. [API Explorerを利用して設定状況を確認してみる](#api-explorerを利用して設定状況を確認してみる)
1. [まとめ](#まとめ)
1. [参考文献](#参考文献)


<!-- 各チャプター -->
# API Explorer
VMC では、DevOps ワークフローとの自動化および統合を可能にする REST API を提供しています。 REST APIは、さまざまな言語やスクリプトからアクセスできます。API Explorer は VMC の管理コンソール（VMC コンソール）に実装されており、管理コンソール画面から VMC 環境向けの API コールの書式やリソース名、ステータスコードなどがその場で確認できるようになっています。

# API Explorerを利用して設定状況を確認してみる
今回は API Explorer を利用して、Org の設定状況を確認してみます。
API Explorer にアクセスするには VMC コンソールから [デベロッパー センター]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/d6b2989d-9b78-d112-14c5-430981812d44.png)

デベロッパー センターが表示されますので、[API エクスプローラー]タブをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/2a44045a-305c-42c2-9416-1714df66e8dc.png)

API エクスプローラーが表示されます。ここから API の実行ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/09d34d4b-358f-b6f2-e162-2b9a9afd3457.png)

Org の設定を確認するには [VMware Cloud on AWS] - [全般] - [orgs] から [Get Orgs](https://developer.vmware.com/apis/vmc/latest/vmc/api/orgs/org/get/) (GET /orgs/{org}) を展開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/0e9321ac-7bd6-6d03-fc7e-1ebec6581b28.png)

実行をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/e47956c3-687c-80bc-8cc4-83325af6e308.png)

[Organization] - [OrgProperties]を展開すると以下のように Org の設定状況が確認できます。
この Org では、現状 SDDC を 2つまで作成できる事が確認できました（赤枠部分）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/974c39a4-783b-88fb-23e5-699597564290.png)

::: note
SDDC の上限は [VMware Configuration Maximums](https://configmax.esp.vmware.com/guest?vmwareproduct=VMware%20Cloud%20on%20AWS&release=SDDC%201.18&categories=52-0) にて確認が可能です。
以下の通り、各 Org ではデフォルトで 2つの SDDC まで作成可能となっております。**soft limit** と書いてある通り、必要あれば上限緩和が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/850c1e37-8a85-8222-ce5f-f80312e75234.png)
:::

この Org では 最大 6個の SDDC を利用する予定があり、VMware のサポートに問い合わせをし、上限を 6 まで緩和をしてもらいました。
上限緩和後、再度同じ API を API Explorer から実施してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441095/b6f73d36-eef4-6251-a708-5b37ab51db2c.png)

上記の通り、**sddc_limit** が 6 に変わりました！


# まとめ
API Explorer は VMC コンソールからアクセス可能で、VMC 環境向けの API コールの書式やリソース名、ステータスコードなどがその場で確認できるようになっています。SDDC の管理画面から確認できないような設定も API Explorer を活用する事で簡単に確認が可能となります。


# 参考文献
- [Getting Started with the API Explorer - VMware Cloud on AWS Developer Center](https://www.youtube.com/watch?v=HEFxCYnCe2Y)
- [VMware Cloud on AWS API Reference](https://developer.vmware.com/apis/vmc/latest/)
Functorの使い方


## juliaでFunctorについて

Functorは、structを通常の関数のように扱いたい時に使われる。
下の例だと、fucntion a::structとすることで、あたかもstrunctを関数として扱うことができる。
例えば、ニューラルネットワークのAffine変換を考える。

```julia  
module My

struct Affine
    W
    b
    Affine(W, b) = new(W, b) #これはなくても動く。
end

# Functorはstruct(Affine)を関数のように扱う。xは引数。
function (a::Affine)(x)
    a.W * x + a.b
end
end

using .My
Affine = My.Affine
keisan(W, b, x) = W * x + b

W = rand(2,3)
b = rand(2)
x = rand(3)
a = Affine(W, b);
@assert a(x) ≈ keisan(W, b, x)
```


juliaのFuctorは、pythonでいうと__call__に相当する。


```python
class Goma:
    def __init__(self, name):
        self.name = name # "ごま"

    def __call__(self, human): # "Azarashi"
        print(f"Hello {human}, I am {self.name}")

g = Goma("ごま")
g("Azarashi")

```
マークダウン記法　基本

# マークダウン記法　基本

## 概要

マークダウン記法のメモです。
ある程度わかっている前提のもと、見ればああこうするんだったと思い出せるように書いてます。  
また基本とあるのは標準記法と拡張機能があるためです。

## 見出しの書き方

- \#を使う
- \#の数で六段階に分かれている。HTMLのh1~6のようなもの
- \#とタイトルの間にはスペースを入れる
- 見出しの前後には空行を挿入する

## 段落

- 特に記法はなく文章を書けば良い
- 空行によって段落は分割される
- インデントはしてはいけない

## 改行

- 文章の末尾に空白を2つ挿入することによって改行される

## 強調

- \*\*アスタリスク2つで囲むことによってボールドが適用される
- \*アスタリスク1つで囲むことによってイタリックが適用される
- \*\*\*アスタリスク3つで囲むことによってイタリックとボールドが適用される

## 引用

- \>を行頭で使用することで引用の表現ができる
- 複数行ある場合には空行も含めて全ての行頭に\>をつけなければならない。
- \>の数を増やすことによってネストの表現ができる
- 引用ないでは他の一部の記法を使用することができる。
- 引用の前後には空行を挿入する

## リスト

- 番号付きのリストを作成するには数字とピリオドによって作成できる1\.
- 番号付きリストの最初の要素は必ず１から始める
- \-ハイフンによって番号なしリストを作成できる。
- 番号なしリストではハイフンを使う
- リストの間に文章やリスト以外の他の要素を挿入したい場合には文章を空行で囲い行頭をインデントする

## コード

- コードを記載するためにはバッククォートを使います\`
- コード内にバッククォートがある場合には2つ使って囲む

## 水平線

- 水平線を表示するためにはハイフンを3つ使用する
- 行の前後に空行を入れる

## リンク

- \[テキスト\]\(リンク\)でリンクが貼れる
- \[テキスト\]\[数字\]とリンクを定義し任意の場所に  
\[数字\]\: \<URL\> とURLを定義することでもリンクを貼れる
- リンクを直接貼りたい場合には\<\>でURLを直接込めばよい

## 画像

- \!\[代替テキスト\]\(画像のリンク\)で画像を参照できる
- \[\!\[代替テキスト\]\(画像のリンク\)](外部リンク)で画像にリンクを貼り付けることができる

## エスケープ

- マークダウンで使用する記号をエスケープするためにはバックスラッシュ\\を使用します。

## 外部リンク

<https://www.markdownguide.org/basic-syntax/#headings>
Wire_Frameまとめ

## _概要_
画面作成でデザインセンスがない場合でも、テンプレのレイアウトを使うと見やすくなると思ったので、自分なりにまとめてみた…

## この記事で学べること
- WireFrameについて
- サイトマップについて
- WireFrame作成方法
- サイトマップ作成方法

## WireFrameとは？
・サイトを開発する前に「何を・どこに・どのように」画面に配置するかを明らかにするもの

https://www.sejuku.net/blog/9176

## WireFrame作成に必要なこと
- サイトマップの作成
- ページのレイアウト決め
- wireFrame作成

https://web-kanji.com/posts/making-wireframe

## サイトマップの作成
サイトマップを作成することで以下の利点がある！！
- Webサイト全体の構成やコンテンツの内容が一覧化され、頭の中の整理ができるようになる

- 他者でもどのような画面構成かが一目でわかるようになる

https://web-kanji.com/posts/making-sitemap-by-excel

## ページのレイアウト決め


### レイアウト作成に必要なパーツ 
- ヘッダー：メニューや検索フォームなどを配置
- コンテンツ：訪問者に伝えたい情報を盛り込みます。文章・画像・動画・表などを提示
- サイドバー：ナビゲーションや広告などを含む
- フッター：コピーライトの表記やサイトマップを配置

https://www.xserver.ne.jp/bizhp/homepage-layout/


### レイアウト
- ___シングルカラムレイアウト___
・それぞれのパーツを縦並びに配置
・レスポンシブWebデザインと相性が良い
・シンプルで見やすい

https://relyl.com/

- ___マルチカラムレイアウト___
・複数のカラム（列）によって構成
・コンテンツの隣にサイドメニューが配置されている
・商品数の多いECサイトや情報量の多いニュースサイトなどで使用

- ___2カラムレイアウト___
・サイドメニューがあるため、いつでも目的のページを見れる
・マルチカラムレイアウトに属す

https://hokuohkurashi.com/


- ___3カラムレイアウト___
・目的が異なるユーザーが訪問しても、網羅的に情報を提供
・マルチカラムレイアウトに属す

https://www.yahoo.co.jp/

- ___フルスクリーン型レイアウト___
・ユーザーにインパクトを与えられる
・写真や動画を最大限活かしたい場合に利用

https://kourijima.info/

- ___グリッド型レイアウト___
・サイドメニューがあるため、いつでも目的のページを見れる
・マルチカラムレイアウトに属す

https://www.pinterest.jp/

## wireFrame作成 
今回は、個人でのWireFrame作成のため[Figma](https://www.figma.com/files/recent?fuid=1158305460454563738)
を利用する

https://notepm.jp/blog/6384

## まとめ
サイトマップを使って画面を洗い出した後に、作成ツールを使うと頭の中が整理されて、意外と簡単にできる…

見づらいや誤っている記載等あればコメント頂けると助かりますm(__)m


## 参考サイト
[なぜエンジニアが作る画面はダサいのか…?「理由」と「対策」を徹底解説【エンジニア向け画面デザイン講座】](https://qiita.com/mskmiki/items/544149987475719e417b
)
[ワイヤーフレームの作り方完全ガイド【サンプル付き】
](https://web-kanji.com/posts/making-wireframe)[ホームページレイアウトの基本！目的別の選び方をわかりやすく解説
](https://www.xserver.ne.jp/bizhp/homepage-layout/)
[【5分でわかる】ワイヤーフレームとは？概要やおすすめツールを簡単解説！](https://www.sejuku.net/blog/9176)
【備忘録】PyInstallerでexe化したときにハマった話

pyinstallerを使ってexe化したら以下のようなエラーがでた。  
pyinstallerの使い方はこちらから
https://camp.trainocate.co.jp/magazine/pyinstaller-python-exe/
```  
PS C:\Users\user\Desktop\chino> .\dist\chino0.exe
Traceback (most recent call last):
  File "chino0.py", line 6, in <module>
    import sklearn.datasets
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "sklearn\__init__.py", line 82, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "sklearn\base.py", line 17, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "sklearn\utils\__init__.py", line 26, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "sklearn\utils\_joblib.py", line 7, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "joblib\__init__.py", line 113, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "joblib\memory.py", line 32, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "joblib\_store_backends.py", line 15, in <module>
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "joblib\backports.py", line 22, in <module>
  File "_distutils_hack\__init__.py", line 88, in create_module
  File "importlib\__init__.py", line 126, in import_module
  File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module
  File "setuptools\__init__.py", line 10, in <module>
  File "_distutils_hack\__init__.py", line 88, in create_module
  File "importlib\__init__.py", line 126, in import_module
ModuleNotFoundError: No module named 'setuptools._distutils'
[10588] Failed to execute script 'chino0' due to unhandled exception!
```

PyInstallerとscikit-learnの問題かと思い、scikit-learnのバージョンを1.1.2 > 1.0.1 に変えてみたけど治らず。

モジュールの相性かも知れないと思ったので`pip list`で一覧を見てみたら
115もあったので特定ができない。
```
PS C:\Users\user\Desktop\chino> (pip list | Measure-Object).Count
115
```
なので大人しくvenvの環境立てて必要なpip installしていったらうまく行った。
https://camp.trainocate.co.jp/magazine/venv-python/

動いたときの`pip list`
```
Package                   Version
------------------------- ---------
altgraph                  0.17.3
future                    0.18.2
joblib                    1.2.0
numpy                     1.23.3
pefile                    2022.5.30
Pillow                    9.2.0
pip                       22.0.4
pyinstaller               5.4.1
pyinstaller-hooks-contrib 2022.10
pywin32-ctypes            0.2.0
scikit-learn              1.0.1
scipy                     1.9.1
setuptools                58.1.0
threadpoolctl             3.1.0
```

## まとめ
Pythonの開発は必ずvenvを使おう
【スクレイピング】Webサイト上の画像取得&保存（全自動化）


# Todo

[こちらのサイト](https://scraping-for-beginner.herokuapp.com/image)から全ての画像を取得し、保存する

## 前提
JupyterLabのインストールを行っておく（目安：5分）

https://qiita.com/rexid/items/41353e0f098ad063a3bd

## 実施
1. JupyterLabを起動
    ```terminal
    $ jupyter lab
    ```

2. コード作成

    ```py:全自動画像取得&保存.ipynb
    # import
    import requests
    from bs4 import BeautifulSoup
    from PIL import Image
    import io
    
    url = 'https://scraping-for-beginner.herokuapp.com/image'
    res = requests.get(url)
    
    soup = BeautifulSoup(res.text, 'html.parser')
    
    # 全てのimgタグを取得
    img_tags = soup.find_all('img')
    
    for i, img_tag in enumerate(img_tags):
    
        # 画像のURL = rootのURL + 画像のsrc
        root_url = 'https://scraping-for-beginner.herokuapp.com'
        img_url = root_url + img_tag['src']
    
        # 画像取得
        img = Image.open(io.BytesIO(requests.get(img_url).content))
        
        i += 1
        
        # 一桁の場合は十の位を0で埋める
        if i < 10:
            i = "{0:02d}".format(i)
    
        # 保存
        img.save(f'img/sample{i}.jpg')
    ```

3. 実行
    `command + Enter`

4. Webサイト上の画像がすべて保存されていることを確認
![スクリーンショット 2022-10-02 16.40.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/de5ce0c6-329d-5a55-e8aa-87034cd92914.png)

関連
---
- [【スクレイピング】データ抽出→CSVファイル作成（全自動化）](https://qiita.com/rexid/items/72b13b14a217d7cb1511)


参考
---
- https://www.youtube.com/watch?v=VRFfAeW30qE
- [【Python】数字を指定の桁数にフォーマット（0埋め）](https://deep-blog.jp/engineer/12248/)
【スクレイピング】データ抽出→CSVファイル作成（全自動化）

# Todo

- [こちらのサイト](https://scraping-for-beginner.herokuapp.com/ranking/)から観光地のランキングデータを抽出し、CSVファイルに書き込む

## 前提
JupyterLabのインストールを行っておく（目安：5分）

https://qiita.com/rexid/items/41353e0f098ad063a3bd


## 実施
1. JupyterLabを起動
    ```terminal
    $ jupyter lab
    ```

2. コード作成

    ```py:全自動ランキングデータ抽出.ipynb
    # import
    import requests
    from bs4 import BeautifulSoup
    import pandas as pd
    
    # ランキングサイト
    url = 'https://scraping-for-beginner.herokuapp.com/ranking/'
    res = requests.get(url)
    
    # html
    soup = BeautifulSoup(res.text, 'html.parser')
    
    #　全ての配列を格納する変数
    data = []
    
    # 10箇所分の観光地の情報
    spots = soup.find_all('div', attrs={'class': 'u_areaListRankingBox'})
    
    # 一つの観光地情報
    # spot = spots[0]
    
    # 観光地情報
    for spot in spots:
        # 観光地名
        spot_name = spot.find('div', attrs={'class': 'u_title'})
        # spanタグ削除
        spot_name.find('span', attrs={'class': 'badge'}).extract()
        # 置換で要らない文字列を消す
        spot_name = spot_name.text.replace('\n', '')
    
        # 評点
        score = spot.find('div', attrs={'class': 'u_rankBox'}).text.replace('\n', '')
        score = float(score)
        score
    
        # 項目
        categoryItems = spot.find('div', attrs={'class': 'u_categoryTipsItem'})
        # dlのみを取得
        categoryItems = categoryItems.find_all('dl')
    
        # for文
        datum = {}
        for categoryItem in categoryItems:
            category = categoryItem.dt.text
            rank = float(categoryItem.span.text) 
            datum[category] = rank
    
        # 観光地名と評点も加える
        datum['観光地名'] = spot_name
        datum['評点'] = score
    
        # dataに格納
        data.append(datum)
    
    df = pd.DataFrame(data)
    # 修正前カラム出力（順番修正用）
    # df.columns
    
    # 順番修正
    df = df[['観光地名', '評点', '楽しさ', '人混みの多さ', '景色', 'アクセス']]
    
    # csvファイルとして出力
    df.to_csv('観光地情報.csv', index=False)
    ```


3. 実行
    `command + Enter`

4.  CSVファイルが作成されていることを確認

![スクリーンショット 2022-10-02 16.21.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2689074/4c1dcd55-c194-a52c-901a-9f6ee6d33ca4.png)

---
関連：[【スクレイピング】Webサイト上の画像取得&保存（全自動化）](https://qiita.com/rexid/items/b055b0a393eec63c3b56)

参考：https://www.youtube.com/watch?v=VRFfAeW30qE
ただただC#でReactive Extensions(Rx)を使ってみる ~周期処理~

# はじめに
本記事はRx初学者の筆者がRxをただただ使ってみて学びや気づきをまとめたものです。
なお、本記事は[こちらの記事](https://qiita.com/tat_tt/items/bf963fe32d1210e47f5f)の続編の位置づけです。

# 周期処理を使ってみる
前回に引き続き、今回はRxを使って周期処理を実現してみます。
以下に例を示します。

# 周期処理で現在時刻を表示する時計を作成する例
以下のように1秒ごとに現在時刻を更新して表示する時計のようなサンプルを考えます。
![アプリケーション動作.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452292/1593256e-3066-b52e-2b84-981fcbc1fa77.gif)
このサンプルは、Rxを使って1秒間隔の周期処理を定義して、その周期処理の中でテキストブロックの内容を現在時刻に更新し続けることで実現しています。
具体的なMainWindow.xamlとコードビハインドのMainWindow.xaml.csは以下です。(サンプルとしての説明をしやすくするためにコードビハインドに記載をしています。MVVMに従った作り方になっていないためご承知ください。)
- MainWindow.xaml
```xml
<Window x:Class="RxTimerSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="75" Width="150"
        Loaded="MainWindow_OnLoaded">
    <Grid>
        <!-- 現在時刻を表現するテキストブロック -->
        <TextBlock x:Name="currentTimeTextBlock"/>
    </Grid>
</Window>
```
- MainWindow.xaml.cs
```csharp
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    #region コンストラクタ

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public MainWindow()
    {
        InitializeComponent();
    }

    #endregion

    #region イベントハンドラ

    /// <summary>
    /// ウィンドウロード時のイベントハンドラ
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        // 周期処理の登録後から周期の計測を始めるまでのインターバル
        // この例では即時で計測開始としている
        var dueTime = TimeSpan.FromSeconds(0);

        // 周期
        // ここで設定した周期の間隔で処理を実行する
        // この例では周期は1秒としている
        var period = TimeSpan.FromSeconds(1);

        // 周期処理の設定
        Observable.Timer(dueTime, period)
            .Subscribe(_ =>
            {
                // 毎周期で行う処理
                // 以下はxamlで定義したテキストブロックの表示内容をその時点での現在時刻に更新する
                Dispatcher.Invoke(() => currentTimeTextBlock.Text = DateTime.Now.ToString());
            });
    }

    #endregion

}
```
大事なポイントはMainWindow.xaml.csのMainWindow_OnLoadedメソッドの部分です。
Observable.Timerメソッドを使って、周期処理の設定をしています。周期の計測を始めるまでのインターバル(変数dueTime)と周期(変数period)を指定したうえで、Subscribeメソッド内で周期処理の実処理を登録します。
上記のコードの場合は、インターバルは0秒、周期は1秒、実処理ではMainWindow.xamlで定義したテキストブロックの表示内容を現在時刻に更新しています。
これによって1秒ごとにテキストブロックの内容が現在時刻に更新されるので、サンプルが実現できています。
上記のように手軽に周期処理が実現できる点が良い点だなと個人的に思いました。

# さいごに
今回はRxを使って周期処理を実現してみました。
手軽に周期処理を実現できる点が良い点だなと思いました。
Rxでできることはまだまだたくさんあるため、今後もRxを使って、理解した内容を技術記事としてアウトプットしていこうと思います。
焼きなまし法での評価関数の打ち切り

よくある焼きなまし法の擬似コードってこんな感じだと思います。評価値は小さい方が良いとします。

    for t in 1, ..., n:
        遷移先の評価値 ← 評価関数(遷移先)
        if exp((現在の評価値 - 遷移先の評価値) / 温度) ≧ random(0, 1):
            現在の状態 ← 遷移先の状態
            現在の評価値 ← 遷移先の評価値

ifの中身の式を変形します。log(random(0, 1))は負の値になることに注意してください。

    for t in 1, ..., n:
        遷移先の評価値 ← 評価関数(遷移先)
        if  遷移先の評価値 ≦ 現在の評価値 - 温度 * log(random(0, 1)):
            現在の状態 ← 遷移先の状態
            現在の評価値 ← 遷移先の評価値

右辺は遷移先に依存しないので先に計算しておきます。

    for t in 1, ..., n:
        閾値 ← 現在の評価値 - 温度 * log(random(0, 1))
        遷移先の評価値 ← 評価関数(遷移先)
        if 遷移先の評価値 ≦ 閾値:
            現在の状態 ← 遷移先の状態
            現在の評価値 ← 遷移先の評価値

この形に書き直すと評価関数より前に閾値を決められるので、評価値が閾値を超えることが分かったタイミングで評価関数を打ち切ることができます。
例：https://atcoder.jp/contests/future-contest-2019-qual/submissions/3600324

以上、焼きなまし法の説明でよく見る exp((e-e')/T) ≧ p って微妙だよね、という話でした。
jupyter上でのmoduleの使い方

## jupyter上でのModuleの使い方

### 一言で言うと

moduleの中でstructを定義しておけば、structに変更を加えてもjupyterのカーネルを再起動する手間が省けるという話です。

### 本題
juliaでstructを定義し、後から変更を加えたい場合、カーネルを再起動しなければならない。例えば、

```julia
struct Hoge
    x::Int
end
```

```julia
h = Hoge(3)
h.x # 3
```

これに後からyというものをstructのフィールドに加えようとし、セルを実行してみる。すると、カーネルを再起動しなければいけなく面倒である。

```julia
struct Hoge
    x::Int
    y::Int
end

# エラーが出る
```

ここで、以下のようにmodule化しておくと、sturctに変更を加えてもエラーが出ることはない。

```julia
module My

struct Hoge
    x::Int
end

end

using .My
Hoge = My.Hoge
h = Hoge(3)
h.x
```

変更を加えてみるとエラー自体は出ないことがわかる。

```julia
module My

struct Hoge
    x::Int
    y::Int
end

end

using .My
Hoge = My.Hoge
h = Hoge(3,4)
h.x
h.y
```

structを作り直すごとにMyモジュールを使って、Hogeを書き直している。今いるmoduleは、メインっていうモジュールにいて、MyモジュールにいるHogeをメインに持ってきている。この場合、エラーが出ることはない。

メインモジュールにいるstructを書き直すと、カーネル再起動しないといけない。
ABC271-C (シンプル)

https://atcoder.jp/contests/abc271/tasks/abc271_c

---

（要約）
$k$巻まで読むと仮定し、$k$巻以下で重複する本は売却します。
売らずに読む本を`s`冊とすると残りは`n-s`冊で、それらを全部売って$k$巻まで揃うかどうかをみればよいです。
（注意）
Julia 1.4です。知らなくても理解できるとは思います。

# 考察

- 2冊の本を売って1冊の本を買うと、本の総冊数は減少する。なのでなるべく売買しないほうがよい
（まず全部売ってしまってから考えるというアプローチは不可）
- $a_i$ の上限が大きい($10^9$)ので対策が必要だが、本の総冊数は最大で$3×10^5$なので解はこの値を超えることはない。
（上界を見積もる）
 
- 売るなら読まれる可能性が最も小さい巻、つまり最後の巻が優先
（貪欲法）

- 巻が重複している可能性がある
（コーナーケースというほどではないが。サンプルコードみて初めて気づいた）

# アプローチ

```:pseudocode
k = 0
while true
    k += 1
    if (k巻まで読める)
        continue
    else
        print(k-1)
        exit
    endif
end
print(k)
```

で、$k$巻まで読めるかどうか。

$k$巻まで読めるかどうかの判定は、

1. 最初に持っている本のうち、1巻から$k$巻までは2冊以上持っていれば1冊を残して売る … $O(k)$、全探索なら改良できる
1. $k+1$巻よりあとは全部売る … $O(N)$、累積和つかえば改良できる
1. 売った本で不足している本が買えればOK … 不足している冊数と売れる冊数が分かれば、$O(1)$。

これを$k = 1$から$N$までについて検討すればOK。
ただし愚直に検討すると1回の検討に$O(N)$かかるので全部で$O(N^2)$で`TLE`。

# 計算時間短縮

## kについて二分探索

公式解説の2番目の要領です。

https://atcoder.jp/contests/abc271/editorial/4937

コードはシンプルですが、結構高度なことをやっています。
C++の人が実装するなら、「$k$巻より前で重複のため売れる冊数」と「$k+1$巻以上の冊数」を累積和で管理することになるでしょうか。

$O(NlogN)$。

## kについて工夫しながら全探索

愚直にやると上記のように$O(N^2)$ですが、$k$を1つずつ増やすので工夫の余地はありそうです。
色々なアプローチがありますが、以下の方法が圧倒的にシンプルなので採用しました↓


$k$巻以下で売らずに読む本を`s`冊とします。`s`の更新は$O(1)$でできます。
残りは`n-s`冊で、それらを全部売って$k$巻まで揃えばよいです。

## ACコード

本番の際のACコードです。(コメントはあとで付加)

```c.jl
function solver()
    n = toI()
    a = toVI()
    v = zeros(Int,300000) # v[i]は第i巻を何冊持っているかを表す
    for ai in a           # ai > 300000 は使用しないので無視してよい
        ai > 300000 && continue
        v[ai] += 1
    end

    s = 0                # 売らずに読むことのできることのできる冊数
    for i in 1:300000    # 第i-1巻まで読むことが可能なとき、第i巻を読むことができるか
        if v[i] ≥ 1      # 1冊以上あれば売らずに読むことができる
            s += 1
        end
        r = n - s        # i巻までのみ読むと仮定すると、s冊以外は全部売ることができる
        if s + r÷2 < i   # r冊売ってr÷2冊買って合計冊数がi冊に満たなければi巻までは読めないので打ち切り
            println(i-1)
            return
        end
    end
    println(300000)      # 打ち切られずにここまでくれば上界
end

toI(x=readline()) = parse(Int,x)
toVI() = [toI(x) for x ∈ split(readline())]

solver()
```

`Datastructures.jl`の`counter`でもっと短いコードにできます。
内部で`unordered_map`に相当するものを使用しているので速度は劣ります。

```c_counter.jl
using DataStructures

function solver()
    n = toI()
    v = toVI() |> counter

    s = 0
    i = 0
    while true
        i += 1
        if v[i] ≥ 1
            s += 1
        end
        r = n - s
        if s + r÷2 < i
            println(i-1)
            return
        end
    end
end

toI(x=readline()) = parse(Int,x)
toVI() = [toI(x) for x ∈ split(readline())]

solver()
```

JuliaはJITなのでコンパイル時間の分だけ不利ですが、1.4から1.8ではかなり改善しています。次の言語アップデートが待ち遠しいです。
サクラエディタのショートカットキー

# はじめに
こんにちは。私は金融系の企業に勤める文系エンジニアです。
職場でサクラエディタを使用する場面が多くあり
自分の備忘録としてサクラエディタのショートカットキーを簡単にまとめます。

# サクラエディタとは？
サクラエディタは日本製のWindows向けテキストエディタで、メモ帳のようなものです。
しかし、メモ帳よりも断然見やすく作業もしやすいので、メモ帳の進化版と考えてもらえればよいです。

# サクラエディタのショートカットキー
よく使いそうなものをピックアップして記載しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671519/2c207473-f87e-1f71-881b-6f4c1284b6e2.png)

# 最後に
今回は私が業務の中で使う場面が多いもの、使う場面がありそうなものに焦点を当てて、まとめさせていただきました。
他にも多くのショートカットキーがあり、皆様それぞれの用途に合わせて使っていただければよいのではないかと思います。
エンジニアのリモート終焉のお知らせ

## リモート率が下がってきている気がする

「Flamevalue」はフレームワークや言語ごとに求人数や給与によってスコアリングするサービスです。

https://flamevalue.short-tips.info/

つい1月前（2022年8月末日にリリース）し、今でも少しづつサービスの改善、改良を行っております。

おかげさまでアクセス数やイベント数も好調...ではないですが、細々とサービスを運営しております。

サービスの運営をしていると当然ながらそのサービスを最も目にするのが私になるわけですが、
**最近ある変化に気が付きました。**

各言語、フレームワークのパラメーターの左上の項目の数値がだんだんと下がって来ているのです...！


一月前にはこんなに張りがあったグラフも

<a src="https://flamevalue.short-tips.info/">
<img src="https://camo.qiitausercontent.com/7f9f2bea50700ee0e6bd10c83a63a80affa598e3/68747470733a2f2f6769746875622e636f6d2f6b61776164617361746f7368692f6d696e6567697368697265692f626c6f622f6d61696e2f666c616d6576616c75652f666c616d6576616c75652e706e673f7261773d74727565">
</a>


今では見る影もない...

<a src="https://flamevalue.short-tips.info/">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1678228/fdc5a3b5-bd55-7adb-996c-79cbf1921a33.png">
</a>


偶然かな？とか思いつつもデータの更新をかけるたびに、**左上のパラメーターの項目が少しづつ内側に入っていくのです...**

これが特定の言語/フレームワークに限らず、全ての言語/フレームワークで発生しているように感じました。

俺たちの楽園が...

<img width="30%" src="https://assets.st-note.com/production/uploads/images/53904906/picture_pc_656519b1181a7829422554cd61f2a066.png?width=2000&height=2000&fit=bounds&quality=85">


## 嘘ではなかったリモートワークの終焉

こちらの記事ではグーグルのスマートフォンの位置情報を分析した結果、**リモートワーク率は21%に及んでいたところが、12.9%まで減少した**とのことです。

「縮小するリモートワーク。緊急事態宣言時の経験で見切りをつけるな」

> グーグルのスマートフォン利用者の位置情報からの分析によると、日本の4月の出勤者はコロナ前（1月から2月上旬の中央値）に比べて21.9％減少。新型コロナウイルスの感染拡大、4月7日の政府の緊急事態宣言を受けて、一気にリモートワークが拡大した。（7月5日日本経済新聞朝刊）

> かし、5月25日に緊急事態宣言が解除されると、リモートワークは一転縮小に向かう。グーグルの分析によると5月にはコロナ前比で21.9％減少していた出勤者の数は6月には12.9％減にまで縮小幅が減少。

https://www.nri.com/jp/keyword/proposal/20200713


ここまで書いてきてハッとしましたが、リモートワークが減少するのはエンジニアだけじゃないですね。

すべての職種で発生している事象のようです。


## リモートワークはなぜ無くなるのか？

ここまで話を進めてきてなんですが、自分はリモートワークなんてしたことないです。

ただ次の会社ではフルリモートが前提となってますので、おそらく出社に切り替わることはないと思われます。

結婚などのライフイベントも予定しているので、次の会社ではリモート前提で転職活動していたのでそれがなくなると正直家庭との両立が厳しい...。

ではなぜリモートワークが無くなるのか？

答えは単純:**上がそう決めたから**

<img src="https://soken.xymax.co.jp/wp-content/uploads/2017/04/1704-workstyle_reform_and_diversified_officespace_fig3-2.png">

参考：https://soken.xymax.co.jp/2017/04/13/1704-workstyle_reform_and_diversified_officespace/

こちらは「働き方の変化へ取組むきっかけ」を調査した際のアンケート結果です。

## リモートワークを続けたい場合はどうすればいいか？

これも単純です。**転職しかないです。**

そもそもリモートワークが始まる原因が「経営層の判断」であれば、リモートが終わってしまう理由も「経営層の判断」と言うことになります。

この経営層を同じ会社にいながら説得するという労力は並ではなく、どう見積もったって会社ごと変えて自分にとっての経営層を変える方がコストパフォーマンスが良いです。

そもそも「転職した方が年収が上がる」と言う状況は「ITという流れの早い業種で、自分の会社が他の会社に遅れをとっている」と考えるには十分だと思います。

また、転職活動の中で「一つの会社にこだわっていないで積極的に自社と他社の比較を行うことができる」というのも転職活動のメリットのような気がします。

つまり何が言いたいかというと、**合理的な理由がなくいきなりリモートをやめる判断をする会社に納得できない場合、まずは他社の調査を行うのも含めて転職活動するのが良いのではないでしょうか**ということです。




## 備考

title:エンジニアのリモート率が下がってきている
Edge ブラウザアンインストール方法

コマンドでインストールフォルダに入る
cd %PROGRAMFILES(X86)%\Microsoft\Edge\Application\

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687031/c1059cf6-c8da-562d-2b59-e0b4c783ae14.png)

アンインストールバッジョを確認し、コマンドでディレクトリに入る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687031/0e2f9bc9-bad5-90c9-dc1a-9fff063a4338.png)

Installerに入ってから、コマンドでアンインストールする

setup.exe --uninstall --system-level --verbose-logging --force-uninstall
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687031/281a0666-85c5-6c2a-b41f-3f4b15936316.png)
KerasCV を使って 2行で StableDiffusion を使う

すごく些末な内容なのですが、便利なのにまだ投稿されていなかったので記事を書きます。 

https://twitter.com/TensorFlow/status/1575213761421623303?s=20&t=t4fsZuaHVjVF5DTOaohqVQ

こちらのツイートで共有されている通り、すごく簡単に使えるようになったよ！という話ですね。keras 版 StableDiffusion のモデルが huggingface に上げられていて、それを使う仕組みになっているようです。

以下のコードを実行することで簡単に StableDiffusion を扱えます。import 文や画像を表示する部分のコードを除けば 2行なので許してほしい...

```Python
import cv2
from keras_cv.models import StableDiffusion
from matplotlib import pyplot as plt
from PIL import Image

model = StableDiffusion(img_height=512, img_width=512, jit_compile=True)
img = model.text_to_image(
    prompt="A beautiful horse running through a field",
    batch_size=1,  # How many images to generate at once
    num_steps=100,  # Number of iterations (controls image quality)
    seed=123,  # Set this to always get the same image from the same prompt
)
Image.fromarray(img[0]).save("horse.png")

img2 = cv2.imread("house.png")
src = cv2.cvtColor(img2,cv2.COLOR_BGR2RGB)
plt.imshow(src)
plt.axis("off")
plt.show()
```

以下は実行する際の注意点です。

- prompt の最大長は 77 token となっています。(refs. https://tech.isid.co.jp/entry/2022/09/27/Stable_Diffusion入門-長い呪文は切り捨てられる)
- num_steps 100 は CPU だと 1時間くらいかかるのでご注意ください。(colaboratory で確認しました)。GPU だと2分くらいです。
- 現時点(2022/10)での colaboratory は tensorflow 2.8 で、この機能を使うにはバージョンが足りないので (2.9以上から)、 `!pip install tensorflow keras-cv -U` を実行してからやってみてください。
- CPUで実行する際は何もエラーは出ませんが、GPUに変更した際、`Original error: UNIMPLEMENTED: DNN library is not found.` と怒られるかもしれません。 cudnn 絡みの問題で、 `!apt install --allow-change-held-packages libcudnn8=8.1.0.77-1+cuda11.2` を実行してランタイムを再起動すると動くようになると思います。
  - refs. https://stackoverflow.com/questions/71000120/colab-0-unimplemented-dnn-library-is-not-found
- 画像を表示する際、 opencv では BGR で画像が扱われているため、RGB に変換する必要があります


それでは 好きな prompt を実験してみた様子を貼ってこの記事の締めくくりとします。

`the living room of a cozy wooden house with a fireplace, at night, interior design, d & d concept art, d & d wallpaper, warm, digital art. art by james gurney and larry elmore.`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109201/e49ded41-d911-a5b7-a5e1-b7a5565c6117.png)

`city made out of glass : : close shot : : 3 5 mm, realism, octane render, 8 k, exploration, cinematic, trending on artstation, realistic, 3 5 mm camera, unreal engine, hyper detailed, photo – realistic maximum detail.`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109201/e8c6d47a-b9b8-9d09-b5b9-73b5c4b2a898.png)


`An expressive oil painting of a tennis player smashing, depicted as an explosion of a nebula`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109201/2e5cb59c-ccf4-adb4-ab3e-5eb92b4cb791.png)

どれも大体いい感じですね。これを使って prompt を自動で集めてひたすら画像を生成し、自宅のデジタルフォトフレームに延々流したらすごく生活が豊かになりそう。そんな GPU 持っていたらもっと別のことに使うべきな気がしますが...