OmniAICreator/Qiita-1.07M huggingface dataset:
Tailwind CSSを初めて触った

# 背景
&emsp;今までの開発はBootstrapを用いて装飾やUIを開発していたため拡張性の高いといわれてるTailwind CSSを触りたいと思った。またこれからの開発に使いたいため。
# 目次
1. Tailwind CSSとは
1. 前提(環境)
1. フォントの大きさ
1. フォントの太さ
1. フォントの色設定
1. ボタン作成
1. 疑似クラスの設定(hover, focus)
1. Transition、Transformの設定
1. Groupの設定
1. まとめと感想
# 1. Tailwind CSSとは
&emsp;Tailwind CSSとは**utility class**を活用したCSSフレームワークである。
Bootstrapなどでは**事前に準備**されたボタンやメニュー、パンくずリストなどのコンポーネントを活用してデザインしていく。
Tailwind CSSはコンポーネントは準備されておらずutility classを使って**独自**のボタンなどを作って使う。そのため**拡張性は高い**。
# 2. 前提
&emsp;今回は簡単に触りたかったのでCDNを用いてHTMLファイルに直書きして使用。
# 3. フォントの大きさ
&emsp;フォントの大きさは以下のように定義してフォントの大きさを変える。
- **text-{大きさ}**
(例): text-xs (font-size:.75rem;), text-base, text-xl, ...
# 4. フォントの太さ
&emsp;フォントの太さも大きさ同様。
- **font-{太さ}**
(例): font-thin (font-weight:100;), font-extralight, font-medium, font-normal, ...
# 5. フォントの色の設定
&emsp;フォントの色の変更は以下の通り。
- **text-{色}-{色の濃さ}**
(例): text-green-100 (color: #f0fff4;), text-green-200, text-red-300, text-blue-500, ...
# 6. ボタンの作成
&emsp;py-2やpx-4でパディングして余白を作ることやボタンテキストのカラーを白にしたり、roundedで角を丸くするなどしてボタンを作る。
```diff_html
<button class="bg-indigo-700 font-semibold text-white py-2 px-4 rounded">ボタン</button>
```
# 7. 疑似クラスの設定 (hover, focus)
&emsp;**hoverやfocusを通してutility classを設定できる**。
# 8. Transition、Transformの設定
&emsp;hoverなどと合わせてdurationやtransformを設定することでutility classに動的な動きを付けられる。
# 9. Groupの設定
&emsp;Groupを設定すること親要素へのアクションによって子要素へアクションを付けることができる。
例としてhoverを用いて親要素にカーソルが乗ると子要素がそれぞれ違う色へと変化する。
```diff_html
<div class="group m-10 p-10 border hover:bg-gray-100">
  <p class="font-black group-hover:text-red-900">New Project</p>
  <p class="font-black group-hover:text-blue-900">Next Project</p>
</div>
```
# 10. まとめと感想
&emsp;初めてTailwind CSSを少し触れ、Bootstrapと比較したところ自分的には**Bootstrapのほうが楽で早く**UI作れるという感じ。しかし**Tailwind CSSは拡張性が高い分**、自身がどれだけ工夫するかによって**よりユニークなUIができそう**。またいろいろな**サンプルのデザインを組み込みやすい**。<br />
&emsp;次はnpmでインストールして環境構築して使いたい。また自身でカラーや幅など簡単な部分のカスタマイズをしてみたい。

# 参考文献
- https://reffect.co.jp/html/tailwindcss-for-beginners#i
awkで複雑な条件のテキスト抽出をする

### やりたいこと
次のようなテキストから目的の行だけを取り出したい

``` input.txt
other-line 
second-pattern
second-pattern
first-pattern     <--- 1.first-pattern が最初に現れて
other-line
other-line
other-line
second-pattern    <---- 2.次の最初の second-patternが現れてから
target-line1　　　　　　　　　　　　＊目的の行
target-line2　　　　　　　　　　　　＊目的の行
target-line3　　　　　　　　　　　　＊目的の行
end-pattern       <--- 3.end-pattern が現れるまでの行
other-line
first-pattern
other-line
first-pattern
```

### コマンドと結果の例
``` bash
1.目的の行だけを取り出す場合
awk "\!f&&/first-pattern/{f=1} f==2&&/end-pattern/{exit} f==2{print} f==1&&/second-pattern/{f=2}"  input.txt
target-line1　　　　　　　　　　　　＊目的の行
target-line2　　　　　　　　　　　　＊目的の行
target-line3　　　　　　　　　　　　＊目的の行
```

``` bash
2.目的の行とsecond-pattern,end-patternの行を含める場合
awk "\!f&&/first-pattern/{f=1} f==1&&/second-pattern/{f=2} f==2{print} f==2&&/end-pattern/{exit}"  input.txt
second-pattern    <---- 2.次の最初の second-patternが現れてから
target-line1　　　　　　　　　　　　＊目的の行
target-line2　　　　　　　　　　　　＊目的の行
target-line3　　　　　　　　　　　　＊目的の行
end-pattern       <--- 3.end-pattern が現れるまでの行
```

### 意味
* fを状態変数として使い、f==2のときに出力している
* !f&&/first-pattern/{f=1}
変数fが0、かつ、「first-pattern」が出現したら、変数fに1を代入（あらゆる変数の初期値は全て0）
* f==2&&/end-pattern/{exit}
変数fが2、かつ、「end-pattern」が出現したら、終了
* f==2{print}
変数fが2の場合、その行を出力
* f==1&&/second-pattern/{f=2}
変数fが1、かつ、「second-pattern」が出現したら、変数fに2を代入

### 検証環境
``` 
% sw_vers
ProductName:	macOS
ProductVersion:	12.6.3
BuildVersion:	21G419

% awk --version
awk version 20200816
```
Swift で全音階を基音からの音程を指定して演奏する方法

１オクターブは半音１２個で構成されている。
ドを基音としてレを出したい場合に２を与えるとそれが達成できるようにしたい。

```
static func hight(_ num : Float) -> Float {
        let base : Float = 440.0 // ピアノでいう真ん中のラの周波数
        let min: Float = -24 // そこから ２オクターブ下を基音とする
        return base * pow(pow(2, num + min), 1/12)
    }
```

１オクターブ上がると周波数が２倍になることを利用して計算。
底が２の対数で何オクターブ上がるかが計算できる。したがってその逆を行うと1/12オクターブを半音として扱うことができる。
NuitkaでPythonをexe化しよう

# はじめに
Pythonのexe化はなかなか悩ましい。
Nuitkaを使用することでそこそこ使えそうなexeファイルをゲットできました。

他にも有名所でPyInstaller, cx_Freezeとかがある。らしい。

# 完成イメージ
今回作成したアプリケーションは下記のようなもので、
画像ファイルを入力すると.icoファイルを作成してくれるものになっています。

容量は26,000kBくらい。このexeのみをコピペすればスタンドアロン使用できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/9835c861-30f3-82ce-9047-988e40ea0405.png)

仮想環境を使用したら9,700kBくらいまで小さくなりました。仮想環境は正義。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/869c99cd-6dde-d97e-4e2b-dd4d2c26cb6e.png)

開くとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/f092223a-1b24-150d-3f5d-cafc03f44957.png)

コード内で呼び出しているライブラリは次のとおり
```python
import tkinter as tk
from tkinter import filedialog
from PIL import Image
from os.path import splitext
```

# インストール
とりあえずnuitkaをインストール。
```
pip install nuitka
```

# 使い方
カレントディレクトリをPythonファイルのある場所にする。
```
cd フルパス
```

基本これを打てばexe化ができる。
```
nuitka ファイル名.py
```
が、これだけでは結局Python環境がないと動かないらしい。それを回避するために色々なオプションがある。

# オプション
基本は上の通りで使用できますが、個人的な好みで以下のオプションを使用しました。
| オプション | 意味 |
|:-|:-|
|```--windows-disable-console```|黒い画面を出さない|
|```--standalone```|Python環境がないところでも動くようにする|
|```--onefile```|ひとつのexeファイルにまとめる|
|```--enable-plugin=tk-inter```|Tkinterをつかうおまじない|
|```--windows-icon-from-ico="*.ico”```|*.icoファイルをアイコンとして使用|
```
nuitka --windows-disable-console --standalone --onefile --enable-plugin=tk-inter --windows-icon-from-ico=“アイコンファイル.ico” ファイル名.py
```

# その他
初回実行時（？）は色々とNuitkaから聞かれることがあるので、Yesと回答しておきましょう。
【Linux】ファイルの特定行を取得する方法

## 1行目のみ取得する

ファイルの1行目のみ取得するには以下のように実行します。

```zsh
head -n 1 対象ファイルパス
```

## 指定した行のみ取得する

指定した行のみ取得するには以下のようにします。

```zsh
sed -n 行数p 対象ファイルパス
```

`./sample.txt`の5行目を取得する場合には以下のように実行します。

```zsh
sed -n 5p ./sample.txt
```

## 指定した行以降を取得する

指定した行以降を取得するには以下のようにします。

```zsh
sed -n '開始行,$p' 対象ファイル
```

`./sample.txt`の5行目以降を取得するためには以下のように実行します。

