OmniAICreator/Qiita-1.07M huggingface dataset:
Node.js、Yarn、Vue.js、Express.js インストール(Windows)

# Node.js インストール ～ 起動（node:v10.16.0, npm:v6.9.0）
- インストーラー取得 https://nodejs.org/en/download/
- インストーラー実行<br>
画面に従い進める、許可などは確認して同意、はいを選択
- インストール確認<br>
コマンドプロンプトで以下を実行してバージョンが表示されればOK<br>
`node --version`<br>
`npm --version`
- プロジェクトフォルダを作成<br>
コマンドプロンプトで以下を実行して${フォルダパス}に node_modules, package.json, package-lock.json あればOK<br>
`cd ${フォルダパス}`<br>
`npm install express --save` ※WARNでるが気にしない<br>
`npm init -y` ※ -y を指定しない場合、対話形式で進む
- 実行用のapp.js, index.html を作成<br>
${フォルダパス}の直下に以下を作成、両方とも utf8<br>

```javascript:app.js
var express = require('express');
var app = express();
app.use(express.static('./'));
var port = 8080;
app.listen(port,function(){
  console.log("express server port %d", port)
});
```
```html:index.html
<!DOCTYPE html>
<html>
<head>
<title>タイトル</title>
</head>
<body>
こんにちは Nodejs
</body>
</html>
```

- server 実行<br>
コマンドプロンプトで以下を実行して起動ログでればOK<br>
`node app.js`
- server アクセス http://localhost:8080/

# Yarn インストール ～ 起動（yarn:v1.17.3）
- Node.js のインストーラー実行までやっておく
- Yarn をインストール<br>
コマンドプロンプトで以下を実行<br>
`npm install -g yarn` ※-g を指定することでどこでも使えるようになる<br>
- インストール確認<br>
コマンドプロンプトで以下を実行してバージョンが表示されればOK<br>
`yarn --version`<br>


# Vue.js (vue:v3.9.3)
- Node.js のインストーラー実行までやっておく
- Vue CLI をインストール<br>
コマンドプロンプトで以下を実行<br>
`npm install -g @vue/cli` ※-g を指定することでどこでも使えるようになる<br>
`npm install -g @vue/cli-service-global` ※-g は上記同様<br>
- インストール確認<br>
コマンドプロンプトで以下を実行してバージョンが表示されればOK<br>
`vue --version`<br>
- プロジェクトフォルダを作成<br>
コマンドプロンプトで以下を実行してプロジェクトフォルダができればOK<br>
`cd ${プロジェクトルートパス}`<br>
`vue create -d ${プロジェクトフォルダ名}` ※-d を指定しない場合、対話形式で設定
- プロジェクトフォルダに移動して server 起動<br>
コマンドプロンプトで以下を実行して npm のプロンプトあがればOK<br>
`cd ${プロジェクトルートパス}\${プロジェクトフォルダ名}`<br>
`npm run serve`
- server アクセス http://localhost:8080/

# Express.js (express:v4.16.1) TBD
- Node.js のインストーラー実行までやっておく
- express インストール<br>
`npm install -g express` ※-g を指定することでどこでも使えるようになる<br>
`npm install -g express-generator` ※-g は上記同様<br>
- インストール確認<br>
コマンドプロンプトで以下を実行してバージョンが表示されればOK<br>
`express --version`<br>
- プロジェクトフォルダを作成<br>
コマンドプロンプトで以下を実行してプロジェクトフォルダができればOK<br>
`cd ${プロジェクトルートパス}`<br>
`express ${プロジェクトフォルダ名}`<br>
`cd ${プロジェクトルートパス}\${プロジェクトフォルダ名}`<br>
`npm install`
- プロジェクトフォルダを作成<br>
- server 起動<br>
コマンドプロンプトで以下を実行<br>
`npm start`<br>
#PowerApps ペン入力コントロールのEmptyを判定する

# はじめに
入力フォームなどをPowerAppsで作成し、「すべて入力されたら次に遷移」みたいな動作って、PowerAppsに限らずよくありますよね。
PowerAppsで実現する場合には、各種コントロールに関して IsBlankや、IsEmptyを使って、入力があるか（空でないか）を判定することができます。
しかし、例えば署名をペン入力コントロールで行う場合、残念ながらペン入力にはIsEmpty、IsBlankは有効ではありません。（空なのにIsEmpty, IsBlankがfalseになる）
また、単純に```PenInput.Image```を変数に入れて比較しただけだと、画像のパスがコントロールを触るたびに変化するので、よろしくありません。

![Screen Shot 2019-07-30 at 12.11.17 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/263d9b81-a297-e761-cbc8-fcb13ba65574.png)
今回はこのような場合に、どうやってペン入力の"空"を判定するかを紹介します。

# セットアップ
状況を簡単化して、画面にペン入力コントロールを１つ、タイマーを１つ、判定結果を表示するラベルを１つ設置します。
タイマーは、ペン入力コントロールの入力された結果の画像を監視するような役割で、10msおきに画像をある変数に格納しています。

![Screen Shot 2019-07-30 at 12.17.21 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/8b1b17b2-b324-5147-997d-18291b5788c7.png)

# いざ判定
方法は単純です。ScreenのOnVisibleプロパティに以下の数式をセットします。

```Screen2.OnVisible
Reset(PenInput3);
Set(defaultImage, JSON(PenInput3.Image, IncludeBinaryData) );
```

Resetはペン入力コントロールの初期化を行なっています。その後、ペン入力コントロールの画像```PenInput3.Image```をJSON関数を用いてdata uriに変換して変数に格納しています。
※ここがポイント！data uriにすると、空の画像に対して一意性を持たせることができます。
※JSON関数の利用については [前の記事](https://qiita.com/h-nagao/items/1e89e16fe59d458bd4d1)を参考にしてください。

ペン入力された画像の検出ですが、これにはタイマーのOnTimerEndに以下の数式を設定しています。なお、タイマーは間隔を10ms、リピート有効、自動スタートにしています。

```Timer1.OnTimerEnd
Set(currentImage, JSON(PenInput3.Image, IncludeBinaryData) );
```

初回表示時と同様に、一定間隔で別の変数（ここではcurrentImage）にペン入力の画像のdata uriを格納しています。
あとはこれらの二つを比較することで、入力が空かどうかを判定できます。

この方法は、例えば入力をXボタンでリセットした場合や、消しゴムで全部綺麗に消した場合にも有効です。
詳細は以下のTweetをご覧ください。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/hashtag/PowerApps?src=hash&amp;ref_src=twsrc%5Etfw">#PowerApps</a> : how to detect &quot;IsEmpty(PenInput)&quot; <a href="https://t.co/mKRjMmY0wr">pic.twitter.com/mKRjMmY0wr</a></p>&mdash; Hiro (@mofumofu_dance) <a href="https://twitter.com/mofumofu_dance/status/1155845207469899777?ref_src=twsrc%5Etfw">July 29, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
AWS VPCでIPv6を使う

# AWS VPCでIPv6を使う

## VPC の作成
この画面から作成を押下
<img width="520" alt="Screen Shot 2019-07-30 at 0.09.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/afdd806a-9692-f577-09a6-d713395a3852.png">

## IPv6 CIDRブロックの指定
「Amazon が提供した IPv6 CIDR ブロック」を選択
<img width="614" alt="Screen Shot 2019-07-30 at 0.10.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/e2217c54-d6b1-d52a-dadc-38469c267641.png">

## VPC 完成
/56が割当完了
<img width="554" alt="vpc.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/e40462e0-c13d-50d9-23f5-85cc3de81312.png">

## サブネットの作成
この画面から作成を押下
<img width="487" alt="Screen Shot 2019-07-30 at 0.18.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/6de06099-1d3b-b355-a3f1-7ba0a87dee91.png">

## アドレス割当
IPv4同様にIPv6のサブネットの2桁(56-64bit)を指定
<img width="792" alt="sub1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55879/f27e7086-24e9-e2e2-bd1d-b1d98234903c.png">
azは必要分作成

##　ec2等 作成
- ネットワーク：作成したVPCを指定
- サブネット：作成したサブネットを指定
Windowsフォームでの高DPI(Hi-DPI)対応のコツ

# はじめに
Windowsフォームアプリをなるべく簡単に高DPI(Hi-DPI)対応させるコツをまとめました。
Windowsフォームの自動スケーリング機能を活用します。

# 今回やらないこと
下記機能が.NET Framework 4.7でサポートされましたが、実装コストが高いので対応はしません。

- 起動中のDPI変更サポート (Dynamic DPI)
- モニタ別のDPIサポート (Per monitor DPI)

# 対応方法
## アプリケーションマニフェストの設定をする
プロジェクトにアプリケーションマニフェストファイル`app.manifest`を追加し、下記の設定を記入します。
この設定でWindowsが高DPIサポート済と認識してくれるので、表示がぼやけることが無くなります。

```xml:app.manifest
<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
  </windowsSettings>
</application>
```
## フォームに高DPI対応のための一連の設定をする
### フォームのデザイン時にはVisual StudioをDPI 100%モードで起動する
高DPI環境下で開発をしている場合、フォームデザイナを開いたとき、下記のような表示が出ます。
**必ず毎回「100% のスケールでVisual Studio を再起動します」を選択してください**。
でないと、コントロールの配置が高DPI前提となり、DPI 100%環境で表示が崩れてしまいます。
※DPI 100%環境で開発している場合には何もしなくてOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/dcc6b1dd-70c7-ab69-0c3a-781bd97b7da2.png)

