OmniAICreator/Qiita-1.07M huggingface dataset:
改めてテストの種類をまとめておく

# ウオーターフォール開発のV字モデルテスト

## 単体テスト UnitTest(UT or PT)
Rspecだと主に`/model`
メソッドや関数が要件通りに動作するか確認する。

## 結合テスト IntegrationTest(IT)
Rspecだと`/request`
複数の処理を組み合わせて、エンドポイントが要件通りに動作するかテストする。
リクエストの振る舞いをテストするので、
システム内で外部連携がある場合はスタブでも良い。(呼び出しができていれば良い)

## 総合テスト SystemTest(ST)
Rspecだと`/system`
複数のエンドポイントを利用してユースケースのシナリオがうまくいくかテストする。
外部連携もスタブでは無くて実際のシステムを結合してテストする。
リアルなデータでテストできると良い。
実際のユーザーの操作するユースケースを網羅する。
シナリオテスト、E2Eともいう。

## 負荷テスト StressTest(ST)
システムに高負荷をかけてパフォーマンスが要件を満たすかテストする。

* システム負荷のピーク時に十分なパフォーマンスが得られるかテストする。
* スパイクに耐えられるかテストする。

## セキュリティテスト SecurityTest(これもSTじゃん)
セキュリティバグが存在しないかテストする。

## ユーザー受け入れテスト (UAT)
システム開発を外注している時に行う。
システムだけでは無く、ドキュメント、契約など含めてテストする。
契約時の成果物の確認

## ユーザーテスト
実際のユーザに新バージョンのサービスを使用してもらうことで、開発やテスト時に気づかなかった問題やユーザビリティーを発見する。

# DevOps系のテスト?(品質担保手法)

## カオスエンジニアリング

http://principlesofchaos.org/?lang=ENcontent

意図的にシステム障害を起こす事で本番稼動中のシステム障害をシミュレートする考え方です。  

* 出る影響がを確認する。
* システムの自動復旧を確認する。
* ダウンタイムを確認する。

## SRE/CREのPRR(Production Readiness Review)

生産準備レビュー
googleのSRE/CREはやっているみたいです。
運用設計(監視、お問合せ体制など)がきちんとできているかをレビューします。

## 探索的テスト

あらかじめ作成されたテストケースをテストするのではなく、ソフトウェアの振る舞いやテスト結果を見ながらテストエンジニアが設計、実施、記録、検証を同時にテストする手法です。
アドホックテスト、モンキーテストとの違いは、

* 方針や目的を明確に定める
* テストエンジニアのスキルに基づき、潜在的な不具合を検知する可能性の高いテストを集中的に行う
* 設計、実施、記録、検証を同時にテストする

# ソースコード解析からのバグ予想
バグ修正のためのコミットで最近何度も修正されたファイルにはバグがある可能性は高いなどのスコアを出してくれます。
Google ではコードの品質保持の一つの方法としてこういった指標も利用しいているとのこと。
ググるとツールが結構出てきます。

といった感じです。
Node.jsのHTTPリクエストヘッダの最大サイズでハマった話

## 現象

- Node.js(v12.3.1)で立てたWebサーバにアクセスすると、時折HTTPリクエストに失敗する
- Cookieを削除したり、ブラウザを再起動すると治ることもあるが、根本的な原因がわからない

```javascript:サンプルコード
const http = require('http');

const server = http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
});

server.listen(8080);
```
## 原因

- Node.jsの最大HTTPリクエストヘッダサイズのデフォルト値である8kBを越えるHTTPリクエストヘッダサイズを送信していたことが原因だった

