OmniAICreator/Qiita-1.07M huggingface dataset:
Python VSCode import文で？？ってなった話

# Pythonの勉強をしていた時のこと
サンプルコードを見ながら、入力してみて動きを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/313e8886-1aa7-b728-f73b-6085e0236036.png)
ふむふむ・・・
「pkg1」と「chapter08」っていうフォルダを作ってその下に「calculator.py」と
「calculator_main.py」っていうファイルを作ればいいのか！
```python:calculater.py
def plus(x,y):
return x + y
```
```python:calculator_main.py
from pkg1.calculator import plus
print(plus(1,2))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/7f215480-7fb6-19aa-7480-e991f95a1870.png)
　　　　↑　実際のワークスペース

よーし、実行だー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/005aa3b4-d3d2-eea2-bbf9-56a6dfaf62f2.png)
（　＾ω＾）・・・・・・ﾌｩ

# 気をとりなおして
わかった！パスの指定がいけないんだ！
ということで
```python:calculator_main.py
from ..pkg1.calculator import plus
print(plus(1,2))
```
こんな感じで書き直してみました。
よし実行！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/e25be28a-1892-31a9-e9fb-4e27d78efc2c.png)
（　＾ω＾）・・・・・・

その後、自分で色々と調べて試してみましたが思うような結果が得られず。。。

（やさしい）上司に頼ることにしました。

すると時間を割いて丁寧に説明してくれました。
こちらでの説明は省かせていただきますが、参考サイトを載せておきますね。
詳しく知りたい方は是非ご参照ください。
[にわこま　ブログ【Python】ImportErrorを解決する方法](https://niwakomablog.com/python-importerror-handling/)

最終的なコードはこちらになります。

```python:calculator_main.py
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))
from pkg1.calculator import plus
print(plus(1,2))
```
実行！
# そしてついに・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2732993/e2b02c7e-f431-8d27-0b11-a123bbf48a45.png)
でました！３です！
いまだかつてこんなに３という数字に執着したことがあったでしょうか・・・。

# おわりに
今回私なりに調べてみたのですが、かなり時間がかかりました。
ところが、上司に相談すると短時間で良い感じの記事を調べてくれました。
すると調べ方にかなり違いがありました。
経験値が足りないのは仕方がないですが、1つの調べ物でいち早く答えが得られれば作業効率も大きく変わってきますよね。
自分もエンジニアに必要不可欠な調べスキルを培っていくとともに、Pythonの勉強をもっと頑張っていきたいと思います！

大きな学びを得たところで、今回はここまでにしたいと思います。
UINavigationControllerのaccessibilityPerformEscape のデフォルト挙動まとめ

# 先に結論
- `modalPresentationStyle = .pageSheet`かつ`isModalInPresentation = false`の場合はスクラブジェスチャでモーダルをdismiss
- それ以外（多分）はpopして、popするものがなくなったら`accessibilityPerformEscape()`を見に行く。

# accessibilityPerformEscape
#### そもそも`accessibilityPerformEscape()`とは...

VoiceOverがオンのときに、二本指のスクラブジェスチャ（二本指でZを描くようなジェスチャ）によって、モーダル（もしくは階層）を閉じるためのメソッドであり、アクセシビリティ要素が特定の動作をサポートするためのメソッド群`UIAccessibilityAction`一つらしいです。

`accessibilityPerformEscape()`の中にスクラブジェスチャによって発火させたい処理（閉じる系以外の処理以外は書かない方が無難ですね）を書くと、スクラブジェスチャによって画面を閉じたり戻したりできます。

試しにVoiceOverを起動して適当なアプリ（SettingsとかSafariとか）を開いてスクラブジェスチャしてみると、popしたりdismissしたりします。

ドキュメント↓

https://developer.apple.com/documentation/objectivec/nsobject/1615091-accessibilityperformescape


# UINavigationControllerにおけるスクラブジェスチャのデフォルト挙動
ところで、ドキュメントによると`accessibilityPerformEscape()`のデフォルト実装は戻り値として`false`を返すようです。
この戻り値は、モーダルが正常に閉じられたかどうかなので、`false`を返すということは中身は空ということじゃないのかなと思います。

なんですけど、`UINavigationController`は何も実装していなくても普通にスクラブジェスチャ効くんですよね、よくわからん。誰か詳しい人教えてください。

というわけで、`accessibilityPerformEscape()`をoverrideする上で`UINavigationController`のデフォルトの挙動に準じた動作をさせられるように、挙動を知っておくことは有意義だと思って色々触ってみたわけです。

試しに以下のような階層のアプリを作りました。
VC1, VC2, Navではそれぞれ`accessibilityPerformEscape()`をoverrideしてdismissするようにしています。
- VC1
    - Nav
        - VC2
        - VC3

ここで、VC3を開いた状態からスクラブジェスチャを複数回行うことでNavの`modalPresentaitonStyle`と`modalInPresentation`を変更してそれぞれどんな挙動をするか、どの`accessibilityPerformEscape`が呼ばれるのかを確認してみました。

以下の表が結果です

|modalPresentationStyle|modalInPresentaion|挙動|呼ばれたaccessibilityPerformEscape()|
|---|---|---|---|
|.pageSheet|true|VC3 -> VC2 -> VC1 | VC2 -> VC1 のタイミングで VC2のメソッドが呼ばれる|
|.pageSheet|false|VC3 -> VC1に遷移 | - |
|.fullscreen <br/> .formSheet <br/> .popOver|true / false|VC3 -> VC2 -> VC1 | VC2 -> VC1 のタイミングで VC2のメソッドが呼ばれる|

他にも`modalPresentationStyle`は定義されていますが、`.pageSheet`以外変化ないので面倒になって確認していません。（誰か...）
多分同じということにしておきましょう！！
OOUI忘備録3章-2 ビューとナビゲーションの検討

### 基本のビュー形式
- オブジェクトを表象するビューには、大きく、コレクションビューとシングルビューがある。
  - コレクションビューは、複数のおぶじぇくとを集合として現すもの。
  - シングルビューは単数のオブジェクトを現すもの。

**人間は身の回りにあるものを眺め、気になるものがあれば近寄ってみる**という行動を繰り返している。

- 眺める(一覧)
- よく見る(詳細)
- 地図やグラフィックアプリケーションなどでは拡大や縮小のズーム表現が用いられる


### メインオブジェクトに「コレクション」と「シングル」のビューを与える

まずは機械的にメインオブジェクトにそれぞれコレクションビューとシングルビューを想定します。

```mermaid
flowchart TD;

subgraph col1[コレクション]
cv1[イベント]
end

subgraph sin1[シングル]
sv1[イベント]
end

col1-->sin1

subgraph col2[コレクション]
cv2[教員]
end

subgraph sin2[シングル]
sv2[教員]
end

col2-->sin2

subgraph col3[コレクション]
cv3[組]
end

subgraph sin3[シングル]
sv3[組]
end

col3-->sin3

subgraph col4[コレクション]
cv4[生徒]
end

subgraph sin4[シングル]
sv4[生徒]
end

col4-->sin4

subgraph col5[コレクション]
cv5[部]
end

subgraph sin5[シングル]
sv5[部]
end

col5-->sin5
```

### シングルビューとコレクションビューの省略

- シングルビュー
  - 「持ち物」オブジェクトの場合、「しおり、お弁当、水筒、着替え」などの一覧だけがあれば事足りる場合は、シングルビューを省略できる。
- コレクションビュー
  - ログインユーザーである自分のアカウント情報のようなものは、アプリケーションの中に1つしかないため、コレクションが必要ない
    - 自分のアカウントのニックネームを変更する
    - 自分の口座の残高を確認する

### コレクションビューとシングルビューの呼び出し関係を検討する

メインオブジェクト同士のつながりとその多重性を手がかりに、ナビゲーションとしての呼び出し関係を考えます。

組と生徒の呼び出し部分について考える

```mermaid
flowchart TB;

subgraph col1[コレクション]
cv1[組]
end

subgraph col2[コレクション]
cv2[生徒]
end

subgraph sin1[シングル]
sv1[組]
end

subgraph sin2[シングル]
sv2[組]
end

col1 --> sin1 --> col2 --> sin2

sin2 --> sin1