### AutoScaleModeプロパティをDpiモードにする
フォームの`AutoScaleMode`プロパティを`Dpi`モードに変更しておきます。
`AutoScaleMode`プロパティは、Windowsフォームに備わっている自動スケーリング機能の挙動を制御するものです。
デフォルトの`Font`モードでは、DPIの比率ではなくフォントの大きさを基準にスケーリングが行われます。
ピクセル単位の座標を扱う処理がある場合、`Font`モードは不適です。
デザイナの挙動にも変な影響があり（後述）、使わないほうがよいです。

### フォームのFontはYu Gothic UIかMeiryo UIにする
MS UI Gothic、ＭＳ Ｐゴシック等、ビットマップ部分を含むフォントは高DPI環境下でレイアウトが崩れる原因になります。
Yu Gothic UI、Meiryo UIのようなビットマップ部分を含まないフォントを使いましょう。
フォントを変更する際、`AutoScaleMode`が`Font`のままだと、フォーム全体のサイズが変わってしまうのでご注意ください。

### ピクセル単位の操作をする箇所には係数をかける
ここまでの設定で、殆どのコントロールは自動でDPIの制御してくれますが、一部のコントロール(DataGridViewの列幅等)や、描画処理では個別に高DPI対応をする必要があります。
下記のようなコードで96dpiに対する現在のDPI比率を宣言しておき、補正が必要な個所で乗算します。
対応個所を洗い出すには、トライアンドエラーが必要になるかもしれません。

```csharp
static readonly float DpiScale = ((new System.Windows.Forms.Form()).CreateGraphics().DpiX) / 96;
```

# まとめ
Windowsフォームアプリは高DPI非対応と見なされることが多いですが、
コツをつかめば標準機能任せでも、いい感じに対応できることが分かりました。

拙作SsidWallpaperChangerは本手法で高DPI対応を行っており、ソースを公開しています。
https://github.com/mono1729/SsidWallpaperChanger
正規表現入門

コーディング時の文字列の置換や、JavaScriptでのフォームの簡易的なバリデーションなどで使う機会があるのでまとめてみました。

## JavaScriptでの正規表現(match)
```
//正規表現のパターンを作る
const pattern = /正規表現/オプション;
 
//検索対象の文字列を作る
const str = "検索対象の文字列";
 
//検索する
const result = str.match(pattern); 

//マッチした文字列を表示(マッチしないとnullを表示)
console.log(result);
```

## 郵便番号をマッチさせてみる

```
const pattern = /^[0-9]{3}-?[0-9]{4}$/;
const string ="123-4567";
const result = string.match(pattern);
 
console.log(result);
```
「^[0-9]{3}-?[0-9]{4}$」を分解して見ていきます。

- 「^」は先頭
- 「[0-9]」は0~9のうち1文字
- 「{3}」は直前の指定を3回繰り返す
- 「-?」は「-」を0回か1回
- 「{4}」は直前の指定を4回繰り返す
- 「$」は末尾

「^[0-9]{3}」の部分で、前半の数字3桁を表しています。
「-?」はハイフンの部分ですが、省略される事も想定して0回か1回としています。
「[0-9]{4}」後半の数字4桁を表しています。


## 記法まとめ

### オプション(フラグ)

|表記|意味|
|---|---|
|g|文字列全体に対して検索(無指定だと最初のマッチングで終了)|
|i|大文字/小文字を区別しない(無指定の場合は区別する)|
|m|複数行の文字列を扱う(^と$が各行の先頭と末尾にマッチする)|


### メタ文字

|表記|意味|
|---|---|
|^|～で始まる文字列|
|$|～で終わる文字列|
|.|任意の1文字|


### 文字クラス

|表記|意味|
|---|---|
|[012]|0,1,2のどれか1つ|
|[0-9]|0～9のどれか1つ|
|[A-Z]|A～Zのどれか1つ|
|[A-Za-z]|A～Zとa～zのどれか1つ|
|[^012]|012以外で1文字|
|[01][01]|00,01,10,11のどれか1つ|


### 略記法

|表記|意味|
|---|---|
|\s|空白|
|\S|空白ではない|
|\d|数字 [0-9]と同じ|
|\D|数字ではない [^0-9]と同じ|
|\w|[A-Za-z_0-9]と同じ|
|\W|[^A-Za-z_0-9]と同じ|



### 出現回数

|表記|意味|
|---|---|
|*|0回以上|
|+|1回以上|
|?|0か1回|
|{n}|n回|
|{n,}|n回以上|
|{n,m}|n～m回|


### グループ化

|表記|意味|
|---|---|
|&#124;|どれか|
|()|まとめる|


### エスケープ

|表記|意味|
|---|---|
|&#92;++|+の1回以上の繰り返し|
|&#92;.|.を表す|
|\/|/を表す|

### まとめ
メールアドレスの正規表現でのバリデーションは事故の元。
先人が考えたものをありがたく使わせていただきましょう。

## おまけ match以外のメソッド

### 何を返すか

|メソッド|返ってくるもの|
|---|---|
|match()|マッチパターンが配列で返される|
|search()|マッチパターンの先頭位置が返される(0番目から)|
|test()|マッチパターンがある場合はtrue、ない場合はfalseが返される|
|exec()|マッチパターンが1つ返される|

### 使い分け

|用途|メソッド|
|---|---|
|マッチパターンを全て抜き出したい場合|match|
|繰り返し操作で順にマッチパターンが欲しい場合|exec|
|マッチパターンがあるかどうかだけを知りたい場合|test|
|先頭のマッチパターンだけが欲しい場合|search、パターンにgを付けないmatch|

### 文法

```:js
//match()
対象文字列.match(正規表現)
 
//search()
対象文字列.search(正規表現)
 
//test()
対象正規表現.test(文字列)
 
//exec()
対象正規表現.exec(文字列)
【GASの3歩目】if文で曜日の処理をする

## formatDate(date, timeZone, format)
```js
function isHoliday() {
  var week = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'u');
  if (week == 7) {
    return true;
  }
}
```

formatDateメソッドの見方
[Class SimpleDateFormat](https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html)

- u
  - Day number of week (1 = Monday, ..., 7 = Sunday)
  - 月[1]
  - 火[2]
  - 水[3]
  - 木[4]
  - 金[5]
  - 土[6]
  - 日[7] 

week == 7
であればweekは日曜日をさすため、isHoliday関数はtrue
hackerrack Loop処理

hackerrankのLOOPのところで躓いたので、その解決方法を残しておこうと思います。

2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
2 x 5 = 10

このように式全体を出したいとき

```
n=int(input())
i=int(input())
n × i = ni
```
このように定義しても、８や１０といった＝の後の数字しか出ませんでした。

ではどのようにすれば式全体が出せるでしょうか？

```
n= int(input().strip())

    for i in range(1,６):
        print("{} x {} = {}".format(n, i, (n*i)))