- Node.jsは、2018/11に[DoS攻撃の脆弱性対応](https://nvd.nist.gov/vuln/detail/CVE-2018-12121)として、デフォルトのHTTPリクエストヘッダの最大サイズを変更前の80kBから8kB(8192Bytes)に変更する修正が加えられた

- デフォルトでは、HTTPリクエストヘッダのサイズが8kBを越えるとソケットが強制破棄されて「431 Request Header Fields Too Large」を返す

```bash

$ npm start

> sample-nodejs-header-overflow@1.0.0 start /../../../sample-nodejs-header-overflow
> node index.js

// curlで8kB以上のHTTPリクエストを送信
ErrorCode:  HPE_HEADER_OVERFLOW
BytesParsed:  8559

// curlで8kB以上のHTTPリクエストを送信
ErrorCode:  HPE_HEADER_OVERFLOW
BytesParsed:  8559

// curlで8kB以上のHTTPリクエストを送信
ErrorCode:  HPE_HEADER_OVERFLOW
BytesParsed:  9085

```

## 対策

- HTTPリクエストヘッダのサイズが超えた場合に起こるclientErrorイベントを補足して、ソケットが強制的に破棄されないようにエラーハンドリングを行う  

```javascript

const http = require('http');

const server = http.createServer((req, res) => {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World');
});

server.on('clientError', (err, socket) => {
    console.log('ErrorCode: ', err.code);
    console.log('BytesParsed: ', err.bytesParsed);
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});

server.listen(8080);

```

- アプリケーション起動時に「--max-http-header-size」という起動オプションを設定して、Node.jsが受け取る最大のHTTPリクエストヘッダサイズを増やす  

```bash 
$ node --max-http-header-size=16384 index.js
```

## おわりに
今回リクエストヘッダのサイズが8kBを越えた主な原因は、多数のCookieを使ってWebサーバにアクセスしていたことでした。
仕様上Cookieの数が多くなり、HTTPリクエストのサイズに不安がある場合は、エラーハンドリングを正しく実装して、起動オプションでNode.jsが受け取るHTTPリクエストサイズの最大値を上げておくと良いかと思います。

## 参考

- https://github.com/nodejs/node/commit/a8532d4d23

- https://www.nearform.com/blog/protecting-node-js-from-uncontrolled-resource-consumption-headers-attacks/

- https://github.com/nodejs/node/issues/25528

- https://nodejs.org/docs/v12.3.1/api/http.html#http_event_clienterror
AWSで業務時間外には使わないリソースを停止しておいてコスト削減するスタックをサーバレスで作った話

以前エンジニア組織のコスト管理おじさん業をやっていて、
その中の一つにインフラコスト管理というテーマがありました。
その時に使ってみてその後色々なプロジェクトに展開して行った手法を紹介します。

## 概要

staging環境など、production環境以外のRDS, EC2を夜間は停止しておいて、
朝方メンバー出社する前に起動しておく事で節約します。

## コード

https://github.com/soartec-lab/aws_cloudformation_batch

## 説明

### 技術スタック
* CloudFormation
-> IaCというより不要になった場合に全て消せるように
* CloudWatchEvent
-> スケジューラー
* CloudWatchLogs/CloudWatch
-> イベントログ取得、監視
* Lambda
-> インスタンスの起動、停止処理

### 説明

インスタンスの起動、停止処理をPythonで実装したLambdaを
CloudWatchEventで起動する。
監視をCloudWatchLogs/CloudWatchで行う。
上記の構成をCloudFormationでサクッと構築する
railsのDigest::UUIDを試す

# Digest::UUID見てみたのでメモ
## 公式ドキュメント
https://api.rubyonrails.org/classes/Digest/UUID.html

## 概要
定義されているメソッドは以下の３つでそれぞれハッシュ関数が違います。

* self.uuid_v3
-> `Digest::MD5`を使用
* self.uuid_v4
-> `SecureRandom.uuid`の簡易メソッド。
* self.uuid_v5
-> `Digest::SHA1`を使用

```ruby
$ Digest::UUID.uuid_v4
=> "4ad2a6a9-0135-4158-94d3-a33e41bbe048"

$ Digest::UUID.uuid_v3("name_space", "sample")
=> "3b0ead59-ca8d-350b-a392-e656db58b0fc"

$ Digest::UUID.uuid_v5("name_space", "sample")
=> "d7a9ae1a-b099-5318-8828-340cc10a1550"
```

## rails -v

```shell
$ bundle exec rails -v
Rails 6.0.2.rc1
```
【英語】follower/followedの話【Rails】

##followうんぬん
Railsチュートリアル１４章をやっていて、followという単語の変化形がどのような意味で使われているかが分かりにくいと感じたので、整理しようと思う（僕だけかもしれないけど）。
この分かりにくさは、単に英語の文法的な話だけでなく、（世間一般の）慣習的な話が絡んでくることから生じていると思う。
よって、能動とか受動、分詞といった英文法を理解できていても、頭に？が浮かぶことになる。

###followerとは何か？
followerはユーザーをフォローしている人である。
AがBをフォローしている場合、Aのことを指す。

```
A follows B
```
である。

しかし、twitterの話題とかで「フォロワー」という言葉を使った時、AとBどちらのことを言っているのだろう。
「フォロワーに〇〇さんっていう人がいて〜」なんて言った場合に、上の意味を使って主体であるAを指すとしたら、自分のことを「フォロワー」と言っていることになる。
つまり、この文脈ではBを指すことになる。
世間一般的な「フォロワー」の使い方としては、こちらがスタンダードなんじゃないかと思う。

しかし、チュートリアルのフォロー機能ではもともとの意味でAを指している。
よって、active_relationship.follower（フォロワーを返す）は、主体としてのAを返す。

###followedとは何か？
followedとは、followerの逆で、フォローされているBのことである。

```
B is followed by A
```
である。

よって、active_relationship.followed（フォローしているユーザーを返す）は、Bを返す。

「フォローしている」って書いてあるんだから、Aを指すんじゃないの？と思うかもしれないが、「Aがフォローしているユーザー」という意味だからBになる。

##結論
結局のところ、世間一般的な慣習として使われている「フォロワー」という言葉を無視して、英文法的に考えればいいだけの話である。
現在分詞を使って

```
following user
```
と書けば、userはAのことであり、"follower"である。
現在分詞は能動関係を表すのだから、当然といえば当然である。

過去分詞を使って

```
followed user
```
と書けば、userはBのことである。
過去分詞は受動関係を表すのだから、やはりこれも当然である。
Raspberry Pi で作る謎のラジオサーバ

radiko.jp でいいじゃん。

毎回 FFmpeg のコマンドラインを忘れるのでメモ。

## 用意するもの

- サン電子 RDPC-101 USB ラジオレシーバー
  - すでに入手困難
- [rdpc101.py](https://github.com/autch/rdpc101.py) 
- Raspberry Pi
  - Pi4B で動作確認。たぶん AAC エンコーダがリアルタイムにできればどんなボードでもいける。

## やり方

拙作 [rdpc101.py](https://github.com/autch/rdpc101.py) で RDPC-101 を同調させておく。

```shell-session
$ python3 rdpc101.py 77.2        # 77.2MHz -- FM NORTH WAVE@札幌大通
```

これで RDPC-101 のオーディオ入力にラジオの音声が来るので、Raspberry Pi の FFmpeg をこんな感じで実行する。

```ffmpeg_stream.sh
#!/bin/sh

mkdir -p hls/
rm -f hls/*

ffmpeg -hide_banner -re \
	-f alsa -ar 48000 -ac 2 -i hw:1 \
	-ar 48000 -ac 2 \
	-c:a aac -b:a 192k \
	-f segment -segment_format mpegts -segment_time 10 -segment_wrap 6 \
	-segment_list_flags live \
	-segment_list hls/radio.m3u8 hls/radio.%04d.ts
```

こうして `hls/` ディレクトリにセグメントとプレイリストができるので、`cd hls && python -m http.server 3000` とかして `hls/` ディレクトリを公開し、VLC とかで公開したサーバの `index.m3u8` を（http で）開くと再生できる。
Python 半角の記号を削除したい

## やりたいこと
* 文字列の中に含まれる以下の記号を削除したい

```
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
```

## 確認環境
* python3.6
* CentOS7

## 方法
```
>>> import string
>>> text = 'Abcd1!EfgH"#$%2s&\'I()j*5k+,-./:l;MMM<=>NNN?@[\Z]^_`{99|00}7~8'
>>> result = text.translate(str.maketrans( '', '',string.punctuation))
>>> print(result)
Abcd1EfgH2sIj5klMMMNNNZ990078
```

## 解説

* 分解して記載してみる

```
>>> import string
>>> text = 'Abcd1!EfgH"#$%2s&\'I()j*5k+,-./:l;MMM<=>NNN?@[\Z]^_`{99|00}7~8'
>>> kigo = string.punctuation
>>> print(kigo)
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
>>> table = str.maketrans( '', '',kigo)
>>> result = text.translate(table)
>>> print(result)
Abcd1EfgH2sIj5klMMMNNNZ990078
```

* 1～4行目
* 記号を含む文字列定数 string.punctuation を利用する
 
```
>>> import string
>>> kigo = string.punctuation
>>> print(kigo)
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
```

* 6行目
* 文字変換の為の translate() 用変換テーブルを作成

```
>>> table = str.maketrans( '', '',kigo)
# 第3引数に指定した文字を削除する
```

* 7行目
* 変換テーブルを使い、対象テキストを変換(対象文字を削除)

```
>>> result = text.translate(table)
```

* 8行目
* 結果の確認

```
>>> print(result)
Abcd1EfgH2sIj5klMMMNNNZ990078
```


## 使用例

* 日時ISOフォーマットから数値のみ抽出

```
>>> from datetime import datetime
>>> d = datetime.now().isoformat()
>>>
>>> print(d)
2019-12-03T19:03:16.015300
>>> 
>>> dnum = d.translate(str.maketrans( '', '',string.punctuation + 'T'))
>>> print(dnum)
20191203190316015300
```

* 消したい記号を絞るなど

```
>>> table = str.maketrans( '', '', '()<>[]{}')
```

## その他、参考情報

* 文字列定数は以下のようにstring.punctuation以外にも多数ある

* 小文字

```
>>> print(string.ascii_lowercase)
abcdefghijklmnopqrstuvwxyz
```

* 大文字

```
>>> print(string.ascii_uppercase)
ABCDEFGHIJKLMNOPQRSTUVWXYZ
```

* 数値

```
>>> print(string.digits)
0123456789
```

* 印刷可能文字 ※空白も含まれるので注意

```
>>> print(string.printable)
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~



>>>
```

* 空白

```
print(string.whitespace)
```

以上
Swift Network.framework Study 20191204「UDP」

# Study
Network.framework
Study：Client側

## 環境

Client：Swift、Xcode
Server：Java、NetBeans

# Client Source Swift

SwiftはNWConnectionに「NWParameters.udp」を設定するだけ。

```swift
import Foundation
import Network

var running = true

func startConnection() {
    let myQueue = DispatchQueue(label: "ExampleNetwork")
    let connection = NWConnection(host: "localhost", port: 7777, using: NWParameters.udp)
    connection.stateUpdateHandler = { (newState) in
        switch(newState) {
        case .ready:
            print("ready")
            sendMessage(connection)
        case .waiting(let error):
            print("waiting")
            print(error)
        case .failed(let error):
            print("failed")
            print(error)
        default:
            print("defaults")
            break
        }
    }
    connection.start(queue: myQueue)
}

func sendMessage(_ connection: NWConnection) {
    let data = "Example Send Data".data(using: .utf8)
    let completion = NWConnection.SendCompletion.contentProcessed { (error: NWError?) in
        print("送信完了")
        running = false
    }
    connection.send(content: data, completion: completion)
}

startConnection()

//dispatchMain()

while running {
    sleep(1)
}
```

# Server Source Java
JavaはTCPとUPDで使用するクラスが違う。

```Java
package example.java.network;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ExampleServerUDP {
    private static final int EXHOMAX = 255;
    
    public static void main(String[] args) {
        try {
            DatagramSocket​ datagramSocket = new DatagramSocket​(7777);
            DatagramPacket datagramPacket = new DatagramPacket(new byte[EXHOMAX], EXHOMAX);
            while(true) {
                datagramSocket.receive(datagramPacket);
                for(int i = 0; i < datagramPacket.getLength(); i++) {
                    System.out.print(datagramPacket.getData()[i]);
                    System.out.print(" ");
                }
                System.out.println();
                datagramPacket.setLength(EXHOMAX);
            }
        }
        catch(Exception e) {
        }
    }
}
```
Laravel6 ViewからControllerへ渡されたget/post データの取得の仕方 パターン整理

# Laravelでviewからpost/get したデータをControllerで記述形式がいくつかあって、よくわからないので整理します。

とりあえず、思いつく限りでどんな記述形式がるか書き出してみます。
仮にview側でpostかgetでデータが送られたときに、3パターンくらい取得方法がある気がします。
記述形式はどれでもいいのかと思いきや、エラーではじかれる組み合わせがあるっぽいので整理します。

形式は１個でいい気がするけど、どうしていくつもあるのでしょう？
たぶん、整理していくうちに分かるかもしれません。

```php:Controller
function example(Request $request){
 $request->input('name');
 $request->name;
 $request('name');
}
```

例えば、View側からPOST形式でデータを渡した場合

```php:View
<form method="POST" action="/index">
   <input type="text" name="name">
   <input type="text" name="pass">
   <input type="submit">
</form>
```
コントローラー側で正しく動作する記述は

```php:Controller
function example(Request $request){
 $request->name;
 $request->input('name');
}
```
の２つでした！
```
$request('name');
```
を使用すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/186e9615-e2e8-c2eb-10c8-7926a9738265.png)
こんなエラーが出ちゃいました。

次にget形式ではどうなるか調べてみます。

```php:View
<form method="GET" action="/index">
   <input type="text" name="name">
   <input type="text" name="pass">
   <input type="submit">
</form>
```

postの時と同じ結果になりました（笑）
ということは、単純に自分の勘違いで使えないコードを覚えてしまったようです。。
どうして、こんな勘違いをしていたのか？
それは２つの記述方法が、混同して記憶違いで直感的に書きやすい記述が刷り込まれてしまったからだと思います（言い訳）
結局、形式が２つある理由はよくわかりませんでした。
１つだけなら、勘違いすることもないのにと思いました。


Laravelでは
ページ表示にview()とredirect()があって、
どちらを使うと便利なのかわからずにいます。

redirect()は記述形式がroute()を使う場合と使わずに記述する方法があるので、
どれがどういうときに向いている記述なのか？
調べたいと思います

以上、勘違いしていましたという記事になりました。
Kaggle初心者に向けたタイタニックコンペの課題


先日、Kaggleのタイタニックコンペを課題とした社内研修を行いました。
その際の説明資料と参加者にやってもらった演習を共有します。
資料と課題はKaggleのNotebookとなっていますので、興味のある方はそちらも合わせてご確認ください。

ちなみにQiita初投稿です。

## はじめに

### なぜKaggleを選んだか

研修だけで全てを教える（学ぶ）ことはできないため、各個人で継続して取り組んでもらう必要があると考えました。
何かを学ぼうとしたときに環境構築で躓くこともあるため、それが不要となるKaggleを利用することにしました。

### 想定した参加者

- 機械学習に興味を持っている
- Kaggleを利用したことがない
- Python未経験

## 研修について

### 研修の目標

- 機械学習の流れを体験する
- 『自分でもプログラムが書けそう』と感じてもらう

### 説明資料、演習課題

Kaggleを使用するので、説明資料もKaggleのNotebookとして作成しました。

- 説明資料：Kaggleチュートリアル『Titanic生存者予測』をやってみよう！ 
https://www.kaggle.com/plasticgrammer/kaggle-titanic

- 演習課題：Titanic: Predict survivors (ΦωΦ)
https://www.kaggle.com/plasticgrammer/titanic-predict-survivors

###進め方

説明と演習をバランスよく組み合わせようと思い、下記の流れで進めました。

1. 資料を使ってデータ分析まで説明
  - Pythonの基本
  - Kaggleの使い方、用語説明
  - 機械学習の流れを確認（データ読込,データ分析）

1. データ分析の演習

1. 資料を使って予測まで説明
  - 前処理
  - モデル作成、学習、予測

1. 予測精度向上の課題

## 用意した演習

下記内容は演習用のNotebookにも記載していますが、一応こちらの記事にも記載しておきます。

### データ分析

#### step1) データの概要を確認
- トレーニングデータとテストデータの行数、列数を確認しましょう
- トレーニングデータの先頭5件を表示してみましょう
- テストデータの先頭5件を表示してみましょう 
- トレーニングデータとテストデータの違いは何でしょうか？  
機械学習で生存者を予測するとは、具体的にどのようなことでしょうか？

#### step2) データの詳細を確認
- infoメソッドでトレーニングデータの情報を表示してみましょう
- トレーニングデータの欠損値状況を確認しましょう
- テストデータの欠損値状況を確認しましょう
- ターゲット変数 Survived の値毎の件数を確認してみましょう
- 変数 Pclass にはどんな値が設定されているか確認してみましょう
- 変数 Age の分布をヒストグラムで確認してみましょう
- 変数 Age の最大値、平均値、中央値を確認してみましょう
- 変数 Sex の分布をvalue_counts＋棒グラフで確認してみましょう
- pd.crosstabを使って、【Survived毎】の 変数 Sex の件数を確認してみましょう

#### Step3) 相関関係があるのか可視化
- 【Survived毎】の 変数 Sex の件数を棒グラフで確認してみましょう  
相関関係はありそうですか？あるとしたらどのような傾向がありますか？
- 【Survived毎】の 変数 Pclass の件数を棒グラフで確認してみましょう  
相関関係はありそうですか？あるとしたらどのような傾向がありますか？

### 特徴量作成および予測

前提）Age（欠損値0埋め）、Sexを使用してRandomForestで予測する流れは作成済み

- Age の欠損値を中央値で埋めてみましょう
- Fare を予測に使ってみましょう
- Embarked を予測に使ってみましょう
- SibSp+Parch+1 を FamilySize として追加してみましょう
- FamilySize<=1 を IsAlone として追加してみましょう
- Cabin の１文字目を特徴量として追加してみましょう

## 振り返っての反省

今回の研修は５時間で行いました。
最後に用意していた予測精度を上げる課題を進めるのに、思った以上に時間かかり、
結果として難しかったという印象を持たれてしまいました。
後日、追加研修という形で再度実施しましたが、演習多めで１つ１つじっくりと進めるのが良いと感じました。

## おわりに

タイタニックコンペについて書かれた記事は多く、色々と参考にさせて頂きました。
Python初心者向けの研修課題にしようとした時に、資料としてまとめることが多かったので、私も皆さんのお役に立てればと共有しました。
Data Refineryで空白値などデータの扱われ方に注意が必要だったのでまとめてみた

#はじめに
Data Refineryとは、IBMのWatson StudioとWatson Knowledge Catalogの両方に搭載される、データの可視化・加工を行う機能です。
Data Refineryを触っていて、以下の扱われ方に微妙な違いがあることに気づきメモしておこうと考えた次第です。少しでもご参考になれば幸いです。

- 空白のみの文字列
- 文字数が0の文字列
- 値なし(missing)

Data Refinery自体の説明については、@ishida330さんが下記の記事でわかりやすくご説明されているので、どうぞご参照ください。

-[分析データの準備作業を楽に！～Watson Studioに標準搭載された「Data Refinery」をザクッと紹介してみる](https://qiita.com/ishida330/items/d7a6dcbce040eeee436a)
# テストデータ
下記のCSVデータをData Refineryで処理して、微妙な違いを確認してみます。
2行目には**「半角の空白１つ」**が2列目と3列目に、3行目には**「文字数が0の文字列」**が2列目、3列目に指定されています。

```text:test.csv
ID,テキスト,数値
1,One,1
2, , 
3,,
```
#データの加工処理
##1.初期状態
Refine開始時点では、1行目の「One」と「1」が表示されていて、2行目、3行目は何も表示されていない状態です。
*なお、ID列のデータタイプはData Refineryの機能により、データの内容から数値データと判別され、自動的にInteger型になっていますが、その他の列はString型となっています。*
![スクリーンショット 2019-12-04 時刻 20.17.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545557/46ac99ad-e56f-6ee8-6e8a-f26fd27b6ba5.png)
##2.数値列のデータタイプ変換
Operationから、Convert column typeを選び、数値列をIntegerに変換します。
2行目、3行目の数値列は「NA」という表示になりました。
![スクリーンショット 2019-12-04 時刻 20.25.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545557/eaaead2e-a4e5-c515-b8ee-38fc369e6736.png)
##3.テキスト列のmissingへの変換
OperationからConvert column value to missingを選び、テキスト列の「One」という値をmissingに変換します。
テキスト列は3行ともに画面上には何も表示されない状態になりました。
![スクリーンショット 2019-12-04 時刻 20.28.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545557/1e57a0ed-1481-82e3-6c8f-97048ae10c56.png)
##4.データの匿名化
テキスト列、数値列に対して、それぞれOperationからSubstitute（匿名化）を行います。これにより、テキスト列の3行はそれぞれ異なる値であることがわかり、
数値列の2行目、3行目は同じ値、さらにテキスト列の1行目とも同じ値であったことがわかります。
![スクリーンショット 2019-12-04 時刻 20.41.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545557/0be3bfe0-000b-fbc1-975c-af9311a4b36a.png)
##5.空行(empty rows）の除去
再び、**3.テキスト列のmissingへの変換**後の状態で、テキスト列に対して、OperationからRemove empty rowsを行います。
1行目、3行目が削除されました。（空白のみの文字列はemptyとは見なさない）
![スクリーンショット 2019-12-04 時刻 20.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545557/500fd348-f1fe-ee1c-a697-0b127316e9ec.png)
#まとめ
上述の結果から、以下であることがわかりました。

- String型の列（今回のテキスト列）では、missing（1行目）、空白1文字（2行目）、文字数0の文字列　は区別されるが、画面上の表示では違いを区別できない。
- Convert column typeにより変換できない値は（今回の数値列の2行目、3行目）はmissingとなる。画面上の表示は「NA」
- Remove empty rowsは、String型の列の場合、missingや文字数0の文字列が削除の対象となる（「空白」の文字列は、対象外）
MYSQLを自宅環境(linux)に構築

#MYSQLをlinuxに構築
勤務先でSQLを使用する機会が多くあり、
勉強の為にも自宅環境にてSQLを使用したいという思いから、
自宅のPC(VMWAERにてlinux環境あり)にてMYSQLを構築することにした。

無料で使用できるものは現状２種類あり、MYSQLとPOSTGRESQLがオープンソースのソフトとして無償ダウンロードできる。
仕様の違いやSQLの方言の違い等差異があるが、職場で使用している環境の物や自分の学びたい方を選ぶと良いかもしれない。

#MYSQLのyumインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502033/7a18060d-b886-c551-a830-c2fbd16e695a.png)

MYSQLのホームページからリポジトリを追加する

$ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm

https://dev.mysql.com/downloads/repo/yum/


なお筆者の環境はこれまでVMWAREでlinuxを構築しただけだったので
これを機にteratermをインストールし、コピーペーストや日本語化が簡単に出来るよう環境を整備し直した。

リポジトリが追加できたら次にyumインストールを行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502033/477467dd-0c9e-1473-5aca-a42db17fc553.png)

$ sudo yum install mysql-community-server

インストールが無事に終えたら次はMYSQLの起動を行う

$ sudo systemctl start mysqld.service


ここで自分はうまく起動することができなかったのだが、
実は最初にパスワード変更をする必要があり、
パスワードにもルールがあって多少ややこしい。

パスワードが最低 1 つの数値文字を含み、1 つの小文字および大文字を含み、1 つの特殊文字 (英数字以外) を含む必要があるという条件があるのだ、

忘れてしまいそうなのでパスワードをrootにし、validate_password_length = 4 に、validate_password_policy = LOW にする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502033/c0c39b88-53a4-ae25-80ee-2e91bc9bfd30.png)

これにて無事起動する事ができた。

次に簡単なデータベースを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502033/7ca4cfa1-9c4f-7836-13d0-f80882e9f25c.png)

テーブルの作成も行う


今月はSQLについてインストールと設定に時間を取られてしまったが、
これから会社で使用しているような物を実践してみたり、将来的にはPHP等を使用して掲示板等を作成してみたい。
jQuery 基本その3 フォームの内容入力について

検索フォームについて書こうと思いましたが
思いの他入力内容について量が多くなったので
別途書き記します。

# .val()
「val()」は、HTMLタグ内に記述されている
value属性を取得したり変更することができるメソッドになります。

```html:html
<form>
    <input type="text" value="入力">
 
    <input type="checkbox" value="sono1">：その1
    <input type="checkbox" value="sono2" checked>：その2
    <input type="checkbox" value="sono3">：その3
</form>
```

上記の入力ボックスやチェックボックスのように
value属性が記述されていれば「val()」メソッドで取得・変更することが可能です。


より基本的な流れを説明すると

```html:html
<button id="btn" value="a">ボタン</button>
<!--これでhtmlでidがbtnとvalueを設定-->
```

```js:jQuery
var btn = $('#btn').val(); //変数にidがbtnのvalueを代入
 
console.log( btn ); //変数btnを出力
```

```bash:コンソール
a　
# valueの値が出力されました。
```

## 上書き・設定
またはjQueryを下記のようにすると

```js:jQuery
var btn = $('#btn').val('b'); //変数にidがbtnのvalueを代入
 
console.log( btn ); //変数btnを出力
```

bが出力されます。
これはhtmlにvalueが設定されてなくても一緒です。
コードの順番から行ってjQueryのval()の
引数の値にvalueが設定または上書きされると考えてください。

## select要素
select要素というのがありますが
ほぼ仕様は一緒でselectと設定すれば値が入力されます。

```html:select
<select multiple>
    <option value="1">a</option>
    <option value="2">b</option>
    <option value="3">c</option>
</select>
<button>ボタン</button>
```
```js:jQuery
$('button').click(function() {
    var value = $('select').val(); //ここで設定します。
    
    console.log(value);
})
```

```bash:コンソール
1,2
# aとbを選択したら出力されます。
```

## checkbox要素
checkbox要素の場合はthisで設定されます。
それを含めてポイントは三つ
①input:checked要素で設定
②each構文でtype="checkbox"でチェックされたのを設定
③thisで現在のチェック内容を拾ってきます。

```html:html
<input type="checkbox" value="1">サンプル１
<input type="checkbox" value="2">サンプル２
<input type="checkbox" value="3">サンプル３
<button>ボタン</button>
```

```js:jQuery
$('button').click(function() {
    
    $('input:checked').each(function() { //①input:checked要素で設定
                                         //②each構文でtype="checkbox"でチェックされたのを設定
        var r = $(this).val(); //③thisで現在のチェック内容を拾ってきます。
        
        console.log(r);
    })
    
})
``` 

## radio要素
radio要素は「select / checkbox」と違い、ユーザーが選択できるのは1つだけでなのでシンプルです。
②each構文でtype="checkbox"でチェックされたのを設定がないので短くなります。

```html:html
<input type="radio" name="sample" value="1">サンプル１
<input type="radio" name="sample" value="2">サンプル２
<input type="radio" name="sample" value="3">サンプル３
<button>ボタン</button>
```

```js:jQuery
$('button').click(function() {
    // ②each構文でtype="checkbox"でチェックされたのを設定がありません。
    var result = $('input:checked').val();
        
    console.log(result);
    
})
```

## textbox要素
textbox要素は、ユーザーが何らかの文字列を入力することができるボックスになります。
value値を設定することで、あらかじめボックス内に任意の文字列を入力した状態にできます。

```html:html
<input type="text" value="サンプルテキスト">
```

```js:jQuery
var value = $('input').val();
 
console.log(value);
```

```bash:コンソール
サンプルテキスト
```
ユビキタス言語アンチパターン

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
この記事は[ドメイン駆動設計#1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ddd-1) 4日目のエントリです。
3日目は@dnskimo@githubさんの[PofEAAで考える値オブジェクトの永続化あれこれ](https://dnskimox.hateblo.jp/entry/2019/12/03/130024)でした。

# ユビキタス言語

DDDを実践したとき、即座に真価を発揮するポイントが2つあると思います。
一つは、対象の問題領域をドメインを認識し、境界付けられたコンテキストを意識してドメインを理解しようとすること。もう一つは、ユビキタス言語を使い、ドメインに対して統一された命名をラベリングすることです。

ドメインモデリングを議論するためにユビキタス言語は不可欠です。共通言語を使う、というだけでユビキタス言語の目的の半分以上は達成できていると思いますが、しかしその命名について語られることは多くありません。

ひとたびユビキタス言語が定義され、会話やドキュメントに登場するようになると、徐々にチーム内に浸透していきます。最終的には関数名や変数名やテーブルの命名にも使われて、一度定着すると簡単には変更できないのがユビキタス言語です。なので、最初の命名で大きく外さないことは結構重要であるように思います。（もちろん、ドメインモデリングを進める中で、より適切な用語や表現にアップデートしていくことが大前提にあります）

# アンチパターン

良い命名へと近付けるプラクティスとして、アンチパターンを避ける戦略が考えられます。
経験則ですが、以下の傾向が強い用語はなるべく避けるべきであると思います。

- 抽象的すぎる
- 汎用的すぎる
- 曖昧すぎる

## 具体例
今のプロジェクトではメンバー全員がユビキタス言語を意識し、一つずつチームで合意を取りながらユビキタス言語を育てています。その実践の中で、ユビキタス言語の命名に使わなかった単語、避けるべきだったかもしれない用語を、いくつかご紹介します。

### モデル

抽象的すぎる例です。

モデルという言葉は抽象的すぎるので、「〇〇モデル」と命名しても「〇〇」と比べてさほど具体化されません。

### 設定

汎用的すぎる例です。

何かの振る舞いに影響を与える項目は全て設定と言えるかもしれません。
設定という単語を思い浮かべたならば、何に対する設定なのか、の方を言語化した方がよさそうです。

### 更新、変更

これも汎用的すぎる例です。

CRUDのU、Updateは全て更新、変更です。
何を更新するのか、あるいは何のために変更するのかを考えてみたいです。

### 有効

曖昧すぎる例です。

何が有効なのか、何に対して有効なのか、無効であるとすれば何を意味するか、などを考えて、曖昧さを排除できるとよさそうです。

# おわりに

ユビキタス言語はその対象を可能な限り、具体的に、明確に、重複のないように命名できるとよいと思います。
言うは易し、行うは難し、なのですが。

ユビキタス言語の命名で後悔した経験や、アンチパターンだった用語はありませんか？
あったらこっそり教えてください。
Androidでリン○フィットアドベンチャー


おはようございます. はじめまして.
NTTドコモ 先進技術研究所 1年目社員 實成です.
僕は社内でも自分の時間が取りやすい部署[要出典]で働いています.
なので,普段の業務では取り扱っていないテーマの記事にしました.バラエティ重視!!

普段の業務は[こんなこと](https://www.nttdocomo.co.jp/info/news_release/2019/12/05_00.html)してます.
(ちょうど3日前にまとまった進捗を報道発表する機会がありました.)
僕は上記の解析担当をメインでやっています.

# 背景
## 入社してから
大学生のときは週2でテニスをしていましたが,社会人になってからは一切運動をしなくなりました.
せめて家でできる運動はしたい と考えて入社早々に腹筋ローラーを買うもこれだけだとすぐ飽きます.
世間では運動不足解消が流行っていて,こんな[アニメ](https://dumbbell-anime.jp/)も流行りました.
運動したい欲に対して満足のいく回答がないまま生きていた僕は[リングフィットアドベンチャー](https://www.nintendo.co.jp/ring/)に出会いました.

## リングフィットアドベンチャーとは??
[公式動画](https://www.youtube.com/watch?v=pmUS1nXq9RI)
｢Nintendo Switchで冒険しながらフィットネス｣というキャッチフレーズのゲームです.
身体に1つセンサーを,コントローラに1つセンサーを装着して全身がコントローラーとなる新感覚ゲーム.
2つのセンサーが腕や脚やお腹などの動きを認識し,ゲームの中のキャラクターを自在に操ることが可能.
ファンタジー世界を己の身体1つで冒険しながら,スリムで引き締まったボディを目指すゲームです.

任天堂は過去にも[WiiFitシリーズ](https://www.nintendo.co.jp/wii/rfnj/)を製作し,見事ゲームと運動を結びつけています.
僕も過去には大人から｢ゲームばかりして｣という言葉を頂いていましたが,今となってはそれは無縁.
加えて,最近のゲームは操作が難しく,遊ぶ人を選んでしまっている要素が増えてきてもいると感じています.
その点,直感的な操作が可能なこのゲームは,誰とでも一緒に遊ぶことが可能です.
これによって,家族や友達との仲を繋ぐ,素晴らしい側面も併せ持っていると考えています.
ぜひこれからもこのようなシリーズが続いていって欲しいです.

## 勘違い
- リングフィットアドベンチャーをやりたい
- でもSwitch買うまでのモチベはない
    - 品薄らしく,中古で13000円する(友人談)
    - 調べたら予想以上だった....
    <img width="773" alt="スクリーンショット 2019-12-08 2.18.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545664/e309255b-e495-55a3-40f2-2250e26aaf05.png">

- ~~**加速度センサーあれば作れそうじゃね?**~~
    - 手元にはAndroid端末が都合よく転がっていました

よくある勘違いでした.
リングフィットアドベンチャーは直感的な操作であるため,
3日ぐらいで実装できて良い小ネタになると考え,このタイトルでAdCを投稿すると宣言しました.

# 準備
最初はTwitterでバズった動画しか見てませんでした.
これが盛大な勘違いの主因であり,実装中に上記の[公式動画](https://www.youtube.com/watch?v=pmUS1nXq9RI)を見たときに
クオリティの高さ(選べる運動の数の多さ)に驚きました. 流石任天堂.

# 実装
Android版リングフィットアドベンチャーの製作方法概要を書きます.
用いるセンサーは加速度センサのみです.
本来,正確な自己位置推定には地磁気センサーも必要なのですが,そこまで正確に求めなくても
動作検知は可能だと感じたので今回は取り扱いませんでした.
センサー情報を取得するViewとスタート画面や操作説明などViewの2種類を行き来しています.
センサー情報の取得はOnSensorChangedで逐一取得する簡単な実装です.

現状,スクワットと腿上げと腰回しの3種類のトレーニングを実装しています.
各トレーニングの1回行ったという判定処理がif文のオンパレードになってしまっています.
もっと効率よく書けたら良かったなと感じています.

##demo 
プレイ中の自分も撮影したのですが,自分の顔が写ってしまったので,アップできませんでした.
Qiitaは動画を上げられないので,無理矢理.gifに変換しました.
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545664/e1963397-e20e-5849-83c6-6a458656fed5.gif)


## コード
例外,効率一切度外視のパワー系実装です.すみません.
1億と2千年ぶりにJava書いたら全然分からなかったです.
コードは[こちら](https://github.com/naname050505/ringfitADV)

## 今後の予定
* [OpenHouse2020](http://docomo-rd-openhouse.jp/2020/)に出します.
    * もしよかったら遊びに来てください
* [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)を使用した実装に切り替えるかもしれません.

# 結論
* 任天堂しゅごい.(見た目簡単そう≠実装簡単.)
* デザイン系のお仕事の人しゅごい
    * 画面遷移やボタン配置などのゲーム設定.レイアウト設定に一番時間がかかった.

# 余談
* 締め切り駆動型RTAは他人に迷惑をかける.
* 本当にすみませんでした!!!
<img width="785" alt="スクリーンショット 2019-12-08 2.08.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545664/d546c70a-f847-ca47-5005-58aaafbb6111.png">
アプリのコンポーネント(サービス, ブロードキャスト レシーバ)について

#概要
androidの開発を始めた頃につまずいた箇所をAdevent Calenderを機に振りかえりたいと思い記事にしました。

[サービス](#サービス)
[ブロードキャストレシーバ](#ブロードキャストレシーバ)


# サービス 
[サービスの概要](https://developer.android.com/guide/components/services?hl=ja)
サービスはバックグラウンドで動作するクラスで、バックグラウンドでのデータダウンロードや音楽の再生などに使われます。
過去のアプリではバックグラウンドで歩数を取得しごにょごにょするなんてこともサービスでしてました。

サービスには以下の３種類があります。

- **フォアグラウンドサービス**
- **バックグラウンドサービス**
- **バインドされたサービス**


例：サービス起動中に通知を表示する

```AndroidManifest.xml
<manifest>
...
    // 追加
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

    <application
    ...
    >
      ...
      // 追加
      <service android:name=".service.ForegroundService" />
    </application>
</manifest>
```

```ForegroundService.kt
class ForegroundService : Service() {
    // `bindService`で呼び出した場合呼ばれる
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    // サービスで実行する処理
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        /* 通知の作成など ... */
        // `startForeground`をサービス起動から5秒以内に呼び出さないといけない
        startForeground(notificationId, builder.build())
        return START_NOT_STICKY
    }
}
```

```MainActivity.kt
//　起動
val intent = Intent(this, ForegroundService::class.java)
if (Build.VERSION.SDK_INT >= 26) {
    startForegroundService(intent)
} else {
    startService(intent)
}
```

```MainActivity.kt
//　停止
val intent = Intent(this, ForegroundService::class.java)
stopService(intent)
```

## ブロードキャストレシーバ
[ブロードキャストの概要](https://developer.android.com/guide/components/broadcasts.html)
[参考にした記事](https://qiita.com/wakwak/items/eaaaa27881fa79dfc180)

システムイベントの受信や位置情報の変更や機内モードへの変更を検知したりできます。

例: 機内モードのon/offを検知

```AndroidManifest.xml
<manifest>
...
    <application
    ...
    >
        ...
        // 追加
        <receiver android:name=".AirplaneModeChangedReceiver">
            <intent-filter>
                <action android:name="android.intent.action.AIRPLANE_MODE" />
            </intent-filter>
        </receiver>
    </application>
</manifest>
```

```AirplaneModeChangedReceiver.kt
class AirplaneModeChangedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (Intent.ACTION_AIRPLANE_MODE_CHANGED == intent?.action) {
            val toast = Toast.makeText(context, "AirplaneMode", Toast.LENGTH_SHORT)
            toast.show()
        }
    }
}
```

```MainActivity.kt
//　登録
val receiver = AirplaneModeChangedReceiver()
val filter = IntentFilter().apply {
    addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}
