OmniAICreator/Qiita-1.07M huggingface dataset:
無線LANの暗号化の種類についてまとめました

#はじめに
今回は自分で興味を持ったことを調べてそれをまとめて記事にしました。
WPA2-PSK(AES)というものを目にしたことはある人が多いと思います。
なので、今回は暗号化について調べ、３つの暗号化方法を簡単にまとめました。
#暗号化の種類
・WEP
・TKIP
・AES

##WEP
WEPは無線LAN用に最初に登場した暗号化技術です。
無線LANのアクセスポイントと機器の間でWEPキーと呼ばれる鍵データを照合して通信する、共通鍵暗号方式です。
**セキュリティ面が心配されるので、あまり使わないほうが良いです**

アクセスポイントの存在を隠す「SSID ステルス」や
機器固有のアドレスで接続を制限する「MAC アドレス制限」を設定していても、
これを回避する方法があるので
「SSID ステルス」「MAC アドレス制限」はあくまでも補助的なセキュリティ対策とお考えください。

---

# TKIP
TKIPはパケット毎に暗号鍵を自動生成する暗号化プロトコルです。
なので、鍵データの生成方法が少し複雑になり、セキュリティ面は増しましたが、
**複雑になっただけで時間をかけて解読することは可能**なので、
出来れば次に紹介するAESの方を使用しましょう

---

# AES
AESは米商務省標準技術局(NIST)によって
2001年に米国政府の標準暗号化技術として認定された方式です。
暗号化の方法を見直し、TKIPと同じ鍵データの生成方法を採用した
最も強固なセキュリティ性を持った暗号化方式です。
AES によって暗号化されたデータの解読・鍵データを
不正入手することは非常に困難ですので、
もし家のWiFiルータがこれに対応しているなら
AESに変更することをお勧めします(もしくはWPA2、WPA-AES)

---

# 最後に

簡単にまとめてみましたが、やはりネットワークに関して勉強するのは
難しいことが多くて大変ですが、この先就職した際に
必要な知識になっていくので頑張って勉強していこうと思います。
McAfee Endpoint Security for Macのアンインストール

Mac OS High Sierra 10.13 に McAfee Endpoint Protection for Mac 2.3.0 をインストールしたら、10.13 非対応？で起動できず、アップデートもアンインストールもできなくなりました😩💦