```zsh
sed -n '5,$p' ./sample.txt
```
【AWS】EC2について(自分用メモ)

# EC2とは
クラウド上に仮想サーバーを構築出来るサービスです。
物理的な機器を必要としない為、お手軽にサーバーを構築出来ます。

EC2ではサーバーを、`インスタンス`と表現しています。

このEC2に関連した用語について、サクッと見返せるようにメモしておきます。

| 名前 | 説明 |
|---|---|
|インスタンスタイプ|インスタンスのCPUやメモリ等のリソースが設定されている項目。サーバを利用する際には`インスタンスタイプ`を指定する必要がある。(`t2.micro`等が存在する。)|
|AMI|インスタンスのOS・MW等が事前に設定してあるテンプレート。こちらも`インスタンスタイプ`同様にサーバーを利用する際には設定が必要となる。|
|セキュリティグループ|インスタンスにおいて、ファイヤーウォールの役割を担っている。`プロトコル`と`ポート番号`で通信の許可を行う。|
|インスタンスプロファイル|IAMロールをEC2インスタンスに渡してくれるもの|
Docker起動時に文字列置換を行うShellを実行したい

## はじめに
AngularなどのSPAで利用する静的コンテンツに対し、アプリケーション起動前に特定文字列をサーバー環境変数で置換した上で、アプリケーションを起動したいという要件が出てきました。

今回はその実装例についてまとめます。
なお、今回はDockerとShellに特化し、SPAソースについては特に記載していません。

---
## 機能要件
- docker-composeを利用する
- コンテナイメージはhttpd(Apache)を利用する
- 環境変数ファイルを用意し、docker-composeで環境変数として読み込む
- コンテナ起動時にShellを実行する
- カレントディレクトリ配下のファイル（今回は*.js)を再帰的に確認し、文字列置換する
- 置換文字列は環境変数から読み込む

---
## ソースコード
作成したソースコードは下記の通り。
- Dokerfile
- run_init.sh
- docker-compose.yml

---
### Dokerfile
```dockerfile:Dokerfile
#################################################
# コンテナの作成
#################################################
# ベースイメージ取得
FROM httpd
# ライブラリインストール
RUN apt-get update && apt-get install -y curl
# shellのコピー
COPY ./shell/run_init.sh /usr/local/apache2/htdocs/run_init.sh
# shellの実行
CMD ["/bin/sh", "/usr/local/apache2/htdocs/run_init.sh"]
```

---
### run_init.sh
```bash:run_init.sh
#!/bin/sh
#-----------------------------------------------------------
# Execute init process
#-----------------------------------------------------------
# STRING 変数が定義されていることを確認
if [ -z "$STRING" ]; then
  echo "STRING 環境変数が定義されていません。"
  exit 1
fi

# find コマンドを使用して .js ファイルを検索し、sed コマンドで置換を実行
find . -name '*.js*' -exec sed -i "s/<your_string>/$STRING/g" {} +

# クライアントアプリケーションの起動
exec apachectl -DFOREGROUND

#コンテナを起動し続ける
tail -f /dev/null
```
---
### docker-compose.yml
```yaml:docker-compose.yml
# コンテナ構築用docker-composeファイル
version: '3.2'

services:
  # アプリケーション用定義
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    container_name: app
    ports:
      - "8080:8080"
    # 環境変数をファイルで指定
    env_file:
      - "./env/app.env"
    #自動起動設定
    restart: always
    tty: true

```

## GitHub
GitHubにも同様のソースを公開しています。

https://github.com/ferret000/docker-replace-string
SAC Analytics Designer 開発者手引き翻訳 (DeveloperHandbookSACAnalyticsDesigner)　②-1 SAC Analytics Designer 事前条件

# SAC Analytics Designer を始める事前条件とは？
(参照元：https://liuat.com/archived/DeveloperHandbookSACAnalyticsDesigner.pdf )
##  Analytics designer
開発者がアプリケーション作成時、SAP Analytics Cloud のウィジェットを利用できる開発環境。スクリプト機能（コーディング）により、異なるウィジェット間の関係をコーディング実装できる

Analytics Designer とストーリーは多くの共通点がある
•SAP Analytics Cloud に統合されている
• Analytics designer とストーリーはデータコネクティビティとインターフェース構造が共有されている
• サービスを通じ、ユーザーが感じる使いやすさ：ユーザーエクスペリエンスを提供する
• SAP Analytics Cloudのライフサイクルマネジメントを継承している

## 事前条件

### アクセス条件
- すべてのアクセス権限にはアプリケーション実行権限があり、開発の為にはCRUDアクセスが必要（Create, Read, Update and Delete）で、開発者権限か全権限を設定されている必要がある。
- アプリケーションへのアクセス設定はフォルダ保存場所による。例えば、パブリックフォルダにアプリケーションが保存されたら、すべてのユーザーがデフォルトでアクセスすることができる。

**アクセス条件の種類**
- Read access:　ユーザーがランタイムで、アプリケーション実行するために必要
- Full access: 開発者はCRUDアクセスが必要（Create, Read, Update and Delete）で 開発者権限か全権限に含まれる
 
（ランタイム：アプリケーションの開発・実行の両方の機能を備えたソフトウェアから、開発の機能を省き、実効の機能のみを取り出したプログラムのこと　参照：IT用語辞典バイナリ）

## 必要なライセンス
全てのSAP Analytics Cloud ライセンスにはアプリケーション作成と実行機能が含まれており、計画業務アプリケーションのみ以下を留意する必要がある

•計画モデルにアクセスして読み込む機能のみが必要な場合は、SAP Analytics Cloud for business intelligenceライセンスが必要
• 全計画業務機能を使用したい場合は、SAP Analytics Cloud for planning, standard editionが必要
• 計画業務アプリケーションに計画モデルをアップデートする必要がある場合は、SAP Analytics Cloud for planning, professional edition が必要

## モード
3種類のモードが存在

• Edit mode
CRUD アクセスが必要で、アプリケーション編集が可能になる
• Present mode、View mode
ランタイムモードで、アプリケーション実行する.


## デザイン要素　Designing Elements
Analytics applicationsではデザインタイムとランタイムで厳格な違いがあり、エンドユーザーはランタイムでしかアクセスや操作ができないが、開発者（キーユーザー）デザインタイム要素を使用しアプリケーション作成することができる。

以下、使用可能なデザイン要素となる
### ①Canvas
アプリケーションは必つのキャンバスを持り、データを配置する場所になる。
### ウィジェットとフィルター　Widgets and Filters
Analytics Designerのウィジェットはキャンバスに配置されユーザが見ることができるユーザインタフェースである
Analytics アプリケーションはページを持たず、その為以下ストーリーコンセプトは利用できない。
- ①cascading story 
- ②page
- ③widget filters
- ④input controls 

代わりに、フィルターのウィジェットを追加する必要がある. フィルターウィジェットはストーリーフィルタと似た機能でキャンバスに配置できる.d chapter.

### データソースとモデル　Data Sources and Models
SAP Analytics Cloudでテーブルウィジェットとチャートはデータバインディングされているため、データを持っている（同じモデルに接続される場合も同様）
Z80エミュレータの製作(1)

### エミュレータを作る！
昔からの夢でエミュレータは作ってみたいと思っていました。
でもエミュレータを作るにはそのハード（CPUや周辺機器など）を事細かく知っていなければなりません。
ハードルは高いのですが、憧れは止まりません。

普段MSXPENを使いまくっていますが、JavaScriptでも実用的な速度になるのでへっぽこなプログラム技術でもなんとかなるのではと思ってしまいました。

前置きはさておき、とりあえずCPUだけでもエミュレーションしてみることにします。
完成した暁にはいろいろな実装実験してみたいと思います。

### プログラム

作成環境はwindows10上のubuntuのgccが使いやすいのでコマンドラインでコンパイルしています。

ソースコードは<a href="https://github.com/kazuki-ryo/z80cpu_emulater/blob/main/README.md">github</a>に上げましたのでこちらを参照。

まだ未完成ですので色々問題があります。（汗）

### 速度はどれくらいでるのか？

自作エミュレータのパフォーマンスは気になるものです。
そこで簡単なテストを行って環境ごとに比較してみました。

まずmsxpen上でZ80とR800で動かして実機相当の速度を計測します。
PC上でエミュレータの速度を計測します。
PCはsurface go(1.6GHz)です。
それと本命のRaspberry pi picoで動作させます。

MSXPenで実行するソースは以下の通り。
```
org 0c000h
LD DE,10
LOOP1:
LD BC,0
LOOP2:
DEC BC
LD A,B
OR C
JP NZ,LOOP2
DEC DE
LD A,D
OR E
JP NZ,LOOP1
RET
```

msxpenのBASICコードは以下を記載して実行する。
```
10 clear200,&hbfff
20 bload"program.bin"
30 defusr=&hc000
35 time=0
40  a=usr(0):t=time
50 print t/60
```

それぞれ環境をMSX2+とturboRに切り替えて実行しました。

### 実行結果

DEレジスタとBCレジスタの値でループ回数を指定します。
今回は655360回ループで時間を計測しました。

|No.|環境|実行時間[sec]|Z80比率|Z80換算クロック|
|:--|:--|:--|:--|:--|
|1|MSXPEN MSX2+（比較用)|5.6|-|3.58MHz|
|2|MSXPEN turboR（比較用) |0.86|6.6倍|23.64MHz|
|3|RPI pico(125MHz)|4.1|1.38倍|4.95MHz|
|4|RPI pico(170MHz)|3.0|1.89倍|6.77MHz|
|5|Ubuntu(1.6GHz) |0.0925|60.54倍|216.73MHz|