registerReceiver(receiver, filter)
```
djangoでホームページを作成

今まで何度も作ってはまた作り直してを繰り返してその度いろんなところをググったりするので、
さすがに備忘録を残しておこうかなと。

ちなみに内容はほぼ、
https://qiita.com/noraricl/items/08937a508a2abecc7179
にかかれてある通りになります。（超簡単なミニマムなページを作りたかったのですごく助かりました・・・）

## 環境設定

pyenvとvirtualenvで3.6.1のバージョンからrate-siteという仮想環境を作っていますが、僕以外の方はここはスルーして大丈夫です。


```
mkdir rate_site
cd rate_site
pyenv virtualenv 3.6.1 rate-site
pyenv local rate-site
```

以下の、 `requirements.txt` を作成。

```
dj-database-url==0.5.0
dj-static==0.0.6
Django==2.2.6
django-heroku==0.3.1
gunicorn==20.0.0
mysqlclient==1.4.4
psycopg2==2.8.4
PyMySQL==0.9.3
python-dateutil==2.8.1
pytz==2019.3
six==1.13.0
sqlparse==0.3.0
static3==0.7.0
whitenoise==4.1.4
```

そして、

```
pip install -r requirements.txt
```

で必要なものをインストール。

※`requirements.txt`を作成したディレクトリ（`rate_site`） がgitで管理する一番トップでディレクトリになる。

## プロジェクトとアプリケーション作成

```
mkdir rate_site # 今いるrate_site内でもう一個作る
cd rate_site
django-admin startproject rate_site .
python manage.py startapp rate_hp
```

## 設定ファイル編集

```rate_site/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rate_hp',　#追加
]
(省略)
LANGUAGE_CODE = 'ja'　#変更
TIME_ZONE = 'Asia/Tokyo'　#変更
(省略)
USE_TZ =  False　#変更
```

## migrateする

```
python manage.py migrate
```

## 管理者ユーザ作成

```
python manage.py createsuperuser
```

## 起動確認

```
python manage.py runserver
```

これで、
http://127.0.0.1:8000/

にアクセスするとdjangoでデフォルトのページが表示される。

## rate_hp にアクセスできるようにする

```rate_site/urls.py
from django.urls import path, include #追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('rate_hp.urls')), #追加
]
```

## HTMLファイル作成

rate_siteやrate_hpがあるディレクトリ内に、
`templates`ディレクトリを作成し、

```templates/base.html
<html>
    <head>
        <title>ホームページ</title>
    </head>
    <body>
        <p>ここがbase.htmlです。</p>

    {% block main_containts %}
    {% endblock %}

        <p>ここがbase.htmlです。</p>
    </body>
