OmniAICreator/Qiita-1.07M huggingface dataset:
【Python入門】Pandas.DataFrameで複数の条件を満たす行を削除する方法

こんにちは。

最近は**Python**にも触れてる僕です。

今は社内の業務効率化で、経理がExcelとCsvを使って手作業で行っている入金消込処理を**Python**を使って自動化を試みています。
※「未だにExcelなの？」のようなツッコミはご遠慮ください。
当初は**VBA**か**C#**を使うかと思いましたが、せっかくならデータ処理が得意との噂の**Python**を使ってみようと思い、はじめて**Python**に触れてみてます。

Excel操作に**openpyxl**、データ処理に**pandas**を使っているのですが、未だに**pandas**には手を焼いており、**C#**なら瞬殺でコードが組める処理でも苦戦したりしています。

そんな苦戦したことをメモ代わりに書き残していきます。

今回のメモはこちら。

##Pandas.DataFrameで複数の条件を満たす行を削除する方法

「そんなん簡単じゃん！」とツッコミが入るかもですが、いろいろ試してたのでメモっておきます。

DataFrameの行を削除する方法を調べると、**drop**と言う関数がありました。
【公式】[pandas.DataFrame.drop](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html)

使い方は↓以下の通りです。
DataFrameのIndex番号を指定して削除します。

```python
import pandas as pd

#Excelファイルを読み込む
data_frame = pd.read_excel('{Excelファイルパス}', sheet_name='{シート名}', header=0)

#10行目(Index=9)を削除する場合
data_frame.drop(9)
#6行目(Index=5)と8行目(Index=7)を削除する場合
data_frame.drop([5,7])
#2行目(Index=1)から5行目(Index=4)を削除する場合
data_frame.drop(range(1,4))
```

今回は表題の通り「**取引先が〇〇かつ摘要が△△で始まるデータを削除**」と複数の条件を満たす行を削除します。

その為には、条件を満たすIndex番号を取得する必要があります。

DataFrameのIndex番号を取得する方法を調べると、**index**と言う関数がありました。
【公式】[pandas.DataFrame.index](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.index.html)

使い方は↓以下の通りです。

```python
#条件にマッチしたIndexを取得
drop_index = data_frame.index[data_frame['取引先'] == '〇〇']
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
```

うん、ちゃんと「**取引先が〇〇**」のデータを削除できました。
次に条件を増やしてみます。

```python
#複数の条件にマッチしたIndexを取得
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'] == '△△*****')]
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
```

よし、2つの条件のデータは削除できてる！
　：
ん？何か忘れてる・・・2つ目の条件は前方一致だった・・・どうやんべか・・・

とりあえず前方一致の**startswith**を試してみる。

```python
#DataFrameにstartswithで前方一致を試してみる・・・
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'].startswith('△△'))]

【結果】
Error:'Series' object has no attribute 'startswith'
```

「**Series**は**startswith**を持ってないよ！」と怒られました。

Pandasには、**str**と言う文字列処理を行えるアクセサ（アクセスメソッド）があり、前方一致で抽出できる**startswith**関数もあります。
【公式】[pandas.Series.str.startswith](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.startswith.html)

**str.startswith**で試してみます。

```python
#DataFrameのstrアクセサのstartswithで前方一致の条件を追加
drop_index = data_frame.index[(data_frame['取引先'] == '〇〇') & (data_frame['摘要'].str.startswith('△△'))]
#条件にマッチしたIndexを削除
data_frame = data_frame.drop(drop_index)
```

お見事！ちゃんと2つの条件のデータが削除できました！

「以上です！」と言いたいところですが、
上記の方法に辿り着くまでに、実は別の方法で実装していました。

```python
#DataFrameの最大行数までの範囲でループ
for i in range(len(data_frame)):
     #指定の列と行の値でチャック
     if data_frame['取引先'][i] == '〇〇' and data_frame['摘要'][i].startswith('△△'):
          #条件にマッチしたIndex番号を削除
          data_frame = data_frame.drop(i)
```

ちょっとアナログな方法ですが、データの行数分をループして1件ごと処理しています。
この方法でも2つの条件のデータをちゃんと削除できます。

他にもいろんな方法がありますが、今回は実際に試した方法を紹介しました。
以上になります。

次回も**openpyxl**や**pandas**を使って苦戦したところを投稿していこうと思います。

ここまで読んで頂き、ありがとうございました。
Rails　テーブルの制約について

<b>
Rails初心者の備忘録です。

#制約とは
Railsでテーブルのカラムやデータに制限を加え、想定通りの値が入るようにします。

例えば郵便番号のように数値のデータが欲しいとき、文字列が入ってしまうと機能がおかしくなってしまうこともあります。
そのため、制約を設定します。

#制約の種類
##データ型
一般的によく使われているのがデータ型で、以下のようなものがあります。

string	短い文字
text	長い文字
integer	数値（整数）
float	数値（浮動小数）
date	日付
datetime　日時
time	時刻
boolean	真偽

##NOT NULL制約
空欄を禁止する制約です。```null: false```を付けます。

```.rb
class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name  
      t.text :image_id, null: false  #これ
      t.text :caption
      t.integer :user_id
      t.timestamps
    end
  end
end

```
##UNIQUE制約
重複を禁止する制約です。```unique: true```を付けます。
例えば、同じユーザーネームを登録できないようにしたい時などに使えると思います。

```.rb
class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, unique: true #これ
      t.text :image_id, null: false  
      t.text :caption
      t.integer :user_id
      t.timestamps
    end
  end
end
```

##DEFAULT制約
初期値を設定しておく制約です。```:default => '' ```を付けます。

```.rb
class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, null: false  
      t.text :image_id, unique: true 
      t.text :caption, :null => false, :default => 'これは例です。'  #これ 
      t.integer :user_id
      t.timestamps
    end
  end
end
```
##主キー制約
主キーが必ずあって、重複もしてはいけないという制約です。idなどでよく使われるみたいです。
Railsでは、テーブルを作成する際にidカラムに元々実装されています。

##外部キー制約
IDなどのキーを利用してテーブルとテーブルを関連付けているとき、親元のテーブルにデータが存在していなければいけないという制約です。

やり方はいろいろあるみたいですが、reference型のものを記載します。
```t.reference :user```の後に``foreign_key: true``を付けます。

このとき、カラム名は```user_id``で、自動でインデックスを割り振ってくれます。嬉しい。笑

```.rb
class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, null: false  
      t.text :image_id, unique: true 
      t.text :caption, :null => false, :default => 'これは例です。' 
      t.references :user, foreign_key: true  #これ 
      t.timestamps
    end
  end
end
```

<b>
他にもいろいろとあるみたいですが、重要なものをメモしてみました。

##参考にしたサイト
[Railsの外部キー制約とreference型について](https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47)
VSCodeでAtcoder用の開発環境を整える


## はじめに
atcoderを始めて2ヶ月ちょいのaxpensiveです。
色はまだ灰色。
[これくらい](https://kenkoooo.com/atcoder/#/user/axpensive?userPageTab=AtCoder+Pie+Charts)問題を解いてます。

今までのC++開発環境は

* OS
    * Mac
* 仮想環境
    * Parallels Desktop for Mac 
* IDE
    * Visual Studio
* 仮想環境OS
    * windows10
* C++コンパイラ
    * Clang

というVisual Studioを使うためにMacの中でwindows10の仮想環境を立ち上げていました。
ですが、競プロでレートを上げやすくするために開発環境を変えようと思いました。

## VSCodeとは
テキストエディタ
[こちら](https://code.visualstudio.com/)でダウンロードできます。

## この記事の対象者
* C++開発環境をMac, VSCode, GCCで構築したい方
* プログラミングができる、Gitを使ったことがある方
* Atcoderでより早く問題を解きたい方
* 解いた問題の解答を整理したい方
* step実行などIDEにある高級な機能を求めない方

## なぜ環境構築し直したか。

### レートを上げるため
Atcoderに参加してこうすればレートが上げられると思った。

* A〜C問題をなるべく早く解く
* D問題まで解答する。

この中で目指しやすいと思ったのは、A〜C問題をなるべく早く解くだったので、開発環境を改善して解く速度を上げようと考えた。
また、vscode用のatcoder支援ツールなどを活用できるというのもある。

### 復習しやすくするため
AtCoder Problemsなどすごい学習支援サイトはあるが、書いたコードを検索しやすいサービスはないと思ったので、自分で環境を作ることにしました。

## どう環境構築したか。

### 1.C++を実行できるようにする。
[ここ](https://qiita.com/EngTks/items/ffa2a7b4d264e7a052c6)を参考にしました。

#### 記事でつまづいたところ

##### ショートカットキーでコードを実行できなかった。
⌥⌘nで実行できなかった
同じことで悩んでいるユーザーもいるみたいでしたが、原因は不明。
違うショートカットを割り当てれば解決できた。
https://github.com/formulahendry/vscode-code-runner/issues/286

### 2.整形ルールを設定する。
[この記事](https://qiita.com/y-w/items/614843b259c04bb91495)で設定ファイルを開き、一番下に下記の文字列を追加する。
この設定だと綺麗にコードを整形できますし、細かく保存してくれるので書いたコードがなくなることは殆どありません。

```setting.json
  "C_Cpp.clang_format_style": "Google",
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,
  "markdown-pdf.convertOnSave": true,
  "editor.formatOnType": true
