OmniAICreator/Qiita-1.07M huggingface dataset:
ウマ娘の馬名当てページを作った

懐かしい馬名が目白押しのウマ娘の馬名で、馬名の早当てページを作ってみました。
Javascriptのみで作ってあります。

poruruba/Umamusume

https://github.com/poruruba/Umamusume

とりあえず、やってみたい場合は、以下のページを参照してみてください。
著作権の都合上、モザイクをかけているのと、ウマ娘がたくさんありすぎて、とりあえず、12頭を入れています。

https://poruruba.github.io/Umamusume/

# ソースコード解説

以下の状態遷移に基づきます。

```js:js/start.js
const QUIZ_STATUS = {
    IDLE : 0, // 開始前
    PREPARE: 1, // カウントダウン中
    WAITING : 2, // 宣告待ち
    INPUT: 3, // 回答待ち
    ANSWER: 4, // 降参
    CORRECT : 5, // 正解時
    MISS: 6, // 誤り時
};
```

状態が変わるたびに以下が呼び出されます。
ユーザからの回答待ち受け時間など、タイムアウト処理も含まれています。

```js:js/start.js
        process: function(){
            if( this.counting < 0 ){
                // 状態遷移直後
            }
            if( this.counting == 0 ){
                // タイムアウト発生
            }
            if( this.counting >= 1 ){
                // タイムアウト待ち受け中
            }
        },
```

状態遷移は以下を呼び出します。

```js:js/start.js
process_status: function(status){
```

上述の通り、状態遷移直後の処理と、タイムアウト発生時の処理を記述しています。

#コンテンツの用意

コンテンツは、quiz_imagesフォルダに置いています。2つ用意していまして、ウマ名を答えてもらうときの絵と、ウマ名を答えた後の結果の絵です。
それらを配置したのち、以下のファイル ```quiz_contents.js``` を作成します。

```js:js/quiz_contents.js
const quiz_contents = [
  {
    name: "スペシャルウィーク",
    image: "quiz_images/スペシャルウィーク.png",
    blank_image: "quiz_images/blank_スペシャルウィーク.png",
    phrase: "お母ちゃん、見てて！ 私、日本一のウマ娘になる！"
  },
　・・・・
```

nameが答えの馬名、imageが答えた後の結果の絵の場所、blank_imageが答えてもらうときの絵です。

以下の部分は、お好みに合わせて適当に変えてください。

```js:js/start.js
        NUM_OF_SELECT: 3,   // 選択肢の数
        PREPARE_COUNT : 3, // クイズ表示までのウェイト時間(秒)
        WAITING_DURATION: 5000, // 宣言待ち時間
        INPUT_DURATION: 3000, // 選択待ち時間
        RESULT_DURATION: 3000, // 結果表示時間
```
以上
・iOSで起動画面を作る上でのはめ込みポイント

・iOSで起動画面を作る上でのはめ込みポイント

-iPhoneを再起動しないと画像が反映されない
  iPhoneが端末内部でキャッシュを持っている
　必ず再起動すること

-画像の背景色と、起動画面の背景色が合わない
　画像側の背景を切り抜いて、単色画像のみにする
WindowsでDockerToolBoxを立ち上げる際の前後に独自の処理を入れる

:::note info
「Docker Toolbox」は「C:\Program Files\Docker Toolbox\start.sh」を実行しています。
この「C:\Program Files\Docker Toolbox\start.sh」を変更しなくても実行する前後に独自の処理を行うことは可能です。
:::

# ■環境変数（私が使用しているものに限定）

* Dockerの環境変数(DockerToolbox限定も含まれます)

|  環境変数 |  内容  |  サンプル（カッコ内はデフォルト値）  |
| ---- | ---- | ---- |
| COMPOSE_FILE | docker-composeの設定ファイル名 |  docker-compose.local.yml(docker-compose.yml)  |
| DOCKER_MACHINE_NAME| docker環境を操作する際の名前 |  test(default) |
| PROXY_ENV | 環境を生成する際に使用される引数（ここにいろいろ設定できます） |  ""(default) |

* VirtualBoxの環境変数

|  環境変数 |  内容  |  サンプル  |
| ---- | ---- | ---- |
|  MACHINE_STORAGE_PATH  | VirtualBoxのイメージ保存場所 |  `D:\VirtualBox VMs` |

# ■前後の処理をカスタマイズ

```start.bat
REM カスタマイズした開始バッチファイル
"C:\Program Files\Git\bin\bash.exe" --login -i "C:\start.sh"
```

```start.sh
# Docker Toolboxの実行前に実行させるスクリプト「C:\start.sh」

##### 
##### Docker Toolboxの前の処理を記述
##### 

sh "C:\Program Files\Docker Toolbox\start.sh" "C:\end.sh"
```

```end.sh
# Docker Toolboxの実行後に実行させるスクリプト「C:\end.sh」

##### 
##### Docker Toolboxの後の処理を記述
##### 

exec "$BASH" --login -i
```

# ■docker構築後にVirtualBoxの設定を変更する

※各仮想環境の設定を自動化したい場合、上記でいう所の「C:\end.sh」で変更します

```end.sh
docker-machine stop $DOCKER_MACHINE_NAME

### VirtualBoxの設定を変更
# windows終了時に仮想マシンの電源をOFFにする
#VBoxManage setextradata $DOCKER_MACHINE_NAME GUI/DefaultCloseAction 3
# 共有フォルダを削除する
#VBoxManage sharedfolder remove $DOCKER_MACHINE_NAME --name "[共有フォルダ名]"
# 共有フォルダをマウントする
#VBoxManage sharedfolder add $DOCKER_MACHINE_NAME --name "[共有フォルダ名]" --hostpath "[共有フォルダにするパス]" --automount
# 共有フォルダ上にsymbolを作成できるようにする
#VBoxManage setextradata $DOCKER_MACHINE_NAME VBoxInternal2/SharedFoldersEnableSymlinksCreate/[共有フォルダ名] 1

docker-machine start $DOCKER_MACHINE_NAME
```

# ■VirtualBox上に複数のdocker環境がある場合の環境を切り替える

```bash
docker-machine regenerate-certs -f $DOCKER_MACHINE_NAME
eval "$(docker-machine env ${DOCKER_MACHINE_NAME})"
```

# ■Windows Home限定の必須設定

:::note alert
windows home では不具合があり、docker toolboxの最新版をインストールすると「Hyper-V」のエラーが表示されます。
これを回避する方法として「PROXY_ENV」の環境変数が利用できます。
:::

※実行時のスクリプトで下記のような処理を入れると回避できます

```bash
# windowsの情報からOS名のみ抽出する
# 英語表示の場合『OS.Name』
OS_NAME=$(systeminfo | findstr "^OS.名" | cut -d ':' -f 2)
# pro/homeを取得
OS_EDITION=$(echo ${OS_NAME} | sed 's/.\+\s\(.\+\)/\1/')
OS_EDITION=${OS_EDITION,,}

if [ ${OS_EDITION} = "home" ]; then
  # home の場合、docker toolboxの不具合回避
  export PROXY_ENV="$PROXY_ENV --virtualbox-no-vtx-check"
fi
```
Debianで鍵認証のユーザを作成する

|  用途  |  コマンド  |
| ---- | ---- |
|  test01を追加  |  /bin/bash user.sh add test01  |
|  test01を削除  |  /bin/bash user.sh del test01  |
|  test01の鍵を再作成  |  /bin/bash user.sh refile test01  |

## ■スクリプト

※鍵の出力先は「DIR_SSH_USER_PUBLIC_KEY」になります

```variables.sh
#!/bin/bash

# 追加するユーザのグループ
USER_GROUP_DEVELOPER=developer

USER_NAME=$1
# 鍵の出力先
DIR_SSH_USER_PUBLIC_KEY=/tmp/ssh/
# sshのファイルディレクトリ
DIR_SSH_USER=/home/${USER_NAME}/.ssh/
FILE_SSH_NAME=${USER_NAME}_rsa
# private key
FILE_SSH_PRIVATE=${DIR_SSH_USER}${FILE_SSH_NAME}
# public key
FILE_SSH_PUBLIC=${FILE_SSH_PRIVATE}.pub
# 認証ファイルパス
FILE_SSH_SERVER=${DIR_SSH_USER}authorized_keys
```

