OmniAICreator/Qiita-1.07M huggingface dataset:
MySQl練習帖①

# 雑

## コマンド羅列

### create

```sql
CREATE TABLE テーブル名 (カラム名 型(桁数) オプション, カラム名 型(桁数) オプション...);
```

```sql

mysql> CREATE TABLE user (
    -> id INT AUTO_INCREMENT PRIMARY KEY,
    -> name VARCHAR(20) NOT NULL,
    -> email VARCHAR(255) UNIQUE,
    -> age INT,
    -> gender TINYINT COMMENT '1が男、2が女',
    -> created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    -> updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

```
___
### alter

```sql
mysql> ALTER TABLE (テーブル名) MODIFY (カラム名) （変更後）;
```
___
### insert

```sql
INSERT INTO テーブル名 (カラム1, カラム2, ...カラムn) VALUES (カラム1の値, カラム2の値, ...カラムnの値);
```

valuesはカンマ区切りで複数レコードを１クエリで挿入できる
___
### delete

___

### select

```sql
SELECT (カラム名) FROM (テーブル名) WHERE （条件）;
```
#### 論理演算子

* AND(&&)
* OR (||)
* NOT

#### 不等号

* =
* !=
* >, >=
* <. <=
* BETWEEN a AND b (a < b)

#### LIKE
`%`をワイルドカードとして部分一致検索に使える

```sql
mysql> SELECT * FROM people WHERE name LIKE '%こ';
```

#### IN
リストで検索

```sql
WHERE カラム名 IN (値1, 値2, 値3...値N);
```

#### DISTINCT
SELECT DISTINCTで重複カラムを削除して取得できる。

#### order by
asc, desc 昇順、降順に並び替えできる
___

### JOIN
join文の種類によって対応する値がない場合の扱いが異なる

#### INNNER JOIN
部分集合

#### LEFT JOIN
左側のテーブルは全て表示（対応する値がないセルはNULLになる）

#### RIGHT JOIN
LEFT JOINの右版

___

### 集計関数

* 基本的に`GROUP BY`と組み合わせて集計を行う。
* `select`できるのは`GROUP BY`したカラムのみ。
* カラムみたいな扱いができる。

#### MIN(), MAX()
最大値。最小値

#### AVG()
平均

#### SUM()
総和

___

## 細かいところ

