OmniAICreator/Qiita-1.07M huggingface dataset:
iOSアプリでよくある上タブ作ってみた

コード：https://github.com/Yaruki00/UnderBarTabView
PodsやCarthage対応はできてないので、もし使いたい場合はファイル引っこ抜いてください:crying_cat_face:
ほら、カスタマイズしやすいし・・・ね・・・:joy_cat:

# 機能
![normal.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84917/954c5b97-80f0-eda4-a51a-52d5fec3f11f.gif)![infinite.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84917/ccc64269-6130-cfb9-30a0-79804ec0fcd0.gif)

- 現在選択している箇所に下線がつきます。
- タブのサイズは、固定と文字列によって可変の2通りから選べます。
- 無限にループするか、しないかを選べます。
- 余白やフォント、色を多少調整することができます。
- 作ったのはタブの部分だけなので、コンテンツ部分やそれとの連携は自作する必要があります。

# だいたいの作り
`UICollectionView`をベースにしており、タブの分だけセルを生成し並べています。
無限スクロールはタブを3セット用意して、スクロールのアニメーション終わったタイミングでスクロール位置を真ん中のセットに戻すことで実現しています。
余白や色、フォント等の設定は別クラスになっており、セットアップ時に渡します。

無限スクロールの参考：
https://techblog.zozo.com/entry/tab_page_viewcontroller

# 既知の問題

## セルの読み込みが遅いときがある
プログラムからタブをスクロールさせる場合(`UICollectionView`の`scrollToItem(at:at:animated:)`とか)、画面外のセルの読み込みが遅い場合があります。
どうもアニメーションが終わってから読み込みが走っているように見えますが、部分的にしか起きないしよくわからないです。わかる方いましたら是非教えて下さい！

参考(？)：
https://living-sun.com/ja/swift/824352-in-auto-scrolling-uicollectionview-cellforitematindexpath-not-triggered-by-contentoffset-swift-uicollectionview-tvos.html

## スクロールが部分的にぎこちない
無限ループするバージョンでは場所によってスクロールの速度が不自然な場合があります。
スクロール位置を調整するところでなにかおかしくなっていると思うのですが、ちゃんとした原因はまだつかめていないです。

# 役に立つかも知れない情報

## セルの座標を取得する
下線を動かす時にセルの座標を取得していますが、`UICollectionViewLayout
`の`layoutAttributesForItem(at:)`を使用することで取得することができます。

## `UICollectionView`のリロードが終わってから処理を行いたい
`UIView`の`animate(withDuration:animations:completion:)`を使用することでリロードの完了を待つことができます。`UICollectionView`のExtensionで書いておくと便利かも知れません。

```swift
UIView.animate(
    withDuration: 0.0,
    animations: {
        self.collectionView.reloadData()
    },
    completion: { _ in
        // reloadData()後に行いたい処理
    }
)
```

参考：
https://qiita.com/ponkichi4/items/d5d46556773a6bc98f9c

# おわりに
この手のライブラリは探せばたくさん見つかるのですが、勉強も兼ねて自作してみました🔧
シンプルな機能で良いのであれば自作してもそこまで手間ではないのでアリかなと思いました💡
OracleAPEX 対話グリッドと対話レポートの「アクション」メニューでできることの違いメモ

# 概要
Oracle DB APEX で、対話グリッドと対話レポートを使っているときに
「あれ？グリッドだとこの機能使えなかったっけ？」って思ったことがあったので、その時のメモ

# 環境
* Oracle Database 12c
* Oracle APEX 18.2

# 対話グリッドでできること
* 列幅拡張
* 列表示制御
* データによるフィルタリング
* ソート
* 各列ごとの集計
  * **コントロールブレーク設定後の全体の集計値の表示も可能**
* ハイライト
* チャートの作成

# 対話レポートでできること
* 列幅拡張
* 列表示制御
* データによるフィルタリング
* ソート
* 各列ごとの集計
  * **コントロールブレーク設定後の全体の集計値の表示は不可**
* **計算**
  * 列同士の算出式を設定し、新しい列を追加する。
* ハイライト
* チャートの作成
* **グループ化**
* **ピポット**

# まとめ
使ってるときに困った内容なので結論はこれ！
**ピポット機能を利用したければ、「対話レポート」を使う！**

時間があるときに各機能ごとにもう少し詳しい説明を書きたしたいとは思うが多分やらない。。。
QiitaでアウトプットしたものをWord cloudでまとめてみた

プロトアウトスタジオアドベントカレンダー10発目の記事です！

#概要
プロトアウトスタジオに入ってから、Qiitaでアウトプットするようになりました。
（まだまだ全然数少ないですが）

そこで今回は、これまでどんなもの書いたんだっけという振り返りも兼ねて、
自分がアウトプットしたものをPythonのWord Cloudで可視化していこうと思います。

##Word Cloudについて
WordCloudとは、文章の中から出現頻度が高い単語を選んで、単語の出現頻度に応じた大きさで図示していくものです。
Python用のライブラリがあるので、コードもこちらを参考にしていきます。
http://amueller.github.io/word_cloud/index.html

##スクレイピングで文章集める
Word Cloudで可視化するために、自分のQiitaをスクレイピングして、文章（材料）を集めていきます。
[自分の過去記事使いながら](https://qiita.com/sksk_go/items/b087e0855edf6167d825)

まずは記事のタグ情報を集めて可視化します。

```python:scraping.py
import urllib.request
from bs4 import BeautifulSoup

url = "https://qiita.com/sksk_go"
res = urllib.request.urlopen(url)
soup = BeautifulSoup(res, 'html.parser')
#タグ取得用に書き換え
name = soup.find_all("a",class_="u-link-unstyled TagList__label")
ret = []
for t in name:
    ret.append(t.text)

print(ret)
```
集めたテキストをWord Cloudで表現してみます。

##Word Cloudで処理
こちらの記事参考にします。
[[Python]銀河鉄道の夜をWordCloudで可視化してみた！](https://qiita.com/uminchu987/items/07baa1a354cf96d2564b)

```python:wordcloud.py
import MeCab
from wordcloud import WordCloud

data = open("data.txt","rb").read()
text = data.decode('utf-8')

mecab = MeCab.Tagger("-ochasen")
node = mecab.parseToNode(text)

data_text = []

while node:
    word = node.surface
    hinnsi = node.feature.split(",")[0]
    if hinnsi in ["動詞","副詞","形容詞","名詞"]:
        data_text.append(word)
    else:
        print("|{0}|の品詞は{1}だから追加しない".format(node.surface,node.feature.split(",")[0]))
        print("-"*35)
    node = node.next

text = ' '.join(data_text)
#除外ワード
stop_words = [ u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと', u'これ', u'さん', u'して', \
             u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した',  u'思う',  \
             u'それ', u'ここ', u'ちゃん', u'くん', u'', u'て',u'に',u'を',u'は',u'の', u'が', u'と', u'た', u'し', u'で', \
             u'ない', u'も', u'な', u'い', u'か', u'ので', u'よう', u'']
wordcloud = WordCloud(font_path='/System/Library/Fonts/ヒラギノ明朝 ProN.ttc',width=480, height=300,background_color='white',stopwords=set(stop_words))
# テキストからワードクラウドを生成する。
wordcloud.generate(text)
# ファイルに保存する。
wordcloud.to_file('wordcloud.png')
```

###できたものがこちら
![wordcloud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/478f2a8b-4efb-9b57-eec1-516d9afd640f.png)

記事の量少ないのでスカスカですね……
Python成分多めな感じ。厚めに教わったIoTなども入ってますね。

##おまけ
先ほどはタグだけだったので、自分のQiita記事の文章をとってきて、Word Cloudで可視化してみます。
![wordcloud2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/d64e95a4-5509-f451-2a37-db8866da4f54.png)

所々変な単語入ってますが、なんとなく言いたいことわかります。
やっぱPythonとか機械学習とかそっちの成分多めですね。
自分の興味もどちらかというと強いですし。傾向がわかるのではないでしょうか。

##終わりに
Qiitaを題材にWord Cloud使ってみましたが、Twitterとか、ブログとかそういう普通の文章から取ってみた方がより個性出てて面白そうですね。歌詞とか小説とかそういう文章でやってみるのも面白そう。

[aki_suga](https://qiita.com/aki_suga)さんです！お楽しみに！
Discordで特定のTwitterのアカウントのツイート更新を取得する(IFTTT/Webhook)

※本記事は2019年12月に投稿したものです。IFTTTやDiscordのUIが変わって同じような画面にならない場合があります。きをつけてね

### やりたいこと
特定のTwitterアカウントがツイートしたら取得してDiscordで通知してほしい！

### つかうもの
・IFTTT　(https://ifttt.com/)
　→Webhookのトリガー用
・Discord(通知先)

###準備　(Discord側)

・Webhookを生成する
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/a60023e0-248d-30e5-636b-2f4fba58d07e.png)
チャンネルの編集→ウェブフック→ウェブフックの作成
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/25297de8-8fd1-5970-2cdd-ce9aece982f6.png)
Webhook用のBotの名前とどのTextチャンネル向けかを指定してから
Webhook用URLをコピーしておく(Ch指定を後で弄るとURL変わるので注意)　→①
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/11b7ab32-a728-dba3-0ee2-59be3ee59b86.png)


###準備　(IFTTT側)
IFTTTにログインしてMenuからCreateを選択(アカウントを登録しておいてね)
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/72425948-dea3-edb9-301a-9cf317d34d23.png)
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/c0580f3a-a179-1eb5-ba4b-d52ef4d8ae5d.png)