```

矢印線がナビゲーションの遷移の方向を表す。

- メインオブジェクト同士のつながりと多重性から参照可能性を導き出し、呼び出し関係を定義する
- 
- 参照可能性のない関係については、つなげないでおく。
- すべての参照可能性をUIとして実装する必要がない場合が多いので、画面を想像しながら行う

「部」や「教員」オブジェクトを追加していく(省略)

### メインオブジェクトの中からルートナビゲーション項目を選定する

ルートナビゲーション項目選定
- 全体から考えて特に重要なオブジェクトを選ぶ
- ユーザーがアプリケーションを使う際に、思考の起点となりそうなオブジェクトを選定する
- 特定のオブジェクトからしか呼び出されないオブジェクトや、ユーザーが参照する頻度が少なそうなオブジェクトは、優先順位を下げて考える。
  - 全体から考えて重要であれば、ルートナビゲーションの候補となる。

#### ルートナビゲーション選定注意事項
- ルートナビゲーションには、メインオブジェクトの中から特に大事なものを並べる
- ユーザーがアプリケーションを使用する際に最初に思い浮かべるオブジェクトを選択する
- アプリケーションを「機能」ではなく「もの」が並んでいるイメージで捉える
- 動詞ではなくオブジェクト名を用いる
- オブジェクト名の語尾に**管理、一覧、閲覧、確認、照会、参照、登録、情報、編集などを付与しない**
- ユーザーがルートナビゲーションを選択すると、そのオブジェクトのコレクションビューが表示される。(コレクションビューが省略されている場合は除く)

#### ルートナビゲーション項目のラベリング

冗長なので次のような文言は項目名の末尾に不要

- 〜システム
- 〜一覧
- 〜管理
- 〜確認
- 〜参照
- 〜照会
- 〜情報
【AWS】安全なリリース方法

# 安全なデプロイ
どんなに完璧なシステムを構築したと思っても、いざリリースしたときに何らかの問題が起こってしまうことは往々にしてあります。問題が起きてしまった時の被害をできるだけ最小限に食い止める体制を整えておく必要がある。
AWSでは様々なデプロイ方法が用意されているので、適切な方法を選択する。


# ブルーグリーンデプロイメント
ロールバック（問題なく動作する時点のプログラムに戻してあげること）しやすいリリースの方法として、ブルーグリーンデプロイメントがある。

稼働中のシステム（ブルー）
リリース後のシステム（グリーン）

を別々に用意してあげて、切り替える形でリリースを実行する。万が一問題が起きたらブルーに戻してあげれば済む話。


# All at Once方式
お馴染みのElasticBeanstalkで提供されているデプロイ方式。
全ての「既存の」インスタンスに一気にデプロイしてしまう方式。一気にやるのでデプロイまでの時間がめっちゃ早い。
ただし一気にやるので、少しの間サービス停止状態になってしまう可能性あり。


V1のバージョンを。。。。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2665477/da0a52c0-7381-52b3-4bc6-87abff95fb80.png)
画像引用：[AWS Elastic Beanstalkで使えるデプロイポリシーを理解する](https://dev.classmethod.jp/articles/elastic-beanstalk-deploy-policy/)

まとめて一気にV2に変更するデプロイを実行する！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2665477/10bc027e-343b-266b-0f19-3357dc3f7e71.png)
画像引用：[AWS Elastic Beanstalkで使えるデプロイポリシーを理解する](https://dev.classmethod.jp/articles/elastic-beanstalk-deploy-policy/)

# 参考
https://dev.classmethod.jp/articles/elastic-beanstalk-deploy-policy/
Docker for Windows のセットアップ

ローカルの Windows PC に Docker をセットアップする必要が出てきたので手順を記録します。
# 環境
- Windows 10 Pro （バージョン21H1）
# セットアップ手順
## インストーラーダウンロード
こちらのページからダウンロードします。
https://www.docker.com/products/docker-desktop/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/4f9ea684-cd2b-c48c-0714-8a0d488aafc5.png)
## インストール実行
ダウンロードしたインストーラー（Docker Desktop Installer.exe）を実行します。
チェックボックスはデフォルトのまま（2つともチェック状態）にし、OKをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/4136ccc8-cbcf-20f4-1b5b-f979297960b7.png)
インストールが始まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/de598777-36e5-5444-b310-e2d3d212a8ca.png)
この画面になれば完了です。
[close and restart] をクリックすると Windows が再起動されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/a074fcf8-aba5-59b7-5acc-a22bfeec6c1a.png)
## Our Service Agreement has Changed
Windows が再起動されログインすると [Our Service Agreement has Changed] という画面が表示されます。
[I accept the terms] にチェックを入れ、[Accept] ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/32f01c4a-b402-e7e1-0ff7-ef7ead33f0e4.png)
## カーネルのアップデート
次に [WSL 2 installation is incomplete.] というダイアログが表示されます。（インストール済みの場合は表示されないようです）
なお、同時に Docker のウィンドウが開くことがありますが、閉じずにそのまま置いておきます。
ダイアログの **ボタンはクリックせず**、リンクをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/5a144d12-1587-a564-c3bb-5374fc119d18.png)
ブラウザで次のページが開きますので、[x64 マシン用 WSL2 Linux カーネル更新プログラム パッケージ] のリンクをクリックすると wsl_update_x64.msi がダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/1e05e89a-cf65-1452-537c-bbe507016811.png)
ダウンロードされた wsl_update_x64.msi を実行します。
ウィザードに従ってインストールし、完了画面で [Finish] をクリックしてウィザードを閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/4c1ab295-9e43-879e-7433-755223971411.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/10eb9b55-8657-fdcc-d495-45673ce5f072.png)
## Docker 再起動
そのままにしておいたダイアログの [Restart] ボタンをクリックします。
Windows の再起動ではなく Docker の再起動です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/6ed79bb1-8c80-6939-843f-2e4e80a17b26.png)
## Docker Desktop 起動
Docker 再起動後、チュートリアル開始画面が表示されますが、[slip tutorial] をクリックしてスキップしても構いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/cb3075f5-5043-0fd0-a05b-3299d4f52749.png)
この画面が表示されたらセットアップ完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200478/5d82c6b5-69f3-fb46-b42f-b00378badb20.png)
piユーザー廃止に伴う、4GPi OSの初期ログインユーザー作成方法

メカトラックス株式会社の@kakuutaです。

[4GPi](https://mechatrax.com/products/4gpi/)のOSイメージがリリースされたので、初回起動時の設定(ユーザー作成～ログイン）を行います。OSイメージの詳細は[こちら](https://github.com/mechatrax/4gpi/blob/main/os/Readme.md#%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88)
今回（4gpi-bullseye-lite-armhf-20220711以降）から初期ログインユーザーが設定されておりません。設定方法は2通りあるのでご紹介します。
※本家Raspberry Pi OSの意向に沿って、piユーザーは使用しておりません。

なお、4GPiの設定方法は以下を参照して頂ければ幸いです。

https://qiita.com/kakuuta/items/2c021b2f65a3748eb36f

# [方法 1]Raspberry Piをモニターと接続して設定する
初回起動時にモニターと接続して設定します。
## 用意するもの
・モニター
・Raspberry Pi
・PC
・microSDカード
・カードリーダー
・HDMIケーブル
・キーボード
・ACアダプター（12V/2A）

## OSイメージをSDに書き込む
以下を参照してOSイメージをSDに書き込みます。

https://qiita.com/kiyonaga/items/73fa842ddcde0e028294

## モニターと接続し設定する
1. キーボードとモニターをRaspberry Piに接続します。
2. 書き込み完了したSDカードをRaspberry Piに接続し、電源を入れ起動します。 
3. 起動後、ユーザーネームを入力します。
※ユーザーネームに大文字、先頭に数字は使えません。
![Username.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636124/5c7de4bb-3e11-8175-04f9-9a46b3347903.jpeg)
4. パスワードを入力します。
![password2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636124/bb5c9232-628f-5d8c-70c3-19b55645b3f5.jpeg)
5. もう一度パスワードを入力します。
![Confirm_Password.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636124/5b624102-35ab-c627-1987-9ba626423ed3.jpeg)

入力後、そのままログインできるようになります。

# [方法 2] Raspberry Pi Imager から設定する
Raspberry Pi OS書き込みソフト[Raspberry Pi Imager](https://www.raspberrypi.com/software/)のオプションで設定します。

## 準備するもの
・ラズパイ
・PC
・microSDカード
・カードリーダー
・Raspberry Pi Imager (今回はv1.7.2を使用）

## Raspbberry Pi Imagerのオプションを設定する
1. SDカードをパソコンに接続します。
2. Raspberry Pi Imagerを起動し、[OSを選ぶ > カスタムイメージ]を選択して
使用するイメージを選択します。
3. Raspberry Pi Imagerのウィンドウがアクティブな状態でCtrl+Shift+Xを押します。
するとオプションウィンドウが出現するので、ユーザー名とパスワードを設定します。
![RaspberryPi_Imagerpassword.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636124/5ae46d32-c618-484d-b69d-2837a466d585.png)


設定を保存し、[ストレージを選ぶ]でSDカードを選択して、書き込みます。

## 起動確認
書き込みが完了したSDカードをRaspberry Piに接続し、電源を入れて起動します。
パソコンとUARTで接続してログインできるか確認してみます。
![Login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2636124/bdafdf36-4389-c372-33b2-f50b9f40b859.png)

無事にログインできました。

# 最後に
初回起動時の設定(ユーザー作成～ログイン）をまとめました。
4gpi-bullseye-lite-armhf-20220711以降のリリースでは初回にログインユーザーの作成が必須になりますので、注意が必要です。
mysql batファイルを用いて、mysqlサーバーのデータベースに接続

<H1>サーバーのパラメータをいれる</H1>

```bat
REM mysql.exeがあるディレクトリパス(適時修正)
set MYSQLPATH=C:\Program Files\MySQL\MySQL Server 8.0\bin\
REM 接続情報
set PASS=パスワード
set USER_ID=ユーザーID
set DB_NAME=データベースの名前
set OPTION=--default-character-set=utf8
REM スクリプト実行
"%MYSQLPATH%mysql.exe" %OPTION%  %DB_NAME% -u %USER_ID% -p%PASS% -D %DB_NAME%
```
postmanでLINE WORKSのコンテンツアップロードする！

LINE WORKSで画像を使用したいとき（プロフィール写真やBotのリッチメニューを設定するときなど）があると思います。
APIから操作する場合にどうしたら良いんだろう。。。と思いまして、今日恥かしい思いをしたので忘れないように手順を残しておこうと思います。

## 悩んだポイント
たまたまLINE WORKSのBotの[リッチメニュー](https://developers.worksmobile.com/jp/reference/bot-richmenu-create?lang=ja)について調べていました。（Bot作成する技術なんかない癖に）

冒頭に以下のような記述がありました。

>Botのリッチメニューを登録する。
Botのリッチメニューを使用するためには、追加で以下の手順が必要。
>
>リッチメニュー画像のアップロード
>アップロードした画像をリッチメニュー画像に設定
>既定リッチメニュー、またはユーザー別リッチメニューを設定

なるほど、画像をアップロードして、設定する必要があるんだなと。

じゃぁそれはどうやるんだい？って話です。

アップロードについては[ドキュメント](https://developers.worksmobile.com/jp/reference/bot-attachment-create?lang=ja)がありました。

コンテンツアップロードというAPIですが、ファイル名をBodyに書いてリクエストするだけなのか！と思い早速実行です。

はい。実行はできました。
uploadUrlとfileIdというものがresponseされましたね。

![01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740500/19c6b082-2a09-9319-3096-8ef31e99dac7.png)


で、その後なんですけど、このドキュメントの冒頭に以下の記載があります。

>Botで使用するファイルや画像をアップロードするためのアップロードURLとファイルIDを生成する。
>生成されたURLにファイルをアップロードする。

なるほどね、アップロードURLにファイルをアップロードね！

ふーん。。。。。。**で！？**

いやいや、待ってくれと。
私が知りたいのはその方法なんですよと。

もうやっぱり自分には無理なんじゃないかなと諦めましたが、知見のある方が教えてくれました。

## postmanを使用したアップロード方法
まずpostmanで以下のように入力・設定します。

* メソッドはPOST
* アップロードURLをそのまま貼り付け
* form-dataを選択
* KEYに「resourceName」と入力

![02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740500/addfb378-1e73-90bb-8614-848a1d760427.png)

VALUEは「値」ってことだと思うので、ここにファイル名を入力するの？とか思ったんです！

赤枠のあたりにマウスオーバーすると、「TEXT」という表示が出てきます。
これをクリックすると.....
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740500/1e370635-ac6a-6818-0a04-3804a1f0c5e1.png)

「File」という選択肢が出てきます！
こちらを選択して....
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740500/467cd812-fd90-3146-fedb-e966e922e197.png)

「Select Files」をクリック！
あとは画像を選択して、Sendすれば完了です！！！！！！
![05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740500/be53046c-c967-5773-23e9-1ef3974e9cd6.png)

私は「TEXT」のままで何度もファイル名を入力してはエラーになる、何度殴っても壊れない壁をひたすら殴り続けるというファミコンのバグったNPCみたいな行動をとっていました。
某文豪は「恥の多い生涯をおくってきました」と言っていましたが、私はその真っ最中です。。。。(;_;)
[GSS] カスタム数式で複数文字列の完全一致でフィルタする

GSSのフィルタを有効化したあと、特定のカラムのフィルタで、特定の複数の文字列に合致するレコードに絞り込みたい。

例えば、A列にaaa, bbb, ccc, ddd.. と文字列が入ってて、その中からA列がaaa, bbb, cccの文字列のレコードだけに絞りたい。

やりたいことはシンプルだが、難しかったのでめも

- フィルタを有効にする
    - フィルタボタンをクリックすればOK
- フィルタかけたいカラムのフィルタボタンをクリック
- 条件でフィルタ
- カスタム数式
- 以下を入力
```
=REGEXMATCH(A2,"^aaa$|^bbb$|^ccc$"
```
- OKをクリックして適用

# 解説

- REGEXMATCHで正規表現検索
- A2と指定すると、Aカラムの2レコードから最終セルまでを範囲に取る。イメージ的にはA2:Aという感じ。1レコード目がヘッダーの場合はこれでOK
- フィルタ対象の文字列を"で囲う。複数の文字列を指定するには、|で区切るとOR検索になる。各文字列を完全一致するために各文字列を^と$で挟む。この指定がない場合は、部分一致になる。
python batファイルを用いて仮想環境のactivate - cmd /k -

<H1>batファイルを用いて仮想環境のactivate注意点【cmd /k】</H1>

```bat
cd \venvで作った仮想フォルダ\Scripts
call activate
cmd /k
REM cmd /k をいれないとすぐ閉じてしまう。
```
【PHP】PHPで<br>を最後に出力しない方法

# コード1
```PHP
<?php
$contents = ['ナルト','サスケ','我愛羅','ボルト'];
$list = '';
foreach($contents as $chara){
    $list .= !empty($list) ? '<br>':'';
    $list .= $chara;
}
echo $list;
```

# 結果
```
ナルト<br>サスケ<br>我愛羅<br>ボルト
```
# コード2
```PHP
<?php
$contents = ['ナルト','サスケ','我愛羅','ボルト'];
$br = '';
foreach($contents as $chara){
    echo $br?:'';
    echo $chara;
    $br = $br?:'<br>';
} 
```

# 結果
```
ナルト<br>サスケ<br>我愛羅<br>ボルト
```
ある列全体を、別の列のとある値で規格化したい

目標はタイトルの通り。
ここでは、とあるファイルdata.txtの4列目を、3列目の一行目（3列目の一番初め）で規格化したいとする。

列全体における操作なのでawkを使ってみる。
まず最初にしないといけないのは、3列目の一行目（3列目の一番初め）を抽出して変数KIKAKUに格納すること。
そのために、
```
KIKAKU=$(awk NR==1'{print $3}' data.txt)
を行う。
```
続いて、規格化を行い、結果はdata_kikaku.txtにいれるとすると、
```
awk '{print $1,$2,$3,($4/KIKAKU)}' data.txt > data_kikaku.txt
```

###注意
KIKAKUが0の場合は割り算ができないので、「0でなければ」という条件を付加する。
```
cat data.txt | awk '
{
   if (KIKAKU != 0 ) {
     print $1,$2,$3,($4/KIKAKU)
    }
}
'
```
と条件をつける。
awk内におけるif構文では、!=がnot equalを表す。
逆引き：親子関係を持たせた Instanciate() 時の生成位置まとめ

すごく今更ですが、逆引きできるものが見つけらなかったので備忘録としてまとめときます。
コメントについて有識者様のご助言いただけますと幸いです。よろしくお願いいたします。


## 親の local 座標の(0, 0, 0)に生成
```c#
Instantiate(prefab, parentTransform);
```
```c#
Instantiate(prefab, parentTransform, false);
```

## world 座標の(0, 0, 0)に生成
```c#
Instantiate(prefab, parentTransform, true);
```
これ何に使えるんだろう...

## 親の local 座標の任意位置に生成
```c#
GameObject obj = Instantiate(prefab, new Vector3(1, 2, 3), Quaternion.identity);
obj.transform.SetParent(parentTransform, false);
```
```c#
GameObject obj = Instantiate(prefab, parentTransform);
obj.transform.Translate(1, 2, 3);
obj.transform.Rotate(0, 0, 0, Space.Self);
```
割と頻出処理な気がするんですが、Instantiate()一発でいけないんでしょうか

## world 座標の任意位置に生成
```c#
Instantiate(prefab, new Vector3(1, 2, 3), Quaternion.identity, parentTransform);
```
```c#
GameObject obj = Instantiate(prefab, parentTransform);
obj.transform.SetPositionAndRotation(new Vector3(1, 2, 3), Quaternion.identity);
```

## まとめ
```Instantiate(prefab, parentTransform)``` で親子関係だけ定義して、そのあとに ```Transform.Translate()```＋```Transform.Rotate()``` か、```SetPositionAndRotation()``` で、位置＋回転を定義するのが、シンプルで混乱が少なくて良さそうに見えます。ただし、[Updete()ループ内で Instanciate()と同時指定しない位置設定は、次の FixedUpdate() が呼ばれないと更新されない](https://qiita.com/yuki2006/items/46b9aafeb2a391b3120b)らしいので、少し意識する必要はありそうです。
EC2 Ubuntu の openssl を最新にした時にしたこと

$ which openssl
$ ldd /usr/bin/openssl
$ openssl version
$ cd /usr/local/src/
$ sudo wget https://www.openssl.org/source/openssl-3.0.5.tar.gz
$ sudo wget https://www.openssl.org/source/openssl-3.0.5.tar.gz.asc
$ gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C
$ gpg -d openssl-3.0.5.tar.gz.asc
$ sudo tar xvf openssl-3.0.5.tar.gz
$ cd openssl-3.0.5/
$ sudo ./config
$ sudo apt-get update
$ sudo apt-get --fix-broken install
$ sudo apt-get install gcc
$ sudo ./config
$ gcc --version
$ sudo make
$ sudo make install
EFCoreでdbo以外のSchemaを指定する

## はじめに

EntityFrameworkCoreでDBを作成すると、テーブルはdboスキーマに作成されます。

> ![dbo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275170/afac6693-c88d-a6d6-ed8a-c5e6fa4e1683.png)

今回はefcoreでdbo以外のスキーマを作成します。

## やること

モデルで設定するTable属性にSchemaプロパティがあるので任意の名前を指定します。

```UserProfileEntity.cs
                                 // ↓
    [Table("UserProfile_Schema", Schema = "test")]
    public class UserProfileEntity
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        public string UserName { get; set; }
    }