```module.sh
#!/bin/bash
#
# ■キーファイル作成
#
function createSshKeyFile() {
  # ユーザの存在確認
  COUNT=$(grep -ce "${USER_NAME}" /etc/passwd)
  if [ ${COUNT} -eq 0 ]; then
    return 1
  fi

  if [ ! -d ${DIR_SSH_USER} ]; then
    mkdir -m 700 ${DIR_SSH_USER} \
      && chown ${USER_NAME} ${DIR_SSH_USER} \
      && chgrp ${USER_NAME} ${DIR_SSH_USER}
  fi

  if [ -f ${FILE_SSH_PRIVATE} ]; then
    rm -f ${FILE_SSH_PRIVATE}
  fi

  if [ -f ${FILE_SSH_PUBLIC} ]; then
    rm -f ${FILE_SSH_PUBLIC}
  fi

  WORK_MEMO="[script create user]${USER_NAME}"
  WORK_MEMO_SED=$(echo ${WORK_MEMO} | sed -e 's/\[/\\\[/g' | sed -e 's/\]/\\\]/g')

  if [ -f ${FILE_SSH_SERVER} ]; then
    sed -i -e "/ ${WORK_MEMO_SED}$/d" ${FILE_SSH_SERVER}
  fi

  ssh-keygen -f ${FILE_SSH_PRIVATE} -t rsa -b 4096 -C "${WORK_MEMO}" -N '' \
    && chown ${USER_NAME} ${FILE_SSH_PRIVATE} \
    && chgrp ${USER_NAME} ${FILE_SSH_PRIVATE} \
    && chown ${USER_NAME} ${FILE_SSH_PUBLIC} \
    && chgrp ${USER_NAME} ${FILE_SSH_PUBLIC} \
    && cat ${FILE_SSH_PUBLIC} >> ${FILE_SSH_SERVER} \
    && chmod 600 ${FILE_SSH_SERVER} \
    && chown ${USER_NAME} ${FILE_SSH_SERVER} \
    && chgrp ${USER_NAME} ${FILE_SSH_SERVER}

  # 不要ファイルを削除
  rm -f ${FILE_SSH_PUBLIC}

  return 0
}

#
# ■生成後のキーを出力先に移動
#
function moveSshPublicKey() {
  if [ ! -d ${DIR_SSH_USER_PUBLIC_KEY} ]; then
    mkdir -m 777 ${DIR_SSH_USER_PUBLIC_KEY}
  fi

  #共有フォルダに移動
  mv -f ${FILE_SSH_PRIVATE} ${DIR_SSH_USER_PUBLIC_KEY}${FILE_SSH_NAME}
}

```

```user.sh
#!/bin/bash
#
# /bin/bash user.sh 【種別】 【ユーザID】
#
# 【種別】 -> add: 追加 del: 削除 refile: 鍵の再生成
#

if [ $# -lt 2 ]; then
    echo "[failed] 引数を入力してください"
    exit 1
fi

DIR_CUR=$(dirname "${BASH_SOURCE:-$0}")"/"
source ${DIR_CUR}variables.sh $2
source ${DIR_CUR}module.sh

ARG_TYPE=$1

if [ ${ARG_TYPE} = 'add' ]; then
  MESSAGE=$(adduser -q --gecos "" --disabled-login ${USER_NAME} 2>&1 > /dev/null)
  if [ -n "${MESSAGE}" ]; then
    echo ${MESSAGE}
    exit 1
  fi

  usermod -aG ${USER_GROUP_DEVELOPER} ${USER_NAME}

  # ファイルを作成
  createSshKeyFile
  if [ ! $? = 0 ]; then
    echo "鍵の生成に失敗しました"
    exit 1
  fi

  # 出力先へ移動
  moveSshPublicKey
elif [ ${ARG_TYPE} = "del" ]; then
  # -rを付けるとホームディレクトリを削除
  #userdel -r ${USER_NAME}
  userdel ${USER_NAME}
elif [ ${ARG_TYPE} = "refile" ]; then
  # ファイルを作成
  createSshKeyFile
  if [ ! $? = 0 ]; then
    echo "鍵の生成に失敗しました"
    exit 1
  fi

  # 出力先へ移動
  moveSshPublicKey
else
  echo "[failed] 引数が正しくありません"
  exit 1
fi
```
JavaScriptテストフレームワークのトレンド比較

# 概要

JavaScriptのテストフレームワークを選定するにあたり、GitHubのスター数とNPMトレンドの推移を比較しました。

https://bugfender.com/blog/best-tools-in-2021-to-do-automated-testing-of-your-javascript-apps/

# Github Star数

|Name|Github Star|URL|
|:---|:---|:---|
|Jest|34.7k|https://jestjs.io/ja/|
|Cypress | 28.9k | https://docs.cypress.io/guides/overview/why-cypress |
|Mocha | 20.4k | https://mochajs.org/|
|Jasmine | 15.1k |https://jasmine.github.io/ |
|Chai | 7.2k |https://www.chaijs.com/ |

2021年3月28日時点の集計結果

# NPMトレンド比較

![スクリーンショット 2021-03-28 13.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/802246/81b36edd-520d-1044-f0f3-f1d6a77485ad.png)

https://www.npmtrends.com/jest-vs-jasmine-vs-mocha-vs-chai-vs-cypress

# 参考

https://bugfender.com/blog/best-tools-in-2021-to-do-automated-testing-of-your-javascript-apps/

https://medium.com/welldone-software/an-overview-of-javascript-testing-7ce7298b9870

https://lifewood.hatenablog.com/entry/2020/01/04/180344
[Docker] WSL2で作成した名前付きボリュームがない

# 追記
この記事は2021/03/28に執筆しました。

しかし2021/03/30現在、改めてvolumeを作成したところ、WSL2のターミナル上から確認できるようになりました。
ディレクトリ：`/var/lib/docker/volumes`
環境は全く変わっていません。謎です。


# はじめに
volumeについて学ぼうとした矢先です。
Linuxと全然挙動が違う＋日本語の記事がなさそうなので書きました。
あと、仕組みを全然理解できないです。

よく言われているWindowsOS上のディレクトリをコンテナ上にバインドマウントする際の注意とは異なります。

# 問題
- **WSL2上で作った名前付きボリュームが消える**

別の言い方をすると、

- **そこにあるって書いてあるのに、そこを見に行ったら"なかった"**

# 結論

Windowsファイルシステム上の以下のディレクトリにある。

```
\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes
```

エクスプローラーでアクセスしてみてください。

# 前提
まず環境は以下です。
**WSL(version1)での確認はしていません。**

- OS
  - Windows 10 Pro 20H2 build 19042.867
- WSL2
  - Ubuntu 20.04.2 LTS
- Docker
  - 20.10.5, build 55c4c88
- Docker Desktop for Windows
  - 3.2.2

# 発生状況
`docker volume create GOMI`で名前付きボリューム"GOMI"を作成
`docker volume inspect GOMI`でどこに作られたか確認し

```
[
    {
        "CreatedAt": "2021-03-28T03:00:15Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/GOMI/_data",
        "Name": "GOMI",
        "Options": {},
        "Scope": "local"
    }
]
```

`"Mountpoint": "/var/lib/docker/volumes/GOMI/_data",`
とあるので、（これはLinuxのデフォでも同じディレクトリに保存されるので特に問題はなし）

```
# cd /var/lib/docker/volumes
# ll
total 40
drwx-----x  2 root root  4096 Mar 10 00:18 ./
drwx--x--x 12 root root  4096 Mar 10 00:18 ../
brw-------  1 root root  0, 2 Mar 10 00:18 backingFsBlockDev
-rw-------  1 root root 32768 Mar 10 00:18 metadata.db

```

あるはずの場所にありません。(動かしてるのはroot権限です)
しかし、`docker volume ls`上では確かにあります。

```
# docker volume ls
DRIVER    VOLUME NAME
local     GOMI
```

それで調べたのですが、Qiitaや他のサイトに投稿されているものは「ホスト上のCドライブをコンテナにマウントする際の注意事項」等しかなさそうでしたので…