```

### 3.git管理ができるようにする。

最終的にディレクトリ構成図のようになります。
Git管理サービスはGithubがおすすめです。

```ディレクトリ構成図.
├── .vscode
├── .gitignore
├── README.md
└── コンテスト名
    ├── A_問題名.cpp
    └── B_問題名.cpp
```

####.gitignoreの内容
* 実行ファイル(拡張子なし)を含めない。
* .DS_Storeを含めない

```　.gitignore
*
!*/
!*.*
.DS_Store
```


## 終わりに
ほとんど引用で申し訳ありませんが、自分のように環境構築したけどやりにくさを感じている人に役立てたなら幸いです。
もっとAtcoderを頑張って水色までいきたいです！
firestoreでユニークな連番を作る

諸事情でfirestoreのドキュメントのUID文字列ではなく、
ユニークな数字が必要になったので、がんばる。
RDBのインクリメントID的な存在の何かをfirestoreで。

firebase functions上で作ってるので、クライアントでどうやるかはわかってないです。

```js
async () => {
  const doc = fireStore
    .collection('something_counters')
    .doc('something-groups')
  const uniqueNumber = await fireStore.runTransaction(async (t) => {
    const tDoc = await t.get(doc)
    const newNumber = ((tDoc.data() && tDoc.data().number) || 0) + 1
    await t.set(doc, { number: newNumber }, { merge: true })
    return newNumber
  })
}
```

- 適当なcollection ( `something_counters` ) を用意する
- documentのIDを適当に指定することで、その単位でユニークな数字を生成できる
- トランザクションかけながらインクリメントして数字を返す

雑に確認した感じ大丈夫そうだけど、そこまで強い確信もててるわけじゃないので、実は重複しちゃったらごめんさい。
ショートコント　ショート

# はじめに
電気初心者が、過放電させてしまったリポバッテリーを無理やり回復しようとした話です。

# 過放電とは
ノートパソコンのバッテリーとか、エネループの充電池ってほんとによく出来ている。
電池を使いきった後も、充電器につなげば回復するのですが、リポバッテリーというのはどうもそうではないらしく（詳しくないけど）、電池を使いすぎると、充電器につないでも充電できなくなります。
例えバッテリーをまだ2回しか使っていなくても、過放電して死にます。

# バッテリーってそんなに安くないから
どうにか回復させたくて、調べたら、もっと強い充電器に突っ込んだら直った、みたいな記事がいくつかあったのですが、充電器は専用のもの1個しか持っていません。
考えた末、「とりあえず電流ぶっこんだら直るかな？」というのをやって見ようと思いました。
今思えば、なんてアホなんだろうって思います。

# ラジコンのバッテリーを直接つないでみた
![P4260603.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228050/5f81de9b-437e-97ac-e71b-01462968a463.jpeg)

とりあえずプラス極っぽいところ（あかん）と、マイナス極っぽいところ（あかん）に、バッテリーをブスっとさして「オラっ！」と電流を流してみた。

#result
ショートしました。
**主な症状**

- パチって音がしました
- ケーブルから煙があがりました
- 慌てて抜こうとしたらケーブルが熱すぎて「熱っ！」って声が出ました
- ケーブルとコネクタが熱で溶けて、抜けなくなりました

# 皆さん、絶対マネしないでください

現場からは以上です。
【Rails】日本語表記化（ページネーション、エラーメッセージ）

railsで英語表記になっているものを日本語にする方法があります。

#ページネーション
Railsのgemである`will_paginate`のラベルを日本語に変えます。

■デフォルト
<img width="391" alt="スクリーンショット 2020-04-26 0.33.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/97236cc1-decd-ab2c-0ae4-6ded37df66d7.png">

■日本語表記後
<img width="308" alt="スクリーンショット 2020-04-26 0.43.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/8a59edd4-472d-7d79-31de-777cbebb4775.png">

##実装
まず`config/environment.rb`に以下を記述します。

```config/environment.rb
WillPaginate::ViewHelpers.pagination_options[:previous_label] = '&lt 前へ'
WillPaginate::ViewHelpers.pagination_options[:next_label] = '次へ &gt'
```
そして該当のページネーションに追記します。

```rb
<%= will_paginate %>
↓
<%= will_paginate , previous_label: '&lt 前へ', next_label: '次へ &gt'%>
```
これで実装できます。

#エラーメッセージ
■デフォルト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/0ce66373-7876-c4f9-eda9-96af3fdd0801.png)
■日本語化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/6fff25d0-090c-b6d3-de24-82c17321432e.png)

##実装
Gemfileにて下記をインストール

```:Gemfile
gem 'rails-i18n'
```
次に`config/application.rb`で以下を追記

```config/application.rb
config.i18n.default_locale = :ja
```
これだけでも日本語表記化されますがモデルのカラム名などが英語のままです。
そこで`config/locales`内に`ja.yml`を追加し下記を入力してください。

```config/locales/ja.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前
        email: メールアドレス
```
これで名前とメールアドレスが日本語表記になります。
AWS Amplifyの問い合わせにtypescript + useQuery<T>で楽したい

# モチベーション
amplifyの普通の問い合わせでは、全て型の世界に閉じ込めようとすると書き方がだいぶ冗長になる。
`apollo-client`のuseQueryを使えば簡潔に書ける上に、ジェネリクスによって型のサポートもあるし、`loading`の状態も検知できる。
でも`apollo-client`を使う方法は、接続設定の記載自体が必要だし、すべてがamplifyの機能に寄せれなくなる可能性がある。
https://qiita.com/sakapun/items/8084d61156b660a8fde1

## 公式サポートはまだない
プロポーザルはあったみたい.
https://github.com/aws-amplify/amplify-js/issues/4235

## カスタムHooksを使って解決できる
https://dev.to/mwarger/aws-amplify-graphql-queries-with-typescript-and-hooks-1e2

こちらの記事から続く4記事の連載で、書き方が学べる。
一つ一つ丁寧に説明されていて、すごくわかりやすい。感謝。
翻訳はしません。

## 作者のライブラリは使わずに、アプリ内にコードを配備しよう
npmパッケージにしてくれているが、`AWS Amplify`周りのライブラリはすぐバージョンアップするので、使えなかった。
https://www.npmjs.com/package/amplify-query-helpers


なので、作者のGithubのコードを自分のアプリ内に配備したほうがいい。
自分は`src/libs/amplify-query-helper/index.tsx`に設置している
https://github.com/mwarger/amplify-query-helpers/blob/develop/src/index.tsx

必要なライブラリは一個だけだった。

```bash
npm i --save-dev @types/zen-observable`
```

注： この型定義は実は最新バージョンだと最終的に必要ないのだが、一度試しに全コピペしてuseQueryを使う分には要る。
というか、dev.toの記事のとおりにuseSubscriptionを使おうとすると動かなくてハマる。  

最新バージョンだと、amplify内部でzen-observable-tsを使うようになっているので、ちょっとコードの改造がいるという解説記事を後で書く, todo。


## 関連投稿：レスポンスの型定義がほしい！
こちらの記事にかいた
https://qiita.com/sakapun/items/247f539da30c14f65c5f
JavaScriptにおいて配列の取扱説明書

# JavaScriptでの配列は？？
結論から言うと、**Rubyとほとんど一緒**です。
実際のコードをみながら説明していきます。

