OmniAICreator/Qiita-1.07M huggingface dataset:
ジェネリックPLEN2

#初めに
二足歩行ロボットって、世間ではもう流行りじゃないんですかね？
今更ながら興味を持った自分がいろいろ調べてみた結果、一番気に入ったのが[PLEN2](https://plen.jp/wp/plen2/ "PLEN2")。

オープンソースでwikiも充実してるし、ちっちゃいのに関節の自由度が高いとか最高じゃないか。
と思ったのにもう売ってないのかよおい！いろいろ弄りたいんだからDMMの高いやつじゃなくていいんだよ！

そんなわけで中華で探して見たらあるわあるわ。
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/d0f1ea69-430d-0a6e-479c-5342644d9c93.jpeg)

早速ポチって見たのはいいのだが、コロナの影響で全然届かねぇ。
暇を持て余してPLEN ProjectとVIVI(中華のPLEN2)のファームを見比べたりしてるうちにあれっと気が付いた。

これもしかしたら制御ボードもサーボも汎用品でいけるんじゃね？

#というわけでまずは確認
PLEN ProjectのgithubhubからPLENの3Dデータを取得。
https://github.com/plenprojectcompany/plen-3DModel_Fusion360

そこにネットで拾ってきたサーボモータES08MAIIのデータを合わせてみると、
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/7886d469-a8a1-a947-8e8a-fb13a8f793f6.jpeg)
完璧に入った。ジャストフィットだ。これはいける！と思ったが、15chのサーボドライバーがはみ出した。惜しい。
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/e5631628-d3ab-4839-510d-2127ab00eaa7.jpeg)

#不思議なこと(2020/04/30追記)
こちらは本家PLEN2の顔パーツ。
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/4eda981a-6060-6708-7a89-b528c29f4387.jpeg)

こちらは[Neck piece for the ViVi robot](https://www.thingiverse.com/thing:3034640)に出てくるVIVI PLEN2の顔パーツ。
![SharedScreenshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/81f18d8a-9367-3881-cbd6-2e934239ee3d.jpeg)

・・・・首の回転軸拡張されてね？

#おどろいたことに(2020/05/02)
二週間で届いた・・・。やるなぁ中国。
![KIMG0454.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628546/7ba4eac9-9732-5492-07fe-6c4a16b41ee8.jpeg)

#続く
https://qiita.com/GetQ/items/548a0af3305a55e8b8f4
最近のiOSのTwitterKit...

最近は、公式TwitterKitを使ってる人は、もう少ないでしょう。
https://github.com/twitter-archive/twitter-kit-ios

既存アプリのメンテナンスのためにTwitterKitをいじったので雑感など。
（結局のところアプリから削除しましたが）

---
TwitterKitを利用したアプリをアップデートすると二点問題がありまして、

1.UIWebViewが使われているため、今後アップデートできなくなる
https://ryukasublog.com/uiwebview-deprecated/
【iOS】UIWebViewのDeprecated対応期限は既存アプリは2020年12月まで、新規アプリは2020年4月まで

2.TwitterKitが位置情報を含むので位置情報を使うセキュリティの設定をしなくてはならなくなった。
位置情報は使ってないので今まで通りにApp store connectにアーカイブをsubmitすると以下のエラーになります。

 - Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSLocationWhenInUseUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data are required to include a purpose string. If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).

これは、TwitterKitがCoreLocationのライブラリを使っているために起きる。

上記の通りplistのNSLocationWhenInUseUsageDescriptionキーに位置情報の使用目的を書けばOKですが、位置情報を使ってないにもかかわらず、ユーザから設定に位置情報利用を利用すための設定が見えてしまってちょっと気持ち悪い。

---
1.についてはUIWebViewが削除された
https://github.com/savani24/TwitterKit5
を使うことによって回避できました。

2.については回避できず、結局のところTwitterの投稿機能そのものを削除した。
（別の方法のライブラリなり自力でなんとかする方法はありそうですが、そこまではしなかったので。）
GoでGeneratorとWorkerのサンプル


大量のJobを捌くこんなケースのGoのサンプルです。

- （Jobの）Generator
    - 生成処理が軽くて1つ
    - 途中でコケたら全体を中断したい（それ以上Jobを生成しない）
- Worker
    - それなりに重たい処理
    - 横に複数並べてJobを捌きたい
    - エラーが発生しても次のJobを継続（最後にエラーをハンドルする）


処理結果とエラーを持つResult構造体

```go
// packageとimportは割愛

type Result struct {
	s string
	e error
}
```

GeneratorはJobの数だけ値を入れてくチャネルを作って渡します。
時々コケると、途中で止めます。

```go
func Generator(num int) <-chan int {
	ch := make(chan int)
	go func() {
		i := 0
		defer close(ch)

		for num > 0 {
			num--

			// sometime happen error, quit to generate
			if rand.Int()%10 == 0 {
				log.Printf("quit to generate\n")
				return
			}

			ch <- i
			log.Printf("gen: %d\n", i)
			i++
		}
	}()
	return ch
}
```

workerは入力と出力のチャネルを受けます。
Jobの実行処理の成否をResultとして詰めていきます。
上位のWaitGroupを受けてDoneするのはお決まりのパターンですね。

```go
func worker(wg *sync.WaitGroup, chIn <-chan int, chResult chan<- *Result) {
	defer wg.Done()

	for {
		i, ok := <-chIn
		if !ok {
			return
		}
		log.Printf("work: %d\n", i)

		time.Sleep(2 * time.Second)

		// sometime happen error, continue to work
		if rand.Int()%10 == 0 {
			log.Printf("continue to work\n")
			chResult <- &Result{
				s: strconv.Itoa(i),
				e: fmt.Errorf("error %d", i),
			}
			continue
		}

		chResult <- &Result{
			s: strconv.Itoa(i),
		}
	}
}
```

本体は上記のGeneratorとworkerとチャネルを取り持つだけです。
Resultの順番はバラけてしまうので、私は配列に詰め直してソートしたりしました。

```go
func main() {
	log.Printf("---start\n")
	rand.Seed(time.Now().UnixNano())

	job := 10
	chIn := Generator(job)
	chResult := make(chan *Result, job)

	var wg sync.WaitGroup
	concurrency := 3
	for i := 0; i < concurrency; i++ {
		wg.Add(1)
		go worker(&wg, chIn, chResult)
	}
	wg.Wait()
	close(chResult)
	log.Printf("---worker done\n")

	for r := range chResult {
		if r.e == nil {
			log.Printf("result %s ok\n", r.s)
		} else {
			log.Printf("result %s err: %s\n", r.s, r.e)
		}
	}
}
```
AWS 認定ソリューションアーキテクト – プロフェッショナル 合格への道#13

#初めに
SAAver2を受けたと思ったらdvaを受けていました。
また忘れかけていたのでおさらいしながら、ver2の根拠を探していきたい。

![SAAver2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/034470a5-f22c-515a-0b44-22aee40c6d18.png)
どこを勘違いしているのか..

#学習
## 二つの評価期間でHTTP504エラーが記録された場合にのみアラームしたい

* 結果に応じてカスタム通知を送信するようにアラームを更新する。
    * 結果とは
* 504が記録されていない間は0をパブリッシュ
    * ？
* 高頻度メトリクスを使用してデータをより高い頻度で取得する
    * 意図にそぐわない
* 統計セットを使用してcloudwatchに送信される前に集計してから送る。
    * 正解
    * アラームを毎回通知していたら困るので一旦統計セットを使用してアヴェレージを計算。そしてそれを送信することでアラームが作動する仕組みがベスト

### AWS再入門 – CloudWatch編
https://dev.classmethod.jp/articles/cm-advent-calendar-2015-aws-re-entering-cloudwatch/

* メトリックス = 名前空間
    *  サポート対象のAWSサービスを開始すると、データポイント（監視データ）がCloudWatchに送信されます。
    *  CloudWatchはメトリックスにデータポイントを格納します。
    *  メトリックスは名前、名前空間、1 つ以上のディメンションで特定されます。
        *  ディメンション
            *  ディメンションを使うことで統計的なモニタリングが可能です。
            *  ディメンションはメトリックスのカテゴリーです。
                *  あるインスタンスのメトリックスを確認する場合、ディメンション[InstanceId]を使用します。
    *  メトリックスは2週間保管されます。
* 名前空間（ネームスペース）
    * メトリックスを特定するための1要素として、名前空間[AWS/EC2]や[AWS/RDS]が使われます。