結論こちらが参考になりました。というか答えが載ってました。
[WSL2 where is docker volume location? · Discussion \#4176 · microsoft/WSL](https://github.com/microsoft/WSL/discussions/4176)


# 解決方法

Windowsの**エクスプローラー**で、下記にアクセスしてください。

```
\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes
```

WSL2上で

```
$ cd /mnt/wsl/docker-desktop-data/version-pack-data
```
としても何も表示されないので気をつけてください。

一番簡単なアクセスの方法は「Windowsキー + R」のファイル名を指定して実行で
`\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes`
と打ってEnterです。
エクスプローラーに打っても同じです。



# なぜこうなってるのか
恐らくWindowsOS上でLinuxを動かす上で仕方のない仕組みなんでしょうが知識がないため全くわかりません。

↓この方が言ってますが
[WSL2 where is docker volume location? · Discussion \#4176 · microsoft/WSL](https://github.com/microsoft/WSL/discussions/4176#discussioncomment-275452)

>Maybe in WSL2 way, data only exists in Windows systems.
>When we use WSL2 based engine, Docker Desktop mount "docker.sock" into Linux "/var/run/docker.sock". >Linux docker client access to windows docker service.
>I find this idea in below link: https://blog.csdn.net/qqhappy8/article/details/106819429

でもマウントされた場所ってどうやって見つけられるんですか？せめてシンボリックリンクでもあると思ったんですが



# 最後に
[dmckee-ebscoさんも言ってます。](https://github.com/microsoft/WSL/discussions/4176#discussioncomment-205936)
>This is... not simple. I don't know why it's this hard.
>：これは...単純じゃない。なぜこんなにも難しいのかわからない。


関係ないですけど、今どきは英語圏のページだけじゃなく中国語も学んで中国語のページも検索できれば効率的に情報を集めれるなと思いました。
Debianで固定IPアドレスを別のIPアドレスに変更する

既に固定IPアドレスになっていることが前提になります。
※下記リンクの「VirtualBoxにDebianをインストール」で固定IPアドレスに変更している前提です

```ip.sh
#!/bin/bash
#
# ip.sh 192.168.1.11
#
IP=$1

# 変更後、SSHは切断されます。
sed -i -e "s/\(address\s\)[0-9\.]\+/\1${IP}/" /etc/network/interfaces.d/local \
  && systemctl restart networking
```

## 参考

https://qiita.com/error484/items/f5fb0cfdaa13a6d99e75
DebianでWale-on-LANを制御する

# ■WOLのスクリプト

```install.sh
#!/bin/bash

# アプリケーションをインストール
apt-get update \
  && apt-get -y upgrade \
  && apt-get install -y \
      wakeonlan
```

```config.sh
#!/bin/bash

# 第一引数は『識別子』
ID=${1}

# WOLリスト（test_01やtest_02が識別子になります）
WOL_LIST=(
  "test_01 XX:XX:XX:XX:XX:XX テストユーザ1"
  "test_02 XX:XX:XX:XX:XX:XX テストユーザ2"
)

# WOLリストのIDにマッチしたMACアドレスが MACADDRESS に設定されます
MACADDRESS=
for ((i=0; ${#WOL_LIST[*]}>$i; i++))
do
  work=(${WOL_LIST[$i]})
  if [ ${ID} = ${work[0]} ]; then
    MACADDRESS=${work[1]}
  fi
done
```

```wol.sh
#!/bin/bash
#
# 設定を表示
#   wol.sh list
#
# PCを起動
#   wol.sh start [識別子]
#
DIR_CUR=$(dirname "${BASH_SOURCE:-$0}")"/"
source ${DIR_CUR}config.sh

ARG_TYPE=$1
ARG_ID=$2

if [ ${ARG_TYPE} = 'start' ]; then
  if [ -z "${MACADDRESS}" ]; then
    echo '設定がありません'
    exit 1
  fi

  # WOLの実行
  wakeonlan ${MACADDRESS}
elif [ ${ARG_TYPE} = "list" ]; then
  for ((i=0; ${#WOL_LIST[*]}>$i; i++))
  do
    echo ${WOL_LIST[$i]}
  done
else
  echo "[failed] 引数が正しくありません"
  exit 1
fi
```

# ■立ち上げるPC側の設定

* BIOS設定(マザーボードによって異なります)
 * APM の ErP Ready 設定をdisableに変更
 * APM の PCIE 設定をenableに変更
 * Fast Boot 設定をdisableに変更
* Windowsの設定
 *  電源とスリープ　→ 電源ボタンの動作を選択するを選択 から「高速スタートアップを有効にする」に無効に変更
* ネットワークアダプタの設定
 * WOL関連を有効に変更する

# ■ネットワークアダプタ - Realtek PCie GbE Familly Controller の場合

:::note alert
ドライバーのバージョンを確認し、『9.1.401.2015』の場合はバージョンアップを行う
※9.1.401.2015は不具合があり、WOLの設定を有効かできません
※公式サイトからドライバーのダウンロードが必要になります
:::

* プロパティの詳細設定タブ
 * Wake on magic packet when systemを有効
 * WOLとシャットダウンリンク速度を最低に変更
 * ウェイク・オン・パターン・マッチを有効
 * ウェイク・オン・マジック・パケットを有効
* プロパティの電源の管理タブ
 * 「このデバイスで、コンピュータのスタンバイ状態を解除できるようにする」にチェック
[Swift5] スクリーンショットを保存

## スクリーンショットを保存

シェアボタンが押された時などに呼ばれるメソッドを作成

```Swift
    var screenShotImage = UIImage()
    func takeScreenShot(){
        let width = CGFloat(UIScreen.main.bounds.size.width)
        let height = CGFloat(UIScreen.main.bounds.size.height)
        let size = CGSize(width: width, height: height)
        
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        
        //viewに書き出す
        self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
        screenShotImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    }
```
Vimコマンド入門

`vi ファイル名`編集可能になります。
もし、ファイルが存在しなかったら作成できます。


| コマンド | 用途 | |
|:---|:---|:---|
|escキー |入力モード切り替え |-- INSERT --になっているか確認|
|:w |保存する |
:wq |保存して終了 |
|:q |保存せずに終了 |
|:q! |変更した内容を保存せずに終了 |
|dd |一行削除 |
|x |1文字削除 |
|yy |一行コピー |
|p |コピーを貼り付け |
|u |変更取り消し |
| g |ファイル先頭へ移動 |
|shiht + g |ファイル末尾へ移動 |
|j|下へ移動 [↓]|
|k|上へ移動 [↑]|
|h|左へ移動 [←]|
|i|右へ移動 [→]|



|
[Swift5] Cocoapodsインストール

## Cocoapodsインストール
```
sudo gem install cocoapods
pod setup
```
## プロジェクトにライブラリを設定
```
cd /Users/XXX/your_xcode_directory
pod init
```
## Podfile編集
```
vim Podfile
```
```
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'XXXXX' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for XXXXX

# ここに追加したいライブラリを設定
pod 'SwiftyJSON'
pod 'Alamofire'
pod 'SDWebImage'

end
```

## Xcodeでライブラリを利用
以下のxcode workspaceファイルを開いてコードを利用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018670/f87562f0-51e5-3a36-1c2a-42c50c1e903d.png)
通院メモ管理システムが完成いたしました

通院メモ管理システムが完成いたしました。
Javaで1クラスで作成いたしました。
ソースコードはこちらです。

```java
//
//    通院リストプログラム
//　　新規作成  2021/03/28(Ver1.0)
//    作成者   乃木坂46好きのITエンジニア
//
//
//
//
//
//
//  所属パッケージの定義
package mental;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;


public class mantal {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String hiduke = "";
		String memo = "";
		int flag =0;
		//日付入力処理
		while (flag==0) {
			System.out.println("日付を自由に入力してください");
			String line = sc.nextLine();
			if (line.length() !=0) {
				System.out.println("日付が正常に入っています");
				hiduke = line;
				flag = 1;
			} else {
				System.out.println("日付を入力してください");
			}
		}
		//通院内容を記録する処理
		System.out.println("通院内容を自由に入力してください");
		String line2 = sc.nextLine();
		memo = line2;

		//ファイルへの出力処理
		FileWriter fw = null;

		try {
			fw = new FileWriter("mental.txt",true);
			fw.write(hiduke +  "\n");
			fw.write(memo +  "\n");
			fw.flush();
		} catch (IOException e) {
			System.out.println("ファイル書き込みエラーです");
		} finally {
			if (fw !=null) {
				try {
					if (fw != null) {
						fw.close();
					}
				} catch(IOException e2) {
					System.out.println("ファイルを閉じるのに失敗しました");
				}
				System.out.println("ファイルの書き込みに成功しました");
			}
		}

	}
}
```

今回は簡単なアプリケーションなのでテキスト保存で1クラスにしています。
[Swift5] AlamofireでAPI接続

##AlamofireでAPIリクエストしてJSON解析
```Swift
    import Alamofire
    import SwiftyJSON
    import SDWebImage

    func getImages(keyword:String){
        
        //API Key
        let url = "https://pixabay.com/api/?key=XXXXXX&q=\(keyword)"
        let parameters:String? = nil
        
        //Alamofireを使ってHTTPリクエスト
        //ImageView.imageにはりつける
        AF.request(url, method: .get, parameters: parameters).responseJSON
            { (response) in
            
            switch response.result{
            case .success:
                let json:JSON = JSON(response.data as Any)
                var imageString = json["hits"][self.count]["webformatURL"].string
                if imageString == nil{
                    imageString = json["hits"][0]["webformatURL"].string
                }else{
                    self.odaiImageView.sd_setImage(with: URL(string: imageString!), completed: nil)
                }
            case .failure(let error):
                print(error)
            }
            
        }
        
    }
```
form_withにclassを適用する方法

## 結論
fooというclassを適用させたい場合↓

```
<%= form_with(model: website, local: true, multipart: true,class:"foo") do |form| %>
```

これで適用されます。

因みに、form_withは画面幅いっぱい(100vw)のフォームが自動生成されてしまいますが、classを適用させて幅を変えれば解決です！
mysql2 gemのインストールに失敗する

# 事象
bundle install
bundle update
gem install mysql2
などでmysql2 gemのインストール時にエラーで失敗する。

# 解決策
mysql自体がインストールされていない可能性があります。
`which mysql`コマンドでmysqlが利用できる状態かを確認しましょう。
無い場合は`brew install mysql`でインストールしましょう。
herokuにデプロイ ⇒ Application error

## エラー内容

```
Application error
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. You can do this from the Heroku CLI with the command
heroku logs --tail
```

## 原因の特定

原因を特定するために、ターミナルで下記を実行。

```
heroku run rails c
```

すると下記のエラーが発生。aws_access_key_idとaws_secret_access_keyの記述が怪しそうです。 

```
 Missing required arguments: aws_access_key_id, aws_secret_access_key (ArgumentError)
```

「rails c」でコンソールを起動し、アクセスキーがちゃんと設定されているかを確認するために下記を実行。

```
Rails.application.credentials.aws_access_key_id
```
するとnilが返ってきた。
nilが返ってくるということは、記述が間違っている。

credentialsの値がしっかりと記載されているか確認するために、下記を実行。

```
EDITOR=vi rails credentials:edit
```

```
aws:
#   access_key_id: ********************
#   secret_access_key: ********************
#   region: ********************
#   bucket: ********************
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
```

「#」でコメントアウトされてしまっていた...。
下記に修正する。

```
aws:
   access_key_id: ********************
   secret_access_key: ********************
   region: ********************
   bucket: ********************
 Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
```

私はこれで解決しましたが、
access_key_id:と【IAMユーザーのアクセスキーID】の間に半角スペースが一つ入っていない場合なども同様の現象が起きてしまいます。
かなり記述には厳しいらしいのです！
Ruby getsについて

getsの使い方
--

getsを使用することで、入力された値を所得できる

```ruby
input = gets
```


gets.chompの使い方
--

getsを使用して所得した値には、文末に改行が入る

getsの後に.chompとつけることで、改行をなくすことができる




```ruby
#.chompを使用しない場合
input = gets
puts "a" + input + "b"
```
getsでbを入力した場合の出力結果は

```
ab
c
```
となる

```ruby
#.chompを使用する場合
input = gets.chomp
puts "a" + input + "b"
```

出力結果は

```
abc
```
となる
gets.to_iの使い方
--

getsの後に.to_iとつけることで、所得した値を数値に変換できる
iはinteger(整数)の頭文字

```ruby
input = gets.to_i 
```

gets.to_sの使い方
--
getsの後に.to_sとつけることで、所得した値を文字列に変換できる
sはstring(コンピューター用語で文字列)の頭文字

```ruby
input = gets.to_s
```
血圧管理システムのWebシステムをデザインしました

血圧管理システムのWebシステムをCSSでデザインしました。
以前の味気ないシステムがいい感じのシステムに変わりました。
昨日のオフラインミーティングでデザインを教えていただいたアドバイスを生かしました。
今後の課題はAWSクラウドに載せる部分になります。
それぞれのsubmitボタンごとに、保存内容を分ける。

## やりたいこと
例えば、一つのページに保存ボタンが複数あり、保存ボタン（1）を押すと「名前を変更」し、保存ボタン（2）を押すと「プロフィール文章を変更」。

## 方法
保存ボタン（１）は下記のように記述

```
<input class="OK" type="submit" value="保存" name="name">
```

保存ボタン（2）は下記のように記述

```
<input class="OK" type="submit" value="保存" name="introduce">
```

違いは、nameの内容(パラメータ値)です。

コントローラーで下記のように条件分岐

```
 def update
    @user = User.find_by(id:params[:id])
# submitで送信したparamsの値によって、保存する内容を変えるようにします。
     if params[:name]
      @user.update(name_params)
     elsif params[:introduce]
      @user.update(introduce_params)
     end
  end

    private

  def name_params
    params.require(:website).permit(:name)
  end

  def introduce_params
    params.require(:website).permit(:introduce)
  end

```

上記は説明用になりますので、redirect_toやsaveなどはご自分で設定下さい。
RubyとCSSを組み合わせる方法

## 内容
RubyとCSSのコードを組み合わせる方法です。
例えば、カラムの値によってデザイン表示を変えたりということが出来るようになります。
やり方は簡単で記事を見なくてもわかる方が多いと思いますが、やり方が書かれている記事がなかったため記事にしました！

## 方法
cssファイルにRubyを組み込むのではなく、

HTMLファイルに、下記のように記述

```
<style>
  .body{
    background-color: #<%=@user.background_color%>;
  }
</style>
```

HTMLファイルの中の

```
<style></style>
```

の中であれば適用されます。
数学メモ用の Web サービス


# https://www.mathcha.io/editor
結論からいうと現時点でこれが一番よかった。


<iframe width="560" height="315" src="https://www.youtube.com/embed/TDLz3oQO02k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# Word

typing 中の document が LaTeX 表記のままで微妙

<iframe width="560" height="315" src="https://www.youtube.com/embed/utIDhYKyyPk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
viewに、他のviewを読み込む方法

## やりたいこと
「users/show.html.erb」に、「users/index.html.erb」のコードを読み込んで、サーバー上で「users/show.html.erb」に接続した際に、「users/index.html.erb」のコードも表示されるようにする。
方法は簡単ですが、意外に質問サイトで詰まっている方が多かったため、記事にしました。

## 手順

①ファイル名の変更
「index.html.erb」を「_index.html.erb」にする。

②読み込むためのコードを記述
「users/show.html.erb」に下記を記述。

```
<%= render 'users/index' %> 
```

※このとき、indexの先頭に「_」はつけなくて大丈夫です。
Python boto3 でS3のディレクトリだけを再帰的に取得して、AthenaのPartition追加をするコード

Python boto3 でS3のディレクトリだけを再帰的に取得する

Athena使用する際に、大量のデータでLoad Partition(MSCK Repair Table)をすると、10分以上実行が走った後、落ちる現象に遭遇しました。

そこで、ディレクトリだけを再帰的に取得し、ALTER TABLEでPARTITIONを追加するクエリを取得するPythonコードを書きました。

```Python3
import boto3
import pyperclip

DIR_LIST = []   # global変数
BUCKET = '{bucket名を入力}'
ATHENA_TABLE = '{Athenaのテーブル名}'
PARTITIONS = ['partitino1','partition2','partition3'] # HIVE形式で partition1=xxx　となっている前提
RootDirectory = 'test/' #ディレクトリを指定

### 再帰的に、s3のディレクトリを取得する
def getS3Dir(prefix):
    client = boto3.client('s3')
    result = client.list_objects(Bucket=BUCKET, Prefix=prefix, Delimiter='/')
    if result.get('CommonPrefixes'):
        for o in result.get('CommonPrefixes'):
            path = o.get('Prefix')
            chLi = getS3Dir(path)
            if chLi:
                for l in chLi:
                    getS3Dir(l)
            else:
                DIR_LIST.append(path)
        return chLi
    return None

### パーティション追加
def hasAllKeys(keys:dict,partitions:list):
    flg=True
    for pt in partitions:
        if pt not in keys:
            flg=False
            break
    return flg

def customRepairTable():
    q1 = []
    query = ''
    for directory in DIR_LIST:
        dirL = directory.split('/')
        keys = {d.split('=')[0]:d.split('=')[1] for d in dirL if '=' in d}
        if hasAllKeys(keys,PARTITIONS):
            part_list = []
            for pt in PARTITIONS:
                part_list.append("{} = '{}'".format(pt,keys[pt]))

            q1.append( "PARTITION ({})".format(','.join(part_list)))
    
    if len(q1) >0:
        query = 'ALTER TABLE '+ATHENA_TABLE  + ' ADD IF NOT EXISTS '  +  ' '.join(q1)
        print(query)

    return query

getS3Dir(RootDirectory)
q = customRepairTable()
pyperclip.copy(q)   # Copy to ClipBoard
print(len(DIR_LIST))
print('クリップボードにコピーしました')
```

pyperclipでクリップボードにコピーできるのは、便利ですね。
destroyを実行した際に発生した「uninitialized constant User::Post」の解決策

## エラー内容

userを削除する処理（destroyアクション）を実行した際に発生

```
NameError in Users::RegistrationsController#destroy
uninitialized constant User::Post
Extracted source (around line #237):
235
236
237
238
239
240
              
            end

            raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
          end
        end

```

## 原因

```
uninitialized constant User::Post
```
上記を翻訳すると
「初期化されていない定数User :: Post」

UserモデルとPostモデルの関連付けを行った際に、
User.rbに「has_many :posts, dependent: :destroy 」を記述し、
Userのデータを削除した際に、関連付けられているPostモデルのデータも一緒に削除するように設定していた。

その後、Postモデル自体を削除。

その為、Postモデルが存在しないのに削除しようとしていたため、「そもそもPostモデルは存在しないですよ」とエラーが発生したということです。

## 解決法

User.rbに記述してある「has_many :posts, dependent: :destroy 」の一文を削除。
windowsでiverilog その96

# 概要　

windowsでiverilogやってみた。
vcdの、調査してみた。


# テストベンチ

```
module test;
	reg a;
	initial
	begin
		$dumpfile("test.vcd");
		$dumpvars(0, test);
		#1;
			a <= 0;
		#1;
			a <= 1;
		#1;
			a <= 0;
		#1;
			a <= 1;
		#1;
			a <= 0;
		$finish;
	end
endmodule

```

# 生成したvcd

```
$date
	Sat Mar 27 16:11:10 2021
$end
$version
	Icarus Verilog
$end
$timescale
	1s
$end
$scope module test $end
$var reg 1 ! a $end
$upscope $end
$enddefinitions $end
#0
$dumpvars
x!
$end
#1
0!
#2
1!
#3
0!
#4
1!
#5
0!

```

以上。
２重ハッシュ

## 初めに
メモがわりに使っているのでわかりにくい部分や省略しているところがありますがご了承ください。
### 2重ハッシュから値を取り出そう

```
user_data = [
 {user: {profile: {name: 'George'}}},
 {user: {profile: {name: 'Alice'}}},
 {user: {profile: {name: 'Taro'}}},
]
```
上記のハッシュを持つ変数user_dateから以下の取り出します。

```
George
Alice
Taro
```
### 解説
ではまずハッシュから値を取り出すには以下のような記述をします。

```
ハッシュ[取り出したい値のキー]
```
しかし今回はハッシュの中にハッシュが入っているためこれだけでは目的の値を散り出すことができません。
ではどのように書いていくかというと順番に取り出していきます。
書き方としては以下のようになります。

```
ハッシュ[取得したいキー][取得したいキー][取得したいキー]
```
今回はnameというキーを取り出したいので順番に書いていくと以下のようになります。

```
ハッシュ[:user][:profile][:name]
```
そして今回の肝はこのハッシュが配列で格納されているということです。配列の取り出し方は色々ありますがeach分を使い１つ１つ取り出すのが綺麗に収まると思います。

```
user_data.each do |u|
  puts u[:user][:profile][:name]
end
```
以上です。ハッシュのなかにハッシュがあり見た目がエグいですが、基本は１つ１つ順番に取り出していく形になります。
今更ながら、ブックマークレットに入門する

# ブックマークレットとは
>ユーザーがウェブブラウザのブックマークなどから起動し、なんらかの処理を行う簡易的なプログラムのこと
>[wikipediaより](https://ja.wikipedia.org/wiki/ブックマークレット)

要するに、**ブックマークに簡単なプログラムを仕込んでおいて、ユーザーが押すタイミングをトリガーに発火する**ってことです。
基本的には、ブラウザで動作する言語JavaScriptを実行するコードを仕込んでおくものだと思っています。


# 試してみよう！
こちらに簡易的なデモページを用意しました。
https://bookmarklet-demo.netlify.app

※Google Chrome(89.0.4389.90)をMac(10.14.6)で操作しております。

---

1.Google Chromeを開き、右上の三点ボタンを押して、**ブックマーク マネージャ**を開きます。
 
![スクリーンショット 2021-03-27 23.46.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/136bf03c-4159-80a5-e9cb-2b4ce50641fe.png)



2.右クリックして、**新しいブックマークを追加**を押します。

![スクリーンショット 2021-03-27 23.50.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/d8ff995e-e68d-6361-f0f7-bc1f3912a0e9.png)


3.URLに以下を入力して、保存ボタンを押します。

```javascript
javascript:document.getElementById('name').value="westhouse";document.getElementById("password").value="password";document.getElementById("button").click();
```
![スクリーンショット 2021-03-28 0.10.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/71cad90e-c99c-8395-61a1-a9cdd607c613.png)


4.お気に入りバーにある**ブックマークレット**を押します。
「NameとPasswordを入力して、送信ボタンを押す」というJavaScriptが実行されます。

![スクリーンショット 2021-03-28 0.11.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/9874c98d-839a-d038-4064-9a0a471ce6e6.png)


# ポイント
ブックマークURLの最初に`javescript:`と書くことで、JavaScriptで実行することができます
結局、やっていることは、開発者ツール「Console」にコードは貼り付けてEnterを押しているようなイメージです。


# 導入アイディア

- Twitter: タイムラインの上から10個いいねを押す
- Outlook: 新規メールに宛先、タイトル、定型文を入力する
- notion: カンバンにアイテムを10個追加する
- Trello: すべてのステータスを完了にする
- 乗換案内: 最寄り駅と職場を入力する


アイディア次第では、色々できるはず！ただ、KeyUp,KeyDownをトリガーに動作しているものを動かすのは難しいかもしれません😥


# 終わりに
JavaScriptが少し書ければ、すぐに導入できます！こういうちょっとした業務を効率化して、1秒でも早く帰りましょう💨
PDF文書に印影画像を埋め込む

<h2>PDF文書にスタンプ角印的な印影を埋め込みたい</h2>
「請求書等のPDF文書に印影っぽいものがほしい」
という要望がありました。

個人的には、形だけで意味があるとは思えない作業なのですが、
取引先から要望を受けた場合は、対応せざるを得ません。

その場合はAdobe Acrobatのスタンプ機能を利用したり、
スタンプ印を押した文書をスキャンしてpdfにしていました。

ただ、これでは対象文書数が多いときに面倒です。
そこでPythonを使って印影画像を埋め込もうと考えました。

<h2>準備</h2>
・glob,pdfrw,pillowをインストール
・pythonファイルと同階層に「pdf」フォルダ、その直下に「export」フォルダを作成
・「pdf」フォルダに印影画像を埋め込みたいpdfファイルを保存
・印影データ（透過png）を「pdf」フォルダ直下に保存
![hanko.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565780/27c8753b-0d07-0744-c128-b7e1e3c3daad.png)

<h2>必要なモジュールをインポート</h2>
```py
import glob
import os
from pdfrw import PdfReader
from pdfrw.buildxobj import pagexobj
from pdfrw.toreportlab import makerl
from reportlab.pdfgen import canvas
from PIL import Image
import io
from reportlab.lib.utils import ImageReader
```
<h2>処理対象のフォルダやファイルを指定</h2>
```py
# 処理対象のフォルダを指定
target_folder = os.getcwd() + r'\pdf'
files = glob.glob(target_folder + r'\*.pdf')

# 埋め込む画像を指定
img = ImageReader(os.getcwd() + r'\pdf\hanko.png')
```

<h2>画像を埋め込んで保存する</h2>
「pdf」フォルダ直下に入っているpdfファイルを順番に開き、
そこに印影画像を埋め込んで保存していきます。
画像の位置の起点は、左上ではなく左下なのでそれを踏まえて位置を指定します。
また、mask='auto'にしておかないと透過がうまくいかないようです。

```py
for file in files:
    export_filename = target_folder + '\\export\\' + os.path.basename(file)
    export_pdf = canvas.Canvas(export_filename)

    # 対象PDFの1ページ目にのみ画像を埋め込む
    target_pdf = PdfReader(file,decompress=False).pages
    page = pagexobj(target_pdf[0])
    export_pdf.doForm(makerl(export_pdf,page))

    # ページの左下を起点にして、x=480,y=640 の位置にサイズx=60,y=60 で画像を埋め込む
    export_pdf.drawImage(img, 480, 640, 60, 60, preserveAspectRatio=True, mask='auto')
    export_pdf.showPage()
    export_pdf.save()
```
<h2>処理結果</h2>
これが

|![文書.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565780/5da1479b-fdd8-490c-9f92-d0fbb4ec642c.png)|
|:--|

こうなりました

|![押印済み.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565780/af0b37d3-e1f7-4e68-34bf-703ab9996c42.png)|
|:--|
続・Pythonでファイル名の一括変換スクリプトを書いてみる

#はじめに
前の記事でファイル名の一括変換スクリプトを作成しました。

https://qiita.com/Lynx_Arc18/items/d5695d2129b1d38a8cf8

が、結果として下記のような問題が起こっていました。

>無事、一括変更することができましたが、
>名前の対応が崩れてしまったようです。。。
>※Pythonで変更前のファイル名を名前順でソートすると「コマンドプロンプト」の画像のような順番になるようですね。。。

今回はこの問題を解決することが目的となります。

#何が問題だったのか
Pythonのsortに関して、いろいろ調べてみた結果、
「文字列」として数値を比較していることが原因のようです。
※文字列として比較する場合は"2"という文字列は"10"という文字列より大きい扱いとなっている

#解決策
原因が分かったので、以下のような解決策を取ろうと思います。
①ファイル名を取得する（ファイル名中には数値が含まれるとする）
②ファイル名中の数値を取得し、文字列型ではなく数値型とする
③数値同士を比較して昇順で並び替え
④③を実施するときに元のファイル名も併せて昇順並び替え

#さっそく書いてみる
①は前回と同様、glob関数を使用します。
②については追加で調査した結果、reモジュールのsub関数を使用すればよさそうです。
③は要は自力でリストを並び替えるだけですね

```:rename_r2.py
#モジュールのインポート
import os, glob, re

#ファイル名を取得したいファイルの拡張子を設定
#※ここでは「.jpg」
ext = ".jpg"

#ファイル名の一覧取得
#ここではrename.pyと同フォルダ内にある.jpgファイルを取得しています。
files = glob.glob("*"+ext)

#ファイル一覧格納配列の要素数を取得
files_size = len(files) 

#ファイル名中の数値を格納する配列を定義
num_list = list(range(files_size))

#数値格納配列用の要素カウンタを初期化
i = 0

#名前に使用する数値のカウンタを初期化
l = 0

#ファイル名の一覧に対して以下を繰り返し実施
#ファイル名一覧から1つを取り出して、変数「file_name」に格納する
for file_name in files:

	#file_name中の数字の個所を取得
	num = re.sub("\\D", "", file_name)

	#numは現在文字列型なので、数値型に変換して配列に格納する
	num_list[i] = int(num)

	#要素数カウンタをインクリメントする
	i += 1

#前述のfor文中で取得した数値を昇順で並び替える（バブルソート）
for j in range(files_size):
	for k in reversed(range(j+1,files_size)):

		#k番目とk-1番目を比較してk番目のほうが小さい場合は数値配列の
		#k番目とk-1番目を入れ替える　ファイル名一覧配列についても同様
		if num_list[k-1] > num_list[k]:
			num_list[k-1],num_list[k] = num_list[k],num_list[k-1]
			files[k-1],files[k] = files[k],files[k-1]

#並び替えが完了したファイル名一覧に対して以下を繰り返し実施
#ファイル名一覧から1つを取り出して、変数「old_name」に格納する
for old_name in files:

	#変更後の名前のベースを設定
	#※ここでは「テスト_001」から数値が+1されていくように設定しています
	change_name = "テスト_"+"{0:03d}".format(l)

	#変更後の名称を変数「new_name」に格納する
	new_name = change_name + ext

	#ファイル名の変更
	os.rename(old_name, new_name)

	#新旧ファイル名の対応を表示
	print(old_name + "->" + new_name)

	#名前に使用する数値カウンタをインクリメント
	l += 1
```

#テストしてみる
早速実行してみます。
変更前(1).jpg～変更前(18)がテスト_000.jpg～テスト_017.jpgとなれば成功です。

実行前のスクリーンショット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048145/7868897d-3ec3-cf6e-df58-f8a312cc17b7.png)
コマンドプロンプト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048145/1460685c-4dd5-7d60-0a62-42ae3221796d.png)
実行後のスクリーンショット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048145/36213f2e-d708-c869-be94-305ff81807e5.png)