調べると、製品の[Knowledge Center](https://kc.mcafee.com/corporate/index?page=content&id=KB88461)に以下のことが書かれていました！

> Mac OS X Sierra 10.12 にアップグレードすると、
Mac 用の Endpoint Security は機能しなくなり、削除することはできません
原因
ENSM 10.2.0（およびそれ以前）は、Mac OS X Sierra 10.12をサポートしていません。

な、なんだと・・・！？

Sierra　がダメなら High Sierra　もダメですよねー😞
Mac のゴミ箱にアプリケーションを入れても削除できないので
[AppCleaner](https://freemacsoft.net/appcleaner/) を使ってみたのですが結果は同じでした💦

## 解決策その１

ターミナルを開いて以下を実行

```terminal
$ sudo /usr/local/McAfee/uninstall EPM
```
全ての ENSM モジュールを削除します
**※削除できない場合は、解決策その2へ**

## 解決策その2


ENSM を削除できない場合は、次の手順を実行して ENSM を手動で削除します
（**※くれぐれも自己責任でお願いします**）

ターミナルを開いて以下を実行

```terminal
$ sudo su
```
※ダイアログが表示されたら、管理者パスワードを入力

以下を順番に実行

```terminal
$ cd /usr/local/
$ rm –rf McAfee/
$ cd /Library/Application/Support/
$ rm –rf McAfee/
$ cd /Library/LaunchDaemons/
$ rm –rf com.mcafee.*
$ cd /Library/LaunchAgents/
$ rm –rf com.mcafee.*
$ cd /Library/Preferences/
$ rm –rf com.mcafee.*
```

削除プロセスが完了したら、Mac を再起動して正常に起動していることを確認！

これで、アンインストールが完了です😌
CentOS7+windows10の共有フォルダのマウント

# CentOS7環境へwindows10の共有フォルダをマウントする方法

## 前提
・ windowsの共有が有効になっていること。
・ centOS上のマウント先のディレクトが作成されていること。

## コマンド
1. `$ mount -t cifs -o user=xxxxx,password=***** //[windows_ip_address]/共有/ /[mount_dir_pass]`

#### 失敗する場合
    mount: wrong fs type, bad option, bad superblock on //[windows_IP_address]/共有/,
    missing codepage or helper program, or other error
    (for several filesystems (e.g. nfs, cifs) you might
    need a /sbin/mount.<type> helper program)

    In some cases useful info is found in syslog - try
    dmesg | tail or so.
    
    cifsがインストールされていないかもしれない。

#### 解決策
cifsを確認し、インストールする。

    $ rpm -qa | grep cifs
    何も表示されない・・
    $ 
1. `$ yum -y install cifs-utils`

##### 
    Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
    base: ftp.riken.jp
    ～～～
    samba-common-libs.x86_64 0:4.7.1-6.el7

    Complete!
    これでインストールされたはず。
#####
    $ rpm -qa | grep cifs
    cifs-utils-6.2-10.el7.x86_64
    $
    インストールされたのを確認できた。
sass、gulpメモ(node.js)

# sassの導入(Node.js)
##Node.jsをインストール
https://nodejs.org/ja/
公式よりダウンロード
コマンドプロンプト、ターミナルでインストールされているか確認
下記のコマンドをたたく
```
node -v
```
バージョン情報が報じされていれば完了


##package.jsonの作成
作業するフォルダのルートに作成
インストールしたパッケージ情報などが記載されてあるらしい。

作成したいディレクトリにcdとかで移動して、
下記コマンドでpackage.jsonを作成
```
npm init -y
```
該当ディレクトリにpackage.jsonができれいればok


## Gulpのインストール
該当の作業フォルダ(ローカル環境)以下で、gulpを使えるようにするために、
下記のコマンドを実行してインストールする
```
npm install -D gulp
```

##タスクの作成
必要なものをローカルにインストール
SassをGulpでコンパイルするためには次の2つのモジュールをインストールする必要がある。
・Gulp本体のgulp
・Sassファイルをコンパイルする為のプラグインgulp-sass
下記のコマンドで両方インストールできる。
```
npm install -D gulp gulp-sass
```
gulpを使用するのに必要な**gulpfile.js**を作業ファイルにを作成
gulpfile.jsにsassをコンパイルするための下記のコードを記載

```
// gulpプラグインの読み込み
const gulp = require('gulp');
// Sassをコンパイルするプラグインの読み込み
const sass = require('gulp-sass');
 
// style.scssをタスクを作成する
gulp.task('default', function () {
  // style.scssファイルを取得
  gulp.src('css/style.scss')
    // Sassのコンパイルを実行
    .pipe(sass())
    // cssフォルダー以下に保存
    .pipe(gulp.dest('css'));
});
```
これで設定は完了


##コンパイルしてみる
```
npx gulp
```
このコマンドでscssファイルがcssにコンパイルされる
保存場所などはgulpfile.jsに記載されている
今回だと「ルート/css」にscssがいて
それをコンパイルして「ルート/css」に出力されている


##watch機能
指定したscssファイルを監視して、そのファイルに変更があるたびに、
自動でcssにコンパイルして出力してくれる。
下記コードをgulpfile.jsに記載すればok

```
// Sassのコンパイルタスクのサンプルファイルです。
  
// gulpプラグインの読み込み
const gulp = require('gulp');
// Sassをコンパイルするプラグインの読み込み
const sass = require('gulp-sass');
  
// style.scssの監視タスクを作成する
gulp.task('default', function () {
  // ★ style.scssファイルを監視
  gulp.watch('css/style.scss', function () {
    // style.scssの更新があった場合の処理
  
    // style.scssファイルを取得
    gulp.src('css/style.scss')
      // Sassのコンパイルを実行
      .pipe(sass({
        outputStyle: 'expanded'
      })
      // Sassのコンパイルエラーを表示
      // (これがないと自動的に止まってしまう)
      .on('error', sass.logError))
      // cssフォルダー以下に保存
      .pipe(gulp.dest('css'));
  });
});
```
下記コマンドで監視を開始
```
npx gulp
```
監視を終了する場合はコマンドを開いてCtrlとCキー同時押して終了


備忘録もかねてのざっくりメモでした。

こちらの記事を参考にさせていただきました。
[絶対つまずかないGulp入門(2018年版) – インストールとSassを使うまでの手順](https://ics.media/entry/3290)
feature specでjsを動かすときのハマりどころ

# はじめに
この投稿は、E2Eテストを書く際にハマった箇所の備忘録です

## 環境
- Rails 5
- rspec-rails (3.5.1)
- poltergeist (1.10.0)
- capybara (2.8.0)
- etc

## feature specを書く
前述の環境にある通り、rspec, capybara, poltergeistの組み合わせでfeature specを書くことにしました

既存の環境だったため、なぜこの組み合わせにしたかは言及しません（できません）

# ハマりポイント
## checkboxをcheckできない
「capybara checkbox」なんかでググると以下のような例がでてきます。

```ruby
check("id")
find("#id").click
```
cssを大していじっておらず、シンプルなデフォルトのチェックボックスを使用している場合は、上記の例で動作します。

ただし！
大抵の場合は通用しません。

### 解決方法

find("id", visible: false).trigger("click")


## iframe内のelementを操作しようとして、Capybara::ElementNotFound
手動でWEBブラウザから見る限り存在するidやクラスに対して、
指定したfill_inなどを実行した際にエラーが生じたとき、このエラーの可能性がある

```ruby:rspec実行結果
Capybara::ElementNotFound:
       Unable to find field "XXX"
```

外部からjsを読み込んでいる場合（下記のようなソース）の場合、

```html:js読み込みを行うソース例
<script type="text/javascript" src="example1.js"></script>
```

ブラウザに渡すbodyには、下記のように変換される

```html:body.inspectの内容
<iframe src=以下略>
</iframe>
```

### 解決方法
[within_frame](http://www.rubydoc.info/github/jnicklas/capybara/Capybara%2FSession%3Awithin_frame)を用いる

他のwithin~は範囲を絞るだけ（ないものはない）だが、within_frameはframeを展開して、
その中の要素を指定することができる
での動作を記述することができる

```ruby:
within_frame("XXX") do
 # この中では、frameで展開される要素を取得できる
 # body.inspectで確認可能
end
```

## たまにCapybara::ElementNotFoundが発生する
"__たまに__"というのが重要
動的にjsをロードし、その要素を操作している場合、このようになることがある

原因はjsのロードが間に合っていないこと

### 解決方法
とりあえずsleepする

というのでも解決しますが、その場しのぎ的な上、
テストの可読性が下がったり、必要以上にテスト実行時間が伸びるため、おすすめしません


# 番外~デバッグで役にたったもの~
## body.inspect
とりあえずputsして、認識しているbodyを吐いてもらうのに利用

## page.save_screenshot
スクショをとってくれる
とりあえず:full => true
動作が追いついているか（jsのロードが終わっているか）など確認できる

## save_and_open_page
htmlを保存しつつ、いっそブラウザで開いてしまえ
といったときに利用
静的に、すぐにchromeの検証ができる

## セレクタ応用
```
within_frame(find(:xpath, '//iframe[contains(@src, "URL")]')) do
end
```
```
within_frame(find(:css, 'iframe[src^="URL"]')) do
end
```
laravelインストーラーがエラーで動かなかった。

#### そうだlaravelを使おう
次の現場でlaravel使うようなので、事前にみてみようと思ったら、最新取ろうとしてエラーになりました。

環境：CentOS6, PHP 7.2.7, composer 1.6.5

#### composerインストール
こちらにしたがってコマンドを実行
https://getcomposer.org/download/

```shell
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

```shell
$ which composer
/usr/local/bin/composer
```
入った！

#### laravelインストーラーをインストール
プロジェクト作成時につかうっぽいインストーラーを公式ドキュメントにそってインストール！！

```shell
composer global require "laravel/installer"
```

```shell
$ which laravel
/usr/local/bin/laravel
```
入った！！

#### laravelインストーラーを動かす
```shell
$ laravel
PHP Warning:  require(/usr/local/bin/vendor/autoload.php): failed to open stream: No such file or directory in /usr/local/bin/laravel on line 7
PHP Fatal error:  require(): Failed opening required '/usr/local/bin/vendor/autoload.php' (include_path='.:/usr/share/pear:/usr/share/php') in /usr/local/bin/laravel on line 7
```
エラー！！！

#### 対策
vendor/autoload.php がないから入れたらいいみたいです。

```shell
cd /usr/local/bin
composer require "laravel/installer"
```
androidのスクリーンショットやムービーを取得するためのシェルスクリプト

# 前提条件

- `~/bin`ディレクトリにPATHが通っていること
- androidのadbコマンドがインストールされていること

# スクリーンショットを取得するシェルスクリプト

## スクリプトの作成
ターミナルで以下のコマンドを実行してください。

```bash
cat << 'EOF' > ~/bin/adbscreencap
#!/bin/sh
# 引数1: ファイル名
if [ $# -eq 1 ]; then
    FILE_NAME=$1
else
    FILE_NAME=android-`date "+%Y%m%dT%H%M%S"`.png
fi 

adb shell screencap -p /sdcard/${FILE_NAME}
adb pull /sdcard/${FILE_NAME}
adb shell rm -f /sdcard/${FILE_NAME}
# 縦横比を保ちつつ「縦幅」指定でリサイズ
#sips --resampleHeight 600 ${file_name} -o ${file_name}
echo "Created ${FILE_NAME}"
EOF
chmod +x ~/bin/adbscreencap
```

## 使い方

```bash
# キャプチャ取得
$ adbscreencap
/sdcard/screen-20201015T150943.png: 1 file pulled, 0 skipped. 16.6 MB/s (386305 bytes in 0.022s)
..
screen-20201015T150943.png created

# 表示
$ open screen-20201015T150943.png
```

# ムービーを取得するシェルスクリプト

## スクリプトの作成

ターミナルで以下のコマンドを実行してください。

```bash
cat << EOF > ~/bin/adbscreenrecord
function stopped () {
  sleep 1
  adb pull /sdcard/record.mp4
  echo "record.mp4 created"
}
trap 'stopped' 2
rm -f record.mp4
adb shell rm -f /sdcard/record.mp4
echo '録画を開始しました。録画を終了する場合は、 Ctrl+C を押下してください'
adb shell screenrecord /sdcard/record.mp4
EOF
chmod +x ~/bin/adbscreenrecord
```



## 使い方

```bash
# ムービー作成
$ adbscreenrecord
録画を開始しました。録画を終了する場合は、 Ctrl+C を押下してください
/sdcard/record.mp4: 1 file pulled. 11.9 MB/s (3292999 bytes in 0.265s)
record.mp4 created

# 表示
$ open record.mp4
```

# gifを取得するシェルスクリプト

## 事前準備

ffmpegをインストールしてください。

```
brew install ffmpeg
```

## スクリプトの作成

ターミナルで以下のコマンドを実行してください。

```bash
cat << EOF > ~/bin/adbscreengif
function stopped () {
  sleep 1
  adb pull /sdcard/record.mp4
  ffmpeg -i record.mp4 -vf scale=320:-1 -r 24 record.gif
  echo "record.mp4 and record.gif created"
}
trap 'stopped' 2
rm -f record.mp4
adb shell rm -f /sdcard/record.mp4
echo '録画を開始しました。録画を終了する場合は、 Ctrl+C を押下してください'
adb shell screenrecord /sdcard/record.mp4
EOF
chmod +x ~/bin/adbscreengif
```

## 使い方

```bash
# gif取得
$ adbscreengif
録画を開始しました。録画を終了する場合は、 Ctrl+C を押下してください

# 表示
$ open record.gif
```

# 参考

- [adb 経由の screenshot の取り方](https://qiita.com/TNaruto/items/b2407f5668e15e42bedd)
- [bashの強制終了（CTRL＋C）検出と後処理/trap](http://takuya-1st.hatenablog.jp/entry/2016/12/27/023858)
- [FFmpegで動画をGIFに変換](https://qiita.com/wMETAw/items/fdb754022aec1da88e6e)
[メモ] JdbcTemplateでafterLastを使って逆順に取得したい

SpringBootでJdbcTemplateを使っていて、結果を逆順に取得したいというケースがあったので備忘録として記録。
order byで逆に取得すればいいのではというつっこみはあると思いますが、単純にorder byで並び替えできないケース（例えば再帰処理（recursive）を使って階層構造を表現した場合等）にまれに遭遇。

# 使うクラスとメソッド
 - SqlRowSet
 - jdbcTemplate.queryForRowSet()

# コード
```
SqlRowSet rs = jdbcTemplate.queryForRowSet(sql, param);
rs.afterLast();
while(rs.previous()) {
  // ここで逆にとれる
  // 例えばrs.getString("name");
}
```
JestのテストコードをVScodeでデバッグする

個人メモとして投稿。

まぁざっくり[公式](https://facebook.github.io/jest/docs/ja/troubleshooting.html#vs-code%E3%81%A7%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%81%99%E3%82%8B)を見ればいいのだが、`launch.json`の記述がわりとアレ（別に動きはする）なのでよりシンプルに書いてみた。

``` ..vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Jest Tests",
            "type": "node",
            "request": "launch",
            "program": "${workspaceRoot}/node_modules/.bin/jest",
            "protocol": "inspector",
            "args": [ "--runInBand" ],
            "windows": {
                "program": "${workspaceRoot}/node_modules/jest/bin/jest.js"
            }
        }
    ]
}
```

環境上書き用の設定は存在するので、わざわざwindowsで書き換えする必要はありません。
この記述だとコンソールが自動で表示されないのですが、それが気に入らない人は下記の通り書いておけばいいでしょう。

``` ..vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Jest Tests",
            "type": "node",
            "request": "launch",
            "program": "${workspaceRoot}/node_modules/.bin/jest",
            "protocol": "inspector",
            "args": [ "--runInBand" ],
            "windows": {
                "program": "${workspaceRoot}/node_modules/jest/bin/jest.js"
            },
            "console": "integratedTerminal",
            "internalConsoleOptions": "neverOpen"
        }
    ]
}
```
ConfigurationBuilder を環境変数と設定ファイルで優先順位をつけて設定する

.NET Core から使われている`ConfigurationBuilder` で、コンフィグレーションを環境変数、`appsettings.json` の順番で読み込みたいというニーズがあったので、簡単なサンプルを作って検証した。

# 事前準備

`ConfigurationBuilder` をインストールするには下記のライブラリが必要

* Microsoft.Extensions.Configuration

さらに、環境変数、Jsonの設定ファイルを使いたい時は次のものが必要です。他のプロバイダもあるので、これ以外に使いたかったら検索するとよいと思います。

* Microsoft.Extensions.Configuration.EnvironmentVariables
* Microsoft.Extensions.Configuration.Json

nuget パッケージをインストールしておきましょう。

# 環境変数と、appsettings.jsonの設定

テスト用に、環境変数と、`appsettings.json`作成します。 環境変数のみのパターン、重複しているパターン、ファイルのみのパターンでデータを作っています。

### 環境変数

```csharp
            // Only Environment Variables has been set
            Environment.SetEnvironmentVariable("SOME_PRIMARY_KEY", "EnvironmentVariablesKey");
            // Evirnoment Variables and appsettings has been set
            Environment.SetEnvironmentVariable("SOME_HOST_NAME", "EnvironmentVariablesHostName");
