OmniAICreator/Qiita-1.07M huggingface dataset:
中国版Qiita――「HacPai」の話

# きっかけ

先日、GitHubで中日対訳について探し、この[**ページ**](https://github.com/kazuhiromishina/SuspiciousJapanese)を見てからQiitaに参りました。一見すると、「Hello hackers !」の挨拶とGitHubのロゴが気づいて、国内の「HacPai」に似てるじゃないかと思った。

Qiitaで文章を読んで、機能を理解し、両者ある程度の機能や理念が似てると判明した。故に、中国版Qiita――「HacPai」を紹介し、日本のプログラマさんのコメントを聞きたい。

# 「HacPai」の紹介

中国人エンジニア向けのコミュニティ「[**HacPai**](https://hacpai.com)」は、Javaによって構築、個人開発者[**D**](https://hacpai.com/member/88250)が2012年に創立し、もともと[**B3log**](https://github.com/b3log/)（「Bulletin Board Blog」の略）のための交流の場、今オープンソースな理念で運営している。オープンソースなコード、GitHubのプロジェクト名は[**Symphony**](https://github.com/b3log/symphony)。

「HacPai」の名は、「Hackers and Painters: Big Ideas from the Computer Age」という本の単語「**Hac**kers」と「**Pai**nters」の前三英文字で合わせたもん。5万会員の中、「Hackers」タグを選んだプログラマは9割、他のユーザーは「Painters」タグ付けのデザイナーです。GitHubアカウントでログイン可能、会員様が働いたデータはほとんど全て公開しているまま、この[**ページ**](https://hacpai.com/article/1566621201255)がそのデータの全貌を集めた。

「HacPai」のソーシャルネットワークで、Qiitaのように自分が書いた記事をタグ付け発表できる以外、「Q&A」分野、「same city」分野、「secret」分野の投稿が可能、タグ別やランキング順やユーザー別で記事を読むことができ、そして、使い方はいつでも自らのアカウントのデータを削除して離れることができる。[**Symphony**](https://github.com/b3log/symphony)がリストように、企業版の細々な機能は多すぎる。

# 「HacPai」とQiitaの対照一覧

1. [x] List of all users　[**あり**](https://hacpai.com/users)
- [ ] List of all organizations　なし（会社、組織等の団体様向けのサービスがないため）
- [ ] Advent Calendar　なし
- [x] Qiita Jobs　**あり**、認証後、職場分野投稿
- [x] Qiitadon　マイクロブログの機能が**あり**、登録後使い、非mastodon
- [ ] Qiita:Zine　なし
- [x] Tags　[**あり**](https://hacpai.com/tags)
- [x] API　[**あり**](https://hacpai.com/article/1488603534762)
- [x] 様々なランキング　[**あり**](https://hacpai.com/top)
- [x] comment/like/follow/emoji　**あり**
- [x] マイページ　[**あり**](https://hacpai.com/member/Vanessa)
- [ ] ミュート設定　なし
- [x] Online Chat広場　[**あり**](https://hacpai.com/cr)、登録後使い
- [x] 点数決算システム　[**あり**](https://hacpai.com/member/jeffjade/points)、登録後使い
- [x] 貢献量システム　[**あり**](https://hacpai.com/article/1531283103334)
- [x] 検索機能　**あり**、未登録はGoogle検索を使い、登録後は無制限
- [x] Markdown編集　**あり**、B3logオープンソースなMarkdown編集ツール[**Vditor**](https://github.com/b3log/vditor)とB3logオープンソースなMarkdownエンジン[**Lute**](https://github.com/b3log/lute)
- [x] コードハイライト　**あり**
- [ ] 下書き保存　なし
- [x] Show article in Markdown　**あり**、2019年9月に追加している機能、登録後使い

# スポンサー

- 中日対訳分野で世界一の「[**有道**](http://fanyi.youdao.com/)」
- [**GitHub**](https://github.com)
- [**Qiita**](https://qiita.com)
- [**HacPai**](https://hacpai.com)
Raspberry Pi への Raspbian インストール方法

Raspberry Pi (Model B) に Raspbian をどのようにインストールしたのか記載します。
なお、今回の作業は[こちらの本](https://www.amazon.co.jp/%E3%81%93%E3%82%8C1%E5%86%8A%E3%81%A7%E3%81%A7%E3%81%8D%E3%82%8B-%E3%83%A9%E3%82%BA%E3%83%99%E3%83%AA%E3%83%BC%E3%83%BB%E3%83%91%E3%82%A4-%E6%94%B9%E8%A8%82%E7%AC%AC5%E7%89%88-Raspberry-Zero/dp/4800712246)を参考にして進めました。

## 1. 事前準備
Raspberry Pi 本体以外に、以下のものが必要になります。

- マウス
- キーボード
- ディスプレイ
- micro SD カード (今回は16GBのものを使用しました。)

## 2. ファイルのダウンロード
[Raspberry Pi の公式サイト](https://www.raspberrypi.org/downloads/noobs/)にアクセスし、「NOOBS」をダウンロードします。「NOOBS」と「NOOBS Lite」の2種類がありますが、以下のような違いがあるようです。

##### NOOBS
必要なパッケージがあらかじめ含まれているため、

- ファイルのサイズが大きい分、ダウンロードに時間がかかる。
- OSのインストール時、Raspberry Pi にネットワーク環境は不要。

##### NOOBS Lite
必要なパッケージが含まれていないため、

- ファイルのサイズが比較的小さいため、短時間でダウンロードができる。
- OSのインストール時、Raspberry Pi にネットワーク環境が必要。

また、どちらにも、ダウンロード形式として ZIP と Torrent が用意されています。
今回は、ネットワーク環境の要らない「NOOBS」を ZIPファイル形式でダウンロードしました。

## 3. SD カードの準備
##### ① SD Formatter のダウンロード
[SD Association の Webサイト](https://www.sdcard.org/jp/downloads/formatter/)にアクセスし、「SD メモリカードフォーマッター」をダウンロードします。（今回はWindows用のフォーマッターを使用しました。）
##### ② SD Formatter のインストール
ダウンロードしたファイルを展開し、「setup.exe」を起動します。
##### ③ SD カードのフォーマット
インストール完了後、パソコンのカードリーダーに SD カードを挿入し、「SDFormatter」を起動します。フォーマットオプションは「上書きフォーマット」を選択し、「フォーマット」ボタンを押すと、挿入された SD カードのフォーマットが開始されます。
##### ④ NOOBS のコピー
SD カードのフォーマットが完了したら、2. でダウンロードした NOOBS ファイルを展開し、中身を全て SD カードにコピーします。コピーが完了したら、SD カードをパソコンから取り出します。

## 4. Raspbian のインストール
##### ① Raspberry Pi の起動
Raspberry Pi にマウス、ディスプレイ、キーボードをつなぎ、3. で準備した SD カードを挿入します。その後電源につなぐと、Raspberry Pi が自動で起動します。
##### ② Raspbian のインストール
Raspberry Pi 起動後、インストールする OS の選択画面が出てきます。「Raspbian」を選択し「インストール」ボタンを押すと、インストールが開始されます。

インストール成功のダイアログが出たら完了です。
みんなでしりとり (paizaランク B 相当)　でやったこと（Python3)

#対象
これは paizaランク B 相当の練習問題として[ここ](https://paiza.jp/works/mondai/skillcheck_archive/word_chain/)にあった問題の解答の解説となる。
Bランク問題のため、かなり初歩的な内容が含まれるが、同じようにこの問題で苦戦した人の一助となれば幸いである。

#問題文
あなたは友達たちと N 人でしりとりを行うことにしました。
1 人目、 2 人目、...、 N 人目、 1 人目、2 人目、... という順序で発言をします。

ここで、それぞれの人は、次に挙げる 4 つのしりとりのルールを守って発言をする必要があります。

1. 発言は、単語リストにある K 個の単語のうちのいずれかの単語でなければならない。
2. 最初の人以外の発言の頭文字は、直前の人の発言の最後の文字と一緒でなければならない。
3. 今までに発言された単語を発言してはならない。
4. z で終わる単語を発言してはならない。

ここで、発言の途中で上のルールを破った場合、ルールを破った人はしりとりから外れます。
そして、その人を抜いて引き続きしりとりを続けていきます。このとき、後続の人は、ルール 2 を守る必要はありません。

N 人がしりとりを行ったログが M 行分与えられます。
このとき、M 回の発言が終わった後、しりとりから脱落せずに残っている人のリストを表示するプログラムを書いてください。

・苦戦した点
１．しりとりが成功するかどうかの判定
２．生き残っているメンバーの管理（また、メンバーが一周すると参照箇所をはじめに戻す処理）

#コードの解説

##変数定義


```py
n,k,m = list(map(int,input().split()))
d = []
for i in range(k):
        d.append(input())
s = []
for i in range(m):
    s.append(input())

member_list = list(range(1,n+1))  #生き残っているメンバーリストの初期化
now = member_list[0]　#現在のターンで発言するプレイヤー名
said = [] #発言の重複を避けるため、言った単語はストックしておく
```

しりとりが成功するかどうかの判定にcheck関数を定義した。
使える単語リスト(d)、用済みの単語リスト(said)、前のプレイヤーの単語(word_b)、今のプレイヤーの単語(word_a)を引数にもつ。
1人目やプレイヤー脱落直後の人はword_bに依存しないため、word_bの値をNoneとしておく。
check関数によりしりとり成功の可否をチェックし、
成功の可否にかかわらずsaidリストにword_aを記録させる。
next_member関数によりプレイヤー名を更新し、ループが１周する

```py
for j in range(m):  #処理開始
    if j == 0:
        word_a = s[j]
        word_b = None
    elif booli == 0:
        word_a = s[j]
        word_b = None
    else:
        word_a = s[j]
        word_b = s[j-1]
    booli = check(d,said,word_b,word_a) #しりとり判定
    said.append(word_a)
    now = next_member(now,member_list,booli)
```



```py
def check(goi,said,word_b,word_a):
    if ((len(said) == 0) or ((word_b == None)and(word_a in goi))): #一言目or脱落後ならtureを返す
        return bool(1)
    else:
        if (word_a in goi)and(not(word_a in said)and(not(word_a[-1]=='z'))):
            if word_b[-1] == word_a[0]:
                return bool(1)
            else:
                return bool(0)
        else:
            return bool(0)
def next_member(now,remain,booli):
    if booli == 0:
        i = remain.index(now) #今のターンの人のindexを取得し、iに保存
        remain.remove(now)    #今のターンの人をremainから削除
        if i >= len(remain):
            i -= len(remain)
        tugi = remain[i]
        return tugi
    elif booli == 1:
        i = remain.index(now)+1
        if i >= len(remain):
            i -= len(remain)
        tugi = remain[i]
        return tugi
```

最後に

```py
ndash = len(member_list)
print(ndash)
for i in range(ndash):
    print(int(member_list[i]))
```

で出力を行う

#反省
saidリストをわざわざ作らなくても、dから使用済みの単語は削除していく方が処理が楽だったかもしれない

#課題

~~実はこのプログラム、意図していない動作があり、（して欲しい動きはしたので放置している）
next_memberはmember_listを引数にとりメンバーの削除を行うが、その結果を関数の外に戻していないため、
関数の外ではmember_listの値はデフォルト（全員分）のままだと思ったが
member_listは最新の状況を反映している。
def内の動きについてもう少し勉強して、理解できれば追記しようと思う。~~

コメントより
>関数の呼び出し元と呼び出し先でオブジェクトを共有します。（変数代入でもオブジェクトを共有します）
リストはミュータブル（可変）オブジェクトです。呼出し先でオブジェクトの内容を変更すると、呼び出し元にも影響します。

とのことで、関数で使用した引数（オブジェクト）は共有されるため、通常の動作でした。

便利な反面、誤動作が怖いですね。勉強になりました。ありがとうございます。
【川原のGo言語＆Elixir奮闘記】#2　今日はGoでHello world

Hello world私だよ。

今日はGoのダウンロードとHello worldまでやっていくよ。

以下のサイトでGoをダウンロードしていくよ。
↓
https://golang.org

普通に.msiをインストールしたよ。

以下の記事を参考にしたよ。
↓
https://qiita.com/ta9star/items/49a3be887698ff6c1b58

ダウンロードが終わったら次はHello worldをやってみるよ。

今回の開発環境はVScodeだよ。

VScodeを開いてFileからNew fileを選択するよ。

以下のプログラムを用意したよ。

```.go
package main

import "fmt"

func main() {
  fmt.Println("Hello world")
}
```

これをコピペしてFileからSaveを選択するよ。

保存するときに型を.goに変えるよ。

ここまで来たらDebugしてみるよ。

どこかでそのファイルがHello worldって言ってるよ。

プログラムの下にあるシェルで言ってるよ。

今日はここまでだよ。

最近、雨が中山きんに君みたいなことするから通学に傘は必須だよ。

また来週。
【Word VBA】選択部分の消費税込み金額を増税に対応させる

# 想定状況
消費税率が変わるので、Word文書内の金額（税込表示）を改訂しなければならない。

## 前提条件
- 消費税が適用される金額と、適用されない金額が混在しており、機械的な判別が困難
- 金額はWord文書内にベタ打ちされている
- ベースとなる税抜金額はすべて100の倍数である

## さてどうする
- 前の金額を消して料金表から再計算するより、Wordで計算してから料金表と照合した方が正確そう（計算苦手並感） 
- 計算過程は残しておきたいので、今回はフィールドを使うことにした（外したいときはUnlinkすればいいし）

# 書いた
書いたらこれを適宜ショートカット登録して、金額部分を選択しながら使う
- 消費税非適用の部分や既に新税率適用済みの箇所を選択してしまっても、前の税率の倍数でなければダイアログで止まる→うっかりミスの可能性が低くなる
- 素人マクロなのはご容赦～

```vb:Module1
Sub VATIncreace()
    Dim i As Long
    Dim Price As Variant '税抜金額
    
    Dim PastVATRate As Variant  '過去の消費税率
    PastVATRate = Array(1.08)
    'PastVATRate = Array(1.08, 1.05, 1.03) '混在している文書用
    
    Const VAT_RATE As Double = 1.1 '変更後の消費税率
    
    '--------------------
    Price = 0
    
    If (IsNumeric(Selection.Text) = False) Then
        GoSub INPUT1
    Else
            
        For i = LBound(PastVATRate) To UBound(PastVATRate)
            If (CLng(Selection.Text) Mod CLng(PastVATRate(i) * 100)) = 0 Then
                Price = CLng(Selection.Text) / PastVATRate(i)
                Exit For
            End If
        Next i
        
        If Price = 0 Then GoSub INPUT1
        
    End If
    
    Selection.InsertFormula Formula:="=(" & Price & ")*" & VAT_RATE, NumberFormat:="#,##0"
        
    Exit Sub
    
INPUT1:
    Price = InputBox("税抜価格を入力してください")
    '数式入力を許容する場合は次のIF文をなんとかする（わかんない）
    If (IsNumeric(Price) = False) Then
        MsgBox ("正しい値が入力されませんでした。処理を中断します")
        Exit Sub
    End If
    Return
    
End Sub

```
# 反省点
- 半角の金額と全角の金額が混在している文書のために、半角化処理とか挟んだ方が良いかもしれない
- 「～円」で検索した結果に対して適用するために、「円」が含まれていても処理できるようにした方が良いかもしれない
- 消費税率が下がることも想定したプロシージャ名にしたほうが良いかもしれない
Growi × Docker × EC2構築

## 概要
AWSでEC2インスタンスを立てて、そこにdocker環境を作り、その上でGrowiを運用する方法をご紹介します。
ちなみに、EC2インスタンス構築の記事はたくさんありますので、それらの詳細は省かせていただきます.

EC2構築の参考
- [AWSでのEC2構築](https://qiita.com/yo_dazy/items/3846915e4db21fe04537)
- [Elastic IP（固定 IP）の割り当て](https://aws.amazon.com/jp/getting-started/projects/fileserver/02-2/)

## 環境
- マシンイメージ: Amazon Linux 2 AMI (HVM), SSD Volume Type


## 構築
### root昇格
```bash
$ sudo su -
```

### dockerインストール
```bash
$ yum install -y docker

// 確認
$ docker -v
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
```

### docker-composeインストール
[公式](https://docs.docker.com/compose/install/)を参照して最新を取得してください。

```
$ curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose

// 確認
$ docker-compose -v
docker-compose version 1.24.1, build 4667896b
```

### 自動起動設定
```
$ systemctl enable docker
```

### docker実行ユーザー設定
#### dockerグループ作成(なければ)

```bash
$ groupadd docker
```

#### 現行ユーザをdockerグループに所属させる

```bash
$ gpasswd -a $USER docker
```

#### dockerデーモンを再起動
```bash
$ systemctl restart docker
```

#### exitして再ログインすると反映

```
$ exit

$ sudo su -
```

### Growiインストール
#### gitインストール

```bash
$ yum install -y git
```

#### Growiをクローン
```bash
$ cd /home/ec2-user
$ git clone https://github.com/weseek/growi-docker-compose.git growi
```

#### 外部から80ポートでアクセスできるように変更

```bash
$ cd /home/ec2-user/growi
$ vi docker-compose.yml
```

```docker
app:
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 80:3000 # ← 公式の説明通り、ローカル以外からも使いたいので`127.0.0.1`を外す
    links:
      - mongo:mongo
      - elasticsearch:elasticsearch
    depends_on:
      - mongo
      - elasticsearch
```

#### コンテナ起動
```
$ docker-compose up -d
```

### 確認
グローバルIP(Elastic IP)または設定したドメインの3000ポートにブラウザからアクセスしてみてください。

http://XX.XXX.XXX.XX

以下のような画面が表示されれば成功です！！

<img width="709" alt="スクリーンショット 2019-09-20 10.46.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290840/12b6ed8f-bc4b-2777-a69f-870d009252d3.png">


参考記事
- [growi-docker-compose](https://github.com/weseek/growi-docker-compose#upgrade)
- [Dockerコマンドをsudoなしで実行する方法](https://qiita.com/DQNEO/items/da5df074c48b012152ee)
【日本語変数名で学ぶ】JavaScriptのエラーの計測について考える

今日の１日の始まりは猫が布団に入ってきたことでした。GENYAです。

## tl;dr
APIの想定内(ロジック)のエラーの場合はハンドリングして、
想定外の場合は例外としてsentryにthrowする。

実際の動きの確認 => https://codesandbox.io/s/try-catch-throw-9ild7

## 課題感
エラーハンドリングの動きが認知されていなかったので、
実際に動くものを参考に挙動を確認する。

今回は sentry が window.onerrrorを監視していて、
ロジカルなエラーのハンドリングとその扱いをどうすべきかということが議論になったので確認していく。


## ロジック内のハンドリングをどう制御するか
APIの接続時など外部への接続でエラーが起きたことを想定、
そのときに throwされたこととする。

この場合、ケースとしてはこんな感じになる。
1. try内でAPIコール
2. エラー発火
3. catchに入ってきてハンドリング処理を実行
4. finallyが実行
5. エラーが発火してもしなくても、最後の到達が呼び出される

```javascript
export const ロジック内のハンドリング = () => {
  try {
    throw new Error("test"); // 1 エラー発火
  } catch (エラー情報) {
    console.log("ロジック内のハンドリングをする", エラー情報); // 2
  } finally {
    console.log("finally called"); // 3
  }

  console.log("ロジック内のハンドリング 到達"); // 4
};
```

### ハンドリングしたが例外が起きたケース
1. try内でAPIコール
2. エラー発火
3. catchに入ってきてハンドリング処理を実行
4. ハンドリングしきれなかったものをthrowする
5. finallyが実行
6. sentryへ例外エラーが送られる

```javascript

export const ロジック外のエラーを再throw = () => {
  try { 
    throw new Error("test");
  } catch (エラー情報) {
    console.log("ロジック外の例外は更にthrowする sentryが発火");
    throw エラー情報;
  } finally {
    console.log("finally called ロジック外のエラーを再throw");
  }
  console.log("ロジック外のエラーを再throw 終了"); // 実行されない
};
```

## まとめ
観測すべきエラーはどういうものか、それはロジカルなエラーなのか、例外のケースなのかで判断をすると良いように思う。
ここで言うロジカルなエラーというのはバックエンドのIFの定義に含まれる status code や 独自のエラーの仕組みの定義を意味する。
それ以外の例外が起きたケースというのは計測して、ハンドリングし、対処方法を考えていく動きをする。

例えばサーバーが500を返すような場合であっても、
フロント側のハンドリングは 500をハンドリングする共通処理を実行を想定していれば、
それはsentryで計測する必要は**ない**と考える。

多段のtryを書く場合のハンドリングも↓に用意したので興味がある人は codesandboxで挙動を確認してみてください。

https://codesandbox.io/s/try-catch-throw-9ild7


### 追記
よくある実装でやる奴を書いておきます。

```javascript

export const よくある実装でやる奴を書いておく = async () => {
  ローディングを表示する()
  try { 
    const {response的な何か} = await APIをリクエスト()
    受け取った値を料理する(response的な何か)
  } catch (エラー情報) {
    // API固有のハンドリング
    if (エラー情報.status === 400) {
      ダイアログを表示する('入力内容に誤りがあります')
    } else if (エラー情報.status === 451) {
      ダイアログを表示する('政府による検閲によりコンテンツが表示できません')
    } else {
      共通のエラーハンドリング関数もしくはアクション(エラー情報)
    }
  } finally {
    ローディングを非表示する()
  }
};
```
Ruby + selenium + stone + 認証プロキシ

#stoneを使ったseleniumの認証プロキシへの接続

seleniumでluminatiの認証プロキシに接続するのが大変だったので共有します。

環境
・AWS Centos7
・言語:Ruby
・認証プロキシ:luminati

stoneというTCP/UDP転送モジュールを使って、
*selenium->ブラウザ->stone(localhost:3200)->認証プロキシ*という順で接続に成功しました。
今回はRubyを使用していますが、「localhost:3200」にアクセスするだけなので応用が利く方法だと思います。また、stoneはwindowsでも使用できるようです。

ちなみに以下の方法を試しましたが失敗しました。
・chromeのオプションコマンドでoptions.add_argument("--proxy-auth=#{user}:#{pass}")みたいにするやつ
・Selenium::WebDriver::Proxy.newで、引数に「user:pass@host:port」みたいにするやつ

###AWSにstoneをダウンロードして解凍

    $ cd /usr/local/src
    $ sudo wget http://www.gcd.org/sengoku/stone/stone-2.3e.tar.gz
    $ sudo tar zxvf stone-2.3e.tar.gz

###Makefileを書き換える
    $ cd stone-2.3d-2.3.2.7/
    $ sudo vi Makefile

下のほうに行くとlinux:っていうのが見えてくるので、「-D_GNU_SOURCE」を追記します。
・変更前
*linux:
\$(MAKE) FLAGS="-O -Wall -DCPP='\"/usr/bin/cpp -traditional\"' -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL \$(FLAGS)" LIBS="-lpthread \$(LIBS)" stone*
・変更後
*linux:
\$(MAKE) FLAGS="-O -Wall -DCPP='\"/usr/bin/cpp -traditional\"' -DPTHREAD -DUNIX_DAEMON -DPRCTL -DSO_ORIGINAL_DST=80 -DUSE_EPOLL -D_GNU_SOURCE \$(FLAGS)" LIBS="-lpthread \$(LIBS)" stone*

linuxコマンドだと「a」で追記、「w!」で上書き「q!」で終了できます。

###stoneファイルの作成
    $ sudo make linux-ssl

これでstoneというファイルができれば成功

###インストール(Pathを通す)
    $ sudo cp stone /usr/local/bin/

###認証情報のBase64エンコード
たとえば認証プロキシが以下の時は
・host: luminati
・port: 8080
・user: takeda
・pass: 12345678
「takeda:12345678」をBase64エンコードして「dGFrZWRhOjEyMzQ1Njc4」となります。
Base64エンコードはここからできます。
http://www.convertstring.com/ja/EncodeDecode/Base64Encode
ネットに流すのがこわい人はフリーソフトもあります。

###stoneをバックグラウンドで実行
    $ stone luminati:8080/proxy 3200 "Proxy-Authorization: Basic dGFrZWRhOjEyMzQ1Njc4" &

ex) $ stone host:port/proxy 3200 "Proxy-Authorization: Basic user:passをBase64エンコードしたもの" &

あとはseleniumでプロキシとして「localhost:3200」にアクセスすると、luminatiへ転送してくれるようになります。

###Selenium headlessChromeの場合（例）
    options = Selenium::WebDriver::Chrome::Options.new
    options.add_argument('--headless')
    options.add_argument("--proxy-server=localhost:3200") #stoneに接続
    
    driver = Selenium::WebDriver.for :chrome, options: options
    driver.get(url)

    #何か処理#

    driver.quit

###参考サイト
stoneのインストール
https://doruby.jp/users/taka/entries/CentOS_stone_
https://ameblo.jp/u-kun-win/entry-11941013718.html
http://noaboutsnote.hatenablog.com/entry/centos6x_stone
stoneの使い方
http://www.gcd.org/sengoku/stone/Welcome.ja.html
http://blog.nocorica.jp/2013/11/stone-proxy-auto-auth/
Windows Virtual Desktop(WVD)におけるホストプールの削除方法

#ホストプールが消せない？
無事プールが作成できたので、一旦消そうと思い管理ツールから削除しようとしたところエラーで消せない・・？
消そうとすると怒られる。
![2019-09-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258122/40e1376d-55bb-14df-db54-3747a81353e1.png)

現状GUIではプールが削除できない・・？ようなので、コマンドで消していく。
多分正式リリースではこの辺改善されていることを祈ろう。

#削除手順

Powershellにて以下コマンドを実行して、Brokerにアクセスする。

```Powershell:Powershell
Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"
```


管理者権限でログインする。
![2019-09-20 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258122/5d09a089-d970-177e-b1e0-6541a7d5fd10.png)

ログインできたことを確認する。

```

PS C:\Users\XXXX> Add-RdsAccount -DeploymentUrl "https://rdbroker.wvd.microsoft.com"

DeploymentUrl                      TenantGroupName      UserName
-------------                      ---------------      --------
https://rdbroker.wvd.microsoft.com Default Tenant Group XXXXX@XXXXX


PS C:\Users\XXXX>
```

以下コマンドを実行して、削除したいホストプールから仮想マシンを削除する。
ちなみにこの時点では仮想マシン自体は消えていないので、後でリソースプールごと削除するのがよろし

```Powershell:Powershell
Remove-RdsSessionHost -TenantName <自身のテナント名> -HostPoolName <削除するホストプール名> -SessionHostName <削除するホスト名>   
```

以下コマンドを実行してアプリケーショングループも削除する

```Powershell:Powershell
Remove-RdsAppGroup -TenantName <自身のテナント名> -HostPoolName <削除するホストプール名> -AppGroupName <削除するアプリケーショングループ名>
```

ちなみに以下コマンドを実行すると消すべきアプリケーショングループがわかる

```Powershell:Powershell
Get-RdsAppGroup <自身のテナント名> -HostPoolName <削除するホストプール名>                                 

TenantGroupName : Default Tenant Group
TenantName      : XXXXXXX
HostPoolName    : XXXXXXXXXX
AppGroupName    : Desktop Application Group
Description     : The default desktop application group for the session host pool
FriendlyName    : Desktop Application Group
ResourceType    : Desktop
```

最後に以下コマンドを実行して完全に消し去る

```Powershell:Powershell
Remove-RdsHostPool -TenantName <自身のテナント名> -HostPoolName <削除するホストプール名>
```

おわり
Exception filter用のi18nモジュールを作った

サーバーサイドのローカライズの仕組みを考えたときに、HTTPリクエスト経由でローカライズしなきゃいけないのってエラーメッセージくらいじゃない？[^1]と思ったのでException filterでエラーをキャッチした段階でローカライズ出来る仕組みを作りました。i18nライブラリとしてi18nextを使っています。

[@anchan828/nest-i18n-i18next](https://github.com/anchan828/nest-i18n/tree/master/packages/i18next#readme)

## 使い方

まずはI18nextModuleをインポート。

```ts
import { I18nextModule } from "@anchan828/nest-i18n-i18next";
 
@Module({
  imports: [
    I18nextModule.register({
      fallbackLng: ["en"],
      resources: {
        en: {
          translation: { test: "Test" },
        },
        jp: {
          translation: { test: "テスト" },
        },
      },
    }),
  ],
})
export class AppModule {}
```

そしてUseFiltersにI18nExceptionFilterを設定します。その後は適切な場所でi18n用に用意しているExceptionの例外をスローします。その際に、引数にキーを指定します。これで準備は終わりです。

```ts
import { I18nExceptionFilter, I18nNotFoundException } from "@anchan828/nest-i18n-i18next";

@Controller()
@UseFilters(I18nExceptionFilter)
class TestController {
  @Get("error")
  public i18nError(): Promise<string> {
    throw new I18nNotFoundException({ key: "test" });
  }
}
```

あとは**Accept-Language**ヘッダーを使って言語を指定してリクエストすれば翻訳されたエラーメッセージを取得することができます。

```js
{
  statusCode: 404,
  message: "テスト",
}
```

またGraphQLでも使用できます。その際はI18nGqlExceptionFilterを使用します。

```ts
import { I18nGqlExceptionFilter, I18nNotFoundException } from "@anchan828/nest-i18n-i18next";

@Resolver("User")
@UseFilters(I18nGqlExceptionFilter)
export class RootUserQueryResolver {
  @Query()
  public async user(@Args("id") id: string): Promise<Nullable<UserEntity>> {
    throw new I18nNotFoundException({ key: "test" });
  }
}
```

こちらも**Accept-Language**ヘッダーを設定してリクエストすれば翻訳されたエラーメッセージを取得することができます。

```json
{
  "errors": [
    {
      "message": "テスト",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": ["user"]
    }
  ]
}
```

## Exception filter 以外で使う

このパッケージはただのラッパーなので、使用したい場所でi18nextの関数を呼び出せば使えます。

```ts
import { t } from "i18next";

t('test', {lng: "jp"}) // テスト
```


[^1]: もちろんサービスによる。メールとか通知系の翻訳とかあると思いますが、それは別途対応でいいと思った。言語情報別で持たなきゃいけないだろうし。
C#で可変長の引数を持つ関数の実装

自作の計算関数を作成するときに気になったので自分用メモ

#例
```C#
void Foo(params int[] a)
{
   // 処理
}

static void Main(string[] args)
{
    int a = 1, b = 2, ...;
    // 無限(有限)に引数が増やせる
    Foo(a, b, ...);
}
```

#配列を渡したい場合
```C#
void Foo(params int[][] a)
{
    // 各配列の要素が欲しいときは下記のように
    // a[第1引数][0番目]
    var tmp = a[0][0];
}

static void Main(string[] args)
{
    int []a = {1, 2, ...};
    int []b = {1, 3, ...};
    ...

    Foo(a, b, ...);
}
```

一応の注意ですが
...は適宜増やしてくださいの意なので
そのままコピペして動かさないでくださいね
【Unity】ゲームビューが勝手に拡大される問題を完全に解決する


##起こっている問題について

この記事で解決するのは、以下のリンク先にあるような問題です。

[ゲームを実行すると　ゲームビューが勝手に拡大される。](https://teratail.com/questions/176405)

##エディタ拡張での解決方法

ゲームビューのScaleが勝手に動いてしまうのが問題なので、これを1に直すエディタ拡張を書いてくださってるのを見つけました。

今回はこれを利用します。
コードはリンク先参照。

[UnityのGameViewのScaleを1に強制的に戻すエディタ拡張](https://dofilabs.blogspot.com/2018/06/unitygameviewscale1.html)

##Unity上での解像度の設定
しかし、これだけでは直らない場合があります。
解像度を追加する際、 `Aspect Ratio` を選んでください。
これにしないとWindowの大きさによっては期待したものと齟齬が生じてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237014/5efbb4fd-9f11-1a8e-d96c-f39b2ecdbee1.png)


もし解決できた方はよろしければいいねお願いします。
ios13 -> DeviceMotionEvent DeviceOrientationEvent  requestPermission になるのか

safari で iOS12.2では 設定からの
![68747470733a2f2f74796f2e73616d75726169776f726b732e6f72672f696d616765732f494d475f303939342e6a7067.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11262/70d9b4d4-ccf5-80e3-e09f-903cd4a8c1ee.jpeg)

でしたが、また変わった🙁。。そしてiOS13ではJS側で許可したクリックイベント作るんですね。
出典：[iOS 13でデバイスの動きと方向の許可を要求する方法](https://medium.com/@leemartin/how-to-request-device-motion-and-orientation-permission-in-ios-13-74fc9d6cd140)

自作のWebAppで実装して動作確認をしたのでメモです
DeviceOrientationEvent ←→ DeviceMotionEvent
window.addEventListener('deviceorientation' ←→ window.addEventListener('devicemotion'

```js:bunki.js
    if (typeof DeviceOrientationEvent.requestPermission === 'function') {
      // iOS 13+
      popupOpen("requestPermissionPopup");
    } else {
      // non iOS 13+
      window.addEventListener("deviceorientation", 今までのイベント);
    }
```
で、13+かを判定して、
なにかUIでクリックイベントを設定して、

```html:hoge.html
<button onclick="requestPermission()">このエリアを押して モーションの利用を許可してください (iOS 13+) </button>
```
13+ で許可されたイベントリスナで

```js:bunki.js
  // for ios13
  requestPermission = ()=> {
    DeviceOrientationEvent.requestPermission().then(response => {
      if (response === 'granted') {
        window.addEventListener("deviceorientation", ios13で許可したイベント);
      }
    }).catch(console.error);
  };

```
で自分のWebAppでdeviceorientation動くことは確認しました。
許可の１タップがまた増えるのがなんだかなぁ。個人の設定で永続性はできないんですかねぇ。IEの記憶再び。。。🙁

chromeは今の所何もせず動いています。：追記　v78 ios requestPermission になった模様。
nuxtjs@vuetifyでvuetify1.5.x系を使用する方法

# 概要
## 前提
- やや調査が必要だったので、共有
- 基本、英語しかないのと、readme.mdが不親切なので、要注意

## 結論
- nuxtjs@vuetifyのバージョン0.x系を使えばいい
    - vuetify自体も、1.5.xの最新版をインストールしておく
- plugin内で、自分で`Vue.use`を書く場合は特に対応不要

## 本作業が発生した背景
- vuetifyは2.x系が最新版 （2019/09/20時点）
    - 1.5.x系から2.x系へのアップグレードはやることが多い
    - https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0#user-content-upgrade-guide
- vuetify.cssを使いたいこともあり、nuxtjs@vuetifyを使用したかった
- すでにvuetifyの1.5.x系でデザインができあがっていた

# 手順
## インストール
- バージョンを指定して、インストールする

``` :npm
npm install vuetify @nuxtjs/vuetify@0.x vuetify@1.5.x
```
``` :yarn
yarn add vuetify @nuxtjs/vuetify@0.x vuetify@1.5.x
```

## あとは、`nuxtjs@vuetify`の手順通りにやる
- 以下が公式の手順
    - https://github.com/nuxt-community/vuetify-module/tree/0.x
- 念のため、本記事でも記載
    - 上記手順の意訳つき

``` js:nuxt.config.js
{
  modules: [
    '@nuxtjs/vuetify' // buildModuleでも問題なく動作する
  ],

  // Vuetify options
  vuetify: {
    // materialIcons: true, // マテリアルアイコンを使うか
    // css: true, // vuetify.cssを全体で読み込みたいか
    // treeShake: false, // vuetify-loaderなど使うのであれば、trueにする
    // theme: { }
  }
}
```
pandas→networkx→pyvisでネットワーク分析＆可視化

ネットワーク分析する際は、いつもjavascriptかpythonでnodeとedigeのjsonファイル（または.dotファイル）を作成してから、[gephi](https://gephi.org/)を利用していたけど、pythonで完結できないかと思って検討した結果。
タイトルのとおり、pythonの３つのライブラリを連携させれば楽にネットワーク分析＆可視化までできる。
中心となるnetworkxさまさま。おかげで苦労してきたデータ作成や出力などが一気に楽になった。

#1.ネットワーク元のデータ
やはりpandasの利用。
[networkxのドキュメント](https://networkx.github.io/documentation/latest/reference/generated/networkx.convert_matrix.from_pandas_edgelist.html)に「from_pandas_edgelist」という関数がある。

    Parameters
    df (Pandas DataFrame) – An edge list representation of a graph
    source (str or int) – A valid column name (string or integer) for the source nodes (for the directed case).
    target (str or int) – A valid column name (string or integer) for the target nodes (for the directed case).
    edge_attr (str or int, iterable, True) – A valid column name (str or integer) or list of column names that will be used to retrieve items from the row and add them to the graph as edge attributes. If True, all of the remaining columns will be added.
    create_using (NetworkX graph constructor, optional (default=nx.Graph)) – Graph type to 
    create. If graph instance, then cleared before populated.


pd.dataframeとして最低限、sourceとtargetという列さえ作ればネットワークを生成できる。

    import networkx as nx
    edges = pd.DataFrame({'source': [0, 1, 2],
                   'target': [2, 2, 3],
                   'weight':[1,1,1]})
    G = nx.from_pandas_edgelist(edges, edge_attr=True)


edge_attrは、sourceとtarget以外の列をedgeの属性として読み込ませることができる。
(pandasの列で"color"とか"weight"とか作ればOK）
create_usingは、有向グラフを生成したい場合には

    G = nx.from_pandas_edgelist(edges,edge_attr=True,create_using=nx.DiGraph())

と指定すればOK。最初無向グラフしか出せずに苦労した。



#2.ネットワーク分析用のデータ生成＆計算
上記のとおり、

    G = nx.from_pandas_edgelist(edges, edge_attr=True)

でnetworkxの形式のデータを生成できる。簡単！
このデータさえ生成できれば、[ネットワーク分析の指標](https://networkx.github.io/documentation/latest/reference/algorithms/centrality.html)を生成したり、

    eigen_centrality = nx.eigenvector_centrality_numpy(G)
    bet_centrality = nx.betweenness_centrality(G)
    degree_centrality = nx.degree_centrality(G)
    degree_coefficient = nx.clustering(G)

[クラスタリング](https://networkx.github.io/documentation/latest/reference/algorithms/community.html?highlight=modu#module-networkx.algorithms.community.modularity_max)など計算できる。

    modu_class = nx.greedy_modularity_communities(G)


#3.可視化
このままnetworkxで可視化するのもいいけど、よく納品形態として喜ばれるのがhtmlでの出力。
色々検討したが、[pyvis](https://pyvis.readthedocs.io/en/latest/)というライブラリが良かった。
ほぼ可視化（html出力）のみに特化しているので、netoworkxとの相性もぴったし。

    from pyvis.network import Network
    pyvis_G = Network()
    pyvis_G.from_nx(G)
    pyvis_G.enable_physics(True)  #html上でレイアウト動かしたくない場合false
    pyvis_G.show("mygraph.html")

でhtmlが生成されてブラウザで様子見れます。ズームイン／アウトとかも可。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/7580bc9e-d426-406f-9f7e-c71dd3df92c8.png)



2000node~100000edgeでも可視化してくれて普通のPCでもちょっと工夫すればうまく動いてくれるので安心。ggplotも頭をよぎったけど、ネットワーク分析関係はこれで結構賄えそう。networkxありがたや。


#4.その他
pandasからだとedgelistのみでnodeの属性は後から追加などしないといけないのが痛い。何かいい方法がないかな。
やり方分かったので今度書く予定。nodeの属性を辞書として入れれば良い。DBでいうjoinのような方法がありました。

[後半](https://qiita.com/niship2/items/07dda072837c571338e0)へ
AOJ 2480 Blame Game

問題は[こちら](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2480) (Aizu Online Judge)

全然わからないのでインターネットを検索すると，「Bobが勝つ $\iff$ 最大マッチング数がM」であるから最大マッチング数を求めれば良い，という内容の[記事](http://ncastar.hatenablog.com/entry/20150510/1431263306)が見つかった．なるほどそうなのか...．

詳しい証明はついていないようだが，多分次のようになるのだろうと思った．

($\Leftarrow$)
Bob の戦略としては，最初に M マッチをひとつ固定しておいて，Alice の指定した点に対して，それとマッチする点を答えれば良い．

($\Rightarrow$)
最大マッチングがMでないとして，Aliceの戦略を作る．Aliceが選択する点 (Bobの失策) の集合を U, Bobが選択する点 (Aliceの失策) の集合を V，2部グラフのエッジ (直接関係するAliceとBobの失策の組) の集合を $E$ ($\subseteq U \times V$) とする．記法を一つ導入して，$A \subseteq U$ に対して，$AE = \\{v \in V \mid (a,v) \in E \text{ for some } a \in A\\}$ と書くことにする． 
[Hallの定理](https://mathtrain.jp/hall) より，$|XE| < |X|$ なる $X\subseteq U$ が存在する．このような $X$ のうちで個数最小のものを1つとる (その個数を$k$とする)．また，$x \in X$ を一つ取り，$X' = X - \\{x\\}$，$Y = X'E$ とする．$X$の最小性より，Hallの定理を今度は$X'$に対して用いると，$X'$ と $Y$ の間で $k-1$ マッチングが存在することがわかる．$k > |XE| \geq |X'E| \geq |X'| = k - 1$ より $|XE| = |X'E|$．したがって，$XE = X'E = Y$．とくに $(x, y) \in E$ なら，$y \in Y$ である．
したがって，Aliceの戦略としては，以下のようにすれば良い．$X'$ と $Y$ の間の $k-1$ マッチングを一つ固定する．初手は $x$ を選択する．Bob が次の手 $y$ を取れるとすれば，$y \in Y$ であるから，マッチングに従って$X'$の要素を選択できる．以下，Bobが取る手は必ず$Y$の要素になるので，マッチングに従って$X'$の要素を選択する．(終)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398368/271e409e-1983-1815-f3a9-313682fdeaf1.jpeg" width="40%">
Visual Studio 2019 で Xamarin.Android アプリをエミュレータで実行すると "ポートの転送に失敗しました" というエラーが出るときの対処

Visual Studio 2019 で Android アプリのプロジェクトを作成し(Xamarin.Forms でも Xamarin.Android でも)、エミュレータで実行すると、次のエラーが出ました。

```
アプリケーションの開始エラー: ポートの転送に失敗しました。
デバッガーに接続できませんでした。詳細については Xamarin 診断出力を、
例外の詳細についてはログをご覧ください。
```

プロジェクトのビルドは成功しており、エミュレータの起動も完了しているにも関わらず、です。

このような場合、日本語のエラーメッセージで検索しても解決できる可能性は低いので、まずは英語のエラーメッセージを表示するために、Visual Studio の言語設定を英語にしましょう。

VS2019 を英語にするには、まずは英語の「言語パック」をインストールする必要があります。

1. Visual Studio Installer を起動します
2. 言語パック → 英語 にチェックを入れてインストールします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/df152335-1a16-515c-9623-b5ea85d88701.png)

次に Visual Studio 2019 の設定で言語を変えます。

1. Visual Studio 2019 のメニュー → ツール → オプション
2. 環境 → 国際対応の設定 → 「English」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/a9a73a0e-d76d-7140-7c9d-5be2a0833cd9.png)


これで同じ手順を辿ると、エラーメッセージは次のような英語になります。

```
Error Starting Application: Failed to forward ports.
Couldn't connect debugger. You can see more details in Xamarin Diagnostic output and the full exception on logs.
```

英語でググるとなんとか解決策に辿り着けるでしょう。

* [Error Starting Application: Failed to forward ports. - Developer Community](https://developercommunity.visualstudio.com/content/problem/733170/error-starting-application-failed-to-forward-ports.html)


> I've solved the problem! I deleted platform-tools in the SDK folder. And replaced it with an older version - platform-tools_r28.0.2-windows.zip. It all worked! Both from VS 2017 15.9.7 and after upgrading to 15.9.16. VS 2019 16.2.5 also successfully works with platform-tools_r28.0.2. Conclusion! - It is not the studio's fault, but the update of platform tools from android sdk to version 29 (29.0.1, 29.0.2 - does not work with VS 2017/2019, 28.0.2 - successfully works!)

Android SDK 内の platform-tools のバージョンが新しすぎると発生するから、古いバージョンにダウングレードすると回避できる、とのこと。

古いバージョンとはこちら → [platform-tools 28.0.2](https://dl-ssl.google.com/android/repository/platform-tools_r28.0.2-windows.zip)

28.0.2 の platform-tools に置き換えて、Visual Studio 2019 を再起動、プロジェクトとエミュレータを再ビルド＆実行すると、正常にエミュレータにアプリが転送できました。

ちなみにこのエラーが出たとき、私の platform-tools は 28.0.3 でした。 
おそらく、Android SDK を Android Studio と共有していて、Android Studio 側で SDK をアップデートしたために、Visual Studio が対応していない **新しすぎる** バージョンに更新されたためと思われます。

ディスク容量節約のために SDK を共有していますが、このようなリスクもある事を頭に入れておきましょう。
M5StickCのUIFlowは秀逸だけどI2Cの実装がよくわからない件

#M5StickCでやりたいこと
+ I2Cを使ってレーザー距離計を使ったり、モータードライバを動かしたり
+ 安いラジコンを動かすのにラズパイよりも手軽かも

#UIFlow
プログラムを作ろうとしたら、グラフィカルなGUIで視覚的に組めそうなものが目に入ったので、今回はUIFlowでやってみることとした。

#簡単なはずなのに、I2Cへのアクセスは大苦戦

![EE1cwOJXUAQLqvs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328520/4b4ed688-bb7f-c18c-b02a-ab8ec8c445b3.png)

こんな感じでうごくんじゃないの？
I2Cで数バイト読むだけなのに・・・

アドバイスをいただきました。

>TinyLiDARでやってみました。
>https://fabcross.jp/news/2017/20170727_simplelidar_tinylidar.html
>
>ご覧のように、pythonでほとんど書きました。
>UIFLOWで用意されたLibraryって。。。なぞ？

![EE3GNNNUcAAbTi-.jfif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328520/0484c8dc-f668-46a4-dd9c-db04b228f192.jpeg)

[Shigeo Kinoshita](https://twitter.com/Shige_OK?s=17) さん、アドバイスありがとうございます。

しかし、ここから色々やるにはどうしたら良いのか？（続く
CSSだけで画像をトリミングする方法

##様々なサイズの画像を、全部同じサイズにトリミングしたい

##1. 高さと横幅のみを指定した場合

```css:main.css
.img {
	height: 200px;
	width: 800px;
}
```
=> 画像の比率がおかしくなり、変な感じに伸びてしまいます。



##2. 高さと横幅、object-fitメソッドを指定
```css:main.css
.img {
	height: 200px;
	width: 800px;
    /*これを追加するだけです*/
	object-fit: cover;
}
```

=> `object-fitメソッド`を追加するだけで、画像が同じサイズにトリミングされました。
Pythonでmathモジュールを使わずに四捨五入/切り捨て/切り上げ

Pythonでmathモジュールを使わずに四捨五入、切り捨て、切り上げするための方法を記します。

```python
A, B = 12, 100
# 四捨五入
res = (x*2+1)//2
# 切り捨て
res = B//A
# 切り上げ
res = -(-B//A)
```

# 追記
round関数は四捨五入ではないというご指摘をいただいたので、修正しました。roundは端数が0.5だと結果が偶数となる方に丸めるみたいです([端数処理](https://ja.wikipedia.org/wiki/%E7%AB%AF%E6%95%B0%E5%87%A6%E7%90%86))。
CentOS 7.x系がサポートしているCPU

# はじめに

[CentOS 6.x系がサポートしているCPU](https://qiita.com/nkojima/items/945f07c33ba541f90f45)を投稿した後、CentOS 7.x系がサポートしているCPUも気になったため、思い切ってテストしてみることにしました。

テストを実施するためにCPUの換装が面倒でしたが、おかげで色々と知見が得られました。

# 材料と方法

## テストに使用した環境

* CPU
 * Skylake: [Core-i3 6100T](https://ark.intel.com/content/www/jp/ja/ark/products/90734/intel-core-i3-6100t-processor-3m-cache-3-20-ghz.html)
 * Kabylake: [Pentium G4560](https://ark.intel.com/content/www/jp/ja/ark/products/97143/intel-pentium-processor-g4560-3m-cache-3-50-ghz.html)
* マザーボード：[ASRock H110M-STX](https://www.asrock.com/MB/Intel/H110M-STX/index.jp.asp)
 * BIOSバージョンはP7.70で、[CPUサポート一覧表](https://www.asrock.com/MB/Intel/H110M-STX/index.jp.asp#CPU)を見ると上記のCPUのいずれにも対応していました。
* OS
 * CentOS 7.0（1406）
 * CentOS 7.2（1511）
 * CentOS 7.4（1708）
 * CentOS 7.6（1810）


## インストール時の条件

* ［ソフトウェアの選択］は［最小限のインストール］を選びました。
 * CentOS6系のインストール時に選択するインストールタイプだと、「Minimal」に相当するものと思われます。
* 外付けDVDドライブからインストールしましたが、その際にBIOS（UEFI）のBoot Menuで`UEFI DVD Drive`というデバイスを選択しました。
 * `USB DVD Drive`を選ぶと、なぜかインストール処理が開始されませんでした。


# インストールのテスト結果

|CPU|7.0|7.2|7.4|7.6|
|---|---|---|---|---|
|Skylake (Core-i3 6100T)|×|×|×|〇|
|Kabylake (Pentium G4560)|〇|〇|〇|〇|

## CentOS 7.0の場合

* SkylakeのCPUだと、インストール開始直前に「ISOLINUX 4.05 2010-07-21...」というメッセージが出て、そこから先に進めませんでした。

```
ISOLINUX 4.05 2011-12-09 ETCD Copyright (C) 1994-2011 H.2010 H. Peter Anvin et al
```

## CentOS 7.2の場合

* SkylakeのCPUだと、インストール開始直前に「ISOLINUX 4.05 0x54f93f16...」というメッセージが出て、そこから先に進めませんでした。

```
ISOLINUX 4.05 0x54f93f16 ETCD Copyright (C) 1994-2011 H. Peter Anvin et al
```

## CentOS 7.4の場合

* SkylakeのCPUだと、インストール開始直前に「ISOLINUX 4.05 0x581e199a...」というメッセージが出て、そこから先に進めませんでした。

```
ISOLINUX 4.05 0x581e199a ETCD Copyright (C) 1994-2011 H. Peter Anvin et al
```

# インストール後の起動の結果

|CPU|7.0|7.2|7.4|7.6|
|---|---|---|---|---|
|Skylake (Core-i3 6100T)|×|×|×|〇|
|Kabylake (Pentium G4560)|△|△|〇|〇|

## CentOS 7.0と7.2の場合

* KabylakeのCPUだと、OSが起動する直前に以下のメッセージが表示されましたが、OSを起動することができました。
 * 直訳すると「このハードウェア（Intel製CPU）は上流のテストを受けていない。」となるため、KabylakeのCPUだと動作が保証されていないということだと思います。
 * なお、このメッセージは一瞬で流れてしまうため、画面の写真を撮ってメッセージを確認しました。

```
Detected CPU family 6 model 158
Warning: Intel CPU model - this hardware has not undergone upstream testing. Please consult http://wiki.centos.org/FAQ for more information
tsc: Fast TSC calibration failed
```

# 結論

## Skylakeの場合

* CentOS 7.4以前のバージョンでは正常にインストール出来ない。
* CentOS 7.6であれば問題なくインストール＆動作する。

## Kabylakeの場合

* CentOS 7.2以前だとインストールは可能であるが、動作が保証されていない。
* CentOS 7.4以降であれば問題なくインストール＆動作する。

# 関連URL

* [CentOS 6.x系がサポートしているCPU](https://qiita.com/nkojima/items/945f07c33ba541f90f45)
* [CentOSの対応CPU一覧 のリンク](https://qiita.com/tukiyo3/items/8ba34ece213858fea4d7#_reference-4c50b95405e7a6ec69a9)
GASにてredash APIを触ってみた


#Javascriptを使ってredash API
実行環境はGAS。ライブラリ公開すれば、汎用性が高まるのでおすすめ。
取得したデータをspreadsheetに書き出すと便利。業務で使う場合は、結構おすすめ。

[Poll for Fresh Query Results (including parameters)](https://redash.io/help/user-guide/integrations-and-api/api)
[参考ソース(python)](https://gist.github.com/arikfr/e3e434d8cfd7f331d499ccf351abbff9)

```javascript


var httpOptions = {
  method: "",
  headers: {
    Authorization: "",
    Accept: 'application/json',
    'Content-Type': 'application/json'
  }
}

function setApiKey(api_key){
  httpOptions.headers.Authorization = "Key " + api_key
}

// redash refresh query
function getRefreshQuery(redash_url, query_id){
  var refreshUrl = redash_url + '/api/queries/' + query_id + '/refresh'
  httpOptions.method = 'POST'
  var res = UrlFetchApp.fetch(refreshUrl, httpOptions)
  if(res.getResponseCode() !== 200){
    Logger.log('Refresh Failed')
    return 'Refresh Failed'
  }
  return JSON.parse(res)
}

// redash query result
function getQueryResult(redash_url, query_id, result_id){
  var resultUrl = redash_url + '/api/queries/' + query_id + '/results/'+ result_id + '.json'
  httpOptions.method = 'GET'
  var res = UrlFetchApp.fetch(resultUrl, httpOptions)
  var results = JSON.parse(res).query_result.data.rows
  return results
}

// redash check status 
function getQueryJobStatus(redash_url, job_id){
  var jobcheckUrl = redash_url + '/api/jobs/' + job_id
  httpOptions.method = 'GET'
  var res = UrlFetchApp.fetch(jobcheckUrl, httpOptions)
  return JSON.parse(res)
}

```
【備忘録】PythonにOpenCVが導入できなかった時

## はじめに
　PythonでOpenCVを使いたいと思ったが、簡単にインストールできなかったので忘れないためにメモ。
### 症状
#### pip install opencv-pythonでのインストールができなかった

###### 当時の環境
​		Windows10
​		Python: 3.7.3

　最初は`pip install opencv-python`で導入仕様としていたが、どうやら最新OpenCVのバージョンとPythonのバージョンがあっていない？インストールは成功するが、パッケージを読み込んでくれなかった。

## 解決方法
#### pip install opencv_python-4.X.X-cpXX-win_amd64.whlでインストール

1).  https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv から、自分のOSとPythonのバージョンにあった.whlファイルを選択する。
   ​			cp37     : Python 3.7.X
   ​			win_amd64: 64bit Windows

2). ダウンロードしたディレクトリに移動し、ターミナルで以下のコマンドを実行

``` 
pip install opencv_python-4.1.1-cp37-cp37m-win_amd64.whl
```

3). 同様にnumpyもインストール

```
pip install numpy
```
この方法で問題なくOpenCVを使うことができるようになりました。 

**補足**
numpyがすでに入っていて、cv2をインポート時に`ImportError: numpy.core.multiarray failed to impor`エラーが出た場合は最新版にアップグレードする（[参考](https://qiita.com/jack-low/items/850ab183c134097b28ad)）。
Linux基礎(ライブラリについて)


#ライブラリとは
よく使用されるプログラムの共通部分を抜き出して、他のプログラムから利用できるようにしたもの。

|ライブラリ|説明|
|---|---|
|静的ライブラリ|プログラムの作成時にその実行ファイル内に組み込まれたライブラリ<br>・メリット｜一つのプログラムだけで動作させられ、別環境で動作可<br>・デメリット｜プログラムのサイズが大きくなる|
|共有ライブラリ|プログラムの実行時にロードされて、複数のプログラム間で共有されるライブラリ<br>・メリット｜プログラム全体のサイズが小さくなる<br>デメリット｜プログラム実行時に適切に設置されたライブラリが必要|


＃スタティックリンクとダイナミックリンク
プログラムからライブラリの機能を呼び出すことをリンクと呼び、リンクには以下の2種類がある。

|ライブラリ|説明|
|---|---|
|スタティックリンク|プログラム作成時に、あらかじめライブラリの機能をプログラム本体に組み込む方法。<br>この時に組み込まれるライブラリは静的ライブラリ|
|ダイナミックリンク|プログラムの実行時に、ライブラリの機能を呼び出す方法。<br>この時に呼び出されるライブラリを共有ライブラリ|

#必要となる共有ライブラリの確認
共有ライブラリは、「/lib」または「/usr/lib」に配置されており、libtinfo.so.5のように「lib~.so~」という名前が付けられる。実行ファイルが必要とする共有ライブラリは「ldd」コマンドで確認することができる。例えば、moreコマンド(/bin/more)が必要な共有ライブラリは、「ldd/bin/more」で確認することができる。

#必要となる共有ライブラリの検索
「lib」や「/usr/lib」ディレクトリ以外の場所に共有ライブラリを設置する場合、その共有ライブラリの検索パスを設定する必要がある。検索パスを設定する方法は以下の2種類がある。

1. 「/etc/ld.so.conf」ファイルに設定

```shell
#ld.so.conf ファイルに /usr/test/lib ディレクトリを検索パスとして設定
$ vi /etc/ld.so.conf
/usr/test/lib

#ldconfig の実行により、/etc/ld.so.cache を更新
$ldconfig
```

2. 環境変数のLD_LIBRARY_PATHへの設定

```shell
#環境変数の LD_LIBRARY_PATH に /usr/test/lib ディレクトリを検索パスとして設定
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/test/lib
```
60日目 AmazonからASINと型番と各種コードをサクっと取ってこれるコードを考えてみました。

最初は、tableやclassでスクレイピングできるかと思っていました。
しかしパターンが複数あり、振り分けの条件が複雑になりすぎる・・・悩んでいたところ、文字だけを抜き出して、行ごとにリストに入れてforで回す方法を見つけました。

試してみた所いい感じに動いてくれました。

[Pythonのスクレイピングで文字だけを抜き出す汎用的な方法](https://qiita.com/poorko/items/9140c75415d748633a10)

Amazonどうやってデータを管理しているんだろう。
今回の件ですごく興味がわいてきました。
これだけ状態が複合していて、ある程度同じ体裁を保ちつつ何年も運用している。それでいてソースが読める。設計した人はすごいと思いました。


```getASIN.py

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
from selenium.webdriver.common.action_chains import ActionChains
from bs4 import BeautifulSoup

def getASIN(url):

  #ブラウザを立ち上げる
  options = Options()
  browser = webdriver.Chrome(options=options)  
  browser.get(url)

  #htmlを取得する
  html = browser.page_source
  
  #BeautifulSoupにほうりこむ
  soup = BeautifulSoup(html, features="html.parser")

　#scriptやstyleを含む要素を削除する
  for script in soup(["script", "style"]):
    script.decompose()

  #テキストのみを取得=タグは全部取る
  text=soup.get_text()
  
  #textを改行ごとにリストに入れて、前後の空白を削除する
  lines= [line.strip() for line in text.splitlines()]

  #リストの空白を削除する
  #text="\n".join(line for line in lines if line)
  #print(text)
　
　#検索キーワードを設定
  key1 = "ASIN"
  key2 = ["型番","JAN","メーカー型番","製造元リファレンス"]

  #noneで初期化する
  ASIN = "none"
  TYPE = "none"

　#リストを一行ずつ確認していく
  for line in lines:
    #"ASIN"が行に含まれていたら変数ASINに入れて、その行を表示する。
    if key1 in line: ASIN = line.strip(key1).strip(":").strip("：").strip()

    #キーワードが行に含まれていたら変数TYPEに入れて、その行を表示する。
    for key in key2:
      if key in line: TYPE = line.strip(key).strip(":").strip("：").strip()

　#結果を表示する
  print(TYPE,ASIN,sep=",")

```
Flask で Vue.js を使おうと思ったら出鼻をくじかれたのでメモ

## はじめに
勉強も兼ねて社内で使う簡単な Web アプリを
バックエンドは Flask で、フロントエンドは Vue.js でそれを Docker のコンテナで動かそうと、
そんな今時の感じで作ろうと思ったら出鼻をくじかれた。

## いけると思ったのに
まずは　Vue.js の公式を見ながら Hello, world! 出してみようと思い、公式通りに作った。
[はじめに-Vue.js](https://jp.vuejs.org/v2/guide/)

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <meta charset='utf-8'>
        <title>index</title>
    </head>
    <body>
        <div id='app'>
            {{ message }}
        </div>
    </body>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!'
            }
        })
    </script>
</html>
```

Flask も最低限に記述

```python:index.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from flask import Flask
from flask import g
from flask import render_template
from flask import request
from flask import Response

app = Flask(__name__)

@app.route('/index')
def index():
    return render_template('index.html')

def main():
    app.run(debug=True, host='0.0.0.0', port=5000)

if __name__ == '__main__':
    main()
```

これで、ホスト:5000->コンテナ:5000 でコンテナに穴を開けて、
http://localhost:5000/index にアクセス

## 何も出ないよね ??
この index.html をブラウザで普通にローカルのファイルとして読み込むとちゃんと表示される。なぜ。

答えはこう

```html:index.html
    <body>
        <div id='app'>
            [[ message ]]
        </div>
    </body>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!'
            },
            delimiters: ['[[', ']]']
        })
    </script>
```

注目は、`[[ message ]]` と、`delimiters: ['[[', ']]']`です。
これは、Flask が使用しているテンプレーエンジンのデリミタと、Vue.js のデリミタが共に`{{ }}`でコンフリクトしてしまっているため、Vue.js のデリミタを `[[ ]]`に変更しています。
[delimiters-Vue.js](https://jp.vuejs.org/v2/api/#delimiters)

**焦った〜**
複数単語からなるパスワードを生成するワンライナー

複数の英単語を組み合わせたパスワードは覚えやすく強固らしいです（ https://xkcd.com/936/ ）。

ところで、macOSなどには `/usr/share/dict/words` という単語一覧の辞書ファイルがあります。パスワードとして辞書に乗っているような単語を設定できないようにするなどの用途で使われるようです。

今回はその「パスワード使用禁止単語」のファイルを使って複数単語のパスワードを生成するワンライナーを考えてみました。

```bash
# bash版
echo $(shuf --random-source=/dev/random -n 4 /usr/share/dict/words) | sed -e 's/ /-/g' | tr '[A-Z]' '[a-z]'
```

```sh
# fish版
echo (shuf --random-source=/dev/random -n 4 /usr/share/dict/words) | sed -e "s/ /-/g" | tr "[A-Z]" "[a-z]"
```

※ 事前に `coreutils` をインストールして `shuf` コマンドを使えるようにしておきます。

```sh
$ brew install coreutils
```

## alias化

### Fish版

```sh
echo 'alias pg=\'echo (shuf --random-source=/dev/random -n 4 /usr/share/dict/words) | sed -e "s/ /-/g" | tr "[A-Z]" "[a-z]"\'' >> ~/.config/fish/config.fish
```

## 実行例

下記のように4つの単語からなるパスワードが生成されます。

```sh
$ pg
aureocasidium-vermis-sellenders-isognathous
$ pg
gutterblood-preallegation-razormaking-unlucky
$ pg
perfectioner-unaggression-scientician-predissolve
```

## その他

- `shuf` コマンドで辞書ファイルから4単語抜き出す際に `/dev/random` を指定してよりランダムにしています。
- `sed` や `tr` でハイフン区切り＆小文字にしています。
散歩促進PGMのようなもの

主にJavaScriptを用いた散歩促進PGMとデータ作成のための副PGM(python,javascript,GoogleAppsScript)です。
PGM内容としては(一応)歩いた距離に応じて距離を算出し、仮想移動点から
歩いた距離に応じて移動し、画像を発見していくようなものとなっています。
2019.10.17: 修正しました(歩数のチャージ機能を追加)

githubURL:https://github.com/NanjoMiyako/Sanpo

データ作成用スプレッドシートURL(sanpo1.gs):https://docs.google.com/spreadsheets/d/1HCxRtQ8jS1P7KaiVmJU4j4XboP9MRylGbk9N9bMtRIU/edit?usp=sharing

GASPGM: https://github.com/NanjoMiyako/SampleGasScripts1/blob/main/randomCol.txt

サンプルページURL: https://nanjomiyako.github.io/Sanpo/

参考サイト
<a href="https://www.finds.jp/rgeocode/index.html.ja#SAMPLE">
簡易逆ジオコーディングサービス
</a>
<a href="https://www.tech-tech.xyz/python-img-resize.html">
【Python】画像の解像度の変更。リサイズ（拡大・縮小）
</a>

データ作成含む一連の処理の流れ

1.　randomIdoKeidoJS.jsにてランダムに日本の(陸地の)緯度経度を取得
2.　緯度経度対応画像リストを出力画像フォルダに格納し、resize.pyにて画像サイズを一定に合わせる
3.　sanpo1.gsにて緯度経度と画像の対応のシートを書き出し、RandomColumn()メソッドにより、行をランダムに置き換え、CreateJsonData()からlandScapeデータを作成する。
4.　sanpoIndex.html(とsanpoJS.js)ファイルより作成したlandScapeデータ(とセーブデータ用のMySanpoData)をインポートし動作させる
msbuild で "Microsoft.Portable.CSharp.targets が見つかりませんでした" というエラーが出たときの対処

Windows をクリーンインストールした後に Visual Studio 2019 を入れてソリューションを msbuild でビルドしたら下記のエラーが発生。

```
(中略)
"C:\Program Files (x86)\Microsoft Visual Studio\2019
\Enterprise\MSBuild\Microsoft\Portable
\v4.5\Microsoft.Portable.CSharp.targets" 
が見つかりませんでした。
```

どうやら PCL(Portable Class Library)のプロジェクトのビルドが失敗している模様。

原因と解決方法はこちら。

* [c# - Build of PCL lib fails with new VS2019 agent? - Stack Overflow](https://stackoverflow.com/questions/54861759/build-of-pcl-lib-fails-with-new-vs2019-agent)

VS2019 の通常のインストールではもはや PCL はサポートされていなくて追加でコンポーネントを入れなければならないとのこと。

1. Visual Studio Installer を起動する

2. 変更 → 個別のコンポーネント → .NET ポータブルライブラリ対象パック にチェックを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/ad34376a-7a66-78ba-4d8e-b30bc383dc04.png)

これをインストールした後は、冒頭のエラーは発生せず無事ビルドできました。
Blenderの　normals_split_custom_set_from_vertices　について

メッシュがFlat Shadingの状態でnormals_split_custom_set_from_verticesするとバグ？ってる
bpy.ops.object.shade_smooth()　を　mesh.normals_split_custom_set_from_vertices() する前に呼ぶこと。

理屈的にはFlat Shadingでは頂点が面毎に法線を持つが、normals_split_custom_set_from_verticesしても両方に面毎に分かれた法線すべてに適応されないのでそうなるのだと思われる。
Smooth Shadingを**先に**設定してやることで、１頂点１法線になるので直る。

smooth shadingをカスタム法線設定後に呼んでいたため(数週間)ハマった。
簡単なパス移動の実装

ある地点とある地点を行き来するようなアルゴリズムを実装していきたい思います。

#下準備
以下に出てくるVector3はこんな感じです(+とか=は省きます)。

```:Vector3.h
//ベクトルクラス
class Vector3 {
public:
float Length();   //ベクトルの長さを取得
void Normalize(); //ベクトルを正規化
float x;          //x
float y;          //y
float z;          //z
};
```

まず、ある地点を表すポイント構造体を作ります。

```
struct Point {
Vector3 s_position;   //ポイントの座標
int     s_number;     //ポイントの番号
};
```

それの配列とポインタをパス移動させたいクラスに持たせます。

```:Enemy.h
class Enemy {
std::vector<Point>   m_pointList;  //ポイント構造体の配列
Point*               m_point;      //ポイント構造体のポインタ、現在の目的地
                                   //となるポイント
    .
    .
    .
Vector3              m_position    //Enemyの座標
};
```
ポイントを設置します。

```:Enemy.cpp
m_pointList.push_back({Vector3(0.0f,0.0f,0.0f),1});     //一番目のポイント
m_pointList.push_back({Vector3(0.0f,100.0f,0.0f),2});   //二番目のポイント
m_pointList.push_back({Vector3(100.0f,0.0f,0.0f),3});   //三番目のポイント
m_pointList.push_back({Vector3(0.0f,0.0f,100.0f),4});   //四番目のポイント
m_point = &m_pointList[0];                              //一番目のポイントを入れる
```

#パス移動

```:Enemy.cpp
//以下ループ

//目標とするポイントの座標から現在の座標を引いて、距離ベクトルを求める     
Vector3 diff = m_point->s_poition - m_position;
//距離が一定以内なら目的地とするポイントを変える
if(diff.Length() <= 20.0f) {

    //今目的地としているポイントが配列の最後の要素なら
　　//一番最初のポイントを目的地とする
    if(m_point->s_number == m_poinstList.size()) {
        m_point = m_pointList[0];
    }

    //そうでないなら配列の次の要素のポイントを目的地とする
    else {
    m_point = m_pointList[m_point->s_number];
    }
}

//目標とするポイントの座標から現在の座標を引いて、距離ベクトルを求める 
Vector3 moveSpeed = m_point->s_position - m_position;
//正規化する
moveSpeed.Normalize();
//適当にスカラーをかける
moveSpeed *= 3.0f;  
//座標に加算する
m_position += moveSpeed;
```
jQueryUIとは

##1. jQueryUIとは
jQueryUIとは、jQueryによるユーザーインターフェース系プラグインの集まりのこと。jQueryjQueryとともに広く利用されている。

[jQueryUI / 公式ページ](https://jqueryui.com/)

__日付選択__や__ドラッグ・アンド・ドロップ__、__オートコンプリート__など、自分で一から作成するとかなり大変なUIも、jQueryUIを使用すると簡単にサイトに導入できる。

jQueryUIでは、これらの各UIを「__Widget（ウィジェット）__」と呼んでいる。


##2. jQueryUIの便利な点

###2-1. アクセシビリティが素晴らしい
例えば、タブであれば「__キーボードの左右キーでタブ選択して[tab]キーでパネル内にフォーカスする__」といったキーボード操作や、スクリーンリーダー（音声読み上げブラウザ）への配慮などが備わっている。

###2-2. 目的に応じて機能を選択して、ダウンロードすることができる
jQueryUIはとても大きなライブラリだが、必要な機能のみをダウンロードすることもできる。
![jqueryui.com_download_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366833/6eb31432-2de5-9847-8d31-e8dae5bc99d6.jpeg)


##3. [注意]jQueryファイルの読み込む順番

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>TEST</title>
	<!-- CSS読み込み -->
	<link rel="stylesheet" href="./css/normalize.css">
	<link rel="stylesheet" href="./css/main.css">
	<!-- スクリプト読み込み ※※※読み込む順番に注意する※※※ -->
	<script src="./js/vendor/jquery-3.4.1.min.js"></script>
	<script src="./js/vendor/jquery-ui.min.js"></script>
	<script src="./js/main.js"></script>
</head>
```
先にjQueryのjsファイルを先に読み込んでから、`main.js`を読み込む。

先にjQueryを読み込んでおかないと、`main.js`のプログラムからjQueryを使用することができないから。