無事、一括変換することができました。
前回の問題点も解決され、想定通りに実行できています。

#終わりに
名前の一括変更をPythonで実施してみました。
ファイル名にくっついている数値を参照して昇順で並び替えています。

今回の場合はファイル名中には数値が1箇所しかないので、この書き方で何とかなっていますが、
ファイル名中に数字箇所が複数出てくる場合（例：2021桜写真01.jpg）はどの箇所の数字を並び替えに使用するのかを決めて、
その部分の数字だけを格納し、並び替えに使う必要があります。
※この辺はre.sub()での取り方で何とかなりそうな気がするので、コードとしては書きません。

今後も何か思いついたらPythonで作ってみようと思います。
ruby ハッシュについて

## 初めに
rubyの練習問題を自分なりにまとめています。メモがわりにまとめているので省略している部分やわかりにくい部分もあるのでご了承ください。
### ハッシュであらわす
```
puts hash.keys
puts hash.values
```
上記のメソッドを使用した時に以下のように表示されるようにします。

```
one
two
three
1
2
3
```

答え

```
hash = { one: 1, two: 2, three: 3 }
```

###用語について
ではまず何個か用語の説明をします。
#####ハッシュ
ハッシュとは関係の表す複数の値を管理する時に使います。
データーとそれに対応する名前をセットにして管理します。
データーをバリュー。対応する名前をキーとしてまとめます。