</html>
```

```templates/index.html
{% extends "base.html" %}
{% block main_containts %}
{% load static %}

  <main>
    ここがindex.htmlです。
  </main>

{% endblock %}
```

rate_hpの中のファイルを編集していく。

```rate_hp/views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader

def index(request):
    template = loader.get_template('index.html')
    context = {}
    return HttpResponse(template.render(context, request))
```

`urls.py` は存在しないので、新規作成

```rate_hp/urls.py
from django.urls import path
from . import views

app_name = 'rate_hp' #django2.0から必要になったnamespace定義
urlpatterns = [
    path('', views.index, name='index'),
]
```

先程作ったtemplatesをdjangoが読み込むようにする。

```rate_site/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],  # 追加
        'APP_DIRS': True,
```


ここでもっかい、
`python manage.py runserver`

を実行して、
http://127.0.0.1:8000/
にアクセスする。

## いったん完了

一応今後は、ここのホームに対して新しく作ったアプリケーションだとかをどんどん追加していって、アクセスできるようにしていく想定。
3つのデバイスタイプを判別する3つの方法

Webサイト訪問者の3種類のデバイス（モバイル、タブレット、デスクトップ）のデータを取得するコード

#1. ユーザーエージェントで判別する方法
```js

function device(){
  return /iPad/.test(navigator.userAgent)?"tablet":/Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Silk/.test(navigator.userAgent)?"mobile":"desktop";
}
```
参照したサイト：どこかのECサイト

#2. ウィンドウの大きさで判別する方法
```js
function device(){
  var width = window.innerWidth,
    screenType;
  if (width <= 520) {
    screenType = "mobile";
  } else if (width <= 820) {
    screenType = "tablet";
  } else {
    screenType = "desktop";
  }
  return screenType;
}
```
参照したサイト：
https://www.upbuild.io/blog/device-specific-gtm-tags/


#3. 何やら外部のコードを使う方法(ユーザーエージェントで判別)
```js
//mobile-detect.js（https://github.com/hgoebl/mobile-detect.js/）を利用