Raspberry pi picは標準クロック125MHzとオーバークロック170MHzで計測しました。
PCが一番速いとして、picoはクロック数の割にはスコアが伸びていません。
原因が分かりませんが、メモリが遅いのでしょうか？
CPUはキャッシュメモリがないし・・・。

エミュレータの完成度が上がったらまたテストしてみます。
投稿ページを作成する #2

# 目的

https://qiita.com/kanerin1004/items/c6141b5ab02f5b307b68

これの続き
投稿した値をテーブルに追加できるようにします。

# 今回やること

今回の目標は以下の2つ。
* アクションの設定
* 遷移リンクを記載する
* 詳細画面を作る


# 環境
* windows 10
* ruby 3.0.4
* rails 6
* Bootstrap 5.0.2


# いざ出陣

## アクションの設定
以下のようにアクションを設定します。
```ruby:app\controllers\communities_controller.rb
class CommunitiesController < ApplicationController
  def index
  end
  
  def new
    @community = Community.new
  end
  
  # 以下を追加
  def create
    community = Community.new(community_params)
    if community.save
      redirect_to :action => 'show', :id => community.id
    else
      redirect_to :action => "new"
    end
  end

  def show
    @community = Community.find(params[:id])
  end

  private
  def community_params
    params.require(:community).permit(:eventname)
  end
  # ここまで

end
```

投稿を押すと、 `create` に飛んで、 `save` が成功したらその詳細画面へ、失敗したらもう一度作成画面に飛びます。
詳細画面にはidが必要なので、 `:id => community.id` で投稿されたレコードのIDを取得しています。
他はまぁ、見たまんまです。オブジェクトがどうとか細かいことは分かりません。

## 詳細画面の作成
投稿した後に詳細画面へ飛ぶため、詳細画面を作成します。
app → views → communities に `show.html.erb` を作成し、以下のように書きます
```html:app\views\communities\show.html.erb
<div class="container">
  <p><%= @community.eventname %></p>
  <p><%= @community.created_at %></p>
</div>

<%= link_to "マイページに戻る", users_path %>
```
これは、上のアクションで設定した `show` で `@community = Community.find(params[:id])` としているので、 `@community.eventname` で投稿内容、 `@community.created_at` で投稿時間を表示できます。

#### ・投稿画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/4ef9deb0-36ba-96b6-aaa3-6ad53fcccaca.png)

#### 「作成する」押下後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/580d60eb-cb6a-e4d0-cb63-5dde8e00b001.png)



遷移ばっちり✨


# 余談
画面をBootstrapできれいにするのは後でしようと思ったのだけど、
よく考えたらせっかく class の指定できれいになるっていうのにもったいないね。

 `private` がどの程度ばれちゃいけないものなのか分かんない。
たとえば、このサイトをリリースしたら見られない方が良いものなんでしょうか...

次から省略しよ。
Angular 

### Node.js
* Node.js（ノード・ジェイエス）は、JavaScriptを使ったサーバーサイドの実行環境です。通常、JavaScriptはクライアントサイドの処理に使用されますが、Node.jsを使用することで、JavaScriptをサーバーサイドのアプリケーションで実行することができます。

Node.jsは、高速でスケーラブルなネットワークアプリケーションを作成するためのプラットフォームとして広く使用されています。また、Node.jsは、npmと呼ばれるパッケージマネージャーを使用して、サードパーティのパッケージやライブラリを簡単にインストールすることができます。これにより、開発者は素早くアプリケーションを構築することができます。
【Unity】シーン上やプレハブの RaycastTarget を一括でいい感じに無効にするEditor拡張

# 概要

uGUI で利用する Image や Text 等の RaycastTarget が有効になっていると、少し処理負荷が高くなります。

https://shibuya24.info/entry/raycasttarget_heavy

それを知らずに途中まで作ったプロジェクトから RaycastTarget を一つずつ見直すのは大変です。
そこで、シーン上やプレハブの RaycastTarget を一括でいい感じに無効にするEditor拡張を作りました。
ただし、Button の targetGraphic に指定されていたり、EventTrigger を持っていたりするとUIが反応しなくなるので、そのような Graphic は無視します。

### 無視する条件

- Button や Toggle といった Selectable の targetGraphic に指定されている
- EventTrigger を持っている
- ScrollRect を持っている
- Scrollbar を持っているか、Scrollbar の handleRect に指定されている
- Slider の fillRect か handleRect に指定されている

GetGraphics() を編集すれば、追加の条件も簡単に加えられます。

# コード

Editor フォルダに追加してご利用ください。

https://github.com/yamara-mh/CodeStorage/blob/main/Codes/Editor/RaycastTargetDisabler

# 使い方

Hierarchy か Project ウィンドウのプルダウンメニューから「Disable RaycastTarget」を選択して利用します。
選択しているものやウィンドウによって処理する対象が変わります。

|ウィンドウ|選択|処理する対象|
|-|-|-|
|Hierarchy|オブジェクト|オブジェクトとその子要素|
|Hierarchy|なし|開いている全シーンの全オブジェクトとその子要素|
|Project|プレハブ|プレハブとその子要素|
|Project|フォルダ|フォルダ内にある全てのプレハブとその子要素|

### 留意点

入力を遮る目的で利用している Graphic の RaycastTarget は、無視する条件では検知できないので無効にしてしまいます。もしそのような Graphic に「Blocker」のような名前が共通で付けられていたら、無視する条件として下記のように利用できます。

``` C#
 if (component.name.Contains("Blocker"))
{
    ignoreRects.Add(component.transform as RectTransform);
}
```

### 補足

プリセットを使えば生成時点から RaycastTarget を無効にできるので、設定忘れを防げます。

https://docs.unity3d.com/ja/current/Manual/Presets.html

https://docs.unity3d.com/ja/current/Manual/DefaultPresetsByFolder.html
VirtualBoxで VM を起動しようとしたら “end Kernel panic と表示され起動出来なくなった時の対応方法

## はじめに

**環境**
- Windows 11 home
- VirtualBox：6.1.38
- （ゲスト）Ubuntu：22.04
- （ゲスト）AlmaLinux：8.6

**注意点**
- VM の電源は切っておく必要があります。

### 状況の整理とエラー内容の説明

まず、起動できないVMは以下の通りです。
- Ubuntu：22.04
- AlmaLinux：8

同じタイミングで起動出来なくなった。（正確に言うと、電源オンは出来るが立ち上げらない状況）
肝心のエラー内容は下記になります。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/2d9c4cf4-3c27-7669-3d16-b4e70c663975.png)
どうやら、カーネル間での同期の問題が発生しているみたいです。

色々ググってみたら、以下のような事が分かりました。

- カーネルのバージョンを下げる
- VirtualBox のバージョン下げる
- Hyper-V を無効にする
- 確保しているメモリやディスク容量が最低要件に達していない
- プロセッサー数を、2以上にする。（もしくは、自分のパソコンと同じコア数にする）

結論から言うと、私は「最後のプロセッサー数を変更する」で解決しました。
以降、プロセッサー数を変更する手順を解説していきます。

## 手順

### プロセッサー数の変更方法

---

1.1　VirtualBox を立ち上げ、該当のVMを選択した上で「設定」をクリック
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/322a9094-4d58-d69f-5f32-d8111a67ab86.png)
1.2　システムタブの「プロセッサー(P)を開く。確かに”1”になっている。」
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/f0f01d6b-1bc0-8c65-5d02-6a4283ff1b1a.png)

1.3　私のPCは6コアなので、”6”に変更後、「ok」をクリック
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/31f33593-1c32-8c91-1392-ed4930e86a8a.png)

1.4　再度起動してみる
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/e129f35c-c425-c60c-d0e9-3cf4b12da383.png)

1.5　問題なく起動している事を確認。解決。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/ac23f3df-3f74-8865-5b97-397e277caa3e.png)

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3282990/b2b5194e-bc01-e642-2fc2-aef780ce5bbc.png)



## まとめ
まず、解決したのはよかった。（一安心）

だが、プロセッサー数は自分でいじったことないのに、何故「1」になったんだろう？と考えた所、最近、Virtual Box のバージョンアップをしてました。
もしかしたら、バージョンアップの影響でプロセッサー数が変わってしまったのではないかな、と予想しております。（次回、バージョンアップする際は要確認しようと思います）

今回は、これで以上です！
私と同様の悩みを抱えていた人のお役に立てますように。
Anacondaで仮想環境を作る方法!!

# __Anaconda promptで仮想環境を作成する方法を伝授！！__
これを見れば __環境構築__ なんてラクチンです！

まず前提としてAnacondaはinstallされているものとします
もしされていなかったら https://www.anaconda.com/products/distribution からご自分の使用しているOSに合わせてinstallしてください。

