OmniAICreator/Qiita-1.07M huggingface dataset:
ElmでHTMLのattributeを自分で作る


# Tl;Dr;

**公式パッケージを読むと色々勉強になるぞ**

# TOC

1. [動機](#動機)
2. [作り方](#作り方)
3. [使い方](#使い方)
4. [他の例](#他の例)
5. [まとめ](#まとめ)


# 1. 動機

最近Elmにハマったばかりのweb初心者なのですが、netlifyで[自分のホームページ](https://cj-bc.netlify.com)を公開してみることにしました
(書き始めたばかりなのとCSSがないのでまだまだです)
そこでnetlifyの*formの投稿を自動で取得してくれる機能*を使ってみようと思い、`netlify`attributeを追加してみました
(ちなみに、機能としてはは上手くいきませんでした。それは後ほど)

## netlify attribute

[netlify attribute](https://www.netlify.com/docs/form-handling/)を`form`タグに追加することで、netlifyが自動的に投稿を取得してくれるようになります。

# 2. 作り方

作り方は公式のパッケージの[elm/Html](https://github.com/elm/html)を参考にしました(elmをインストールしてあれば、`$HOME/.elm/0.19.0/package/elm/html/`以下にあり、自分はそちらを参考にしました)

とても簡単、以下の要領でできます

```elm
import VirtualDom

netlify : String -> Html.Attribute msg
netlify str =
  VirtualDom.attribute "netlify" str
```

# 3. 使い方

```elm:Main.elm
view : Model -> Html Msg
view _ =
  form [netlify]
       [ input [ type_ "text" ] []
       , button [ type_ "submit" ] [ text "submit" ]
       ]
```

この`view`は以下のようになります

```html
<form netlify>
  <input type="text">
  <button type="submit">submit</button>
</form>
```

思った通りにできたね！やったね！！


# 他の例

[Youtubeの登録ボタン](https://developers.google.com/youtube/youtube_subscribe_button)を使用するには以下のような感じです:

```elm
dataChannelid : String -> Html.Attribute msg
dataChannelid id =
    VirtualDom.attribute "data-channelid" id


dataLayout : String -> Html.Attribute msg
dataLayout str =
    VirtualDom.attribute "data-layout" str


dataCount : String -> Html.Attribute msg
dataCount str =
    VirtualDom.attribute "data-count" str


view =
  div [ class "g-ytsubscribe", dataChannelid "UCPf-EnX70UM7jqjKwhDmS8g", dataLayout "full", dataCount "default" ] []
```

こうすると[魔王まぐろなちゃんのYouTubeへのリンクができます](https://www.youtube.com/channel/UCPf-EnX70UM7jqjKwhDmS8g)
イメージ画像↓
<img width="202" alt="screenshot 2019-06-11 16.00.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222594/31f64c6e-3c91-5dc2-03d7-fca5939e7ce9.png">

(但しこれも諸条件があるらしく、ページが開かれた時に読み込まないと上手くいきません。コードのせいというよりは仕組みの問題だと思います)


# まとめ

- 意外と`Html.Attribute`の追加は簡単だった!
- 公式のパッケージが観れるのは本当にありがたい、色々学べる

ちなみにその近くに`property`の追加方法等も書いてあるので木になる人は是非に...?


---

# netlifyのformとしては上手く行かなかった

実装したのはいいものの、実際に使用してみるとどうやらきちんと機能していないようです。

> Netlify comes with built-in form handling.
> *Our build bots do it by parsing your HTML files directly at deploy time,*
> so there’s no need for you to make an API call or include extra JavaScript on your site.
>
> https://www.netlify.com/docs/form-handling/

ふむ。

> *Our build bots do it by parsing your HTML files directly at deploy time,*

...

> *at deploy time*

...`デプロイ時にHTMLをパースして行います`とのことなので、静的ファイルに存在しないのでアウトでした。

## 解決策

**Elmからではなく`index.html`内に置こう**
DynamoDBのUpdate性能の落とし穴

#作業環境
PHP5.3 + CentOS 7 + AWS Cli DynamoDB

#前提条件
①DynamoDBへのクエリ操作は基本[Paginated](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/query.html#synopsis)（検索結果がページ単位でもどってくる）だ。一回800件にしよう！

②[この](https://stackoverflow.com/questions/40478904/dynamodb-batch-update)通り、DynamoDBに複数件データの更新は不可能、ループで一件ずつ更新するほかありません。現状自分の環境では、一件データの処理更新あたりに1秒がかかります。

③DynamoDBに新データが常に発生する。今回は**実行時点**で対象データが1000件とします。

#作業内容
作業で、aws cliでDynamoDBの対象テーブルにクエリをかけ、取得した対象データを処理してから、当該データのステータスを**更新**するバッチを作成する。

対象データを全部処理するつもりで、①のクエリ結果に、続きがあるよ！と示す「"LastEvaluatedKey"」がなくなるまで、無限ループで実装してます。

#問題
つまり、プログラムのイメージは

```
while(前の①のレスポンスに「LastEvaluatedKey」が存在){
    ①(クエリ)
    foreach(List as obj){
        処理…
        ②（Update）
    }
}
```

↑の実行時間を考えると、１クエリ（１ページ）が800件の場合、whileが一周廻る時間は約800秒=13分20秒を要する。whileが一周廻る間、もし新たな対象データがDynamoDBに登録されると、次に終わるはずのwhileループがもう一周伸びることになる。

本番運用上↑の状況が起こる懸念が残ります。

#対策
対策本当にある？上記の状況が起きてしまう場合、現実的ないい対策が見当たらない想定です。理由は、こうなる際、データ発生スピード＞データ消化スピードからです。今の段階で、データ発生スピードが1000/Day以内の話を聞いたので、まずは大丈夫だが。将来大量のデータの業務が発生の場合、AmazonがBatchUpdateItem見たいな操作をリリースしてくれると助かります。
iCheckで全選択、全解除、全反転を実装する

ネットで上の内容を調べると結構小難しいやり方ばかりが見つかりました。
もっとシンプルにできたので忘れないうちに掲載します

### デモ

https://codepen.io/qwe001/pen/GbRWae

### HTML

```html
<div>
	<a href="#" data-target=".sample" class="btn_check_all_on">全選択</a>
	<a href="#" data-target=".sample" class="btn_check_all_off">全解除</a>
	<a href="#" data-target=".sample" class="btn_check_all_revert">全反転</a>
</div>
<ul>
	<li><label><input type="checkbox" class="sample" value="1">1<label></li>
	<li><label><input type="checkbox" class="sample" value="2">2<label></li>
	<li><label><input type="checkbox" class="sample" value="3">3<label></li>
	<li><label><input type="checkbox" class="sample" value="4">4<label></li>
</ul>
```

1. checkboxに適当なクラス名をつけます
2. ボタン要素にdata-target属性をもたせ、そのクラス名のセレクタをつけます
3. ボタン要素のクラス名を次のようにします。

全選択 -> btn_check_all_on
全解除 -> btn_check_all_off
全反転 -> btn_check_all_revert

### JavaScript

```javascript
(function($){
'use strict';

 /**
 * init iCheck for checkbox and radion buttons.
 *
 *
 * @link http://icheck.fronteed.com/
 */
function initICheck(elem)
{
  var elem = elem !== undefined ? elem : "input[type=checkbox], input[type=radio]";
  var options = {
    checkboxClass : "icheckbox_flat-blue",
    radioClass : "iradio_flat-blue",
  };

  $(elem).iCheck(options);
}

/**
 * Checkbox State Change With iCheck.js
 *
 * @link http://alphasis.info/2011/10/jquery-checkbox-all/
 * @link https://github.com/fronteed/icheck/issues/298
 */
function initICheckControls()
{
  iCheckAllOn();
  iCheckAllOff();
  iCheckAllRevert();
}

function iCheckAllOn(elem)
{
  var elem = elem !== undefined ? elem : ".btn_check_all_on";

  $(elem).click(function(){
    var target = $(this).data('target');
    $(target).prop('checked', true).iCheck('update');
  });
}

function iCheckAllOff(elem)
{
  var elem = elem !== undefined ? elem : ".btn_check_all_off";

  $(elem).click(function(){
    var target = $(this).data('target');
    $(target).prop('checked', false).iCheck('update');
  });
}

function iCheckAllRevert(elem)
{
  var elem = elem !== undefined ? elem : ".btn_check_all_revert";

  $(elem).click(function(){
    var target = $(this).data('target');
    $(target).prop('checked', function(index, oldValue){ return !oldValue; }).iCheck('update');
  });
}

})(jQuery);
```

initICheck関数はiCheckを呼び出しています。
おそらくこれを読んでいる人は既にこれにあたる内容を実装済みだと思いますので、この関数は必須ではありません。

initICheckControls関数に、全選択、全解除、全反転の機能を集約しています。これが今回の実装の主です。

### 使い方

```javascript
$(function(){
  initICheck();
  initICheckControls();
});
```

当然ながらjQueryとiCheckを事前に読み込んでいる必要があります。

### 参考にしたURL

* http://alphasis.info/2011/10/jquery-checkbox-all/
* https://github.com/fronteed/icheck/issues/298
type="module"がsafariで上手く読み込めなかった時の対応

# 概要
今まで何も考えず`</body>`前にJSを読み込ませてたのですが、最近のベストプラクティスとして`head`タグに

```html
// モダンブラウザ用
<script type="module" src="js/main.js"></script>

// IE11などレガシーブラウザ用
<script nomodule src="js/nomodule.main.js" defer></script>
```

のように読み込むというプラクティスを発見し、実践した。
その際にsafariでのみ読み込みエラーが発生したため、その解決方法の備忘録です。

# 解説
`type="module"`での読み込みに関しては下記の記事の解説が分かりやすかったため
一読をおすすめします。
[モダンブラウザに最適化した JavaScript を提供する](https://qiita.com/il-m-yamagishi/items/119cd99197cd3e9b79c2)
[ライブラリ以外はとりあえず type="module" にしよう](http://var.blog.jp/archives/77519253.html)


`nomodule`に関しては下記。
[ES Modules への橋渡しとしての nomodule 属性](https://blog.jxck.io/entries/2017-06-21/nomodule-attribute.html)

ひとまずざっくり説明すると、`type="module"`はモダンブラウザのために最適化された読み込み方式（deferとかでタイミング調整しなくても良い）で、`type="module"`に対応していないブラウザは`nomodule`の方を自動的に読んでくれます。
逆に言えば`nomodule"`のJSは`type="module"`対応ブラウザでは読み込まれないため、複数のpolyfillを読み込んで肥大化したファイルを読み込む必要がなくなります。便利。
なのでWebpackでそのあたりを出し分ければモダンブラウザで無駄のないJSファイルを配信できますね。

# ハマったポイント
ここでタイトルの内容に入ります。
[モダンブラウザに最適化した JavaScript を提供する](https://qiita.com/il-m-yamagishi/items/119cd99197cd3e9b79c2)
の記事内にありますが、`type="module"`でJSを読み込む場合、CORS通信（ざっくり言うと外部通信的な）扱いとなってしまい、MacOS、iOSのsafariでのみ
`Blocked https://example.com/js/hoge.js from asking for credentials because it is a cross-origin request.`
とアラートが出て読み込みができない問題が発生しました。

# 解決方法
[ご紹介記事](https://qiita.com/il-m-yamagishi/items/119cd99197cd3e9b79c2)の中にもありますが、`.htaccess`などサーバーサイドで`Access-Control-Allow-Origin: https://example.com`のようにCORS通信を許可する方法があります。（セキュリティー上問題があるようなので、ワイルドカードでの指定はやめたほうが良さそう。）
ですが、実案件ではクライアントのサーバー設定をイジれないケースもあり、上記の方法では解決できませんでした。
また、`Access-Control-Allow-Origin`の設定先を開発環境URLにしていて、公開したときに書き換え忘れて読み込めない！のような自体も想定できます。

いろいろ調べた結果、下記のように`<script>`タグにcrossorigin属性をつけることでサーバーサイドをイジる必要なく解決しました。

```html
// crossorigin属性を追加
<script type="module" src="js/main.js" crossorigin="use-credentials"></script>
```

`crossorigin`の詳しい解説は[こちら]
(https://developer.mozilla.org/ja/docs/Web/HTML/CORS_settings_attributes)

`crossorigin="anonymous"`としても読み込みをされますが、こちらは実際に外部のCDNなどから読み込む場合に使用したほうが良さそう？なので`crossorigin="use-credentials"`としました。（『ちげぇよ馬鹿野郎！』というご指摘があれば教えていただけると助かります…）
Node.jsのFileSystemでインターネットから画像をダウンロードする(with request-promise))

Node.jsには`fs`と呼ばれるモジュールがあり、ファイルを作成したり読み込んだりすることができます。

これを用いてインターネット上にある画像をダウンロードすることができます。

## 事前準備
Node.jsが使えるように環境構築する。
今回は[初心者も簡単！UbuntuでNode.jsの環境構築](https://qiita.com/Hiroro0970/items/f899498f018e80c65952)で紹介した環境で実行する。

また、今回使用するモジュールをnpmコマンドでインストールします。

```
npm install fs request request-promise —-save
```
別に`request-promise`を使わなくても実現できるのですが、今回はあえて`request-promise`を用いて実装したいと思います。
なお、`request-promise`を使うときは依存性の事情から`request`もインストールするようにしましょう。

## 流れ
非常にシンプルです。
1. 画像のURLを定義する
2.  `fs.createWriteStream`で書き込みファイルを用意する
3.  URLにリクエストを送り、取得した内容をファイルに書き込む

実装すると以下のようになります。

``` index.js
const rp = require('request-promise');
const fs = require('fs');

// Downloadしたい画像のURLを記載
const url = 'http://www.example.com/hoge.jpg'

// ファイル名を記載
// 事前にimgディレクトリを用意する必要がある
const file = fs.createWriteStream('./img/hoge.jpg');

// URLにアクセスしてファイルに書き込む
rp(url).pipe(file);
```

あとは以下コマンドでファイルを実行するとimgディレクトリ内に画像ファイルが格納されます。

```
node index.js
```

## 個人用メモ
URLにアクセスしたとき、バイナリデータを受け取り、そのバイナリデータをファイルに`pipe`することでファイルに画像情報が書き込まれ、そのファイルを開くと画像が表示される。つまり画像のダウンロードというのは**インターネットから画像情報をバイナリ形式で受け取り、その内容を作成したファイルに書き込むこと**だということか。
よくわかっていないけど。


## まとめ
とりあえずnode.jsを用いて画像をインターネットからダウンロードできるようになりました。
これと[Node.jsでニュース記事をWebスクレイピングしてみよう](https://qiita.com/Hiroro0970/items/7b1167033b15d3c95996)の内容を組み合わせることで画像も出力できるスクレイピングプログラムが書けるようになります。
近々試してみようと思います。
intel Core i7-8700 & RTX 2070 における Ubuntu Desktop19.04インストール手順

#事のきっかけ
何かと縁が深いNvidiaのGPUを搭載したパソコンで、Ubuntuをインストールしようとすると高確率で問題が起こる場合がある。そこで、新たにパソコンを購入したのを機会に、自分が成功した手順をここに記そうと思った。
#Ubuntuのインストール

1.[Ubuntu公式サイト](https://www.ubuntu.com)からUbuntu DesktopのISOファイルをダウンロードする。

2.macOSの場合はbalenaEtcher、Windowsの場合は、RufusにてUbuntuのUSBインストーラを作成する。
各アプリケーションのインターフェイスがかなりわかりやすいので、初めてでもいけるはず。

3.インストールしたいパソコンのBIOS画面で、セキュアブートの無効化と、Boot設定をUEFIのUSBが最初に起動できるように設定し、再起動。

4.起動時にUbuntu Install(safe graphics)があると思うので選択する。(safe graphicsがない方を選ぶと、もれなく画面が乱れまくってインストールできない。)

5.Ubuntuのインストールの指示に従いインストールしていくが、" アップデートとその他のソフトウェア "がタイトルとなっている時の下の方にある、" グラフィックスとWiFi.... "のチェック念の為はしない。（意味あるかは不明）

(以下6,7は、インストール後に出てくる起動選択で、"ubuntu"を選んでも正常に起動できない場合の対処)
6.インストールが完了後再起動を行うと、" GNU GRUB ...."というタイトルが一番上についた、背景が紫色の起動選択画面に出るので、矢印キーを操作して" Ubuntu " を選択し、eキーを押すと起動に関しての詳細な編集画面となる。

7.下から二行目あたりに" quiet splash ...."とあるので、"splash"の右側にスペースで1つ空けて、"splash nomodeset"となるように追記する。その後、Ctrl-XかF10キーを押して起動する。

#Ubuntu起動後の設定
1.nvidiaのドライバーのみ有効化する必要がある。以下端末で実行
`sudo vi /etc/modprobe.d/blacklist-nvidia-nouveau.conf`を実行し、以下を入力して保存する。
`blacklist nouveau
options nouveau modset=0`

最後に、`sudo update-initramfs -u`を実行する。

#Nvidiaドライバーインストール
`Ctrl + Alt + F1(F4)`を入力し、CUIモードに移行する。
※端末によって、上記のショートカットでモード変更出来ない場合は、他のショートカット方法を調べていただきたい。
・NVIDIA GPU ドライバリポジトリ登録
`sudo add-apt-repository ppa:graphics-drivers/ppa`
(プロキシの場合)
`sudo -E add-apt-repository ppa:graphics-drivers/ppa`
・Ubuntu apt update
`sudo apt update`
・Ubuntu デバイス確認(third party free recommendedのバージョン確認)
`ubuntu-drivers devices`
・Nvidia ドライバ インストール(xxx=recommendedのバージョン)
`sudo apt install nvidia-driver-xxx`
・再起動
`sudo reboot`
・確認
`nvidia-smi`

リポジトリ登録で失敗する場合は、プロキシ系を怪しんでください。
おしまい。

#参考サイト
(ubuntuインストール時に参考)
https://qiita.com/riv/items/345373398cf30d16b8ad
https://qiita.com/bohemian916/items/8c7f0c4b3d3ea0958559
(Nvidiaドライバインストール時に参考)
https://linuxconfig.org/how-to-install-the-nvidia-drivers-on-ubuntu-19-04-disco-dingo-linux
https://krhb.hatenablog.com/entry/2019/05/17/181509
プロジェクトの進め方（保守）


改修の進め方

ドキュメントの作成
レビュー（評価というより、複数人の目で見てよくすると考える）
回収
テスト
検証環境にアップ

ドキュメントの作成では、
最近の修正項目は赤字での表記
ドキュメント場所は改定日付をつけていく
【Node.js】Twitter APIからDMが飛ばせなくてハマった件

##はじめに
勉強目的でNode.js+Express.jsでTwitterAPIを叩くだけの簡単なAPIを作成したのだがDM送信時に認証エラーが出てハマったので備忘として。

```twitterSecret.json
{
    "consumer_key": "xxxxxxxxxxxxxxxxxxxxxx",
    "consumer_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "access_token_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "access_token_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
```

```sendDM.js
const twitter = require('twitter');
const fs = require('fs');

/* 略 */

const secret = JSON.parse(fs.readFileSync("twitterSecret.json","utf-8"));
const client = new twitter(secret);

const params = {
  event: {
    type: "message_create"
    , message_create: {
      target: {
        recipient_id: "xxxxxxxxxxxx"
      }
      , message_data: {
        text: "test"
      }
    }
  }
};

client.post("direct_messages/events/new", params, function(error, data, response){
  if(!error){
    console.log("成功!");
  }
  else {
    console.log("失敗");
    console.log(error);
  }
});
```

あれこれ文献を読み進めながら書いたけど、これで概ねOKなはず...だったのだが下記のエラーに遭遇

```
{code:32 message: 'Could not authenticate you.'}
```

どう見ても認証エラー。
てっきりトークンのパーミッションが足りてないのかと思ったけど、他のエンドポイント("direct_messages/events/list"とか "statuses/update")は成功してるから、そういうわけでもなさそう。
というか、**DMの送信だけできない**。

##原因・解決方法
あれやこれやと頭を悩ませていると、[公式のドキュメント](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/guides/direct-message-migration)にこんな記述が
>Summary
> - Message is defined in JSON POST body
> - Content-type header must be set to application/json
> - JSON body is not included in the generation of the OAuth signature.

ここら辺の仕様にライブラリが対応してないと先のエラーが出るらしい。

というわけで試しにライブラリを変えてみる。

```
npm install twit
```

**※twitインスタンス作成時のトークンのプロパティは"access_token_key"ではなく"access_token"なことに注意**

```twitterSecret.json
{
    "consumer_key": "xxxxxxxxxxxxxxxxxxxxxx",
    "consumer_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "access_token_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
```

```sendDM.js
//const twitter = require('twitter');    // del
const twitter = require('twit');         // add
const fs = require('fs');

/* 略 */

const secret = JSON.parse(fs.readFileSync("twitterSecret.json","utf-8"));
const client = new twitter(secret);

const params = {
  event: {
    type: "message_create"
    , message_create: {
      target: {
        recipient_id: "xxxxxxxxxxxx"
      }
      , message_data: {
        text: "test"
      }
    }
  }
};

client.post("direct_messages/events/new", params, function(error, data, response){
  if(!error){
    console.log("成功!");
  }
  else {
    console.log("失敗");
    console.log(error);
  }
});
```

これで問題なく動作した。
てっきり何か認証系の記述を書き洩らしているんだと思ってたから長いことハマってしまった。。。
フォント名についてるNとかProとかStdとかPr6とかUDとか


仕事をしているときに何気なく、導入していたフォントですがうしろについてるNとかProとかUDとかなんなんやろ〜と思いながら、なんとなくにしか思っていなかったので改めて調べてみました。
備忘録ですが誰かのお役に立てればうれしいです！！

#UDってなに？

ユニバーサルデザインと呼ばれ、ユニバーサルデザインの観点「より多くの人が可能な限り快適に利用できるよう配慮されたデザイン」をもとに、「誰もが見やすい、読みやすい」をコンセプトとして、より美しい文字デザインを追求したフォントのことです。

![スクリーンショット 2019-05-31 9.52.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409259/e4f2cc16-3e03-ed8e-f1c7-acba6c5c8bc0.png)
![スクリーンショット 2019-05-31 9.52.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409259/075e9fbb-7484-eacd-d58e-616773d1abd8.png)
![スクリーンショット 2019-05-31 9.52.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409259/91d175b1-73c8-336b-0ebb-afce846797f3.png)

>出典：https://www.morisawa.co.jp/fonts/udfont/lineup/


##ProとかProNとかStdとかpr6ってなに？

ヒラギノ角ゴ Pro
ヒラギノ角ゴ ProN
ヒラギノ角ゴ Std
ヒラギノ角ゴ StdN
.....etc

##Proってなに？Stdってなに？

この「Pro」や「Std」などはアドビシステムズ社が日本語フォント製品用に決めた規格

[「Adobe Japan Character Collection for CID-keyed Fonts」](https://reference.pdfa.org/iso/32000/wp-content/uploads/2017/04/5078.Adobe-Japan1-6.pdf)

に添って作られています。

その規格は、Adobe-Japan1-3やAdobe-Japan1-4のような文字セットのバージョンのようなものがあって、その文字セット（Adobe-Japan1-3以降）のどれを基準に作ったかによって「Std」「Pro」「Pr5」「Pr6」と名前が変わります。

大きな違いは内包されている文字数の違いです。
以下ざっくり。

###「Std」
Adobe-Japan1-3
総合計：9,354文字

###「Pro」
Adobe-Japan1-4
総合計：15,444文字

###「Pr5」
Adobe-Japan1-5
総合計：20,317文字

###「Pr6」
Adobe-Japan1-6
総合計：23,058文字

##じゃあ「N」ってなんなん？
『N』JIS2004という意味。
フォント名に『N』がついてるものは、JIS2004字形の文字が使われているフォントを意味します。

2004年にJISの規格のひとつ、JIS X 0213が「JIS X 0213:2004」となり、例示字形に変更と文字の追加がおこなわれ、下記の6つのシステムフォントに採用されました。

・ＭＳ Ｐゴシック
・MS ゴシック
・MS UI Gothic
・ＭＳ Ｐ明朝
・MS 明朝
・メイリオ

![kanji_code_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409259/6025785a-1987-89cb-f0e1-d2d891f10f32.jpeg)
![kanji_code_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409259/4f32f55f-7749-4767-5975-c6148113344a.jpeg)

>出典:http://www.risosha.jp/upload/guide/k_code.html

##ProやStd、Nについてのまとめ
結論から言えば、迷ったらPro6Nを使用すれば守備範囲も広く、最新の字形で使用できそうです。

#参考記事

[知ってた？フォント名のあとについてる文字の意味！](https://www.plusdesign.co.jp/blog/?p=848)

[ユニバーサルデザインフォント](https://jpn.nec.com/font/ud/)

[モリサワUD書体のラインナップ](https://www.morisawa.co.jp/fonts/udfont/lineup/)

[日本語フォントの後ろにある「Std/Pro/Pr5/Pr6」と「N」の意味](https://blog.karasuneko.com/1962/)
TwitterのDMをGmailを経由してSlackに通知する方法

# 目的

SlackのTwitterアプリで自分の投稿などは通知することができますが、DMを通知することはできませんでした。
そこで、以前はDMをメール通知できることを利用して、`Twitter→Gmail→IFTTT→Slack`とすることで簡単に実装することができました。しかし、2019年3月末から`Gmail→IFTTT`の連携が使用できなくなり、別の手段を考えることにしました。

# 概要

- Twitterのメール通知機能でDMが来たら内容がGmailに届くようにする。
- Gmailの設定から、DMに関するメールに`DM`というラベルを付けるようにする。
- GASを用いてSlackに通知する。
- 通知した分のメールにはスターを付ける。

# 実装

## Twitterの設定

Twitterの設定＞通知＞メール通知 から「ダイレクトメッセージ」をONにしておきます。また、設定＞アカウントのメールアドレスをGmailにしておきます。

## Gmailの設定

Gmailの設定＞フィルタとブロック中のアカウント から新しいフィルタを作成します。
条件は、
>from: @twitter.com
>件名：ダイレクトメッセージ

とし、`DM`というラベルが付くようにフィルタを更新します。

![スクリーンショット (234).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430946/1105352f-3bba-2296-d425-acf279e4df6b.png)

## GASの設定

GASに以下のコードをコピペします。Incoming Webhooksのところは後ほど設定します。

```js:GAS
var FindSubject = 'label:DM';
 
function getMail(){
 
  //指定した件名のスレッドを検索して取得 
  var myThreads = GmailApp.search(FindSubject); 
  //スレッドからメールを取得し二次元配列に格納
  var myMessages = GmailApp.getMessagesForThreads(myThreads);
  
 
  for(var i in myMessages){
    for(var j in myMessages[i]){
          
      //スターがないメッセージのみ処理   
      if(!myMessages[i][j].isStarred()){ 
        var strDate　=　myMessages[i][j].getDate();
        var strSubject　=　myMessages[i][j].getSubject();
        var oriMessage　=　myMessages[i][j].getBody();
        var cutMessage  =  oriMessage.match(/1px;font-size:1px;color:#ffffff;"> [\s\S]*?<d>/g);
        var strMessage  =  cutMessage[0].replace('1px;font-size:1px;color:#ffffff;">','').replace('<d>','');
        Logger.log(strMessage);
        Logger.log(strDate);
        Logger.log(strSubject);
        
        //Slackにメッセージを送信
        sendSlack(strDate,strSubject,strMessage);
 
        //処理済みのメッセージをスターをつける
        myMessages[i][j].star(); 
      }
    }
  }
}

function sendSlack(strDate,strSubject,strMessage){
  const userName = "DM通知";
  var jsonData = {
      "username": userName,
      "attachments":[
         {
            "fallback":strSubject,
            "pretext":strSubject,
            "color":"#1DA1F2",
            "fields":[
               {
                  "title":strDate,
                  "value":strMessage
               }
            ]
         }
      ]
    }   
  const payload = JSON.stringify(jsonData);
  post(payload);   
}

function post(payload) {
  const postUrl = "https://hooks.slack.com/services/****************"; //Incoming Webhooksの「Webhook URL」を入力
  const options = {
      "method" : "post",
      "contentType" : "application/json",
      "payload" : payload,
  };
  UrlFetchApp.fetch(postUrl, options);
}
```

### トリガー

`getMail()`関数のトリガーを設定します。間隔はどれぐらいでも大丈夫ですが、あまりにも短いとGASがエラーを吐くので、注意が必要です。自分は即時性を求めていないので、１時間に１回にしています。

## Slackの設定
`Incoming Webhooks`を導入します。設定時に表示される`Webhook URL`を上記GASの該当部分にコピペします。表示名やアイコンは好みです。

# 困ったところ

メールでDMの内容は通知されるのですが、`getPlainBody()`で取得するとなぜかDMの内容が含まれないので、`getBody()`でHTML形式で丸々取得しています。そして内容が含まれるところの前後を正規表現で検索し、余分なところを空白に置換することで内容だけを取得するようにしています。

# 改善点

- メールのHTML形式が変わったらそれに合わせて正規表現のところを変更しないといけない。
- DMが来たらすぐに通知するというのはトリガーを変えて頑張ればなんとかなるかもしれない。
英語論文を読む技術

# [Google翻訳](https://translate.google.com/?source=gtx#view=home&op=translate&sl=auto&tl=ja)
知らない人はいないと思う。でも、PDFなどの[ドキュメント翻訳](https://translate.google.com/?source=gtx#view=home&op=docs&sl=auto&tl=ja)があるのを知っていました？
PDF以外にもWord、PowerPoint、Excelも訳せてしまいます。すごい子です！

**ちょっと待って。1MBまでしかアップロードできねーじゃん！使えねぇじゃん！（怒）**

そういう人（私のことです）は、まず落ち着け。そして、次の段落にあるツールを使え。
図や写真がガンガン入っている論文などは余裕で1MB超えることがあるが、なんとかなる。

# [iLovePDF](https://www.ilovepdf.com/ja)

この世の中にはPDF周りの便利なツールが[オンラインで公開](https://www.ilovepdf.com/ja)されている。
**これを使えば、1MBに収まるかもしれない。**

* [iLovePDF](https://www.ilovepdf.com/ja) 
    * [PDFを圧縮](https://www.ilovepdf.com/ja/compress_pdf)
        * 写真や図を圧縮すれば1MBに収まるかもしれない。
        * **実際に3MB超のファイルを900KBにしてくれた神ツール。**
    * [PDFを分割](https://www.ilovepdf.com/ja/split_pdf)
        * 長い文章もページを分ければ1MBに収まるかもしれない
    * [PDFのページを削除](https://www.ilovepdf.com/ja/remove-pages)
        * いらないページを消せば1MBに収まるかもしれない
    * [PDFをWordに変換](https://www.ilovepdf.com/ja/pdf_to_word)
        * Wordだけじゃなく、他のフォーマットに変換していらない部分を消せば1MBに収まるかもしれない

以上です。
言語の壁を超えていけ！
IX2000シリーズルータとOCI間をVPN接続、BGPでルート制御してみた

OCIとオンプレミス間のVPN接続にBGPを使用した場合の検証を行いました。
スタティックルートによる制御に比べてオンプレミス及びOCI側のルート設定のための
手間が省けることと、冗長化する場合の経路制御が簡単になります。

テスト構成ではBGPルータを1台(IX2105)用意、1本のインターネット回線を利用してOCIと
2本のIPSecトンネルを張りました。
またOCIとオンプレミス間の経路交換にはBGPを利用してMain＆Backupの冗長構成にしており、
AS-PATH PREPEND機能を使って制御してみました。

**【BGP利用時の構成イメージ】**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/add205e1-6812-d2a4-2e9a-c70deec522c1.png)


**【OCI側の設定方法】**
![ipsec connection-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/847bcd4b-5886-729a-9289-7fede1bdc653.png)

- 「Create IPSec Connectionを選択します」

![ipsec connection-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/5b56581a-d15d-2947-1f61-3955133db687.png)

- CUSTOMER-PREMISES EQUIPMENT COMPARTMENT
⇒　IPSec接続の対象になるCPEを選択します

- DYNAMIC ROUTING GATEWAY COMPARTMENT
⇒　IPSec接続に利用するDRGを選択します

![ipsec connection-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/be165bea-3d01-8739-a069-dc3c8a85de9a.png)

- CPE IKE IDENTIFIER
⇒　CPEのグローバルIPを入力します（NAT or NAPTを利用時は変換前のIPを入力）

![ipsec connection-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/fe7d972b-fffc-dc8a-7abb-4780378a7065.png)
**※Tunnel1＆Tunnel2共通**

- ROUTING TYPE
⇒　「BGP DYNAMIC ROUTING」を選択します

- BGP ASN
⇒　オンプレミス側のASNを入力します

- INSIDE TUNNEL INTERFACE - CPE
⇒　BGPピアリングに使用するCPE側のIPアドレスを入力します

- INSIDE TUNNEL INTERFACE - ORACLE
⇒　BGPピアリングに使用するORACLE側のIPアドレスを入力します

**【IXルータのBGP設定抜粋】**
ip prefix-list as-path-in 10 permit any
ip prefix-list as-path-out 10 permit any
⇒ route-mapを適用する通信(inbound＆outbound)を指定するためのprefix-listを作成

route-map rmap-in permit 10
  match ip address prefix-list as-path-in
  set as-path prepend 31898 31898 
⇒　inbound通信に適用するためのroute-mapを作成
条件にmatchした場合はAS-PATHを追加(31898×2)する
※TUNNEL1またはTUNNEL2から受信する経路のAS-PATH値を制御するための設定

route-map rmap-out permit 10
  match ip address prefix-list as-path-out
  set as-path prepend [オンプレミス側のASN] [オンプレミス側のASN]
⇒　outbound通信に適用するためのroute-mapを作成
条件にmatchした場合はAS-PATHを追加(オンプレミス側ASN×2)する
※TUNNEL1またはTUNNEL2から送信する経路のAS-PATH値を制御するための設定

router bgp [オンプレミス側のASN]
  neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#1] remote-as 31898
  neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#1] timers 10 30
  neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#2] remote-as 31898
  neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#2] timers 10 30
  address-family ipv4 unicast
    neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#2] route-map rmap-in in
    neighbor [INSIDE TUNNEL INTERFACE - CPEのIP#2] route-map rmap-out out
⇒　CPE#2とのBGPピアリングを経由する通信にroute-mapを適用


**【設定後の確認】**

- Main経路のルート交換状況
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/7e931c57-2f70-8c70-90c5-4e58523affec.png)

- Backup経路のルート交換状況

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/7869296b-edaa-a84b-af87-ca336dbdca74.png)
Mockery\Exception\RuntimeException: Could not load mock (クラス名) already existsの修正

問題
---------------------------------------
```
Mockery\Exception\RuntimeException: Could not load mock (クラス名), class already exists
```

テストを走らせたときに、該当するクラスが他のテストで使用されているときに、上記のエラーが表示される。


修正
---------------------------------------
```
/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function テスト名() {
   いろいろテスト
}
```

エラーを表示するテストに上記のアノテーションを追加すること、該当するテストを別のPHPプロセスにて実行する。


参考
---------------------------------------
https://phpunit.readthedocs.io/ja/latest/annotations.html#runinseparateprocess
【Unity】TextMesh Proで文字を潰さず縁取りする方法 (Editor & Script)

# はじめに

TextMesh Proではアウトライン(`Thickness`)を広げると内側につぶれてしまう現象があるのですが、`Dilate`(拡張するという意)を調整することで綺麗に表示されることが出来ます。今回はその変更方法を紹介します。

![20190611-142930.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/1ca194ef-a4fa-ae05-61e8-6b9631f714de.png)

体感的に、`Thickness`と`Dilate`は同じくらいの値に調整すると大抵綺麗に見えると思います。

# Editorから変更する

FontAsset、もしくはTextMesh ProコンポーネントのInspectorからマテリアルを選択し、[Face]-[Dilate]と[Outline]-[Thickness]の値を調整してください。

<img width="312" alt="スクリーンショット 2019-06-11 14.33.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/49e9336e-4d2d-caf8-a233-c264500a56ab.png">

# スクリプトから変更する

```.cs

void SetOutline(TMPro.TextMeshProUGUI tmp, float outlineWitdh, float dilateRate)
{
    tmp.outlineWidth = outlineWitdh;
    tmp.materialForRendering.SetFloat("_FaceDilate", dilateRate);
    tmp.UpdateFontAsset();
}
```


アウトライン幅はメソッドが用意されていますが、Dilateに関しては直接マテリアルのパラメータに代入する必要がある点がハマりどころです。`tmp.UpdateFontAsset()`は呼び出す前後の処理によっては不要かもしれません。

ちなみにコードには含めていませんが、`Thickness`の値域は`[0,1]`、`Dilate`の値域は`[-1,1]`です。

## 拡張メソッド版

拡張メソッドにしておいても便利そうだと思ったので載せておきます。

```TextMeshProUGUIExtensions.cs
namespace TMPro
{
    public static class TextMeshProUGUIExtensions
    {
        public static void SetOutline(this TextMeshProUGUI tmp, float outlineWitdh, float dilateRate)
        {
            tmp.outlineWidth = outlineWitdh;
            tmp.materialForRendering.SetFloat("_FaceDilate", dilateRate);
            tmp.UpdateFontAsset();
        }
    }
}
```

拡張メソッドを呼び出すためには`TMPro`をusingする必要がある点に注意です。

```呼び出し側.cs
using TMPro:

public class Hoge
{
    TextMeshProUGUI title;

    public void EnableOutline()
    {
        title.SetOutline(0.5f, 0.5f);
    }
}
```


# 参考

【Unity】TextMesh Pro でアウトラインを太くしたら文字が潰れてしまう現象を防ぐ方法 - コガネブログ
http://baba-s.hatenablog.com/entry/2018/09/18/120000
PowerShellでイベントソースを追加・削除する

　作成したスクリプトの実行結果などをイベントログに任意のイベントソースで出力させたい場合がある。
　それには事前にイベントソースを登録する必要がある。下記の方法でイベントソースを登録することができる。

●イベントソースの追加

```powershell
　New-EventLog -LogName ログの種類 -Source "イベントソース" [-ComputerName ホスト名もしくはIPアドレス]
```

・ログの種類は「Application」「Security」「System」のどれかを指定。
・イベントソースは自分で任意につけたイベントソース。
・-ComputerName は任意であり、リモートで行う場合は指定する。

例：Applicationログにhogeというイベントソースを登録する。

```powershell
New-EventLog -LogName Application -Source "hoge"
```

●イベントソースの削除
イベントソースを間違えて登録してしまった場合や、イベントソースの名称を変更したい場合などは一度削除させる必要がある。

下記のコマンドで登録したイベントソースの削除が可能

```powershell
Remove-EventLog -LogName ログの種類 -Source　"イベントソース" [-ComputerName ホスト名もしくはIPアドレス]
```
※New-EventLogにすれば登録で、Remove-EventLogに変えると削除となる。
【Unity】Unsupported Swift Version エラー 解決法

##一応経緯
ARKitを使ったアプリを開発するために、
iPadPro(iOS12.2)をつなげたところ、
「Xcode10.2じゃなくて10.1に下げなさいよ」とエラーが。
↓
Xcode10.1にしたら、「iOS12.2に対応してないよ」とエラーが。
↓
Xcode10.2のまま解決するのは面倒そうだったので、
10.1で解決する方法を調べた

##とりあえず結論
iOS12.2に対応させるファイルがGithubで手に入る様です。

▽こちらの記事で解決いたしました！
【Swift】エラー「Could not locate device support files（iOS 12.2）」の対処方法
https://pippi-pro.com/swift-error-could-not-locate-device-support-files-12-2


##補足
▽複数バージョンのXcodeを入れる方法。ダウングレードは不要です
http://vdeep.net/xcode-multi-version
学生が応用情報技術者試験を受験した記録


# 応用情報技術者試験受験記録

2018年春の情報処理技術者試験にて、応用情報技術者区分に合格したので備忘録的に記録を残しておきます。

## はじめに

応用情報技術者試験を受けてみるか、という気持ちになって情報収集をした際、大学生による受験体験記が非常に少ない印象を受けた（そもそも社会人向けの資格みたいな風潮ありますね）ので記しておくべきかなと感じたというのがこの記事を書いた理由です。したがって、大筋は受験するかどうか迷っている/受験することが決まった学生に向けたものとなります。

### 筆者のステータス（当時）

- 学部2年生（18年度）

- 文理融合学部所属

- 17年秋に基本情報技術者試験合格（午前・午後共におよそ8割）

- CとJavaが書ける(学部の講義で困らない程度)

- 高校生の時から一応はプログラミングには触れていたが何かを作るとかそういう感じではなかった。Javaでゲーム作った程度
- セキュリティとIoTがすき

## 受けた理由

- 友人が取っていたため

- 情報技術の基本的な部分について一通り目を通しておきたかったのでその指標として

- 基本情報技術者試験に合格して、得た知識についてもう少し詳しく理解しておく必要性を感じた
- 社会人になってからは時間がなく資格類は取りにくいという話を聞いていたため
- 暇つぶし
- 学部が受験推奨していた

## 勉強期間

- 教本自体は基本情報技術者試験に合格した直後の秋に買ったがなんだかんだで手をつけ始めたのは1月ごろ

- 3月から1h~2h/day勉強

- 4月は4h〜5h/day程度（やる気がある日は10hぐらいまで取り組むこともあった。学部低学年だとこの時期はオリエンテーションの嵐なので資格勉強に時間を突っ込んでも学業に差し支えないので都合がよかった）

## 使ったもの

- [応用情報技術者 合格教本/技術評論社](https://gihyo.jp/book/2017/978-4-7741-9315-1)

- [要点早わかり 応用情報技術者 ポケット攻略本]( https://gihyo.jp/book/2017/978-4-7741-8507-1)

- [応用情報技術者.com](https://www.ap-siken.com)

- [IPAのサイトからダウンロードした過去問pdf](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html)

## 勉強方法

- ひたすらに教本を読み、自分の言葉で説明できるように理解する

上に挙げた合格教本は非常に網羅的で、初見で読破するのはしんどい。そのため、過去問を解いていてわからないことを辞書的に調べて使う、という方法が様々な方から推奨されているようだ。しかし、私の場合は購入から試験まで比較的時間があったので、少しずつ重要そうなポイントを抑え、軽く読み飛ばしながら読んだ。

一周読んで「この単語みたことあるな」レベルの基礎を作った上で、もう一度通読することで、過去問もある程度解けるようになった。
ポケット攻略本については、合格教本を持ち歩くのが嫌だったので買ったが、あまり使わなかった。

- 4月に入ってから問題（午前）を解き始めた。

おそらくもっと早めに問題に取り組むべきだが、間違え続けると著しくモチベーションが下がる性格なので、ある程度正解できるようになってから解き始めた。午後問題は直前1週間ぐらいで午前の知識の抜け落ちを確認しながら過去問を4年分ぐらい解いた。（どう考えてももっと早く取り組んだ方がいい）

- 過去問を解いている間、どうしても「どこまで詳しく記述すべきか」というところで悩みまくったので、一度解いてみて納得のいく回答ができなかったときは解答を丸写しして「どんな思考プロセスを経由すればよいのか」といったことについて考えた。

- 試験直前の復習のために、わからなかったり間違えたりした項目に付箋を貼っていた。その後、友人が受験するというので教本を貸したところ、「過去問で分からなかったところを調べるのに使ったが、行き着く先にはだいたい付箋が貼ってあったので面白かった」と言われた。n=2なのでなんとも言えないが、他の人がどんな問題を間違えたのか気にしてみるのも良いかもしれない。自分の弱点が見出せるかも。

## 受験直後の感想

午前試験で不合格を確信するレベルで出来が悪かった。昼休みは教本をパラパラめくりながらTwitterを見ていたが、とにかく強そうなおじさんたちの殺伐とした雰囲気に飲まれないのが大事だなと感じた。午後試験は「まあ落ちててもいい経験になるやろ」といった感じの気持ちで受けた。組み込みシステムの問題では以前に読んだIoT/M2Mシステムの本に出てきた事例がほとんどそのまま出てきたので元気が出た。

帰りにご飯を食べて喫茶店にいったところで解答が出てたので自己採点したら、落ちたと思っていた午前に合格していた（結果としては7割ぐらいだった）。
そのまま2ヶ月ぐらい「受かってたらいいな〜」ぐらいの気持ちで過ごしたが、午後試験もまあまあギリギリで合格していた（こちらも7割ぐらい）。

## 最後に

情報処理技術者試験の資格は就職で役に立つか？　といったことをすごく聞かれるのですが、ぼくは就活をしたことがないので知りません。
ただし、応用情報技術者関連の他の様々な記事で書かれてあるように、学生時代はポートフォリオの充実、作品作りをしたほうが伸びるというのも事実だと感じています。

私の場合は、もともと気になっていたセキュリティやらマネジメントやらといった分野がより好きになったので今後の方針決定に役立ちました。
あくまで個人的な意見ですが、自分のやりたいことが明確に決まっている学生はそれについてきちんと勉強してみる方がよいかもしれません。
そうは言っても学生だって人生一度きりなので、資格だろうが作品制作だろうが、やりたいと思ったことをやったらいいと思いました。

-完-
Markdownのテーブルを爆速に書けるエディタを作ったよ～(この手のツールの作り方もまとめた)

# 作ったもの

**table2md**
ExcelライクなテーブルからMarkdownのテーブルにリアルタイムに変換できます。

[ここ](https://hand-dot.github.io/table2md/)からすぐに使えます。
コードは[ここ](https://github.com/hand-dot/table2md)です。


---
# 終わり

これでこの記事終了だとおもしろくないので、
作業過程をさらしたいと思います。

マークダウンを書きたいだけの人はありがとうございました。

--- 

# ツールの作り方

個人的にこの手の改善系のツールの作り方のスムーズなパターンとして定着しつつあるのでまとめてみた。

前提としてReactになってますが悪しからず。

今回のツールは作業時間は2時間くらいで最初のサービスの公開までいけた。
平日の仕事の後でも公開まで行けるはず。

## プロトタイピング→コミット→環境構築

1. [stackblitz](https://stackblitz.com) でgithubと連携してブラウザでプロトタイピングする(大体Reactのテンプレート使うことが多い)
  - codesandboxとかjsfiddleでもいいけど環境構築よりも先にコーディングをして形にする
  - npm install しなくても依存をガンガン入れて動きを試すことができる
  - この段階ではコンポーネントとか下手に分けないほうがいい
2. 動くものや使えるものができたらコミット
3. ローカルのマシンで2をクローン
4. create-react-appで1で作ったコンポーネントをApp.jsに置き換える

---

## 公開


外部に公開したくなったら、

githubでレポジトリのSettingsからGitHub PagesのSourceを`gh-pages branch`に設定

<img width="578" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/eb4a1039-6012-71c0-f38a-a3fb0c8f1a08.png">


package.jsonに下記を追加

```
"homepage": "https://username.github.io/reponame/",
```
scriptsには下記を追加

```
"deploy": "gh-pages -d build"
```

そのあと、

 gh-pagesをインストールしてビルドしてデプロイ

```
$ npm i --save-dev gh-pages
$ npm run build
$ npm run deploy
```

で公開まで行けます。

---


# まとめ

プロトタイピングの段階でうまくいかなかったり、思ったのと違ったってなったりしますので、いちいちレポジトリ作って環境作ってとやるよりも、`stackblitz` ,`codesandbox`,`jsfiddle`とかでコード書いちゃったほうが速いし、思い立った時にカジュアルにツールが作れるのでおススメ。(ちゃんとつくりたいものがある場合は普通に作ったほうがいいと思うけど。)


# 速さは正義
かもしれない
【Swift】PDFKitを使ってみよう

今回はPDFKitを使って簡単にPDFを表示させてみました！

##完成形
PDFとサムネイルが表示されています。
![pdfSample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/1a0b0f1c-0d32-3da6-c3f7-03dd6195b29a.gif)

##0. PDFKitフレームワークの導入
まずはPDFKitフレームワークをプロジェクトに追加します。General > Linked Frameworks and Libraries からプラスボタンを押し、PDFKitと検索してフレームワークを追加します。
<img width="904" alt="スクリーンショット 2019-06-11 14.01.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/961a2214-e876-1ebb-f954-8d201cd62286.png">
<img width="392" alt="スクリーンショット 2019-06-11 14.12.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/bef4d0fb-425c-bc08-7b1d-006db5987c0e.png">

##1. Storyboardの編集
ViewController上にPDFを表示させるためのUIViewとサムネイルを表示させるためのUIViewを配置し、適宜Constrainsをつけておきます。
<img width="875" alt="スクリーンショット 2019-06-11 13.55.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/b7d4329a-71d7-d353-660d-70745e08195c.png">

次に配置したUIViewのカスタムクラスをそれぞれ`PDFView`、`PDFThumbnailView`に変更します。
<img width="255" alt="スクリーンショット 2019-06-11 14.16.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/e7624665-3d0a-adbc-dbac-0b0a644ee059.png">
<img width="258" alt="スクリーンショット 2019-06-11 14.16.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/51b80f4d-00c8-7b38-55cd-e403b5adbafb.png">

##2. コーディング

全体のコードは以下の通りです。
ViewControllerに配置した2つのViewの宣言をした後、関連づけを行います。
`getUrl()`で表示させるPDFのurlを取得し、showPDF()で取得したurlを元にPDFをViewに表示させています。
今回は横方向にスクロールできるようにするために`.displayDirection`を`.horizontal`に設定してあります。

```Swift
import UIKit
import PDFKit

class ViewController: UIViewController {
    
    @IBOutlet weak var pdfView: PDFView!
    @IBOutlet weak var pdfThumbnailView: PDFThumbnailView!
    
    var pdfDocument: PDFDocument!
    var url: URL?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationItem.title = "PDFKit Sample"
        
        getUrl() 
        showPDF()   
    }
    //URLを取得
    func getUrl() {
        if let path = Bundle.main.path(forResource: "pdfSample", ofType: "pdf") {
            url = URL(fileURLWithPath: path)           
        }
    }
    //PDFを表示
    func showPDF() {
        pdfDocument = PDFDocument(url: url!)
        
        //画面サイズに収まるように表示
        pdfView.autoScales = true
        // 単一ページのみ表示
        pdfView.displayMode = .singlePage
        //スクロール方向を水平方向へ
        pdfView.displayDirection = .horizontal
        //余白を入れる
        pdfView.displaysPageBreaks = true
        pdfView.pageBreakMargins = UIEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
        //pageViewControllerを利用して表示(displayModeは無視される)
        pdfView.usePageViewController(true)
        //上で取得したpdfDocumentをdocumentに設定し、表示させる
        pdfView.document = pdfDocument
        
        pdfThumbnailView.layoutMode = .horizontal
        pdfThumbnailView.pdfView = pdfView        
    }
}

```

##おまけ
`.displayDirection`を`.vertical`にするとこんな感じになります。
![ダウンロード (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271820/35164649-6ae1-08bc-1a58-066150bbbb8e.gif)
【Google App Script】 insertImageの削除の覚書


英語がわからない私には全く情報を見つけられず。
マクロを頼って充てがいました。

```javascript:最後の画像を削除
function del_image(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getSheetByName(sname);
  var images = s.getImages();
  var image = images[images.length - 1];
    try {
      image.remove();
    } catch(ex) {
      Logger.log("削除する画像はありません");
    }
}
```

```javascript:シート内画像_全削除
function del_image(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getSheetByName(sname);
  var images = s.getImages();

  for (var i = 0;i < images.length;i++) {
    images[i].remove();
  }
}
```
grep -A (-B) (-C)

-A -B -C それぞれの後に数字がくる 例：grep -A 1
-Aはgrep検索の該当箇所とその後ろの「数字」行の内容を表示する 
-Bはgrep検索の該当箇所とその前の「数字」行の内容を表示する
-Cはgrep検索の該当箇所とその前後の「数字」行の内容を表示する

例：
  grep -A 3 yyy test.html 

test.htmlファイルで"yyy"文字列を検索し、該当箇所の行及びその後ろの3行を表示する
digdagのhttp_callオペレータを動かしてみた

# 概要
digdagの0.9.37で追加された`http_call>`オペレータを動かしたメモ
  
# 前提
digdag 0.9.37

# http_callオペレータとは

[公式ドキュメント](https://docs.digdag.io/operators/http_call.html)より訳

> `http_call>` オペレータはHTTPリクエストを作成し、レスポンスボディをワークフローとしてパースし、サブタスクとして埋め込む。`call>`オペレータと似ている。違う点は、HTTP経由で取得すること。

> Content-Typeヘッダを元にレスポンスボディをパースする。Content-Typeは設定されている必要があり、以下の値がサポートされている。
>   
>  
> - application/json: JSONとしてパース
> - application/x-yaml: レスポンスボディをそのまま使う


> `store_content`というパラメータを除き、`http>`オペレータと同じパラメータがサポートされている。オペレータ名は`http>`と似ているが、役割は違う。 


# 動かしてみた

https://github.com/tosametal/digdag-http_call-sample

↑docker-composeとdigdagがあれば簡単に動作確認出来ます。




`call>`オペレータではプロジェクトを跨いだワークフローの呼び出しは出来ませんが、複数のプロジェクトで共通的に使用したい時は`http_call>`を使うと解決できそうです。
SAP Web IDEでAdaptation Projectが作成できない

#### 概要

openSAPのコース [Evolved Web Apps with SAPUI5](https://open.sap.com/courses/ui52) をやって、Adaptation Projectをオンプレでも試してみようとしたら、

* オンプレのSAPUI5 ABAP Repositoryを選んでもアプリケーションの一覧が表示されない（504接続エラーになる）
* 一覧から選んでも「Adaptation project doesnt support the selected application」というエラーが表示される

な問題が発生したので、対処法を備忘で書く。

#### 解決法

* HANA Cloud ConnectorのCloud To On-Premise＞Resources Accessible On …（サーバー名）に `/sap/bc/ui2`と`/sap/bc/lrep`を追加する。
 * `/sap/bc/ui2`でサーバー選択時のエラーが解消する。
 * `/sap/bc/lrep`でアプリケーション選択時のエラーが解消する。

開発者ツールでエラーになってるパス見つけて通してみただけ。
Cloud Connectorに登録するパスの一覧ってどっかにあるのかな。。


#### 参考
* Adaptation Projectについて→[Adaptation Projects – it’s time for a new way to extend your Fiori Elements applications](https://blogs.sap.com/2018/09/28/adaptation-projects-its-time-for-a-new-way-to-extend-your-fiori-elements-applications/)
About MagicScript build errors (magic-script-cli v2.2.0 and Windows PC)

#In the case of magic-script-cli v.2.2.1 or later, this correspondence is not necessary. 

**Prepare**
Magic Leap One
https://www.magicleap.com/magic-leap-one

mlsdk v.0.2.2.0 
https://creator.magicleap.com/downloads/lumin-sdk/overview

If you apply the following patch, the error will not occur.

1. Check **GLOBAL PATH**.

```sh
npm bin -g
```

2.Edit the following file.

**GLOBAL PATH**\node_modules\magic-script-cli\commands\build.js
(Added shell: true,)

```jsx
13    const proc = spawn('npm', ['install'], { shell: true, stdio: 'inherit' });
```

**Reference**

MagicScript Getting Started
https://www.magicscript.org/docs/getting-started

Thanks!
RailsのView機能のメモ

#RailsのView機能についてのメモです。
Railsの勉強のメモです。
HTMLにはしょうもないことを反映させたほうが覚えが早くなるので悪しからず。。

##文字の表示
コントローラ作成時に出来た、
hello_controller.rb

に新しく関数を作り、表示したい文字を変数に当て込みます。
コントローラ側で当てはめた変数を、テンプレート変数といいます。

```hello_controller.rb
  def view
    @msg = 'こんにちは、ちん棒'
  end
```

hello_controller.rbで当てはめたテンプレート変数を呼び出すのに、
~~html.erb拡張子のファイルを作成します。

```view.html.erb
<div id="main">
<%= @msg -%>
<div/>
```

html.erbファイルで変数を表示させたいときは、

```view.html.erb
<% tinbo = "ちん棒や"-%>
<div>
<%=  tinbo -%>
</div>
```

と書けば表示させることが出来ます。

こんな感じになりました。

![スクリーンショット (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203857/f618e0d4-3a92-b9e7-9e59-21e490ab4040.png)


##検証画面の中身
検証画面で、表示したHTMLを見れば、自分が記述していないコードがたくさん出てきてると思うのですが、どこからきているものなのでしょうか？

application.html.erbを開けば分かります！

```application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Railbook</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

この<yield>に、テンプレートファイルで記述した内容が反映されているみたいですね！！

また、 application.html.erbのことを、レイアウトと呼びます。


レイアウトを利用することで、以下のメリットが得られます。

・サイトデザインを変更する場合も、レイアウトだけを変更すればいい
・個別のテンプレートにはページ固有のコンテンツを記述すればいい
・サイトの構成(ナビゲーションなど)に一貫性ができるため、使い勝手も上昇する。
Nuxt.jsのメソッド内で外部APIを叩くとcorsエラーが起きる

## 環境
nuxt 2.8.1
@nuxtjs/axios: 5.3.6

## 問題

asyncDataだとできるのに

```javascript
asyncData({ app, params, store }) {
    const data = {key: "value"}
    return app.$axios.$post([URL], data
    ).then(res => {
      console.log(res)
    })
  },

```

普通のメソッドだとできない

```javascript
getData: function(data) {
      const res = this.$axios.$post([URL], data
      ).catch(error => {
        console.log(error)
      })
      
      
//結果
// Access to XMLHttpRequest at [URL] from origin 'http://localhost:3000' has been blocked by CORS policy: 
// Response to preflight request doesn't pass access control check: 
// No 'Access-Control-Allow-Origin' header is present on the requested resource.      
```

### 理由：
asyncData() では、SSRにより表示を行うため、Proxyを挟まなくてもデータを取得できるため。

[参考にした記事](https://qiita.com/FrozenVoice/items/2ae814be437eaa492579#ssr%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A7%E3%81%AE%E9%80%9A%E4%BF%A1)

SSR(ServerSideRendering)についてはこちらの記事が参考になりました。
[React での ServerSideRendering 入門](https://qiita.com/euxn23/items/10d051c62e7b2160f4fc)

## 解決方法
**Proxyを導入しました。**
@nuxtjs/axiosにある機能を使用し、以下の設定をした後、全てのエンドポイントの冒頭に **/api/** をつけました。



```nuxt.config.js
...
modules: [
    '@nuxtjs/axios'
  ],

  axios: {
    proxy: true
  },
  proxy: {
    '/api/': {target: 'YOUR API URL', pathRewrite: {'^/api/': '/'}}
  },
  plugins: [
    { src: 'plugins/axios.js', ssr: false }
  ],
...
```

```plugins/axios.js
export default function({ $axios, redirect }) {
  $axios.setToken('access_token')

  $axios.onResponse(config => {
    $axios.setHeader('Access-Control-Allow-Origin', 'YOUR API URL')
  })
}
```

【参考記事】

- [nuxt.js で axios から外部APIを叩くとCORSエラーを解決](https://qiita.com/penton310/items/4312ddbe015476fd67ff)
- [Axios Module](https://axios.nuxtjs.org/options#proxy)
超初心者が受けるJS社内勉強会：第１回

「JS（プログラミング）なんて大っ嫌いだぁああああ!!!!!!!!!!!!!!!!」と言い続けて早●●年。
すでに諦めかけていた私にとうとう見かねたのか、社内勉強会なるものを開催してくれました。（終了回数未定）
せっかくなので、メモを公開していこうと思います。

##Java Scriptとは？
- HTML文書の「ふるまい」を担当する言語
- ECMA Scriptがもとになっている言語

### ブラウザ対応状況
- ES2019 (ES7)　javascriptの仕様が変わっていく。先に言語がアップグレードされるので、最新の言語に対応するブラウザは少ない。ブラウザの方が後追いしている。
- EdgeはChromiumベースになる。

### 型演算
- `1 == "1"`  「１」が文字列として区別されるようにするには、`1 === "1"`　とイコールを３つにする
`=` が２つの時は、比較する　、1つの時は代入する。
- `this` の使い方は様々（スコープによって変化する）なので注意が必要。

### 使いづらさを解消するための中間言語
#### altJS
- Javascriptの使いづらさを解消したもの。実行には、Javascriptのコンパイルが必要。

### Node.js
- サーバーサイドで動かすjavascript。

### jQuery
- JSの記述を容易にするためのライブラリ。ブラウザごとの実装の違いを吸収できるため、ブラウザごとの対応が必要ない。
- 画面単位では、違うバージョンを読むことは可能。書き方はバージョンによって違うので、共通のjsはコピーする必要がある。

#### jQueryでできること
- DOMの操作。（追加削除変更）
- イベント処理（ボタンクリック）
- エフェクト・アニメーション
- Ajax　非同期通信
- ユーティリティ

### Ajax
- 同期→全部の情報をサーバーから取得する
- 非同期→一部分だけ（取得したいHTML）を取得できるような処理をサーバー側においておき、部分的に取得する処理をjsでできる。

### jQuery は$を作る
#### 変数
- よくある箱の説明。
- セミコロンで終わる（省略できる）。改行されるとセミコロンの扱いと同じくなる場合がある。
- 文字列は　`''`　でくくる。`""`　も可。
- 値の種類・・・数字、文字列

ここまでで既に脳に拒否反応が現れそうでしたが、第２回も開催が予定されてますので、脳を鍛えたいと思います！

[超初心者が受けるJS社内勉強会：第2回](https://qiita.com/m_hamada/items/3e83a39d7dd86b403346)
php-master-changes 2019-06-10

今日は Azure Pipelines の設定への Mac 用のビルド設定追加、各 sapi モジュールのバージョン指定箇所の修正、.editorconfig の整理、テストの修正、opcache の 32 ビット版でのアライメント修正、BIND_LEXICAL の行番号がおかしかった問題の修正、VM の局所最適化の修正があった！

# 2019-06-10
## Stricted: azure macos
- https://github.com/php/php-src/commit/0741494f302ea7982d3250d4b86338667a830749
- [7.4~]
- Azure Pipelines の設定で、Mac 用のビルド設定を追記

## petk: Use PHP_VERSION for zend modules
- https://github.com/php/php-src/commit/5b36c9fef6a03246765d10ea77ad6a68d2843cb6
- 各 sapi モジュールで、zend_module_entry のバージョン指定箇所で NULL だの NO_VERSION_YET だのが指定されていた箇所を PHP_VERSION に修正

## petk: Simplify LiteSpeed SAPI module version
- https://github.com/php/php-src/commit/2dd6ec07d1e098e109412c1cc3099f52a1b17b88
- sapi/litespeed で、sapi_module_struct のモジュール名に自前で V7.3.2 などと付けていたのを消した

## petk: Extend wildcard files section in EditorConfig [ci skip]
- https://github.com/php/php-src/commit/65ada393602ad6125928c33a5c18dd05c84c29fa
- [7.2~]
- .editorconfig のワイルドカード指定を整理

## krakjoe: fix flaky ipv4 loopback test
- https://github.com/php/php-src/commit/52ca8ca7d570dc3b37f8bd03264a4c249f487a33
- [7.4~]
- ext/sockets で、一定範囲で頑張って開いてるポートを探そうとする怪しいテストでポート 0 を使うよう修正

## dstogov: Fixed possible misalignment in 32-bit build.
- https://github.com/php/php-src/commit/199eb2b110aa57c423bada077f6c9e71c5d17daf
- [7.2~]
- ext/opcache で、32 ビット版だとアライメントずれてたかもなコードを修正

## krakjoe: BIND_LEXICAL has a meaningless line number
- https://github.com/php/php-src/commit/42d60addef7c9a8979529fae55ea2b22ee2c3ae6
- [7.4~]
- BIND_LEXICAL の行番号がおかしかった問題の修正

## krakjoe: watchpoints have flaws in implementation
- https://github.com/php/php-src/commit/1e5004060e9e7c3623c863c9b2339678d0f2dc9b
- [7.4~]
- sapi/phpdbg で、watchpoints の実装がなんか壊れてるらしく一旦テストに XFAIL を付けている

## dstogov: micro-optimization
- https://github.com/php/php-src/commit/374f7699821eb723a3a82a9854d18c0530b9d4e9
- VM の局所最適化
- LOAD_OPLINE() してた箇所が LOAD_OPLINE_EX() と SAVE_OPLINE_EX() に分かれてるので、ZEND_VM_IP_GLOBAL_REG に応じ `opline = EX(opline)` したりしなかったりの違いが出てる
- とはいえ VM のレジスタ割り当ての都合まで見ても分からんねんという気持ちでいる
Escキーの無効化

WindowsでEscキーを無効化するために変更したレジストリのメモ

・レジストリエディタを開く
  ファイル名を指定して実行 → Win+R
  レジストリエディタを開く → regedit

・対象レジストリを開く
  HKEY_LOCAL_MACHINE¥SYSTEM¥CurrentControlSet¥Control¥Keyboard Layout

・Scancode Mapを新規作成する
  右クリック → 「新規」 → 「バイナリ値」 → 「Scancode Map」

・値の入力
0000  00 00 00 00 00 00 00 00
0008  02 00 00 00 00 00 01 00
0010  00 00 00 00

  先頭16個：ヘッダー（0で固定）
   次の8個：キーの個数（ターミネータを含む）
   次の4個：変更後のScancode（無効にするため0）
   次の4個：変更前のScancode（Escのコード01）
   次の8個：ターミネータ（0で固定）

・再起動して変更を反映
Magic Leap MagicScript About debugging using the web inspector with Google Chrome.

#In the case of magic-script-cli v.2.2.1 or later, this correspondence is not necessary. 

**Prepare**
Magic Leap One (Lumin OS v0.96.1)
https://www.magicleap.com/magic-leap-one

mlsdk v.0.21.0
https://creator.magicleap.com/downloads/lumin-sdk/overview

magic-script-cli v2.2.0 [patch](https://qiita.com/tokufxug/items/2827b2ef644b3a213695)
https://www.npmjs.com/package/magic-script-cli

**Example Code**

Change app.js
Web inspector can not debug without overriding updateLoop.

```jsx
export class App extends LandscapeApp {
  onAppStart () {
     ...  
  }
  
  // Known Issues: Web Inspector does not work unless the updateLoop function is present in source
  updateLoop(delta) {
    return true;
  }
}
```

**Build**

```sh
magic-script build -i
```

**Run**

```sh
magic-script run --port=10000
```

**Reference**

MagicScript Inspector Client
https://www.magicscript.org/docs/inspector-client

Lumin OS v 0.96.0 Release Note
https://creator.magicleap.com/learn/guides/lumin-os-0-96-0-release-notes

Thanks!
PowerShell で「tail -f」を実現する。

前提条件：Windows PowerShell
バージョン：3.0以上

PowerSHellにてLinuxコマンドでいうtail -f を実現したいこともあるでしょう。
（例えばサービスが起動しないがどのようなエラーがログに出るのか、など）
下記の方法で可能です。

```powershell

　Get-Content -Path ファイル名 -Encoding "UTF8" -Tail 0 -Wait
```
※ポイントはエンコードをUTF8にしてあげること。
ElasticsearchとKibanaが起動しなくなる問題への対処法

ElasricsearchとKibanaが急に起動しなくなる問題が発生することがあったので、対処法を記しておきます。
同じ問題に見舞われた方は試してみてください。
なお、日本語analyzerプラグインのanalysis-kuromojiを導入している方向けです。

#対処法
アップデートをした時に、突然起動しなくなる問題の時は、プラグインanalysis-kuromojiが原因になっている可能性があります。再インストールしてみましょう。

```console

$ sudo -s
# cd /usr/share/elasticsearch
# bin/elasticsearch-plugin remove analysis-kuromoji #analysis-kuromojiの削除
# bin/elasticsearch-plugin install analysis-kuromoji #analysis-kuromojiのインストール
# service elasticsearch start #elasticsearchの起動
# service kibana start #kibanaの起動
```

Elasticsearch( http://localhost:9200 )とKibana( http://localhost:5601 )にアクセスして、起動していればOK(起動には時間がかかる場合あり)


macの場合でも対応したディレクトリで同様の手順を行えば、対処できます。
※最近のアップデートでは、この問題は起こらないようになっていますが、もし起こればプラグインが原因になっていることを疑ってみると解消できるかもしれません。