* テーブル名・カラム名が予約語とかぶるときはバッククォート(　`　)を使う
* NULLを検索したいときは`=`ではなく`IS`を使う
Alfred Web Search お気に入り

Alfred Web Search のお気に入りを列挙します。
ブラウザの URL 欄にアドレスをコピペして実行することでインストール可能です。


- amazon - [Search Amazon.co.jp for '{query}'](https://www.amazon.co.jp/s?k={query})
 - alfred://customsearch/Search%20Amazon.co.jp%20for%20%27%7Bquery%7D%27/amazon/utf8/nospace/https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%7Bquery%7D

- kindle - [Search Kindle for '{query}'](https://www.amazon.co.jp/s?k={query}&i=digital-text)
  - alfred://customsearch/Search%20Kindle%20for%20%27%7Bquery%7D%27/kindle/utf8/nospace/https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%7Bquery%7D%26i%3Ddigital-text

- ck - [Search ClinikalKey for '{query}'](https://www.clinicalkey.jp/#!/search/{query})

 - alfred://customsearch/Search%20ClinikalKey%20for%20%27%7Bquery%7D%27/ck/utf8/nospace/https%3A%2F%2Fwww.clinicalkey.jp%2F%23%21%2Fsearch%2F%7Bquery%7D

- eijiro - [Search EijiroPro for '{query}'](https://eowp.alc.co.jp/search?q={query})

 - alfred://customsearch/Search%20EijiroPro%20for%20%27%7Bquery%7D%27/eijiro/utf8/nospace/https%3A%2F%2Feowp.alc.co.jp%2Fsearch%3Fq%3D%7Bquery%7D

- mesh - [Search MeSH term for '{query}'](https://www.ncbi.nlm.nih.gov/mesh/?term={query})
 - alfred://customsearch/Search%20MeSH%20term%20for%20%27%7Bquery%7D%27/mesh/utf8/nospace/https%3A%2F%2Fwww.ncbi.nlm.nih.gov%2Fmesh%2F%3Fterm%3D%7Bquery%7D

- pm - [Search Pubmed for '{query}'](https://pubmed.ncbi.nlm.nih.gov/?term={query})
 - alfred://customsearch/Search%20Pubmed%20for%20%27%7Bquery%7D%27/pm/utf8/nospace/https%3A%2F%2Fpubmed.ncbi.nlm.nih.gov%2F%3Fterm%3D%7Bquery%7D)

- pmid - [Search PMID for '{query}'](https://pubmed.ncbi.nlm.nih.gov/{query})
 - alfred://customsearch/Search%20PMID%20for%20%27%7Bquery%7D%27/pmid/utf8/nospace/https%3A%2F%2Fpubmed.ncbi.nlm.nih.gov%2F%7Bquery%7D)
volatilityの作法 その16

#概要

volatilityの作法、調べてみた。
plugin書いてみた。

#サンプルコード


```
import volatility.plugins.common as common

class TestPlugin(common.AbstractWindowsCommand):
    """Prints Hello world!"""
    def render_text(self, outfd, data):
        outfd.write("Hello world!\n")
```

#実行結果

```
volatility --plugins=voltest/ -f zeus.vmem/zeus.vmem testplugin
Volatility Foundation Volatility Framework 2.6
Hello world!
```

#サンプルコード

```
import volatility.plugins.common as common
import volatility.utils as utils
import volatility.win32 as win32

class Test2(common.AbstractWindowsCommand):
    """ Works exactly like pslist """
    def calculate(self):
        addr_space = utils.load_as(self._config)
        tasks = win32.tasks.pslist(addr_space)
        return tasks
    def render_text(self, outfd, data):
        for tasks in data:
            PID = tasks.UniqueProcessId
            CreateTime = tasks.CreateTime
            Process_name = tasks.ImageFileName
            outfd.write("{0}\t {1}\t {2}\n".format(PID, CreateTime, Process_name))

```

#実行結果

```
volatility --plugins=voltest/ -f zeus.vmem/zeus.vmem test2
Volatility Foundation Volatility Framework 2.6
4	 1970-01-01 00:00:00 UTC+0000	 System
544	 2010-08-11 06:06:21 UTC+0000	 smss.exe
608	 2010-08-11 06:06:23 UTC+0000	 csrss.exe
632	 2010-08-11 06:06:23 UTC+0000	 winlogon.exe
676	 2010-08-11 06:06:24 UTC+0000	 services.exe
688	 2010-08-11 06:06:24 UTC+0000	 lsass.exe
844	 2010-08-11 06:06:24 UTC+0000	 vmacthlp.exe
856	 2010-08-11 06:06:24 UTC+0000	 svchost.exe
936	 2010-08-11 06:06:24 UTC+0000	 svchost.exe
1028	 2010-08-11 06:06:24 UTC+0000	 svchost.exe
1088	 2010-08-11 06:06:25 UTC+0000	 svchost.exe
1148	 2010-08-11 06:06:26 UTC+0000	 svchost.exe
1432	 2010-08-11 06:06:26 UTC+0000	 spoolsv.exe
1668	 2010-08-11 06:06:35 UTC+0000	 vmtoolsd.exe
1788	 2010-08-11 06:06:38 UTC+0000	 VMUpgradeHelper
1968	 2010-08-11 06:06:39 UTC+0000	 TPAutoConnSvc.e
216	 2010-08-11 06:06:39 UTC+0000	 alg.exe
888	 2010-08-11 06:06:49 UTC+0000	 wscntfy.exe
1084	 2010-08-11 06:06:52 UTC+0000	 TPAutoConnect.e
1732	 2010-08-11 06:07:44 UTC+0000	 wuauclt.exe
1724	 2010-08-11 06:09:29 UTC+0000	 explorer.exe
432	 2010-08-11 06:09:31 UTC+0000	 VMwareTray.exe
452	 2010-08-11 06:09:32 UTC+0000	 VMwareUser.exe
468	 2010-08-11 06:09:37 UTC+0000	 wuauclt.exe
124	 2010-08-15 19:17:55 UTC+0000	 cmd.exe

```

以上。
M5StackでSoftwareSerial

#M5StackではSoftwareSerialを使おう
M5Stack（私はM5Stic-Cを使いましたが）でのSoftwareSerialのすゝめです。

#背景
　Arduinoでコード書けるM5Stackでは、そもそもハードウェアコントロールなシリアルポートが3個あって、困らないからわざわざプログラムリソースを使いそうなSoftwareSerialなんてどうなのって思うかもしれません。
　しかしながら、少なくともArduinoベースでコード書いている場合、一度にある程度長いデータ長をUARTで受信した場合、困ったことが起こることにかが付くかと思います。

そう、なんか欠損するのです。

　この現象はM5Stackの問題というよりもArduinoのほうにあるみたいで、リファレンスとしては64Byteのリングバッファが確保されているらしいものの、実際は16Byteくらいから怪しくなってます。
（本当のところはちょっと調べてませんが、実際32Byteくらいからちょこちょこ欠損しだして、40Byte超えてくると2/3くらいはまともに取れなくなりました。

#先に結論から
はい。
ここに至った経緯とか色々書きたいですが、自分の備忘録的にも、まず対応方法を記述します。

##EspSoftwareSerialのライブラリをインストール
まずはM5のESP32に提供されているSoftwareSerialのライブラリをインストールします。
（Arduino標準のでもできるかわかりませんが、私は何か間違えたのかダメでした）

Arduino IDE：　スケッチ＞ライブラリのインクルード＞ライブラリ管理＞
　検索項目に　”EspSoftwareSerial”を入力すればでてくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/c64e8804-f8e9-dd90-1bec-15f6ba04c1ef.png)
これをインストール。
（画像は既にインストールしたあとです）

##コードno追記箇所
```cpp
#include <SoftwareSerial.h>
#define swrxPin 32
#define swtxPin 33
SoftwareSerial mySerial;
readBuf[64];  //64じゃなくても良いですが、十分に受信したい数値で
int read_cnt = 0;

void setup(){
  pinMode(srxPin, INPUT);
  pinMode(stxPin, OUTPUT);
  mySerial.begin(9600, SWSERIAL_8N1, swrxPin, swtxPin , false, 256);
}

void loop(){
  if(mySerial.available()){
    readBuf[read_cnt] = mySerial.read();
    reac_cnt++;
  }

  // あとは受信したいデータ長までのread_cntのカウントクリアとか、受信したreadBufの処理とか。

}
```
#SoftwareSerialのメリットとは
そうです、これが大事。
UART長いデータを受信するのが目的で、何故これでうまくいくかですが、
ハードウェアコントロールのSerialポートのバッファサイズを変えるにはArduino IDEのHerdwareSerial.hを書き換えないとならないとかとか、
またそれをやってもM5ではうまくいかなかったので、リングバッファを自由に設定できるSoftwareSerialならどうかと考えたわけです。

###SoftwareSerialでは、開始時に指定
mySerial.begin(9600, SWSERIAL_8N1, swrxPin, swtxPin , false, 256);

の最後の"256"がそのリングバッファの指定オプションです。

#デメリットは
それはもちろん、ハードウェア処理任せにならないので、何サイクルか捨てることになるかとおもいます。
しかしながら、M5StackのESP32Coreは240MHz動作していますから、実用上115200bps以下であればまず問題ないかなと思います。

それ以上のよりリッチな通信をするのであればもっと違った通信を使えばよいのかなと。

最後までありがとうございます。
Mahalo!
Power BI Desktop から Azure Databricks に接続する 【2020/10現在】

# はじめに
Azure Databricks と Power BI Desktop を接続する場合、以前は spark コネクタ経由だったので JDBC URL から情報を拾う必要がありました。2020年9月のアップデートでとても楽になったので手順をのこしておきます。

[spark コネクタで接続する方法載せた以前の記事](https://qiita.com/Catetin0310/items/eb8431f38a51641b0db1)
[新しい Azure Databricks Power BI コネクタ (パブリック プレビュー)](https://docs.microsoft.com/ja-jp/azure/databricks/release-notes/product/2020/september#new-azure-databricks-power-bi-connector-public-preview)

# 1. databricks トークンの発行
右上のユーザーアイコンから user setting をクリック
![2020-10-23_13h57_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/c0d6fe0e-f182-aab1-9b01-f99428f668f4.png)

generate new token を選択、任意で名称をいれ、generate をクリック
![2020-10-23_13h58_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/a225c082-e566-12d9-3269-5461ae25f04c.png)

トークン id を控えておきます。一回しか発行されないので注意
![2020-10-23_13h59_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/dfb46732-04cc-d43b-4090-c2fe9ff9249b.png)

# 2. databricks 接続情報の確認
databricks ワークスペースの cluster から接続したいテーブルへのアクセス権限があるクラスタを選択
![2020-10-23_13h50_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/fdf9470c-b67d-32ed-f073-5213e0531717.png)

advanced option から JDBC/ODBC を選択。hostname と https path を控えておきます。
![2020-10-23_14h01_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/71427b66-e8e0-00a5-98de-20387a284bb1.png)

# 3．Power BI Desktop で databricks に接続
Power BI Desktop を起動し、データの取得 → Azure Databricks → 接続
![2020-10-23_14h05_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/ad0f0938-530c-8699-1a0b-ae31274a0a0d.png)

先ほど控えておいた hostname と http path を入力、OK をクリック
![2020-10-23_14h07_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/ad95250e-0930-b4c4-f3c3-2e1848f5af71.png)

Personal Access Token を選択し、先ほど控えておいたトークンid を入力、接続をクリック
![2020-10-23_14h09_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/78a2ab79-3196-2e3d-42ec-1cf0fc2b567c.png)

これで databricks 側で永続化されているテーブルを取り込むことができます。
![2020-10-23_14h11_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/4b8216d5-5add-5b69-252c-e41c389e38aa.png)

簡単！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363781/e4060271-9f0a-ac0c-e51c-4d20936b7ed9.png)
Dart(Flutter)の非同期周り(compute)

[Dartの非同期周り(async, await, then)](https://qiita.com/tanaka512/items/6a326b0d92667b3cac65)でシングルスレッドでの非同期の挙動を調査したので、マルチスレッドでの非同期の挙動を確認。
DartではIsolateという仕組みでマルチスレッドを実現出来る。
FlutterではIsolateをラップしたcomputeライブラリで簡単に利用出来るのでそちらでの挙動を確認。

# 動作検証
## async thenの場合

```dart:async.dart
void main() async {
  print("${DateTime.now()}: 001");

  returnTwo().then((value) {
    print(value);
  });
  
  print("${DateTime.now()}: 003");
}

Future<String> returnTwo() async {
  print("${DateTime.now()}: returnTwo");
  await Future.delayed(Duration(seconds: 2));
  return "${DateTime.now()}: 002";
}
```

```shell
2020-10-14 16:15:17.068856: 001
2020-10-14 16:15:17.072159: returnTwo
2020-10-14 16:15:17.075668: 003
2020-10-14 16:15:19.080595: 002
```
これはおさらい。
２秒の待ちが002と003の間にあるのがポイント。

## 重い処理の場合
Dartのイベントループはいい感じにシングルスレッドで非同期処理を実現しているが、とはいえ重い処理がアプリ上にある場合には当然スレッドを専有してしまう。
それをWhileループで再現してみる。

```dart:while.dart
void main() async {
  print("${DateTime.now()}: 001");

  returnTwo().then((value) {
    print(value);
  });
  
  print("${DateTime.now()}: 003");
}

// 厳密にはFutureでも無い
Future<String> returnTwo() async {
  print("${DateTime.now()}: returnTwo");

  int beforeLoop = DateTime.now().millisecondsSinceEpoch;
  while(true) {
    int nowLoop = DateTime.now().millisecondsSinceEpoch;
    if ((beforeLoop + 2000) <= nowLoop) {
      break;
    }
  }

  return "${DateTime.now()}: 002";
}
```

```shell
2020-10-14 16:23:11.857362: 001
2020-10-14 16:23:11.860570: returnTwo
2020-10-14 16:23:13.861902: 003
2020-10-14 16:23:13.860: 002
```
２秒の待ちが発生しているのが、returnTwoと003の間である。
returnTwo()内部で重い処理があるとこのようにスレッドが専有される。
UIを持つアプリであれば当然その間はUIの描画は停止し、ユーザーからのラップなどのイベントの受付も動作しなくなってしまう。

002より003のログ出力が早いのがちょっと意外な感じだけど、イベントのさばき方の問題かな？
DateTime.now()が処理されてるのは002が先という...

## computeの場合
重い処理をcompute(マルチスレッド)で実現した場合の挙動を確認してみる。

```dart:compute.dart
  Future<void> _test() {
    print("${DateTime.now()}: 001");

    compute(returnTwo, "").then((value) {
      print(value);
    });

    print("${DateTime.now()}: 003");
  }

  static String returnTwo(String param) {
    print("${DateTime.now()}: returnTwo");

    int beforeLoop = DateTime.now().millisecondsSinceEpoch;
    while (true) {
      int nowLoop = DateTime.now().millisecondsSinceEpoch;
      if ((beforeLoop + 2000) <= nowLoop) {
        break;
      }
    }

    return "${DateTime.now()}: 002";
  }
}
```

```shell
I/flutter (21174): 2020-10-14 16:57:54.280819: 001
I/flutter (21174): 2020-10-14 16:57:54.309237: 003
I/flutter (21174): 2020-10-14 16:57:54.480967: returnTwo
I/flutter (21174): 2020-10-14 16:57:56.487022: 002
```
２秒の待ちポイントがreturnTwoと002の間になってる！
returnTwoより003が早いのはスレッドを立ち上げたりするコストによるもの。


# 参考
https://sbfl.net/blog/2014/07/10/multithreading-in-dart/
https://cbtdev.net/dart-compute/
eslint の設定で import をきれいにする

# はじめに
複数人で開発する際に「コーディングルールを揃えたい」というケースはよくあります。
各々が自由に開発していると、import の順番がバラバラになったりして、プルリクエストの際に本質的ではない変更が混在します。

私が香港のスタートアップで開発していたときは、チームメンバー全員が VSCode を利用しており、settings.json に

```json
"editor.codeActionsOnSave": {
    "source.organizeImports": true,
},
```

を入れることで、統一していました。
しかし、エディタ（は宗教問題なので）を統一したくないケースもあると思いますので、 eslint で出来ればベターだと思います。

今回は、その方法をご紹介します。

# 実装
今回ご紹介するプラグインは `import`, `unused-imports` です。
まずはプラグインをインストールします。

```sh
yarn add -D eslint-plugin-import eslint-plugin-unused-imports
```

次に `.eslint.yaml` を下記のように変更します。

```yaml
# .eslint.yaml
env:
  browser: true
  es2021: true