```
### appsettings.json

```json
{
  "SOME_HOST_NAME": "AppSettingsHostName",
  "SOME_SECRET":  "AppSettingsSecret"
}
```

ちなみに、コンフィグファイルを VS に含めるときは、`Property > Advanced > Copy to Output Directory` が `Copy always` になっているようにすること。そうでないと実行ディレクトリに該当ファイルがコピーされません。

# Builder を使用する

Builderの使用は単純に New をして、読み込みたいコンフィグレーションを足していくだけです。インターフェイスがあるので、そちらで受けるようにしておきました。すると、テストが楽になりそうですね。

```csharp

IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile("appsettings.json");
builder.AddEnvironmentVariables();
var configration = builder.Build();

```
あとは使うだけです。

```csharp
Console.WriteLine($"SOME_PRIMARY_KEY: {configration["SOME_PRIMARY_KEY"]}");
Console.WriteLine($"SOME_HOST_NAME: {configration["SOME_HOST_NAME"]}");
Console.WriteLine($"SOME_SECRET: {configration["SOME_SECRET"]}");
```

## 実行結果

ちなみに、後から足したソースで上書きされるようですね。無ければ、最初のものがセットされます。これは便利。

```
SOME_PRIMARY_KEY: EnvironmentVariablesKey
SOME_HOST_NAME: EnvironmentVariablesHostName
SOME_SECRET: AppSettingsSecret
```

# リソース

* [ソースコード](https://github.com/TsuyoshiUshio/ConfigurationBuilderSpike)
Macアドレスの表記を整えたい

Macaddressを取得し、データを処理する上で、機種やメーカによって表記が違ったりする。

```
①　XXXX.XXXX.XXXX
②　XX-XX-XX-XX-XX-XX
③　XXXX-XXXX-XXXX
④　XX:XX:XX:XX:XX:XX
```
だいたいこのくらいパターンがある。

そんなとき、Pythonでなんとか綺麗にまとめようと思ったときのもの。



2桁コロン区切りのものに統一したい。

```
# -*- coding: utf-8 -*-

maclist=[
        'fa:16:3e:ad:ba:a0',
        'fa:16:3e:ac:b2:e0',
        'fa:16:3e:83:80:be',
        'fa16.3ef9.8d1e',
        'fa16.3ef9.8d1e',
        '0016.3e2a.3302',
        '0016-3e10-102e',
        '0016-3ed9-075d',
        ]

pat = str.maketrans({
    '-': '',
    ':': '',
    '.': '',
})


for dirtymac in maclist:
    clsmac = dirtymac.translate(pat) # '0016-3e10-102e' -> '00163e10102e'
    colmac =':'.join([(i+j) for (i,j) in zip(clsmac[::2],clsmac[1::2]) ]) # '00163e10102e' -> '00 16 3e 10 10 2e' -> '00:16:3e:10:10:2e'
    print("colmac : ",colmac)
```

dirtymac・・・未整形の変数
clsmac・・・コロンやハイフンなどを取り除いた変数
colmac・・・2文字づつ切り出して、”：”でジョインシていったもの

という感じの単純なものです。

実行するとこんな感じの結果が帰ってきます。

```
$ python3 mac.py
colmac :  fa:16:3e:ad:ba:a0
colmac :  fa:16:3e:ac:b2:e0
colmac :  fa:16:3e:83:80:be
colmac :  fa:16:3e:f9:8d:1e
colmac :  fa:16:3e:f9:8d:1e
colmac :  00:16:3e:2a:33:02
colmac :  00:16:3e:10:10:2e
colmac :  00:16:3e:d9:07:5d
```

いつもその場しのぎで。
Golangで構造体に対して複数項目にまたがるバリデーションを定義する

Golangの[validator.v9](https://github.com/go-playground/validator)を使って構造体に対する複数項目にまたがるバリデーションを定義するには、バリデータタグを定義するよりも `RegisterStructValidation` を使ったほうが簡単に書ける。

以下は **ある特定の項目が真のとき他の項目に対してバリデーションを行う** コードの例。

```go:multiple_conditional_validator.go
package main

import (
	"fmt"
	"gopkg.in/go-playground/validator.v9"
)

type Person struct {
	IsMan  bool
	Age    int
	Height int
}

func main() {
	person := Person{
		IsMan:  true,
		Age:    10,
		Height: 0,
	}

	validate := validator.New()

	// personの構造体に対するバリデータを登録
	validate.RegisterStructValidation(multipleConditionalValidator, person)
	err := validate.Struct(person)

	if errorFields, ok := err.(validator.ValidationErrors); ok {
		for _, errorField := range errorFields {
			fmt.Printf("%s.%s\n", errorField.StructNamespace(), errorField.Tag())
		}
	}
}