## Anaconda promptを開く
タスクバーの検索ボックスからAnaconda prompt検索して開いてください。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161551/a8223909-e78b-86b4-0b05-005e3a794087.png)
↑このような画面が表示されるはずです(※塗りつぶしているところはお使いのPCの名前です)

## 仮想環境を作ってみる
習うより慣れろということで、無駄な説明は省いて早速仮想環境を作ってみましょう！！
フォルダは開いたままの位置で大丈夫です。(cdなどで移動する必要はありません)

まず、Anaconda prompt内で使用するコマンドには、~~ほぼ~~ 必ず頭に __「conda」__ を付けて下さい。
なんでかと言われても知りません。決まり事として納得しましょう。
そして仮想環境を創るのは __conda create -n 環境名__ というコマンドで作成できます！簡単ですね♪
ちなみに __-n__ はnameの「n」です。ここでは __「test」__ という名前の仮想環境を作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161551/76e6b314-4114-92e7-5c1d-7e1dc8f4e542.png)
これで仮想環境は作れたのですが、大抵はPythonも一緒に入れてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161551/de4b9a78-111c-3d63-b67a-31c9bb5d3262.png)
バージョンを指定しなければ自動で最新版がinstallされます。バージョンを指定したい場合は、
「Python=3.7」など指定すれば指定したPythonのバージョンが入った仮想環境を作成する事ができます！

## 仮想環境を起動にする
作った仮想環境は起動しなければ意味がありません！
仮想環境の起動方法は __conda activate 環境名__ です。これも簡単ですね♪
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161551/668c7f34-a9a9-dbcc-0d65-0fa3fe154b52.png)
↑こんな感じで(base)だったところが(環境名)になってれば大丈夫です！

## 仮想環境から抜ける
仮想環境から抜ける場合には __conda deactivate__ で抜けることできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161551/9a1546f3-25fa-1ecc-6627-28a8456eb4de.png)
(環境名)から(base)に戻ったことが確認できましたね。

:::note info
今まではdeactivateだけで抜けられてたんですけど、今日やったら警告が出ちゃいました。
皆さんはちゃんとcondaを付けてから抜けるようにしてくださいね。
:::

## 仮想環境を捨てる
仮想環境のいいところは気軽に作って気軽に捨てられるところです！
これからいらなくなった仮想環境を捨てる方法を紹介します。
      __conda remove -n 環境名 -all__
こちらのコマンドできれいさっぱり環境を消すことができます！
このコマンドで仮想環境がなくなったかを確認するには __conda info -e__ で今存在している仮想環境を確認することができます。

#### 以上、超初歩的な仮想環境作成方法でした！
Terraformで作ったECRリポジトリにimageをpushするBash Scriptを書く

# 動機

pushするイメージが多くなると、コマンドの実行も面倒である。

# ディレクトリアーキテクチャ

Makefileから`scripts`ディレクトリにあるスクリプトを実行する。
ルートディレクトリに直接スクリプトを置いてもコードは変わらない。

```
.
├── Makefile
├── scripts
└── terraform
```

# 前提

TerraformからECRリポジトリのURLを得る必要がある。
ここでは、`terraform output`からURLを取得する。
ハードコーディングしてもよい。

```tf:outputs.tf
output "region" {
  description = "AWS region"
  value       = var.region
}

output "ecr-user-url" {
  description = "user ECR repository url"
  value       = aws_ecr_repository.user.repository_url
}
```

# コード

`push-image.sh`を作成する。

```sh:push-image.sh
#!/bin/bash

# cd from root dir
cd ./terraform

REGION=`terraform output region`
REGION=`sed -e 's/^"//' -e 's/"$//' <<<"$REGION"`
```

Terraformのアウトプットには`" (ダブルクォーテーションマーク)`がついているため、取り除いてやる必要がある。
上のコードでは、Terraformからのouputを`REGION`に代入し、改めてダブルクォーテーションを外して再代入している。

このようにして必要な変数を用意したら、イメージをbuild、tagづけ、pushする。
次のコードはマイクロサービスの一つである`user`のイメージをpushしている。

```sh:push-image.sh
#!/bin/bash

# cd from root dir
cd ./terraform

PRODUCT_NAME=example
REGION=`terraform output region`
REGION=`sed -e 's/^"//' -e 's/"$//' <<<"$REGION"`
ECR_USER_URL=`terraform output ecr-user-url`
ECR_USER_URL=`sed -e 's/^"//' -e 's/"$//' <<<"$ECR_USER_URL"`

# back to root dir
cd ../

aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ECR_USER_URL
docker build . -t $PRODUCT_NAME-user -f ./build/package/docker/user/Dockerfile
docker tag $PRODUCT_NAME-user:latest $ECR_USER_URL
docker push $ECR_USER_URL
```

* なお、`aws ecr`コマンドを実行するには、`.aws/credentials`にアクセスキーなどが必要である。
これがない場合は`aws configure`で作成しよう。

* Dockerfileのファイルパスやタグは適宜書き換えてほしい。

* `docker login`のusernameは`AWS`のまま変えてはいけない。
あなたのユーザネームを使うわけではないので注意しよう。
Tips: RubyでCloud Functionsを書くときに、レスポンスだけ先に返して処理を続ける方法


## この記事は何
最近RubyでCloud Functionsを書くときに、レスポンスだけ先に返して処理を続ける必要があったので、その方法を紹介する記事です。

## Cloud Functionsで開発していた時の課題
Cloud Functionsを使ってSlackでスラッシュコマンドを用いたボットの開発を行っていたのですが、開発するにあたり、以下のような問題が発生していました。

- スラッシュコマンドは3秒以内にレスポンスを返さないとエラーになる
    - https://api.slack.com/interactivity/slash-commands#responding_basic_receipt
- スラッシュコマンドがエラーになってもCloud Functions上で処理を続けることはできるが、その場合スラッシュコマンドで入力した文章を他のメンバーに共有できない
    - https://qiita.com/memomaruRey/items/82f7ea73cb3cfb856925 にある通り、`in_channel`というresponse_typeをレスポンスで返さないと共有できない

これらの問題を解決する方法としては https://qiita.com/saken649/items/b70e462ae41614b72f77 
のように

1. レスポンスを先に返す
    - 「Running...」のようなレスポンスだけ先に返す
1. 自在の処理はレスポンスを返した後に続ける
1. 処理が終わったタイミングで、SlackのAPIを用いて結果をポストする

というような処理を行う方法が一番シンプルです。

## Rubyでの実現方法

https://qiita.com/saken649/items/b70e462ae41614b72f77 はNode.jsで実装されていますが、
Rubyでも同じようなことができないか調べてみました。
結論から言うと、`Thread`を用いることで実現ができます。
以下のようなコードを書くことで、先にレスポンスを返し、処理を続けることができました。

```rb
require 'functions_framework'

FunctionsFramework.http 'function' do |request|
  Thread.new do
    very_long_transaction
    'OK'
  end
  
  'Running...'
end
```
VPCピアリング

・VPCは目的別に分離するのがベストプラクティス
⇒VPC同士の通信が必要となる。
↓
VPCピアリングを使用してVPC同士を接続する。

# VPCピアリング
* VPCの機能のひとつ
* プライベートIPでVPC同士を接続する
* IPアドレス範囲は重複できない。
* VPC同士の接続1か所につき、ピアリング接続が１つ必要
* 異なるAWSアカウント・リージョンでも接続可能

::: note
ピアリング接続ポイント（Peering Connection）作成とルートテーブルの設定変更で実装可能
:::

### ピアリング接続ポイント（Peering Connection）作成
* リクエスト側でピアリング接続を設定する。
* アクセプタ側で、承認する。

### ルートテーブル設定
* ルートテーブル設定：設定したピアリング接続ポイントのルーティングを設定。（VPC内のそれぞれのサブネットに設定要）
* アクセプタ側の戻りの設定も忘れずに。
Leetcode 1768. Merge Strings Alternately

https://leetcode.com/problems/merge-strings-alternately/description/

# アプローチ
- Brute-force

# コード
```java
class Solution {
    public  String mergeAlternately(String word1, String word2) {
        String result = "";

        int word1Size = word1.length();
        int word2Size = word2.length();

        int word1index = 0;
        int word2index = 0;

        int turn = 1;

        while (true) {
            if (word1index >= word1Size && word2index >= word2Size) {
                break;
            }

            if (turn % 2 == 1) {
                if (word1index <= word1Size - 1) {
                    result += "" + word1.charAt(word1index);

                }
                word1index++;


            } else {
                if (word2index <= word2Size - 1) {
                    result += "" + word2.charAt(word2index);

                }
                word2index++;

            }
            turn++;
        }

        return result;
    }
}
```
すごすぎAIグラドル生成コマンド公開


AIグラドル作って動画配信

![04232-20230415065840__20230415065819__3890638507.0__20230415_065840_797494.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119461/697f485e-130f-4b3c-b52d-8c514a10007f.jpeg)

https://youtu.be/DaFSHNLoJ9U

