OmniAICreator/Qiita-1.07M huggingface dataset:
TypeScriptで画像をリサイズする

#概要
重い画像をサーバに送りたくなかったので、canvasを使ってリサイズする処理をTypeScriptで書きました。
コードは自由に使ってください。

#方法
指定したwidthに合わせてリサイズしています。
Blob形式の画像をわたすと、DataURL形式で返ってきますので
そのままimgのsrcなどに入れることもできます。

createObjectURLを使っているので、caniuse等で対応ブラウザのチェックをした方が良いかもしれません。

```typescript:resize_util.ts

export class ResizeUtil {

    /** input等から取得したfileを、リサイズしdataUrlで返す */
    resize (file:Blob, imageWidth:number, afterAction:(dataUrl:string)=>void) {
        
        var canvas = document.createElement("canvas")
        var ctx = canvas.getContext('2d')
        var image = new Image()

        canvas.width = 0
        canvas.height = 0

        image.src = URL.createObjectURL(file)
        image.onload = ()=> {

            var w = imageWidth
            var h = image.height * (imageWidth/image.width)

            canvas.width = w
            canvas.height = h

            ctx.drawImage(image, 0, 0, w, h)

            afterAction(canvas.toDataURL(file.type))
        }
    }
}
```

使ってるほう

```TypeScript:main.ts

let file = $('input').prop('files')[0]
let width = 300
let util = new Util.ResizeUtil()

util.resize(file, width, (dataUrl)=>{
    //imgのsrcとかにdataUrlを入れる
})

```

#参考
http://aoyama-tech.hatenadiary.com/entry/2015/08/21/220355
https://qiita.com/FiNGAHOLiC/items/4bddee7b0bfe9555636a
Androidで固定幅や固定高さの要素を置いて、残り全部を別要素で占有させたい

多分死ぬほど既出で、みんな知ってて、自分自身でも何度もやったことあるレイアウトなんだけど、今まさにどうやっても出来ない！
ってなる。なった。
なったときにどう検索してもドンピシャな解法が出てこなかった。
のでメモ。

なんか固定値の高さをもつボタンやナビゲーションや画像を置いた上で、残りの領域にListViewとかRecyclerViewとかとかを配置したい。
RelativeLayoutを使ったりとか色々試したんだけど、どうしても要素がはみ出たり重なったりする。

結局、LinearLayoutで要素を並べて、固定幅・固定高さじゃない方、残った高さをフルに使いたい方にlayout_weightを指定して占有させることで目的を達成できた。

```xml
 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

   <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1"
      android:orientation="vertical">

      <!-- なんかいろんな要素 -->
      <!-- ListViewとかを含む -->
  </LinearLayout>

  <Button
      android:layout_width="match_parent"
      android:layout_height="55dp"
      android:layout_gravity="bottom"
      android:text="button" />

</LinearLayout>
```

(いまどきConstraintLayoutでやらないのもどうなのかね)
(まあいいじゃん)
秀丸エディタ > アウトライン解析 > 黄色の表示 > 検索しているキーワードを含む関数 | 誤判定1,2

```txt:動作環境
C++ Builder XE4
秀丸エディタ Version 8.22
```

秀丸エディタのアウトライン解析機能にて「関数一覧」を表示した時、黄色で強調されることがある。

黄色は検索機能(Ctrl+F)により検索した文字列が含まれる関数を表すようだ。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/84dc1de7-ae58-17ae-00d3-62c13bbfde61.png)

この機能を使うことで、どの変数がどの関数で使われているか一瞥できる。
grep検索で順番に見ていくよりも見通しが良い場合があるかもしれない。

黄色の表示は「アウトライン解析」ダイアログを閉じてからEscキーにて解除できる。

### 誤判定1

一行での関数実装があると、それ以降の関数定義の内容を誤判定して黄色の表示になる。
例として、`someVal`で検索してからアウトライン解析で表示すると`xxxfunc()`が黄色になる。

```xxx.cpp
int xxxfunc(void) { return yyy; }

void yyyfunc(void)
{
    someVal = ...
}
```

### 誤判定2
(追記 2018/04/10)

下記のような場合、s_some_data[]がxxxfunc()で使われているという誤判定が起きる。

```xxx.cpp
int xxxfunc() 
{

}

static int s_some_data[];
```
[Windows 10]NICにVLANを設定する方法

# 経緯
- vSphere Client で ESXi サーバに接続する際に、vSwitch側でtrunkの設定をしてあったので
接続するPCのNICでVLANの設定をする必要があった

# 動作環境
- 自分の動作環境は Intel Ethernet Connection l219-LM です
- OS: Windows 10 Pro