```

この設定をした上で再度マイグレーションを行うとマイグレーションファイルにスキーマ関連の記述が追加されています。

```Migration.cs
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.EnsureSchema(
            name: "test");

        migrationBuilder.CreateTable(
            name: "UserProfile_Schema",
            schema: "test",
            //...
    }
```

実際のデータベースではtestスキーマが追加されます。

> ![schema.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275170/4eb55cf9-1f5e-f1a9-512e-c36c98861073.png)

### __MigrationHistoryテーブルのスキーマを変更する

このままでは変更履歴テーブル(__EFMigrationsHistory)のスキーマはdboのままなのでこちらも合わせて変更します。

```MyDbContext.cs
    public class MyDbContext : DbContext
    {
        //...

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
                optionsBuilder.UseSqlServer(ConnectionString,
                // ここを追加 
                x => x.MigrationsHistoryTable("__EFMigrationsHistory", "test"));
        }
    }
```

データベースを更新することで反映されます。

> ![migrationhistory.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275170/1fb94d50-3b19-d1d4-4208-92fc5316642e.png)

- [参考](https://docs.microsoft.com/ja-jp/ef/core/managing-schemas/migrations/history-table)
grep 使い方

## 検索したい言葉が入っているファイルを探したい時
```
grep <検索したい言葉> -rl 
```

-r ：ディレクトリ内も検索対象とする
-l :検索結果にファイル名のみ表示

その他オプション参考サイト：
・https://eng-entrance.com/linux-command-grep
・https://www.ibm.com/docs/ja/aix/7.1?topic=g-grep-command
NextPageって使わなくちゃだめ?? React.FCとどう違うの?

# `React.FC`と`NextPage`ってどう違う？

## 型自体について

`React.FC`は

```typescript
type FC<P = {}> = React.FunctionComponent<P>
```
だいぶ汎用的

対して`NextPage`は
```typescript
type NextPage<P = {}, IP = P> = React.ComponentType<P> & {
    getInitialProps?(context: NextPageContext): IP | Promise<IP>;
}
```

となっています.
大きな違いは`getInitialProps`でしょう.

## getInitialPropsについて

[getInitialPropsのドキュメント](https://nextjs.org/docs/api-reference/data-fetching/get-initial-props)によると

> getInitialProps enables [server-side rendering](https://nextjs.org/docs/basic-features/pages#server-side-rendering) in a page and allows you to do initial data population, it means sending the [page](https://nextjs.org/docs/basic-features/pages) with the data already populated from the server. This is especially useful for [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization).

### ちなみに

[pagesの公式ドキュメント](https://nextjs.org/docs/basic-features/pages)によると

> By default, Net.js is **pre-renders** every pages.

## まとめ
 - `React.FC`はその名の通り一般的な関数型コンポーネントに対して用いることができる型．pageに対しても使用することはできると思う．
 - pageを構成するコンポーネントに必要な要素が絞れる(さらにNextjsではroutingのシステムを提供している)ため，Nextjs側がpageを構成するコンポーネントを定義することで,routingシステムをより強く設計でき

### **pageコンポーネントには`NextPage`を使おう**
firebase loginの認証

localhostに飛ばされてしまって、うまくいかないかなーって思ったけど、
ローカルネットワークだったらLAN内のIPに変えたらちゃんと認証された。
ラッキー

自分がわすれないように。



![スクリーンショット 2022-07-22 164228.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43608/275c9adc-c222-c15f-626b-57db7c6c0343.png)
HTMLの基礎知識（星評価の平均）

今日もプログラミングしていますか？:sunny:

今回は星機能の平均の出し方を実装していきたいと思います！！




<dt>＊注意
ここでは以下の詳細ページの実装が大前提となっております！！！</dt>


"https://qiita.com/tomo089/items/246230912c32aa5c7864"
<br>
<dt>Step1:コントローラーの追加</dt>

```:tweets_controller.rb
def show
      @tweet = Tweet.find(params[:id])

       @reviews = @tweet.reviews
       @review = Review.new