extends:
  - 'plugin:prettier/recommended'
  - 'prettier/@typescript-eslint'
  - 'prettier/react'

parser: '@typescript-eslint/parser'
parserOptions:
  ecmaFeatures:
    jsx: true
  ecmaVersion: 12
  sourceType: module
plugins:
  - react
  - '@typescript-eslint'
  - import
rules: 
  sort-imports: 0
  "import/order":
    - warn
    - groups:
        - builtin
        - external
        - internal
      alphabetize:
        order: asc
```

筆者の環境では VSCode の設定に、

```json
"editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
},
```

が入っているので、ファイルを変更して保存した瞬間に import の順番が変わります。

##### 修正前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/403da9d7-34ae-3e49-df3a-3ea6bfffa426.png)


##### 修正後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/333c9e40-051d-02d2-4dfd-ebe154e3009e.png)


しかし、このままでは不要な（利用していない）import が残っています。
これも自動で消したいです。

その設定を入れていきます。

```yaml
# .eslint.yaml
...
plugins:
...
  - unused-imports
rules: 
...
  "@typescript-eslint/no-unused-vars": off
  unused-imports/no-unused-imports-ts: warn
...
```

##### 修正後

![Screen Shot 2020-10-23 at 14.45.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/81ab6da5-0e3a-cdba-1481-ebd768f0d0ca.png)

不要な import が消えました。

# おわりに

複数人で開発する時に、コードフォーマッタや elinter で記述ルールを揃えると開発速度が一気に加速します。

今回紹介した方法よりも良い方法や、他にも記述改善するためのテクニックがあればぜひ教えてください。
日本語化Kibanaを立ち上げた場合の時間のずれを治すには

下記のようなdocker-compose.ymlを書いて
ElasticsearchとKibanaをインストール

docker-composeでのインストールは[こちら](https://qiita.com/t-baba-11/items/27e71bf289163fd8980e)を参照


```doccker-compose.yml

version: "3.3"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
    environment:
      - discovery.type=single-node
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - "TZ=Asia/Tokyo"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - 9201:9200
    volumes:
      - es-data:/usr/share/elasticsearch/data
  kibana:
    image: docker.elastic.co/kibana/kibana:7.8.1
    ports:
      - 5602:5601
    environment:
      - ELASTICSEARCH_URL=http://elasticsearch:9201
      - "TZ=Asia/Tokyo"
      - i18n.locale: ja-JP #日本語化
volumes:
  es-data:
    driver: local


```


現在時刻が9時間ずれてしまい、全体の表示時刻がおかしくなるので、

Management > Slack Management > Advanced Settings内の
Timezone for date formattingをJapanに変更する

![kibana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189046/d2a3d809-874b-b51f-05be-287255629d0d.png)
【Swift】どこまで勉強したら実務に飛び込むべきなのか

Twitterを見ていると、
「そんなレベルまで勉強しているの！？」
と思うことがよくあります。

逆に、
「(そのレベルじゃ厳しいだろうな...)」
ということもあります。

初学者にとってどこまでを実務へのラインとするべきなのかがはっきりしない為、
当然の現象だと思います。
あくまで一個人の体験に基づいて、どのラインまで身に付けたら
実務へ飛び込むべきなのかを書いていきます。

##実務へのライン

**最低限身に付けたい**
Swiftエンジニアとして、独学でどこまで勉強するべきかをリストアップしてみました。
・基本的な実装
・基本的な実装のカスタマイズができる
・APIからデータを取得し、利用できる
・Cocoapodsでライブラリをインストールし、カスタマイズができる
・sourcetree・githubが使える
・Firestoreが使える
・ある程度のUI/UX感覚
・ある程度のエラーを自分で解決することができる

大体ここまで出来ていれば、すぐにでも実務に飛び込むべきです。
独学は実務に敵わないからです。
ライブラリも、いくつも勉強する必要はありません。
チャットライブラリや図形ライブラリなどが使えれば十分かと思います。

実務に入るラインま出来たらあとは実務で学ぶのが良いでしょう。
プロジェクトに携わり、実際に動くコードで書かれている物を見本とできるので、
吸収効率も違いますし、何よりわかりやすいです。(百聞は一見にしかず)

##最低限身に付けたいスキルを詳しく

**・基本的な実装**
こちらはXcodeのコアライブラリにあるようなTableViewやCollectionViewなどの
基本的な実装です。それが出来たら次はカスタマイズをしていきます。
**・基本的な実装のカスタマイズができる**
TableViewやCollectionViewのレイアウトなどを自分好みにカスタマイズできるように
いじくりまわします。カスタムセルなどもここで抑えたいですね。
**・APIからデータを取得し、利用できる**
非同期処理の勉強をします。DispatchQueueやクロージャを使い、
APIを利用できるようにします。
**・Cocoapodsでライブラリをインストールし、カスタマイズができる**
ライブラリを使用しないプロジェクトはほとんどありません。
pod installでのライブラリインストールに慣れておきたいですね。
あとは外部ライブラリをカスタマイズできるようにします。
(外部ライブラリの使用は面接用のポートフォリオなどで役に立ちます。)
**・sourcetree・githubが使える**
定番のプロジェクト管理ツールです。
最低限使えるようにしたいところです。
**・Firestoreが使える**
ポートフォリオとしてある程度役に立ちます。
**・ある程度のUI/UX感覚**
どんなに複雑なロジックよりも、第三者の目をまず惹くことができるのがUIです。
ここに拘れると評価が高くなりやすいです。
UI、つまりデザインはセンスというよりも引き出しを増やす感覚に近くて、
例えばリンゴを知らない人がリンゴを書けないように、
美しいデザインをストックしておかなければ
美しいデザインを表現するのはなかなか難しいです。
pinterestで「app ui」などで検索し、引き出しを増やすと良いです。
**・ある程度のエラーを自分で解決することができる**
言うまでもなく、これはエンジニアとしてとても大切なポイントですね。

##おわりに
いかがでしたでしょうか。
いつまでもインプットせず、まず実務に入ることを目的として勉強するのが
良いかと思います。
Android Navigationでアニメーション付きで画面遷移させる

## config.xmlとアニメーション用のxmlを作成する

```main/res/values/config.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="config_transitionAnimTime">400</integer>
</resources>
```

```res/anim/slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="50%p"
        android:toXDelta="0"
        android:duration="@integer/config_transitionAnimTime" />
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:duration="@integer/config_transitionAnimTime" />
</set>
```

```res/anim/slide_out_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="-50%p"
        android:duration="@integer/config_transitionAnimTime" />
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="@integer/config_transitionAnimTime" />
</set>
```

```res/anim/slide_in_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="-50%p"
        android:toXDelta="0"
        android:duration="@integer/config_transitionAnimTime" />
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:duration="@integer/config_transitionAnimTime" />
</set>
```

```res/anim/slide_out_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="50%p"
        android:duration="@integer/config_transitionAnimTime" />
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="@integer/config_transitionAnimTime" />
</set>
```

# navigationファイルでアニメーションを設定する。

```res/navigation/nav_graph.xml
        <action
            android:id="@+id/action_hogeFragment_to_fugaFragment"
            app:destination="@id/fugaFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