”This”を選択
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/190452de-1234-4f36-3cac-1bd5ae6eac1a.png)

"Search service"にTwitterを記述して選択
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/dd7a1961-5b43-cf51-1456-f601e5cee201.png)

"New Tweet by a specific user"を選択
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/91dc96ff-9fb5-cf00-143c-e70fba21be29.png)

Watchしたい特定のユーザーを記載、Create Trigger
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/fd21908c-6c1d-8010-912f-66bcedf9d7c4.png)

Thatを選択
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/b212673e-7bfb-d15c-5820-8ffbf07e7e3f.png)

"Webhooks"、"Make a web request"を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/29948bb4-0a66-fdde-9dea-ad1fc3d12534.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/42631287-a1e5-5732-43c7-09a535267dff.png)

URL　　　　　　→①をペースト
Method　　　　 →Post
Content Type　　→”Application/json”
を記載
![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/854ac821-c77f-ae4b-c8b0-4962eb15eeaa.png)

Body →　以下を記載する(ここは自由に一応いじれます)
```{ "content":"@{{UserName}} {{LinkToTweet}}" }```
例えばこんなのが入れられる
UserName　　→ TriggerしたアカウントID
LinkToTweet　 → ツイートのリンク
CreatedAt 　　→日時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45721/d4d6d17a-eb1d-779c-e630-76cff2e74d42.png)

CreateしてFinish
ほっとくと通知が入ってくると思います

※特定のアカウントのTweetをすべて取得するため
RT，リプライ等も通知に拾われてしまいます。
リプライやRTを制御したい場合はマイナス検索をかけた
”New Tweet form search”等をつかおう！
```(from:ユーザID) -filter:links -filter:replies```

おわり
初心者によるプログラミング学習ログ 179日目

# 100日チャレンジの179日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

179日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>179日目<br><br>webサイトコーディング課題<br>フッター作成（途中）<br><br>テンションあがらずあんまりできなかった<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1203767712003969024?ref_src=twsrc%5Etfw">December 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
CTF例題のデータベース脆弱性まとめ

年末年始大学授業も忙しくて、セキュリティノートを書くことをずいぶん忘れてしまった。

**データベースをめぐるセキュリティホール、脆弱性などセキュリティ問題は、ほとんどSQLインジェクションでしょう。**

#mysql
default port：3306
攻撃手法：
1,弱いパスワード、デフォルト設定そのまま使う:アカウント名：'localhost'@'@''　パスワードは任意
2,DOS攻撃（shellおよびHigh権限が必要）
3,CVE-2012-2122など

#PostgreSQL
default port：5432
攻撃手法：
1,弱いパスワード設定： postgres postgres
2,buffer-overrun（バッファオーバーラン）：CVE-2019-10164
3,CVE-2014-2669
4,CVE-2018-1058など

#Oracle
default port：1521
1158
8080
210
それぞれは、データベースポート、Oracle-EMCTL、Oracle-XDB、Oracle-XDB FTPサービス。

問題点：パラメータの設置ミス：
1,UTL_FILE_DIRは*にする（この場合、攻撃者は既知のorapworclファイルを入れ替え、低権限ユーザーもSYSパスワードを再設置できる）
2,AVASYSPRIV
EXECUTE ANY PROCEDURE
DBMS_IJOBそれぞれは低権限ユーザーに与えてしまう。

**対応**：
OSファイルへのアクセス用変数（もしくはパラメータ）、書き込みなど、禁止or削除
マニュアルに従って設置する（人間はセキュリティの最大の弱点）
ペネトレーションテスト、ツールを使い、定期診断を行う。

#参考文献：
https://docs.oracle.com/cd/E16662_01/doc/timesten.1121/b56057/accesscntl.htm
65日目 Jupyter notebookでグラフを描くためにmatplotlibをインストールしました。

#Jupyter notebookでmatplotlibを使ってみます。

importしてみると・・・

![スクリーンショット 2019-12-09 19.51.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/a006c74b-b6cf-b553-c777-ea0f9a956820.png)

あら、はいっていません。

matplotlibで調べると、いろんなグラフのサンプルがありました。おもしろそうなのでダウンロード。後でみてみます。