function device(){
  var md = new MobileDetect(window.navigator.userAgent);
  var mobile = md.phone() ? "mobile" : undefined;
  var tablet = md.tablet() ? "tablet" : undefined;
  return mobile || tablet || "desktop";
}
```
参照したサイト：
https://github.com/hgoebl/mobile-detect.js/
https://support.google.com/tagmanager/forum/AAAAnP_FwdICvO-Fx7PeW8

#背景
- 広告サービスCriteoのサーバーに送信するデータとしてデバイスタイプを取得しておく
- このJavascriptコードはタグマネジメントツール（GoogleタグマネージャーのカスタムJavascript）に設置する
- （※上記背景の場合、実際には関数名や返すデバイスタイプの値を少し修正する）

---
何かあればお手数ですが、本記事か以下アカウントでお知らせください！

**\ *Follow Me!* /**
**[*Qiitaアカウント*](https://qiita.com/MasatoEmata)**
**[*Twitterアカウント*](https://twitter.com/masatoemata)**
【Objective-c】AutoLayoutで位置を決める


UIButton、UILabel等はstorybord上で、位置を指定して配置できますが
コード上でもAutoLayoutを使用して位置を指定することができます。


``` 
-(void) button_autolayout:(UIButton *)button top:(int)top left:(int)left right:(int)right bottom:(int)bottom {
    //AutoLayoutを使用することを指定
    [button setTranslatesAutoresizingMaskIntoConstraints:NO];

    // 上　位置指定
    NSLayoutConstraint* topAnchor = [button.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:top];
    // 左　位置指定
    NSLayoutConstraint* leftAnchor = [button.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:left];
    // 右　位置指定
    NSLayoutConstraint* rightAnchor = [button.rightAnchor constraintEqualToAnchor:self.view.rightAnchor constant:right];
    // 下　位置指定
    NSLayoutConstraint* bottomAnchor = [button.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-bottom];

　　 //viewに追加
    [self.view addConstraint:topAnchor];
    [self.view addConstraint:leftAnchor];
    [self.view addConstraint:rightAnchor];
    [self.view addConstraint:bottomAnchor];
}
```


例えば上記の関数をボタンごとに指定することで、以下のように配置できます。

```
//上　緑色
[self button_autolayout:top_button top:0 left:0 right:0 bottom:596];

