OmniAICreator/Qiita-1.07M huggingface dataset:
Google Coral 開発ボード/USB Accelerator の販売開始

コーラル開発ボード

$ 149.99
![6.27-DEV.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/fd0ddcf1-1d42-7463-9ecf-1e145692bdfa.jpeg)


オンデバイスML製品を迅速にプロトタイプするための開発ボード。 取り外し可能なシステムオンモジュール（SoM）を使用して、プロトタイプから製造までの規模を調整します。

高速ML推論を実行します

オンボードのEdge TPUコプロセッサは、毎秒0.5ワット（ワットあたり2 TOPS）を使用して、1秒間に4兆回の操作（テラ操作）を実行できます。 たとえば、MobileNet v2などの最先端のモバイルビジョンモデルを100 + FPSで、電力効率の高い方法で実行できます。

TensorFlow Liteをサポート

ゼロからモデルを構築する必要はありません。 TensorFlow Liteモデルは、Edge TPU上で動作するようにコンパイルできます。

AutoML Vision Edgeをサポート

AutoML Vision Edgeを使用すると、高速で高精度のカスタム画像分類モデルを簡単に構築してデバイスに配置できます。

プロトタイプから製造までの規模

製造上のニーズを検討します。 SoMはベースボードから取り外し、まとめて注文し、ハードウェアに統合することができます。

完全なシステムを提供

SoC + ML +ワイヤレス接続を備えたシングルボードコンピュータで、すべてメンデルと呼ばれるDebian Linuxの派生物を実行しているので、このボードでお気に入りのLinuxツールを実行できます。

USBアクセラレータ

$ 74.99
![6.27-USB.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/448511/cdf61992-19e1-69fe-419a-ba5a384153bd.jpeg)


既存のシステムに機械学習推論をもたらすUSBアクセサリー。 ラズベリーパイや他のLinuxシステムで動作します。

高速ML推論を実行します

オンボードのEdge TPUコプロセッサは、毎秒0.5ワット（ワットあたり2 TOPS）を使用して、1秒間に4兆回の操作（テラ操作）を実行できます。 たとえば、MobileNet v2などの最先端のモバイルビジョンモデルを100 + FPSで、電力効率の高い方法で実行できます。

Debian Linuxで動作します

付属のUSB 3.0 Type-Cケーブルで、DebianベースのLinuxシステムに接続します。

TensorFlow Liteをサポート

ゼロからモデルを構築する必要はありません。 TensorFlow Liteモデルは、Edge TPU上で動作するようにコンパイルできます。

AutoML Vision Edgeをサポート

AutoML Vision Edgeを使用すると、高速で高精度のカスタム画像分類モデルを簡単に構築してデバイスに配置できます。

関連URL：購入 https://store.gravitylink.com/global
vue-routerでのレイアウトの出し分け

## したいこと
ログイン画面とその他の画面で表示するレイアウトを変えたい

## 環境
| laravel | vue.js |
|:------------------:|:------------------:|
| 5.8.26 | 2.9.6 |

## 実装
```php:index.blade.php
<body>
    <div id="app">
        <app></app>
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
</body>
```
---
```js:resources/js/router.js
import VueRouter from 'vue-router';

import Login from './components/Login.vue'
import Top from './components/Top.vue'

const router = new VueRouter({
    mode: 'history',
    base: '/',
    routes: [{
            path: '/login',
            name: 'login',
            // metaにlayoutを追加
            meta: { layout: 'none'},
            component: Login
        },
        {
            path: '/',
            name: 'top',
            component: Top
        }
    ]
});

export default router;
```
---
- デフォルトレイアウトのcomponent作成
- ヘッダーフッターのないログイン用レイアウトのcomponent作成

```vue:resources/js/components/layout/DefaultLayout.vue
<template>
    <div>
        <custom-header/>
        <router-view></router-view>
        <custom-footer/>
    </div>  
</template>
<script>
// ヘッダー、フッターコンポーネントをimport
// コンポーネントの詳細は省略
import CustomHeader from '../common/Header'
import CustomFooter from '../common/Footer'

export default {
    name: 'login',
    components: {
        CustomHeader,
        CustomFooter,
    },
}
</script>
```

```vue:resources/js/components/layout/NoneLayout.vue
<template>
    <div>
        <router-view></router-view>
    </div>  
</template>
```
---

```vue:resources/js/components/App.vue
<template>
    <div>
　　　　　<!-- v-bind:isでタブインタフェースのコンポーネントを切り替えられる -->
        <component v-bind:is="layout()"></component>
    </div>
</template>

<script>
// レイアウトコンポーネントをインポート
import DefaultLayout from './layout/DefaultLayout.vue';
import NoneLayout from './layout/NoneLayout.vue';

export default {
    components: {
        DefaultLayout,
        NoneLayout
    },
    methods: {
        layout() {
            // router.jsのroutesにmeta.layoutの存在確認
            // セットするレイアウトを判断する
            let layout = this.$route.meta.layout ? this.$route.meta.layout + '-layout' : 'default-layout';
            return layout;
        }
    }
}
</script>
```
pythonでスレッドのIDを取得する

## 何がしたかったのか

既存のソースコードの改修が発端です。
複数回並列で行える処理で最新のスレッドだけが動作するような作りにしたかった。
並列して動くスレッドのIDは別個のものが振られるため、IDを取得できればうまく動かせるのではと考えた。

※　その設計がいいとは限らないです。
　　ちゃんと状態管理してあげるのが正しいんだろうけど
　　手早く済ませたかったのでこんなやり方をしてます。

## 検証環境

OS: Ubuntu 18.04
python: 3.6.7

## 使うモジュール・関数

- threadingモジュール
  - get_ident()

これでスレッドIDは取得できるとのことなので、
後は下のサンプルコードで並行で動いているスレッドがちゃんと別のIDを返してくるかだけ確認する

### サンプルコード

```python:thread_id_test.py
import threading as th
import time

def say_th_id(secouds, th_no):
    time.sleep(secouds)
    print("thread no:{0}, ident:{1}".format(th_no, th.get_ident()))

if __name__ == "__main__":
    th1 = th.Thread(target=say_th_id, args=(6,1))
    th2 = th.Thread(target=say_th_id, args=(5,2))
    th1.start()
    time.sleep(1.0)
    th2.start()
```

### 結果

```
thread no:1, ident:139790510892800
thread no:2, ident:139790502500096
```

ちゃんと別々のスレッドIDが取得できました。
解釈違いなどあればコメントをください！

## 参考にしたサイト

