OmniAICreator/Qiita-1.07M huggingface dataset:
パソコンでオーディオCD再生

FreeBSDのコマンドラインでオーディオCDを直接再生でききるtcdというパッケージがありました。

パソコンでのCDの再生方法は二種類あり、一つはCDドライブが出力するアナログ出力をそのままスピーカーなどで再生する方法で、もう一つはCDのデーターを読み出して(リッピング)それをDA変換してサウンド出力から出す方法です。アプリにレベルメーターのようなものがある場合は後者で、前者ではできません。また古いPCではCPUが遅いので後者の方法はできず前者の方法で再生していました。

![tcd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/039d925d-6579-097f-3ceb-e3c029058e31.png)

小一時間くらい探しました。mplayerはリッピングしながら再生するようですが、使い方がわかりませんでした。

CDDBが効いてないみたいなので、誰かデバッグしてください。

以前はわざわざPCでCDを聴く必要は無いと思っていましたが、CDを再生できる環境が少なくなってきてちょっと貴重な気がしてきました。また圧縮してないので音も良いはずです。

後から気が付いたのですが、/usr/sbinに入っているコマンドでもできました。

```
% sudo cdcontrol -f /dev/cd0 play 
% sudo cdcontrol -f /dev/cd0 stop
```

CDドライブは定期的に動かしておくと、故障防止に良いような気がします。

# FreeDOS編

cdpというコマンドがありました。

```
C:\APPS\CDP\ENGLISH>CDP /D:FDCD0001 P
CDP: Plaing tracks 1-16.
```

FreeDOS 1.3ではドライバ名がFDCDX001に変更されていました。