//右　赤色
[self button_autolayout:right_button top:298 left:207 right:0 bottom:298];

//左　黄色
[self button_autolayout:left_button top:298 left:0 right:207 bottom:298];

//下　青色
[self button_autolayout:bottom_button top:596 left:0 right:0 bottom:0];
```

<img width="499" alt="スクリーンショット 2019-12-03 0.04.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431502/81fa912a-9acc-a4a0-74b3-8aa2b179a7a6.png">


#参考
https://developer.apple.com/documentation/uikit/nslayoutanchor/1500937-constraintequaltoanchor?language=objc

https://qiita.com/edo_m18/items/5c224c823ca163629f54
Raspberry Pi 4B Rev 1.2 は USB Type-C電源問題の夢を見るか?

公式フォーラムを斜め読みしていて目に留まったのが以下。
[New Pi 4B v1.2?](https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=256646&p=1574984&hilit=rev+1.2#p1574984 "New Pi 4B v1.2_ - Page 5 - Raspberry Pi Forums")
リビジョンなんて気にしたことなかった。手持ちの RPi4B を確認。

```shell-session
pi@raspberrypi4:~ $ cat /proc/cpuinfo
(中略)
Hardware        : BCM2835
Revision        : c03112
Serial          : 1**************c
Model           : Raspberry Pi 4 Model B Rev 1.2
pi@raspberrypi4:~ $
```
Rev 1.2 らしい。ところが公式を確認してもこのリビジョンの記載が無い。
[Raspberry Pi revision codes](https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md "Raspberry Pi revision codes - Raspberry Pi Documentation")

|Code	|Model	|Revision	|RAM	|Manufacturer|
| ---- | ---- | ---- | ---- | ---- |
|a03111	|4B	|1.1	|1GB	|Sony UK|
|b03111	|4B	|1.1	|2GB	|Sony UK|
|c03111	|4B	|1.1	|4GB	|Sony UK|

冒頭のフォーラムにもその指摘があり、それもあってホントに Rev 1.2 なんてあるの？　と紛糾している状態。
ネットを検索したところ、日本に流通している技適対応版が Rev 1.2 で、USB Type-Cの電源問題修正版らしい。
[日本で出たRaspberry Pi 4と電源問題とファームウェアの件](http://akkiesoft.hatenablog.jp/entry/20191128/1574911998 "日本で出たRaspberry Pi 4と電源問題とファームウェアの件 - あっきぃ日誌")

「らしい」ってのは、この件に関する公式情報が見つからなかったから。
それこそ冒頭のフォーラムでも、上記のブログのリンクが張られているぐらいで、英語圏でも公式情報が見当たらないという。フォーラムも荒れる訳だよ。
とはいえ、海外ではまだ珍しい Rev 1.2 が日本では当たり前に流通している状況はちょっと面白いと思う。

###### 2019/12/20 追記
いつの間にか公式にも Rev 1.2 が追加されてるし。
[Raspberry Pi revision codes](https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md "Raspberry Pi revision codes - Raspberry Pi Documentation")

|Code	|Model	|Revision	|RAM	|Manufacturer|
| ---- | ---- | ---- | ---- | ---- |
|a03111	|4B	|1.1	|1GB	|Sony UK|
|b03111	|4B	|1.1	|2GB	|Sony UK|
|c03111	|4B	|1.1	|4GB	|Sony UK|
|c03112	|4B	|1.2	|4GB	|Sony UK|
【Androidアプリ入門】内部ストレージに保存・読込する♪文字化け解消

[【Androidアプリ入門】内部ストレージに保存・読込する♪ハマった編](https://qiita.com/MuAuan/items/d7131513db3fb7a03c2d)で日本語等が文字化けしていましたが、以下のコードで文字化け解消しましたm(__)m

```kotlin
R.id.btClick1 -> {
                    var temp=""
                    var pathUtf8 =  getFilesDir().getAbsolutePath(); 
                    temp = File(pathUtf8+"/testfile.txt").readText(Charsets.UTF_8)

                    output.text = df.format(date) + "\n"  + temp
                    input.setText("")
                }