# 手順
1. [Intel公式サイト](https://downloadcenter.intel.com/ja/download/25016/Ethernet-Windows-10-?product=82185)からWindows 10対応のドライバーをダウンロードしてインストールする。
2. **「コントロールパネル」**を起動する。(Windowsキー + R 同時押下 -> control -> Enter )
3. **「ネットワークとインターネット」**をクリックする。
4. **「ネットワークと共有センター」**をクリックする。
5. 画面左にある**「アダプターの設定の変更」**をクリックする。
6. **「イーサネット2」**を右クリックする。
7. 
<img width="455" alt="VLAN01.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/0fb7e456-ea01-88b4-92f3-8181d0d41aee.jpeg">
7. **「プロパティ(R)」**をクリックする。
<img width="530" alt="VLAN02.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/3e2145a6-dfa0-44be-817e-2eec54a4fd4b.jpeg">
8. ネットワークタブにある、**「構成(C)...」**をクリックする。
<img width="301" alt="VLAN03.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/677323d6-a2a1-28c6-4e8b-888ae6aa85d1.jpeg">
9. VLANタブをクリックする。
<img width="331" alt="VLAN04.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/fa58c2aa-2d9d-9321-ce40-7bb793c9407b.jpeg">
10. **「新規作成(N)」**をクリックする。
<img width="332" alt="VLAN05.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/192e73d7-3ff1-5232-7186-ce6d03568045.jpeg">
11. VLAN ID に所属するVLAN IDを入力する。(例) 201
<img width="277" alt="VLAN06.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/42c27a58-fe68-6261-2911-65686ba2b826.jpeg">
12. VLAN名にVLAN名を入力する。(この項目はVLANの設定をした人間側が分かり易くする項目)
13. **「OK」** をクリックする。
14. VLAN設定後にステータスが「有効」になっていることを確認する。
<img width="331" alt="VLAN07.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/5a4f9267-e130-a09b-5d90-d9ef3f5f5c86.jpeg">
15. **イーサネット**が自動作成される。
<img width="789" alt="VLAN09.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/198480/3ee8f7d4-c29a-abed-5f35-668616f86cad.jpeg">
16. 以上です。お疲れ様でした。
Oracle Grid Infrastructureとは

Oracle DBをRAC構成とする場合に必須となる Oracle Grid Infrastructureだが、機能や構成が見えづらく、12cでも重要な機能追加があったのでまとめてみる。機能名の先頭の「Oracle」は自明なので省略。

#Grid Infrastructure(以下GI)構成
　GIは下記の3つの機能に(私的には)分類される

1. Clusterware
    + Flex Cluster
    + CHM(Cluster Health Monitor)
1. ASM(Automatic Storage Management)
    + Flex ASM
    + ADVM(ASM Dynamic Volume Manager)
    + ACFS(ASM Cluster File System)
        - HANFS(High Availability NFS Server)
1. Listener
    + Local Listener
    + SCAN(Single Client Access Name) Listener

#各機能の概要

| No | 機能名称       | 概要                     |
|---:|:--------------|:-------------------------|
|1   |Clusterware    |リソースとその関連性を管理し、リソースの起動・停止・障害監視・ノード移動を行う。一般的なクラスタウエアは稼働系と待機系があり、障害時に全体を待機系に切り替えるが、部分的な切り替えやRACに必要な複数稼働系にすることが可能。DB以外のアプリケーションリソースも追加可能。障害時のSNMPトラップやメール送信機能はないため、監視ツールは別途必要。|
|    |Flex Cluster   |DBが稼働するHUBノードと、アプリケーションが稼働するリーフノードからなる構成。リソースの依存関係を利用してアプリケーションも含めた起動・停止が可能。（使ったことはない）|
|    |CHM            |OS及びクラスタ・リソースの状況の悪化や障害について検出、及び分析を行う機能。このためMGMTDB/MGMTLSNRが作成される。本リソースは削除してもDB機能には影響がない。|
|2   |ASM            |ストレージ管理機能（グルーピング、冗長化、動的追加、削除、バランシング、共有アクセス）を提供。ベース機能はASMインスタンス+DISKグループ毎にリソース(プロセスは+ASM)が作成される。|
|    |Flex ASM       |ASMをDBインスタンスと分離し別サーバのASMも利用可能とする。ASMを配置しないサーバも構成可。各サーバのproxy_advmリソース(プロセスは+APX)がASMとの中継を行う。またASMリスナが各ノードに追加される。中継ネットワークはInterconnectを利用もしくはASM専用ネットワークを指定。|
|    |ADVM           |ASM上でのLVMのようなもの。任意サイズのボリュームを切り出しACFS(将来的に他にも増えるかも)に提供。ボリューム毎にADVMリソースが作成される。|
|    |ACFS           |ASMの機能を拡張して、ADVMで作成したボリューム上にOSからアクセス可能なファイルシステムを提供。当初はDBファイルは配置できなかったが12.1(の途中)から可能となった。ボリューム毎にACFSリソースが作成される。|
|    |HANFS          |ACFSボリュームをNFSv3サーバとする機能。仮想ipを利用して高可用性を実現。|
|3   |Listener       |GIをインストールした場合、DBリスナはDBから分離しGIが管理する。|
|    |Local Listener |通常のDBリスナと同じ機能だが、障害時のため仮想IPを利用する。アプリケーションは設定でLocal Listener直接接続も可能。|
|    |SCAN Listener  |アプリケーションとLocal Listenerの間に入りリスナの仮想化を行う。構成変更時はDNSサーバの内容を変更するだけで良い。|

+ GIで「スタンドアロンサーバ向けインストール」を行った場合、Clusterwareのサブセット的な、Oracle Restartと呼ばれる機能がインストールされる。この場合、DBをACFS上に配置できない(ASM上は可)。スタンドアロンサーバだけどACFS上にDBを配置したい場合、変則的なインストール手順が必要。

#参考資料
[RACを越えた!! Oracle Database 11g Release2のOracle Grid Infrastructureを理解する](https://blogs.oracle.com/oracle4engineer/rac-oracle-database-11g-release2oracle-grid-infrastructure)
[12c新機能 等](http://www.oracle.com/technetwork/jp/ondemand/20130823-db12c-rac-2241511-ja.pdf)
[Flexクラスタ・FlexASM](https://www.ashisuto.co.jp/corporate/column/technical-column/detail/1197778_2274.html)
[MGMTDB概要(CHM)](https://techlab.sixsquare.co.jp/archives/1231)
[スタンドアロン・サーバー用のOracle Grid Infrastructure](https://docs.oracle.com/cd/E49329_01/install.121/b71312/oraclerestart.htm)

#変更履歴
2018/03/23 初版作成
2018/03/28 スペルミス修正（指摘Thanks）。ついでにOracle Restartの説明を追加。
Windows7 以降で JT65 や FT8 等の時刻同期が厳密に要求される場合の対処方法

管理者権限で、以下のレジストリファイルを実行すれば、180 秒　(0x168h) 毎に ntp.nict.jp へ問い合わせするようになる。
下手なアプリケーションを入れずに時刻同期の制度を上げられる。

```text:NtpServer.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters]
"Type"="NTP"
"NtpServer"="ntp.nict.jp,0x1"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient]
"SpecialPollInterval"=dword:00000168
```
Windows+PHP7でCSVパースに失敗する場合の解決方法

# 環境
- Windows7
- PHP 7.1.10

# setlocale
Windowsではロケールの設定に失敗することがあるようです。
`setlocale`の指定を`ja_JP.UTF-8`以外にしてください。

# コード

```php
<?php

use SplFileObject; 

setlocale(LC_ALL, 'English_United States.1252');

$filename = 'SJISのcsvふぁいる.csv';
$spec = "php://filter/read=convert.iconv.cp932%2Futf-8/resource=$filename";
$csv = new SplFileObject($spec, 'rb');
$csv->setFlags(
   SplFileObject::DROP_NEW_LINE |
   SplFileObject::READ_AHEAD |
   SplFileObject::SKIP_EMPTY |
   SplFileObject::READ_CSV
);

foreach($csv as $i => $row) {
    print_r($row);
}
```

# 参考
[Windows版 PHP7 の環境で CSV アップロードに失敗する · Issue #1780 · EC-CUBE/ec-cube](https://github.com/EC-CUBE/ec-cube/issues/1780)
[PHPでSJISのCSVを読み込んでUTF-8として処理する場合のサンプルコード コメント](https://qiita.com/knt45/items/8cd383382b8a69ee939c#comment-7e010088b575c3f601cd)
Bootstrap4を導入方法について(CDNを利用しない場合)

#最初に
ウェブサイトを製作することになり、苦労した部分を振り返れるように記載していく。

#Bootstrapを導入した理由
Bootstrapを友人に勧められたことで借りた資料を読んでコンテンツの配置調整とレスポンシブへの対応が楽になると判断して導入することを決めた。

また、Bootstrap3ではなくBootstrap4を採用することにしたのは、長期間サイトの管理もする上で、いずれは新しいバージョンに切り替える必要があり、0から始めるため覚える知識量は変わらないと判断したため。

#Bootstrap4の導入

まず、公式サイトと日本語の解説サイトのリンクを載せておく。
特にカラーユーティリティについては、日本語の解説サイトを見ておくことを推奨する。
[Bootstrap4(公式サイト)](https://getbootstrap.com/)
[Bootstrap4移行ガイド](http://cccabinet.jpn.org/bootstrap4/)

CDNを利用した場合のテンプレートは公式サイトやBootstrap4移行ガイドがあるため省略する。
ソースファイルをダウンロードする場合について理解するまで大変だったため簡単な手順について記載しておく。

- 公式サイトからbootstrapのソースファイルをダウンロードする。
- jQueryのソースファイルをダウンロードする。
リンク先より「Download the compressed, production jQuery 3.3.1」のリンク先が「jquery-3.3.1.min.js」なので保存する。
[jQuery(ダウンロードページ)](https://jquery.com/download/)

- 「bootstrap-4.0.0.zip」を解凍し、「dist」内の「css」、「js」をフォルダごと自前サイトのフォルダに保存する。
また、「jquery-3.3.1.min.js」を「js」フォルダ内に保存する。
- htmlを以下のように記述することでBootstrap4を利用できるようになる。


##参考ソースコード

```html
<!DOCTYPE html>
<html lang="jp">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>index</title>

  <link href="./css/bootstrap.min.css" rel="stylesheet">
</head>

<body class="container-fluid">
  <main class="row justify-content-center mx-0">
    <div class="col jumbotron text-center bg-primary">
      <div class="col jumbotron">
        <h1>hello,world!</h1>
      </div>
      <div class="col jumbotron bg-transparent">
        <p class="lead font-weight-bold">hello,world!</p>
      </div>
    </div>
  </main>

  <script src="./js/jquery-3.3.1.min.js"></script>
  <script src="./js/bootstrap.bundle.min.js"></script>
</body>
</html>
```

※補足
　`<body>～</body>`内でbootstrap.jsを読み込む前にjQuery、popper.jsを読み込む必要があるが、「bootstrap.bundle.min.js」に「popper.js」が含まれているため不要。

2018年4月20日 追記
bootstrap4.1.0が最新バージョンになります。

2019年2月1日　追記
bootstrap4.2.1が最新バージョンになります。
bootstrapを4.1.0から4.2.1へサイトを更新したが、利用している範囲では特に影響はなかった。
任意の関数をTemplateHaskellでコンパイル時に実行して安全性を確保する

## 動機

論理的に安全だと分かるが、コンパイラで安全性が保証できないようなことを、少しでも保証したいという思いからです。

## コンパイラが保証できない例


以下のような`settings`があったときに、

```hs
settings :: [(String, String)]
settings = 
  [ ("http.port", "8080")
  , ("http.host", "example.com")
  ]
```


以下の式は失敗せずにうまくいきます。

```hs
fromJust (lookup "http.port" settings) == "8080"
```


ですが、`fromJust`は引数が`Nothing`のときに失敗するため安全ではないです。

```hs
fromJust :: Maybe a -> a
-- (import Data.Maybeする必要あり)
```

浅い階層で`fromJust`を使っていれば、実行してすぐにエラーに気がつけると思いますが、ある関数が呼ばれるまでは評価されない状況などでは、とても不安になります。（将来の変更でキーの名前が`"http.port"`から`"port"`に変更になったりすることも考えられ、そういうときにコンパイルして、変更すべき箇所をすぐ検出したいですよね）





## TemplateHaskellでコンパイル時実行

上記の解決策として、型レベルプログラミングで頑張るという案もあると思います。

それよりも、`fromJust (lookup "http.port" settings)`を**コンパイル時に実行してしまう方がより直感的で分かりやすい**スタイルになると思ったので模索しました。
コンパイル時に実行すれば、`"http.port"`という**キーが無いときにはコンパイルしたタイミングで検出できる**ようになります。

書き方は以下でOKです。
`$(lift (fromJust (lookup "http.port" settings)) )`

全部書いた例を以下に載せます。

```hs:Settings.hs
module Settings where

settings :: [(String, String)]
settings = 
  [ ("http.port", "8080")
  , ("http.host", "example.com")
  ]
```

```hs:Main.hs
{-# LANGUAGE TemplateHaskell #-}

import Data.Maybe
import Settings
import Language.Haskell.TH.Syntax (lift)


main :: IO ()
main = do
    -- (from: https://www.reddit.com/r/haskell/comments/7yvb43/ghc_compiletime_evaluation/)
    let p = $(lift (fromJust (lookup "http.port" settings)) )
    print p
```

```:出力
"8080"
```

一つ注意点は、TemplateHaskellの都合上、変数`settings`を別モジュールに定義して、importする必要があることです。


試しにわざと
`"http.part"`とタイポしちゃった場合は、ちゃんとコンパイル時にコンパイルエラーがでるので、間違いにすぐ気づけます！

```hs
-- （タイポしちゃった）
let p = $(lift (fromJust (lookup "http.part" settings)) )
```

```:コンパイルエラー
    • Exception when trying to run compile-time code:
        Maybe.fromJust: Nothing
      Code: lift (fromJust (lookup "http.part" settings))
    • In the untyped splice:
        $(lift (fromJust (lookup "http.part" settings)))
   |         
26 |     let d = $(lift (fromJust (lookup "http.part" settings)) )
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

## サンプルリポジトリ

この記事にある、コードをリポジトリにしたものがここにあります。
手元でコンパイルエラーするかどうか試したりするに役立ててください。

<https://github.com/nwtgck/compile-time-evaluation-example-haskell>

## 他の書き方

以下のようにも書いても、同じように働きました。

```hs
-- (from: https://www.reddit.com/r/haskell/comments/1kpu1h/can_haskell_programs_be_compiled_such_that_the/)
let p2 = $( let x = fromJust (lookup "http.port" settings)  in [| x |] )
```

すこし、`x`を定義したり、冗長に感じたので、最初のものを先に紹介しました。


## おわりに

この方法なら、グローバル変数を引数にとる任意の関数を実行時に評価することが、できるため、利用範囲が広そうです。
もっと直感的で簡素な書き方を模索中・募集中です。

## 参考

* [GHC Compile-time evaluation : haskell](https://www.reddit.com/r/haskell/comments/7yvb43/ghc_compiletime_evaluation/)
* [Can Haskell programs be compiled such that the resultant binary already has all possible compile-time calculations already performed? : haskell](https://www.reddit.com/r/haskell/comments/1kpu1h/can_haskell_programs_be_compiled_such_that_the/)
taskerでHTTPリクエストを出してGASのメソッドをコールするまでの道のり。


# はじめに
使用したアプリ
tasker:https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm

---

# taskerを使いたい！
## taskerってなんぞや？
Androidのセンサ類をリスナ代わりに使えるアプリ。
いろいろ自動化できる。

## 今回やろうとしたこと
tasker → GAS → 諸々の処理 
今回は諸々の処理はあとから考えるのでログ出力にしておいて、それ以外の部分について準備していく。

## しかしいきなり蹴躓く。
taskerからhttpリクエストを送信→tasker上では成功しているが、GASのdoPostメソッドに到達していない。 
ステータスコードは200(成功)。 
なんでー？

## ログインできない！
htmlでレスポンスを出力させ、見てみるとログイン画面に飛ばされていることがわかった。 
なるほど、chromeで実行したときはログインされてたから問題なかったのか。 
じゃあhttpを駆使して手動でログインしないといけない…？(面倒くさそう…) 

## AOuth2.0で呼び出してみる?
ココらへんを参考に。 
https://qiita.com/yamazako/items/84dab378c9899b40c780

これ、そんな厳密にログインする必要あるのか？→ない。

## ログインしなくても利用可能にする
>アプリケーションにアクセスできるユーザーの選択肢は全員（匿名ユーザーを含む）を選択します。 
>これを選ぶことでGoogleアカウントにログインしていないユーザーでもAPIを叩くことができます。 
https://qiita.com/rf_p/items/2eeb5e5e863fb3f42860

これなら簡単。
他の人にpostされた場合を考えたいなら、passwordを一緒にhttpに乗せればいいと思う。(パケット上ではバレバレかもしれないけど。)

## それでも動かない！
htmlは実行した胸が表示されたが、loggerで吐き出したはずのログが表示されない。
どうして…。

## doPost,doGetメソッド内ではloggerは使えない。
らしい。
https://qiita.com/takanakahiko/items/c8990145605eb4e1452d
結局スプレッドシートにログ代わりになにか出力することに。

## やっと実行までたどり着く
ようやく実行完了。 
コードを書く以外の部分でだいぶ時間を取られた。
でもこれでスマホについているセンサー類をリスナにしてなにかの処理をキックできるようになった。(少なくともサーバー上では。) 
なおかつ、開発がスクリプトエディタ上で完結するので出先だろうがなんだろうがコードを触れる。 
スバラシー。
環境構築　001　GitHub　アカウント作成から初期リポジトリ


#1. ブラウザ 【GitHub TOP画面】

<https://github.com> にアクセス、画面右上の 「**Sing up**」 をクリック

![github_001.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/61d898af-3af9-4237-1f87-4a3f746e4116.png)


#2. ブラウザ 【GitHub Join GitHub画面】

## 2.1.  Step 1:Create personal account

『*Username*』『*Email address*』『*Password*』を入力後、画面下部「**Create an account**」をクリック
![github_002.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/e298bef6-d2cb-fdb7-51f2-8fd05eaea474.png)

## 2.2.  Step 2:Choose your plan

『*Unlimited public repositories for free*』をチェックON、画面下部「**Continue**」をクリック
![github_003.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/622c67a7-a4cf-9fb1-a73c-fc92dbb782da.png)


## 2.3. Step 3:Tailor your experience

『*プログラミングへレベル*』『*GitHub利用用途*』『*最も近い立場*』をそれぞれ選択後、画面下部「**Submit**」をクリック
![github_004.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/157d2f3f-5087-3f5f-0cc0-3bbab0f9d136.png)


#3. ブラウザ 【GitHub Your Actions画面】

「**Start a project**」をクリック
![github_005.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/df7b4cc5-f5e4-5bb1-4e37-f761a02965c6.png)

#4. ブラウザ 【GitHub Please verify your email address画面】

2.1の『*Email address*』で入力したメールアドレス宛に、GitHubからメールアドレス検証用のメールが送信されているので、メーラー等でメールを確認 
![github_005_01.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/a2638b89-ea19-1690-5558-7dcd3fbcd274.png)


#5. メーラー等 【Subject: [GitHub] Please verify your email address】

GitHubからのメールをメーラー等で開き、リンク『**Verify email address**』をクリック 
![github_005_02.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/4364ab56-74cd-cca3-586f-a1b54ab21578.png)


#6. メーラー等 【Subject: [GitHub] Thanks for verifying your email address.】

GitHubでのメールアドレス検証が成功すると、下記画像内容のメールが送信されてくる
![github_005_03.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/f35c616d-8334-29e3-158b-49e05e7356cc.png)


#7. ブラウザ 【GitHub Sign in 画面】

<https://github.com/login> にアクセス
2.1. で登録した『*Username*』or『*Email address*』と『*Password*』を入力、「**Sign in**」をクリック
![github_006_01.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/dea6ed3a-f7ff-1714-4bd9-cb067dd2d7fc.png)
 
# 8. ブラウザ 【GitHub Sign in 後画面】

「**Start a project**」をクリック
![github_006_02.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/1af32c91-7078-1cb5-11f4-16111ab7f5a1.png)


# 9. ブラウザ 【GitHub Create a New Repository画面】

メールアドレス検証済の場合、この画面が表示される
![github_006_03.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/ade1b66d-8aaf-b686-472a-4fb092504896.png)

## 9.1. リポジトリ作成

『*Repository name*』に任意名を入力、（思いつかない場合は、GitHubから提案される *How about xxxxxx-yyyyyy* のリンクをクリックして反映）、『*Initialize this repository with a README*』はチェックONで、「**Create repository**」をクリック
![github_006_04.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/1fbe52e4-20ba-1e03-0fc1-415f078edbd6.png)

## 9.2. リポジトリ完成

リポジトリとREADME.mdが作成される
![github_006_05.PNG](https://qiita-image-store.s3.amazonaws.com/0/244997/0b9eaae1-b261-5190-a52b-ac72e37f86fc.png)
Qiitaで箇条書きの間に空行を入れたい

Qiitaの記事に於いて、箇条書きの間に空行を入れたい。

然し、Markdownで次のように記述しても、間の空行は無視されてしまう。

```markdown:【入力】

+ あ
+ い



+ う

```

【出力】
- - -

+ あ
+ い



+ う

- - -

そこで、HTMLの`<br>`タグを用い、次のように記述する。

```markdown:【入力】

+ あ
+ い
<br/>

+ う

```

【出力】
- - -

+ あ
+ い
<br/>

+ う

- - -
又は、HTMLの改行コードの文字参照を用い、次のように記述する。

```markdown:【入力】

+ あ
+ い

&#13;&#10;

+ う

```

【出力】
- - -

+ あ
+ い

&#13;&#10;

+ う

- - -
[Review] Bidirectional LSTM-CRF Models for Sequence Tagging

author
Zhiheng Huang
Baidu research
huangzhiheng@baidu.com
Wei Xu
Baidu research
xuwei06@baidu.com
Kai Yu
Baidu research
yukai@baidu.com

Link: https://arxiv.org/pdf/1508.01991.pdf
to be continued...
useraddでアカウント一括登録するPerlスクリプト

##概要
centOSでアカウントを一度に登録したいときが必ず一度はありますよね。
useraddを使おうと思いますが、パスワードの指定は-pオプションでできるのですが、暗号化された文字列出ないと登録できないようです。
そこで、今回perlのcrypt関数で登録できるスクリプトを作成しました。

##実行方法
`perl uadd.pl`

##ファイル構成
<dl>
<dt>account.txt</dt>
<dd>アカウント設定ファイル。アカウントと平文のパスワードをタブ区切りで記述します。</dd>
<dt>uadd.pl</dt>
<dd>プログラム本体</dd>
</dl>

```txt:account.txt(sample)
taro	pa123Sadu
Jackson	o4anDex
```

```perl:uadd.pl
#! /usr/bin/perl

# 下記形式のアカウント設定ファイル
# アカウント<TAB>パスワード
$PASSFILE = "account.txt";

# useraddコマンド
$USERADD_CMD = "useradd";

# ユーザーシェル
$USER_SHELL = '/sbin/nologin';

# salt
$SALT = 'a5';

open(DATAFILE, "< $PASSFILE") or die("error :$!");

while (my $line = <DATAFILE>) {
	chomp($line);
	@data = split(/\t/, $line);

	# 暗号化されたパスワード生成
	$pass = crypt(@data[1], $SALT);

	# 実行するコマンド
	$cmd = sprintf("sudo %s -s %s -p %s %s %s", $USERADD_CMD, $USER_SHELL, $pass, @data[0]);

	print "$cmd\n";

	# 実行
	system($cmd);
}
```
pandasでixを使うのはもうやめよう

# はじめに

pandasのDataFrameには`ix`というメソッドがあります。
が、これは[今はもう非推奨](http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated)です。
→いつの間にか完全に抹殺されたみたいですね。リンク先にはもう影も形もありません。

非推奨な理由はリンク先の本家ドキュメントに書いてありますが適当に訳すと、
「ixはユーザーがほしいものを推測し、魔法を提供してきた。インデックスのデータ型により、位置的なインデックスとしても、ラベルでのインデックスとしても動作した。しかしこれは長年ユーザーに混乱をもたらした」

Qiitaにも「非推奨だしix使うのやめよう」という記事は見かけましたが実際どういう困ったことが起きたという記事は見かけなかったので、以後、私の体験談です。

# 実際に困る状況

こんな感じのcsvを読み込ませたとします。

```sample.csv
No,data1,data2
1,12,34
2,23,45
3,34,56
4,45,67
5,56,78
6,67,89
7,78,90
8,89,12
```

3行目（位置インデックス2）から3行分取り出すぜ、と以下のように書きます。

```py
>>> import pandas as pd
>>> df = pd.read_csv('sample.csv')
>>> df.ix[2:5]
   No  data1  data2
2   3     34     56
3   4     45     67
4   5     56     78
5   6     67     89
```

あれ？

## 起きていることの整理

今回の場合、インデックスの型は整数です。このとき、ixメソッドは`2:5`とスライスを渡されると「インデックスの値が2から**5まで**」を返しているようです。しかしPythonプログラマなら「2から**4まで**」が返されると期待するでしょう。[^1]

[^1]: まあこのスライスで指定したもの-1までという動作も毎回微妙には感じていますが

# 代替方法

本家ドキュメントに書いてありますが位置インデックスで取りたいのかラベルインデックスで取りたいのかによって`iloc`もしくは`loc`メソッドを使いましょう。

`iloc`を使えば意図しない「インデックスの値が5の行」は含まれなくなります。

```py:ilocを使って位置インデックスで取る
>>> df.iloc[2:5]
   No  data1  data2
2   3     34     56
3   4     45     67
4   5     56     78
```

本当に「インデックスの値が2から**5まで**」取りたいという場合も明示的に`loc`を使いましょう。

```py:locを使ってラベルインデックスで取る
>>> df.loc[2:5]
   No  data1  data2
2   3     34     56
3   4     45     67
4   5     56     78
5   6     67     89
```
SkyWayでAndroidで音声の出力先を切り替える

skywayを使っていて、Androidでつまづいたのですが、GalaxyS5・Android6.0でとりあえず動いたのでメモ

```kotlin

enum class AudioOutput{
    Speaker,
    Call
}

fun setAudioOutput(type:AudioOutput?){
    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
    val mediaPlayer = MediaPlayer()

    // MODE_IN_COMMUNICATION: In communication audio mode. An audio/video chat or VoIP call is established.
    audioManager?.mode = AudioManager.MODE_IN_COMMUNICATION

    type?.let{
        // Adjust output for Speakerphone.
        audioManager?.isSpeakerphoneOn = when(it){
            AudioOutput.Call -> false
            AudioOutput.Speaker -> true
        }
    } ?: run{
        if(this.isHeadsetOn()){
            audioManager?.isSpeakerphoneOn = false
        }else{
            audioManager?.isSpeakerphoneOn = true
        }
    }

    mediaPlayer.setAudioStreamType(AudioManager.MODE_IN_COMMUNICATION)
}

fun isHeadsetOn(): Boolean {
    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        return audioManager.isWiredHeadsetOn() || audioManager.isBluetoothA2dpOn()
    } else {
        val devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
        for (i in devices.indices) {
            val device = devices[i]
            if (device.type === AudioDeviceInfo.TYPE_WIRED_HEADPHONES
                    || device.type === AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
                    || device.type === AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
                return true
            }
        }
    }
    return false
}

```
値の変更をトリガーにwebWorkerに処理をさせる。

### Proxyはデータを監視できる。
```js
let ob =new Proxy({},{ 
 set:function(o,p,v){
  w.postMessage({[p]:v});
  o[p]=v;//default;
 } 
})
```

### URL.createObjectURLで生成するメモリURLは今の所、同一ドメイン。 そこからworkerを作る。
```js
fn.worker=(src)=>{
 //inner.js or text or element
 let is={},f=(d=>URL.createObjectURL(new Blob( [d], {type:"text\/javascript"} )));
 is.element=function(o){return !!(o && o.nodeType === 1)};
 is.url=(d=>!/\n|;/.test(d));
 return new Worker( is.element(src)?f(src.textContent):is.url(src)?src:f(src) );
}
```
```js
let w =fn.worker(fn.q('[data-worker="1"]'));//same new Woker...
```
### フロント側はProxyにデータを詰める。
```js
fn.q('input').oninput=function(ev){ ob.value1 = this.value}
```

### 全部
```html
<input></input>
<output></output>
<script type="text/plain" data-worker="1">
console.log('worker boot');
function calc(data){
 console.log(data) 
 return data;
}
onmessage=function(e){postMessage(calc(e.data))}
onerror=function(e){console.log(e)} 
</script>
```
```js
var fn={}
fn.worker=(src)=>{
 //inner.js or text or element
 let is={},f=(d=>URL.createObjectURL(new Blob( [d], {type:"text\/javascript"} )));
 is.element=function(o){return !!(o && o.nodeType === 1)};
 is.url=(d=>!/\n|;/.test(d));
 return new Worker( is.element(src)?f(src.textContent):is.url(src)?src:f(src) );
}
fn.q=(s)=>{return document.querySelector(s)};
fn.jsy=(d)=>{return JSON.stringify(d,null,2)}
;
let w =fn.worker(fn.q('[data-worker="1"]'));//same new Woker...
let ob =new Proxy({},{ 
 set:function(o,p,v){
  w.postMessage({[p]:v});
  o[p]=v;//default;
 } 
})
fn.q('input').oninput=function(ev){ ob.value1 = this.value}
w.onmessage=function(e){ fn.q('output').textContent = fn.jsy(e.data)}
;
```
席替え問題による整数計画問題入門(pulp)

こんにちは。
今日は席替え問題を通じて整数計画問題やpulpの基礎的な内容について紹介したいと思います。

整数計画問題とは最適化問題の解が整数である制約を入れているものになります。

今日は席替え問題と僕が勝手に名付けた問題を用いて整数計画問題について説明します。

席替え問題とは決められた席数の中で各々の人がそれぞれの席に対して希望度を持っていて、全体の希望をなるべく満たすような席替えを決めるという問題です。
図で考えると以下のようになります。
<img width="500" alt="スクリーンショット 2018-03-23 12.18.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/182836/13640fd5-9367-a036-b062-21df4712c6c0.png">

#定式化

数学的に定式化していきます。

生徒$i$は席数次元の希望度ベクトル$W_i$を持っています。
生徒$i$の座席の所属を表すベクトルを$x_i$で定義し、座席$j$に座るならば１、座らないならば０が入るベクトルです。この$x_i$が求める変数になります。

生徒集合を$I$で、座席集合を$S$で定義します。

目的関数は、$\displaystyle \sum_{i \in I} {W_i}^t x_i$になります。全体の希望度を最大化したいのでこの目的関数を最大化します。

制約を入れて行きます。
##### 制約① １つの席には１人しか座れない
```math
\displaystyle \sum_{i \in I} x_{ij} = 1 \ (\forall j)
```

##### 制約② １人につき１つの席にしか座れない
```math
\displaystyle \sum_{j \in S} x_{ij} = 1 \ (\forall i)
```

##### 制約③ 席には座るか否か
```math
x_{ij} \in \{ 0 ,1 \} \ (\forall i\in I, \forall j\in S )
```

まとめて書くと今回解く最適化問題は以下のようになります。

```math
\begin{align}
Maximize \hspace{22pt}& \displaystyle \sum_{i \in I} {W_i}^t x_i\\
subject \ to \displaystyle \sum_{i \in I} x_{ij} &= 1 \ (\forall j)\\
\displaystyle \sum_{j \in S} x_{ij} &= 1 \ (\forall i)\\
x_{ij} &\in \{ 0 ,1 \} \ (\forall i, \forall j )
\end{align}
```

#pulpによる実装

定式化が完了したのでpulpを用いて実装して行きます。

pulpの使い方については以下の記事が非常にまとめられています。
https://qiita.com/mzmttks/items/82ea3a51e4dbea8fbc17

```seat_change.py
import pulp
import random
import numpy as np


def main():
    n = 10
    seat = n
    W = np.zeros([seat,n])

    #値を入れる
    for i in range(seat):
        for j in range(n):
            W[i,j] = random.random()

    # 各行を割合に変換
    sumbox = W.sum(axis=0, dtype='float') 
    W /= sumbox


    # 問題の宣言
    problem = pulp.LpProblem(name='change seat', sense=pulp.LpMaximize)

    # 変数の宣言
    x = {(i,j):pulp.LpVariable(name='x_{}_{}'.format(i, j), cat='Binary') for i in range(seat) for j in range(n)}

    # 目的関数
    problem += pulp.lpSum([W[i,j]*x[i,j] for i in range(seat) for j in range(n)])

    #一つの席には一人だけ
    for i in range(seat):
        problem.addConstraint((pulp.lpSum([x[i,j] for j in range(n)]) == 1),"seat_limitation_{}".format(i))

    #ユーザーは１つの席のみに入る
    for j in range(n):
        problem.addConstraint((pulp.lpSum([x[i,j] for i in range(seat)]) == 1),"user_gets_onlyoneseat_{}".format(j))

    status = problem.solve()
    print(pulp.LpStatus[status])
    print("目的関数値 = {}".format(pulp.value(problem.objective)))


    for j in range(n):
        for i in range(seat):
            if pulp.value(x[i,j]) > 0:
                print(f'user {j} seat {i} : {pulp.value(x[i,j])}')



if __name__ == '__main__':
    main()
```

③の制約は変数の宣言の際に'Binary'という形によって入っています。
また、生徒の希望度は今回、乱数を用いています。

実行すると以下のような結果が得られます。
<img width="226" alt="スクリーンショット 2018-03-23 12.59.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/182836/b8923b02-33d9-8cb9-1741-7885cc914556.png">

このようにして席替え問題をpulpを用いて解くことができました。

#最後に

整数計画法として解くことのいい面の１つとして、この基本の問題に対して制約を追加することでやりたい問題を解くことができることです。

例えば、
*人に重み付けをして優先度を考慮する*
*隣り合う人の条件を加える*
などが考えられます。どのように定式化するのかは考えてみてください。
Project Euler 60「素数ペア集合」

かなり頑張ったんですが、それでも12~13分くらいかかります。
最初に見つかった値が最小値である確証が持てれば30秒程なんですが。
ちなみに初めに書いたコードは驚異の2時間コースでした。

# Problem 60 「素数ペア集合」
素数3, 7, 109, 673は非凡な性質を持っている. 任意の2つの素数を任意の順で繋げると, また素数になっている. 例えば, 7と109を用いると, 7109と1097の両方が素数である. これら4つの素数の和は792である. これは, このような性質をもつ4つの素数の集合の和の中で最小である.
任意の2つの素数を繋げたときに別の素数が生成される, 5つの素数の集合の和の中で最小のものを求めよ.

```python
from itertools import count

def hoge(num):
    def get_ans(S, L):
        if len(L) == num:
            #print(sum(L), L)
            ans.append(sum(L))
        else:
            for s in S:
                get_ans(S & primes[s], L + [s])
#
    f = lambda x, y: is_prime(int(x + y)) and is_prime(int(y + x))
    primes, ans = {}, []
    min_under = hoge(num-1) if num > 1 else 0
    for n in count(3, 2):
        if n % 5 == 0 or not is_prime(n):
            continue
        S = set()
        for p in primes.keys():
            if f(str(n), str(p)):
                S.add(p)
        if len(S) >= num-1:
            get_ans(S, [n])
        if ans and  min(ans) <= n + min_under:
            return min(ans)
        primes[n] = S

def is_prime(n):
    if n < 2: return False
    if n == 2: return True
    if n % 2 == 0: return False
    return all(n % i != 0 for i in range(3, int(n ** 0.5) + 1, 2))

print(hoge(5))
```

最初に書いたコードはこちら

```python
from itertools import count, permutations

def hoge(num):
    f = lambda x, y: is_prime(int(x + y)) and is_prime(int(y + x))
    primes = []
    for i in count(3, 2):
        if not is_prime(i): continue
        l = []
        for n in primes:
            if f(str(i), str(n)): l.append(n)
        if len(l) >= num:
            print(i, l)
            for P in permutations(l, num):
                if all( f(str(p[0]), str(p[1])) for p in permutations(P, 2) ):
                    return i + sum(P)
        primes.append(i)

def is_prime(n):
    if n < 2: return False
    if n == 2: return True
    if n % 2 == 0: return False
    return all(n % i != 0 for i in range(3, int(n ** 0.5) + 1, 2))

print(hoge(5))
```

最小性も示せてないのにすっごい遅いよ！
Tikz の foreach を使う練習

Tikz の foreach の使い方を練習した例。

参照：TikZ & PGF manual (version 3.0.1a)
https://ctan.org/pkg/pgf
83 Repeating Things: The Foreach Statement

# foreach の繰り返し変数の使い方

```latex:
\draw [help lines] (0,0) grid (4,3);

% foreach statement for nodes
\draw (0,0) node foreach \x in {0,1,2,3,4} at (\x, 0) {$x_\x$};


% 繰り返し回数 count 注意：１始まり
\foreach \x [count=\i] in {0, 1, ..., 4}
{
    \node(a\i) at (\x, 1) {$a_\i$};
}

% 0始まりでカウント
\foreach \x [count=\i from 0] in {0.0, 0.5, ..., 4.0}
{
    \node(b\i) at (\x, 2) {$b_\i$};
}

% 複数変数
\foreach \x / \y in {0/3, 1/2, 2/1, 3/0, 4/0}
{
    \draw [red] (\x,\y) circle (0.3);
}

% 演算結果 evaluate
\foreach \x [evaluate=\x as \y using 3-0.2*\x] in {0, 1, ..., 4}
{
    \fill [blue] (\x,\y) circle (0.1);
}

% 直前の値を記憶 remember
\node (P) at (0.5,0.5) {P};
\foreach \x / \y / \n [remember=\n as \npre (initially P)] in {2.5/0.5/Q, 2.5/1.5/R, 3.5/1.5/S}
{
    \node (\n) at (\x, \y) {\n}; 
    \draw (\npre) -- node[sloped,below,font=\tiny]{\npre\n} (\n);
}
```

# 結果
![tikzforeach.png](https://qiita-image-store.s3.amazonaws.com/0/242007/757d8801-7d2c-a87c-3110-6abeb38bddef.png)
Alexaスキル開発で工夫したこと、感じたこと

# はじめに
2018年2月よりAlexaスキル開発に着手し、3月にめでたくスキルを公開、現在二作目のスキルを開発中です。そこで、開発時に工夫した点などを簡単に紹介したいと思います。ちなみにスキル開発は、仕事上の開発ではなく趣味の範囲での開発です。

参考までに私の経験値は以下のとおりです。同じような境遇？の人や、これからスキル開発を始める人に、この記事が参考になれば幸いです。

- Alexaスキル開発 ⇒ 初めて
- Node.js ⇒ 初めて
- JavaScript ⇒ 初めて
- AWS ⇒ 初めて
- ソフト開発経験 ⇒ あり（本業です）
 
「初めて」が多いですが、経験値と、皆さんがネットで公開してくれている貴重な情報を頼りに、なんとかなるレベルです。それと、過去に仕事で音声合成エンジンを利用したソフト開発経験が数年ほどあります。

# 発話フローの設計
スキル開発では、どのような発話の流れを構築するかが重要です。私の場合、Google Sheetsを使って以下のようなドキュメントを書きました。

![名称未設定.png](https://qiita-image-store.s3.amazonaws.com/0/148011/ed0e882c-1823-16d2-dfb1-b2392a671ecb.png)

画像は開発段階のものです。仕事ではないので、自分がわかればいい範囲の記述ですが、インテント名に対するユーザーの発話パターンと、それに対するAlexaの発話内容を記述しています。
発話フローが複雑になればなるほど、この手の資料で十分に検討する必要がありますね。

# 誤読への対応
日本語音声合成エンジンの宿命「誤読」は、避けては通れないものです。私が過去に利用したことがある、いくつかのエンジンは、いずれも「読み上げ辞書」なるもの（IMEで言うと単語登録みたいなもの）を作成することができたのですが、現在公開されているAlexaの仕様には、そのような機能は存在しません。

可能な範囲でなるべく誤読を避ける方法の一例として、私は次のような方法で対応しています。
以下のように、駅名のスロットを作成したとします。この例では「古淵駅」は「コブチエキ」が正しい発話ですが、現在のAlexaは「フルブチエキ」と読み上げます。

![名称未設定1.png](https://qiita-image-store.s3.amazonaws.com/0/148011/4fa4124f-a6d9-476d-14b0-a358ca678462.png)

そこで、ID(OPTIONAL)に、正しく読み上げるための文字列を定義して、その文字列を発話するように実装します。以下は、インテントのrequestから定義した値を取得するコード例です。

```Sample.js
const Station = this.event.request.intent.slots.Station
// Alexaが認識した文字列。この文字列を発話することが多いと思われる。
const alexaSpeech = Station.value;
// VALUEの値はこれ
const value = Station.resolutions.resolutionsPerAuthority[0].values[0].value.name;
// IDの値はこれ。これを発話して誤読を避ける。
const speech = Station.resolutions.resolutionsPerAuthority[0].values[0].value.id;
```
そもそも、IDの使い方として問題ないか不明ですが（問題ないと思っていますが）、お気づきの点があれば、ご指摘頂けると幸いです。

# 感じたことなど
正直なところ、この部分だけの記事が書けそうですが、Qiitaの主旨からちょっと外れるので簡潔に。あくまで私感です。

- 現在、言語が日本語の場合、アクセントがつけられません。個人的にはかなり残念です。Amazonにリクエストし開発部隊にエスカレーションする旨の回答を頂きました。
- 「スマートスピーカーは、あれば便利だよね」は、健常者視点の言葉。障がいを持った人や、お年寄りなど、体の自由がきかない人たちには生活必需品になる可能性を秘めている。
- 見た目のわかりやすさ、デザイン性が高くなると、音声（文章表現）だけで伝えるのは難しくなる傾向にある。
- 最近のWEBページはデザイン性の高いものが多い。しかし、WEBアクセシビリティ規格に真剣に対応したWEBサイトは数少ない（せいぜい文字の大きさを変えられるぐらい）。
- これからの時代、「スマートスピーカーが読み上げやすい情報提供」が求められると思う。
- スマートスピーカーの登場で、情報のバリアフリー化（アクセシビリティの向上）機運がもっと高まればいいなと思う。

スキル開発者の皆さん、不具合報告など建設的な意見をAmazonへ報告して、日本語上手なAlexaに育てていきましょう。
.bashrcで本番サーバと間違えないようにしよう

本番サーバとテストサーバを間違えてシェル実行しちゃうとか、そういうことをしないようにしよう
というメモ
間違っても
<pre>
[root@localhost ~]#
</pre>
みたいな状態で置いてはいけないし、そもそも基本的にrootで作業続行すんな

.bashrcに以下追加。IPアドレスの取得方法とかは合わせてね


<pre>

source ~/.git-prompt.sh
source ~/.git-completion.bash


export WARNING=''
export WARN_IP='192.168.111.111'
export IPADDR=`ip addr show | /bin/grep 192.168 | /usr/bin/perl -nle '/192\.168\.\d+.\d+/ && print $&;'`
if [ $WARN_IP = $IPADDR ]; then
        export WARNING='(***PRODUCTION SERVER!!!***)'
fi
export PS1='\[\033[1;32m\]\u\[\033[00m\]@$IPADDR\[\033[1;31m\]$WARNING\[\033[00m\]:\[\033[1;34m\]\w\[\033[1;31m\]$(__git_ps1)\[\033[00m\] \$ '
</pre>

.git-*.shはここを参考に入れましょう。git使ってるのであれば必須
使ってないなら適当に__git_ps1あたり消せばいいいでしょう

[「Git補完をしらない」「git statusを1日100回は使う」そんなあなたに朗報【git-completionとgit-prompt】](https://qiita.com/varmil/items/9b0aeafa85975474e9b6)

PS1も上記を改変しました。

//後でちゃんと書く
JShellでジェネリクス型パラメータ推論結果を確認する

Java 10で導入された `var` によるローカル型推論結果は JShell で手軽に確認できる。[^1]
[^1]: `/vars` はJShellのコマンド。

JShellではGenerics Type Parameters部の推論結果も表示されるため、Javaコンパイラ(`javac`)より役立つケースがあるかもしれない。（※個人差があります）

```
$ jshell
|  Welcome to JShell -- Version 10
|  For an introduction type: /help intro
```

```
jshell> var as = new ArrayList<String>();
as ==> []

jshell> var ao = new ArrayList<>();
ao ==> []

jshell> var ar = new ArrayList();
ar ==> []

jshell> /vars
|    ArrayList<String> as = []
|    ArrayList<Object> ao = []
|    ArrayList ar = []
```

```
jshell> var li = List.of(1, 2);
li ==> [1, 2]

jshell> var lx = List.of(1, 2.0);
lx ==> [1, 2.0]

jshell> var ly = List.of(1, "2");
ly ==> [1, 2]

jshell> /vars
|    List<Integer> li = [1, 2]
|    List<Number&Comparable<? extends Number&Comparable<?>>> lx = [1, 2.0]
|    List<Serializable&Comparable<? extends Serializable&Comparable<?>>> ly = [1, 2]
```

変数`lx`, `ly`で推論されている複雑な型は [型推論と無限型(infinite type)](http://d.hatena.ne.jp/yohhoy/20160913/p1) を参照のこと。
PHPでのスコープで少しびっくりした

識者の方がいれば教えていただきたいのと
ほかの言語ってどうだっけ、と思ったので書くのですが、
以下の結果ってどうなると思いますか？

```.php
<?php
$a = 1;

$array_1 = [1,2,3,4,5];
foreach($array_1 as $val_1){
  $b[] = $val_1;
}
echo($a);
var_dump($b);
```

\$aがecho(\$a)で1を出力するのは当然ですが、
自分のイメージだと\$bはforeachの中でしか有効でない
と思っていました。
もっと言うと、\$bはforeachでループする度に無くなり
生成されを繰り返すのかと思っていました。

以下が結果です。

```
1array(5) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
}
```

\$bには値が入っていますね。
foreachの外で\$bを取得したいのであれば、
\$bを使用したい階層より浅い場所で宣言してあげないと
いけないんじゃないか、と思っていましたが、、
そうではないみたいです。

```php:私のイメージ
<?php
$a = 1;

$b = []; // <==私のイメージではこれが必須でした
$array_1 = [1,2,3,4,5];
foreach($array_1 as $val_1){
  $b[] = $val_1;
}
echo($a);
var_dump($b);
```

ということは

```.php
<?php
$a = true;

if($a){
  $b = "bbb";
}
echo($b);
```
もできたりするんだろうな、と思いました。

まぁ、動くのはわかったのですが、こんなものなのでしょうか。。
わかる方がいれば教えていただきたいです。
macでatomを試してみた（php用)


sublimeText3を使っていたけど、最近atom良いよって聞いたので試してみた。

#atomをインストール
　[インストールサイト](https://atom.io/)
　TOPページにあるダウンロードボタンをクリック
　ダウンロードしたzipファイルを展開するとAtomというファイルができる
　※自分はアプリケーションに移動した
　Atomをダブルクリックで起動


#設定変更(自分好み)
###タブスペース
　・phpタブスペースを4にする
　　左メニューの「Packages」を選択し、入力欄に「php」と入力すると
　　「language-php」が表示されるので　Settingsをクリックして「Tab Length」を「4」に変更
　　※更新ボタンはない

###インデント
　・左メニューの「Editor」を選択し、「Show Indent Guide」にチェックを入れる。
　　インデントに縦線が表示され、構造がわかりやすくなる。
　・メニューの「Editor」を選択し、「Show Invisibles」にチェックを入れる。
　　半角スペース、タブ、改行を可視化することができる。

#各packageをインストールする。
※メニューの「install」を選択して入力欄にインストールしたい「package名」を入力

##docblockr
　PHPDocの生成や入力をサポートしてくれる

##linter-php
　PHPの構文チェック
　※なんか必要なものがなかったみたいで2つ3つインストールするか？って聞かれて
　　Yesで全部インストールしたらちゃんとチェックしてくれる様になった

##goto-definition
　Classなどの定義にジャンプできる
 
##show-ideographic-space
　全角スペースを可視化するパッケージです。

##atom-autocomplete-php
　PHPコードの自動補完をするパッケージです。

#参考サイト
http://tech.innovator.jp.net/entry/2016/11/16/121345
https://itcaret.com/archives/595/
http://tech.machiiro.jp/entry/2016/10/31/104815

#所感
見やすいし、結構良い感じ。気に入った^^
sublimeと比べてファイルの中を「ctl+f」で探すときに日本語がちゃんと検索できるところが助かる。
【RPA】非エンジニアによるUiPathロボット開発 Episode02 - ワークフローの新規作成

今回はワークフローの新規作成をして見ましょう。
DESIGN画面の画面構成と、代表的なワークフローをざっくり説明します。
最後に、ワークフロー作成時のTipsを説明します。

#UiPathStudioの画面構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243922/d852f341-77de-9e31-6de9-38ae930ab0bf.png)

- ツールバー　：START, DESIGN, EXECUTE, SETUPで構成されています。各メニューの主な機能は下記です。
    - START：プロジェクト作成/選択
    - DESIGN：ロボット開発、実行
    - EXECUTE：デバッグ、ログファイルの確認
    - SETUP：ログ開発したロボットのパブリッシュ（ビルド）
- アクテビティパネル：ロボットが実施する動作。UiPathでは人間がPCに行う操作を**アクティビティ**として提供しており、これを繋げてUI操作を実現します。なお、複数のアクティビティを繋げてたものを**ワークフロー**と呼びます。
    - 例１：クリックする → Clickアクテビティ
    - 例２：テキストボックスに文字列を入力する → Type into アクテビティ
- 開発パネル
    - ワークフローが表示されます。アクティビティの追加・変更・削除をします。
- プロパティパネル
    - 各アクティビティのパラメータを設定できます。
- 変数パネル
    - 変数の宣言・管理をします。
- ログパネル
    - ロボット実行ログが表示されます。

#新規ワークフロー作成
よく使うワークフローは下記の２つです。

|ワークフロー種類|メリット|デメリット|サンプル|
|-----------------|------------------|------------------|------------------|
| Sequence        |簡単、アクティビティを矢印でつなぐ必要なし|分岐処理の表現が分かりづらい、可読性が低くなりやすい|![image.png](https://qiita-image-store.s3.amazonaws.com/0/243922/01004117-3f8e-0be6-96ef-50e1fbd88ec5.png)|
| Flowchart       |分岐処理が視覚的にわかりやすい、Sequenceよりは可読性を保ちやすい|各アクティビティを矢印でつなぐ必要がある|![image.png](https://qiita-image-store.s3.amazonaws.com/0/243922/52bb6d2e-e0fb-b3b7-89c6-61f1550ef3d3.png)|

Flowchartのほうが良く見えますけど、実際に使ってみると矢印でアクティビティで繋ぐ面倒さ、さらに矢印がぐちゃぐちゃになって見た目が・・・と気になりました。
私はSequenceを処理単位に細かく分けて作成するとった手法での開発を非エンジニアの方にはオススメしています。その方が学習コスト低いですしね。この連載は非エンジニア向けですので、**Sequence**を採用します。

では、今回は**Sequence**を新規作成してみましょう。
UiPath Studioを起動すると、下記の画面が表示されますので、**Blank**を選択してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243922/ab07467f-b9a6-1827-f9eb-ea64afd1f6bb.png)


はい、ひとまずロボットの枠ができました。開発パネルがブランクの状態です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243922/ee561745-f0a9-5d97-a8d7-28e82fcf96f9.png)

#Tips 1 ワークフローはできるだけ小さい単位でつくる
上述しましたが、**基本的に１ワークフロー１処理**といったように実装すると、後々メンテナンスがしやすいです。
例えば、あるWebアプリにログインして特定の検索条件で検索した結果を取得する、という操作をUiPathで実現しようとすると

- Webアプリへのログイン処理
- 検索処理
- 検索結果読み取り処理

といったように３つのワークフローに分けた方が良いです。

なぜこのような作り方をするかというと、実際に作っていくと分かると思いますが、**ワークフローは簡単に縦長になり視認性と可読性が悪化しがち**なのです。

#Tips 2 .net記法に慣れよう
UiPathで開発をするにあたって、上述したアクティビティとワークフローの関係以外に、もうひとつ知っておきたいことがあります。それは.net記法です。
例えば、変数strHogeを文字列としてUiPathに認識させたい場合は

- strHoge.ToString

のように、**.ToString**を付ける必要があります。.net記法を完璧に習得する必要はありませんが、おそらく**.ToString**は最もよく使うことになるので、これだけは覚えていた方が良いと思います。

では次回はRecording機能を使ってWebアプリの操作を自動化してみましょう。
gRPC C#環境を作成する

# はじめに

gRPCのC#環境を作成するためのインストール手順です。
Goで作成する場合に比べて手間がかかるので公開いたしました。

https://grpc.io/docs/quickstart/csharp.html

# 作成手順
1. C#プロジェクトを作成
2. 各種GRPCのパッケージをインストール
3. Protocol Buffers生成

# GRPCのパッケージ
C#のプロジェクト上で使用するには下記のパッケージが必要です

- Grpc.Core
 - Grpcを使用するためのコアライブラリ

- Grpc.Tools
 - 各種ツールライブラリが格納されている
 - protocol Buffersのprotoファイル作成
 - パフォーマンステスト

- Google.Cloud.Language
 - [Google Cloud Natural Language](https://cloud.google.com/natural-language/?hl=ja) API用のクライアントライブラリ

# Grpc.CoreとGoogle.Cloud.Languageのインストール

Windows, Mac共に
Visual Studio上のNugetパッケージ管理で行うのが一番楽かと思います。

- プロジェクトを選択してNugetパッケージを追加
![VisualSturio1.png](https://qiita-image-store.s3.amazonaws.com/0/76076/50739bec-469a-6fb7-5514-20e564db4ad9.png)


- Grpcを選択してパッケージ追加
![VisualSturio2.png](https://qiita-image-store.s3.amazonaws.com/0/76076/ab11f7d1-5540-2bb0-5593-32ea5f28ec30.png)


- ソリューションエクスプローラー上でパッケージ追加がされていることを確認
![VisualSturio4.png](https://qiita-image-store.s3.amazonaws.com/0/76076/2c2c7dcb-4e8b-edb5-f86f-8d370e612fa4.png)

- Google.Cloud.Languageのインストール
<img width="822" alt="GoogleCloundLanguage.png" src="https://qiita-image-store.s3.amazonaws.com/0/76076/d2c610b6-998d-3277-3b9a-44937ef5c89d.png">


- (注意)Grpc.Toolsはここではインストールしない
![caution.png](https://qiita-image-store.s3.amazonaws.com/0/76076/8b2847a7-d58e-8f96-5911-59f1e891c942.png)


# Grpc.Toolsのインストール

結論から申し上げますと
Grpc.ToolsもVisual Studio上のNugetパッケージ管理で落として来ることは可能ですが、
何故かProtocol Buffers、Grpc用各種クラスの生成ができません。(Window, Mac共に)
よって、下記の方法で取得・実行を行いました。


## .protoファイル

```user.proto
syntax = "proto3";

package proto.user;

service Users{
    rpc Get (Request) returns (Response) {}
}

message User {
    int32 id = 1;
    string name = 2;
}

message Request {
    int32 id = 1;
}

message Response {
    User user = 1;
}
```

## Protocol Buffers生成(Macの場合)

- HomeBrewを使用してインストール

```
brew tap grpc/grpc
brew install --with-plugins grpc
```


- Protocol Buffers、Grpc用各種クラスの生成
 - HomeBrewで入れた/user/local/bin配下のprotocとgrpc_csharp_pluginを使用します

```
# --csharp_out: cshapスクリプト出力場所
# --grpc_out: grpc cshapスクリプト出力場所
# --plugin: protoc-gen-grpc指定をする

/usr/local/bin/protoc -I ./protos --csharp_out=./GrpcSample/Proto --grpc_out=./GrpcSample/Proto --plugin=protoc-gen-grpc=/usr/local/bin/grpc_csharp_plugin ./protos/user.proto
```


## Protocol Buffers生成(Windowsの場合)

- nuget.exeの取得
[こちら](https://www.nuget.org/downloads)からnuget.exeをダウンロード

- Grpc.Toolsを取得

```
nuget.exe install Grpc.Tools
```

- Protocol Buffers、Grpc用各種クラスの生成
インストールしたGrpc.Tools配下のprotocとgrpc_csharp_pluginを使用します

```
# --csharp_out: cshapスクリプト出力場所
# --grpc_out: grpc cshapスクリプト出力場所
# --plugin: protoc-gen-grpc指定をする

C:\Users\xxxxx\Grpc.Tools.1.10.0\tools\windows_x64\protoc.exe -I protos --csharp_out GrpcSample\Proto --grpc_out GrpcSample\Proto --plugin=protoc-gen-grpc=C:\Users\xxxxx\Grpc.Tools.1.10.0\tools\windows_x64\grpc_csharp_plugin.exe protos\user.proto
```


## 生成されたクラス

Protoフォルダ配下に下記のクラスが生成されていることを確認

- User.cs
 - メッセージで使用するUser, Request, Responseのクラス
- UserGrpc.cs
 - メーッセージ送受信を行うUsers, UsersClientクラス
HTTPSのページで外部の非SSLページの画像を表示させても警告にならないようにする

ここ最近、SSL化が必須というか、SSLじゃないとダメという風潮ですが
サイトを作るに辺り、外部コンテンツのものを表示する際、
そのサイトが非SSLだとただ単に＜img src=＞タグで表示させるとブラウザは警告出しますよね・・
解決方法として
・その外部サイトをSSL化する
・画像を自サイトにコピーする
(画像など引用する著作権関連は正しく扱いましょう。この記事の外部サイトの想定は自社の別ドメインのサイトという意味合いです)
がベストなんでしょうけど
ささっとPHPでコード書いちゃえばいいんじゃないかと思う次第

```<img src="http://他サイトドメイン/画像.jpg">```

となっているので

```<img src="/imgsrcproxy.php/http://他サイトドメイン/画像.jpg">```

こんな感じに変更し
画像URLのデータを取得して表示する様なPGを書いておけば、

```php:imgsrcproxy.php
<?php

//リクエストされたURLからPHPファイル名+/を外すと、画像URLがわかる
$url=str_replace($_SERVER["SCRIPT_NAME"]."/","",$_SERVER["REQUEST_URI"]);

//画像URL先頭にあるはずのドメインが指定のものかどうか
//踏み台にされるのを防ぐ処理の一環
if(strpos(" ".$url,"http://目的の他サイトドメイン/")==1 || strpos(" ".$url,"https://目的の他サイトドメイン/")==1 )
{
	//file_get_contentsで取得する準備
	$context = stream_context_create(array(
			'http' => array('ignore_errors' => true,
					'timeout' => 10,		//半分の秒で設定。20秒設定の場合は10
			)
	));
	//file_get_contentsで取得
	$r=@file_get_contents($url , false, $context);
	if($r!="")
	{
		//渡ってきたレスポンスヘッダーはそのまま返す
		foreach($http_response_header as $key=>$data)
		{
			header($data);
		}
		//コンテンツ表示する
		echo $r;
	}
	else
	{
		echo "error";
	}
	exit();
}
//不正アクセスなら何もしない
echo "hello";
```
ブラウザ的には自サイトのコンテンツ表示をしているだけに見えます。

PGの処理的にはリバースプロキシです。

JSでのクロスドメインにも応用できますね。
コード上でも言及していますが、踏み台にされてしまうことがあるので、
必ず目的以外には利用させないように防ぐ手立ては入れておきましょう。
androidでコピーライトの記号 © のスタイルが変更されない問題

# 結論

androidでコピーライトの記号文字のスタイルが変更されていなかった。
androidの日本語で適用されるシステムフォントではスタイルを変更できないので英語で適用されるシステムフォントを当てることで解決した。

# 経緯

## android標準の表示

以下のようなhtmlを記載したところ、androidでは意図したスタイルになりませんでした。

```html
<!doctype html>
<html lang="ja">
<head>
    <style type="text/css">
        h1 {
            color: red;
            font-size: 60px;
        }
    </style>
</head>
<body>
    <h1>© font default</h1>
</body>
</html>
```

![1.JPG](https://qiita-image-store.s3.amazonaws.com/0/90513/099b6358-067a-d6fa-40b9-b3c4240bea34.jpeg)

## langをenに変更した際の表示

同様の現象に直面した人の解決策を見た所、langをenにすることで解決したとのことです。
それに習って変更を行ったところ記号のスタイルは変更されるようになりましたが、最新のchrome for androidでは自動翻訳のポップアップが表示されるようになってしまいました。

```diff
<!doctype html>
- <html lang="ja">
+ <html lang="en">
<head>
```

![2.JPG](https://qiita-image-store.s3.amazonaws.com/0/90513/d253463d-3e59-3bc3-42c2-2aac72c30ea3.jpeg)

## font-familyを適用させた際の表示

翻訳のポップアップが表示されるのは困るので、langがenの際に適用されるフォントを調べたところ[androidのフォントについて調べてくださった方曰く](https://www.mirucon.com/2017/03/04/android-font-family/)、英語はRobotoというフォントが使われているようです。
以下のようにfont-familyを適用させて確認し、意図したように表示できることを確認できました。

```html
<!doctype html>
<html lang="ja">
<head>
    <style type="text/css">
        h1 {
            color: red;
            font-size: 60px;
        }
        .roboto-font {
            font-family: Roboto, Arial, Helvetica, Tahoma, Verdana;
        }
    </style>
</head>
<body>
    <h1>© font default</h1>
    <h1 class="roboto-font">© font roboto</h1>
</body>
</html>
```
![3.JPG](https://qiita-image-store.s3.amazonaws.com/0/90513/a7b424aa-14d0-67b1-2f79-22465c748052.jpeg)
Tegaki.aiにかける画像をOpenCVで補正

#きっかけ
手書き文字認識API（[Tegaki.ai](https://www.tegaki.ai/)）を使ってみました。ルールベースのOCRではなく、AIで手書き文字をデータ化したOCRのようです。認識率99.22%。

サービスの詳細は、HPを参照して欲しい。わくわくする。

本投稿で必要なことだけ説明すると、Tegaki.aiは手書き画像の認識、読取結果取得をAPIで提供していて、そのAPIコールに必要な画像は自分で用意する必要があります。
画像の傾きの補正や、ノイズ除去をすることにより、読取精度が上がりやすいとのことなので、OpenCVで画像補正してみました。

#まずはTegaki.ai使ってみる
Tegaki.aiは有料サービスですが、無料トライアルで使えるみたいなので、早速申し込み。
無料トライアルが使えるようになったので、
まずは、手書き文字認識用の画像を自分で用意しました。
これから手書き文字認識されると思うと、いつもより丁寧に文字を書いてしまいますねｗ

Tegaki.aiにリクエストを投げて結果を受け取ると、99%の認識率。
画像補正しなくても読取精度が高い結果となりました。誤読された文字も、人間でも読めないかもなーと感じる文字でしたので、まぁよしとしましょう。

次に、業務で使っている手書き書類を使って、tegaki.aiに投げると98%の認識率。

ただ、FAX受信した紙の場合、88%の認識率と精度が低かった。
ここで、FAX受信すると少し縮小されるため、読取位置がずれてしまうのではないか？と仮定して、

FAXの前と後でスキャンした画像の
罫線をぴったりあわせたいと考えました。

結論からいうと、２つの画像を罫線をぴったり合わせることができ、88%→95%まで精度をあげることができました。その過程を本投稿で説明します。
残りの5%は、やはり人間でも読めないような文字や、罫線をはみ出している文字でした。

#実際につかった画像の一部

他にもJANコードや単価、金額などが手書きしてある。
![address.png](https://qiita-image-store.s3.amazonaws.com/0/120078/0b05d9ed-7ab1-0454-2894-65f7e4ea6f07.png)

#Tegaki.aiで提供されているTegaki-editorでデザイン
tegaki-editorでデザインすると、リクエスト用の画像が容易に準備できる。
緑が「単線」フィールド。１行読取
赤が「チェックボックス」フィールド。○囲みや、レ点を読取
「ボックスキャラクター」フィールドもあるが、2018/3時点では数字とカナのみの対応とのこと。

あらかじめデザインした「テンプレート画像」、「読取画像」それぞれの罫線のがぴったり合わないと、読取精度が落ちると思われます。
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/120078/56c7188c-672e-63fd-daac-cdebfbe9e5df.png)

#OpenCVでやったこと
OpenCVを使って、次のような画像補正をしてみた。
・紙をスキャンするときに傾いてしまう→傾き補正（水平に）
・縮小される→リサイズ
※上下逆、手書き文字のかすれ、ノイズ、などの対策はしていない。


#環境
OpenCV3.1
python3.5

#画像補正

##傾き
[こちら](http://reverent.hateblo.jp/entry/2017/01/11/112726)を参考にしました。
ほぼコピペです。
１．cv2.Canny() でエッジ検出
２．cv2.HoughLinesP()で直線検出
３．水平方向の直線の平均角度を取る
４．直線が水平になるように画像全体を回転
の処理をしています。

今回使用した画像は紙をスキャンしたものですが、スキャンしたときに書類が斜めだと、黒い背景ができますよね。
参考）スキャン画像の左下。
![無題1.png](https://qiita-image-store.s3.amazonaws.com/0/120078/004dc7c5-966b-f173-d864-d1cce1875e01.png)

これを直線としてカウントしてしまうと、
３．水平方向の直線の平均角度を取る
で平均角度が適性ではないことがあったので、
唯一変更したのが、if文に`arg != 0`を追記したことです。




ファイル名：degree.py

```python
import cv2
import numpy as np
import math
import sys
from scipy import ndimage

def get_degree(img):
    l_img = img.copy()
    gray_image = cv2.cvtColor(l_img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray_image,50,150,apertureSize = 3)
    minLineLength = 200
    maxLineGap = 30
    lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)

    sum_arg = 0;
    count = 0;
    for line in lines:
        for x1,y1,x2,y2 in line:
            arg = math.degrees(math.atan2((y2-y1), (x2-x1)))
            HORIZONTAL = 0
            DIFF = 20
            #arg != 0を条件に追加し、傾きの平均を0に寄りにくくした。
            if arg != 0 and arg > HORIZONTAL - DIFF and arg < HORIZONTAL + DIFF : 
                sum_arg += arg;
                count += 1
    if count == 0:
        return HORIZONTAL
    else:
        return (sum_arg / count) - HORIZONTAL;


if __name__ == "__main__":
    read_file = sys.argv[1]

    img = cv2.imread(read_file)
    arg = get_degree(img)
    rotate_img = ndimage.rotate(img, arg)
    cv2.imwrite('degree.jpg', rotate_img)
```


実行してみる


```
> python degree.py input.jpg
```
degree.jpgというファイル名で出力されます。


一旦、ここまでで投稿。
次回リサイズ