```
dockerでdocker-compose up -dができない

#困りごと
macos 2020 にて、
どこかしらのディレクトリでサーバーに接続したいとき、
dockerは起動しているのに、ターミナルで、

```
docker-compose up -d
```

としても、エラーが出てしまいます↓

ERROR: 
        Can't find a suitable configuration file in this directory or any
        parent. Are you in the right directory?
        Supported filenames: docker-compose.yml, docker-compose.yaml
![E41F52C2-788C-4ED3-B6C5-019E45F957C2_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699159/c69b7727-3a3b-54c6-1ec9-8d5beb56fdb2.jpeg)
#解決

どこかしら別のディレクトリでdocker-compose up -dを起動したままだった為でした。
そのディレクトリにて停止させます。ターミナルで、

```
docker-compose stop
```

これで一旦落着！

####おわり。
playwrightのテスト結果を動画として残す方法

# はじめに
e2eテスト界にキラ星のごとく登場した[playwright](https://playwright.dev/)。
後発ツールなだけあって超絶クールですが、標準構成のみでテスト結果を動画として保存することができます。

# 動画を出力するための設定
```javascript
const context = await browser.newContext({
  videosPath: 'videos/'  // 動画を出力するフォルダ名
});
```

テストコードに上記設定を追加するだけで、テスト結果を動画に残せます。
本当にこれだけでOKなので、世の中便利になったものだなと思います。
なお、公式サイトには、これ以外のやり方も書かれているので、
よろしければ参考にしてください、

公式ドキュメント
https://playwright.dev/#version=v1.5.1&path=docs%2Fverification.md&q=videos

# サンプルコード

```javascript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    headless: false
  });
  const context = await browser.newContext({
    videosPath: 'videos/'
  });

  // Open new page
  const page = await context.newPage();

  // Go to https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8
  await page.goto('https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8');

  // Click input[name="search"]
  await page.click('input[name="search"]');

  // Fill input[name="search"]
  await page.fill('input[name="search"]', 'ユニットテスト');

  // Go to https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88
  await page.goto('https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88%E3%83%86%E3%82%B9%E3%83%88');

  // Go to https://ja.wikipedia.org/wiki/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88
  await page.goto('https://ja.wikipedia.org/wiki/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88');

  // Click text="契約による設計"
  await page.click('text="契約による設計"');
  // assert.equal(page.url(), 'https://ja.wikipedia.org/wiki/%E5%A5%91%E7%B4%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0');

  // Click text="ソフトウェア開発工程"
  await Promise.all([
    page.waitForNavigation(/*{ url: 'https://ja.wikipedia.org/wiki/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88' }*/),
    page.click('text="ソフトウェア開発工程"')
  ]);

  // Close page
  await page.close();

  // ---------------------
  await context.close();
  await browser.close();
})();
```

wikipediaのページを遷移するテストを書きました。
8行目で``` videosPath: 'videos/' ``` と書いていますが、これが動画出力の設定です。
テストを実行するとvideosフォルダ配下に、テスト動画が自動生成されます。
念のためにgithubにコードのフルセットを用意したので、
実際に動かしてみたい方はぜひお試しください。

コードフルセット
https://github.com/kaidouji85/playwright-video-record
【備忘録】プロジェクト作成

[戻る](https://qiita.com/Mosaku_Anchu/items/9dbf06c34577dfc7aa9c)
#新規プロジェクト作成
※著者のAndrid Studioは日本語化されています。

- Android Studioの以下の画面又は、[メニュー]→[新規]→[新規プロジェクト]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362978/d643e5ee-9c8b-751b-880e-bdd5da9aeaa8.png)

***
- とりあえず[空のアクティビティー]を選択し、[次へ]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362978/c8cdd561-1066-3200-7045-38f234e3a303.png)

***
- プロジェクト構成
 - 名前 変更は面倒なのでよく考える
 - パッケージ名 所持ドメインの逆順が一般的？
 - 保存ロケーション　保存先どこでも
 - 言語(JAVA or Kotlin)　今回はJAVA 
 - 最小SDK 使用する環境に合わせて選択
 - Use legacy~ とりあえずチェック

[完了]を推すとプロジェクトが作られる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362978/6f60e434-1ef4-e0de-b404-b13f37e787f4.png)
[戻る](https://qiita.com/Mosaku_Anchu/items/9dbf06c34577dfc7aa9c)
[Python] Python文法のサンプルコード

## はじめに
Pythonの勉強のために以下のようなプログラムを書きましたが、
もっと効率的な書き方があると考えているので、
有識者の方々の意見が聞きたく記事にしました。
もっと行数短く書けるよ!っていう有識者の方々、是非ともコメント頂きたいです。

## 和暦変換
```Python:和暦変換
# 年数(西暦)で入力
year = int(input())

Syear  = [1868, 1912, 1926, 1989, 2019, 9999]
wareki = ['明治', '大正', '昭和', '平成', '令和', '']

i = 0

# 和暦変換
while Syear[i] <= year:
   Wyear = year - Syear[i] + 1
   Wname = wareki[i]
   i += 1

# 出力
print(str(year) + '年は' + Wname + str(Wyear) + '年')
```

## 年齢判定
```Python:年齢判定
import datetime

# 生年月日(西暦)を入力
Tymd = input()

# 年月日に分割
param  = Tymd.split('/')
Tyear  = int(param[0])
Tmonth = int(param[1])
Tday   = int(param[2])

# 現在の日付を取得
Today = datetime.datetime.now()
year  = Today.year
month = Today.month
day   = Today.day

# 年齢計算
age = int(year) - int(Tyear)
if int(month) < int(Tmonth):
    age -= 1
else:
    if month == Tmonth:
        if day < Tday:
            age -= 1

# 出力
print(Tymd + 'の人は' + str(age) + '歳')
```

## 曜日判定
```Python:曜日判定
import math

# 入力値(例: 1997/9/11)をうけとる
x = input()

# 入力値を年月日に分割
y     = x.split('/')
year  = int(y[0])
month = int(y[1])
day   = int(y[2])

# 出力
print(str(year) + '年' + str(month) + '月' + str(day) + '日は', end = '')

if month < 3:
    month = month + 12
    year  = year - 1

# 曜日を求める
weekday = (year + math.floor(year / 4) - math.floor(year / 100) + math.floor(year / 400) + math.floor((13*month+8) / 5) + day) % 7
week    = ['日', '月', '火', '水', '木', '金','土']

# 出力
print(str(week[weekday]) + '曜日です')
```

## 複数桁の桁分解
```Python:複数桁の桁分解
# 入力値をうけとる
x = int(input())

num = []

# 1桁ごとに分解
while x > 0:
    num.append(x % 10)
    x //= 10
num.reverse()

# 出力
for i in range(len(num)):
 print(num[i], end = ' ')
```

## 閏年判定
```Python:閏年判定
# 年数(西暦)を入力
year = int(input())

# 閏年判定
if year % 4 == 0:
    if year % 100 == 0:
        if year % 400 == 0:
            print(str(year) + '年は閏年')
        elif year % 400 != 0:
            print(str(year) + '年は閏年ではない')
    else:
        print(str(year) + '年は閏年')