[Tutorials This page contains more in\-depth guides for using Matplotlib\. It is broken up into beginner, intermediate, and advanced sections, as well as sections covering specific topics\.](https://matplotlib.org/tutorials/index.html)

##matplotlibをインストール
```
$ conda install matplotlib
Collecting package metadata (current_repodata.json): done
Solving environment: / 
The environment is inconsistent, please check the package plan carefully
The following packages are causing the inconsistency:

(以下略、7分後)

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
$ 
$ pip list | grep matplotlib
matplotlib                         3.1.1     
```
いい感じです。

##Jupyter notebookを起動して、matplotlibを呼び出します。

![スクリーンショット 2019-12-09 20.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/46e3d848-5cec-4608-cde5-118398a3695c.png)

font cache を作るからちょっと待ってねってメッセージがでます。ちょっとってどのくらいでしょう。とりあえず５分待ってみました。

とくに変化はないので、とりあえず次へ。

##グラフを書いてみます。

![スクリーンショット 2019-12-09 20.37.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356263/5f607012-d0b9-e3d7-dd55-bb911b5b69de.png)

###グラフができました！
(１時間）
AndroidでKinesis Video Stream のWebRTC機能を試す

（雑ですが備忘録です）

## ビルド＆実行
以下のGithubに沿ってCognitoの設定を行い、サンプルコードをビルドする。
https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-android

Master起動後に、別のAndroid端末でViewerを起動すると、ビデオ通話ができました。

また、Kinesis Video Streams のSignaling Channelsから、CloudWatchのログ等が確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102681/e4a8d47c-7b7a-c008-3971-baf975d8966b.png)


## コード上のメモ

### チャネルARNの取得

```java
mChannelArn = describeSignalingChannelResult.getChannelInfo().getChannelARN();
```
```
Channel ARN is arn:aws:kinesisvideo:ap-northeast-1:123456789:channel/demo-channel/1575874258965
```
ARNの末尾の `1575874258965` はUnix Time Stampぽいです


### Endpoint 取得

上記のARNやロール（MasterかViwerか）を設定し、リソースエンドポイントを取得しています。

```java
                GetSignalingChannelEndpointResult getSignalingChannelEndpointResult = awsKinesisVideoClient.getSignalingChannelEndpoint(
                        new GetSignalingChannelEndpointRequest()
                                .withChannelARN(mChannelArn)
                                .withSingleMasterChannelEndpointConfiguration(
                                        new SingleMasterChannelEndpointConfiguration()
                                                .withProtocols("WSS", "HTTPS")
                                                .withRole(role)));
```

```
{ResourceEndpointList: [{Protocol: WSS,ResourceEndpoint: wss://<id>.kinesisvideo.ap-northeast-1.amazonaws.com}, {Protocol: HTTPS,ResourceEndpoint: https://<id>.kinesisvideo.ap-northeast-1.amazonaws.com}]}
```
こちらで取得したHTTPSのエンドポイントを使って、`AWSKinesisVideoSignalingClient`のインスタンスを作成し、ICEサーバーの情報を取得しています。

### ICE Server list
```
getIceServerConfigResult.getIceServerList()
```
手元で出力されたログをみたところ、2つのIPをturnを使って取得しているようでした。

```
{Uris: [turn:12.34.56.78:443],Username: xxx,Password: XXX,Ttl: 300}
{Uris: [turn:23.45.67.89:443],Username: yyy,Password: YYY,Ttl: 300}
```

``` java:WebRtcActivity.java
        PeerConnection.IceServer stun = PeerConnection
                .IceServer
                .builder(String.format("stun:stun.kinesisvideo.%s.amazonaws.com:443", mRegion))
                .createIceServer();
        peerIceServers.add(stun);

```
Stun サーバーについてはは、リージョンごとに固定のエンドポイントを指定しています。
上記の情報等を用いて、 `PeerConnectionFactory.createPeerConnection()`でピア接続を行います。
FreeDOS上からBitVisorを起動する

以下の記事ではUSBメモリーにGNU GRUBをインストールして使いましたが...
https://qiita.com/hdk_2/items/c5b8eefcb925412da3ee
方法を知らない方もいらっしゃるかも知れません。より簡単に、FreeDOS上からBitVisorを起動する方法がありますので紹介します。

まず、GRUB4DOSをダウンロードしてFreeDOSからアクセスできるところに展開します。長いファイル名が見えないのでディレクトリ名も短くしておくといいと思います。

https://sourceforge.net/projects/grub4dos/

次に、grub.exeと同じディレクトリに置かれているmenu.lstというファイルを消すか、または、名前を変えて、新しくmenu.lstファイルを作ります。中身は以下のような感じでOKです:

```
title BitVisor
  find --set-root /bitvisor.elf
  kernel /bitvisor.elf
```

/bitvisor.elfのところは、もしルートディレクトリに置いていない場合は適切なパス名に変えておきます。ここでは長いファイル名が使えるはずです。(長いファイル名の短い版は逆に使えないかも知れません。)

そして、FreeDOSを起動する際に、仮想8086モードを使う拡張メモリードライバーは組み込まないようにします。デフォルトのFDCONFIG.SYSを使っているのであれば、以下の画面で3か4を選べば良いはずです:
![aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103733/fcd0a6fc-703e-31bb-1b33-0a50780c4574.png)

そして、FreeDOSが起動したらGRUB4DOSのディレクトリのgrub.exeを起動すると、ちょっと懐かしいGNU GRUBっぽい画面が出てきて、BitVisorを起動することができます。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103733/2ecc2597-689d-8fb8-b871-0d76d28505e7.png)
脆弱性診断をやってみよう（前編）

# はじめに

12月のくせに飲みに行くのが少ないなーと思っている今日この頃。
鬼滅の刃に手を出してしまいました。善逸が好きです。

今日は脆弱性診断について書きます！（本業がセキュリティなのでそろそろ）
1つの記事にすると長くなるので2部構成にしますね。
前編は脆弱性診断の紹介です。コマンドなどの技術的な要素はございません。

# 脆弱性診断ってなんなの
サーバやPC上にある脆弱性を見つけるためにツールを使ってあれこれ処理をかけること。
「脆弱性診断」というビジネスをやっている会社様は結構あります。
診断自体をウリにしていたり、診断結果を受けてソリューションの提案へつなげる（ドアノック）などやり方は様々です。


# ツールの種類
脆弱性を調査できるツールはたくさんあります。

- 有償
    - Rapid7、Nessus etc
- 無償
    - Nikto、OpenVAS etc


# できること
言うまでもありませんが「脆弱性を見つけること」です。
ただし、対象領域（OS、ミドルウェア、アプリケーションなど）に注意が必要で診断できる・できないや得意・不得意があります。
何を診断するかによってツールを使い分けることが大事ですね。

# おわりに
脆弱性診断についてざっと紹介しました。
構築したサーバとか作ったアプリって意外とセキュリティ面はザルだったりします。
ぼくたちエンジニアはインフラ・アプリ問わず「ものを作れる」は当たり前で、
あるべき姿は「**最適な**ものを作れる」だと思っています。
機能なり設定なり過不足なく作れるようになってスタートラインですよね。
そういった気づきにつながればいいなと思います。

後編では実際にツールを使ってみます！さようなら！
ビッグデータ分析業界での様々な職種と私の今後のキャリアについて

#はじめに
初めまして！
主にデータアーキテクトとして仕事をしているヒロリーと申します。

これまでに
・コンビニ系共通ポイントカードのデータ戦略チーム
・メガベンチャーWebサービスでのビッグデータ活用PJTチーム(総合EC事業会社、予約系サービス事業会社)
・ゲーム事業会社でのデータ戦略チーム
などで働いてきました。

様々な業種で企業内ビッグデータのデータ活用部門を経験してきた上で
今後のビッグデータに関わるエンジニアの方向性について書いて行こうとお思います。