prompt
```shell
ulzzang-6500-v1.1, Random posture, (raw photo, 8k, photorealistic:1.3), (masterpiece, best quality), 35mm shot, 8k, Fujifilm XT3, masterpiece, detail face, beautiful detailed eyes, ultra realistic details, sharp focus, looking at viewer, detailed skin, on back, (a young girl, solo), (detailed beautiful face, detailed perfect skin), (beautiful detailed eyes), <lora:yaeMikoRealistic_yaemikoMixed:0.2>, extremely detailed, high res, best quality, korean girl, full body, 1girl, ulzzang-6500, kpop idol, yae miko, bright brown hair, long hair, best quality, (wave hair:1.35), jewelry, brown eyes, standing, revealing modern outfit, see through, low cut, portrait, looking at viewer, solo, bokeh, professional light, detailed skin, <lora:Hana_Bunny_v1.5.1:0.2>, full body, standing, cute face,slim body,blonde messy hair,(slender, korean beauty:1.1), (Women is sitting on the bed and laughing and talking:1.4) ,(Women in summer pajamas :0.5),( Nightwear,Short Set,Pink,Lightweight:1.2)
```

Negative Prompts

```shell
nsfw, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, bad anatomy,(fat:1.2), lowres,bad anatomy,bad hands, text, error, missing fingers,extra digit, fewer digits, cropped, worstquality, low quality, normal quality,jpegartifacts,signature, watermark, username,blurry,bad feet,cropped,poorly drawn hands,poorly drawn face,mutation,deformed,worst quality,low quality,normal quality,jpeg artifacts,signature,watermark,extra fingers,fewer digits,extra limbs,extra arms,extra legs,malformed limbs,fused fingers,too many fingers,long neck,cross-eyed,mutated hands,polar lowres,bad body,bad proportions,gross proportions,text,error,missing fingers,missing arms,missing legs,extra digit, extra arms, extra leg, extra foot
```

```
Steps
22

Sampler
DPM++ 2M Karras

Size
512x768

CFG Scale
10

Model
ChilloutMix

Seed
3890638507
```
Flutterでビルド時にpod installが失敗した時の模索


Flutterアプリをビルド(flutter run)した時にpod installで失敗していたので、その時の私の模索記事になります。（あまり当てにならないので参考程度でお願いします）

# エラー内容

ビルド時に以下のエラーが発生

```
Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.
To update the CocoaPods specs, run:
  pod repo update

Error running pod install
```

# 開発環境

- Apple Silicon Mac
- macOS Monterey 12.6
- Xcode 14.2
- Android Studio Chipmunk | 2021.2.1 Patch 1
- Flutter 3.7.11
- CocaoPods 1.11.3
- ffi 1.15.5

# 試したこと

多くの人が遭遇しているエラーになるようで、情報もたくさん出てくるが、（環境により対処法が違うのか）私はどれもうまくいかなかったので、試したことを残しておきます。

## Step1. pod repo update

とりあえず、メッセージ通りpod repo updateを実行してみたが、CocoaPodsのバージョンが違うのか、CocoaPodsをインストールしろと言われたので次へ。

```
$ pod repo update
Updating spec repo `trunk`

CocoaPods 1.12.0 is available.
To update use: `gem install cocoapods`

For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.12.0

$ pod --version
1.11.3
```

## Step2. ffiをインストールする

以下の情報を参考にして、ffiをインストールしてみたがダメだった。
私はすでにffiをインストール済みだったので、ダメだったのかもしれない。

https://stackoverflow.com/questions/67443265/error-regarding-undefined-method-map-for-nilnilclass-for-flutter-app-cocoap


```
$ sudo arch -x86_64 gem install ffi

...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [libffi.la] Error 1
make[2]: *** [all-recursive] Error 1
make[1]: *** [all] Error 2
make: *** ["/Users/[User Name]/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/ffi-1.15.5/ext/ffi_c/libffi-arm64-darwin21"/.libs/libffi_convenience.a] Error 2

make failed, exit code 2

Gem files will remain installed in /Users/[User Name]/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/gems/ffi-1.15.5 for inspection.
Results logged to /Users/[User Name]/.rbenv/versions/3.0.4/lib/ruby/gems/3.0.0/extensions/arm64-darwin-21/3.0.0/ffi-1.15.5/gem_make.out
```

## Step3. Podfile.lockを削除してpod install

結論としては、以下の情報を参考にしながら作業をしていたら、いつの間にかビルドが出来るようになっていた。

https://dolphinetech.com/flutter/error-running-pod-install/

### 手順
1. iosフォルダ内にある「Podfile.lock」ファイルをどこかに移動する
2. Android StudioのTerminalから「ios」フォルダに移動して`pod install --repo-update`
   - →`pod install --repo-update`は成功したが、Podfile.lockが書き変わってしまった（のでNGかなと諦めモード）
3. `flutter clean`
4. `flutter run`
   - →とりあえず、pod installは成功したが、GoogleService-Info.plistが見つからないエラー（実際には存在するんだけどな…）
   - →諦めてやり直し
5. Podfile.lockを元に戻す
6. `flutter clean`
7. `flutter run`
   - →意味が分からないが、もう一度ビルドしたら成功した！（おそらく何か理由があるのだろうが…）

とりあえず、ビルドは出来たので環境構築は終了。
iOSのシミュレータでもアプリ起動は出来たし、難しいことは後で考えよう。


## おまけ. (公式ドキュメント通り)ffiを再インストールする

後から気付いたので試しておりませんが、公式ドキュメントに記載されている方法を試していたら、pod installは成功していたのかな？

```
$ sudo gem uninstall ffi && sudo gem install ffi -- --enable-libffi-alloc
```

https://docs.flutter.dev/get-started/install/macos

> Note: The default version of Ruby requires sudo to install the CocoaPods gem. If you are using a Ruby Version manager, you might need to run without sudo.
> Additionally, if you are installing on an Apple Silicon Mac, run the command:
> 
>  $ sudo gem uninstall ffi && sudo gem install ffi -- --enable-libffi-alloc
pandasの不要な改行を削除する方法

## なぜ書いた？
pandasで事前処理を実装していた時に`df.replace('\r','')`が機能せずに苦しんだため、他の方にも解決法を共有できればと思ったためです。

## うまくいかなった原因
オブジェクト型のデータに対して文字列のための（デフォルトの）replaceを使っても効果がなかったためです。

## うまくいく書き方
オブジェクト型のデータにも効果があるreplaceの使い方をすることで効果を出すことができました。

## 実際の書き方
具体的には、下記のように正規表現を利用した形でreplaceを使うことでうまくいきました。

```python:事前に整形できていないデータの場合（df内の対象がオブジェクト型の場合）
import pandas as pd
import tabula 

# pdfの表を無理やりpandasのdataframe型の集合体に変換 （不要な改行などが入っているdataframeが作成されます）
dfs = tabula.read_pdf("xxx.pdf", lattice=True, pages='1-3')

# 以下のように記載することで改行がなくなります
for df in dfs:
  df = df.replace("\r", "",regex=True)
```


## 余談（綺麗なデータの場合（df内の対象が文字列型の場合）のreplace関数の使い方）
```python:よくある書き方
import pandas as pd 

data = {
    'Name':['A','B','C','D','E'],
    'Number':[100,200,300,400,500]
}

# 綺麗なテストデータを作成
df = pd.DataFrame(data, columns =['Name','Number'],index=['Item1','Item2','Item3','Item4','Item5'])

# 以下のように記載することでAがaへと変換されます
df.replace('A','a')
```

## 参考資料
解決につながった記事（Yahoo知恵袋）:
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14268433589

公式リファレンス：
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html
【AWS-SAA】Organizationsについて

4/22にSAAの試験を受けるためOrganizationsについて書き出して整理する

## Organizationsでできること
・複数AWSアカウントの一元管理
・アカウントの新規作成を自動化
・請求の簡素化

## 機能セット
Consolidated Billing Only → 支払代行のみ
All Feature → 企業内でアカウント統制する

## Organizationsで新規作成アカウントの初回ログイン方法
・ルートアカウントのパスワードリセット
・スイッチロール
・SSOなどのフェデレーションでログイン

### アカウント作成時
AWSアカウントの作成時にIAMロールの指定が可能
※マスターアカウントから管理するロールは統一する方が運用上◎

## サービスコントロールポリシー(SCP)
ポリシーは組織ルート、OU、アカウント単位で割り当て可能
階層構造に基づきSCPが継承される。

### ポリシーの許可・拒否の機能について
許可はAND条件で反映
SCP・IAMポリシー・リソースポリシー全てで許可されている部分が実際に許可される範囲

拒否はSCPで拒否すればIAM・リソースポリシーで許可されていても全拒否
順位付
SCP/IAMポリシーで明示的に拒否 > IAMポリシーとSCPで許可 > 明示的拒否(デフォ)

### ポリシーの方式
・ブラックリスト：禁止するポリシー
・ホワイトリスト：許可するポリシー

※ホワイトリストで管理する場合、デフォで割り当てられている全サービス許可のFullAWSAccessは削除要


## Organizationsを活用したサービス
・SSO
  -ADユーザにOrganizationsの組織内にあるAWSアカウントを対象にマネジメントコンソールへのSSOを提供

・CloudFormation
  -Organizationsの組織単位を対象にして複数のAWSアカウントにまたがってデプロイ可能
LaravelのwithoutGlobalScopes()ってSoftDeleteも消えるの盲点だった・・・