　　　　#変更箇所
       @totals=@reviews.average(:eve)
　　　　#ここまで   
       
    end
```

<dt>Step2:Viewの追加</dt>


```:tweets_show.html.erb.
 <p>平均評価</p>

  <span class="star-rating">
   <span class="star-rating-front" style="width:  <%= getPercent(@totals) %>%;">★★★★★</span>
   <span class="star-rating-back">★★★★★</span>
</span>
```

<dt>Step3:確認！！！</dt>

![スクリーンショット (61).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738887/45b547fa-a07c-ee06-7a7e-36cf33c905a4.png)

以上になります！！
簡単でしょ！！！
ぜひ実装してみてください！！
R で、複数の時系列プロットを重ね描きする方法

# 目的
R を使って、複数の時系列データのプロットを重ね描きする。データ毎の色分けを、ランダムな配色にしたい。



### PC の環境
Windows 10


# 前準備
今回使用する R のパッケージをインストールする。
#### 1. tidyverse
データ解析に有用なパッケージコレクション。グラフを作るggplot2 や、データ加工ができる tidyr などのパッケージが含まれている。

#### 2. rondomcoloR
ランダムな配色ができるパッケージ。
多データの円グラフを作成するときなど、特に有用だと思う。

```R
install.packages("tidyverse")
install.packages("randomcoloR")
```

# 時系列データの作成

今回は、A,B,C,D,....,Z の26地点で、1日目から7日目までの7回温度を測定した結果の
時系列データのプロットを作成することを目的に、進めていく。

まずは、その時系列データを作成する。

```R
# データの作成
# 今回は、AからZの26地点において、温度測定（7回測定) の結果を想定している。
m <- matrix(rnorm(n=7*26, mean = 25, sd= 5), nrow = 7)
m <- cbind(c(1:7),m)
data_m <- data.frame(m)
colnames(data_m) <- c("day", LETTERS)
```
上記のコマンドにより、1列目に日付、2列目から27列目に A,B,C,D,....,Z の温度が並んだデータフレーム"data_m" が作成された。

# データの整列
次に、時系列プロットの重ね書きに適した形に、データフレームを整列させる。

今回Rでグラフを描く方法では、プロットするデータの xとy が1対1対応している形にデータを整形させないといけない。
したがって、26x7=182行の縦長のデータに、"data_m" を整列させる。

```R
# データ整列に必要な "tidyr" パッケージを含む、"tidyverse" を呼び出す。
library(tidyverse)

# 各地点の温度変化を示す折れ線グラフを作成するために、データを整列。
# データを縦長に変更
data_long <- pivot_longer(data = data_m, 
                          cols = -day, 
                          names_to = "Place", 
                          values_to = "Temperature")