[multithreading - How to find a thread id in Python - Stack Overflow](https://stackoverflow.com/questions/919897/how-to-find-a-thread-id-in-python)
Rollbarのdeploy通知をslackに流して、みんながリリース物のエラーを瞬時に見つけられるようにする

## 背景
本番のエラーをRollbarに通知している。
特に定期リリースをした当日は、リリースしたものによるエラーがでた場合すぐに気づいて修正をする必要がある。
しかしリリースは社員が行うため、業務委託の人(&リリース担当じゃないメンバー)はいつリリースされたのかわからず、rollbarを見張りにくかった。

## やったこと
**Settings > Notifications > Slack > Rules** 
にいく。

次にtemplateから `Deploy → Post Message` を選択してruleを作成する。
後はchannnelを選択したりよしなにやる。

メッセージ内容も自由に変更できる。
使える変数は以下のリンクにある。
ちなみに絵文字も使える。
https://docs.rollbar.com/docs/notifications

slackで@hereや@channnelをしたい時はこちらを参照。
https://docs.rollbar.com/docs/slack
MySQL　joinのイメージ

# はじめに
業務でクエリ文を書いてjoinの使い方のイメージが集合関係で考えるとわかりやすいと思ったので、それについてメモ

#結論 
inner がつくjoinの仕方は集合論でいう「かつ」になる
outer がつくjoinの仕方は基準にするテーブルが全体集合としてjoinしたいテーブルのカラムがくっ付いた形になる
参考画像の２段目のような集合になる

参考画像は以下の通り

![sql-joins.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413235/4e42f067-9f5d-70c5-5cb4-9c0701fc1ce3.png)

画像引用元
https://www.dofactory.com/sql/join


## inner join
これは結論で書いたように結合したい条件を共に満たすテーブルを用意できる。

```
select * from A inner join B on <条件>
```
このコードでAというテーブルとBというテーブルをくっつける際に、条件を満たすデータしか用意しない。
満たさないデータは、テーブルから除ける


## right outer join
これは、参考画像の２段目右側の画像のような集合になる。

```
select * from A right outer join B <条件>
```
このコードでAというテーブルとBというテーブルを右側のBテーブルを基準に条件を参照してくっつける。
基準にするときはBテーブルの全ての行を参照して条件を満たさないデータはNULLを入れてくっつける。

## left outer join  
これは、参考画像の２段目の左側のような集合になる。

```
select * from A left outer join B <条件>
```

これはright outer joinとほとんど同様で、
左側のAテーブルを基準に条件を参照してAとBテーブルをつなぐ。
基準にするときはAテーブルの全ての行を参照して条件を満たさないデータはNULLを入れてくっつける。
raspbian　Proxy経由のアップデート

備忘録

apt-getがproxy経由の場合
sudo nano /etc/apt/apt.conf.d/apt.conf
Acquire::http::proxy "http://【Servername or ip】:8080/";
Acquire::https::proxy "http(s)://【Servername or ip】:8080/";

RaspberryPIのFirmwareアップデート
sudo HTTPS_PROXY=http://【Servername or ip】:8080 rpi-update


よく忘れるので、記録・・・
【Rollbarエラー】The deploy can not be updated because its status is not started. 

## 背景
slackに、deploy時にrollbar通知を出しているが、突然エラーを吐くようになった。

```  
 DEBUG 403; Forbidden; {  "err": 1,  "message": "The deploy can not be updated because its status is not started."}
 ERROR Unable to update deploy status in Rollbar: The deploy can not be updated because its status is not started.
The deploy can not be updated because its status is not started.
```



## 解決策

githubにissueが上がっており、どうやらtimeoutを調整すれば大丈夫とのこと。
https://github.com/rollbar/rollbar-gem/issues/853


**Settings > Deploys**
メニューからTimeoutを変更。
私の場合はdeployに最長3分ほどかかっており、現状が1分の設定になっていたので5分にしました。
解決。
three.js「GLSL Sandboxのシェーダ使いたくね？」

# 事の経緯
1. AR.js+three.jsで動く名刺を作っていました
2. ぼく「ちょっと[GLSL完全に理解した](https://twitter.com/Krgm4D/status/1144144309085540352)しこれ名刺のやつに組み込みたくね？」

# やってみた

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">一日中three.jsとGLSLやってた成果物がこちらになります。 <a href="https://t.co/6ttbyNdJJS">pic.twitter.com/6ttbyNdJJS</a></p>&mdash; Kurogoma4D🗼 (@Krgm4D) <a href="https://twitter.com/Krgm4D/status/1144276384979664898?ref_src=twsrc%5Etfw">June 27, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

GLSL Sandboxでそれなりに動くシェーダを用意し，
バーテックスシェーダを各所を参考にしながら書き，
なんとなくシェーダは別ファイルで置いときたかったので[先人の知恵](https://github.com/codecruzer/webgl-shader-loader-js)を使ってセットアップ…

となんやかんやで動きはしました． 動きは…

## ぼく「なんかおかしくね？」
上の動画をよくよく見ていただければ分かると思うんですが，シェーダの向きがが名刺の上に出してる板ポリの向きに合ってません．常にカメラの向きに投影されている状態になってます．

![20190701_145445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154601/37b0ca12-326c-b40e-d2f1-1d259fcf8de4.png)

まぁ動いてはいるし楽しいので別にいいんですが，気持ちよくないので解決策を探しました．

# 解決策
結論としては，フラグメントシェーダ内での座標のとり方が問題になってました．
やることはただ一つだけです．

__`gl_FragCoord.xy`を`UV座標.xy * resolution.xy`に書き換える__

以上です．three.jsの場合，UV座標は`varying`としてバーテックスシェーダから渡してくる必要がありますが，上の処理をするだけで下のように想定通りポリゴン上にシェーダを投影してくれます．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">three.js × GLSL完全に理解した<br>（ちゃんとポリゴンのUV上に投影できた） <a href="https://t.co/RU9mvwCfUi">pic.twitter.com/RU9mvwCfUi</a></p>&mdash; Kurogoma4D🗼 (@Krgm4D) <a href="https://twitter.com/Krgm4D/status/1145555094353485824?ref_src=twsrc%5Etfw">July 1, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

しかしthree.jsも資料は十分あるはずなのになぜ詰まったのか… ちなみにこのワークアラウンドは[Shadertoyの作品をthree.jsに移植する記事](https://threejsfundamentals.org/threejs/lessons/threejs-shadertoy.html)を見て気づきました(`mainImage`の引数で上の計算をしていたため)． GLSL Sandboxの場合，作者がthree.jsと同じなので`uniform`とかゴニョゴニョせずすんなり移植できるのが良いですね．

# おまけ
AR名刺のソースコードがこちら
https://github.com/Kurogoma4D/bizcard
GoのユニットテストでAWS SDKのモックをする

Goのユニットテストでどうしてもaws-sdkを叩くレイヤーのtestがしたくなったとき、localstackなど実際のawsを模した機能を用意できればそれが一番だが、たいてい大掛かりになってしまう。
goのaws-sdkには大抵interfaceが用意されているので、これをmockでうまく使うとなかなか良かった。

そもそもDIの基本になるが、なるべくs3.S3などのstructそのものでなく、このようなinterfaceへの依存を持っておくことで簡単にmockが可能になるので、設計の際に留意しておく。

例えば、s3であれば [S3APIというinterface](https://godoc.org/github.com/aws/aws-sdk-go/service/s3/s3iface)がある。

今回はこういうものを用意した。


```golang 
package aws_sdk

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/service/s3"
)

type S3SdkMockImpl struct {
	//テストごとに差し替え可能にする
	ListObjects_Mock func(*s3.ListObjectsInput) (*s3.ListObjectsOutput, error)
	HeadObject_Mock  func(*s3.HeadObjectInput) (*s3.HeadObjectOutput, error)
}

// auto generated by jetbrains
func (S3SdkMockImpl) AbortMultipartUpload(*s3.AbortMultipartUploadInput) (*s3.AbortMultipartUploadOutput, error) {
	panic("implement me")
}

func (S3SdkMockImpl) AbortMultipartUploadWithContext(aws.Context, *s3.AbortMultipartUploadInput, ...request.Option) (*s3.AbortMultipartUploadOutput, error) {
	panic("implement me")
}

func (S3SdkMockImpl) AbortMultipartUploadRequest(*s3.AbortMultipartUploadInput) (*request.Request, *s3.AbortMultipartUploadOutput) {
	panic("implement me")
}

func (S3SdkMockImpl) CompleteMultipartUpload(*s3.CompleteMultipartUploadInput) (*s3.CompleteMultipartUploadOutput, error) {
	panic("implement me")
}

func (S3SdkMockImpl) CompleteMultipartUploadWithContext(aws.Context, *s3.CompleteMultipartUploadInput, ...request.Option) (*s3.CompleteMultipartUploadOutput, error) {
	panic("implement me")
}

...

// ダミーが刺されていれば使う
func (self *S3SdkMockImpl) HeadObject(in *s3.HeadObjectInput) (*s3.HeadObjectOutput, error) {
	if self.HeadObject_Mock != nil {
		return self.HeadObject_Mock(in)
	}
	panic("implement me")
}

....
func (self *S3SdkMockImpl) ListObjects(in *s3.ListObjectsInput) (*s3.ListObjectsOutput, error) {

	if self.ListObjects_Mock != nil {
		return self.ListObjects_Mock(in)
	}

	panic("implement me")
}

```

interfaceを埋めるメソッド自体はGolang等のIDEですぐにgenerateできるが、テストケースごとに生成するのも見通しが悪いため、必要なメソッドごとに差し替え可能にし、使いまわせるようにした。
使用側はこうなる。

```golang 
s3SdkMockTestCase01 := aws_sdk.S3SdkMockImpl{
	ListObjects_Mock: func(input *s3.ListObjectsInput) (output *s3.ListObjectsOutput, e error) {
		
		return &s3.ListObjectsOutput{
			... //自由に返す
		} , nil
	},
}

s3SdkMockTestCase02 := aws_sdk.S3SdkMockImpl{
	ListObjects_Mock: func(input *s3.ListObjectsInput) (output *s3.ListObjectsOutput, e error) {
		
		return &s3.ListObjectsOutput{
			... //自由に返す
		} , nil
	},
}

s3DataRepoisitoryForTest01 := NewS3DataRepository(s3SdkMockTestCase01)
s3DataRepoisitoryForTest02 := NewS3DataRepository(s3SdkMockTestCase02)
```

場合に応じて差し替えが簡単になり、使いまわせるようにもなった。

## 追記
interface自体を埋め込んであげるともっといいですね...
DevSecOpsについて

先日、こちら( https://circleci.connpass.com/event/134220/ )に参加してきて、GitHub社の方がおっしゃれていた`DevSecOps(デブセックオプスと呼ぶらしい)`という聞きなれない言葉が出てきたので、以下まとめてみた。

# DevSecOpsとは
DevOpsにSecurityの観点を含めて自動化していくという考え方の事だった。

# DevSecOpsが生まれた背景
2018/11/26 node.jsのイベントストリームというオープンソースソフトウェアにバックドアが仕込まれた。（ビットコイン関連のマルウェアソース）
→気づくのに2ヶ月かかったのを非常に重く受け止めて改善策の検討・実行を本格的に開始したとの事。

# 開発者に関係あるGitHubのSecurity機能
詳細はこちら:
https://github.blog/jp/2019-05-24-introducing-new-ways-to-keep-your-code-secure/

### ■セキュリティ脆弱性アラート（ベータ版）
リポジトリの依存関係ツリーを完璧に書けるという強みをGitHubは生かして、怪しいライブラリーを洗い出す機能を作成した。
去年1年で26,923,394件のセキュリティアラートを送信した。
また、WhiteSourceと提携して、セキュリティ洗い出し機能を強化している。
### ■ディペンデンシー・インサイト
プロジェクト内の依存関係から、セキュリティの脆弱性を可視化できるツール。
GitHubのInsightタブから依存しているライブラリーのグラフが見えるそうだが、手元の適当なリポジトリを見てもグラフは見えなかった。。。
![06dd5daef6be200e5c65648a29ff4c9b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429583/2d602fc1-6b04-52fa-7132-fc995eff9457.png)
### ■Dependabotによるセキュリティパッチの自動化
最近、PRの中に謎のContributorが登場したのを見た事がないだろうか？
![96d96c978e9babf6f8226031fbe992b7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429583/84bc102f-5efb-3e26-ca52-c4b31905fa66.png)
実はこれは、Dependabotによる利用中のライブラリのの依存関係を洗い出して、セキュリティパッチを自動生成してPRを出すツールとの事。
GitHubのSecurityタブから、`Automated security fixes`というものをONにしておくだけという優れものだ。
自動だけではなく、その場で手動でセキュリティパッチを作成する事もできるとの事。
![1d99147010c2516d3da305ab2fde89d6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429583/026f3c9e-c3e6-0386-5bd7-ec78e47db25a.png)

# まとめ
開発者がそこまで意識しなくても使えるようにしてあるものばかりだ。今後、DevSecOpsがバズワードになるのか業界の隅っこで見守っていく。
Flaskの自分用いろいろ

#インストール
######pythonはインストール済みのUbuntu(18.04)前提です。
```bash:
pip install Flask
```
# メインになるやつ
```python:run.py
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0', port=80)
```
###備考
<dl>
<dt>これだと80ポートで動くのでapache2とか動いてるとエラーが出ます.<dt>
<dt>誰でもアクセスできる状態（変更したい場合はapp.runのあたりを変える）</dt>
<dt>デバッグモードが有効化されてる状態(無効化したいときはapp.debugをFalseに）<dt>
<dt>処理とかはここに書く..らしい（他サイト参照）<dt>
</dl>
#htmlとか各種ファイルのパス
~~ここで2時間ぐらい躓いてた~~
###htmlはtemplatesフォルダ内に置く
###css、JavaScript、画像等はstatic内にフォルダを作って置く
```
run.py
/templates
//index.html
//hogehoge.html
/static
//css
///main.css
///ほげほげ.css
//images
///hoge.png
//JS
///hogehoge.js

```
~~(見にくいなこれ）~~
置く場所を変更することもできるらしいけど標準だとこうなるらしい.
#htmlでのパスの書き方
```html:index.html
<head>
<link rel="stylesheet" href="{{ url_for('static',filename='css/main.css')}}">
<script src="{{ url_for('static',filename='JS/hogehoge.js')}}"></script>
</head>
<body>
...
<img src="{{ url_for('static',filename='images/hoge.png')}}"></img>
...
</body>
```
```{{ url_for('static',filename='hoge/hoge')}}```って形で指定するらしい。
#実行
```bash:
hoge@hoge:/var/www/html$ sudo python3 run.py
 * Serving Flask app "run" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 810-364-364

```

#感想（？）
色々なサイトからのコピペの集合体なのでもっと効率のいい方法があると思います。見つけた方は教えていただけると幸いです。
お疲れ様でした。
SSHを実際に使ってみた

学校である程度知識もついたので、学んだことを実践してみようと思いSSHを実際に使って見ようと思いました。
サーバーはconohaで一番安いプランのVPSをレンタルしました。
#公開鍵と秘密鍵を作る
SSHは暗号化を行う事により盗聴されても大丈夫なようにして、遠隔操作を行うためのプロトコルだという認識です。
Teratermで公開鍵と秘密鍵を作成し、公開鍵の方をサーバーに渡し、.ssh/authorized_keysへ移動。

公開鍵で暗号化した物は秘密鍵でしか復号できず、秘密鍵で暗号化した物は公開鍵でしか復号できない。このおかげでクライアントとサーバーの通信は盗聴されても複合出来ない、安全である…という認識です。
書いてて思っちゃったんですけど、これ公開鍵をサーバーに渡した際に誰かに盗聴されてて公開鍵を取られてた場合、クライアント側で暗号化した文を復号されちゃうんですかね。最初にユーザーログインしてから公開鍵を渡したからパスワードで暗号化されてたりするんでしょうか、やはりまだ勉強が足りないですね。
#sshdのコンフィグを弄る
sshdのコンフィグを弄ってsshでのrootログインを禁止して、パスワードでのログインも禁止に設定しました。
sshの外部からログイン出来る性質上、なんでも出来るroot権限を万一にでも奪取されたらまずい、というのがrootログイン禁止の理由、辞書攻撃やブルートフォース攻撃によって突破されたらいけない、というのがパスワードでのログインを禁止する理由らしいです。
そういえばちょっとここで詰まってしまいました。sshでログインしようとしてもTeratermの反応がなくなってしまう事態が発生しました。最初からやり直したら解決したのですが、どうやらauthorized_keysのパーミッションの設定を忘れていたのが原因のようです。
パーミッションというのはアクセス権の事らしいですね、書き込み読み込み実行の権限が無かったせいで止まっていた、という感じなのでしょうか。

#FWの設定を変える
なんやかんやで無事SSHでのログインは出来るようになったのですが、ウェルノンポート番号のままだと攻撃を非常に受けやすいとのことなので、sshのポート番号を変更することにしました。
残念ながらココらへんのコマンドは半分くらいしか理解できませんでした。iptablesというのは昔聞いたことがあったのですがfirewalldというのを使うようになったみたいですね。
恐らくですが、sshのウェルノンポート番号を塞ぎ、適当なポート番号をssh用に開く、という処理を行ったようです。そのうち完全に理解できるようになりたい。

#感想
linuxを触るの自体あまり経験がなかったので、今回のはいい経験になりました。応用情報取得で学んだだけの知識を少しは実際に使えるようになれたと思います。qiita自体もあまり馴染みが無いのですが、アウトプットはしっかり出来るようになっていたほうがいいとの事なので…書ける内容も記事の質も少しずつ良く出来るようにこれからも精進していこうと思います。
The Go Playground上で簡単に複数のファイルをシェアする #golang

## The Go Playgroundが複数ファイル対応になった

Goコミュニティでみんなが便利に使っている[The Go Playground](https://play.golang.org/)ですが、ついに複数ファイルに対応しました。

参考：https://github.com/golang/go/issues/32040

[txtar](https://godoc.org/cmd/go/internal/txtar)という複数のファイルを1つのファイルにまとめる方法を使うことによって複数のファイルを記述しています。

例えば、次のようなディレクトリ構成のGoのプロジェクトがあったとします。

```
.
├── fuga
│   └── fuga.go
├── go.mod
└── main.go
```

これをtxtar形式で1つのファイルにまとめると次のようになります。

```go
-- go.mod --
module hogera

go 1.12
-- fuga/fuga.go --
package fuga

func Fuga() string {
	return "Fuga"
}
-- main.go --
package main

import (
	"fmt"
	"hogera/fuga"
)

func main() {
	fmt.Println(fuga.Fuga())
}
```

txtar形式はファイルを`-- ファイルパス --`で区切って表現します。
シンプルな形式なので簡単に書くことができますが、ファイル中に`--`で始まる行があるとうまくいかないので注意が必要です。

https://play.golang.org/p/4CGQN8slkSl

```go
package main

import (
	"fmt"
)

/*
-- hogera --
*/

func main() {
	fmt.Println("Hello, playground")
}
```

手で入力していくのはなかなか大変なため、[Chromeの拡張機能](https://chrome.google.com/webstore/detail/go-playground-addons/kjhcofplemokahbgknjgabnkidaabnde)を使うとファイルごとにタブで記述できるようになるため便利です。

## コマンドラインから複数のファイルをまとめてシェアする

コマンドラインから手元のソースコードをサクッとシェアできると便利です。
筆者が開発しているThe Go Playgroundをコマンドラインから操作するツールである[`gp`](https://github.com/tenntenn/goplayground)を使うと簡単に複数のファイルをtxar形式でシェアすること可能になります。

`gp`のインストールは`go get`で行うことができます。

```sh
$ go get https://github.com/tenntenn/goplayground/cmd/gp
```

複数のファイルをまとめてシェアするには、次のように`share`サブコマンドを用います。

```sh
$ gp share a.go b.go
```

複数のファイルをまとめるには、次のように`find`コマンドなどで用いると良いでしょう。
なお、ここでは不可視ファイルを無視するように`-path '*/\.*'`を指定しています。

```sh
find . -not -path '*/\.*' -type f | xargs gp share
```

## The Go Playgroundからソースコードをダウンロードする

`gp`コマンドを用いるとThe Go Playground上でシェアされたコードをダウンロードすることもできます。
次のように何も指定しない場合には標準出力に出力されます。

```sh
$ gp download https://play.golang.org/p/sTkdodLtokQ
package main

import (
        "fmt"
)

func main() {
        fmt.Println("Hello, playground")
}
```

txtar形式の場合でも何も指定しなければそのまま標準出力に出力されますが、`-dldir`オプションでディレクトリを指定するとディレクトリ以下にtxttar形式を展開した形でファイルやディレクトリを保存してくれます。

```sh
$ gp download -dldir=output https://play.golang.org/p/Ccn7TxELuAT
$ tree output
output
├── fuga
│   └── fuga.go
├── go.mod
└── main.go
```

## まとめ

`gp`便利なのでぜひ使ってみてください。

* https://github.com/tenntenn/goplayground
【ReactNative+Redux】ActionとReducerの記述を改善？した話

# はじめに
Typescript+ReactNative+Reduxを勉強中なのですが、
下記のような記述が個人的にはすごく気持ち悪い。

```HogeAction.ts
export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';

export class HogeAction1 {
  type : string = HOGE_ACTION_1;
  data1: string = '';
}

export class HogeAction2 {
  type : string = HOGE_ACTION_2;
  data2: boolean = false;
  data3: number = 0;
}
```
Reducer側ではtypeを参照してどのActionか判定しているけど、Actionはちゃんと型として定義しているのだからそんなことする必要はないのでは？？

と思ったらReducerではActionをanyで受けているのか...

```HogeReducer.ts
import {
  HOGE_ACTION_1,
  HOGE_ACTION_2,
  HogeAction1,
  HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';

// Stateを初期化
const initialState: HogeState = new HogeState();

export default function HogeReducer(state = initialState, action : any){

  if(!action){
    return state;
  }

  switch(action.type){

    case HOGE_ACTION_1:
      // HogeAction1処理...

    case HOGE_ACTION_2:
      // HogeAction2処理...

    default:
      return state;
  }
}
```

# 修正後

それならActionBaseというActionの基底クラスを作って、そこで各Actionのインスタンスの区別がつくようにしてあげればいいのでは(言語化すると何言ってるのか分からんので、下記コードを見てください)

```ActionBase.ts
export default class ActionBase {
  // コンストラクタ
  constructor(){
  }

  // クラス名
  public type : string = this.getClassName();

  public getClassName() {
    if(!this || !this.constructor){
      return '';
    }
    
    // コンストラクタからクラス名を取得
    const constructorRegex: RegExp =/function (.{1,})\(/;
    const results = (constructorRegex).exec((<any> this).constructor.toString());
    return (results && results.length > 1) ? results[1] : '';
  }
}
```

getClassName()でインスタンス化した各Actionのコンストラクタ文字列を呼び出してActionを特定している。

typeはActionBaseに持たせておけばよいので、各Actionクラスは純粋に操作するプロパティだけを持たせる。

```HogeAction.ts
import ActionBase from './ActionBase';
//export const HOGE_ACTION_1: string = 'HOGE_ACTION_1';
//export const HOGE_ACTION_2: string = 'HOGE_ACTION_2';

export class HogeAction1 extends ActionBase{
  //type : string = HOGE_ACTION_1;
  data1: string = '';
}

export class HogeAction2 extends ActionBase{
  //type : string = HOGE_ACTION_2;
  data2: boolean = false;
  data3: number = 0;
}
```

Reducerはaction.typeと各Actionクラスの.nameを突合させて判定している。

```HogeReducer.ts
import {
  HogeAction1,
  HogeAction2
} from '../HogeAction';
import HogeState from '../HogeState';
import ActionBase from '../ActionBase';

// Stateを初期化
const initialState: HogeState = new HogeState();

export default function HogeReducer(state = initialState, action : ActionBase){

  if(!action){
    return state;
  }

  switch(action.type){

    case HogeAction1.name:
      // HogeAction1処理...

    case HogeAction2.name:
      // HogeAction2処理...

    default:
      return state;
  }
}
```

これで少しはモヤっとする書き方をせずに済むかも。
もっと良い書き方があれば教えていただければ幸いです。
Asus UX430U ZenBook 14でUbuntuが再起動できない時

# エラー
![1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68213/3505780b-6a79-4661-ccf8-9de50bbc1cef.jpeg)

# 対処法
- Ubuntu起動時にリカバリーモードを選択
- rootを選択
- エンターキーを押す
- 参考のリンクの通りnanoエディタやvimなどで修正
- sudo update-grub
- reboot
![2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68213/076ee554-088b-2e61-1a53-3abeeb1d7c09.jpeg)
![3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68213/ba65534b-6efd-3b5a-ca41-6d28ab450669.jpeg)

# 参考
https://askubuntu.com/a/1144512
Windowsのログアウト(サインアウト)時にごみ箱を空にする

#容量にシビアなサービス
ディスク容量を増やす前、削れるところは削ること。クラウドサービスは増やしたら簡単に減らせない。
ログイン・アウト時、実行する仕組みはいろいろカスタム処理で愛用している。

#グループポリシー
ユーザの構成→ポリシー→Windwosの設定→スクリプトーログイン->プロパティ（PowerShellスクリプト）
\\{ADサーバ}\sysvol\hoge.local\scripts\RemoveItem-Recyclebin.ps1

#スクリプト
```RemoveItem-Recyclebin.ps1
function RemoveItem-Recyclebin {
    $Shell = New-Object -ComObject Shell.Application;
    $RecycleBin = $Shell.Namespace(0xA);
    $RecycleBin.Items() | ForEach-Object { Remove-Item $_.Path -Recurse -Confirm:$false }
}
RemoveItem-Recyclebin
```

#参考
[PowerShell – ごみ箱を空にする方法](https://codeday.me/jp/qa/20190416/640871.html)
WDL workflowの書き方について

# はじめてのwdl  


- wdlはGATKが採用しているworkflow
- inputはJSON  
- 5つのコンポーネントから形成されている。  
	- workflow, task, call, command and output

## 1.コアコンポーネントの基本構造  

### minimal WDL scriptの例  
#### top level compornent

```  
workflow myWorkflowName {
	call task_A
	call task_B
}
task task_A { .... }
task task_B { .... }
```  

- topレベルでは、タスクを組み合わせ呼び出すワークフローを定義します。  
- ワークフローの中でタスクを呼び出しますが、ワークフローのブロックの外で、タスクを定義しておきます。   
- ワークフローを先に書くか、タスクの定義を先に行うかは自由です。  


#### Core task-level components  

```  
task task_A {
	command { ... }
	output { ... }
}
```  
タスクの中では、シェルで実行するコマンドなどのコアコンポーネントを記載します。また、outputは、出力を担うコマンドを記載します。　　

--- 

# 2. 変数の加え方

ここでの変数とは、実際のファイル名やパラメータ値を除く、スクリプト上に記載する変数のことです。以下の代入方法を利用することで、内部のスクリプトを書き換えることなく必要なくワークフローを実行することができます。この変数代入は、タスクレベルとワークフローレベルの２種類があります。  

## task-level variable
 
```  
task task_A {
	File ref
	File in
	String id
	
	command {
	do_stuff R=${ref} I=${in} O=${id}.ext
	}
	output {
	File out="${id}.ext"
	}
}
```

```  
workflow myWorkflowName {
	File my_ref
	File my_input
	String name
	
	call task_A {
		input: ref= my_ref, in= my_input, $id= name
	}
	call task_B {
		input: ref= my_ref, in= task_A.out
	}
}
task task_A { .... }
task task_B { .... }
```  


---  

# 自作workflowのValidation   

自作workflowのバリデーション用にツールがついています。
> java -jar wdltool.jar validate myWorkflow.wdl  



---  
## input fileの生成  

input fileをカスタマイズする場合は以下のような形でjsonを生成します。

> java -jar wdltool.jar inputs myWorkflow.wdl > myWorkflow_inputs.json
（メモ）su させない

#/etc/sudoers.dディレクトリ配下を編集
rootユーザで/etc/sudoers.d配下に ban_commandファイル（このファイル名はなんでもいい）を作成。

```
# cd /etc/sudoers.d
# touch ban_command
# vi /etc/sudoers.d/ban_command
Cmnd_Alias BAN_COMMAND = /bin/su
<ユーザ名> ALL=NOPASSWD: ALL, !BAN_COMMAND
```

visudoで内容を確認し、「:q」でvisudoから抜ける

```
# visudo
```

#suできないか確認
「Sorry〜」のメッセージが出力されればOK

```
$ su - <ユーザー名>
$ sudo su
Sorry, user <ユーザ名> is not allowed to execute '/bin/su' as root on ip-xx-xxx-xx-xx.ap-northeast-1.compute.internal.
```

#参考
[sudoを/etc/sudoers.d/fileで許可する](https://qiita.com/kkoito/items/f5242991c43b719ef2db)
Djangoのstaticファイルが404から復活した話

# あらすじ

djangoのstaticファイルがrunserverだとアクセスできたのにapacheだとアクセスできませんでした。解決方法が分かったので、頭の整理を兼ねて書き起こしました。Bitnami前提のため、直接Apacheを入れている人は読みかえてください。

# 流れ

1. Windows PC を用意。 64bit。
1. [BITNAMI DJANGO STACK](https://bitnami.com/stack/django/installer) を利用して、mysqlとapacheをインストールする。
1. [Create A New Django Project](https://docs.bitnami.com/installer/infrastructure/django/get-started/start-django-project/)を参考にdjangoでプロジェクトを作成
1. [Deploy A Django Project](https://docs.bitnami.com/installer/infrastructure/django/get-started/deploy-django-project/)を参考にデプロイ設定
1. サイトにアクセス
1. 画像やCSSを読み込めまない！
1. settings.pyとhttpd-app.confに追記して collectstatic した。
1. サイトにアクセス
1. 無事に読み込み成功！

# 読み込まなかったファイル

```django:画像の例
<img  width="30" src="{% static '[app-name]/bitmap.png' %}" height="30" class="d-inline-block align-top" alt="">
```
```django:CSSの例
<link rel="stylesheet" href="{% static '[app-name]/css/style.css' %}">
```

# ディレクトリ構成

`:directory-tree
[project-directory]/
   ┣ [project-name]/
   ┃    ┣ settings.py
   ┃    ┗ ...
   ┣ static/
   ┃    ┗ ...
   ┣ [app-name]/
   ┃    ┣ static/
   ┃    ┃    ┗ [app-name]/
   ┃    ┃         ┣ css/
   ┃    ┃         ┃   ┗ ...
   ┃    ┃         ┣ js/
   ┃    ┃         ┃   ┗ ...
   ┃    ┃         ┣ img/
   ┃    ┃         ┃   ┗ ...
   ┃    ┃         ┗ ...
   ┃    ┗ ...
   ┗ deploy/   # deploy用のディレクトリ

        ┃
        ┣ [app-name]/
        ┃    ┗ ...
        ┗ ...
`

# staticのアクセス許可を設定

`py:[projectname]\settings.py
STATIC_URL = '/static/'  # 配信用のURL

STATIC_ROOT = os.path.join(BASE_DIR, 'deploy')  # 配信用のURL

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),  # プロジェクト直下のstaticディレクトリを指定

)
`

```conf:conf\httpd-app.conf：追記
# collectstaticでコピーしたstaticディレクトリのパスを登録

Alias /static/ [deploy用のディレクトリ]

# staticへのアクセスを許可

<Directory [deploy用のディレクトリ]>
    Require all granted
</Directory>
```
`[deploy用のディレクトリ]`はWindows10では

```
"%userprofile%/Bitnami Django Stack projects/[project-dirctory]/deploy/"
```

# Staticファイルのコレクション

設定追記が出来たら`python manage.py collectstatic`で一か所にまとめます。

Note : adminサイトなどを用意している場合、
そのstaticも一緒にまとまるので予想外のファイル数に驚かないように！
↓
apacheを再起動してブラウザでアクセス

# 参考にしたサイト

- [djangoは誰が動かしているのか？（デプロイのための俯瞰）](https://qiita.com/ming_hentech/items/9e21fe175988448e204b)
    - ここを読まなければ詰んだままでした。感謝。
- [Django staticファイル まとめ](https://qiita.com/okoppe8/items/38688fa9259f261c9440)
- [Djangoにおける静的ファイル(static file)の取り扱い](https://qiita.com/saira/items/a1c565c4a2eace268a07)
    - [Django Static Files](http://rahmonov.me/posts/django-static-files/)
- [The staticfiles app | Django Official](https://docs.djangoproject.com/ja/2.2/ref/contrib/staticfiles/)

**Excelsior!**
JavaでLambda Layersを使用する

## はじめに
JavaでLambda Layersを使用する際の手順を探したけど、わかりやすいのがなかったのでメモりました。

## 事前準備：使用するJava
##### lambda layer側
layer_print.jarでエクスポートする

```java:Print.java
package layer_print;

public class Print {
	public static void print() {
		System.out.println("print from layer!!");
	}
}
```
##### layerを使用するLambdaのHandlerクラス
layer_print.jarを含まずにjar作成 → lambda関数にアップロードする

```java:MyLambda.java
package lambda_layer_java;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import layer_print.Print;

public class MyLambda implements RequestHandler<Integer, String> {
	@Override
	public String handleRequest(Integer in, Context context) {
		// lambda layer呼び出し
		Print.print();
		return "success";
	}
}
```

## 手順

1. ローカルでjava/libフォルダ作成
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/2a21036d-ce88-c9a7-867c-fba8f5a1b986.png)

2. libにlayerにするjarファイルを置く
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/1583c8a9-f73b-5770-4f82-4b566e80c961.png)

3. javaフォルダをzipに変換
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/a664746a-2f22-b6f4-f680-9f21bb013a51.png)

4. AWSコンソールのlambdaのLayers選択。レイヤーの作成押下
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/33642e3e-1b97-bc25-3d0b-91f32ee4a4e6.png)

5. 名前、説明を入力。互換性のあるランタイムでjava 8を選択。作成したzipファイルをアップロードしてlayer作成
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/fd6b5ab2-a107-5030-4eb1-c05c91e2a93d.png)

6. layerを使用するlambda関数に移動して、Layersを選択して、レイヤーの追加を押下
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/c51947f3-b7ca-d456-19d0-058c08dca1c8.png)

7. layer、バージョンを選択して追加
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/5b669ae1-501d-0a05-2104-a0fa822757c7.png)

8. 保存して完了
![キャプチャ8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403332/fb540a87-2145-7b98-2ebf-c50c2586bb1e.png)

以上です。
DELL Inspiron 15 3537でUbuntuをインストールする方法

# 方法
F12を押して、Boot menuからLegacy mode（UEFIだと下記画像のようなエラーが出る）

# エラー
PXE-E61: Media test failure
PXE-MOF: Exiting PXE ROM.
![4.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68213/07293f2e-1fa5-b11c-c8f7-140b919a3fb2.jpeg)

# 参考
https://askubuntu.com/a/404679
Linux(主にAWS)でのユーザー追加方法

ユーザーの追加とSSHの認証用の鍵を生成する。

```
# useradd ユーザー名 
# su - ユーザー名
$ ssh-keygen -t rsa
```

sudoをパスワード無しで利用するためvisudoで下記のコメントアウトを外す。

```
%wheel  ALL=(ALL)       NOPASSWD: ALL
```

対象ユーザーをwheelグループに追加する。

```
usermod -aG wheel ユーザー名
```

所属グループを確認する。

```
groups
```

下記は単体ユーザーを設定するやり方。
sudoを使用する場合はvisudoでユーザーを追加する。

```
# Allow root to run any commands anywhere
ユーザー名 ALL=(ALL) NOPASSWD:ALL
```
ESLintのバージョンあげたらhasOwnPropertyで怒られるようになった。

ESLintのバージョンを6にあげたらいろいろな箇所でエラーになるように...

object.hasOwnProperty(key)で怒られてました。

検索すると説明がありました。

[ESLint v6.0.0 の変更点まとめ](https://qiita.com/mysticatea/items/274347ff9473b26b575a)

「[no-prototype-builtins](https://eslint.org/docs/rules/no-prototype-builtins)」でひっかかってたんですね。

## Examples of incorrect code for this rule: ダメな書き方

判定するときには下のようにしてたんですが、それでもダメなんですかねぇ？

```javascript
if (obj && obj.hasOwnProperty(key)) {
 // something
}
```

## Examples of correct code for this rule: 良い書き方

ESLintのサイトに説明があったのでこのように変更しました。

```javascript
if (obj && Object.prototype.hasOwnProperty.call(obj, "key")) {
 // something
}
```

長い...

関数にしたほうがいいかも？

```javascript
const hasProperty = (obj,key) => {
  return !!(obj) && Object.prototype.hasOwnProperty.call(obj, key);
}
```

みたいな？
dockerコンテナ内のビルド済みファイルを更新する方法

# はじめに
dockerコンテナ内でエントリーポイントとして指定された実行ファイルを更新する方法について調べた内容になります。

# 背景・問題点
JavaやkotlinでWebアプリケーション開発を行う上でdockerコンテナを立てて開発することはよくあるかと思います。
下に示すのはアプリケーション層用コンテナのDockerfileの一部です。

```dockerfile
FROM openjdk:8-jdk-alpine
COPY build/libs/application.jar application.jar
ENTRYPOINT  ["java", "-jar", "application.jar"]
```

ファイル内で行っているのは以下です。
1行目:ベースイメージの指定
2行目:ビルド済みjarファイル(実行ファイル)をホスト側(左)からコンテナ側(右)にコピー
3行目:コンテナの起動プロセスを設定(上記では渡したjarファイルを実行している)

最後のエントリーポイントで指定したコマンドの実行プロセスが起動することでアプリケーションが動作します。
開発中は変更のたびにプログラムの再ビルドを行いますが、実際のアプリケーション上で変更を確認するためには再ビルドした結果をコンテナに反映させなければなりません。単純な方法としては作成したコンテナを一旦停止し、削除した後でコンテナの再ビルド・起動を行うことが考えられますが、それなりの時間がかかってしまいます(特にコンテナの再ビルド)。

# 解決方法
上の問題の解決策の一つとして以下の方法があります。

**解決策**
1 . 起動中のコンテナに対してコンテナ内の古いjarファイルを新しいファイル(application-new.jar)で上書きする。
 
```docker
docker cp build/libs/application-new.jar application.jar
```

2 . コンテナ(コンテナ名:app)を再起動する。

```docker
docker restart app
```

この方法だとコンテナの再ビルドが必要ないため、より短時間でコンテナの更新ができます。

# 参考
- docker公式ドキュメント
http://docs.docker.jp/engine/reference/builder.html#from
SMS送信をワイヤレスボタンで実行する

以前、「[Gmail送信をワイヤレスボタンで実行する](https://qiita.com/mikawan/items/60226243074ea07e60ef)」を投稿いたしましたが、今回はSMS（ショートメッセージ）を送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/120d591f-651b-4d7b-21e6-784aa20060c8.png)

SMSを送信するために、SMS送受信サービス「[AIX Message SMS](https://www.aixmsg.com/)」と連携します。
AIX Message SMSでは、APIを使用したSMSの送信をシンプルに使うことができます。
SMS送信システムの比較については下記記事をご参照ください↓↓↓↓
[2019年度対応　SMS送信システム比較](https://qiita.com/shuuuuu/items/0f33c8ed1ca604c5e5cd)

前回と同様に、ホワイトボードマーカーが切れた際に総務への通知をボタン操作で行うことを想定しています。
SMSの本文には、ボタンを押した時間が記載されるようにします。


【本文】　ボタンを押した時間　＋　会議室Aのホワイトボードマーカーを交換してください。
　　　　　（例：15:40　会議室Aのホワイトボードマーカーを交換してください。）


#使用したもの
###ハードウェア

- Windows 10 PC（バージョン1809）
- Gravioレンタルデバイス
    -  Gravioワイヤレススイッチ（ワイヤレスボタンスイッチ）

###ソフトウェア

- Gravio
    - Gravio Studio Ver.2.2.2111.0
    - Gravio Server Ver.2.2.2354.0
    
###サービス

- [AIX Message SMS](https://www.aixmsg.com/)<br>
TEXT 1-Wayプランのトライアル環境にて検証

#Gravioの設定。
Gravioの設定は以下の3STEPです。

1. ワイヤレススイッチの設定
2. SMSを送信する設定
3. スイッチが押されたタイミングで2.が動作するように設定

まずは、ワイヤレススイッチの設定をします。

##ワイヤレスボタンの接続
ワイヤレスボタンの設定方法は[**こちら**](https://qiita.com/mikawan/items/60226243074ea07e60ef#%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%81%AE%E8%A8%AD%E5%AE%9A)を御覧ください。

##動作の設定
AIX Message SMSのAPIへショートメッセージの送信をリクエストするアクションを作成します。

アクションカードを作成し、HTTPPostコンポーネントを追加します。
ステップの追加の下に表示されている”＋”　＞ "HTTPPost"コンポーネント　＞　"選択”　の順でクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/f48f5c6b-56e9-1276-16b3-39d864e1abfb.png)

追加されたHTTPPostコンポーネント ＞プロパティの順でクリックし、表示されるプロパティに各種項目を設定します。
設定項目は下記表のとおりです。

|項目|設定内容|
|:---|:---|
|URL|https://qpd-api.aossms.com/p11/api/mt.json|
|Method|POST|
|Content-Type|application/x-www-form-urlencoded|
|Body|"token=[トークン]&clientId=[クライアントID]&smsCode=[SMSコード]&message="+ToStringFromDateTime(ToLocalTime(Now()),"HH:mm")+"　会議室Aのホワイトボードマーカーを交換してください&phoneNumber=［電話番号］"|
|その他|変更なし|

AIX Message SMSを利用するためのトークン情報などの取得方法は、AIX Message SMS上の利用マニュアルをご参照ください。
（AIX Message SMS上では各種情報を確認する以外、必要となる設定はありません）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/697d455b-e32b-5e01-b301-a09a9e8c86b0.png)


以上で、SMSを送信する設定が完了しました。

##動作タイミングの設定
スイッチを押したタイミングで動作するように、動作タイミング（トリガー）を設定します。
トリガータブを表示し、右上の"＋"をクリックし、新規トリガーを追加します。
トリガーの各項目は以下のように設定します。

|項目|設定値|
|:---|:---|
|トリガー名|（任意）|
|エリア|設定したワイヤレススイッチのエリア|
|レイヤー|設定したワイヤレススイッチのレイヤー|
|アクション名|作成したアクションカード名|
|送信元ID|空白|
|Interval|5（任意）|
|Classic/Threshold Trigger|Classic Trigger|
|Button Press|Single press|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/27833085-cf2f-d93f-3546-0eba05fa03b5.png)

以上ですべての設定が完了しました。

#動作確認
スイッチを押すとSMSが届きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/169f1319-7713-595c-fc9d-cef4bc86ab51.png)


#あとがき
このように、インク切れを忘れる前にすぐ押してもらえるカンタンなボタンを用意することで、ファシリティーの管理が楽になります。
マーカーペン以外にも、様々な現場で消耗品の管理をカジュアルに実現できるのではないでしょうか。

また、HTTPリクエストを使用することで、APIを使用できる他のサービスへ対応できます。
センサーで取得したデータと連携したいサービスがございましたら、ぜひお問い合わせいただければと思います。
VSCodeで拡張機能「Live Server」を使う

## 拡張機能「Live Server」って？

VS Codeに簡易ローカルサーバを立てることができる拡張機能。
また、ファイルを更新すると自動的にブラウザを更新する。

## インストール

Visual StudioのMarketplace（[LiveServer](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)）、もしくはVS Codeの拡張機能メニューからLive Serverを検索しInstallする。

## 使い方
VS Code右下に表示される「Go Live」をクリックすると、ブラウザで `http://127.0.0.1:5500/` が実行される。
![スクリーンショット 2019-07-01 13.49.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109744/d4cf0fac-f339-1ddf-c4c6-62ef99ae6c17.png)
あとはスクリプトをがりがり書くだけ。

## 設定

[Settings Docs](https://github.com/ritwickdey/vscode-live-server/blob/master/docs/settings.md) より。

- `liveServer.settings.port`
    - デフォルトは5500
- `liveServer.settings.root`
    - 例、`/sub_folder1/sub_folder2`
    - デフォルトは `/` （ワークスペースのルート）
- `liveServer.settings.CustomBrowser`
    - `chrome`、`chrome:PrivateMode`、`firefox`、`irefox:PrivateMode`、`microsoft-edge`、`blisk`
    - デフォルトは `null` （システムのデフォルトブラウザ）
【UiPath】データスクレイピングで次ページへ進めない場合の対応

#概要
UiPathでよく使う「データスクレイピング(Data Scraping)」では、端末の環境によっては
上手く次ページを取得できない場合があるため、その場合の対処法です。

#どういうことが起きるの？
データスクレイピングで次ページへのリンクセレクターを指定しても、うまく動作せず1ページ分しか取得できない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/688891df-83c2-9c55-8f01-520e198ad867.png)

#何が起きてるの？
ブラウザをIEに設定して、**「エラー時に実行を継続(Continue On Error)」**プロパティをFalseにしてデバッグしてみるとこんなエラーが…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/d914ae85-e5b3-26dd-873e-fc9ad360b751.png)
調べてみると'getComputedStyle'メソッドは指定した要素のスタイル情報を取得してくれるJavaScriptのメソッドだそう。
[window.getComputedStyle() で要素のスタイルを取得する](https://qiita.com/amamamaou/items/bb79bec002a6ff033810)

参考にした記事ではIE8以上では動く(サポートしてる)みたいですが、現在の環境はIE11…なぜ動かないんだろう…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/fda7720e-e72e-6d42-c982-220217222132.png)


#対処法
本当ならJavaScriptについても調べたうえで根本的な解決方法を探すのがセオリーだと思うのですが、何しろ相手はRPAツール。
個人で作って個人で楽しんだりメンテナンスするならまだしも、管理や運用が他の人に渡ることを考えると、あまり技術を深追いしすぎても引き継ぎや引き渡し時に困るので、代替手段を考えます。

###1.ブラウザを変える
これが一番早いと思います。
IEではうまく動作しませんでしたが、Chromeに変更したところ問題なく動作しました。
（データスクレイピングウィザードから生成された**「ブラウザーにアタッチ(Attach Browser)」**コンテナーのプロパティからブラウザを変更できます。）
ただし、IE以外のブラウザを使用する場合は拡張機能のインストールが必要となるので、環境に応じて注意が必要です。
公式ガイド：[Chrome拡張機能](https://studio.uipath.com/lang-ja/docs/chrome-extension)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/c29c504c-4d27-a05a-e654-702bd29edd68.png)

###2.次ページへのクリックを1アクティビティとして繰り返す
1の方法でもうまく行かない、拡張機能のインストールが宗教上の理由でちょっと…という場合は
取得条件と次ページへのクリックをデータスクレイピングのアクティビティから分離して、それぞれを処理として記述します。
####①取得したい件数が決まっている場合
**「繰り返し(後判定)(Do While)」**でデータスクレイピングアクティビティと次ページへのクリックアクティビティを繰り返します。
関数を用いて抽出用のデータテーブル内の現在の行数を取得し、その値が指定件数未満の場合繰り返す仕組みです。

| 意味 | 処理の記述 |
|:-:|:-:|
| データテーブルの行数を取得 | DataTable名.Rows.Count|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/dd4c5371-0c0e-44d3-5194-7154d97dad98.png)

####②最後のページまで取得したい場合
①と同じく、**「繰り返し(後判定)(Do While)」**でデータスクレイピングアクティビティと次ページへのクリックアクティビティを繰り返します。
①と異なり、繰り返し条件を分子と分母を表示している要素を取得し、分子が分母と同じになるまで繰り返す
という記述に変更します。

[Yahoo!ファイナンス](https://finance.yahoo.co.jp/)の出来高ランキングを例に挙げると、分子と分母が記載された項目は**「●～△件/XXX件中」**という形で記載されています。
これが全100件のページであれば、△部分が100になれば最終ページなので、最終ページになったら繰り返しを終了する形で処理を記述します。

#####条件式(その1)
| 日本語 | 処理の記述 |
|:-:|:-:|
| 分子に分母の値が含まれているか | 分子**.Contains(**分母**)**|
ただし、この記述方法だと分母に含まれる**「件中」**が邪魔です。
そのため、ここにさらに関数を加えて「件中」を取り除きます。

#####条件式(改良版)
| 日本語 | 処理の記述 |
|:-:|:-:|
| 分子に分母の数値が含まれているか | 分子.Contains(分母**.Replace("件中","")**)|

分子に分母が含まれていれば繰り返しを終了するために**繰り返しフラグにFalseを代入**、
そうでない場合は次のページに移動するための**クリックアクティビティを記述**します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176879/05c85a27-0221-59a1-2386-63c8844e7916.png)

#最後に
今回は2つの方法を挙げてみましたが、1つのアクティビティや環境で全て解決しようとするのではなく、理解を深めるためにも今回は使わなかったとしても別の方法を試してみるのもよいかと思います。
特にRPAツールはトライアンドエラーの繰り返しなので、このやり方も他の環境ではうまく動かない可能性があるので、対処法の1つとして捉えてもらえると幸いです。
C#でPollyを使ったリトライ処理

nugetでPollyをインストールしたら後は下記のように実装するだけです。
今回はAzureSQLDatabaseを使用するため、シンプルに指定したエラーの際にリトライするよう実装しました。

``` RetryHelper.cs

using Polly;
using System.Collections.Generic;
using System.Data.SqlClient;

namespace Common
{

    public static class RetryHelper
    {
        public static void OpenWithRetry(this SqlConnection connection)
        {

            PolicyResult policyResult = Policy.Handle<SqlException>(ex => TransientErrorNumbers.Contains(ex.Number))
                .Retry(3)
                .ExecuteAndCapture(connection.Open);

            if (policyResult.Outcome == OutcomeType.Failure)
            {
                // 実行に失敗した
                if (policyResult.FinalException is SqlException)
                {
                    SqlConnection.ClearPool(connection);

                    throw policyResult.FinalException;
                    // FinalException に例外が格納されている
                }
            }
        }

        private static readonly HashSet<int> TransientErrorNumbers = new HashSet<int>
        {
            50000,
            40197,
            40501,
            10053,
            10054,
            10060,
            40613,
            40143,
            233,
            121,
            64,
            53,
            20,
             -2
        };

    }

}

```
深層学習（前編 1）：「Section5：誤差逆伝播法」

算出された誤差を、出力層側から順に微分し、前の層へ順次伝播する計算手法。最小限の計算で各パラメータでの微分値を解析的に計算することができる。
計算例として、誤差関数を二乗誤差、出力層の活性化関数を恒等写像とすると、
E(y) = 1/2Σ(yj-dj)^2 = 1/2||y-d||^2
y = u
u = wz +b
dE/dy = y-d
dy/du = 1
dE/dw = dE/dy*dy/du*du/dw = (y-d)*z
iPadのShortcutsアプリで映画モードとノートモードをかんたんに切り替えられるようにした

# 何に困っていたかというと

iPadを使っている時間のほとんどは「Apple Pencilでノートをとっている」か「映画を観ている」の２択。

ノートをとっているときは、画面を暗く、音量を小さくしたい。
映画を観ているときは、画面を明るく、音量を大きくしたい。

スワイプしたら設定画面は出てくるけど、いちいち変えるの面倒くさいなあと。


# iOSのShortcutsをつかう！！

iOSにはShortcutsというアプリがあるので、これを使うことにした。

やっていることはかんたんで、モードを選択し、それによって画面の明るさと音量を変えるだけ。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/fdeda180-b00d-ee3a-a06b-225410bbb453.jpeg">

設定で「ウィジェットに追加」にしておくと、ホーム画面を右にスワイプして、このショートカットを呼び出せる。

べんりー。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/a9786fbc-2ec5-01ae-3200-42530d3a8b17.jpeg">
【Rails 備忘録】デプロイする時に定番で使うコマンド

# はじめに
備忘録です。

# デプロイで使うコマンド
前提条件として、
AWS EC2環境`/var/www/app/` 配下でgit cloneさせます。

## git clone
言わずもがなgit cloneです。

## git pull
言わずもがなgit pullです。

## bundle install

```
bundle install --path=vendor/bundle --without development test
```

## assets precompile

```
bundle exec rails assets:precompile RAILS_ENV=staging
```

## migrate

```
bundle exec rails db:migrate RAILS_ENV=staging
```

## rails server起動

```
bundle exec rails s -e staging -d
```

## rails server停止

```
ps aux | grep rails （rails s -e staging -d のプロセスidを見つける）
kill プロセスid
```


##rails コンソール
```
bundle exec rails c -e staging
```

#ちなみに
上記はstaging環境でのコマンドとなります。
production環境の場合、`staging`を**`production`**に変更すればOK。
Pythonの推薦システム向けライブラリSurpriseとFlaskでレコメンデーションエンジンを作成する

まずはSurpriseというライブラリをインストールします。

`pip install scikit-surprise`

```python:recommender.py
import json
from collections import defaultdict

from surprise import SVD
from surprise import Dataset


def get_top_n(predictions, n=10):
    '''
    予測セットに基いて各ユーザにトップN件のレコメンデーションを返す。
    '''

    # まず各ユーザに予測値をマップする。
    top_n = defaultdict(list)
    for uid, iid, true_r, est, _ in predictions:
        top_n[uid].append((iid, est))

    # そして各ユーザに対して予測値をソートして最も高いk個を返す。
    for uid, user_ratings in top_n.items():
        user_ratings.sort(key=lambda x: x[1], reverse=True)
        top_n[uid] = user_ratings[:n]

    return top_n


# まずmovielensデータセットでSVDアルゴリズムを学習させる。
data = Dataset.load_builtin('ml-100k')
trainset = data.build_full_trainset()
algo = SVD()
algo.fit(trainset)

# そして学習用データに含まれていない全ての（ユーザ、アイテムの）組み合わせに対して評価を予測する。
testset = trainset.build_anti_testset()
predictions = algo.test(testset)

top_n = get_top_n(predictions, n=10)

# 各ユーザにレコメンドされるアイテムを表示する。
for uid, user_ratings in top_n.items():
    print(uid, [iid for (iid, _) in user_ratings])

# json形式で結果を保存する。
with open('./results.json', 'w') as f:
    json.dump(top_n, f, indent=2, ensure_ascii=False)
```

```python:api.py
import json

import flask
from flask import request, jsonify

app = flask.Flask(__name__)
app.config["DEBUG"] = True
app.config['JSON_AS_ASCII'] = False

# データの読み込み
with open('./results.json') as f:
    movies = json.loads(f.read())

# ホーム
# http://127.0.0.1:5000/

@app.route('/', methods=['GET'])
def home():
    return '''<h1>シンプルな推薦システム</h1>
<p>映画レコメンデーションのためのAPIプロトタイプ</p>'''

# 全てのアイテム
# http://127.0.0.1:5000/api/v1/resources/movies/all

@app.route('/api/v1/resources/movies/all', methods=['GET'])
def api_all():
    return jsonify(movies)

# 特定のユーザIDのアイテム
# http://127.0.0.1:5000/api/v1/resources/movies?id=1

@app.route('/api/v1/resources/movies', methods=['GET'])
def api_id():
    # URLにIDが含まれているか確認する。
    # IDが含まれていれば、変数に代入する。
    # IDが含まれていなければブラウザにエラーを表示する。
    if 'id' in request.args:
        id = str(request.args['id'])
    else:
        return "エラー: IDが含まれていません。IDを指定してください。"

    items = movies.get(id)

    # 結果のために空のリストを作成する。
    results = []

    # リストに映画を追加していく。
    for i in range(len(items)):
        item = items[i][0]
        results.append(item)

    # Pythonの辞書のリストをJSON形式に変換するためFlaskのjsonify関数を使う。
    return jsonify(results)

app.run()
```

ターミナルもしくはコマンドプロンプトで
`python recommender.py`
を実行して、レコメンドするアイテム一覧を作成。

`python api.py`
を実行してFlaskアプリケーションを起動。

ブラウザで

`http://127.0.0.1:5000/`
がホーム画面

`http://127.0.0.1:5000/api/v1/resources/movies/all`
が全てのアイテム

`http://127.0.0.1:5000/api/v1/resources/movies?id=1`
がIDが1のユーザに対して推薦するアイテムのID
となります。

何かおかしな点やアドバイス等がございましたらコメントいただけますと幸いです。

参考：
https://surprise.readthedocs.io/en/stable/FAQ.html
https://programminghistorian.org/en/lessons/creating-apis-with-python-and-flask
【Yahoo!API】在庫APIエラー

Yahoo!APIを使用したシステムの開発を行っております。

テスト環境にて動作確認を行っており、以前は問題ありませんでしたが
6/24頃から以下のAPIでエラーが発生するようになりました。

・在庫参照API
https://test.circus.shopping.yahooapis.jp/ShoppingWebService/V1/getStock

・在庫更新API
https://test.circus.shopping.yahooapis.jp/ShoppingWebService/V1/setStock

・エラー内容（抜粋）
<!doctype html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Yahoo - 400 Bad Request

ちなみに注文系のAPIは正常に動作しております。

何かご存じの方がいらっしゃいましたら、ご教授お願い致します。
【記録】iPadでいちばん便利なこと：モーニングページ

iPad（Pro 11インチ）でもっともありがたいのは、
セキュアなノートがつくれること。
ふつうのノートはやっぱりいつか誰かに見られる。
生体認証で守られたiPadのなかに入っていると、
（おそらく）誰にも見られないノートをつくれる。

日記をつける習慣はないのだけれど、
ジュリアン・キャメロン女史が提唱している
「モーニングページ」をつけている。
かなり深くまで降りていってしまうので、
あまり見られる心配のあるところに
書きたくないわけ。

そんなときにiPadとGoodNotesの組合せ、最高。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/f5670456-2361-4132-de8a-17e85cd628b0.jpeg">

使い方や設定など：

+ GoodNotes 4。5もいいけれど、4のほうがレイテンシが短いと思う
+ 自動バックアップをオンにし、Google Driveの指定フォルダ格納。Goodnotes形式
+ モーニングページはひと月に1冊つくる。1月あたり約50MBとなり、これが取扱いが良いかなと思い
+ 表紙は、シェプフェル（Schoper）。iPad以前もシェプフェルで書いていたのが安定していたから
+ ノートの用紙は、基本 > 罫線
+ 1日に2ページ書いている
+ 通常は青、夢記録は緑、特定テーマは灰色など、色を分けている
+ 横置きにして、ノート幅を最大まで（手で）広げて書いている。ウィンドウモードも使ってみたけど、ダイレクトのほうが気持ち良い
 

いまのところ、ノート機能、
とくにモーニングページのためだけであっても、
iPad Proを持っていても良いと思うぐらい。
ノートとして考えると、高いけどね……
[MySQL8.0] InnoDB でinformation_schema.TABLESのAUTO_INCREMENTが古いとき 

バージョン：MySQL 8.0.16

#ALTER TABLEで変更したのに…
```ALTER TABLE テーブル名 AUTO_INCREMENT = 値```でテーブルのオートインクリメントの値を変更できます。
なのに、```SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE table_name = テーブル名```で変更前のオートインクリメントの値が取れてしまう…

#対策
``information_schema.INNODB_TABLESTATS``には変更後の値が入っていました。
```SELECT AUTOINC FROM information_schema.INNODB_TABLESTATS WHERE NAME = DB名/テーブル名 ```で取得できました。カラム名が``AUTOINC``な点に注意です。

##追記
上記はそもそも権限がなくてINNODB_TABLESTATSの情報にアクセスできない場合も多いです…。

また、それとは別に、同じ件について書いている情報がありました。→[参考](https://stackoverflow.com/questions/52705477/mysql-show-table-status-auto-increment-is-not-correct)
MySQL8.0からの仕様のようです。どうやら、information_schema.TABLESのAUTO_INCREMENTはキャッシュを取られているとか。
上記リンク先では、
```SET PERSIST information_schema_stats_expiry = 0```としてキャッシュを取らないように設定するよう書いてありました。そちらも合わせて参考になれば幸いです。

###### この記事
初投稿です。お手柔らかにお願いします。
深層学習（前編 1）：「Section4：勾配降下法」

深層学習の目的として、学習を通して出力層で発生する誤差を最小化するネットワークを作成すること、すなわち誤差E(w)を最小化するwを発見することである。そのために勾配降下法を利用してパラメータの最適化を行う。
w(t+1) = w(t) – εΔE 、ΔE = dE/dw
またΔEの計算方法として、勾配降下法、確率的勾配降下法、ミニバッチ勾配降下法がある。
勾配降下法：全サンプルの平均誤差
確率的勾配降下法：ランダムに抽出したサンプルの誤差
ミニバッチ勾配降下法：ランダムに分割したデータの集合体に属ずるサンプルの平均誤差
modelの作成と削除、Railsで指定可能なデータ型

Railsのデータベースとのやりとりを担うmodel。その作成と削除方法、Railsで指定可能なデータ型についてまとめます。

# 1.modelの作成方法
ターミナルで次のコマンドを実行すると必要なファイルを自動的に作成することができます。

```
$ rails generate model モデル名 カラム名：データ型 カラム名：データ型 ・・・
```

データ型については、後述します。
以下のファイルがcreateされます。

- app/models/モデル名.rb
- db/migrate/yyyymmddhhmmss_create_モデル名.rb


この情報でデータベースを作成する(マイグレーション)には以下のコマンドを実行します。

```
$ rails db:migrate
```

# ２.modelの削除方法
手動で作成された2ファイルを削除することもできますが、作成したファイルをまとめて削除するには次のコマンドを実行します。

```
$ rails destroy model モデル名
```

これで先程generateで作成された２ファイルは削除されます。

# 3.Railsで指定可能なデータ型

カラムを作成するときのデータ型についてまとめました。

|データ型|用途|例|
|:--|:--|:--|
|binary|バイナリデータ|画像、ファイルなど|
|boolean|Boolean|フラグ|
|date|日付|YYYY-MM-DD|
|datetime|日時|YYYY-MM-DD HH:MM:SS|
|decimal|固定小数点|1.000001|
|float|浮動小数点|1.00000234|
|integer|整数|1 , 10 ,9999|
|primary_key|主キー| |
|string|文字列|２５５文字までの文字列|
|text|長い文字列|２５６文字以上の文字列|
|time|時間|HH:MM:SS|
|timestamp|タイムスタンプ|1970-01-01 00:00:01 UTC|