いろいろカスタムしてグローバルスコープでややこしいクエリも少ない記述で効率化なんてことをしてたんですが、時にはそれを打ち消したい時も。
いちいち消したいものを書くのもめんどくさく、一気に `withoutGlobalScopes()` って書いてました。
そうすると論理削除したものが取得されてるってことにテストで気づきました。
SoftDeleteもグローバルスコープ経由なので当然っちゃ当然でした。

なのでSoftDelete以外のグローバルスコープを一気に無効化する方法を作りました。

```php
    public function scopeWithoutGlobalScopesWithSoftDelete(Builder $query): Builder
    {
        $scopes = [];
        foreach (static::getGlobalScopes() as $scope => $val) {
            if ($scope !== \Illuminate\Database\Eloquent\SoftDeletingScope::class) {
                $scopes[] = $scope;
            }
        }
        return $query->withoutGlobalScopes($scopes);
    }
```

このスコープを呼べばいいので `Model::withoutGlobalScopesWithSoftDelete()->get();`こんな感じに使う。
プログラマとして長く続けていくためのモチベーション向上術


どうもこんにちはたくびー(@takubii)です。

エンジニアの仕事にはある程度のモチベーションがないとツラい部分があります。
モチベーションを保つためにどのようなことをしているのか参考になればと思い、この記事を投稿します。

### 業務そのものが自分のやりたいことでモチベーションが湧いてくる
この状態はエンジニアとして理想的な状態ですね。
仕事をするだけで技術力がつき、その上楽しいという状況です。
このような環境はなかなか巡り会えないので、その環境での仕事を大切にしましょう。

### 自分のキャリア設計を考えて仕事をする
今の業務を終わらせると職務経歴書にこんな実績が書けるなとか、技術的にアピールできるポイントが増えるなとかを考えることでモチベーションを上げていく方法です。

こちらも仕事を通してモチベーションを上げていく方法です。この方法の利点はひとまずある程度形になるまで辞めようと思っていた気分を軽減させてくれる効果もあります。

### 休憩中に興味のある技術のチュートリアルをやってみる
ReactやVueなどの公式サイトには大抵チュートリアルがあります。
チュートリアルに従ってコードを書き、なにかを作り上げるという行動はエンジニアにとって学習と達成感を与えてくれます。

### 興味のある技術の環境構築を行ってみる
チュートリアルに取り掛かれるほどモチベーションがない時は環境構築だけでも手を出してみてはどうでしょうか？

先ほどと同じように大抵の公式サイトにはGetting Startのような構築手順が書かれたページがあるので、それに従って開発環境を作ってみてください。

完成されたデモプロジェクトとサンプルコードがすぐに手に入るので、そのコードを眺めて実装などの学習をするのも良いと思います。

### 技術ブログを漁ってみる
もう手を動かせるほどやる気が起きない場合はQiitaやZennなどの技術ブログを眺めてみてください。
様々な人が学んだこと、詰まっていたところをブログにして発信しています。

もしかすると、今やっている仕事に関係のある部分を記事にしてくれる方もいるかもしれません。
また、疲れるのは目だけなのでひとまず目を通してみてはどうでしょう。

### もういっそのこと技術のことから離れて休憩する
常に仕事、勉強のことばかり考えていると疲れてしまいます。
一旦休憩を挟んでリフレッシュするのも大事です。

Twitterやソシャゲなどちょこっと気を紛らわすものは周りにたくさんあります。
もちろん、プライベートの時間では読書やゲーム、友達と飲みにいくのもいいと思います。

### 終わりに
エンジニアとして働いていると急遽新しい技術を使ったプロジェクトに放り込まれたり、既存のプロジェクトの移行計画などでずっと同じ技術を使い続けることが難しい場面に出くわすこともあるでしょう。
そういった学び直しの時にある程度のモチベーションを維持して、対応できるようになっていたいですよね。

私も年々モチベーションが落ちつつあるという自覚があり少し焦っていますが、柔軟に新しい技術に対応できるようにしたいと思っています。（それがエンジニアとしての強みになればいいなとも思いますが... ）

今回ご紹介した方法は仕事中に行えることばかりです。私にとって最もモチベーションを高められるのはプライベートを充実させることなので、みなさんもライフワークバランスのよい仕事ができるように頑張っていきましょう。
gRPCのインターフェースドキュメント自動生成に苦しんだので記事化

# gRPCのインターフェースドキュメント自動生成に苦しんだので記事化

今回の容疑者
```sh
protoc --doc_out=. --doc_opt=html,index.html file.proto
```
上記コマンドで自動生成出来るはずだった。



<br/>
<br/>
<br/>
<br/>
<br/>
しかし、出来なかった。

```sh:error内容

protoc-gen-doc: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable      
--doc_out: protoc-gen-doc: Plugin failed with status code 1.

```

<br/>
<br/>
<br/>
現場に居るパッケージは以下の通り。

```sh:go.mod
github.com/pseudomuto/protoc-gen-doc v1.5.1
```

こちらのコマンドは実行済だ。

```sh

go get -u github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc

# 実行結果
# module github.com/golang/protobuf is deprecated: Use the "google.golang.org/protobuf" module instead.
```

<br/>
<br/>
<br/>
わけがわからない。

ひたすら記事を探し(公式とか海外のは出来るだけ避けた(あかん))...


- gRPC開発におけるドキュメントを自動生成する(Zenn)
    - https://zenn.dev/jy8752/articles/2e77da36cae0c3
```sh
# 実行
go install github.com/pseudomuto/protoc-gen-doc/cmd/protoc-gen-doc@latest

#go: downloading github.com/envoyproxy/protoc-gen-validate v0.3.0-java
#go: downloading google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4
#go: downloading google.golang.org/protobuf v1.27.1
#go: downloading github.com/google/uuid v1.1.2
#go: downloading golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9

# 実行
protoc -I. --doc_out=. --doc_opt=html,index.html *.proto
```

# ( ﾟдﾟ)ﾊｯ!ﾃﾞｹﾀ!!!
ありがとう、どこかの(Zenn)ぱんださん
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081664/ef6f16d4-c24f-1705-4af3-e0bae860c8c6.png)

# Conclusion
- 1時間失いました。
【Laravel6】サインアップ後、自動的にログイン状態に

# 背景
Laravel6で制作中のECサイトにおいて、カートページから決済ページに移る際、認証ミドルウェアをかけていた。
ログイン状態ならそのまま決済ページに、未ログイン状態なら、認証ページに移動して、認証を求めるという流れ。

ログイン後はそのまま決済ページに移動できるが、サインアップ後はうまく行かず、トップページに移動してしまっていた。

# Laravelのデフォルトの設定では、サインアップしただけではログイン状態にはならない

Laravelでは、ユーザーがサインアップした後に自動的にログインさせるには、Authファサードを使用してログインする必要がある。

Auth\RegisterControllerの、RegistersUsers.phpに、サインアップ後に、自動ログイン状態とし、かつ、URLに"cart"が含まれていた場合、決済ページにリダイレクトさせる処理をかく。

```RegisterUsers.php
    protected function registered(Request $request, $user)
    {
        // ユーザーをログインさせる
        $this->guard()->login($user);

        // cartが含まれるURLからリダイレクトする
        if (strpos(session('url.intended'), 'cart') !== false) {
            return redirect()->intended('/checkout');
        } else {
            return redirect($this->redirectPath());
        }
    }
```
[AWS Q&A 365][Redshift]AWSのよくある問題の毎日5選 #33

# 1. Amazon Redshiftのマテリアライズド・ビューとは何ですか？
回答：Amazon Redshiftのマテリアライズド・ビューとは、1つ以上のベーステーブルに対するSQLクエリに基づく事前計算された結果セットで、データベース内の他のテーブルやビューと同様にクエリできます。これにより、ベーステーブルにアクセスせずに、マテリアライズド・ビューから事前計算された結果を返します。

# 2. Amazon Redshiftのマテリアライズド・ビューを使用する利点は何ですか？
回答：Amazon Redshiftのマテリアライズド・ビューは、予測可能で繰り返されるクエリを高速化するのに特に役立ちます。大きなテーブルに対してリソースを大量に消費するクエリ（集約や複数の結合など）を実行する代わりに、アプリケーションはマテリアライズド・ビューをクエリして事前計算された結果セットを取得できます。これにより、ベーステーブルから同じデータを取得するよりも、クエリ結果が速くなります。

# 3. Amazon Redshiftで自動化されたマテリアライズド・ビューを開始および作成するためのSQL文はどのようなものですか？
回答：自動化されたマテリアライズド・ビューは、GROUP BY句または以下の集約関数のいずれかを含むクエリまたはサブクエリによって開始および作成できます：SUM、COUNT、MIN、MAX、AVG。ただし、以下のものは含めることができません：左、右、または完全な外部結合、SUM、COUNT、MIN、MAX、AVG以外の集約関数、DISTINCTを含む集約関数、ウィンドウ関数、SELECT DISTINCTまたはHAVING句、外部テーブル（データシェアや連携テーブルなど）、および他のマテリアライズド・ビュー。

