OmniAICreator/Qiita-1.07M huggingface dataset:
【QA】同値分割

## これはなに？
同値分割というテスト技法がどういうものなのか
また、どういう場面で使うべきものなのかを例を混ぜながら説明した記事になります

## この記事に書かれていること
- 同値分割とは？
- 同値分割の使用場面と使用例

## 同値分割とは？
>ソフトウェアテストのテストケースを設計する代表的なテクニックの1つ。システム機能における入力、出力関係の集合をいくつかの同値クラスに分け、各クラスから代表値を選んでテストデータとする方法をいう。  [IT Media エンタープライズより引用](https://www.itmedia.co.jp/im/articles/1111/07/news178.html)

引用にもあるとおり、入力に対して同じ出力をするものをいくつかのグループに分けて、各グループごとに代表値を選んでテストする、というものです。


## 同値分割の使用場面と使用例

なんなのかは分かったけど、実際にどう言う場面で使われるの？と思った方に向けて書いています。

### 使用場面
同値クラスだった場合の処理が同じであり、どの値を入力しても共通の出力をする場合、同値分割を行います。

### 使用例
以下のような項目で割引額が正しく機能しているかを確認したいと仮定します。

- 5,000円以上の購入で5%OFF
- 10,000円以上の購入で10%OFF



| 購入金額 | 割引率 |
|:-----------:|:-----------:|
| 0~4,999円 | 割引なし |
| 5,000~9,999円 | 5%OFF |
| 10,000円~ | 10%OFF |

単純に考えると0~10,001円の購入を合計10,002回繰り返せば良いのですが、皆さんご存知のとおり、リリースまでにそんな時間はあるわけもないです。

そこで同値分割の出番です。

同値分割では出力結果が同じと期待される入力ごとにグループ分けをしてグループごとにテストをするという手法です。

今回の例で言うと、購入金額が`0~4,999円`と`5,000~9,999円`と`10,000円~`の3つのグループに分けられます。

この3つの各グループで代表的な値を入力することで網羅性を落とさずにテストを行うことができ、かつテストにかける工数を大幅に減らすことができます



## まとめ
今回の同値分割については手法を知らずとも無意識にやりそうなものですが、しっかりと自分の知識として定着させるために書いてみました。
これからソフトウェアテストに携わる方にとっては必ず着手するものなのでこの記事が役に立てば幸いです。

次回は[境界値分析](https://qiita.com/mu-suke08/items/81be49b5a03534b95dd6)と言う、同値分割と似たような場面で使われる技法について紹介したいと思います。




## 参考記事
- [ITmedia エンタープライズ](https://www.itmedia.co.jp/im/articles/1111/07/news178.html)
AWS Protonのメモ

## メモ

AWSが用意してくれた、ECSのサンプルをベースに自分なりに整理
（注：どんなサービスも環境側とサービス側で定義可能）

![proton1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587858/4fc57d22-f3cf-b84e-097b-b083233acd30.png)

解釈が微妙な奴もあるかも（特にサービスとサービスインスタンスがまだ微妙）

###### Proton概要
[AWS Proton：コンテナおよびサーバーレスデプロイメント向けの管理の自動化](https://aws.amazon.com/jp/proton/)

###### Protonのサンプル（READMEがチュートリアルみたくなってる）
[aws-samples/aws-proton-sample-templates](https://github.com/aws-samples/aws-proton-sample-templates)

###### ProtonのECSのサービスサンプル
[aws-samples/aws-proton-sample-fargate-service](https://github.com/aws-samples/aws-proton-sample-fargate-service)

###### ProtonのLambdaのサービスサンプル
[aws-samples/aws-proton-sample-lambda-crud-service](https://github.com/aws-samples/aws-proton-sample-lambda-crud-service)

###### Protonのロードマップ

[aws/aws-proton-public-roadmap](https://github.com/aws/aws-proton-public-roadmap)

###### Protonのクォータ

[Protonのクォータ](https://docs.aws.amazon.com/ja_jp/proton/latest/userguide/ag-limits.html)
【mongoDB】mongoDBチートシート「セキュリティー」(外部アクセスの制限・認証設定)

#外部アクセスの制限

###ポート番号の変更


設定を変更する場合は、mongoDBを再起動させる必要がある。


####設定ファイルの場所

macの場合
/usr/local/etc/mongod.conf

linuxの場合
/etc/mongod.conf

###設定ファイルのポート番号を変更する

```
net:
 port:<変更するポート番号>
```
ポートを変更した場合は、アクセスする場合にオプションで指定する必要がある。

```
mongo --port <変更後の番号>
```

linuxでSElinuxをONにしたまポート番号を変更する場合

```
sudo semanage port -a -t mongod_port_t -p tcp <変更番号>
```

###接続IPアドレスを制限する。

```
net:
  bindIp: <IPアドレス>

//127.0.0.1は必ず指定する。
//例  [127.0.0.1, 192.168.100.100]
//制限を設けない場合は、0.0.0.0を指定
```

#ユーザー認証(単体構成)

MongoDBはデフォルトの状態だと、認証がかかっておらず誰でもアクセスができてしまうため、認証をかける必要がある。
ユーザー情報は、**「adminデーターベース」**の、**「system.users」**コレクションに保存されている。

※ユーザーを作成する前に、認証を設定してしまうと、誰もアクセスできなくなるので注意!

####rootユーザーの作成

```
use admin
//adminデーターベースに移動
```

```js
db.createUser({
  user:"root",
  pwd:"root",
  roles:[{role:"root", db:"admin"}]
  })
```

一覧を確認

```
db.getUsers()
```
configファイルの修正

```
vim /usr/local/etc/mongod.conf
```

認証を行うように設定

```
//末尾に追記
security:
  authorization: enabled
```

再起動

```
brew services stop mongodb-community
brew services run mongodb-community
```
###確認

```
mongo
use admin
show dbs

//表示されない。

db.auth("root","root")    //先程作ったユーザーでログインしてみる。(username, password)
show dbs

//今度は表示される。(認証がかかっている）
```

####dbごとの個別のユーザーを作成

```
use test //対象のデーターベースに移動（今回はtest)
```

```js
db.createUser(
   {user:"tester", 
    pwd :"tester",
    roles:[{role:"readWrite" ,db: "test"}] //testデータベースに対し、読み書き権限をtesterに与える。
   }
)
```
####認証の確認
一度mongodbから出る。

```
mongo //mongodbにアクセス
use test
show collections

結果
Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
```
認証がかかっていることを確認。
再度mongodbから出る。

認証付きでログイン

```
mongo -u tester -p -authenticationDatabase test

enter password

show collections

//表示されることを確認
```

##主なロールの一覧
| 分類 | ロール名 | 説明 |
|:--|:--|:--|
|ユーザーDB操作用ロール|read|コレクションに対する読み|
|ユーザーDB操作用ロール|readWrite|コレクションに対する読み書き|
|  ユーザーDB操作用ロール |  dbAdmin |db管理用ロール   |
| ユーザーDB操作用ロール  |  userAdmin |指定したデーターベースに対してユーザー管理できる|
|  ユーザーDB操作用ロール | dbOwner  |  指定したデータベースのオーナー<bu>システム管理用ロール<br>以下のロールを含む<br>dbadmin<br>userAdmin<br>readWrite |

| 分類 | ロール名 | 説明 |
|:--|:--|:--
| クラスタ管理・操作用ロール  |clusterManager   |クラスタ管理用ロール    |
|  クラスタ管理・操作用ロール |  clusterMonitor | クラスタ読み取り専用ロール |
|クラスタ管理・操作用ロール   |  hostManager |   クラスタ操作用ロール|
|クラスタ管理・操作用ロール   |  clusterAdmin | クラスタ管理用ロー<br>clusterManager<br>clusterMonitor<br>hostManager<br>dropDatabaseアクション  |

| 分類 | ロール名 | 説明 |
|:--|:--|:--|
| バックアップ・リストア用ロール |backup   | バックアップ用ロール   |
| バックアップ・リストア用ロール  | restore  |リストア用ロール   |

##adminデーターベースのユーザーにのみ指定できる特別なロール
| 分類 | ロール名 | 説明 |
|:--|:--|:--|
|全DB管理操作用ロール  |  readAnyDatabase | 全DBの読み取り専用ロール |
| 全DB管理操作用ロール  |  readWriteAnyDatabase | 全DBの読み書き用ロール  |
| 全DB管理操作用ロール  | userAdminAnyDatabase  |  全DB のユーザー管理用ロール |
| 全DB管理操作用ロール  | dbAdminAnyDatabase  |  全DB 管理用ロール |

| 分類 | ロール名 | 説明 |
|:--|:--|:--|
| システム管理用ロール  |root   | システム管理用ロール  |
|  mongodb内部使用ロール | _system  | mongodbが内部で使用するロール  |


###最低限、以下の２つのユーザーは作成しておく

adminデータベース：rootユーザー
各データベース：readWrite
SQLについて整理する

##前書き
正直ポートフォリオを作成するときにSQLはあまり力を入れていなかった。（大事だとは思っていた）
自分にとって大切なことはポートフォリオを完成させることになってしまっていたからである。業務では確実に知っておくべき知識であるためここで一旦整理しておく。

##そもそもSOLとは？

SQL(structured query language)のことである。
データを定義する「DDL（Data Definition Language）」
データを操作する「DML（Data Manipulation Language）」
データを制御する「DCL (Data Control Language)」
がある。

そのSQLはDB(データベース)と呼ばれる箱のようなもので管理される。

テーブル形式でデータを管理するDBを特にRDB(リレーショナルデータベース)と呼ぶ。

テーブルとはカラムとロウからなる表のことである。（イメージとしてはエクセルだと思っている）

またクエリと呼ばれるSQLを実行した時にデータベースに送る命令文がある。

##SQLによるデータベースの操作



##実践（DDL）
| 命令              |機能                    |
|:-----------------|:------------------:|
| create           | データベースやテーブルの作成 |
| alter            | データベースやテーブルの更新 |
| drop             | データベースやテーブルの削除 |


###CREATE
CREATEは、データベースやテーブルを作成できるSQLの文。
データベース名を入れることで指定した名前で作成できる。

```
mysql> CREATE DATABASE 《データベース名》;
```

###SHOW
SHOWは、データベースやテーブルを一覧表示できるSQLの文。

```
mysql> SHOW DATABASES;
作成されているデータベースを一覧で表示
```

###DROP
DROPは、データベースやテーブルを削除できるSQLの文。
データベース名を入れることで指定した名前で削除できる。

```
mysql> DROP DATABASE 《データベース名》;
```

###USE
USEは、どのデータベースを使用するのかを指定するSQLの文。

```
mysql> USE sqltest;
Database changed←これが出たら成功
```

###ALTER
ALTERは、データベースやテーブルを編集できるSQLの文。
テーブルに対してカラムの追加や削除などができる。

```
mysql> ALTER TABLE 《テーブル名》 操作
```

###テーブルとカラムを作成する

先ほどのcreateコマンドでカラムを追加することができる。

```
mysql> CREATE TABLE テーブル名 (カラム名1 カラム名1の型, カラム名2 カラム名2の型, …);
```

ちなみにrailsでrails db:migrateを実行した際には裏でCREATE TABLEというSQLが動いておりカラムの追加や編集がなされている。




##終わりに
随時更新していきます。SQLのコマンドについてしっかり理解できていなかったため良い復習になりました。記事を書こうとするとわかりやすく書かないといけないため自然と頭が整理されますね笑
yarnでgatsby newする(Docker)

Docker環境(他の環境は調べていない)では、`gatsby new`、`gatsby new ~`をした際に、**問答無用でnpmインストール**してきます。

ここでは`yarn`を使って`gatsby new`する方法をご紹介します！

## 開発環境

- Docker: 20.10.1
- docker-compose: 1.27.4
- Node: 12.17.0
- Gatsby: 2.10.0

## 完成後のディレクトリ構成の確認

```
project-name
    |- .config
        |- gatsby
            |- config.json
    |- 生成されるgatsbyファイル群
        |- ...
    |- docker-compose.yml
    |- Dockerfile
```

上記に書いている生成されるgatsbyファイル群以外は事前に用意しておきます。

## config.jsonを作成する
ずばりこれがyarnを使う方法です。
↓詳しくはコチラを参照↓
[Using Yarn as your Gatsby package manager](https://www.gatsbyjs.com/docs/glossary/yarn/#using-yarn-as-your-gatsby-package-manager)

先ほどの構成通りに`config.json`を作成して、公式ドキュメントを参考に以下のような記述をしていきます。

```json:config.json
{
	"cli": {
		"packageManager": "yarn"
	}
}
```

## Docker系の設定

`config.json`の設定をコンテナ内の設定と繋げるために以下のような構成となっています。

```Dockerfile:Dockerfile
FROM node:12.17.0

RUN mkdir project-name
WORKDIR /project-name
COPY .config /root/.config/

RUN yarn global add gatsby-cli
```

続いて`docker-compose`ファイルになります

```yaml:docker-compose.yml
version: '3.8'
services:
  gatsby:
    build: ./
    tty: true
    stdin_open: true
    volumes:
      - ./:/project-name
    environment:
      - NODE_ENV=development
    ports:
      - 8000:8000
      - 9000:9000
```

## 実行

イメージを作成して、コンテナを起動、コンテナ内に入っていきます。

```
$ docker-compose build
$ docker-compose up -d
$ docker-compose exec gatsby bash
```

一度コンテナ内でファイルが存在しているか見に行きましょう！

```
$ cat /root/.config/gatsby/config.json
```

先ほど作成していた`config.json`があれば成功です！

では`gatsby new ~`してみてください！

```
$ gatsby new 生成されるgatsbyファイル群のフォルダ名
```

**`yarn`さんが作成してくれているはずです！！**

## さいごに
いろいろな記事を漁ってきて、yarnだけで作成する方法はないかと探っていたところ、見つけられたので共有致しました！

なお`config.json`ファイルには自分にはよく分からなかった値が含まれているので、pushする際に本体はignoreして、`config.example.json`など作成した方が良いかも知れません。
VSCodeでVue + ESLint + Prettierの環境構築する

# 概要
VSCodeで、Vue + ESLint + Prettierを導入し、vueファイルやjsファイルの保存時に、自動的にフォーマットがかかるような環境を整えようとしたが、ちゃんと動くまでに時間がかかったのでメモしておく。

# 試した環境
- macOS Catalina (10.15.7)
- VSCode (1.52.1)

# 手順

## 1. Vueプロジェクトの作成
- vue cliをインストール
    - `npm install -g @vue/cli`
- プロジェクト作成(途中でvue 2か3かを聞かれるが、2にしておく。)
    - `vue create (プロジェクト名)`

## 2. ESlint, Prettier関連の設定
(https://www.npmjs.com/package/eslint-plugin-prettier-vue を参考にしたら比較的簡単にいった。)
 
- 上で作成したプロジェクトのルートディレクトリで、以下を実行
    - `yarn add -D eslint-plugin-prettier-vue eslint-plugin-vue eslint-config-prettier eslint prettier`

- プロジェクト作成時に自動で作成された、ルートディレクトリにある`.eslintrc.js`を、以下のものに置き換える。なお、rulesのセクションで、色々とセミコロンとかクォーテーションの設定等をしているが、ここは好みのものにする。

```javascript:.eslintrc.js

module.exports = {
  extends: ['plugin:vue/recommended', 'plugin:prettier-vue/recommended', 'prettier/vue'],
  settings: {
    'prettier-vue': {
      SFCBlocks: {
        template: true,
        script: true,
        style: true,
        customBlocks: {
          docs: { lang: 'markdown' },
          config: { lang: 'json' },
          module: { lang: 'js' },
          comments: false,
        },
      },
      usePrettierrc: true,
      fileInfoOptions: {
        withNodeModules: false,
      },
    },
  },
  rules: {
    'prettier-vue/prettier': [
      'error',
      {
        printWidth: 100,
        singleQuote: true,
        semi: false,
        trailingComma: 'es5',
      },
    ],
  },
}

```

- 以下のような`.prettierrc.js` をプロジェクトのルートディレクトリに作成。このファイルに書く設定は、`.eslintrc.js`の、rulesのセクションに書いたものと必ず合わせる。

```javascript:.prettierrc.js
module.exports = {
  printWidth: 100,
  singleQuote: true,
  semi: false,
  trailingComma: 'es5',
}

```

- プロジェクトの作成時に自動で作成された、`package.json`内の`eslintConfig`セクションは、不要と思われるので削除しておく。

## 3. VSCodeの準備

- 以下のextensionを導入する。(Veturは入れない)
    - ESlint
    - Prettier
    - vue

- ファイル保存時に自動的にprettierでフォーマットしてくれるように、プロジェクトのルートディレクトリに`.vscode`ディレクトリを作成し、その配下に、以下のような`settings.json`を作成。

```json:.vscode/settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
}

```

- VSCodeを再起動する。

## 4. 適当にjsファイルかvueファイルをVSCodeで書いて保存してみる

- 書いているときにフォーマット違反があったらエラーを出す&保存時に自動フォーマットしてくれるはず
【初心者向け】hタグには直接見出しデザインのCSSを当てない方が良い。デザインごとに専用クラスを付けると管理しやすい。

# どうも7noteです。見出しデザインに関するTips。

hタグにCSSを付ける時、どう書いていますか？
もしこのような書き方をしていれば、注意が必要かも！

```index.html
<!-- 推奨しないCSSの付け方 -->

h2 {
  color: #f00;
  font-size: 200%;
  border-bottom: 1px solid #f00;
  margin: 0 0 50px;
}
```


## なぜhタグに直接デザインのCSSを書いてはいけないのか？

例えば、何ページかあるサイトの開発をするとします。
このとき、全ページで使える共通のCSSファイルを用意するのが一般的かなと思いますが、
この共通のCSSファイルに上のようなCSSを書いてしまうと躓く可能性があります。


`「サービスのページや会社概要のページは同じ見出しの見た目なので、html側ではh2タグを使って書きました。
しかし、お問い合わせのページでは見出し(h2)の見え方を後で変更しようという話になってしまいました。」`

`「急遽変更が必要だったため、お問い合わせのページ専用のCSSファイルに共通のh2のCSSを上書きするような書き方をしました。」`


**こうしてしまうと今後の修正の際に、共通のCSSファイルとお問い合わせのCSSファイルの2つに気を付けながら修正しなければなりません**

また、お問い合わせの見出しデザインをほかの申込ページなどでも使うことになった場合、同じCSSが複数のファイルに分散してまたまた管理が大変になってしまいます。

このような場合でもclassで体裁を管理しておけば、クラスを付けたり外したりするだけで簡単に調整が可能になります。


## まとめ

**共通パーツの作りすぎにも注意**

ある程度どこまで浸透するのかをしっかり把握していなければ、共通のパーツやCSSを安易に修正できなくなってしまいます。
そうならないためにも、分かりやすいクラス名とコメントを付けて管理を行ない、自分以外でも読めば分かるような作りで設計して作成をしましょう。

```sample.css
/* よく使う赤色の下線付きの見出し */
.h-type01 {
  /* CSSデザイン */
}

/* フォームのあるページの見出し */
.h-type02 {
  /* CSSデザイン */
}

```

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【CentOS】Gitの指定バージョンをダウンロードしてビルドする

あまりにも毎回忘れるのでスクリプトを作りました。

## 結論

以下のようにバージョン名を指定してGitをインストールできるプログラムを公開しました。
リポジトリ：[Polarbear08/centos-git-installer](https://github.com/Polarbear08/centos-git-installer)

```
# ./installer.sh 2.29.2
```

詳細はREADMEを参照してください。 

## モチベーション
* Gitは時々脆弱性が発表されてアップデートを促してくる割にはパッケージマネージャでは最新版が入らない
* 最新版を入れるためにソースからビルドする方法を毎回検索していてよろしくない
* 多分探せば類似リポジトリはあるけれどシェルスクリプトの練習をしたい

## スクリプトの内容

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

# verify input
VERSION=$1
if [[ $VERSION =~ [1-9]+\.[0-9]+\.[0-9] ]]; then
        GIT_DIR=git-$VERSION
        GIT_TAR=$GIT_DIR.tar.gz
        URL="https://mirrors.edge.kernel.org/pub/software/scm/git/$GIT_TAR"
else
        echo -e "Usage:\t $0 <VERSION>"
        echo -e "e.g.)\t $0 2.29.2"
        exit 1
fi

# install wget for downloading git
yum install -y wget

# confirm installation
wget -q --spider $URL
if [ $? = 0 ]; then
        echo "install git version $VERSION"
else
        echo "something seems wrong with URL: $URL"
        exit 1
fi

# install dependencies
yum install -y \
        curl-devel \
        expat-devel \
        gettext-devel \
        openssl-devel \
        perl-devel \
        zlib-devel \
        gcc \
        make

# download and install git
mkdir -p /usr/local/src
cd /usr/local/src
wget https://mirrors.edge.kernel.org/pub/software/scm/git/${GIT_TAR}
tar xf ${GIT_TAR}
rm -f ${GIT_TAR}

cd ${GIT_DIR}
make prefix=/usr/local all
make prefix=/usr/local install

# completion notice
git version > /dev/null  && echo "$(git version) was successfully installed"
```

文字コードで変なエラー踏んだら嫌なのでASCII文字だけにしています。

## 参考
* [セマンティック バージョニング 2.0.0](https://semver.org/lang/ja/)  
  セマンティックバージョニングに従ったバージョン名を識別する正規表現が記載されています。
  今回はそんないかついパターンは必要なかったですが参考にしました。
* [Gitのインストール](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)  
  公式ドキュメントです。gitのビルドに必要な依存関係が示されています。gccとmakeは載ってないんですが必要でした。DockerHubのcentosイメージを使ったため普通はデフォルトで入っているパッケージが入っていなかったのかもしれません。
DocumentDBの初期値が不親切な件

#DocumentDBとは
MongoDB互換のAWSマネージドサービスです。ドキュメント指向型のNoSQLでJSONやXMLをそのまま保管できます。

#DocumentDBのインスタンス料金
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/85a51b14-7350-c5d5-f86b-2d71945c7047.png)

（参考：https://aws.amazon.com/jp/documentdb/pricing/）

>料金は、インスタンスの作成から終了あるいは削除までのインスタンス時間単位で計算されます。

一番小さいもので1日あたり0.119USD×24＝2.856USDです。

#インスタンスクラスの初期値が不親切な件
以下は、AWSでDocumentDBを作成する時の最初の画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/b3d079ec-574f-2115-0c48-ad08049c045d.png)

赤字枠の部分が「db.r5.large」になっています。一番小さい「db.t3.medium」ではありません。これ罠ですね。デフォルトのまま作成すると1日あたり8.016USDとなり「db.t3.medium」の約3倍になるのでご注意を！
ERROR: build step 0 "gcr.io/cloud-builders/gcs-fetcher" failed: step exited with non-zero status: 1 【GCP デプロイエラー】


## 解決方法

1. GCP → Storage → ストレージブラウザで `staging.my-project.appspot.com` を削除
2. 再びデプロイ



*参考*

[Google Cloud Build - source-context.json SHA mismatch](https://stackoverflow.com/questions/61346136/google-cloud-build-source-context-json-sha-mismatch)

[gcloud app deploy source-context.json SHA mismatch](https://issuetracker.google.com/issues/154588981?pli=1)
リボルバーリストの作成

円形のリストを表示し、スクロールと連動して回転するピストルのリボルバーのような
アニメーションをするリストの作成

![リボルバーリスト.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411120/e6f10781-9449-9747-916a-25ac0f2e725d.gif)

# デモページ
https://syogo-suganoya.github.io/revolver/

# ソース
https://github.com/Syogo-Suganoya/revolver

# 説明
## リストの作成
回転用のリストの作成をします

CSSで子要素の表示を維持しつつ、要素を回転させる方法
https://www.nxworld.net/css-element-rotate.html

こちらの記事を参考に画面作成をします

今回はスクロールとともに回転させる動きを実装するので、下記をはじめとするのanimation部分は不要です

``` css
ul {
  animation: rotate 30s linear infinite;
}
```


## スクロールアニメーション
CSS と jQuery で作るスクロールにあわせて回転するロゴ
https://hyper-text.org/archives/2013/07/css_spin_logo.shtm
こちらの記事を参考にスクロールアニメーションを実装します
jsで指定してるセレクタを調整します

``` javascript:変更前
$(window).scroll(function(){
 rotate($(".logo"), $(window).scrollTop()*0.2);
})
```

``` javascript:変更後
const selList = ['twitter', 'facebook', 'pinterest', 'instagram', 'google'];
const listCnt = selList.length;

$(window).scroll(function () {

 // 1回転する角度
 var angle = $(window).scrollTop();
 // 180pxスクロールするごとに72度回転する
 angle = Math.round(angle / 180) * (360 / listCnt);

 rotate($("ul"), angle);
 rotate($("ul > li"), angle * -1);
})
```

##  選択中リストの動的更新

``` html
<p class="select-menu">
 twitter
</p>
```

選択中のメニューを表示している箇所の動的書き換えをjsで実装します

```js
// 選択中リストの動的更新
roleCnt = angle / (360 / listCnt);

// 回転数がリストの要素以上なら要素数分マイナスする
while(true) {
 if (roleCnt < listCnt) {
  break;
 }
 roleCnt -= listCnt;
}

var selText = selList[roleCnt];
$(".select-menu").text(selText);
```

 これで完成です

# 備考
元ネタはドラマ「リッチマン、プアウーマン」に出てくる「パーソナルファイル」という架空のWebアプリのUIがこのリボルバーリストのような挙動をしていたので試してみましたw

いつかパーソナルファイルが開発されて転入届などがネットで完結できるようになってくれることを期待しています

【公式】リッチマン、プアウーマン
https://fod.fujitv.co.jp/s/genre/drama/ser4389/
form_withのlocalとflashメッセージ

# ちょっと困ったこと
Railsでよくあるflashメッセージを出そうと頑張っていたが、flash.nowだけ出せない。。。

例えば、以下のようにSessionControllerで、ユーザログインを行うようなコードを書く。

```
 def create
    @user = User.find_by(login_id: params[:session][:login_id])
    if @user && @user.authenticate(params[:session][:password])
      log_in(@user)
      redirect_to @user, success: 'ログインしました'
    else
      flash.now[:danger] = 'ログインに失敗しました。'
      render :new
    end
  end
```

ログイン成功したとき、すなわち、redirect_toした後の「ログインしました」は出るんだけど、ログイン失敗した時、すなわち「ログインに失敗しました」が全く表示されないという問題が発生しました。

# 問題点
結論から言うと、form_withに対してlocal: trueをつけていなかったからでした。
そのため、以下のようにlocal: trueをつけたらうまくいきました。

```
= form_with scope: :session, url: login_path, local: true do |f|
  = f.label :login_id, 'ログインID'
  = f.text_field :login_id, { class: 'form-control' }
  = f.label :password, 'パスワード'
  = f.password_field :password, { class: 'form-control' }
  = f.submit 'ログイン', class: 'btn btn-primary'
```

# なぜlocal: trueが必要か
話がそれますが、form_withにはlocalオプションなるものがあることは知っていました。form_withを使うにあたって、色々調べながら実装していったわけで、参考にする情報は大体local: trueがついていました。

ただ、別にlocal: trueなくても、普通にログインセッション張れるし、つけなくてもいいんじゃね？ということに気がついたので、local: trueは外していました。しかしながら、今回こういう壁にぶち当たった以上、このlocal: trueって何ですか、というところを放置するのはよくないと思ったので、もう少し深堀してみます。

## そもそもform_withにおけるlocalオプションって何？
とりあえずRailsドキュメントを見ましょう。https://railsdoc.com/page/form_with
すると「local：リモート送信の無効」と書いています。これだけでは何のことだかさっぱりです。

もう少し詳しく見たかったので、こちらをあたりました。https://techracho.bpsinc.jp/hachi8833/2020_03_09/39502#6
すると「local: trueを指定するとフォームのリモート + unobtrusive XHR送信が無効になります（デフォルトのフォームではリモート + unobtrusive XHRが有効になります）」という記載があります。

これだけ見るとはてなマークばかりですが「unobtrusive XHR送信」というのはAjax通信のことです。というわけで、form_withにおけるlocalオプションは「当該箇所のform_withはAjax通信を無効（true）にするか、有効（false）にするか」ということになります。

## Ajax通信と今回のflashメッセージ問題考察
さて、ここからは完全に憶測になるので、誤った記載となると思います。参考にする場合はほどほどでお願いします。ちなみに、Ajaxについての詳しい記載は本筋とは少し違うので、省略します。詳細を知りたい方は、本記事最後の[参考](https://qiita.com/k47320/items/3ab4269b97962c5b8fa0#%E5%8F%82%E8%80%83%E8%A8%98%E4%BA%8B)をどうぞ。

### 考察
#### 元のコードでうまくいかなかった理由

- form_withでlocalを指定しない場合、デフォルトでlocal: falseが設定される、すなわち、Ajax通信有効となっている。
  - 今回私が書いたコードもそうなっている。
- これにより、ログインセッションを作成する処理は非同期通信で行われている。
- 非同期通信のため、クライアント側からサーバ側にログインセッションを生成しに行ってもそれがうまくいったかどうかはサーバ側から、クライアント側に返ってこない
    - 例えば、HTTPステータス200とか404とかの情報が返ってこない。
- 今回のケースで言うと「ログイン失敗した」という情報がサーバ側から返ってこないため「flash.now[:danger]」は実行されない。

ところで冒頭に書きましたが「local: trueがない状態で、サーバ側からログインセッション生成しに行った結果が返ってこないのに、なぜ「ログインしました」のメッセージが出て、ログイン後の画面に遷移するのか」という次の疑問が出てきます。

これは、renderメソッドとredirect_toメソッドの違い、というところにあるかと思っています。ざっくりいうと、renderはHTTPリクエストをサーバに送らず、redirect_toはHTTPリクエストをサーバに送ります、というところですね。

今回のケースではログイン処理後にredirect_toを実行している、すなわちサーバからリクエストを送っています。redirect_toメソッドはリクエストに応じたHTMLをクライアントに返すので、クライアント側で画面遷移が発生します。

#### local: trueでうまくいった理由
上記の裏返しなんですが、local: trueにして、Ajax通信を無効、すなわち同期通信をすることによって、サーバからログインできたかどうかの結果がちゃんと返ってきます。それを検知して、flashメッセージが出せるようになるわけです。

# 参考記事

* MDN
https://developer.mozilla.org/ja/docs/Web/Guide/AJAX/Getting_Started

* MDNよりわかりやすいQiitaの記事
https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9

* renderとredirect_to
https://qiita.com/january108/items/54143581ab1f03deefa1
「実際にCOVID-19の状況をデータセットを使って可視化してみる」の二番煎じ

# はじめに

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">せっかくなので作ったんだけど、東京都の感染者数、すごい伸び... <a href="https://t.co/iCPIQktLJi">pic.twitter.com/iCPIQktLJi</a></p>&mdash; Orangeat (@orange_aus) <a href="https://twitter.com/orange_aus/status/1246332258266443776?ref_src=twsrc%5Etfw">April 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388631/f5cb4d75-c96c-9dd9-79e2-6eb680f100a2.png)


> 俺「これもうやるしかねぇな.........」

<div class="flourish-embed flourish-bar-chart-race" data-src="visualisation/4782776"><script src="https://public.flourish.studio/resources/embed.js"></script></div>

＿人人人人人人人＿
＞　[できたもの][2]　＜
￣Y^Y^Y^Y^Y^Y￣



# やりかた

めちゃくちゃ簡単です。

- [SIGNATE COVID-19 Case Dataset - Google スプレッドシート][0]からcsvをダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388631/4e28721c-d760-eda9-8c2d-6749f4801ad5.png)

- 以下のコードを書きます。(たったの3行！！！！)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388631/eb5db5ba-e617-14f0-8e53-6c40b30be56c.png)

- このままだと少し困るので、好きなofficeアプリで整形します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388631/05bb35b6-2120-f924-3529-1acaf1a5bfa6.png)

- Flourishにアップロードします。これで終わり。(えっ！？)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388631/d8cda35f-878e-7454-1428-ee71c73bdbf3.png)

# おわりに

簡単だったでしょ？ぜひ画面横にあるLGTMボタンを押していってください！！！

元ネタ：[実際にCOVID-19の状況をデータセットを使って可視化してみる][1]


[0]:https://docs.google.com/spreadsheets/d/10MFfRQTblbOpuvOs_yjIYgntpMGBg592dL8veXoPpp4/edit#gid=809590826
[1]:https://qiita.com/Orangeat/items/4b6f45b04b677cd2b461
[2]:https://public.flourish.studio/visualisation/4782776/
Ansible: Dockerインストール時にダウングレードを許可する

年末にAnsible勉強中です。
AnsibleでDockerをインストールするときにターゲットバージョンより、新しいバージョンがインストールされていた時の対処方法を備忘録として残します。
aptモジュールを使った他のパッケージのインストール時も同様の対処でいけるはず。

# 結論

* forceにtrueを設定
* dpkg_optionsにforce-downgradeを設定

```yml:main.yml
- name: Docker | Install Docker | apt
  apt:
    name:
     - "docker-ce={{docker_ce_version}}"
     - "docker-ce-cli={{docker_ce_cli_version}}"
     - "containerd.io={{containerd_io_version}}"
    state: present
    update_cache: yes
    force: yes
    dpkg_options: force-downgrade
```

# 実行環境

* vagrant
    * ubntu18.04
        * box-image:ubuntu/bionic64
        * 20201125.0.0
* ansible:2.9.16

# 実行結果（失敗）

最初にオプションが不足したまま、実行して、以下のようなエラーが出力され、調査しました。

```:ansible実行結果
fatal: [192.168.xx.xx]: FAILED! => {"cache_update_time": 1609061762, "cache_updated": true, "changed": false, 
"msg": "'/usr/bin/apt-get -y -o \"Dpkg::Options::=--force-confdef\" -o \"Dpkg::Options::=--force-confold\"
install 'docker-ce=5:18.09.2~3-0~ubuntu-bionic' 'docker-ce-cli=5:18.09.2~3-0~ubuntu-bionic' 'containerd.io=1.3.7-1'
' failed: E: Packages were downgraded and -y was used without --allow-downgrades.",
 "rc": 100, "stderr": "E: Packages were downgraded and -y was used without --allow-downgrades.",
 "stderr_lines": ["E: Packages were downgraded and -y was used without --allow-downgrades."],
 "stdout": "Reading package lists...
Building dependency tree...
Reading state information...
The following package was automatically installed and is no longer required:\n
docker-ce-rootless-extras
Use 'sudo apt autoremove' to remove it.
The following packages will be DOWNGRADED:
  containerd.io docker-ce docker-ce-cli
0 upgraded, 0 newly installed, 3 downgraded, 0 to remove and 10 not upgraded.",
 "stdout_lines": ["Reading package lists...", "Building dependency tree...", "Reading state information...",
 "The following package was automatically installed and is no longer required:",
 "  docker-ce-rootless-extras", "Use 'sudo apt autoremove' to remove it.",
 "The following packages will be DOWNGRADED:",
 "  containerd.io docker-ce docker-ce-cli", "0 upgraded, 0 newly installed, 3 downgraded, 0 to remove and 10 not upgraded."]}
```

# 調査不足

ダウングレードするより、ターゲットバージョンと一致しない場合はアンインストールすべき？

# 参考

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html
https://stackoverflow.com/questions/56332649/is-there-a-way-to-allow-downgrades-with-apt-ansible-module
Githubおもしろリポジトリ① ~面白そうなグラフィック系のリポジトリを発見したので試してみた~

## 経緯
前にgithubのトレンドリポジトリから情報を定期通知するという[記事](https://qiita.com/Hiroaki-K4/items/61b357fa69c90fd9bbfd)を書いたのですが、それを通じて、面白そうなリポジトリを発見したので共有します。今回は[taichi](https://github.com/taichi-dev/taichi)を紹介します。これシリーズ化しようかな(笑)。
**追記: シリーズ化しました。目次は[こちら](https://qiita.com/Hiroaki-K4/items/b6d780f636e87923ad8e)です。**

## taichiとは
**Taichi (太极) is a programming language designed for high-performance computer graphics.**
リポジトリの最初に上のように書かれているのですが、taichiがプログラミング言語なのかはわかりません。taichiはpythonで書かれたコンピュータグラフィックスのためのライブラリだと、勝手に解釈してます(笑)。違ったら教えてください。
**追記: ドキュメントを見ると、taichiはdomain-specific language (DSL)だと書いてありました。DSLについては[こちら](https://qiita.com/aya_eiya/items/07d89eb6c15317eeb68f)をどうぞ。** 
## 試してみた 
導入はpipでtaichi入れるだけです。自分はcudaを使ったgpuモードでやってみました。cpuモードもあるみたいですが、試してはいません。

```bash
pip install taichi
git clone https://github.com/taichi-dev/taichi.git
```
taichiリポジトリの中にexmaplesフォルダがあり、その中にたくさん使用例があります。今回はfractal.pyのコードを共有します。数学詳しい友人に聞くと[フラクタル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%AB#:~:text=%E3%83%95%E3%83%A9%E3%82%AF%E3%82%BF%E3%83%AB%EF%BC%88%E4%BB%8F%3A%20fractale%2C%20%E8%8B%B1,%E3%81%84%E3%82%8B%E3%82%82%E3%81%AE%E3%81%AA%E3%81%A9%E3%82%92%E3%81%84%E3%81%86%E3%80%82)という数学の概念？を使っているそうです。今回は試すだけので、深入りはしません(笑)。

```fractal.py
import taichi as ti

ti.init(arch=ti.gpu)

n = 320
pixels = ti.field(dtype=float, shape=(n * 2, n))


@ti.func
def complex_sqr(z):
    return ti.Vector([z[0]**2 - z[1]**2, z[1] * z[0] * 2])


@ti.kernel
def paint(t: float):
    for i, j in pixels:  # Parallized over all pixels
        c = ti.Vector([-0.8, ti.cos(t) * 0.2])
        z = ti.Vector([i / n - 1, j / n - 0.5]) * 2
        iterations = 0
        while z.norm() < 20 and iterations < 50:
            z = complex_sqr(z) + c
            iterations += 1
        pixels[i, j] = 1 - iterations * 0.02


gui = ti.GUI("Julia Set", res=(n * 2, n))

for i in range(1000000):
    paint(i * 0.03)
    gui.set_image(pixels)
    gui.show()

```
これを実行するとこんな感じになります。
![fractal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/ad96903d-5dac-39e8-657c-ad9e09a8b3d2.gif)
なんかわかんないけど、すごいですね(笑)。
## その他
他の使用例もいくつか載せておきます。

**点と点が繋がって面白いやつ**
![mass_spring_game.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/4f94dd73-acbf-bd44-6263-c094ef99fa7b.gif)

**水の波紋みたいなやつ**
![waterwave.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/092c0053-1889-7156-cc35-0841089e5d12.gif)

**煙を操れます**
![stable_fluid2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/ac114db2-002d-b90b-1ec2-74efbae2bb89.gif)

## まとめ
taichiすごく面白いけど、プログラムに使われてる数学とか物理の知識が自分に足りなさすぎる。勉強します(笑)。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
Josh Skeen, David Greenhalgh著　『Kotlinプログラミング』　章末問題に挑戦(第１８章)

　[Josh Skeen, David Greenhalgh著『Kotlinプログラミング』](https://www.shoeisha.co.jp/book/detail/9784798160191)には章末問題がある。残念なことに解答がないので、[第１５章](https://qiita.com/guijiu/items/0f67138483e12641dfc3/)に引き続き本を読み進めながら答案を記述する。
　もし回答に間違いや意見があれば、ぜひご指摘いただきたい。

#第１８章　章末問題 回答案

##18.11　チャレンジ！　toDragonSpeackエクステンション
toDragonSpeak()関数をコメントアウトし、新たにString関数に対してtoDragonSpeakの拡張関数を作る。この時phraseをthisに置き換る。

```kotlin:Tavern.kt

//private fun toDragonSpeak(phrase: String) = phrase.replace(Regex("[aeiouAEIOU]")) {
//    when (it.value) {
//        "a", "A" -> "4"
//        "e", "E" -> "3"
//        "i", "I" -> "2"
//        "o", "O" -> "1"
//        "u", "U" -> "|_|"
//        else -> it.value
//    }
//}

private fun String.toDragonSpeak() = this.replace(Regex("[aeiouAEIOU]")) {
    when (it.value) {
        "a", "A" -> "4"
        "e", "E" -> "3"
        "i", "I" -> "2"
        "o", "O" -> "1"
        "u", "U" -> "|_|"
        else -> it.value
    }
}
```
また使い方は、次のとおり。

```kotlin:Tavern.kt
private fun placeOrder(patronName: String, menuData: String) {
                     //省略
    // 所持金が代金を上回っているとき
    val phrase = if (name == "Dragon's Breath") {
        "Madrigal exclaims " + "Ah, delicious $name!".toDragonSpeak()    // <==使用箇所
//        "Madrigal exclaims ${toDragonSpeak("Ah, delicious $name!")}"    // 元の記述
    } else {
        "Madrigal says: Thanks for the: $name."
    }
                    //省略
```

##18.11　チャレンジ！　額縁エクステンション


```kotlin:frame_extention.kt
fun main() {
//    print(frame("Welcome, Madrigal", 5 ))
    print("Welcome, Madrigal" .frame(5,"+"))
    print("Hello, Morgal!" .frame(5))
}

fun String.frame(padding: Int, formatChar: String = "*") = {
    val greeting = this
    val middle = formatChar.padEnd(padding)
        .plus(greeting)
        .plus(formatChar.padStart(padding))
    val end = (0 until middle.length).joinToString("") { formatChar }
    "$end\r\n$middle\r\n$end\r\n"
}()

//
//fun frame(name: String, padding: Int, formatChar: String = "*"): String {
//    val greeting = "$name"
//    val middle = formatChar.padEnd(padding)
//        .plus(greeting)
//        .plus(formatChar.padStart(padding))
//    val end = (0 until middle.length).joinToString(""){formatChar}    // ＜＝＝誤記？ formatCharを{}で囲む
//    return "$end\r\n$middle\r\n$end"
//}
```


[第２章チャレンジ！答案](https://qiita.com/guijiu/items/dd3313f2a73401e29bc4)
[第３章チャレンジ！答案](https://qiita.com/guijiu/items/672b8daf014d4e6bb346)
[第４章チャレンジ！答案](https://qiita.com/guijiu/items/08dfa397b989b7ecdb3a)
[第７章チャレンジ！答案](https://qiita.com/guijiu/items/452cfa51bee6c4a4af9d)
[第８章チャレンジ！答案](https://qiita.com/guijiu/items/9a7871b1e41bdabd85e7)
[第１０章チャレンジ！答案](https://qiita.com/guijiu/items/9619abd4d5bf3488e58f)
[第１３章チャレンジ！答案](https://qiita.com/guijiu/items/5eda8682b1c05fa48c7d)
[第１５章チャレンジ！答案](https://qiita.com/guijiu/items/0f67138483e12641dfc3)
[第１８章チャレンジ！答案](https://qiita.com/guijiu/items/18e904913a429aaa58ea)
[第１９章チャレンジ！答案](https://qiita.com/guijiu/items/69579929129715e9cb75)
Djangoでredirectがうまくいかない場合

##この記事の内容



views.pyでこういうコードを打つと

```python:views.py
def example(request):
    return redirect('YYYY')
```




>エラー
>Reverse for 'YYYY' not found. 'YYYY' is not a valid view function or pattern name.

こんなエラーが出たときの対処法


##プロジェクトのurls.pyを確認
プロジェクトのurls.pyにおけるpathの第三引数で「namespace=」で名前を指定してあげないとredirectが該当のviewを探せません。

```python:プロジェクトのurls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('example.urls',namespace="example")),
]

```

##appのurls.pyを確認
「name=」で名前を指定してあげているか確認。
（以下の例では'YYYY'）

```python:appのurls.py
from django.urls import path
from . import views

app_name = 'example'
urlpatterns = [
    path('xxxx/',views.example,name='YYYY'),
]
```


##views.pyを確認
プロジェクトのurls.pyで指定したnamespaceも併せて以下のように指定すると、
redirectが該当のviewを探せます。

```python:views.py
def example(request):
    return redirect('example:YYYY')
]
```

##参照URL
https://docs.djangoproject.com/en/3.1/topics/http/urls/#naming-url-patterns

>Naming URL patterns¶
In order to perform URL reversing, you’ll need to use named URL patterns as done in the examples above. The string used for the URL name can contain any characters you like. You are not restricted to valid Python names.

>When naming URL patterns, choose names that are unlikely to clash with other applications’ choice of names. If you call your URL pattern comment and another application does the same thing, the URL that reverse() finds depends on whichever pattern is last in your project’s urlpatterns list.

>Putting a prefix on your URL names, perhaps derived from the application name (such as myapp-comment instead of comment), decreases the chance of collision.

>You can deliberately choose the same URL name as another application if you want to override a view. For example, a common use case is to override the LoginView. Parts of Django and most third-party apps assume that this view has a URL pattern with the name login. If you have a custom login view and give its URL the name login, reverse() will find your custom view as long as it’s in urlpatterns after django.contrib.auth.urls is included (if that’s included at all).

>You may also use the same name for multiple URL patterns if they differ in their arguments. In addition to the URL name, reverse() matches the number of arguments and the names of the keyword arguments. Path converters can also raise ValueError to indicate no match, see Registering custom path converters for details.


とか
>URL namespaces and included URLconfs¶
Application namespaces of included URLconfs can be specified in two ways.

>Firstly, you can set an app_name attribute in the included URLconf module, at the same level as the urlpatterns attribute. You have to pass the actual module, or a string reference to the module, to include(), not the list of urlpatterns itself.

このあたりの邦訳等、のちほど整理します
【Swift】Shareボタンを押したときの挙動の設定

# ほぼコピペでいける

――はず。
ただシェアする先はこの記事では指定しない（インスタとかツイッターとか）。
Shareボタンを押したときに下からモーダルが出てくるのがおなじみだと思いますが、主にそれの設定になります。

## 実装

```swift:ViewControlloer.swift
  @IBAction func share(_ sender: Any) {
    
    // ここの文章と同時にSNSサービスなどにシェアされる
    let text = "#サービス名"
    // シェアする画像をjpeg形式で圧縮。圧縮率は任意。かけるほど画像は荒くなるが処理が早くなる
    let image = backImageView.image?.jpegData(compressionQuality: 0.5)
    // シェアするものをitemとして定義。型を訊かれるが何型でもないのでAny
    let item = [text,image as Any]
    // 画面遷移（下から出てくるモーダル）の設定
    let activitiyVC = UIActivityViewController(activityItems: item, applicationActivities: nil)
    // 画面遷移
    self.present(activitiyVC, animated: true, completion: nil)
  }
```
[React] JavaScriptのクラスとReact

#JavaScriptのクラスとReact

※ 個人用の覚え書きでございます。

###JavaScriptのクラス（継承）

```javascript:script.js
class Class_1{
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  info() {
    console.log(`名前は${this.name}です`);
    console.log(`${this.age}歳です`);
  }
}

class Class_2 extends Class_1 {
}

const class_2 = new Class_2("山田",20);

class_2.info();
```

###React（ボタンをクリックすると表示が切り替わる）

```react:app.js
import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name: '山田'};
  }

  handleClick(f_name){
    this.setState({name: f_name});
  }
  
  render() {
    return (
      <div>
        <h1>こんにちは、{this.state.name}さん！</h1>

        <button onClick={
          () => {this.handleClick('山田')}}>
          山田
        </button>
        
        <button onClick={
          () => {this.handleClick('田中')}}>
          田中
        </button>
      </div>
    );
  }
}

export default App;
```
複数のバージョンのCUDAを同一環境で扱う方法

大学の研究で機械学習をやっていて、同一環境で複数のバージョンのCUDAを扱うにはどうすればよいのか困ったことがあったのでそれについて書いていく。

# 前提
Windows10環境においてPyTorchをGPUで動かす。
PyTorchのバージョンによって必要なCUDAのバージョンが異なる。
これに伴って、複数のバージョンのCUDAをインストールした。

# 対象者
PyTorchをGPUで動かしたことがあり、cuDNNやCUDAのインストール方法やパスの通し方は大体知っているが、複数のバージョンの扱い方がわからない方。

# 方法
結論から言うと、ユーザーは何もしなくてよい。
パスさえ通っていれば、PyTorchのどのバージョンを動かすかによって必要なCUDAを自動で認識してくれる。

`where nvcc`とコマンドプロンプトに入力した時に

```
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin\nvcc.exe
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0\bin\nvcc.exe
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin\nvcc.exe
```
というように、使うバージョンのCUDAのパスがあれば問題ない。
もしない場合は、（こんなことはまずないはずだが、もし自分でわからずつついている内に消してしまうことはあるかも？）システム環境変数の`Path`に以下のようなパスを追加すればよい。（バージョン10.2の場合）

```
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.2\libnvvp
```

ちなみに、CUDAをインストールしたフォルダはこのようになっている。
![CUDAFolder.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864254/fbb51e72-2c85-c01e-74bf-c1e93b34a65c.png)
`nerves.local` の名前を `orenonerves.local` にする

NervesにSSHする場合、よく `nerves.local` を使ってログインするなど説明があると思います。

個人的には `nerves.local` でなくIPアドレスでSSHしたい方なので、あまり使わない方がいいのではないかなーと思ってます。名前でアクセスする場合はDNSサーバたてたくなる…。

`nerves.local` はmDNSを利用していて同一ネットワークに1つしか名前利用できないので、

- 同じネットワーク
- 複数のNervesが存在する可能性がある

といった場合、とてもとても使いづらい状況になります。

これは、Nervesの名前がデフォルトで `"nerves"` となっているのが問題なので、例えば、自分のNervesに `"orenonerves"` という名前をつけると、`orenonerves.local` にSSHできるようになります。当然ですが、同一ネットワークで名前の重複はNGなのでNervesが増えてくると名前の管理が必要になってきます :wink: 

```elixir:config/target.exs
config :mdns_lite,
  host: [:hostname, "nerves"],
↓
config :mdns_lite,
  host: [:hostname, "orenonerves"],
```
画像内のA4プリントを切り出す

# 画像内のA4プリントを切り出す
写真に存在するプリントを真上視点から切り抜いた画像に変換する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/319b1a3a-22f2-694c-d39f-cd19d22a606e.png)
上の写真を下の写真に変換できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/d3b500a6-75ce-b258-10c6-db609554ef73.png)


# コードに関する注意
- 縦長のA4ファイルに変換するので横長の場合はxとyを書き換えること。
- xが短辺の長さになっているので適度に書き換えること。

# コード


```python:cutting_a4.py
#カラー画像を受け取って紙を切り取って返す
def cutting_paper(img):
    x = 2000 #切り取り後のx座標
    y = int(x*1.415)
    img_gray = gray(img)
    #２値化
    ret,img_th1  = cv2.threshold(img_gray,220,255,cv2.THRESH_TOZERO_INV)
    img_not = cv2.bitwise_not(img_th1)
    ret,img_th2  = cv2.threshold(img_not,0,255, cv2.THRESH_BINARY | cv2.THRESH_OTSU )
    #輪郭抽出
    contours, hierarchy = cv2.findContours(img_th2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    #２番目にでかい四角が紙の輪郭なのでpaper_tapを取り出す
    pic_tap = None #画像の輪郭
    paper_tap = None #紙の輪郭
    for i, con in enumerate(contours):
        size = cv2.contourArea(con)
        if pic_tap is None:
            pic_tap = (con,size)
            continue
        if pic_tap[1] <= size:
            pic_tap = (con,size)
            continue
        elif paper_tap is None:
            paper_tap = (con,size)
        elif paper_tap[1] <= size:
            paper_tap = (con,size)
        
    #直線近似して描画
    epsilon = 0.1*cv2.arcLength(paper_tap[0],True)
    paper_corners= cv2.approxPolyDP(paper_tap[0],epsilon,True)#紙の頂点座標
    fix_con = np.array([[[0,0]],[[x,0]],[[x,y]],[[0,y]]], dtype="int32")#整形後のサイズ

    M = cv2.getPerspectiveTransform(np.float32(paper_corners),np.float32(fix_con))#変換行列の生成
    img_trans = cv2.warpPerspective(img,M,(x,y))#変換
    return img_trans

img = cv2.imread('input.png',-1)
cv2.imwrite("output.png", img)
plt.imshow(plt.imread("output.png"))
```
Aurora Serverlessの接続数について調べた

#はじめに
Aurora Serverlessへ接続するアプリで「Too many connections」というエラーが頻発したので接続数について調べたことのメモ。

#接続数はいくつに設定されているか
これはパラメータグループで確認できる。以下のようにキャパシティー（ACU）に応じて変化する設定になっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/b1a47020-99e7-4a26-1601-b6d13301b52b.png)

各ACUごとの接続数は以下の通り
1ACU：90
2ACU：180
4ACU：270
8ACU：1000
（参考：https://qiita.com/kaba-chan/items/bfd1d8d333d277d6e11a）

現状ACUの最大値を1に設定しているので、最大90接続までということになる。

#ACUに対する接続数を増やすことができるか
例えば以下のように設定すれば1ACUでも180の接続を許可できるのではないか

```
GREATEST({log(DBInstanceClassMemory/805306368)*90},{log(DBInstanceClassMemory/8187281408)*2000})
```

やってみるとエラーになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191613/b16cbef6-481e-9722-d936-6e858ad26f12.png)

AWSのサポートに問い合わせてみたところ、ACUを増やす以外ないと回答あり。

質問
>max_connection のパラメータをデフォルトより増やし、かつスケールさせる設定としたい。

回答
>max_connections を大きくするには現状 ACU を大きくとっていただくほかない状況であり、お客さま>ご想定のようにデフォルトより大きくした状態でかつスケールさせるといった設定値には対応いたしておりません。


#接続数が足りない場合ACUは増えるか
ACUの最大値を増やしたとして、接続数だけが足りない場合にACUは増えてくれるのか。
マニュアルには以下のように記載されている。
>Aurora Serverless DB クラスターに割り当てられたキャパシティーは、クライアントアプリケーションで生成される負荷（CPU 使用率と接続数）に基づいてシームレスにスケールアップ/ダウンされます。また、DB クラスターの容量設定で、一時停止と再開のオプションを有効にすると、接続がないときに容量を 0 にスケールできます。詳細については、「Aurora Serverless の自動的な一時停止と再開」を参照してください。

（参考：https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.how-it-works.html）

接続数が足りなければスケールアップするように見えるが、詳細な条件は公開されてない模様。
Notionの「Add a comment...」を非表示にする

# はじめに
私はNotionを1年ほど使用しているのですが、個人で使っているため、Comment機能を使用していませんでした。
にもかかわらず、ノートの上をコメント記入欄がずっと占領していることにモヤモヤしていました。Notionって意外とまだ検索しても欲しい情報がでてこないんですよね。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/4e53317d-f577-072e-e21e-fc2a9a4d1014.png)
しかし、やっと非表示にする方法がわかったので、同じ問題で困っている方のために共有します
# 方法
1. 「Add a comment...」が表示されているページを開きます
1. ページ右上の「...」からメニューをひらき、「Customize page」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/bf88d7a3-c470-8e7d-0ed0-3123f852c692.png)
1. Page commentsがExpandedになっていると思うので、プルダウンメニューからOffに変更します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/9ef78cbf-823b-8502-3fef-ecf984d60e1b.png)

以上

# おわりに
Notion回りの情報をググっても、別のソフトの情報が出ることが多い印象があります。
みなさんも、もし便利な情報を知っていたら、どんどん発信していきましょう！
愛用者が増えますように...笑
M5StickCのDCDCをオフにしたら稼働時間が倍に延びた話

こういう使い方で稼働時間が40分から80分に延びました。
![IMG_20201227_180221.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607008/9d11ae96-a5d3-1150-3406-02278ce84840.jpeg)
#はじめに
DCDCというのはこちら↓ の記事によるとM5StickCから5Vを出力するために使うものだそうで……
[M5StickCでの省電力ノウハウ](https://lang-ship.com/blog/work/m5stickc-power-saving/#toc8)
「初期化時にOFFにするパラメーターが追加されています」とのことだったのですが、あまり情報がなかったので、GitHubのソースを見ながらやってみることにしました。
Zoom用に作ったbluetoothキーボード(上の写真)の電池の持ちをよくしたいというのが趣旨です。

setup()の中で

```
M5.Axp.begin(false,false,false,false,true);
```

とするとDCDC3をオフにできるようです。(2020 12/27時点)

#で、やってみた
最初に書いちゃいましたが、稼働時間が__40分だったのが80分に__なりました。
__DCDCをオフにするのは省電力にかなり有効__だということが分かりました。
5V出力が必要ない時は積極的にオフしていきたいと思います。

#注意事項
M5.Axp.begin()ですが、使うときに注意事項が２つあります。

*  __オフにするのはDCDC3です__。DCDC1ではありません。

初期化可能なDCDCには DCDC1 と DCDC3 があります。

```void AXP192::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, bool disableDCDC1, bool disableDCDC3)```

DCDC1をtrueにするとディスプレイやボタンが反応しなくなりました。（電源ボタンは使えます）
また、ArduinoIDEでスケッチの書き込みができなくなりました。
（M5Burnerを使ったら書き込めました。そのあとはまたArduinoIDEで書き込みできるようになります
M5Burnerを使っても復旧できない場合があるそうです。(2022 4/26 追記)）

くれぐれも、不用意にDCDC1をtrueにしてしまわないように気を付けてください。

* M5StickCの__ライブラリのバージョンによって引数が異なります__。

この記事の内容は **ArduinoIDE のM5StickCライブラリ  バージョン 0.2.0** 対応です。
GitHubに上がっている最新バージョンではAxp.begin()の引数が一つ増えています。
手元のライブラリではどうなっているか確認してからお試しください。

(GitHubの最新バージョン 2020 12/27現在)
```void AXP192::begin(bool disableLDO2, bool disableLDO3, bool disableRTC, bool disableDCDC1, bool disableDCDC3, bool disableLDO0)```

（twitterで[Lang-ship](https://lang-ship.com/blog/)のたなかまさゆきさん@tnkmasayukiにおしえていただきました。ブログいつも拝見しています。ありがとうございました）

____
追記：
それにしても………参考文献によるとDCDCは常時1.3mA以上使っているという話だったのですが、それだけで稼働時間がこんなにも変わるものでしょうか？
でもソースは他にどこも変えていないし…
何か他の原因に心当たりのある方がいらっしゃれば、教えていただけたら幸いです。
____
###参考文献
[Lang-ship M5StickCでの省電力ノウハウ](https://lang-ship.com/blog/work/m5stickc-power-saving/#toc8)
[GitHub M5StickC/src/AXP192.cpp](https://github.com/m5stack/M5StickC/blob/master/src/AXP192.cpp)
Webカメラから映像取得・画像撮影

# はじめに
ラズパイ用に、USB接続のWebカメラをもらった。
今回はその動作確認とプログラムのメモ。

# カメラ
使用するカメラはこちら。
Logicool　Brio Ultra HD Pro Webcam

# 接続の確認

```
$ lsusb
Bus 002 Device006: ID 046d:085e Logitech, Inc.
```


```
$ ls /dev/video*
/dev/video0  /dev/video1  /dev/video2  /dev/video3
```

が追加された。

# 動作確認
## 1. guvcview
まずインストールしたのは `guvcview` というソフト。

```
$ sudo apt-get install guvcview
```

以下のコマンドで実行。

```
$ guvcview &
```

実行されたはいいものの、最初の画像取得後動かなかった。
動画もとってみたが上手く保存されず。

## 2. fswebcam
調べたが解決しないため諦めて、次は `fswebcam` というものをインストール。

```
$ sudo apt-get install fswebcam
```

実行方法は

```
$ fswebcam img.jpg
```

撮影した画像が `/home/[ユーザー名]/` に `img.jpg` として保存される。

# python上で動かす
以下のコードを実行。

```py
import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    ret, frame = cap.read()
    cv2.imshow('frame',frame)

    key = cv2.waitKey(1)

    if key == ord('q'):
        break
    if key == ord('s'):
        path = "/home/kono/画像/カメラ画像/photo.jpg"
        cv2.imwrite(path,frame)

cap.release()
cv2.destroyAllWindows()
```

キーボードの `s` を押すと撮影、 `q` を押すと終了する。
撮影した画像は指定された場所に `photo.jpg` として保存される。

参考サイトはこちら。
[【Raspberry Pi】webカメラを接続する方法](https://hellobreak.net/raspberrypi-webcamera-0511/)

# まとめ
ソフトウェア上よりも自分で書いたプログラムのほうが動作が安定するなんて。
硬貨識別の課題がんばる。
Dockerコンテナで動いているmariadbを直接操作する

#Wordpressにログインできなくなった
Wordpressを運用していて管理者でログインできなくなってしまい焦りました。
パスワードリセットもうまく効かずmariadbを直接操作してパスワードを変更することにします。


#KUSANAGI RoDのmairadbのパスワード
Kusanagi Rod上で構築している場合、mariadbのパスワードは`.kusanagi.mysql`に記載されています。

```bash:.kusanagi.mysql
MYSQL_ROOT_PASSWORD=wp_root_password          <-- これです！
MYSQL_DATABASE=wp_database
MYSQL_USER=wp_username
MYSQL_PASSWORD=wp_password
MYSQL_CHARSET=utf8mb4
#MYSQL_ALLOW_EMPTY_PASSWORD=
#MYSQL_RANDOM_ROOT_PASSWORD=
#SOCKET=
#MYSQL_INITDB_SKIP_TZINFO=
#MYSQL_ROOT_HOST=
```

#Dockerコンテナのmariadbにログインする
dockerコマンドでDockerのmariadbにログインしてからWordpressのパスワードを変更します。
データベース内ではパスワードはMD5でハッシュ化されていますのでMD5コマンドを使って変更しておきます。

```bash
$ docker-compose exec db mysql -uroot -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.5.6-MariaDB-1:10.5.6+maria~focal mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 
MariaDB [(none)]> use wp_database;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [wp_database]> 
MariaDB [wp_database]> select * from wp_users;
+----+------------+-----------+---------------+--------------+----------------------+---------------------+-----------------------------------------------+-------------+--------------+
| ID | user_login | user_pass    | user_nicename | user_email   | user_url      | user_registered     | user_activation_key                           | user_status | display_name |
+----+------------+-----------+---------------+--------------+----------------------+---------------------+-----------------------------------------------+-------------+--------------+
|  1 | admin      | md5_password | admin    | mail@ddress  | http://example.com | 2020-08-05 05:53:54 | ???? |           0 | admin   |
|  2 | user       | md5_password | user     | mail@ddress  |                    | 2020-08-05 06:30:29 | ???? |           0 | ????    |
+----+------------+-----------+---------------+--------------+----------------------+---------------------+-----------------------------------------------+-------------+--------------+
2 rows in set (0.023 sec)

MariaDB [wp_database]> 
MariaDB [wp_database]> update wp_users set user_pass=MD5('newpassword') where id=1;
Query OK, 1 row affected (0.034 sec)
Rows matched: 1  Changed: 1  Warnings: 0
```

これでWordpressにログインできるようになっていればOKです。
Goのnetパッケージを理解する～2日目～

# はじめに

>この記事は、[Goのnetパッケージを理解する～1日目～](https://qiita.com/Marny/items/918f292614de7d8fa8f7)の二日目の記事です。

今回は、**POSTやGETの処理・htmlの出力**をしていきます。

## ソースコード

```go:main.go
package main

import (
	"fmt"
	"log"
	"net/http"
	"text/template"
	"time"
)

type Host struct {
	Title string
	Date  time.Time
	Text  string
}

func main() {
	http.HandleFunc("/", handler)
	http.HandleFunc("/temp", handlerTemp)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		fmt.Fprint(w, "Hello GET")
	case "POST":
		fmt.Fprint(w, "Hello POST")
	default:
		fmt.Fprint(w, "Hello")
	}
}

func handlerTemp(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("template/index.html")
	if err != nil {
		log.Fatalf("template ERROR")
	}
	host := Host{
		Title: "テストタイトル",
		Date:  time.Now(),
		Text:  "これは、netパッケージの練習です。",
	}

	t.Execute(w, host)
}
```
```html:index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    Test Page
    <form method="POST" action="/">
        <button type="submit">POST</button>
    </form>

    <p>{{ .Title }}</p>
    <p>{{ .Date }}</p>
    <p>{{ .Text }}</p>
</body>
</html>
```

前回のコードを引用して作成しました。
関数一つ一つ解説していきます。
### main関数
ここはほぼ前回と同じ。
8080番ポートでサーバの起動をしています。
`/temp`ってのを追加したくらい

### handler関数
前回とは大きく変更しました。`handler`に飛ばされてくるメソッドを`switch`文で捌いています。

この書き方は、同じ関数を引数にとっても、メソッドが異なるため、正常な動作をしてくれます。
(なんとなくかっこいい感じもする)

今回は、`/`に対するメソッドを確認したかったので、このように書きました。

### handlerTemp関数
今回の肝の関数。
ここで、htmlの出力系の処理をしています。

まず、変数`t`を宣言して、`template.ParseFiles("template/index.html")`を指定してます。

これにより、`template`ディレクトリにある`index.html`を出力しますよーって言っている。

`index.html`のコードにもあるように、`{{ .hoge }}`みたいにテンプレートを扱っているので、`Host`を構造体として作成し、定義している。

最後の`t.Execute`でhostを返している

## 実行してみる

### /にアクセスしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/b4a81053-7f4d-bad2-32e3-97c05313cec7.png)

GETメソッドのため、print文が`Hello GET`になっている

### /tempにアクセスしてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/3476ca4c-2562-5829-a0bc-1ee57f9904d6.png)

hostの内容が出力されていることがわかる。ここで、POSTボタンで`/`にアクセスしてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450534/de258418-e92b-639b-287d-95750633d1b2.png)
POSTでアクセスしたので、print文が`Hello POST`になっている事がわかる。


# まとめ
Goでなにか作るときは、ginとかechoを使ってアプリケーション開発してたんですが、netパッケージもアプリケーション開発以外にも有効に使えるので、これからも継続的にメモとして書いていきます。

netパッケージ。結構いい感じやん。