~~IBMのAptivaなのですがCD-ROMドライブが不調でDVDドライブに取り替えたのですが、イヤホンジャックが無く、サウンドカードを抜いてあって、内部でも接続されていないので、実際は聞くことができません。:(~~ ValueStarのドライブがイヤホンジャックがあり、使えない状態だったので交換しました）

# PC-9801編

PC-9801のSoundBlasterにはQCDというプログラムがありました。

![IMG_20210920_103639.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/b53cdb03-f33b-d28a-040b-cbaed7adad76.jpeg)

~~Windows 3.1のアプリもあるのですが、エラーが出て使えません。~~

![CDERR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/f8167636-29fe-b50a-c14b-e02fed709581.png)

メイン -> コントロールパネル -> ドライバで [MCI] CDオーディオを追加したら使えるようになりました。

![cd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/3ab4428b-55bb-7a52-1587-34c62a9f3867.png)

上のエラーメッセージですがCDが入っていないのとドライバがインストールされていないのはまったく別の話で、一緒のダイアログで出すのはおかしいと思います。

# Debian編

cdtoolというパッケージにcdplay,cdstopというコマンドが入っています。
ssh公開鍵登録

IAMuserを作成した前提したで記載してまいります。
その後の設定を追記してまいります。

```


osを選択後に以下の設定が面画
AWSのEC2を構築
ssh port 22  myip を選択
http port 80 カスタム を選択
https port 443 カスタム を選択


#ダウンロードフォルダからsshフォルダに鍵を持っていきますが、既にあれば大丈夫です。
mkdir .ssh
chmod 700 .ssh
その後.sshフォルダへ移動させる。
mv /Users/ユーザ名/秘密鍵名.pem .ssh/

#権限指定
chmod 400 ~/.ssh/秘密鍵名.pem
ssh -i ~/.ssh/秘密鍵名.pem ユーザ名@パブリックDNS
でログインします。

sudo yum update -y


#以下のコマンドを実行してyum-cronをインストールし、パッケージの自動更新を設定します。
sudo yum install yum-cron -y

#有効化確認
sudo chkconfig --list yum-cron

#有効化
sudo chkconfig yum-cron on

#自動更新設定
sudo sed -i "s/^apply_updates.*$/apply_updates = yes/g" /etc/yum/yum-cron.conf

#起動
sudo service yum-cron start

#起動確認
sudo service yum-cron status


#現在の設定確認
date

#ローカルタイムを【Japan】に変更
sudo ln -sf /usr/share/zoneinfo/Japan /etc/localtime

#ハードウェアクロックを【Japan】に変更
sudo sed -i "s/\"UTC\"/\"Japan\"/g" /etc/sysconfig/clock

#システム再起動
sudo reboot

#現在の設定確認
date

#文字コードを日本語に変更(以下のコマンドを実行して文字コードを日本語対応に変更します。)文字コードを日本語に変更
sudo sed -i "s/en_US\.UTF-8/ja_JP\.UTF-8/g" /etc/sysconfig/i18n

#ログインユーザーを作成
sudo useradd user
sudo passwd user
sudo usermod -aG wheel user

#sudo権限の変更
以下のコマンドを実行してsudoersファイルを安全に編集します。

#sudoersファイルの編集
sudo visudo

#作成したnewuserグループをsudoコマンドがパスワード無しで実行できるように追記します。

## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL
+ %newuser      ALL=(ALL)       NOPASSWD: ALL

編集の蔡はi
編集後はesc
:wq！
で終了してください。

#ユーザーアカウント切り替え
#以下のコマンドを実行してnewuserへ切り替えます。
sudo su - newuser

#newuserのホームディレクトリに.sshディレクトリを作成
mkdir .ssh

#ファイルパーミッションを700（所有者のみ、読み取り、書き込み、削除が可能）に変更
chmod 700 .ssh

#authorized_keysを作成
touch .ssh/authorized_keys

#ファイルパーミッションを600（所有者のみ、読み取りおよび書き込みが可能）に変更
chmod 600 .ssh/authorized_keys

パブリックキーをコンピュータから取得
ssh-keygen -t rsa

#ファイルのパスを指定しますが、特にこだわりがなければエンター連打で問題ないです。
(割愛します)

#.ssh/authorized_keysを作成し追記その後、その公開鍵の情報を削除
touch .ssh/authorized_keys

#.ssh
mv id_rsa.pub .ssh/
cat id_rsa.pub >> authorized_keys
rm -rf id_rsa.pub

#既にある場合は.ssh/authorized_keysが存在する場合は、以下でいいです
cat id_rsa.pub >> authorized_keys


もしくは
cat id_rsa.pub
の中身をviエディタとかで
編集[iコマンド]
編集後は[esc]
:wq！

rm id_rsa.pub
sudo systemctl 

#authorized_keysファイルとid_rsaのパーミッションは 0600 に変更。
ケースにもよりますが、一般的には600がいいかなと。
chmod 600 authorized_keys
chmod 600 id_rsa

ssh -l [ユーザ名] -i [秘密鍵のパス] [サーバホスト名もしくはAWSのグローバルIP]

#疎通確認ができたら、デフォルトユーザーを削除します。
sudo userdel -r ec2-user

ssh -l [ユーザ名] -i [秘密鍵のパス] [サーバホスト名もしくはAWSのグローバルIP]


→いちいち打つのが面倒だなと思ったらbash化することを推奨します。
./login.sh

みたいに

※これは.sshがない前提で記載しております。
またLinuxのterminalで記述した内容です。
AWSの場合、パブリックIPのアドレスが変更される仕様であるため、エラスティックIPの設定も必要になります。
teratermでVPS等でログインする場合は、IPアドレスは変更されることがないため、ユーザー名と鍵のパスフレーズを入力し、秘密鍵を選択してログインすることになります。

以上です。
【Python】SeleniumでChrome操作時に出るエラーメッセージ「システムに接続されたデバイスが機能していません。 (0x1F)」の消し方

#はじめに
Pythonでブラウザを自動操作してスクレイピングするプログラムを組んでいたときに、ターミナルに「システムに接続されたデバイスが機能していません。 (0x1F)」というエラーメッセージが出てきて、printメソッドでターミナルに表示した結果とごっちゃになって、邪魔だな～と思っていました。
そのエラーメッセージを消すことができましたので、稚拙ながら紹介したいと思います。

#動作環境
まず私の動作環境を書いておきます。

* Windows 10 Home (64bit)
* Chrome 93.0.4577.82
* chromedriver 93.0.4577.63
* Python 3.8.1
* Selenium 3.141.0

#エラーメッセージ「 システムに接続されたデバイスが機能していません。 (0x1F) 」とは
Python にてブラウザ操作を自動化できるライブラリ Selenium を使って Chrome を起動すると VSCode のターミナルに「システムに接続されたデバイスが機能していません。 (0x1F)」というエラーメッセージが出てきます。

これは WebUSB を使用したデバイスへの接続に問題がない場合はとくにプログラムに影響はなく無視しても構わないエラーメッセージのようです。おそらく WebUSB から制御する USB機器が動作していません的な内容だと思います。

【 WebUSB 】 : Chrome などで利用できる API のこと。WebUSB を使うと Chrome などのブラウザの JavaScript から直接 USB 機器を制御することができるようです。


#エラーメッセージを消す
とくに放っておいても問題ないエラーメッセージのようですが、毎回実行時にターミナルにいちいち出てきては邪魔です。そこで Chrome のオプションを指定してあげることでそれを非表示にすることができます。

```python
from selenium import webdriver

#-------------------------------エラーメッセージを消す-------------------------------
ChromeOptions = webdriver.ChromeOptions()
ChromeOptions.add_experimental_option('excludeSwitches', ['enable-logging'])
#----------------------------------------------------------------------------------

#Chromeを起動する
driver = webdriver.Chrome(executable_path = "PATH", options=ChromeOptions)

#対象URLのページにアクセスする
url = "URL"
driver.get(url)
```

'enable-logging' とは chromedriver が Chrome にデフォルトでログ出力を有効にする起動オプションのことで、このデフォルトの起動オプションを excludeSwitches オプションで無効化します。これでエラーメッセージを非表示にすることができます。

#ちなみに
オプションに 'enable-automation' を追加することで Chrome 起動時に表示される「 Chrome は自動テストソフトウェアによって制御されています。」という警告も消すことができます。

```python
ChromeOptions.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
```


#参考ページ
* テスト実行警告を非表示、ログを出力しない : https://magenta-magenta.com/2020/11/18/post-1154/
* Edgeでの消し方 : https://miya-mitsu.com/python-0x1ferror/
* WebUSB : https://softengineerblog.com/webusb-wo-sawaru/
ABC207 C - Many Segments から学んだ

https://atcoder.jp/contests/abc207/tasks/abc207_c

![207_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/42601f78-12ad-793b-f42f-fc2e6a58e1f4.png)
![207_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/2b6767e2-213e-6a46-943c-e82cb35f6100.png)
![207_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/c45f83e1-8b07-6f6c-a262-cd2b79a4037b.png)
![207_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/2761af84-2932-2d03-cb5a-ad4d47abff64.png)

余裕じゃね？
いや、余裕で WA。

##恥ずかしい勘違い
区間を**未満** とした場合、値そのものを削った。

```yarakashita.py
for _ in range(N):
    t,l,r = map(int,input().split())
    if t == 1:
        lis.append([l,r])
    elif t == 2:
        lis.append([l,r-1])
    elif t == 3:
        lis.append([l+1,r])
    else:
        lis.append([l+1,r-1])
```

だがしかし、問題文には以下の記載がある。
i 以上 j 以下の**<font color="Red">実数</font>**からなる区間で共通部分を持つようなものは幾つありますか？
ふーむ。
実数って何！？

![zissuu-300x203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/cee49b46-a9d8-6251-55c4-26d89fc8030d.png)

なるほど、とりあえず小数も存在する領域か。
じゃあ、-1 したらダメですね、0.1 くらいかな。

```ManySegments_r0.py
N = int(input())
lis = []
for _ in range(N):
    t,l,r = map(int,input().split())
    if t == 1:
        lis.append([l,r])
    elif t == 2:
        lis.append([l,r-0.1])
    elif t == 3:
        lis.append([l+0.1,r])
    else:
        lis.append([l+0.1,r-0.1])
ans = 0
for i in range(N-1):
    for j in range(i+1,N):
        if lis[i][1] < lis[j][0] or lis[j][1] < lis[i][0]:
            continue
        else:
            ans += 1
print(ans)

```

問題文に素直に 2<= N <= 2000 と計算量が少なめの
問題は、尚の事、油断禁物のようだ。
JSON Array型ではじまるAPIレスポンスをRetrofitで受け取る方法

# この記事について
Androidアプリの個人開発をする中で、JSON Arrayで囲まれたAPIの受け取り方で少々苦戦してしまいました。同じ状態でハマってしまった方のお力になれればと思い、自分の記録も兼ねて残しておきます。

# どのようにしてハマったのか
今回使用したAPIが、こちらのフリーAPIです。
https://ghibliapi.herokuapp.com/#

スタジオジブリ作品について、映画や登場人物の情報を取得できるものなのですが、この中の映画一覧情報の取得でハマりました。。。
該当のJSONが以下になります。

```api.json
[
 {
  "id": "2baf70d1-42bb-4437-b551-e5fed5a87abe",
  "title": "Castle in the Sky",
  "original_title": "天空の城ラピュタ",
  "original_title_romanised": "Tenkū no shiro Rapyuta",
  "description": "The orphan Sheeta ...",
  "director": "Hayao Miyazaki",
  "producer": "Isao Takahata",
  "release_date": "1986",
  "running_time": "124",
  "rt_score": "95",
  "people":["https://ghibliapi.herokuapp.com/people/598f7048-74ff-41e0-92ef-87dc1ad980a9", 
  "https://ghibliapi.herokuapp.com/people/fe93adf2-2f3a-4ec4-9f68-5422f1b87c01",…],
  "species":[
    "https://ghibliapi.herokuapp.com/species/af3910a6-429f-4c74-9ad5-dfe1c4aa04f2"
  ],
  "locations":[
    "https://ghibliapi.herokuapp.com/locations/"
  ],
  "vehicles":[
    "https://ghibliapi.herokuapp.com/vehicles/"
  ],
  "url": "https://ghibliapi.herokuapp.com/films/2baf70d1-42bb-4437-b551-e5fed5a87abe"
 },
 {...},
]
```

そして、私のコードがこちら(**Retrofit**, **Moshi**, **Coroutine**を使用)
まずは、データの定義ですが、今回は必要なものだけ定義しています。

```Film.kt
data class Film(
    // 映画ID
    @Json(name = "id") val filmId: String,
    // 英語タイトル
    val title: String,
    // 日本語タイトル
    @Json(name = "original_title") val originalTitle: String,
    // 映画説明文
    val description: String,
    // 監督
    val director: String,
    // プロデューサー
    val producer: String,
    // 公開年
    @Json(name = "release_date") val releaseDate: String,
    // 評価
    @Json(name = "rt_score") val rtScore: String
)
```

次にServiceクラス(OkHttpやRetrofitのBuildは割愛します)

```ApiService.kt
interface ApiService {

    @GET("films")
    suspend fun getFilms(): Response<List<Film>>
}
```

この状態でAPIを叩いてみると...
`Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $`
「ARRAYで始めなきゃいけないのに、OBJECTで始まってるぞ！」
てことで怒られてしまいました。

ここで私は、「MoshiでのJSONのパースの仕方が悪いんじゃね？」と考え、自作のJsonAdapterを作成してみるもうまくいかない。
ぐぬぬ。。。と唸りながら、ググって出てきた「**RetrofitのCallbackで受け取ればできる**」という記事を参考に、
`Call<List<Film>>`で受け取った後に`enqueue`してみるも、できない。。。（これは自分のやり方が悪かったかも？）

色々と試している中で、その時は突然に、それもものすごく単純な方法で解決してしまったのです。

# 解決方法
解決した方法が以下です。

```ApiService.kt
interface ApiService {

    @GET("films")
    suspend fun getFilms(): Response<Array<Film>>
}
```
・・・え？　
`List`を`Array`にするだけ？
というか、こんなことでハマってたのか自分は・・・。

確かに単純に考えてJSON Arrayで始まってるんだからArrayで受け取ればいいだけですよね。なんと頭の固い自分。


#まとめ
というわけで、こんな初歩的なところで詰まってしまって情けなかったわけですが、もし考えすぎてしまって同じようにハマってしまった人がいれば、この記事が助けになれたら嬉しいです！
vueファイルが表示されない問題


既存RailsアプリにVue.jsを使用しフォロー機能を追加しました。
開発環境では無事にフォローボタンが表示されていましたが、
本番環境では表示されないという事案が発生。表示させるまでの経緯を振り返りたいと思います。

開発環境
windows10 home
Ruby 2.6.3
Ruby on Rails 5.2.6
vue.js 2.6.14

#実現したいこと
開発環境では表示される
![開発環境.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1061608/6240c457-f2b3-adb4-11b8-bafeecd4dc52.png)

# 問題点
本番環境では表示されない、、
vueを呼び出しているidの要素がElementsになく、下記のコードが表示される。

```
<!--function (e,n,r,o){return sn(t,e,n,r,o,!0)}-->
```

![本番環境.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1061608/67d16667-ad01-7e1c-4716-401df7c78932.png)

？？？？？
検索しても引っかからず、、
今まで要素が読み込まれないことがなかったので混乱しました。

## 原因究明
ファイル自体は読み込まれ、
idの要素のの中に入ると表示されない。

```_follows.html.erb
<%= javascript_pack_tag 'relationship' %>

<%# 表示できる %>
<p>test</p>

<div id="relationship">
  <%# 表示できない %>
  <p>test</p>
  <% if current_user.id != user.id %>
    <relationship-button :follower-id="<%= current_user.id %>" :followed-id="<%= @user.id %>"></relationship-button>
  <% end %>
</div>
```

# 結論

ランタイムビルドのみをしていたので、完全ビルドに切り替えることによって、
テンプレート文字列を JavaScript レンダリング関数にコンパイルする。
本番環境では完全ビルドが必要

公式ドキュメント参照
https://jp.vuejs.org/v2/guide/installation.html#%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%93%E3%83%AB%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

```webpack.config.js
module.exports = {
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
}
```
それをjsファイルにインポート

```relationship.js
import Vue from 'vue/dist/vue.esm.js'
import RelationshipButton from '../components/RelationshipButton.vue'

document.addEventListener('DOMContentLoaded', () => {
  new Vue({
    el: '#relationship',
    components: { RelationshipButton },
  })
});
```

無事に表示されることができました！！
![完全ビルド後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1061608/6f767632-f160-5bd9-883d-24457cd31033.png)


参考記事
Vue.jsの完全ビルドとランタイムビルドの違い
https://qiita.com/sansaisoba/items/58f8176f6e462fe4d591

<!--function (e,n,r,o){return sn(t,e,n,r,o,!0)}-->になった原因
https://stackoverflow.com/questions/49334815/vue-replaces-html-with-comment-when-compiling-with-webpack
kintone JavaScriptカスタマイズで画面遷移が発生してもconsole.logを追いやすくする


# 問題
kintoneの場合、画面遷移が発生する場合と発生しない場合があります。
例えば、レコードの編集をした場合は、画面遷移が発生しません。
この場合 `app.record.edit.submit` イベントなどは `console.log()` を使ったりしてデバッグすることはやりやすいです。
しかし、レコード作成においては、その後、レコード詳細画面に画面遷移が発生します。
この場合 `app.record.create.submit` や `app.record.create.submit.succeed` イベントなど、`console.log()`をつかってもあっという間にログが消えてしまう、という現象がおきます。

- ログを出したいが、保存ボタンを押した後画面遷移が起こり `console.log()` の結果が一瞬しか表示されない

```js
(function() {
  'use strict';
  kintone.events.on('app.record.create.submit', function(event) {
    console.log('レコードが作成されました。');
  });
})();
```

  ![g2M3gEsGS8lb3esmlirk1632032393-1632032477.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31957/acd3908d-6069-b75a-1e15-160b29e5d615.gif)

# 解決方法
画面遷移をしてもConsoleタブの結果を残す方法があります。
![個人設定_経費精算_-_レコードの再利用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31957/d7d554e1-1578-d3e8-beb4-7f51ec7b992e.png)
![個人設定_経費精算_-_レコードの再利用.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31957/00b19846-6733-9402-e48f-3020da0b1f7b.png)

上記の設定をすると、画面遷移してもログが残ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31957/8341aff2-e89b-1a80-b315-9b89b9f87400.png)

# 注意
今回はChromeを使用した場合です。他のブラウザを利用の方はそのブラウザのヘルプなどをご確認ください。
Vue.js v-show編

#はじめに
Vue .jsを学習し始めたのでアウトプットしていきます

#v-show
要素の表示/非表示を切り替える

:::note info
v-ifとの違い　
要素の表示・非表示を切り替えをDOMレベルで削除ではなくCSSのdisplayプロパティをON/OFF
:::

```html:index.html
<div id="app">
  <p v-show="thank">
  　Thankyou
  </p>
</div>
```

```javascript:app.js
var app = new Vue({
  el: '#app',
  data: {
  	tank: true
  }
})
```

上記のようにデータの真偽値をtrueにすれば画面に「Tankyou」が表示されます

```javascript:app.js
var app = new Vue({
  el: '#app',
  data: {
  	tank: false
  }
})
```
上記のようにデータの真偽値をfalseにすれば画面に何も表示されません。
ここで検証ツールを開いてみると

```
<body>
 <div id="app>
    <p style="display: none;"> Thankyou </p>
 </div>
```

となっておりp要素がCSSのdisplay: none;により非表示になっています。

##学び
要素を頻繁に表示/非表示を繰り返す用途の場合描画コストを抑える事ができて　v-if　よりも今回の　v-show
を使った方が良い
粒子解析した後のデータを、M水準の正規分布に分割する


以前会社で使ったリソースをそのままアップロードします

特に、**「閾値(シックスシグマなど)では、統計データを分離出来ない場合」**、
または、**「評価値が外的要因で常時変動する場合」**
こうした解析方法は役立ちます

# 対象とするデータ

紙に、微妙に直径が異なる円と潰れた円を印刷しておく
粒子解析（ブロブ解析）を使用すると、円の部分だけを抽出して、円の座標と直径(フェレ径に相当）を出してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/ec52bbe0-cec4-d7cc-778a-e826958568a3.png)

その直径を混合したデータが、Excelデータで保存され、くり抜いた画像がbitmapデータで保存される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/29a4733b-2ea4-ccae-7516-c7aa05349464.png)

緑に囲われたデータが、実際に検出したエリア。

そのCSVファイルはこうなっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/21e67fe6-d199-ca74-09ec-fcb4970ea418.png)

ここにある「実効面積」は、小さい円と大きい円が混ざったデータとなっているので、このデータからどのような分布が混在しているかを調べたい。
なお、水準数Mは固定とする

## 参考サイト

広島大学　栗田先生の教材

https://home.hiroshima-u.ac.jp/tkurita/lecture/prnn/node16.html

## アルゴリズムの整理

EMアルゴリズムで実装する

### 初期値

ガウス分布の水準iの分布の混合率、平均、分散を$ \alpha_i, \mu_i, \sigma_i^2 $とすると、その正規分布の密度関数は

```math
p_i(x) = \frac{1}{\sqrt{2 \pi \sigma_i^2}} \exp[ - \frac{(x-\mu_i)^2}{2\sigma_i^2}]
```

ここで定義された$ \alpha_i, \mu_i, \sigma_i^2 $は初期値のパラメータとして与えて置く


### Eステップ

この分布の値から、kをデータ番号とすると、
全体に対する各データに対する暫定の混合率$a_j(x_k)$、平均$u_j(x_k)$と分散$v_j(x_k)$を出すことが出来るので

```math
a_j(x_k) = \frac{p_j(x_k)}{\sum_{i=0}^{M} p_i(x_k)} \\
u_j(x_k) = a_j(x_k) \times x_k \\
v_j(x_k) = a_j(x_k) \times (x_k - \mu_j)^2
```

### Mステップ

Eステップから求めた値を使用して、$ \alpha_i, \mu_i, \sigma_i^2 $を更新する。
データ数をNとすると

```math
\alpha_i = \frac{\sum_{k=0}^{N} a_i(x_k)}{N} \\
\mu_i =  \frac{ \sum_{k=0}^{N} u_i(x_k)}{\sum_{k=0}^{N} a_i(x_k)} \\
\sigma_i^2 =  \frac{ \sum_{k=0}^{N} v_i(x_k)}{\sum_{k=0}^{N} a_i(x_k)} \\
```

なお、推定粒子数はここから出てきた結果

```math
N_i = \alpha_i \times N
```

で計算する。

## 実行結果

デモプログラムより

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281173/65fb29a3-0408-3bdb-2010-3bb12b599f89.png)



## ソースコード

展示会はVisual Studio 2013の開発環境でC#にて実施

https://github.com/belre/MixingGaussian

アルゴリズムの部分コードはこちら

https://github.com/belre/MixingGaussian/blob/main/ClipGraphTool/ClipGraphTool/StatWithLabelColor/EM1dim.cs
【競プロ典型90問】012の解説（python）

## 概要
[競プロ典型90問](https://atcoder.jp/contests/typical90)の解説記事です。
解説の画像を見ても分からない（~~理解力が足りない~~）ことが多々あったので、後で解き直した際に確認できるようまとめました。

## [問題012-Score Sum Queries](https://atcoder.jp/contests/typical90/tasks/typical90_l)

### 問題概要
白で塗られたH×Wのマス目に対して、以下の２パターンのいずれかのQ個のクエリを処理する。
1. 白いマス(r, c)を赤で塗る
2. (r1, c1), (r2, c2)の２点が与えられた時、以下の条件をどちらも満たしているか判定する
    - ２点が共に赤く塗られている
    - 2点が赤いマスを辿っていけば、連結している

### 解き方
この問題は、**Union-Find**を知っているか知らないかの問題です。
一応、簡単に説明すると、Union-Findとは、グループ分けの管理を非常に高速に実装できるデータ構造で、
ある集合のグループ分けや、同じグループに属しているかなどを高速に判定することができます。
Union-Findについての詳細は、ぜひ以下のスライドなどをご参照ください。

[![Union-Find](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425582/f0a0a4e4-8b0c-f5d4-19a8-e59cde25de88.png)](https://www.slideshare.net/chokudai/union-find-49066733)
引用元：[Union find(素集合データ構造)](https://www.slideshare.net/chokudai/union-find-49066733/1) from [Atcoder Inc.](https://www.slideshare.net/chokudai)

Union-Findを用いると、各クエリの処理は以下のように、考えられます。
1. 白いマス(r, c)を赤で塗る
→ 白いマスを赤で塗り、隣接しているマスに赤いマスがあれば、連結させる。

２. (r1, c1), (r2, c2)の２点が与えられた時、赤いマスを辿っていけば、２点が連結している
→ 同じグループに属しているかを判定する

ここまで、手順が分かったので、以下で実際に実装していきたいと思います。

![参考画像](https://raw.githubusercontent.com/E869120/kyopro_educational_90/main/editorial/012.jpg "公式解説画像")

引用元：[競プロ典型90問 Github](https://github.com/E869120/kyopro_educational_90)

### 実装

```python:answer.py

# 入力の受け取り
H, W = map(int, input().split())
Q = int(input())

# 二次元配列を一次元化する関数
def flatten(h, w):
  return h+(H+1)*w

# 赤塗りかどうかを判定する配列。配列の要素数をnに格納。
M = [False]*((H+1)*W)
n = len(M)

# UnionFindの実装例
class UnionFind():
  def __init__(self, n):
      self.n = n
      self.parents = [-1] * n

  def find(self, x):
    if self.parents[x] < 0:
      return x
    else:
      self.parents[x] = self.find(self.parents[x])
      return self.parents[x]

  def union(self, x, y):
    x = self.find(x)
    y = self.find(y)

    if x == y:
      return

    if self.parents[x] > self.parents[y]:
      x, y = y, x

    self.parents[x] += self.parents[y]
    self.parents[y] = x


  def same(self, x, y):
    return self.find(x) == self.find(y)

# 要素数nを入れて、Union Findのインスタンスを作成。
uf = UnionFind(n)


for _ in range(Q):
  q = list(map(int, input().split()))

# ti = 1の時、[r, c]を赤く塗り、隣接マスを探索、もし赤なら、グループを結合する。
  if q[0] == 1:
    r, c = q[1]-1, q[2]-1
    x = flatten(r, c)
    M[x] = True
    for i, j in [[0, 1], [0, -1], [1, 0], [-1, 0]]:
      r_dash, c_dash = r+i, c+j
      y = flatten(r_dash, c_dash)
      if 0 <= r_dash < H and 0 <= c_dash < W:
        if M[y]:
          uf.union(x, y)
# ti = 2の時、[r1, c1], [r2, c2]が共に赤なら、同じグループに属するか判定。
  else:
    x = flatten(q[1]-1, q[2]-1)
    y = flatten(q[3]-1, q[4]-1)
    if M[x] and M[y] and uf.same(x, y):
      print("Yes")
    else:
      print("No")
```

## 最後に
問題の解説を読んでも他の人のコードを見てもさっぱり分からないという方の
力に少しでもなれれば幸いです。
コードの改善点やその他、ご意見、ご質問などあれば、気軽にコメントください。

ここまでお読みいただきありがとうございました。
プログラミングスクールでの学習と今後の展望

１、私の色々
２、プログラミングを学ぼうとしたきっかけ
３、テックキャンプでの学習
４、転職活動と今後の展望


１、私の色々
・秋田県出身（1992年生まれ）
・大学では野球部に所属。法学部に在籍するも野球漬けの毎日で学業は置き去りに
・大学卒業後、ガス会社に入社する（2014年4月）
・プロ野球選手になる!という夢をもう一度追うべく、四国にあるプロ野球球団のトライアウトを受験（2014年10月）
・トライアウトに合格したので、会社を退職。もう一度プレーヤーとして奮起することに（2015年1月）
・2年間（2015,２０１６年）プレーしたものの、自身の実力に限界を感じ引退。
・2017年3月に球団からの紹介で都内の企業に入社。
・4年間、営業や販売業務に従事。2021年3月に退職。
・2021年7月~テックキャンプ105期生としてプログラミング学習をすることに←ここ急だねって思った:thinking:


２、プログラミングを学ぼうとしたきっかけ
端的に説明すると以下の３点です。
・今までやった事のない仕事をしたい!
・世の中に自分が出した結果、成果を残したい。より多くの人々の目に届けてみたい!
・今までよりも収入を増加させたい!


３、テックキャンプでの学習
2021年7月5日にテックキャンプ受講スタート！

いくつかスクールの候補がありましたが、プログラミング未経験の私が短期間でスキルを身につけられる可能性が一番高いと感じた
テックキャンプでの受講を決意しました。正直、軽い気持ちで望んだ部分もありました。
受講開始から14日間以内は全額返金保証とあるので、最悪合わなかったら・・・と当時は考えていました。
金額もかなり大きいので:sweat_smile:ただ、実際に選択は正解だったと感じています。

受講のカリキュラムに沿って正確な方向に進んでいけることが一番良いなと感じました。
後半は自走力が求められる部分が多く、自分で考えてアクションを起こしていきましたが
やはり最初からそう出来るほど私は賢くないので・・・
学習のルーティンを確立することで、1日の学習があっという間に終わる感覚が出てきました。机に向かって学習したのはほぼ中学校以来の
私が約１０週間の学習を継続してこられたのは間違いなくテックキャンプのおかげだと思いますし、今後も学習を続けることはそんなに
苦にならないと思っています。本当に良かった！

４、転職活動と今後の展望
主要の学習期間が終わり、現在は転職に向けた準備を進めています。ポートフォリオも作成し、履歴書や職務経歴書も仕上げました。
ただ、私自身就職活動をあまりした経験がなく、すごく緊張しています。
新卒入社した会社は大学の部長の紹介があり面接日の2日後には合格通知を頂きましたし、プロ野球球団にはそもそも面接とかではなく
野球の試験で合格したので（打ったり、守ったり、走ったりってやつです！）
その後も球団紹介で面接に行ったら、野球の話で盛り上がって、「で、いつから来る？」みたいな感じで決まって・・・
なので、今回が実質初めての就活の感覚です！不安が大きいけど、これも新鮮な経験なので頑張る！

ポートフォリオもまだまだ改良できる部分が多いので、転職活動中も学習を継続して、どんどんブラッシュアップしていければと思います。

今回はこの辺で！
本当は受講期間中にQiitaに知識をアウトプットすべきだったと後悔しています。が、悔やんでもしょうがないので今後は自身が知り得た知識を
ここに共有していければと思っていますので、よろしくお願いいたします。
「terser-webpack-plugin」でproduction時にだけconsole.log()などを削除する

`console.log()`などを使って、変数の値を確認しながら関数を作っていくことはよくあると思います。
でも、本番公開時にはログは消しておきたいけど、これから変更があることを考慮すると`console.log()`を残しておきたいこともあります。

「terser-webpack-plugin」を使えば、以下のような処理をwebpack側に設定できるようになります。

- `cross-env NODE_ENV=development`：`console.log()`を残す
- `cross-env NODE_ENV=staging`：`console.log()`を残す
- `cross-env NODE_ENV=production`：`console.log()`を**削除する**

## webpackの設定例
[webpackの公式サイト](https://webpack.js.org/plugins/terser-webpack-plugin/)によると、webpackのv5以降は「terser-webpack-plugin」が標準でインストールされているようです。
ただし、オプションを変更したい場合とv5未満を使っている場合は以下のようにインストールが必要になります。

```
npm install terser-webpack-plugin --save-dev
```

「webpack.config.js」での設定は以下のようになります（一部割愛）。

```js
const TerserPlugin = require('terser-webpack-plugin'); // ココ

const environment = process.env.NODE_ENV;
const isDevelopment = environment === 'development';
const isStaging = environment === 'staging';
const isProduction = environment === 'production'; // productionを判定
const environmentMode = isDevelopment ? 'development' : 'production';

module.exports = {
  mode: environmentMode,
  entry: {
    ...
  },
  output: {
    ...
  },
  module: {
    ...
  },
  plugins: [
    new TerserPlugin({
      terserOptions: {
        compress: { drop_console: isProduction ? true: false }  // ココ
      }
    }),
  ],
};
```

書式は[terserOptions](https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions)で確認できます（今回は`minimizer:`ではなく`plugins:`で指定していますが、理由は忘れました…）。

`console.log()`などを削除するかどうかは、[Compress options](https://github.com/terser/terser#compress-options)の`drop_console`で設定できます。デフォルトは`false`なので、通常は削除されないことがわかります。
設定をすべて把握できていないのですが、プロジェクトの途中で導入する場合は、設定まわりを確認しておいたほうが安全そうですね。
AttributeError: module 'typesystem' has no attribute 'SchemaDefinitions'

# 結論
requirements.txtに`typesystem==0.2.5`を追加すると解決します。
# 起きたこと
二日前にビルド成功してたのに、Cloud RunでResponderのAPIのビルドが上手くいかない。コードの変更によって上手くいってないのかと思ったので、コミット巻き戻して確認したりしたが、どうやら

```
import responder
```
でこける。


# エラー全文
```

AttributeError: module 'typesystem' has no attribute 'SchemaDefinitions'
at <module> (/usr/local/lib/python3.9/site-packages/apistar/schemas/jsonschema.py:3)
at <module> (/usr/local/lib/python3.9/site-packages/apistar/schemas/openapi.py:6)
at <module> (/usr/local/lib/python3.9/site-packages/apistar/schemas/__init__.py:1)
at <module> (/usr/local/lib/python3.9/site-packages/apistar/core.py:7)
at <module> (/usr/local/lib/python3.9/site-packages/apistar/__init__.py:11)
at <module> (/usr/local/lib/python3.9/site-packages/responder/ext/schema/__init__.py:4)
at <module> (/usr/local/lib/python3.9/site-packages/responder/api.py:25)
at <module> (/usr/local/lib/python3.9/site-packages/responder/core.py:1)
at <module> (/usr/local/lib/python3.9/site-packages/responder/__init__.py:1)
at <module> (/app/main.py:7)
```

# したこと
- 二日前にはビルド成功していたので、二日前のコードに戻してビルド→動かない
- `pip show responder` で依存関係確認したが大丈夫そう。これはどのバージョンに依存してるとかまで見れる。

# 解決策
ちゃんとエラーを読んだ。前まで上手くいってたので、前のコードに戻しても上手くいかないのは自分のせいだと思ったのがミスだった。全人類エラーを読め
`responder` は `apistar` に依存。
`pip show apistar` で依存関係を確認すると、

```
Name: apistar
Version: 0.7.2
Summary: API documentation, validation, mocking, and clients.
Home-page: https://docs.apistar.com/
Author: Tom Christie
Author-email: tom@tomchristie.com
License: BSD
Location: c:\users\yuuta\anaconda3\lib\site-packages
Requires: click, typesystem, jinja2, pyyaml, requests
Required-by: responder
```
typesystemに依存してる。
`AttributeError: module 'typesystem' has no attribute 'SchemaDefinitions'`
といわれているので、実際のコードをGithubで見に行ってみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513355/8ac160ae-c164-0693-ebf2-77e5bcc468f3.png)
（この写真は記事投稿時の写真。見に行った当時は2days ago に変更が入っていた）
この時点でかなり嫌な予感
実際のcommitを眺める。
https://github.com/encode/typesystem/commit/851b60f3e08ae37b6548cc42e0e5407934f0a0d9
31ファイル変更は多いので、`SchemaDefinitions`で検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513355/a4d2de1d-a679-c162-1eaa-917a9bc4dd52.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513355/6fac1055-4775-d123-8200-2002f0ea58a1.png)
「あっ...名前、変えられたんですね」

このcommitがVersion 0.3.0なので、`requirements.txt`の中身に`typesystem==0.2.5`を追加し、解決。
apistarが対応するまでは、これで対応できるはず。ちゃんと`pip freeze`でバージョンを管理すればローカルで動いてたらCloud Run上でも動いたはずなのに、余計な時間を過ごしました。
ローカルリポジトリの作成

#目次
-　目次
-　ローカルリポジトリを作成する



#ローカルリポジトリを作成する
※gitのインストール済みを前提とする。

##ローカルリポジトリの作成

```
git init
```

上記コマンドをターミナルに記入し、実行。

結果↓

```
Initialized empty Git repository in /Users/ユーザー名/作業ディレクトリ/.git/
```

カレントディレクトリに.gitディレクトリが作成されます。

確認してみましょう。

```
$ ls -la
total 0
drwxr-xr-x  3 inumaru  staff   96  9 19 13:59 .
drwxr-xr-x  5 inumaru  staff  160  9 19 13:58 ..
drwxr-xr-x  9 inumaru  staff  288  9 19 13:59 .git
```

この.gitの中に入っているものの中にローカルリポジトリが入っています。

確認してみましょう。

```
cd .git
```
```
$ ls -la
total 24
drwxr-xr-x   9 inumaru  staff  288  9 19 13:59 .
drwxr-xr-x   3 inumaru  staff   96  9 19 13:59 ..
-rw-r--r--   1 inumaru  staff   23  9 19 13:59 HEAD
-rw-r--r--   1 inumaru  staff  137  9 19 13:59 config
-rw-r--r--   1 inumaru  staff   73  9 19 13:59 description
drwxr-xr-x  15 inumaru  staff  480  9 19 13:59 hooks
drwxr-xr-x   3 inumaru  staff   96  9 19 13:59 info
drwxr-xr-x   4 inumaru  staff  128  9 19 13:59 objects
drwxr-xr-x   4 inumaru  staff  128  9 19 13:59 refs
```
objectsというディレクトリがありますが、これがリポジトリ本体になります。
git commitしたものがこの中に入っていきます。


以上、git init コマンドをすると、.gitディレクトリが作成され、その中でgitの管理がされていくということでした。
LGWAN とは

## 勉強前イメージ

WANは広範囲のネットワークですよね・・？
LGってなんぞ？
モニターとか売ってるメーカーしか出てこない

## 調査

### LGWANとは

Local Government Wide Area Network の略で、総合行政ネットワークと呼びます。
都道府県・市町村の自治体のネットワーク(庁内LAN)を相互に接続する、高度なセキュリティを維持した行政のネットワークのことで、です。
パブリックネットワークとは切り離された閉域ネットワークとして構築されています。
J-LIS(地方公共団体情報システム機構)が運営しています。

### LGWANのセキュリティ

- firewallの設置

外部からの不正な侵入を防ぎます

- 暗号化

暗号化を行い、データが盗まれたとしても内容までは読み取れないようにします。

- IDSの設置

自治体間の直接通信を制御し、
全ての通信に[侵入検知機能(IDS)](https://qiita.com/miyuki_samitani/items/b4676484119a89c00467) を導入。
不正アクセスされた際の検知を行います。

- SOCの設置

SOC(Security Operation Center)を設置して24時間365日ネットワークを監視、検出、分析を行う。

- 公開鍵認証による認証

公開鍵認証によってなりすましなどを防ぎます。


## 勉強後イメージ

行政、地方自治体は特別なネットワークがあってそれを通じてやりとりしているのかー
なんかあってパブリックネットワークは使わんねんやろなーとは思ってたけど、初めて知った。
あとドメインのlgって地方自治体のことか・・・
調べてみたら東京都のドメインもlg.jpだった

![1東京都公式ホームページ — Mozilla Firefox 2021-09-19 14.20.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/d33863da-9cf6-bb2f-137a-0fd9b4c6dfcf.png)


## 参考

- [LGWAN について](https://www.j-lis.go.jp/lgwan/about/cms_15039.html)
- [総合行政ネットワークLGWANとは](https://www.soliton.co.jp/column/filezens/local-government/lgwan.html)
pandas.read_sql()の中にSQL文を書くと"explicit type casts"というエラーが出る

#注(2021/09/20 25:40)
コメントにてSQLインジェクション対策についてご指摘をいただき、
それに従って内容を追記しました（本文下部の追記をご確認願います。）

PostgreSQLからデータを取得する際、
pandas.read_sql()の中にSQL文を書くと"explicit type casts"というエラーが出る現象に悩まされていました。

```python:エラー発生.py
import pandas as pd
from sqlalchemy import create_engine

connection_config ={
    'user':'workuser',
    'password':'********',
    'host':'localhost',
    'port':'5432',
    'database':'database_test'
}


engine = create_engine(f'postgresql://{user}:{password}@{host}:{port}/{database}')

df_a = pd.read_csv("sample.csv")
sample_id = df_a["id"].iloc[-1]
#00000000と仮定

df_b = pd.read_sql(f'SELECT * FROM sample_table WHERE id = {sample_id}', con=engine)

```

```エラー内容
LINE 1: SELECT * FROM sample_table WHERE id = 00000000

HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. [SQL: 'SELECT * FROM sample_table WHERE id = 00000000']
```

このエラーに対して、次のstackoverflowの記事を元に修正したところ、
解決しました。

[Python Dataset module error: You might need to add explicit type casts]
(https://stackoverflow.com/questions/31829269/python-dataset-module-error-you-might-need-to-add-explicit-type-casts/)

次のようにSQL文を二重引用符で囲い、{sample_id}を一重引用符で囲うとエラーが消えました。

```python:エラー解消（該当部分のみ）.py

df_b = pd.read_sql(f"SELECT * FROM sample_table WHERE id = '{sample_id}'", con=engine)

```

#追記
次のURLによればpd.read_sql()の（）内にSQL文を書くと
SQLインジェクション対策ができないとのことです。

[Python pandas.read_sql SQL injection safe?](https://www.reddit.com/r/Python/comments/8glw9h/python_pandasread_sql_sql_injection_safe)

こちらの内容に従い、内容を追記いたします。

```python:エラー解消（SQLインジェクション対策追加）.py
import pandas as pd
import psycopg2

connection_config ={
    'user':'workuser',
    'password':'********',
    'host':'localhost',
    'port':'5432',
    'database':'database_test'
}

url = 'postgresql://{user}:{password}@{host}:{port}/{database}'.format(**connection_config)

df_a = pd.read_csv("sample.csv")
sample_id = df_a["id"].iloc[-1]
#00000000と仮定

try:
    conn = psycopg2.connect(url)
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM experiment WHERE id = %s;" , (sample_id,))
        result = cursor.fetchall()
        df_b = pd.DataFrame(result)

except Exception as e:
    print(e)
finally:
    conn.close()

```
【EC2】Windows Server 2019でChromeをインストールする方法

# はじめに

[以前の記事](https://qiita.com/onishi_820/items/85ddc95869109dad53ec)で、EC2を使いWindowsサーバを構築しました。

今どきIEを使うのもナンセンスなので、Google　Chromeをインストール使用としたのですが、
ファイルをダウンロードできませんと表示される・・・。

今回はそちらを解決しましたので、
その手順について記載していこうと思います。

## インストールまでの流れ

サーバにログインすると、左上に２つのショートカットファイルがあると思います。
その内の１つ、「**EC2 Microsoft Windows Guide**」を開きます。

恐らくこんなのが表示されると思います。
![スクリーンショット 2021-09-19 13.48.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/d7ee707e-372d-94ca-3b04-56c8c5f07321.jpeg)

イライラせずにIEを閉じてやりましょう。

左下のスタートメニューから、サーバーマネージャーを起動します。
![スクリーンショット 2021-09-19 13.49.27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/48d2b8ff-9ba8-04fb-406f-a316bdd723d5.jpeg)

左ペインから、「ローカルサーバ」を選択し、
「IEセキュリティ強化の構成」の**有効**の箇所をクリック。
![スクリーンショット 2021-09-19 13.50.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/bf20f6ec-670d-56bb-97ee-958cb14fb195.jpeg)

全て**オフ**にし、OKをクリックします。

サーバーマネージャーは閉じて、**EC2 Microsoft Windows Guide**を開きます。

`What is Amazon EC2?`と表示された、AWSのページが表示されましたかね？

表示されたことを確認したら、URLの欄に以下のURLを入力して開きます。
https://www.google.com/intl/ja_jp/chrome/

Chromeのダウンロードページに飛びますので、ダウンロードをクリックしましょう。
![スクリーンショット 2021-09-19 13.56.28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/5ebc692c-a3b7-722b-e747-e83a75d010e4.jpeg)

すると画像のものが表示されますので、**実行**をクリックします。

保存に枠をつけてしまいましたが、実行でも大丈夫です。
もちろん、保存してからフォルダを開き、実行しても構いません。
![スクリーンショット 2021-09-19 13.56.40.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/cd3fa869-1c8a-db5a-7525-88226c1b91f4.jpeg)

Chromeのショートカットが、デスクトップに表示されているはずです。
![スクリーンショット 2021-09-19 14.00.39.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/dd950ab7-d4a7-59d4-3f1b-1fe9a9af06cd.jpeg)

#さいごに

これでChromeを利用することができると思いますので、
さっさとIEから乗り換えてChromeを利用しましょう！！

最後までご覧いただきありがとうございました。
踏み台サーバー経由でのSSHポートフォワーディング

踏み台サーバー経由、かつ、送信元PC上で設定なしに目標のコンテナにSSH接続させたい時の検証メモ。

```dockerfile:Dockerfile
# CentOS7を使用
FROM centos:centos7

# OpenSSH サーバ/クライアントをインストールする
RUN yum -y install openssh-server openssh-client

# iprouteをインストールする
RUN yum -y install iproute

# sshでログインできるようにする 
RUN sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config

# root のパスワードを 設定
RUN echo 'root:rootpass' | chpasswd

# 使わないにしてもここに公開鍵を登録しておかないとログインできない 
RUN ssh-keygen -t rsa -N "" -f /etc/ssh/ssh_host_rsa_key

# sshd の使うポートを公開する
EXPOSE 22

# sshd を起動する
CMD ["/usr/sbin/sshd", "-D"]
```

```bash
# イメージ作成
$ docker build -t ssh-test .

# 接続したいコンテナ作成（ip addrコマンドで 172.17.0.2 を確認）
$ docker run -d --hostname target-container --name target-container ssh-test

# 踏み台コンテナ作成（PCのローカルポート6666から踏み台コンテナの7777にアクセスする形にする）
$ docker run -d -p 6666:7777 --hostname bastion --name bastion ssh-test

# 踏み台コンテナに入ってポートフォワードコマンドを実行（ip addrコマンドで 172.17.0.4 を確認）
$ docker exec -it bastion2 /bin/bash

# 踏み台コンテナで実行
$ ssh -L 7777:172.17.0.2:22 root@localhost -fNg

# PCから疎通確認
$ ssh -p 6666 root@localhost
<< OUTPUT
root@localhost's password: 
Last login: Fri Sep 17 04:59:26 2021 from 172.17.0.4
[root@target-container ~]#
OUTPUT
```
行列みたいな標準入力を1行で変数に代入する方法【Python】

### 概要
コーディングテストやpaizaのスキルチェックでおなじみの行列っぽい標準入力。

```
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
```

このような標準入力はPythonのリスト内包表記を使うことで、1行のコードで変数に代入できる。
一般的に使えるように、ここではH行W列の標準入力とする（上の場合は4行4列）。

```
board = [[int(i) for i in input().split()] for _ in range(H)]
```

### 解説
1. まず`input()`で受け取った1行目の文字列`'1 2 3 4'`に対して、`split()`で空白区切りのリストにします。これで`['1', '2', '3', '4']`となります。

1. このままでは文字列なので、足し算をしても`'1' + '2' = '12'`みたいな事になってしまいます。そこで、配列`input().split()`(= ['1', '2', '3', '4'])に対して、要素を取り出す`for i in (配列)`で一つずつ要素を取り出しては`int(i)`として文字列から整数値に変換します。これで`[1, 2, 3, 4]`になりました！

1. あとはこれを行列の行数、つまり標準入力の回数繰り返します。繰り返すときの変数は何でもいいので、ここでは`_`としています。`(1と2の処理) for _ in range(H)`

1. 忘れずに両端を`[]`で囲ったら完成です！お疲れさまでしたm(_ _)m

### 実行例

```
（標準入力）
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

（コード）
board = [[int(i) for i in input().split()] for _ in range(4)]
print(board)
print(board[0])
print(board[3][3])

（結果）
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
[1, 2, 3, 4]
16
17
```
RSpecモデルのテスト　メモ

```models/ostomy.rb
class Ostomy < ApplicationRecord
  #患者さんのストーマの記録
  has_one_attached :image
  belongs_to :patient
  has_many :comments
  has_many :favorites
  #has_many :so_good, dependent: :destroy
  validates :color, {presence: true}
  validates :edema, {presence: true}
  validates :skin, {presence: true}

#ストマの色
  enum color: {"pink":0,"red": 1,"brown": 2,"black": 3,"other":4}, _prefix:true
#皮膚の色
  enum skin: {"same":0,"red":1,"brown":2,"black":3,"white":4,"blister":5}, _prefix: true
#むくみ
  enum edema: {"normal":0,"edema":1}, _prefix: true

  def favorited_by?(staff)
    favorites.where(staff_id: staff.id).exists?
  end
end

```

https://qiita.com/mightysosuke/items/8fc12d43ae5e183a8c74

```factorys/ostomy.rb
FactoryBot.define do
  #患者さんのストーマの記録
  factory :ostomy do
     color { "pink" }　　　#edemaはなにかしら入れればOK
     edema { "normal" }
     skin { "same" }
  
     association :patient #belongs_toは設定する
    
    #edemaは次のように書いくと何度も書かずに済む
    # https://qiita.com/mightysosuke/items/8fc12d43ae5e183a8c74
    Ostomy.colors.keys.each do |color|
      trait :"#{color}" do
        status { color }
      end
    end
    Ostomy.skins.keys.each do |skin|
      trait :"#{skin}" do
        status { skin }
      end
    end
    Ostomy.edemas.keys.each do |edema|
      trait :"#{edema}" do
        status { edema }
      end
    end
  end
end

```

https://zenn.dev/yukihaga/articles/21a871020c7b6c


```models/ostomy_spec.rb
require 'rails_helper'

RSpec.describe Record, type: :model do
  #pending "add some examples to (or delete) #{__FILE__}"
   before do  
    @patient = build(:patient)
    @record = build(:record,patient: @patient)
   end

    describe 'バリテーション' do
        it 'ABCd設定されていれば、OK'do
         expect(@record.valid?).to eq(true)
       end

       it 'adjacentが空はNG' do
          record_without_adjacent = build(:record, adjacent: nil)
          expect(record_without_adjacent).to be_invalid
       end

       it 'barrierが空はNG' do
           record_without_barrier = build(:record, barrier: nil)
           expect(record_without_barrier).to be_invalid

       end

       it 'circumscribingが空はNG' do
          record_without_circumscribing = build(:record, circumscribing: nil)
          expect(record_without_circumscribing).to be_invalid
       end

       it 'discolorが空はNG' do
          record_without_discolor = build(:record, discolor: nil)
          expect(record_without_discolor).to be_invalid
       end
    end


    describe 'アソシエーションのテスト' do
      context 'Patientモデルとの関係' do
        it 'belongs_toとなっている' do
          expect(Record.reflect_on_association(:patient).macro).to eq :belongs_to
        end
      end
    end
end

```
【エラー対処】(Wordpress) body_classテンプレートタグ付加によるCSSの崩れの対処

<h1>前書き</h1>
静的サイトをWordpress化する際に一部のCSSが崩れているのを発見、、、
何が原因なのか調べていったらbody_classテンプレートタグによって生成されたクラスに原因があったことが判明。
修正前↓
![スクリーンショット 2021-09-19 13.25.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1750261/d8c2d2a2-44db-9e2f-8290-781b0c3f03be.png)
修正後↓
![スクリーンショット 2021-09-19 13.25.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1750261/f7866b6f-b6e5-b506-1281-bbda6e39d0e1.png)


<h1>解決策</h1>
フックを活用してblogタグが生成されないようにしました。
こちらを参考にさせていただきました。
<a href="https://techmemo.biz/wordpress/body_class_addclass/">WordPressのbody_class()に独自のクラスを追加したり既存のクラスを削除する方法</a>


```
function del_body_class($classes) {
  foreach ($classes as $key => $value) {
    if ($value == 'blog') {
      unset($classes[$key]);
      // $valueがblogなら最後の要素への参照を解除します
    }
  }
  return $classes;
}
add_filter('body_class', 'del_body_class');
```
ずばりこのままです。
CSSにはblogのclass名は付けていないのですがなぜこの部分だけが崩れてしまったのかは疑問です。。
【初心者向け】Google検索方法

#はじめに
今回は技術力ではなく、検索力を上げるための方法を紹介します。
既に知っている人が多いかとは思いますが、知らない人もいると思うので、ご参考までに。

#使える検索方法
①キーワードを「"」で囲んで、キーワードが完全一致するサイトを検索する。
`例) "Google検索"`

②「-」を使って、あるキーワードを除外する。
`例) iphone -13`

③「OR」を使って、どちらかのキーワードが含まれるサイトを検索する。
`例) PHP OR Ruby`

④「intitle:」を使って、サイトのタイトル名で検索する（本文は含まない）。
`例) intitle:PHP`

⑤「intext:」を使ってサイトの本文で検索する。
`例) intext:PHP`

⑥「site:」を使って特定のサイトの中から検索する。
`例) site:yahoo.co.jp iphone`

⑦「ツール」をクリックして、更新日で絞りをかける。

#おわりに
ほかにもいろいろな検索方法がありますが、使う頻度の高そうなものをピックアップして紹介しています。
ほかにどんな方法があるか気になる方は是非ググってみてください。
"ソ能表"問題

具体的には、Shift_JIS文字コードで、2バイト目に0x5cを持つ文字の問題の事なんだけど。。。

詳しくは、下記に書いてくれている。
http://www5f.biglobe.ne.jp/~fuku-labo/library/program/common/1/004.htm

組込み開発、やってた頃、原因不明のビルドエラーが起きてて、
突き詰めると、コメント行の最後が、"能"だったということがあった。

下記みたいなコードだった。

```
// ここで〇〇の判定が可能
                     ↑↑↑コレ。コメントが"能"で終わっている。