func multipleConditionalValidator(sl validator.StructLevel) {
	args := sl.Current().Interface().(Person)

	// IsManが真のときのみ他のフィールドに対してバリデーションを継続して行う
	if args.IsMan {
		if args.Age < 1 {
			sl.ReportError(args.Age, "Person", "Age", "positive", "")
		}

		if args.Height < 1 {
			sl.ReportError(args.Age, "Person", "Height", "positive", "")
		}
	}
}
```

```shell:出力
$ go run multiple_conditional_validator.go
Person.Height.positive
```
Mysqlの個人的なメモ

`/var/lib/mysql/データベース名`の所に、DBのデータが全部格納されてる。
データベース名のディレクトリを削除すると、そのDBが完全に削除される。
特定のテーブルがshow tablesで存在しているのに、存在していない場合は、そのテーブルのファイルを直接削除すれば、大抵解決する
ARReferenceImageの制限について

# はじめに
WWDC 2018でARKit2が発表されました。
そこで今までに追加されている機能をおさらいしていたら、ARReferenceImageで様々な警告を受けたのでまとめておこうと思います。
ARReferenceImage.init(_ image: CGImage, orientation: CGImagePropertyOrientation, physicalWidth: CGFloat)で生成した時に発生する警告では判断がつかないことが多いので、目を通しておくといいと思います。

ちなみにこんな感じの雑なエラーが発生し、ARSessionが停止します。

```
2018-06-21 08:59:03.738531+0900 ARKit-Sample[359:15389] [Session] Session (0x12dd09560): did fail with error: Error Domain=com.apple.arkit.error Code=300 "Invalid reference image." UserInfo={NSLocalizedFailureReason=One or more reference images have an invalid size: <Unnamed>, NSLocalizedRecoverySuggestion=Make sure that all reference images are greater than 100 pixels and have a positive physical size in meters., ARErrorItems=(
    "<Unnamed>"
), NSLocalizedDescription=Invalid reference image.}
```

# ARReferenceImageとは
そもそもARReferenceImageって何かと言うと、ざっくり説明すると「AR空間で画像を使用するためのもの」です。
例えばAR空間で画像の認識をしたいとなった時に使用します。
確かARKit1.5から加わった機能だったと思います。

# 引っかかった制限(随時追記)
## The aspect ratio of the image is high. The aspect ratio should be lower than 3:1.
> 和訳: 画像の縦横比が高い。 縦横比は3：1より小さくする必要があります。

アスペクト比の差が大きすぎると発生します。
使用していた画像のアスペクト比が8:1だったので、3:1にしてみたところ解消されました。

## The histogram of the image is narrow or not well distributed. Recognition works better on images with wider, flatter histograms.
> 和訳: 画像のヒストグラムは狭いか、またはうまく分布していません。 認識はより広く、より平らなヒストグラムを有する画像上でより良好に機能する。

画像の輝度の差があまりないものは認識に向かないようです。
画像の色のバランスとかコントラストの調整をすると上手くいきました。
参考: http://www.asahi-net.or.jp/~ax2s-kmtn/ref/histogram.html

## The image has uniform cokor regions, low texture, or low local contrast regions. Recognition works better whem there are higher local contrast regions distributed across the image.
> 和訳: 画像は、均一なココア領域、低いテクスチャ、または低い局所コントラスト領域を有する。 認識は、より高い局所コントラスト領域が画像全体に分散している場合にはより効果的である。

これも画像の色のバランスとかコントラストの調整をすると上手くいきました。
具体的な解決法を知っている人は教えていただけると幸いです。

## The resolution of the image is low. Noth width and height should be at least 480 pixels.
> 和訳: 画像の解像度は低いです。 幅と高さは、少なくとも480ピクセルにする必要があります。

画像の解像度は縦横どちらも480ピクセル以上にしなければいけないようです。
縦が300ピクセルしかなかったのを480ピクセルにしたら解消しました。

# まとめ
他にも様々な制約があると思います。
こんなの出たよーとか、こうしたら解決したよーというのがあれば、編集リクエストいただけたら幸いです。
Salesforce 静的リソースのJavaScriptでグローバル変数を扱う

# 結論
　グローバル変数、Apex変数などをjavascript（以降js）に埋め込んで処理したい時（コンポーネントのidなど）に、jsが静的リソースにあるとページがレンダリングされた時にグローバル変数は展開されずに、ただの文字列としてレンダリングされます
　つまり、**静的リソース内のjsでグローバル変数を扱えない**

# 理由
　Visualforceページは動的ページで、ページがレンダリングされる時にグローバル変数、Apex変数などはブラウザが解釈できるHTMLタグに変換される
　なので、Visualforce外のJavaScript内（静的リソースのjs）に含まれているApex変数やグローバル変数は展開されずに、そのまま文字列としてページにレンダリングされます

# 対策方法

## 1. グローバル変数の外だし

visualforceでしかグローバル変数やApex変数を展開できないので、静的リソースを読み込む前にjsの変数にグローバル変数を代入する

```html:visualforce.page

<script>
var componentFormId = "{!$Component.form.xxx}";
</script>
<script src="静的リソースのhogehoge.js"></script>
```

静的リソース内のjsでは上記の`componentFormId`変数ありきで実装する

```javascript:hogehoge.js

document.getElementById(componentFormId).value;
```

## 2. visualforceにjavascriptをまとめる

- 静的リソースを使わずにvisualforceにjavascriptをまとめる
- visualforceのincludeを使って、javascriptのみが書かれたvisualforceを読み込む（静的リソースのような使い方）
GPSの研究　その18

#概要
GPSを理解したかった。
android2.1で、NMEAを眺めるだけのアプリ。

#写真

![device-2018-06-21-071855.png](https://qiita-image-store.s3.amazonaws.com/0/18104/b9c9905a-5d73-becc-e003-b18aab226836.png)

#サンプルコード

```
package com.ohisamallc.ohiapo9;

import android.app.Activity;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TextView;
import android.view.ViewGroup;

public class ohiapo9 extends Activity
{
	private LocationManager mLocationManager;
	private LocationListener mLocationListener;
	private TextView textView;
	@Override public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		textView = new TextView(this);
		textView.setWidth(200);
		textView.setText("ok");
		TableLayout tableLayout = new TableLayout(this);
		tableLayout.addView(textView, new TableLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
		setContentView(tableLayout);
	}
	@Override protected void onDestroy()
	{
		super.onDestroy();
		mLocationManager.removeUpdates(mLocationListener);
	}
	@Override public void onStart()
	{
		super.onStart();
		mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
		{
		}
		mLocationListener = new locationListener();
		mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 5, mLocationListener);
		mLocationManager.addNmeaListener(nmeaListener);
	}
	private final GpsStatus.NmeaListener nmeaListener = new GpsStatus.NmeaListener()
	{
		public void onNmeaReceived(long timestamp, String nmea)
		{
			String s = nmea + textView.getText().toString();
			textView.setText(s);
		}
	};
	private class locationListener implements LocationListener
	{
		public void onLocationChanged(Location loc)
		{
		}
		public void onProviderDisabled(String arg0)
		{
		}
		public void onProviderEnabled(String provider)
		{
		}
		public void onStatusChanged(String provider, int status, Bundle extras)
		{
		}
	}
}



```

以上。
Git memo

# Git memo

随時追記して行きます。

- git fetch: ローカルにあるリモートブランチの追跡内容を最新のものに更新する。
- git fetch --all: すべてのリモートブランチの追跡内容を最新にする。
- git branch: ブランチ情報を取得する。
- git branch BRANCH_NAME: 現在のブランチから新しいブランチを作成する。
- git branch -d BRANCH_NAME: ブランチの削除（リモートブランチは削除されない）
- git branch -D BRANCH_NAME: ブランチの強制削除（リモートブランチは削除されない）
- git branch BRANCH_NAME origin/BRANCH_NAME: ローカルにないリモートブランチをローカルに持ってくる。
- git checkout BRANCH_NAME: 作業ブランチを変更する。
- git checkout -b BRANCH_NAME: ブランチの作成とチェックアウトを同時に行う。
- git push --set-upstream origin BRANCH_NAME: リモート側に同名のブランチを作る。

## マージ

```bash
git checkout master
git merge BRANCH_NAME
```

これでmasterブランチにBRANCH_NAMEブランチをマージする。
競合が起きたときはコンフリクトするので、
ファイルを開いて直して、

```bash
git merge --continue
```

## リベース

コミットを綺麗にしたいとき。
他の人が同時に作業していたときに不整合が起きる可能性あり。

```bash
git checkout BRANCH_NAME
git rebase master
```

これでBRANCH_NAMEブランチにmasterブランチをリベースする。
masterの変更がBRANCH_NAMEの変更の下に入るので、
コンフリクトを直して、

```bash
git rebase --continue
```

その後

```bash
git checkout master
git merge BRANCH_NAME
```

これでfast-fowardの綺麗なコミットになる。

## コミットし忘れたファイルがあった場合

```bash
git commit --amend
```

コミットメッセージを変更する必要がないときは

```bash
git commit --amend --no-edit
```

## マージの取り消し

```bash
git merge --abort
```

`--abort`オプションでだいたいのコマンドは取り消しできる。

## ローカルの変更取り消し

```bash
git checkout .
```

## 強制プッシュ

```bash
git push -f
```

他の人の変更が無効になるので、十分気をつけること。

## コミットを取り消したいとき

```bash
git reset --hard HEAD^
```

## コミットを取り消したいが、ファイルの変更は残したいとき

```bash
git reset --soft HEAD^
```
react-routerに依存したコンポーネントをStorybookに追加する

## 問題

例えば、次のようなコンポーネントをStorybookに追加すると

```jsx:Header
import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { Toolbar as RebassToolbar, NavLink } from 'rebass';

