OmniAICreator/Qiita-1.07M huggingface dataset:
デジタルの世界へ！！初心者がLINE BOTで「図書館検索ツール」作ってみた件

## LINE BOT「図書館検索ツール」ができるまで
皆さん、こんにちは！私は北海道の小売業で働いているサラリーマンです！
業務としては営業ではなく、会社として環境や社会への貢献に取り組む業務をメインに働いています。
その業務の中で青少年の育成として小学１年生から中学３年生までを対象に環境や社会について学ぶクラブの運営をするという業務があり、そのクラブに所属する子供たちがいろいろな体験や気づきが得られるような企画を考えることも業務の一つです。
クラブは、全道各地にあり北は名寄、南は静内、他にも函館や釧路など広範囲に発足しています。
そんな各地域で活動するメンバーに、幅広くいろいろな学びを得てもらうことを考えたとき、小学生でも活用しやすく様々なジャンルの本がある図書館を思いつき、各地域の図書館を簡単に調べることが出来る**LINE BOT**を作成しました。

## 図書館検索ツールの概要
今回作った**LINE BOT**は、自分が検索したい地域を入力すると**図書館の名前**と**住所**が出てくるものです！
<img width="400" alt="スクリーンショット 2022-04-22 6.12.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/8987cecc-5d3a-94f7-6b71-00a3c58946ec.png">
## LINE BOT作成に使用したもの
- [LINE Messaging API](https://developers.line.biz/ja/)
- [Make](https://www.make.com/en)
- [図書館API(カーリル)](https://calil.jp/doc/api_ref.html)

## 作成の手順
**1.**[LINE Messaging API](https://developers.line.biz/ja/)の登録(Webhook設定・チャンネルアクセストークンの発行)

**2.**[Make](https://www.make.com/en)の登録・[Make](https://www.make.com/en)と[LINE Messaging API](https://developers.line.biz/ja/)の連携
<img width="700" alt="スクリーンショット (80)" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/bb0b6840-73d1-00b6-d677-8830764a2413.png">


**3.** HTTPモジュールに図書館APIのURLを入力
<img width="500" alt="スクリーンショット (83).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/533b3d0c-4635-60ba-ebb8-d1c7f5b8f48b.png">


**4.** JSONモジュールに図書館APIを入力
<img width="600" alt="スクリーンショット (84).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/df2e0afa-ffa8-f240-ce23-356b5ad70153.png">


**5.** LINE（Send a Reply Message)モジュールのTextに図書館名と住所を指定
<img width="500" alt="スクリーンショット (86).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/02327dae-93ca-353f-baf2-13e5cdb65c20.png">


**6.**検索したい市を入力
<img width="500" alt="スクリーンショット 2022-04-22 6.12.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2621180/8987cecc-5d3a-94f7-6b71-00a3c58946ec.png">


## 最後に
完成形には程遠いですが、ひとまず形にはなったと思います。
本当は、市にある図書館と住所が全部出るように作りたかったのですが今後の課題として取り組んでいきます。
今回取り組んでみて、改めて**為せば成る**と実感しました！**新しいことに挑戦しないなんてもったいない！**
**この記事が皆さんの新たな挑戦の一助になればうれしいです！一緒に新しいことにどんどん挑戦していきましょう！**
AWS EC2でnode.jsのバージョンの下げ方


AWS EC2でnode.jsのバージョンが原因で、上手くいかない...。
そんな時の対処方法を記しておきます。
# 準備
SSHを使用してEC2に接続します。
```
$ ssh ec2-user@255.255.255.255 -i .ssh/qiita-sample.pem
Last login: Wed Apr 20 20:13:54 2022 from qiita-sample.com

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
19 package(s) needed for security, out of 33 available
Run "sudo yum update" to apply all updates.
```
nvmはnode.jsのバージョン管理ツールです。
```
$ nvm --version
$ nvm 0.34.0
```
# nvmの使い方
現在、システムにインストールされている node.js のバージョンを確認します。
```
$ nvm ls
->      v17.7.0
default -> v17.7.0
node -> stable (-> v17.7.0) (default)
stable -> 17.7 (-> v17.7.0) (default)
lts/gallium -> v16.14.2 (-> N/A)
```
インストール可能なバージョンはnvm ls-remoteコマンドで確認できます。
```
$ nvm ls-remote
# インストール可能なnode.jsのバージョン一覧
         ~ 略 ~
        v16.14.1   (LTS: Gallium)
        v16.14.2   (Latest LTS: Gallium)
         ~ 略 ~
        v17.9.0
        v18.0.0
```
一覧からインストールしたいバージョンを選び、`nvm install`でインストールします。
```
$ nvm install v16.14.2
```
インストールが終わると、自動的にインストールしたバージョンのnode.jsが使われるように設定されます。
```
$ node -v
v16.14.2
```
# node.jsのバージョンを固定
ターミナルを再起動すると、元のバージョンに戻ってしまいます。
```
$ node -v
v17.7.0
```
`nvm alias`を使い、デフォルトのバージョンを変えます。
```
$ nvm alias default v16.14.2
```
ターミナルを再起動すると、デフォルトのバージョンが変わります。
```
$ nvm ls
->     v16.14.2
        v17.7.0
default -> v16.14.2
node -> stable (-> v17.7.0) (default)
stable -> 17.7 (-> v17.7.0) (default)
lts/gallium -> v16.14.2
```
GCP Cloud Run デプロイ時エラー「Container failed to start. Failed to start and then listen on the port defined by the PORT environment variable.」でハマった場合

GCP Cloud Runのデプロイ時に上記のエラーが出て、リスニングポートは指定したのにエラーが解消しないケースがありました。

まずはGCPの公式ドキュメント通りにトラブルシューティングします。
[Cloud Run のトラブルシューティング](https://cloud.google.com/run/docs/troubleshooting)

それでもエラーが解消されない場合、
`DBのテーブルのカラム設定とプログラムで記述しているカラム設定が一致していない`可能性があります。

今回のケースではCLoud SQLを利用しており、
テーブルにレコードが残っている場合は、プログラムのカラム設定が反映されないケースがあるのでテーブルのレコードを全て削除して再デプロイすると成功しました。
【rails入門】ページのスクロールに合わせて要素を動かす！

# 完成したこんな感じ
![scroll.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/f51bc88d-cda0-6d18-927e-7cfba53be42f.gif)

スクロールに応じて要素を左右に動かす！

# コード
```html:index.html
<div class="scroll">
    <div class="scroll-1">My name is Naoya.</div> <!-- 動かす要素 -->
    <div class="scroll-2">GeekSalon Fukuoka</div> <!-- 動かす要素 -->
</div>
<script>
    const scroll1 = document.querySelector('.scroll-1'); //要素取得
    const scroll2 = document.querySelector('.scroll-2');　//要素取得

    window.addEventListener('scroll', () => { //eventlistener定義
        scroll1.style.setProperty('--scroll',window.scrollY + 'px'); 
        //カスタムプロパティ --scroll の値にy軸方向のスクロール量を代入
        scroll2.style.setProperty('--scroll',window.scrollY + 'px');
        //カスタムプロパティ --scroll の値にy軸方向のスクロール量を代入
    })
</script>
```
```css:index.css
.scroll{
    overflow: hidden; /*適当*/
}
.scroll-1{
    width: 500px; /*適当*/
    position: absolute;
    --scroll: 0; /*カスタムプロパティ（変数）宣言*/
    top: 50vh; /*適当*/
    left: var(--scroll);
    /*2行上で宣言してるカスタムプロパティの位置に移動させる。javascriptでカスタムプロパティの中身変更してる*/
}
.scroll-2{
    width: 500px; /*適当*/
    position: absolute;
    top: 60vh; /*適当*/
    --scroll: 0; /*カスタムプロパティ（変数）宣言*/
    right: var(--scroll);
    /*2行上で宣言してるカスタムプロパティの位置に移動させる。javascriptでカスタムプロパティの中身変更してる*/
}
```
# 解説
特になし

終わり
ばいちゃ
【Next.js】404ページのカスタマイズ

## はじめに
本記事は、プログラミング初学者が学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  
そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  
間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。  

## 404ページのカスタマイズ
まず、`pages`に`404.js`を追加します。

![スクリーンショット 2022-04-22 4.04.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/9ea3a2f5-f530-2175-a666-10c9d55359c2.png)

次に`404.js`に以下のように記述します。
```404.js
export default function Custom404() {
  return <h1>ページが見つかりません</h1>
}
```

すると以下のように404ページが変更されます。

デフォルト

![スクリーンショット 2022-04-22 4.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/f5237359-9bdf-117f-0a19-1ea85bf51fa4.png)

カスタマイズ

![スクリーンショット 2022-04-22 4.11.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ec5477ea-a42d-951f-e239-32dc425f08d7.png)
CronJobからVolumeClaimTemplateを用いてtknコマンドでパイプラインを実行する

jobTemplate内でConigMapをVolumeとしてマウントさせることで、CronjobからVolumeClaimTemplateを用いてパイプラインを実行させられたのでメモとして残します。

## 前提
task, pipelineはapply済み。Dynamic Provisioningが設定されている環境を想定しています。

##  やりたいこと
CronJobからVolumeClaimTemplateを用いてパイプラインを実行させたい。

## 課題
job上で、tknコマンドを用いてパイプラインを実行したいが、現時点ではtknコマンドはパラメータでのVolumeClaimTemplateの細かな設定は実装されておらず、外部ファイルのパスを参照する仕様となっているようです。
参考：https://github.com/chmouel/tektoncd-cli/blob/main/docs/cmd/tkn_pipeline_start.md

>$ tkn pipeline start [name] --workspace name=[name],volumeClaimTemplateFile=/path/to/volume-claim-template.yaml

```volume-claim-template.yaml
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: abc-xxx
```

ローカルからtknコマンドを実行する場合であれば問題ないが、Jobで実行しようとするとコンテナ内にファイルが存在しないためエラーとなります。

## 解決策
CronJobはjobTemplateの形式で記載できるので、ConfigMapでマウントさせることでコンテナ内にyamlを配置する。

volume-claim-template.yamlをConfigMapとしてapply。

```volume-claim-template-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: volume-claim-template
data:
  volume-claim-template.yaml: |
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
      storageClassName: abc-xxx
```

作成したConfigMapをCronJob作成時に任意のパス（/volume-claim-templateなど）にマウントさせ、tkn実行時にパラメータで該当のパスを指定します。
```test-cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: test-cronjob
spec:
  schedule: "0 0 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: sample
          containers:
          - name: sample-cronjob
            image: image-registry.openshift-image-registry.svc:5000/openshift/pipelines-cli-tkn-rhel8:0.19.0-3
            command: ["sh", "-c"]
            args:
            - |
              tkn pipeline start sample-pipeline \
              --prefix-name sample-pipeline \
              --serviceaccount sample \
              --param git-url=https://xxx/sample.git \
              --param git-revision=develop \
              --param maven-context-dir=sample \
              --param maven-image=image-registry.openshift-image-registry.svc:5000/openshift/maven:3.8-openjdk-8 \
              --param maven-goals=\
              clean,\
              verify,\
              deploy,\
              sonar:sonar \
              --workspace name=maven-settings,secret=mvn-settings \
              --workspace name=shared-workspace,volumeClaimTemplateFile=/volume-claim-template/volume-claim-template.yaml
            volumeMounts:
            - name:  volume-claim-template
              mountPath: "/volume-claim-template"
          restartPolicy: Never
          volumes:
          - name: volume-claim-template
            configMap:
              name: volume-claim-template 
```

これにより稼働させたコンテナ内でyamlファイルを読み込ませることができ、CronJobからVolumeClaimTemplateを用いたパイプラインが実行可能となります。
【php】文字列操作基礎

### 複数行の入力

ヒアドキュメントと呼ばれる方法。EOMの目印が出てくるまで文字列を出力する

```PHP
echo <<< EOM
one
two
three
EOM;
```

### 小文字から大文字に変換
```PHP
echo strtoupper('hello world!');
```
```PHP
HELLO WORLD!
```

### 文字列の一部を取得
文字列の最初の値は0
substr(string, 取り出し開始位置, length);
```PHP
echo substr('abcde', 0, 2);
```
```PHP
ab
```

### 配列の中の最大値・最小値を取り出す
```PHP
$array = array(1, 2, 3, 4);
echo max($array);
echo min($array);
```
```PHP
4
1
```

### 文字列の中の特定の要素の個数をカウント
```PHP
echo substr_count("aAaAaA", "A");
```
```PHP
3
```

### 文字列の文字数をカウント
```PHP
echo mb_strlen('abcde');
```
```PHP
5
```

### 文字列の置き換え
```PHP
$str = "helloatworld";
echo str_replace("at", "@", $str);
```
```PHP
hello@world
```

### 特定の文字列を含むかのチェック
strpos(検索対象の文字列, 特定の文字列);
該当する文字列が見つからなかった場合、falseを返す
```PHP
$subject = "abcdefg";
if(strpos($subject, "bc") !== false){
	//$subjectの中に"bc"が含まれている場合
}

if(strpos($subject, "bc") === false){
	//$subjectの中に"bc"が含まれていない場合
}
```
Ubuntu環境のgitkを開いた瞬間にすぐクラッシュすることがある問題について

# 問題

ある特定Gitリポジトリを可視化しようと gitk コマンドによってウインドウを立ち上げた。
しかし、何故かあるリポジトリのみ即時にクラッシュし、それ以外のリポジトリは正常に開ける。

環境は Ubuntu 20.04 LTS。 クラッシュ時には以下のようなメッセージが表示された。

```bash
$ gitk --all
X Error of failed request:  BadLength (poly request too large or internal Xlib length error)
  Major opcode of failed request:  140 (RENDER)
  Minor opcode of failed request:  20 (RenderAddGlyphs)
  Serial number of failed request:  4767
  Current serial number in output stream:  4830
```

# 原因と対応策

https://unix.stackexchange.com/questions/629281/gitk-crashes-when-viewing-commit-containing-emoji-x-error-of-failed-request-ba

上記で説明があるように、絵文字（🍣とか）を gitk 上に表示しようとしてクラッシュしているらしい。
デバッグ結果を見る限り、絵文字として利用するフォントのピクセルが大きすぎて文字を表示しきれないエラーが生じているように見える。


```bash:デバッグ結果
$ XFT_DEBUG=1 gitk --all
XFT_DEBUG=1
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (13.3333 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (13.3333 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (13.3333 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: 5 (13.3333 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: 5 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: 5 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: 5 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: 5 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc: 0 (12 pixels)
XftFontInfoFill: /usr/share/fonts/truetype/noto/NotoColorEmoji.ttf: 0 (109 pixels)
X Error of failed request:  BadLength (poly request too large or internal Xlib length error)
  Major opcode of failed request:  140 (RENDER)
  Minor opcode of failed request:  20 (RenderAddGlyphs)
  Serial number of failed request:  4236
  Current serial number in output stream:  4282
```

絵文字を使わないように、該当の絵文字フォントを削除することでも対応できるが、これを実施するとそれ以外の場面で絵文字が使えなくなってしまうため、別の方法で対処したい。

その方法の１つとしては、別のフォントをインストールする方法がある。
`unifont` をインストールすることで、gitk 上の絵文字は豆腐文字として表示されるようにはなるが、クラッシュすることはなくなる。

```bash
$ sudo apt install unifont
```

ちなみに、今回この現象は Gatsby が自動生成する README.md をコミットしたことによって発生した。
一部抜粋すると、以下のように 🚀 の絵文字が使われていることが分かる。

```md
## 🚀 Quick start

1.  **Create a Gatsby site.**

    Use the Gatsby CLI to create a new site, specifying the minimal TypeScript starter.

    ```shell
    # create a new Gatsby site using the minimal TypeScript starter
    npm init gatsby
    ```
```
Atcoder B - Nice Shopping

## 問題
https://atcoder.jp/contests/hitachi2020/tasks/hitachi2020_b

## 回答

```Python
A,B,M = map(int,input().split())
a = list(map(int,input().split()))#冷蔵庫
b = list(map(int,input().split()))#電子レンジ
ans = min(a) + min(b)
 
for i in range(M):
  x,y,c = map(int,input().split())
  num = a[x-1] + b[y-1] - c
  if ans > num:
    ans = num
 
print(ans)

```

または
```Python
A,B,M = map(int,input().split())
a = list(map(int,input().split()))#冷蔵庫
b = list(map(int,input().split()))#電子レンジ
ans = min(a)+min(b)
for i in range(M):
    x, y, c = map(int,input().split())

    ans = min(ans,a[x-1]+b[y-1]-c)
 
print(ans)

```

## ポイント
for文の中で```x, y, c = map(int,input().split())```の標準入力を記載すること」。これが思いつかず。
.devcontainer.jsonの設定をいつも忘れるのでメモ 

こんにちは。

VSCodeを使ったRemoteContainer開発、とても便利ですよね！

ただ、作るたびに`.devcontainer.json`をどう設定すれば快適なのか考えてしまうので、必ず設定している部分をメモしておきます。

## 前提
docker-composeは使わないものとします。

## .devcontainer.jsonの中身
エクステンション部分は省略しますがだいたいこんな感じです。

```json:.devcontainer.json
"name": "My DevContainer",
"build" : {
	"dockerfile": "Dockerfile",
},
"workspaceFolder": "/workspace", 
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
"mounts": [
     "source=${localEnv:USERPROFILE}/.aws,target=/root/.aws,type=bind,consistency=cached",
     "target=/workspace/node_modules",
],
"onCreateCommand": "git config --local core.editor code",
```

### workspaceFolder
今ローカルで開いているワークスペースをコンテナ内のどのパスに配置するかを指定します。
デフォルトだと`/workspaces/<VSCodeのワークスペース名>`になりますが、私はプロジェクトに限らず開発用コンテナのルートは同じにしたいので固定しています。

基本的に**workspaceMount**と合わせて使います。

### workspaceMount
Docker CLIの`--mount`オプションの書式でワークスペースのマウント方法を指定します。

`target`の指定は**workspaceMount**と同じパスを指定します。


### mounts
ローカルの各ディレクトリのマウント方法を指定します。
私がいつも設定しているものは

- AWSの認証情報などワークスペース外のファイル
- node_modulesなどマウントする必要のないファイル、ディレクトリを名前付きボリュームで指定

です。

特に2つ目はローカルマウントした状態でコンテナ内でビルドすると致命的に遅くなるので大切です。


### onCreateCommand
開発用コンテナが出来上がった際に実行されるコマンドです。
Dockerfileに書いても良いのですが、Dockerfileにはあまり手を加えたくないのでこっちに書いています。

私はgitのデフォルトエディターを設定しています。


&nbsp;  
&nbsp;  
  
以上です。

他にこんな設定しておくと良いぞ！などあれば教えてください。
Unityで''スクリプトが追加出来ません''とポップアップが表示されてしまう現象の解決策

<h1>''スクリプトが追加できません''の原因と解決策</h1>

<h2>端的に結論、class名とスクリプト名を一致させる必要がある</h2>
詳細は以下に....<br>
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/39a4ee98-386e-ed6c-9b14-453017541196.png"> 
<br>エラースクリプトクラスが見つからないため、スクリプトコンポーネント'Practive'を加えることができません。コンパイルエラーがなく、ファイル名とクラス名が一致していることを確認してください。
<br>というポップアップが出現した。<br>
Unityを触り始めた初日に遭遇した（タイポは見逃して欲しい笑）<br><br>
○推測される原因<br> 
・スクリプト(C#ファイル)作成後にファイル名を変更している<br>
・スクリプト(C#ファイル)の名前を変更した

→**クラス名とスクリプト名が一致していない**
 
　
以下には私自身の失敗例を示します
<img width="210" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/a8bf59a8-9ab7-e610-f70f-4e2c43d593b0.png">
<br>①ファイル作成時<br>
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/7acd4fc7-d1de-75c4-772d-eb89faf9c19f.png">
<br>②エンター押して確定<br>
<img width="200" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/81a24641-4301-b411-cf4e-0c8b9ecc4b64.png">
<br>③名前を変更<br><br>

このように変更すると、スクリプト名は''**Practice**''であるのに対し、スクリプト内に記述されたクラス名（赤線部）は''**NewBehaviourScript**''になってしまっている。(下の画像)
<br>**クラス名とスクリプト名を一致させる必要がある**ため以下のように書き換える<br>
○変更前
<img width="600" alt="IMG_0012.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/1f50d4f1-af3a-6972-dc34-fe73e5f49345.jpeg">
<br>
○変更後
<img width="600" alt="IMG_0011.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627419/bc9009d9-bddb-ea10-a919-f7172095260a.jpeg">

これで解決できた！！！！

**スクリプトを作成する際には最初に名前をしっかり決めてあげよう！！！**

<h2>初投稿で見苦しい記事ですが誰かの助けになれば幸いです</h2>
読んでいただき、ありがとうございました(⌒▽⌒)
Spring Data JPAのカラム名でハマったところ【Unknown column '○○' in 'field list'】

Spring boot,JPA,MySQLを使用して、DB接続した際にカラムに関するエラーが発生してハマってしまったので忘備録として残しておく。


タスク管理アプリ作成しており、タスクテーブルに対応するentityであるTaskクラスを作成してアプリを起動した時に以下のエラーが発生した。

**【発生したエラー】**
Unknown column 'created_date' in 'field list'


フィールドに'create_date'という不明なものがあると言っているのはわかるが、以下の通り、entityでは'createdDate'と書いているし、MySQLでも同様の名前で命名している。


```Task.java
@Entity
public class Task {
	
	@Id
	@GeneratedValue
	private int id;
	
	@Column
	private int user_id;
	
	@Column
	private String title;
	
	@Column
	private String task;
	
	@Column(updatable = false)
	@CreationTimestamp
	private Timestamp createdDate;
	
	@Column
	@UpdateTimestamp
	private Timestamp updatedDate;
}
```






テーブルの構造↓(面倒なので画像で)

![スクリーンショット 2022-04-22 1.08.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/935552/e2eee0ea-5be5-5552-3b43-b27df10ae6fe.png)



'created_date'というフィールドはないのにエラーでは存在していると言われて原因と解決方法がわからずハマってしまった。



# 原因と対応策

JPA(Hibernate)の仕様によるものでキャメルケースで命名されたフィールドはスネークケースに変換されるようだ。

調べたところ、Hibernateでは以下の順に変換を行ってからカラム名が作成される。(デフォルト)

**①論理名の生成**
クラス名、フィールド名を論理名として取得し、@Columnや@Tableで指定されていれば、その文字列を論理名にする

**②物理名の生成**
ピリオドをアンダーバーに置き換える
キャメルケースをスネークケースに置き換える


今回の場合、タスクテーブルのカラム'createdDate'に対応するTaskクラスのフィールド名をそのまま'createdDate'としていたが、'created_date'に変換されてしまったため、カラム名に対応していなくてエラーが発生した。

対応策として、タスクテーブルのカラム名を'created_date'に変更したことで解決できたが、entity側を修正する場合は@Column(name="createddate")のように全て小文字にすれば問題なく取得できるとのこと。
MacBookで再度RMeCabからneologdを使えるようにしました。そのメモ


以前、RMeCabからneologdを使えるようにしました

https://qiita.com/tex_owleyes/items/19a4abf1a4f888f78818

ただ、別のMacにインストールする際、思ったより参照しにくかったので、その手順を飲みをメモしておくことにしました。

# Macターミナルでインストール

~~~php
#mecabインストール
% xcode-select –install
% cd ~/Downloads
% curl -fsSL "https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE" -o mecab-0.996.tar.gz
% tar xf mecab-0.996.tar.gz
% cd mecab-0.996
% ./configure –with-charset=utf8
% make
% sudo make install

#brewインストール
cd
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

#Next steps:
#- Run these two commands in your terminal to add Homebrew to your PATH:
#上記メッセージに従い以下実行
% echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/hiro_ogawa/.zprofile
% eval "$(/opt/homebrew/bin/brew shellenv)"

#brewのバージョン確認
% brew -v

#動作に必要なパッケージ「xz」インストール
% brew install xz

#neologd辞書のクローン作成
% git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git

#neologd辞書インストール
% cd
% ./mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a

#neologd辞書を指定してmecab実行
% mecab -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/
両面宿儺と肉体を共有することとなった虎杖悠仁は、最強の呪術師である五条悟の案内で、対呪い専門機関である「東京都立呪術高等専門学校」へと編入
両面宿儺	名詞,固有名詞,人名,一般,*,*,両面宿儺,リョウメンスクナ,リョーメンスクナ
と	助詞,並立助詞,*,*,*,*,と,ト,ト
肉体	名詞,一般,*,*,*,*,肉体,ニクタイ,ニクタイ
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
共有	名詞,サ変接続,*,*,*,*,共有,キョウユウ,キョーユー
する	動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
両面宿儺と

#（扱いやすいと考え）neologd辞書を標準辞書ディレクトリにコピー
% cd /Users/user_name/mecab-ipadic-neologd/build/mecab-ipadic-2.7.0-20070801-neologd-20200910/
% sudo cp -f mecab-user-dict-seed.20200910.csv /usr/local/lib/mecab/dic/ipadic/
#コピー先確認
% cd /usr/local/lib/mecab/dic/ipadic/

#RMeCabにneologdにインストール
% cd /usr/local/lib/mecab/dic/ipadic/
% sudo /usr/local/libexec/mecab/mecab-dict-index \
-d /usr/local/lib/mecab/dic/ipadic \
-u mecab-user-dict-seed.20200910.csv.dic \
-f utf-8 \
-t utf-8 mecab-user-dict-seed.20200910.csv
~~~

# Rで試す

~~~R
input <- "両面宿儺と虎杖悠仁"
library(RMeCab)
RMeCabC(input, dic = "//usr/local/lib/mecab/dic/ipadic/mecab-user-dict-seed.20200910.csv.dic")

[[1]]
      名詞 
"両面宿儺" 

[[2]]
助詞 
"と" 

[[3]]
      名詞 
"虎杖悠仁" 
~~~
Wordpressの管理バーを簡単なCSSだけで邪魔にならないようにする

### はじめに
&lt;headeer&gt; が動的に動くサイトを作成していると、Wordpressの管理バーが邪魔！なの

### 調べたこと
- 超簡単な方法 簡単かもしれないがめんどくさい方法
- プラグインを入れる。もっと簡単だが、プラグインの入れすぎは。

### これで解決

```wordpress-admin.css
body.admin-bar header {
  margin-top: 32px;
}

```

### 理由
あくまで最新のWordpressのお話ですが、
ページによって body に 以下のclass を付与してくれます。

例えば

- TOPページ = home
- 記事ページ = single
- 固定ページ = page
- ログイン中 = admin-bar

のように入れてくれます。

この bodyのclassの有無で判別すれば良いことになります。
既存のGatsbyプロジェクトをDocker化した。

# はじめに
既存のGatsbyプロジェクトをDockerで起動できるようにしました。色々学ぶことが多かったので、恐れ多いながら記事にしてみようという試みです。何かの参考になれば嬉しいです！

- 環境
    - macOS Monterey
- プロジェクト概要
    - フレームワーク: [Gatsby](https://www.gatsbyjs.com/)
        - Gatsbyのバージョン: 3
    - パッケージマネージャ
        - [yarn](https://yarnpkg.com/)
- 対象者
    - 「既存のGatsbyプロジェクトをDocker化したい！」という方。

# Dockerfile,docker-compose.yml周り
最終的に、以下のような内容のDockerfileとdocker-compose.ymlを作成したらうまくいきました。もちろん、これが最善策だとは思ってないです。「ここはこうした方がいいよ！」などのご指摘がありましたら、ぜひコメントなどでお伝えいただきたいです！
Dockerfileはこちら↓
```Dockerfile
# NOTE: nodeをベースイメージにすると、sharp周りでエラーが起きる。cf. https://gotohayato.com/content/548/
FROM node:16-bullseye

# NOTE: WORKDIRの値は、有効な任意のディレクトリ名
WORKDIR /sample

COPY . ./
# NOTE: 念の為node_modulesを削除。cf. https://github.com/lovell/sharp/issues/2443
RUN rm -rf node_modules 
RUN yarn install
RUN yarn global add gatsby-cli

ENTRYPOINT [ "gatsby","develop","-H", "0.0.0.0", "-p", "8000" ]
```
docker-compose.ymlはこちら↓
```docker-compose.yml
version: '3'
services:
  sample:
    build: .
    volumes:
      - ~/.ssh/:/root/.ssh
      - .dockervenv:/src/.venv
      - .:/src
    env_file:
      - .env.development
    ports:
      - 8000:8000
```
この記述の上で`docker-compose up`（初回は--buildオプションをつける）を実行すれば、localhost:8000でプロジェクトが起動するはずです。

以下、上記コードについていくつか説明を加えていきます。
## Dockerfileの記述について
まずはFROMについて。
```Dockerfile
FROM node:16-bullseye
```
最初は「FROM node:16.x.x」のように書いていたんですが、この記述だと以下のようなエラーが生じました。
```shell
sharp: Installation error: Use with glibc 2.28 requires manual installation of libvips >= 8.10.6
```
これについては、[こちらの記事](https://gotohayato.com/content/548/)を参考にベースイメージを変えることで対処しました。

続いて、ENTRYPOINTについて。
```Dockerfile
ENTRYPOINT [ "gatsby","develop","-H", "0.0.0.0", "-p", "8000" ]
```
こちら、["gatsby","develop"]だけではうまくいきませんでした。ホストとポートを指定する必要がありそうです（参考: https://www.gatsbyjs.com/docs/reference/gatsby-cli/#develop ）。
## docker-compose.ymlの記述について
docker-compose.ymlは[こちらの記事](https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04)を参考にさせていただきました。まあでも正味、あまり理解できてないです（特にvolumes周り）。。どなたか、解説いただけますと幸いです。


## 最後に
手探りで取り組んだこともあり至らない点多数だとは思いますが、何かの参考になれば嬉しいです。

また、この記事の内容についてアドバイスや訂正などございましたら、ぜひコメントなどでお知らせいただけますと幸いです。
window.confirm()で配列のデータを改行する

window.confirm()で配列を改行して表示することに躓いてしまったので、そのメモを残します。
やりたかったことは「警告メッセージは配列のデータを一列ではなく、改行して表示したい。」でした。

## ①うまく表示できなかった時
実行すると、何も加工していないので配列の形のまま表示されていました。（まあそうですよね。。。）
ちなみにwindow.confirm()は、onsubmitの部分でreturnで返す形にしないと「キャンセル」をクリックした場合でもサブミットしてしまうので注意です。
##### ＜画面＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659954/527ac24d-9f63-d7ad-1d7b-f34d7c9ad73e.png)
##### ＜ソースコード＞
```
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<form onsubmit="return checkWarnings()">
    <div>
        <label for="example">window.confirmの練習です。文字を入れて「送信」ボタンを押してください！→</label>
        <input id="example" type="text" name="text">
    </div>
    <div>
        <input type="submit" value="送信">
    </div>
</form>
<script>
function checkWarnings() {
    var warnings = ['実行しますか？', '本当に実行しますか？', '実行して後悔はないですか？'];
    if(!window.confirm(warnings)){
       return false;
    }
}
</script>
</body>
</html>
```

## ②うまく表示できたとき
~~改行コード「\r\n」をforEach文で回して詰め込むことによって解決できました。~~
改行コード「\n」をforEach文で回して詰め込むことによって解決できました。
**2022/04/22追記：「\r\n」より「\n」を使用する方がトラブルが少ないとのなので、「\n」に修正しました。**
##### ＜画面＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659954/ad9e1140-375c-c04a-a44d-fc6562277925.png)
##### ＜ソースコード＞
```diff_javascript
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
<form onsubmit="return checkWarnings()">
    <div>
        <label for="example">window.confirmの練習です。文字を入れて「送信」ボタンを押してください！→</label>
        <input id="example" type="text" name="text">
    </div>
    <div>
        <input type="submit" value="送信">
    </div>
</form>
<script>
function checkWarnings() {
    var warnings = ['実行しますか？', '本当に実行しますか？', '実行して後悔はないですか？'];
+    var formatWarnings = '';
+    warnings.forEach(function(element){
+        formatWarnings += element + '\n';
+    });
-    if(!window.confirm(warnings)){
+    if(!window.confirm(formatWarnings)){
       return false;
    }
}
</script>
</body>
</html>
```
改行コードをループで回すことがなく戸惑ってしまいましたが、また一つ勉強になりました。

## 追記：スマートな書き方
ループ分で回していましたが、joinを使うことでスマートに書けました。
```diff_javascript
function checkWarnings() {
    var warnings = ['実行しますか？', '本当に実行しますか？', '実行して後悔はないですか？'];
    if(!window.confirm(warnings.join('\n'))){
       return false;
    }
}
```
絶対はずさないお店を検索できるwebアプリケーションをリリースするまで②

実装したいこと
jsonデータ形式にすること

修正前
~~~
def index
    @cooks = Cook.all
    render json:@cooks
end

~~~
結果、jsonデータ形式をしたい場所が、indexではないため、変化なし

修正後
~~~
def show
    @cook = Cook.find(params[:id])
    render json:@cook
end
~~~
結果、json形式できた
はじめてのNFT

NFTを私用で触り始めたので備忘録として記載する。

## 用語
### ブロックチェーン
P2Pネットワーク上でお互いに資産(データ)を保持することで、資産の可用性を上げ改ざんを難しくした方式
それぞれの資産をhashとして保持し、hashを通して資産を連続してチェーンのように繋げる。

処理は大きく分けて、下記の手順で動作する。
1. 資産の作成(ハッシュ化など)
1. 資産の保存(合意形成)
1. 資産のやりとり、閲覧

## ノード
ブロックチェーンのP2Pネットワーク(以下ブロックチェーンネットワーク)に参加している計算機

## 合意形成、合意形成アルゴリズム
ブロックチェーンに資産を保存(繋ぎこむ)するアルゴリズム
主にPoW, PoSがある。

### PoW(Proof of Work)
日本語に直すと「作業(仕事)による証明(仮)」
Minerが資産をハッシュ計算し、ブロックチェーンネットワークへ資産を保存(承認)すること。
Nonceの計算等は省略。
ブロックチェーンネットワークへ完全に保存されるには過半数以上のノードに正しく保存されなければいけない。
代表的なコインはBitcoin(処理時間 約10分~20分)

### PoS(Proof of Stake)
日本語に直すと「掛け金による証明(仮)」
コインを多く持つノードに資産の保存(承認)を依頼する方法。
初めて使用したコインはNxt

## NFT
日本語名 非代替性トークン
ブロックチェーンに画像などの資産を登録することでその資産が一意のものであることを示す方式

### ERC-721
Ethereumネットワーク上でNFTを取り扱うための規格の技術提案
openseaにて利用されている。


## スマートコントラクト
ブロックチェーン上で契約を自動で実行する仕組み
プログラムとして記述した通りに動作する。
現実世界では預金通帳に書き込む動作を行うイメージ。
Ethereum では `Solidity` でよく記述される。
JavaScriptのhardhatを用いた開発が有名?
Plotlyのローソク足描画が遅いのでBokehを採用した話

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/ee808bf7-d526-b38e-f608-0e2c5ce95be3.gif)

ローソク足チャートを[Plotly](https://plotly.com/python/)で書くと、少ないコード量でインタラクティブなグラフができて、素晴らしいのですが、10年分のデータくらいで我慢できないくらい描画が遅くなっていました。
[Backtesting.py](https://kernc.github.io/backtesting.py/)で出力するグラフだと全然固まらないのでいいなーと思っていたら、内部で[Bokeh](https://docs.bokeh.org/en/latest/)を使っていたので、bokehでローソク足を書いてみました。
コード量は多くなるのですが、作りたいグラフを作れたので、Bokehもいいぞって思いました。

以下のローソク足は、pandasのDataFrameでデータを渡しており、dateで指定したところに帯をつけます。

```python
from bokeh.plotting import figure, save, output_file
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CDSView, CustomJS
from bokeh.models import BooleanFilter, HoverTool, Span
from bokeh.events import DoubleTap

def make_one_chart(df, date):
    source = ColumnDataSource(data=df)

    # 陽線と陰線はそれぞれに色の異なる四角を描画するため
    # どちらもデータをフィルターしたViewを用意する
    inc = df.Close >= df.Open
    view_inc = CDSView(source=source, filters=[BooleanFilter(inc)])
    dec = df.Open > df.Close
    view_dec = CDSView(source=source, filters=[BooleanFilter(dec)])
    w = 12 * 60 * 60 * 1000  # half day in ms

    TOOLS = "pan,box_zoom,ywheel_zoom,crosshair"

    p = figure(
        height=200,
        x_axis_type="datetime",
        tools=TOOLS,
    )
    p.grid.grid_line_alpha = 0.3

    # 一番下のレイヤーなので最初に記述
    p.add_layout(
        Span(
            location=date,
            dimension='height',
            line_color='red',
            line_dash='solid',
            line_alpha=0.1,
            line_width=10,
        )
    )

    p.segment(
        'Date', 'High', 'Date', 'Low',
        color="black", source=source, line_width=2,
    )
    p.vbar(
        'Date', w, 'Open', 'Close',
        fill_color="red", line_color="black",
        source=source, view=view_inc
    )
    p.vbar(
        'Date', w, 'Open', 'Close',
        fill_color="blue", line_color="black",
        source=source, view=view_dec
    )

    # 出来高用のグラフ
    p2 = figure(
        height=100,
        x_axis_type="datetime",
        max_width=600,
        x_range=p.x_range,
        tools=p.tools,
    )
    p2.vbar(x='Date', top='Volume', width=1, fill_color='black', source=source)
    p2.js_on_event(DoubleTap, CustomJS(args=dict(p=p), code='p.reset.emit()'))

    return column(p, p2)
```

おおよそこんな感じの記述でトップのようなグラフができます。（ホバー情報は少し調整している）
なかなか書きやすくていい感じです。

上記関数を以下のように使います。

```python
from backtesting.test import GOOG
from datetime import datetime as dt

GOOG.index.name = 'Date'
date = dt(2013, 2, 28)
p = make_one_chart(GOOG, date)
output_file('google.html')
save(p)
```
2022/4/22/勉強日誌

# 現状はどうなの？
## 英語力は？
■ TOEIC480点

## IT系の資格は？
■ ITパスポートくらい

## 仕事はできてる？
■ 全然できない
正確に物事を聞けない。

## 体重は？
■ 10年で10キロ太った
今78キロ

# １年間でどうなりたいか
■ TOEIC700点
■ 基本情報技術者取りたい
■ LPIC1とっときたい
■ 仕事でまずは人の言った事について正確にアウトプットができるようになりたい
■ 9月までに62キロで

# まずどうするべき？
・ ぶれない
・ やることを3本に絞る

### 明日何をする？
■ 中学高校6年分の英語を総復習する
・本書の基本的な考え方を読む
・中学編Part4

■ 基本情報技術者試験の勉強
・過去問マネジメント

■ LPIC
・ハードウェア設定の決定と設定
MAMP+dnsmasq環境構築

# はじめに
MACローカル環境でサブドメインを設定し、
SSL化した状態でhoge.example.comにAndroidからアクセスするまでについて説明する記事です。個別の記事は散見されたのですが、他にまとまっている記事がなかったので、備忘録を兼ねて書きました。
初心者向けにできる限りコマンドを全て記載しております。

#1. MAMPダウンロード&インストール
https://www.mamp.info/en/downloads/
よりダウンロードとインストール

#2. SSL化
OpenSSLを利用して、
自己署名証明書を発行します。

opensslがインストールされていない場合はインストール
 
```
brew install openssl
```

apacheの設定ディレクトリに移動

```
cd /Applications/MAMP/conf/apache/
```

秘密鍵を保存するディレクトリを作成し移動

```
mkdir ssl && cd $_
```

秘密鍵を作成

```
openssl genrsa -out server.key 2048
```

CSRの作成

```
openssl req -new -key server.key -out server.csr
```

対話型になるのでCommon Name (eg, fully qualified host name)にホスト名を入力。今回はexmple.comを利用。

```
Country Name (2 letter code) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:example.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
```

サーバー証明書の作成

```
openssl x509 -req -days 365 -signkey server.key -in server.csr -out server.crt
```

コメントアウトを解除してhttp-ssl.confファイル読み込み

```/Applications/MAMP/conf/apache/httpd.conf
Include /Applications/MAMP/conf/apache/extra/httpd-ssl.conf
```

下記3行を追記して証明書、秘密鍵の読み込み

```/Applications/MAMP/conf/apache/httpd.conf
SSLCertificateFile "/Applications/MAMP/conf/apache/ssl/server.crt"
SSLCertificateKeyFile "/Applications/MAMP/conf/apache/ssl/server.key"
```

httpd-ssl.conf内でDocumentRoot、サーバー証明書、秘密鍵の読み込みを下記のように修正

```/Applications/MAMP/conf/apache/extra/httpd-ssl.conf
DocumentRoot "/Applications/MAMP/htdocs"
...
SSLCertificateFile "/Applications/MAMP/conf/apache/ssl/server.crt"
...
SSLCertificateKeyFile "/Applications/MAMP/conf/apache/ssl/server.key"

```

apacheシンタックスチェック

```
/Applications/MAMP/Library/bin/apachectl configtest
```

server.crtをドラッグアンドドロップでキーチェーンアクセスのシステムに追加し、
信頼を常に信頼に変更
![スクリーンショット 2022-01-30 22.01.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314423/d35ddd04-e5af-2f99-c2e2-001c5e8e97aa.png)

dnsmasqインストール

```
brew install dnsmasq
```

example.comをループバックアドレスとして解決する。
hostsファイルを読み込む。
```
echo 'address=/.example.com/127.0.0.1' >> $(brew --prefix)/etc/dnsmasq.conf
echo 'addn-hosts=/etc/dnsmasq.hosts' >> $(brew --prefix)/etc/dnsmasq.conf
```

名前解決をローカルのDnsmasqに任せる

```
mkdir -p /etc/resolver
vi /etc/resolver/example.com
```

ローカルを名前解決

```/etc/resolver/example.com
nameserver 127.0.0.1
```

dnsmasqを起動

```
sudo brew services start dnsmasq
```

名前解決できることを確認

```
ping hoge.example.com 
```
macOS で "failed to open for writing: Resource busy" と表示される場合の対処法

# TL;DR
先にアンマウントする。

# 症状
USB 内にあるデータを完全削除しようと思い、shred コマンドを実行したら "Resource busy" と言われてしまった。shred コマンド以外でも、このエラーが出ることはある。

# 解決法
## ファイルシステム名の検索
以下のコマンドを実行する。

```shell:Shell
df
```

対象のファイルシステム名 (例: `/dev/disk2s1`) をクリップボードにコピーしておく。macOS では、USB は `/Volumes` 以下にマウントされるので、"Mounted on" の欄が `/Volumes/<USB_NAME>` となっているディスクの "Filesystem" の欄をコピーすれば良い。

## アンマウント
そして、対象のファイルシステムをアンマウントする。

```shell:Shell
diskutil unmount <FILESYSTEM_NAME>
```

## 所望のコマンドを実行
その後、実行したいコマンドを実行する。たとえば、USB の中身を完全消去したければ以下のコマンドを実行する。

```shell:Shell
sudo shred -uvz <FILESYSTEM_NAME>
```

参考: [ハードディスク内のデータを本当の意味で完全消去する方法](https://zenn.dev/noraworld/articles/delete-data-in-hdd-completely)

# 参考サイト
* [Using dd I'm getting a Resource Busy error](https://forums.macrumors.com/threads/using-dd-im-getting-a-resource-busy-error.384730/?post=4475931#post-4475931)
* [Mount & Unmount Drives from the Command Line in Mac OS X](https://osxdaily.com/2013/05/13/mount-unmount-drives-from-the-command-line-in-mac-os-x/)
ActiveRecord で作成・更新状態を確認するメソッド

よく使う割に忘れてしまうので、メモしておく。

# 前提
- Rails 6.1.7
- レコードを更新する際に、変更内容をログ出す時に使うこと多い

# 新しいレコードか
```ruby
# 保存前
user.new_record?
=> true

# 保存後（id値は変更されない前提）
user.id_before_last_save.nil?
=> true
```

# オブジェクトが更新されたか
```ruby
# 保存前
user.has_changes_to_save?
=> true

# 保存後
user.saved_changes?
=> true
```

# どの属性が更新されたか
```ruby
# 保存前
user.changed_attribute_names_to_save
=> ["name"]

# 保存後
user.saved_changes.keys
=> ["name"]
```

# ある属性が更新されたか
```ruby
# 保存前
user.will_save_change_to_name?
=> true

# 保存後
user.saved_change_to_name?
=> true
```

# ある属性の更新前の値は何か
```ruby
# 保存前
user.name_in_database
=> "foo"

# 保存後
user.name_before_last_save
=> "foo"
```

# ある属性がどのように更新されたか
```ruby
# 保存前
user.changes_to_save
=> {"name"=>["foo", "bar"]}

# 保存後
user.saved_changes
=> {"name"=>["foo", "bar"]}
```

# 参考
* [紹介記事](http://blog.lambda-consulting.jp/2017/09/11/article/)
* [公式ドキュメント](https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html)
1日１企業紹介　エムスリー株式会社

１日１企業を紹介していく。

やる気がある限りは続ける。

エムスリー株式会社

医療従事者を対象とした医療ポータルサイト「m3.com」のサービスを行っている企業である

従業員数	連結：8,249人、単独：554人

ソニーがこの会社の株の30％くらい保有してるっぽいので
子会社ではないが持分法適用関連会社となっている。
一応事業上の依存関係は無く、一定の独立性を確保してるとのこと（公式サイトより）
役員も一名しかソニーの人間はおらず親子会社のような関係では
ないっぽい

「m3.com」は国内30万人以上、世界600万人以上の医師が利用しているらしい

世界でもユニークなベンチャー企業と銘打っている
（ベンチャーじゃねえだろと突っ込みたくなる。。。）
一応フォローしておくと社風やビジネス速度はベンチャー気質ということが
随所から感じられる。

ベンチャーというよりメガ・ベンチャーのほうがしっくりくる

「m3.com」だけではなく、MRをサポートするサービスや治験もサポートしている

年収は600後半～700半ばといった感じ。会社の人間が若いことを考えると

データサイエンティスト人材も働いている。良い水準であるといえそう
約15名のデータサイエンティストが在籍しているとのこと

求められる技術としてはこんなもん
・統計技術：機械学習, 因果推論, 組合せ最適化, 自然言語処理等
・言語：Python3.x, SQL, Shell Script
・DB：BigQuery, PostgreSQL, Oracle Database
・インフラ：PC (Windows / Mac希望に応じて), オンプレミスサーバー, AWS
・コード管理：GitLab
・コミュニケーション：Slack, JIRA, Confluence

業務内容は以下のような感じだがこれだけみてもぬーんて感じ
・機械学習を用いたレコメンドエンジン開発
・デジタルマーケティングにおける戦略立案と実装
・統計技術を利用したクライアントの課題を解決する新商品開発
・担当事業におけるデータを活用した事業成長のロードマップ作成
FoundryとHardhatを比較してみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168116/b63fa8f4-7cb4-e897-0b7b-26c94ed388cb.png)

この記事は以下の記事の翻訳・まとめです。
https://yamenmerhi.medium.com/foundry-vs-hardhat-918c55e47add

# 主な違い

### 1. コンパイル速度
FoundryはRustで作られていて、どうやらコンパイル速度が速いらしいということを知ってる人が多いと思います。

https://github.com/YamenMerhi/foundry-lsp-smart-contracts
このレポジトリでの検証結果では、
- hardhat: 39.33s
- Foundry: 26.22s

hardhatの2/3程になっています。

### 2. テスト言語

Hardhat => Javascript/Typescript
Foundry => Solidity

Foundryでは、コントラクトとテスト両方solidityで書くので、開発からテストに移る際に脳の切り替えをせずにそのまま始めることができます。＋JSよりもSolidityの方がテスト速度が全然速いです。

### 3. Dependencies
Hardhat => npm 
Foundry => git submodule (default)

# Foundryにしかない機能

## Traces
トレースは、関数処理の内部状態を見ることができる機能です。どの関数がどんなパラメーターで呼び出され、どのイベントが吐かれたかなどを、構造的に確認することができます。これにより、Hardhatであれば コントラクト内でconsole.log()して頑張っていたデバッグが超簡単になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168116/ba2a1ac6-eeb1-f187-39ac-623bc8d2adc0.png)


## Fuzz Testing

Fuzzing testとも言い、ランダムなパラメーターを渡すテスト方式です。通常のUnitTestと同じくらい大事なテストですが、知名度の低さやそもそもの導入難易度の高さでほとんどの場合無視されています。
開発者が想定していない状態をテストでき、スマコン開発では必須級です。

Foundryではこれをネイティブ実装しており、個人的にはこれが一番嬉しいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168116/f9676a65-4285-c980-2f09-fb289df7c4ea.png)
もし想定と異なる動きをした際、その時渡されたパラメーターを出してくれます。


# 最後に
Foundryは非常に強力ですが、まだまだ開発初期段階です。ドキュメントやチュートリアルの充実、追加機能がユーザーから求められています。


## 参考リンク
https://www.youtube.com/watch?v=Rp_V7bYiTCM&t=1119s
https://book.getfoundry.sh/index.html
https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox
【Swift】Fontファイルを読み込んで使う

# XCodeにFontファイルを取り込む
![スクリーンショット 2022-04-21 22.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/042dac2b-e15e-cab3-3bdc-5338998c0314.png)

- [x]  Copy items if needed
- [ ]  Create groups
- [x]  Create folder referenses
- [ ]  Add to targets

![スクリーンショット 2022-04-21 22.37.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8ce9fd02-9d2d-3b0e-1bd7-815b5b7d2ed1.png)

こんな感じで取り込めたらOKです

# Info.plistでFontの設定
![スクリーンショット 2022-04-21 23.01.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d84e0582-8040-7001-81b3-402490ca0d63.png)
ここで設定するFontの名前は拡張子までです
![スクリーンショット 2022-04-21 23.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b62f313c-9c37-9127-0d4d-05a6cd72ffbb.png)
一応ズームした画像も載せておきます
```
<dict>
	<key>UIAppFonts</key>
	<array>
		<string>JF-Dot-jiskan24h.ttf</string>
	</array>
</dict>
```
Source Codeで開くとこうなります

# Copy Bundle Resourceに追加
![スクリーンショット 2022-04-21 22.54.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a6287073-5969-9d30-7228-969049f3c775.png)
+を押します
![スクリーンショット 2022-04-21 22.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/449ac9b6-b749-2fc0-c266-f7fdcd6e5da2.png)
使用したいFontファイルを選択して「Add」を押します

以上で準備は完了です。

# 使い方
### SwiftUI
```Swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("こんにちは")
            .font(.custom("JF-Dot-jiskan24h", size: 25))
    }
}
```
### UIKit
```Swift
import UIKit

class ViewController: UIViewController {
    @IBOutlet var label: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        label.text = "こんにちは"
        label.font = UIFont(name: "JF-Dot-jiskan24h", size: 25)
    }
}
```

# おわり
今回サンプルとして使用させて頂いたのは[こちら](http://jikasei.me/font/jf-dotfont/)の「JFドットjiskan24h」というFontです
ありがとうございます

このフォントを使ってアプリを公開してますので是非使ってみてください

https://apps.apple.com/jp/app/%E9%9B%BB%E5%85%89%E6%8E%B2%E7%A4%BA%E6%9D%BF/id1618602482
CRMシステムでビジネスがどう変わる？

# はじめに
IT×ビジネスという視点で週1本記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiita.com/7_inai_)

# CRMシステムとは
CRM(Customer Relationship Management) システムとは、直訳すると __顧客管理システム__ のことです。顧客情報を一元管理することで、顧客との関係性を維持・向上させるというアプローチ、およびその目的のために開発されたツールのことです。

# CRMシステムでビジネスがどう変わる？
### ■顧客の情報分析
以下のような購買実績を商品ごとに管理できます。この蓄積した情報から顧客の購買傾向を分析することができます。
基本情報(属性情報)：顧客の年齢や性別、職業、住所
購買履歴情報：購入日や購入金額、購入時期

### ■業務の引き継ぎをスムーズ化
CRMシステムでは体系的に情報管理ができるため、必要な顧客情報を属人化することなく統一された書式で管理できます。これにより、必要な情報を漏れなく素早く引き継ぐことができます。

### ■関係部門間でのリアルタイム共有
CRMで入力された情報はリアルタイムで共有されます。この機能により多くの関係部門にメリットを生みます。例えば、カスタマーサポート部門であれば、何らかの問い合わせがあった場合、その顧客のすべての情報を瞬時に見渡すことができます。また、マーケティング部門が集めたリストに、インサイドセールスがどの程度テレアポを実施しているかなども簡単に把握できるようになります。

# 終わりに
CRMシステムを導入する際には、色々な種類がある中から最適なものを選定する必要があります。機能が多ければ良いというわけではありません。必要な機能が備わっていれば、それ以外の機能は操作性の低下や、コストの増加といったデメリットに繋がります。導入する目的を明確にした上で、コスト、機能、操作性といった観点で最適なシステムを選定しましょう。

最後までお付き合いくださりありがとうございました。
apt install でインストールしたパッケージをアンインストールするには apt remove, apt purge をすればOKという備忘録

apt install でインストールしたパッケージをアンインストールするには apt remove, apt purge をすればOKという備忘録です。

例えば、以下のように`openssh-server`をインストールした後、

```sh
sudo apt install -y openssh-server  # install
```

以下のようにするとパッケージをアンインストールできる

```sh
sudo apt remove -y openssh-server   # uninstall
sudo apt purge -y openssh-server    # uninstall
```

あまりアンインストールする機会はないかもしれないが、、パッケージの挙動がおかしく再インストールが必要になる場合に役立つかもしれない。

# 備考

`openssh-server`のインストール時に以下のようなエラーが出た場合は再インストールすると解決するかもしれない。

```
sshd.service - OpenSSH Daemon Loaded: 
loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: failed (Result: start-limit) since xxx
...
systemd[1]: Unit sshd.service entered failed state.
systemd[1]: sshd.service holdoff time over, scheduling restart. 
systemd[1]: Stopping OpenSSH Daemon... 
systemd[1]: Starting OpenSSH Daemon...
systemd[1]: sshd.service start request repeated too quickly
```

# 参考

https://codechacha.com/ja/linux-apt-purge-vs-remove/

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12158584442
1年前の日付を求める

1年前の日付とググるとdateutilの`relativedelta()`を使う旨がよく出てくる。
一目datetimeでマイナス365日で良さそうだが`うるう年`を考慮すると`relativedelta()`が良いようだ。

| 日付      | timedelta(days=365)  | relativedelta(years=1) | 備考 |
| --------- | -------------------- | ---------------------- | - |
| 2020/2/28 |  2019/02/28          |  2019-02-28            | 期待通り|
| 2020/2/29 |  2019/03/01          |  2019-02-28            | うるう年はずれる|
| 2020/3/01 |  2019/03/02          |  2019-03-01            | 同上|


```

// 2020/2/28 の365日前
$ python3 -c "import datetime; print(datetime.date(2020,2,28) - datetime.timedelta(days=365))"
2019-02-28

// 2020/2/28 の一年前
$ python3 -c "import datetime, dateutil.relativedelta; print(datetime.date(2020,2,28) - dateutil.relativedelta.relativedelta(years=1))"
2019-02-28

// 2020/2/29 の365日前
$ python3 -c "import datetime; print(datetime.date(2020,2,29) - datetime.timedelta(days=365))"
2019-03-01

// 2020/2/29 の一年前
$ python3 -c "import datetime, dateutil.relativedelta; print(datetime.date(2020,2,29) - dateutil.relativedelta.relativedelta(years=1))"
2019-02-28

// 2020/2/29 の365日前
$ python3 -c "import datetime; print(datetime.date(2020,3,1) - datetime.timedelta(days=365))"
2019-03-02

// 2020/2/29 の一年前
$ python3 -c "import datetime, dateutil.relativedelta; print(datetime.date(2020,3,1) - dateutil.relativedelta.relativedelta(years=1))"
2019-03-01
```
Zennシェア:PiniaとVuex比較してみた

最近Vue３を勉強と使い始めていました。
色々ハンズオンとか、情報集めとか頑張っています。

そんな中に、vuexとPiniaは似ているもので、比べてみました。

ちなみに、自分はPinia派です。

[PiniaとVuex比較してみた](https://zenn.dev/reinf0rce/articles/2b187f611b329f)
mediapipeを試す17行

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 顔に線がびっしり張り付くやつ


# mediapipeにとっつきたい
表情認識などで使われるmediapipeを手元のpythonで使ってみます。
使い方の理解のためになるべくシンプルにして試します。

# 準備
がんばってmediapipeをインストールします。
方法は調べると出てくると思います。

未対応のM1 silicon Macの方は下記の記事が参考になるかもしれません。 

https://qiita.com/Ninagawa_Izumi/items/10e1cbc825f806ea61fa

# 参考記事
[MediaPipe Face Mesh](https://google.github.io/mediapipe/solutions/face_mesh.html)
こちらの公式記事にあるスクリプトを、解説用にギリ動作するレベルまで短く刈り込んでいます。

# 理解のための素朴なコード
もろもろ省略したシンプルなコードです。ちょっとわからないところもありました。

```python:mediapipe_simple.py
import cv2
import mediapipe as mp

cap = cv2.VideoCapture(2)#カメラのIDを選ぶ。映らない場合は番号を変える。

with mp.solutions.face_mesh.FaceMesh(#mesh化の設定をしてその処理名をface_meshとする
    max_num_faces=1,refine_landmarks=True,min_detection_confidence=0.5,min_tracking_confidence=0.5) as face_mesh:
    #↑顔の数, 目の周りを細かくするか, ランドマーク検出成功判定の閾値, ランドマークトラッキング成功判定の閾値

  while cap.isOpened():
    success, image = cap.read()#キャプチャが成功していたら画像データとしてimageに取り込む
    results = face_mesh.process(image)#メッシュ化計算の結果がresutsに入る

    if results.multi_face_landmarks:#ランドマークが取得できたら
      for face_landmarks in results.multi_face_landmarks:#結果データについて順次描画処理をしていく
        mp.solutions.drawing_utils.draw_landmarks(#以下の設定で描画を実行
            image=image, landmark_list=face_landmarks, connections=mp.solutions.face_mesh.FACEMESH_TESSELATION,
            #↑画像データ, ランドマークのリスト, メッシュの繋ぎ方?(テッセレーション)
            landmark_drawing_spec=None,connection_drawing_spec=mp.solutions.drawing_styles.get_default_face_mesh_tesselation_style())
            #↑わからぬ, わからぬ

    cv2.imshow('MediaPipe Face Mesh', cv2.flip(image, 1))#imageを鏡像で表示

    if cv2.waitKey(5) & 0xFF == 27:#ESCキーが押されたら終わり
      break

cap.release() #カメラを終了
```
multi_face_landmarksは468個のランドマークで表されるらしい。
ランドマークはx,y,zを持ち、x,yは0~1で正規化されているらしい。
zは頭を頂点を原点として、カメラに近いほど小さい値になるらしい。

# 実行結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a405fc05-a6e4-abe0-088f-a159efbf70c0.png" width=300//>

スマホ画面をカメラに向けて撮影しているので色が悪いですが、高速にフェイスメッシュをとってくれます。
もちろん動画で、リアルタイムに線が顔にびっしり張り付きます。

# 実行結果
間違いやおすすめの解説ページがありましたら教えてください。
OSI参照モデル -ネットワーク層-

### ネットワーク層とは
OSI参照モデルの第3層であり、IPアドレスを認識して通信を行います。

### データリンク層との違い
データリンク層との違いは異なるネットワーク間の通信が行えます。
データリンク層の場合、同じネットワーク内に閉じたお話になり、
MACアドレスを使用してデータ通信を行います。

![スクリーンショット 2022-04-21 22.55.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281678/e3531ef6-36e6-8962-407a-913c87edc8dc.png)


ネットワーク層の場合は通信範囲が広がり、異なるネットワークの通信を実施します。

![スクリーンショット 2022-04-21 22.55.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2281678/3b32ebc6-aa9c-a526-807a-7a80a5f26e44.png)


### ルーター
異なるネットワークで通信するにはルーターを使用します。
データ内に存在する宛先のIPアドレスを確認し、送信、受信します。

### 参考文献
https://www.seraku.co.jp/tectec-note/industry/network-layer/
motoでPynamoDBのモデルをテストする



DynamoDBのORMの[PynamoDB](https://github.com/pynamodb/PynamoDB)で作ったモデルを、motoを使ってテストするためのコード例です。

```
> pip install moto pynamodb pytest
```

```
/
├─models
│   └─user.py
└─tests
    ├─__init__.py
    └─test_user.py
```

```python:models/user.py
from pynamodb.models import Model
from pynamodb.attributes import (
    UnicodeAttribute,
    NumberAttribute,
    ListAttribute,
)


class UserModel(Model):
    class Meta:
        table_name = 'user'
        region = 'ap-northeast-1'

    id = UnicodeAttribute(hash_key=True)
    name = UnicodeAttribute(null=False)
    age = NumberAttribute(null=False)
    hobbies = ListAttribute(null=True)

```

```python:tests/test_user.py
from models.user import UserModel
from moto import mock_dynamodb
import uuid


@mock_dynamodb
def test_user_model():
    UserModel.create_table(
        read_capacity_units=5, write_capacity_units=5, wait=True)

    id = str(uuid.uuid4())

    user = UserModel(id)
    user.name = "foo"
    user.age = 20
    user.hobbies = ["chess", "singing"]
    user.save()

    print("count:{count}".format(count=UserModel.count()))

    bar = UserModel.get(id)
    print("name:{name}".format(name=bar.name))

    bar.delete()
    assert UserModel.count() == 0

```

```
> pytest -vvs
=================================================================================================== test session starts ====================================================================================================
platform win32 -- Python 3.8.10, pytest-7.1.1, pluggy-1.0.0 -- c:\users\danishi\pynamodb-test\venv\scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\danishi\pynamodb-test
collected 1 item

tests/test_user.py::test_user_model count:1
name:foo
PASSED

==================================================================================================== 1 passed in 1.40s =====================================================================================================
```