```

これによって、1列目は日付、2列目は観測地点、3列目は温度を示す縦長のデータフレーム"data_long" ができた。


# 時系列データのプロットの重ね描き
データフレーム"data_long" からプロットを作成すると、時系列データを重ね描きしたプロットが作成される。

```R
# 折れ線グラフを作成
graph <- ggplot(data_long, aes(x = day, y = Temperature, color = Place))
graph <- graph + geom_line()
graph
```

これによって、作成された"graph"は、以下のグラフ。
![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608299/f24af143-cda2-6acf-ae6b-f18a15147899.png)

右に示される凡例をみると、AからZの26データの色分けが、グラデーションになっているのが分かる。R で一定数以上のデータをプロットする場合、自動的にグラデーションカラーが適用される。
R には、様々なカラーパレットが用意されているが、そのほとんどは1限られたデータ数（例えば、12色までなど）にしか適用できない。
折れ線グラフでは、あまり弊害がないかもしれないが、円グラフとなるとデータ凡例が分かりづらくなる。


# ランダムな色で配色したグラフの作成
そこで、ランダムな色を生成できる "rondomcoloR" パッケージを利用する。

```R
# ランダムな色を配色した、折れ線グラフを作成
graph2 <- ggplot(data_long, aes(x = day, y = Temperature, color = Place))
graph2 <- graph2 + geom_line()
plot_color <- randomColor(26,hue="random")
graph2 <- graph2 + scale_color_manual(values = plot_color)
graph2
```
これによって、作成された "graph2" は以下の通り。
![graph2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2608299/70d25cb1-e384-7565-6056-4d042608225d.png)

データの並びに関係ない配色となった。

以上！
備忘録 LeetCode-83. Remove Duplicates from Sorted List

## はじめに
この記事はアルゴリズム振り返り用メモ.
言語化練習用に作成した記事です.
### URL
[Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/ )
## 対象者
特になし
## code
```
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        //アドレスをコピーする
        ListNode* copy = head;
        
        //現在の位置 && 次の位置が nullになるまで続ける
        while(copy != nullptr && copy->next != nullptr){
            //現在の位置　と　次の位置が一致している場合　
            //次の位置　を　次の次のnodeで上書きする
            if(copy->val == copy->next->val)copy->next = copy->next->next;
            //一致していない場合 次のnodeに更新する
            else copy = copy->next;
        }

        //アドレスを変更していたのでheadを返す
        return head;
    }
};
```
## 結果
Runtime: 17 ms, faster than 50.06% of C++ online submissions for Remove Duplicates from Sorted List.
Memory Usage: 11.5 MB, less than 97.36% of C++ online submissions for Remove Duplicates from Sorted Lis
## 詳細
headのアドレスをコピーする

現在の位置と次の位置のvalが一致している場合は
次のnodeを次の次のnodeに上書きする
というのを繰り返して連続した重複値を消去している。

headのアドレスをコピーして編集していたため
headが間接的に更新されるので
headを返す.

## 参照
[動画](https://youtu.be/foMqZAL00UU)
## おわりに
今回の問題は前回の[LeetCode-142. Linked List Cycle II](https://qiita.com/IXKGAGB/items/17e71b6c1d34003f2ecf)に比べて簡単に感じた
新卒エンジニア〜これまでの経緯、勉強法、目標〜

# はじめに
新卒1年目のきゃべつと申します。これまでの経緯や今後の目標を振り返り、キャリアアップの計画に役立てたいと思います。

<h3>プロフィール</h3>
・20代女性<br>
・私立大学 家政学部卒業<br>
・2022年4月、ITベンチャー企業へエンジニアとして就職<br>
・現在は研修課題をこなす日々を送る。

<h3>経緯</h3>
小学生の頃からパソコンで動画やゲームをするのが好きでした。<br>
自身のパソコンを持ってからは動画編集やイラストに挑戦するようになり、そこで作成する楽しさを知ようになりました。<br>
そして、2020年にドットインストールでHTML/CSSを使用したサイトの作成をきっかけに、エンジニアへの興味を持ち始めました。

<h3>勉強法</h3>
2020年：ドットインストール、Youtube、プログラミングスクール<br>
2021年：udemy、プログラミングスクール<br>
2022年：プロゲート、udemy、Youtube、LT参加

<h3>今年の目標</h3>
・フロントエンジニアとして、HTML/CSS・JavaScriptの知識を磨く。<br>
・基本情報技術者の資格を取得する。<br>
・LTに登壇者として参加する。<br>
VSCode C++ ヘッダーから宣言/定義の作成を１クリックで実行する拡張機能

![generate-definition.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282788/73c5ef73-8921-e470-dc95-55935643f7b3.gif)
https://marketplace.visualstudio.com/items?itemName=reignofwebber.c-cpp-definition-generator
【Git】コミット前にブランチを移動してはならない理由

# はじめに
Gitを使い始めて間もない新人エンジニアです。
以前コミット前にブランチを移動してしまい、コードが混ざり面倒なことになってしまいました。
その時になかなか仕組みが理解できなかったので、なぜそのような挙動になるのかをこの記事でまとめます。

# 内容
１. コミット前にブランチを移動するとどうなるのか
２. なぜ共有されるのか
３. 番外編：コミットしたくない場合

# １.コミット前にブランチを移動するとどうなるのか
コミットを行わずにブランチを移動する際、移動先と競合する変更があった場合は、下記のようなエラーが発生します。
```
error: Your local changes to the following files would be overwritten by checkout:
       XXXXX.XX
Please commit your changes or stash them before you switch branches.
Aborting
```
しかし競合する変更が無かった場合、そのままブランチを移動することが出来てしまいます。
そして**コミットしていない変更が移動後のブランチに勝手に共有されます。**



# 2. なぜ共有されるのか
このことを理解するには、ブランチの仕組みを理解することが必要です。
## ブランチとは

**Git におけるブランチとは**
> 特定のコミットを指す 40 文字の SHA-1 チェックサムだけを記録したシンプルなファイルです。

引用：[Git のブランチ機能 - ブランチとは](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E6%A9%9F%E8%83%BD-%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%A8%E3%81%AF#rdivergent_history)

したがって、**ブランチはコミットの内容を参照しているにすぎません。**
そのため、**コミットしていない情報をブランチは保持してくれません。**

このことを踏まえて、共有されるまでの流れを以下のモデルを使用し説明します。
<img width="900" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706423/ada58437-b954-a6ff-ebf7-6513e9850500.png">
|○|<font color=d2302f>➡</font>|
|:-----:|:-----:|
|コミット履歴|現在のブランチ|


**ワーキングツリーで編集を行う**
ワーキングツリーでファイル等の編集を行うと、ワーキングツリーのみにファイルの変更が保存されます。
<img width="900" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706423/0ffcdb37-18e1-a9cf-cb7d-846916fbce15.png">

**コミットを行わずブランチを移動する**
移動前のブランチに変更が保持されず、ワーキングツリーにファイルの変更が残っています。そのため移動先のブランチでもその内容を参照することになります。
<img width="900" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706423/c2d24655-024b-11af-ddcb-348a88c43bf3.png">

その結果、コミットしていない変更が移動後のブランチにも共有されます。
したがって、**必ずコミットしてからブランチを移動する必要があります。**

# 3. 番外編：コミットしたくない場合
作業途中にブランチを移動したいが、コミットはしたくないという時に便利なのが**git stash**です。

## git stash
作業中のファイルを一時的に退避してくれるコマンドです。
- **git stash** ： ワーキングツリー内の変更内容を一時的に退避する
- **git stash apply** ： 退避した内容を現在のブランチに適用する

このコマンドを使うことによっても、意図しない共有を避けることが出来ます。
コミットしたくない時に便利ですが、退避したことを忘れないようにしましょう！


# 所感
ブランチの仕組みを誤解していたことが今回のミスの原因でした。
何事も仕組みを正しく理解することが重要だと改めて感じました。

# 参照
- https://www.granfairs.com/blog/staff/git-stash
- https://backlog.com/ja/git-tutorial/stepup/03/
AWS EC2 の SSH アクセスで Permission denied (publickey).

AWS EC2 の SSH アクセスでいきなり接続失敗。
Permission denied (publickey). とのこと。

まずは、単にローカルの Cert PEM ファイルが正しく指定されていないかも。
→ その場合無難に絶対パスで指定したら、うまくいく。
認証付き(ユーザ名とパスワードを伴う)プロキシを超えてzsh環境でHomebrewを使うには

初歩的なことかもしれませんが、あまり他に記事を見かけなかったので、ここに記しておきます。

# 1. 環境設定

.zshenvのどこでもいいので、以下の設定を書き込みます。

<!-- Markdown記法でコード例を書くときは、4文字分スペースを空けて字下げする。 -->
    export http_proxy=http://$ユーザ名:$パスワード@$server:$port
    export https_proxy=$http_proxy
    export HTTP_PROXY=$http_proxy
    export HTTPS_PROXY=$http_proxy

ここで`$ユーザ名`と`$パスワード`はそれぞれプロキシサーバのユーザ名とパスワードです。`$server`はサーバ名(あるいはサーバIPアドレス)、`$port`はポート番号(8080とかが多いんですかね)です。

この設定を即座に反応させるには、以下のコマンドを実行しましょう。

    source ~/.zshenv

ファイル名`.zshenv`の前に`~/`を付けるのを忘れずに！
上記の設定を書き込むのは、`.zshenv`でなくても`.zshrc`でもよいかと思います。

# 2. Homebrewを使おう

あとはHomebrewに関する各種コマンドを実行して、お好きなアプリケーションをダウンロード・インストールしましょう。

# あとがき

`brew upgrade`をしようとしたら突如リポジトリからのダウンロードが不可能になったので、慌てて色々と調べました。皆様のご参考になれば幸いです。
UnityでDIを導入する目的

## VContainerは何のため？を流れを追って見ていく
ここでは一例を挙げて説明していく。

このPJではMVPを採用しているものとする。
例えば、ガチャで排出確率0.1%のものにバグがないか確認したい時があるとすると、本番と同じ設定で行おうとした場合、該当のものを引き当てるまで引き続けるという無駄な行動が増えてしまい、バグ検証どころではなくなってしまう。
そのため、本番とは違うインスタンス（ガチャで該当のものが必ず出るような設定）を作りデバッグをスムーズに進めたい。
この時ガチャの実装をModelで実装していたとする。
↓
すると、Prsenterでは状況（本番かさまざまなデバッグを行うための設定か）に応じてどのインスタンスを使用するか受け取りたい
↓
Modelにインターフェースを作り、本番とデバッグする設定の型を統一することでPresenterで呼び出す際に同じ型で呼び出すことができるようにする（入れ物を作って置ける状態）
↓
条件分岐で呼び出すインスタンスを変える
ここでPresenter内でインスタンスを呼び出したくなく（DI実装にするため）、Prsenterにインスタンスを引数として渡し、コンストラクタでインスタンスを読み込む形にしたい
↓
PresenterにはMonobihaviorがありコンストラクタが機能しない！！
そこで出てくるのがDIコンテナのVContainer

...という流れでVContainerが必要になってくるらしい。

下記、間違いもあるかもしれないがイメージがつきやすいようにコード記載
```C#:Model.cs
public interface IModel
{
    int CalcNewVal(int currentVal);
    PadlockStatus CalcNewStatus(List<int> currentVals);
}