#データサイエンス職種の細分化
[データ系職種の色々](https://qiita.com/msdtakashi/items/8ae653b4f7ef3dccc6d7#%E5%85%A8%E5%93%A1%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89%E3%81%82%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%E3%81%AE%E3%81%8B)
こちらの記事で　
@msdtakashi
さんが書いていただいたようにデータ界隈といっても様々あります。

>チーム・データサイエンス
- クライアントや社内の他の部署との調整をするAIコンサルタント
- 分析用のサーバを構築したりデータ基盤を管理するデータエンジニア
- 高度な統計学や数理モデルを用いて問題を解決するデータサイエンティスト
- ビジネスサイドからデータで課題を解決するデータアナリスト
- データの可視化を行い多くの人にデータの姿を伝えるBIデザイナー
- データの管理を行い皆が作りやすいように管理するデータアーキテクト

一般的には「データサイエンティスト」というと
上記の区分の中でデータサイエンティスト兼AIコンサルタント
のイメージが強いのではないでしょうか？

現在、データサイエンス系案件において、
高度な統計学や数理モデルを開発改良していく、ポジションは凄く少ないです。

これはマシンラーニングなどで未来予測をする段階には、
多くの企業が到達していないという現状があります。

#ビッグデータ活用プロジェクトの種類
ビッグデータ活用系のプロジェクトには２段階あります。
・現状把握のシステム化
・未来予測のシステム化
未来予測の１段階前の現状把握を効率化するためのツールがBI(Business Intelligence)ツールです。

BIツールの例(Tableau)
![営業ダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125159/8ada9adc-19dc-c157-61ed-d0050b75d43e.png)


私は、AIとBIは補完関係にあると考えています。
 
BIツールが運用されていてKPIに関するデータが一元管理されているデータウェアハウスがあれば
AIプロジェクトは教師データが作成しやすくなりスムーズに進みます。
 
AIツールがあったとしても、AIで導き出したデータを施策判断に活かすためには、
チームメンバーが毎日チェックできる、BIダッシュボードが無ければAIの真価をフル活用できません。

# 今後どのような方向性でキャリアを構築して行こうと考えているのか？

まだまだ、人の直感と全体感を掴む能力はAIには負けてはいないと思います。
課題に対してBIでこと足りることを考え仕分け、
本当にAIを使うべき場所を見極めていくのが今後重要になっていくと考えています。

それなので、私は今後の方向性としては
「データアーキテクト」と「BIデザイナー」のスキルを伸ばしつつ
「AIコンサルタント」
ビッグデータ処理インフラの開発、管理をする「データエンジニア」
を磨いて行こうと考えています。

データサイエンス系プロジェクトで働く仕事人を目指すみなさんには
データサイエンティストの職種を細分化して捉えた上で、
自分にとって合う今後のキャリアを考えていっていただきたいです。

最後までお読み頂きありがとうございました！
技術ポートフォリオを作った話

つい先月，自分のgithubアカウントで技術ポートフォリオを作成した．→　[**tackkyのポートフォリオ**](https://tackky.github.io/portfolio/)
どうしてgitもhtmlも慣れていないのに作ろうと思ったのか，その辺の話も含めて記事にする．

## 技術ポートフォリオは何に役立つ？
### 1. 就活で使える
#### 1. 逆求人
これが一番大きい.  特に最近IT系の就活では逆求人(企業様の方から連絡が来る就活)で，まず自分の情報を見ていただく．  
例えば，

- 研究室での研究内容
- 資格，その他技術的にやってきたこと
 
など．この場合，研究内容だけ突き詰めて研究している方ならそこを詳しく書けばいいけれど，私などのようにいろんな技術をつまみ食いしているような人には不利になる．githubで公開リポジトリーとしてアップするという手もあるけれど，やはり就活では技術に詳しくない人事の方も見ているので，見た目にも綺麗なwebページが一番企業様へのインパクトは大きい．

#### 2. エントリーシート
このような目的で作成されたポートフォリオは，エントリーシートの作成にも役立つ．
研究内容にも言及していれば，そのポートフォリオ記事を参考に書くことができるし，アピールポイントにこのページのURLを貼ることができる．(後たまに，技術ポートフォリオがあれば教えてくださいみたいな欄があることがある)

### 2. 勉強になる
最後に，HTMLとCSSを使うので何より勉強になる．私は研究室や講義でHTMLは兎も角CSSは使用したことはないけれど，技術ポートフォリオを作ることはHTMLとCSSの使用経験につながる．


## 技術的観点から
### GitHub
技術者になる者，Github含め，Gitは使えるようになった方がいい．私は研究を他の人と共同でやっていないので研究室としてgitを使用することはないけれど，バージョン管理システムとして少し前から使い始めた．特に共有する相手がいなくてもgitはおすすめ．よく考えなくてもgitは **バージョン管理システム**である．私が最近使用しているgitの使い道が参考になるかもしれない．

- 理由１　論文を書くときにも使える．  
参考URL：[ライトに知りたい人はこちら](https://fromatom.hatenablog.com/entry/2014/02/09/001136)  ，[しっかり読みたい人はこちら](https://www.jstage.jst.go.jp/article/isciesci/61/10/61_394/_pdf)  
> [ナウいヤングは論文執筆にGitHubを使う](https://fromatom.hatenablog.com/entry/2014/02/09/001136)
> まず、学会や学校などのテンプレートを導入して正しくコンパイルされる状態にしたものをfirst commitとしてmasterブランチにコミットします。
> 次にmasterから1stブランチを切って、GitHub上でmasterブランチにPull Requestを送ります。
> PRを送ったら、1stブランチでガリガリ初稿を書いていきます。コミットの粒度は小節毎だったり段落ごとだったりしますが、これは執筆が進んでいくと変わっていくと思います。後半になると修正箇所も少なくなるので「○○先生添削分修正」などとふわっとしてきます。
> 添削の依頼をして返ってきたら、1stブランチをmasterにマージします。そして2ndブランチを切ってPRを送って……の繰り返しです。

- 理由２　スライド管理にも使える．
様々な版(学会用，卒業発表用等)とわけることができる．次のページがわかりやすすぎるので説明は割愛．  
参考URL：[ここのページからスライド管理するようになった](https://qiita.com/kyusque/items/fd7a2287662298b9b949)

### HTMLとCSS
…ざっくり仕組み使えるようになりたいなって思ってた，それだけです．講義で扱うのはHTMLだけなのでやっぱり心寂しい．

## 技術ポートフォリオの作り方
作ってみた流れ．

### 1.githubでページを作る
GitHub Pagesというサービスがある．これは，Githubに登録したリポジトリーをwebページとして公開することができるGitHubのサービスである．`setting`に`github pages`の項目があるのでそこでソースをマスターブランチに登録するだけである．とりあえずhello worldとでも書いた`index.html`を用意して公開すればいい．

一応：[github pagesによる静的サービス公開方法](https://www.tam-tam.co.jp/tipsnote/html_css/post11245.html)


### 2.サンプルページを探してくる
結構フリーでHTMLとCSSのソースは落ちている．特に`template free engineer portfolio`とでも検索すれば，ごまんとフリーテンプレートが見つかる．私は以下のサイトから見つけてきた．(確か．)
[50 free portfolio website templates 2019](https://colorlib.com/wp/cat/portfolio/)

### 3.自分仕様に変更する
後はダウンロードしたデータを自分仕様にカスタマイズするだけだ．先のテンプレートサイト等には結構な量のデータがあるので，私のような初心者エンジニアにはいらない部分が多すぎる．なので「*いらない部分を削る*」作業が必要になる．これには，どこからどこまで削っても問題なく動作するのか判断するために，HTMLの構造を理解している必要がある．CSSは色のテイストや配置などを変えたくなってから触る方が楽なのでとりあえず置いておいて，`HTML`→`CSS`の順でカスタマイズするのがおすすめ．




## おめでとう！
ここまでのプロセスでやっと技術ポートフォリオをつくることができる．新しいことに取り組むことがあれば，どんどん追加して素晴らしいポートフォリオにしよう．


## 参考サイト
[エンジニア向けのポートフォリオサイトまとめ](https://qiita.com/turmericN/items/37c3fbe00ee6bbc7e201)
[ポートフォリオをGitHub で公開する](https://qiita.com/0622okakyo/items/e911b6ca26f45d4f5e37)
【Rails】画像のパスを指定する

Railsアプリを作成中、画像パスの指定でつまづいたのでメモ

## 前提
sass-railsを使っている。（デフォルトで入っていた）
画像は`app/assets/images/`or`public/`に保存。

## HTMLから指定
htmlの`img`タグを使って、`<img src='assets/{ファイル名}'>`のような指定もできますが、何かと不具合が起きやすいので`image_tag`を使うようにしましょう。

### `app/assets/image/`以下の画像
`<%= image_tag '<ファイル名>'`で指定。

```erb
<%= image_tag 'logo.png' %>
```

または`src="/assets/<ファイル名>"`で指定

```erb
<img src="/assets/logo.png" alt="">
```

### `public/`以下の画像
`<%= image_tag '<publicディレクトリからの相対パス>'`で指定

```erb
<%= image_tag '/logo.png' %>
```

## Sassファイルから指定
### `app/assets/image/`以下の画像
`image-url('<ファイル名>')`で指定

```app/assets/stylesheets/style.scss
h1 {
  background-image: image-url('logo.jpg')
}
```

### `public/`以下の画像
```app/assets/stylesheets/style.scss
h1 {
  background-image: url("/images/hogehoge.png");
}
```


## その他
開発者が用意するファイルは`app/assets/images/`に保存して、`public/`にはユーザーがアップロードした画像とかを保存する、といった使い分けが一般的なようです。

## 参考
[Rails で背景に画像を表示したいのですが取り込み方を教えてください。](https://teratail.com/questions/106200)
[Railsで扱う画像はassetsとpublic、どちらに置くといいのでしょうか？](https://teratail.com/questions/16345)
Python 例外クラス一覧

```
BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      |    +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

```
windowsバッチ関連の参考URL

個人用のメモです。
僕が初学者なので、初学者の人が読んでわかるリンクを載せています。
日々更新します。

- *ファイルから文字列を読み込む*

[https://jj-blues.com/cms/wantto-readstringfromfile/](https://jj-blues.com/cms/wantto-readstringfromfile/)

- *特定箇所の文字列を抜き出す*

[https://web.plus-idea.net/2016/09/windows-bat-substr/](https://web.plus-idea.net/2016/09/windows-bat-substr/)

- *ファイル内の文字列置換*

[https://jj-blues.com/cms/wantto-replacestring/](https://jj-blues.com/cms/wantto-replacestring/)

- バッチファイルからteratermマクロ実行

[http://www.illinternet.com/2017/06/24/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8B%E3%82%89%E3%80%81teraterm%E3%81%AE%E3%83%9E%E3%82%AF%E3%83%AD%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B/](http://www.illinternet.com/2017/06/24/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8B%E3%82%89%E3%80%81teraterm%E3%81%AE%E3%83%9E%E3%82%AF%E3%83%AD%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B/)
スクレイピング事例4選 | スクレイピングの活用事例をご紹介

####Webスクレイピングとは？
Wikiで[Webスクレイピング](https://jp.scrapestorm.com/)がWebクローラと呼ばれるのを記載します。実際に、両者にはちょっとだけ差別があります。スクレイピングと[クローリング](https://jp.scrapestorm.com/)はどちらもインターネット上の情報を収集することですが、[スクレイピング](https://jp.scrapestorm.com/)は取得した情報の加工ができます。より詳しくデータを抽出すると、より深いデータ分析を行います。
データスクレイピングは今様々分野に活躍しています。これから、幾つかの[ScrapeStorm](https://jp.scrapestorm.com/)のスクレイピング活用事例を紹介します。
####1.Google/Yahoo
SEOとは、“Search Engine Optimization”の略で、検索エンジンに向けてWebサイトを最適な状態に近づけること（検索エンジン最適化）を意味します。自分のサイトを検索エンジンに上位表示させるため、キーワードの収集は不可欠です。[Webスクレイピング](https://jp.scrapestorm.com/)を通じて、検索エンジンでキーワードのトップを収得できます。自分もよくGoogleまたはYahooでキーワードをスクレイピングして、競争者サイトはどんなキーワードを持っていますか、今人気があるキーワードは何ですか、ユーザさんはよく検索するキーワードにも、スクレイピングされたデータから分析できます。
**[複数のGoogle検索結果URLをスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-multiple-urls-from-google/)**
**[Yahooの検索結果をスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-search-results-from-yahoo/)**
![alt](https://jp.scrapestorm.com/wp-content/uploads/2019/12/Google.png)
####2.ネットショッピング
ネットショッピングは人々に大歓迎される以来、Amazon、Yahoo！ショッピング、楽天市場、色々なネットショッピングサイトが我々の日常生活に進入します。ではデータ収集はネット通販でどのような役割を果たしているのでしょうか？買主にとって、お金を節約、価格の比較は一番関心になるでしょう。スクレイピングを通じて、全ての目標商品の価格を取得します。売り手にとって、価格の監視、商品詳細、商品レビューなどの収集はマーケティングに大切なものです。
**[Amazonの商品価格をスクレイピングして監視する](https://jp.scrapestorm.com/tutorial/how-to-scrape-and-monitor-amazon-product-prices/)**
**[楽天市場から商品最安価格をスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-product-lowest-price-from-rakuten/)**
![alt](https://jp.scrapestorm.com/wp-content/uploads/2019/12/Amazon.png)
####3.株価指数
株式市場は目まぐるしく変動しています。定時的に株価指数を収集する、MySQL、SQLサーバーにエクスポートすることもできます。リアルタイムで株価指数を把握します。Yahoo！ファイナンスで株価予想と言う項目があります。株式の数か月以来のデータと予想を分析して、株式の購入に役立つかもしれません。
**[株価投資メモで複数のURLから株価指数をスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-stock-index-from-multiple-urls-with-kabukatoushimemo/)**
**[Yahoo!ファイナンスから単元株価格上位情報をスクレピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-unit-stock-price-top-information-from-yahoo-finance/)**
![alt](https://jp.scrapestorm.com/wp-content/uploads/2019/12/yahoo%EF%BC%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%8A%E3%83%B3%E3%82%B9.png)
####4.ホテル情報
自分も旅行好きですが、旅に行く前の準備は十分面倒だと思います。特にホテルの選択は、旅行に大きな影響を与えるでしょう。ならば、どうやって適当なホテルを選択するか？これがスクレイピングの番だ！ホテルの施設、近頃の交通、駐車場、朝食など、全部手に入れます！
**[Bookingからホテル情報をスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-hotel-data-from-booking/)**
**[Tripadvisorからホテル情報をスクレイピングする](https://jp.scrapestorm.com/tutorial/how-to-scrape-hotel-information-from-tripadvisor/)**
![alt](https://jp.scrapestorm.com/wp-content/uploads/2019/12/%E3%83%9B%E3%83%86%E3%83%AB.png)
価格監視や研究用途、情報分析するといった際に必要なデータを収集するのにスクレイピングが活躍します。今回は、SEO、E-コマースなどの活用事例を紹介しますが、もちろん、以上の領域しかありません。一つ注意すべきところがありますが、スクレイピングで悪意のあるリクエストを送ることはダメです！正しい容量・用法を守った上で利用してみてください。
The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. 

### 現象

次のようにJaCoCoのレポート対象から特定のクラスを除外している場合に、

```gradle
    jacocoTestReport {
        reports {
            html.enabled = true
            xml.enabled = true
        }
        afterEvaluate {
            // 自動生成されるクラスをカバレッジ集計対象から除外
            classDirectories = files(classDirectories.files.collect {
                fileTree(dir: it, exclude: [
                    '**/_*.class', '**/*DaoImpl.class'
                ])
            })
        }
```

Gradle 6.0で `JacocoReportBase#setClassDirectories` は廃止されるよと警告されます。

```
The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...)
        at build_e2otrmuro5f5yvbdc9709fstk$_run_closure1$_closure10$_closure16.doCall(/path/to/build.gradle:46)
        (Run with --stacktrace to get the full stack trace of this deprecation warning.)
```

### 確認環境

* macOS 10.13.6
* Gradle 5.1
* JaCoCo 0.8.4

### 修正方法

警告メッセージの示す通り、 `JacocoReportBase#getClassDirectories` を使って書き換えます。Gradle力が低くて、警告メッセージの通り修正するだけでも毎回ググっている気がする…

```diff
diff --git a/build.gradle b/build.gradle
index 54b418e84..be6bd6966 100644
--- a/build.gradle
+++ b/build.gradle
@@ -43,7 +43,7 @@ allprojects { subproj ->
         }
         afterEvaluate {
             // 自動生成されるクラスをカバレッジ集計対象から除外
-            classDirectories = files(classDirectories.files.collect {
+            classDirectories.from = files(classDirectories.files.collect {
                 fileTree(dir: it, exclude: [
                     '**/_*.class', '**/*DaoImpl.class'
                 ])
```
Civictechで活動することの意義について書いてみました。

#CivicTechアドベントカレンダー9日目です。
##今回は実際に起きていることを主題にしたいと思います。
私は実際に実はだんまりで熊本地震から災害ボランティアとして復活しておりました。
その時は文字で支援ばかりしていたのですが。
今年の9月の台風15号のとき思ったのですが文字情報が多くて重要な情報が得られないんじゃないかと思いました。
自分での主導で初めてクライシスマッピングを行いました。
当初は10人ぐらいだったんですが。
やはり文字情報からの洗い出しが難しく最終的には自分ひとりのボッチ活動となってしまいました。
<strong>今後必要なのはクライシスマップをもとにしたクライシスマネージメント</strong>と自分は思っています。
DRONBIRDチームの発足により被災地域の情報はわかるようになりましたが。
実は本来必要となる被災地の避難所情報や給水所や充電設備などの情報が文字氾濫してもう見るに耐え難い状況だったので自分が先頭に立ったわけですが。
<strong>本来これは実際はFacebook災害支援グループの立ち上げサイドが人を募り作業を始めるべき</strong>と自分は思っています。
今回自分も運営側でもあったので動きましたが。
クライシスマネージメントはしっかりと運営者側が主導権を取るべきだと思います。

ここで消防団時代の先輩方々から学んだ言葉を書いておきます。
大垣消防団北分団伊藤元分団長・高橋分団長・山田部長並び先輩及び同期後輩の方々ごめんなさい。
こんな大きい場所で書いてしまい申し訳ございません。
重要なことなのであえて書かせていただきます。
お叱りはもちろんお受けいたします。
<strong>ボランティアというものは本業ができてこそのボランティアであって、本業をそっちのけでボランティアするんじゃない。</strong>
と毎回教えていただいていました。
今もこの言葉をもとに活動しております。

これってCivicTechにも言えることだと自分は思っています。
ボランティアしなくちゃいけないから帰りますと本業では言ってはいけません。
いくら遅れてでもいいので本業を優先すべきというのもボランティアのうちであることを常に考えてください。
優先順位はCivicTech（ボランティア）ではなく本業です。
本業なくしてCivictechもといCivicハッカーまたはボランティアは成り立ちません。

たまにボランティアが優先で本業そっちのけの人よく見かけます。
それって本当に大切なことですか？
自分実は9月最後の方に実は千葉に移住しようかなと思ったことがありました。
立正大学後藤先生が<strong>Civictechを本業にしちゃいかん</strong>とお叱りをいただきました。
今は自分はフロントエンドエンジニアとして仕事をいましていますが。
本業もボランティアもCivicハッカーも誰一人としてかけてはいけないと思います。

今後もFacebookの災害対応グループやクライシスマップの作業向上に向けての作業をしていくつもりです。
本当に<strong>誰一人もかけてもボランティアやCivicTechは成り立ちません</strong>
皆様の協力があっての活動だと自分は思っています。
強制ではありませんし自分がやりたいという気持ちで進んでいきましょう。
ガチな活動もしておりません。
ゆるふわな感じで皆さん頑張っていきましょう。
BigQueryの関数の返す型を調べる

BigQueryを使っていて気持ち悪いのは、関数の返り値の型がマニュアルに書いていないことが多い点です。

たとえば`SIGN`関数の説明は次のようなものです。

> SIGN(X)
>
> 負、ゼロ、正の引数に対してそれぞれ -1、0、+1 を返します。浮動小数点引数では正と負のゼロは区別されません。NaN 引数に対しては NaN を返します。

これだけでは `SIGN(0.0)` の返り値の型が何なのかはわかりません。INT64を返すのかFLOAT64を返すのか考えると夜も眠れませんね。また、引数の型がNUMERICの場合はどうなるのでしょうか。

そもそもSQL言語全般の特徴として暗黙の型変換により型を意識しなくても不便しないことが多いわけですが、未知のバグを作らないためにも型を調べておくことは大事だと思います。

## 型の調べ方

関数の返り値の型が何かは次のような方法で調べられます（絶対もっといい方法があると思うんだけどわかりませんでした…）。

```sql
SELECT 1 AS id, [1] feature UNION ALL
SELECT 2 AS id, SIGN(0.0) AS feature
```

これを実行すると次のようなエラーが表示されます。

> Column 2 in UNION ALL has incompatible types: ARRAY<INT64>, DOUBLE at [2:1]

暗黙の型変換ができない型とUNIONしてエラーを出せば、エラーメッセージから関数の返り値の型がわかるというわけです。この場合なら`SIGN(0.0)`はFLOAT64型を返すとわかります。

また、次のように`SIGN`関数の引数にINT64型とNUMERIC型を引数に取ってみると、返り値の型がそれぞれINT64とNUMERICだとわかります。

```sql
SELECT 1 AS id, [1] feature UNION ALL
SELECT 2 AS id, SIGN(0) AS feature
```

> Column 2 in UNION ALL has incompatible types: ARRAY<INT64>, INT64 at [2:1]

```sql
SELECT 1 AS id, [1] feature UNION ALL
SELECT 2 AS id, SIGN(CAST('0.0' AS NUMERIC)) AS feature
```

> Column 2 in UNION ALL has incompatible types: ARRAY<INT64>, NUMERIC at [2:1]

`SIGN`関数は引数の型と返り値の型が同じになることがわかりました。やりましたね。

ちなみに、BigQueryの数学関数の多くはINT64型とFLOAT64型が引数のときはFLOAT64型を返し、NUMERIC型が引数のときはNUMERIC型を返すようです[^1]（例：`ROUND()`）。

[^1]: 単にINT64を引数に取る定義がなくて引数の時点で暗黙の型変換でFLOAT64に変換されているものが多い

## JSON_EXTRACT_SCALAR関数の返す型

`JSON_EXTRACT_SCALAR()`というJSON文字列から値を取り出す関数があるんですが、こいつの型も調べてみました（というかこれを調べたくてこんなことをしていた）

```sql
SELECT JSON_EXTRACT_SCALAR('{"num": "1"}', '$.num')
SELECT JSON_EXTRACT_SCALAR('{"num": 1}', '$.num')
```
上の結果って前者がSTRING、後者がINT64を返しそうな気がしませんか？実際はどちらもSTRINGが返ってきます。冷静に考えたらそりゃそうよねって話でした。
Elixir で Parameterized test

>[個人ブログにも転載しています](https://metareal.blog/post/2019/12/09/parameterized-tests-in-elixir/)

ユニットテストの現場では、一部のパラメータだけが異なるコピペが見過ごされがちで、コードを保守する立場にとってはテスト対象のコードよりも頭が痛い存在だ。こういうテストは異なるパラメータのパターンのみを記述して、他のコードは使いまわしたい。いわゆる Parameterized test というやつである。

## 既存の手法

Elixir の ExUnit は標準の Unit Testing ライブラリとして非常によく出来ているが、残念ながら Parameterized test の仕組みは用意されていない。

[KazuCocoa/ex_parameterized](https://github.com/KazuCocoa/ex_parameterized) を試してみたこともあるのだが、記法が変則的（こうなる理由も分かる）なのと、[パラメータを評価する部分で動かないコードがある](https://github.com/KazuCocoa/ex_parameterized/issues/19)ので採用を見送っている。

## いま採用している手法

結局、いろいろ試した末、いまは[このようなコード](https://gist.github.com/ishikawa/2ad8c415c2a5b6a619e99c18870d6392)に落ち着いている。

```elixir
# 1. The helper functions for the test module. To make it possible to import
# this helper module in the test module, define this module outside the context that uses it.
defmodule MyTest.Helpers do
  @spec fake_params(Enumrable.t()) :: map
  def fake_params(override \\ %{}) do
    %{
      country: "jp",
      phone_number: Faker.phone_number(),
      locale: "ja",
      company: "My Company",
      department: "My Department",
      email: Faker.Internet.email(),
      first_name: Faker.Name.first_name(),
      last_name: Faker.Name.last_name()
    }
    |> Map.merge(Map.new(override))
  end
end

defmodule MyTest do
  use MyApp.ConnCase

  # Because I'd like to use functions in the helper module both in parameterized cases and
  # test cases, alias and import it.
  alias MyTest.Helpers
  import Helpers

  describe "signup" do
    for {description, signup_params} <- [
          # 2. You cannot invoke functions in the testing module which is not defined yet.
          # So we need the helper module.
          "all filled": Helpers.fake_params(),
          "department can be omitted": Helpers.fake_params(department: nil),
          "department can be null": Helpers.fake_params() |> Map.delete("department")
        ] do
      # 3. You cannot use variables in this context in the context inside a test case.
      # So you have to use module attributes or `@tag` feature in ExUnit. Personally,
      # I prefer the latter.
      @tag signup_params: signup_params
      test "no errors: #{description}", %{conn: conn, signup_params: signup_params} do
        # ...
      end
    end
  end
end
```

なんでこうなってるかはコメントの通りで紆余曲折あるのだが、

1. ヘルパー関数を定義するモジュールはテストのモジュールの外側で定義する。なぜなら、そうしないと `import` できないから。もちろん、`import` しなくてもいいのだが、テストコードからノイズはできるだけ減らしたい
2. そもそも、なんでヘルパー関数をプライベートな関数ではなく、わざわざ別のモジュールに定義しているか、というと、パラメータのパターンを生成するときに使いたいから。この時点ではテストのモジュールは定義されていない
3. 少々トリッキーなのは `test` を記述する部分。`test do ... end` の内部では、外部の変数が見えないことに注意

すこし冗長な書き方にはなるが、はじめて見る人でも「ループで異なるパターンのテストを書いてる」感が伝わるのは重要だと思う。
WTFormsでAnyOfバリデーションがSelectMultipleFieldのとき常にエラーを返す

## TL; DR
AnyOfバリデーションがSelectMultipleFieldに対応していないため。
カスタムバリデーションを用いる必要がある。

## 詳細
AnyOfバリデーションの実装をみると、SelectMultipleFieldに対応していません。
SelectMultipleFieldの場合、field.dataがlist型で渡ってくるので562行目が常にTrueを返してしまいます。

https://github.com/wtforms/wtforms/blob/23f730a9cfca478f01fda2b38fde17ad56e9a83d/src/wtforms/validators.py#L562
## 解決策
こんな感じでSelectMultipleField用のバリデーションを作成してあげれば良いです。

```python

def anyof_for_multiple_field(values):
  message = 'Invalid value, must be one of: {0}.'.format( ','.join(values) )

  def _validate(form, field):
    error = False
    for value in field.data:
      if value not in values:
        error = True

    if error:
      raise ValidationError(message)

  return _validate
```
Minecraft の起動オプション[Linux] 自分用メモ

CentOS8
Java11
Ryzen7 3700X
Ram 32GB
GTX1660SUPER
nvme ssd 500GB

現状。UseShenandoahGCを使いたいがためにLinuxを入れたと言って過言ではない。(openJDKで配られている奴には入ってないCentOSのRedHat系はdnfでinstallできるやつに入ってる、すごいGCらしい) i7-6700k-ram16GB-GTX1070に較べてパフォーマンスが変わったかというと数瞬した程度ではよくわからない。もうちょっと試す。。。
正直チャンクアップデートのスパイクの方をなんとかしないといけないのだけれど、GCじゃどうにもならんかな。
```
-Xmx16G -Xms8G -server -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseNUMA -XX:MaxGCPauseMillis=20 -XX:+DisableExplicitGC -XX:+UseAdaptiveGCBoundary -XX:+UseBiasedLocking -XX:+UseCompressedOops -XX:+OptimizeStringConcat -XX:ReservedCodeCacheSize=2G -XX:+UseCodeCacheFlushing -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true
```
ref: vmoptions
https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html
2022-0507 win向け(RAM48GB
```
-Xmx16G -Xms16G -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+AlwaysPreTouch -XX:+UseNUMA -XX:+UseLargePages -XX:MaxGCPauseMillis=20 -XX:+DisableExplicitGC -XX:+OptimizeStringConcat -XX:ReservedCodeCacheSize=2G 
```

2022-04-23 win向け(RAM16g
```
 -Xmx4G -Xms4G -server -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseNUMA -XX:MaxGCPauseMillis=20 -XX:+DisableExplicitGC -XX:+OptimizeStringConcat 
```

ps.windows側からバックアップを取るスクリプト（git bash 使用
```
."C:\path\to\git-bash.exe" -c "scp -P 51234 -i /C/path/to/.ssh/id_rsa  -r username@ipaddr:/path/to/saves/world/ /path/to/tmp_save/ |  .Robocopy.exe I:\path\to\tmp_save C:\path\to\OneDrive\minecraft_linux_save -E -MIR"
```
ポイント：robocopyのオプションを / -> -

試したいこと
https://wiki.openjdk.java.net/display/shenandoah/Main
>adaptive (default). This heuristics observes the previous GC cycles, and tries to start the next GC cycle so that it could complete before heap is exhausted
>-XX:ShenandoahInitFreeThreshold=#: Initial threshold at which to trigger "learning" collections

>-XX:ShenandoahMinFreeThreshold=#: free space threshold at which heuristics triggers the GC unconditionally

>-XX:ShenandoahAllocSpikeFactor=#: How much heap to reserve for absorbing allocation spikes

>-XX:ShenandoahGarbageThreshold=#: Sets the percentage of garbage a region need to contain before it can be marked for collection. 

for win
```
-Xmx8G -Xms8G -server -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UseNUMA -XX:MaxGCPauseMillis=20 -XX:+DisableExplicitGC -XX:+UseAdaptiveGCBoundary -XX:+UseBiasedLocking -XX:+UseCompressedOops -XX:+OptimizeStringConcat -XX:ReservedCodeCacheSize=2G -XX:+UseCodeCacheFlushing -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true
```
doctrineのQueryBuilderが自分的にうれしい点を考えてみた

doctrineのQueryBuilderを使用すると
sqlを直接書くのと比べて、自分的に何がうれしいのかを考えてみました。

doctrineしか使用したことがないので、他でも同じかもしれません。

#QueryBuilderでうれしいこと

### 少し違ったものを作るのが簡単です
作成済みのものを使用して、少し違ったものを作るのが便利です。

例えば、where条件などは共通のままにしたいが、取得する値は変えたい場合に便利です。

#### sqlの場合

```sql

select name from customer where id = 1;
```
上記をそのまま利用して、下記を作るのはどうしようかと思います。
文字の置換などでしょうか。。。

```sql

select company from customer where id = 1;
```

#### QueryBuilderの場合

```php
$qb
  ->select('c.name')
  ->where('c.id = 1');
```
上記の$qbを利用して、下記のようにselect()でselect定義を上書きすれば完成です。
where条件もそのまま残ります。

```php
$qb
  ->select('c.company');
```

### 順番がめちゃくちゃでも良い
sql要素の順番がめちゃくちゃでも定義できるので、コードの書きやすさに合わせられます。

例えば、where条件だけを先に設定しておいて、

```php
$qb
  ->where('c.id = 1')
  ->andWhere()
  ...
```

あとでselectを追加したりできます。

```php
$qb
  ->select('c.name')
```
おれがコンピュータに足し算を教えてやろうと思ったらもう知ってた


```php
echo gmp_add(
	'2345760293460295683704558703456102394871348756109347501936410934756102913874187344541930193470934875',
	'7947618927365019364019257691823461928734634570193248703473987562093471093576293478628949398873429857'
); // 10293379220825315047723816395279564323605983326302596205410398496849574007450480823170879592344364732
```

はい。

まあ、これだけだとアレなので、GMPを使わず[addBigInt](https://qiita.com/noritakaIzumi/items/7b95852c3d5cc626c7b7)をもう少し簡単に書けないか検討してみることにします。

```php
function addBigInt(string $a, string $b): string{
    $a = strrev($a);
    $b = strrev($b);

    $ret = '';
    for ($i = $c = 0;isset($a[$i]) || isset($b[$i]); $i++) {
        $tmp = ($a[$i] ?? 0) + ($b[$i] ?? 0) + $c;
        $c = $tmp > 9;
        $ret[$i] = $tmp % 10;
    }

    if ($c) {
        $ret[$i] = 1;
    }
    return strrev($ret);
}
```

とりあえず何も考えずに書いたらこんなかんじになりました。
単に1桁毎に順番に計算しているだけですね。

strrevが3回も入ってたりisset判定が残念な感じだったり`if($c)`とかわざわざ書いてたり微妙なのでどうにかしたいところです。


```php
function addBigInt(string $a, string $b): string
{
    $i = max(strlen($a), strlen($b));
    $a = str_pad($a, $i, 0, STR_PAD_LEFT);
    $b = str_pad($b, $i, 0, STR_PAD_LEFT);
    $ret = '';

    for ($c = 0, $i--; $i >= 0; $i--) {
        $tmp = ($a[$i] ?? 0) + ($b[$i] ?? 0) + $c;
        $c = $tmp > 9;
        $ret[$i] = $tmp % 10;
    }

    if ($c) {
        return '1' . $ret;
    }
    return $ret;
}
```

strrevを消して逆順に計算することとし、また桁数を揃えることで毎回issetで条件判定せずに済むようにしました。
しかしstr_padのもっさり感と、`if($c)`がやっぱり消せないのが惜しいところです。


# 最終式

```php
function addBigInt(string $a, string $b): string
{
    for($a=str_pad($a,$i=max(strlen($a),strlen($b),$c=0),0,0),$b=$r=str_pad($b,$i--,0,0);$i>=0;$c=($t=$a[$i]+$b[$i]+$c)>9,$r[$i--]=$t%10);return$c?'1'.$r:$r;
}
```

単に詰めただけです。
エラーを出さない条件では、このあたりが限界でした。

ちなみにエラーを許容するなら、strrevを使ったほうが短くなります。

```php:エラー出る
function addBigInt(string $a, string $b): string
{
    for($f=strrev,$l=max(strlen($a=$f($a)),strlen($b=$r=$f($b)));$i<$l;$c=($t=$a[$i]+$b[$i]+$c)>9,$r[$i++]=$t%10);return($c?1:'').$f($r);
}
```



## 最終式の問題点

`max(strlen($a))`と入力値を元にした数値を使っているので、PHP_INT_MAX桁を超える文字列だと正常に動かなくなります。
その前にメモリとかが死にそうですが。

あと0未満の値は正しく計算できません。
これは元の関数からしてそうなので仕様としておきます。


# 感想

残った2カ所の`,`を消せないものか。
あれがあると結局単に複数の式を並べてるだけになるから、なんというかこう面白くないんだよね。
【React Native】簡易な地図アプリ

React Nativeを書籍で一通り学習したので
少しアプリっぽいものを作ってみたくて
いろいろネットを参照しながら、簡易ですが地図アプリが実装できたので
公開いたします。

# ハマったこと
importのところでimport先が書籍では古くずっとエラーがで続けたところ。
最新の公式ドキュメントをみたら無事解決しました。

# 環境
今回初めてExpoで環境作って動かしてみました。
[【React Native】 Expoを使えば審査なしにアプリ更新出来てウハウハなのか？](https://qiita.com/keneo/items/625c7623d0dfb0cf0c6c)

# 成果物
<img width="461" alt="スクリーンショット 2019-12-09 20.02.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/642be878-2403-2569-9134-283d28a466b7.png">


# コード

```js:App.js
// 簡易な地図アプリ

import React, { Component } from 'react';
import { StyleSheet, AsyncStorage, Alert, TextInput, Text, View, Picker, Button } from 'react-native';
// npm install react-native-elements --save
import { Header } from 'react-native-elements';
// 注意 こちらではエラーとなります
// import { Permissions, MapView, Location, Constants } from 'Expo';
// 下記が正解（公式ドキュメント 2019.12.9現在）
import Constants from 'expo-constants';
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
// npm install react-native-maps --save
import MapView from 'react-native-maps';

export default class App extends React.Component {
  render() {
      return (
        // Map全体
        <MapView
            style={{ flex: 1 }}
            initialRegion = {{
                latitude: 34.6941375,
                longitude: 135.1962625,
                // 小さくなるほどズームになる
                latitudeDelta: 0.01,
                longitudeDelta: 0.01,
            }}
        >
          {/* Mapスポット */}
          <MapView.Marker
              coordinate = {{
                  latitude: 34.6941375,
                  longitude: 135.1962625,
              }}
              title={ 'JR三ノ宮駅' }
              description={ 'JR三ノ宮駅です' }
              onPress={ () => alert('JR三ノ宮駅がクリックされました') }
          />
          <MapView.Marker
              coordinate={{
                  latitude: 34.6929378,
                  longitude: 135.1944493,
              }}
              title={ '阪急神戸' }
              description={ '阪急神戸です' }
              onPress={ () => alert('阪急神戸がクリックされました') }
          />
      </MapView>
      );
  }
}

const styles = StyleSheet.create ({
  // propaty: {
  //   margin: 
  // },
});
```
はじめてのRuby on Rails環境構築(Mac)(2019/12/09)

#はじめに
こんにちは。

ここでは、これまで主に、JavascriptやTypescriptでフロントを開発していたエンジニアが、ローカルのMacにRuby on Railsの開発環境を作ってみましたのでその手順をまとめてみました。

###エンジニアスペック(主な開発経験)
Java
Python
Javascript
Typescript
React
ReactNative
Next
Node
Vue
など。

#Homebrewのインストール
今回、購入直後の真新しいMacに環境構築を試みたので、まずはHomebrewのインストールから始めます。
https://brew.sh/index_ja


```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

おっと、、エラーが出た。↓

```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
==> This script will install:
/usr/local/bin/brew
/usr/local/share/doc/homebrew
/usr/local/share/man/man1/brew.1
/usr/local/share/zsh/site-functions/_brew
/usr/local/etc/bash_completion.d/brew
/usr/local/Homebrew

Press RETURN to continue or any other key to abort
You have not agreed to the Xcode license.
Before running the installer again please agree to the license by opening
Xcode.app or running:
    sudo xcodebuild -license
```

xcodeのライセンス承認をしろとのこと。
ライセンス承認後、再度上記コマンドを実行します。

成功!

#Rubyのインストール
現時点でv2.6.5が使えそうなので、こちらを選択します。

```
$ brew install rbenv ruby-build
$ rbenv install --list
2.6.3
2.6.4
2.6.5
2.7.0-dev
2.7.0-preview1
2.7.0-preview2
2.7.0-preview3
$ rbenv install 2.6.5
```

pathを通します。

```
$ echo 'export PATH="~/.rbenv/shims:/usr/local/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
```

global環境を汚さないように、特定のディレクトリ下でv2.6.5を使えるようにします。

```
$ cd ./特定のディレクトリ
$ rbenv local 2.6.5
```

#bundlerのインストール
次に、bundlerをインストールします。
gem でインストールするのですが、`rbenv local` したディレクトリで行います。

```
$ cd rbenv local 2.6.5 を実行したディレクトリ
$ gem install bundler
$ bundler -v
Bundler version 2.0.2
```

それ以外のディレクトリで `bundler -v` すると、

```
rbenv: bundler: command not found

The `bundler' command exists in these Ruby versions:
  2.6.5
```
のエラーが出ます。

#Railsのインストール
まず、workspace 用のディレクトリを作ります。

```
mkdir workspace
```

Gemfile を生成します。下記コマンドを実行すると `Gemfile` が生成されます。

```
$ bundle init
```

Gemfile の下記1行のコメントアウトを削除します。

```
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem "rails" ← ここ
```

```
# railsのインストール
$ bundle install --path=vendor/bundle

# railsのバージョンチェック
$ bundle exec rails -v
Rails 6.0.1

# workspace内にプロジェクトを作成
$ bundle exec rails new .

# 起動
$ bundle exec rails server
=> Booting Puma
=> Rails 6.0.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
```

#Yay! You’re on Rails!
最後に、 `http://localhost:3000/` へアクセスしてページが表示されたら完了です!
![Screen Shot 2019-12-09 at 19.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223429/5f31de77-2a7a-256f-e83c-aaaa72b2794b.png)

ruby のバージョンが2.6.5になってました!
作業時間としてはおおよそ1h程度で、非常に簡単に環境が構築できました!

以上でRuby on Railsの開発環境ができましたので、いろいろ遊んでみようかと思います!
【SQL Server】俺的チートシート（クエリ）

## はじめに
SQL Serverで開発やデータ抽出をやっていますが、いつも使うクエリの定型文が思い出せず毎回調べているのでこのタイミングでまとめて見ようかなと（~~アドベントカレンダーに登録したけど書く内容に行き詰まったから~~）


## 作成・更新・削除系
### テーブル作成
```sql:
create table  テーブル名A(
    カラム1 INT IDENTITY(1,1) NOT NULL, --自動採番（始まりの値,インクリメントする値）
    カラム2 INT DEFAULT 5, --デフォルトを指定したいとき
    カラム3 INT NULL, --NULL許容
    カラム4 INT NOT NULL, --NOT NULL制約
    カラム5 DATETIME
)
```
テーブル作成でよく使う設定を記述しました。
デフォルトを指定したいときはそんなに使わないけど、忘れた頃にやってくる。。。


### 制約削除
```sql:
ALTER TABLE テーブル名A DROP CONSTRAINT 制約名B
```
カラム削除しようとしたら、制約に依存しているから～というエラーが出る。制約付きカラムの削除のときによく使った。（上記のテーブルでいうと「カラム2」がそれに価する）

### カラム削除
```sql:
ALTER TABLE テーブル名A DROP COLUMN カラム2 
```

### 自動採番設定済みカラムに対して任意の値をインサートする
```sql
set identity_insert テーブル名A on;
insert into テーブル名A(カラム1,カラム2,カラム3,カラム4) values (2,1,1,00000000000)
set identity_insert テーブル名A off;
```
`identity_insert ` を上記のように指定してあげればインサートできます。
このときに気をつけなければならないのが、インサート文で全カラムを明示しないといけません。
（いつもそのことを忘れてしまう）

## その他系
### テーブルを全取得
```sql
SELECT
    *
FROM
   sys.objects
WHERE
   type = 'U';
```

### シノニムを全取得
```sql
SELECT
    NAME
    ,BASE_OBJECT_NAME
FROM
    SYS.SYNONYMS
ORDER BY
    BASE_OBJECT_NAME
```

### テーブルの情報を取得
```sql
SELECT
    TABLE_NAME
    ,COLUMN_NAME
    ,DATA_TYPE
    ,COLUMN_DEFAULT
FROM
    INFORMATION_SCHEMA.COLUMNS
WHERE
    TABLE_NAME='テーブル名A'
```


## アンチパターン
### NULLの扱い
NULLを許可しているカラムではスカラー式が任意の値にならないことに注意する。
SQLは3値論理であることを忘れない。
最近、これを忘れていて痛い目にあった。。。