OmniAICreator/Qiita-1.07M huggingface dataset:
GlusterFSで新しいサーバを追加できないときの対処"already part of another cluster or having volumes configured"

# 状況
既存のGlusterノードが複数個ある
ここに、新たに複数のノードを追加したい。
そのためにpeer probeを試みると以下の**エラーメッセージ**のような事態に。
＊念の為ボリュームは全て削除済み


# エラーメッセージ
Ansible経由で"あるひとつのノードからみた、自分(e.g. server0)以外のノード全て"をpeer probeしようとした。
以下は例です。大人の事情により色々コードの見た目変えてます。

```:AnsiblePlayBook
    - name: Probe gluster nodes
      shell: |
         gluster peer probe server{{item}}
      with_sequence: end=99 start=1
```

話それますが、ひとつのノードからこれをやれば十分です。すべでのノードで自分以外のノードを全てpeer probeしようとしなくても、GlusterFSは賢いのでpeer nodesを自動で共有してくれます。

これでいけるはずと思いましたが、以下のエラーで、新規のノードから既存のノードへのpeer probeが失敗します。
Ansibleがコマンドラインを紅に染めてしまいます。。。

```
 server1 is either already part of another cluster or having volumes configured 
 .......
```

# 解決法

1. 既存のノードたちのうち一つをピックアップし、そこでピックアップしたノードで、それ以外のpeer nodesをdetachしました。

まずは繋がってるノードを確認しましょう。

```:Bash
gluster peer status
```

これで出てきたノードのうち、ピックアップしたノード以外のノードを、ピックアップしたノードからdetachしましょう。

```:Bash
gluster peer detach {{自分以外のpeer nodes}}
```
ひとつのノードからこれをやれば十分です。すべでのノードで自分以外のノードを全てpeer detachしようとしなくても、GlusterFSは賢いのでpeer nodesの変更を自動で共有してくれます。

これで、既存のノードたちは一時的に職を失い、無我の境地に至ります-これまで頑張ってファイルを分散してきたのに、新入りのノードのために容易くもdetachされるとは、まさに、諸行無常。。。

2. 新規のノードの集団(peer probe済み)に、既存のノードをpeer probeする。

例として既存のサーバーがserver[1-5]だとすれば、新規ノードのうち一つをピックアップして、それだけに以下のようなAnsible playbookを適用しました。大人の事情により、色々コード書き換えてます。

```:AnsiblePlayBook
    - name: Probe gluster nodes
      shell: |
         gluster peer probe server{{item}}
      with_sequence: end=5 start=1
```

あとは、適当なノードで、peer nodesのステータスを確認し、新旧のノードが仲良くしていることを確認してください。

```:Bash
gluster peer status
```


# 感想　インフラ構築は丸亀製麺のような手打ちは通用しない
うどんは丸亀製麺のように手打ちがいいですよね。
でも、インフラの構築には手打ちは通用しないです。
だって、十数台の大量のサーバーに手打ちでコマンド打ったら、手が疲れるし、気が狂います。
Ansibleなら、正しいplaybookさえ作れば、実行終了を待つだけです。

もうね、Ansibleしか勝たん。。。って感じですよ。
AnsibleをはじめとするInfrastructure as Code, IaCはROI高めなので、エンジニアのキャリアの初期に学ばさせていただけたのは本当に感謝です！

というわけで、Ansibleに感謝！
ここまで読んでいただき感謝です！
pyenv globalでpythonのバージョンが切り替わらない(mac)

pythonの環境設定をこちらの記事に沿って進めていきました。

https://prog-8.com/docs/python-env

macではデフォルトでpythonがインストールされていますが、2系の古いバージョンであるため、こちらを使わず使わず新たにインストールしていきます。
ここで、pythonのバージョン管理ツールpyenvを使用してインストールしていきます。
記事通りの内容は割愛しています。

```:zsh 
.....

% pyenv global 3.9.5

% python --version
Python 2.7.16
```
...切り替わらない

ググると eval "$(pyenv init -)"　をやれと書いてある。
早速実行

```:zsh
 % eval "$(pyenv init -)" 
WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.
```

ここでエラーが発生
pyenv initをしろと書いてある。

実行

```
% pyenv init

# (The below instructions are intended for common
# shell setups. See the README for more guidance
# if they don't apply and/or don't work for you.)

# Add pyenv executable to PATH and
# enable shims by adding the following
# to ~/.profile and ~/.zprofile:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

# Load pyenv into the shell by adding
# the following to ~/.zshrc:

eval "$(pyenv init -)"

# Make sure to restart your entire logon session
# for changes to profile files to take effect.

```
記事の方では　echo 'export ~'とやっていたが。。
echoなしで、もう一度設定をやり直す必要があるようだ。

実行

```:zsh
% export PYENV_ROOT="$HOME/.pyenv"
% export PATH="$PYENV_ROOT/bin:$PATH"
% eval "$(pyenv init --path)"
% eval "$(pyenv init -)"
% pyenv global 3.9.5   
% python --version  
Python 3.9.5
```
切り替えに成功

今後なぜechoコマンドでの設定が成功しなかった理由を調べます。
Laravelでマークダウンプレビュー機能を実装する