```
変数 = {キー１: 値　,キー２：　値}
```
####シンボル
シンボルとはコロン記号:を前置きして定義したもの。
文字列のようですが実際の中身は数値である値のことです。私も詳しく理解できていないところはありますが、メソッドなどの名前を識別するためにオブジェクトみたいなものだと思います。

###解説
今回の回答ではハッシュを[one:]のようにシンボルで記述しています。これはシンボルで記述すると数値として扱われるので処理速度が上がるというメリットがあります。よって基本的ハッシュを書くときはシンボルを用いることが多いです。
続いてハッシュのキーを取得するにはkeysメソッドを使用します。値にはvaluesメソッドにです。
なのkeysになるところを[one:]、値になるところを[1]とすることでoneと１を取得することができるのです。
これと同じようにtwo: 2,three: 3,と記述していき他の値の取得します。
Postgreの「PGSQL.5432"?」エラー解決法

## エラー内容

```
ctiveRecord::ConnectionNotEstablished
could not connect to server: Connection refused
Is the server running locally and accepting
connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
Extracted source (around line #83):
81
82
83
84
85
86
              
            raise ActiveRecord::NoDatabaseError
          else
            raise ActiveRecord::ConnectionNotEstablished, error.message
          end
        end
      end
```

## 主な解決策
ターミナルで以下のコマンドを実行（データベース再起動のコマンドになります）