# 実際にconsole.log()で確かめてみた
console.log()って何？って思った人は以下の記事を必ず読んでください。
[console.log()って何なの？](https://qiita.com/Nyanmaru-12/items/fc430a1ee28c26901e91)
必要なファイルは以下の２つ
:page_facing_up:index.html
:page_facing_up:script.js
そしてscript.jsに以下の記述をしましょう。

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
console.log(list);
```
index.htmlをブラウザ上で開き、検証画面のコンソールで以下のように出力されてるはずです。
<img width="1439" alt="54D93F7C-E274-4806-ADC1-0FA1A2946CA6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/bbef7958-6a39-b882-1830-d044ac093f39.png">
ここから取り出してみたり色々遊んでいきます。
##配列から要素を取り出す方法
Rubyと一緒なのですが、復習もかねて。
ここでさっきの検証画面でもっと詳細に配列の中身をみてみましょう。
<img width="1101" alt="F81487BC-20E6-4781-B33D-F979866BE6DC_1_105_c.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/c97bbc9f-8589-0993-a0c0-532a2d8286e8.jpeg">
それぞれ番号がふられています。
０から振られているのに気づきましたか？**１から始まるのではなく、０から始まります。**
以下のように要素を取り出してみます。
作業はscript.js

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
console.log(list[1]);
```
記述できたら検証画面をみていきましょう。
<img width="1200" alt="B2BF35A2-E591-4EA9-86C0-736643C2F5C6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/a919bfa5-c667-7470-29b4-1b60ae248793.png">
Hanakoが出てくるはずです。**ポイントは０から始まることです。**
##配列の要素数を調べる
これも**Rubyと一緒**です。
**lengthメソッド**を使います。
script.jsに、以下記述。

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
console.log(list.length);
```
そうすると、検証画面に以下のように出てくるはずです。
<img width="1200" alt="CE1458A2-8561-4D7A-A22B-1933C25FADC1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/6ee90663-c68d-bc2f-c811-0e0a8277a546.png">

##配列に要素を追加する
これもRubyと一緒です！
**pushメソッド**を使います。
作業はscript.jsで

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
list.push("Sato")
console.log(list);
```
<img width="1197" alt="0A02B2D3-E9F6-44AB-B237-05E3BC586C81.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/35fd1468-bbef-a7fe-9f74-5a753c7f36c2.png">
一番最後にSatoが追加されているのが確認できます。
##配列から要素を削除する。
これはRubyとちょっと違います。
Rubyでは要素番号を指定して、指定の要素が取り消せたかと思いますが
~~JavaScriptではそれが**できません。**~~
spliceを使えばできます。

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
list.splice(2, 1);
console.log(list);
```

**popメソッド**を使いましょう。
作業はscript.jsで。

```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
list.pop()
console.log(list);
```
<img width="1194" alt="8EDF2569-4F98-4748-9527-BF819A2806C5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/0f38edbf-63cb-65b9-1399-3ec034b5dab1.png">
**一番最後のKatoがコンソール上では反映されていない**のが分かります。
**今度はshiftメソッド**を使ってみましょう。


```javascript
let list = ['Yamada', 'Hanako', 'Taro', 'Suzuki', 'Kato'];
list.shift()
console.log(list);
```
<img width="1192" alt="B1799B29-E59F-4EE5-9603-DF22565BD8A7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/9448b6a9-e3c5-8015-9ab5-55143735ad14.png">

今度は**一番最初のYamadaがコンソール上では反映されていない**のが分かります。

さあ、これで配列を恐れなくて大丈夫！次回はオブジェクトでも書こうかな。

※本記事に登場する文字列は意図的な文字列ではなく、ジャストアイディアで生まれたものです。
ダウンロードしたHTMLに対してスクレイピングしてCSV出力

ダウンロードしたHTMLファイルに対してスクレイピングをかけてCSV出力したいときにどうぞ

（例えば。。。ツイッターのフォロワー画面は無限スクロール機能があると思います。最深部までスクロールした状態のHTMLをchoromeの検証機能でダウンロードしたらCSV形式であなたのフォロワーリストが作れますよ）

---

ディレクトリ構造
scraping
┝ target_html
┃　┗ target.html
┝ scraping.rb
┗ result.csv

---

対象HTMLの構造

```target.html
(省略)
<tr>
  (省略)
  <div class="name">
    <a>
      <span>なまえー</span>
    </a>
  </div>
　(省略)
  <div class="id">
    <a>あいでぃー</a>
  </div>
　（省略）
</tr>
（以下複数の別のtr）

```

```scraping.rb
require "nokogiri"
require "csv"

f = File.open('./scraping/target_html/target.html')
doc = Nokogiri::HTML(f)

infos = []
trs = doc.xpath('//tr')

trs.each do |tr|
  name = tr.css('div[@class="name"]').css('a').css('span').inner_text
  id = tr.css('div[@class="id"]').css('a').inner_text
  info = [name,id]
  infos << info
end

CSV.open('result.csv', 'w') do |csv|
  infos.each do |info|
    csv << info
  end
end

f.close()

```
###結果
```result.csv
なまえー,あいでぃー
なまえー１,あいでぃー１
なまえー２,あいでぃー２
　︙
```

以上
Ubuntu 18.04.4 DesktopにWindowsからRDP接続

# 前書き
Ubuntu 18.04.4 DesktopにRDP接続したかっただけなのに、いろいろ躓いたのでまとめる。

# HWEをGEに入れ替える
Ubuntu 18.04 DesktopにはHWEが入っているがこれがあると後でインストールするxrdpが動かなくなる。なのでxrdpをインストールする前にHWEをGEに入れ替える。
[参考サイト](https://qiita.com/gbgb-ojisan/items/4a3e261183bdde588d32)

```
sudo telinit 3 #コンソールログイン
apt update
apt -y purge ubuntu-desktop xorg # xorgを入れ替えるのでpurge
apt install linux-generic # GEカーネルインストール
apt purge linux-generic-hwe-18.04 # HWEカーネル削除
reboot
sudo telinit 3
apt purge xserver-xorg-core-hwe-18.04 xserver-xorg-input-all-hwe-18.04 xserver-xorg-legacy-hwe-18.04 linux-headers-generic-hwe-18.04 linux-image-generic-hwe-18.04 # HWE関連パッケージ削除
dpkg -l | grep hwe # HWE関連パッケージが残っていないか確認、あれば削除
apt install xserver-xorg-core
apt install ubuntu-desktop xserver-xorg xserver-xorg-video-all xserver-xorg-input-all libgl1-mesa-dri libgl1-mesa-glx
reboot
```

# xrdpをインストールする
[参考サイト1](https://note.spage.jp/archives/576)
[参考サイト2](https://linux.just4fun.biz/?Ubuntu/Windows%E3%81%8B%E3%82%89Ubuntu%E3%81%AB%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B)

```
sudo apt install xrdp
cat <<EOF > ~/.xsessionrc
export GNOME_SHELL_SESSION_MODE=ubuntu
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop
export XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
EOF
sudo sed -e 's/^new_cursors=true/new_cursors=false/g' -i /etc/xrdp/xrdp.ini

cat <<EOF | \
sudo tee /etc/polkit-1/localauthority/50-local.d/xrdp-color-manager.pkla
[Netowrkmanager]
Identity=unix-user:*
Action=org.freedesktop.color-manager.create-device
ResultAny=no
ResultInactive=no
ResultActive=yes
EOF

sudo reboot
```

# xrdpユーザをssl-certに追加する
このままだと`Cannot read private key file /etc/xrdp/key.pem: Permission denied
`とエラーログが出るので権限を追加する

```
sudo gpasswd -a xrdp ssl-cert
```

# RDPからログインするユーザをログアウトする
RDP以外からログインしているとRDP接続できないようなのでRDP以外からはログアウトする
ドメインを管理しているネームサーバーを調べる方法

お名前.com などでドメインを取得した後は、ネームサーバーを、ウェブサイトをホスティングしているサービスのネームサーバーに切り替える必要があります。（ホスティング・サービスでドメインを買えるところもありますが、お名前.com で買う事が多いかなと思います）

例えばウェブサイトを Netlify で作った場合は、以下のネームサーバーを指定して、[ドメインの管理を委任](https://docs.netlify.com/domains-https/netlify-dns/delegate-to-netlify/)します。

```
dns1.p04.nsone.net
dns2.p04.nsone.net
dns3.p04.nsone.net
dns4.p04.nsone.net
```

ネームサーバーの切り替えは時間がかかることがあり、[お名前.com の説明](https://help.onamae.com/answer/8081)によると、最大72時間ほど待つ必要があります。（これはDNSのTTLの最大値などが関係していて、全体に浸透するのに掛かるであろう時間らしいです）

ホスト名をブラウザに打ち込めば、IPアドレスが解決できているか、簡単に調べられますが、ネームサーバーを切り替えるときは、これだと切り替わっているかどうかは、分からないので `dig` コマンドを使います。

`dig` コマンドに `ns` をつけると、ネームサーバーが確認できます

```
$ dig example.com ns

; <<>> DiG 9.10.6 <<>> example.com ns
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54382
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;example.com.			IN	NS

;; ANSWER SECTION:
example.com.		3643	IN	NS	a.iana-servers.net.
example.com.		3643	IN	NS	b.iana-servers.net.

;; Query time: 5 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sat Apr 25 23:57:54 JST 2020
;; MSG SIZE  rcvd: 88
```

`example.com` は `a.iana-servers.net` と `b.iana-servers.net` というネームサーバーで管理されていることがわかります。因みに `example.com` は IETF が保有しているドメインで、ドメインが悪用されないようになっているので、サンプル・コードを書く場合に、クリックされても安全なドメインとなっています。
Force Install .msi file Command (Windows)

1. Create a new empty folder on the root drive (C:); call it temp or tmp.

2. Copy example.msi package into the temp folder.

3. Open Terminal which called Command prompt Windows

4. Go to the C: folder (command : cd ../..)

5. Type following command and enter cd temp/example.msi / qb

6. Follow installation process.


When I cant install GlobalProtect64.msi , I used this process.
Please try it.
Django DB初期化時のコマンド

DjangoのDBを作り直したいときのため、コマンドを自分の備忘録のために残しておきます。

1. cd (削除したいアプリケーション)
2. rm -d -r migrations/
3. cd (プロジェクトファイル)
4. rm -d pr db.sqlite3
5. python manage.py makemigrations (アプリケーションネーム)
6. python manage.py migrate
7. python manage.py createsuperuser
gazeboのシミュレーター環境

Gazeboには、4種類のphysics enginesがあります。

- ode
- bullet
- simbody
- dart

今回はこの4種の違いを簡単に調べました。


### ODE
- Open Dynamics Engine 
- Gazeboのデフォルト
- Gazebo debianで利用可能
- 簡易ロボットダイナミクス
- 乱雑な環境をシミュレート
- 最大座標ソルバー

### Bullet
- Gazebo debianで利用可能
- ゲーム向け
- 乱雑な環境をシミュレート
- 最大座標ソルバー
 
### DART
- Dynamic Animation and Robotics Toolkit
- source install
- コンピュータグラフィックスおよびロボットコントロール
-  Georgia Tech発
-  Featherstoneベースのソルバー
-  ヒューマノイドロボットなどの多関節システムのシミュレーション
  
### Simbody
- source install
- バイオメカニクス
- Stanford発
- Featherstoneベースのソルバー
- ヒューマノイドロボットなどの多関節システムのシミュレーション
 

また随時情報を更新したいです。

参考
[GAZEBO Physics Parameters](http://gazebosim.org/tutorials?tut=physics_params&cat=physics)

[GAZEBO New Feature Highlight: Multiple Physics Engines](http://gazebosim.org/blog/feature_physics)
Amplify（Appsync）でApollo clientを使う2020年4版

#Tl;Dr

https://qiita.com/yuuyun/items/a20192ecd7a6a45db5f3
の記事でやると、`apollo-client`のバージョンアップせいで動かない

https://medium.com/@guillac124/create-your-custom-apollo-client-for-aws-appsync-to-use-hooks-2d5cbce29db5
の記事を参照に治すコードを最後に提示する

## モチベーション
AWS Amplifyでサーバレスアプリケーションの簡単な構築を試していて、つなぐところまでなんとかできた。
しかし、React Hooksで書こうとしたらとても冗長になって嫌だった。
なので、もっと楽できる方法はと思い、[上記](https://qiita.com/yuuyun/items/a20192ecd7a6a45db5f3)の記事が見つかった。
useQueryめっちゃ使いたくなったので、そのとおりにやったらここ一年のアップデートのせいでうまくいかなかったので、その対策法を残す

## 解説
当時のバージョンに固定させてもなんとかなるけれども、それは悪手だから今の書き方にあったようにしような。と[対応方法記事](https://medium.com/@guillac124/create-your-custom-apollo-client-for-aws-appsync-to-use-hooks-2d5cbce29db5)には書かれている。
その、別の書き方で進めるが、また時期の違いとして`@apollo/client`を使っていく。
まだβ版だが、そちらを使うとライブラリの多くを一つで済ませられる

`npm i @apollo/client aws-appsync-auth-link`

さて、あとはサンプルコードである。

```typescript
 import { ApolloProvider, ApolloClient, ApolloLink, createHttpLink, InMemoryCache } from '@apollo/client';
 import { createAuthLink } from 'aws-appsync-auth-link';
 

 const authConfig = {
   url: awsExports.aws_appsync_graphqlEndpoint,
   region: awsExports.aws_appsync_region,
   auth: {
     type: awsExports.aws_appsync_authenticationType,
     jwtToken: async () =>
       (await Auth.currentSession()).getIdToken().getJwtToken(),
   }
 }
 
 const link = ApolloLink.from([
   // @ts-ignore
   createAuthLink(authConfig),
   createHttpLink({uri: authConfig.url})
 ])
 const client = new ApolloClient({
   link,
   cache: new InMemoryCache()
 });

ReactDOM.render(
  <ApolloProvider client={client}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </ApolloProvider>,
  document.getElementById('root'),
);
```


## TSのエラーが出る問題
`@apollo/client`はβ版（3.0.0-beta.44）であり、2020年4月25日現在、正しく型を扱っていてもエラーが出る

``` typescript
createAuthLink(authConfig)
```
の部分で型エラーが出る。
https://github.com/apollographql/apollo-link/issues/1258


なので、エラー無視で潰すしか無い。

```
// @ts-ignore
```

で潰したほうが実践上良さそう。

### ts−ignoreを使わない潰し方

```typescript

 import { ApolloProvider, ApolloClient, ApolloLink, createHttpLink, InMemoryCache } from '@apollo/client';
 import { createAuthLink } from 'aws-appsync-auth-link';
 
 
 const authConfig = {
   url: awsExports.aws_appsync_graphqlEndpoint,
   region: awsExports.aws_appsync_region,
   auth: {
     type: awsExports.aws_appsync_authenticationType as "AMAZON_COGNITO_USER_POOLS",
     jwtToken: async () =>
       (await Auth.currentSession()).getIdToken().getJwtToken(),
   }
 }
 
 const link = ApolloLink.from([
   createAuthLink(authConfig) as unknown as ApolloLink,
   createHttpLink({uri: authConfig.url})
 ])
 const client = new ApolloClient({
   link,
   cache: new InMemoryCache()
 });
```

非常に微妙であるが、サンプルに載せておく。


# そもそも、本当にapollo使う必要あんの？？？？
なんとかしてamplifyでapollo + appsyncが使えるようになったわけだが、本当にapolloっているの？と疑問が生じた。
私が使いたかったのはuseQueryという簡単に書くための記法である。

その解説については、一応別記事あつかいとする。
[AWS Amplifyの問い合わせにtypescript + useQuery<T>で楽したい](https://qiita.com/sakapun/items/26e234b04faa7972a885
)
Elasticserachをlocalhost以外で起動する方法

 Qiita初心者です．よろしくお願いいたします．

この記事では，Elasticserachをlocalhost以外でバインドする際の設定方法を記載しています．localhost以外で起動すると，localhostの時よりも起動時ののチェックが厳しくなります．この記事ではlocalhostの時の設定に加えて必要な設定方法を記述します．

##環境
私の環境は次の通りです．

- Elasticsearch 7.3.2　
- ubuntu 18.04.1

## localhost 以外でバインドする

例えば，インターフェスの指定がしたい場合次のように指定ができます．

```yaml:elasticsearch.yml

network.host: [_<インターフェース名>_,_local_]
```

*(elasticsearch.ymlは，.tar.gzでunzipした場合config/フォルダ内に，apt等でインストールした場合 /etc/elasticserach/にあります．)*

IPアドレスで指定する場合は次のように指定できます．どのインターフェスからもElasticserachがアクセスできるようにしたい場合0.0.0.0でできます．ただし，セキュリティ上あまりオススメはしません．

```yaml:elasticsearch.yml

network.host: 192.168.1.xx
```
(https://www.elastic.co/guide/en/elasticsearch/reference/current/network.host.html より参照)

## マスターノードの指定

Elasticserachでは，複数のコンピュータ(ノード)でデータを共有することができます．それ関連して，マスターノードを指定する項目があるのですが，localhost以外でバインドする場合，この設定がされていないと次のエラーが出ます．

```
the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
```

####一つのノード単独で行う場合

次の設定を入力すると一つだけのノードとして起動するようになるため，マスータノードに関する起動時のエラーは発生しなくなります．

```yaml:elasticsearch.yml

discovery.type: single-node

```
(https://www.elastic.co/guide/en/elasticsearch/reference/current/bootstrap-checks.html#single-node-discovery 　より参照)

####複数ノードを設置する予定がある場合

複数ノードを設置する予定がある場合次のように設定します．

```yaml:elasticsearch.yml

cluster.initial_master_nodes: ["node-1"]

```

また，いま設定をしているelasticsaerchのノード名も指定しておきます．

```yaml:elasticsearch.yml

node.name: node-1

```
(https://www.elastic.co/guide/en/elasticsearch/reference/7.6/discovery-settings.html  より参照)

##仮想メモリの設定(rpmやapt等でインストールした場合必要なし)
仮想メモリを増やす設定をしないと次のエラーが発生します．

```
max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
```
仮想メモリを増やす設定は次のコマンドでできます．なお，rootユーザで実行する必要があります．

```shell:
sudo sysctl -w vm.max_map_count=262144
```
(https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html  より参照)

##ページサイズの変更(rpmやapt等でインストールした場合必要なし)
ファイルディスクリプタを65535に変更しないと起動しません．次のコマンドを入力すると，起動できます．なお，ulimitで指定した後exitで抜けてしまうとulimitの変更が元に戻ってしまいelasticsaerchが起動しなくなりますので注意してください．

```shell:
 sudo su  
 ulimit -n 65535 
 su <ユーザ名>
 ./elasticsearch #Elasticsearchをこのションで起動
```

(https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-system-settings.html#ulimit　 より参照)
この設定をしないと次のエラーが出力されます．

```
max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
```

##参考サイト
Important System Configuration - Elasticsaerch Reference
https://www.elastic.co/guide/en/elasticsearch/reference/current/system-config.html
Neo4j入門

#はじめに
Neo4jは3.5系と4.0系があります。
4.0系はJAVA11が必要です。

環境変数にJAVA_HOMEに変更すると、ほかの開発（JAVA８）にも影響がありますので、Neo4jのみJAVA１１を使うように設定が必要です。

#Neo4jとは
Neo4jはJavaで実装された、 オープンソースの最も人気のあるグラフデータベースである

Neo4j: https://neo4j.com/

DBランキング：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/c18664cb-2a7c-647d-cfdf-f643710253db.png)

Graph DBMSランキング：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/46e8c55a-6cd1-6163-6986-3730271f7b09.png)

出典：https://db-engines.com/en/ranking

#Neo4j４インストール
##ダウンロード
URL：https://neo4j.com/download-center/#community
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/68881107-c7c1-0a24-09d8-44986d51ca45.png)

##ダウンロードしたZIPを解凍
適宜な場所に解凍。例：C:\neo4j-community-4.0.3

##JAVA_HOMEをPSファイルに追加
修正ファイル：neo4j-community-4.0.3\bin\neo4j.ps1

```powershell
# 一時的にJAVA_HOMEをJAVA１１で設定
$env:JAVA_HOME = "C:\jdk-11.0.7"

try
{
    Unblock-File -Path '%~dp0Neo4j-Management\*.*' -ErrorAction 'SilentlyContinue'
}
catch
{
};
```

##Neo4j起動
```
 .\neo4j.bat console
```

サービスに登録したい場合は、`.\neo4j install-service`

##ブラウザからアクセス
http://localhost:7474/browser/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/6779f7b1-26af-3527-63f2-4ea307eb0db8.png)


##ログイン
Username:neo4j
Password:neo4j
を入力してConnectボタンを押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/914a1603-149a-a99c-77f2-263de3302ba0.png)

新しいパスワード入力して変更した後TOPページに遷移
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/fb3b743e-dcbf-3e36-96dd-c813bd319923.png)

#データ操作
コンセプト：

- Nodes - graph data records
- Relationships - connect nodes
- Properties - named data values

##Cypher
Neo4j's Cypher language is purpose built for working with graph data.

URL: https://neo4j.com/docs/cypher-manual/4.0/introduction/

###Create例
```cypher
CREATE (tanaka:Person { name: "田中　一郎", from: "Tokyo", age: 20, gender: "male" }),(yamato:Person { name: "大和 美奈子", from: "Tokyo", age: 19, gender: "female" }),
(suzuki:Person { name: "鈴木　涼", from: "Tokyo", age: 22, gender: "male" })

CREATE (tanaka)-[:KNOWS]->(yamato),(tanaka)-[:LIKES {from: 2019}]->(yamato),(yamato)-[:KNOWS]->(suzuki)
```
###検索例
```cypher
MATCH (tanaka:Person) WHERE tanaka.name = "田中　一郎" RETURN tanaka;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/f96da9b1-1ca5-fa64-4c20-85404afada6f.png)