```
このように書くことでできます。
詳しく説明すると、
strip()で文字列の前後の空白を取り除きます。
２行目のrange関数では（）の中で、変数の初めと終わりの値を定義できます。
そして、{}を使うことで、変数は変えつつ、文字列として出すことができます。
.formatの（）の中の引数の順番と{}の中の変数は一致するので、
この場合だと１つ目にはn、２つ目にはi、３つ目にはn*iがが入ります。

以上になります。
何か間違いや指摘があればお願いします。
Photoshopのスクリプトでスマートオブジェクトを見分ける方法

CCからスマートオブジェクトは二種類ある

1. 埋め込みのスマートオブジェクト
<img width="420" alt="埋め込み.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189041/c2b01010-f664-8402-307d-fa00d3fecf98.png">
従来のスマートオブジェクトの形式。

2. リンクのスマートオブジェクト
<img width="388" alt="リンク.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189041/804b4ac3-6743-03f7-4b74-0f660662d7c0.png">
CCから追加されたスマートオブジェクト。別のPSDをリンクさせた形式のスマートオブジェクト

これらをjsxで見分ける方法がなんとなくあるんだろうなーと思っていたのですが、ドキュメントとにらめっこをしても一筋縄では行かないので、ちょっと遠回りな方法でチェックしているよーという備忘録。

# スマートオブジェクトレイヤー判定
まずはそもそもレイヤーがスマートオブジェクトなのか判定しないといけない。これ自体はLayerKindを参照すればわかる。

```jsx
if(layer.kind == LayerKind.SMARTOBJECT)
{
  alert("スマートオブジェクトですよ");
}
```

これで他のArtLayerやLayerSetとかからは見分けがつく。
ただし、このLayerKind.SMARTOBJECT判定では埋め込みもリンクも反応してしまうので、どっちの種類なのか判定するのは難しい。

# 埋め込み？リンク？判定
埋め込みとリンクとの見分けをするのに使えそうなのはリンク形式特有の機能が問題なく発行されるかをチェックすること。

使えそうな機能は属性パネルに出現する「コンテンツを編集」という機能。
(「コンテンツを編集」を実行すると、リンクしているPSDが別タブで開きます。)
これは埋め込みスマートオブジェクトにはない機能なので、埋め込みの場合は実行するとエラーが出るはずです。
<img width="425" alt="スクリーンショット 2019-07-29 23.55.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189041/34e469b7-2e76-65f5-1574-f579bf1931d9.png">

```jsx

var document = app.activeDocument;
// 調べたいレイヤーを取得する
var layer = document.layers[0];
if(layer.kind != LayerKind.SMARTOBJECT) return;

try
{
  document.activeLayer = layer;

  // 「コンテンツを編集」を実行
  var idplacedLayerEditContents = stringIDToTypeID( "placedLayerEditContents" );
  var desc3 = new ActionDescriptor();
  executeAction( idplacedLayerEditContents, desc3, DialogModes.NO );

　// 開いてしまったリンクのドキュメントを閉じておく
  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
  
  // 元のドキュメントに操作を移す
  app.activeDocument = doucment;

  alert("ここまで処理がくればlayerはリンクのスマートオブジェクト");
}
catch(e)
{
  alert("エラーが出た場合はリンクのスマートオブジェクトではない");
}
```

スマートオブジェクトリンクとレイヤーカンプ周りをここ最近調べているのですが、必要なAPIが用意されていなくてやりずらい....もっと充実してほしいです。。。

# ActionDescriptorを使ってスマートオブジェクトを見分ける
2019/10/23 こちらの方が健全そうなやり方なので追記。ActionDescriptorを自前で書く方法です。
ActionDescriptorからは通常のAPIで取得できないパラメーターが色々取得できるのですが、SmartObjectの「link」というパラメーターもそのうちの一つです。

このlinkというパラメーターは外部リンクになっているSmartObjectにしか付いていないので、これを見て判定します。

```getLinkLayerPath.jsx

function getLinkLayerPath(layer)
{
  if(layer.kind != LayerKind.SMARTOBJECT) return undefind;

  app.activeDocument.activeLayer = layer;

  try
  {
     var ref = new ActionReference();
     ref.putEnumerated(charIDToTypeID("Lyr "),charIDToTypeID("Ordn"),charIDToTypeID("Trgt"));
     var desc = executeActionGet(ref);

     var o = desc.getObjectValue(stringIDToTypeID("smartObject"));
     var link = o.getPath(stringIDToTypeID("link"));
     return link;
  }
  catch(e)
  {
    return undefined;
  }
}
```

指定したレイヤーがSmartObjectでかつ他のPSDとリンクしているものであれば、PSDのファイルパスが返ってきます。
ただの埋め込みSmartObjectだとundefindが返ってきますので、返り値をみてリンクされているレイヤーなのか、埋め込みなのか判定できる、というロジックです。
この方法だと、SmartObjectのドキュメントを一度開けるという手法を取らなくていいので、動作がすごく軽くなります！

ActionDescriptorとても便利でがしがし使ってしまうのですが、読めない人が多いのでどれくらい入れていくかが大変難しいですね....。
【GAS × ChatWork】『メッセージを送る』　メモ


```js
function myFunction() {
  var roomId = "--roomID---";
  var API_TOKEN = "--------API---------"; 
  var params = {
      headers: {"X-ChatWorkToken":API_TOKEN},
      method: "post"
    };
  var url = "https://api.chatwork.com/v2/rooms/" + roomId + "/messages";
  var body = "hello"";
  params.payload = {body :body}; 
  UrlFetchApp.fetch(url,params);
}
```
- roomid
  - チャットワークのトークルームごとに当てられているID。URLの最後の「#rid〇〇〇〇〇〇〇〇」の部分
- API_TOKEN
  - メッセージ送信やタスク追加などといったChatworkの機能を、外部のプログラムから簡単に使用することができるようにするもの。便利にしてくれる窓口を通すための証明書みたいなもの
- params
  - [パラメータ](https://wa3.i-3-i.info/word1443.html)、結果に影響を与える外から渡す値。ここではGoogleAppsScriptの外部（ChatWork）から結果に影響を与える値を渡している？
- url
  - ここでのURLはリクエストURL？？
- params.payload
  - payloadはパラメータの一種？POSTのbody部分に当たる→本文の内容
    - HTTPのことを勉強せんと（Webを支える技術）
- UrlFetchApp.fetch
  - UrlFetchAppはGASの"Script Services"の分野のクラスの一つ（GmailAppはGASの"G suite Services"の分野のクラスの一つ）
  - fetchメソッド
    - Makes a request to fetch a URL using optional advanced parameters.　This works over HTTP as well as HTTPS.
    - URLからオプショナルアドバンスドなパラメータを取ってくるようにリクエストするメソッド。


<br>
同じ結果が出る違う書き方（メモ）

```js
//This code can be moved

function myFunction() {
  var roomId = "--roomID---";
  var API_TOKEN = "--------API---------"; 
  var body = "hello";
  var params = {
      headers: {"X-ChatWorkToken":API_TOKEN},
      method: "post",
      payload: {body :body}
  };
  var url = "https://api.chatwork.com/v2/rooms/" + roomId + "/messages";

  UrlFetchApp.fetch(url,params);
}
```
Linux IPv6 関連コマンドメモ

# Linux で IPv6 を利用する際の基本的なコマンドメモ

## インタフェイスに付与されたアドレス確認

```shell
$ ip address show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 06:a3:df:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet 172.31.xx.xx/20 brd 172.31.xx.xx scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2xxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
```

## ルーティングテーブル

```shell
$ ip -6 route list type unicast
2xxx:xxxx:xxxx:xxxx::/64 dev eth0  proto kernel  metric 256  pref medium
fe80::/64 dev eth0  proto kernel  metric 256  pref medium
default via fe80::xxxx:xxxx:xxxx:xxxx dev eth0  proto ra  metric 1024  expires xxxsec hoplimit 64 pref medium
```

## Ping 疎通確認
- localhost

```shell
$ ping6 ::1
```

- google

```shell
$ ping6 2001:4860:4860::8888
```

## curl 接続確認

```shell
$ curl -6 -i https://www.jpn.earth/remote_addr.cgi
HTTP/2 200 
date: Mon, 29 Jul 2019 14:54:49 GMT
content-type: text/plain; charset=UTF-8

2xxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
```

## DNS

```shell
$ dig aaaa www.google.com +rec +short
2404:6800:4004:81a::2004
```
## 公開サービス

```shell
$ ss -al -6
Netid                  State                   Recv-Q                  Send-Q                                    Local Address:Port                                              Peer Address:Port                  
raw                    UNCONN                  0                       0                                                     *:ipv6-icmp                                                    *:*                     
udp                    UNCONN                  0                       0                                                     *:dhcpv6-client                                                *:*                     
udp                    UNCONN                  0                       0                                                     *:45617                                                        *:*                     
udp                    UNCONN                  0                       0                                                     *:mdns                                                         *:*                     
tcp                    LISTEN                  0                       128                                                [::]:ssh                                                       [::]:*                     