```
pg_ctl -D /home/linuxbrew/.linuxbrew/var/postgres status
pg_ctl -D /home/linuxbrew/.linuxbrew/var/postgres restart
pg_ctl -D /home/linuxbrew/.linuxbrew/var/postgres status
```

私の場合はこれで大抵解決します。
[JavaScript] スプレッド演算子で配列の重複を削除する

#概要
jsでスプレッド演算子を活用して、配列の重複している部分を削除する際のメモです。

#実装

```.js
const array1 = [1, 2, 2, 1, 3, 4, 4];
const array2 = [...(new Set(array1))];
console.log(array2);

//結果：[1,2,3,4]
```

Setオブジェクトは重複した値がないことを保証するので、このような記述で重複しない配列を作成することができます。
null/undifinedになるのを防ぐ

Reactでアプリを製作していたら以下のエラー文に出会いました。

```
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
```

色々試した結果

```jsx
value={name || ''}
```
とすることで解決した

恐らく一瞬でもnullもしくはundifinedになることでエラーが出るので、それを防ぐために```''````を一緒に入れることで未然に防ぐことが出来ます。
バッチファイルによく出てくる@echo offの意味

最近バッチファイルを触ったのですが

```shell
@echo off
```

って何？　と思って調べたのでアウトプット

ついでに誰かのためになったら嬉しいかも？

#echo offの意味#
結論から言うと、**コマンドラインを見やすくする**ためのコマンド

こいつを付けないとファイルに書いてある文字がすべて出力されます。

##echo off 付けないvar##

```shell:sample.bat
set str=hello world
echo %str%
rem comment
pause
```
**結果：**

```
C:\Users\Sanada\Documents\BatFileTest>set str=hello world