```

| 1 | 2 | 3 |
|:-:|:-:|:-:|
|![honjitu2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/891f60d2-eaf5-172a-c20a-a66eaf264655.jpeg)| ![ihaveanapple.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/1541c84a-ea9b-aeee-d31b-5206159ef1e3.jpeg)| ![kaochai2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/8d671323-d1c4-1a20-a9c2-6b30b306f934.jpeg)|

###まとめ
・すっきりできた
・情報が多いので迷ってしまった

・DBや追記が出来ていないのでやろうと思う
アセットプリコンパイル時のuninitialized constantのエラー

# はじめに

今回のエラーの解決策は至ってシンプルであり、凡ミスでもあったが、
今後忘れないよう、自分への備忘録として記録しておきます。

# 状況

・Herokuへのデプロイ時にアセットプリコンパイルがうまくいかない。
・GemのDeviseの実装テスト中

# 原因から解決まで

アセットプリコンパイルを実施。

```
rails assets:precompile RAILS_ENV=production
```



以下エラー文が発生。

```
NameError: uninitialized constant Devise
```



Deviseの読み込みがうまくいっていないとのこと。

```ruby:Gemfile
group :development, :test do
gem 'devise'
end
```

Gemfileのテスト環境位置にgem 'devise'を記入した状態でしかbundle installしていなかったので、本番環境に位置に変更してbundle installでOK。

経験値が少なすぎるからかなかなか気づけませんでした。。。
リーダブルコードの要約

# はじめに
リーダブルコードの２章から６章までの要約を残しておきます。

##　２章　変数・関数の命名の仕方
２章は理解しやすい変数・関数名を命名するためのメソッドが記されている
本書では、必要な情報を詰め込むことが命名の鍵であり、そのための６つのテーマが紹介されている

1. 目的を表す明確な単語を選ぶ  
 Ex) GetPage -> FetchPage/DownloadPage
2. tmpやretvalなど情報のない名前は避ける  
 「役割がない」という情報を伝えるためだったり、ループイテレータにおけるi,jなど以外の場面で、怠慢によって汎用的な名前を用いるのは避ける
3. 抽象的な名前より動作を表す具体的な名前を使う  
 Ex) ServerCanStart -> CanListenOnPort
4. 接尾辞や接頭辞を使って情報を追加する  
 単位やフォーマットを指定する   
 Ex) id -> id_hex , start -> start_ms  
 注意喚起など重要な属性を追加する  
 Ex) password -> plaintext_password / ciphertext_password , html -> html_utf8
5. 名前の長さを決める  
 適した長さは、スコープの大小によって決める　理解できる範囲であれば、名前の一部を頭文字に置き換えたり、削除して良い
6. 大文字、アンダースコアなどを使って情報を伝える  
 
##　3章　誤解されない名前の命名の仕方
３章は、名前から推測される動作が曖昧になるのを避けるためのメソッドが記されている
・曖昧な単語は使わない
 Ex) filter -> select/exclude 
・限界値を含めるときはmax,minを使う
 Ex) limit -> max_/min_ 
・範囲がわかりやすい名前にする
 Ex) 包含的ならfirst/last , 包含/排他的ならbegin/end
・ブール値にはそれがわかるようis,has,can,shouldなどを名前に入れる
・ブール値の名前は否定形にするのを避ける
 Ex) disable_ssl -> use_ssl
・ユーザの期待する動作をさせる
軽量な動作を期待されるget,sizeには、重い動作をさせない

## ４章　美しいコードのレイアウト
４章では以下の３つの原則にそって読みやすいレイアウトにするメソッドが記されている
・読み手が慣れているパターンと一貫性を持たせる
　変数の定義の順をフォームのinputフィールドと一致させるなど
・似ているコードは似ているように見せる
　改行や空白、あるいはメソッドを使用してコードを整列させ、シルエットを似せる
・関連するコードはまとめてブロックにする
　宣言をまとめる、段落で分割し適宜コメントを追加するなど

## ５章 コメントの書き方
５章ではコメントすべきこととすべきでないことが記されている
コメントの目的は、読み手に意図を正確に理解してもらうことである
###コメントすべきでないこと
　・コードを読めばすぐにわかること
　・ひどいコードを補うためのコメント（優れたコード＞ひどいコード＋優れたコメント）
###コメントすべきこと
　・最適化に関する情報や、コードの可読性に関する考え
　・欠陥がある場合などの情報
「TO DO：」あとで手をつける、
「FIXME:」既知の不具合があるコード、
「HACK」あまり綺麗じゃない解決策、
「XXX]危険！大きな問題がある
　・読み手が理解し難い部分の補足
　・前もって予測できる誤った使用法をさせないための告知
　・全体像や要約のコメント

## ６章　密度の高いコメントの仕方
６章ではどうすれば正確で簡潔なコメントができるのかが記されている
・「これ」や「それ」などの代名詞は名詞を代入して置き換える
・単純で短く直接的な文章をかく
Ex）これまでにクロールしたURLかどうかによって優先度を変える　ー＞
これまでにクロールしていないURLの優先度を高くする
・適切な、視覚化しやすく正確な実例をコメントする
Ex）　'src'の先頭や末尾にある'chars'を除去する　ー＞
Strip("abba/a/ba","ab")は”/a/” を返す
・作成意図と矛盾しないコードを記述するために、コードを書いていた時に考えていたことと近い、高レベルからの説明をコメントする
・引数にインラインコメントで名前をつける
Ex)　Function(/* arg=*/ ...)
・簡潔にパターンやイディオムを表現する言葉で置き換える
Ex）「キャッシュ層」「正規化」

#終わりに
プログラムの作者ではない人の視点を第一に考え、理解しやすい・簡潔なコードを心がけたいです
Chrome Dev ToolsにIDEみたいなテーマを適用させる方法

# 結論
こんな感じにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/0dc2e9e0-a85d-d724-5f9d-a0f8135dc503.png)

# 方法

## Allow custom UI themes の実験フラグを有効にする
* [chrome://flags/#enable-devtools-experiments](chrome://flags/#enable-devtools-experiments) にアクセスする
* **Developer Tools experiments** を **Enabled** にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/fb077658-643a-1efa-612e-71c843d3dc76.png)

* 画面右下の **Relaunch** をクリック (chromeが再起動される)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/6746dc4f-1f8b-07c4-d78c-4639e2843427.png)

## Theme を Dark にする

* Ctrl + Shift + J で chrome dev tools を開く
* F1 を押す
* Settings > Pereferences > Appearance > Theme を Dark に変更する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/ce6bf20f-846e-4702-cc18-b5bf0e1c49a2.png)

## Allow custom UI themes を有効にする

* Settings > Experiments > **Allow custom UI themes** を有効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/dd3baceb-2baa-4eea-3fd5-3c2f4d941bda.png)

## Material DevTools Theme Collection 拡張機能を追加する

* [chrome ウェブストア](https://chrome.google.com/webstore/search/material%20theme) を検索し **Material DevTools Theme Collection** を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136348/8f0dc2c9-aed3-7fe6-9ae2-888bf376f14b.png)
トップページ

##### Unity
[Unity トップ](https://qiita.com/ogawa-to/items/739a8ce9516dd4309ac2)

##### C♯
[C# トップ](https://qiita.com/ogawa-to/items/d84ac04cca3c4bd3f530)

##### UI
[Gimpでいろいろな手法](https://qiita.com/ogawa-to/items/20f98fab0c1c64190185)

##### VBA
[ブラウザから英単語音声ファイルを一括ダウンロード](https://qiita.com/ogawa-to/items/893e5b3c57aa8ff53f63)

##### その他
[ゲーム用語](https://qiita.com/ogawa-to/items/f29519e796a29d0e5638)
Amazon Aurora(Postgres)におけるデータ復元方法について検討してみた

# はじめに
RDBを使った新規案件が発生し、バッチ運用がメインとなってくるシステムだった為、
スモールスタートで運用するにはコストが安く、スケールしやすいと言う事で
Amazon Aurora(Postgres)を使うことになった。

自動でバックアップをしてくれる事から、復元も安易に出来るような雰囲気があったが
実際の所はどうなのか、調査した。

# 2種類の復元方法

復元方法は2種あり、いずれの復元の方法もデフォルトで7日間、最大35日分のデータを保存できる

- スナップショットによる復元
    スナップショット一覧から選択して復元が可能で、
    バックアップは一日1回、自動で実施している

- 特定時点への復元
    コンソール右上の「アクション」から「特定時点への復元」を選択すると実行でき、
    こちらは任意の時点のデータへ復元することが出来る。

## リレーションの担保

- 「特定時点への復元」ではDB間整合性が担保出来ないと書いてある。
(つまり復元前後でアクセスがあるとリレーションが崩れる可能性がある) 

- スナップショットにはその旨の記載が無かった
(現状、システムを動かしていないタイミングで丁度スナップショットが実施されており、
コールドバックアップされているかは確認が取れなかった)


# 障害発生 → 復元を実行して後は放置　とはならない

これが重要なのですが、今稼働している復元元のDB識別子は復元先に選べません
(考えてみればそれはそうだとなった箇所ですが、
 当初出来るものと思い込んで居たのでこの記事を書いてます)

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200155/7709c522-e36e-7da7-2610-8391ee98f3e0.png)

(Auroraの復元画面。DBクラスター識別子を同じにしても実行時エラーが出る)

つまり...

<img src="http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU9AIIn9J4eiJbLGUhvYpzFctYSxrZwRi-Rvr5KkJaeAYSKA1KNvAV4fILp9EVcbAGfAZgL5-KM9ZnjNFsxgUDpK_Q9zrTFkgO-R9pnkRdxSjFvnqo8GetawM6jIOd9sQG4Nr0G5NJkO28G22i1Dvt98pKi1kWS0">

↑ こういう事が出来ない。
恐らく稼働中のDBを誤ってデータを消さないようにする措置だと思います。
[こういう事態は避けるべきですね](https://qiita.com/advent-calendar/2019/yarakashi-production)

## 今回検討した案

今回は案を2つ出し、その中の案2を採用しました。

- 案1 : 新しく本番DBを作る

    <img src="http://www.plantuml.com/plantuml/png/TP1DgzD058RtzrUCMTqBDmdSvQK8jReNNBWHoYGpjS4a4-Q3uh8pI0f5AOMgb2BY1qZzq8tIHQe_PjeqE_-2ayGGQd4sXyCyx_kUSyw0UJSG7WGn1jtxz-wAA0H3pXDsxReKZfo70HyAJp1CVH9p77F79v4BHoo47Ykh7PWFPWy8jPCGnjmOk15a75CN1OpN0K7iXm9XGSCcn3MrHwA8n4vYslzYXaa4n-wTtbKBckOS-rVzX19qQLcNLhxwT5YijPfffRGQQ_bTgwngC-kYaY38eGSP1jRXGxPNJtURpxNezYqBG0PAgpxo_c4RH8-_5E_IukssPNsIFAveFoG20QihAA5GZpzgET5oMgJh_NJnToBvLSitrMWlAWCF-ez4KggRND1nGBCHk0PrRlxi_U77KijvyVELbcQhwP74HlRD4wjoBD2nZyoUVsltsEGlq_nrLWbgBJ0khRJ23IZdk-qgdymUnETQfUKrvQ_z4_KxMvxSx-Bi3m00">

    - 復元したDBを新本番DBとし、復元元と全く同じ設定に仕上げ、DB接続先設定を新本番DBに向ける
    - 慣れれば問題無いのだろうが、障害発生の際に設定項目を精査するのは難がある
        - DB識別子も変わる
        - 既に大量にデータを持っている場合には後述する手順に比べれば復元手順に掛けるコストは少ない

- 案2 : 復元用のDBを作り、postgresのダンプ機能から復元を実施する

    ![an2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200155/16d3ae47-713d-9176-dda8-d52a5ba5d141.png)

    - 復元したDBをリカバリー用DBとし、PostgresコマンドにてDBバックアップを取得、それを本番機へリストアする
    - 手を加える本番システムがDBのみなのでミスの積み重ねが起きにくい
    - 手順が一定化しやすい
    - PostgresによるDB吸出しを行う為時間が掛かる、リカバリー中はデータも膨れる

参考URL：
- https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html
- https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_PIT.html
【C#】トップ

# 文法
[ローカル関数](https://qiita.com/ogawa-to/items/a09654f72a6a58182937)
[ref, out, tuple, 匿名型](https://qiita.com/ogawa-to/items/00b132ee6899c83d914f)
[プロパティ](https://qiita.com/ogawa-to/items/f11f294dacc3b928d57b)
[インデクサ](https://qiita.com/ogawa-to/items/4c9dfda6c78190adabba)
[オーバーライド, is, asによるキャスト](https://qiita.com/ogawa-to/items/50d505334ca40c19c1d0)
[Enum列挙型](https://qiita.com/ogawa-to/items/f96468b4f7300676c049)
[ジェネリック](https://qiita.com/ogawa-to/items/fed7e7726ac360dfee8a)
[デリゲード, ラムダ式](https://qiita.com/ogawa-to/items/dfd634fb26f84f0b7630)
[LINQ](https://qiita.com/ogawa-to/items/b5e20fd6d6e217917add)
リーダブルコード chapter1

## コードの良し悪しについて

コードは、他の人が理解する時間が短いモノが良い

読みづらいと、ストレスもかかるしバグの元にもなる

```ruby:サンプルコード