###Delete例
```cypher
MATCH (n { name: '田中　一郎' })
DETACH DELETE n
```

###すべて削除
```cypher
MATCH (n)
DETACH DELETE n
```


以上
代替手段の探し方

新しいものを勉強する時や久しぶりに触るミドルウェアとかアプリケーションについて、もっといいものあるんじゃないかなって時にどうしてます？

自分は
`アプリケーション名 alternative`
って検索してみてます。

例）
`nvm alternative`
node.jsのversion　managerの代替アプリを探した場合。
[nve](https://github.com/ehmicky/nve)って製品が見つかりました。

あとは出てきたものと、元の製品とあわせて
`nvm nve`
とか調べてみたりします。
Railsの開発環境でサブドメインをテストする

# 概要
Railsではデフォルトではlocalhost:3000で開発環境にアクセスできますが、
ルーティングをサブドメインで切り替えるテストをしたいなと思った時にハマったので、解決策を示します。

# ルーティング

```rb:routes.rb
# hostがexample.comの時だけアクセスさせたい
constraints host: example.com do
  get 'top', to: 'top#index'
end
```

# 新しいドメインを追加する
OSがmacまたはlinuxの場合は、/etcディレクトリに、windowsの場合はC:\Windows\System32\driversに存在するhostsファイルに新しいドメインを追加します。

```linux:hosts
127.0.0.1	localhost	example.com
```

これで、127.0.0.1というIPアドレスにlocalhostとexample.comというホスト名を設定できました。

# Blacked Hostsの設定
Rails6を使用している場合は、アクセス可能なホストにexample.comを追加しましょう。
Blacked HostsはRails6の新機能で、ブラウザがRailsアプリケーションにアクセスする際に使用できるホスト名を制限するためのものです。
デフォルトでlocalhostのみが許可されています。

```rb:config/initializers/blocked_hosts.rb
Rails.application.configure do
  config.hosts << "example.com"
end
```

これで、以下サブドメインにアクセスすることができます。
`http://example.com:3000/top`

# おまけ
ちなみに、blocked_hostsを追加するとrspecが通らなくなるので、rpsec用のホストを追加します。

```rb:test_spec.rb
Spec.describe "Admin::StaffMembers", type: :request do
  p admin_staff_members_url
end

結果:
"http://www.example.com/admin/staff_members"
```

rspecではホストがwww.example.comでアクセスしているようなので、blocked_hostsにwww.example.comを追加します。

```rb:config/initializers/blocked_hosts.rb
Rails.application.configure do
  config.hosts << "example.com"
  # rspecが通らないので、以下ホストを追加
  config.hosts << "www.example.com"
end
```

これで、テストが通るようになります。
java開発環境構築

参考にした記事
https://manga.crocro.com/?cat=java&pg=make_cui_app
javaの環境構築まで終わり。
アプリケーションまで作業したがやったばかりで全然わからない。

名前変更
実行ボタンで右クリック
[![Image from Gyazo](https://i.gyazo.com/b1cc03292639b2bbf6e3604341e40614.png)](https://gyazo.com/b1cc03292639b2bbf6e3604341e40614)
GASでGoogleカレンダー1週間分の予定をLINEに通知する

きっかけ：どうしても予定を忘れるときがあるので…

## 出来上がり
GASでGoogleカレンダーから1週間分の予定を取得、LINEに通知します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/8595d060-f865-935a-9ae1-c5ba7d7a6155.jpeg" width="300px">

#### 今回やっていないこと
* 祝日対応
* 2日以上をまたいだ予定の通知

## 実装
今回必要なものはこちら

* GAS（Google App Script）
* LINE Notify

### LINE Notify
[LINE Notify](https://notify-bot.line.me/ja/)にログイン、マイページのアクセストークンの発行(開発者向け)でトークンを発行する。
トークン発行時、トークン名（通知のタイトル）と通知先トークルームを選択するのだが、どちらかを変更したい場合はトークンを再発行する必要がある。

### GASを書く
#### GASの新規作成
Googleドライブ＞新規＞Google App Scriptを選択

#### プロジェクトのプロパティを記述
環境変数にあたる値は直接スクリプトに記述せず、ファイル＞プロジェクトのプロパティに追加する。
今回は、GmailのカレンダーID、LINE Notifyで発行したトークン。
個人のカレンダーならカレンダーIDは自分のGmailのアドレス "***@gmail.com" を指定する

#### Googleカレンダーから予定を取得
```
function thisWeekSchedules(now) {
  // プロパティに指定した値を取得する
  var calendar_id = PropertiesService.getScriptProperties().getProperty('CALENDAR_ID')
  var calendar = CalendarApp.getCalendarById(calendar_id);
  // 1週間の開始日時と終了日時
  var startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  var endDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()+7, 23, 59, 59);
  // 指定した期間の予定の取得
  var events = calendar.getEvents(startDate, endDate);
  return events;
}
```

#### LINEに通知を送信
```
function sendLineNotify(message) {
  // LINE_TOKENにはLINE Notifyで発行したトークンを指定する
  var accessToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
  var message = message
  var options = {
     'method'  : 'post'
    ,'payload' : 'message=' + message
    ,'headers' : {'Authorization' : 'Bearer '+ accessToken}
    ,muteHttpExceptions:true
   };
  // 通知を送信
  UrlFetchApp.fetch('https://notify-api.line.me/api/notify', options);
}
```

#### ログの出力の仕方

```
Logger.log("message = " + message);
```
表示＞ログで実行時のログを確認できる。

### 実行トリガーの指定
編集＞現在のプロジェクトのトリガーを表示を選択
トリガーを追加、で実行したいタイミングを指定する。
（今回のスクリプトは毎日1回実行される想定で書いてます）

## 今回のスクリプト
今回作成したスクリプトはGistにあげています。
[gist](https://gist.github.com/kn339264/dfe021e8bc6eda75f7dab3f73a0d96c3)
RStudioで「figure margins too large」を回避する

## 「figure margins too large」が発生する理由

描画したいグラフの大きさに対し、プロット領域が狭いときに出力されるエラー。

次のように、Plotsウィンドウが小さい場合にグラフを描こうとすると、`plot.new() でエラー: figure margins too large`が発生して描画に失敗する。
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/c6f7cf70-7f68-c30b-e950-12f3f724086d.png">

## 解決策1（まずはコレ）
Plotsウィンドウを大きくする。
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/4b9357b7-a76f-77f0-a4d2-1afa9b4d5222.png">

## 解決策2
`par("mar"=c(1,1,1,1))`を呼び出して余白をなくす。
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/888d748e-d6f9-ed6a-94cf-45bfb00a6ceb.png">

※ただし、この操作では、おそらく軸名やラベル名が消えてしまうとおもうので留意。

## 解決策3
次のコードで、描画用の別ウィンドウを立ち上げてプロット関数を実行する。

```R
dev.new()
plot()

#終了時は下記コードまたはウィンドウの「×」ボタンで閉じる
dev.off()
```

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/de03aca7-8575-2a3c-f556-6e932cc25e7d.png">

もし`dev.new()`を呼び出しても別ウィンドウが立ち上がらない場合は、もう一度`dev.new()`を呼び出すことで立ち上がるはず。

※1度目の`dev.new()`呼び出しで別ウィンドウが立ち上がらない理由は、まだPlotsウィンドウがアクティブでないときに、`dev.new()`を呼び出すとPlotsウィンドウをアクティブにするため。

## 解決策4（上記でダメな場合）
解決策1、2、3のあわせ技。
描画用の別ウィンドウを作り、余白をなくし、ウィンドウサイズを大きくした上で描画する。

```R
dev.new()
par("mar"=c(1,1,1,1))

#ここでウィンドウのサイズを手動で大きくする。

plot()

#終了時は下記コードまたはウィンドウの「×」ボタンで閉じる
dev.off()
```

<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254095/4c296fa5-cd82-a515-4efd-b0a81dda343a.png">

以上です。
gatlingのStructureBuilderクラスを拡張する


###経緯
業務でパフォーマンステストのためにgatlingでテストシナリオを書くことがあるため
gatlingを使用しているとexec関数の部分がネストにより複雑化するため、
既存のStructureBuilderクラスを拡張してネストする部分を隠蔽化してみる

#exec関数のネスト問題
gatlingではexec関数を使用してメソッドチェーンの形式でコードを書いていきます。
下記のコードはgatlingでログインとログアウトする場合を考えたシナリオです。
この例はネストする部分が短いですが、gatlingではexec関数の中にさらにexec関数を書けるため複雑なテストシナリオを書こうとするとネストが深くなりコードが複雑化します。

```scala
class MySimulation extends Simulation {

  val httpProtocol = http
    .baseUrl("http://localhost:8080")

  val id: String = "testUser"
  val pass: String = "hello"

  val scn = scenario("MySimulation")
    .exec(http("login")
                .post("/login")
                .body(StringBody("""{ "id": """" + id +"""", "pass": """" + pass +"""" }""")).asJson
                .check(status.is(200))
    .pause(1)
    .exec(http("logout")
                .post("/logout")
                .check(status.is(200))
   
   setUp(scn.inject(rampUsers(100) during (10 seconds)).protocols(httpProtocol)
}
```

# 解決策
Scalaにはimplicitという修飾子があり、implicit classを使用することで既存のクラスを拡張することができます。
そこでgatlingの既存クラスのStructureBuilder自体にログインとログアウトする処理を直接追加し、ネストする部分をここに隠蔽化します。
下記がStructureBuilderを拡張したコードになります。

```scala
package test
import io.gatling.core.structure.StructureBuilder

object MyScenario {

    implicit class StructureBuilderWithWhatevers[B <: StructureBuilder[B]](b: B) {

        def login(id: String, pass: String): B = {
            b.exec(http("login")
                .post("/login")
                .body(StringBody("""{ "id": """" + id +"""", "pass": """" + pass +"""" }""")).asJson
                .check(status.is(200))
        }

        def logout(): B = {
            b.exec(http("logout")
                .post("/logout")
                .check(status.is(200))
        }
}
```

StructureBuilderを拡張したMySenarioを使用するために使用側のクラスでimportします。

```scala
import test.MyScenario._

class MySimulation extends Simulation {

  val httpProtocol = http
    .baseUrl("http://localhost:8080")

  val id: String = "testUser"
  val pass: String = "hello"

  val scn = scenario("MySimulation")
    .login(id,pass)
    .pause(1)
    .logout()
   
   setUp(scn.inject(rampUsers(100) during (10 seconds)).protocols(httpProtocol)
}
```

こうすることによって追加したログイン,ログアウトする関数を使用側のクラスでメソッドチェーンで簡潔に記述できるようになり、ログインとログアウトの処理も再利用しやすくなりました。

###参考記事
[gatling.io](https://gatling.io/docs/current/)
通常関数とアロー関数の違い

#通常関数とアロー関数の記述
以下，二つの関数の記述法である．

```Javascript:
//function 
function f(x) {
  return x + 1;
}

//arrow function 
const f = (x) => x + 1;
```

#通常関数とアロー関数とでは参照するthisが異なる
JavaScriptでは，関数もconstructor同様にthisのオブジェクトを持つことができる．
このthisオブジェクトの参照先が通常関数とアロー関数とで異なる．

* 通常関数：宣言元のオブジェクト

```Javascript:
//////通常関数のthis//////
function test1 {
  this.param = 'test1' //JavaScriptでは関数の中に関数を持つことも可能

  function printParam () {
    console.log( this.param )
  }

  let object1 {
    param: 'object1',
    func: printParam(),
  }

  let object2 {
    param: 'object2',
    func: printParam(),
  }

  object1.func()
  object2.func()
}

test1()
```

```:出力
object1
object2
```


* アロー関数：宣言時のスコープを持つオブジェクト

```Javascript:
///////アロー関数///////
function test2 {
  this.param = 'test2' //JavaScriptでは関数の中に関数を持つことも可能

  function printParam () {
    console.log( this.param )
  }

  let object3 {
    param: 'object3',
    func: printParam(),
  }

  let object4 {
    param: 'object4',
    func: printParam(),
  }

  object3.func()
  object4.func()
}

test2()
```

```:出力
test2
test2
```
公開されたcsvファイルをGASで読み取りスプレッドシートに転記・jsonで公開する

# はじめに
## What is This
外部で公開されたcsvファイルを読み取り、シートに出力するGoogle App Scriptです。

## 開発の経緯
 - [公開されたcsvをGithub ActionでスクレイピングしてGithub Pagesで公開する](https://qiita.com/iori_ama/items/6cc8f4162b52387e4a46)
 - [Googleドライブのフォルダに格納したcsvファイルをGASで読み取りスプレッドシート->json化して出力する](https://qiita.com/iori_ama/items/b6cf9c8ee901884d0305)

の2つを公開したところ、<b>「CSVをGASで読み取ってGoogleスプレッドシートに転記・JSON出力したほうが良いのでは」</b>とアドバイスをいただいたので、作成しました。技術的には上記2記事の合わせ技です。

# Product 
## Github
https://github.com/iamakawa/CSV2GSheet

## 参考データ
岐阜県オープンデータ
https://data.gifu-opendata.pref.gifu.lg.jp/dataset/c11223-001

# how to use
## csvファイルの読み込み
- 本コードをGoogle App Scriptにコピーし、読み取りたい任意のCSVファイルのURLに変更してください
- csvを格納し、本スクリプトを実行するとcsvを読み取り、スプレッドシートに指定した名称のシートが作成されます

## (備考)APIとしてスプレッドシートを出力する方法
- Googleスプレッドシートのメニューで「ファイル->ウェブに公開」で「公開」を選択する
- https://docs.google.com/spreadsheets/d/xxxxx/edit#gid=0
  - スプレッドシートの「xxxx」部分をコピー
- https://spreadsheets.google.com/feeds/list/YYYY/ZZ/public/values?alt=json
  - YYYY:先程コピーした「xxxx」の部分をペースト
  - ZZ: シートを左から数えた順番。左から2番目なら「2」
  - 置き換えた値で実行するとjsonファイルを出力できる。
- 詳細は[Googleドライブのフォルダに格納したcsvファイルをGASで読み取りスプレッドシート->json化して出力する](https://qiita.com/iori_ama/items/b6cf9c8ee901884d0305)にて、写真付きで公開しています

## 前回2記事と何が違うか
今回の開発では下記の2点が求められていました。
- ①自動取得できること
- ②<b>万が一データの更新が行われないとき、スクレイピングを停止し、Googleスプレッドシートでも手動で修正が行えること</b>。(原則は更新しない)

「[公開されたcsvをGithub ActionでスクレイピングしてGithub Pagesで公開する](https://qiita.com/iori_ama/items/6cc8f4162b52387e4a46)」では①はできるが②ができず、「 [Googleドライブのフォルダに格納したcsvファイルをGASで読み取りスプレッドシート->json化して出力する](https://qiita.com/iori_ama/items/b6cf9c8ee901884d0305)」では逆に①はできないが②はできました。
①も②も達成するためには、csvを取得し、最終的にGoogleスプレッドシートに出力できる必要があったため、開発しました。

# 技術仕様
```javascript:csv2Gsheet.gs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var REMOTE_SOURCES = [
  {
    'url': 'https://opendata.com/sample1.csv',
    'sheetname': 'sample1',
  },
  {
    'url': 'https://opendata.com/sample2.csv',
    'sheetname': 'sample2',
  },
  {
    'url': 'https://opendata.com/sample3.csv',
    'sheetname': 'sample3'
  },
];
var REMOTE_SOURCES_OPTIONS = {
  method : "get"
};

function CSV2Gsheet(){
  for(var i =0; i<REMOTE_SOURCES.length; i++){    
    response = UrlFetchApp.fetch(REMOTE_SOURCES[i].url, REMOTE_SOURCES_OPTIONS);
    var sheetName = REMOTE_SOURCES[i].sheetname;
    var sh = ss.getSheetByName(sheetName);
    if(sh == null)
    {
      ss.insertSheet(sheetName);
      sh = ss.getSheetByName(sheetName);
    } 
    var data = response.getContentText("Shift_JIS"); 
    var csv = Utilities.parseCsv(data);
    sh.getRange(1,1,csv.length,csv[0].length).setValues(csv);
  }
}
```

- githubには実際に参照しているデータを掲載しています
- 参照するデータのURLと、転記するGoogleスプレッドシートのシート名を明記する
- シートが無ければ新たにシートを作成。シートがあれば上書きする。(clearしない。万が一の場合は手動で行追加も念頭に置くため)
Dockerでコンテナ内で作成したファイルをローカルにコピーする方法

プログラミングを勉強中です。
Dockerを使用して開発している最中に少し詰まった部分があったため、備忘録として残します。

##状況　
Docker内で作成したファイルを、ホスト環境にコピーしたい。

##（脱線）ホスト環境とは？？

Dockerの勉強を始めた時は（今もそうですが）ホスト環境？コンテナ内で開発？？？
というワードの段階ですでに理解が追いついていなかったので簡単にまとめます。

###ホスト環境
今目の前で使用しているパソコン内の開発環境のこと。
ローカル環境ともいいます。

###リモート環境
Dockerのコンテナ内の環境のことです。


##（本題）Dockerでコンテナ内で作成したファイルをローカルにコピーするコマンド
コンテナのファイルをローカルにコピーするには下記のコマンドで実行できました。


```
docker cp 【コンテナID】:アプリ名/ディレクトリ名/ファイル名 コピーしたいディレクトリ名/つけたいファイル名
```
コンテナIDを確認するには↓↓

```
docker ps
```

コンテナ内のディレクトリ指定と、ローカルのディレクトリ指定の間にはスペースが必要です！

コンテナとローカルについては、ローカルのファイルをコンテナにコピーすることもできるみたいなので
いろいろ試してみたいと思います。

何かご意見があれば、何卒宜しくお願い致しますm(__)m
HerokuのPostgreSQLにSSL接続する

　　
短いですが備忘録として残しておきます！

## エラー

Node.jsのORM（Object Relation Mapping）であるSequelizeを利用して、
ローカルからHerokuのPostgreSQLに接続する際に下記のエラーが出て接続できませんでした。。

```
error: no pg_hba.conf entry for host "DB_HOST", user "DB_USER", database "DB", SSL off
```
これはSSL接続がオフになっているためオプションでオンにしてあげる必要があります。

## 解決

```javascript
const Sequelize = require('sequelize')
const sequelize = new Sequelize(
  'postgres://~~', // DB情報
  {
    // DBにSSL接続する
    dialectOptions: {
      ssl: true,
    },
  }
)
```

上記のようにSSL接続をtrueとすることで解決しました！
OutSystemsで回帰テストを外部から実行する

OutSystemsで現在推奨されているユニットテストツールはForgeにある、BDDFrameworkです。これを外部から実行する方法です。

環境内のテストケースを自動抽出するためにForgeにあるCI/CD Probeを使います。抽出したテストは、BDDFrameworkが提供しているREST APIで実行可能です。

# サンプル
https://www.outsystems.com/forge/Component_Overview.aspx?ProjectId=7086
CICDProbeTest Screenです。
事前準備として、インストール後、ConsumeするREST APIの設定が必要です。画面に設定方法を書いてあるので参考にしてください。

# 環境
Personal Environment(Version 11.8.0 (Build 10304))
Service Studio(Version 11.7.2)
CI/CD Probe(Forgeコンポーネント、Version 2.1.0)
BDDFramework

# CI/CD Probeの役割
OutSystemsにおけるCI/CDパイプライン内で使う情報をREST形式で提供するコンポーネントです。
ただし、2020/4/23時点では、目立った機能は、環境内のBDD Frameworkのテストスイートをリストアップする機能だけです。

なお、BDD Frameworkは、Forgeで提供されているコンポーネントで、自動実行できるユニットテスト作成などに使います。
BDD Frameworkの使い方は以前書いた記事を参考にしてください。1テストスイートは1画面です。画面をAnonymousでもアクセスできるようにするのを忘れずに。
[OutSystemsでテスト駆動開発の写経するためのTips](https://qiita.com/jyunji_watanabe/items/2341a3bff5d2572ee156)

OutSystemsの標準的なCI/CDパイプラインについては、以前メモを作りました。
[OutSystemsのCI/CD関係情報まとめ(2020/04/18時点)](https://blog.house-soft.info/archives/1516)

# CI/CD Probeを使った回帰テストの実行
## CI/CD ProbeのREST APIを呼び出し、環境内の全テストをリストアップ。
このScanBDDTestEndpointsをパラメータ無しで呼ぶと、全テストをリストアップしてくれます。
![qCICDProbe1_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/47f841a4-b36d-68aa-4f84-c7759d417b54.png)

戻り値はモジュール毎に、Screenを列挙したものになっています。
![qCICDProbe1_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/76404312-991f-4d24-6baf-85e3812f5551.png)

## BDDFrameworkのテストスイートを実行する
BDDFrameworkは、テストを実行するためのREST APIを提供しています。
2つのInput Parameterは必須ですが、↑でCI/CD Probeから取得したモジュール名とScreen名が使えます。
![qCICDProbe1_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/586f2ec6-5d72-ff1d-0ef2-3429a1aad540.png)

つまり、CI/CD ProbeのREST APIの結果をループで順番に実行していく場合、
TestESpace：ScanBDDTestEndpointsResponses.Current.BDDTestEndpointsInfo.EspaceName
TestSuiteScreen：ScanBDDTestEndpointsResponses.Current.BDDTestEndpointsInfo.WebFlows.Current.WebScreens.Current.Name
のように指定します。

あとは、RunTestSuiteの結果を一端Entityに格納するなどした上で、Processで開発者に結果確認タスクを降るなり、結果メール送信するなりすればいいでしょう。

# 応用的な利用方法の検討
本来、CI/CD ProbeのScanBDDTestEndpointsは回帰テストを専用環境で実行することが想定されています。
しかし、例えばScrumで開発しているとしたら、スプリント終了まで回帰テストが壊れていることに気づけないのは痛いですね。

そこで、開発環境に上記の通知まで行うTimerを日次でしかけておくと解決できます。
localStorage

https://developer.mozilla.org/ko/docs/Web/API/Window/localStorage


sessionStorageと似ているが、
セッションのデータ満了期間によって無効になるが、
lcoalStorageはnot volatile

※localStorageに保存するときは全部文字列になる
なので、

```javascript

var objArray=[{"text":"test1","id":1},{"text":"test2","id":2}];

localStorage.setItem("objArray", objArray);
```
> console確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/59b6312d-666a-0ed3-17d2-ec8cf6be8d36.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/d916c98e-c1c9-f99b-3165-840e7d5c7594.png)


読み取れなくなるので、JSONを利用する


```javascript

var objArray=JSON.stringify([{"text":"test1","id":1},{"text":"test2","id":2}]);

localStorage.setItem("objArray", objArray);
```
> console　確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209211/558c0d8f-4bef-f8e4-fd47-6d7147f72102.png)


望ましい結果が出ることを確認する
【React】GoogleMapで地図をドラッグして移動した後にMarkerを更新する

## やりたいこと
GoogleMapと地図のMarker一覧を取得するAPIを組み合わせて、Reactアプリケーションを作ることを想定しています。
その際に、地図の中心地がドラッグで移動された際に、Marker一覧も取得し直して、地図にMarkerの再配置をしたいです。
イメージとしてはドラッグ前が以下のような感じとした場合、
<img height="300" width="700" alt="スクリーンショット 2020-04-25 2.51.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/91e42571-45c0-4018-d7d4-2ab226fa74a3.png">

ドラッグ後はこのような感じでMarkerも再取得される感じです。
<img height="300" width="700" alt="スクリーンショット 2020-04-25 2.52.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/04744b53-c473-5ec5-3531-23eb0b9495ec.png">

## 前提
* 地図用のライブラリとして、[google-maps-react](https://github.com/fullstackreact/google-maps-react)を使います。詳細は[React.js内でGoogle Mapの現在地を表示する](https://qiita.com/Mitsuw0/items/b026c637c4294de0ccbf)を参照ください。
* 実装は、React Hooksの形式でstateの管理は[【React Hooks】useReducer + useContextでグローバルなストアを扱う](https://qiita.com/nishiurahiroki/items/d2733e7108e6e59a9930)を参考にしています。

## サンプルソース
※ reducerやstoreの実装内容は割愛

``` GoogleMapComponent.js
import React, { useContext } from "react";
import { GoogleApiWrapper, Marker, Map } from "google-maps-react";
import { MapStore } from "../../store/MapStore";

export const GoogleMapComponent = ({ google }) => {
  const { state, dispatch } = useContext(MapStore);
  const location = state.currentLocation;
  var markerList = [];
  // ステートの情報でMarkerを作成
  state.markerList.map((m, i) => {
    return markerList.push(
      <Marker
        key={i}
        title={m.name}
        position={{ lat: m.latitude, lng: m.longitude }}
      />
    );
  });
  // 地図ドラッグ時に走る関数
  const centerMoved = (_, map) => {
    // 変更後の中心を取得
    const center = map.getCenter();
    // APIでのMarker取得処理
    axios
      .get("http://localhost/test", {
        latitude: center.lat(),
        longitude: center.lng(),
      })
      .then((results) => {
        if (results.status === 200) {
          dispatch({
            type: "CHANGE_LOCATION",
            currentLocation: {
              latitude: latitude,
              longitude: longitude,
            },
            markerList: results.data,
          });
        } else {
          // エラー時の処理
        }
      })
      .catch(() => {
        // エラー時の処理
      });
  };
  return (
    <Map
      google={google}
      zoom={15}
      center={{ lat: location.latitude, lng: location.longitude }}
      initialCenter={{ lat: location.latitude, lng: location.longitude }}
      onDragend={centerMoved}
    >
      {markerList}
    </Map>
  );
};

export default GoogleApiWrapper({
  apiKey: process.env.REACT_APP_GOOGLE_MAP_API_KEY,
})(GoogleMapComponent);

```
浮動小数点の情報落ち対策を試してみた

浮動小数点の情報落ち対策をしない場合とした場合でどれくらい差がでるのか興味が湧いたので試してみました。

1秒毎に測定した気温の3分間の移動平均計算を想定して25前後の乱数を180個つくり、情報落ち対策をしなかった平均値ave1と情報落ち対策をしたave2の差diffを表示するようにしてみました。

結果としてはe-14～e-15のオーダーに違いが見られました。情報『落ち』というぐらいだから常にave1≦ave2かと思っていましたが、ave1の方が大きくなる場合もあるんですね。

なお、情報落ち対策の計算方法は以下のサイトを参考にさせて頂きました。感謝。
https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html

```tcl
for {set j 0} {$j < 10} {incr j} {
	for {set i 0} {$i < 180} {incr i} {
		lappend values [expr {rand() * 50 + rand()}]
	}
	set n [llength $values]

	set ave1 [expr ([join $values +])/$n]

	set ave2 0.0
	set losted 0.0
	foreach value $values {
		set actual [expr {($losted + $value) + $ave2}]
		set losted [expr {($losted + $value) - ($actual - $ave2)}]
		set ave2 $actual
		#puts [format "losted=%+.17f" $losted]
	}
	set ave2 [expr {$ave2 / $n}]

	puts [format "ave1 = %.17f\nave2 = %.17f\ndiff = %+.17f\n" $ave1 $ave2 [expr {$ave1-$ave2}]]
}
```

出力例は以下の通り。乱数を使っているので、結果は毎回異なりますが。

```
ave1 = 25.07280401240855028
ave2 = 25.07280401240854673
diff = +0.00000000000000355

ave1 = 25.00120967717174381
ave2 = 25.00120967717172960
diff = +0.00000000000001421

ave1 = 25.27157371650008599
ave2 = 25.27157371650005757
diff = +0.00000000000002842

ave1 = 25.37179051766786841
ave2 = 25.37179051766785776
diff = +0.00000000000001066

ave1 = 25.79864019810365150
ave2 = 25.79864019810365505
diff = -0.00000000000000355

ave1 = 25.67349073410403548
ave2 = 25.67349073410403548
diff = +0.00000000000000000

ave1 = 25.85428135154362650
ave2 = 25.85428135154361939
diff = +0.00000000000000711

ave1 = 25.78256482459444499
ave2 = 25.78256482459445920
diff = -0.00000000000001421

ave1 = 25.74491985400320360
ave2 = 25.74491985400321425
diff = -0.00000000000001066

ave1 = 25.62551834231759074
ave2 = 25.62551834231758363
diff = +0.00000000000000711
```