# 4. Amazon Redshiftで他のマテリアライズド・ビューを使用してマテリアライズド・ビューを定義できますか？
回答：はい、Amazon Redshiftで他のマテリアライズド・ビューを使用してマテリアライズド・ビューを定義できます。マテリアライズド・ビューをマテリアライズド・ビューに使用して、マテリアライズド・ビューの機能を拡張できます。このアプローチでは、既存のマテリアライズド・ビューが、クエリがデータを取得するためのベーステーブルと同じ役割を果たします。

# 5. Amazon RedshiftのSTV_MV_DEPSテーブルとは何ですか？
回答：Amazon RedshiftのSTV_MV_DEPSテーブルは、マテリアライズド・ビューが他のマテリアライズド・ビューに依存していることを示します。このテーブルは、異なる集約やGROUP BYオプションに対して事前計算された結合を再利用するのに特に便利です。
Vim(Neovim)の基本操作

今回は、私自身現在エンジニアとして働いていますが、Vim(Neovim)に関してはちょろっとコマンド知ってるくらいのほぼ初心者だったので、基本的なコマンドを備忘録としてまとめました。

## VimとNeovimの違い(背景など)
+ Vimは昔から使われているが、古くから開発されているので、動作とかがちょっと遅くなってきているだとか、複雑になってきているというところがあるので、過去に改善を積み重ねてきたVimを作り直し、**軽量化や拡張性を考慮した新たなVim**として**Neovim**がつくられた。
+ Vimができることは、ほぼNeovimでできる
+ **使い方はほぼ一緒なので、Vimを習得してもNeovimを習得してもスキルレベルはほぼ一緒**
+ 今後の世間の動向で切り替えれば良い
+ Neovimの方がよりプラグインが豊富

|Vim|Neovim|
|:---:|:---:|
|拡張しにくい|拡張しやすい|
|LSPサポート(他のプラグインに依存)|LSPサポート(備わっている)|

## Neovimのエイリアス設定
以下の手順で設定ファイルにエイリアスを記述する(VimコマンドでNeovimが起動するようにする)

```zsh
# ①編集するファイルを開く
$ open -a TextEdit ~/.zshrc 
または、
$ vim ~/.zshrc

# ②以下を追加▼(VimコマンドでNeovimが起動するようにエイリアス設定)

alias vi="nvim"
alias vim="nvim"
alias view="nvim -R"

# vimで編集した場合は、escキーでインサートモードから抜けたら :wq (保存して終了)を実行

# ③中身の確認
$ cat ~/.zshrc

# ④変更が反映されるよう保存
$ source ~/.zshrc
```


## Vim(Neovim)の基本操作



### 移動系
|vimコマンド|実行結果|
|:---:|:---:|
|k (Normal Mode)|↑に移動|
|j (Normal Mode)|↓に移動|
|h (Normal Mode)|←に移動|
|l (Normal Mode)|→に移動|


### 単語移動

|vimコマンド|実行結果|
|:---:|:---:|
|w|単語の先頭に順移動|
|b|単語の先頭に逆移動|
|e|単語の末尾に順移動|
|ge|単語の末尾に逆移動|


### 編集系

+ Viewモード
    + 何か間違えてファイルを書き換えたくないけども、Vimの機能を使って移動したいとか、そういった時に使う

|vimコマンド|実行結果|
|:---:|:---:|
|i|インサートモード|
|a|次の文字からインサートモード|
|o|選択行の下に空白を入れ、インサートモード  (コメントを書く時などよく使う)|
|O|選択行に空白を入れ、インサートモード|
|esc|Normal mode|
|:w ファイル名|名前をつけて保存|
|:w|上書き保存|
|:q|編集終了|
|:q!|保存しないで編集終了|
|:wq|保存して終了|
|view|Viewモードで起動|




### 削除系


|vimコマンド|実行結果|
|:---:|:---:|
|vim /tmp/test/test.txt|ファイル指定で開く|
|x(ノーマルモード)|1文字削除|
|dd(ノーマルモード)|1行削除(同時にコピーしてくれる)|
|dw(ノーマルモード)|単語の削除|
|cw(ノーマルモード)|単語の削除(実行後インサートモード)|
|2dd(ノーマルモード)|2行削除(指定した数だけ行を削除)|
|u(ノーマルモード)|Undo(戻す)|
|Control + r(ノーマルモード)|Undo redo(進める)|



### コピー・ペースト系

|vimコマンド|実行結果|
|:---:|:---:|
|yy(ノーマルモード)|1行コピー|
|:%y|全行コピー|
|p(ノーマルモード)|下にペースト|
|P(ノーマルモード)|現在行にペースト👈よく使う！|
|.|直前に実行したコマンドを再度リピート|
|v(ビジュアルモード)　移動してからy(yank)|カーソル指定コピー|




### 検索・置換系


|vimコマンド|実行結果|
|:---:|:---:|
|/{検索したい文字列}　例) /hoge|検索(検索結果の文字がハイライトで表示される)|
|:noh|ハイライトを消す|
|:set hlsearch|再度ハイライトを表示|
|n|次の検索結果に移動|
|N|前の検索結果に移動|
|R|置換(あまり使わない)|
|:%s/{検索したい文字列}/{置き換えたい文字列}/g|一括置換|
|:%s/{検索したい文字列}/{置き換えたい文字列}/gc|1箇所ずつ確認しながら置換|





### その他の移動(ファイル内移動)

|vimコマンド|実行結果|
|:---:|:---:|
|:set number|行番号を表示|
|:10|10行目に移動|
|$|行末に移動|
|0|先頭に移動|
|^|インデントの先頭に移動|
|{|段落毎に上に移動|
|}|段落毎に下に移動|
|[[|セクション毎に上に移動|
|]]|セクション毎に下に移動|
|:1 もしくは　gg|ファイルの先頭に移動|
|G|ファイルの最後に移動|
|Control + o|移動前に戻る|



### Vimのコマンドモードでスクリプトを実行

#### 前提条件
vimで編集したPythonスクリプト(test.py)をvimのコマンドモードで実行したい時(Python3系をインストール済みとする)


+ vimのコマンドモードで実行する
    + 一連の流れとして以下を入れてやる
    + `:!python3 test.py`

+ 編集して再度実行を繰り返したい時
    + i(インサートモード)で編集
    + `:w`で変更内容を保存
    + `:!!`で前に実行したコマンドを参照して実行