else:
    print(str(year) + '年は閏年ではない')
```

## 干支判定
```Python:干支判定
# 年数(西暦)を入力
year = int(input())

# 全干支
Alleto = ["申(さる)", "酉(とり)", "戌(いぬ)", "亥(いのしし)", "子(ねずみ)"
            , "牛(うし)", "寅(とら)", "卯(うさぎ)", "辰(たつ)", "巳(へび)", "午(うま)", "未(ひつじ)"]

# 干支判定&出力
print(str(year) + '年の干支は' + Alleto[year % 12])
```

## 素数判定
```Python:素数判定
# 2以上の数値を入力
num=int(input())

# 0: 素数
# 1: 素数ではない
sosu = 0

# 素数判定
for i in range(2, num):
    if num % i == 0:
        sosu = 1
        break

# 出力
if sosu == 0:        
    print(str(num) + 'は素数である')
elif sosu == 1:
    print(str(num) + 'は素数ではない')
```
MySQLデータ型まとめ

# MySQLとは
DBMS（DataBase Management System）のひとつ、高速でポピュラー

# データ型

詳細は次章で

* 整数(TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT)
* 浮動小数点
* 固定小数点
* BIT
* 日付・時刻(DATE, TIME, DATETIME, TIMESTAMP, YEAR)
* CHAR・VARCHAR
* BINARY・VARBINARY
* BLOB・TEXT
* ENUM
* SET

# 詳細説明
## 整数
### TINYINT

8bitで表現できる整数。

- 符号付きで -128 ~ 127
- 符号なしで 0 ~ 255

の整数を格納できる。
____
### SMALLINT

16bitで表現できる整数。

- 符号付きで -32768 ~ 32767
- 符号なしで 0 ~ 65535

の整数を格納できる。
____
### MEDIUMINT

24bitで表現できる整数。

- 符号付きで -8388608 ~ 8388607
- 符号なしで 0 ~ 16777215

の整数を格納できる。
____
### INT

32bitで表現できる整数。

- 符号付きで -2147483648 ~ 2147483647
- 符号なしで 0 ~ 4294967295

の整数を格納できる。
____
### BIGINT

64bitで表現できる整数。

- 符号付きで -9223372036854775808 ~ 9223372036854775807
- 符号なしで 0 ~ 18446744073709551615

の整数を格納できる。
____

## 浮動小数点
小数点付きの数値を表現できる。桁数や仮数部の大きさにより誤差が生じてしまう場合がある([参考](https://www3.cuc.ac.jp/~miyata/classes/system/d03.pdf))
### FLOAT
32bitで表現できる符号付き小数

* 符号 : 1bit
* 指数 : 8bit
* 仮数 : 23bit

で構成される。
およそ7桁くらいの小数を表現できる。
____
### DOUBLE
64bitで表現できる符号付き小数

* 符号 : 1bit
* 指数 : 11bit
* 仮数 : 52bit

で構成される。
およそ16桁くらいの小数を表現できる。
____


## 固定小数点
予め小数点以下の桁数を指定するため精度が高い
### DECIMAL[(M[,D])]
M : 精度。合計桁数 (max65)
D : 小数点以下の桁数 (max30)

```math
± （ 10 ^　M \div 10^D ）
```

の範囲を表現できる

## BIT
ビット型。1~64bitのbit値を格納できる

## 日付・時刻型(DATE, TIME, DATETIME, TIMESTAMP, YEAR)

### DATE
日付
'1000-01-01' から '9999-12-31'
フォーマット ： `YYYY-MM-DD`
___
### DATETIME[(fsp)]
日付と時間の組み合わせ
'1000-01-01 00:00:00.000000' から '9999-12-31 23:59:59.999999'
フォーマット ： `YYYY-MM-DD HH:MM:SS[.fraction]`
___
### TIMESTAMP[(fsp)]
タイムスタンプ
TIMESTAMP 値は、エポック ('1970-01-01 00:00:00' UTC) からの秒数
`1970-01-01 00:00:01.000000` UTC から `2038-01-19 03:14:07.999999` UTC
フォーマット ： 
___
### TIME[(fsp)]
時間
'-838:59:59.000000' から '838:59:59.000000'
フォーマット ： `HH:MM:SS[.fraction]`
___
### YEAR[(2|4)]
2 桁または 4 桁の形式の年
4 桁の形式では、値は 1901 から 2155 と 0000
2 桁の形式では、値は 70 から 69 ( 1970 から 2069 に相当)
フォーマット ： YYYY または YY 

## CHAR・VARCHAR
CHARは余った文字数を空白文字で埋める
→末尾スペースは取得時に削除される

## BINARY
char/ varcharのバイナリデータ版

## TEXT
varcahrの文字数指定しなかった版でOK

## BLOB
varbinaryの文字数指定しなかった版

## ENUM
文字列のリストを予め定義し、その中の文字列のみ格納できる。NULLも格納できる。
リストの先頭からインデックスが割り振られ、内部的にはインデックスが格納されている。

## SET
ENUMの複数要素選択できる版

# 参考文献

* https://www3.cuc.ac.jp/~miyata/classes/system/d03.pdf
* https://www.dbonline.jp/mysql/type/
VuetifyのClearableはtextfieldとselectで戻り値が違う

# TL;TR
textfieldの場合にはnull
selectの場合にはundefined

#何が問題なの？
人によっては問題ではないのかもしれませんが、axiosでポストする際に、オブジェクトのバリューがundefinedだとサーバーサイドにそもそも送信されません。

```js
axios.post('http://localhost:3000/api', {sample: 'a', test: undefined})

//Request Body {sample: 'a'}
```
そのため単純にv-selectにてクリアブルを使用していると、そのプロパティに関しては、まず存在チェックをかける必要があり、その上で値の確認をする必要があります。
テキストフィールドの場合と挙動が違うのとあらかじめ設定しておいたプロパティに存在チェックをかけなければいけないのも面倒だったので、selectに関してもクリアしたときにnullを返すように修正してみました。

```vuejs
<template>
  <div>
    <v-text-field
      label="sample"
      v-model="form.sampleText"
     ></v-text-field>
     <v-select
       label="select"
       v-model="form.sampleSelect"
       :items="selection"
       append-icon="close"
       @click:append="form.sampleSelect = null"
      ></v-select>
  </div>
</template>
<script>
export default {
  data: () => ({
    form: {
      sampleText: '',
      sampleSelect: null,
    }    
  }) 
}
</script>
```
【塞がれました】Teams の Power Appsで作ったアプリを普通のPower Appsで編集する

# 2021/4/9 この方法がふさがれたことを確認しました

これまでの方法で編集しようとすると「直接編集せずにTeamsでやってね」というメッセージが出るようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f5a158d7-425a-3c95-ef4a-a26806d47dfe.png)

残念ですが、直URLでも難しいようなので、あきらめるしかなさそうです。

左側のメニューについては、Power Apps アプリ自体をポップアウトすることで解消されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/12ff31a5-152f-7cb6-2d52-92b4409c8c1b.png)

ということで以下は以前できたことです・・・。

# もう使えなくなった方法

Microsoft Teams内でPower Appsを作れるようになって少したちますが、いまだに慣れないのがここです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/02798951-5579-c870-1a13-c91aa250c455.png)

Power Apps Studioが持っているタブやメニューと、TeamsのメニューまたはTeamsアプリとしてのPower Appsのもつメニューが近い！
これによって押し間違え、アプリを作っているときに間違えて閉じちゃって編集内容が損なわれる などなど、Authoring experienceがあまりいいとは思えず、できれば普段のキャンバスアプリを作っているPower Apps Studioで編集したいなと思っていました。

また、新しく追加されたFluent UIを使ったコントロールも、普段のキャンバスアプリと設定が違ったりしていて少し厄介なところがあります。

ここでは普段使っているPower Apps StudioでTeams内で作ったキャンバスアプリを編集する方法をご紹介します。

なお、**『Fluent UIなコントロールは追加できない』**という点に注意してください。


# Power Apps Studioで開くまでの道筋

Teams内のPower Apps Studioで作成したアプリは自動的にそのチームに関連づいた環境のソリューションに入ります。

Power Appsからはこのチームに関連づく環境は開けませんが、Power Automateからだと環境の選択肢に出てきます。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/a87e3506-0a06-cc84-a492-c2fa5f00b0be.png)

上図では、「AutomateTest」と「Paragon test」という2つの環境がTeams由来の環境です。

まずはPower Automateを表示して、環境を切り替えます。その後左のメニューから「Solutions」> 「Common Data Services Default Solution」と辿ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/ad642857-1868-4a4b-ca3a-1587c9b82b46.png)

ソリューションの中には、Teams側で作ったキャンバスアプリが含まれているかと思います。
選択して、「Edit」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/de7f300d-d037-17ca-6b60-12ce5d4e30df.png)

これでいつものPower Apps Studioでアプリを編集可能になりました。テーマもTeamsカラーになっていますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/b380d9cc-e51c-f991-c5ff-d787a135b738.png)

編集して保存→発行すれば、Teams側から見ても変更が反映されていることが分かります。

# 注意事項

先ほど書いた通り、TeamsのPower AppsではFluent UIなコントロールが一部採用されています。（テキストインプットやカレンダーなど）
これらのコントロールは通常のPower Apps Studioでは追加できないということに注意してください。

もしFluent UIなコントロールを追加したい場合には、Teams側で一度追加しておいて、Studioでコピペしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/449e95f1-6b1c-06ea-4488-8451a91a9350.png)
【Ruby on Rails】コントローラー間で共通処理（concerns使用）

# はじめに
サイトページが多くなるにつれて、同じコントローラーの記述が増えてくるかと思います。
そのときにconcernsを活用すると記述もスッキリとなり、可読性が上がります。

# 実際のコード
```rb:app/controllers/posts_controller.rb
class PostController < ApplicationController
  before_action :set_posts
  def set_posts
    @posts = Post.all
  end