* アラーム
    * CloudWatchアラームは、メトリックスの値と定義されたしきい値の比較によって3つの状態を持ちます。
        * OK – メトリックスの値が、しきい値を下回ってい
        * ALARM – メトリックスの値が、しきい値を上回っている
        * INSUFFICIENT_DATA – アラームが開始直後であるか、メトリックスが利用できないか、データが不足していてアラームの状態を判定できない

### 統計
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Statistic

> 統計は、指定した期間のメトリクスデータの集計です。CloudWatch は、カスタムデータまたは AWS の他のサービスから CloudWatch に提供されたメトリクスデータポイントを基に、統計を提供します。集約は、指定した期間内に、名前空間、メトリクス名、ディメンション、データポイントの測定単位を用いて行われます。次の表は利用可能な統計を説明しています。

![統計.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/eb92f78e-5611-2097-aa53-3e62f8a6ae9d.png)

### Amazon CloudWatch における高解像度メトリクスとアラーム
> 最初はメトリクスを 5 分間隔で保存していましたが、ユーザーから寄せられたリクエストに応え、2010 年にこれを 1 分間隔に変更しました (詳細モニタリング)。これについては高い評価を頂きましたが、そろそろレベルアップさせる時期が来ました。アプリケーションが 1 秒の解像度で CloudWatch にメトリクスを発行できるようになりました。発行後、数秒でメトリクスを画面で見ることができるほか、10 秒ごとに評価する高解像度の CloudWatch アラームをセットアップできます。

## codebuildプロジェクトを編集できる権限なしにビルドコマンドをオーバーライドする方法

* ソースコードの一部のbuildspec.ymlを編集して新しいビルドを定義する。
    * ソースコードに含まれるbuildspec.ymlは権限的に編集できないのではないか
    * codebuild:UpdateProject権限が必要
    * 
* buildcommandsセクション内のコマンドを編集
    * プロジェクトを編集できない
* cliからbuildspec-locationプロパティを編集して新規buildspecymlファイルを渡す
    * 正解
* startbuildapiのbuildspecプロパティの値を更新しビルド実行時にビルドコマンドをオーバライドする
    * たぶんひっかけ。知らない人は直接値を渡すと勘違いさせるための選択肢
    * ここでファイルをまた指定する

### buildspec ファイル名とストレージの場所
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html
> WS CLI の start-build コマンドを実行し、buildspecOverride の値を、組み込みの環境変数 CODEBUILD_SRC_DIR の値を基準にした代替 buildspec ファイルのパスに設定します。また、AWS SDK の start build オペレーションで同等の処理を行うこともできます。

https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html#CodeBuild-StartBuild-request-buildspecOverride
> このビルドについてのみ、ビルドプロジェクトで既に定義されている最新のファイルをオーバーライドするbuildspecファイル宣言。

## Amazon Aurora でのレプリケーション
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.Replication.html
Blueprintのネイティブ化エラーの解析と解決

##結論
 fatal error C1083: include というエラーが出ている場合

 1.空でも良いのでC++のファイルを作成
 2.エディタの「ファイル⇒visualstudio2017プロジェクトを更新」
 3.エクスプローラーでプロジェクトファイルを「右クリック⇒Generate Visual Studio project files」
上記を順に行う。

##トラブルシューティング話

