OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift] UITextViewに画像を添付する方法

# はじめに

[GameWith AdventCalendar 2019](https://qiita.com/advent-calendar/2019/gamewith) の14日目の記事になります。

普段はiOSエンジニアをやっていて、最近はWebの業務を行なっているのでその辺りについても来週のアドベントカレンダーで話したいと思います。

今回の記事では`UITextView`に`NSTextAttachment`クラスを用いて画像を添付する方法をまとめています。
入力中の文字のpositionなどを取得して、その上下に`UIImageView`を配置するなどといった事をしなくても簡単に実装できるので具体例をまじえて紹介したいと思います。

# 具体例

SNSサービスなどでカメラロールから画像を選択し、テキストと一緒に投稿などを行う場合のUIイメージを想定しています。

## カメラロールから画像を取得

シンプルに`UIImagePickerController`を使うケースです。

```swift
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
```

## UIImagePickerControllerDelegateを設定する

```swift
extension SampleViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[.originalImage] as? UIImage {
            
            let fullString = NSMutableAttributedString(string: textView.text)
            
            let imageWidth = image.size.width
            // 画像の幅を調整したい場合paddingなどをframeから引く
            let padding: CGFloat = 16

            let scaleFactor = imageWidth / (textView.frame.size.width - padding)
            
            let imageAttachment = NSTextAttachment()
            imageAttachment.image = UIImage(cgImage: image.cgImage!, scale: scaleFactor, orientation: .up)
            
            let imageString = NSAttributedString(attachment: imageAttachment)
            fullString.append(imageString)
            
            // TextViewに画像を含んだテキストをセット
            textView.attributedText = fullString
        } 
        dismiss(animated: true, completion: nil)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
    
}
```

# 終わりに

[NSTextAttachment](https://developer.apple.com/documentation/uikit/nstextattachment)

今回利用している `NSTextAttachment` ですが、こちらを使う事で`UILabel`にも画像を適用する事ができるので非常に便利なクラスになっています。
今後文字と画像を結合するUIを実装する際には是非使ってみてください！
FormDataって何？ゼロから解説

jQueryを使ったAjaxの実装をしていてよく分からなくなってしまったのでまとめます。

##FormDataって何？

>FormData オブジェクトは、XMLHttpRequest を使用して送信するためのキーと値のペアのセットを収集可能にします。本来はフォームデータの送信に使用することを想定していましたが、キーのついたデータを伝送するためにフォームとは独立して使用することもできます。
[Mozillaのサイトより(FormData オブジェクトの利用)](https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects)

これだけではよく分からないので、ひとつひとつ読んでいきます。

>> FormData オブジェクトは、XMLHttpRequest を使用して送信するためのキーと値のペアのセットを収集可能にします。

　XMLHttpRequestとはブラウザ上から[Http通信](https://qiita.com/belion_freee/items/5ad1c9c0eefebea0957d)を行うための[API](https://www.sejuku.net/blog/7087)です。 XMLとはマークアップ言語のひとつで、データの受け渡しを分かりやすくするために使われます。で、このXMLの形式を用いて「キーと値のペアのセット」とやらを収集する訳ですね。実際に書いてみるとこんな感じになります。それぞれのキー（左側）に対して値（右側）が存在していることが分かりますね。それぞれのキーの詳細については[このサイト](http://semooh.jp/jquery/api/ajax/jQuery.ajax/options/)が詳しいです(jQueryのAjaxに渡すkey valueについてのサイトですが、FormDataと同様のkey valueについて記述があり、参考になると思います)。
    
      $.ajax({
      type: 'GET',
      url: '/hoge/fuga',
      data: fd,
      processData: false,
      contentType: false,
      dataType: 'json'
    })

　実際に書く時はこれの前にnew FormDataをしてあげましょう。
    
  ```var fd = new FormData($('.hogefuga_form').get(0))```

>> 本来はフォームデータの送信に使用することを想定していましたが、キーのついたデータを伝送するためにフォームとは独立して使用することもできます。

元々HTMLのformタグから取得したデータを送ることを目的に作られたようですね。ただformとは別にちゃんと指定してあげればもちろんform外のデータも送信できます。
【今さら極める VB6 -Part 1】文字列連結の100倍高速化（VB6 版 StringBuilder）

`ADODB.Stream` クラスの `WriteText` メソッドを使用することにより、文字列の連結を高速に行うことができます。

# 手法と技術的背景

## 文字列連携のパフォーマンス

`String` はイミュータブル（不変）であり、生成後に値を変更できないため、文字列を連結する際は新たにインスタンスを生成することになります。
`String` の連結を繰り返すとメモリを消費し、処理速度が大きく低下するため、.NET では変更可能な文字列クラス `StringBuilder` の使用が推奨されています。
VB6 にはこれに相当するクラスが用意されていませんので、自前で作りました。

## ADO によるストリームアクセス

ADO（Microsoft ActiveX Data Objects）は、古くは MDAC（Microsoft Data Access Components）、Vista 以降は Windows DAC（Windows Data Access Components）の一部として、Windows OS に含まれています。
VB6 でデータベースにアクセスする際の標準的なライブラリとして広く使用されていますが、「[ADO の基礎](https://docs.microsoft.com/ja-jp/sql/ado/guide/data/ado-fundamentals)」に列挙されているように、データベース以外の「データソース」も扱うことができるように設計、実装されています。
`ADODB.Stream` クラスは、一般的にはファイルアクセスに使用することが多いと思いますが、メモリ内で使用することもできます。

# 改善例
#### ケース
20文字 × 10,000行 を行ごとに連結
#### 処理時間
40秒 → 0.4秒（100倍高速化）

# 使用イメージ

下記 `StringBuilder` クラスを使って、
`sLines = sLines & "Line" & vbCrLf`
に相当する処理を
`sb.AppendLine("Line")`
のように記述し、`ToString()` で連結後の文字列を取得することができます。

```vb:変数宣言する場合
Dim sb As StringBuilder
Set sb = New StringBuilder
Call sb.Append("変数")
Call sb.AppendLine("を使います")
Debug.Print sb.ToString()
```

```vb:Withブロックで使用する場合
With New StringBuilder
    Call .Append("With ブロック")
    Call .AppendLine("を使います")
    Debug.Print .ToString()
End With
```

# VB6 版 StringBuilder クラスのソースコード

```vb:StringBuilder.cls
Option Explicit

'改行文字
Public Enum LineSeparatorsEnum
    adCR = 13
    adCRLF = -1
    adLF = 10
End Enum

'ストリームオブジェクト
Private mStream As Object 'ADODB.Stream

'改行文字　※既定は CR+LF
Public Property Get LineSeparator() As LineSeparatorsEnum
    LineSeparator = mStream.LineSeparator
End Property
Public Property Let LineSeparator(ByVal e As LineSeparatorsEnum)
    mStream.LineSeparator = e
End Property
 
'文字列の長さ
Public Property Get Length() As Long
    If mStream.Size <= 0 Then
        Length = mStream.Size
    Else
        'Len(ToString()) だと遅い。
        'UTF-16 なので1文字2バイトと換算。Len 関数同様、サロゲートペアには対応していない。
        Length = (mStream.Size / 2) - Len(vbNullChar)
    End If
End Property

'コンストラクタ
Private Sub Class_Initialize()
     
    Set mStream = CreateObject("ADODB.Stream")
    mStream.Type = 2 'adTypeText
    LineSeparator = adCRLF
    'Charset は既定の "Unicode"（UTF-16）
    
    Call mStream.Open
     
End Sub

'文字列を追加する。
Public Function Append(ByVal s As String) As StringBuilder
     
    Call mStream.WriteText(s, 0) 'adWriteChar
    
    Set Append = Me
     
End Function

'改行付で文字列を追加する。
Public Function AppendLine(Optional ByVal s As String = "") As StringBuilder
     
    Call mStream.WriteText(s, 1) 'adWriteLine
    
    Set AppendLine = Me
     
End Function

'文字列化する。
Public Function ToString() As String
     
    mStream.Position = 0
    ToString = mStream.ReadText()
    mStream.Position = mStream.Size
     
End Function

'デストラクタ
Private Sub Class_Terminate()
     
    Call mStream.Close
     
End Sub
```

---
これで終わりません。
翌日公開の [Part 2](https://qiita.com/CodeOne/items/0d09948d5a4a1e98d001) に続きます。
Akka HTTPでメンテナンス時のレスポンスを制御する

サブスクリプションの管理SaaSを提供しているアルプ株式会社でエンジニアをしています、[@showmant](https://twitter.com/showmant_) です。
これは[Scala Advent Calendar 2019](https://qiita.com/advent-calendar/2019/scala) 14日目のエントリです。

#はじめに
サービスを運用していると、場合によってはサービスを停止し、メンテナンス時間を入れることがあると思います。
今回はAkka HTTPで運用しているアプリケーションのメンテナンス時のハンドリングについて簡単にご紹介させてください。

# ユースケース
メンテナンス時に`メンテナンス中`であることをクライアントに返却する

# やりたいこと
- confの切り替えによってメンテナンス中か否かを制御したい
    - これにより、ある程度柔軟にメンテナンスモードに入ることができる
- [RejectionHandler](https://doc.akka.io/docs/akka-http/current/routing-dsl/rejections.html#the-rejectionhandler)を使ってレスポンス制御したい
    - Routingをシンプルにし、RejctionHandlerにロジックを集中することで、Routingが間違っていて事故が起こるようなことを避けたい

# 実装

## Custom Rejection の実装
標準でもAuthのRejectionをはじめ、いくつものRejectionを搭載していますが、今回はカスタムのRejectionクラスを作ってみます。作り方はRejectionを継承すればいいだけですので、簡単です。

```scala
import akka.http.scaladsl.server.Rejection

case object MaintenanceRejection        extends Rejection
final case class MaintenanceRejection() extends Rejection
```

## Rejection Handlerの実装
[RejectionHandler](https://doc.akka.io/docs/akka-http/current/routing-dsl/rejections.html#the-rejectionhandler)は ドキュメントのサンプルのように書けばいいのですね。 もちろん `entity` の部分をJSONレスポンスに変更したりもできます。

```scala
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import sample.akkaHttp.MaintenanceRejection

RejectionHandler.newBuilder()
  .handle{
    case MaintenanceRejection =>
      complete(HttpResponse(ServiceUnavailable, entity = "メンテナンス中です"))
  }
  //他のRejectionの制御方法をここに追加していけばよい
  .handleNotFound { complete((NotFound, "Not here!")) }
  .result()
```

## Routingの実装

Routingでどのような条件分岐で`reject` をするかはプロダクトによって大きく変わってくると思います。例えば、hcは通すけど、それ以外はメンテナンスモードにいれる、というようなこともあると思います。
今回は本題に集中するため、それらは省いてシンプルにメンテナンスモードの`ON/OFF`で分岐する実装をサンプルとしました。


```scala
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import sample.MaintenanceRejection

class SampleRouter(
  conf: SampleConf
) {
  override def routes: Route =
    extract(ctx => ctx.request) { request =>
      if (conf.isInMaitenance) reject(MaintenanceRejection)
      else ??? //メンテナンスモードでなければこちらでハンドリングする
    }
}
```

## サーバーの実装

最後にサーバー立ち上げ時に、`RejectionHandler`の読み込みと、`Routing` を差し込めばOKです。


```scala

object SampleApiServer extends App {
  implicit val system       = ActorSystem()
  implicit val materializer = ActorMaterializer()
  implicit def myRejectionHandler =
    RejectionHandler
      .newBuilder()
      .handle {
        case MaintenanceRejection =>
          complete(HttpResponse(ServiceUnavailable, entity = "メンテナンス中です"))
      }
      //他のRejectionの制御方法をここに追加していけばよい
      .handleNotFound { complete((NotFound, "Not here!")) }
      .result()
  val route = (new SampleRouter).routes

  Http().bindAndHandle(route, "localhost", 9000)

}
```

# おわりに
実際のプロダクトでは、特にRoutingをどのようにわけるか、他のRejectionが一緒に積まれた場合はどうするかなど、考えるべきことがもう少しあるかのように思います。
記事を書き始めると意外とシンプルであまり中身がない感じになってしまいましたが、どなたかの参考になれば幸いです。

あしたは @grimrose@github さんです！
WIndows 10 1909でMicrosoft IME以外のSKK日本語入力FEP等を規定の入力にできない問題


# 背景
[SKK日本語入力FEP](http://coexe.web.fc2.com/skkfep.html) を新規でインストールしようとしたところ、インストールは成功しますが、デフォルトの設定として正しく出来ませんでした。
Microsoft IME以外のATOK等の入力ソフトを使用する場合に同様の問題が発生する可能性があります。

# 環境
Windows10 Pro 1909

# 現象
1. SKK日本語入力FEPをインストール
2. SKK日本語入力FEPに切り替え
3. Windowsの**キーボード詳細設定**で **規定の入力方式の上書き** にて **日本語 - SKKFEP** に設定
4. Windows 再起動
5. Microsoft IMEに自動的に戻ってしまう
6. Windowsの**キーボード詳細設定**では **規定の入力方式の上書き** では **日本語 - SKKFEP**のままである 
7. 再度画面上でSKK日本語入力FEPに切りかえても再起動するとMicrosoft IMEに戻る

# 試した事
1. [公式](http://coexe.web.fc2.com/programs.html)にある**Windows 10の無償アップグレードや大規模更新の後、動作がおかしくなった場合の対処方法** を試しましたが駄目でした。

> 1. 最新版のセットアップを実行し「アンインストール」を選択。再起動を促すメッセージをガン無視して次に進む (再起動してもOK)
> 2. 続けざまに「インストール」を選択。「新しいキーボードをインストールしています」とシステムメッセージが出れば完了 (ここで再起動を推奨)
> 3. 何も出ない時は再度セットアップを実行し「入力方式」を選択。「言語の設定の変更」の右端の「オプション」を押し、「入力方式」の下の「入力方式の追加」を押して追加

2. Windowsの**キーボード詳細設定** で **規定の入力方式の上書き** を設定しなおしても現象はかわりません。

#他の環境での事例
検索してみるとやはりATOK等で色々とあります。
しかし以下の情報を試してみましたが解消しませんでした。

- ジャストシステムの情報
http://support.justsystems.com/faq/1032/app/servlet/qadoc?QID=026460

- MicrosoftのQA情報
https://support.microsoft.com/ja-jp/help/4027670/windows-10-add-and-switch-input-and-display-language-preferences

# 解決策
色々試してみましたが、以下で解消致しました。
どうも画面上は設定出来ていても内部的に反映されていない為、一度削除して再設定が必要のようです。
でも設定の画面上はSKKFEPに変更されているように見えています。
**日本語 - 使用できない入力方式**になってしまう場合の条件がわからないのですが、私の環境では100%発生していました。

1. 一旦SKK日本語入力FEPのインストーラでアンインストールする
2. Windowsの設定画面で **時刻と言語** から 言語の**「常に規定として使用する入力方式を選択する」**のリンクをクリック
3. **規定の入力方式の上書き** で以下を変更する
**日本語 - 使用できない入力方式** → **言語リストを使用します(推奨)**

4. インストーラで再インストールする
5. Windowsの設定画面で **時刻と言語** から 言語の **常に規定として使用する入力方式を選択する** のリンクをクリック
6. **規定の入力方式の上書き** で以下を変更する
**言語リストを使用します(推奨)** → **日本語 - SKKFEP**

新規インストールの時には毎回これをやらないと反映されないようです。

# 愚痴
Windowsで社外品 の日本語入力の設定ってアップデートの度に色々問題が出ますね。

#最後に
SKKはいいですよ。ファンクションキーを使わないのでHHKでも万全。
とくにSKK日本語入力FEPは[サイト](http://coexe.web.fc2.com/skkfep.html)からして情熱がたまらない。
yarn link実行後、cliでコマンドを入力してもPermission deniedになる場合

# 実行環境
- node: v12.13.1
- yarn: 1.19.2

自前で作成したcliツールをローカルで試したい場合、`yarn link` を使用しますが、Permission deniedで実行できないことがあるようです。

```bash
$ yarn link
$ パッケージ名
bash: /usr/local/bin/パッケージ名: Permission denied
```

実行権限を付与する必要があるとのこと。

```bash
$ chmod +x /usr/local/bin/パッケージ名
```

で実行可能になる。
JavaScriptで1を31ビット左シフトするとマイナスになる

JavaScript で `2^32` の値が必要になりました。そこで、`1 << 32` を計算したところ、`1` になってしまいました。試しに `1 << 31` を計算してみると、`-2147483648` と負の値が返ることがわかりました。

以下のコードを書いてみると、`1 << 30` までは期待通りの結果が得られているようですが、`1 << 30` より大きい値は変な結果になってしまいました。

```javascript
for (let i = 1; i <= 32; i++) {
    console.log(`1 << ${i}: ${1 << i}`);
}

console.log("1 << 32 << 32 << 32 << 32:", 1 << 32 << 32 << 32 << 32);
```
```
1 << 1: 2
1 << 2: 4
1 << 3: 8
1 << 4: 16
1 << 5: 32
1 << 6: 64
1 << 7: 128
1 << 8: 256
1 << 9: 512
1 << 10: 1024
1 << 11: 2048
1 << 12: 4096
1 << 13: 8192
1 << 14: 16384
1 << 15: 32768
1 << 16: 65536
1 << 17: 131072
1 << 18: 262144
1 << 19: 524288
1 << 20: 1048576
1 << 21: 2097152
1 << 22: 4194304
1 << 23: 8388608
1 << 24: 16777216
1 << 25: 33554432
1 << 26: 67108864
1 << 27: 134217728
1 << 28: 268435456
1 << 29: 536870912
1 << 30: 1073741824
1 << 31: -2147483648
1 << 32: 1
1 << 32 << 32 << 32 << 32: 1
```
[Wandboxで実行する](https://wandbox.org/permlink/GMjgmIrSD5EmBuo0)

# 原因
JavaScript ではビット演算は符号付き 32 ビット演算で行われます。

`1 << 30` は

```javascript
1 << 30 = 0b010000000000000000000000000000000
```

であり、 `2147483648` と解釈されますが、`1 << 31` は

```javascript
1 << 31 = 0b100000000000000000000000000000000
```

となります。ここで、負の値は 2 の補数形式で表現されることに注意しましょう。最上位ビットが 1 のときは、負の値であることを表します。よって、 `1 << 31` は `-2147483648` と解釈されます。また、ビット演算は 31 ビットシフトまでしかサポートされていないようです。そのため、`1 << 32` も正しく計算できませんでした。

> ビット演算子 - JavaScript | MDN
> https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

JavaScript の数値型は大きな値も保持できる [^js-max] ので適当にビットシフトしても大丈夫だろうと考えていましたが、大丈夫ではありませんでした...。

[^js-max]: `2 ^ 1024` まで保持できます: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_VALUE


# 対策
べき乗演算子 `**` を使いましょう。`2 ** 32` (`1 << 32`)  も正しく計算できます。

```javascript
for (let i = 1; i <= 32; i++) {
    console.log(`2 ** ${i}: ${2 ** i}`);
}
```

```
2 ** 1: 2
2 ** 2: 4
2 ** 3: 8
2 ** 4: 16
2 ** 5: 32
2 ** 6: 64
2 ** 7: 128
2 ** 8: 256
2 ** 9: 512
2 ** 10: 1024
2 ** 11: 2048
2 ** 12: 4096
2 ** 13: 8192
2 ** 14: 16384
2 ** 15: 32768
2 ** 16: 65536
2 ** 17: 131072
2 ** 18: 262144
2 ** 19: 524288
2 ** 20: 1048576
2 ** 21: 2097152
2 ** 22: 4194304
2 ** 23: 8388608
2 ** 24: 16777216
2 ** 25: 33554432
2 ** 26: 67108864
2 ** 27: 134217728
2 ** 28: 268435456
2 ** 29: 536870912
2 ** 30: 1073741824
2 ** 31: 2147483648
2 ** 32: 4294967296
```

[Wandboxで実行する](https://wandbox.org/permlink/2lXKPfHsJhMq3SUO)


# C++ では？
ちなみに、C++ でも試したのですが、`1 << 31` は JavaScript と同様に `-2147483648` になってしまいます！

```cpp
#include <iostream>

int main()
{
    long long i = 1 << 31;
    std::cout << i << std::endl;
}
```
```
-2147483648
```
[Wandboxで実行する](https://wandbox.org/permlink/n9pMhLCic2Cqf2OS)

これは整数リテラル `1` が `int` 型であり、32 ビット符号付き整数型のためです。きちんと `long long` 型であることを明示しましょう。

```cpp
#include <iostream>

int main()
{
    long long i = 1 << 31;
    std::cout << i << std::endl;
    
    long long j = 1L << 31;
    std::cout << j << std::endl;
}
```
```
-2147483648
2147483648
```
[Wandboxで実行する](https://wandbox.org/permlink/BownHfh3sWSkrq9v)
prerender-spa-pluginでogp対応

# prerender-spa-plugin

SPAをプリレンダリングして事前に各ページのhtmlを作って動的なOGPに対応する方法としては[rendertron](https://github.com/GoogleChrome/rendertron)、[prerender.io](https://prerender.io/)、[netlify](https://docs.netlify.com/site-deploys/post-processing/prerendering/) などいろんな外部サービスがあるが、ページ数の少ないSPAの場合は、[prerender-spa-plugin](https://github.com/chrisvfritz/prerender-spa-plugin) を使うのが一番お手軽だった。

使い方もwebpackに以下のような設定を入れておくだけ。

```js
const PrerenderSPAPlugin = require("prerender-spa-plugin");
const path = require("path");

module.exports = (config, env) => {
  if (env === "production") {
    config.plugins = config.plugins.concat([
      new PrerenderSPAPlugin({
        routes: ["/", "/sign-in"], // 事前にレンダリングしておきたいページ
        staticDir: path.join(__dirname, "build")
      })
    ]);
  }

  return config;
};
```

このwebpackの設定をしている状態でビルドを行うと、以下のような感じで各ページごとにhtmlが吐き出される。

```
build
├── index.html
├── sign-in
│   └── index.html
```

あとは[react-helmet](https://github.com/nfl/react-helmet)などを使って各ページにmetaタグを入れておけば動的にogpが変わるようになる。

# 動作確認

動的にOGPが変わることをローカル環境で確認したい場合は、
1) まずビルド行なう
2) [web-server-for-chrome](https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=ja&)や、[serve](https://github.com/zeit/serve)などを使ってビルド後のファイルが格納されているディレクトリを対象にサーバーを立てる。
3) [ngrok](https://ngrok.com/)を使って 2 で立てたサーバーを外部公開する
4) https://metatags.io/ などのogpが確認できるサイトに 3 で生成されたurlを貼り付ける。

をすれば確認できる。

# ci

`prerender-spa-plugin` は `puppeteer` を使っているのでcircle ci上などでビルドしている場合は `puppeteer` のインストールも必要。
https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md#running-puppeteer-on-circleci

インストールしていない状態でビルドすると以下のようなエラーが出る。

```terminal
Creating an optimized production build...
Error: Failed to launch chrome!
/home/circleci/repo/node_modules/puppeteer/.local-chromium/linux-686378/chrome-linux/chrome: error while loading shared libraries: libXtst.so.6: cannot open shared object file: No such file or directory

TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
```

トラブルシューティングの説明にもあるように、以下のようなpuppeteerをインストールするコマンドを定義し、実行しておけば上記エラーは解消された。

```yml:.circleci/config.yml
commands:
  puppeteer_install:
    description: Install puppeteer and headless chrome
    steps:
      - run:
          name: Install Headless Chrome dependencies
          command: |
            sudo apt-get install -yq \
            gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
            libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
            libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
            libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
            fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
      - run:
          name: Install puppeteer with chronium
          command: |
            yarn add puppeteer
```



prerender-spa-pluginはページが多いようなSPAだと不向きだが、個人で作ってるようなページ数が少ないSPAで使うなら必要十分なんじゃないかと感じた。
Siv3DでDiscord Webhookのクライアントを作ってみた話

# 作ったもの
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/OpenSiv3D?src=hash&amp;ref_src=twsrc%5Etfw">#OpenSiv3D</a> <a href="https://twitter.com/hashtag/Discord?src=hash&amp;ref_src=twsrc%5Etfw">#Discord</a> <br>OpenSiv3Dで簡単なDiscordのWebhookクライアントを作った。<br>今の所テキストを送信するぐらいしかできない。<br>通信はcurllibを使用している。 <a href="https://t.co/J1rwlyBZMv">pic.twitter.com/J1rwlyBZMv</a></p>&mdash; ほた (@hota1024) <a href="https://twitter.com/hota1024/status/1201208594240176128?ref_src=twsrc%5Etfw">December 1, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ソースコードはここです：<https://github.com/hota1024/discord-webhook-test-with-opensiv3d>

# Discord Webhookとは
ゲーマー向けのチャットサービスである[Discord](https://discordapp.com)にはWebhookという機能があります。
Webhookを使うとボットを作らなくてもWebhookのURLにPOSTリクエストを投げることでDiscordのチャットにメッセージを送ることができます。

また例として、GithubとDiscord Webookを連携させることもできます。

> `git push origin master`した時のスクショ。
> 参考：<https://support.discordapp.com/hc/ja/articles/228383668-タイトル-Webhooksへの序章>
> <img width="430" alt="スクリーンショット 2019-12-14 20.10.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154299/047b2952-d435-4ceb-cec2-81ce08c43414.png">

# C++でHTTP
今回C++でHTTP通信を行うために`curllib`を使用しました。

```main.cpp
// POSTリクエストを送る例
# include <curl/curl.h>

int main()
{
  // curl の初期化
  CURL *curl;
  curl = curl_easy_init();

  // curl の設定
  curl_easy_setopt(curl, CURLOPT_POST, 1); // メソッドをPOSTに設定
  curl_easy_setopt(curl, CURLOPT_URL, "<URL>"); // URLを設定
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "<POST_DATA>"); // データを設定
  curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L); // データのサイズを指定

  // 送信
  curl_easy_perform(curl);

  // クリーンアップ
  curl_easy_cleanup(curl);

  return 0;
}
```

# 今回の詰まった&詰まっているポイント
今回作ったソースコードだと何故かjsonでデータを送ることができませんでした...
下のようなレスポンスが返ってくる...

```json
{
  "message": "Cannot send an empty message",
  "code": 50006
}
```

# 感想
もうちょっと頑張ってDiscordのGateway(ボット)のプログラムをC++で書いてみたいなと思いました。
Androidビルドエラーについて

Androidビルドを行った際に、比較的多いビルドエラーとして、`google-services.json` ファイルに関連したものがあります。この google-services.json ファイルは、FCMプッシュ通知を行う際に必要になるファイルになります。

今回は、この google-services.json ファイルに関連したビルドエラーを紹介します。


# ビルドエラーその1

```
Android project created with cordova-android@8.0.0Source path does not exist: google-services.json

または

CordovaError: Promise rejected with non-error: 'Please place your Firebase configuration file (google-services.json) in the root folder of this project.'
```

このエラーの原因には、以下が考えられます。

 - google-services.json 用の設定はあるが、設定場所に google-services.json が存在しない。

Monacaバックエンドのプッシュ通知用Cordovaプラグイン（MonacaBackendプラグイン）の場合、google-services.json は、Monacaプロジェクトのルートに配置し、config.xml に以下のように設定を行います。

```xml:config.xml（Cordova9.0プロジェクトの場合）
<platform name="android">
  <resource-file src="google-services.json" target="app/google-services.json"/>
</platform>
```

Monacaプロジェクトのルートに google-services.json を配置する場合は、MonacaクラウドIDEのメニューにある、

`ファイル` > `アップロード`

から行うことができます。

Monacaプロジェクトのルートにファイルをアップロードする場合のパス指定は、「/」を設定します。

プッシュ通知用Cordovaプラグインによっては、config.xml に設定を行わないものもあります。利用しているCordovaプラグインのドキュメントを確認して、正しい設定を行ってください。


# ビルドエラーその2

```
Execution failed for task ':app:processDebugGoogleServices'.
> File google-services.json is missing. The Google Services Plugin cannot function without it. 
   Searched Location: 
  /tmp/download/platforms/android/app/src/nullnull/debug/google-services.json
  /tmp/download/platforms/android/app/src/debug/nullnull/google-services.json
  /tmp/download/platforms/android/app/src/nullnull/google-services.json
  /tmp/download/platforms/android/app/src/debug/google-services.json
  /tmp/download/platforms/android/app/src/nullnullDebug/google-services.json
  /tmp/download/platforms/android/app/google-services.json
```

このエラーの原因には、以下が考えられます。

- config.xml に google-services.json の設定がない。
- config.xml に設定されている google-services.json の設定が間違っている
- 正しく google-services.json の設定が行われていない。

config.xml の設定や利用しているCordovaプラグイン用の設定に間違いがないか確認してみてください。


# ビルドエラーその3

```
Execution failed for task ':app:processDebugGoogleServices'.
> No matching client found for package name 'com.example.helloworld'
```

このエラーの原因には、以下が考えられます。

 - Monacaプロジェクトのパッケージ名と google-services.json に設定されているパッケージ名が一致していない。

Monacaプロジェクトのパッケージ名とFirebaseコンソールにある対象のプロジェクトに設定されているパッケージ名が一致しているか確認してみてください。


# おわりに

今回紹介したビルドエラーは、プッシュ通知用のCordovaプラグインを利用している際に比較的多く発生します。プッシュ通知用のCordovaプラグインを利用して、今回紹介したビルドエラーが出力されている場合は、一度、設定内容を見直してみてください。
Brackets の拡張機能を作る


## はじめに

Brackets の拡張機能を作る話は資料が少ないので書いてみる。

ミニマムなコードとできることを書きます。

開発環境は Mac の想定。

（軽く書いたので あとで書き足すかもしれない。）


## おおまかなこと

HTML, CSS, JS (Browser, Node) で作ります。Web屋万歳。

フレームワークっぽいのは次が使えます。

- Bootstrap
- RequireJS
- jQuery


## ディレクトリ

- /Users/`ユーザ名`/Library/Application Support/Brackets/extensions/
    - 拡張機能マネージャからインストールした拡張機能がある
    - Brackets の「ヘルプ」メニュー →「拡張機能のフォルダーを開く」で確認できる
    - 「無効」にした拡張機能は disabled に、「有効」は user にある
- /Applications/Brackets.app/Contents/www/extensions/default
    - プリインストールの拡張機能がある
- /Applications/Brackets.app/Contents/www/extensions/dev
    - 開発中の拡張機能を置ける
    - Brackets をアップデートすると /Applications/Brackets.app を上書いて拡張機能が消えるので注意
- /Applications/Brackets.app/Contents/www/extensions/samples
    - サンプルの拡張機能がある
    - インストールはされない
    - 開発の参考になるかも

今回は /Applications/Brackets.app/Contents/www/extensions/dev に新しいディレクトリを置きます。
新しいディレクトリの名前は `yourname.hello-world` にします。

## ファイルを置く

少なくとも次のファイルが必要です。

- package.json
- main.js

これらを新しいディレクトリに置きます。

### package.json

拡張機能マネージャの検索や表示などに使うメタ情報を書きます。

```json
{
    "name": "yourname.hello-world",
    "version": "1.0.0"
}
```

### main.js

メイン処理を書きます。

```js
define(function (require, exports, module) {

    console.log("こんにちは世界");

});
```


## デバッグ

もう動きます。

Brackets の中身はブラウザなのでリロードができます。

Brackets のメニュー「デバッグ」→「拡張機能付きでリロード」
またはショートカットキー `Command` + `R`

拡張機能マネージャーを開くと、作った拡張機能を確認できます。

<img width="877" alt="スクリーンショット 2019-12-18 22.03.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247334/d56775b7-9994-6895-4346-59262799d454.png">


今回はコンソールに出力するので、コンソールを見てみます。

Brackets のメニュー「デバッグ」→「開発者ツールを表示」
またはショートカットキー `Option` + `Command` + `I`

Chrome でよく見る開発者ツールが開きます。

Console タブを開くと、「こんにちは世界」が出力されていることを確認できます。

<img width="877" alt="スクリーンショット 2019-12-18 22.08.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247334/9f9c6993-c331-b4bc-d0db-ee1d6b049390.png">

開発者ツールは Brackets のメニュー「デバッグ」→「ステータスバーにエラーを表示」にチェックを入れておくと、Brackets 下部の「エラー：XX」からワンクリックで開くこともできます。

## できること

### UI 要素の追加
- メニュー
- ショートカットキー
- ツールバーのアイコン
- パネル

### 言語サポート
- クイック編集
- クイックドキュメント
- 定義をクイック検索
- コードヒント
- 定義にジャンプ
- 構文ハイライト
- Lint

### その他
- ライブプレビュー
- ファイルツリー
- 設定

DOM 操作や Node API も使えるので、ほかにもいろいろできます。


## より詳しいリンク

- [How to write extensions · adobe/brackets Wiki](https://github.com/adobe/brackets/wiki/How-to-write-extensions)
- [Brackets API](http://brackets.io/docs/current/index.html)


## おわりに

意外と簡単に始められて、できることも多い。
最小公倍数を求めるコードを書く時の注意点

#はじめに
以下のAtCoderの問題を解く際に、予め用意していた「最小公倍数を求める関数」を使ったのですが、オーバーフローが起きてしまいました。

[C - Multiple Clocks](https://atcoder.jp/contests/abc070/tasks/abc070_c)

正の整数$a,b$について最小公倍数を$l$、最大公約数を$g$とすると、

```math
ab = gl
```

となることが分かっています。このため、$\frac{ab}{g}$で最小公倍数を求めることができます。
ここで、$a*b$ を $g$ で割って最小公倍数を求めるような実装方法だと、上述したAtCoderの問題では$a*b$ のタイミングでオーバーフローが起こる可能性があります。
そのため、掛け算と割り算の順序を以下のように入れ替える必要があります。


#コード(修正前)
```c++
int lcm(int x, int y) {
    return x * y / gcd(x, y);//この順番だとオーバーフローが起きやすい
}
```
#コード(修正後)
```c++
int lcm(int x, int y) {
    return x / gcd(x, y) * y;//先に割り算をして掛けられる数を小さくして掛け算を行う
}
```

#終わりに
ネットで調べてみると、修正前のパターンが紹介されていることが多かったため、私と同じような失敗をした方がいらっしゃるのではと思い当記事を書きました。
参考になれば幸いです。
SATySFiの組版結果をテストする

この記事は [SATySFi Advent Calendar 2019](https://adventar.org/calendars/3929) 14日目の記事です。13日目はしょうだいさんの[「SATySFiでD論を書いた話」](https://qiita.com/shoudai7856/items/2f7a19f7bc56a49ed3ee)でした。

SATySFiで組版ライブラリを書いていると組版の結果の確認を自動化したいと思うことがしばしばあります。現在 [satysfi-base](https://github.com/nyuichi/satysfi-base) の組版ライブラリに回帰テストを導入を試みているところで、とりあえず最低限のものが出来上がったので、どういう風に使うものかをこの記事で紹介します。*(2019/12/28)無事[マージされました](https://github.com/nyuichi/satysfi-base/pull/15)*

## 回帰テストとは
コードに新機能を加えたりリファクタリングをした際に、その変更が既存の機能を壊してないかというのはプログラマの心配の種です。そこで既存の機能の確認をうまいこと自動化できれば、手間の削減にもプログラマの精神衛生にも寄与するわけです。そういう目的のためのテストを**回帰テスト**と呼びます。

具体的に言うと今回やりたい回帰テストの手順は以下のようになります。

* 新機能を追加する際は、その機能のテスト用のコードとその時点の組版結果も追加する
* 機能に変更があった際には、テストコードから組版結果を再出力して
  * もとの結果と同じ → ヨシ！
  * もとの結果と違う → 差分を報告してプログラマに確認させる
* 以下繰り返し

## 回帰テストを動かす
実際に satysfi-base の回帰テストを動かしてみましょう。今回の進捗は [visual-regression-test ブランチ](https://github.com/nyuichi/satysfi-base/tree/visual-regression-test)に置いてあります。もう少し完成度を高めてからmasterに入れてもらう予定です。

組版ライブラリのテストには [Jest](https://jestjs.io/ja/) を使っています。Javascriptを使っているのはフロントエンド回りの資産を流用したいというのが主な理由で、実際に [jest-image-snapshot](https://github.com/americanexpress/jest-image-snapshot) がテストの仕事の大半をやってくれています。

### セットアップ
テストの実行には SATySFi と Yarn と GraphicsMagick が必要です。予めインストールしておきましょう。GraphicsMagickはUbuntuなら`sudo apt install graphicsmagick`でインストールできます。
然る後に `yarn install` で依存関係を解決してから `yarn test`でテストを実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11817/6698ac14-f6e2-6550-52b3-cb16cba74b2e.png)

今回テストしているのは導出木を書くための`Derive`モジュールです([紹介記事はこちら](https://qiita.com/zptmtr/items/6bbbacb18000e9be4889))。チェックマーク付きの"renders ..."の行がそれぞれSATySFiのソースコードをコンパイルして出力結果を確認するテストになっています。毎回コンパイルしているので1テストに2,3秒くらいかかっちゃっていますね。まあそんなもんです。

### 既存の機能を変更する
`Derive`ではデフォルトのラベルの位置は左側なのですが、これを右に変更したことにしましょう。そうすると既存の機能が変更されたため、`yarn test`は失敗するようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11817/4a7287ae-54b1-2934-1560-33ebd31cabc9.png)

組版の出力結果が既存のものと違う場合には、jest-image-snapshotがご丁寧にdiffをとって報告してくれます。上のテスト結果の "See diff for defails: ..." にある差分画像は以下のようになっています。

![render-test-js-derive-renders-by-1-diff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11817/22766593-4d53-3032-0a60-14e2303ea4f4.png)

今のところStdJaを使ってるので本当にテストしたい導出木のパートは真ん中のちっこいやつです。~~すみません、このあたりを調整してる時間がなかったんや…~~ ([standalone-likeなクラスファイルが追加された](https://qiita.com/wasabiz/items/676a08c158514aa30f2d)ので解決されました。)

画像の左が既存の出力(ラベルが左)、右が現在の出力(ラベルの右)になっていて、真ん中にdiffが表示されています。このdiffは差分がわずかな場合に役に立ちますが、今回は変更点が明らかなのであんま気にしなくて大丈夫です。他の失敗したテストについても同様の画像が出力されており、これらを見れば出力結果の変更が期待したものであることを確認できるようになっているわけです。

### 現在の出力を既存のものとして上書きする
差分画像に問題がなければ`yarn test --updateSnapshot`で現在の結果を既存の結果として上書きすることができます(ところで記録してある既存の結果のことを *snapshot* と呼びます)。スクリーンショットの下部で4つのSnapshotが更新されているのが確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11817/8f6f5bf0-17b8-6ae7-5f76-b41f5f5a38c4.png)

## まとめ
以上SATySFiで回帰テストやるとしたらこんな感じかなというのを紹介しました。この記事ではテストのコードの詳細には立ち入りませんが、[`__test__`ディレクトリ](https://github.com/nyuichi/satysfi-base/tree/visual-regression-test/__test__)に置いてあるので興味のある方はご覧ください。

明日の15日目の記事はわさびずさんの「satysfi-base (旧 satysfi-lib) の宣伝」です。ではではー
Raspberry Pi と Python 3 を使ってANT+自転車パワーメーターの値を読む

基本こちらの内容通りすれば動く
[Track Your Heartrate on Raspberry Pi with Ant+](https://johannesbader.ch/blog/track-your-heartrate-on-raspberry-pi-with-ant/)

## 必要なもの
Raspberry Pi
USB ANT+ ドングル

## USB-Serialの準備
USBドングルを指して dmesg | tail もしくは lsusb で idVendorとidProductを確認する
> Bus 001 Device 004: ID 0fcf:1008 Dynastream Innovations, Inc. ANTUSB2 Stick

/etc/udev/rules.d/garmin-ant2.rules を編集して usbserial を設定

```garmin-ant2.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fcf", ATTRS{idProduct}=="1008", RUN+="/sbin/modprobe usbserial vendor=0x0fcf product=0x1008", MODE="0666", OWNER="pi", GROUP="root"
```
/dev/ttyUSB0 があることを確認
> ls /dev/ttyUSB0

## ソフトウェアの準備
ソフトウェアは以下の repository をクローン。オリジナルは Python3 で動かない。こっちのフォークのほうが新しい。
[mch/python-ant](https://github.com/mch/python-ant)

クローンしてセットアップ
> git clone https://github.com/mch/python-ant
cd python-ant
sudo python3 setup.py install

## パワーメーターの信号を読み取る
自転車パワーメーターを読む場合は、 ID = 11, Period = 4091 もしくは 8182 となる。
python-antのサンプルコードを Python3 の文法に合わせて以下のようになった。
[Git Repository python3-ant-receive](https://github.com/sadaoikebe/python3-ant-receive)

> sudo python3 powermeter.py
Flutter でアプリ開発してみる

# はじめに

個人的にスマホアプリをいくつか作りリリースしているのですが、作ったアプリを友達などに見せると、必ず言われるのが、
「iPhoneで動かないの？じゃいいや」
でした。
自分の周りでは、iPhoneを使っている率が高い気がしますが、実際のところ Android と iOSの日本でのシェア率は、ほぼ[半々ぐらい](http://www.moba-ken.jp/whitepaper/19_chap1.html)のようです。

そのような状況なので、モバイルアプリをリリースする場合は、Android, iOS の両対応が必須です。

ただ、Android と iOS はまったく別物なので、Native なアプリを作るとなると、工数は倍近く掛かってしまいます。

ということで、クロスプラットフォーム対応のフレームワークがいくつかあります。
たとえば、 Xamarin や PhoneGap、うちの会社なら Qt もその一つだと思います。

その中で、最近注目され、実際に使われ始めているものに Flutter があります。
この記事では、その Flutter について紹介致します。

# Flutter って？

![flutter1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129972/d125d052-1aeb-8b16-9aef-d5e9e5e6e71b.png)

Flutter は、Google が、これまで蓄積してきたモバイルアプリ作成の知見を基に、新たに作ったクラスプラットフォーム対応のフレームワークです。

使用する言語は Dart です。Java に比較的近い言語なので、Java を理解していれば、容易に使えるようになるかと思います。

パフォーマンスは AndroidでもiOSのそれぞれ、Native code にコンパイルして実行するらしく、Nativeアプリに比べても遜色は無いパフォーマンスだと思います。

UI周りでは、マテリアルデザインの UI Widget が揃っているので、マテリアルデザインに沿った アプリを、Android Native で作成するよりも比較的簡単に実現できるかと思います。
![flutter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129972/e68d651b-7e3e-7b97-e78b-8eb078f1e6cf.png)

Flutter の導入事例はすでに多くあり、Google だと、Google Assistant で使用されています。
https://flutter.dev/showcase

また、個人的雑感ですが、Android アプリをJavaで開発するのは、そろそろ限界に来ていると思います。これまで、スマホの使われ方の進歩に併せて機能拡張をして来た結果の構造的欠陥があちこちに出てきていると思います。
よって、Android だけにリリースするアプリでも、Flutter で作るのが良いと感じています。

# 開発環境

iOS アプリとして動作させる場合は、最終的に Mac が必要になりますが、開発自体は、Windows, Mac, Linux のどれでも大丈夫です。

開発環境としては、Android Studio か、VS Code を使用します。
https://flutter.dev/docs/get-started/install
に従って進めてゆけば、開発環境の構築は完了します。
もちろん全て無料で開発できます。

Flutter の特徴として、HotReload というものがあります。
エミュレータや実機などで開発中のアプリを動作させておくと、ソースコードを書いて保存した瞬間に、その挙動が反映されます。
ビルドやアプリの再インストールが不要なため、結果を見ながらのコーディングが可能です。
特にUI周りの挙動などのコーディング時に役立ちます。

# 入門

公式にサンプルやチュートリアルが豊富に用意されているので、それから始めるのがお勧めです。
またcodelabs を順に実施すると、基本的なところから学習できます。
https://flutter.dev/docs/codelabs



# Flutter のデメリット?

## 英語が必須
正式版のリリースから1年経った今でも頻繁に update されるので、公式ドキュメントを参照する場面がよく出てきます、ただ、公式ドキュメントはすべて英語なので、そこが多少の障壁になってしまうかと思います。

## Dart のエラーメッセージが不親切

エラーメッセージがちょっと分かりにくい場合があります。
例えば、以下のようなソースだと、

``` 
void main() {
  double x;
  double y = 0.2;
  double z = x + y;
  print ("answer = $z");
}
```

実行時に

```
The method '+' was called on null.
Receiver: null
```

のようなエラーメッセージが表示されます。
これは、x を初期化していないことが原因ですが、ちょっと分かりにくいかな？と思いました。

## UI Widget の挙動を変えるのが大変

実際のアプリを作成する際、用意された UI Widget を使って実装するわけですが、UI の挙動を変えたい場合など、苦労することがあります。
以前、Tar bar を使ったアプリを作ったのですが、TabView の追加、削除はサポートされていなかったので、それを実現するために、結構泥臭い実装が必要になりました。


#　で、作ってみたアプリ

お試しでアプリを Flutter で作成し、リリースしてみました。
消費税計算機です。
https://play.google.com/store/apps/details?id=com.gmail.kazutoto.works.flutter_consumption_tax
![calc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129972/e8a691f3-a777-08bc-db88-bf2c80eb7d1d.png)


ちなみに、Flutterで作ったので iOSでも動くのですが、Apple税を払うの辞めてしまったので、公式にリリースはしていません。
WindowsADKを一般人が使う機会って

WindowsPEを作成するには必須とされるWindowsADK。なのだが、ふと思った。

##一般人がWinADKを使う必要性って本当にあるのか？

多くのマシンにWindowsをインストールする必要あるプロの方々、その他私が全く分からない業種の方々はいろいろ活用されているのだろうと思います。今回はその方々のことは対象外とさせていただきますm(_ _)m


### WinADKを使ってPEを作ることのメリット

１．コマンドを使ってパッケージを追加できる
２．バックアップツール等を組み込む時に要求される
いろいろ考えた結果、この2点となりました。

#####・基本性能はほとんどWinPtchXに負けている
PE作成ツールのWinPtchXはADKファイルのうちPE作成に必要な最低限しかダウンロードしない(約1GB)ので、ADKの一部＋ADKaddon全部をダウンロードするADK(約5GB)よりも所要時間が圧倒的に短い(作成時間も、私の環境で約10分-約50分)。作成したPEについてもWinPtchXを通すことにより隠しファイルの表示等も行われるため使いやすくなっています。

#####・公式の方法にしても、インストールDVDに勝てない
もちろん、ソースコード丸見えとはいえWinPtchXが何やっているかわからないので使いたくない人もいるでしょう。そんな方でも、WindowsインストールDVDを使えばいいことです(公式のメディア作成ツールを使いましょう)。ADKを使うときもファイルを5GBくらいダウンロードせにゃならず、ダウンロードにかかる時間はインストールDVDを作るのと大して変わらないからです。
「とりあえずコマンドプロンプトが起動できれば良い」
インストールのウィザード途中で"Shift + F10"でコマンドプロンプトが起動することはご存知だと思います。あとはADK使うときと同じになります。

##コマンドプロンプトから難しいこと覚えずにファイルをコピーする方法
ご存知の方も多いでしょうしコマンドで充分という方もここでは多いとは思いますが、軽く復習します。

１．"notepad"とうち、メモ帳を起動する
２．もう一回うち、メモ帳を二つにする
３．"ファイル"から"開く"
４．右下の"テキスト文書"を"すべてのファイル"に変更
５．もう一つのメモ帳で３，４を行う
６．目的のフォルダに移動する
７．いつものようにドラッグ＆ドロップでコピー
以上。
なお、シャットダウンは"Wpeutil Shutdown"
Gitでブロックチェーンのようなことをする

ブロックチェーンはGitと何が違うの？ということでブロックチェーンのようにGitで Proof-of-Work する。

暗号通貨の送金などのトランザクションが`git add`であり、ブロックチェーンのブロックが`git commit`である、として考える。
そうするとブロックチェーンはgitの履歴であり、トランザクションの確定は`git commit`を Proof-of-X することで信頼性（？）が担保される。

簡易的な Proof-of-Work を hooks/post-commit に書くことにする。
コミットのハッシュが特定の条件を満たさない場合はコミットのやり直しという感じ。

```
$ git commit --allow-empty -m foo
c501d4fd3d6522ac34f0977c87d2942b1438fb1c -
f28f9c80a4431fe9f2bd2cc806e1b0880ac58619 -
99513727ca14d70b336a1aaccd11e8c17a65e3c9 -

...

ad6e20750dc378eac2a15f73623fb49a0cf45973 -
00a824e2b63a0260e1bec773780d44b323b87b43 -
  ---  
done 0s.
  ---  
done 7s.
[master 3eaaac4] foo
```

なんか最後の出力がミスってるけど、とりあえずこれで。

https://github.com/nishimura/gitmining-hook

```
$ git log --oneline
0058b75 add readme
0054dde add empty readme
00842e6 update command
009b8bc add post-commit file
0008b42 initial commit
```

コミットハッシュの先頭を`00`に揃えることができた。

ランダムな文字列をコミットコメントに追加して PoW している。
コミットコメントやAuthor、Committerを自分の公開鍵のハッシュのみの固定文字にして変更不可にすれば、1秒ごとにマイニングするPoSになる、と思う。コミット時刻が変わるとハッシュが変わるので。


ブロックチェーンはトランザクションがブロードキャストされるので、これを更にブロックチェーンに近付けるなら`git add`をブロードキャストするようにしなければいけない。
あとはコミットを検証してコミットハッシュが`00`で始まらない場合や間違った計算のコミットは`recieve`も`pull`も拒否しなければならない。

さて、上記ブロードキャストや検証の仕組みを作っても、今のままでは特に意味は無い。
単に面白いハッシュが作れるという以外の意味を見出すには、コミットに成功したらコインが増えるというような仕組みがないとどうしようもないよね。
普通のGitでいいじゃん、となる。

逆に言うと、自分のローカルのリポジトリが見ず知らずの他人によってブロードキャストされたデータで勝手に更新されるような環境だと、PoXが必要なのかもしれない。
ただし、そのデータの価値がコミットのPoXの価値と関連していなければ、やはり普通のGitでいいよね、となる。

ブロックチェーンをコイン以外の何かに使うことを考えるというのは、この`0008b42`ハッシュが何かに使えるかと探すようなことかもしれない。
RedshiftのIAM 認証を使用したデータベースユーザー認証情報の生成の制約事項

## はじめに
[UL Systems Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ulsystems) の16日目です。

データ分析などユーザーがアドホックなクエリを実行する環境では、誰が発行したクエリであるかを把握するために、作業者ごとにデータベースユーザーを作成することがあります。

Redshiftにはデータベースのユーザー認証もIAMで行うことができます。
本機能「[IAM 認証を使用したデータベースユーザー認証情報の生成](https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/generating-user-credentials.html)」が導入できるか技術検証を行った際、数点制約事項があることが判明したため、その情報共有となります。

## パブリックインターネットアクセスが必須

データベースユーザーの認証情報生成API「get-cluster-credentials」にて、HTTPS (ポート443)で**redshift.ap-northeast-1.amazonaws.com**にアクセスします。  
2019年12月現在、RedshiftはVPCエンドポイントに対応していないため、パブリックインターネット経由でのアクセスが必須となります。

プライベートサブネット上のEC2などからアクセスする場合、「NAT ゲートウェイ / NAT インスタンス」、「プロキシ」などを利用することになります。  

## get-cluster-credentialsで生成されたユーザーの権限情報を他ユーザーから参照できない

get-cluster-credentialsで生成されたユーザー（user_a）の権限を、他のユーザー（user_b）が参照することができません。
[HAS_TABLE_PRIVILEGE](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_HAS_TABLE_PRIVILEGE.html)などの権限確認関数は、実行ユーザーによって結果がかわります。今回の例ではuser_aで実行すればtrue、user_bで実行すればfalseが返ります。

その為、user_aが作成したテーブルに対し、あるグループはデフォルトでselectできるようalter default privilegesで権限付与を行いたい場合、user_aでしか行えません。


## まとめ

上記のような制約も多いため、導入する前に十分な技術検証期間を設けたほうがよいと思います。
また、公式ドキュメントはあるものの、導入事例の少ない技術でもあるため、問題が発生した場合、自力で解決することになります。
AWSサポートへの問い合わせがなければ解決が難しいことも多いため、ビジネスプラン以上を契約している環境で検証は行いましょう。
ミニマムなVueファイルでcomponentの表示順を確認してみた。

どうもはじめまして。
エンジニア一年目の@mjnjvdです。

今回はアドベンドカレンダーなるものにお誘いをいただいたので、
重い腰を上げてqiita初投稿をする決意をしました！

現在案件でVueを用いたフロントエンド開発を担当しているのですが、
リロードをかけた時や画面遷移した時の画面表示の際に、小さい要素が先に表示されてしまう現象に陥ってしまいました。
そこで今回はミニマムなVueファイルにコンポーネントを持たせ、描画が行われる順序について確認していきたいと思います。

#使用したファイル
VueCLIで作成したプロジェクトを使っていきます。
今回は既存のApp.vueを以下のようにしcomponents配下にも同様のクラスを当てたコンポーネントを用意しました。
さらにchild1コンポーネント内でchildAコンポーネントを呼び出している構成を取っています。
そしてそれぞれのvueファイルのmountedにconsole.logを仕込んでいます。

```App.vue
<template>
  <div class="parent">
    {{text}}
    <child1/>
    <child2/>
  </div>
</template>

<script>
import child1 from './components/child1.vue'
import child2 from './components/child2.vue'

export default {
  components: {
    child1,
    child2
  },
  data(){
    return {
      text: "parent"
    }
  },
  mounted: function(){
      console.log('parent')
  }
}
</script>

<style scoped>
  .parent{
    border:solid black
  }
</style>
```

実際にブラウザに表示させてみると以下のようになります。
極限にシンプルですね。
<img width="714" alt="sample1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542640/40822159-08c9-14a9-e716-4da2679f8dd2.png">


#実行結果
ではコンソール画面を開いてリロードをかけてみましょう。
結果は...
<img width="343" alt="console.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542640/eb2c8f06-e66b-9247-955b-7ae07d7b727e.png">


なんと！孫コンポーネントであるchildAコンポーネントから描画されていますね...
これは小さい要素から描画されてしまうのにも納得です。

#苦労した点
・Unexpected console statement (no-console)と言う謎エラー
App.vueに設置したconsole.logが原因となったエラーですね。
調べたところによるとVueCLIでプロジェクトを作成した際にデフォルトの設定を用いた結果として、ESlintもインストールされ、その初期設定でnoーconsoleが有効になってしまっていたようです。
設定をいじるのもありですが今回は煩わしさに勝てずカスタム設定でプロジェクト作成をし直し解決しました。
・child1内でcilldAのインポートがうまくいかない問題
同じ階層にあるファイルなので"import childA from 'childA.vue'"と書いていたのですが"import childA from './childA.vue'"とする必要があったようです。

#追記
子コンポーネントのコードについてコメントいただいたので貼り付けておきます。child2はchild1の数字とborderの色を変えたのみになります！

```child1.vue
<template>
    <div>
        {{text}}
        <childA/>
    </div>
</template>

<script>
import childA from './childA.vue'

export default {
    components: {
        childA,
    },
    data(){
        return {
            text: "child1"
        }
    },
    mounted: function(){
        console.log('child1')
    }
}
</script>

<style scoped>
    div{
        border:solid blue
    }
</style>
```
```childA.vue
<template>
    <div class="childA">
        {{text}}
    </div>
</template>

<script>
export default {
    data(){
        return {
            text: "childA"
        }
    },
    mounted: function(){
        console.log('childA')
    }
}
</script>

<style scoped>
    div.childA{
        border:solid gray
    }
</style>

```

#最後に
いかがでしたでしょうか。
同じようにVueの描画処理に苦労している方のお役に立てれば幸いです。

それにしても自身が悩んだことを文章化するというのは非常に難しい作業ですね。（そもそも自分が悩んでいる状態なのか判断するのも難しいと感じているのですが...）
日常的にqiita投稿といかないまでも悩みを細分化して整理する作業はやってこうと思った次第であります。

次回は@shg_shgさんの投稿です！
C#foreachで自身の配列にデータを追加する 


<strong>前に書いた記事の部分抜粋（C++）</strong> この後にC#コードがあるので慌てずに  

```c++:main.cpp

#include <iostream>
#include <vector>
using namespace std;

void Print(vector<int> v)
{
	for (auto& i : v)
	{
		cout << " " << i ;
	}
	cout << endl;
}

int main()
{
	vector<int> vkeep{ 5, 5, 0, 5, 1 }; //5個
	Print(v);
	cout << "--- rfor内で自身のコンテナ追加 ------rforの値がバグる--------------" << endl;
	for (auto& i : v)
	{
		cout << " " << i ;
		if (i == 5)
			v.emplace_back(123);
			//v.push_back(123);
	}
	cout << endl << "-----５は３つあるので３つ１２３が増えないといけないが、バグっている-----" << endl;
	Print(v);
}
```

実行結果、イテレータの位置がおかしくなり、エラーでなくバグる << 仕様らしい（デバッグビルド、もしくはデバッグ実行でエラーにしてほしいが・・・）

実行結果　：要素数も増えていなくて値も　-572662307　という表示になる

```
--- rfor内で自身のコンテナ追加 ------rforの値がバグる--------------
 5 -572662307 -572662307 -572662307 -572662307
```


これのC#バージョンを作る、ついでにラムダ記述方法も忘れたので確認

結論から言うと、foreach内での自身の配列（List）に要素数を増やすと実行時にエラーになる。
下記では、別配列（List）を用意して一旦こちらに追加して、まとめて追加（AddRange）している

```C#:main.cs
using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            List<int> v = new List<int>(){ 5, 5, 0, 5, 1 };
            var vpp = new List<int>();
            foreach (var a in v)
            {
                //if (a == 5) v.Add(123); //error
                if (a == 5) vpp.Add(123);
            }
            // ラムダで書いたバージョン
            //v.ForEach(a => { if (a == 5) v.Add(123); });   //error
            //v.ForEach(a => { if (a == 5) vpp.Add(123); });
            v.AddRange(vpp); // v配列に appデータを増やす
            foreach(var a in v)
            {
                Console.Write(" {0}",a);
            }
            // ラムダで書いたバージョン
            //v.ForEach(a =>{
            //    Console.Write(" {0}",a);
            //});
            Console.WriteLine();
        }
    }
}
```

実行結果

```
Hello World!
 5 5 0 5 1 123 123 123

```
ちなみにエラーコメントの行のコメントを外してもビルドエラーは出ない。**実行時にエラーになる。**

C# ではforeach で自身配列の変更をしてはいけないとなっており、
実行するとエラーが **foreach の行** ですぐ出る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/beebddf9-6595-1134-4d58-e0a85d69bd25.png)

C++では参照型を用い、rfor内の配列内の値の変更は可能だが、C#ではforeach 内ではそれすら許されない。
それは要素の増加に関しても同様のようだ。

※Visual Studio 2010時の C# では、foreachでの自身の値の変更はできて便利だった・・・時代の流れか
Python学習ノート_001

実施日：2019年12月14日
テーマ：Pythonのインストール

##実施手順
- OS環境：MacOS_10.13.6（17G65）
- Pythonのダウンロード：https://www.python.org/downloads/
- コードのダウンロード：https://www.oreilly.co.jp/books/9784873118741/
 - 「第1刷正誤表」タブ中の内容を本に反映する
![印刷ミスを訂正する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/e2288dc1-86a9-45b7-489f-e07e55314bbc.png)
 - 「関連ファイル」タブ中の[「サンプルコード」](https://www.oreilly.co.jp/pub/9784873118741/sample-code.zip)のリンクをクリックして、ソースコードや関連ファイルをダウンロードする
- インストール手順は省略します。
- 動作確認：アプリケーションの中に「Python 3.8.0」の中の「IDLE.app」を起動してシェル環境の画面が見える。  
![IDLE起動後の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/47703ee6-e0bc-14b5-eaa7-c4fd31a82679.png)
フォームの表示非表示の切り替え【JavaScript】



```
<!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>表示非表示の切り替え</title>
</head>

<body>
	<form>
		<table border="0" cellspacing="0" cellpadding="0">
			<tr>
				<th>利用方法</th>
				<td>
					<label><input type="radio" name="entryPlan" value="hoge1" onclick="entryChange1();"
							checked="checked" />初めて申し込む</label>
					<label><input type="radio" name="entryPlan" value="hoge2" onclick="entryChange1();" />2度目以降の利用</label>
				</td>
			</tr>

			<!--表示切替-->
			<tr id="firstBox">
				<th>紹介者</th>
				<td><input type="text"/>
					<p>紹介された方のお名前を入力してください。
					</p>
				</td>
			</tr>

			<!--	表示非表示切替-->
			<tr id="secondBox">
				<th>会員番号</th>
				<td><input type="text"/>
					<p>会員番号を入力してください</p>
				</td>
			</tr>
		</table>
	</form>

	<!--	表示非表示切替 -->
	<div id="firstNotice">特典:初めての方は30%オフ!</div>
	<script src="js/main11.js"></script>
</body>

</html>
```




```
function entryChange1() {
  radio = document.getElementsByName('entryPlan')
  if (radio[0].checked) {
    //フォーム
    document.getElementById('firstBox').style.display = "";
    document.getElementById('secondBox').style.display = "none";
    //特典
    document.getElementById('firstNotice').style.display = "";
  } else if (radio[1].checked) {
    //フォーム
    document.getElementById('firstBox').style.display = "none";
    document.getElementById('secondBox').style.display = "";
    //特典
    document.getElementById('firstNotice').style.display = "none";
  }
}

//オンロードさせ、リロード時に選択を保持
window.onload = entryChange1;
```

ブログ↓
https://greenberet.net/mosya-coding-udemy/
ホスト側の保存先を指定せずに作ったdata volumeを、望みの保存先に変更したい

dockerコンテナ内の/var/www/htmlがマウントしているホスト側のディレクトリを変更したいのだが、一度コンテナをrunした後は変更はできなくなってしまうらしい。
したがって移動の手順はこのようになる。

1. ホスト側のvolumeの内容を望みの保存先にコピーする
2. コンテナを破棄する
3. docker-compose.ymlのvolumesの設定を望みの保存先に変更する
4. コンテナを新規に起動する

#### ホスト側のvolumeの内容を望みの保存先にコピーする

docker-compose.yamlのあるディレクトリにhtmlディレクトリを作成し、そこにvolumeの内容をコピー

```shell
mkdir html
cd html
docker run --rm --volumes-from wordpress-study_wordpress_1 -v $(pwd):/html busybox cp -rp /var/www/html /
```

#### コンテナを破棄する

```shell
docker-compose down
```

#### docker-compose.ymlのvolumesの設定を望みの保存先に変更する

```yaml
    volumes:
      - ./html:/var/www/html
```

#### コンテナを新規に起動する

```shell
docker-compose up -d
```
HHKB HYBLID での複数台接続方法

# ２台目から接続する時は、 fn+control+[2]を押す

説明書の説明が解りづらくハマってしまったのでメモしておきます
1台目を既に登録済みで2台目を登録する時は下記のステップを実行します。

```
step 1
fn+q　（LEDインジゲーターが青くゆっくり点滅）

step 2
fn+control+[2]
```

3台目を登録する　fn+control+[3]
4台目を登録する　fn+control+[4]


## 使用する機器を切り替える時は、 fn+control+[1]を押す

1台目に切り替える　fn+control+[1]
2第目に切り替える　fn+control+[2]


## リセット方法

```
step 1
fn+q

step 2
fn+z+[BS] (英語配列の場合は、一番右上のボタン)
```
Android Code SearchでAOSPのソースを見る


# Android Code Searchとは
AOSP(Android Open Source Project)のソースコードを閲覧するためのサービスです。

# 使ってみました
https://cs.android.com/

![スクリーンショット 2019-12-14 18.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102273/33fb5943-e106-515b-1765-c7d1360c2f92.png)

`BluetoothGattServer`で検索してみます。
Bluetoothのソースコードはframeworksというディレクトリ下に入っているんですね。
![スクリーンショット 2019-12-14 18.25.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102273/76c8374f-7751-e7cb-9b8b-ca9f3f1d1a88.png)

左上のブランチを指定すると、各Androidのバージョン毎のソースが見れます。
ソースコード間をジャンプすることもできます。
![スクリーンショット 2019-12-14 18.26.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102273/7fc95ed6-bcb0-abe6-5b65-2893267b6e9d.png)

画面下の`History` を押すと、コミット履歴が見れます。
最初のコミットは2009年なので10年も前ですね。歴史が感じられます。
![スクリーンショット 2019-12-14 18.32.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102273/60ff0325-1771-8947-44e3-9469cb111f01.png)

アプリ開発をしているとAOSPのコードを見る機会は少ないですが、Androidのバージョン毎の挙動の変化を
知りたい時や、単純に興味本位で眺めることもあるので今後はAndroid Code Searchを活用していきたいです！


# 参考
* https://cs.android.com/
* https://android-developers.googleblog.com/2019/12/code-search-with-cross-references-for-aosp.html
AWS RoboMakerのROS2(Beta)版を使ってみる

# 概要
最近AWS robomakerでROS2がサポートが開始されました！バージョンはbetaですが、[2020年の後半くらいにbetaが取れるらしい](https://aws.amazon.com/jp/about-aws/whats-new/2019/10/aws-robomaker-introduces-support-robot-operating-system-2-beta-release/)です。今回は、robotmakerの開発環境でros2を選択し、そこでノードの実行をしてみたいと思います。

また、ros1でのAWS RoboMakerは次の記事がとてもよくまとめられていて助かりました。
https://qiita.com/nmatsui/items/6721c820000cf5115bdc


## 実行手順
　今回はros2のチュートリアルとして公開されている"Hello World"を使用してros2のノードを実行してみたいと思います。また、aws robomakerのros2対応のチュートリアルは現在、2つあります。（2019/12/14 現在）他のディストリビューションだと全部で5つあります。今後サポートが続けてられ行くうちに、他のディストリビューションで公開されているチュートリアルもROS2で実行できるようになると思います。

>**1. AWSコンソールを開き、開発新規->環境の設定を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/a4cf86b5-a4eb-9b32-054f-b9f0bdaac931.png)


>**2. ROSディストリビューションをROS2 Dashingに設定する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/95d81741-37df-8d1c-6c69-6cc18ddc85a5.png)

>**3. Cloud 9が立ち上がったらHello Worldチュートリアルをダウンロードする**

ー立ち上がり前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/e4f0e0e1-5dea-ff81-a428-37b9c2e0b8b1.png)

ー立ち上がり後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/0eae501a-10ec-2715-f033-3a36d1f23739.png)


>**4. Hello Worldチュートリアルのコンフィグレーションを行う**
コンフィギュレーションはCloud9の下部にあるbash shellで行ってください.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/db3f9ba2-1d7f-8986-2a3f-ac2a2b0b3ba0.png)

内容は以下の通りです。

```bash
sudo apt-get update
rosdep update
cd robot_ws
rosws update
rosdep install --from-paths src --ignore-src -r -y
colcon build
Simulation
cd simulation_ws
rosws update
rosdep install --from-paths src --ignore-src -r -y
colcon build
```

>**5. /HelloWorld/robot_ws/src/hello_world_robot/srcのrotate.pyを適当に編集する**

>**6. ターミナル(Cloud 9上)で実行する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169342/80f443a8-91df-ef3c-4691-b98c1fe88fbc.png)

## まとめ
今回は実行環境の構築と確認だけ行いましたが、今後はシミュレーションジョブを追加してgazeboとかを試していきたいと思います。すごく簡単にできるのでawsのアカウントを持っている人はぜひ一度試してみて下さい！