bad

return exponent >= 0 ? mantissa * (1 << exponent) : maintissa / ( 1 << -exponent);

good

if (exponent >= 0){
  return mantissa * (1 << exponent)
} else {
  return maintissa / ( 1 << -exponent);
}

```
【Swift】Cell上のUIImageViewにAPIから取得した画像(URL)を表示させたこと

# 概要
Cell上のUIImageViewにAPIから取得した画像(URL)を表示するということが結構難しかったのでメモします。
※URLSessionを使用します。

## 作業の順序
##### 1.APIから取得したURLを使ってサーバーから画像を取得
##### 2.imageviewに取得した画像をセットする


## 実装

``` swift:SongTableViewCell.swift


class SongTableViewCell: UITableViewCell {
    
    @IBOutlet weak var trackImage: UIImageView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

    }

//"Result", "artworkUrl100"はAPI実装のファイルから取得している値
    func setup(set: Result) {
//2:imageviewに取得した画像をセットする
        trackImage.setImageByDefault(with: set.artworkUrl100)

    }
}

//1:APIから取得したURLを使ってサーバーから画像を取得
extension UIImageView {

    func setImageByDefault(with url: URL) {
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            if error == nil, case .some(let result) = data, let image = UIImage(data: result) {
               //ここでメインスレッド実行するように記述(無いとサブスレッドで実行されて落ちる)
                DispatchQueue.main.async {
                    self?.image = image
                }

            } else {
                // error handling

            }
        }.resume()
    }

}

```

``` swift:ListTableViewController.swift
 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "SongTableViewCell") as? SongTableViewCell else {
            return SongTableViewCell()
        }
        let info = resultsCount?.results?[indexPath.row] else {
             return SongTableViewCell()
        }
        cell.setup(set: info)
        return cell
    }

```

ひとまず画像は取得できるようになりました。

## 終わりに
以下の記事などを参考にして実装しました。

https://qiita.com/H_Crane/items/422811dfc18ae919f8a4
https://qiita.com/nbapps_dev/items/d22837b04d8bb0a3127d
TeXworks で Latexmk を使えるようにする2つの方法

# 概要
TeXworks で Latexmk を使うには

- Texworks editor のタイプセット設定ですべてを済ませる方法
- Texworks editor のタイプセット設定と `.latexmkrc` ファイル作成による方法

の2つの方法がある．

# 詳細
TeX 文書をコンパイルする際，相互参照を持っていれば複数回タイプセットしたり，文献参照に BibTeX を利用したい場合は別途 BibTeX も実行したりする必要がある．それらの手続きを必要な分だけ一通りやってくれるのが Latexmk である．以下，TeXworks で Latexmk を使えるようにするための設定方法を説明する．

## 設定方法
### TeXworks editor の設定
1. TeXworks editor を開き，メニューバーから編集>設定をクリック．
2. 設定画面内の「タイプセット」タブをクリック．
3. 「タイプセットの方法」欄右下にある＋ボタンをクリック．
4. 次の通り Latexmk の情報を入力する．なお，dvi ファイルだけでなく PDF ファイルも出力させたい場合は，下記 `$fullname` の上に `-pdfdvi` も引数として追加する．

- 名前: Latexmk
- プログラム: latexmk
- 引数: `$fullname`

![Latexmkの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478774/1ba951db-fb86-42da-0934-5ed162521798.png "Latexmkの設定画面")

以降の設定はその1，その2のいずれかを行えばよい．

### その1: 続・TeXworks editor の設定
上記と同じ画面で引数[^2]をさらに追加し，OKボタンをクリック．

- `-e`
- `$latex='platex -synctex=1 %O %S';
$bibtex='pbibtex %O %B';
$dvipdf='dvipdfmx %O -o %D %S';`
- `$fullname`

![Latexmkの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478774/3185d76c-9a8c-8a26-cda8-f299782764e4.png "Latexmkの設定画面")

なお，新たに追加した引数の意味は次の通りである．

- `-e`: 2行目の引数を読み取るためのオプション
- 2行目の長い引数: 「pLaTeX を使用する」「pBibTeX を使用する」などの指示[^1]

### その2: `.latexmkrc` ファイルの作成
次のコード[^3]を `.latexmkrc` という名前で作成し，ホームディレクトリに保存する．Windows 10 の場合は `C:\Users\ユーザー名` に保存する．

```:.latexmkrc
$latex='platex -synctex=1 %O %S';
$bibtex='pbibtex %O %B';
$dvipdf='dvipdfmx %O -o %D %S';
```

[^1]: 必要に応じて Makeindex などの設定も書き加える．詳細は参考文献の1つ目や3つ目を参照のこと．
[^2]: 引数は他にもいろいろある．詳細は参考文献の1つ目や3つ目を参照のこと．
[^3]: その1の「2行目の長い引数」にあたる部分である．

## 設定終了後
以上の設定を終え，`Latexmk` を選択してタイプセットすれば，一発でカンペキな dvi ファイルないし PDF ファイルが出力される．

# 参考
- [Latexmk - TeX Wiki](https://texwiki.texjp.org/?Latexmk)
- [TeXworks/設定/Windows - TeX Wiki](https://texwiki.texjp.org/?TeXworks%2F%E8%A8%AD%E5%AE%9A%2FWindows)
- [CTAN: Package latexmk - Manual page](http://mirrors.ctan.org/support/latexmk/latexmk.pdf)

ところで，Latexmk を LaTeXmk とは言わないの，ちょっと違和感．