```
サーバーの仮想化とは

最近注目されている**AWS , Docker, Kubernetes**を学習する前に**仮想化**について学習をしたのでざっくりではありますがまとめて行きます。

####※あくまで仮想化についての記事なのでAWS , Docker, Kubernetesについてのハンズオンや技術的な解説はしていません。


##サーバーの仮想化とは

1台のサーバー上で複数OSを同時動作させることで、複数の業務システムの処理を可能にする技術です。物理的には1台のハードウェア(PC)ではあるものの、複数のサーバー（論理サーバー）が稼働する仮想的サーバー環境を構築でき、多くのアプリケーションにサーバーリソース（サーバー本体、外部記録装置など）を割り当てることができます。これによって、ひとつの業務システムがサーバーを独占してしまうような無駄がなくなり、サーバーリソースをより有効に活用することができます。
サーバーのハードウェア性能の向上に伴い、サーバー仮想化技術を用いることで、多くの業務処理を行えるようになるだけでなく、既存の複数のサーバーを1台の高性能サーバーに統合することも可能になります。

長い説明になってしまいましたが端的に言うと**仮想化を実現するソフトウェアで物理的には一台のハードウェアにも関わらず複数の独立したサーバーとして機能させる技術**です。

![aboutVirtualization.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351739/cc685d52-5e2f-800d-fcd6-6d70a4d9d77a.png)

サーバー仮想化を実現させるソフトというのは**"ハイパーバイザー"**です。

###サーバー仮想化の例

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

構成１
　DBやWebなどのソフトウェアは一台のハードにインストールをして稼働させることは可能ですが、そのハードに障害が起きてマシンを停止した場合にはそのハード上で稼働しているサービス（DB/Webサーバーなど）を全て停止することになる。
また、悪意のある第三者にホストが侵入されroot権限を奪われた場合、全てのサービスに対して改竄などの不正行為が行われる可能性がある。
このために次の構成２に比べて、セキュリティは弱くなる。

構成２
　１台のハードでありながら、仮想化技術を使い各サーバーを独立させて稼働している。
仮想化を実現するハイパーバイザー上に仮想マシンを構築しその上にゲストOS(CentOSやUbuntuなど)を稼働させます。
ゲストOSは仮想マシンごとに異なるOSを利用することが可能であり、そのゲストOSに対してDBやWebサーバーソフトフェアをインストールして利用することが可能。



##ハイパーバイザー
ハイパーバイザーは、その上で仮想マシンを稼働させるソフトウェア。
典型的なハイパーバイザーには２種類のタイプがある。

1.ベアメタル型
　ハイパーバイザーが直接ハードウェア上で動作し、全てのOSはそのハイパーバイザー上で動作する方式。 Xenがこの方式

2.ホスト型
　ハードウェア上でOS（ホストOS）が動作し、その上でハイパーバイザーが動作する方式。
VMwarePlayerやVirtualBoxがこの方式

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351739/44e999a7-98e2-b548-733a-d789b000b7fc.png)
> [画像引用URL](https://japan.zdnet.com/article/20416942/)

###クラウドによる仮想環境
　クラウドでは、ハイパーバイザーによる仮想環境の上で多数のVM（仮想マシン）インスタンス(AWSで言えばEC2インスタンス)を稼働させることができる。
クラウドのVMインスタンスは容易に作成と削除ができるので、負荷の状況に応じて手動あるいは自動でインスタンスの個数を増減することで処理能力を調整ができる。(AWSのELBやAutoScalingを用いる)

AWSでは、ハイパーバイザーとしてXenが使われており、最近ではKVMも導入がされたみたいです。
Googleが提供するクラウドのGCPではハイパーバイザーとしてKVMが使われている。


###最後に
AWSやGCPなどのクラウド技術を使うにしてもそれを支えてる技術は仮想化の技術です。
クラウド技術だけを学ぶのではなく基盤となる技術を学習できてよかったですし、AZと呼ばれるAWSのデータセンターが存在する限りオンプレミスの知識も必要になってくると思いますしまだまだインフラについて学習すべきことが多いなと感じます。
Chromebookで開発環境を構築する（覚醒編）

# Chromebookで開発環境を構築する（覚醒編）

## プロローグ

[前回](https://qiita.com/gontaneko/items/def4238d1b6b1cf0685a)からの続きです。
Chromebookらしさを自問自答して真理を見出していきます。

## そう言えば

Chromebookを購入した直後は以下を利用していました。

- AWS Cloud9
- Amazon WorkSpaces

やはりクラウド上のサービスを使ってこそChromebookらしさです。

## AWS Cloud9

初期はAWS Cloud9を使ってVue.jsを開発をしてました。
JS系の開発においては使い勝手も悪くない感じでしたが、C#など開発においてはちょっと手に馴染まない感じでした。  
細かいところではありますが、環境の起動にいたるまでの手順がちょっと面倒くさく感じてしまいだんだん使わなくなってしまいました。

## Amazon WorkSpaces

普通にリモートデスクトップでWindowsにログインして作業できます。  
当然ながらOfficeやらWindowsで使い慣れたIDEを利用して開発できます。
ただマシンスペックもディスク容量も少なくバリバリ開発には向かないと思いました。  
もともとChromebookへ移行している際にバックアップ環境的な用途として契約していたののもあり、利用機会激減に伴い解約しました。

## 余談

Crostiniが使えるようになってローカルにAtomやらVSCodeやら導入し放題かと胸踊らせましたが、即その夢は打ち砕かれました。この時利用していた端末ARM系であり、対応するバイナリが当時なく挫折しました。  
ソースからビルドを試みましたが恐ろしく時間とリソースを消費した覚えがあります。  
（今ではARM系のVSCodeのバイナリは[ここ](https://packagecloud.io/headmelted/codebuilds)にあります）

## VSCode + Remote SSH + GCP

VSCode 1.35のリリースより[Remote Development](https://code.visualstudio.com/docs/remote/remote-overview)に対応しました。  
これによりローカルのVSCodeからリモートの開発環境に直接アクセスできるようになりました。  
まさに真打ち登場といった感じです。  
立ち上げまでの手順は簡単です。

 1. GCPでVMインスタンスを立ち上げ
 2. VSCodeにRemote-SSH Extensionを導入する
 3. $home/.ssh/configを整備する
 4. Remote-SSH Extensionの「Always reveal the SSH login terminal」をチェックする

### GCPでVMインスタンスを立ち上げ

常時起動しないのでプリエンティブインスタンスで良いのではないかと思いました。  
その分CPUメモリはけちらずに行きましょう。

### Remote-SSH Extensionの導入

特に迷うことはないかと思います。

### .ssh/config

こんな感じの定義ファイルです。  
設定しておけばRemote-SSH Extensionが拾ってくれます

```config
  Host <Name>
    HostName <Host>
    User <SSH Login User>
    IdentityFile <ssh private key Path>
```

### Show Login Terminal

VSCodeのファイル>基本設定>設定からRemote-SSHの設定を探しましょう。  
「Always reveal the SSH login terminal」のチェックをつけておきます。
SSHでログインする際に秘密鍵のパスワードを入力します。これが何度も入力しないといけないのが、この方式の唯一面倒な点です。

## まとめ

ローカルで作業しているのと遜色ない使用感です。  
サーバーリソースを最大限活用して開発できるのはまさにChromebookらしい開発スタイルでないでしょうか。
AWS Fargateでコンテナのコマンドを変えて定期実行する方法

## 実現したいこと
* Rakeタスクのスクリプトを内包したDockerイメージがあり、AWS ECRにpush済みである
* 別々のRakeタスクをAWS Fargate上で定期実行したい
    * A Rakeタスクは毎分
    * B Rakeタスクは毎時

サンプルコードとして以下の foo、bar Rakeタスクを定期実行したいとします。

### Rakeタスク

```ruby
task default: %w[foo]

task :foo do
  puts "Hello Foo"
end

task :bar do
  puts "Hello Bar"
end
```

### Dockerイメージ

```dockerfile
FROM ruby:2.6.3

ENV LANG ja_JP.UTF-8

RUN gem install bundler
RUN mkdir /app
WORKDIR /app
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
ADD Rakefile /app/Rakefile
RUN bundle install