public void checkXxxx() {
}
```

あまり工数もない中、無駄にすごい時間を費やして、冷や汗だったのを覚えている。

それ以来、コメントはなるべく、ブロックコメント(/**/) を使うようにしている。
numpyの二次元配列の解像度を下げる

# やること
二次元配列の解像度を下げる。
## 例

```python
>>> a=np.arange(24).reshape((4,6))
>>> a
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
```
これを2*2ごとに平均値を取った以下のようにしたい。

```python
>>> b = rebin(a, (2, 3))
>>> b
array([[  3.5,   5.5,  7.5],
       [ 15.5, 17.5,  19.5]])
```


## 回答
reshapeとmeanで頑張る。

```python
def rebin(a, shape):
    sh = shape[0],a.shape[0]//shape[0],shape[1],a.shape[1]//shape[1]
    return a.reshape(sh).mean(-1).mean(1)
```

具体的な数字で書くと以下

```python
>>> import numpy as np
>>> a = np.arange(24).reshape((4,6))
>>> a
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
>>> a.reshape((2,a.shape[0]//2,3,-1)).mean(axis=3).mean(1)
array([[  3.5,   5.5,   7.5],
       [ 15.5,  17.5,  19.5]])
```


多次元バージョンは以下

```python
def bin_ndarray(ndarray, new_shape, operation='sum'):
    """
    Bins an ndarray in all axes based on the target shape, by summing or
        averaging.

    Number of output dimensions must match number of input dimensions and 
        new axes must divide old ones.

    Example
    -------
    >>> m = np.arange(0,100,1).reshape((10,10))
    >>> n = bin_ndarray(m, new_shape=(5,5), operation='sum')
    >>> print(n)

    [[ 22  30  38  46  54]
     [102 110 118 126 134]
     [182 190 198 206 214]
     [262 270 278 286 294]
     [342 350 358 366 374]]

    """
    operation = operation.lower()
    if not operation in ['sum', 'mean']:
        raise ValueError("Operation not supported.")
    if ndarray.ndim != len(new_shape):
        raise ValueError("Shape mismatch: {} -> {}".format(ndarray.shape,
                                                           new_shape))
    compression_pairs = [(d, c//d) for d,c in zip(new_shape,
                                                  ndarray.shape)]
    flattened = [l for p in compression_pairs for l in p]
    ndarray = ndarray.reshape(flattened)
    for i in range(len(new_shape)):
        op = getattr(ndarray, operation)
        ndarray = op(-1*(i+1))
    return ndarray
```

## 参考
https://stackoverflow.com/questions/8090229/resize-with-averaging-or-rebin-a-numpy-2d-array
QEMU Raspberry Pi のmini uartの受信割り込みが入らないのでデバッグしてみた

QEMU 4.2 で動いていた Raspberry Piのmini uartの受信割り込みがQEMU 6.1.0だと動かないのでデバッグしてみました。

# 問題の現象

以前の動作はドキュメントの実行例によると

```
$ make run
qemu-system-aarch64 -M raspi3 -m 128 -serial null -serial mon:stdio -nographic -kernel kernel.elf
qemu exit: Ctrl-A x / qemu monitor: Ctrl-A c
int02
a c_irq_handler
b c_irq_handler
c c_irq_handler
```

のようにキーボードから一文字入力毎に割り込みが1回発生した。

このプログラムをQEMU 6.1.0を動かすと

```
$ qemu-system-aarch64 -M raspi3 -m 1024 -serial null -serial mon:stdio -nographic -kernel kernel.elf
qemu exit: Ctrl-A x / qemu monitor: Ctrl-A c
int02
 c_irq_handler
 c_irq_handler
 c_irq_handler
 c_irq_handler
 c_irq_handler
 c_irq_handler
```

のようにキーを入力してないのに割り込みが入り続ける。

# デバッグ

QEMUのソースを見てみます。
```hw/char/bcm2835_aux.c```
が該当のファイルです。

割り込みを生成している部分のコード

```
static void bcm2835_aux_update(BCM2835AuxState *s)
{
    /* signal an interrupt if either:
     * 1. rx interrupt is enabled and we have a non-empty rx fifo, or
     * 2. the tx interrupt is enabled (since we instantly drain the tx fifo)
     */
    s->iir = 0;
    if ((s->ier & RX_INT) && s->read_count != 0) {
        s->iir |= RX_INT;
    }
    if (s->ier & TX_INT) {
        s->iir |= TX_INT;
    }
    qemu_set_irq(s->irq, s->iir != 0);
}
```

これをみたら原因らしきものが分かったかもです。送信割り込みがイネーブルだと常に割り込みが入るみたいです。

あれ、受信割り込みしか有効にしてないはずだけどなぁと思って確認したところ、datasheetの送信割り込み有効ビットと受信割り込み有効ビットが間違っていた。

https://datasheets.raspberrypi.org/bcm2835/bcm2835-peripherals.pdf
だとbit1がEnable receive interruptでEnable transmit interruptです。

https://elinux.org/BCM2835_datasheet_errata
にBits 1:0 are swaped. bit 0 is receive interrupt and bit 1 is transmit.
の記載があります。

ということで以下の変更で解決しました。

```
     /* enable UART RX interrupt. */
     *AUX_ENABLES = 1;
     //*AUX_MU_IIR = 4;
-    *AUX_MU_IER = 2;
+    *AUX_MU_IER = 1;
```

変更をpushしときました。

*  https://github.com/eggman/raspberrypi/commit/b4f405a197b22e6ce99917c89a9fa2e3365060dd

以上です。
【Ruby】2つの配列で、和集合・積集合・差集合を取得したい。

# 概要
Rubyの操作の学習として、「和集合・積集合・差集合」の取得方法をまとめました。

# 和集合（A∪B）
![和集合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/7698037c-916c-4145-e1b1-d02669a01b60.png)

2つの配列の和集合をとるには`Aeeay#|`メソッドを使用します。

```ruby
# 和集合（A∪B）
array1 = [1,2,3]
array2 = [4,5,6]
array3 = [2,3,4]
array4 = ["A","B","C"]
array5 = ["B","B","C","D"]

array_result1 = array1 | array2 #=> [1, 2, 3, 4, 5, 6]
array_result2 = array1 | array3 #=> [1, 2, 3, 4]
array_result3 = array4 | array5 #=> ["A", "B", "C", "D"]

p array_result1
p array_result2
p array_result3
```

# 積集合（A∩B）
![積集合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/c27d0969-8256-d0ac-87b1-6ca53bd0f560.png)

2つの配列の積集合をとるには`Aeeay#&`メソッドを使用します。

```ruby
# 積集合（A∩B）
array1 = [1,2,3]
array2 = [4,5,6]
array3 = [2,3,4]
array4 = ["A","B","C"]
array5 = ["B","B","C","D"]

array_result1 = array1 & array2 #=> []
array_result2 = array1 & array3 #=> [2, 3]
array_result3 = array4 & array5 #=> ["B", "C"]

p array_result1
p array_result2
p array_result3
```

# 差集合（A＼B）
![差集合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/308a5ef7-19d0-da0e-e7f3-a649fe69624e.png)

2つの配列の差集合をとるには`Aeeay#-`メソッドを使用します。

```ruby
# 差集合（A＼B）
array1 = [1,2,3]
array2 = [4,5,6]
array3 = [2,3,4]
array4 = ["A","B","C"]
array5 = ["B","B","C","D"]

array_result1 = array1 - array2 #=> [1, 2, 3]
array_result2 = array1 - array3 #=> [1]
array_result3 = array4 - array5 #=> ["A"]

p array_result1
p array_result2
p array_result3
```

# 参考
◇Ruby 3.0.0 リファレンスマニュアル Arrayクラス
https://docs.ruby-lang.org/ja/latest/class/Array.html

◇和集合
https://ja.wikipedia.org/wiki/%E5%92%8C%E9%9B%86%E5%90%88

◇差集合
https://ja.wikipedia.org/wiki/%E5%B7%AE%E9%9B%86%E5%90%88

◇共通部分(積集合)
https://ja.wikipedia.org/wiki/%E5%85%B1%E9%80%9A%E9%83%A8%E5%88%86_(%E6%95%B0%E5%AD%A6)
UIDatePickerView 当日から１週間後までしか選択できない様にする

# 今回の内容

<img width="150" alt="8071FE00-E95E-4394-9CFB-7EBB49FC77E5_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/2f22d3ab-4266-fc3c-94e8-bb9b09b2031c.jpeg">

#コードと簡単解説

* `.datePickerMode`では表示する内容を設定できます。(今回は年月日だけ表示)

* `.date`では、表示された時の選択状態を設定できます。

* `.minimumDate`では、選択できる最小の値を設定します。（今回は当日を設定）

* `.maximumDate`では、選択できる最大の値を設定します。（今回は当日から1週間後を設定）

```Swift:
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let datePickerView = {() -> UIDatePicker in
            
            let datePicker = UIDatePicker()
            datePicker.center = view.center
            datePicker.backgroundColor = .tertiarySystemGroupedBackground
            datePicker.datePickerMode = .date
            datePicker.locale = Locale(identifier: "ja_JP")           
            datePicker.date = Date()           
            datePicker.minimumDate = Date()            
            datePicker.maximumDate = Date(timeInterval: 60 * 60 * 24 * 7, since: Date())
            
            return datePicker
        }()

        view.addSubview(datePickerView)     
    }

}
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
[Android]カメラで利用可能なFPSを判定する

## これはなに
Android のカメラで、対応しているFPSを判定するためのコードメモ
解像度XXXに対する最高FPSを返すようなAPIがあれば便利なんですが、見つからなかったので、特定の解像度とFPSの組み合わせで利用可能かどうか判定しています。

あまり自信はないので、おかしいところは指摘いただけたらと思います。



## コード

```
    var mCameraId: Int? = null

    private fun findCameraId() {
        var manager = activity?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
        var camerIds: Array<out String> = manager.getCameraIdList()
        for (cameraId in camerIds) {
            if (checkCameraFPS(cameraId.toInt(),
                    CamcorderProfile.QUALITY_1080P, // 利用可能なFPSはカメラの設定で異なる。ここでは1080pに対しての60FPSが利用可能か確認している
                    60) 
            ) {
                mCameraId = cameraId.toInt()
                break
            }
        }
    }

    // 特定の解像度とFPSの組み合わせで利用可能かどうか判定
    private fun checkCameraFPS(camaraId: Int, quality: Int, targetFPS: Int): Boolean {
        val profile = CamcorderProfile.get(camaraId, quality)
        val videoFrameRate = profile.videoFrameRate
        return videoFrameRate >= targetFPS
    }
```


以上です

参考: 
https://stackoverflow.com/questions/36904707/how-to-know-maximum-supported-fps-by-android-device-on-api-level
https://developer.android.com/reference/android/media/CamcorderProfile.html
[Ruby] AtCoder過去問 C - Count Order

##はじめに
AtCoder過去問のC問題を解いてみました。
よろしくお願いします。

問題はこちらから確認してください↓

https://atcoder.jp/contests/abc150/tasks/abc150_c

##C - Count Order
とりあえず入力を受け取ります。

```ruby
n = gets.to_i
p_ary = gets.split.map(&:to_i)
q_ary = gets.split.map(&:to_i) 
```

さて、どうしたもんかと、組み合わせの配列をどうやって作ろうかめちゃめちゃ悩みました。
しかし、しっかりrubyには便利なメソッドが準備されていました。
それがpermutationメソッドです。

配列の組み合わせを返してくれます。```array.permutation(n).to_a```という形で記述すると配列の中にそれぞれのパターンが配列として出来上がります。
例```[[1, 2, 3], [1, 3, 2], [2, 1, 3]...]```
こんな感じです。

引数に対象とする数を指定します。今回の場合は全てなのでnでオッケーです。

ここで気をつけたいことで、問題では辞書順にしなければなりません。
例えば、入力例1のpをpermutationにかけても全てのパターンを返してくれますが、辞書順になりません。

私は偶然気付いたのですが、これ、sortで昇順に並び替えてからpermutationをかけると辞書順に並んで返ってくるのです。

ここまでをコードにおこしてみます。

```ruby
n = gets.to_i
p_ary = gets.split.map(&:to_i)
q_ary = gets.split.map(&:to_i) 

p_permu = p_ary.sort.permutation(n).to_a

q_permu = p_ary.sort.permutation(n).to_a
```

これでpとqそれぞれの全てのパターンが入った配列が完成しました。
p_permuとq_permuと名前にしています。相変わらず命名下手くそです。

さて、次はp_aryとq_aryが辞書順の何番目にあるかを知りたいです。
つまりp_permuとq_permuの何番目かわかれば良いです。

indexメソッドを使いましょう。これめちゃめちゃ便利。
indexはインデックス番号で返してくるので+1してあげます。

```ruby
n = gets.to_i
p_ary = gets.split.map(&:to_i)
q_ary = gets.split.map(&:to_i) 

p_permu = p_ary.sort.permutation(n).to_a

q_permu = p_ary.sort.permutation(n).to_a

a = p_permu.index(p_ary) + 1

b = q_permu.index(q_ary) + 1
```

あとはa-bをして、absメソッドで絶対値にして出力で完成です。

```ruby
n = gets.to_i
p_ary = gets.split.map(&:to_i)
q_ary = gets.split.map(&:to_i) 

p_permu = p_ary.sort.permutation(n).to_a

q_permu = p_ary.sort.permutation(n).to_a

a = p_permu.index(p_ary) + 1

b = q_permu.index(q_ary) + 1

puts (a-b).abs
```