end
```

```rb:app/controllers/users_controller.rb
class UserController < ApplicationController
  before_action :set_posts
  def set_posts
    @posts = Post.all
  end
end
```

上記のように同じset_postsという共通処理があります。
ただし、もし変更があった場合は両方を修正する必要があり手間です。
これらを解決する方法がconcernsの利用です。


# concernsファイルの作成
app/controllers/concerns配下にファイルを作成します。
今回ファイル名は「postable.rb」にします。

```rb:app/controllers/concerns/postable.rb
module Postables
extend ActiveSupport::Concern

  def set_posts
    @posts = Post.all
  end

end
```

そしれそれぞれのコントローラー呼び出すためには
```include Postables```と記述します。

```rb:app/controllers/posts_controller.rb
class PostController < ApplicationController
  include Postables
  before_action :set_posts
end
```

```rb:app/controllers/users_controller.rb
class UserController < ApplicationController
  include Postables
  before_action :set_posts
end
```

これでOKです。

# まとめ
これらを行うことで修正があったとしても一箇所の修正で済み、エラー時にも早急に対応できます。
記述の少なさは保守性にもつながりますので、使用することをおすすめします。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork
[自分用メモ] Jenkins コンソール出力 をテキストファイルで取得する

# やりたい事

**Jenkins**で ジョブをビルドすると、[コンソール出力]画面にて ログを確認することができる。
このコンソール出力 で表示されているログを、テキストファイルで取得したい。

# コンソール出力 取得

**curl コマンド**を実行して コンソール出力 をテキストファイルで取得する。

```
curl https://<JENKINS_HOST>/job/<JOB_NAME>/<BUILD_NUMBER>/consoleText --output <出力ファイル名> -k --user <ユーザー名>:<パスワード>
```

**--output オプション** にて、*<出力ファイル名>*を指定。
**-k オプション** で、SSL証明書のエラーを無視する。(デフォルトでは すべてのSSL接続の安全性が確認される。)
**--user オプション**で、*<ユーザー名>*と*<パスワード>*を指定。


# 参考情報

How To Use - curl
https://curl.haxx.se/docs/manpage.html
日本人プログラマは海外人材に取って代わられるのか

いまからエンジニアを目指そうという奮闘している人にも、
今の身分を捨てて転身しても大丈夫だろうか・・・と、
不安になる気持ちもあると思います。

なかでも表題は「競争が激しい」「インド人やベトナム人に日本人は淘汰される」
などと気を迷わせるトピックの一つだと思います。

社内でもオフショア開発をメンバーに起用したという話で盛り上がっていたので、
様々なエンジニアやビジネスマンの見解、私の所感を述べてみたいと思います。

# いきなり結論から
**現状は代替されることは考えにくい**です。
あまり悲観的になる必要はないと思います。

ただし、努力を怠っていいと言っているわけではありません。
プログラミング能力で見れば海外人材は非常に高い水準にあります。
下記、そのように結論づけた理由（私の所感）を述べます。

## コミュニケーションコスト
誰もがまず注目する点だと思います。日本語話せるのか？と。
実際モバイルアプリ開発の現場からは、「ほとんど遜色なく話せる」とのことです。
もちろん個々でばらつきはありますが、言語の壁はさほど障壁になりません。

さて、ではなぜコミュニケーションコストを取り上げたかというと、
商習慣や日本特有のビジネスユースなど、日本人にとっての暗黙の了解を
要件に落としていくことは非常にコストがかかるからです。
日本人同士でも認識の齟齬が出るので当然といえば当然です。

確かに発注側にオフショアをハンドルできる能力がついてればいいやん、と思われるかもしれませんが、
実際には日本人エンジニア相手でも非常に難しい行為です。

>小規模のWebアプリ開発はオフショアになって行くと思いますけど
中規模以上のものは国産じゃないとキツイ

これも設計や要件定義で日本人エンジニアが必要な要因ですね。

## 選定責任
「日本人のほうが安全」「海外に出すのは嫌（特に役所系）」という感情もあります。
オフショアは安いですが、オフショアを選定した場合その人に全責任がかかります。
日本の受託開発会社なら責任を取らせやすいですし。
単純に金額が安いだけでは乗り換え辛いのだと思います。

## インターフェースが不可欠
少々上記とかぶる点もありますが、つよつよエンジニアの見解から。
>クライアント → 制作会社 → 開発会社 → 一部機能をオフショアに外注
これが限界だと思います。
間に日本人開発者が必要な時点でオフショアが取って代わることは不可能です

# 高度人材はどうなの？
少しオフショアとは話がそれますが、日本にやってくる高度人材はどうなのか？
これは意見が分かれるところだと思います。

- 日本の現場は安いので来ない
- アメリカや中国に流れる
+ 親日国（ベトナムなど）からたくさんの人材が流れ込んでくる
+ スキルの高い外国人が安く雇える

これも私の所感になって恐縮ですが、カンボジアで住んでいたときは、
日本に行きたがっている人（プログラマ）が多い印象でした。単価の面では日本はそこそこレベルであり、中国やアメリカとは程遠いのも事実です。
それでも日本を選ぶ理由は、社会主義色の残るベトナムやカンボジアはアメリカのVISA取得が困難であることや、嫌中が多いということ。現地のカンボジア人プログラマがそのように語ってくれましたし、概ねその理解で正しいのかなと思っています。何より、月所得2-3万円の世界ですから、日本でも万々歳だということです。

ちなみに安く雇えるかどうかですが、在留資格関連の規定で、同等の能力を満たすなら日本人と変わらない給料を支払う必要があります。
なので、純粋にリソース補填が目的であり、安い労働者を雇うといった発想は成り立たちません。
ただ、リソースが潤沢になったり、外国人材の求める単価が、総じて日本人プログラマの単価をアンカリングする可能性は十分にありえると思います。
大幅には下がらないが、じわじわ効いてくるといった予想です。

# オフショアが活用される場面
比較的小規模プロジェクトであったり、受託会社監督のもとチームの人員となるような運用は考えられます。
このつなぎ役をブリッジSEと呼んだりします。インターフェースですから、的確な仕様や設計の伝達、言語の壁がある場合は英語などを活用してマネジメントしていくことが求められます。
個人的にはこの様なマネジメントができることは非常に付加価値が高いと思っています。

一部業務を切り出すことで顧客ニーズを満たす設計などに注力できたり、開発費用削減を実現するなど、あくまでサプリメント的運用になるとは思います。

# 付加価値
完全にオフショアに置き変わらないとはいえ、付加価値は常に意識する必要があります。
日本は文化的にも経済的にも優位性がありますが、あぐらをかいているとあっという間に置いてかれるでしょう。ビジネス視点からのコメントを引用（少し改変してます）します。

>ベトナムで「できるオフショア」のエンジニアは、日本で言うと「旧帝大卒＆国力増強に対するコミットが高い」というものだと聞いたことがあります。
一概に高学歴がすごいという話ではなくて、「理解力が比較的高い人」がいる可能性が高い。ということで脅威を感じています。
日本の優位性、ではなくて、個人は「徹底した理解(文化、ニーズ、情報、などを網羅的に)」と「考える力」が主眼であるべきと、自分は感じています。
日本の文化の優位性は期限があるものとしてそれに挑戦し続ける個であること、が前提です。
組織は上記のような個を「尊重」出来る、かつ、「プロである」という厳しさを両立した形なのかなと考えています。

#まとめ
情報が錯綜し競争が激化していると云われる現在においてエンジニアになることや、続けていくことに不安を覚えることは当然にあると思います。それはエンジニアに限らず外部に接していれば、少なからず起きる脅威です。
悲観的になる必要はなく、むしろうまく扱う側に回ることでチャンスにもなり得るはずです。
【備忘録】業務用Andoridアプリ開発への挑戦

#前提情報

## 挨拶
乱筆乱文にて失礼いたします
業務改善のためAndroidアプリの開発に挑戦することに
開発手順を検討しつつ進める所存
都合により細部をぼかすことがあるはご容赦いただきたし
内容は随時追加予定

## 選定経緯
- 紙に記入→PCへ入力の業務が非常に多く  
  データ化されていない情報も多い
- PC台数が少なく調べものもままならない
- ネットワーク環境が弱いためオフラインでも使える  
___→Androidでアプリ開発が最適では___

***
## 投稿者スペック
  - システム管理者3年目(2020/10現在)
  - Android使用経験なし
  - Java経験なし

## 環境確認
- Windows10 Pro + Java7
- Android Studio 4.0
- サーバー + SQL Server + Tomcat7
- Androidタブレット(Android 9 Pie)

# 開発手順

## 要件定義
- ターゲット補足
- 理想形の構築
- 現状の確認
- すり合わせ

## Androidアプリ
- [プロジェクト作成(Android Studio)](https://qiita.com/tackchemshot/items/d1a5500a4a8909619f02)
- [基本情報設定(gradle)]
(https://qiita.com/Mosaku_Anchu/items/46207bba3ee3ddb0be40)
- GUI作成(activity_.xml)
- [SQLite関連]
(https://qiita.com/Mosaku_Anchu/items/6a2f527f3308fe07eda5)
- [http通信関連(okhttp3)]
(https://qiita.com/Mosaku_Anchu/items/93b1d82409fca7fc5a40)

## WebAPI
- Tomcat7関連
- http通信関連
- 帳票印刷
freezedやjson_serializableのfromJson()でDateTimeの変換がうまくいかないときの解決法

## 問題
freezedを使う場合に以下のように fromJson()を作ると、Firebaseライブラリを使った場合などでDateTime変換関連のエラーが出てしまいます。

例として、Messageというデータ型を作る場合を考えます。

```dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:meta/meta.dart';

