OmniAICreator/Qiita-1.07M huggingface dataset:
ベクトルタイルを QGIS で確認できるようにするまで

ベクトルタイルを、例えば元データと突き合わせて確認する場合には、デスクトップ GIS で確認するほうが何かと便利でしょう。そこで、業務環境を想定して Windowds と QGIS を使い、ベクトルタイルを見ることができることを確認してみました。

# 下準備
1. [QGIS 3.6.0 Noosa](https://qgis.org/ja/site/forusers/download.html#) をインストールしました。
2. [Vector Tiles Reader](https://plugins.qgis.org/plugins/vector_tiles_reader/) を QGIS の中からインストールしました。

# 実地確認
Vector Tiles Reader には Server, MBTiles, Directory の3機能があります。うち、Server と MBTiles について動作確認してみました。

個人的な感触としては、Vector Tiles Reader の TileJSON 対応及び Mapbox Style 対応は脆いと感じました。TileJSON については、そもそも仕様の収斂がうまくいっていないところがありますが、Vector Tiles Reader が必須としている vector_layers など、それほど一般的には実装されていないので、かなり我慢強く試してみても、Invalid TileJSON というエラーメッセージを戻してきます。

また、Mapbox Style を反映させることには成功できませんでした。私は expression を多用する方向に振り切っているのですが、例えば expression には（まだ）対応しないという設計判断をして開発を進めているとすると、うまく動かなくてしかたないのかなと思います。

いまのところ、この Vector Tiles Reader は、OSM ベースの少数のベクトルタイルサービスがうまく動くことを狙いに開発されているという段階であるように思います。

唯一、ある程度まともに動いたのは、MBTiles から .mbtiles ファイルを指定する、という方法でした。.mbtiles ファイルの中にあるメタデータを読み取って、適当に読み込んでくれます。スタイルは手探りで設定する必要はあるかもしれませんが、TileJSON や Mapbox Style を Vector Tiles Reader のために試行錯誤して調整するよりは、そういう設定をするほうが手っ取り早いかもしれません。
Symfonyで特定のControllerのみ署名認証する

# 背景・動機

既存のSymfonyプロジェクトに署名付きのREST APIを追加することになり、他の処理に影響を与えないよう特定のControllerのみ追加する必要があったため、備忘録を兼ねて実装方法を投稿します。

# 環境

Symfony 3.0.1
PHP 7.0.2

# 手順

ざっくりと以下のような手順になります。

1. 署名認証したいControllerに設定するインターフェースを追加。
2. イベントリスナーを作成しサービスコンテナに登録。
3. イベントリスナー内でControllerを参照し、インターフェースを見て署名認証を行う。
4. 署名認証に失敗すれば例外をスロー。


## 1. 署名認証したいController用のインターフェースを作成

空のインターフェースでOKです。
署名認証が必要なControllerを特定する目的で利用します。

```php
interface SignatureAuthenticatedController {}
```

## 2. イベントリスナーを作成

以下のようなイベントリスナーを作成します。

```php
class SignatureListener {
  public function onKernelController(FilterControllerEvent $event) {
    // Controllerを取得
    $controller = $event->getController();
    if (!is_array($controller)) {
      return;
    }
    // Controllerがインターフェースを実装しているかチェック
    if ($controller[0] instanceof SignatureAuthenticatedController) {
      // Requestを取得
      $request = $event->getRequest();
      // ヘッダーから署名を取得
      $signature = $request->headers->get('x-hogehoge-signature');
      // Requestを使ってダイジェスト値を計算
      // 署名の方法については適宜実装してください
      $canonicalString = $request->getMethod() . "\n" .
                         $request->getHost() . "\n" .
                         $request->getPathInfo() . "\n" .
                         $request->getQueryString() . "\n" .
                         $request->getContent();
      $digest = hash_hmac('sha256', base64_encode($canonicalString), 'secret');
      // ダイジェスト値と署名が違っていたら例外をスロー
      if ($signature !== $digest) {
        throw new AccessDeniedHttpException('Invalid signature.');
      }
    }
  }
}
```

## 3. services.ymlにリスナーを追加

```yml
app.action_listener:
  class: AppBundle\EventListener\SignatureListener
  tags:
    - { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
    - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
```

## 4. 署名で保護したいControllerにインターフェースを実装

```php
class SecretController extends Controller implements SignatureAuthenticatedController {
}
```

今回はControllerとExceptionのイベントリスナーを利用しましたが、他にも色々あるようですのでいつか試してみたいと思います。
もし似たような問題を抱えている方がおられましたら、割と簡単な手順で実装できますので、お試しください。
MurataのLoRaWANチップCMWX1ZZABZ搭載ボードをArduino IDEで開発(プログラム編)

前回 CMWX1ZZABZ搭載ボードをArduino IDEで開発するための環境構築に関して説明しましたので
今回は実際にサンプルプログラムからLoRaWANにOTAAモードで接続してみます。

なお接続先は「[福岡市LoRaWAN実証実験](http://www.city.fukuoka.lg.jp/keizai/kagakugijutsu/business/lorawan.html)」ゲートウェイでテストしました。

ベースとしたプログラムは
[LoRaWAN_Join_OTAA](https://github.com/GrumpyOldPizza/ArduinoCore-stm32l0/blob/master/libraries/LoRaWAN/examples/LoRaWAN_Join_OTAA/LoRaWAN_Join_OTAA.ino) です。
このプログラムは Arduino IDE の スケッチ例からも選択できます。

```LoRaWAN_Join_OTAA.ino
/* Simple OTAA join for a LoRaWAN network
 *  
 *  In setup() below please replace the argument to LoRaWAN.begin()
 *  with your appropriate region specific band:
 *
 *  AS923
 *  AU915
 *  EU868
 *  IN865
 *  KR920
 *  US915
 *
 *  AU915/US915 networks have 64+8 channels. Typical gateways support only
 *  8 (9) channels. Hence it's a good idea to pick the proper channel
 *  subset via select via LoRaWAN.setSubBand(),
 *    
 *  EU868/IN865 have duty cycle restrictions. For debugging it makes sense
 *  to disable those via setDutyCycle(false);
 *    
 *  For an external antenna one should set the proper antenna gain
 *  (default is 2.0) via setAntennaGain().
 *    
 *  Please edit the keys below as they are just debugging samples.
 *    
 *    
 * This example code is in the public domain.
 */

#include "LoRaWAN.h"

const char *appEui = "0101010101010101";
const char *appKey = "2B7E151628AED2A6ABF7158809CF4F3C";
const char *devEui = "0101010101010101";

void setup( void )
{
    Serial.begin(9600);
    
    while (!Serial) { }

    LoRaWAN.begin(US915);
    // LoRaWAN.setSubBand(2);
    // LoRaWAN.setDutyCycle(false);
    // LoRaWAN.setAntennaGain(2.0);
    LoRaWAN.joinOTAA(appEui, appKey, devEui);

    Serial.println("JOIN( )");
}

void loop( void )
{
    if (LoRaWAN.joined() && !LoRaWAN.busy())
    {
        Serial.print("TRANSMIT( ");
        Serial.print("TimeOnAir: ");
        Serial.print(LoRaWAN.getTimeOnAir());
        Serial.print(", NextTxTime: ");
        Serial.print(LoRaWAN.getNextTxTime());
        Serial.print(", MaxPayloadSize: ");
        Serial.print(LoRaWAN.getMaxPayloadSize());
        Serial.print(", DR: ");
        Serial.print(LoRaWAN.getDataRate());
        Serial.print(", TxPower: ");
        Serial.print(LoRaWAN.getTxPower(), 1);
        Serial.print("dbm, UpLinkCounter: ");
        Serial.print(LoRaWAN.getUpLinkCounter());
        Serial.print(", DownLinkCounter: ");
        Serial.print(LoRaWAN.getDownLinkCounter());
        Serial.println(" )");

        LoRaWAN.beginPacket();
        LoRaWAN.write(0xef);
        LoRaWAN.write(0xbe);
        LoRaWAN.write(0xad);
        LoRaWAN.write(0xde);
        LoRaWAN.endPacket();
    }

    delay(10000);
}
```

変更箇所
LoRaWAN.begin(US915);    ->  LoRaWAN.begin(**AS923**);  
**appEui**、**appKey**、**devEui** はゲートウェイへの登録値に合わせてください。
なおこのままだと10秒おきの送信となりますので delay(10000) の 10000 をもっと大きい数字に変更してください。
例 **5分 : 300000**
Dart-Variables

# Dart Variables
この文章の内容は[dart公式tour](https://www.dartlang.org/guides/language/language-tour#variables)のvariablesをまとめたものです。

## 動的変数と静的変数
Dartは静的型付き言語と動的型付け言語といった両方の側面を持つため、下記のどちらのような宣言の仕方が可能です。

```dart
// 動的変数
var s1 = '文字列'
// 静的変数
String s2 = '文字列'
```
## Default value
Dartの変数の初期値はnullになります。

```dart:defaultValue.dart
main() {
  int i;
  assert(i == null);
}
```

assesionは「enable-asserts」を実行時に指定しないと実行されないため、以下のように起動します。

```
dart --enable-asserts defaultValue.dart
```

## finalとconst
Dartでは定数を宣言する方法として２つの方法(finalとconst）があります。

### final
final をつけて宣言された変数は、一度代入を行った後に、再度、代入ができません。
イメージとしてプログラム実行時に振る舞いが決まる感じです。プログラム実行時には値は決まってなくともよい。

```dart
final int i = 1;
i = 2 //不正なプログラム
```

### const
constも一度代入を行った後に、再度、代入ができません。
finalとの違いは、コンパイル時に値が評価されて、プログラム実行時にはすでに値が決まっていることです。
(Javaでいうところのstatic finalに近いイメージです。)

```dart
const int i = 1;
const int j = 2;
const int k  = i * j;
```
Puppeteer で HTTP リクエストエラーを検知し、テストを失敗させる


実行環境（package.json）

```json
  "engines": {
    "node": "^10.9.0",
    "yarn": "^1.12.0"
  },
  "dependencies": {
    "ava": "^1.2.0",
    "puppeteer": "^1.12.1"
  },
```

SPA での非同期の API 呼び出しのエラーを検知したい場合など

参考：[event: 'response'](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#event-response)

```js
  page.on("response", async response => {
    const status = response.status();
    if (status === 400 || status >= 500) { // どのステータスコードをテスト失敗としたいかは要件による
      const method = response.request().method();
      const url = response.url();
      const body = await response.text();
      test.fail(`failed to request. status=${status} method=${method} url=${url} body=${body}`);
    }
  });
```
Elixir~等差数列をモジュール化して実装、PJとして動かす~

#ここまでのあらまし

まだまだ四則演算に毛が生えた程度ですが、今回は等差数列を用いてモジュール化と実装を行います！

#等差数列

a=初項 d=公差 等差数列のn個めの項の大きさは

```
a+(n-1)*d
```

となります。
詳しくは[こちら](http://yama-taku.science/mathematics/numerical-sequence/basis-of-arithmetic-and-geometric-progression/)

#モジュール化、関数定義

```elixir:lib/progression/arithmetic_progression.ex
defmodule ArithmeticProgression do
	def calc(a,d,n) do
		 a + (n - 1) * d 
	end

end
```

適当なディレクトリでPJを作成したあと、

```elixir
mix new progression
```



手で以上のディレクトリとファイルを作成します。
その後

```elixir
iex -S mix
```

おっとここでわたしは2回のエラーに阻まれました。

ひとつめ

```elixir
unexpected parentheses. If you are making a function call, do not insert spaces between the function name and the opening parenthes. ~~
```
予測していないカッコ。
関数呼び出しを作ろうとしてるなら、関数と最初のカッコのあいだにスペースを入れないでね。
的な感じで訳しました。calcと(のあいだにスペースあいてるじゃん〜

もう一度コンパイルも、エラー。

```elixir
warning: variable "d" does not exist and is being expanded to "d()", please use parentheses to remove the ambiguity or change the variable name
  lib/progression/arithmetic_progression.ex:3

warning: variable "b" is unused (if the variable is not meant to be used, prefix it with an underscore)
  lib/progression/arithmetic_progression.ex:2
```

正確にはどのように訳していったのか失念しましたがどうもdとbまわりでなにかが...あっdを使うところbにしてた、というふうに解決しました。

ターミナルで関数を呼び出します。

```elixir
iex(1)> ArithmeticProgression.calc(3,6,2)
9
```

やった！これは初項3の公差6の2個目の項の大きさですね。


#編集後記
またなんとか自分のつくったPJを動かすことができた！
ここからスピードアップしていきたいです。
うまずたゆまず、頑張ります。
Kento Mizuno
Puppeteer で JavaScript の実行時エラーを検知し、テストを失敗させる


実行環境（package.json）

```json
"engines": {
    "node": "^10.9.0",
    "yarn": "^1.12.0"
},
"dependencies": {
    "ava": "^1.2.0",
    "puppeteer": "^1.12.1"
},
```

現在開発しているプロダクトで、フロントエンドを Vue.js でつくっていて UI の見た目上は問題なさそうだけど、実は裏で JavaScript の実行エラーが発生していたケースが何度かあり、そういったエラーを E2E テストでも拾いたいと考え、このような仕組みを入れています。

参考：[event: 'console'](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#event-console)

```js
  // JavaScript、Vue コンポーネント関連のエラーを捕捉し、テストを失敗させる
  // NOTE:　page.on("error"), page.on("pageerror") でも捕捉できそうだが
  //       期待通り動かなかったので　console のエラーメッセージをチェックする
  page.on("console", msg => {
    const type = msg.type();
    const text = msg.text();
    if (type === "error" || type === "warning") {
      test.fail(text);
    }
  });
```
JavaScriptのスコープとクロージャをコンソールで確認する（Google Chrome）

Google Chromeのデベロッパーコンソールで
`console.dir(<functionオブジェクト>)`
と実行すると
![closure.jpg](https://qiita-image-store.s3.amazonaws.com/0/238976/84537edd-4df8-a9b5-05d9-739150161484.jpeg)
クロージャのスコープを確認できます。

もちろんアロー関数でも使えます。
![closure2.jpg](https://qiita-image-store.s3.amazonaws.com/0/238976/8a778bdb-24c5-3cd7-d390-088bd0f46dfe.jpeg)

---

コンソールでクロージャが見える！大発見だ！
と小躍りしながら記事を書き始めたわけですが、5年以上前に既にあったようです。
[Chromeのコンソールで、クロージャーで使ってる変数が見えるようになってた](https://qiita.com/ginpei/items/4cb9c9c7108a7f458b91)
iOS环境下<iframe>标签上拉事件无效

## 背景
在Web应用程序中，有的列表需要异步加载，这时候通常就会支持上拉加载更多和下拉刷新事件。在某个项目中，我们用到的是[jQuery WeUI](http://jqweui.com)中的组件。奇怪的是，在Android环境下运行正常，但是在iOS环境下却出现上拉事件无效。

## 寻找原因
在该项目中，使用的是父页面中包括了子页面，并且使子页面响应上拉事件：

```html:Parent.html
<style>
#wrapper {
    height: 100%;
}
iframe {
    width: 100%;
    height: 100%;
    margin: 100%;
    padding: 100%;
    border: 100%;
}
</style>
<div id="wrapper">
    <iframe src="" name="list"></iframe>
</div>
```

在jQuery WeUI中上拉加载更多使用的是下面的js代码：

```js:IFrame.js
var loading = false;
$(document.body).infinite().on("infinite", function() {
    if (loading) return;
    loading = true;
    setTimeout(function() {
        // load data and add to list...
        loading = false;
    }, 1500);
});
```

但是用Safari实时调试的时候并没有响应这个方法。

## 解决
- 比较简便的方法是给``<iframe>`外的`<div>`加上以下样式：

```css:Parent.css
#wrapper {
    -webkit-overflow-scrolling: touch;
    overflow: auto;
}
```

- 而在当时考虑的是，当前的代码是在子页面响应上拉事件，所以考虑直接在父页面上面响应上拉事件。这个方法也解决了问题。

```js:IFrame.js
var loading = false;
function LoadMoreCallByParent() {
    if (loading) return;
    loading = true;
    setTimeout(function() {
        // load data and add to list...
        loading = false;
    }, 1500);
}
```

```js:Parent.js
window.addEventListener("scroll", function (e) {
    var body = document.body;
    if (body.scrollTop + body.clientHeight == body.scrollHeight) {
        // iframe is scroll to the bottom so call the refresh method
        list.window.loadMoreCallByParent();
    }
});
```

## 参考
[Iframe scrolling iOS 8](https://stackoverflow.com/questions/26046373/iframe-scrolling-ios-8)
[Scroll IFRAMEs on iOS](https://davidwalsh.name/scroll-iframes-ios)
vscodeのjs intellisenseからjqueryを除外する

# なぜそんなことを

vscodeが(適切な設定になっていれば)```@types```パッケージを自動的に取得してjsに補完を効かせてくれることは有名だと思うが、その際にハマったポイント。

Webdriver.ioを利用したコードをvscodeで書いていたのだが、"\$"という名前を打つとWebdriver.ioの"\$"ではなくjqueryの"\$"が勝手にintellisenseされてしまった。

---

↓この"$"はjqueryのものなので使わないでほしい
![1.png](https://qiita-image-store.s3.amazonaws.com/0/171162/240a4769-eea7-a03d-d67e-d2ae5dc8c022.png)

↓ちなみに"$$"などは正しくWebdriver.ioのものをとってきている
![2.png](https://qiita-image-store.s3.amazonaws.com/0/171162/c2029443-f203-4c63-5e0a-51d58f381bdc.png)

# 解決策

vscodeのtype intellisense除外設定はjavascriptの場合jsconfig.jsonに書く。

```json
{
  "compilerOptions": {
    "target": "es6",
    "baseUrl": "./src"
  },
  "exclude": ["node_modules"],
  "typeAcquisition": {
    "exclude": [/*ここに除外するものを書く*/],
  }
}

```

ただ、このexcludeにjqueryと書いたらいけるかというとそうはならない。

なぜなら、正確には```@types/jquery```が指定されてインストールされているわけではなく、他の```@types```パッケージが依存関係に```@types/jquery```を指定しているため結果的に入ってしまっているから。(ややこしい)

では具体的にどのパッケージを除外すればいいかというと、それを確認するためにまず"@types/jquery"がどこにあるかを確認する必要がある。

確認の仕方は"$"を選択して右クリック→Go to Type Definition→ファイル名が書いてあるタブにマウスをhover。

筆者の場合は
```C:\Users\{name}\AppData\Local\Microsoft\TypeScript\3.3```
の下のnode_modulesにあった。

上記の場合
```[略]\TypeScript\3.3```
に行くとおなじみのpackage.jsonがあるので、そこで以下のコマンドを打つ。(npm必須)

```
C:\Users\{user}\AppData\Local\Microsoft\TypeScript\3.3> npm ls @types/jquery
C:\Users\{user}\AppData\Local\Microsoft\TypeScript\3.3
+-- @types/urijs@1.15.38
| `-- @types/jquery@3.3.29
`-- @types/velocity-animate@1.2.33
  `-- @types/jquery@3.3.29  deduped
```

この例でいうと```@types/urijs```と```@types/velocity-animate```が```@types/jquery```を必要としているので結果的に```@types/jquery```が入ってしまっているということがわかる。

そのためjsconfig.jsonには以下のように指定すれば良い。

```
{
  "compilerOptions": {
    "target": "es6",
    "baseUrl": "./src"
  },
  "exclude": ["node_modules"],
  "typeAcquisition": {
    "exclude": ["urijs", "velocity-animate"]
  }
}
```

その後vscodeを再起動する。

# 結果
うまいこと補完されるようになった。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/171162/60821c0f-d2cf-cc8f-cc2e-6b674740cd95.png)
[Android]FDL実装でintent-filterに入るのはDeep Link方だった。

# FDL(Firebase Dynamic Links)実装依頼が来た

なぁにFDLって。ふむふむ…リンクを踏んだら**アプリのリンク先のコンテンツに直接移動**させるし、**デスクトップではウェブサイト上の同じコンテンツに移動**させてくれると…そしてアプリが**インストールされていない場合、ストア側に自動的に飛ばしてくれる。**

### めっちゃええやん！

# 実装してみたが…

じゃさっそく実装してみようか！
Firebase用のアカウント作って、プロジェクトを作って、アプリを登録して、コンソールでFDLを作ってみよう。

Dynamic Linkは *dynamichoge.page.link* として…
Deep Linkは *hogehoge.com/top* としよう。(https://とwwwは省略)

次はAndroidでIntent-filter設定が必要だな。
って、どう書けばいいのか…ぐぐってみようか。おっと出た。


```AndroidManifest.xml
<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data
        android:host="dynamichoge.page.link"
        android:scheme="https"/>
</intent-filter>
```

これでオッケーと。
で受信するActivityでリスナー付けて終了だ。

よおし、テストしてみるぞ
リンクを踏むと*ブラウザで開くか、アプリで開くか選択*が出るな。
で、アプリを方を開くと？よし*起動と画面遷移成功*だ
ブラウザを開いたら…うん？*ぐるぐるが出た後、アプリが起動して画面遷移*したぞ？
うん…次はQRコードを試してみよう。あれ、*起動はするけど画面遷移しない*ぞ？
どういうこった…

# Documentをちゃんと読もう

話はここまで。で、何が問題だったのかを先に言うとタイトル通り、intent-filterの宣言を間違ったのです。 
先にFDLの動きをざっくり書くと

FDLを踏む -> ブラウザがこれをFDLと認識し、Firebaseに投げる -> FirebaseはFDLに設定していたディープリンクにリダイレクトさせる -> アプリをインストールするなり、起動するなりする。

そして公式のDocumentの一部を見てみましょう。

<img width="897" alt="スクリーンショット 2019-03-29 17.28.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/240914/fd373350-8b7b-da7d-3f6a-84824829859f.png">


そうです。上記のコードはリダイレクトURL(ディープリンク)の*hogehoge.com/top*ではなく、ダイナミックリンクである*dynamichoge.page.link*をintent-filterに入れたのです。なんてこった。
正しく書くとこうなります。

```AndroidManifest.xml
<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data
        android:host="hogehoge.com"
        android:pathPrefix="/top"
        android:scheme="https"/>
</intent-filter>
```

公式Documentをまともに読まなかったのを反省します…
Unity + Visual Studio環境のAndroid実機デバッグ方法

# はじめに

初投稿です。
UnityのIDEにVisual Studioを利用している場合に、
Android端末を使用してスクリプトデバッグをする方法の備忘録です。
(Unity初心者なので最近のIDE主流がわからない)

# 前提条件
- Unity + Visual Studioの開発環境が構築されている
- Unity Androidのビルド環境が構築されている

# 手順

## Build SettingでDebugを許可する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93835/73aa8307-ae96-1307-2262-aac4e6a2f0b7.png)

デバッグに使用するandroid端末をPCと同じネットワークに接続させると、Run Deviceから選べるようになる。
あとはDevelopment BuildとScript Debbuggingにチェックを入れる。  
ちなみに、Wait For Managed Debuggerにチェックを入れておくと、デバッガーが起動するまでアプリの開始を待ってくれるので、アプリ起動直後の挙動を実機で確認することができる。  

## Visual Studioから実機にアタッチする

Build SettingからBuild And Runをクリックした後、アプリが起動するまで待つ。  
アプリが起動したら、Visual Studioから
Debug→Unity デバッガーのアタッチを選ぶ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/93835/92d72ddc-f9f7-e3cf-cf1a-f365f2dd254f.png)

ここからデバッグに使用してる端末を選択すると、デバッグ状態になる。
Webpacker v4で同一CSSなのにfingerprintが変わってしまう問題に対処する

## 発生していた問題

Webpacker 4.0.2を使ったRailsアプリケーションを本番環境にデプロイすると、CSSやJSの内容を変更していないのに毎回fingerprintの値（`application-a72ac9c7.css`の`a72ac9c7`の部分）が変わってしまう。

fingerprintがデプロイのたびに変わると、ブラウザのキャッシュ効率が悪くなるという問題が発生するが、それ以上に複数台のサーバーにデプロイするときにCSSのファイル名が一致しない問題の方が深刻だった。

なぜファイル名が一致しないのかというと、デプロイのたびにファイル名が変わるので、複数台のサーバーにデプロイしたときにもサーバーごとにファイル名が異なってしまうから。

アクセスしたタイミングによって参照するCSSファイル名が異なるため、CSSファイルの404エラーが発生し、画面の表示が崩れてしまうという問題が起きていた。

### 問題が発生していた実行環境

- Rails 5.2.2.1
- Webpacker 4.0.2
- css-loader 2.1.1 (JSモジュール)

## 問題の原因

この問題が発生したのは以下のような複数の条件が重なっていたせいだった。

- Webpacker v4を使っていた（バージョン3系では発生しない）
- assets:precompile時にソースマップを生成するようになっていた（＝デフォルト設定）
- 複数台のサーバーにデプロイする際、デプロイ先のディレクトリ名にタイムスタンプが含まれていた（つまり、デプロイ先のパスがサーバーごと、またはデプロイごとに異なっていた）

なぜ、これが問題になるのかというと、

ソースマップ生成時に絶対パスの値（＝タイムスタンプに依存する値）が含まれる
　↓
fingerprintのハッシュ値は、ソースマップを含めたファイル全体の内容から算出する
　↓
つまり、サーバーごと（またはデプロイごと）にCSS（＋ソースマップ）の内容が異なる = fingerprintも異なる

というロジックになっているため。

## 解決策
根本的な対応としては「ソースマップ生成時に絶対パスではなく相対パスを使用すること」になる。
だが、これはcss-loaderの修正が必要であり、記事執筆時点（2019年03月29日、css-loaderの最新バージョン 2.2.1）では以下のissueで議論はされているものの、まだcloseされていない。

[Setting sourceMap: true generates different content hashes on Linux vs MacOS · Issue \#886 · webpack\-contrib/css\-loader](https://github.com/webpack-contrib/css-loader/issues/886)

そこで、今回は応急処置として「ソースマップを生成しない」という設定を入れることにした。

### 手順

webpack-mergeをインストールする。

```
$ yarn add webpack-merge
```

`config/webpack/production.js`に以下の変更を加える（[参考](https://github.com/rails/webpacker/blob/master/docs/webpack.md#overriding-loader-options-in-webpack-3-for-css-modules-etc)）。

```diff:config/webpack/production.js
 process.env.NODE_ENV = process.env.NODE_ENV || 'production'
 
+const merge = require('webpack-merge')
 const environment = require('./environment')
 
+const myCssLoaderOptions = {
+  sourceMap: false,
+}
+const CSSLoader = environment.loaders.get('sass').use.find(el => el.loader === 'css-loader')
+CSSLoader.options = merge(CSSLoader.options, myCssLoaderOptions)
+
 module.exports = environment.toWebpackConfig()
```

この対応で複数台のサーバーにデプロイしてもfingerprintの値が変わらないようになった😄

## 謝辞
一緒にこの問題の解決策を調査してくれた弊社ソニックガーデンのメンバーと、原因と解決策を見つけてくれた@maedanaに感謝します。
Node.js＆GraphQL part4 ~ Prisma APIとAsync/Await ~


## Prisma API と Promise Chain

以下のような Type を定義して、新しくPostを作成する。

```:datamodel.prisma
type User {
  id: ID! @unique
  name: String!
  email: String! @unique
  posts : [Post!]!
}

type Post {
    id: ID! @unique
    title: String!
    body: String!
    published: Boolean!
    author: User!
}
```


```javascript:prisma.js
import { Prisma } from 'prisma-binding'

// prisma: Prisma configuration object
// Prisma: Its constructor creates connection to Prisma endpoint
const prisma = new Prisma({
    typeDefs: 'src/generated/prisma.graphql',
    endpoint: 'http://xxx:4466',
})

/**
 * prismaオブジェクトは基本操作を行う4つのオブジェクトをもつ
 * 1. prisma.query
 * 2. prisma.mutation
 * 3. prisma.subscription
 * 4. prisma.exists
 *
 * それぞれクエリを行うためのメソッドを持っており2つの引数を必要とする
 * 1. Operation Argument
 * 2. Selection Set
 *
 * Promiseをreturnする
 */

// async はPromiseを返します
const createPostForUser = async (authorId, data) => {

    // 新しい Post を作成する
    // その際に、その Post を作成した User を authorId で指定する
    // 作成した Post の id を return させる
    const post = await prisma.mutation.createPost({
        data: {
            ...data,
            author: {
                connect: {
                    id: authorId
                }
            }
        }
    }, '{ id }')

    // 上で使用した authorId と一致する id をもつ Usedr を取得する
    const user = await prisma.query.user({
        where: {
            id: authorId
        }
    }, '{ id name email posts { id title published } }')

    // async なので Promise として resolve する
    return user
}

// 新しく作成する Post の情報と、Post を作成した User の id を引数に渡してメソッドを呼ぶ
// Promise が返ってくるので .then でつなげられる
createPostForUser("cjttne201003s0720tlslaqz8", {
    title: "Great Book",
    body: "Very GOOOOOOD!",
    published: true
})
.then( data => console.log(JSON.stringify(data, undefined, 2)))
```

```:出力
{
  "id": "cjttne201003s0720tlslaqz8",
  "posts": [
    {
      "id": "cjttsih2a006r0720nesau8xd",
      "title": "Great Book",
      "body": "Very GOOOOOOD!",
      "published": true
    }
  ]
}
```

Async/Await でスッキリす。



本当は2回もawait使う必要なかったけども。


```javascript:prisma.js(await1回ver)
import { Prisma } from 'prisma-binding'

const prisma = new Prisma({
    typeDefs: 'src/generated/prisma.graphql',
    endpoint: 'http://xxx:4466',
})

const createPostForUser = async (authorId, data) => {
    const post = await prisma.mutation.createPost({
        data: {
            ...data,
            author: {
                connect: {
                    id: authorId
                }
            }
        }
    }, '{ author { id name email posts { id title published } } }')
    return post.author
}

createPostForUser("cjttne201003s0720tlslaqz8", {
    title: "Great Book",
    body: "Very GOOOOOOD!",
    published: true
})
.then( data => console.log(JSON.stringify(data, undefined, 2)))
```
Arch Linux で pdf.js を使う

1) インストール

```bash
pacman -S pdfjs
```

/usr/share/pdfjs にインストールされます。

2) Web サーバーでアクセスできるところにシンボリックリンクを張る

```bash
ln -s /usr/share/pdf.js/ .
```

>例えば /var/www/tmp/mar29 にシンボリックリンクを作成します。

3) http://localhost/tmp/mar29/pdf.js/web/viewer.html にアクセス
![viewer01.png](https://qiita-image-store.s3.amazonaws.com/0/179446/97e834c5-791b-d1b9-df09-fa68ea42e8de.png)

4) /var/www/tmp/mar29 に cities.pdf というPDFを置きます。
http://localhost/tmp/mar29/pdf.js/web/viewer.html?file=../../cities.pdf にアクセス
![viewer02.png](https://qiita-image-store.s3.amazonaws.com/0/179446/b29dc304-4366-e715-1ca7-dac5cfd45bfc.png)

5) iframe を使って２枚のPDFを表示してみました。
https://ekzemplaro.org/oyama/
![pdf_apr02.png](https://qiita-image-store.s3.amazonaws.com/0/179446/36fcc358-f206-1e25-a59d-9eeaff661949.png)
[C++]主要な文法メモ

# C++の文法メモ

C++を勉強しようと思ったけれど文法が難しい。
自分のために文法のメモを残す。

## クラス

クラスの基本的な概念は様々な資料がありますのでここでは省略致します。
取り急ぎ変数と処理をひとかたまりのプログラムにまとめたものをクラスと呼びます。

~執筆中

## テンプレート
変数やクラスの型が変わっても一つの関数やクラスで処理を実行するための機能

### テンプレート関数
関数の引数や戻り値の型が変わっても対応できるようにする
一旦、何が入るかわからない仮の型を宣言しファンクションを作成する。
ファンクションを使用するときに引数や戻り値の型が決定されるようにプログラムする。

#### 関数の引数を仮の型にする

```C++:template
template<class 任意型名>　　//この任意型名が仮の型になる
型 関数名(任意型名 引数)　　　
{
　～コマンド～
}
```

引数aに1をプラスするプログラムを作って挙動を確認してみます
引数aの型をintとdoubleのどちらが来ても計算できるようにします

```C++:Example_template.cpp

template<class T> //なんでもよい型Tを宣言
int add(const T c)　//引数の型は何でもよいT、戻り値は整数で固定
{
	return c + 1;
}

int main()
{
	//整数
	int a=1;
	std::cout << add(a) << "\n";

	//実数
	double b = 1.5;
	std::cout << add(b);
}
```

#### 関数の戻り値も仮の型にする

```C++:template2
template<class 任意型名>
任意型名 関数名(任意型名 引数)
{
　～コマンド～
}
```

引数aに1をプラスするプログラムを作って挙動を確認してみます
引数と戻り値の型をintとdoubleのどちらが来ても計算できるようにします


```C++:Example_template.cpp

template<class T>
T add(const T c) //戻り値の型をTにしました
{
	return c + 1;
}

int main()
{
	int a = 1;
	std::cout << add(a) << "\n";

	double b = 1.0;
	std::cout << add(b) << "\n";
}
```

##### ダメな例

引数と戻り値の型を別々にするとエラーになります
多分戻り値の型が決まらないから？

```C++:Example_templateError.cpp
//引数の型はT、戻り値の型はU
template<class T>
template<class U>
U add(const T c)
{
	return c + 1;
}

//mainはExample_template.cppと同じ
```


```エラーメッセージ
重大度レベル	コード	説明	プロジェクト	ファイル	行	抑制状態
エラー	C2568	'<<': オーバーロード関数のうち、どれを呼び出すのか決定できません。	
エラー	C2568	'<<': オーバーロード関数のうち、どれを呼び出すのか決定できません。	
エラー	C2065	'add': 定義されていない識別子です。	
エラー	C2065	'add': 定義されていない識別子です。
エラー	C3857	'add': 複数の テンプレート パラメーター リストは使用できません	
エラー (アクティブ)	E0777	この宣言では複数の 'template <...>' 句を使用することはできません	
```

**追記**
コメントにてaeioaeu様から正しい方法をお教えいただきました！
aeioaeu様本当にありがとうございます。

+ templateの宣言は二つの任意型をカンマで区切らないといけませんでした
+ ファンクションを呼び出すときに戻り値の型を指定しないといけませんでした

```C++:Example_template2.cpp
template<class U, class T>  //templateの宣言は二つの任意型をカンマで区切って宣言
U add(const T c)
{
	return c + 1;
}


int main()
{
	int a = 1;
    std::cout << add<int>(a) << "\n";   //addファンクションを使うときに<>内に戻り値の型を指定する

	double b = 1;
	std::cout << add<double>(b) << "\n";　　//addファンクションを使うときに<>内に戻り値の型を指定する
}

```


### テンプレートクラス

クラスにもテンプレートが使用できます

#### メソッドの引数を仮の型にする

```C++
template<class 任意型名>
class クラス名{
    public:メソッドの戻り値の型　メソッド名(任意型名　引数){
        ～コマンド～
}

int main(){
    クラス名<任意型名> インスタンス名;

    ～コマンド～
}
```

```c++:templateClass
//引数aに1をプラスするプログラム
//引数と戻り値の型をintとdoubleのどちらでも良いようにする

#include <iostream>

template<class T>
class add {  
public:int oneAdd(T c) {  //メソッドの戻り値はint、引数はインスタンスに依存
	return c + 1;
}
};

int main()
{
	int a = 1;
	add<int> add1;
	std::cout << add1.oneAdd(a) << "\n";
}

```

## 継承

執筆中
JSFのdataTableで選択行のデータを取得

JSFのdataTableで作成した一覧から選択行のデータを取得する方法をメモ。
ほとんどおまじないみたいなものですが……。

```ruby:TestCBb
// 選択行データ取得
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext exContext = context.getExternalContext();

@SuppressWarnings("rawtypes")
Map map = exContext.getRequestMap();
SelectDataInfo selectData = (SelectDataInfo)map.get("m");
```

すこしだけxhtmlの内容にかかっているので、
xhtmlの内容も追記しておきます。

```ruby:xhtml
<h:dataTable value="#{TestCBb.pageData}" var="m" styleClass="list">
  <h:column headerClass="header">
    <f:facet name="header">見出し1</f:facet>
    <h:outputText value="#{m.value1}" />
  </h:column>
  <h:column headerClass="header">
    <f:facet name="header">見出し2</f:facet>
    <h:outputText value="#{m.value2}" />
  </h:column>
  <h:column headerClass="header">
    <f:facet name="header">見出し3</f:facet>
    <h:outputText value="#{m.value3}" />
  </h:column>
</h:dataTable>
```

もちろんTestCBb.pageDataの型はSelectDataInfoをListにしたものです。
要するに、
　SelectDataInfo selectData = (SelectDataInfo)map.get("m");
のmはdataTableで設定した名前を持ってきているというだけなんですが……。
すぐ忘れそうなのでメモ。
Gradle BOM importでAndroidのライブラリバージョン管理

## はじめに
Gradle5.0から正式にBOM(bill of materials)ファイルの読み込みに対応しました。
まだ提供されているライブラリは多くないですが、このBOMファイルによってライブラリ毎のバージョン定義を省くことができるようになります。
参考: https://docs.gradle.org/5.0/userguide/managing_transitive_dependencies.html#sec:bom_import

## Before

```gradle

dependencies {

    // Kotlin
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version_kotlin"
    implementation "org.jetbrains.kotlin:kotlin-test-junit5:$version_kotlin"

    // Firebase
    implementation 'com.google.firebase:firebase-core:16.0.8'
    implementation 'com.google.firebase:firebase-storage:16.1.0'
    implementation 'com.google.firebase:firebase-config:16.4.1'
    implementation 'com.google.firebase:firebase-invites:16.1.1'
    implementation 'com.google.firebase:firebase-messaging:17.5.0'
    implementation 'com.google.firebase:firebase-firestore:18.2.0'
    implementation 'com.google.firebase:firebase-dynamic-links:16.1.8'
    implementation 'com.google.firebase:firebase-perf:16.2.4'
    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.3'

    // OkHttp
    def version_okhttp = '3.12.2'
    implementation "com.squareup.okhttp3:okhttp:$version_okhttp"
    implementation "com.squareup.okhttp3:logging-interceptor:$version_okhttp"
    testImplementation "com.squareup.okhttp3:mockwebserver:$version_okhttp"
}
```

## After

```gradle
dependencies {

    // kotlin
    implementation platform('org.jetbrains.kotlin:kotlin-bom:1.3.61')
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    implementation 'org.jetbrains.kotlin:kotlin-test-junit5'

    // Firebase
    implementation platform('com.google.firebase:firebase-bom:16.0.0')
    implementation 'com.google.firebase:firebase-core'
    implementation 'com.google.firebase:firebase-storage'
    implementation 'com.google.firebase:firebase-config'
    implementation 'com.google.firebase:firebase-invites'
    implementation 'com.google.firebase:firebase-messaging'
    implementation 'com.google.firebase:firebase-firestore'
    implementation 'com.google.firebase:firebase-dynamic-links'
    implementation 'com.google.firebase:firebase-perf'
    implementation 'com.crashlytics.sdk.android:crashlytics'

    // OkHttp
    implementation platform('com.squareup.okhttp3:okhttp-bom:3.12.2')
    implementation 'com.squareup.okhttp3:okhttp'
    implementation 'com.squareup.okhttp3:logging-interceptor'
    testImplementation 'com.squareup.okhttp3:mockwebserver'
}
```

Kotlin Libraries Bill of Materials: https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-bom
Firebase BOM: https://mvnrepository.com/artifact/com.google.firebase/firebase-bom
OkHttp (Bill of Materials): https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp-bom
KotlinのtakeIf、takeUnlessを使う

元本 : "[Using Kotlin takeIf(or takeUnless)](https://medium.com/@elye.project/using-kotlin-takeif-or-takeunless-c9eeb7099c22)"
`takeIf`と`takeUnless`のことを調べていたら、上記に良い記事があったので、自分なりに頑張って翻訳してみました。

Kotlinの[標準関数](https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/util/Standard.kt)には、If文のような`takeIf`と`takeUnless`という２つの関数があります。

次の例文のようにIf文の代わりに使う場合があります（オススメしません）

```kotlin
// Original Code
if (status) { doThis() }

// Modified Code
takeIf { status }?.apply { doThis() }
```

# takeIfとtakeUnlessについて
例文の`takeIf`と`takeUnless`をどうやって使うかの前に`takeIf`の関数の定義をみてみましょう。

```kotlin
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? 
    = if (predicate(this)) this else null
```

上記のtakeIfを見ると、次のような特徴があるのがわかります。
・ この関数はTオブジェクト自身から呼び出される。つまり、`T.takeIf`で使える
・ takeIfの条件関数の`predicate`はパラメーターとして`T`オブジェクトを受け取る
・ `takeIf`の条件関数の`predicate`の結果によって`T`オブジェクトのthisやnullを返す

`takeUnless`関数は`takeIf`関数とは逆に動作します。 `takeUnless`は条件関数が`true`の場合`null`を返し、`false`の場合thisを返します。

```kotlin
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? 
    = if (!predicate(this)) this else null
```

# 使い方
上記の特徴を元に下記のようなif文コードに相応する`takeIf`関数の使い方がわかります。

## 1. この関数はTオブジェクト自身から呼び出される。つまり、T.takeIfで使える。
nullをチェックし、結果によって作業を実行する利点があります。

```kotlin
// Original code
if (someObject != null && status) {
   doThis()
}
// Improved code
someObject?.takeIf{ status }?.apply{ doThis() }
```

## 2. takeIfの条件関数 predicate はパラメーターとして T オブジェクトを受け取る
`predicate`関数のパラメーターとしてTオブジェクトを使う場合、もっと単純にコードの作成ができます。

```kotlin
// Original code
if (someObject != null && someObject.status) {
   doThis()
}
// Better code
if (someObject?.status == true) {
   doThis()
}
// Improved code
someObject?.takeIf{ it.status }?.apply{ doThis() }
```
上記の改良されたコードのように作成もできますが、オリジナルコードでは使っていなかった追加キーワードの`true`との比較が必要です。ですが、これは最適なコードではありません。

## 3. takeIfの条件関数 predicate の結果によって T オブジェクトのthisやnullを返す
takeIfの条件関数の`predicate`の結果がtureの場合thisを返すので、これを利用して演算を繋いで処理するチェーンリング技法が使えます。
従って、下記のようなコードに改良できます。

```kotlin
// Original code
if (someObject != null && someObject.status) {
   someObject.doThis()
}
// Improved code
someObject?.takeIf{ status }?.doThis()
```
または[Kotlin Doc](https://kotlinlang.org/docs/reference/whatsnew11.html#also-takeif-and-takeunless)の例のように`takeIf`関数が条件に満たされない場合、`null`を返す特性を利用してあるデータを返したりエルビス演算子(?:)を使って関数を終了させる時にも使えます。

```kotlin
// takeIfの条件が満たされなかったらエラーを返す
val index 
   = input.indexOf(keyword).takeIf { it >= 0 } ?: error("Error")
// takeIfの条件が満たされなかったらreturnし、終了する
val outFile 
   = File(outputDir.path).takeIf { it.exists() } ?: return false
```

# 注意点
次のようなコードの場合は注意が必要です。

```kotlin
// 構文的には正しいです。ですが、論理的には間違っています。
someObject?.takeIf{ status }.apply{ doThis() }
// 正しい例文です。(applyの前の演算子 "?." に注意が必要です)
someObject?.takeIf{ status }?.apply{ doThis() }
```

一列目の例文では`apply`関数は`takeIf`関数が`null`を返しても呼び出されるため、`status`の`true`、`false`と関係なく`doThis()`関数が実行されます（この例の`doThis()`は`someObject`の関数ではありません。）
`takeIf`関数の後ろに存在する演算子"?."を付けることによって結果が大きく異なるため、論理的にはとても重要です。
Gitが怖くなくなりました！(たぶん)　〜Udemy感想その３〜

# 概要
プログラミング初心者が1年くらいUdemyで勉強した
講座とその感想を書いていくぞのその３です

今回は[もう怖くないGit！チーム開発で必要なGitを完全マスター](https://www.udemy.com/unscared_git/)の感想を書きます

ちなみに[その１](https://qiita.com/Shinichiro_Matsuzawa/items/1d886c4af99421b17e83)と[その２](https://qiita.com/Shinichiro_Matsuzawa/items/48e053e81ee9badb6f1d)

# 使った講座

[もう怖くないGit！チーム開発で必要なGitを完全マスター](https://www.udemy.com/unscared_git/)

基本的なコマンドの使い方やGitHubの使い方、またコマンドを入力した時に
どのようなことが起きているのか、どんな仕組みになっているのかなどを
図を使いながらかなりわかりやすく教えてくれます

たぶんGitを全く触ったことなくてもこの講座を見れば基本的な使い方は理解できるはず！

# その頃の自分
「どうもエンジニアはみんなGitHubってのに自分の書いたコードを載せてるらしい。。。」
「就活用のフォームでもGitHubのURL貼るとこあるし一応作っとくか。。。」
「GitとGitHubは違うもの？？？」
「よくわからんけどinitしてaddしてcommitすればいいのかな。。。」

こんなレベルでした笑
何にもわかってなかったです

なのでとりあえずネットに書いてある通りにコマンド入力して、
エラーが出てもネットに書いてある通りの解決法でなんとかする

実際に自分が何をするコマンドを入力しているのかよくわかってなかったと思います

# 良かった点
 - **Gitにたくさん触れた**

それまでずっと独学でプログラミングを勉強してきて
なかなかGitを触る機会がなかったんですよね

エンジニアからすればGitを使うのが当たり前なのかもしれないですけど
正直使い方わからないし、あんまり恩恵感じないし、、、

ただでさえ勉強中にエラーでまくるんだからGitでもエラーなんて勘弁してくれって感じでした

当たり前ですけどGitの講座なのでGitコマンドをたくさん入力します
たくさん使っていく中でよく使うコマンド、一般的な流れなんかが理解できました

 - **仕組みがわかった**

それまではaddはcommitするためにしなきゃいけない、コメントはcommitするために書かなきゃいけないなど、今自分は何をしてるのか、何のためのコマンドなのかが全然理解できていませんでした

この講座の中ではワークツリー、ステージ、リポジトリのどこで変更したとかどこで記録したとか1つ1つを細かく解説してくれているでコマンドを打ち込んだ時に裏側では何が起こっているのかを初めて理解することができました

この講座を終えてから、自分で開発をしているときに何度かうまくいかなかったことがありましたが、その時は講座に戻って今一度ワークツリー、ステージ、リポジトリのどこで何が起こって今問題が起きているのか考えるようになりました

こないだもconflictしましたが(一人でやってるのに。。)すぐに解決できました
以前ではよくわからずググるだけだったと思います

 - **スライドがわかりやすい** 

とてもわかりやすいです
しかもPDFでダウンロードできます
僕はGitで躓いたらとりあえずこれをみてます

# 今ひとつな点
これも特に文句はないような、、

ただ僕がまだチーム開発をしたことがないので、チーム開発で必要な力が身についているかはまだわかりません

# まとめ
やり終えてからもGitで悩んだらとりあえず講座に戻って、というような
辞書的な使い方をしてます

優しく教えてくれてるのでGit触ってみたけどよくわからんって人にはおすすめです
ldapsearchの検索メモ

# ldapsearchの検索メモ

最近LDAPのユーザー検索、ユーザー属性追加・削除などの操作をやっていました。
自分の理解を深くするために、整理してメモを書きます。

### ユーザー検索

LDAPの中、対象ユーザーの全ての情報を出力する場合：

```
ldapsearch -x -h localhost -D "cn=Manager,o=company,c=jp" -b "uid=test1111,ou=users,o=company,c=jp" -w "password"
```

ldapsearchの各オプションの詳細説明は、[ldapsearch](http://software.fujitsu.com/jp/manual/manualfiles/M050000/B1WN4911/01/idmgrae/idmgr764.htm)を参考しました

対象ユーザーのuid番号だけを出力する場合：

```
ldapsearch -x -h localhost -D "cn=Manager,o=company,c=jp" -b "uid=test1111,ou=users,o=company,c=jp" -w "password" uid | grep ^uid`
```


### ユーザー属性の追加

例：ユーザー情報にメールアドレスを追加

```
ldapmodify -x -h localhost -D "cn=Manager,o=company,c=jp" -f modify1.ldif -w 'password'
```

modify1.ldifの内容

```
dn: uid=test1111,ou=users,o=company,c=jp
changetype: modify
add: mail
mail: test@test.co.jp
```


### ユーザー属性の削除

例：ユーザー情報にメールアドレスを削除

```
ldapmodify -x -h localhost -D "cn=Manager,o=company,c=jp" -f modify2.ldif -w 'password'
```

modify2.ldifの内容

```
dn: uid=test1111,ou=users,o=company,c=jp
changetype: modify
delete: mail
```


### ユーザー属性の更新

例：ユーザー情報にメールアドレスを更新

```
ldapmodify -x -h localhost -D "cn=Manager,o=company,c=jp" -f modify3.ldif -w 'password'
```

modify3.ldifの内容

```
dn: uid=test1111,ou=users,o=company,c=jp
changetype: modify
replace: mail
mail: test2@test.co.jp
```

### 複数ユーザーの複数属性を一括変更

例：
ユーザーtest1111にメールアドレスを更新と会社の追加を実施
ユーザーtest1112にメールアドレスを更新と部門の変更を実施

```
ldapmodify -x -h localhost -D "cn=Manager,o=company,c=jp" -f modify4.ldif -w 'password'
```

modify4.ldifの内容

```
dn: uid=test1111,ou=users,o=company,c=jp
changetype: modify
replace: mail
mail: test2@test.co.jp
-
add: o
o: テスト会社

dn: uid=test1112,ou=users,o=company,c=jp
changetype: modify
replace: mail
mail: test1112@test.co.jp
-
replace: ou
ou: 人事部
```


### LDAPから対象ユーザーリストのUIDを取得する

DBに格納されるユーザーのUIDとLDAPにマッピングしたい場合、

##### 検索対象ユーザーのUIDリストを用意

userlist.csv

```
 test1111
 test1112
 test1113
```

##### 検索用シェル

```
#!/bin/bash

numLine=0
users_csvfile=userlist.csv
for line in `cat ${users_csvfile}` ## | while read line
do
 uid=$line
 result=`ldapsearch -x -h localhost -b c=jp "uid=$uid" uid | grep ^uid`
 echo $result >> result.txt
 numLine=$((numLine + 1))
 if [[ $((numLine % 3)) == 0 ]]; then　　　# 検索対象ユーザーが多い場合、LDAPサーバの負荷を考える必要がある
   echo $numLine: "3件を取得しました。"      # 3件ずつを取得後、1秒を停止
   sleep 1s
 fi
done
```

これで検索された結果をresult.txtに出力される
NMFで画像を分解

みなさん、NMF(Non-negative Matrix Factorization：非負値行列因子分解)って知ってますか？
知ってましたか．．．では、何に使ってますか？

今回、とあるシーンで使ってみたところ、意外と使えました。
でもやっぱり目で見て感動したかったので、画像の分解で使ってみました。

# NMFとは

アチラコチラで説明はいっぱい書かれていますので、詳しい解説は省略します。

ざっくりとした説明ですが、ある行列を2つの行列に分解します。
このとき、分解される行列をR（MxNの行列）とし、分解後の2つの行列をP（FxNの行列）とQ（FxMの行列）とします。
このとき、「F」が分割数になり、いわゆる「特徴」を表すことになります。
「次元圧縮」とも言われたりします。

絵で書くとこんな感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/c4692cc9-e063-87e8-c97d-cdcb0a3fa0a4.png)

でも、数学をやっている人的には違和感がある図ですので、ちゃんと式にしてみます。

```math
R \approx P \times Q^{T}
```

※実際には正確に分解できるわけではないので、「＝」にはなりません


# 画像に適用すると？

これを画像に使ってみます。
といっても、Rは一枚の画像を表すわけではなく、複数枚の画像を表します。
つまり画像を2次元から1次元に変換し、画像枚数で2次元化します。

例えばMNISTの場合だと、28x28の画像ですので784になり、これを60,000枚使ったとすると、行列Rは
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/4e0fd628-222e-2b1a-7acc-93fb21692214.png)
となります。

これを使ってNMFを実行すると、Pはどうでもいいとして、Qには60,000枚の画像データを学習して抽出したF枚の「特徴画像」が出来上がります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/a0d1068b-95e7-57de-b0e4-0737f61b5e21.png)

今回はそれを眺めて感動（笑）したいと思います。

# MNISTで試してみる

MNISTとは．．．はいいですね ^^;
0～9の手書き文字のデータセットです。

ちなみに、開発・実行はJupyter Notebook上で行っています。

```python
%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt

from sklearn.decomposition import NMF

import keras
from keras.datasets import mnist
```

まずはこんな感じでモジュールを読み込みます。
MNISTデータはkerasで読み込み、NMFはscikit-learnを使いたいと思います。
特徴画像はmatplotlibで表示します。

```python
# MNISTデータの取得
(x_train, _), (_, _) = mnist.load_data()

x_train = x_train.reshape(-1, 784) # 2次元配列を1次元に変換
x_train = x_train.astype('float32')   # int型をfloat32型に変換
x_train /= 255                        # [0-255]の値を[0.0-1.0]に変換
print(x_train.shape[0], 'train samples')
```

MNISTデータを読み込みます。
テスト用とかカテゴリとかはいらないので読み込みません。
また、numpy配列にしてから、0.0～1.0に変換しています。

```python
# 分解数
n_components = 4

# 分解
model = NMF(n_components=n_components, init='random', random_state=0) # n_componentsで特徴の次元を指定
P = model.fit_transform(x_train) # 学習
Q = model.components_
```

NMFで分解します。
とりあえずここでは4つに分解してみました。
最後の「Q」を使用します。

```python
# 28x28の画像に変換
Q_image = Q.reshape(n_components, 28, 28)

# 画像の表示
fig = plt.figure(figsize=(18, 12))
for i in range(0, n_components):
    ax = fig.add_subplot(1, n_components, i+1)
    ax.imshow(Q_image[i])

plt.show()
```

Qを28x28になおして、画像を表示してみると、こうなりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/48350c20-188e-5ec6-d825-3646f3296344.png)

0～9の数字は、「0」「3」「9」「1」で表せるようです（嘘）
正直、もうちょっとぐちゃぐちゃな画像になるかと思ったので、意外でした。

# もっと試してみる

では「10個に分割したら、ちゃんと0～9になるんじゃね？」ということで、試してみました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130771/ed19f89a-47a8-b07d-2493-215aad4f633f.png)

世の中、そんなに甘くはないです。
もっと別の特徴を見つけ出してくれたようです。
ということは、10進法はベストな数字の分割数ではないのかもしれませんね．．．
※形状だけでのお話ですが (￣ー￣)ﾆﾔﾘ

そんな中でも、「3」「6」「7」「9」あたりは特徴的な形状のようです。

# 使ってみての感想

非常に簡単に特徴抽出できるのは嬉しいのですが、固定値で分割数を指定しなくてはいけないのが、ちょっと気持ち悪いですね～
Python奮闘記①

こんにちは。
未来電子テクノロジー(https://www.miraidenshi-tech.jp/intern-content/program/)
でインターンをしているodattiです。

僕は今、Progateというオンライン教材でプログラミングを学習しています。
先週からPythonを勉強しています。

まだPythonを学び始めて間もないのですが、Pythonを使ってみた率直な感想をまとめます。

#面白い！！
Pythonが二つ目の言語なのですが、これまで学んでいたHTMLとCSSとは特性が全く違うというのが率直な感想です。

コードがより数学的という印象を受けました。
たとえば、変数や代入といった考え方です。

#学習教材が作れそう！
かなり安直な発想ではありますが、Pythonを使って算数や一問一答系の学習教材が作れるかもしれないと思いました。

また、Pythonは分類に優れた言語だと感じています。
何かしらのリストを管理することもできるのかもしれません。

#まとめ
まだPythonの学習は始まったばかりなのですが、これから「あれできそう！これもできそう！」という気づきを増やしていきたいです。
それがプログラミングを学ぶ自分のモチベーションにもなっています。

Pythonを学ぶ上でおすすめのサイトや参考図書があれば、ぜひ教えてほしいです！
[メモ]Squid で Proxy サーバーを立てて Proxy 経由でアクセスする

メモ。
AmazonLinux2 を使って squid をインストールし、squid を経由してアクセスしてみたときのメモ

# Proxy(Squid)

```bash
# install と起動、自動起動設定
$sudo yum install squid
$sudo systemctl start squid
$systemctl enable squid
Created symlink from /etc/systemd/system/multi-user.target.wants/squid.service to /usr/lib/systemd/system/squid.service.

# デフォルトは 3128 で listenしている
$cat /etc/squid/squid.conf |grep 3128
# Squid normally listens to port 3128
http_port 3128
```

これで OK.
アクセスログは以下を監視する。

```bash
$tail -f /var/log/squid/access.log
```

# クライアント側

以下のような感じで Proxy を経由してリクエスト

```bash
$curl -vvv --proxy http://[squid private IP]:3128 https://www.google.co.jp
```

これで Proxy のアクセスログが記録され、レスポンスも返却される
クライアントは PrivateSubnet に配置して Proxy  経由でリクエストするとかが可能
Swift5で文字列補間がカスタマイズ可能に


Swift5がリリースされてざっと一通り目を通して、良くわからなかったのが

SE-0228 Fix ExpressibleByStringInterpolation
https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md

これです。

英文（読めない）をチラ見していると、以下のように`format:`で文字列補間の際にフォーマットを指定できるようになったのかな？と思ったのですが

```swift:
// Use printf-style format strings:
"The price is $\(cost, format: "%.2f")"

// Use UTS #35 number formats:
"The price is \(cost, format: "¤###,##0.00")"

// Use Foundation.NumberFormatter, or a new type-safe native formatter:
"The price is \(cost, format: moneyFormatter)"

// Mimic String.init(_:radix:uppercase:)
"The checksum is 0x\(checksum, radix: 16)"
```

どうやら「フォーマットを指定できるようになった」のではなく、「フォーマットを指定するようなことも出来るようになった」という一例のようです。

自分で適当に組んだ感じでは

```swift:
import UIKit

extension String.StringInterpolation {
    mutating func appendInterpolation<Value: CVarArg>(_ number: Value, format: String) {
        appendInterpolation(String(format: format, number))
    }
}

print("\(1.2456, format: "%.2f")") // 1.25

```

このように`String.StringInterpolation`型の`appendInterpolation`関数をオーバーロードしてやることで、好きな拡張を行うことができるようになったようです。

使い分けに関しては他の方の記事に期待します😊

参考：
https://github.com/twostraws/whats-new-in-swift-5-0/blob/master/Whats-New-In-Swift-5-0.playground/Pages/Customizing%20string%20interpolation.xcplaygroundpage/Contents.swift
はじめてのpandas

pandasを使い始めたので、忘備録的に書いていく。

#pandasって何？
csvとか一定の規則性を持って書かれたファイルを取り扱うのに便利なpythonライブラリ。
numpyだと扱えない文字列とかも取り扱える。
データの整理とかに便利らしいので使ってみることにした。

#pandasをインポート
```python
import pandas as pd
```

#データを読み込む
- 列がカンマで分けられているとき

```python
hoge = pd.read_csv("hoge.csv")
```

- タブキーで分けられているとき

```python
hoge = pd.read_table("hoge.txt")
```
- スペースや空白で分けられているとき

```python
hoge = pd.read_csv("hoge.txt", delim_whitespace=True)
```

- その他何らかの文字で分けられているとき

```python
hoge = pd.read_csv("hoge.txt", sep="なにか区切り文字")
```

#列を呼び出す
```python
hoge[['任意の列タイトル１','任意の列タイトル２',…]]
```
ツール開発の遅れに対する対策としてやったこと

# 背景
ツールのテストが様々な事情で遅れて締め切りに間に合わない状況になってきた。:cold_sweat:  
その時の対策を以下に書く。
# 行ったこと
## 自分一人でやっていたテスト作業を２名アサインしてもらった。  
- メリット  
    - テストと障害修正で項目消化に時間がかかっていたが、自分のやることが修正だけになったので項目消化のスピードが上がった。
    - 第三者検証の効果も得られた。
- デメリット  
    - 最初、新メンバに説明するのに時間がかかった。ただし、テストに加わった一名は、プロトタイプ作成で関わっていたため、説明や作業の仕方のフォローをしてもらえた。  

## テストで検出されたインシデントをGitLabのissue に入れてもらった。
障害管理が楽になった。記録に残るので障害傾向もわかりやすくなった。  

## GitLab issue を分析して、期間内に終わらすための優先度をつけた。
issue を Excelにコピペして、影響度と期間内で実施するか否かをまとめた。
あとで、障害傾向から、テスト完了見込みの資料として利用とした。

- 優先度の基準  
  使われる機能に影響するか否か
- Excel の例  
　　　　　　  　　　　　　　　　　　　●：修正済み、◎:修正確認待ち、○：修正する、
                                  △：時間があれば修正、-:対応しない

| 番号|タイトル　             | 障害内容、見解など               |影響度|対応　　 |
|:----|----------------------|--------------------------------|------|--------|
| #21 |○○オプションが動かない  | ××処理の誤り                    |あり  |○       |
| #19 |〇〇機能が動かない      |××処理の誤り。次工程では使わない。 |なし  |-       |
| #10 |△機能で不要なメッセージ|△△処理の誤り。機能自体は動くので影響はほとんどない|小 |△ |
|...  |...                   |...                             |...   |...     |

## 感想
作業に追われるだけでなく、**振り返り**が大事。周りと**相談**することも大事。

## 今後
GitLab のissueにはいろいろな機能があるそうなので、時間があったら活用してみたい。

## 参考
https://qiita.com/yakumo/items/48a06b4650ef768ee4b0
Solaris11にバージョンアップ後、TCP接続が失敗するようになった

Solaris11.3にバージョンアップ後、ネットワーク接続数が多くなると、ソケット接続が失敗する現象が稀に発生し、処理をやり直すことになりました。原因は、TIME_WAITとエフェメラルポートのポート番号の設定方式に起因するとわかたっため、備忘録として記載しました。

#事象
Solaris10からSolaris11.3へバージョンアップ後、サーバ間（サーバA⇒サーバB)のコネクション接続でconnect()から
ECONREFUSED が復帰し、接続不可となる事象が発生しました。
接続数が多い時に発生しましたが、Solaris10の時と、接続数、通信量は変わっていませんでした。
なお、接続ポートにはエフェメラルポートを使用していました。

#原因　
　ネットワークトレースを取るなどして再現調査を行った結果、以下が判りました。

* コネクションをクローズ後、一定時間（デフォルトは60秒）、そのコネクションをTIME-WAIT状態で保持します。  
これはTCPの仕様です。その際、使用していたポート番号もOSで保持しています。
* 次の接続で、ポート番号に直前にクローズされたコネクションで使用していたポート番号（エフェメラルポート）が割り振られました。  
そのため、TIME-WAIT状態とみなされ、connectでRSTが復帰されました。  
これは、Solaris11からエフェメラルポートがランダムに選択されるように動作が変わったため、まれに直前で使用していたポート番号と同じ番号が割り振られたためでした。  
（Solaris10以前は+1カウント方式なので同じポート番号が割り振られる可能性は極めて低いものでした）

SolarisではTIME-WAIT状態の保持期間中に同じクライアントのIPアドレス・ポート番号から　　
接続要求があった場合はRFC793の規約に準じてRSTを返す実装になっています。 
RFC793より新しいRFC1122ではTIME-WAITでも新しい接続要求を受け付けてよいとされており、
WindowsやLinuxはこれに準じているようで、RSTは発生しませんでした。

<img width="479" alt="プレゼンテーション1.png" src="https://qiita-image-store.s3.amazonaws.com/0/387829/58e5954a-cc7e-bca7-cbbb-64814817c53f.png">



#対処・教訓
TIME-WAIT時間の変更など考えましたが、他に与える影響を考慮し、
最終的には、RSTが返る場合に備えて、リトライを組み込むようにしました。
実際に3回リトライとし、その後問題は発生していません。

Windows、Linuxでは、この問題は発生しませんが、Solaris転用を考慮する必要がある場合、
connectでRSTが復帰した場合、リトライ処理は組み込んでおくべきかと思います。
AWSのVPCについて理解したい

VPNについてちゃんと理解したいので、調べたことをQiitaに残します。
みなさんの参考になればうれしいです。
ツッコミ、補足等お待ちしております。

## VPC
VPC(Virtulal Private Cloud)はAWSアカウント専用の仮想ネットワーク。
AWS クラウドの他の仮想ネットワークから論理的に切り離されており、
AWSのリソース(EC2等)をVPC内で起動できる。

### DNS resolution
DNS resolutionをenabledにすると
起動した(している)インスタンスにパブリックDNS(IPv4)が付与される

### DNS hostnames
DNS hostnamesをenabledにすると
起動した(している)インスタンスにIPv4パブリックIPが付与される

## サブネット
VPCのIPアドレスの範囲。
AWSのリソース(EC2等)は指定したサブネット内で起動できる。
インターネットに接続が必要なリソースにはパプリックサブネット
インターネットに接続しないリソースはプライベートサブネットに接続する。

## ルートテーブル
ネットワークトラフィックの経路を判断する際に使用される。
VPCの各サブネットをルートテーブルに関連付ける必要がある。
サブネットのルーティングは、このテーブルによってコントロールされる。

## インターネットゲートウェイ
VPC のインスタンスとインターネットとの間の通信を可能にする VPCコンポーネント。
インターネットでルーティング可能なトラフィックの送信先を VPC のルートテーブルに追加する
パブリック IPv4 アドレスが割り当てられているインスタンスに対してネットワークアドレス変換(NAT)を行う

### インターネットアクセスを有効にする時
- VPC にインターネットゲートウェイをアタッチする。
- サブネットのルートテーブルがインターネットゲートウェイに繋がっていることを確認。
- サブネットのインスタンスに、グローバルに一意なIPアドレス(パブリックIPv4アドレス、ElasticIPアドレス、IPv6アドレス)
が割り当てられていることを確認。
- ネットワークアクセスコントロール(ネットワークACL)とセキュリティグループルールが
インスタンス間で関連するトラフィックを許可していることを確認。

サブネットに関連付けられているルートテーブルにインターネットゲートウェイへのルートがある場合、
そのサブネットを「パブリックサブネット」と呼ぶ

## セキュリティについて

### ネットワークACL
1つ以上のサブネットのインバウンドトラフィックとアウトバウンドトラフィックを制御するファイアウォールとして動作する

### セキュリティグループ
インスタンスの仮想ファイアウォールとして機能し、インバウンドトラフィックとアウトバウンドトラフィックをコントロールする

### ネットワークACLとセキュリティグループの違い
| セキュリティグループ | ネットワークACL |
|:-:|:-:|
| インスタンスレベル | サブネットレベル  |
| ルールの許可のみ  | ルールの許可と拒否 |
| ステートフル: 戻りの通信はセキュリティグループの設定に関わらず許可されます。（VPCの場合はステートレス）|  ステートレス: 戻りの通信はACLのルールに従うので許可設定の必要がある |
| 該当のトラフィックを許可する前に全ての許可設定を評価する。  |  該当のトラフィックを許可するとき、ルール番号順にACLのルールを処理します |

#### ステートレス
状況によってあるリクエストをしたらレスポンスが変わるもの
####ステートフル
状況に関わらずあるリクエストをしたらレスポンスが同じ結果になるもの

## 参考
[Amazon VPC とは?](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)
[インターネットゲートウェイ](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html)
[ネットワークACL](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-network-acls.html)
[VPCに推奨されるネットワークACLルール](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-recommended-nacl-rules.html#nacl-rules-scenario-1)
[VPCのネットワークまわりをもう一度](https://qiita.com/ryosukes/items/9ad289e1d673899fc628)
ECMAScript2019(ES10)でClassにPrivateが来る、かも？

もう`_`を付与する必要は無い？

ECMAScript2019 (ES10)の情報がちらほら出てきておりますが、その中でも気になった"private class"のメモ。


# これまでのClass
インスタンス内は全てPublicなプロパティ/メソッドとなっているのはご存知の通りです。
そもそもJavaScriptのClassは、`class`と言いつつ中身は`prototype`なのでその辺を考えれば普通に違和感はありません。

隠したい場合は、名前の頭文字に`_`を付与するなどして「これは隠したいの！」と明示的にアピる必要がありました。
しかしこれはあくまで規約であって、仕様としての強制力は無いので、アクセスしようと思えば簡単に出来てしまいます。


# これからのClass
C++などと同様に、インスタンス内にPrivateなプロパティ/メソッドを持つ事が可能となります。
当然、外部からのアクセスは仕様的に出来なくなります。
クラス本体のスコープに直接、プロパティ/メソッド/ゲッター/セッターを定義する事で可能になったそうです。


# つかいかた
```javascript:ES10_Class
class MyClass{
    constructor(){
        this.#privateProp = "";
        this.publicProp = "";
    }

    #privateMethod(){
        this.#privateProp = "Private!";
    }

    publicMethod(){
        this.publicProp = "Public!";
    }
}
```
新たに`#`構文文字が実装されます。
一目瞭然ですが、Privateにしたいプロパティ/メソッドは、先頭に`#`を付与します。
するとそれは、上記で説明した"本体直接定義"となる訳です。

ちなみにPublicなプロパティ/メソッドに関しては、従来通りそのままです。

```javascript:ES10_Instance
const myClass = new MyClass();
myClass.#privateProp = "Overwrite"; // Error
myClass.#privateMethod();           // Error
```


# おわりに
`Google Chrome 73.0.3683.86` はまだ未対応でした。
ES10の中で一番便利そうだと感じたのはコレでしたが、他にも"Top Level`await`"など、地味に便利そうな機能がいくつかありました。


# SpecialThanks!
- [The Complete Guide to ES10 Features - Medium](https://medium.com/@js_tut/the-complete-guide-to-es10-features-f09a8c7be1bd)
- [クラス本体とメソッド定義 - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes#Class_body_and_method_definitions)
Git メモ

指定ファイルの差分抽出
git diff <コミットID1> <コミットID2> <ファイル名>

**https://qiita.com/kasyuu/items/bc8489831e200b641456**


セキュリティとしては０点だがWindows上のJenkinsでリポジトリクローン出来た。
https://gist.github.com/n-shinya/5675834