Laravelで[marked.js](https://github.com/markedjs/marked)を使用したマークダウンプレビュー機能を実装したので備忘力として残して置こうと思います。

## 完成形
![スクリーンショット 2021-06-12 10.37.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477510/ca957bc8-a84e-96d8-4c6e-a7a93ac57f0c.png)



## 1.marked.jsをインストール

```terminal
$ npm install marked
```
インストールができたのか確認は`package.json`の`dependencies`をみていただけると`marked`が入っていると思います。



## 2.テンプレート作成

```php:resources/views/posts/form.blade.php
<form class="post-page-wrapper" action="{{ route('post.create') }}" method="post">
@csrf
    <div class="row">
        <div class="col-6 m-1">
            <textarea name="body" id="markdown_editor_textarea" cols="30" rows="10" class="form-control"></textarea>
        </div>
        <div class="col-6 m-1">
            <div id="markdown_preview"></div>
        </div>
    </div>
    <div class="post-page-footer">
        <input type="submit" class="post-button m-1" value="投稿">
    </div>
</form>
```

マークダウンをプレビューに表示する処理をjsに記述

```js:resources/js/markdown.js

import marked from 'marked';

// マークダウンをプレビュー画面に表示する
$(function() {
	marked.setOptions({
		langPrefix: '',
		breaks : true,
		sanitize: true,
	});

	$('#markdown_editor_textarea').keyup(function() {
		var html = marked(getHtml($(this).val()));
		$('#markdown_preview').html(html);
	});

    //マークダウンをHTMLに変換する
    var target = $('.item-body')
    var html = marked(getHtml(target.html()));
    $('.item-body').html(html);

	// 比較演算子が &lt; 等になるので置換
	function getHtml(html) {
		html = html.replace(/&lt;/g, '<');
		html = html.replace(/&gt;/g, '>');
		html = html.replace(/&amp;/g, '&');
		return html;
	}
});

```

app.jsに読み込ませる

```js:resources/js/app.js
require('./markdown.js');
```

これでこのようにプレビュー表示できるようになります。
また、[highlight.js](https://highlightjs.org/static/demo/)を使用するとプレビューにハイライトをつけたりおしゃれにすることができるので是非やって見てください。
Oracle実験室 / CentOS7.x 初期設定

# 前書き
私が勉強中のOracle DatabaseについてVirtualBox環境でセットアップ・各種操作等を行った際のメモです。

- 記事一覧 [Oracle実験室 / Oracle Restart環境構築 (19.3)](https://qiita.com/Que-sera-sera/items/df2a5f53953ea500f333)
- 前の記事 [Oracle実験室 / CentOS7.xインストール](https://qiita.com/Que-sera-sera/items/5caf51f9f55f962ff7e3)
- 次の記事 [Oracle実験室 / Oracle Database 19c Grid Infrastructure (19.3) インストール](https://qiita.com/Que-sera-sera/items/c23143f9cb62bb360aa9)
<br> 

# CentOS7.x初期設定
Minimalインストール済のCentOS7.xにOracle Databse 19c稼働用の初期設定を行います。

## パッケージインストール
### OSアップデート
```
# yum -y update
```
### GNOME Desktopのインストール
```
# export LANG=C
# yum -y groupinstall "GNOME Desktop"
```
## 時刻同期
### 設定
```
systemctl enable chronyd.service
systemctl start chronyd.service
```
### 確認
```
systemctl status chronyd.service
chronyc sources
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/b163455b-f8ea-e0d3-7e08-39ac93afa4d8.png)

## ランレベル確認・変更
### 確認
```
# systemctl get-default
multi-user.target
```
### 設定
```
# systemctl set-default graphical.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/graphical.target.
```
### 確認
```
# systemctl get-default
graphical.target
```

## firewall設定
Oracle*Net用のポート番号1521を開放しておきます。
EM Expressのポート番号はOracle Databaseインストール後に開放しますのでここでは実施しません。
Oracleでは必要ありませんがサーバーも使用するのででhttpサービス用も開放します。

```
### 設定
# firewall-cmd --add-service=http --permanent
success
# firewall-cmd --add-port=1521/tcp --permanent
success
# firewall-cmd --reload
success
```
### 確認
```
# firewall-cmd --get-default-zone
public
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s3 enp0s8
  sources:
  services: dhcpv6-client http ssh
  ports: 1521/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294043/dd1e76e8-9a71-9bf8-fd73-4d020bc389cc.png)
plunkerでruffle

#概要

plunkerでruffleやってみた。

#サンプルコード

```

var swfobject = {};
swfobject.embedSWF = function(url, id, width, height) {
  var ruffle = window.RufflePlayer.newest();
  var player = Object.assign(document.getElementById(id).appendChild(ruffle.createPlayer()), {
    width: width,
    height: height,
    style: 'width: ' + width + 'px; height: ' + height + 'px',
  });
  player.load({ 
    url: url 
  });
}
swfobject.embedSWF('https://e9x.github.io/ruffle/1on1soccer_24.swf', 'ruffle', 300, 300);



```

#成果物

https://embed.plnkr.co/plunk/P4ujL6aj2COkeobG

以上。
Ruby on Rails　プロジェクトを作成　勉強用

# デスクトップにrubyディレクトリを作成
rubyディレクトリに移動

```
mkdir Desktop/ruby

cd Desktop/ruby
```
#rubyのバージョンを2.6.3に指定
※ディレクトリ内でバージョンを指定
※バージョンが違うとエラーになる

```
rbenv local 2.6.3
```
# プロジェクトを作成

```ruby
#rails new プロジェクト名
rails new project
```
#プロジェクト先に移動
```ruby
#cd プロジェクト名
cd project
```

#railsのサーバーを立ち上げる

```ruby
rails s
```
#railsのサーバーを停止

```
Controlle + c
```

#プロジェクトURL

```
http://localhost:3000/
```

#vsCodeでプロジェクトを開く

```
code .
```

#Gemfileのファイルにインストールするgemを記載して保存
```ruby
#ログイン機能
gem 'devise'

gem 'refile',require: 'refile/rails',github: 'manfe/refile'

gem 'refile-mini_magick'
#スタイル
gem 'bulma-rails'
```

#Gemfileの変更を適用

```
bundle install
```
【アルゴリズム】JavaScriptで反転問題を解く

#はじめに
以前からアルゴリズム系に苦手意識があり、ずっと勉強を後回しにしてきたのですが、このたびQiitaで「競技プログラミング強化月間」が始まったので便乗して勉強してみることにしました。

試しに解いたLeetCodeが解説も意味不明なレベルだったので、もっと優しいレベルの問題を解いて記事にまとめていくことにしました。

JavaScriptでアルゴリズムの勉強をされている方の参考になれば幸いです。
記事を順次まとめていきますので、その他の記事ついてはマイページからご覧ください。

https://qiita.com/suzuki0430

https://qiita.com/official-events/5a0502a2d94ed6a00c30


#文字列反転
引数に文字列を与えたときに反転した文字列を返してください。
ex.) `reverse('apple') === 'elppa'`, `reverse('hello') === 'olleh'`, `reverse('Greetings!') === '!sgniteerG'`

##解答
初期値が空の文字列`reversed`を用意し、引数の文字列`str`の文字`character`をfor文で先頭から取り出します。
`reversed`を後ろから`character`に連結していくことで、反転した文字列`reversed`が完成します。

```js:index.js
function reverse(str) {
  let reversed = '';

  for (let character of str) {
    reversed = character + reversed;
  }

  return reversed;
}
```

#回文
引数に与えた文字列が回文だったときにtrue、回文ではなかったときにfalseを返してください。
ex.) `palindrome("abba") === true`, `palindrome("abcdefg") === false`

##解答
文字列`str`を`split('')`で文字の配列にした後に、`reverse()`で配列の順番を反転させ、`join('')`で再び文字列`reversed`に戻します。
最後に`str`と`reversed`を比較した結果を返します。

```js:index.js
function palindrome(str) {
  const reversed = str.split('').reverse().join('');

  return str === reversed;
}
```

#整数反転
引数に正負整数を与えたときに反転した正負整数を返してください。
ex.) `reverseInt(15) === 51`, `reverseInt(981) === 189`, `reverseInt(-15) === -51`

##解答
`String(n)`で引数`n`を文字列に変換し、回文のときと同様に文字列`reverseStr`として反転させます。
記号も含めて反転されてしまっているので、`parseint(reverseInt)`で正の整数に戻した後、`Math.sign(n)`で`n`の正負(+/-1)をかけてあげます。

```js:index.js
function reverseInt(n) {
  const reverseStr = String(n).split('').reverse('').join('');

  return parseInt(reverseStr) * Math.sign(n);
}
```

#参考資料
https://www.udemy.com/share/101WNkCEEZd11VRno=/
Rubyのsplat展開について

## はじめに
『プロを目指す人のためのRuby入門』を読み進めていた時に気になった、splat展開についてまとめてみます。
Qiita初投稿ですので、どうかお手柔らかに。

## そもそもsplat展開って何？
Arrayオブジェクトにアスタリスクをつけることによって、配列が自動で展開される構文のことです。
文章で説明するよりも、実際に使い方を見せた方が分かりやすいと思います。

```ruby:irb
ary = [1, 2, 3]

# splat展開を使わない
[ary] #=> [[1, 2, 3]]

# splat展開を使う
[*ary] #=> [1, 2, 3]
```
上記を見ればわかる通り、配列を勝手に展開してくれます。

## 実用例
「別にいらない」と心の中で叫んだ方、いると思います。私もそうでした。
そんな方のために、今からsplit展開の実用例をお見せしますね。

例として、配列同士を連結させたい時は下記のような書き方になります。

```ruby:irb
ary = [1, 2, 3]
[-1, 0] + a + [4, 5] #=> [-1, 0, 1, 2, 3, 4, 5]
```
長ったらしくて読みづらいですよね。こんな時にこそ、splat展開を使いましょう。

```ruby
ary = [1, 2, 3]
[-1, 0, *ary, 4, 5] #=> [-1, 0, 1, 2, 3, 4, 5]
```
どうですか？読みやすくなりましたね。

## 最後に
最後に、この記事を書くにあたって参考にした『プロを目指す人のためのRuby入門』の著者の伊藤 淳一様、ありがとうございました。
実務ではRailsばかり触っているが、言語そのものの知見も同時に伸ばしたいという方にオススメの一冊です。
時間がある方はぜひ一度、じっくり読んでみましょう！

[プロを目指す人のためのRuby入門](https://www.amazon.co.jp/dp/B077Q8BXHC/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
QAエンジニアのロードマップ

PCを買う（2020年8月）
MacbookAir 

Javaを学ぶ
プログラミングの導入として
→SpringBootのフレームワーク
→Tomcatの基礎知識
ThymeleafでDBの値をブラウザに表示する

HTML/CSSを学ぶ
基本的なタグの使い方を把握

JavaScript
基本的な読み方を学ぶ

Ajax

jQuary

SQLを学ぶ
無料で使えるPostgresSQLでSQL文を動かしてみる

Linux
最低限のコマンドを学ぶ

<h3>JSTQBを学ぶ</h3>
テスト技法やテストの知識を学ぶ
境界値分析
デシジョンテーブル
同地分割法
状態遷移テスト
PICTでパターン網羅

JUnit5
ユニットテストのコーディング、view、

Jmeter
リクエストが返ってくるまでの時間を計測

GitHubの使い方を学ぶ
pull,push,commit,コンフリクトの対処

Docker

Selenium
ブラウザの自動操作コーディングを学ぶ

Cypress
Postman
Node.jsの概要<基本のき>

#Node.jsとは

##Node.jsについて
・JavaScriptの実行環境
→つまり、Mac、Linux,WindowsなどのOSに依存せずにJavaScriptを実行することができる
→ソースコードを理解して実行するものが、実行エンジンという
→そのソースコードを理解するための言語が、ECMAScript(JS)で書かれている

##npmについて
・JavaScriptに向けたパッケージマネージャー
→数多くのモジュールを管理してくれるもの

##Node.jsの特徴
・シングルスレッド
→一つのリクエストに対して、一つのリスポンスを返す。
→つまり、一度に複数のリクエストが来ても、一つのスレッドが完了しなければ新たなスレッドは立たない

・ノンブロッキングI/O
→メインプロセスを止めずに、他の処理を行うことができる
→つまり、非同期処理のこと

・イベント駆動
→一つのイベントに対して、処理を実行する

##Node.jsを使用するには
・任意のプロジェクト(ファイル）とその中にpackage.jsonがあればOK
→任意のファイルに移動して、npm initをコマンドプロンプトで入力すれば終了
OS初学者の学習記録 〜4. メモリ管理〜

# メモリ管理とは？

一次元の物理アドレス空間を持つメインメモリ上には、OSの自身だけでなく、複数のアプリケーションプログラムやデータも共存することになる。
↓
どの領域が使用済みor未使用かを管理し、確実に書き込み&読み出しをおこなうことが要求される。(メモリ管理、メモリ保護)



### アドレス空間

通常、プログラムは実行可能形式のデータとして補助記憶装置に格納されていて、実行時に物理メモリに読み出す。
多くのOSでは、物理メモリ上の任意の位置にプログラムを配置することができる。

* **物理アドレス**：物理メモリ上のアドレス
* **物理アドレス空間**：物理アドレスの集合
* **論理アドレス**：各プロセスに独立に与えられた、論理的なアドレス
* **論理アドレス空間**論理アドレスの集合

上の2つのアドレスの変換は、**アドレス変換**と呼ばれ、**メモリ管理ユニット(MMU)**と呼ばれるハードウェアを用いて行われる。


### スワッピング

##### スワップアウト
メモリ容量が不足した場合に、時間刻みを使い切ったプロセスを**スワップファイル(スワップ領域)**に書き出して停止し、専有していたメモリ空間を開放する。

##### スワップアウト
スワップファイル(スワップ領域)から再度メモリに書き戻す。


スワップを繰り返すと、メモリ名にたくさんの利用できない小さな空き領域が生じてしまう。(**フラグメンテーション**)
解消するには、**メモリコンパクション**という、小さな細切れの空き領域を大きな空き領域にする処理を行えば良いが
処理コストが大きいので、現実的には困難な場合が多い。


### 空きメモリ管理

##### 固定区画方式
メモリを固定長の区画に分割してメモリを割り当てる。
各区画へ1つのプロセスを割り当てる**単一区画方式**と、複数の固定長の区画に分ける**多重区画方式**がある。
↓
同時に実行可能なプロセスの多重度は、いくつの区画に分割しているかによる区画の数に依存するので、原罪ではあまり利用されていない

##### 可変区画方式
メモリの**どの部分が利用可能で、どの部分が使用済みか**を記録した表を用いて管理する方法。これが現在のOSでは一般的。
この方式では、大きさの異なる様々な空き領域が生じるので、適切に割り当てることが必要になる。


##### ファーストフィット
最初に見つかった領域に入れる。


##### ベストフィット
１番ギリギリで格納できる領域に入れる。


##### ワーストフィット
ベストフィットの逆


##### ビットマップによる管理
各ブロックの使用状況をビットマップ(ビットベクトル)で管理する。


##### 連結リストを用いた管理

* 空きもしくはプロセス所有
* その領域の先頭アドレス
* 領域サイズおよび次エントリのアドレス

などをが合わさった構造体を連結させたリストを使って管理する。



# 仮想記憶

物理メモリ容量より大きなプログラムを動かす場合は、工夫が必要。
↓
メインメモリを抽象化し、巨大で一様な記憶領域である仮想アドレス空間として、物理アドレスから独立させた形で論理アドレス空間を提供する。


### オーバーレイ

補助記憶装置上のプログラムを、いくつかの断片に分け、必要に応じてその断片をスワップイン・アウトする。
この手法は、プログラマがどのタイミングでどの部分をスワップするか指定する必要があった、、、



### ページング

仮想アドレス空間を、**ページ(page)**と呼ばれる固定長ブロックに分割。
一方、物理アドレス空間を、**ページフレーム(page frame)**と呼ばれる固定長ブロックに分割。
この２つのサイズは同じにするのが一般的。(Linuxは4096バイト)
↓
**ページテーブル**という対応表を使って、ページとページフレームをマッピングすることで、ペーz単位でメモリを割り当てることができる。(ページイン・ページアウト)


### ページングの高速化

ページテーブルをCPUのレジスタにおくことができれば、メモリにアクセスすることなくマッピングを行えるが、ページテーブルのサイズが大きい場合は、ページテーブルの実装にレジスタを使うのは適していない。
↓
そこで、**TLB(transration look-aside buffer)または連想メモリ**と呼ばれる、小型かつ高速な、キャッシュ用の専用ハードウェアを利用することが一般的。


### 大容量仮想記憶でのページテーブル

**逆ページテーブル法**と呼ばれる、物理アドレス空間のページフレームごとにエントリを作成する方法がある。
【C言語】隣接行列でサイクルを作成する/しない

#概要
隣接行列におけるサイクルを作成する、しないの条件をなかなか実装できず、有識者に教えていただいたのでメモとして記事にしようと思います。

#コード
前提条件として、ひとつの頂点からは辺が１本の一方向にのみ生成されるという場合を考えています

```ruby:qiita.rb
// j -> i へのパスが存在するか？
cur_node = j;
while (true) {
  if (cur_node == i) {
    // パスが存在する
    // do something
    break;
  }
  bool end = true; // while 終了フラグ
  for (int to = 0; to < n; to++) {
    // 辺が存在したら進む
    if (locked[cur_node][to]) {
      cur_node = to;
      end = false;
      break;
    }
  }
  if (end) break;
}
```
[Python]Seleniumを用いたDocker環境でのE2Eテスト方法 メモ

* Docker環境でのSeleniumを用いたE2Eテスト方法についてメモする。

## 構成

![docker-selenium.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/889bdaae-2949-c64c-12ee-9577ae537770.png)


## 事前準備

* Docker環境で動かすため、[こちら](https://qiita.com/KWS_0901/items/5076a2f4cff544505c5d)の構成でdocker-compose.ymlやDockerfileなどdocker-seleniumを利用するための設定を準備する。

## テストコード`test.py`

* `selenium`でQiita検索した結果を確認する。
* テストコードの大まかな書き方
  1. テスト前処理：ドライバ設定などを記述する。
  2. テスト実行：ブラウザ操作とその際の期待結果を記述する。
  3. テスト後処理：ドライバクローズなどを記述する。

```python
import os
import unittest
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

class SampleTest(unittest.TestCase):
    # テスト前処理: ドライバ設定
    def setUp(self):
        self.driver = webdriver.Remote(
            command_executor=os.environ["SELENIUM_URL"],
            desired_capabilities=DesiredCapabilities.CHROME.copy()
        )
    # テスト後処理：ドライバクローズ
    def tearDown(self):
        self.driver.quit()

    # Qiita検索 テスト
    def test_qiita_search(self):
        # 任意のHTMLの要素が特定の状態になるまで待つ
    	# ドライバとタイムアウト値を指定
        wait = WebDriverWait(self.driver, 10)
        # テスト対象へアクセス
        self.driver.get("https://qiita.com/")
        # 検索ボックス入力→検索実行
        self.driver.find_element(By.NAME, "q").send_keys(
            "selenium" + Keys.RETURN)
        # 1件目の検索結果を取得(描画されるまで待機)
        first_result = wait.until(
            presence_of_element_located((By.CSS_SELECTOR, "h1")))
        print("first_result:"+first_result.get_attribute("textContent"))
        # タイトルに`selenium`が含まれるかを判定
        assert "selenium" in (
            first_result.get_attribute("textContent")).lower()

if __name__ == '__main__':
    unittest.main()

```

## 動作確認

* ビルド→起動→コンテナの中に入る。

```shell
docker-compose build --no-cache
docker-compose up -d
docker-compose exec app bash
```

* コード実行

```shell
cd test
python test.py
```

* 期待値

```
...省略
----------------------------------------------------------------------
Ran 1 test in 7.221s

OK
```



## 参考情報

* [pythonでseleniumのテストコードを書いてみる](https://qiita.com/reflet/items/8f541edde58d635daac4)
* [`unittest --- ユニットテストフレームワーク`](https://docs.python.org/ja/3/library/unittest.html#module-unittest)
streamlitで動的なウェジェット（ボックス）のまとめ

##はじめに
前回の続きでstleamlitを活用してインタラクティブなウェジェットを作っていく。
インタラクティブとは双方向や対話式といった意味で動的な物を指す
インタラクティブなウェジェットは簡単に言うと動的なパーツということである。

今回作るのは
######「チェックボックス、セレクトボックスとテキストボックス、スライダーである。」

##チェックボックス

```
st.checkbox
```
結果はtrueとfalseで帰ってくる→if文に変えることでチェックボックスに条件を付けることが出来る。

ここではチェックボックスにチェックを入れることで画像を表示させてみる。

```
if st.checkbox('Show Image')
    img = Image.open('~~~~.~~~')
    st.image(img,caption='kizunaAI',use_column_width=True)
```
![2021-06-12 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1634469/9f8c05fc-4830-dc5c-60b1-4ba19ea6aa05.png)

##セレクトボックス

```
st.selectbox
```
１～１０の好きな数字を選択するシステムを作ってみる。

```
st.selectbox('あなたの好きな数字は',
    list(range(1,11))
```
これでラベル付けと１～１０の範囲のリストを作ることが出来た。

さらに今回はoptionという変数を付けることで「あなたの数字は～です」という形を作りたい。

```
option=st.selectbox('あなたの好きな数字は',
    list(range(1,11))
'あなたが好きな数字は',option,'です。'
```
![2021-06-12 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1634469/16e690e7-db68-86d7-39fe-fc112ddbdf38.png)

上の画像は結果画面をスクショしたものだが、好きな数字は隠れてしまっているがきちんと反映されていた。

##テキストボックス
テキストボックスも先のセレクトボックスやチェックボックスと大差なく、
st.text_inputと置くことで出来上がる。
変数を使って、結果を丁寧に表示させることをしてみた
結果を下に貼っておく。
![2021-06-12 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1634469/0a7088ec-a7e2-2abc-b072-28a52db0b48c.png)

##スライダー
最後にスライダーだ。これはゲージのような物で、
動く範囲の数値と初期位置を最初にとってあげる必要がある。

```
st.slider('あなたの今日の調子は？',0,100,50)
```
カッコ内、最初の２つの数字が範囲で後ろの50というのが初期位置を表している。
これも先ほど同様変数で変数に代入させ、ゲージの数値を表示させたものが下の画像である。
![2021-06-12 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1634469/081b4b90-054e-f9aa-0cfd-33a095a94249.png)

#まとめ
１行の簡単な文のみでこれほどまでに本格的に出来上がるのかととても感動した。
まだまだstreamlitのさわりでしかないが、やはりCSS無しでもpythonのみで完結できる簡潔さはちょっとした物を作る上ですごく楽だと感じた。

それと今回はコメントアウトの方法を覚えたのでメモっておく。

・コメントアウトのやり方
選択　➡　Ctrl＋（K→C）
C++で, エンジニアがしてはならないこと

# はじめに

~~今週~~ 毎週怒り狂っています. 今関わっているプロジェクトは, **C++ プログラマがしてはならない** ことを全てしています.

用語について,

- オブジェクト: オブジェクト指向でよく知られる. 情報とそれに対する操作を, ひとつにまとめて抽象化したもの. 現実の物とは関係ない, 問題を情報と操作で抽象化する.

# フォーマッタで, 強制できない規約を作ってはならない

```
//----------------------------------
/** 冗長だし, 見やすいと思います？あびゃー
*///--------------------------------
```

このような規約を守るため, 同僚は一日中"カタカタカタターン"しています. 単純に五月蠅いのでやめていただきたいです. 私が知っているフォーマッタでは対応できないと思います. フォーマッタを使った後で, "このようなフォーマットに補正するPowerShellのワンライナー"を作ってあげたとか, 頭おかしなるで.

# copy, and paste をしてはならない

気になってリファクタリングをした結果, 300箇所程度を修正することになりました. 聞くところによると, `copy, and paste`を推奨する, 私より歳をとったうましかがいるらしいです. しかも, 2箇所, 不具合にはならないが他と違う箇所が見つかりました, 意味は同じになるコードです. Error～という文字列があるのでほとんど通らないパスと思われます.
もちろん, "やめろや"と言いますが, 二言目には"いや", "でも", "ずっとこうだったし"と言われます.

```
template<class T>
void add(Base* base, const char* name)
{
	add(base, name);
}

template<class T>
Base* find(const char* name)
{
	return dynamic_cast<Base*>(find_(name));
}
```

というコードに対して,

```
add<Class0>(Class0::Name);
Base* base = find<Class0>(Class0::Name);
```

300箇所, 該当の2箇所以外は, このようなコードです. 要するに, `class Class1`を作ったら, `static const char* Class1::Name` を必ず定義するわけです. これもコピペで量産されています, 珍妙なコメントごと.
余談ですが, `RTTI`はコンパイラオプションで無効化されているので, `dynamic_cast`は意味がないどころか害悪になっています.

# stringのコピーをしてはならない

パフォーマンスを気にしなくてよい環境はありますが, このプロジェクトはそうではありません. それどころか, "処理堕ちしたからなんとかして欲しい", と言い出す始末, 訳がわからないです.
"Copy On Write (COW)があるから"という言い訳は[とおりません](https://qiita.com/taqu/items/249d08ddaaa52ce3a5c6).

# autoを正しく理解しなければならない

```
const std::vector<int>& Class0::getList() const;
```
に対して,

```
auto list = class0.getList();
```

をしてはならない. 言語を正しく理解してないだけです. 勉強する気がないなら, **イキリauto** はやめましょう.
補足します. 次のようにコメントの意図通りにならないのです.

```cpp
void initialize()
{
    //処理するアイテムを優先度順にソートする
    auto list = class0.getList();
    std::stable_sort(list.begin(), list.end());
    //優先度順に初期化処理をする
    for(size_t i=0; i<list.size(); ++i){
    }
}

void terminate()
{
    //優先度と逆順に終了処理をする
    auto list = class0.getList();
    for(int64_t i=list.size()-1; 0<=i; --i){
    }
}
```

# `free` と `delete` はヌル値に対して何もしない

`SAFE_FREE`, `SAFE_DELETE`などと称して, ヌル値でないかチェックしてから解放する処理は意味がありません.
大事なことは次の３点です. これらを犯した場合, `SAFE_`なんたらは全く安全ではないです. 1.と 2.が守られていない場合, 全く安全ではないです, 安全であるかのように誤解させる関数やマクロを定義するのはやめましょう, 大事なことなので.

1. コピーを禁止にする
  - 私の少ない経験では, オブジェクトのコピーが必要になったことはありません
    - ディープコピーは, 自ら地獄へダイブする行為なのでしてはいけません
        - 画面遷移の際に, ユーザデータをディープコピーしようとした輩がいるので
  - swapやmoveで十分, 用に足ります
    - moveの実装はswapより難しいため, swapを推奨します
2. 確保時に, 確実に初期化する, ヌル値も有効な値です
  - オブジェクトの作成時に, 確実に初期化します.
3. 解放時に, ヌル値など意味のある値にする
  - オブジェクトの破壊時に値を設定することに意味はないですが, デバッグ時に役立つ場合があります

# まとめ

TODO: 見つけ次第更新

余談ですが, IDEの多くはデフォルトで `TODO`, `TODO:`, などを検出するようになっています. `TODO_XXX`などの検出にヒットしない書き方は避けましょう.
【Php】GET, POSTの学習ノート(1)

# 初めに
GETについて学習した内容のoutput用記事です。

※内容に間違いなどがある場合はご指摘をよろしくお願いします。
※こちらの記事はあくまでも個人で学習した内容のoutputとしての記事になります。

# GETのテスト
Http通信でリクエストを行う方法の一つであるGETを試してみるための入力フォームを作成します。methodには"GET"と入力し、actionにはリクエスト先のページを入力します。ここではform.phpとしました。nameにはデータを取得するための名前を付けておきます。

```html
 <form method="GET" action="form.php">
        名前
        <input type="text" name="input_name">
        <br>
        <input type="checkbox" name="dishes[]" value="カレー">カレー
        <input type="checkbox" name="dishes[]" value="チヂミ">チヂミ
        <input type="checkbox" name="dishes[]" value="牛丼">牛丼

        <input type="submit" value="submit">
</form>
```
GETの場合、ブラウザーのアドレスバーに?から始まるquery stringが表示され、入力した値をみることができます。
![スクリーンショット 2021-06-12 9.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/70710bbc-47c3-5c5b-9cff-7d6094e7aa37.png)

# $_GET
phpに予め用意されているスーパグローバル変数$_GET。GETメソッドでリクエストした値が格納されています。

```php
$_GET["nameの値"]);    //$_GETの書き方
```

var_dumpを使って \$_GETの中身を表示してみます。また、empty()メソッドを使い\$_GETに値が入っている場合にだけ$_GETが表示されるようにします。

```php
echo '<pre>';
if (!empty($_GET)) {
    var_dump($_GET);
}
echo '</pre>';
```

keyとvalueの連想配列として保存されていることが分かります。

![スクリーンショット 2021-06-12 10.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/e01325ab-3117-8791-fd7b-6c743d054219.png)

# POSTのテスト
POST通信を行うため、methodをPOSTにした入力フォームを作成します。

```html
<body>
    <form method="POST" action="form.php">
        <select name="books">
            <option value="--">本を選択</option>
            <option value="novel">小説</option>
            <option value="comic">漫画</option>
            <option value="magazine">雑誌</option>
        </select>

        <input type="submit" value="submit">
    </form>
</body>
```

# $_POST
phpに予め用意されているスーパグローバル変数$_POST。POSTメソッドのリクエストとして入力した値が格納されています。

```php
$_POST["nameの値"]);    //$_POSTの書き方
```
\$_GETとは違って入力値を送信してもアドレスバーには何も表示されません。同じくvar_dumpメソッドで中身を確認します。

```php
echo '<pre>';
if (!empty($_POST)) {
    var_dump($_POST);
}
echo '</pre>';
?>
```
こちらも\$_GETと同様、連想配列という形でデータが保存されていることが分かります。

![スクリーンショット 2021-06-12 10.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/8f312017-4f51-195d-2300-2f47dbd5275a.png)

# 参考サイト
https://www.php.net/manual/ja/reserved.variables.get.php
https://www.php.net/manual/ja/reserved.variables.post.php
STM32G031で温度,S-5851Aをソフトウェアシリアル出力


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり


```c++

#include <Wire.h>

//STM32G031J6M6 i2cピンの定義
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

#define S5851A 0x48

int     tempval;                //温度
char    data_read[3];           //バッファー

//#define in7 1 //uno
#define in7      PB7  // 1pin

#define DW   digitalWrite
#define UART_DELAY 102   //  9600bps ok 031

//10の割り算 0から1028までは、正しい。主に0から999
#define DVI10(n) ((n*205)>>11)

//仮想シリアルへの一文字出力 9600bps
int pc_putc(char ch) {

  DW(in7, HIGH);

  DW(in7, LOW);//START
  delayMicroseconds(UART_DELAY);

  for(int ii=0;ii<8;ii++){
    DW(in7, (ch>>ii)&1  );
    delayMicroseconds(UART_DELAY);
  }//for

  DW(in7, HIGH);//Stop
  delayMicroseconds(UART_DELAY);

  return(0);
}//pc_putc

//文字列の表示
int pc_printf(char *str1) {

    //文字の中身がゼロか
    while(*str1){

        //一文字出力
        pc_putc(*str1 ++);
        //Serial.print( *str1 ++ ); //uno

    } //while

    //戻り値
    return(0);
}//pc_printf

//0から999まで文字列に変換
char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
  int a,b,c;

  b=DVI10(l_num);
  c=l_num-(b*10); //1の桁
  a=DVI10(b);     //100の桁
  b=b-(a*10);     //10の桁

  ch_hex_a_b[0] = '0' + a;
  ch_hex_a_b[1] = '0' + b;
  ch_hex_a_b[2] = '0' + c;
  ch_hex_a_b[3] = 0;

  return(ch_hex_a_b);
}//ch_hex_a

//初期化
void setup()
{
  //ポートをhiにする 初期化
  pinMode(in7, OUTPUT);
  DW(in7, HIGH);
  delayMicroseconds(UART_DELAY*10);

  Wire.begin(sdaPin,sclPin); //STM32G031J6M6

  //Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  //0番目のレジスター
  Wire.beginTransmission(S5851A);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);

  //温度の読み込み
  tempval = 99;
  Wire.requestFrom(S5851A, 1);
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    tempval = (int)Wire.read(); // 1バイトを受信
  }//while
  delay(1);

  //tempval=12; //debug

  //表示
  data_read[0] = '0' + (tempval / 10);
  data_read[1] = '0' + (tempval % 10);
  data_read[2] = 0;
  pc_printf( data_read );
  pc_printf( "\r\n" );

  delay(1000); //1秒待つ
  
} //loop




```
SSHの設定からWANを介した通信から片付けまでまとめ。

<a id="#詳細"></a>
#概要
　SSHの設定方法は結構たくさん記事にされているのですが、「LANで使えるようになって終わり」とか、「SSHの設定は別の人を見てDDNSの設定方法を教えます」みたいな細々したものばかりなので、それらのURLをまとめ、UbuntuでSSHを設定してWANを介して通信できるまでの一連の流れを、一つにしてみました。
　ほとんどURLを張り付けただけの自分用のメモです。
　
<a id="#行うことについて"></a>
#行うことについて
　最初にUbuntuのSSHDを起動して、SSHサーバを立ち上げ、LAN内でWindowsからSSHサーバへの接続を行います。
　その後、公開鍵認証の設定やセキュリティの確認を行った後に、WANを介するためのDDNSやポートの設定を行います。
　WANを介して接続する際は、スマホにいれた[JuiceSSH](https://juicessh.com/)を用いて、外からSSHサーバに接続できることを確認します。
　最後に立ち上げたSSHサーバを閉じます。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033231/6f45f388-922d-25df-042c-7b1c5c967ecc.png)
<a id="#IPアドレスの設定"></a>
#IPアドレスの設定
　サーバーのIPが変わらないようにIPを固定します。
　IPを固定する前にDHCPサーバーに自分のIPアドレスをリースしてもらうように設定します。
　こうしないと、固定したIPアドレスが別の端末に勝手に使われてしまいます。
　IPアドレスのリースの設定はルータごとに異なるため、型番などで調べること。

https://www.buffalo.jp/support/faq/detail/15917.html

　先ほどリースしたIPアドレスをサーバー側に設定します。

https://qiita.com/zen3/items/757f96cbe522a9ad397d

<a id="#sshの設定"></a>
#SSHの設定
 以下のURLではECDSA-521の公開鍵認証を使い、SSHサーバの構築からWindowsを用いての接続を行っています。

<b>[Windows10からLinuxへのSSHに安全性の高いSSH公開鍵認証を設定](https://www.rem-system.com/sshd-pubkey/)</b>


#設定するとよいセキュリティの設定
　[sshの設定](#sshの設定)の段階で十分なセキュリティが確保されているのですが、さらに強固にする方法をいくつか紹介します。
###ポート番号の変更
　攻撃者は22番ポートを集中的に攻撃するので、ポート番号を変えて、攻撃者の数を減らすことで、事実上、安全性をあげることができます。
　ただし、その他の設定で穴があれば、安全性は0に等しいので、本質的には安全性は変わりません。

https://qiita.com/hana_shin/items/4a90fa66e2d77324912c

###ログイン失敗回数の制限　
　ログインを失敗した回数が一定以上を超えた場合に、一旦すべての接続を遮断するような設定もあります。

https://www.server-memo.net/server-setting/ssh/account_lock_ssh.html

#セキュリティホールはありませんか？
　この後にポートを開けるのですが、とても危険な行為なので、セキュリティの設定をちゃんと行えているかを再度確認してもらうため、わざと、章に分けなくていい部分を分けました。
　以下のうち1つでも達成できないものがあれば、もう一度[sshの設定](#sshの設定)に戻って設定をよく確認してください。

1. [このリスト](https://nordpass.com/most-common-passwords-list/)にあるような安直なものを設定していない。
2. Lan内のクライアントから、パスワードを入力せずにログインはできない。
3. 秘密鍵の設定をせずに、ログインはできない。
4. SSHのポート番号を別のソフトが使用していない。（コマンドで調べてた後に、[wikipedia](https://ja.wikipedia.org/wiki/TCP%E3%82%84UDP%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7%E3%81%AE%E4%B8%80%E8%A6%A7)のリストにもなければ問題ないはずです。）


#WANを介して接続できるようにする
　まずは、家庭内のルーターの設定を行いポート開放を行います。
　ルーターによって、設定の方法が変わるため、「型番　ポート開放」などで調べてください。

　「NO-IP」を用いてDDNSの設定を行います。

https://tarufu.info/domain_acquisition_no-ip/

　JuiceSSHの設定を行って、SSHサーバへ接続してみます。
　この時、接続ができない場合はスマートフォンのWi-Fiを切っておきます。

https://juicessh.com/faq

#不正なログインがないか確認
　ログを確認する方法。
　想定外の人がアクセスしてくることは稀ですが、週に1回は確認しておくことをお勧めします。

https://t-min.hatenablog.com/entry/2017/12/07/090529

　
#片付け
　もし、もうSSHは必要なくなったという時のため、片付けを行う方法も書いておきます。
　ここまで、ちゃんと設定すれば不正なログインはされないと思いますが、「SSHに脆弱性があった」何てことはいつも使って意識していないと気付かないものなので、使わなくなったら、片付けは忘れず行いましょう。
　最初に、家庭内のルーターでポート開放するために行った設定を削除します。
　次にSSHDを起動しないように「 /etc/init/ssh.conf」のに書き込まている「start on filesystem」をコメントアウトし、再起動を行えばSSHDが起動していないはずです。

https://server-setting.info/ubuntu/ubuntu-stop-sshd.html

　再度、起動させたい場合は「#start on filesystem」をアンコメントしてSSHDを起動した後に、家庭内のルーターのポート開放を行うだけです。
Html.map

ちょっと混乱したので自分用のメモです。

ElmはHaskellと異なり`map`はそれぞれの型に対して個別に定義されている。

Html型に対する`map`は次の仕様。

```.elm
 map : (a -> msg) -> Html a -> Html msg
```
- Htmlによって生成された（附帯した）メッセージを変換する関数
- 第1引数は、ある型の値を別の型（メッセージに使う型）に変換する純粋関数
- 第2引数はHtml型の何らかの値
- 戻りは第2引数のメッセージ部分を第1引数の関数で変換した結果となる

Haskellのmapで、こういうことをしているのと同じ

```.hs
>>> map digitToInt ['1','2','3']
[1,2,3]

-- (Char -> Int) -> [Char] -> [Int]
```
ここでリスト（`[]` Elm風に書くなら`List`）がHtmlに相当する


https://package.elm-lang.org/packages/elm/html/1.0.0/Html#map の例では

```.elm
type Msg = Left | Right

view : model -> Html Msg
view model =
  div []
    [ map (\_ -> Left) (viewButton "Left")
    , map (\_ -> Right) (viewButton "Right")
    ]

viewButton : String -> Html ()
viewButton name =
  button [ onClick () ] [ text name ]
```
- viewButton関数はHtmlを返すが、メッセージは`()`（空のイメージ）
- この`Html ()`の`()`をview関数内で無名関数をmapしてMsgに変換している。

要するにメッセージを特定しない汎用のボタンを描画する関数を作っておいて、あとから生成したいメッセージをmapするという使い方か。
引用元には「これはあまり頻繁には役に立ちません。」って書いてあるんですが（笑）、Elmとしては例のケースではわざわざmap使うより

```.elm
view model =
  div []
    [ button [ onClick Left ]  [ text "Left" ]
    , button [ onClick Right ] [ text "Right" ]
    ]
```
と書くほうがシンプルで分かりやすい、ってことなんだろう。

もう少し複雑なものを書くようになると便利な局面が出てくるのだろうか。
使いどころを理解したら追記します。
フォーマット中のSDカードを抜いてしまった

Linux PC（ubuntu 16.04）でフォーマット中のSDカードを誤って抜いてしまい、
SDカードを読み込めなくなったので、SDカードを読み込めるようするためにしたことをメモしておく。

1. SDカードをフォーマットする
1. ファーマットが終了したと思ってSDカードを抜く
1. 再度SDカードを挿したが、認識しない
1. フォーマットしたものとは別のSDカードを挿してみたが認識しない
4. PCを再起動（GUIで再起動したが、なぜかpasswordの入力を求められた）
4. なかなか（5分待っても）再起動しないので、強制再起動（Alt+PrtScを押しながら R→S→E→I→U→B）
4. 再起動後、問題のSDカードを挿すが認識しない
4. 別のSDカードを挿してみると問題なく認識した
4. 再度、問題のSDカードを挿し、dmesgで確認

    ```
    xxx@xxx:$dmesg | tail  
    [  849.515807] mmc0: cannot verify signal voltage switch  
    [  849.645988] mmc0: new ultra high speed SDR104 SDHC card at address aaaa  
    [  849.648696] mmcblk0: mmc0:aaaa SC16G 14.8 GiB  
    [  849.651696] mmcblk0: p1 p2
    ```

4. mmcblk0でググってSDカードだと確認（mmcblkは「「Multimedia Card」(SD含む) のブロックデバイス」らしい。。。）
4. とりあえずマウントしてみる

    ```
    xxx@xxx:$sudo mount -t vfat /dev/mmcblk0p1 /mnt
    mount: wrong fs type, bad option, bad superblock on /dev/mmcblk0,
           missing codepage or helper program, or other error
           In some cases useful info is found in syslog - try
           dmesg | tail or so.
    xxx@xxx:$sudo mount /dev/mmcblk0 /mnt
    mount: wrong fs type, bad option, bad superblock on /dev/mmcblk0,
           missing codepage or helper program, or other error
           In some cases useful info is found in syslog - try
           dmesg | tail or so.
    ```

4. マウントできなかった、いろいろググッた結果フォーマットするコマンドがわかったのでフォーマット
    (もともとフォーマットするつもりだった)

    ```
    sudo mkfs.vfat -F 32 /dev/sdc1
    ```

10. SDカードを抜いてから、再度挿し直すと認識できた（ファイルマネージャで自動マウントされた）
docker login azureでAzureにログインしようとしたがno such hostでブラウザが開かない

# はじめに

JupyterLabの環境をデプロイしたいと思い、Azureの勉強をしているのですが、会社で利用している環境でコマンドが正しく動作しなかったのでまとめてみました。

# 開発環境
- Vscode
- Docker desktop 3.3.0

# 問題

結論として、`Docker desktopのバージョンが古いことが原因でした`

以下に解決までの道のりとアップデートの方法についてまとめます。

Azure Container InstanceでACIを作成するときに以下のコマンドをpowershellに入力します。

```
docker login azure
```

本来であれば自動でブラウザが立ち上がり、microsoftの認証画面が開きログインすることで`login successed`と表示されます。

しかし、以下のような入力を求めてきてブラウザは開きません。

```
> username:
> password:
```

とりあえず言われた通りAzureアカウントのユーザー名とパスワードを入れたところ、以下のようなエラーがでました。

```
Error response from daemon: Get https://azure/v2/: dial tcp: lookup azure on 192.168.65.1:53: no such host
```

調べてもうーんよくわからない。
私用のPCで試した時にはブラウザが開いているのでおかしいと思い、調べて解決したことを以下にまとめます。

# 解決方法

直接的な解決方法はネットに落ちておらず、ツイッターにて同じ症状の方がいるくらいでした。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">docker login azure doesn&#39;t popup a browser. So how do I sign in?</p>&mdash; Matthijs Hoekstra (@mahoekst) <a href="https://twitter.com/mahoekst/status/1291890114692632579?ref_src=twsrc%5Etfw">August 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

色々、調べたところ以下の記事で手掛かりを見つけます。

https://www.atmarkit.co.jp/ait/articles/2009/25/news009.html

この記事にこのような記述があります。(要約は以下)

```
Docker Desktop Communityの安定板をリリースをした。
Docker CLIのクラウドインテグレーションは、ネイティブなdockerコマンドを使用して、クラウドのサーバーレスコンテナ実行環境である「Azure Container Instance (ACI)」にアプリケーションをデプロイして実行できるものです。
```

この記述から、`Docker desktop`のバージョンによって機能が追加されているのかと考えました。いまのバージョンは2020年5月に追加したもので、私用のDocker desktopは最新版にアップデートをしています。

## Docker desktopを最新版にアップデート

タスクバーからDockerを右クリックしてupdateを選択しアップデートをします。

アップデートの準備ができると以下のようになります。

![1623376404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/31b8a73c-f4b9-41b4-3f0c-af62861bbd6f.png)

`Download and update`をクリックします。

すると最新版にアップデートできます。

![1623376559.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/be98b085-c13e-5cb1-7465-9321cd4935ef.png)

その後、再度アイコンを右クリックして`update and restart`をクリックして終了です。

## 確認

再度コマンドをたたいてみます。

```
docker login azure
```

![1623376803.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/f7d726e4-2ea2-65dc-a516-0e06fc2ff237.png)

無事成功しました。

`docker login azureができないのはDocker desktopのバージョンが古いのが原因でした`

# おわりに
社内のAzure環境のアカウントを頂いたときに、権限周りでエラー起きるかもとのことで、それが原因かなとも思っていましたがそんなことありませんでした。

Azureは記事が少ないのもあるのか原因解決が難しいです。

# 参考記事

[Azure Container Instances（ACI）とDocker Desktopの連携が強化](https://www.atmarkit.co.jp/ait/articles/2009/25/news009.html)
jQueryとJavaScriptを使ってWebデザインページを作成しました。

jQueryとJavaScriptを使ってWebデザインページを作成しました。
今回はjQueryフレームワークを使いました。（普段はBootStrap派です)


```HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>jQueryを使ったアニメーションテスト</title>
</head>
<!-- jQueryを使ったテスト -->    
<script src="jquery.js"></script>    
<script>
//F1タグの色を青に変える    
$(function(){
    $('h1').css('color','blue');
});

//F2タグを消す    
$(function(){
    $('h2').fadeOut();
});

//h4タグの色を変える    
$(function(){
    $('h4').css('color','deeppink');
});

//h5タグの背景を変える    
$(function(){
    $('h5').css('background-color','black');
});
    
//fuori-classeサイトを別ウィンドウで開く    
function test100(){
    let i = 0;
    while (i< 1){
        window.open('http://www.fuoriclasse2.com/','flora','width=600,height=450');
        i++;
    }
}

//EURO2020のイタリアVSトルコ戦のサイトを別ウィンドウで開く     
function fuoriclasse(){
    let i = 0;
    while (i< 1){
        window.open('http://www.fuoriclasse2.com/cgi-bin/g.cgi?euro&2020&210611','italy vs Turkey','width=600,height=450');
        i++;
    }
}
    
</script>
<style>
h1 {
   color:red;
   font-size:50px;

}
h2 {
   color:black;
   font-size:40px;
}
.test
{
   color:lawngreen;
   font-size:50px;
   background-color:dimgray;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 10px #8b7348;    
   width:350px;
   height:150px;    
}

.test2 {
    background-color:aliceblue;
    text-align: center;
    color:darkred;
    font-size:80px;
    padding: 100px;
}    
.test3{
   color:indianred;
   font-size:30px;
   background-color:aliceblue;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 10px #b0c100;    
   width:400px;
   height:100px;   
}    
.test4{
   color:#05AB92;
   font-size:20px;
   background-color:whitesmoke;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 5px #cccccc;    
   width:200px;
   height:100px;
}

.test5{
   color:#00FF00;
   font-size:20px;
   background-color:whitesmoke;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 5px #66AA33;    
   width:80px;
   height:50px;
}

.test6{
   color:yellow;
   font-size:20px;
   background-color:darkorchid;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 5px #66AA33;    
   width:200px;
   height:100px;
}
    
.test7{
   color:black;
   font-size:18px;
   background-color:white;
   text-align: center;
   padding :20px;
   margin: 20px;
   border:solid 5px #66AA33;    
   width:200px;
   height:100px;
}
    
    
    
    
</style>		

<body>
<h1 class="test">jQueryのテスト</h1>

<h2 class="test2">この部分は消えます</h2>
<h3 class="test3" >I will move to Osaka at next year.</h3>
<h4 class="test4">大阪で頑張るぞー</h4>
<h5 class="test5">以上報告でした</h5>
    
<br>
<a class="test6" onclick=test100()>株式会社fuori-classe</a>
<br>
<br>
<br>
<br>
<br>    
<a class="test7" onclick=fuoriclasse()>EURO2020の試合結果が出てるぞ</a>    
<br>    
</body>
```

完成したWebページです

![Web.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/efad8334-a773-c55a-ff2f-ea15cb93f85c.jpeg)
競技プログラミングでdcを使う(1/?)

**1** [2](https://qiita.com/shogo314/items/059094162959029cce3e) [3](https://qiita.com/shogo314/items/6838b0beb84f911f0515) [4](https://qiita.com/shogo314/items/a7b6668602bb976ef940) 5(執筆中)

# はじめに
この記事はAtCoderのABCのA問題をdcで解くためのものです。
私は全くの初心者であり、ネットで適当に拾ってきた情報から自分なりに解釈したものなので間違っている部分があればお教えください。C言語やPythonなどの一般的な言語を扱える（A問題やB問題がその言語で解ける）ことを前提としているので、説明をとばしている部分があります。

dcを勉強するにあたって[こちら](https://kazmax.zpp.jp/cmd/d/dc.1.html)のページ（以下、参考ページ）を参考にしました。
# dcについて
まずdcが何かについては[Wikipedia](https://ja.wikipedia.org/wiki/Dc_(UNIX) "dc (UNIX)")でも見てください。私はそもそもUNIXが何かすらわかっていません。私が認識しているのはAtCoderで使える言語の中で単純な計算問題ならばdcが最も短く書けるということだけです。ただ速く解きたいだけの私にはそれで十分なのです。
# 本題
この記事と対応するように問題を分類した記事を作成しました。
[AtCoderのABCのA問題でdcで書きやすいものまとめ](https://qiita.com/shogo314/items/fff4be1573d2f86dba2a#%E5%8D%98%E7%B4%94%E3%81%AA%E8%A8%88%E7%AE%97)
# 単純な計算
実際に問題を見ていきましょう。<br>[ABC004](https://atcoder.jp/contests/abc004/tasks/abc004_1)<br>数字をひとつ読み込んでそれを二倍したものを出力すればよいです。コードは

```
?2*p
```

こうなります。短いですね。これを読み解くと、<br>「?」で数字を読み込む→「2\*」で読み込んだ数字に2を掛ける→「p」でその数字を出力する<br>
という流れになります。「2」と「\*」の順番が気になると思いますが、2を掛けるという言葉の通りの順番だと解釈しましょう。
「\*」以外にも「+」「-」「/」「%」などが同様に扱えます。また「^」で累乗の計算もできます。
***
少し練習しましょう。<br>[ABC007](https://atcoder.jp/contests/abc007/tasks/abc007_1)<br>数字をひとつ読み込んでそれから1引いたものを出力すればよいです。

```
?1-p
```
***
2回以上の演算も行えます。<br>[ABC009](https://atcoder.jp/contests/abc009/tasks/abc009_1)<br>読み込んだ数字を2で割って切り上げたものを出力すればよいです。<br>つまり読み込んだ数字に1を足して2で割ります。
<details><summary>1を足す理由</summary>ほとんどの言語において整数の割り算は計算結果を切り下げたものになります。dcはちょっと複雑なのですが、A問題を解くときは数字は常に整数型であると思っておいて問題ないでしょう。このような切り捨てになる割り算において、切り上げの計算にしたいときは、割られる数に割る数を足して1引いておきます。つまり
⌈a÷b⌉=⌊(a+b-1)÷b⌋ (⌈⌉:天井関数 ⌊⌋:床関数 [参考](https://ja.wikipedia.org/wiki/%E5%BA%8A%E9%96%A2%E6%95%B0%E3%81%A8%E5%A4%A9%E4%BA%95%E9%96%A2%E6%95%B0))
となります。if文を使う必要がなくなるので是非覚えておきましょう。</details>

```
?1+2/p
```

普通なら「*」や「/」を「+」よりも先に計算しますがdcでは言葉で説明したときと同じ順になります。
***
dcでは「A」「B」「C」「D」「E」「F」はそれぞれ「10」「11」「12」「13」「14」「15」と解釈されます。なぜか微妙に16進数を採用しているのです。また、おもしろいことに「BD」と書くと「123」と認識されます。これは10の位に11が入って、1の位に13が入るためです。

[ABC013](https://atcoder.jp/contests/abc013/tasks/abc013_1)

```
?9-p
```

「?」は本来文字は読めないのですが、この問題で使う文字はA~Eなので読めてしまいます。
# おわりに
これらの知識だけで解ける問題があるので[こちら](https://qiita.com/shogo314/items/fff4be1573d2f86dba2a#%E5%8D%98%E7%B4%94%E3%81%AA%E8%A8%88%E7%AE%97)の「単純な計算」の箇所にある問題を解いてみましょう。

ここまででも十分速くなりますが、残念ながらA問題といえども、これだけで解ける問題は少ないです。次の記事ではスタックについて勉強します。

#
**1** [2](https://qiita.com/shogo314/items/059094162959029cce3e) [3](https://qiita.com/shogo314/items/6838b0beb84f911f0515) [4](https://qiita.com/shogo314/items/a7b6668602bb976ef940) 5(執筆中)
STM32F767で温度,S-5851Aをシリアル出力 (Arduino)


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり



```c++

#include <Wire.h> //I2C library

#define S5851A 0x48

int     tempval;                //温度
char    data_read[3];           //バッファー

void setup()
{  

  //i2cの初期化
  //Wire.begin(); //uno
  Wire.begin(); // initialise the connection
  //Wire.begin(sdaPin,sclPin); //STM32G031J6M6
  //Wire.begin(PB_9,PB_8); //f767

  //シリアルの速度設定
  Serial.begin(9600);


Serial.println("767");
  
} //end setup

void loop()
{

  //0番目のレジスター
  Wire.beginTransmission(S5851A);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);

  //温度の読み込み
  tempval = 99;
  Wire.requestFrom(S5851A, 1);
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    tempval = (int)Wire.read(); // 1バイトを受信
  }//while
  delay(1);

  //表示
  data_read[0] = '0' + (tempval / 10);
  data_read[1] = '0' + (tempval % 10);
  data_read[2] = 0;
  Serial.println( data_read );

  delay(1000); //1秒待つ

}//loop


```
[Python]docker-selenium環境 構築方法 メモ


* 環境依存しないスクレイピング/E2Eテスト環境を作りたかったため、docker-seleniumの利用方法を調べた。その備忘録記事。

  

## docker-selenium

* Selenium
  * Web アプリケーションをテストするためのフレームワーク。
  * 各種 Web ブラウザに対する操作を自動化することができる。

* docker-selenium
  * SeleniumをDocker環境で動かすためのイメージ

## 構成

![docker-selenium.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/b9f63fe8-404f-a715-2027-005227dd99d3.png)




## コード

### ディレクトリ構成

```
ルート	- 	app	----- text --- test.py 
	  |			|__ Dockerfile
	  |			|__ requirements.txt
	  |__ docker-compose.yml			
```



### docker-compose.yml

```yml
version: "3"
services:
  selenium:
    image: selenium/standalone-chrome-debug:3.2.0-actinium
    ports:
      - 4444:4444
      - 5900:5900
  app:
    build: ./app
    volumes:
      - ./app:/app
    environment:
      SELENIUM_URL: http://selenium:4444/wd/hub
    tty: true
    volumes:
      - /dev/shm:/dev/shm
```

### Dockerfile

* Python実行環境設定。依存ライブラリインストール含む。

```dockerfile
FROM python:3.7

ENV PYTHONIOENCODING utf-8

WORKDIR /app

COPY . .

RUN pip install -r requirements.txt
```

### requirements.txt

* 依存ライブラリ定義

```txt
selenium
```

### test.py

* `selenium`でGoogle検索した結果の1番目のタイトルを表示するコード。

```python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import os

if __name__ == '__main__':
    # Selenium サーバーへ接続する。
    driver = webdriver.Remote(
        command_executor=os.environ["SELENIUM_URL"],
        desired_capabilities=DesiredCapabilities.CHROME.copy()
    )
    # 任意のHTMLの要素が特定の状態になるまで待つ
    # ドライバとタイムアウト値を指定
    wait = WebDriverWait(driver, 10)
    # Googleにアクセス
    driver.get("https://google.com")
    # "selenium"で検索
    driver.find_element(By.NAME, "q").send_keys("selenium" + Keys.RETURN)
    # 1件目の検索結果を取得(描画されるまで待機)
    first_result = wait.until(
        presence_of_element_located((By.CSS_SELECTOR, "h3")))
    print(first_result.get_attribute("textContent"))

    driver.quit()

```



## 動作確認

* ビルド→起動→コンテナの中に入る。

```shell
docker-compose build --no-cache
docker-compose up -d
docker-compose exec app bash
```

* コード実行

```shell
cd test
python test.py
```

期待値：`10分で理解する Selenium - Qiita`のように検索結果が表示される。



## 参考情報

* [Dockerコンテナからseleniumを使ってスクレイピング](https://qiita.com/kei0919/items/f6f696169c92c936374c)
* [DockerでPython-Seleniumスクレイピング環境を立てた](https://qiita.com/ryoheiszk/items/93b2d52eec370c09a22e)
* [docker-seleniumを動かしてみる](https://note.com/shift_tech/n/nb5a721ab91ab)
Databricks LabsにおけるAutoML-ToolkitのPythonラッパーであるpyautoml_toolkitの環境構築手順

## 概要
Databricks Labsにて開発されているAutoML-ToolkitのPythonラッパーであるpyautoml_toolkitの環境構築手順を紹介します。
環境構築は実施できたのですがdemoのノートブックを適切に実行できなかったため、環境構築手順を残して未来に託すことにしました。


AutoML-Toolkitについては、下記で紹介されております

-   [automl-toolkit/APIDOCs.md at master · databrickslabs/automl-toolkit (github.com)](https://github.com/databrickslabs/automl-toolkit/blob/master/python/docs/APIDOCs.md)
-   [AutoML Toolkit - Deep Dive - Databricks](https://databricks.com/jp/session_na20/automl-toolkit-deep-dive)


AutoMLがどういったものであるかは下記の記事の手順により体験できます。

- [無償版Databricks Community EditionにてDatabricks AutoMLが動いた話 - Qiita](https://qiita.com/manabian/items/103b50c8aed5b232fbb2)


## 手順
### 1. 下記のコードを実行してGithubのレポジトリをクローン後、セットアップの実行。
```python
%sh
git clone https://github.com/databrickslabs/automl-toolkit.git /tmp/automl
cd /tmp/automl/python/
python setup.py bdist_wheel
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/24ab0c4d-53ae-6871-1a81-8e577d348151.png)

### 2. ビルドしたwhlファイルをDBFS上に移動。
```python
# create the directory
dbutils.fs.mkdirs("/lib/automltoolkit")

# delete files in the directory
dbutils.fs.rm("/lib/automltoolkit", True)

# whl file to dbfs
dbutils.fs.mv("file:/tmp/automl/python/dist", "/lib/automltoolkit", recurse = True)  
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/31149d27-1603-0c97-fd61-a6ed5105152a.png)

### 3. AutoML-Toolkitのライブラリをインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/689bed1d-e7da-222b-1957-9377225422d9.png)

### 4. 先ほどビルドしたwhlファイルをインストール。"Library Source"に"DBFS/ADLS"を、"Library Type"に"Python Whl"を、"File Path"に"dbfs:/lib/automltoolkit/pyautoml_toolkit-0.8.1-py3-none-any.whl"を入力。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d2c8c488-0288-669b-ff98-40e0e730050e.png)

### 5. インストールされたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7fe0dbaa-b48b-21d2-a0b1-043d46df3946.png)
無償版Databricks Community EditionにてDatabricks AutoMLが動いた話

## 概要
Databricks AutoMLが、Databricks Community Editionでも動作したことを共有します。
簡単な手順を紹介しますので、MLflowと連携されたAutoMLの素晴らしさを実感してください。

自動でMLflowにAutoMLの実行結果が保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/58507b26-9c12-ba55-0c26-d0f91f3cd3eb.png)

実行されたMLモデル構築のコードを確認することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7cbe0454-574e-0720-de6c-4280f8f14a17.png)

下記のドキュメントが公開されており、分類と回帰の参考ノートブックもあります。

-   ドキュメント
    -   [Databricks AutoML | Databricks on AWS](https://docs.databricks.com/applications/machine-learning/automl.html)
-   参考ノートブック
    -   [分類のDatabricks AutoMLノートブック](https://docs.databricks.com/_static/notebooks/machine-learning/automl-classification-example.html)
    -   [回帰のDatabricks AutoMLノートブック](https://docs.databricks.com/_static/notebooks/machine-learning/automl-regression-example.html)


## 手順
### 1. 8.3 MLのランタイムを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/13c5621b-ba2d-fbcd-439f-6d954b29c9f0.png)

### 2. 参考ノートブック（例：https://docs.databricks.com/_static/notebooks/machine-learning/automl-classification-example.html ）をdatabricksにインポート。インポート方法は、[こちら](https://qiita.com/manabian/items/534b14396077f31fed90)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4dde2706-aa56-b3b6-1027-3aff7f557324.png)

### 3. クラスターをアタッチしてコードを実行。完了までに少し時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/71ea8518-9e77-83ab-6583-e0d441c08ea1.png)

### 4. ノートブックの右の方にある"Experimet"を選択後、"View Experiment UI"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c43e3e9e-8ace-3d15-6e82-269968e6d0ae.png)

### 5. 実行されてRUNを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/58507b26-9c12-ba55-0c26-d0f91f3cd3eb.png)

### 6. Notebook列の項目を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/55cc0e24-201f-90f1-335a-53bb10aff914.png)

### 7. 実行されたコードのノートブックが開かれたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/403a70ce-63f5-2c55-4dcf-cad4dbb44261.png)
Railsの関連付けに関するエラーActiveRecord::HasManyThroughOrderErrorについて

#1.エラー文
ActiveRecord::HasManyThroughOrderError at /posts
Cannot have a has_many :through association 'Post#tags' which goes through 'Post#tag_relationships' before the through association is defined.

#.2やろうとしていること
タグ機能をつけてpost投稿にタグを一緒に投稿できるようにしたい。

#.3 原因
1.のエラー文を日本語訳してみたところ
>has_many :through association 'Post#tags'が、through associationが定義される前に、'Post#tag_relationships'を経由することはできません。

となっていたので

```ruby:post.rb
 has_many :tags, through: :tag_relationships
 has_many :tag_relationships, dependent: :destroy
```
中間テーブルと関連づけを定義するコードの順番が逆だということに気づきました。
#4.解決
```ruby:post.rb
 has_many :tag_relationships, dependent: :destroy
 has_many :tags, through: :tag_relationships
```
とすることでこのエラーは解決しました！
最後までご覧いただき本当にありがとうございました！