## 参考資料
[現役シリコンバレーエンジニアが教える NeoVim(VIM) + Tmux + Zsh 入門 - Udemy](https://www.udemy.com/course/vim-tmux-zsh/)
[AWS Q&A 365][Redshift]Daily Five Common Questions #33

# 1. What is a materialized view in Amazon Redshift? 
Answer: A materialized view in Amazon Redshift is a precomputed result set based on an SQL query over one or more base tables that can be queried like other tables or views in the database. It returns the precomputed results from the materialized view, without having to access the base tables at all. 

# 2. What are the benefits of using materialized views in Amazon Redshift? 
Answer: Materialized views in Amazon Redshift are especially useful for speeding up queries that are predictable and repeated. Instead of performing resource-intensive queries against large tables (such as aggregates or multiple joins), applications can query a materialized view and retrieve a precomputed result set. This results in faster query results compared to retrieving the same data from the base tables. 

# 3. What kind of SQL statements can initiate and create an automated materialized view in Amazon Redshift? 
Answer: An automated materialized view can be initiated and created by a query or subquery, provided it contains a GROUP BY clause or one of the following aggregate functions: SUM, COUNT, MIN, MAX or AVG. But it cannot contain any of the following: Left, right, or full outer joins, aggregate functions other than SUM, COUNT, MIN, MAX, and AVG, any aggregate function that includes DISTINCT, any window functions, SELECT DISTINCT or HAVING clauses, external tables, such as datashares and federated tables, or other materialized views. 

# 4. Can you define a materialized view in terms of other materialized views in Amazon Redshift? 
Answer: Yes, you can define a materialized view in terms of other materialized views in Amazon Redshift. You can use materialized views on materialized views to expand the capability of materialized views. In this approach, an existing materialized view plays the same role as a base table for the query to retrieve data. 

# 5. What is the STV_MV_DEPS table in Amazon Redshift? 
Answer: The STV_MV_DEPS table in Amazon Redshift shows the dependencies of a materialized view on other materialized views. This table is especially useful for reusing precomputed joins for different aggregate or GROUP BY options.
Pythonで線形探索を実装してみた

# 概要
Pythonで線形探索を実装してみました。以下のページを参考にしました。
https://paiza.hatenablog.com/entry/2020/05/01/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A3%E3%81%A6%E3%81%AA%E3%81%AB%EF%BC%9F%E6%8E%A2%E7%B4%A2%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92Python%E3%81%A7%E5%AE%9F#%E7%B7%9A%E5%BD%A2%E6%8E%A2%E7%B4%A2Linear-Search

# ソースコード
データが存在しないパターンを作りました。-1が返ってくるのを確認した。
num_list_1は2番目に見つかる。num_list_2は6番目に見つかる。num_list_3は見つからない。
```linear_search.py
# coding: UTF-8

# 以下のリストからターゲットとなる値が何番目にあるか探す
num_list_1 = [1,17,4,14,7,5,9,3,5]
num_list_2 = [1,3,9,14,7,12,4,17,5]
num_list_3 = [1,3,9,14,7,12,14,17,5]
target_num = 4

# 線形探索する
def linear_search(list, target):
    result = -1
    
    for i in range(len(list)):
        print("for文を通った回数：{}".format(i + 1))
        
        # リストの要素とターゲットの値が一致したら
        if list[i] == target:
            result = i
            break
    return result

# ターゲットとなる値の位置を出力
print(linear_search(num_list_1,target_num))
print(linear_search(num_list_2,target_num))
print(linear_search(num_list_3,target_num))
```

# 実行結果
期待通りの結果が得られた。

```
$ python linear_search.py 
for文を通った回数：1
for文を通った回数：2
for文を通った回数：3
2
for文を通った回数：1
for文を通った回数：2
for文を通った回数：3
for文を通った回数：4
for文を通った回数：5
for文を通った回数：6
for文を通った回数：7
6
for文を通った回数：1
for文を通った回数：2
for文を通った回数：3
for文を通った回数：4
for文を通った回数：5
for文を通った回数：6
for文を通った回数：7
for文を通った回数：8
for文を通った回数：9
-1
```
何かの役に立てばと。
初心者向けオブジェクト指向解説：プログラムを効率的に開発するためのアプローチ

オブジェクト指向は、プログラムを開発するための一つのアプローチで、プログラムを部品に分割し、それらを再利用可能な「オブジェクト」として扱います。この記事では、オブジェクト指向の基本的な特徴を紹介します。

# オブジェクト
オブジェクトは、それ自体が機能を持った再利用可能な部品で、他のオブジェクトと相互作用することができます。例えば、ウェブサイトのページを作る場合、テキストや画像を含むコンテンツを一つのオブジェクトとして扱うことができます。このオブジェクトは、再利用可能で、別のページで同じように使用することができます。

# クラス
クラスは、オブジェクトの設計図のようなもので、オブジェクトを作成するためのテンプレートです。クラスには、オブジェクトのプロパティとメソッドが含まれます。オブジェクトは、クラスを元に作成され、それぞれ独自のプロパティとメソッドを持ちます。

# カプセル化
カプセル化は、オブジェクトが内部の状態を保持し、外部からアクセスできないようにすることです。オブジェクトの内部状態は、外部から変更できないため、安全性が高くなります。

# 継承
継承は、既存のクラスから新しいクラスを作成し、新しいクラスに既存のクラスの機能を追加することができます。このようにして、プログラムの再利用性が高まります。

# ポリモーフィズム
ポリモーフィズムは、オブジェクトが同じ名前のメソッドを実行することができますが、その動作はオブジェクトのタイプによって異なります。このようにして、オブジェクトの種類によって処理が異なる場合に、コードの再利用性が高くなります。

# まとめ
オブジェクト指向プログラミングは、初心者にとっては難しいかもしれませんが、一度理解すれば、プログラムの開発に大きな助けになります。プログラミング言語によっては、オブジェクト指向をサポートしていない場合もありますが、多くの言語がオブジェクト指向をサポートしています。
AI・機械学習でよく使うアルゴリズムメモ。-- 決定木分析 --

# もくじ
>[決定木分析ってなあに？](#決定木分析ってなあに？)
[決定木分析の種類](#決定木分析の種類)
[で、何に使うの？](#で、何に使うの？)

# 決定木分析ってなあに？
ざっくりまとめると、**ある目的に対して関連の強い項目から順に分岐させ、ツリー状に表す分析手法**です。
例えば、好きなキャラクターの画像を入力してキャラの属性を分析する場合だと、
髪の長さは？[長いor短い] ＞ 肩幅は？[広いor狭い] ＞ 付いてる？[あるorない] ＞ 最終的に「これはおとこのこ！」
といった感じで**一つの項目からどんどん分岐**していき、最終的にたどり着いた場所から結論を導き出す。という分析手法のようです。
~~（つまりは、よくあるまったく参考にならない性格診断チャート的なイメージ。他にはアキネ〇ターなんかもそうですね。）~~

# 決定木分析の種類
大きく二つの手法があり、総称して「**決定木（ディシジョンツリー）**」と呼称されています。
~~個人的なイメージでは分類木はswich文、回帰木はif文という印象を受けました。~~
#### ・分類木
もし○○なら△△or◇◇と答え、最終的な結論を出す手法。何かを分類したいときに主に使われます。
先ほど例に出した、おとこのこかどうか？や性格診断チャートなんかが当てはまりますね。

#### ・回帰木
連続的なデータを分析する手法。先ほどの例で当てはめると
「髪の長さが何cm以上か？」「肩幅は何cm以下か？」＞ 最終的なおとこのこ率n%！
のように数字でデータを線引きするような感じで分類する際に使うことが多いようです。

# メリット
#### 可視化しやすい。
これに関しては説明するまでもないとは思うのですが、結果がチャート表のような感じや樹形図の形にしたりと、**一目見て理解できる形にできる**のはこれ以上ない程のメリットですね。数学や分析の知識に乏しくても、表にしてしまえば何が起きているのかをざっくり理解することができます。つまりは**データの解釈がしやすい**とも言えますね。

#### データの型に依存しにくい。
感のいい方は気が付いたかもしれませんが、今回の例で出した文字としての情報だけでなく、画像や数字データ、音声等だいたいどんな形式の物でも分析することができてしまいます。

# 発展形
### アンサンブル学習
それぞれ、得意が違う決定木を集めて学習を行う手法です。
これに関してはまた別途で記事を書くつもりです。


### ランダムフォレスト
アンサンブル学習の発展系で、簡単に言ってしまえば**複数の決定木を集めて多数決させる**手法です。
分類木Aと分類木Bと回帰木αの三つのうち2が結果Nを出したから最終結果はN！といった感じですね。
ひとつの面からの分析からではなく、多角的な複数の決定木を用意することでより精度の高い分析をすることができます。

記事作成：K&Q
Githubを用いてレビュー時に発生したError Domain=NSCocoaErrorDomain Code=260への対応

こんにちわ。ZaQです。

会社内でおいてGithubを用いてプロジェクト管理を行い、メンバー内でのコードレビューを実施しています。

そして、ある日、レビューを実施していたのですが、下記のエラーが発生。

```
error:Error Domain=NSCocoaErrorDomain Code=260 "Thefile"XXX.png" 
coundn't be opened because there is no such file.
"UserInfo={NSFilePath=/XXX/XXX/XXX.png,
NSUnderlyingError=0x281a54450
{Error Domain=NSPOSIXErrorDomain Code =2 "No such file or directory"}}"
```

あれ？:innocent:

新しいブランチに合わせて、ローカルブランチに持ってきて、自分のローカル環境のみで行ったのだが・・・。

自分の環境の設定がおかしいのか・・:weary:

自分が行ったことを振り返り。

```
git branch ckechout review-#AAA
```
ここで、一度review-#AAAに対応して、ローカルブランチ上でコードを修正。
レビューが終わりGithub上でコメントを送信。

その後、新しいブランチに対して、

```
git branch checkout review-#BBB
```
続いてBBBに対してローカルでのブランチ上で動作を確認した結果、今回のエラーが発生。

よく読んでいると、、、

:::note info
<dt>review-#AAAに変更した内容がreview-#BBBの内容に反映されていた〜〜</dt>
:::


これは、気づきませんでした。

では何をするかというと、

新しいブランチでのレビューを行う前に、

```
git checkout .
```
を実施し、<dt>今までの変更の取り消しを実施します！</dt>

レビューを多く行っていくと、自分のローカルブランチだからと言って過去の変更からの反映されることに忘れてしまいますね。是非、プロジェクト内でのレビューを行うときはお気をつけ下さい〜。

これからも色々と体験を共有できればと思います。

それではまた。

弊社サイト：https://www.winescan.co.jp/
私たちの働きでひとり一人の自分らしさをupdateし続けることができる社会を目指します
アプリがアクティブな時だけ値を保持する方法としてDIを推したい

## はじめに
アプリの仕様で、アプリ起動時に取得（あるいは生成）し、**アプリ起動中だけ**抱えておきたい情報がある時、
- SharedPreferenceやDataStoreに値を保存し、起動時に上書きする
- ViewModelを使う
- DaggerHilt等でDI
といった方法があります。

みんなならどれ使う？
私はDIがいいと思うな〜、という記事です。

## 前提条件
- MVVM + CleanArchitecture
- DaggerHilt使ってる想定
- 値の特徴
  - アプリ全体で共通で使いたい情報
  - 有効期限の短いトークンやサーバの向き先など、Viewとは直接関係のない値
  - どのクラスからでも呼ばれる可能性がある

## DIで管理することに決めた理由
- 値の性質として、アプリ全体で共通で使いたい情報だから
- ViewModelの役割は「画面やUIコンポーネントに対し、何らかの働きかけを行う値や処理そのものを持つこと」で、この値はViewとは直接関係のない値だから
- Repository層と連携させたい値だから
  - ViewModelにしてしまうとRepository層にViewModelをInjectすることになる、ここに違和感があったから
- SharedPreference等、不揮発性の場所に格納すると、ユーザーが好きなタイミングで消去できるから
  - 設定 > アプリと通知 > アプリを選ぶ > ユーザーデータの消去


異論は認める