public class ModelS: IModel
{
    public int CalcNewVal(int currentVal)
    {
        if (currentVal == 9) return 0;
        return currentVal + 1;
    }

    public PadlockStatus CalcNewStatus(List<int> currentVals)
    {
        if (currentVals[0] == 1 && currentVals[1] == 1 && currentVals[2] == 2 && currentVals[3] == 3) return PadlockStatus.Unlocked;
        return PadlockStatus.Locked;
    }
}


public class StubModelS : IModel
{
    public int CalcNewVal(int currentVal)
    {
        if (currentVal == 9) return 0;
        return currentVal + 1;
    }

    public PadlockStatus CalcNewStatus(List<int> currentVals)
    {
        if (currentVals[0] == 1 && currentVals[1] == 1 && currentVals[2] == 2 && currentVals[3] == 3) return PadlockStatus.Unlocked;
        return PadlockStatus.Locked;
    }
}

public enum PadlockStatus
{
    Locked,
    Unlocked
}
```

```C#:Presenter.cs
public class PresenterS : MonoBehaviour
{
    private IModel model;
    [SerializeField] private IView view;
    //[SerializeField] private ViewS view;
    //private ModelS model = new ModelS();

    bool debugflag = true;
    
    private readonly List<int> initialValue = new List<int>() { 0,0,0,0 };

    private PresenterS(IModel model,IView view)
    {
        this.model = model;
        this.view = view;
    }

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

}
```

恐らくここで用いられているインターフェイスの使い方は

https://qiita.com/yutorisan/items/d28386f168f2f3ab166d

ここで言う疎結合を目的としたインターフェイスであると思う。
備忘録 LeetCode-142. Linked List Cycle II

## はじめに
この記事はアルゴリズム振り返り用メモ，
言語化練習用に作成した記事です．
### URL
[Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/)
## 対象者
特になし
## code
``` main.cpp
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        //1つも要素がない場合
        if(head == nullptr || head->next == nullptr)return nullptr;
        
        //fast = 2つ先
        //slow = 1つ先
        ListNode* fast = head;
        ListNode* slow = head;
        
        //fastがnullになるまで続ける
        while(fast != nullptr && fast->next != nullptr){
            //要素更新
            fast = fast->next->next;
            slow = slow->next;
            
            //一致check
            if(fast == slow)break;
        }
        //要素がない場合 && 次の要素がない場合
        if(fast == nullptr || fast->next == nullptr)return nullptr;
        
        //初期位置に設定し直す
        slow = head;
        //slow と fast　が一致するまで続ける
        while(slow != fast){
            //両方1進める
            fast = fast->next;
            slow = slow->next;
        }
        //nodeを返す
        return fast;
    }
};
```
## 結果
Runtime: 7 ms, faster than 92.06% of C++ online submissions for Linked List Cycle II.
Memory Usage: 7.7 MB, less than 35.33% of C++ online submissions for Linked List Cycle II.
## 詳細
![LeetCode-142. Linked List Cycle II.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2736795/f4b74fd5-b2f0-e93f-298d-094a5c13fbe1.png)

ループが始まるまでをA
ループが始まり&折り返し地点までをB
折り返し地点からループ開始地点までをC
何週したかをn

//fastはslowの2倍移動しているのでこのような式になる
fast = A+(B+C)n+B
slow = A+B
A+(B+C)n+B = A+B
2(A+B)=A+(B+C)n+B
2A+2B = A+Bn+Cn+B
A = B(n-1) + Cn
になる

nが1の場合
A = C
ループの開始位置(5)になる

nが2の場合
A = B+2C
ループの開始位置(5)になる

nが3の場合
A = 2B+3C
ループの開始位置(5)になる

nが4の場合
A = 3B+4C
ループの開始位置(5)になる

以降も同じようになる

## 参照
[動画](https://youtu.be/Oz7-VlcTpSQ)
## おわりに
今回も前回に引き続き英語の理解に苦しめられ約40分かかってしまいました。。。
まだまだ動画等で解説を見ないと完全に理解ができないのでより頑張っていきたいです！
VSCode C++ Cpp デバッグでコンソールが閉じないときの対処法

# 結論
launch.jsonを作成する。

# 考察
対象のファイル上でF5押したときにtasks.jsonを作成しファイルがビルドされて、一応の動作確認ができてしまうのでデバッグが実行されていると勘違いしてしまうが、**デバッグは実行されておらず、ビルドしたプログラムが実行しているだけである**

tasks.jsonでビルドして、そのご実行ファイルがある状態でlaunch.jsonを作成してprogramに実行ファイルのパスを指定すれば、workspace内のどこからでもF5を押すことでデバッグを開始できる

※ programとmiDebuggerPathは適当な値を指定する

```launch.json
{
	// IntelliSense を使用して利用可能な属性を学べます。
	// 既存の属性の説明をホバーして表示します。
	// 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
	"version": "0.2.0",
	"configurations": [
		{
			"name": "(gdb) Launch",
			"type": "cppdbg",
			"request": "launch",
			"program": "${workspaceRoot}/project_name/main.exe",
			"args": [],
			"environment": [],
			"cwd": "${workspaceFolder}",
			"stopAtEntry": false,
			"externalConsole": true,
			"MIMode": "gdb",
			"miDebuggerPath": "C:\\mingw64\\bin\\gdb.exe",
			"setupCommands": [
				{
					"description": "Enable pretty-printing for gdb",
					"text": "-enable-pretty-printing",
					"ignoreFailures": true
				}
			]
		}
	]
}
```
UIアンチパターン 決定ボタンを藪に隠す

「即時公開する」がボタン形式でない。メニューの中に紛れているように見える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/6645e180-941c-3eaf-3b67-c0920ce61ca3.png)

隠れんぼか？



<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【Ruby on Rails】Slimでコメントアウトする方法

## Slimでコメントアウトする方法
```
      /             
        .card-body
          h5 ゴリラ