CMD ["bundle", "exec", "rake", "foo"]
```

## 前提
* AWS ECRにイメージはpush済みとする
* AWS ECSクラスターは作成済みとする

## 環境構築
今回のポイントはここです。ECS タスクの定義作成時のコンテナ追加画面でコマンドの上書きをすることができます。これを利用して、foo, bar Rakeタスクを実行するタスク定義を２つ用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29755/67f4edc6-bfe8-b607-f52b-7eae65782fa0.png)


タスク定義を２つ用意しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29755/665820cd-d6a7-c0af-6e73-d757bfe75f7f.png)


最後に各々のタスク定義用にタスクのスケジューリングを設定すれば完了。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29755/8a0a600b-8fb8-ea49-b763-c553bd7b625d.png)

これで複数Rakeタスクスクリプトを内容したDockerイメージを利用して、各々のRakeタスクを別々のスケジュールで定期実行することが実現でした。

今回は簡単なスクリプトの実現例だが、他の言語やフレームワークのバッチ処理もECS + Fargateに移植できるようになるはずです。

## 参考
* [タスク定義パラメータ \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html)
* [Amazon ECS タスクのスケジューリング \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/scheduling_tasks.html)
* [ECSタスクでRakeタスクを定期実行する](https://naoty.dev/posts/73.html)
SMB暗号化した共有フォルダをLinuxにマウントする

AWSにWindowsサーバを立ててLinux(RHEL)とファイル共有する機会があったのですが、クラウドなのでSMB暗号化を使ってみたいと思って調査した結果です。

環境は以下です。

- Windows_Server-2016-English-Full-Base-2019.07.12 (ami-0404c1383f6b870a2)
- RHEL-7.6_HVM_GA-20190128-x86_64-0-Hourly2-GP2 (ami-00b95502a4d51a07e)

Windows 8 以降のOSであれば標準で共有フォルダの暗号化ができますが、デフォルト無効なので有効にしてやります。

以下のようにします。

```PowerShell
New-SmbShare -Name Share -Path C:\Share -EncryptData $True -FullAccess hoge
```

PowerShell を使わずに有効化するにはサーバマネージャの「ファイルサービスと記憶域サービス」のウィザードを使うようです。フォルダのプロパティにはそれらしいオプションは見当たらなかったので、サーバOS以外でやる場合は大人しくPowerShell使いましょう。

Linux からは以下のように[マウント](https://access.redhat.com/ja/solutions/1447443)します。root か sudo で実行します。

```bash
mount -t cifs -o 'username=hoge,password=pass,vers=3.0' //windows-ip/Share /mnt
```

`vers=3.0` というのは無くても繋がるみたいですが、messages に警告が記録されるので明示してあげます。

`mount` のオプションはカンマ区切りなので、パスワードにカンマやシングルクォートが入っているとマウントできず、エスケープする方法があれば知りたいところ。

Windows側から以下のようにすると接続しているSMBプロトコルのバージョン（ダイアレクトというらしい）を確認できます。

```PowerShell
Get-SmbSession | select *
```
```text:出力
SmbInstance           : Default
ClientComputerName    : <Linux IP>
ClientUserName        : <Windows Hostname>\Administrator
ClusterNodeName       :
Dialect               : 3.0 <----- SMB3.0で接続されている
NumOpens              : 0
ScopeName             : *
SecondsExists         : 347
SecondsIdle           : 347
SessionId             : 292057776193
TransportName         :
PSComputerName        :
CimClass              : ROOT/Microsoft/Windows/SMB:MSFT_SmbSession
CimInstanceProperties : {ClientComputerName, ClientUserName, ClusterNodeName, Dialect...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties
```

双方で特に準備など不要というところが手軽で良いですね。IISでFTPSなどすると手間なので。

# ログ監視

鯖缶としてはセキュリティだけでなく、エラーが出ないか気になるところなので確認してみました。

マウントした際に以下のようなメッセージが記録されますが、[カーネルの問題らしい](https://bugzilla.kernel.org/show_bug.cgi?id=199203)ので抑止は諦めます。尚、修正は 4.17 らしいのですが [RHEL7 はカーネル 3 系](https://access.redhat.com/ja/articles/16476)なので駄目みたい。

```
kernel: CIFS VFS: ioctl error in smb2_get_dfs_refer rc=-5
```

また、繋ぎっぱなしにしていると15分毎に以下のようなメッセージが出ますが、やはり[カーネルの問題らしく4.4で修正されている](https://lore.kernel.org/patchwork/patch/836460/)とのこと。これもやはり諦め。

```
kernel: CIFS VFS: Free previous auth_key.response = ffff92647a8d1800
```

# 参考

[第9回　強化されたファイル共有プロトコルSMB 3.0の概要：Windows Server 2012クラウドジェネレーション - ＠IT](https://www.atmarkit.co.jp/ait/articles/1304/25/news118.html)
[SMB セキュリティ拡張機能 | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows-server/storage/file-server/smb-security)
データ構造_削除フラグを使ったテクニックを紹介

###削除フラグ
たとえば名簿のデータを配列で管理しているとき、
誰かのデータを名簿から削除したい場合、配列ではその位置より後ろのデータを
移動させて要素を詰めなければならないですよね・・
そこで各要素に「削除フラグ」というフラグをもたせ、要素を削除する際には
そのフラグを立てるだけにするというテクニック。
一覧表示を行う場合、削除フラグが立っている要素は除外する、といった使い方です。
コードは下記のようなイメージです。

```
for(i=0;i<person_count;i++){
  if(person_array[i].deleted)
  continue;

  /* 処理本体をここに記述 */

}
```

この配列に新規の要素を追加する方法としては、
**①配列を先頭から探して削除フラグが立っている要素を探す**
空いたところはすぐに有効活用しよう！的な発想です。配列の順番はぐちゃぐちゃになりますが、それでもOKという場合に。
**②とりあえず末尾に追加する**
空いたところを検索する必要がないので追加が高速です。そして配列がいっぱいになったら
空いた場所を詰めるわけです。
lodash でよく使う王道関数

JavaScript を使っているなら [lodash](https://lodash.com/docs/) は大変便利なのですが、関数が多すぎてどれ使ったらいいのか解りづらいのが難点です。

ここではその中から特によく使う関数を紹介します。


### [_.chunk(array, [size=1])](https://lodash.com/docs/#chunk) : 配列を指定サイズで分割

```js
// 配列を指定サイズで分割
_.chunk(['a', 'b', 'c', 'd'], 2);
// => [['a', 'b'], ['c', 'd']]
```

### [_.difference(array, [values])](https://lodash.com/docs/#difference) : 差集合。つまり左から右を除去。

```js
_.difference([2, 1], [2, 3]);
// => [1]
```

### [_.intersection([arrays])](https://lodash.com/docs/#intersection) : 積集合。つまり全てに共通してあるもののみ。

```js
_.intersection([2, 1], [2, 3]);
// => [2]
```

### [_.union([arrays])](https://lodash.com/docs/#union) : 和集合。つまり全ての合算（重複なし）。

```js
_.union([2, 1], [2, 3]);
// => [2, 1, 3]
```

### [_.xor([arrays])](https://lodash.com/docs/#xor) : 排他的論理和。つまり全ての中で重複の無い値のみ。

```js
_.xor([2, 1], [2, 3]);
// => [1, 3]
```

### [_.fill(array, value, [start=0], [end=array.length])](https://lodash.com/docs/#fill) : 配列を値で埋める。

```js
var array = [1, 2, 3];
_.fill(array, 'a');
console.log(array);
// => ['a', 'a', 'a']
```

### [_.uniq(array)](https://lodash.com/docs/#uniq) : 重複排除。

```js
_.uniq([2, 1, 2]);
// => [2, 1]
```

- [_.uniqBy(array, [iteratee=_.identity])](https://lodash.com/docs/#uniqBy) : 重複比較時に要素を処理したいとき用。例:
    - `_.uniqBy([{a: 1}, {a: 1}], 'a')`
    - `_.uniqBy([{a: 1}, {a: 1}], x => x.a)`

### [_.isEnpty(value)](https://lodash.com/docs/#isEnpty) : 空判定。

```js
_.empty({});
// => true
_.empty({a: 1});
// => false
```


lodash関連の記事
======

- [lodash の path を使う関数でオブジェクト操作が便利になる](https://qiita.com/waterada/items/8c57f37d3decdbc583fe)
- [lodash の forEach/map/reduce 系の関数を紹介](https://qiita.com/waterada/items/22ef4c618050ea766137)
- [lodash ちょっとマニアックだけど便利な関数](https://qiita.com/waterada/items/63eb186e2150d38bb6ed)
- [lodash の debounce や throttle で簡単に負荷対策](https://qiita.com/waterada/items/986660d31bc107dbd91c)
- [lodash でよく使う王道関数](https://qiita.com/waterada/items/986660d31bc107dbd91c)
【Ruby】二次元配列の宣言を間違えて、要素の変更が想定通りにできなかった原因と反省

# はじめに

Rubyをつかってコーディングテストに取り組んでいます。
その際に、いろいろなところを参考にして二次元配列を使ったときに、
値の書き換えがうまくいかずに失敗しました。

# やりたかったこと

3x5の二次元配列を作成する。初期値はすべて0とする。
```[0][0]```の要素の値だけ、1に変更したい。

# 動作確認環境

- Windows 10
- ruby 2.5.5p157

# 失敗作

自分が最初に書いた失敗作のコードです。
```line[0][0]``` だけ1に書き換えたかったのですが、```line[1][0]```と```line[2][0]``` も1に書き換わってしまいました。

```ruby
line = Array.new(3, Array.new(5, '0'))

line.each do |n|
  p n
end
# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["1", "0", "0", "0", "0"]
# ["1", "0", "0", "0", "0"]
```

## なぜ？

各行の配列が同じオブジェクトを参照していました。
下記の実行結果から、配列のオブジェクトIDが3つすべて「21014940」となっています。
そのため、```line[0][0]```だけ更新したつもりでも、結果的には同じオブジェクトを更新する結果になりました。

```ruby
line = Array.new(3, Array.new(5, '0'))

line.each do |n|
  p n.object_id
end
# 実行結果
# 21014940
# 21014940
# 21014940
```

# 成功例1

最初の二次元配列を作る箇所を```Array.new(3).map{Array.new(5, '0')}``` とすると、想定通りの結果を得ることができました。

```ruby
line = Array.new(3).map{Array.new(5, '0')}

line.each do |n|
  p n
end
# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
```

もちろん配列のオブジェクトIDがそれぞれ異なるため、```line[0][0]```を更新した場合、他の配列に影響を与えることはありません。

```ruby
line = Array.new(3).map{Array.new(5, '0')}

line.each do |n|
  p n.object_id
end
# 実行結果
# 21620400
# 21620240
# 21620080
```

# 成功例2

最初の二次元配列を作る箇所を```Array.new(3) { Array.new(5,'0') }``` としてもよいです。
こちらのほうがコードが短いので、こちらのほうがよいかもしれません。

```ruby
line = Array.new(3) { Array.new(5,'0') }
line.each do |n|
  p n
end

# 実行結果
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]