part 'message.freezed.dart';
part 'message.g.dart';


@freezed
abstract class Message with _$Message {
  factory Message(
      {@required String username,
      @required String body,
      @required DateTime createdDate}) = _Message;

  factory Message.fromJson(Map<String, dynamic> json) =>
      _$MessageFromJson(json);
}
```

freezedによる生成コード

```dart
// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'message.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

_$_Message _$_$_MessageFromJson(Map json) {
  return _$_Message(
    username: json['username'] as String,
    body: json['body'] as String,
    createdDate: json['createdDate'] == null
        ? null
        : DateTime.parse(json['createdDate'] as String),
  );
}

Map<String, dynamic> _$_$_MessageToJson(_$_Message instance) =>
    <String, dynamic>{
      'username': instance.username,
      'body': instance.body,
      'createdDate': instance.createdDate?.toIso8601String(),
    };

```

自分の場合は、この生成コードのfromJson()中の以下の部分でエラーが出てしまいました。

```dart
createdDate: json['createdDate'] == null
        ? null
        : DateTime.parse(json['createdDate'] as String),
  );
```

このコードを以下のように修正することで問題は解決します。

```dart
createdDate: json['createdDate'] == null
        ? null
        : json['createdDate'] as DateTime,
  );
```

しかし、生成されたコードを書き換えると、生成されるたびに書き換える必要が出てしまいバグの原因となる可能性があるため、できるだけやりたくありません。



## 解決策
そんなときは、以下のように[JsonConverter](https://pub.dev/documentation/json_annotation/latest/json_annotation/JsonConverter-class.html)を実装したクラスを作ると、任意の方法でfromJson()を行うことができるようになります。

```dart
class MessageConverter implements JsonConverter<Message, Map<String, dynamic>> {
  const MessageConverter();

  @override
  Message fromJson(Map<String, dynamic> json) {
    if (json == null) {
      return null;
    }
    
    // ここで自由に変換方法を指定
    return _$_Message(
      username: json['username'] as String,
      body: json['body'] as String,
      createdDate: json['createdDate'] as DateTime,
    );
  }

  @override
  Map<String, dynamic> toJson(Message data) => data.toJson();
}
```


利用する側はこんな感じです。

```dart
@freezed
abstract class Message with _$Message {
  factory Message(
      {@required String username,
      @required String body,
      @required DateTime createdDate}) = _Message;

  // ここでMessageConverterを使う
  factory Message.fromJson(Map<String, dynamic> json) =>
      messageConverter.fromJson(json);

  static const messageConverter = MessageConverter();
}
```

## 追記
フィールド毎にもConverterを設定することができるようですので、そちらの方が影響範囲を少なくできてより良いと思います。（以下のコメント参照。 @renoinn さんありがとうございます）

https://qiita.com/tetsufe/items/3c7d997f1c13c659628c#comment-5ce93b14ddfbc9ee6428


## 参考
https://github.com/rrousselGit/freezed#fromjson---classes-with-multiple-constructors


## 僕のTwitter
https://twitter.com/tetsufe_
freezedでxxx.g.dartが生成されない時にチェックすべきこと

freezedの処理としては成功しているけど、xxx.g.dart、つまりはjson_serializedのファイルが生成されない。でもエラーが出ないので何が間違っているかがわからないということがありました。これは、そもそも「生成の指示が適切にできていない」ことが問題です。以下は、この問題を解決するためのチェックリストです。

## `part 'message.g.dart';`は書いているか

```dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:meta/meta.dart';

part 'message.freezed.dart';
part 'message.g.dart'; // ←これ

@freezed
abstract class Message with _$Message {
  factory Message(
      {@required String username,
      @required String body,
      @required DateTime createdDate}) = _Message;

  factory Message.fromJson(Map<String, dynamic> json) =>
      messageConverter.fromJson(json);

  static const messageConverter = MessageConverter();
}
```

## json_serializableをpubspec.yamlに書いているか
これで15分くらい詰まりました。

pubspec.yaml

```yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

  freezed: ^0.11.6
  json_serializable: ^3.3.0 # ←これ

