OmniAICreator/Qiita-1.07M huggingface dataset:
Ionic × FCMでiOSのPUSH配信ができなかった時の解決策メモ

# この記事について
`Ionic` を用いたアプリ開発をしており、PUSH配信に `FirebaseCloudMessaging` を使用しているのですが、iOSへのPUSH配信が出来なかったのでその時の解決方法です。

## 実装時の環境
* Ionic : 3.9.4
* Cordova: 8.0.0
* cordova-plugin-firebase: 2.0.5
* Java11 (APIサーバー)
* [Firebase Admin SDK](https://firebase.google.com/docs/admin/setup)

## 現象
#### Ionic側

```
import { Firebase } from "@ionic-native/firebase/ngx";

export class Sample {
  constructor(private firebase: Firebase) {}

public sample() {
    // 通知許可の設定
    this.firebase.hasPermission().then( data => {
      console.log("data.isEnabled:" + data.isEnabled)
      if(data.isEnabled != true) {
        this.firebase.grantPermission().then( () => {
          console.log("grantPermission:")
        }).catch((error) => {
          console.log("grantPermission Error:" + JSON.stringify(error))
        })
      }
    })
}
```

上記のコードで `トークン` の取得は正常に行えてるように見えました。

#### APIサーバー側
[Firebase Admin SDK](https://firebase.google.com/docs/admin/setup) を用いて、
PUSH配信を行おうとすると、下記の例外が発生しました。

```
com.google.firebase.messaging.FirebaseMessagingException: Request contains an invalid argument.
	at com.google.firebase.messaging.FirebaseMessaging.handleSendHttpError(FirebaseMessaging.java:291)
	at com.google.firebase.messaging.FirebaseMessaging.access$600(FirebaseMessaging.java:55)
	at com.google.firebase.messaging.FirebaseMessaging$1.execute(FirebaseMessaging.java:260)
	at com.google.firebase.messaging.FirebaseMessaging$1.execute(FirebaseMessaging.java:240)
	at com.google.firebase.internal.CallableOperation.call(CallableOperation.java:36)

Caused by: com.google.api.client.http.HttpResponseException: 400 Bad Request
{
  "error": {
    "code": 400,
    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "INVALID_ARGUMENT"
      },
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.ApnsError",
        "statusCode": 400,
        "reason": "BadDeviceToken"
      },
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "message.token",
            "description": "Invalid registration token"
          }
        ]
      }
    ]
  }
}
```
## 解決策
xcodeでのビルド時に、下記の設定をする必要がありました。
`Xcode > File > Project Settings > Build System [Lagacy Build System]`

## FCMのその他の設定について
[こちら](https://qiita.com/kgsi/items/5cc4ee1d645598ba0cb6) の記事を参考にさせて頂きました。

## 最後に
結構ハマってしまったので、誰かの助けになれば幸いです・・・！

# 共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくは[Wantedly](https://www.wantedly.com/projects/134741)からお問い合わせください。
お待ちしております！
Nginxでdjango/adminの管理者ページのスタイルシートを読み込ませる方法

#現状
初期設定のままnginxでプロダクトを立ち上げ、/adminで管理者画面に行くと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302864/176cce05-b109-5f87-12e9-cdc63abe4af6.png)
このようにローカルの時とは違うスタイルで出力されてしまう。
ページの検証でコードを確認すると、stylesheetのリンクは示されていることがわかる。しかし、このurlをクリックするとnginx 404 not found エラーが出る。
つまりsytlesheetのリンクが未設定ということである。（/var/log/****/error.logからも確認できる。）

#解決策
nginxでファイルのpass指定をするのは**/etc/nginx/sites-available**というfileである。
初期設定ではこのようになっているであろう。

```terminal
cat /etc/nginx/sites-availabe
server{

    listen 80;

    server_name 54.249.69.17;

    location = /favicon.ico {access_log off; log_not_found off;}

    location /static/ {

        root /home/ubuntu/myblogapp2/myblogapp;

        }

    location / {

        include proxy_params;

        proxy_pass http://unix:/home/ubuntu/myblogapp2/myblogapp/myblogapp.sock;

        }

    }
```

ここに以下のようにadminのstylesheetのpassを指定すれば良い

```nginx:/etc/nginx/sites-available
server{

    listen 80;

    server_name 54.249.69.17;

    location = /favicon.ico {access_log off; log_not_found off;}

    location /static/ {

        root /home/ubuntu/myblogapp2/myblogapp;

        }

    location /static/admin {

        root /home/ubuntu/py36/lib/python3.6/site-packages/django/contrib/admin/static/admin;

        }

    location  / {

        include proxy_params;

        proxy_pass http://unix:/home/ubuntu/myblogapp2/myblogapp/myblogapp.sock;

        }

    }
```

これで無事/adminに行けばローカルと同じスタイルの管理者画面が開かれる。


  

Good Luck!
今年の言語はRust その２０


# 今年の言語はRust その２０


Rustを学びます


Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル(英語)
https://doc.rust-lang.org/book/



#### 実行環境

```sh
$ cargo -V
cargo 1.33.0 (f099fe94b 2019-02-12)
$ rustup -V
rustup 1.17.0 (069c88ed6 2019-03-05)
$ rustc --version
rustc 1.33.0 (2aa4c46cf 2019-02-28)

$  cat /proc/version
Linux version 4.14.97-74.72.amzn1.x86_64 (mockbuild@gobi-build-64002) (gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) #1 SMP Tue Feb 5 20:59:30 UTC 2019

$ uname -a
Linux ip-10-100-0-8 4.14.97-74.72.amzn1.x86_64 #1 SMP Tue Feb 5 20:59:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/\*release
NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
Amazon Linux AMI release 2018.03

```


## 9. エラー処理


### 9.3 panic!すべきかするまいか

__Resultを返却する__ ことは、 失敗する可能性のある関数を定義する際には、いい第一選択肢になります。

```rust
fn some_method() -> Result<String, io::Error> {    
}

fn some_method() -> String {
}


```


#### エラー処理のガイドライン

__コードが悪い状態に陥る可能性があるときにパニックさせるのは、推奨されることです__ 

>・ 悪い状態がときに起こるとは想定されないとき
>・ この時点以降、この悪い状態にないことを頼りにコードが書かれている場合
>・ 使用している型にこの情報をコード化するいい手段がないとき


悪い状態の時の選択肢

1. __panic!__ を起こす
	- 誰かが自分のコードを呼び出して筋の通らない__値を渡してきたら__  
2. __Resut__ を返す
 	- __呼び出し側__ に問題の処理方法を決定させる



### 検証のための独自の型を作る

以前のチュートリアルで、ユーザ入力(0-100)までの数値入力を託す例題があった。

例題中では1未満、100より大きい場合はユーザに再入力を託す

```rust
loop {
    // --snip--

    let guess: i32 = match guess.trim().parse() {
        Ok(num) => num,
        Err(_) => continue,
    };

    if guess < 1 || guess > 100 {
        println!("The secret number will be between 1 and 100.");
        continue;
    }

    match guess.cmp(&secret_number) {
    // --snip--
}
```


しかし、これは__理想的な解決策__ではない

> プログラムが1から100の範囲の値しか処理しないことが間違いなく、 肝要であり、この要求がある関数の数が多ければ、このようなチェックを全関数で行うことは、 面倒でパフォーマンスにも影響を及ぼす可能性があるでしょう。

代わりに、__新しい型__ を作って検証を__関数内に閉じ込め__、
検証を全箇所で繰り返すのではなく、 その型のインスタンスを生成することができます。


```rust


pub struct Guess {
    value: u32,
}


impl Guess {
    
    pub fn new(value: u32) -> Guess {
        
        if value < 1 || 100 < value {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        
        Guess {
            value
        }
    }
    
    pub fn value(&self) -> u32 {
        self.value
    }
}

```

これで、Guessを信じて、後の処理を書くことができるよね




次回はジェネリックいくよ！


イエス！
CSSでシンプルなトグルボタンを実装

# CSS でシンプルなトグルボタンを実装

:arrow_down: ON のとき
<img width="362" alt="スクリーンショット 2019-04-17 16.25.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12033/7d9b607b-e34c-97df-8029-ebe7b6bc2d0d.png">

:arrow_down: OFF のとき
<img width="360" alt="スクリーンショット 2019-04-17 16.26.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12033/5ac19e01-557f-7f02-d8a8-8d6f056fc1f1.png">

haml

```haml

.form-toggle.half-cell
  = f.check_box :name
  = f.label :name, '.', class: 'clickable'

```

scss

```scss

$form-checked-color: #fe6970;
$form-unchecked-color: #f3f3f3;

//*** Toggle button ***//

.form-toggle {
  > input[type="checkbox"] {
    display: none;
  }
  > label {
    display: inline-block;
    position: relative;
    width: 50px;
    height: 26px;
    color: transparent;
    background-color: $form-unchecked-color;
    border-radius: 15px;
    &:before {
      display: block;
      content: '';
      position: absolute;
      top: 3px;
      left: 3px;
      width: 20px;
      height: 20px;
      background-color: #fff;
      border-radius: 10px;
      transition: 0.4s;
    }
  }
  > input[type="checkbox"]:checked + label {
    background-color: $form-checked-color;
    &:before {
      left: 27px;
    }
  }
}
.clickable {
  cursor: pointer;
}
```
Power BI ウォーターフォール図のY軸に戸惑った、備忘メモ

ウォーターフォール図を使おうとして少し戸惑ったので
備忘メモとして残します。
わざわざ記事にするほどのボリュームでもないな…と迷ったけど
主に自分のためにアウトプットしておこうかと。

#ウォーターフォール図の使い方２種類
詳細 エリアを使う、使わないによって
Y軸に設定する項目が大きく変わる挙動にハマりました。

##サンプルデータ
２種類の商品(A,B)について、在庫の推移を例にします。

|日付|商品|増減数|在庫数|
|---|:---:|---:|---:|
|12/1|A|+5|5|
|12/1|B|0|0|
|12/3|A|-1|4|
|12/3|B|+3|3|
|12/4|A|0|4|
|12/4|B|+3|3|
|12/5|A|0|4|
|12/5|B|+3|3|
|12/7|A|+1|5|
|12/7|B|-2|1|

そのまま折れ線グラフにしたらこんな感じ
![折れ線.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239983/28790ebb-0bfd-a88b-da37-dc294f42a761.png)

##グラフ全体の増加･減少を表示する場合（詳細なしver）
![詳細なしver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239983/23d1d0a0-92fb-d3ab-02a0-73be7295dfc5.png)

グラフ全体の最後に1回だけ<font color="DarkCyan">合計</font>が表示されます。

###作り方
カテゴリに`日付`を
Y軸に`増減数`を設定します。
グラフ中の<font color="Green">増加</font>･<font color="Red">減少</font>は、Y軸のデータがそのまま表示されます。

##カテゴリごとに増加･減少を表示する場合（詳細ありver）
![詳細ありver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239983/af2ba190-71fe-c8b3-5d81-d3ff912b7e81.png)

カテゴリ(`日付`)ごとに<font color="Green">増加</font>･<font color="Red">減少</font>と<font color="DarkCyan">合計</font>が表示されます。

###作り方
カテゴリ に`日付`を
Y軸 に`在庫数`を
詳細 に`商品`を設定します。

グラフ中の<font color="Green">増加</font>･<font color="Red">減少</font>は、Y軸(`在庫数`)の差分で計算されます。
例えば、12/3時点で商品Aの在庫は**4個**ですが、その直前の(12/1時点の)**5個**と比較した結果、4-5=**-1**となります。

---
もし、[詳細なしver](#グラフ全体の増減値を表示する場合（詳細なしver）)のようにY軸に`増減数`を設定してしまうと、
まったく違うグラフになってしまうのでご注意を…。
![詳細ありでY軸を誤った.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239983/2d6dc8f4-ef78-a581-cb78-09271fe40fb1.png)

##あとがき
超個人的なメモ書きを最後まで見ていただき ありがとうございます。
ウォーターフォール図をこんな風に使ってるよ！という方がいらっしゃいましたら
コメント欄にお願いします。
Nginxが404notfoundエラーを出してくる時の対処

#エラーの内容
ローカルファイルをサーバーに送りnginxの設定が終わったところで立ち上げてみると以下のようなエラーが発生することがある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302864/69f326f1-8755-52f4-f535-f969888da1a2.png)

困ったことにこの原因が何なのかこのページでは表示してくれない。

#エラー内容確認の方法
サーバー側のファイルの/var/log以下に実はエラーがでた際にエラーログが出るようになっている。  

```text:/var/log/nginx/error.log.1
2019/03/19 00:53:45 [error] 15445#15445: *93 open() "/usr/share/nginx/html/.git/config" failed (2: No such file or directory)
```

何回も立ち上げようとしたので実は同じようなエラーメッセージがこの階層に大量に残されていた。 　
ここで書いてある内容を確認するとconfigのfileがないと言われているのでconfigの設定をしているfileにエラーがあることがわかる。

```nginx:/etc/nginx/sites-available/myblogapp
server{

    listen 80;

    server_name ************;

    location = /favicon.ico {access_log off; log_not_found off;}

    location = /static/ {

        root /home/ubuntu/myblogapp2/myblogapp;

        }

    location = /static/admin {

        root /home/ubuntu/py36/lib/python3.6/site-packages/django/contrib/admin/static/admin;

        }

    location = / {

        include proxy_params;

        proxy_pass http://unix:/home/ubuntu/myblogapp2/myblogapp/myblogapp.sock;

        }

    }
```
すると読み込みfileのpass指定に=を誤ってつけてしまっていることがわかる。これを修正して　　

```nginx:/etc/nginx/sites-available/myblogapp
server{

    listen 80;

    server_name ************;

    location = /favicon.ico {access_log off; log_not_found off;}

    location = /static/ {

        root /home/ubuntu/myblogapp2/myblogapp;

        }

    location /static/admin {

        root /home/ubuntu/py36/lib/python3.6/site-packages/django/contrib/admin/static/admin;

        }

    location / {

        include proxy_params;

        proxy_pass http://unix:/home/ubuntu/myblogapp2/myblogapp/myblogapp.sock;

        }

    }
```
これで保存して再び立ち上げると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302864/ad6b8f59-2d05-9eb0-42d8-b91b0e1a5989.png)

しっかり立ち上がった。

#まとめ
nginxでのエラーメッセージはルートディレクトリのなかの/var/log/対象のディレクトリの中にあるerrorlogを確認することで、修正することができる。　　


Good Luck!
Laravelで認証用APIのテストを書く

Laravel + Vue.jsを勉強している際に、APIを利用した認証でログアウトを確認するためのUnitテストで、便利なアサーションがあったので、備忘録として記録

# 前提
- Laravel5.8(5.5～)

# テストケースの作成
Laravelのドキュメントルート上で、以下コマンドを実行する

```shell
php artisan make:test AuthenticationTest
```

# テストコード

```php:tests/Feature/AuthenticationTest.php
<?php

namespace Tests\Feature;

use App\User;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class AuthenticationTest extends TestCase
{
    use RefreshDatabase;

    protected $user;

    public function setUp(): void
    {
        parent::setUp();

        // テストユーザ作成
        $this->user = factory(User::class)->create();
    }

    /**
     * ログイン認証テスト
     */
    public function testLogin(): void
    {
        // 作成したテストユーザのemailとpasswordで認証リクエスト
        $response = $this->json('POST', route('login'), [
            'email' => $this->user->email,
            'password' => 'password',
        ]);

        // 正しいレスポンスが返り、ユーザ名が取得できることを確認
        $response
            ->assertStatus(200)
            ->assertJson(['name' => $this->user->name]);

        // 指定したユーザーが認証されていることを確認
        $this->assertAuthenticatedAs($this->user);
    }

    /**
     * ログアウトテスト
     */
    public function testLogout(): void
    {
        // actingAsヘルパで現在認証済みのユーザーを指定する
        $response = $this->actingAs($this->user);

        // ログアウトページへリクエストを送信
        $response->json('POST', route('logout'));

        // ログアウト後のレスポンスで、HTTPステータスコードが正常であることを確認
        $response->assertStatus(200);

        // ユーザーが認証されていないことを確認
        $this->assertGuest();
    }
}

```

注目すべきは、ヘルパメソッドの使い勝手の良さ。

`actingAs()`は、現在認証済みのユーザーを容易に設定することができる。
`assertGuest()`は、認証状態でないことを簡単に確認することができる。

## 参考サイト
- [Vue + Vue Router + Vuex + Laravelで写真共有アプリを作ろう (4) 認証API | Hypertext Candy](https://www.hypertextcandy.com/vue-laravel-tutorial-authentication/)
- [Vue + Vue Router + Vuex + Laravel チュートリアル（全16回）を書きました。 - Qiita](https://qiita.com/MasahiroHarada/items/2597bd6973a45f92e1e8)
- [HTTPテスト 5.8 Laravel](https://readouble.com/laravel/5.8/ja/http-tests.html)
sshポートフォワーディングについて図示してみる

使いたいときにいつも混乱するので、ここにまとめておく。
図の左側はインターネットに接続できるクライアント環境（Windowsパソコンなど）、右側はインターネット接続のないサーバセグメントを想定している。

# 共通オプション
* -f: バックグラウンドで動作
* -N: リモートでコマンドを実行しない
* -g: ポートフォワードで作ったトンネルを他の端末が使うことを許可する（本記事では利用していません）

# ローカルポートフォワード
## 用途
* sshクライアント端末から、sshサーバ側ネットワークにある特定サーバ特定ポートにアクセスしたい

## コマンド
```sh
hostA$ ssh -fN -L 8080:hostD:80 userC@hostC
```
![ssh-L.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13722/ff3b64be-50a6-8782-9df2-671301b10c5d.png)

# リモートポートフォワード
## 用途
* sshサーバ端末から、sshクライアント側ネットワークにある特定サーバ特定ポートにアクセスさせたい

## コマンド 
```sh
hostA$ ssh -fN -R 8080:hostB:80 userC@hostC
```

![ssh-R.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13722/1d51e871-054d-df6a-0083-6438e58d5f81.png)

# ダイナミックポートフォワード
## 用途
* sshクライアント端末から、sshサーバ側ネットワークにある、あらゆるサーバにアクセスしたい

## コマンド
```sh
hostA$ ssh -fN -D 1080 userC@hostC

# hostAのブラウザにlocalhost:1080をSOCKSプロキシとする設定を投入する
```
![ssh-D.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13722/01fd0d0a-2aff-6769-239a-c73a7db73b67.png)

# リバースダイナミックポートフォワード
## 用途
* sshサーバ端末から、sshクライアント側ネットワークにある、あらゆるサーバにアクセスさせたい（特にインターネット）

## コマンド(パターン1)
```sh
hostA$ ssh -fN -D 1081 userA@localhost  # hostAの中にSOCKSプロキシを準備
hostA$ ssh -fN -R 1080:localhost:1081 userC@hostC

# hostCのブラウザにlocalhost:1080をSOCKSプロキシとする設定を投入する
```
![ssh-RD1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13722/1c756e9c-4211-e8fc-5fa6-6a2de4617f22.png)

## コマンド(パターン2)
```sh
hostA$ ssh -fN -R 2022:localhost:22 userC@hostC
hostC$ ssh -fN -D 1080 -p 2022 userA@localhost   # hostCでの実行に注意
```

![ssh-RD2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13722/93266555-3cdb-2da5-c9fe-fad6ed0e91ec.png)

# 番外編

## SOCKSプロキシの設定ができないツールでもSOCKSを使いたい

ダイナミックポートフォワードやリバースダイナミックポートフォワードを利用する際、
ブラウザであればSOCKSプロキシ設定が簡単に可能だが、apt,yumコマンド、自作ツールなどでの対応は難しかったりする。

しかし、[proxychains](http://proxychains.sourceforge.net/) を使うことで、通信を横取りしてSOCKSプロキシを通すことができる。（LD_PRELOADを使い、通信関連APIを上書きしているようだ）

```config:$(HOME)/.proxychains/proxychains.conf
[ProxyList]
# SSH reverse proxy
socks5  127.0.0.1 1080
```

```sh
hostC$ proxychains telnet google.com 80
hostC# proxychains yum update
hostC# proxychains apt-get update
```
（個人用）Djangoチュートリアルその２：django.shortcuts

###1. render(request, テンプレート, コンテキスト)</h3>

```python:polls/views.py
from django.http import HttpResponse
from django.template import loader

def index(request):
    (中略)
    template = loader.get_template('polls/index.html')
    return HttpResponse(template.render(context, request))
```

django.http.HttpResponse, django.template.loaderの代わりに、
django.shortcuts.renderを利用することでコンパクトに記述可能。


```python:polls/views.py
from django.shortcuts import render
# ...
def index(request):
    (中略)
    return render(request, 'polls/index.html', context)
```
###2. get_object_or_404(オブジェクト, pk)

```python:polls/views.py
from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})
```

django.http.Http404の代わりに、django.shortcuts.get_object_or_404をインポート。
try~except文を用いた分岐を用いなくても良いので、よりコンパクトな記述が可能となる。


```python:polls/views.py
from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})
```
ちなみに、
`get_list_or_404()`
という関数もあるそうです。
この関数は 
`get_object_or_404()`
と同じように動きますが、
get() ではなく、 filter() を使います。
Excelの全角数値を半角数値に変換する

##経緯

前職SIerの自称・技術力高い上司(50代)が、顧客から「全角数値を半角数値に変換できないか？」という要望に対して、「技術的に難しい」と回答したらしい。

自称・技術力高い上司が***「全角から半角に変換できない」***というからには、おそらく難しいのだろうと思ったのであるが、(不慣れな)Go言語を用いて対応可能かを検証してみた。


## やること
同じフォルダにエクセル(.xlsxのみ)を保存して実行すると、copy_***.xlsxというファイルが作成され、全角数値だった箇所のみが半角数値に変換される

##ソース

```go:main.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"regexp"
	"strings"
	"time"

	"github.com/tealeg/xlsx"
)

func main() {
	dt1 := time.Now()

	var files []string
	files = GetFiles() // カレントディレクトリのエクセルを取得
	for _, file := range files {
		fmt.Println("ファイル名", file)

		copyfile := "copy_" + file
		err := os.Link(file, copyfile) // ファイルのコピー
		if err != nil {
			fmt.Printf(err.Error())
		}
		excel, err1 := xlsx.OpenFile(copyfile) // コピーしたファイルを開く

		if err1 != nil {
			fmt.Printf(err1.Error())
		}

		for _, sheet := range excel.Sheets {
			fmt.Println("シート名", sheet.Name)
			for _, row := range sheet.Rows {
				for _, cell := range row.Cells {
					v := cell.String()
					val := ZenkakuToHnakaku(v)
					// 変換不要なセルもあるが、とりあえず全て書き換え
					// fmt.Println(val)
					cell.Value = val
					//cell.Value = fmt.Sprintf(val)
				}
			}
		}

		// ファイルを保存
		err = excel.Save(copyfile)
		if err != nil {
			fmt.Printf(err.Error())
		}

	}

	dt2 := time.Now()
	fmt.Println(dt2.Sub(dt1)) //Excelファイル変換時間

}

func GetFiles() []string {
	dir, _ := os.Getwd() //カレントディレクトリ
	//dir := "/home/.../" //フォルダを直接指定する場合
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		panic(err)
	}

	var paths []string
	for _, file := range files {
		if !file.IsDir() && path.Ext(file.Name()) == ".xlsx" &&
			!regexp.MustCompile(`^~$*`).Match([]byte(file.Name())) {
			paths = append(paths, file.Name())
		}
	}
	return paths
}

func ZenkakuToHnakaku(str string) string {
	// Replacerを使って置換する
	r := strings.NewReplacer("０", "0", "１", "1", "２", "2", "３", "3", "４", "4", "５", "5", "６", "6", "７", "7", "８", "8", "９", "9")
	resStr := r.Replace(str)
	return resStr
}
```
##結論
簡単にできた。
C# PDF to Word

PDFファイルはますます多くの人に使われています。しかし、PDFファイルのテキストとフォーマットの編集は難しいです。MS Wordはこれまで最も人気のあるワープロです。したがって、簡単に編集できるように、PDFファイルをワード形式に変換します。

Spire.PDFソフトウェアは開発者にC#プログラミングの方式を提供しており、NETプラットフォームでPDFファイルをwordに変換する機能を提供しています。この文章では、Spire.PDFを使ってPDF to word変換機能を実現する方法を紹介します。

すべてのコード:

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Spire.Pdf;

namespace PDF
{
    class Program
    {
        static void Main(string[] args)
        {
            // PDFをロード
            PdfDocument pdf = new PdfDocument();
            pdf.LoadFromFile("Sample.pdf");
            //Pdf to Word
            pdf.SaveToFile("Pdftoword.docx", FileFormat.DOCX);      
         }
    }
}
```
元PDFファイルのスクリーンショット：
![SamplePDF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/b1f6a0a8-82ea-8f5d-fe59-9ab0242568a3.png)

ワードドキュメントに変換した後の効果スクリーンショット：
![PdftoWord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/4548f2ae-7f79-f220-d28a-f75e0a0ec02d.png)
EC２　Hello World!!　の表示



$ sudo vi /var/www/html/index.html

でindex.htmlを作成する。

vimの画面で、

```
<html>
<head>
<meta charset="utf-8">
<title>AQ</title>
</head>
<body>
Hello World!!
</body>
</html>

```

を入力。

http://★自分のIPv4 パブリック IP★/　にアクセス。


Hello World!!　

が表示される。


http://★自分のIPv4 パブリック IP★/
[jekyll × Github Pages - Tips]  本番環境にだけ出力したいタグを設定する方法


# jekyll × Github Pages を使う時のTips

jekyll を使って、ポートフォリオを作成し、
GitHub Pages上で公開した時の備忘録です

## 本番環境にだけ出力したいタグを設定する方法

GoogleAnalyticvsなどのような、開発時には読み込みたくないタグの記載方法です

### HTMLへの記載方法

```
  {% if jekyll.environment == "production" %}
  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-00000000-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag() { dataLayer.push(arguments); }
    gtag('js', new Date());

    gtag('config', 'UA-00000000-1');
  </script>
  {% endif %}
```

### 本番環境に反映するコマンド／手順

```
$ JEKYLL_ENV=production bundle exec jekyll build
```

- 上記コマンドを実行することで、GoogleAnalyticsタグが出力されますので、出力確認を行う
- git commit & git push を実行する
- GitHubPagesを確認する


## ローカル環境で動作確認するコマンド

```
$ bundle exec jekyll serve
```

- 上記コマンドを実行した場合は、GoogleAnalyticsタグが出力されません。
HTML超初心者~HTMLを知ろう~

# HTMLについて

HTML ( エイチティーエムエル)とは、
ページを構成するための「マークアップ言語」です。

簡単にいうと、HPの文章に意味や役割を持たせる言語です。

段落や見出しなどを明確に分けて、文書の意味を正確に分類、整理して記述します。

今見ているこのホームページもHTMLで書かれています。



## HTMLの歴史

HTMLはインターネットを使い世界中の論文をどこでも閲覧することはできないか？という目的で作成されました。

1983年にティム・バーナーズ=リーを中心にバージョン1.0が誕生。

バージョンアップを重ね、機能が追加され、デザインに関する記述までHTMLで行ってきました。



##CSSの誕生

構造からデザインまで書いてしまうとHTMLが長くなり複雑になります。

そのためデザイン部分まで抜き出した[CSS(シーエスエス)](https://qiita.com/Sayaka38/items/c08309e63aa696ae7728)が誕生しました。

文書の構造はHTMLでページの見栄えはCSSの役割が明確に分けられたのです。

##HTMLの記述方法

HTMLは文書が書ける`ソフト`と`ブラウザ`があれば作れます。

Windowsは「メモ帳」 Macでは「テキストエディト」というソフトが入っています。

##  おすすめのテキストエディタ
共通している機能は「コードヒント」と呼ばれる関連する情報が表示されることです。
間違った記述があれば指摘もしてくれる機能でミスが気づきやすくなります。
web開発に特化した自分の使いやすいエディタを利用しましょう。

>[Atom](https://atom.io)
>

> [Sublime Text](https://www.sublimetext.com)

> [Mi(Macのみ)](https://www.mimikaki.net)
>

> [TraPad(Windowsのみ)](https://forest.watch.impress.co.jp)


## ブラウザ

ブラウザとはHPを見るためのソフトです。

Windowsは「internet Explorer」というブラウザが入っていますし Macでは「Safari」というブラウザが入っています。これだけでも十分ですが、他によく使われているブラウザをご紹介します。

>[Google Chrome](https://www.google.co.jp)
>


> [Firefox](https://www.mozilla.org)
>
>

# index.htmlの作成



###1. 各OS標準のテキストエディタを起動する

まずはテキストエディタを開きましょう。

###2. コードの入力

ひらがな以外のタグは必ず半角半英数字で入力します。

###3. ファイルの保存

記述ができたら名前をつけて保存します。

その際、ファイル名の末尾に「.html」をつけます。

> 例：index.html

###4.  ファイルの表示

デスクトップに保存したファイルをWクリックすると勝手にファイルが開きます。

画面に何も表示されていない時は、どこかが間違っているので、もう一度確認をしましょう。

### 5. ファイルの編集

ファイルを編集するときはWクリックではなく、テキストエディタの画面のなかにファイルをドラック＆ドロップすればひらけます。

### 6.HTMLの解説

HTMLでは基本的にタグと呼ばれる文字列で何かを挟みます。

>  <◯◯>   〜　</◯◯>

先頭の<◯◯>は開始タグ

末尾の</◯◯>は終了タグといい「/」スラッシュがつきます。（例外もあります）

##   html タグ

HTMLファイルでは必ず最初と最後を<html></html>で囲みます。

これは<html>から</html>までの間がHTML文であることを宣言しています。

htmlタグの内部にはheadタグとbodyタグを入れます。

##   head タグ

ページ上に表示されない情報（タイトルや文字コードなど）を入力するタグ。body タグの前に挿入しましょう。

##   body タグ

画面に表示する文章などの本文部分を入力するタグ。

headタグのあとに挿入しましょう。

## title タグ

ページタイトルを入力するタグ。このタグ内入力した内容がブラウザーの

タイトルバーに表示されます。

##   h1 タグ

見出し入力をするタグ。h1~h6まで6段階のタグがあります。数字が小さいほどじ重要度があり大見出しになります。h1を大見出し、h2を中見出し、h3を小見出しと、段階的に使用します。

##  p タグ

"paragraph"の略で「段落」を意味するタグ。改行するための使いかたではないので注意しましょう。
Pythonでフィボナッチ数列をワンライナー

# はじめに
今回はネタでフィボナッチ数列をワンライナーしてみたのでそのコードの軽い解説的な感じです。
ワンライナーってロマンありますよね。
そんな毒にも薬にもならない記事になっております。

## コード

```fibo.py
[(lambda n:functools.reduce(lambda x,y:(x[0]+x[1],x[0]),[(1,1)]*(n-2))[0])(int(input())) for functools in [__import__('functools')]]
```

# 解説
特に難しいことはなくて、見たままのコードですが順番に

```python
[lambda n:functools.reduce("残りの処理")(int(input())) for functools in [__import__('functools')]]
```

この部分ではlambda式の引数nにinputを代入しています。右側のimportでfunctoolsライブラリを入れています。
reduce関数は畳み込み演算を行う関数です。
list内包表記でimportするやり方は普通に書く時には使わないようにしましょう。

```python
[(lambda x, y:(x[0] + x[1]. x[0]*(n-2)[0]), [(1, 1)*(n-2)[0]])]
```

これが実際の畳み込み演算の中身です。
最初の引数nまで順番に足し合わせます。

# まとめ
最近、Pythonって内包表記とか三項演算子で結構ワンライナーしやすくて面白いなと思います。
皆さんも複雑な数列をワンライナーしてみてはいかがでしょうか。
（個人用）Djangoチュートリアルその１

初投稿＆個人用記事なのでショボいです…
Markdownなどの確認も兼ねて記事を作成しています。

```html:polls/template/polls/detail.html
{{ text }}
```

```python:polls/views.py
from django.shortcuts import render

def detail(request):
    test_text = "abc"
    render(request, "polls/index.html", {"text": test_text})
```
長押しボタンを作ってみた【マルチブラウザ対応】

#　はじめに
前回作成した記事の続きです。
[長押しボタンを作ってみた【円プログレス対応】](https://qiita.com/ta__ho/items/d726e2fc0355eb7f6c1d)

# 今回やりたいこと

前回、 `conic-gradient` を使って長押しの進捗を表現したのですが、この関数がChrome以外のブラウザだと、利用できないため、それをなんとかします。

# 調べる

`conic-gradient` をググると以下の記事がでてきます。
[CSS4のconic-gradientを先取りする方法](https://qiita.com/cawpea/items/f70fa08559a664762697)

こちらの記事を読んでみるとpolyfillが存在するらしいので、まずはそれを使ってみます。
[CSS conic-gradient() polyfill](https://leaverou.github.io/conic-gradient/)

### polyfillの導入

導入方法は、 polyfill用のjsを読み込ませるだけです。

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="conic-gradient.js"></script>
```

[conic-gradient.js](https://leaverou.github.io/conic-gradient/conic-gradient.js)は、こちらに落ちているので、落として、読み込ませれば大丈夫です。

### Edgeで動かない

ブラウザのコンソールに、以下エラーがでます。

```
SCRIPT1014: SCRIPT1014: Invalid character
```

`conic-gradient.js`内で使われている`π`とか`τ`とかが、Edgeだとダメみたいです。
なので、`π`を`pai`、`τ`を`tau`、`ε`を`epsilon`に書き換えました。

これで動きました。

で、css部分を確認してみると、
`background-image`としてjs内で動的に作成したsvgを設定しているみたいです。

### svgデータの準備

polyfillの処理でcssに設定されている`conic-gradient`を`background-image`に変換しているぽいのですが、
これを連続でリアルタイムに変換する方法がわからないので、あらかじめ、svgのデータを準備して、それをレンダリングする方法を考えました。

また、そのために必要なsvgデータを準備しました。

[svg.js](https://github.com/takuhou/smart-ui/blob/feature/apply-multi-browser/svg.js)

20個のsvgデータ保持しているjsです。色は黒のみ。`window.SMART_UI`というグローバル変数に格納してあります。

### レンダリング処理

```index.js
・・・
if (ua.indexOf('firefox') > 0 || ua.indexOf('edge') > 0 || ua.indexOf('trident') > 0) {
  var svg = 'url("' + SMART_UI.black[0] + '")';
  outerCircle.style.backgroundImage = svg;
} else {
  outerCircle.style.background = 'conic-gradient(black 0deg,white 0deg 360deg)';
}
・・・
progress = progress + (360 / (LIMIT / 100));
var outerCircle = document.getElementById('outer-circle');
if (ua.indexOf('firefox') > 0 || ua.indexOf('edge') > 0 || ua.indexOf('trident') > 0) {
  var svg = 'url("' + SMART_UI.black[progress/18] + '")';
  outerCircle.style.backgroundImage = svg;
} else {
  outerCircle.style.background = 'conic-gradient(red ' + progress + 'deg, white 0deg 360deg)';
} 
・・・
```

こんな感じで`background-image`に動的にsvgを設定するようにしました。

# 完成

https://www.youtube.com/watch?v=gqiTLU8EBUE&t=2538

若干チラチラしますが、一応動きました。

ソースコードは、以下にあります。
https://github.com/takuhou/smart-ui/blob/feature/apply-multi-browser/index.html

今後の対応として、ライブラリ化します。

今回の記事で書いたプログラミングの様子をYoutube上にアップロードしておりますので、是非ご覧ください。
[【実況】長押しボタンをプログラミング【ブラウザ対応その１】](https://www.youtube.com/watch?v=tDown1mDcms)
[【実況】長押しボタンをプログラミング【ブラウザ対応その２】](https://www.youtube.com/watch?v=gqiTLU8EBUE)
[えんじにぁ〜TV](https://www.youtube.com/channel/UCYCbtkuInmgpK0Hv3W2orEg)
IPアドレスからPCのホスト名(NetBIOS名)を見つけたい(Win/Mac)

# はじめに

Windowsユーザの場合、IPアドレスから同じLAN内のPCの名前(NetBIOS名)を取得することができました、ではMacOSやLinuxから同じことはできないのでしょうか。
というのが発端です

# 比較してみよう

- WindowsでIPからホスト名(NetBIOS名)を引く場合

```
nbtstat -A "IPアドレス"
```

例 : `Desktop-Main001` というPCが見つかりました

```
>nbtstat -A 192.168.1.15

ローカル エリア接続:
ノード IP アドレス: [127.0.0.1] スコープ ID: []

           NetBIOS リモート コンピューター ネーム テーブル

       名前               種類         状態
    ---------------------------------------------
    Desktop-Main001      <00>  一意        登録済
    MAC アドレス = 00-00-00-00-00-00
```

- MacOSX/LinuxでIPからホスト名(NetBIOS名)を引く場合

実はSambaUtilsで調べることができます

```
smbutil -v status -ae "IPアドレス"
```

例 : `Desktop-Main001` というPCが見つかりました

```
$ smbutil -v status -ae 192.168.1.15
Using IP address of 192.168.1.15: 192.168.1.15
NetBIOS Name                     Number  Type    Description
Desktop-Main001        　　　     0x00    UNIQUE  [Workstation Service]
```

#最後に

これで、特定のIPを使ってる機材の名前がわからなくなった時に調べることができますね
参考までに
mac で pyenv を使おうとしたら悲しいことになった話。

pip を使いたくなったんだけれども、Mac (Mojave) に標準で入っている python さんは pip ないのですよね。
環境どうしようかな。標準の python を汚したくないので homebrew から入れることにしました。

```
$ brew install pyenv
-- 略 --
$ pyenv --version
pyenv 1.2.11
$ pyenv versions
* system (set by /Users/ninjaninja/.pyenv/version)
```

インストールが終わったようなので、 https://github.com/pyenv/pyenv#homebrew-on-macos ここにあるとおり、Basic GitHub Checkout の#3以降の手順を盲目的に進める。何も考えていない。

```
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
$ cat ~/.bash_profile
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

おっけいっぽ

```
$ exec "$SHELL"
```

$SHELLなんて定義はなかったんで、sourceする

```
$ source ~/.bash_profile
```

では python をインストールしよう（・｀ω・´）

```
$ pyenv install 3.7.3
python-build: use openssl from homebrew
python-build: use readline from homebrew
Downloading Python-3.7.3.tar.xz...
-> https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
Installing Python-3.7.3...
python-build: use readline from homebrew

BUILD FAILED (OS X 10.14.4 using python-build 20180424)

Inspect or clean up the working tree at /var/folders/qn/21yqw2396zl26pmq6tq0sw9c0000gn/T/python-build.20190416181805.8376
Results logged to /var/folders/qn/21yqw2396zl26pmq6tq0sw9c0000gn/T/python-build.20190416181805.8376.log

Last 10 log lines:
Python/pytime.c:1092:9: warning: this function declaration is not a prototype [-Wstrict-prototypes]
Python/pytime.c:1092:26: warning: comparison between pointer and integer ('int' and 'void *')
    if (gmtime_r(&t, tm) == NULL) {
        ~~~~~~~~~~~~~~~~ ^  ~~~~
10 warnings and 8 errors generated.
make: *** [Python/pytime.o] Error 1
make: *** Waiting for unfinished jobs....
2 warnings generated.
2 warnings generated.
2 warnings generated.
```

何か失敗したようだ。ログをみるとー

```
Python/pytime.c:695:11: error: implicit declaration of function 'clock_gettime' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    err = clock_gettime(CLOCK_REALTIME, &ts);
```

他にもあるけれども、これっぽ。
C99ではこの呼出し方は許さぬ。と、いう感じかなあ。

そういうわけで世界のみんなに聞いてみたところ、Macのライブラリに clock_gettime なんてものはないとのことでした:(；ﾞﾟ'ωﾟ'）:
そしてたくさんの人が困っておりました。
シンプルな回答はこれ。
https://stackoverflow.com/questions/47506176/error-while-trying-to-run-make-command-on-darknet-yolo-library-on-a-mac

別の方法を実装してコンパイル通せとのこと。他を探すとたくさん実装例がでてくるので書き換えちゃえばいいんだろうけれども、 homebrew 使って管理したいなって思っているので、考えるのをやめました。

なんの参考にもならない記事になってしまった。
venv でも使おう(´・ω・｀)
【BluePrism】Excelシートにセル着色する

##概要
Excelシートのセルを着色するVBOがなかったので自作しました。（あったらすみませんｗ）

##方法
Format Cellをコピー元として「セル着色」ページを作ります。
以下、手順は画像の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/a2eba4cc-4fd9-cc49-cb99-22d53a10aa8d.png)

入力パラメータ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/fc2c6a83-184f-6988-a822-e6ada93b897f.png)

###変数
変数Red_Value, Green_Value, Blue_Valueは**Number型**の変数とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/7ff91602-e08e-abd9-ab4f-7c3f3ca71bf1.png)


ソースコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/bd05956d-818a-6474-b728-d45f83a4bd05.png)

```vb
GetWorkbook(handle,Nothing).ActiveSheet.Range(cellref,cellref).Interior.Color = RGB(Red_Value, Green_Value, Blue_Value)
```

##使い方
アクションステージにて、

- **ビジネスオブジェクト：MS Excel VBO - extend**（←自作した拡張用VBO）
- **アクション：セル着色**

入力パラメータにセル位置とRGBを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/a5bd962d-6ce8-8d82-abec-b1c1cbf62684.png)
UiPathで「ExcelとWebアプリの自動処理」するタスクを作ってみた

#概要
本件はRPAツール"UiPath"で自動処理を作成し、タスクスケジューラで実行できるようにやってみた記事です。

UiPathの概要とインストールは下記を参考に実施しました。
https://dekiru.net/article/17131/

今回は無料で使用できるCommunityエディションを使用しています。

#やってみたこと
コチラから「できるUiPath」のPDFをダウンロードして、「ExcelとWebアプリの自動処理」を実施しました。
https://www.uipath.com/ja/notice/dekiru

チュートリアルで使用するExcelデータやデモサイトも上記サイトで入手可能です。

#苦労したこと
Webアプリにエクセルデータを書き込むまでは良かったのですが、Webアプリから返される値をエクセルに書き込む際にエラーが発生ました。
何が問題かわからなかった為、デバッグのやり方から学習しました。
幸い、VisualBasicにそっくりな操作であったのですぐに慣れることができました。
あとで調べたら、UiPath社はルーマニア発のスタートアップですが、CEOのDaniel Dinesが元Microsoftの人だとか。

UiPathではじめるRPA入門（４）〜 デバッグ編
https://tutorial.co.jp/rpa/2017/11/uipath-debug/

今回はカウンタ変数を設置した際にスコープ範囲が誤っていた為、Excelに書き込む際に存在しない行を指定していたという不具合を発見できました。

#パブリッシュ
exeにしたいと思い、方法を調べたところ、パブリッシュすれば良いことが判明。

![2019-04-17_15h06_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/f23ee066-a5c3-56df-d6c7-142682eef2f2.png)

パブリッシュしたパッケージをUiRobot.exeに引数として渡してやるだけなので、下記のバッチファイルを作成しました。

![2019-04-17_15h16_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/bf883441-bc3d-9a84-881c-f179b1fec640.png)
雑なネーミングのバッチファイル

↓↓中身↓↓
C:\Users\userName\AppData\Local\UiPath\app-xx.x.xxxx\UiRobot.exe -file:“C:\UiPath\helloworld\Main.xaml”
※各種パスやuserNameとapp-xx.x.xxxxの箇所は各自の環境に合わせて書き換えて下さい。

#実行
タスクスケジューラに登録し、いざ実行！！
すんなり実行できました。
今回はこれで良しとします。

#今後やりたいこと
今回はあくまでローカル実行のみでしたので、実行環境に左右されるような面倒なことは何もしていません。また、デバッグで紹介した記事の中に例外処理の方法が記載されているので、例外処理は今後試してみたいと思います。
タスクスケジューラで実行できることまで確認できたので、業務を自動化する目処が立ちました。
Webスクレイピングやメール送信処理のガイドもある為、やってみたらまた記事を作成します。
goumlでgoプロジェクトのUML図を出力する


goプロジェクトの依存をグラフとして可視化できるツールとして [kisielk/godepgraph](https://github.com/kisielk/godepgraph) や [paulbuis/golistdepgraph](https://github.com/paulbuis/golistdepgraph) がありますが、その粒度は少し荒いものでした。（パッケージ間の依存を解析）

そこに颯爽と登場したのが [kazukousen/gouml](https://github.com/kazukousen/gouml) です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Goのコードを静的解析してDDDパターンライクなPlantUMLを生成するツールを作り始めました。<br>ぽつぽつ開発していきたいと思います<a href="https://t.co/eyydVrOCoV">https://t.co/eyydVrOCoV</a></p>&mdash; にったマン (@one_meets_seven) <a href="https://twitter.com/one_meets_seven/status/1116241515800432642?ref_src=twsrc%5Etfw">2019年4月11日</a></blockquote>

goプロジェクトを解析してumlファイルを出力してくれる素晴らしいツールで、実際に出力してみた図はこのような感じになります。UMLですね〜

![sqGdbHwwgeOaDUR1555466459_1555466479.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47014/675229e8-9007-b75b-2dff-70a0afd101c5.png)



以下でコマンドの実行し、画像として保存するところまでを紹介していきます。

## インストール

```bash
go get -u github.com/kazukousen/gouml/cmd/gouml
```

## goumlを実行しumlファイルを出力する

```bash
gouml init
```

対象のディレクトリを指定する場合は `-d` or `--dir` を指定します。

```bash
gouml init -d ./src/
```

出力するumlファイル名を指定する場合は `-o` or `--out` を指定します。

```bash
gouml init -o xxxx
```

## umlファイルを画像ファイルに変換する

いくつか方法がありますが、goumlは標準で`http://plantuml.com/plantuml/svg/`からはじまる、図を表示するためのリンクを出力してくれます。これを開くのが最も簡単な方法です。

<img width="925" alt="スクリーンショット 2019-05-08 14.59.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47014/c1259989-af14-aabc-d086-529c87b0e3aa.png">

あるいはローカルのplantumlコマンドを使うこともできます。

```bash
brew install plantuml
brew install graphviz
brew install gnu-sed
```

```bash
cat xxxx.uml | gsed  '1i @startuml' | gsed '$a @enduml' > xxxx.pu
plantuml -tpng xxxx.pu
```

ここで`xxxx.png`という画像が生成されているはずです。ご確認ください。


## 注1: 出力されるpngファイルについて、デフォルトでは縦横ともに4096に制限されています。
画像にuml図の全体が収まっていないときは以下の環境変数のことを思い出してください。

```bash
echo 'export PLANTUML_LIMIT_SIZE=32768' >> ~/.bash_profile
```


 注2: 現状では特定の条件下でグラフがちょっと悲しい感じになることがあります。

ものすごい勢いで開発されており、以下の問題も爆速で解消されました。


僕が遭遇したのは、string型のグローバル変数が宣言されている場合で、[これに対処するパッチを一応投げて置きました](https://github.com/kazukousen/gouml/pull/21)
<img width="882" alt="スクリーンショット 2019-04-17 12.54.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47014/d3540240-cacc-97c0-d07c-dd67ba6e4b6e.png">
EnterPrise ArchitectのWindows/macOS/Linux対応

ISO/IEC 20741対応の確認の仕方を整理中。

EnterPrise Architectというソフトウェアを題材に整理

Windows版のソフトウェアであるEnterPrise Architectが、macOS, Linux OSのWidnowsシミュレータ上で動作するようになったらしい。確認作業中。

# ハードウェア要件
https://www.sparxsystems.jp/products/EA/ea_sysreq.htm

Intel 32bit CPU(64bit CPU可）
> Core i5か、同等以上の性能を持つCPUを推奨

> 64ビット版Windows環境ではWOW64上で動作

メモリ：12GByteで利用している。2GByteでの動作は未確認。
>2GByte以上のRAM

バス：未確認
OSが対応するバス

周辺装置：
必要ディスク容量：確認中
>900MB程度のハードディスクの利用可能領域

入力装置：OSが対応したキーボード、マウス類

画面：OSが対応した画面の大きさ
>1280x768以上の解像度のディスプレイ

# ソフトウェア要件
>Hyper-V・VMWareの各仮想環境でのご利用も製品サポートの対象に含まれます。

## Windows
>Windows Server 2008 (R2含む), Windows 7, Windows Server 2012 (R2含む), Windows 8.1, Windows 10

https://www.sparxsystems.jp/help/14.0/installea.html

DB
>コーポレート版でモデルの情報をDBMSリポジトリに格納する場合には、DBMSの設定も必要です。対応するDBMSは、SQL Server・MySQL・ PostgreSQL・ Access 2007・ Sybase Adaptive Server Anywhere・ Oracle 9i, 10g, 11g, 12cなど

通信：
ライセンス確認の際にインタネット接続が必要
https://www.sparxsystems.jp/products/EA/ea_documents.htm

###文字コード
文字コードの確認には、Windows利用者の利用方法から、次の方法を検討する。

!. MS ExcelのCSVファイルで、文字コードを３種類以上用意できれば、どの場合が大丈夫か確認する

2. MS Wordで作成したCSVファイルで、文字コードを３種類以上用意できれば、どの場合が大丈夫か確認する

3. 文字編集ソフト(text editor)で、文字コード３種類以上のCSVファイルを作成し、どの場合が大丈夫か確認する

4. 上記ソフトウェアから文字等のコピペが可能か実行する。
5. 

## macOS
>MacOS 10.8以降, Wine 1.9以降 (3.0以降を推奨), XQuartz 2.7.7以降 (Wineの動作に必要)
MacOSにEnterprise Architectをインストールする
https://www.sparxsystems.jp/help/14.0/enterprise_architect_macos.html

https://www.winehq.org

homebrew

```shell-session
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
```

## Linux
>カーネル 2.4以降 (Ubuntu 16以降を推奨), Wine 1.9以降 (3.0以降を推奨)

 LinuxにEnterprise Architectをインストールする 
https://www.sparxsystems.jp/help/14.0/enterprise_architect_linux.html
# 遠隔・多人数操作
docker対応:未確認

## 多人数
複数人数による設計開発での利用法 マニュアル
https://www.sparxsystems.jp/bin/docs/EA_Deployment.pdf

>FEAP ファイルを利用して複数人数で設計する場合には、バージョン管理機能との併用が必須になります。

>DBMS リポジトリ はコーポレート版以上で利用できます。
# 文書履歴(document history)
ver. 0.01 初稿
ver. 0.02 標題追記 20210509
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
iOS標準のCLGeocoderを使って郵便番号から住所を取得する

##郵便番号から住所を取得する
CLGeocoderには標準で

```swift

func geocodeAddressString(_ addressString: String, completionHandler: @escaping CLGeocodeCompletionHandler)
```

こちらの郵便番号から住所を取得するメソッドがあるのですが、これで取得するとCLPlacemarkの`subLocality`が取得できませんでした。
そのため、一度このメソッドを使って取得した住所の緯度経度を使ってCLLocationを作り

```swift
func reverseGeocodeLocation(_ location: CLLocation, completionHandler: @escaping CLGeocodeCompletionHandler)
```
こちらのCLLocationから住所を取得するメソッドを使うことで`subLocality`が取得することができます。

扱いやすいようにCLGeocoderにextensionで上記の方法で郵便番号から住所を取得するメソッドを追加すると良いかと思います。

```swift
extension CLGeocoder {

    struct Address {
        var administrativeArea: String? // 都道府県 例) 東京都
        var locality: String? // 市区町村 例) 墨田区
        var subLocality: String? // 地名 例) 押上
    }

    func convertAddress(from postalCode: String, completion: @escaping (Address?, Error?) -> Void) {
        CLGeocoder().geocodeAddressString(postalCode) { (placemarks, error) in
            if let error = error {
                completion(nil, error)
                return
            }
            if let placemark = placemarks?.first {
                let location = CLLocation(
                    latitude: (placemark.location?.coordinate.latitude)!,
                    longitude: (placemark.location?.coordinate.longitude)!
                )
                 CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
                    guard let placemark = placemarks?.first, error == nil else {
                        completion(nil, error)
                        return
                    }
                    var address: Address = Address()
                    address.administrativeArea = placemark.administrativeArea
                    address.locality = placemark.locality
                    address.subLocality = placemark.subLocality
                    completion(address, nil)
                }
            }
        }
    }
}
```



```swift
// 郵便番号はハイフンなしでも取得可能です
CLGeocoder().convertAddress(from: "131-0045") { (address, error) in
    if let error = error {
        print(error)
        return
    }
    print(address?.administrativeArea) // → 東京都
    print(address?.locality) // → 墨田区
    print(address?.subLocality) // → 押上
}
```
Cordova でローカルファイルをホニャホニャする


バージョンに依ってだとか、W3CのDraftやRFCに依って変化が激しくて、このあたりを触る度にネットの渦に巻かれるのでメモ。

## ファイル初期化したいんだよう

cordova.file.checkFile(): Promise<boolean>

この子で良いのは良いのだけど、Promise で boolean が返るなら、ある／なしが .then() の中で判定できると思ったら大間違い。
無いときは error 側に流れます(X_X)

```
  /// constructor で `file: File` で cordova-plugin-file が inject されてる前提
  /// DirectoryEntry, FileEntry は cordova-plugin-file から import してください。
  /// import { DirectoryEntry, File, FileEntry } from '@ionic-native/file';
  
  const fileName: string = "FileFile.txt";
  
  return new Promise( (resolve, reject) => {
    this.file.checkFile( this.file.dataDirectory, fileName)
    .then( (/* isExists */) => {
      // ファイルあるよー
      window.resolveLocalFileSystemURL( this.file.dataDirectory, (dirEntry: DirectoryEntry) => {
        dirEntry.getFile(fileName, {create: false, exclusive: false}, (fileEntry: FileEntry) => {
          resolve(fileEntry);
        }, (er) => {
          reject(er);
        });
      });
    }, () => {
      // ファイルないよー
      this.file.createFile(this.file.dataDirectory, fileName, true)
      .then( (fileEntry) => {
        resolve(fileEntry);
      })
      .catch( (er) => {
        reject(er);
      });
    })
    .catch( (er) => {
      reject(er);
    });
  });
```
Webpack v4 の babel-loader で async / await に対応させ、 IE11 にも対応させる設定

## 要件

- Webpack で Babel をコンパイルしたい
  - async / await (ES2016+) に対応
  - IE11 にも対応 (polyfill)

## install

`npm install webpack babel-loader @babel/core @babel/preset-env @babel/polyfill core-js@2`

## 書き方

### 設定ファイル

（ルールの箇所のみを抜粋）

```webpack.config.js
{
    test: /\.js$/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
                modules: false,
                targets: {
                  node: 'current',
                  ie: 11
                },
                useBuiltIns: 'entry',
                corejs: 2
              }
            ]
          ]
        }
      }
    ]
  }
```

### entryポイントのjs

（importの箇所のみを抜粋）

```app.js
import '@babel/polyfill';
```

## [追記]

`@babel/polyfill is deprecated`

@babel/polyfill は廃止予定らしい？！

今後は、@babel/polyfill を構成している
`core-js`と`regenerator-runtime/runtime`を直接読み込んで対応していくっぽい。

```app.js
// import '@babel/polyfill';
import 'core-js';
import 'regenerator-runtime/runtime';
```

```webpack.config.js
{
    test: /\.js$/,
    use: [
      {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              '@babel/preset-env',
              {
//              以下の設定は、無くても動いた
//                modules: false,
//                targets: {
//                  node: 'current',
//                  ie: 11
//                },
                useBuiltIns: 'entry',
                corejs: 2
              }
            ]
          ]
        }
      }
    ]
  }
```

参考: core-js@3 だと、IE11でエラーが出る模様。。
https://github.com/zloirock/core-js/issues/514#issuecomment-476364862
機械学習用の画像集めに便利な「google-images-download」の使い方

## Google画像検索から画像をダウンロードするツール

Google検索から画像を一括でダウンロード出来る。
画像認識のモデルに学習させる時に便利。

>参考にしたページ
[Googleから画像を一括でダウンロードするツール「google\-images\-download」 \| cupOF Interests](https://co.bsnws.net/article/295)


## インストール方法
```
pip install google_images_download
```

pipでインストールする。

## 使い方
コマンドラインから簡単にダウンロード出来る。

```
googleimagesdownload --keywords "リンゴ"
```

カレントディレクトリに「リンゴ」の検索結果を100件保存。

## オプション一覧

|オプション|ショートカット|説明|
|:---:|:---:|:---|
| keywords | k| ターゲットとなる画像のキーワード|
| suffix_keywords| sk | キーワードを追加する為の接尾辞<br>('りんご' '赤' など)|
| limit| l| 一度にダウンロードする画像数<br>(デフォルトでは100個)|
| format | f| ダウンロードする画像の形式<br>(jpg, gif, png, bmp, svg, webp, ico) |
| color| co | ダウンロードする画像の色を指定<br>(red, orange, yellow, green, teal,blue,purple,pink, white, gray, black, brown) |
| color_type | ct | ダウンロードする画像色のタイプ<br>(full-color, black-and-white, transparent) |
| size | s| ダウンロードする画像のサイズ<br>(large, medium, icon, >400*300, >640*480,>800*600,>1024*768, >2MP, >4MP, >6MP, >8MP, >10MP) |
| aspect_ratio | a| ダウンロードする画像の形。パノラマなど<br>(tall, square, wide, panoramic) |
| type | t| ダウンロードする画像のタイプ。パノラマなど<br>(face, photo, clip-art, line-drawing,animated) |
| time | w| インデックスされた画像の期間を指定 1日以内, 一週間以内など<br>( past-24-hours, past-7-days) |
| similar_images | si | 指定した画像ファイルやURLから、似たイメージをダウンロードします |
| output_directory | o| 指定したディレクトリに画像を展開。<br>デフォルトではコマンドを実行したディレクトリに画像がダウンロードされます|
| language | la | 画像を入手するGoogleサービスの言語を指定<details><summary>指定できる言語一覧</summary>Arabic, Chinese (Simplified), Chinese (Traditional), Czech, Danish, Dutch, 　English, Estonian. Finnish, French, German, Greek, Hebrew, Hungarian,Icelandic, Italian, Japanese, Korean, Latvianm, Lithuanian, Norwegian,   Portuguese, Polish, Romanian, Russian, Spanish, Swedish, Turkish</details>|
| chromedriver | cd | 画像を入手するドライバをchromedriverに変更できます。

## 100件以上のダウンロードには「ChromeDriver」が必要

デフォルトで設定されている100件以上の画像をダウンロードするには「chromeDriver」が必要。

下記URLからダウンロード。
[Downloads \- ChromeDriver \- WebDriver for Chrome](http://chromedriver.chromium.org/downloads)

解凍して出てきた「chromedriver.exe」をカレントに置く。

```
googleimagesdownload -ri -cd "chromedriver.exe" -l 1000  -k "猫"
```
こんな感じで叩けば出来るっぽい。
ソーシャルレンディング事業者の選び方に関して

#ソーシャルレンディング事業者は数多い。
日本国内には、現在、20社以上のソーシャルレンディング事業者が存在している。
新規参入を予定している企業も複数あるとされており、
国内ソーシャルレンディング業界における競争は激しさを増している。

#ソーシャルレンディング事業者選びは、ソーシャルレンディング投資における重要なステップ。
ソーシャルレンディング投資における重大なステップは、主に、「ソーシャルレンディング事業者選び」と、「ファンド選び」である。
このうち、「ソーシャルレンディング事業者選び」のほうが、重要性が高いと言われる。
ソーシャルレンディング事業者が不誠実である場合、
そのようなソーシャルレンディング事業者が公開しているファンド概要をどれだけ読み込んだとしても、
本末転倒であるから。

#ソーシャルレンディング事業者選びの視点
ソーシャルレンディング事業者を選ぶ際の視点としては、
いくつかの視座が提唱されている。

##上場企業が運営しているソーシャルレンディングサービスを選ぶ
日本国内の主要証券市場に上場している企業が運営しているソーシャルレンディングサービスを選ぶ、という見解もある。
この場合、東証マザーズ上場企業である、ロードスターキャピタル株式会社が運営しているソーシャルレンディングサービス「オーナーズブック」等が候補となるだろう。

##上場企業子会社が運営しているソーシャルレンディングサービスを選ぶ
上場企業が直接運営していなくても、
上場企業の100パーセント子会社が運営しているソーシャルレンディングサービスを選ぶ、という見解もある。
この場合、SBIソーシャルレンディングや、LCレンディング、といったサービスが、候補となるだろう。

#ソーシャルレンディング事業者選びにおける情報参照
下記コンテンツ等が参考となる。
[ソーシャルレンディングおすすめ会社・危険会社ランキング](https://social-lending.online/qanda/kiken-kaisya-minukikata/)
jenvでjavaのバージョン管理

# jenvでjavaのバージョン管理



## はじめに

現在(2019/4/17)のjavaの最新バージョンは12です。

## 環境

- MacOS Mojave 10.14.4
- HomeBrew 2.1.1

### jenvのインストール

```sh
$ brew install jenv
```

.bash_profileに以下を追記し、パスを通す。

```shell
# jenvのPATHを通す
export JENV_ROOT="$HOME/.jenv"
if [ -d "${JENV_ROOT}" ]; then
  export PATH="$JENV_ROOT/bin:$PATH"
  eval "$(jenv init -)"
fi
```

## JDKのインストール

brew caskでインストールする方法もありますが、現環境ではbrewからインストールできなかったのでOracleからインストールします。

[ここからインストール](<https://www.oracle.com/technetwork/java/archive-139210.html>)

私は今回は12,10,8をインストールしたので、説明はその前提で記述します。

```
$ /usr/libexec/java_home -V
```

上のコマンドを実行すると、インストールされているJDKのバージョンが一覧で表記されます。

私の場合コマンドを実行して返ってきたのが以下になります。

```
12, x86_64:	"Java SE 12"	/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home
10.0.2, x86_64:	"Java SE 10.0.2"	/Library/Java/JavaVirtualMachines/jdk10.0.2.jdk/Contents/Home
1.8.0_202, x86_64:	"Java SE 8"/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
```



/Library…jdk-12.jdk/Contents/Homeのように表示される部分が以降で必要になります。・

```
$ jenv add /Library...jdk-12.jdl/Contents/Home
```

のように、先ほどの部分を``` jenv add ```以降に入力し、jenvに登録します。

```
$ jenv versions
```

のコマンドでjenvに登録されているjavaのバージョンが一覧で表示されます。

## GlobalのJavaのバージョンを変更する

```
$ jenv global 12
$ jenv rehash # 必要ない場合もある
```

```$jenv gobal [version]```の後に

```$jenv rehash```をしなくちゃ自分の場合はバージョンが切り替わりませんでした。

## LocalのJavaのバージョンを変更する



```
$ jenv local 12
```

```$jenv local [version]```で変更します

変更できているかは

```
java -version
```

で、確認して、変更が反映されていたらおｋです！！
【BluePrism】画面読込時間が一定でない場合の画面遷移実装について

##概要
画面に表示するデータ量がアクセスのタイミングによって変動するなど、
画面読込時間が一定でない場合、タイムアウトの時間を一定にしていると

- **（データ量が少ないの場合）Waitの時間が長くて処理が遅くなる**
- **（データ量が多い場合）Waitの時間が足りなくて例外になる**

などの事象が起こりえます。
そのため、変動する画面読込の時間に合わせて正常に処理が進み、
かつ、パフォーマンスを下げない実装をするのがベストです。

今回はそのような実装の方法について解説します。アイデアの一つとして参考にしてみてください。

##方法
リトライ処理を実装します。（僕は**「個別リトライ」**と呼んでいます）

①　画面の特定の要素が表示されるまでWait
②　タイムアウトの場合、リトライ回数が上限（今回は10）に達しているかチェック
③　（上限未達の場合）リトライカウントを+1
④　Wait後、再度①から実行

の流れを実装することで、個別リトライを実現しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/a1148f3a-c810-32ab-aca2-269be5abafb2.png)


タイムアウトの秒数やリトライ上限回数は、オブジェクトの**Initialise**ページに
変数として置いておくと良いでしょう。
**「プロセス内の他ページから隠蔽する」**チェックを外すことを忘れずに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/c351c22d-bd7a-f999-8404-a9c120d44ae1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/54c798a7-c3f2-ae9d-7468-c8a720b5dc8c.png)