line[0][0] = '1'
line.each do |n|
  p n
end
# 実行結果
# ["1", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
# ["0", "0", "0", "0", "0"]
```

# おわりに

これのせいで、コーディングテストに失敗しました。
コーディングテストがおわったあと、参照が一緒なんだろうなぁとすぐ気づきました。
制限時間に追われて焦ってしまい、テスト中はさっぱり原因がわかりませんでした。

# 参考文献

[Ruby 配列の初期化と多重配列 &#8211; こととこネット](http://blog.cototoco.net/work/201405/ruby-%E9%85%8D%E5%88%97/)
[【初心者必見】Ruby配列の初期化の方法まとめてみた！](https://www.sejuku.net/blog/14332#i-4)
WebXR Device API をChromeで使えるようにする

# (＊chrome v79以降では標準でWebXR Device APIが使えるようになったようです。)
https://qiita.com/ikkou/items/0c6231ddc7d916419690
ただし、chrome v81までは、下記の変更をする必要があるのは変わらない模様です。

* Oculus VR support: Enabled (Oculus Rift, RiftS用)
* XR device sandboxing: Disabled


# WebXR Device APIとは何か
[WebXR Device API](https://immersive-web.github.io/webxr/)とはブラウザとOculusRiftやHTCVIVEなどのVRデバイスが通信を行うためのAPIである。
同様の機能を提供するAPIとしてWebVRがあるが、標準ではChromeの77では廃止されることが決まっている。WebXR Device APIは、[WebVR](https://immersive-web.github.io/webvr/spec/1.1/)の後継として策定が進んでいる。
2019/08/19現在、これはW3Cの仕様策定段階でいうと最初期に当たるEditor's draftであり、仕様が確定している状態ではない。しかしながら開発者のやる気は最高潮*(https://www.chromestatus.com/feature/5680169905815552 によると`Web Developers:
Strongly positive`)である。W3Cがどのように仕様を策定していくかについては参考文献を参照。
Chrome以外のブラウザでも対応が進んでおり、Firefoxでは標準で使える他、Oculus GOやOculus QuestなどのOculusブラウザでも標準で対応している。

# WebXR Device APIの対応バージョン
* Chrome: 76以上

# Chromeの設定方法
1. Chromeのバージョンを確認して必要であればアップグレードする
2. WebXR Device APIを使用できるようにChromeのFlagsを変更する
3. Chromeをリスタートする


## 使用しているchromeのバージョンを確認する
`設定` > `Google Chromeについて` > `Chromeについて`
(参考までに画像ではChromeのバージョンは`76.0.3809.100`)
<img width="681" alt="Screen Shot 2019-08-19 at 0.21.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93401/9e4b8b87-6858-d231-75a6-dfa4ed5993fd.png">



## WebXRを使用するためのFlagsを有効化する
`chrome://flags`にアクセスして、この[ページ](https://docs.google.com/document/d/1R8Bz0_vK9YmY5-ZhsbLtZ9-DDJpTOgNeibFD4SdUnbw/edit)に書いてあるように以下の項目を変更する。検索すると初期は`Default`になっているため、`Enabled`または`Disabled`に変更する。

- WebXR Device API: `Enabled`
- Oculus VR support: `Enabled` (Oculus Rift, RiftS用)
- OpenVR support: `Enabled` (HTC VIVE用)
- XR device sandboxing: `Disabled`

<img width="1116" alt="Screen Shot 2019-08-19 at 0.13.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93401/1e06cb4f-afd2-d91d-4485-13df3c2fa80b.png">

## Chromeをリスタートする
Flagsの変更を反映させるためにChromeをリスタートする必要がある。忘れがちなので必ずしましょう。

# サンプルを動かす
WebXR Device APIのサンプルを公開しているページからサンプルを選び試してみる。
https://immersive-web.github.io/webxr-samples/

例えば、360°のシアターモードで映画館のようにサンプル動画を観れるサンプルは以下のものである。VRデバイスが接続されていれば`ENTER VR`ボタンを押すことでVRモードに移行することができる。
https://immersive-web.github.io/webxr-samples/stereo-video.html