```
このように``/``を記述すると、``/``より下のコードについてはコメントアウトされ、画面で確認をすると非表示となる。
premiere pro 自動でマーカー打つや～つ

既に投稿されている日本語版の動画を
他言語への翻訳テロップを再編集で挿入したいという、かなりの量の編集依頼が来た。

渡されたデータはタイムコードと翻訳文のデータ

これは楽したいと思いましたので作業しました。

テキストデータをエッセンシャルに変換するものは作ってあるので

タイムコードにマーカーを打って、後はShift+Mでマーカー移動するショートカットでトリミング作業行えばいいだけだなと・・・
トリミング作業もマクロ組んでやれば、恐らく数分の作業で終わると見たっ！

とりあえずテキストファイルからタイムコードを打つまで

ちょっと前までこのマーカー打つ関数は用意されていないと思ってたけど、もしかしてあった？


```jsx
//タイムコードのテキストファイルの行ごとに配列に挿入
var mytextArray =[]; 

//テキストファイルを行ごとに読み込み
function readtext(){
var fileDirectory = File.openDialog("Select Text file","");
var myFile = new File(fileDirectory);
    if (myFile.open("r")){
        var myText = "";
        while(!myFile.eof){
            mytextArray.push(myFile.readln())
        }
    }
myFile.close();
}

//タイムコードのテキストファイルを秒数に変換
//ちなみにテキストファイルのタイムコードはフレームは無しで0:00:00ように時間：分：秒で格納されている

function timecodeToSecond(timeString){
    var timeArray = timeString.split(":");
    var hours   = parseInt(timeArray[0]) * 60 * 60;
    var minutes = parseInt(timeArray[1]) * 60;
    var seconds = parseInt(timeArray[2]);
    
    return hours+minutes+seconds
}

//とりまテキストファイルを配列に入れる関数を実行
readtext()

//あとは配列の分だけマーカー作成を実行
//CREATE NEW MARKERS
for (var i=0; i < mytextArray.length ; i++ ){
    var markers = app.project.activeSequence.markers;
    var newMark = markers.createMarker(timecodeToSecond(mytextArray[i]));
}
```


これでとりあえずシーケンスにだ～～～～っとマーカーは打たれました！
あとはマクロ組んで、次のマーカーに移動→リップルトリミング
これの繰り返しで、イージーモードかな！

タイムコードとエッセンシャルテキストを同時に配置する出来るようにやる事も出来るけど、
それは時間ある時に纏めてやります！

とりま自動でマーカー打つや～つのメモでした！
wpfでテーマカラーやアクセントカラーなどのユーザー情報を取得する

# 前置き
皆さんは設定からダークテーマにしたりだとか、ホワイトテーマにしたりだとか、アクセントカラーを付けたりして、大いにパソコンをカスタマイズしていますよね。
当然、wpfソフトではそこら辺の設定を反映できるようにしたいところです。
ですが、取得方法を探すのに時間がかかったのでメモ書きです。
# 前提条件
ここで一つ注意なのですが、これはWindows10(10.0.10240.0)から導入されたメソッドなので、ターゲットバージョンをwindows7からwindows10に引き上げなければなりません。
windows7も対象にするという方々は、従来通りDllImportとかしてやってください。最後にメモはしておきます。
# 取得してみる。
まず、おもむろにプロジェクトのプロパティを開いて、対象をWindows10にします。
これで使えるようになるので
```cs
UISettings settings = new UISettings(); // Windows.UI.Color
var foreground = settings.GetColorValue(UIColorType.Foreground);
var background = settings.GetColorValue(UIColorType.Background);
var accentcolor = settings.GetColorValue(UIColorType.Accent);
```
とかいう感じで適当にコードを打ち込みます。

https://docs.microsoft.com/en-us/uwp/api/Windows.UI.ViewManagement.UISettings

とかいう公式ドキュメントを見ると分かりますが、
このUIのカラー情報などを取得する以外にも、ダブルクリックの許容時間やらEventやらが多々あり、中々にしっかりしています。
ユーザー情報を取得するなら一番楽だと思います。

https://docs.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.uicolortype

UIColorType一覧は上のURLです。参考にしましょう。

アクセントカラーが変更されたら即座に色を変更するのも、ここのイベントハンドラーを使えば行けると思います。

# DllImportを使う
これは参考にした人の完全なパクリなので、あまり書きたくはないのですが、まとめておきます。

```cs: theme.cs
[DllImport("uxtheme.dll", EntryPoint = "#95")]
public static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode);
[DllImport("uxtheme.dll", EntryPoint = "#96")]
public static extern uint GetImmersiveColorTypeFromName(IntPtr pName);
[DllImport("uxtheme.dll", EntryPoint = "#98")]
public static extern int GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail);