import Logo from './Logo';

const Toolbar = styled(RebassToolbar)`
  padding: 0 20px 0 20px;
`;

const NavLinks = styled.div`
  margin: auto 12px;
`;

const Header = () => (
  <Toolbar>
    <Logo>Takus</Logo>
    <NavLinks>
      <NavLink to="/" is={Link} children="ホーム" />
      <NavLink to="/posts" is={Link} children="一覧" />
    </NavLinks>
  </Toolbar>
);

export default Header;
```

```jsx:Header.stories
import React from 'react';
import { storiesOf } from '@storybook/react';

import Header from './Header';

storiesOf('Header', module).add('default', () => <Header />);
```

次のようなエラーが発生する

>`You should not use <Link> outside a <Router>`

react-routerのLinkをRouterでWrapされたコンポーネント外で使っているためにエラーが発生している

<img width="690" alt="スクリーンショット 2018-06-20 8.50.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/79414/029c862c-fdff-2be5-dc51-59063c56c4c6.png">

## 解決策

`storiesOf` に生えている `addDecorator` というAPIを使って、対象のコンポーネントを `MemoryRouter` でWarpします。react-routerのドキュメント[Testing](https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/testing.md)にもある通り、テスト時にルータのコンテキストをスタブする用途で使われるようです。

```jsx:Header
import React from 'react';
import { MemoryRouter } from 'react-router'
import { storiesOf } from '@storybook/react';

import Header from './Header';

storiesOf('Header', module)
  .addDecorator(story => (
    <MemoryRouter initialEntries={['/', 'posts']}>{story()}</MemoryRouter>
  ))
  .add('default', () => <Header />);
```


initialEntriesというプロパティには、対象のコンポーネントがLinkの`to` で指定しているパスをダミーとして登録しておきます。

## 参考
https://github.com/storybooks/storybook/issues/769
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/MemoryRouter.md
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/testing.md
ターミナルvsコマンドプロンプト 主要13コマンド早見表

#はじめに
Mac愛用歴2年のぼくが（短い！！:sweat_smile:）、今度現場に出てWindowsを使うことになりそうなので、
ターミナルvsコマンドプロンプト主要13コマンド早見表を作ってみましたー！！
「わざわざまとめなくても、、」という声が聞こえてきそうですが、
プログラミング初心者の誰かと来月の自分の役に立てれば幸いです:innocent:

▽アジェンダ
- ターミナルとは
- コマンドプロンプトとは
- 主要13コマンド早見表


##ターミナルとは
簡単に言うと、**「黒いカッコいい画面」**です！！！
ターミナルとはMacOSに標準装備されているツールで、さまざまな操作をコマンド（命令）するためのものです。

主にマウスによる操作のほとんどが、GUI（グラフィカル・ユーザ・インタフェース）と呼ばれている操作方法となります。対して、ターミナルはマウスの操作（GUI）の代わりにコマンドを打つ（キーボードを打つ）ことで、操作できるCUI（キャラクター・ユーザ・インタフェース）と呼ばれる操作方法となります。

##コマンドプロンプトとは
ターミナルのWindows版です（MacOS愛用者の偏って意見:sunglasses:）
ターミナルと同じく、CUI上でコマンドを打つことで様々な操作を行えます。


##主要13コマンド早見表
*なんかプレビューには出てない崩れが、、:innocent:

|ターミナル 　　　　　　|コマンドプロンプト 　　　　　　|コマンド内容 |
|:---------------:|:------------:|:----------------------:|
|cd        | cd        | ディレクトリ間移動         |
|ls        | dir      | ディレクトリやファイルを表示       |
|-         | tree        |　ディレクトリ構造をグラフィカルなツリーで表示         |
|mkdir     | -          | ディレクトリを作成           |
|-         | type       | テキストファイルの内容を確認       |
|mv        | move     | ファイルやディレクトリの名を①変更する②移動する場合      |
|mv        | ren     | ファイル名を変更      |
|find  　　　　　　　　| -    | ファイルやディレクトリの検索  |
|cp        | copy     | ファイルをコピー      |
|rm        | del     | ファイルを削除するコマンド      |
|man   　　　　　　　　| help     | コマンドのマニュアル開示      |
|clear 　　　　　　　　| cls     | ターミナル画面をクリアし、表示された文字を全て消去      |
|exit　　 　　　　　　　　| -    | ログアウト  |




*ちょっとここで気持ちが折れてしまったので、コマンド内容詳細は気分が乗ったときに追記します。
すいません笑


#####▽参考ページ（参考にさせていただきました:relieved:）
https://techacademy.jp/magazine/5318
https://techacademy.jp/magazine/5155
jQuery で form を動的に追加して POST する（target 付き）

jQuery で form を動的に追加して POST するサンプルです。

```js
$(/*document).ready(*/function () {
    $('.some_buttons_class').click(function () {
        var $fm = $('<form />', {
            method: 'post',
            action: 'action_receiver.php',
            target: '_blank',
        });
        $fm.append($('<input />', {
            type: 'hidden',
            name: 'data_id',
            value: $(this).data('id'),
        }));
        $fm.appendTo(document.body);
        $fm.submit();
        $fm.remove();
    });
});
```

ググって最初に出てくるサンプルが最後の `.remove()` をしておらず気持ち悪かったので投稿しました。
LaravelでSlack Notification

# Laravelのインストール
```sh
$ laravel new SlackNotification
$ cd SlackNotification
```

# guzzleライブラリのインストール
```sh
$ composer require guzzlehttp/guzzle
```

# Webhook URLを取得
https://api.slack.com/incoming-webhooks
上記URLよりWebhookのURLを取得

# Notificationの作成
```sh
$ php artisan make:notification SlackPost
```

下記のようにファイルを修正

```php:app/Notifications/SlackPost.php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;

class SlackPost extends Notification
{
    use Queueable;

    public function via($notifiable)
    {
        return ['slack'];
    }

    public function toSlack($notifiable)
    {
        return (new SlackMessage)
            ->content('こんにちは');
    }
}

```

# UserモデルにWebhhok URLを設定
取得したWebhook URLを設定

```php:app/User.php
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    //...

    public function routeNotificationForSlack($notification)
    {
        return 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX';
    }
}
```

# テスト用コマンドを作成

```sh
$ php artisan make:command NotifySlack
```

下記のように編集

```php:app/Console/Commands/NotifySlack.php
<?php

namespace App\Console\Commands;

use App\Notifications\SlackPost;
use App\User;
use Illuminate\Console\Command;

class NotifySlack extends Command
{
    protected $signature = 'notify:slack';
    protected $description = 'Slackへテスト送信';
    public function handle()
    {
        $user = new User();
        $user->notify(new SlackPost());

    }
}
```

コマンドを実行

```sh
$ php artisan notify:slack
```
<img width="519" alt="スクリーンショット 2018-06-21 8.04.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/2469/7a49830c-2b31-0f70-5a8c-8741ff76eca4.png">

# メッセージ内容を修正

```php:app/Notifications/SlackPost.php
//...
public function toSlack($notifiable)
{
    return (new SlackMessage)
        ->from('ららべる')
        ->image('https://laravel.com/favicon.png')
        ->content('こんにちは');

}
//...
```
<img width="536" alt="スクリーンショット 2018-06-21 8.06.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/2469/858f419c-be1a-7035-8887-e22f834d8c42.png">

```php:app/Notifications/SlackPost.php
//...
public function toSlack($notifiable)
{
    $url = 'https://qiita.com';

    return (new SlackMessage)
        ->from('きーた')
        ->image('https://cdn.qiita.com/assets/favicons/public/apple-touch-icon-f9a6afad761ec2306e10db2736187c8b.png')
        ->success()
        ->attachment(function ($attachment) use ($url) {
            $attachment->title('Qiita', $url)
                ->fields([
                    'タイトル' => 'LaravelでSlack Notification',
                    'タグ' => '入門',
                    'ユーザー' => '@kei4eva4',
                    '投稿日時' => \Carbon\Carbon::now()->toDateTimeString()
                ]);
        });

}
//...
```
<img width="505" alt="スクリーンショット 2018-06-21 8.13.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/2469/093c0bf4-a115-e9c4-4b3b-2853279bd4fb.png">
Ubuntu 18.04にアップグレードした環境でIPアドレスを固定できない

# 前提
Ubuntu 18.04はnetplanを使ってIPアドレスを固定するが、毎日不定の時間にIPアドレスが変わってしまう。環境はUbuntu 17.10からdo-release-upgradeを利用してアップグレードした。少なくとも数バージョン、do-release-upgradeを重ねたため、17.10からのアップグレードに問題があるかは分からない。

# 現象
netplanによる固定IPアドレス設定を行ってもほぼ毎日dhclientが走ってしまい、ルータからIPを取得して固定IPが解除されてしまう。
dhclientは/var/log/syslogに実行ログを残すため、IPアドレスが変更になった時間の前後を確認することで現象を確認できる。

# 原因
ifupdownパッケージが入っており、/etc/network/interfaces 内にIPアドレスをDHCPで設定するデフォルト設定が残っていたことが原因。

# 対処法
ifupdownパッケージを削除する。Ubuntu 18.04 LTSのクリーンインストール環境にはifupdownは入っていないため、削除して問題ないと思われる。

```bash
  # apt purge ifupdown