## WebXR Device APIの使い方を詳しく知りたい人はこちら
[WebXR Device API Explained](https://github.com/immersive-web/webxr/blob/master/explainer.md)
WebXR Device APIの説明やユースケース、実装方法など具体的に書いています。

# 参考文献
* [WebXR Device API Editor's draft](https://immersive-web.github.io/webxr/) 
* [WebXR Device API Working Draft](https://www.w3.org/TR/2019/WD-webxr-20190521/)
* [PSA - The State of WebXR
](https://docs.google.com/document/d/1R8Bz0_vK9YmY5-ZhsbLtZ9-DDJpTOgNeibFD4SdUnbw/edit)
* [WebXR Device API サンプル](https://immersive-web.github.io/webxr-samples/)
* [W3C勧告とはなんぞ？Web標準化とW3Cにおける勧告プロセスについて](https://wemo.tech/795)
* [WebVRだのWebXRだの状況をまとめてみた](https://qiita.com/emadurandal/items/baf68501b3a50b9a2b17)
* [WebXR Device API Explained](https://github.com/immersive-web/webxr/blob/master/explainer.md)
Raspberry PiにLinux Brewをインストール

# Raspberry PiにLinux Brewをインストールして、Node.jsを動かします。
## 自分の構築時環境
<p>※Debian/Ubuntuにインストールする際、同じ手順でインストールできます。
</p>
- クライアント側
     - Windows 10上のコマンドプロンプト
     - Visual Studio Code InsidersのRemote Development
- サーバー側
     - Raspberry Pi 3B
     - Raspbian 10

## Linux Brewのインストール
 - 文字コードの変更
    - ` sudo raspi-config ` コマンドを実行します。
    - ` 4 Localisation Options ` → ` I1 Change Locale `の順にロケールの選択画面を表示させます。
    - ` en_US.UTF-8 UTF-8 `と` ja_jp.UTF-8 UTF-8 `をスペースキーで選択し、エンターキーを押します。
    - デフォルトのロケールを設定する画面が表示されるので、` en_US.UTF-8 UTF-8 `を選択してエンターキーを押します。
 - Linux brewのインストール
    - <a href="https://docs.brew.sh/Homebrew-on-Linux" target="_blank">Linux Brew</a>のサイトから、コマンドをコピー&ペーストして使用します。
    - 基本的に、最新版のRaspbianを使用していれば、必要なパッケージ類はインストールされていますが、Linux Brewの<a href="https://docs.brew.sh/Homebrew-on-Linux#debian-or-ubuntu" target="_blank">Debian or Ubuntu</a>のコードを打ち込みます。

```
sudo apt-get install build-essential curl file git
```
   - インストーラーをダウンロードして実行

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
```

   - PATHを通す。

```
test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile
```
   - 正常にインストールされたかの確認。

```
brew install hello
```
と入力して、特にエラーが表示されることなく実行されていることを確認します。<br>最後に、` hello `と入力して` Hello, World!`か` 世界よ、こんにちは！ `と表示されると成功です。

## nodebrewのインストール。
<a href="https://github.com/hokaccha/nodebrew" target="_blank">nodebrew</a>のGitHubの手順通り行います。
インストール

```
curl -L git.io/nodebrew | perl - setup
```
PATHを通す。

```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```
設定を再読み込みします。

```
source ~/.bashrc
```
正常にインストールされたかの確認。ヘルプが表示されると成功です。

```
nodebrew help
```

## Node.jsのインストール
インストールすることのできるNode.jsのバージョンの確認

```
nodebrew ls-remote
```

インストールしたいバージョンが12.8.0の場合

```
nodebrew install-binary v12.8.0
```
※最新版をインストールしたい場合

```
nodebrew install-binary stable
```
※安定板をインストールしたい場合

```
nodebrew install-binary stable
```

正常にインストールされたかの確認。インストールしたNode.jsのバージョンが表示されると成功です。

```
nodebrew ls
```
※下記のコマンドでもNode.jsのバージョンを表示することが可能です。

```
node -v
```
Tinder 右スワイプ自動化

## まずはじめに

1.<a href="tinder.com">Tinder.com</a>でログイン後、ディベロッパーウィンドウを開き、下記のコードをconsoleにコピペ。
2.ENTER を押す。
3.コーヒーでも入れて、座ってゆっくり自動化を楽しむ。

## コード

```tinder.js
let run = true, time_step = 1000;
const wait = (n = 1) => new Promise((rs, rj) => run ? setTimeout(rs, n) : rj()),
	click = async (cn, i = 0) => {
		document.getElementsByClassName(cn)[i].click();
		return wait(time_step)
	};
document.onkeydown = (e = window.event) => {
	if (e.key === "a") run = run ? true : explore() || true;
	else if (e.key === "z") console.log(time_step *= 0.9);
	else if (e.key === "x") console.log(time_step *= 1.1);
	else run = false;
};
const explore = async () =>
	click("recCard__info").then(() =>
		Array.from(document.getElementsByClassName("bullet")).reduce((p, e) =>
			p.then(() => {
				e.click();
				return wait(time_step)
			}), Promise.resolve())
	).then(() =>
		click("recsGamepad__button--like")
	).then(() => explore());
explore();
```

## 操作方法
```
a - start
z - 10%スピードアップ
x - 10%スピードダウン
```

## 注意点
1秒に1回スワイプ、つまり1時間に3600人スワイプすると、使えなくなっちゃうらしいので、自分でお試しの際はそこだけ気をつけましょう。
ローカルのHTMLファイルでfetchを試す & CORSとその回避策

# やりたいこと

* 気軽にfetchを試したい
    * 今後いろんなコードを試す為
* いちいち仮想マシンとかAPIサーバーとかフロントのサーバー立てたくない
* ローカルのHTMLファイルに素のJavaScriptを書いて試したい
* 気軽に叩ける公開APIが欲しい

# 気軽に叩ける公開API
* zipcloud（郵便番号の取得とか）
    * http://zipcloud.ibsnet.co.jp/ 
    * 登録不要

* NHKの番組表API
    * http://api-portal.nhk.or.jp/ 
    * 簡単な登録でAjax使ってAPIを叩ける（CORSできる）
    * 一日３００回の制限（各API毎？合計？）

今回はzipcloudで試す。NHKも良い感じ

# 出来たコード
* fetchメソッドの戻り値はpromise
* レスポンス.json()メソッドの戻り値はpromiseなので同期的に処理したい場合はawaitする
* ハンドリングとか何もしていない

```test.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <input type="button" value="取得" onclick="apiRequest()" />
    <div id="export"></div>
    <script>
      async function apiRequest() {
        const downloadUrl =
          "http://zipcloud.ibsnet.co.jp/api/search?zipcode=1620825";
        const response = await fetch(downloadUrl);
        const json = await response.json();
        const string = JSON.stringify(json);
        const exportTarget = document.getElementById("export");
        exportTarget.innerHTML = string;
      }
    </script>
  </body>
</html>
```


# CORSでハマったので調べた
* オリジン間リソース共有
* Cross Origin Resource Sharing の略
* Originというのはプロトコル、ドメイン、ポートの組み合わせ
* リクエスト元のオリジンとリクエスト先のオリジンが異なることをクロスオリジンという
* 異なるオリジン間でリソースを共有できるということをCORSという
* ChromeなどのWebブラウザはクロスオリジンでAjax通信を行った場合、CORSの条件を満たしていないとデータをくれない
* fetch APIの勉強をしているAさんがいると仮定して例えると（まあ私なんですが）
    * AさんがPC上にHTMLファイルを作成し、その中に`http://hoge.com:80`へAjaxのリクエストを行うコードを書いてChromeを使って実行する
    * 仮にAさんのPCに割り当てられたグローバルアドレスが`http://10.1.2.3:3000`だった場合、Aさんのグローバルアドレスとhoge.comのアドレスのオリジン（プロトコル、ドメイン、ポートの組み合わせ）が異なる為、クロスオリジンとなる
    * クロスオリジンである場合Chromeはリクエストを行なったのち、レスポンスヘッダーに`Access-Control-Allow-Origin`キーとそのバリューとして`http://10.1.2.3:3000`（もしくはワイルドカードの*など）が存在するかを確認し存在しない場合はCORS出来ないとしてエラーを起こしデータを教えてくれない
    * その他にもJSONPとかいうのを使った回避策もあるらしいけど調べていない（古いし覚える必要なさそう）
* CORSして良いかどうかの判定を行なっているのは基本はCORSの仕様に準拠したWebブラウザ
* CORSの仕様に準拠していないWebブラウザだったり、そもそもWebブラウザ以外の何かしらからリクエストを送った場合はそのままデータを得られる
* Chromeの拡張機能でCORS回避することが出来るものがある
    * [Moesif Orign & CORS Changer](https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc?hl=ja&)
    * 追加してONにするだけで使えた
* ちゃんとした開発であればCORSのことを考えて実装するべきだが、今回のような場合は回避したいだけなので拡張機能を使う
    
CORSの実現はリクエスト元やリクエスト先のやりとりで行われているものと思っていましたが、実際にはもう一人Webブラウザという登場人物が存在し間を取り持っていて、重要な検証の部分を担っているということでした。

実際の開発の観点では、ブラウザを介さずに回避する方法はあるので、やろうと思えば他サイトのリソースを無理矢理共有することも出来そうで、CORS機能（とその検証機能）はあんまり意味無さそうに思えた。
【Flutter】flutter build iosコマンドがCode Signing Errorで失敗する

# 事象
Flutter製のiOSアプリをリリースする前に実行すべきコマンド`flutter build ios`を実行したところ、`Code Signing Error: No profiles for '<BundleID>' were found:  Xcode couldn't find any iOS App Development provisioning profiles matching '<BundleID>'. `と表示されてコマンド実行に失敗しました。

# 原因
このエラー文言の続きを読んでみると、`Automatic signing is disabled and unable to generate a profile. To enable automatic signing, pass -allowProvisioningUpdates to xcodebuild.`と記載されています。
どうやらXCodeの自動署名機能？は無効化されるようです。

# 対処
XCodeでプロジェクトを開いてSigningの項目を確認してみると、`Automatically manage signing`の設定にチェックが付いていました。
これを外して下記の通り作業した結果、無事`flutter build ios`の実行が成功しました。

1. `Automatically manage signing`のチェックを外す。
2. `flutter clean`を実行する。
3. `flutter build ios`を実行する。
初心者向けLookMLと可視化について


lookerを運用するには、**lookML（yaml形式のデータモデリング言語）の習得が必須。**です。
これだけで導入ハードル高いなー。と感じる人が多いのではないかと思います。

ここでは、lookMLの定義（細かい説明は公式に丸投げ）と実際にlookMLと可視化のイメージを紹介したいと思います。

## LookML概要
・**dimension**と**measure**の２つを指定する
・**dimensionは表やグラフの行列情報**で、**measureはグラフ内の数値情報**になる
・この項目の組み合わせ、掛け合わせによってデータの可視化を行う。

細かい情報や定義などは[公式ページを参照](https://docs.looker.com/ja/data-modeling/learning-lookml/lookml-terms-and-concepts)

## LookMLのコードと可視化について
・**dimension**と**measure**は以下のように指定する

```yaml
  dimension: prefecture_name {　　　　　-- dimensionの指定
    type: string
    sql: ${TABLE}.prefecture_name ;;
  }

  measure: count {　　　　　　　　　　　　-- measureの指定
    type: count
    approximate_threshold: 100000
    drill_fields: [prefecture_name, general_name]
  }
```

上記lookMLの**dimension**と**measure**から以下のような可視化が行われる。
![lookML説明用1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/6c674b8e-2a93-8643-9a31-0fd093eb5889.png)


## まとめ
細かな説明をすると、Lookerの**project**とか**model**とか仕組みと概念的な話に広がっていきます。

そうなると、理解に至るまでかなり時間を要してしまうと思いますので、お勧めなのは、**最低限の情報をなんとなく知って、Lookerのダッシュボードを1個作ってみる。**

その後に、疑問や興味が沸いてきたところで、概念的な部分まで徐々に深掘っていく。という感じがよいのかなと思いました。
算譜と与件。仮説（121）

集合論としては、与件(data)の一部が算譜(program)である。

# ハードウェア
CPUによっては、プログラム領域とデータ領域を分けている場合がある。
http://www.cpu-world.com/Arch/8086.html

CS: code segment ->instruction pointer (IP) 
DS: data segment -> stack pointer (SP)  base pointer (BP)
SS: Stack segment -> general registers (AX, BX, CX, DX) index register (SI, DI) 

プログラムの分岐が狭い範囲と、広い範囲とでコードの長さが違うことがある。
狭い範囲でプログラムが分岐している場合には、高速でかつ小規模なソフトウェアになることが8086系CPUの利点であった。

論理的には68000系の線形なメモリ配置の方がわかりやすいかもしれない。

# 算譜(program)
ソフトウェアで、プログラム領域とデータ領域を分けることがある。

抽象データ型では、プログラムとデータをあるメモリ空間に閉じ込めることにより保守を容易にしようとする。

ハードウェアでメモリの局所的利用に優位性があるかどうか。
ソフトウェアでメモリの局所的利用に優位性をもたらす機能をOS, 言語で設定するかどうか。

# 与件(data)
プログラムとデータを別々に持っていたとしても、
データを分類分けしてプログラムを短くしたりすることがある。
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
[Peek] UbuntuでGIFで画面録画するツール

Ubuntuで画面録画するアプリの紹介です。
Qiitaの投稿やGithubのissueやPRに添付したいなと思ったので調べました。

## Peek

https://github.com/phw/peek

## インストール方法

※READMEに書いてあります
https://github.com/phw/peek#ubuntu

```
sudo apt install software-properties-common
sudo add-apt-repository ppa:peek-developers/stable
sudo apt update
sudo apt install peek
```

## デモンストレーション

![Peek 2019-08-18 22-38.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/9e11f376-133b-51c3-ed2b-30221841783c.gif)


## 使用方法

### ①どちらの方法でも良いので `Peek` を起動する

- コマンドラインで `peek` とタイプする
- `Peek` アプリを起動する

![Screenshot from 2019-08-18 22-52-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/ad900291-97a6-0d9e-8e19-df0e94421d25.png)

### ② ウィンドウサイズを調整する

### ③ `Record as GIF` ボタンを押して録画開始

3秒後に録画が開始されます

![Screenshot from 2019-08-18 22-55-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233666/3b12cb0c-2d12-b206-11f3-83ceaa26b091.png)

### ④ `Stop` ボタンを押して録画停止

ボタンを押すと保存場所を聞かれるので、任意の場所を指定して保存する

## 参考

https://github.com/phw/peek
https://www.virment.com/install-use-peek-gif-recorder-ubuntu/
HackerRank　Python3　Algorithmsを解く


#はじめに
未来電子テクノロジー（https://www.miraidenshi-tech.jp/intern-content/program/）
でインターンをしているrayaと申します。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

#今回の内容
前回の続きで、Python初心者がいきなりHackerRankに挑みます。
AlgorithmsのCompare the Tripletsからです。

#Compare the Triplets
前回からの続きになります。

前回の内容です。
↓
https://qiita.com/breakthrough/items/fba8c9e7b1709240ee68

後日、調べて変数名とrange（）の範囲を変えたところ正解できました。
また、コードを記載する場所が間違っていました。
if\_\_name\_\_...の後に書いてはダメなんですね。

コードは以下の通りです。

```python
   alicepoint=0
   bobpoint=0
   for i in range(3):
       if a[i]>b[i]:
            alicepoint += 1
       elif a[i]<b[i]:
            bobpoint += 1
       else:
            alicepoint += 0
            bobpoint += 0   

    result=[]
    result.append(alicepoint)
    result.append(bobpoint)
    return result
```
ここでは使えていませんが、zip()関数が便利なようです。

・zip()関数：for文の中で、複数のリストの要素をまとめて取得できる。要素数が異なる場合は、余った要素を無視する。

Youtubeで見つけたzip関数を使ったコードです。
いたずらに変数を増やしていないので、簡潔です。
参考にしたいです。
↓

```python
def compareTriplets(a, b):
    result=[1 if x > y else -1 if y > x else 0 for x, y in list(zip(a,b))]
    return result.count(1), result.count(-1)
```
#Simple Array Sum, A Very Big Sum

配列の要素の合計を返す問題。

```python
ar_sum = sum(ar)
return ar_sum
```

正解でした。
・sum()関数:リストの要素を合計する
#Diagonal Difference
n×nの行列になるよう数値を配置。
その後、2つの対角線上の数値の合計をそれぞれ求め、その差の絶対値を返す。

```python
#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the 'diagonalDifference' function below.
#
# The function is expected to return an INTEGER.
# The function accepts 2D_INTEGER_ARRAY arr as parameter.

def diagonalDifference(arr):
    # Write your code here    
if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    n = int(input().strip())

    arr = []

    for _ in range(n):
        arr.append(list(map(int, input().rstrip().split())))

    result = diagonalDifference(arr)

    fptr.write(str(result) + '\n')

    fptr.close()
```
・2次元配列：数Cの行列のこと。aという行列でa[0][1]なら0行目で1列目の要素を指す。通常、ネストされたforループで処理する。最初のループが行番号、次のループがその行の列を示す。
・abs()関数:引数の絶対値を返す

```python
lr_diagonal = sum(arr[i][i] for i in　range(n))
rl_diagonal = sum(arr[j][n-1-j] for j in range(n))
value = lr_diagonal - rl_diagonal
return abs(value)
```
法則に気付けたので正解できました。

#おわりに
Algorithmsは５問解けました。
現在はData StructuresのEasy５問とMedium１問を解き終わった状態です。
後日、復習として投稿します。
docker-composeをインストールなしで使う


## どういうこと？
* docker-compose を docker コンテナで実行します。
* DockerHubにOfficialのイメージが公開されています。
  -  https://hub.docker.com/r/docker/compose

## どうやって？

* .bashrc などに、alias で設定すれば、通常のdocker-composeと同等に利用できました。
  - .bashrc  書き換えたら、`source ~/.bashrc` 忘れずに。


```
alias docker-compose='docker run --rm \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v "$PWD:/$PWD" \
    -w="/$PWD" \
    docker/compose:1.24.1'
```


* 実行できた！

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

## あれこれ
* dockerhubに上がっている `docker/compose` は latest のtagがないので、バージョンを指定して実行する必要がありました。
* [通常のインストール方法](https://docs.docker.com/compose/install/)だと少なからず環境を汚すことになるので、docker-compose も dockerコンテナで実行できることでとてもおしゃれですね。
Vue CLIでビルドしたら背景画像のパスが合わず表示されない

#問題点
単一コンポーネント（.vueファイル）内のstyleタグ内に指定した背景画像のパスが、distされたら合わなくなってうまく表示されない。

```css:適用したいCSS
background-image: url("./assets/images/sample.jpg");
```

開発環境であればもちろんこれで問題なく表示されるが、ビルド ⇨ distされたファイルを確認するとCSSにこのパスがそのまま適用されてしまうため、背景画像が表示されない問題が発生。


#解決策

まず、画像のパスを以下のように定義。export文の上あたりに記述すればOK。
（※ @/のあとはsrcより下の階層のパス）

```js:scriptタグ内
import src from '@/assets/images/sample.jpg';
```

適用したい要素に定義したパスを直接記述する。

```vue:templateタグ内
<div class="bg-image" v-bind:style= "{ 'background-image':' url(' + src + ')' }">
```

#結果

distされた背景画像のパスを見ると・・・

```html:distされたindex.html
<div class="bg-image" style="background-image: url('./assets/img/sample.e25529e.jpg');">
```

これできちんと背景画像が表示された。

ちょっと面倒だが、このままサーバーにアップしてもうまく表示されたのでとりあえずこれで問題ないかな。