C:\Users\Sanada\Documents\BatFileTest>echo hello world
hello world

C:\Users\Sanada\Documents\BatFileTest>rem comment

C:\Users\Sanada\Documents\BatFileTest>pause
続行するには何かキーを押してください . . .
```
これめちゃめちゃ見にくくないですか？
一行づつ読み込んでいくので、読み込んだ物がすべて出力されてます。

##echo off 付けたvar##
```shell:sample2.bat
@echo off
set str=hello world
echo %str%
rem comment
pause
```
**結果：**

```
hello world
続行するには何かキーを押してください . . .
```

必要な部分だけ出力されて非常に見やすいですね。

#@にも意味があった#
@echo off と echo off では結果が違う…

先に結論を言っておくと、その行を対象とするかどうかだ

##@ 付けないvar##
```shell:sample3.bat
echo off
set str=hello world
echo %str%
rem comment
pause
```
**結果：**

```
C:\Users\Sanada\Documents\BatFileTest>echo off
hello world
続行するには何かキーを押してください . . .
```

##@ 付けたvar##
```shell:sample2.bat
@echo off
set str=hello world
echo %str%
rem comment
pause
```
**結果：**

```
hello world
続行するには何かキーを押してください . . .
```


つまり下のような違いがあります
**@あり**：その行も対象
**@なし**：その行は対象外、それ以降の行から適用
[passed] AWS Certified Security - Specialty (SCS-C01)

<!-- # [passed] AWS Certified Security - Specialty (SCS-C01) -->

![passed_sec_exam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/966e7fe1-dd4a-5b63-6989-de2105739bc1.png)


標題の認定試験に合格しましたので簡単ですが記録を残したいと思います

## 学習

|item|description|
|---|---|
|教材|公式情報のみ（各種トレーニング、ホワイトペーパー、ドキュメント、 動画等）|
|期間|約二ヶ月|
|総学習時間|約 160 時間|
|模擬試験|本番の約一週間前に受験|
|言語|英語|

## 本試験

|item|description|
|---|---|
|受験方法・場所|オンライン・自宅|
|時間|120分　※*PCバッテリートラブルのため途中退出。本来は170分*|
|Pass/Fail|PASS|
|Candidate Score|822|
|言語|英語|

## 受験者のスキル

|item|description|
|---|---|
|SAA|※*失効済み*|
|AWS を利用したシステム開発経験|あり|
|セキュリティ関連実務経験|あり|

## 備考

* 学習教材は AWS 公式かつ無料でアクセス可能なコンテンツに限定
    * 限定したとはいえそれでも選択肢や情報量は膨大で、品質にも不満は感じなかった
    * 費用が発生したのは模擬試験と本試験の受験料のみ（各一回）
* 実務上扱ったことがなかったり、模擬試験で低スコアだった領域はとくに念入りにドキュメントを読み込む等
* 以後活用できそうな知識や発想を得る機会となり、良かったと思います
Postgresqlで年-月でグループ集計をする

sqliteでrails実装していたときに、年-月集計をstrftimeで実装していた。
postgresqlにDB変更したら、strftimeが使えないとエラーが出た。
これで動いた。

## CONVERSION モデル

|  Column |  Type  |
|---|---|
|  price  | integer  |
| conversion_date  | date  |

## 取得したいテーブル

|  年-月 |  総額  |
|---|---|
|  2021-1  | ¥1000000  |
| 2021-2  | ¥1000000  |


## 月次集計用のSQL

```sql
      SELECT sum(price) as total_price, 
             to_char(conversion_date, 'YYYY/MM') AS month
             from conversions 
             group by month
             order by month ASC;
```

## 参考キーワード

* postgresql group by year-month
* postgresql strftime
【Java】文字列を結合する方法(join)

# はじめに
本記事ではJava8で追加されたStringクラスのjoinメソッドについてアウトプットします。

#使い方
・指定された引数で文字列を結合します。
・１つ目の引数は区切り文字を指定し、２つ目の引数に結合する文字列を指定します。任意の数を指定できます。
・文字列の結合時に新たなインスタンスは生成されます。(StringBuilderを使うよりも遅くなる)
・文字列がnullの場合、nullという文字が追加されます。

```java
public static String join(CharSequence delimiter,CharSequence... elements)
```

```java
public class Sample {
    public static void main(String[] args) {
          
        String a = String.join("","A","BC","D");
        System.out.println(a);// ABCD
        
        String b = String.join("-","A","BC","D");
        System.out.println(b);// A-BC-D
        
        // 配列の各値を結合
        String[] sports = {"soccer","baseball","basketball"};
        String c = String.join("-",sports);
        System.out.println(c);// soccer-baseball-basketball

    }
}
```

#参照
[Java SE Platform SE 8 #join](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html#join-java.lang.CharSequence-java.lang.CharSequence...-)
Vue.js開発におけるXSS対策 メモ

* Vue.js開発におけるXSS対策について、学習した内容を備忘録としてメモする。



## XSS(クロスサイトスクリプティング)とは

* 発生の流れ
  * 攻撃者は、入力内容に、スクリプト付のリンクを貼る等の罠を仕掛ける。
  * 被害者となるユーザが誤って罠を実行する（リンクをクリック等）と、セキュリティ的に問題のある別のウェブサイト（クロスサイト）に対し、脆弱性を利用した悪意のあるスクリプトが含まれた通信が実行される。
  * その結果、偽のページがユーザに表示される。
* 反射型、蓄積型、DOMベース型がある。

 

### XSSによる被害

* CookieやlocalStorageに保存された個人情報などの抜き取り。
* Webページの改竄（入力フォーム送信先の変更など）



### DOM ベース XSS

* 攻撃者が実行可能なJavaScriptをJavaScriptによって生成されるHTML DOMに注入できる脆弱性。

  * SPAのような、Web ページ全体を都度読み込むのではなく、ページの一部分を書き換えるアプリで発生する可能性がある。

  

## Vue.jsでXSSが発生するパターン

### HTMLの挿入(v-html)

* 以下のようなコードでスクリプトをフォーム入力した場合、そのスクリプトが実行される。

```html
<div id="app">
    <p><span v-html="userProvidedHtml"></span></p>
    <input v-model="userProvidedHtml">
</div>
<script>
    new Vue({
        el:"#app",
        data:{
            userProvidedHtml: ""
        }
    })
</script>
```

#### 対策

* 入力された値を表示する際には、マスタッシュ記法(`{{userProvidedHtml}}`)を使用する。



### URLの挿入(v-bind)

* 以下のようなコードでスクリプトをフォーム入力した場合、`a`タグにスクリプトが反映される。
* クリックすると、そのスクリプトが実行される。

```html
<div id="app">
    <a v-bind:href="userProvidedUrl">
  		click me
	</a>
    <input v-model="userProvidedUrl">
</div>
<script>
    new Vue({
        el:"#app",
        data:{
            msg: ""
        }
    })
</script>
```

#### 対策

* [sanitize-url](https://www.npmjs.com/package/@braintree/sanitize-url) 等のライブラリや算出プロパティを使用して間接的に値を渡す。

### スタイルの挿入(v-bind)

* サニタイズ未実施のスタイル(`userProvidedStyles` を利用すると、攻撃者はクリックジャックのための CSS を設置することができる。以下は例。
  * ログインボタンの上の透明ボックスにリンクをスタイリングする。
  * ログインページに似せたサイトが構築されていた場合、ユーザーはログイン情報を盗まれる可能性がある。

```html
<a
  v-bind:href="sanitizedUrl"
  v-bind:style="userProvidedStyles"
>
  click me
</a>
```

#### 対策

* オブジェクト構文を使用し、特定のプロパティのみ指定させる。

  ```html
  <a
    v-bind:href="sanitizedUrl"
    v-bind:style="{
      color: userProvidedColor,
      background: userProvidedBackground
    }"
  >
    click me
  </a>
  ```

  

### サーバーサイドテンプレートの挿入

* 下記のようなPHPコードをサーバー上に配置し、パラメータに `param={{スクリプト}}` を設定してアクセスすると、スクリプト が実行されることがある。

```php
<div id="app">
  <?= htmlspecialchars($_GET["param"], ENT_QUOTES, "utf-8") ?>