```
JavaScript の Array.some と Array.includes の使い分け、値・参照型の動作の違い

JavaScript の `Array.some` と `Array.includes` は、
どちらも配列に特定の要素が存在するか判定するのに使えます。

`Array.some`と`Array.includes`をどのように使い分ければいいのかを考えたいと思います。

---

## 古えの JavaScript では...

ES2015 で`Array.some`が追加されるまで、配列にある要素が存在するか判定するには、
（本来の用途と違うため）直感的でない`indexOf`や、`for`文で冗長な記述をする必要がありました。

```js

const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];
const target = "d";

// for 文でループして探す
let exists = false;
for (const char of chars) {
  if (char === target) {
    exists = true;
    break;
  }
}
console.log(exists);

// インデックスが 0 より大きかったら存在する
exists = chars.indexOf(target) >= 0;
console.log(exists);
```

---

## `Array.some` と `Array.includes` の実装後

ES2015 で`Array.some`、ES2017で`Array.includes`が追加されました。
どちらも配列に特定の要素が含まれるかを直感的・簡潔に書くことができます。

`includes`は特定の要素が配列に含まれているかどうかを`true` / `false` で返します。

```js
const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];
const target = "d";

const exists = chars.includes(target);
console.log(exists); // => true
```

`some`は配列の少なくとも1つの要素が、渡されたテスト関数を通るかどうかを`true` / `false` で返します。

```js
const chars = ["a", "b", "d", "g", "h", "i", "m", "n"];
const target = "d";