public Color GetThemeColor() // アクセントカラー取得
{
    var colorSetEx = GetImmersiveColorFromColorSetEx(
        (uint)GetImmersiveUserColorSetPreference(false, false),
        GetImmersiveColorTypeFromName(Marshal.StringToHGlobalUni("ImmersiveStartSelectionBackground")), 
        false, 0);

    var colour = Color.FromArgb((byte)((0xFF000000 & colorSetEx) >> 24), (byte)(0x000000FF & colorSetEx),
        (byte)((0x0000FF00 & colorSetEx) >> 8), (byte)((0x00FF0000 & colorSetEx) >> 16));

    return colour;
}
```

# 参考

https://stackoverflow.com/questions/37774307/c-get-windows-8-1-10-selected-color-theme

https://github.com/File-New-Project/EarTrumpet/blob/d4acc41d5ac9dc4b5fb7d6165fe853d70c729940/EarTrumpet/Interop/Uxtheme.cs

https://docs.microsoft.com/ja-jp/windows/win32/api/dwmapi/nf-dwmapi-dwmgetcolorizationcolor?redirectedfrom=MSDN

http://grabacr.net/archives/6671

https://www.fixes.pub/program/180127.html

https://nishy-software.com/ja/dev-sw/metroradiance-fork-1/

https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/1062wpfthemes2/wpfthemes2.html

https://github.com/vb2ae/WPFLightDarkMode
AI OCRが搭載された帳票電子化ツール AI JIMY Paperbotを使ってみた

# AI OCRについて調査

### AI OCRとは

OCRは、画像データのテキスト部分を認識し、文字データに変換する認識機能のことを言います。具体的には、紙文書をスキャナーで読み込み、書かれている文字を認識してデジタル化する技術です。

人間は、紙に書かれている文字を無意識に理解しますが、コンピューターは自動的に読み取ることが出来ません。

そのため、紙に書かれた文字をデジタルデータとして活用するには、一度、人間が読み取って文字に変換する必要があります。これがデータ入力と呼ばれるものです。しかし、単に文字を入力するという作業は非常に効率が悪く時間がかかります。この作業を人間の代わりに行ってくれるのがOCRです。

AI OCRは、OCRにAI技術を加えたものです。AI技術を組み合わせることで、手書き文字も読めるようになりました。

***

### AI OCRの現状

近年、中小企業では人手不足が深刻化しています。
そこでAI OCRを使用することでデータ入力の人件費を抑え、作業の効率を上げることが出来ます。
しかし、現状業績50億未満の中小企業でのRPAの導入率は11%、そのうち、AI OCRを導入しているのは4%と低い数字になっています。

その原因はコストがかかってしまう点であると考えます。
従来の製品では文字を読み取る際に、読み取る項目ごとにコストがかかってしまい、項目数が多いほど料金が高くなります。

また、AI OCRのみでは文字をデータ化することはできてもExcel等のアプリケーションに入力はできません。データの入力までを行おうと思うと別途RPAツールや仕分けツールが必要になってしまいます。

# ツール選択背景
出力したデータを他のアプリケーションに入力する際に別のツールが不要で、１つのツールで完結するものがないか探していました。また、読み取り項目ごとに料金が加算されていくと、コストがかかってしまう点が気になるポイントでした。そこで見つけたのがAI JIMY Paperbotというツールでした。

[AI JIMY Paperbot公式サイト](https://aijimy.com/)

# AI JIMY Paperbotについて

AI JIMY Paperbotはスキャンから文字認識、データ入力まで紙のデジタル化に必要な機能がすべて搭載されているとの事でした。

AI OCRのデメリットであったコスト面も、読み取る項目ごとではなく、帳票一枚単位のためコストを抑えることが出来ます。また、スキャンからデータ入力までの工程を１つのツールで完結することができ、従来のAI OCR、RPAツール、仕分けツールを組み合わせて使用するよりランニングコストも10分の1以下で運用可能です。

さらに、AI JIMY Paperbotではリアルタイム処理やカメラと連動してスキャンをすることができます。既存製品のRPAとAI OCRを組み合わせた場合と、AI JIMY Paperbotとの違いを表にまとめてみました。

|  | 既存製品の組み合わせ | AI JIMY Paperbot |
|:-----------:|:------------:|:------------:|
| ツール数 | RPA ＋仕分けツール + AI OCR | 統合型 |
| RPA | むずかしい | 比較的簡単 |
| リアルタイム処理 | 不向き | 可能 |
| スキャン機能 | なし | カメラと連動可能 |
| コスト | 利用代金と導入開発費用 | 利用代金のみ |

***

### AI JIMY Paperbotの作成手順

AI JIMY Paperbotのワークフローの作成手順は以下の通りです。

- 取り込み（スキャン）
- 仕分け
- 文字認識
- データ出力
- RPA（データ入力）

それぞれの手順の詳しい説明はAI JIMY Paperbotの[ナレッジベース](https://knowledge.aijimy.com/article-categories/ai-jimy-paperbot/)で確認することができました。

***

### AI JIMY Paperbotの認識率

実際にAI JIMY Paperbotを使用して認識率を検証してみました。
その結果、印字された文字は90%、手書きの文字は86%という結果になりました。
認識率は100%ではありませんが、これはどの製品を使用しても100%になるのは難しいと感じました。例えば、1（いち）やl（エル）の違いは前後の文脈から判断しなければなりません。手書き文字であるとなおさら区別が難しいです。
AI JIMY Paperbotでは認識結果を確認・修正できる設定があるため、読み取りを完全にAI OCR任せにするのではなく、人間が結果を確認すると良いと思います。
人間が確認を行うと100%自動化ではないと思うかもしれませんが、今までは手書き伝票を目で読みながら入力していました。それに比べると、作業が認識結果の確認・修正だけになるため、大幅に業務の効率化を図れると思います。

## 使ってみた感想

### 良かった点

* ワークフローが簡単に作成できる
>各項目の設定画面がわかりやすく、プログラムを触ったことのない人でも作成することができると思いました。RPAの部分もシンプルな作りで、組み立てるだけでシナリオが作成できます。

* データの入力可能
>他の製品では別途ツールを導入しなければ入力を行えませんが、AI JIMY Paperbotでは入力まで一つのツールで行うことができます。RPAを使用することで条件式等も指定できるため、特定のデータだけを入力することも可能です。

* コスト削減
>従来の製品に比べて項目ごとに課金するシステムではないため、読み取りたい項目が多い場合でもコストを抑えることができます。また、別途ツールを導入する必要が無く、運用コストも従来の製品の10分の1以下にすることが可能です。

***
### 良くなかった点
* RPA機能
>RPA機能というより転記機能でした。CSVファイルを出力できるので、複雑な処理はPowerAutomateなどを使うのが良いと思います。

***

### 使う際の注意点

* チェックボックスモードの読み取り範囲
>チェックボックスにチェックが入っているかの認識を行う際、チェックボックスの枠が読み取り範囲内に入ってしまうと結果がすべてtrueになってしまうため、チェックボックスモードでの範囲設定は読み取り画像を拡大して設定するなどして枠が入らないように注意が必要です。

* 認識結果の修正設定
>認識結果をAI OCRにすべて任せるのではなく人間が確認、適宜修正を行うことでより確実にデータを読み取ることができます。そのため、認識結果の修正を利用するに設定すると良いと思います。

***

## まとめ

AI JIMY Paperbotを使用することで紙文書のデータ化だけでなく、データの入力まで行ってくれるため業務の効率化が図れると思いました。他の製品で入力まで行おうと思うと別途ツールが必要であったり、コストがかかってしまったりとなかなか導入が難しいと感じました。ですが、AI JIMY Paperbotでは１つのツールでデータの入力まで完了する上、コストも抑えることができるため是非導入したいと思いました。
How to remove a tag without deleting its content with jQuery

https://stackhowto.com/how-to-remove-a-tag-without-deleting-its-content-with-jquery/
から参照

```
<html>
    <head>
        <meta charset="utf-8"></meta>
            <title>Remove a tag without deleting its content</title>
            <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
            <script type="text/javascript">
                $(document).ready(function(){
                    $("button").click(function () {
                        $("p").find("a.lien").contents().unwrap();
                        $("th[class='sort-enabled']").find("a").contents().unwrap();
                    });

            </script>
    </head>

    <body>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing <a href="#" class="lien">this is a link</a>. In dictum, non amet consequat facilisis, augue convallis tempor dapibus.</p>
        <table>
            <th class="class='sort-enabled'"><a href="#">リンク</a></th>
            <tr><td></td></tr>
        </table>
        <button type="button">Remove link</button>
    </body>
</html>



======================================================
Salesforceのダッシュボードのエラーの原因～ユーザ無効化で起こるエラー～

Salesforceのダッシュボードのエラーの１つとして以下のようなものがあります

「Can't display dashboard
You're viewing this dashboard as もとはし 太郎, who is now inactive.

Try viewing the dashboard as someone else.」


鍵マークの画像が表示される特徴的なエラーです

![ダッシュボードエラー１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b10db433-5bb7-da44-fc4f-82974409cc25.png)


このエラーの原因について解決方法を示します


## 原因

今回のエラーの原因はダッシュボードに設定されているユーザが無効になったことです。

## 解決

ステップ１

まずはエラーがでている名前のユーザを「有効化」します
（今回はエラーメッセージに出ている通り「もとはし太郎」さんが原因です）
![有効０２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/2e9c6fa0-0760-e0a3-07cf-2e147a7e25d8.png)


ステップ２
さきほどエラーが発生しているダッシュボードを確認しエラーが無いことを確認します
エラーが無い場合「編集」ボタンが押せますので「編集」をクリックします
![ステップ２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/6409dbd7-b909-7287-5ce2-3f014d772e42.png)

ステップ３
歯車マークをクリックし「プロパティ」から先ほどのユーザ（今回でいうと「もとはし太郎」）ではなく違うユーザに編集し保存します
![ステップ３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/10b5f9a2-8a88-666b-88a0-7a1177087e3a.png)


以上で設定は可能です。
この設定が終われば先ほどのユーザを無効にしてもダッシュボードエラーは出ません
![有効０２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ff84bb03-0692-7540-bbe6-dc4c2730d99e.png)
初心者がリファクタリングに挑戦してみる#1-2

# はじめに
今回変更した部分としては、力技で書いていたものをクラス化、メソッド化してすっきりさせる、というものです。
[#1-1](https://qiita.com/snow_saboten/items/c43865d57ec63635ab1d)では、全てをtestクラスで記述していましたが、今回Storyクラスを作成しました。
また、ファイルの内容を格納するのに、普通の配列を使っていたところを、ArrayListというものを使うようにしました。これは、配列宣言時に要素数を指定せずに使えて、中身を入れるたびに自動で要素数を増やしてくれる優れもののようです。
使い方は[こちらのサイト](https://www.javadrive.jp/start/collection/index1.html)を参考にさせていただきました。


## 改良コード
```java:test.java
import java.io.*;
import java.util.ArrayList;

class Story
{
	String fileName;
	ArrayList <String>  story = new ArrayList<>();

	public void readFile(String fn) throws IOException
	{
		fileName = fn;
		
		BufferedReader br = new BufferedReader(new FileReader(fileName));
		
		String str1;
		
		while((str1 = br.readLine()) != null)
		{
			story.add(str1);
		}
		
	}

	public void showText() //全部出力
	{
		for(int i=0; i<story.size(); i++)
		{
			System.out.println(story.get(i));
		}
	}
		
	public void showText(int s) //要素番号ｓから最後まで
	{
		for(int i=s; i<story.size(); i++)
		{
			System.out.println(story.get(i));
		}
	}
	
	public void showText(int s, int g) //要素番号ｓからｇまで
	{
		if(g<story.size())
		{
			for(int i=s; i<=g; i++)
			{
				System.out.println(story.get(i));
			}
		}
		else
		{
			System.out.println("2つ目の引数が要素数を超えています");
		}
	}
}


class test
{
	public static void main(String[] args) throws IOException
	{
		Story story1 = new Story();
		
		story1.readFile("test1.txt");
		
		story1.showText(0,5);

		BufferedReader ibr = new BufferedReader(new InputStreamReader(System.in));
		String option = ibr.readLine();
		int option1 = Integer.parseInt(option);
	
		if(option1 == 1)
		{
			story1.showText(6, 7);
		}
		else if(option1 == 2)
		{
			story1.showText(8,9);
		}
		else
		{
			System.out.println("無効な選択肢です");
		}

		System.out.println("おしまい");	
	}
}
```
実行結果は[#1-1](https://qiita.com/snow_saboten/items/c43865d57ec63635ab1d)と全く同じです。
クラスやオーバーロードを使ったことで、mainの中がかなりすっきりしました。
選択肢分岐のところももう少しきれいになりそうですが、今回はいったんこれでおしまい。