```


## 参考
[freezed 公式パッケージページ](https://pub.dev/packages/freezed)
【未経験の方必見】アプリエンジニアが狙い目な理由


こんにちは。
この記事では、言い方は悪いですが
「なぜアプリエンジニアが狙い目なのか」
「なぜアプリエンジニアが少ないのか」
にフォーカスを置いて書いていきます。

##なぜアプリエンジニアが狙い目なのか

理由は簡単です。
母数が少ないからです。
この理由から、需要に対しての供給が足りていません。
経験者の採用を諦め、未経験者の教育に力を入れている会社もあるようです。

実際、弊社では全ポジションを募集していますが、
アプリエンジニアの面談回数はサーバーサイドやフロントに比べてかなり少ないです。

サーバーサイドやフロントに対してアプリエンジニアは
大体5分の1〜10分の1ほどしか応募がきません。
アプリエンジニアの中でもAndroidエンジニアは特に、iOSエンジニアの10分の1ほどしか
来ないため、Androidエンジニアの希少性はかなり強いと言えます。

##なぜアプリエンジニアが少ないのか

Twitterを通していろいろな意見を見たり、実際に勉強会で交流を通して意見を聞いてきた中で、
アプリエンジニアが少ない理由がいくつか見えてきました。

###苦手意識
初学者の人はまず、「どの言語をやるか」「どのポジションをやるか」
について選択が迫られます。
この時、「フロントの方がすぐに結果が見えてわかりやすい」
という意見がよく見られました。

また、「**プログラミングの勉強を始めるならまずHTML・CSS**」
という暗黙の何かがあるように思えました。
（「HTML・CSSはプログラミング言語じゃない」という気持ちはわかります)
そこから派生してJavascript・jQuery・Vue.jsなどフロントエンジニアの道を歩む人が
多いのではないでしょうか。

###アプリエンジニアを勧める環境が少ない
初学者の言語選択に対して、「PHP×Javascript」「Rails」
を勧める環境が多いように感じられました。
特に「PHP×Javascript」は、「初学者が最短で仕事につくのに最適だ」「一番簡単だ」
と勧める人をよく見かけました。

Railsが多い理由はスクールの影響が大きいかと思います。
確かにわかりやすいですし、レール(rail)にのっとった書き方ができるため初学者に優しいかもしれませんが、
逆に言えば経験者が爆速開発するためのフレームワークで少数精鋭でやるものだと言う声もあり、
初学者に本当に優しいのかと聞かれると
はっきりとYesと言えない言語です。

これらから分かるように、初学者にとってウケがいい言語は「手頃(そう)な言語」で、
またウケを狙った(？）スクールによってRails学習者が増え、
バランスが偏ってしまっているのではないかと推測しました。

###iOSエンジニアはMacBookが必要

正確に言えば、MacBookがなくてもOSをぶち込めれば良いのですが、
いきなりの初学者がそんなことを思いつきませんし、できません。
勉強を始めるためにMacBookを買うと言うフィルターがあるために、
アプリエンジニアの頭数が少ないのだと推測しました。

###Androidユーザーが少ない

アプリエンジニアの道に進んだとしても、iOSかAndroidかの分岐があります。
ここでは、多くの人がiOSエンジニアを選択することでしょう。
なぜなら日本では、世界でも稀にiPhoneユーザーが多いためです。
Android端末を使ったことがないのにAndroidの勉強をする人はかなり稀です。

##結局のところアプリエンジニアは少ない

これらの理由から、エンジニア市場には偏りが見られます。
iOSエンジニアをやるにしても高価なMacbookが必要で、
Androidエンジニアへの道も国内OSシェアからその道に進む人があまりいません。

サーバー・インフラ>>アプリエンジニア(iOS >> Android)

のような構図が見られるため、ただでさえアプリエンジニアは狙い目であるのに
Androidエンジニアとなれば更に母数が減るのです。

これからプログラミングの勉強を始めようと考えている方がいましたら、
ぜひアプリエンジニアを検討してみてはいかがでしょうか。

##誤解してはいけない

誤解してはいけないのが、「供給が足りないのだから簡単なんだ！」と言うことです。
あくまでも一定レベルのスキルは必要であり、それなりの勉強時間が必要になります。
はっきり言ってエンジニアになるには大変です。
数ヶ月でなれる人は天才だと思います。


最後まで記事を読んでいただきありがとうございました。
GitHub Actionsからツイートできるtwitter-togetherを使ってみる

# 概要
[twitter-together](https://github.com/gr2m/twitter-together)はGitHubリポジトリに作成した`tweet`ファイルをGitHub Actionsを通してツイートしてくれる。GitHub Actionです。

# 使い方

## 1.Twitter Developerでappの作成

[Twitter Developer](https://developer.twitter.com/en)のリンクからTwitterログインをしてappを作成してConsumer API keysとAccess token & access token secretを取得できる状態にしてください。

## 2.プロジェクトの作成

プロジェクト作成といってもGitHub Actions用のymlを用意するだけです。
今回はお試しなので、Readmeに記載されているものをそのまま使います。

`.github/workflows/twitter-together.yml`

```yml
on: [push, pull_request]
name: Twitter, together!
jobs:
  preview:
    name: Preview
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: gr2m/twitter-together@v1.x
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  tweet:
    name: Tweet
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/master'
    steps:
      - name: checkout master
        uses: actions/checkout@v2
      - name: Tweet
        uses: gr2m/twitter-together@v1.x
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
          TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
          TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }}
          TWITTER_API_SECRET_KEY: ${{ secrets.TWITTER_API_SECRET_KEY }}
```

## 3.リポジトリ作成とpush

[GitHub](https://github.com/)にログイン後、`New repository`からリポジトリを作成。

作成後、プロジェクトと紐づけてpush

```bash
git remote add origin https://github.com.....
git branch -M master
git push -u origin master
```

これでプロジェクトの設定は完了。

ちなみに、pushした段階でtwitter-togetherからPRが追加されるのでこちらもmergeしちゃいましょう。 mergeすると`tweets/`デイレクトリが作成されます。このディレクトリにツイートしたい内容のファイルを格納していきます。

![twitter-together.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/3c0b9916-07d0-b0ec-4438-012dc97c3123.png)


## 4.リポジトリの環境変数の設定

作成したGitHubのリポジトリから`Settings`→`Secrets`→`New secret`からtwitter-togetherで使う環境変数を設定してください。この時に使う値はさきほどTwitter Developerで作成していただいた、API_KEYなどです。

設定するKEY項目 ※GITHUB_TOKENは設定しなくて大丈夫です。

```
TWITTER_API_KEY
TWITTER_API_SECRET_KEY
TWITTER_ACCESS_TOKEN
TWITTER_ACCESS_TOKEN_SECRET
```

## 5.tweetファイルを追加してツイートする

リポジトリからtweetsフォルダをクリックして右上の`Add file`からtweetファイルを作成してみましょう。ローカルからだとめんどくさいので

![Create new file](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/47a346d8-8443-8d99-27c0-709e4c94bf26.png)

ファイル名はtogether-first.tweetに設定

![together-first](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/1b2a8a00-8f05-146c-0a86-6d00e949d319.png)

ファイル内容は以下の内容に設定

![スクリーンショット 2020-10-23 11.55.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/38ffb92f-ba51-325d-e013-0fa1966b7fc2.png)

下のほうにあるコミット設定はそのままで、`Commit new file`ボタンをクリック。

コミットが完了するとGitHub Actionが動き出し成功すればGreenのチェックマークになります。

![github-action](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325401/0d4ca68d-5659-5f58-5e3c-f25bbad18fcf.png)


連携してるTwitterを確認しツイート出来てればokです。

# 最後に

コミュニティのTwitterアカウントやOSSのアカウントなど持っている方は宣伝等のツイートで使ってみるといい感じになるかもしれません。

# 参考資料

[GitHub twitter-together](https://github.com/gr2m/twitter-together)
インターネットにつながらなくなって解決した記録

## インターネットにつながらなくなった
朝起きたらWi-Fiのアクセスポイントにはつながるがインターネットにはつながらなくなった。

**昨晩と今朝の間にあったこと**
PCを移動した。

**移動した人**
ネットワークに関して何かした記憶はない。

**対処療法**
いくつかあるネットワークを切り替えてみる。
Wi-Fiを切ってみる。
*->インターネットにつながるときがある。*

**どんな時につながったのか**
調べてみると

```
C:\WINDOWS\system32>ipconfig
```
 IPv4 アドレス . . . . . . . . . . . .: 192.168.1.*(255までの数値)
 サブネット マスク . . . . . . . . . .: 255.255.255.0
の時につながって、

 IPv4 アドレス . . . . . . . . . . . .: 192.168.11.*(255までの数値)
 サブネット マスク . . . . . . . . . .: 255.255.255.0
の時につながらない。

**DHCPが怪しい？**
移動した人に確認してもらったところ「ひかり電話ルーター」のほかに無線LANルータのDHCPも動いていたということでそちらを無効にしてインターネットに無事接続できるようになった。（解決）

**結局なにが原因だったのか**
PCを移動した時に無線LANルーターの電源を切ってしまって電源をいれたタイミングでDHCPがオンになってしまったようだ。（予想）
結果的にDHCPサーバが家庭内LANに２台ある状態になり割り当てられるIPアドレスがおかしくなっていたためインターネットにつながらなかった。

こちらにいい解説があったのでご参考までに。

日経クロステック（xTECH）
[2台のDHCPサーバーが同一LAN上にあったらどうなる？](https://xtech.nikkei.com/it/article/COLUMN/20060215/229396/)