const exists = chars.some(c => c === target);
console.log(exists);
```

---

## オブジェクトの配列で`Array.includes`を使ってみる

`Array.includes`で`Book`オブジェクトの配列から対象の本を探してみます。

```js
const books = [
  { title: "幼年期の終り", author: "アーサー・C・クラーク" },
  { title: "1984年", author: "ジョージ・オーウェル" },
  { title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = {
  title: "1984年",
  author: "ジョージ・オーウェル"
};

const includes = books.includes(target);
console.log(`includes: ${includes}`); // includes: false
```

同じオブジェクトがあるように見えますが、結果は`false`が返ります。

---


## オブジェクトの比較は参照が比較される

オブジェクトを比較するとき、その比較は**同じ参照を指しているかどうか**がテストされます。
`includes`による比較も同様です。

つまり、以下のようなコードなら`Array.includes`は`true`を返します。

```js
const books = [
  { title: "幼年期の終り", author: "アーサー・C・クラーク" },
  { title: "1984年", author: "ジョージ・オーウェル" },
  { title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = books[1];
const includes =  books.includes(target);
console.log(`includes: ${includes}`); // includes: true
```

---

## 要素がオブジェクトの配列には`Array.some`

`Array.some`は引数にテスト関数を渡すことができます。
オブジェクトの値型のプロパティがすべて等しいか調べるテスト関数を渡すことで、
要素がオブジェクトの配列に特定の要素が含まれているかを簡単に調べることができます。

```js
const books = [
  { title: "幼年期の終り", author: "アーサー・C・クラーク" },
  { title: "1984年", author: "ジョージ・オーウェル" },
  { title: "われはロボット", author: "アイザック・アシモフ" }
];

const target = {
  title: "1984年",
  author: "ジョージ・オーウェル"
};

const some = books.some(
  b => b.title === target.title && b.author === target.author
);
console.log(`some: ${some}`); // some: true
```

`Array.some`は要素1つ1つに対しテスト関数を反復実行し、
テスト関数をパスする要素が見つかった時点で`true`を返し処理を終了します。

---

## まとめ

要素が値型の配列には`Array.includes`
要素が参照型の配列（または条件を詳しく指定したい時）には`Array.some`

と使い分けるといいと思います。
LinLibertineIとかいうポストスクリプト名のフォントの罠

こんなトピックで初投稿を飾ろうとは……
調べてもほとんどヒットしなかったおそらくニッチな問題に関して気づいた事メモです．
MSWordでAcrobatプラグインのPDFMakerでPDFを発行する際に**Linux Libertineのイタリック体がTOFU化**してしまって困っている or もやもやしてる人には少しお役に立てると思います．

#Linux Libertineとの出会い
とある学会予稿を書くときに指定されるACM CONFのWordテンプレでは，本文フォントにLinux Libertineが指定されています．
このLinux LibertineはTimes New Romanをなんかいい感じにしたがって作られたものらしいですが，とある罠が仕掛けられていました．
この罠によってMSWordからPDFMakerを使用してPDFを作る際に**フォントの文字化け**が生じてしまいます．
本稿ではこの原因らしき事象と，その回避方法についてメモしていきます．

#Linux Libertine Initialsとか名前だけそっくりさん
各種文字の見た目を変えるために皆さんフォントを変えると思いますが，フォントにはフォントファミリーというものがあります．
一つのフォントをもとにイタリック体やボールド体などを派生させたものをまとめて一つのフォントファミリーと呼びます．
例えば`Linux Libertine`というフォントファミリーには以下のようなフォントが含まれます．

- ノーマルフォントとして`Linux Libertine`
- イタリック体フォントとして`Linux Libertine Italic`
    - https://ja.fonts2u.com/linux-libertine-italic.%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88
- イタリックボールドとして`Linux Libertine Bold Italic`

MSWordやAdobe Acrobatなど，フォントをいじれるソフトではLinux Libertineをフォントとして指定し，イタリック指定をすることでLinux Libertine Italicが使用できるようになります

そしてLinux Libertineの名を冠するフォントがいくつかありますが，そのうちの`Linux Libertine Initials`というフォントがあり，これがまた以降に示すある理由により件の厄介を引き起こしています．

`Linux Libertine`と`Linux Libertine Initials`，フォントファミリーとしてはそれぞれ別です．
`Linux Libertine Initials`フォントファミリーの中には

- ノーマルフォントとして`Linux Libertine Initials`のみが内包されています．
    - 大文字のみを含むフォントで，小文字を入力するとTOFUが並びます．
    - しつこいですがこれは`Linux Libertine Initialsファミリー`の中の一つのフォントです．
    - https://ja.fonts2u.com/linux-libertine-initials.%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88
    
以上に示してきたフォント名のなかで似た名前を持っているフォントがいます．

- `Linux Libertine Italic`
    - Linux Libertineファミリに属する
- `Linux Libertine Initials`
    - Linux Libertine Initialsファミリに属する

`Linux Libertine I`まで同じですね．でも確かに別の名前です．
ただし，別の名前であるのはその**フルフォントネーム**の場合なのです......

# Full Font Name vs. Postscript Name

というのも，フォントにはいくつかの名前が用意されていて，フルフォントネームとポストスクリプトネームがあります．
そしてこのポストスクリプトネームにおいて，上記二つのフォントは，タイトルの通り
**LinLibertineI**
という名前でおそろいなのです．~~知能の足りないアベックかよ……~~

実際，MS WordとかのAdobe Acrobatプラグインの設定の箇所でフォントを除くとポストスクリプトネームで埋め込む/埋め込まないフォントなどの一覧が見れるのですが，`LinLibertineI`というフォントのみ（？）2つ並んでいます．

しかも一方を常に埋め込むように設定すると，もう一方をもし埋め込まない設定にしていたとしても埋め込まない設定から外れてしまうという残念な仕様
(まあ残念なのはポストスクリプトネームで管理してるAcrobatというよりは，名前を同じにしたLibertine製作チーム？の方でしょうが)

#引き起こされるバグ#
MSWordでLinux Libertine Italicとして文字を含む文書をPDF Maker(Acrobatのプラグイン)を利用してPDFに変換する際ポストスクリプト名でフォントがやり取りされるらしく，その際名前を取り違えられ，Linux Libertine ItalicがLinux Libertine Initialsに変えられてしまい，Initialsは小文字用フォントがないのでTOFU文字が並ぶという凄惨な事態を招くバグが存在していました......
#回避方法#
これを回避するためにはInitialsをアンインストールするくらいしか思いつきませんでした．
Acrobatの設定でどちらかのLinLibertineIを埋め込まない設定とかにすればもしかしたらいいのかもしれませんが，見分けられないので，きっと必要になったらその時インストールするでしょと思うので，消してしまっていいと思います．
またMSWord標準機能でPDFを制作する場合にはInitialsをインストールしている状態でもちゃんとItalicはItalicでPDF文書に変換されましたので，Acrobatを使う必要のない場合はこれでもいいと思います．
ask-sdk v2 で別のインテントハンドラーに処理を移譲する書き方



v1 では `this.emitWithState` で処理を移譲することができた。  
v2 だとシンプルにこう書けば良いらしい。

```js

const fooHandler = {
    canHandle(input) {
        ....your logic
    },
    handle(input) {
        // invoke another handler
        return barHandler.handle(input);
    }
}
```


## 参考

- https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs/issues/391
android カメラアプリを作ろう　その２ androidのカメラから映像を取得する

えー、別に火曜日はお休み！とか言うルールではないんですが、
なぜか2週に渡って火曜の更新が止まってますね。

さ、サボってた訳じゃないから･･･


ってことで今日もあんま時間取れないけど作業はーじめーるよー

# カメラから映像を受け取る

## androidのカメラAPIはいずこや？

ここです。
[android Developers - Camera API(英語)](https://developer.android.com/guide/topics/media/camera)

２行で全部回答が出た気がしないでもないけど継続。
なんか元々Cameraクラスがあったんだけど、非推奨で、今はCamera2クラス使ってね！みたいなことが冒頭に書いてありますね。
しかも追加されたのがAPI level 21(Lollipop)からだとか。

[Android Developers Documentation - android.hardware.camera2(英語)](https://developer.android.com/reference/android/hardware/camera2/package-summary)

とりあえずドキュメントを読んでみる。
ふむ。

使うには…えーと…

あー…

あ、これ凄い手順めんどくさいやつだ。
必要なものと手順とで分けた方がよさそう。

## プレビューのために必要なもの

|番号| グループ | 名称 | 前提 | 説明 | 取得方法 |
|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | カメラ制御 | CameraManagerインスタンス  | - | カメラの制御に必要。システムサービスからオブジェクトをもらう。  | getSystemService(CAMERA_SERVICE)  |
| 2 | カメラ制御 | CameraId  | 1  | 個々のカメラに割り振られた端末固有の番号。  | (CameraManager).getCameraIds() |
| 3 | カメラ制御 | CameraCharacteristicsインスタンス  | 1,2 | カメラの設定情報。  | (CameraManager).getCameraCharacteristics(<CameraId>)   |
| 4 | カメラ制御  | CameraDeviceインスタンス  | 1,2 | カメラの実体となるオブジェクト。 | CameraDeviceクラスからのコールバック  |
| 5 | 画面描画 | SurfaceTexture  | - | 描画対象となるテクスチャ。カメラから取得した画面を投影する  | TextureViewなど  |
| 6  | 画面描画 | Surface | 5 | SurfaceTextureを貼り付ける描画先のターゲット  | new Surface( SurfaceTexture )  |
| 7 | セッション | CaptureSession | 4,6 | カメラとアプリをつなぐもの。カメラで取得した画像はこのセッションを介して取得する  | CameraCaptureSessionクラスからのコールバック   |
| 8  | セッション  | CaptureRequest | 4,6 | カメラへのキャプチャ要求を示すもの。  | CaptureRequestBuilderを利用する  |
| - |パーミッション| android.permission.CAMERA | - |カメラへのアクセス要求を示すパーミッション。|androidマニフェストに記述|

...たぶんこれで合ってるはず？
図で描いてみないとちょっとわかりにくいかも。
シーケンス図も合った方がいいかなぁ…コールバックも絡んでるから文章でつらつら書いても困るよね…

とりあえずぐちゃぐちゃ弄ってみて、プレビューできるところまではこぎつけました（疲弊）

↓こんな感じ
![Capture_00.jpg](https://qiita-image-store.s3.amazonaws.com/0/259679/5adaba56-0200-56f2-8287-3a75e8f3978d.jpeg)

---

ソースは試作なのもあってすっごい汚いので、どっちにしても作り直しですね･･･
技研。技研だから･･･

えー...今日は04:20:48でフィニッシュ。
四色碁のルール説明

プログラミングの題材として、四色碁を作ってみようかと思います。

# 四色碁とは
[豆腐の角さん](http://qwer191.blog.fc2.com/blog-entry-1018.html)が考えた四人対戦の囲碁です。四人の中で一番地が多いことを目指います。囲碁のルールがわかっていれば、誰でも楽しむことができます。
# 石の取り方
まず一色のカラーでしか石をとることはできません。相手の赤をとるためには必ず一色のカラー、つまりこの場合であれば青で囲う必要があります。
![sample01.png](https://qiita-image-store.s3.amazonaws.com/0/265586/a04e5db5-f340-c5eb-ea52-0f0b112a1250.png)
なので緑がこう打っても、赤はとられません。石の逃げ道は３に増えました。
![sample02.png](https://qiita-image-store.s3.amazonaws.com/0/265586/bba8c9f5-e2d9-1a10-ea08-db5e12e314ee.png)
中の石がどんなカラーでも、周囲を一色で囲めばすべて取ることができます。
![sample03.png](https://qiita-image-store.s3.amazonaws.com/0/265586/855a8aea-526b-8554-7b63-1f4602197e64.png)

# ソースコード
説明の図は[Processing](https://processing.org/)で作成しました。今回はここまでです。

```java:sketch.pde
Board board;

void setup()
{
  size(880, 880);
  board = new Board();
  board.initGame();
} 

void draw()
{
  background(255, 255, 203);
  board.display();
}
```

```java:Board.pde
class Board {
  int cellSize = 80;
  ArrayList<ArrayList> cells = new ArrayList();

  Board() {
    for (int i=1; i <= 9; i++) {
      ArrayList<Cell> row = new ArrayList();
      for (int j=1; j <= 9; j++) {
        row.add(new Cell(j, i ));
      }
      cells.add(row);
    }
  }
  void initGame() {
    getCellAt(4, 3).putStone( Cell.GREEN);
    getCellAt(3, 4).putStone( Cell.BLUE);
    getCellAt(4, 4).putStone( Cell.PINK);
    getCellAt(5, 4).putStone( Cell.BLUE);
    getCellAt(4, 5).putStone( Cell.BLUE);    
  }
  Cell getCellAt(int col, int row) {
    if(col < 0 || col > 7 || row < 0 || row > 7){
      return null;
     }
     return (Cell)cells.get(row).get(col);
  }
  void display() {
    for (ArrayList row : cells) {
      for (Object c : row) {
        Cell cell = (Cell) c;
        cell.display();
      }
    }
  }
}
```

```java:Cell.pde
class Cell {
  static final int SIZE = 80;
  static final int GREEN = 1;
  static final int YELLOW = 2;
  static final int PINK = 3;
  static final int BLUE = 4;
  static final int GHOST = 14;

  int x;
  int y;
  int stone = 0;
  int size = SIZE;

  Cell(int x, int y) {
    this.x = x;
    this.y = y;
  }

  int getCol() {
    return this.x;
  }

  int getRow() {
    return this.y;
  }

  boolean hasStone() {
    return (this.stone != 0);
  }

  int getScore() {
    return this.stone;
  }

  void display() {
    stroke(0);
    fill(210, 185, 80);
    rect(x * size, y * size, size, size);
    if (this.stone != 0) {
      if ( this.stone == GREEN)
      {        
        fill(#49b675);
      } else if ( this.stone == YELLOW)
      {        
        fill(#FFE374);
      } else if ( this.stone == PINK)
      {        
        fill(#EF9CB5);
      } else if ( this.stone == BLUE)
      {        
        fill(#0044FD);
      }else{
        fill(#FFFFFF,200);
      }
      stroke(0);
      ellipse(x * size, y * size, size * 0.9, size * 0.9);
    }
  }

  boolean putStone(int stoneColor)
  {
    this.stone = stoneColor;
    return true;
  }
}
```
aptによるパッケージ管理

#はじめに
普段はCentOSばかり使っているため、先日少しDebianを使ってみたら、そもそもパッケージ管理の方法すら分かりませんでした。慌てて勉強しました。

#パッケージ管理コマンド
CentOS (RHEL) でのyumに相当するaptというコマンドがあります。単にaptと叩くと簡単な使い方が出てきますので、これでコマンドを調べていきます。
```apt: 基本コマンド```

##パッケージの更新
### apt update ~ apt list --upgradable ~ apt upgrade

```apt update```コマンドでパッケージの更新確認が行えます。

```
# apt update
Hit:1 http://jp.archive.ubuntu.com/ubuntu xenial InRelease
Hit:2 http://jp.archive.ubuntu.com/ubuntu xenial-updates InRelease                                    
Hit:3 http://jp.archive.ubuntu.com/ubuntu xenial-backports InRelease                                  
Hit:4 http://security.ubuntu.com/ubuntu xenial-security InRelease                                     
Reading package lists... Done                         
Building dependency tree       
Reading state information... Done
94 packages can be upgraded. Run 'apt list --upgradable' to see them.
```

アップグレード可能パッケージがあり、```apt list --upgradable```で確認できると言われました。早速やってみます。

```
~# apt list --upgradable
Listing... Done
apt/xenial-updates 1.2.26 amd64 [upgradable from: 1.2.24]
apt-utils/xenial-updates 1.2.26 amd64 [upgradable from: 1.2.24]
base-files/xenial-updates 9.4ubuntu4.6 amd64 [upgradable from: 9.4ubuntu4.5]
（以下略）
```

アップデートの実施は```apt upgrade```で実施します。RHEL系で言うところの```yum update```でしょうか。

##パッケージのインストール
### apt list [packeage] ~ apt install [package]

パッケージを検索するには、```apt list```を使います。例としてapache httpdでやってみます。

```
# apt list apache2
Listing... Done
apache2/xenial-updates,xenial-security 2.4.18-2ubuntu3.8 amd64
N: There is 1 additional version. Please use the '-a' switch to see it
```

見つかったのでインストールします。

```
# apt install apache2
# apt list apache2
Listing... Done
apache2/xenial-updates,xenial-security,now 2.4.18-2ubuntu3.8 amd64 [installed]
N: There is 1 additional version. Please use the '-a' switch to see it
```

後ろに[installed]が表示されているので、インストールがうまくいっていることが分かります。
VSCode上でxmodmapのリマップが無効になる

# 環境
- Ubuntu 16.04.4 LTS
- VSCode 1.24.1

# 症状
VSCode上でxmodmapのリマップが無効になる

# 解決
下記の設定を追加すると無事解決

```js
"keyboard.dispatch": "keyCode"
```
# 参考
[VS Code no longer respects remapped escape key using xmodmap · Issue #32037 · Microsoft/vscode](https://github.com/Microsoft/vscode/issues/32037)
Teslaシリーズ用nvidiaドライバーの正しいインストール方法

2020/04 おそらくこの記事の内容はもう古いです. GPUサーバーに今はもう触れてないので記事の更新および検証が出来ない状態です. 

# 背景

<b>NVIDIAのドライバー関連の完備かつ簡便なインストール方法は現状存在しない．これが重要</b>

とあるGPUサーバーに環境構築を頼まれてやっていたところ、業者がドライバーをインストールしているのにDKMSを入れていなかった+寝ぼけてsudo apt-get updateした結果、いじる必要のないはずだったNVIDIAドライバーが使用不能になり、GUIが壊れ、事態は迷宮入りしたのだった…

業者許さん

# TL;DR
- aptを信用してはいけない
- 面倒でもrunファイルを使うべき
- DKMSは入れよう
- GeForceでないものでaptは特に危ない模様

# 失敗する（ログインループに陥る）方法

```bash:
sudo apt-get update
sudo ubuntu-drivers autoinstall
sudo reboot
```
なーんだ、Canonicalやるやん…そう思った俺がアホやった

これでうまく行く人も一定数居るようだがクリーンインストール直後で駄目なら下の方法を試したほうが多分うまく行く

# 正しい方法

## nouveauを止める

```bash:
lsmod | grep -i nouveau
```
↑のコードでnouveauを含む行を観測したら

```conf:/etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
```
を新規作成する

```bash:
sudo update-initramfs -u
sudo reboot
```
これでもう一度lsmod（以下略）して1行も出なければOK

## 必要なものを先に入れる

```bash:
sudo apt-get install build-essential
sudo apt-get install dkms
```

## CUDAとドライバーのインストール

ドライバーとCUDAはCUDAから先に入れる
バージョンの不整合に注意して共々runファイルを
https://developer.nvidia.com/cuda-downloads
http://www.nvidia.com/Download/index.aspx?lang=jp
まず上でCUDAのバージョン適当に選んで、次に下で対応するバージョンのドライバーをダウンロードする

後はrun叩くだけ chmod忘れないこと
<b>ここからが今回の本題</b>

```bash:
./cuda_version_requiringdriverversion_linux-run --silent --toolkit --no-opengl-libs
./NVIDIA-Linux-arch-driverversion.run --silent --no-opengl-files --no-libglx-indirect --dkms
```

ここで--no-なんたらのオプションが足りないと<b>皆様おなじみログインループに入る。</b>
cudaのサンプルが欲しい人は --samples --samplespath=/hoge/fuga/
をcudaのrunのオプションにつけるとよしなにやってくれる

ここでcudaのログにライブラリが足りないと言われたら（例としてlibhogeとしておく）素直に

```
sudo apt-get install libhoge(-dev)
```

すればいいのだが、cudaのrunファイルはどういうことか/usr/lib/直下しか見てくれない　そこでインストールされたlibhoge(-dev)の実体を探して（大体/usr/lib/x86_64-linux-gnuらへんに居る）、

```
sudo ln -s /usr/lib/x86_64-linux-gnu/libhoge.so /usr/lib/libhoge.so
```

としてやる必要がある。全く面倒である。

最後に、rebootする前に下を適当にbashrcの末尾なりprofile.dに新規sh設置するなりして終了

```bash:
export CUDA_HOME="/usr/local/cuda-<version>" 
export PATH="$CUDA_HOME/bin:$PATH" 
export LD_LIBRARY_PATH="/usr/local/lib:$CUDA_HOME/lib64:$LD_LIBRARY_PATH" 
export CPATH="/usr/local/include:$CUDA_HOME/include:$CPATH" 
export INCLUDE_PATH="$CUDA_HOME/include" 
```

CUDNN関連はただコピーするだけだし省略

# 参考
https://help.sakura.ad.jp/hc/ja/articles/115000122721-CUDA-Toolkit-GPU%E3%82%AB%E3%83%BC%E3%83%89%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E5%B0%8E%E5%85%A5%E6%89%8B%E9%A0%86
さくら様様　大体の方針はこれでうまく行った　だがnouveauについてや、libが足りないエラーについては特に書かれていなかったのでちょっと躓いた
Ubuntu周り、Qiitaも含め思い思いの解決策が載っていたがどれも当たらなかったのでこのサイトにたどり着くまで無限に時間消費したのが辛い

https://qiita.com/sasayabaku/items/2323a2c501e58c0621b6
blacklist nouveau関連はこれがミニマムになりそう
他にもinitramfs関連色々いじれる人はいじっていけばいいと思いました
僕が考えた最強のキーリマップ

***
キーレイアウト弄りが趣味の私が、個人的に愛用しているキーリマッピングを紹介するだけの記事です。なおここで紹介するのは特殊キーのリマップとなっています。
***

![JIS配列](https://i.imgur.com/f6yOuz6.jpg)
※JISキーボード

- 変換 -> Enter
- 無変換 -> 半角/全角
- CapsLock -> BackSpace
- ] -> ハイフン
- ハイフン -> @
- @ -> ]

特に多用するキー(Enter, BackSpace, E/J)をホームポジを崩さずに打てると生産性がぐっと上がるので、どんどん布教していきたい。その他にも、推しのリマップがあれば教えてくださると大変嬉しいです。
rbenvで.ruby-versionに書いてあるバージョンのRubyをインストールする

こんなにシンプルなのに2回も方法を忘れてしまったのでちゃんと文字に起こす

```bash
$ ls ./.ruby-version
.ruby-version

$ cat ./.ruby-version
2.4.4

$ rbenv install
ruby-build: use openssl from homebrew
Downloading ruby-2.4.4.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.bz2
Installing ruby-2.4.4...
ruby-build: use readline from homebrew
Installed ruby-2.4.4 to /Users/naari3/.rbenv/versions/2.4.4
```

バージョン番号を指定しない場合、カレントディレクトリにある`.ruby-versions`の値をバージョン番号として見てくれる

カレントディレクトリに`.ruby-version`がない場合は`~/`に辿り着くまで親のディレクトリを走査していく