BPのネイティブ化のみでゲームを制作していましたが、[KawaiiPhysics](https://github.com/pafuhana1213/KawaiiPhysics)がとても良さそうだったので、プラグインに入れると、下記のようにエラーが発生。

```
UATHelper: パッケージ化 (Windows (64-bit)):C:\Users\xxx\Documents\Unreal Projects\プロジェクト名\Intermediate\Plugins\NativizedAssets\Windows\Game\Source\NativizedAssets\Public\MakeWThirdPerson_AnimBP__pf889424572.h(6): fatal error C1083: include �t�@�C����J���܂���B'../Plugins/KawaiiPhysics/Source/KawaiiPhysics/Public/AnimNode_KawaiiPhysics.h':No such file or dir
```

見てみるとNativizedAssetsに置かれているファイルからエラーが発せられています。
ネイティブ化がエラー要因と予想し、一度ネイティブ化を切ってパッケージ化してみると、正常に成功しました。
ということで、ネイティブ化周りのあるあるエラーをググる。
Generate Visual Studio project でプロジェクトにプラグインのファイルが追加されてないとでるっぽいことがわかった。
"結論"の手順を実行⇒解決。やったぜ。


凄く荒い記事だけど、この記事が誰かの一助になればと思います。
【JavaScript】ある文字列のn番目の位置から、特定の文字あるいは単語が入っているかどうか調べたい

## はじめに
JavaScriptで、ある文字列のn番目の位置から、特定の文字あるいは単語が入っているかどうか確認したい。
そんな時、ありますよね。（競プロで使っただけです。）

そんな時に使えるのが、**startsWith**です。

## startsWithとは
文字列のn番目からみて、指定した単語が含まれているかどうかを判定します。返り値はbooleanです。

```js
// word.startsWith('調べたい文字列', 文字列の中の位置)

const word = '私はずんだもちが食べたい'

console.log(word.startsWith('私はずんだもち'))
// => true
console.log(word.startsWith('ずんだもち'))
// => false
console.log(word.startsWith('ずんだもち', 2))
// => true
console.log(word.startsWith('食べたい', 8))
// => true
```

これで、ある文字列のn番目の位置から、特定の文字あるいは単語が入っているかどうか確認できます！
やったね！

## おしまい
こんなんいつ使うんだよ。
競プロは知らないメソッドとの出会いがあって楽しいですね。
自分のJavaScript力のなさを実感できます。
ローカルネットワークでmomo同士で手軽な双方向の映像音声通信

[momo](https://github.com/shiguredo/momo) 2020.6 でサーバ不要のmomo to momo の通信ができるようになったので試してみました。

Mac 2台でやっています。
2台のうちの1台がサーバーを兼務します。

## サーバーを兼務する方

まずはhost名の確認。

```
$ hostname
koba-mac.local
```

momoの起動。

```
momo --use-sdl --show-me test
```

先にこちらを起動しておく必要があります。

## クライアント

さきほど確認したサーバのhost名が `koba-mac.local` だったので

```
momo --use-sdl --show-me ayame ws://koba-mac.local:8080/ws test
```

これでつながって双方向の映像音声通信ができます。簡単ですね！
mac同士だとmDNSが使えるのでIPアドレスを調べる必要もありません。


## 開発者に感謝！

@tnoho さん素晴らしいです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">医療機関向けお手軽テレビ電話システムを構築したお話｜tanpoponet <a href="https://t.co/KmnPKbHs3D">https://t.co/KmnPKbHs3D</a><br>この素晴らしい話にできるだけ答えるべく <a href="https://t.co/4UwZHE6bOZ">https://t.co/4UwZHE6bOZ</a> を作りました。Momo 2台運用で Ayame を挟まない直接通信が可能になります。起動してすぐ繋がるところまでだいぶ近付いたかな？</p>&mdash; tnoho (@tnoho) <a href="https://twitter.com/tnoho/status/1254067960638922752?ref_src=twsrc%5Etfw">April 25, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Chrome で documentFragment をつかって DOM 上に存在しなくなった要素を再度DOMに追加すると表示されないことがある

# 追記(2020-05-25)

Chrome 83.0.4103.61 だともう起きません。

# 概要

Chrome で documentFragment をつかいつつ `appendChild` すると存在してるはずの要素が表示されないことがある。

# 条件

調べた限りだと、以下の全てを満たしてると起きる。

- Chrome 81.0.4044.122
    - 他のバージョンは調べてない
- 子要素が隠れる可能性のある要素
    - `<select>` と `<option>` とか
    - [`<details>` とその子要素とか](https://developer.mozilla.org/ja/docs/Web/HTML/Element/details)
- 一つの関数内で、親要素を空にして子要素をいったんdocumentFragmentにいれてから本物のDOMに追加する処理を行う
- DOM上にかつて存在したが今は存在していない子要素を追加する


つまり以下のいずれかの条件を満たすと起きない。

- Firefox
- 常にブラウザ上に表示される親子要素に対する操作
    - `<ul>` と `<li>` とか
    - `<div>` とか
    - (要はほぼ全ての要素)
- documentFragment を使わない
- `document.createElement` で新たに作成した要素を追加する
- 親要素を空にする操作と子要素の追加の操作を、ちょっと時間置いて実行する

# 例

```html:example.html
<select id="list">
  <option class="item" value="1">1</option>
  <option class="item" value="2">2</option>
  <option class="item" value="3">3</option>
</select>
```
上のようなHTMLに対して jQuery で以下の操作を行う。

```javascript
const $list = $('#list');
const $items = $('.item');

(() => {
  // リストを空にする
  $list.empty();
  // DOM上には存在しなくなった items を再度 append する
  $items.each((index, el) => $list.append(el))
})()
```

すると開発者ツールの Elements タブでは存在して見えるのに、ブラウザ上では表示されなくなる。 `<select>` 要素をクリックしても何も出てこなかったり、2, 3 だけ出てきたりして不審な挙動を起こす。

![append.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26239/63c605a3-69e3-89e2-52fa-52a4c0f4085d.png)



jQuery を使ってなくても以下のようにやると再現する。 jQuery append も内部で `document.createDocumentFragment()` をつかってるので fragment の挙動がなんかおかしいっぽい。

```javascript
const list = document.querySelector('#list');
const items = document.querySelectorAll('.item');

const append = (parent, child) => {
  const fragment = document.createDocumentFragment();
  fragment.appendChild(child);
  parent.appendChild(fragment);
}

(() => {
  // リストを空にする
  list.innerHTML = '';
  // DOM上には存在しなくなった items を再度 append する
  items.forEach( item => append(list, item) );
)();
```


# 解決策

どうやら `appendChild` したあとにレイアウト(リフロー)が起きてないっぽい。なのでリフローすればよい。見えなくなった要素の高さを取得したり、開発者ツールでハイライトしたりするとリフローが起きて表示される。

もしくは DOM を使い回さない。適宜 `createElement` などする。


```javascript
// 高さを取得したり
item.offsetHeight
// jQueryならcloneしたりで要素を作り直してやるとか
$items.each((index, el) => $list.append($(el).clone()))
```

# リンク集

- [demo](https://enormous-separated-buckaroo.glitch.me/)
    - [ソースコード(gist)](https://gist.github.com/ee6efa93fbe3ed3010e8f9000a1d409b)
- [Document.createDocumentFragment - MDN](https://developer.mozilla.org/ja/docs/Web/API/Document/createDocumentFragment)
- [.append() - jQuery API Documentation](https://api.jquery.com/append/)
DjangoでCSSを反映させる方法

# DjangoでCSSを反映させる方法
DjangoでCSSを反映させる方法をご紹介します。

### 環境
Python 3.7.6
Django 3.0.5

### setting.pyの編集
setting.pyの最下部に下記のようなコードを記述します。

```setting.py

# 上部省略

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    [
        os.path.join(BASE_DIR, "static"), 
    ]
)
```
### CSSファイルの追加
staticフォルダを追加し、下記のような構成にします

```
| - webproject
| | - setting.py
| | - urls.py
| - webapp
| | - urls.py
| | - views.py
| - templates
| | - form.html
| - static
| | - css
| | | - style.css
|manage.py
```
### HTMLファイルの編集
最上部に```{% load static %}```を追記します。

```
{% load static %} 
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>WebApp</title>
    <link href="{% static 'css/style.css' %}" rel="stylesheet">
  </head>
  <body>
    <p>Hello World!</p>
  </body>
</html>
```

### CSSファイルの編集
反映されているか確かめます。

```
p {
  color: blue;
}
```

### 確かに反映されました^_^
<img width="730" alt="スクリーンショット 2020-04-28 21.33.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587506/954c92c1-a90d-6a44-5c06-a94f7b7ee434.png">
Vagrant + Hyper-V でMattermostを立ててみる

# 趣旨

テレワークをきっかけに、既存のコミュニケーション手段だけでは不足しているため、チャットツールを使いたい…
でも大人の事情でイントラネットに閉じたものしか使えない…
しかもサーバは準備できず、普通のWindows10 PCしか用意できない…

といったこともあると思うので、その場合でも環境構築出来ないか検証してみました

## 前提

- 母艦はWindows10
    - Hyper-Vが使える、ProもしくはEnterpriseエディション
    - HomeならVirtualBox使えると思いますが、検証してないのでよく分かりませぬ :-)
- 構築するツールはSlack互換OSSの、[Mattermost](https://mattermost.com/)

# Vagrant のインストール

まず[ドキュメント](https://www.vagrantup.com/docs/installation/)に従って一旦無効にする

```powershell
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All
```

[公式ページ](https://www.vagrantup.com/downloads.html)でWindows用インストーラをダウンロードし、インストールする
なお、再起動することになるので注意

再起動後、もう一度Hyper-Vを有効化する
また再起動入ります…

```powershell
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
```

# Cent7イメージのBoxダウンロード

再起動後、Powershellで

```powershell
vagrant box add centos/7 https://app.vagrantup.com/centos/boxes/7
```

途中、プロバイダを聞かれるので…

```powershell
1) hyperv
2) libvirt
3) virtualbox
4) vmware_desktop

Enter your choice:
```

`1) hyperv`を選択
ダウンロードが始まるのでお茶でも入れて待つ

# Vagrantファイルの作成

適当な場所にディレクトリを掘って(例：Desktop\mattermost)
Vagrantfileを作成し、以下を張り付ける

```
Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"

  config.vm.hostname = "mattermost.vagrant.local"

  config.vm.provider "hyperv" do |h|
    h.cpus = "2"
    h.memory = "2048"
    h.vmname = "mattermost-vagrant"
  end

  config.vm.provision :shell do |shell|
    shell.path = "./setup.sh"
    shell.privileged = true
  end
end
```

# setup.shの作成

Vagrantファイルと同じディレクトリ内に、setup.shを作成し、以下貼り付ける

```bash
#!/bin/sh

# --- Package update ---

yum upgrade -y


# --- Docker setup ---

yum install -y yum-utils device-mapper-persistent-data lvm2 git
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io

systemctl start docker
systemctl enable docker

if !(type "docker-compose" > /dev/null 2>&1); then
  curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  chmod +x /usr/local/bin/docker-compose
  ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
fi

# --- Container setup ---

mkdir /mattermost
cd /mattermost

git clone https://github.com/mattermost/mattermost-docker
cd ./mattermost-docker

sed -i -e "s/      # args:/      args:/" docker-compose.yml
sed -i -e "s/      #   - edition=team/        - edition=team/" docker-compose.yml

mkdir -p ./volumes/app/mattermost/{data,logs,config,plugins}
chown -R 2000:2000 ./volumes/app/mattermost/
docker-compose up -d

echo "Script done!"
```

# 起動

Powershellを管理者権限で開き、
Vagrantファイルと、setup.shが入っているディレクトリに移動、
その後、`vagrant up`で起動する

# サービス確認

NATで割り振られたIPに対し、母艦からWebブラウザにアクセスすると、初期設定画面が表示される（はず）

Hyper-Vの仮想スイッチをデフォルトのものにしておくと、NATになるため、
他のクライアントからアクセスさせるためにはポートフォワーディングの設定が必要になる（追記予定）

## 参考

https://qiita.com/esparrago_b/items/a919f985ca01de253820
https://qiita.com/daichi87gi/items/d5da33c76295ee32a735
https://4thsight.xyz/324
https://patorash.hatenablog.com/entry/2019/05/02/184639
https://qiita.com/ymasaoka/items/b6c3ffea060bcd237478
https://qiita.com/8ayac/items/b6b6f0a385d08659316b
RailsのRSpecで外部サービスを使ったAPIをテストする

RailsでAPIを作成する際、外部サービスのAPIにリクエストを投げる処理が含まれている場合、webmockを使うとテストコードが簡単に書けたので、備忘録としてまとめておきます。
テスト時は実際に外部サービスにはリクエストを投げたくないので、外部サービスのレスポンスを返してくれるモックサーバーをwebmockで作成します。

# webmockを導入する
テスト環境でモックサーバーを作成するために[webmock](https://github.com/bblimke/webmock)というgemを導入します。
`Gemfile` に下記を追加し、 `bundle install` を実行してください。

```
group :development, :test do
  gem 'webmock'
end
```

# RSpecにテストコードを追記

テストしたい箇所に、下記のように追記します。
今回は `./spec/requests/hoge_api_spec.rb` にテストを作成していることを想定しています。

モックサーバーからのレスポンスは、 `./spec/fixtures/response.json` にjson形式で作成しておきます（この場所も任意です）。

モックサーバーのurlは `https://external_api_test` としていますが、こちらも任意に決めることが出来ます。

```rb
require "rails_helper"
require "webmock/rspec"  # webmockをrequire

describe "Hoge API", type: :request do
  before do
    WebMock.enable!  # webmockを有効化
  end

  describe "POST /api" do
    context "with valid params" do
      it "return 200" do
        # モックサーバーからのレスポンスのjsonファイルを読み込み
        let(:external_api_response) { 
          ActiveSupport::JSON.decode(File.read("spec/fixtures/response.json")).to_json
        }

        # モックサーバーを起動
        stub_request(:post, "https://external_api_test").to_return(
          body: external_api_response,
          status: 200
        )

        post hoge_path, params: { params: "hoge" }
        expect(response).to have_http_status(200)
      end
    end
```

# テスト時に叩かれる外部サービスのurlをモックサーバーのURLと同じものにする

先程、モックサーバーのurlを `https://external_api_test` としたので、テスト時に叩かれるurlを合わせておきます。
環境毎に指定をしている箇所を、下記のように修正します。

```yaml
# モックサーバーのurlと合わせる
test:
  protocol: https
  host: external_api_test

development:
  protocol: http
  host: localhost
  port: 8080

production:
  protocol: https
  host: external_api
```

とても簡単ですね！
【Kotlin】Spigot プラグイン チュートリアル

## Java と Kotlin
「まずは Java から…」って思ってる人、たくさんいますよね？
いや、Kotlin やりましょう！
「楽に」「早く」「間違えにくく」書けるほうが絶対良いです！！
Kotlin を知っていれば Java の知識も付きます。
習うより慣れよ。とりあえず書いてみましょう！！！

## 目次
### 1. 環境構築
#### [1.1 開発環境のインストール](https://qiita.com/sya-ri/items/87ad160d5418cdf5db00)
#### [1.2 プロジェクトを作成する](https://qiita.com/sya-ri/items/1ecccdba38fd3260f5ff)

### 2. やってみよう
#### [2.1 参加・退出メッセージを変更する](https://qiita.com/sya-ri/items/2b3e9e063048699ead50)
#### [2.2 コマンドを新しく作る](https://qiita.com/sya-ri/items/f69f1489b60650a7dd41)
#### [2.3 プレイヤーの頭を取得する](https://qiita.com/sya-ri/items/bebee642f72b46b59d0d)
#### [2.4 サイコロを作る](https://qiita.com/sya-ri/items/e6e5b94c5fff0b9af7e9)
#### [2.5 カウントダウンタイマーを作る](https://qiita.com/sya-ri/items/cc8be71c42dba8f86066)
文字列を操作するメソッド

よく使う文字列系メソッドについてまとめる．
※今後も継続して追加予定


###```trim()```メソッド
trimメソッドは，文字列の両端の空白を削除した文字列を返すメソッド．

```js:
const str = '   Hello!    '
console.log(str.trim())
//Hello!
```

###```split()```メソッド
splitメソッドは，引数で渡した文字列を取り除き，その前後で文字列の配列を生成するメソッド．

```js:
const str = 'abcdefg'
console.log(str.split('d'))
//['abc','efg']
console.log(str.split('de'))
//['abc','fg']
```
MAMPを使ったWordpressでのWEB制作方法4　初心者向け

#MAMPを使ったWordpressでのWEB制作方法4　初心者向け

前回の記事はこちら
[#MAMPを使ったWordpressでのWEB制作方法3　初心者向け](https://qiita.com/fumiya0414/items/4c855b29fd24a28a9538)

#トップページのwordpress化

今回から実際にPHPファイルを記述していきます。
その前に管理者画面で使用するテーマを有効化しましょう

外観→テーマからテーマを有効にします

[![Image from Gyazo](https://i.gyazo.com/57d30773668948f210978a652d282145.gif)](https://gyazo.com/57d30773668948f210978a652d282145)

サイトを表示すると真っ白な画面が表示されるはずです。
何も記述していないindex.phpを読み込んでいるので問題ありません。

次にindex.phpにindex.htmlの記述をすべてコピペします
ブラウザを再読み込みするとhtmlの記述が読み込めます
まだCSSは当たっていません

[![Image from Gyazo](https://i.gyazo.com/4a60201ca2dba957c75adcf0b48072b7.gif)](https://gyazo.com/4a60201ca2dba957c75adcf0b48072b7)
##ヘッダーの読み込み

次にheader.phpにヘッダー部分をカット＆ペーストします。
headerになるのは以下の部分です。

bodyタグの始まりやcontainerの始まりが含まれていて
気持ちが悪い感じがしますが問題ありません。

終了タグはfooter.phpで読み込みをするため
ここでは気にせずに進めましょう。
[![Image from Gyazo](https://i.gyazo.com/d606718762ed2f6d24a700a0b624fc39.png)](https://gyazo.com/d606718762ed2f6d24a700a0b624fc39)

そしてindex.phpの一番上に以下を記述します
ヘッダー読込の関数です

```php:index.php
<?php get_header(); ?>
```

②つのファイルは以下のようになります
[![Image from Gyazo](https://i.gyazo.com/f22ca95ec7790cf7b5f69881a4fc5635.png)](https://gyazo.com/f22ca95ec7790cf7b5f69881a4fc5635)

ブラウザを再読み込みすると結果は変わりませんので
2つのファイルがつながって読み込まれていることがわかります。

##フッターの読み込み
続いてindex.phpからフッターを切り取ります。
フッターは以下の箇所を切り取りします。
※jsの読込をしていますが使用しませんので無視して下さい。
bodyの終了タグなども一緒に切り取りをしてください。
[![Image from Gyazo](https://i.gyazo.com/6b9a4b893a56f3acf741b377954360d3.png)](https://gyazo.com/6b9a4b893a56f3acf741b377954360d3)

そしてfooter.phpに貼り付けをします。
切り取ったindex.phpに以下の記述をしてください
閉じカッコがないのは誤記ではなくPHPの仕様です。
ファイルの最後に来る場合はバグになることがあるため省略します。
※最後に来ない場合は閉じカッコをいれましょう

```php:index.php
<?php get_footer();
```
[![Image from Gyazo](https://i.gyazo.com/d8d94d1ae51395016cae91fe8a3fc9fa.png)](https://gyazo.com/d8d94d1ae51395016cae91fe8a3fc9fa)

再度ブラウザーを読み込むと結果は変わりませんので
分割したフッターも読み込みができていることがわかります。

##サイドバーの読み込み
続いてサイドバーを切り取り＆貼り付けします。
サイドバーの読み込みは以下のコードです

```php:index.php
<?php get_sidebar(); ?>
```

2つのファイルは以下のようにつながります。
[![Image from Gyazo](https://i.gyazo.com/44a0cf61917bcb217b195a6ce2519fda.png)](https://gyazo.com/44a0cf61917bcb217b195a6ce2519fda)

この処理でヘッダー、フッター、サイドバーの
各ページ共通部分を1つにまとめることができました。

次回はCSSなどの表示を直していきます。

次の記事をこちら
[MAMPを使ったWordpressでのWEB制作方法5　初心者向け](https://qiita.com/fumiya0414/items/f9a42a1957d89a3a4d18)
Dockerイメージの作成（初級２）


# 概要

「docker container run」と「docker-compose」の対応関係がよく分からないので大雑把に把握したい。
[「Dockerイメージの作成（初級１）」](https://qiita.com/yuzutarogo/items/66c22ea2dec593980169)の
「作成したDockerイメージから、docker container runでコンテナを実行」を
**「作成したDockerイメージから、docker-composeにてコンテナ実行」**に置き換えてみる。

## 作業の内容

- [こちら](https://qiita.com/yuzutarogo/items/66c22ea2dec593980169)で作成したDockerイメージを利用する
- Dockerイメージを単に実行するだけのdocker-compose.ymlを用意する
- 「docker-compose up」コマンドでコンテナを起動する。シェルが実行されて「Hello, World!」と出力する
- イメージ名：shellsample
- コンテナ名：shellsample
- [「初級１」](https://qiita.com/yuzutarogo/items/66c22ea2dec593980169)で作成したコンテナは「docker container rm」コマンドで事前に削除しておく
- 今回はComposeを覚える目的であるため、起動するコンテナは１つとする
- 階層構造は以下のとおり

```
shellsample
 ├ hello.sh
 ├ Dockerfile
 └ docker-compose.yml
```

# Docker Composeとは

Docker Composeはyaml形式の設定ファイルで、複数のコンテナ実行を一括で管理できる。
コマンドを１つ実行するだけで、設定した全てのサービスを作成・起動する。
※[詳細はこちら](http://docs.docker.jp/compose/overview.html)

# docker-composeに置き換えるコマンド

以下の「docker container run」コマンドと同等のことをdocker-composeで実現する。

```:Powershell
> docker container run -it --name shellsample shellsample
```

# docker-compose.ymlの作成

```:docker-compose.yml
version: "3.3"
services:
  shell:
    image: shellsample:latest
    container_name: shellsample
    stdin_open: true
    tty: true
```

【補足】
**version: "3.3"**
docker-compose.ymlのファイルフォーマットバージョンを宣言している。※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/)

**image**
コンテナーを起動させるイメージを設定。 ※[詳細](https://qiita.com/yuzutarogo/items/66c22ea2dec593980169)　

**container_name**
デフォルトのコンテナー名ではない、独自のコンテナー名を設定する　※[詳細](https://matsuand.github.io/docs.docker.jp.onthefly/compose/compose-file/#container_name)

**stdin_open**
「docker container run」のオプションに対応づいている（iオプションに相当）。
コンテナの標準入力とDockerホストの標準入力を接続する。

**tty**
「docker container run」のオプションに対応づいている（tオプションに相当）。
コンテナの標準出力とDockerホストの標準出力を接続する。

# コンテナ起動

「docker-compose up」コマンドでコンテナの作成と起動を行う。

```:Powershell
> docker-compose up

Starting shellsample ... done
shellsample | Hello, World!
shellsample exited with code 0
```
※「Hello, World!」を出力できた
※本サンプルはバックグラウンド実行する必要がないため、「-d」オプションは指定していない。

【補足】
[docker-compose コマンドの概要](http://docs.docker.jp/compose/reference/overview.html)


# 分かること

- 作業後のコンテナ一覧

「docker container run」の時と同様に「shellsample」コンテナが作成された。

```:Powershell
> docker container ps -a

CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS                     PORTS                    NAMES
4701fb8ae2b7        shellsample:latest    "/opt/shell/hello.sh"    51 minutes ago      Exited (0) 3 minutes ago                            shellsample
```

- コンテナを再度起動したときに出力がなされるか確認

出力されない。

```:Powershell
> docker-compose start
Starting shell ... done     
```
おそらく、「stdin_open: true」「tty: true」の設定をしたとしても実際にコンテナの標準入出力がアタッチされるのは「docker attach」コマンドを実行したあとであろうと思う。「docker attach」コマンドは、コンテナが実行されている状態で実行が必要だが、本サンプルは、出力を行った後、すぐにコンテナは終了するので試せない。

# 関連記事

- [Windows10でDocker環境構築手順](https://qiita.com/yuzutarogo/items/6b46c48e41b10949ba58)
- [Dockerイメージの作成（初級１）](https://qiita.com/yuzutarogo/items/66c22ea2dec593980169)
- [Dockerイメージの作成（初級３）](https://qiita.com/yuzutarogo/items/235f723f32195cda39a7)
「MixLeap Live Study #59 - Reactとその仲間たち」の参加まとめ

# はじめに

今回は[MixLeap Live Study #59 - Reactとその仲間たち](https://yahoo-osaka.connpass.com/event/170013/)に参加してきましたのでその内容についてまとめます。発表テーマはお題の通り、[React](https://ja.reactjs.org/)に関するお話でした。

# 「React + [GraphQL](https://graphql.org/)で社内の負債を解決した話」藤本 卓哉さん（株式会社Gemcook）

GraphQLを実際に業務に用いた話です。実際に用いたのはAWSのサービスの[AppSync](https://aws.amazon.com/jp/appsync/)をとのこと。実際にGraphQLをチャットアプリの開発に用いたお話をされました。GraphQLについての解説はここではしませんが、本格的に知りたい場合は[このオライリー本](https://www.oreilly.co.jp/books/9784873118932/)がオススメです。
ここでは開発にGraphQL(AppSync)を用いて良かったことと悪かったことについてお話されました。そのことについて以下にまとめます。

- 良かったこと
  - エンドポイントの本数を減らせた
  - ドキュメントの管理コストがなくなった
  - 必要なレスポンスを得られる
  - すべてをAWSで開発できた
- 悪かったこと
  - リゾルバーやマッピングテンプレートの管理方法の検討が必要になった
  - GraphQLの学習や実装コストが増えた
  - RESTで取得したくなる気持ちと戦う必要があった

印象としてはGraphQLという新しい形の仕様を導入するという学習コストが大きいが、フロントエンドとバックエンドの技術負債は減ったという感じでした。

# 「React Hooks公開から1年で得られた知見」西村 爽さん（株式会社Gemcook）

[React Hooks](https://ja.reactjs.org/docs/hooks-intro.html)を業務に導入して得られた恩恵についてのお話をされました。
Gemcookでも当初はクラスコンポーネントやRecomposeを用いていたみたいです。しかしHooksを導入することでStateの管理をシンプルにできたり、カスタムフックを用いてコンポーネント間のロジックの共通化ができるようになったとのことです。実際に用いたライブラリは以下のものとのこと、

- [react-use](https://github.com/streamich/react-use)
- [react-table](https://github.com/tannerlinsley/react-table)
- [Formik](https://jaredpalmer.com/formik/docs/overview)

これからはカスタムフックを提供するライブラリが主流になるとのお話をされました。

# 「React/ReduxにSelectorを導入したら幸せになった話」松井 真子さん（ヤフー株式会社）

Reactで入稿ツールを開発するといった内容でお話されました。テーマは、入稿ツールを開発する際に困ったことの一つとしてのバリデーションの実装が複雑になったことへの解決についてでした。
[Reselect](/github.com/reduxjs/reselect)を用いることでStateを渡す前にバリデーションをかけることができて、実装を切り分けることができたとのことでした。

# 「React × Unity」 青山 広大（ヤフー株式会社）

[Unity](https://unity.com/ja)とReactの連携を[react-unity-webgl](https://www.npmjs.com/package/react-unity-webgl)を用いて行ったというお話でした。このライブラリを用いることでUnityでビルドしたソースコードをReactで呼び出すことができるみたいです。また逆に、Unity側からReactのコードを呼び出すこともできるみたいですね。

# 「[React Native](https://reactnative.dev/)で家計簿アプリを作って得たもの」 西仲 幸太さん（ヤフー株式会社）

タイトルの通り、家計簿アプリをReact Nativeで行ったというお話でした。経緯としては、複雑な家計簿の計算を行うアプリを開発したかったからとのことです。ステート管理にRedux、画面遷移のハンドリングに[React Navigation](https://reactnavigation.org/)、データの保存には[Firebase](https://firebase.google.com/?hl=ja)を用いたそうです。
これらのツールを用いることで高速でアプリの開発ができるようです。

# さいごに

使ってなかったツールの紹介がほとんどだったので、明日にでもやってみたい（やるかどうかは別として）なと思いました。個人的にはAppSyncで次は記事を書いてみたいなと思いました。
フロントエンドエンジニアリング

#JSONとは
ブラウザ上にどのようにテキストを表示させるかを指定するマークアップ言語の一つ.

同じマークアップ言語でもあるXMLと比較して，簡易的でわかりやすいというメリットがある．

##JSON文字列→JavaScriptオブジェクトへの変換

```js:
JSON.parse(jsonString)
```

##JavaScriptオブジェクト→JSON文字列への変換

```js:
JSON.sringify(jsObject)
```
#DOMとは
マークアップ言語をJavaScriptなどのプログラミング言語で操作するためのAPI.

DOMにおいて，マークアップ言語はツリー構造として扱われる．

※今後ajaxなどにも触れてより詳細にまとめる予定
ConsoleAppFramework ＋ ZLogger の実装例

[前回の記事](https://qiita.com/panda728z/items/7638c84d0e07a9f85ec3)でConsoleAppFrameworkのサンプル作りましたが、
ロガーは既存のプログラムからの移行の関係でSerilogでした。

でもロガーとしては[ZLogger](https://github.com/Cysharp/ZLogger)があります。
とりあえず動作してみましたというだけのサンプルになります。

（残念ながら現在、構造化ログを扱える環境がないので、
　　構造化ログに移行するなら環境整えるところからスタートです）

（余談：既存のSerilogで貯めこんだログはありますが、あまり活用できてません。
Slack投稿や、特に見たいデータについては、別に集計プログラム作って対応なので手間かかってますｗ
構造化ログに移行して、かっこいいグラフとかで見てみたいですね）

```c#:Program.cs&nbsp;(全文)
using System;
using System.Threading.Tasks;
using ConsoleAppFramework;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ZLogger;

namespace MyConsoleApp {
    class Program {
        static async Task Main(string[] args) {
            await CreateHostBuilder(args).RunConsoleAppFrameworkAsync(args);
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(logging => {
                    logging.ClearProviders();
                    logging.SetMinimumLevel(LogLevel.Debug);
                    logging.AddZLoggerConsole(options => {
                        options.EnableStructuredLogging = true;
                    });
                    logging.AddZLoggerRollingFile((dt, x) =>
                        $"logs/{dt.ToLocalTime():yyyy-MM-dd}_{x:000}.log",
                        x => x.ToLocalTime().Date,
                        1024,
                        options => {
                            options.EnableStructuredLogging = true;
                        });
                })
                .ConfigureServices((hostContext, services) => {
                    services.Configure<Settings>(
                        hostContext.Configuration.GetSection("Settings"));
                });
    }
}
```

ConsoleAppBaseは変更なしのため省略します。
[前回の記事](https://qiita.com/panda728z/items/7638c84d0e07a9f85ec3)を参照ください

ログ設定を書き換えただけなので簡単です。内容はサンプルそのままです。

作成されるログは構造化ログを指定したので以下の通り。（起動ログだけですが）

```json
{"CategoryName":"Microsoft.Extensions.Hosting.Internal.Host","LogLevel":"Debug","EventId":1,"EventIdName":null,"Timestamp":"2020-04-28T11:47:08.9890315+00:00","Exception":null,"Message":"Hosting starting","Payload":null}
{"CategoryName":"Microsoft.Extensions.Hosting.Internal.Host","LogLevel":"Debug","EventId":2,"EventIdName":null,"Timestamp":"2020-04-28T11:47:08.9950747+00:00","Exception":null,"Message":"Hosting started","Payload":null}
{"CategoryName":"Microsoft.Extensions.Hosting.Internal.Host","LogLevel":"Debug","EventId":3,"EventIdName":null,"Timestamp":"2020-04-28T11:47:09.001556+00:00","Exception":null,"Message":"Hosting stopping","Payload":null}
{"CategoryName":"Microsoft.Extensions.Hosting.Internal.Host","LogLevel":"Debug","EventId":4,"EventIdName":null,"Timestamp":"2020-04-28T11:47:09.0026856+00:00","Exception":null,"Message":"Hosting stopped","Payload":null}
```


このご時世なので、家で構造化ログを調べようかと。DataDog楽しそうですし。
ルートパスの設定方法

#ルートパスの設定方法
英語で書くとrootになる。
以下。記述
`routes.rb`

```ruby
root to: "コントローラー名#アクション名"
```
英語でrootは根っこという意味があり、
ここから様々に分岐していくイメージです。
なので、色んなアクションが記載されているコントローラー名を記載します。
アクションの種類を知りたい方がいるなら以下を参照してください。
[７つのアクション種類](https://qiita.com/Nyanmaru-12/items/fa03252b740bb1a49332)
【Node.js】SequelizeのDB接続情報を環境変数で管理する

# 経緯
Sequelizeのデフォルトは `config.json` というファイル内でDBへの接続情報を管理しているので、 `.env` などの環境変数で管理したかった。

# 結論
`config/config.json` の中身を以下のようにモジュール化して、拡張子を `.js` に変更する。

`dotenv` で環境変数を読み込む。

``` config.js
require('dotenv').config();

module.exports = {
  'development': {
    'username': process.env.DB_USERNAME,
    'password': process.env.DB_PASS,
    'database': process.env.DB_DATABASE,
    'host': process.env.DB_HOST,
    'port': '3306',
    'dialect': 'mysql',
    'operatorsAliases': false,
  },
};
```

`model/index.js` の以下を編集を編集する。

```index.js
// 編集前
const config = require(__dirname + '/../config/config.json')[env];
//　編集後
const config = require(__dirname + '/../config/config.js')[env];
```
Javascript勉強メモ_基礎_VSCode開発環境の構築

#VSCodeをインストールする

####1.VSCodeの以下のダウンロードページにジャンプします。

https://code.visualstudio.com/

ページのDown Load for Windowsのボタンをクリックしてインストーラをダウンロードします。

![2020-04-28 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/e45dd8e7-92ed-75e7-7ba8-cdf894ffc063.png)

インストール方式などを選択する場合は、ページの最下部まで移動し、好きなインストール方式をダウンロードします。

![2020-04-28 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/0bef80bf-51c6-3f26-9065-dcd154d5305a.png)

画面の左下のWindows版では"User Installer"、"System Installer"、".zip"の3種類がありますが、ここでは、User installer版(64 bit)を使うことにします。

####2.VSCodeをインストールする

自分のインストール手順は以下の通りです。
①ダウンロードしたインストーラー(ここでは、VSCodeUserSetup-x64-1.44.2.exe)をダブルクリックします。
②同意するを選択し、次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/a138fdae-dd30-2741-9797-4ad104763f0d.png)
③お好みのフォルダに変更して(ここでは、G:\Develop\Microsoft VS Code)、次をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/25f21776-cada-d6d5-755d-007145b51c27.png)
④そのまま次をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/15f8b467-378b-1fab-ab22-df1e20a7d818.png)
⑤このままPATHへの追加のみチェックが入った状態で次へをクリックしてもいいですが、個人的にコマンドから実行することはないので、チェックを外しました。また、ここでは「エクスプローラーのファイルコンテキスト～」「エクスプローラーのフォルダコンテキスト～」の両方にチェックを入れて、次へをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/2d2062f6-bfa9-d3ce-4511-86cd0fe35e03.png)
⑥設定内容を確認して、インストールをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/5bc99c61-05c3-ef94-fd76-7c06e6896231.png)
⑦インストール完了まで待ちます、インストール完了後に、完了をクリックしてVSCodeを立ち上げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/ea642981-97a6-a4ee-85fb-09c2e9a167d3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/aaa5cb8f-6eb5-100b-ffca-38f40b562067.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622314/7e5fd45f-738e-3573-d368-bdc6a3b569a0.png)

VSCodeのインストールは以上です。
Google Colabを用いてGoogle Drive内のフォルダを削除する

#はじめに

Google colabでスクリプトを作る際には、Google Driveと連携させるのが便利です。
スクリプトにより生成されたファイルはGoogle Driveに保存されていきます。

連携において不便に感じるのは、ColabからDrive内のフォルダを削除しようとするとエラーが出ることです。
中身が空のフォルダは消せますが、中のファイルを1個1個消すのも面倒です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/511e0d4c-7058-2484-9d27-dce7ecfb33ed.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620139/ad6f2603-5b62-81dd-90f4-c24e3d9510e8.png)


#Google Drive内のフォルダを削除するスクリプト

###フォルダごと削除したいとき
shutil.rmtreeを使うと、指定したフォルダごと削除できます。
削除されたフォルダはGoogle Driveのごみ箱に入ります。

```
import shutil

directory = 'ここにパスをコピペ'

try:
    shutil.rmtree(directory)
except FileNotFoundError:
    pass
```

###フォルダを残して中身だけ削除したいとき
中身ごと一度消してしまって、フォルダを作り直すと楽です。

```
import shutil

directory = 'ここにパスをコピペ'

try:
    shutil.rmtree(directory)
except FileNotFoundError:
    pass

#同名のフォルダを作成する
os.mkdir(directory)
```

###下位のフォルダは残して、中のファイルのみ削除したいとき
glob.globを用いる方法もあります。

```
import os

directory = 'ここにパスをコピペ'
files = os.listdir(directory)
print(directory)
print(files)

for i in files:
    try:
        os.remove(directory+'/'+i)
    except IsADirectoryError:
        pass
```

#おわりに
Colabのスクリプトの後ろにコピペしておくと、ちょくちょく掃除ができるので便利です。
では、快適なColab Lifeを！！
AWS CLI v2 と Session ManagerでEC2にログインする時のssh config

# 目的

AWSのEC2インスタンスに[Session Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager.html)で接続する場合に接続先としてインスタンスIDを指定しなければならないがインスタンスIDは再作成などで変更される場合がある。
インスタンスIDが変更になってもSSH Configを変更しなくて良いように設定する。

# 前提条件

* 利用環境にAWS CLI v2 がインストールされている (インストール方法https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html)
* 利用するIAM User は作成済み
* 利用するアクセスキーとシークレットキー も発行済み
* 接続先のEC2インスタンスにはtagにインスタンス名が設定されている

このようにインスタンスにNameタグが付いているとする

```bash

$ aws --profile foo ec2 describe-instances --query "Reservations[*].Instances[*].Tags[]" --output table
----------------------------------------------------
|                 DescribeInstances                |
+-----------------+--------------------------------+
|       Key       |             Value              |
+-----------------+--------------------------------+
|  Name           |  development-01                |
|  Name           |  development-02                |
|  Name           |  staging-01                    |
|  Name           |  staging-02                    |
+-----------------+--------------------------------+

```

# 今回の環境

macOS 10.14.6
AWS CLI v2 (aws-cli/2.0.0dev2 Python/3.7.4 Darwin/18.7.0 botocore/2.0.0dev1)

# 設定方法

## AWS CLIの Profile

今回は fooというプロファイルを設定して利用する

```~/.aws/config

(抜粋)

[profile foo]
output=json
region=ap-northeast-1
```

アクセスキーとシークレットキーをfooに設定する

```~/.aws/credentials

(抜粋)
[foo]
aws_access_key_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxx
aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

```


## SSH configの設定

このような構成

```bash

$ tree ~/.ssh
├── aws-ssm-ec2-proxy-command.sh
├── config
└── foo-key

```



sshのプロキシコマンドのスクリプト（作成したらchmodで実行権限を与えておく）

```aws-ssm-ec2-proxy-command.sh
#!/bin/sh
instanceId=$(aws --profile $1 ec2 describe-instances --query "Reservations[*].Instances[*].InstanceId" --filters "Name=tag:Name,Values=[$2]" --output text)
echo "ssm start session... to $2(${instanceId})"
aws --profile $1 ssm start-session --target ${instanceId} --document-name AWS-StartSSHSession --parameters 'portNumber=[22]'
```

1行目： AWS CLIを使ってインスタンスIDを取得している
3行目： 1行目で取得したインスタンスIDでSessionを開始するコマンドを実行している


SSH config 設定

```~/.ssh/config

Host pj-d1
    User ec2-user
    IdentityFile ~/.ssh/foo-key
    ServerAliveInterval 60
    TCPKeepAlive yes
    ProxyCommand ./aws-ssm-ec2-proxy-command.sh foo development-01

```

Host： 自分が指定したいホスト名（覚えやすい任意の名前をつける）
User: sshログインユーザ
IdentityFile: 秘密鍵ファイルのパス
ServerAliveInterval: 接続タイムアウトする秒数
TCPKeepAlive: 接続を維持するかどうか
ProxyCommand: 上記で作成したsshのプロキシコマンドのスクリプトファイル(引数１：AWS CLIのprofile名, 引数2: 接続したいEC2インスタンスのタグに指定した名称


## SSH接続する

```bash

$ ssh pj-d1

```

## SCPでファイル転送する

カレントのbar.txtファイルをpj-d1のホームディレクトリにアップロードする。

```bash

$ scp ./bar.txt pj-d1:~

```

インスタンスIDを気にすることなく接続できるようになった。
【Node.js】Dockerで作成したMySQLをDUMPする

# 経緯
Docker-composeで作成したMySQLのデータをAmazonRDSに移行する必要があった。

# 結論

## Dockerコンテナで作成したMySQLデータをRDSなどの外部サーバーに移行する

エクスポート時

```
$ docker exec コンテナ名 mysqldump --default-character-set=文字コード（utfmb4など） -u　ユーザ名 -p パスワード データベース名 > backup.sql
```

インポート時

```
mysql --default-character-set=文字コード -h エンドポイント（AmazonRDSの場合） -P 3306 -u admin -p データベース名 < backup.sql
```

## Sequelize（Node.jsのORM）を使ってスキーマを作成していた場合

エクスポート時

```
$ docker exec コンテナ名 mysqldump  --skip-lock-tables　--default-character-set=文字コード（utfmb4など）　--ignore-table=データベース名.SequelizeMeta  -u　ユーザ名 -p パスワード データベース名 > backup.sql
```

インポート時

```
mysql --default-character-set=文字コード -h エンドポイント（AmazonRDSの場合） -P 3306 -u admin -p データベース名 < backup.sql
```

Sequelizeを使ってスキーマを作成していた場合は `SequelizeMeta` というテーブルが作成されているので、dumpを作成しようとすると、以下のようなエラーになります。（アッパーキャメルだから？）　

```
doesn't exist when using LOCK TABLES
```
```
Couldn't read status information for table SequelizeMeta
```

なので、dump作成時に `--skip-lock-tables` と `--ignore-table` オプションを使います。

Sequelizeを用いたアプリケーションにおける、dump作成からRDSなどの外部サーバーで同じ環境を構築する流れは以下のようになります。

```
コンテナ内でdump作成
↓
RDSなどの移行先サーバーでマイグレーションを実行する
(ここでSequelizeMetaテーブルは正常に作成される)
↓
dumpをインポートする
```

## インポートしたデータが文字化けする場合
dumpしたデータを読み込んだ際に日本語のデータが文字化けする場合があります。

原因は
`--default-character-setオプション` の設定が間違っている
`DBサーバの文字コード設定` が間違っている
といったものが予想されます。

RDSの場合は以下の記事が参考になりました。
[[AWS][RDS][MySQL] 文字コードをutf8mb4にする](https://qiita.com/Masahiro_T/items/9db89e12e39b2b6dbb45)
Salome-Meca2019.0.3のubuntu18.04へのインストール

##PC環境
+ CPU intel Core i5 8th Gen
+ RAM 8GB（うち4GBをゲストに割当て）
+ HDD 90GB残（うち30GBをゲストに割当て）
+ Host OS Windows 10
+ Guest OS Ubuntu18.04.4
+ 仮想マシン Virtual Box 1.6 r137129 (Qt5.6.2)

#Ubuntuのインストール
+ VirtualBoxのディスプレイの設定でビデオメモリーを128MBにする以外はデフォルトのまま．ストレージにUbuntu18のisoファイルをセットする．
+ Ubuntuのインストーラーを起動し，英語環境（キーボードは日本語）でインストール開始する．サードパーティのソフトウエアを受け入れる．
+ インストールが済んだら再起動
+ OSの更新

```
sudo apt update
```

+ Guest Additionのインストール
+ 共有フォルダの設定
+ 共有フォルダにアクセス権を与える

```
sudo gpasswd -a user vboxsf
```

※ userはユーザ名

+ 再起動する

##Salome-Mecaのインストール
+ 次の記事を参考にprerequisitesをインストールする
code-aster.orgの記事(https://www.code-aster.org/spip.php?article1112)
+ prerequisitesのインストール

```
sudo apt install wget net-tools python python3 libbsd0 libbz2-1.0 libc6 libdbus-1-3                  libexpat1 libffi6 libfontconfig1 libfreeimage3 libfreetype6 libgcc1 libgfortran3 libglib2.0-0 libglu1-mesa libgomp1 libharfbuzz0b libice6 libicu60 libilmbase12 libjbig0 libjpeg62 liblcms2-2 liblzma5 libmng2 libmuparser2v5 libnlopt0 libnss-sss libopenblas-base                  libopenexr22 libpcre3 libpng16-16 libquadmath0 libraw16 libreadline7                  libsm6 libssl1.0.0 libstdc++6 libtbb2 libtiff5 libtinfo5 libuuid1 libx11-6 libx11-xcb1 libxau6 libxcb-glx0 libxcb1 libxcursor1 libxdmcp6 libxext6 libxfixes3 libxi6 libxml2 libxmu6 libxrender1 libxss1 libxt6 xterm x11-xkb-utils xkb-data zlib1g
```

+ 更新
 
```
sudo apt update
```

+ code-aster関係GUIのインストール

```
sudo apt install code-aster-gui
```

+ 自動インストールスクリプトのダウンロード
https://www.code-aster.org/spip.php?article1112 より
![edfscript2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608825/cb569312-8417-a568-19ba-a9f63b136ed9.jpeg)
+ スクリプトの解凍と実行

```
unzip sm2019_ubuntu18_install.sh.zip
bash sm2019_ubuntu18_install.sh
```
sm2019_ubuntu18_install.shはダウンロードしたスクリプト名に合わせる

+ インストールが正常終了したら再起動する

# 起動確認
+ インストール先フォルダからappli_V2019xxxを探す
+ そのフォルダでsalomeを実行する

```
./salome
```

+ 起動したらFileメニューから「Save as」を開き，作業フォルダを作成してhdfファイルを保存する

![OpenFrame.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608825/871d1918-379d-e752-27e0-cc0f7f6dbcdc.jpeg)
さくらサーバで指定ディレクトリだけPHPバージョン変更している際にBASIC認証除外が効かなくなる問題

# 前提

さくらサーバのマネージドプラン（他のプランは調べてない）は、以下のようにすることで指定ディレクトリ以下のPHPのバージョンを任意に指定することができる。

```:/webルート/.htaccess
Action myphp-script /php.cgi
AddHandler myphp-script .php
```

```:/webルート/php.cgi
#!/bin/sh
exec /usr/local/php/7.3/bin/php-cgi
```


# 問題
`/webルート/.htaccess`で除外認証を設定しつつ、`/webルート/api`ディレクトリのBASIC認証除外するために以下のファイルを設置したが、BASIC認証が解除されない。

```/webルート/api/.htaccess
Satisfy any
order allow,deny
allow from all
```


# 解決方法
`/webルート/.htaccess`のBASIC認証部分に以下を追記する。

```:/webルート/.htaccess
# さくらサーバで指定ディレクトリだけPHPバージョン変更している際にBASIC認証除外が効かなくなる問題の対応
<FilesMatch "(php\.cgi)$">
  Satisfy Any
  Order allow,deny
  Allow from all
  Deny from none
</FilesMatch>
```


# まとめ
昔は問題なかった気がするけど、いつのまにかこれしないといけなくなってた。
【devise】　管理者　ユーザー　ログイン、ログアウト分ける


#【ゴール】
deviseで管理者とユーザーのログインとログアウトを別物にする。
どちらかがログイン、ログアウトするとviewの内容の変更を防ぐ為

参考にしたページ：https://pinzolo.github.io/2016/01/30/devise-not-sign-out-all-scopes.html

#【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

#【実装】

とても簡単！！
下記ファイルの２４３行目あたりの記述を変更

```config/initializers/devise.rb

# config.sign_out_all_scopes = true　#これを

            　↓

config.sign_out_all_scopes = false　#これに

```


以上
MAMPを使ったWordpressでのWEB制作方法3　初心者向け

#MAMPを使ったWordpressでのWEB制作方法3　初心者向け

前回の記事はこちら
[#MAMPを使ったWordpressでのWEB制作方法2　初心者向け](https://qiita.com/fumiya0414/items/5cd17bf734af65368763)

##Wordpress化に必要なファイルの作成
今回htmlファイルをwordpress化するために必要な
phpファイルを作成していきます

今回作成するファイルは以下の６つです
ファイル名はwordpressにて定義されているので同じ名前にしてください
中身は空で大丈夫です

index.php　トップページのファイル
header.php　ヘッダーのファイル（部分テンプレート）
footer.php　フッターのファイル（部分テンプレート）
sidebar.php　サイドバーのファイル（部分テンプレート）
page.php　固定ページ用ファイル
single.php　投稿ページ用ファイル
archive.php　記事一覧ページ用ファイル
functions.php　機能追加時などのファイル

まずはこれらをhtmlファイルのあるディレクトリに作成しましょう

[![Image from Gyazo](https://i.gyazo.com/989d56033c38af8c0192756874a7ad0b.png)](https://gyazo.com/989d56033c38af8c0192756874a7ad0b)

このような構成になっていればOKです

次にこれを以下のディレクトリに格納します

Application/MAMP/htdocs/wordpress/wp-content/themes

以下のようになっていればOKです。
今回使用するファイルはcorporate_sampleという名前にしてあります。
こちらは任意ですので好きな名前をつけましょう
[![Image from Gyazo](https://i.gyazo.com/06272f4e952b2cfb3607d77f26b0773a.png)](https://gyazo.com/06272f4e952b2cfb3607d77f26b0773a)

この段階でMAMPを起動しlocalhostを確認しましょう
パスの末尾にadminをつけると管理者画面に入れます。
[![Image from Gyazo](https://i.gyazo.com/5cadaa78bfecaf88bc919b7212f7d3d2.png)](https://gyazo.com/5cadaa78bfecaf88bc919b7212f7d3d2)

外観→テーマをクリックすると作成したファイルの一覧が表示されます。
が、今の段階ではまだここに表示がされません
下の方を確認すると壊れているテーマと警告が出ています。

[![Image from Gyazo](https://i.gyazo.com/46b0c09f23c0f4c2b2f901ea1f11b7ff.png)](https://gyazo.com/46b0c09f23c0f4c2b2f901ea1f11b7ff)
##style.cssの設定

wordpressのテーマはディレクトリの一番上にstyle.cssの
CSSファイルが必要なため警告が出ています。

よってディレクトリの一番上にstyle.cssの空ファイルを作成します。
[![Image from Gyazo](https://i.gyazo.com/e59c8c25adde3eeae593d8a5a7f108ee.png)](https://gyazo.com/e59c8c25adde3eeae593d8a5a7f108ee)

管理者画面を再読み込みすると以下のようにテーマとして認識されます。
[![Image from Gyazo](https://i.gyazo.com/8e6c690397958b7230c666379bc8c764.png)](https://gyazo.com/8e6c690397958b7230c666379bc8c764)

このシートにはテーマの情報を記入できますので以下のように書いておきましょう

```css:style.css
/*
Theme Name: corporate_sample　テーマの名前
Theme URI: http://　URL
Description: A theme by <a href="http://www">title</a>.
Version: 1.0.0　バージョン
Author: fumiyaozaki　製作者
Author URI: http://www 制作者のURL
*/
```

記載した情報はテーマの詳細として認識されます
[![Image from Gyazo](https://i.gyazo.com/27a54195602895ec38445f72b540804b.png)](https://gyazo.com/27a54195602895ec38445f72b540804b)

ここまでの動作が問題なければ
次回よりphpファイルに記述をして
wordpress化をしていきます。

[MAMPを使ったWordpressでのWEB制作方法4　初心者向け](https://qiita.com/fumiya0414/items/6ba9d0617bfd5a032fbd)
Athenaでtimestamp型が空白になる場合の対応とutcからjstへの変換

## timestamp型で困ったこと

```
2020-04-21 04:51:25 UTC
2020-04-26 16:01:22 UTC
```
といった時刻表記をAthenaでjstの時刻でtimestamp型に変換する際に調べたことを記録しておく。
上記表記はUTCという余計な文字列が入っていたりとそのままではtimestamp型に変換できないのでいくらか変換の手順を踏んだ。
今回はカラム名をtime_columnとする

## 結論
```sql
cast(substr(time, 1, 20) as timestamp)  + interval '9' hour as time
```
これで変換できた

## 変換手順

#### 文字列削除
まず、UTCといった文字列を削除するためにsubstr関数で文字列を消去する。

```sql
substr(time_column, 1, 19)
```

#### キャスト
余計な文字列の削除ができたのでtimestamp型にキャストする

```sql
cast(substr(time, 1, 20) as timestamp)
```

#### utcからjstに変換
+ intervalで時間の加減算が可能となる。今回はhourだがdayなども可能。
[参考](https://docs.aws.amazon.com/kinesisanalytics/latest/sqlref/sql-reference-date-timestamp-interval.html)

```sql

cast(substr(time, 1, 20) as timestamp)  + interval '9' hour
```

## timestamp型を指定すると値が空白になってしまう
今回の元データがもし

```
2020-04-21 04:51:25
2020-04-26 16:01:22
```
だったとしても元からtimestamp型を選択したとしても、エラーはでないが値がとれない（空白となる）。
これは`YYYY-MM-DD HH:MM:SS.fffffffff`という形式でないといけないかららしい。
AWSのドキュメントにもその対応がある
[Amazon Athena のテーブルにクエリを実行すると、TIMESTAMP の結果が空になる](https://aws.amazon.com/jp/premiumsupport/knowledge-center/query-table-athena-timestamp-empty/)
リンク先の解決でも良いが、自分は今回parquetにも変換したかったので`create table as`で対応した
[AthenaでCSVファイルからParquet形式へ変換](https://qiita.com/YujiHamada3/items/711945d84b27b079ad38)
こんなドキュメント用意するくらいなら`YYYY-MM-DD HH:MM:SS`に対応してくれないのかな…とはちょっと思う（キャストはうまくいくわけだし）。