</div>
<script>
      new Vue({
        el: '#app'
      })
</script>
```

#### 対策

* 可能な限り、バックエンド側とフロントエンド側のテンプレートを混在させない。
  * HTML の動的な生成はフロントエンド側のみで行うなど。
* ユーザー入力を出力する箇所では、HTMLエスケープを行ったうえで、v-preを使用し、PHP などで動的に出力する箇所のコンパイルをスキップさせる。



## 参考情報

* [セキュリティ — Vue.js](https://jp.vuejs.org/v2/guide/security.html)
* [Vue.js で XSS](https://www.slideshare.net/tobaru_yuta/vuejs-xss)
* [Vue.jsエンジニアなら知っておきたいセキュリティー](https://kotamat.com/post/vuejs-security/)
* [Vue.js で XSS を作り込まないために気を付けること](https://techblog.securesky-tech.com/entry/2018/08/01/110000)
コマンドラインで、csvファイルの列数と行数を取得する

# 概要

業務にて、データ分析のために拡張子が.csv のファイルを扱う機会があった。
`pandas.DataFrame`にデータを食わせて取得しても良いのだが、コマンドラインでささっと数と行数・列名（カラム名）一覧を確認したかったので、備忘録として残しておく。

## 行数を取得
`wc`を使う。

https://www.atmarkit.co.jp/ait/articles/1611/07/news026.html

```bash:terminal
$ wc -l hoge.csv
30
```

## 列数を取得
`awk`を使う。

https://www.atmarkit.co.jp/ait/articles/1706/15/news021.html

```bash:terminal
$ awk -F ',' 'NR==1{print NF}' hoge.csv
1000000 hoge.csv
```
条件で1行目`NR==1`を指定し、列数`(NF)`を出力している。

## 列名を取得
`awk`を使う。

```bash:terminal
$ awk -F ',' 'NR==1{print $0}' hoge.csv
id, age, gender, time, created_at, updated_at, ...
```
条件で1行目`NR==1`を指定し、1行目の文字列全体`$0`を出力している。

---
列数、行数や列名（カラム名）一覧の確認程度であれば、`Jupyter`を開かずともLinuxコマンドで実現できるので、知っておきたいですね。
ささっとコマンドが書けると、ちょっと楽しい。
Jetson NanoでCEF (Chromium Embedded Framework)をビルドしてみた

# はじめに

Jetson Nanoでライブ配信ソフトOBS Studioを"ブラウザソースあり"でビルドできないの？！という質問を受けた。

https://qiita.com/kitazaki/items/3950c48a68bab1766fb6

![スクリーンショット 2021-03-28 9.09.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/b33cb453-dd25-5974-db93-bc87b688d7e4.png)

公式ページを参照すると、"ブラウザソースあり"＝ブラウザソースプラグインをビルドするためには、CEF (Chromium Embedded Framework)が必要ということが分かった。

https://obsproject.com/wiki/install-instructions

### CEF (Chromium Embedded Framework)とは

Google Chromeの表示部分だけを抜き出したフレームワークで、他のアプリ(今回はOBS Studio)に埋め込んで使用する。CEFはChromium本体から作られる＝ビルドに時間がかかるので、Spotify社が提供するビルド済ライブラリを利用してビルドしてみた。

# ビルド手順

## 1. ビルドに必要なパッケージのインストール

```bash
$ sudo apt install build-essential gtk2.0 libgtk2.0-dev libgtkglext1-dev
```

## 2. ソースのダウンロード

```bash
$ git clone https://bitbucket.org/chromiumembedded/cef-project
```

## 3. CMakeLists.txtの変更

Jetson Nano (JetPack 4.5.1)はlinuxarm64アーキテクチャで、CMakeLists.txtはlinuxarm64を想定していないため、CMakeLists.txtの変更が必要になります。

```bash
$ cd cef-project
```

CMakeLists.txtに以下の内容を追加します。

```
    if(PROJECT_ARCH STREQUAL "linuxarm64")
      set(CEF_PLATFORM "linuxarm64")
    endif()
```

差分は以下のとおりです。

```bash
$ diff CMakeLists.txt CMakeLists.txt_org 
36,38d35
<     if(PROJECT_ARCH STREQUAL "linuxarm64")
<       set(CEF_PLATFORM "linuxarm64")
<     endif()
```

変更したCMakeLists.txtをgithubに置きます。

https://github.com/kitazaki/JetsonNano_CEF

## 4. ビルド

```bash
$ mkdir build && cd build
$ cmake -G "Unix Makefiles" -DPROJECT_ARCH="linuxarm64" -DCMAKE_BUILD_TYPE=Release ..
$ make -j4
```

# 5. cefclientの動作確認

ビルド途中に表示されるchrome-sandboxの所有者と権限を変更します。

```bash
$ cd third_party/cef/cef_binary_87.1.12+g03f9336+chromium-87.0.4280.88_linuxarm64/tests/cefclient/Release
$ sudo chown root:root chrome-sandbox
$ sudo chmod 4755 chrome-sandbox
```

cefclientを起動します。

```bash

$ ./cefclient
``` 

![Screenshot from 2021-03-28 09-48-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1d99c70f-13a5-b34d-7775-1f54808dbb0d.png)

![Screenshot from 2021-03-28 09-49-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1ac1991e-2fe8-e13b-026e-1233183c2e20.png)

### 参考

https://qiita.com/propella/items/aaeabca6a4ba67b86cd1

https://www.youtube.com/watch?v=5Zf9OAHTDLU

* 2022/3/21 追記

# Jetson Nano JetPack 4.6.1 / cef_binary_96.0.16+g89c902b+chromium-96.0.4664.55_linuxarm64

### 環境

- Jetson Nano 4GB (A02)
- JetPack 4.6.1
- cef_binary_96.0.16+g89c902b+chromium-96.0.4664.55_linuxarm64

## 1. ビルドに必要なパッケージのインストール

追加で以下のパッケージのインストールが必要です。

```bash
$ sudo apt install libgtk-3-dev
```

これ以外の手順は同じです。
【Java】数値と文字列の変換方法 (valueOf)

# 数値を文字列に変換
valueOfメソッドで数値を文字列に変換できます。

```java
public class Sample {
	public static void main(String[] args) {

		int num1 = 2021; // int型
		String a = String.valueOf(num1);//String型に変換
		System.out.println(a);//2021

		long num2 = 2021; // long型
		String b = String.valueOf(num2);//String型に変換
		System.out.println(b);//2021

		double num3 = 2021.21; // double型
		String c = String.valueOf(num3);//String型に変換
		System.out.println(c);//2021.21
	}
}
```

# 文字列を数値に変換
valueOfメソッドは文字列を数値に変換することもできます。

```java
public class Sample {
	public static void main(String[] args) {

		String str1 = "2021";
		int a = Integer.valueOf(str1); //int型に変換
		System.out.println(a);	// 2021

		long b = Long.valueOf(str1); //long型に変換
		System.out.println(b);	// 2021

		String str2 = "2021.21";

		float c = Float.valueOf(str2); //float型に変換
		System.out.println(c);	// 2021.21

		String str3 = "2021.21";

		double d = Double.valueOf(str3); //double型に変換
		System.out.println(d);	// 2021.21

	}
}
```

# 参照
[Java Platform SE8 クラスString](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html)
【rails】gemの処理にbinding.pryを差し込む方法

# なにこれ
railsで開発をしていると、
「このgemの処理ってどうなってるんだろう？」
と考えることがあると思います。

そこで、今回はgemのコードの中に
`binding.pry`を置く方法を紹介します！


# やり方

## 環境変数BUNDLER_EDITORを定義

今回はvimで検証します。

```ターミナル.
$ export BUNDLER_EDITOR=vim

// 確認
$ echo $BUNDLER_EDITOR
#=> vim
```

## bundle openで開きたいgemを開く

```
bundle open <gem_name>

// 例
bundle open rails
```

無事gemの中に入ることが出来ました！
ディレクトリを移動して、好きなファイルに`binding.pry`を置きまくりましょう。

```gemの中.
../                                                                          
./
README.md
```

#### tips
vimで検索する方法は、ノーマルモードで`?hoge`と入力します。

## 変更を反映させる方法
railsを再起動すれば、差し込んだ箇所で`binding.pry`が呼ばれます！

## 参考
https://tbpgr.hatenablog.com/entry/2016/11/15/231818