OmniAICreator/Qiita-1.07M huggingface dataset:
【Vue.js】store パターンでシンプルな状態管理を実装する。

# はじめに
Vue.js初心者が書いた記事です。
そのためつっこみどころがたくさんあるかと思いますが、その際はご教授していただけると幸いです。

この記事では、[Vue.jsのチュートリアル | 状態管理](https://jp.vuejs.org/v2/guide/state-management.html)を自分なりに噛み砕いてまとめたものになります。
また、今回書いたコードは[GitHub](https://github.com/residenti/vuex-sample/blob/master/store_patern.html)にあげてます。

# storeパターンでシンプルな状態管理を実装する。

[状態管理](https://jp.vuejs.org/v2/guide/state-management.html)
上記サイトの項目「シンプルな上端管理をゼロから作る」で、コンポーネント間で共通の状態を保持しているときに、
その状態を各コンポーネントまたは、そのサブコンポーネントから`this.$root.$data`等を通じてアクセスし変更していると、どこで状態が変更されたのかを把握しずらくなり、デバッグが大変になってしまう。

そんな時は、`storeパターン`を利用することでこの問題を解決することができる。

下記は参考サイトのサンプルコードを検証するために、自分なりに変更を加えたコードです。（コピペでそのまま使えるように全て載せています。）

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Vuex</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>

<body>
  <div id="app1">
    {{ this.$root.$data.sharedState }}
    <button v-on:click="setMessageAction">setMessageAction</button>
    <button v-on:click="clearMessageAction">clearMessageAction</button>
  </div>

  <div id="app2">
    {{ this.$root.$data.sharedState }}
    <button v-on:click="setMessageAction">setMessageAction</button>
    <button v-on:click="clearMessageAction">clearMessageAction</button>
  </div>

  <script>
    /* storeパターン
    状態管理を中央集権的にすることで、
    どういった種類の状態変化が起こりうるか、
    あるいはそれがどうやってトリガされているか、
    が分かりやすくなる.
    */
    var store = {
      debug: true,
      state: {
        message: 'Hello!'
      },
      setMessageAction(newValue) {
        if (this.debug) console.log('setMessageAction triggered with', newValue)
        this.state.message = newValue
      },
      clearMessageAction() {
        if (this.debug) console.log('clearMessageAction triggered')
        this.state.message = ''
      }
    }

    const vmA = new Vue({
      el: app1,
      data: {
        sharedState: store.state
      },
      methods: {
        setMessageAction: function () {
          store.setMessageAction('newValue from app1')
        },
        clearMessageAction: function () {
          store.clearMessageAction()
        }
      }
    })

    const vmB = new Vue({
      el: app2,
      data: {
        sharedState: store.state
      },
      methods: {
        setMessageAction: function () {
          store.setMessageAction('newValue from app2')
        },
        clearMessageAction: function () {
          store.clearMessageAction()
        }
      }
    })
  </script>

  <style>
  </style>

</body>

</html>
```

ここで大切なのは、状態（state.message）を変更するactionは全てstore自身が持っているということ。
下記は参考サイトより
>
このように状態管理を中央集権的にすることで、どういった種類の状態変化が起こりうるか、
あるいはそれがどうやってトリガされているか、が分かりやすくなります。
これなら何か良くないことが起きても、バグが起きるに至ったまでのログを見ることもできます。

![state.png](https://qiita-image-store.s3.amazonaws.com/0/151720/ad8d24fa-5160-fa15-3975-ca53b63d42a8.png)

# まとめ
コンポーネントでは直接storeの持つ状態を変更することはせずに、
代わりにstoreに定義されているアクションを呼び出し状態を変更するようにする。

最後まで読んでいただきありがとうございました。
Cognos 10 Framework Manager のFixPack

#Cognos 10 Framework ManagerのFixPack
Cognos 10 BIの話です。Cognos Analyticsは該当しません。
Cognos 10 BI には、Fixpackという定期的にリリースされる、バグFixが集まったPackがあります。
以下のTechnoteのように、Cognos BI 10.2.2の場合、FixPack 10まであります。
**Cognos Business Intelligence 10.2.2 Fix Lists**
http://www-01.ibm.com/support/docview.wss?uid=swg27042898

このFixPackですが、IBMのFix Centralからダウンロードできます。
**Fix Central**
https://www-945.ibm.com/support/fixcentral/

こんな風に、製品グループでCognosを選択し、Cognos Business Intelligence を選択し、バージョンを選択し、今時はほとんど64bit環境だと思いますので、Windows 64bitプラットフォームを選択し、次へ進んでいくと、
![001.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/1a1e164c-6189-5558-36cf-9cbe62ebe8f4.jpeg)

FixPackがリストされます。
赤枠で囲んでいるのが、Cognos BI 10.2.2のFixPack 10です。
これをダウンロードして、Cognos 10 BIの、Report Serverノード、Conetent Managerノード、Gatewayノードなどに適用します。FixPackのファイルはどのノードでも共通です。
![002.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/0156793b-3f3d-a08c-3bec-11aa738dc118.jpeg)

この様にFixPackをダウンロードして、Cognosサーバーに適用しているのはどこの環境でも行っていると思いますが、実はFramework Managerにもバグはもちろんあって、FixPackを当てる必要があります。

では、先ほどのFix CentralでFramework ManagerのFixPackを探してみようとしても、「以下から選択 Cognos」のプルダウンには、Framework Managerというものはリストされません。

では、どうしたら良いかというと、ここですね、プラットフォームで「Windows 32-bit x86」を選択し、リストされるFixPackは、Cognos 10 BI Server 32bitとCognos 10 Framework Managerの共通のFixPackです。
![003.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/3c1d72c5-5194-946f-1b7f-a49d8ac375b7.jpeg)

32bit版のFixPackをFramework Managerに当てて頂ければ良いですが、注意点として、新しいFixPackレベルのFramework Managerで開いたモデルファイルは、古いFixPackレベルのFramework Managerでは開けませんので、複数の端末にFramework Manager入れて開発している環境では、各端末のFramework ManagerのFixPackレベルを揃える様に気をつけましょう。
【React Native】react-navigationでbottomTabメニューのdefaultタブを設定する

## ライブラリ
- [react-navigation](https://github.com/react-navigation/react-navigation) 
    - [doc](https://reactnavigation.org/)

## やりたいこと
以下の画面構成のとき、MAIN画面にナビゲートされたらTAB 2がinitialで表示されるように

- LOGIN
- MAIN
    - TAB 1
    - TAB 2
    - TAB 3

## どうやるか
`initialRouteName`を`createStackNavigator()`の第二引数のオブジェクトに設定する

```Navigator.js
import Main from './Main';

const Navigator = createStackNavigator(
  {
    'LOGIN': {
      screen: Login,
    },
    'MAIN': {
      screen: Main,
    },
  },
);
export default Navigator;
```

```Main.js

const Main = createBottomTabNavigator({
  'TAB 1': {
    screen: tab1screen,
    navigationOptions: {
      tabBarLabel: 'TAB 1',
    },
  },
  'TAB 2': {
    screen: tab2screen,
    navigationOptions: {
      tabBarLabel: 'TAB 2',
    },
  },
  'TAB 3': {
    screen: tab3screen,
    navigationOptions: {
      tabBarLabel: 'TAB 3',
    },
  },
},{
  // このoptionはBottomTab共通で適用される
  tabBarPosition: 'bottom',
  initialRouteName: 'TAB 2',// ← ココ
  tabBarOptions: {
    activeTintColor: 'red',
    labelStyle: {
      fontSize: 9,
    },
    style: {
      backgroundColor: COLORS.WHITE,
    },
  }
}
export default Main;

```
【BigQuery】日付跨ぎセッションの注意点

##はじめに
分析をするにあたって、BigQueryのテーブル構造や指標の出し方に則って、
『1レコード1セッション』にデータを持つと便利。
うまくデータ取得したはずでも『1レコード1セッション』にならないとき、
日付を跨いでいるセッションにポイントがあったのでメモ。

##前提・仮説
◯前提：
　GAのセッションが切れるタイミング：
　・30分に1度
　・日にちを跨ぐとき

◯仮説
　BigQueryでの30分に一度、日にち跨ぐとセッションIDが変わっている

#問題
rawテーブルからデータを抜いてきても、1レコード1セッションにならない！
※1意性の判断には、「ユーザーID+セッションID」の複合キーの重複なしカウントを利用します。

##発見
日にち跨ぎ前後でも同じセッションIDが使われている！
(例)

```sql
--①rawデータ抜く
SELECT
fullVisitorId,
visitId,
date,
HOUR(DATE_ADD(SEC_TO_TIMESTAMP(visitStartTime), 9, 'HOUR')) AS hour, --時刻(日本時間)
CONCAT(fullVisitorId,STRING(visitId)) AS uniqSessionId --ユニークのセッションIDと定義
FROM (TABLE_DATE_RANGE( [dataset.table_],TIMESTAMP('2018-01-01'), TIMESTAMP('2018-01-02')))
```

```sql
--②日にち跨ぎセッションのユニークIDを指定して、データを確認
SELECT *
FROM ①で作成したテーブル WHERE uniqSessionId = 'aaaaaaaaaaaaaaaaaaabbbbbbbbbb'
```
| fullVisitorId    |visitId       | date     |hour   |uniqSessionId                |
|:-----------------|-------------:|:--------:|:-----:|:---------------------------:|
|aaaaaaaaaaaaaaaa…|bbbbbbbbbb    |20180101  |23     |aaaaaaaaaaaaaaaaaaabbbbbbbbbb|
|aaaaaaaaaaaaaaaa…|bbbbbbbbbb    |20180102  |0      |aaaaaaaaaaaaaaaaaaabbbbbbbbbb|


##解決策
Dateの箇所だけ初日側に寄せ、『1レコード1セッション』にする。

(例)ユニークのセッションID毎にDATEを元にSEQをふる。⇒次のテーブルでSEQが1のものだけ対象にする。

```sql
--SEQを振る
SELECT
uniqSessionId,
COUNT(*) OVER (PARTITION BY uniqSessionId ORDER BY date) AS SEQ,
CONCAT(fullVisitorId,STRING(visitId)) AS uniqSessionId --ユニークのセッションIDと定義
FROM dataset.table
```

※来訪時セッションを取るのはこれでOK
集約が必要なデータ(ヒット数、CV数など)については、集約関数を利用するべき。
来訪時セッション用と、集約セッション用でテーブルを作成し、新たにテーブルにまとめる。

##注意点
どうしても毀損させたくない・クレンジングしたくない要件がある場合には、
違うやり方をやってみる必要があるかも。
git repository

# git addの際にエラー　"warning: adding embedded git repository"


###直訳`注意：埋め込まれたgitリポジトリを追加しようとしています。`



出て来たエラー

```github
warning: adding embedded git repository: caliper-v2
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
```


解決策

`rm -rf .git/`
でgitリポジトリを削除する。
iPhone から localhost で起動しているアプリにアクセス

レスポンシブな画面を作っていると iPhone から PC の localhost にアクセスしたくなるもの💩
やり方は簡単、2ステップ🤘

1. iPhone のプロキシ設定
2. iPhone のブラウザから起動している PC で起動しているアプリへアクセス

## 1. プロキシ設定

1. PC と iPhone を同一のネットワーク配下にする
2. iPhone の「設定」を開く
3. 接続している Wi-Fi の `i` マークをタップ
4. HTTP プロキシ -> プロキシを構成 をタップ
5. 「手動」を選択
6. 「サーバー」に PC の IP アドレス (e.g., 192.168.120.95) を入力
7. 「ポート」に localhost で起動しているアプリのポート (e.g., 3000) を入力
8. 「保存」をタップ

## 2. ブラウザから起動しているアプリへアクセス

ブラウザのアドレスバーに PC の IP アドレス (e.g., 192.168.120.95) を入力
アクセス成功！！

## 参考
[MacのlocalhostにiPhoneで接続する方法 \- Qiita](https://qiita.com/nilfeli/items/c4725c649c57a0432104)
[localhostをiphoneなどでアクセスする \- 初心者のWEBデザイン](http://bellsmarket.hatenablog.com/entry/2017/01/24/001504)
Laravelクエリービルダーで作成したSQLにパラメータをバインドして出力した話

# helper関数を使ってBind部分にパラメータを挿入

※　参考
[【朗報】Laravel の SQL 実行ログが取得しやすくなる](https://qiita.com/fuwasegu/items/c6e668dae1546184ff15#%E5%85%88%E6%97%A5%E3%81%AE-taylor-%E6%B0%8F%E3%81%AE-tweet)
こちらで書かれている通り、Laravel 10.x 系で `toRawSql()` が実装されるそうです。 　
対象の方は、こちら確認してください。

LaravelでQueryBuilderを使用時に、`$builder->toSql()`で作成中のSQLは見れるんだけど、バインドした後のデータをPHP側から出力したかったので、Helper関数を使ってBindしてみた。

## コード例
```
// modelには適当なEloquentモデルを指定してください。
$builder = Model::where('id', 1)->where('name', 'name');

$sql = preg_replace_array('/\?/', $builder->getBindings(), $builder->toSql());

dd($builder->toSql(), $builder->getBindings(), $sql);
```
## 結果
```
"select * from `model` where `id` = ? and `name` = ?"

 array:2 [▼
  0 => 1
  1 => "name"
]

 "select * from `model` where `id` = 1 and `name` = name"
```

ヘルパーの、preg_replace_arrayを使い、toSql()の出力結果の?に順番に値をバインドする事が出来ました。
バインドがうまくいかない場合の検証などに良さそうですー
sublime textでmarkdownを使う

# Install Package

1. OmniMarkupPreviewer - プレビュー
2. Monokai Extended - シンタックスハイライト
3. Markdown Extended - コードをハイライト

`control` + `shift` + `p`でinstall packageを選択→上記3つのパッケージをインストール

# 設定

1. color schemaからMonokai Extendedを設定
2. View > Syntax > Open all with the current extension as > Markdown Extendedを選択
3. 

# ブラウザで確認

`command + option + o` を押すと、ブラウザで見れる

# 参考

http://webmem.hatenablog.com/entry/sublime-text-markdown
チャットワークの Ctrl+Enter / Shift + Enter をAutoHotKeyで無効化する

チャットワークは、Enterで送信をON/OFFできるのですが
Ctrl + Enter / Shift + Enter で送信することを防止できないので

AutoHotKey で、それらの機能をチャットワークのブラウザとアプリの両方で、それらのキーが飛ばないようにしました。
当たり前ですが、Windows版です。

```
/*
    ChatWork Post
        Ctrl + Enter    Cancel
        Shift + Enter   Cancel
*/

SetTitleMatchMode, 1 ;前方一致
#IfWinActive, ChatWork
^Enter::
+Enter::
^+Enter::
#IfWinActive

#IfWinActive, チャットワーク - 
^Enter::
+Enter::
^+Enter::
#IfWinActive
```

# ポエム

そもそもチャットワークのデフォルトにこういう機能がないことについて、がっかり。
AutoHotkeyを持ち出さなきゃいけないことに、めんどくささとか憤りとか。

スカイプやLINEや、MSTeamsや、なんやかんやと過去もあったし今もいろいろあるし、そういうの使っていると、Enter/Ctrl+Enter/Shift+Enter、どれが改行でどれが送信なのかよくわからなくなる。

なので、誤って押した場合でも、改行ならともかく、送信してしまうのは避けたい。
だから、このようなCtrl+Enterで送信するしないのON/OFF機能は必須だと思うが、そのあたりの実装センスがチャットワークさんにはないらしい。(いちおう要望も出してみたけどな。)

SlackやSkypeのように自分自身への送信を行って動作を試すこともできないし、
いろんな面で Slackと比べて、Chatworkは、UIなどが考えられてなくて、Slack に負けていくと思う。

和製(だっけ？)で応援したい気もするけれども、
将来的に負けていくコミュニケーションツールとか、使っていきたくネーわ。
(今更)稼働中の Linux が 32ビット版か 64bit 版かを確認する方法

# 序
一般的に、タイトルを実現する方法としてよく知られている方法は

```shell-session
[hoge@fuga ~]$ uname -m
x86_64
```

上記コマンドの結果が x86_64 か i686 かどうかで 64bit版か 32bit版かがわかる、というものである・・・が、
64bit VMWare 鯖上の 32bit 仮想マシンで上記コマンドを実行しても
x86_64 が返ってくるんですよ・・・

# ということで
```shell-session
[hoge@fuga ~]$ getconf LONG_BIT
64
```

こっちが正解。戻り値が文字列ではなく数値という点もでかいし、RaspberryPI でも使える。
JavaScript promptもどき ～ onKeyUpを取りたくて ～

##何がしたかったのかと言うと。

「prompt で onKeyUp を 取りたかった」
でも、できそうにないので「もどき」を自分で作ることにしました。

ようは入力欄に入力した後に、[OK]を押すのが面倒くさかったのです。
タブキー→スペースキーでも、クリックでも大して変わらないのですが、少しでも省略したかった。
明確に用途が決まっていて、入力欄には12桁の番号をペーストするだけだったので、ペーストされたら即時に次に進んでほしい。というのが これを作った理由です。

```javascript

/* promptもどきを表示(Toastもどきの使い回し) */

var sc = document.scrollingElement.scrollTop; 

var text = document.createElement("span");

var prm = "何か入力して下さい。<br><br>";
prm += "<input type=text id=memo size=20 placeholder='追跡番号とか' value=''><br><br>";
prm += "<input type=button id=ok value='OK'>&nbsp;";
prm += "<input type=button id=cancel value='キャンセル'>";
prm += "<p id=output></p>";

text.innerHTML=prm;

var ts = text.style;

ts.color = '#000';
ts.backgroundColor = 'white';
ts.padding = '15px';
ts.border = '1px solid gainsboro';
ts.boxShadow = '3px 3px 10px';
ts.zIndex = '100';

document.body.appendChild(text);

ts.position = 'absolute'; 
ts.top = 50 + sc + 'px'; 
ts.left = (window.innerWidth / 2)-(text.offsetWidth / 2) + 'px'; 

/* イベント関係の処理 */

var m=document.getElementById('memo');
var o=document.getElementById('output');

m.focus();
m.onkeyup = input_check;

/* 入力チェック */

function input_check() {
/* 何かテキトーにしたいことをする */
}

/* [OK]を押した場合、次の処理へ。(入力内容のチェックはしてない) */

document.getElementById('ok').onclick = next;

function next() { alert(m.value); cls(); }

/* [キャンセル]を押した場合は、ただ閉じる。 */

document.getElementById('cancel').onclick = cls;

function cls() { document.body.removeChild(text); }

```

## 動作確認環境

Windows 10
Google Chrome 67
Vue.js watch の動き

# 目的

- Vue.js の watch を使い データ変更時に関数を実行した時の挙動が予想と違っていたので メモする

# コード

``` javascript
const Vue = require('vue')

var data = { a: 1 }

var vm = new Vue({
  data: data,
  created: function(){
    console.log('a is: ' + this.a)
  },
  methods: {
    aaa: function() {
      console.log('aaa function a is: ' + this.a)
    }
  }
})

console.log(vm.a)

vm.$watch('a', function(aVal) {
  console.log('change: ' + aVal)
})

vm.a = 2

vm.aaa()
```

# 予想した動き

- watch が実行されたあと　vm.aaa()　が実行される

# 実際の動き

- 「aaa function a is: 2」が出力され watch（「change: 2」が出力） があとから非同期で実行されたことが確認できた
- 順番通り実行させたい時は注意が必要。
- 非同期じゃなきゃ watch できないんだから「そりゃそうだ」っちゃそうなんだけど、勘違いするとトラブルになりそうなのでメモった。
AWS Glue + PySpark逆引きメモ

PySparkでバッチ処理をやろうとしたときに必要だったこと

# 操作

## DataFrameでRDB的操作

調べると方法がいろいろあるのでうれしい

### カラムの並び替え

- [Python/pyspark data frame rearrange columns](https://stackoverflow.com/questions/42912156/python-pyspark-data-frame-rearrange-columns)

```python
dataframe.select(["col1", "col2", "col3"])
```

### カラムのリネーム

- [How to change dataframe column names in pyspark?](https://stackoverflow.com/questions/34077353/how-to-change-dataframe-column-names-in-pyspark)

`selectExpr`, `withColumnRenamed`, `alias` or `as`, 最後に普通にSQL使う方法

### 固定値追加
- [Adding constant value column to spark dataframe](https://stackoverflow.com/questions/44033037/adding-constant-value-column-to-spark-dataframe)

`lit('固定値')` を使う

### DataFrameを一時Viewとして登録

- [なんとなくな Developer のメモ-Spark SQL で CSV ファイルを処理 - GeoLite Legacy](http://fits.hatenablog.com/entry/2014/11/03/222102)

>registerTempTable メソッドを呼び出す際に RDD から Spark SQL の SchemaRDD へ暗黙変換が実施されます。
>
>registerTempTable の引数としてテーブル名を渡す事で、SQL 内でこのテーブル名を使用できるようになります。

```python
#...SparkSQLを実行したり、RDDを変形したりする処理…
df.registerTempTable('table_name') # 結果を一時テーブルにできる
```


## DataFrameでファイル操作

やり方がいろいろある

### 取り込み

S3からの取り込み、ローカルのファイルの取り込み。どちらもSparkContextに生えている`textFile`でできるようだ（便利すぎる…）。まだ正規化されてないデータの処理に使えそう。（以下もどこかのサイトで調べたコードなのだが、記録してなかったのでURLなし。）

```python
# Loads RDD
lines = sc.textFile("s3://hoge/hoge.csv")
# Split lines into columns; change split() argument depending on deliminiter e.g. '\t'
parts = lines.map(lambda l: l.split(','))
# Convert RDD into DataFrame
df = spark.createDataFrame(parts, ['your', 'column', 'name'])
df.printSchema() # スキーマ表示
df.show()        # プレビュー表示
```

### 書き出し

ファイルを書き出すには `.write.save()` を使えばいいのだが、複数ファイルに分かれてしまうと困る。その場合は `repartition(1)` , `coalesece(1)` という関数でファイルをまとめることができる。

- [Write single CSV file using spark-csv](https://stackoverflow.com/questions/31674530/write-single-csv-file-using-spark-csv)

```python
df
   .repartition(1)
   .write.format("com.databricks.spark.csv")
   .option("header", "true")
   .save("mydata.csv")
```

## RDD

データ自体を変形するときはRDDを直接いじったほうが自由度が高い。というかいったんRDDを取り出してしまえばPythonでできることはすべてできるのでアルゴリズムの組み立てで困ることはなさそうだ。正規化されてないデータを処理する際に役立ちそう。

APIドキュメント → [pyspark.RDD - A Resilient Distributed Dataset (RDD), the basic abstraction in Spark.](https://spark.apache.org/docs/2.2.0/api/python/pyspark.html#pyspark.RDD)

### 連番

- [add one column including values from 1 to n in dataframe](https://stackoverflow.com/questions/42690565/add-one-column-including-values-from-1-to-n-in-dataframe)
  - 普通のプログラム的な処理（ループ＋インデックス付加）

```python
rdd_indexed = df.rdd.zipWithIndex().map(lambda x: (x[0][0],x[0][1],x[1]+1))
df = rdd_indexed.toDF(['id','score','rowNum'])
df.show()
```
BIツールとは | おすすめツール5選を紹介！

会社経営には、会社の将来を不安に感じたことがあると思います。例えば「今何が求められているのか」「足りないものは何なのか」など、悩みは尽きません。その悩みを解決するために「ユーザーアンケート」や「市場動向」といった情報が必要です。ですから「情報」の収集が不可欠です。前回[ネット情報収集の味方「スクレイピングツール」3選](https://qiita.com/Octoparse_Japan/items/326c3e307624e1edd263)（[Octoparse](https://www.octoparse.jp)、Import. Io、Scraper）を紹介しました。

ただ、ここで問題になるのが情報の管理方法です。企業が膨大な情報を用いて、迅速かつ精度の高い意思決定を行うためには、BIツールという道具の活用が欠かせません。


BIツールの「BI」とは、「ビジネス・インテリジェンス（Business Intelligence）」のことです。BIは、企業に存在するデータを、収集・蓄積・分析・報告することで、経営上の意思決定に役立てることをいいます。 このBIを助けるシステムを総称したものを「BIツール」と呼びます。BIツールの導入によって、時間と手間を大幅に減少できます。

 

BIツールが備えている代表的な機能をご紹介しましょう。

**1.レポーティング**
企業内のシステムからデータを取り出し、見やすいように「ダッシュボード」やなどにまとめて共有することができます。KPIなどのパフォーマンスチェックや、「異常の感知」をすばやくすることで、意思決定を効率よく行えます。

**2.ダッシュボード**
複数の分析結果をまとめて、チャートやグラフなどを一覧に表示し、気になったものを任意に選び、拡大表示をしながらデータを見比べれば、その問題はどれほど深刻かなどを考えながら監視していきます。

**3.OLAP分析**
OLAPとは「Online Analytical Processing（オンライン分析処理）」の略で、問題箇所を多角的に分析していきながら要因を深掘るものです。蓄積したデータを「スライシング」「ドリルダウン」などの処理を行うことができます。

**4.シミュレーション**
今までの結果より得られた改善案の根拠を、科学的に実証するものです。日々の変動に併せて柔軟かつ容易に予測をシミュレーションすることができます。主に経営者が「予算編成」などに使うためのものです。

 

それでは、どんなBIツールを導入したら良いのでしょうか？今回はおすすめのBIツール5選を紹介しようと思います。

 

**Tableau**

ドラッグ&ドロップするだけで、誰でもデータの整理と管理ができてしまうデータ分析のためのソフトウェアです。コンテンツ整理やアクセス分析にぴったりのサービスで、グラフの種類、色、大きさなども自由に簡単に調整が可能です。バージョンによっては、データ共有、共同編集が行えるコラボレーション機能を備えているものもあります。
公式サイト：https://www.tableau.com/ja-jp


**QlickView**

QlikViewは、現場のビジネスユーザーが、それぞれ革新的な意思決定を行ない、最大限の能力を発揮できるよう真のセルフサービスBIを提供します。オプション機能が充実しており、企業ごとに必要な機能をカスタマイズすることができます。
また、利用制限なく無料で使うことのできるプランもあるため、手軽に始められるツールとなっています。
公式サイト：https://www.qlik.com/ja-jp/products/qlikview


**Power BI**

Power BI は、マイクロソフト社が開発したBIツールです！データを分析し、洞察を共有し、さまざまなデバイスに対応した機能豊富なダッシュボードでビジネスを監視します。多様なデータ ソースに接続し、データ作成を単純化し、アドホック分析を促進します。また料金は最高でも月額3,270円なのでリーズナブルであるといえますね！また、機能制限付きで無料プランを提供しているので、お試しに利用してみるのもありです。
公式サイト：https://powerbi.microsoft.com/ja-jp/


**Actionista!**

Actionista!は業種/業務問わず、幅広く活用できるBIツールです。初心者でも比較的使いやすいインターフェースや機能を提供しています。指定されたフォーマットのデータを用意するだけで、分析目的に沿ったダッシュボードが自動生成されるので効率性の高い分析が可能です。
公式サイト：http://www.justsystems.com/jp/products/actionista/


**Yellowfin**

社内のあらゆるデータをビジュアライズすることで可視化するツールです。グラフや地図などになって見やすくなったデータは、チームで共有することができます。データに基づいた企画立案や調査、意思決定をすることを促してくれます。これらの機能が安定しているためYellowfinは全世界100万人に利用されています！
公式サイト：https://yellowfin.co.jp/

 

BIツールは、会社の成長をサポートしてくれるありがたいパートナーであると言えます。“ビッグデータ分析で何をしたいのか？”をじっくりと考え、“どんな課題を解決したいのか？”を明確に、基本的な要件定義を行った上でBIツールの導入を検討してみてはいかがでしょうか。
Anaconda環境でPyTorch 〜株価予想〜 #01 環境構築編

## はじめに
[株式会社クリエイス](http://creaith.jp/)の[モトキ](https://qiita.com/pickles)です。
突然ですが、PyTorchなるものを知ったので
「何も知らない自分がディープラーニングできちゃうのか」挑戦してみたいと思います。

Anaconda環境でPyTorch 〜株価予想〜 #01 環境構築編 (今回)
[Anaconda環境でPyTorch 〜株価予想〜 #02 基礎知識・学習編](https://qiita.com/creaith/items/2d606a7f0effd5d839d5)
[Anaconda環境でPyTorch 〜株価予想〜 #03 予測編](https://qiita.com/creaith/items/710405db451577ae1580)
[Anaconda環境でPyTorch 〜株価予想〜 #04 予測(リベンジ)編](https://qiita.com/creaith/items/a7d0ba9b9cbb4be42490)
[Anaconda環境でPyTorch 〜株価予想〜 #05 表示編](https://qiita.com/creaith/items/54c1666682210d8cbce3)



## 別チーム
[別チームでもPyTorchの記事](https://qiita.com/creaith/items/92b00f5d03c8ecf3948c)を書いているようです。
> 曽宮・モトキ「AI？それっておいしいんですか？」

こう紹介されていますが、間違っていません。


## 基礎知識

### PyTorchとは？
深層学習(ディープラーニング)のライブラリ。

### 深層学習とは？よく聞く機械学習と何が違うの？
|キーワード|概要|
|---|---|
|機械学習|与えられた情報から、機械が法則やルールを見つける手法・プログラムを指す。|
|深層学習|機械学習の一種で、ニューラルネットという生物の神経系の振る舞いを模したモデル。<br>機械学習と異なり、学習する事柄をコントロールできる。|

それぞれにはさらに細かい特徴があるようですが、とりあえずこのレベルの知識で進めていきます。
つまりPyTorchは「学習して欲しいものを学習させるために必要なもの」が揃ってるということです。

---
## 環境構築
環境構築〜Quandlからデータを貰ってくるところまで
環境は**Macローカル環境**で作ります。敷居の低さアピール
(環境を汚したくない人は、[別チームの記事](https://qiita.com/creaith/items/92b00f5d03c8ecf3948c)を参考にしてください)

### すでにAnacondaで環境を作ってしまった人
Anacondaを片付ける手順を書きました。
[Anaconda3をお掃除する](https://qiita.com/pickles/items/12c8c73d3d4bbd61f738)

### Anacondaインストール
[anaconda(Python3.6version)](https://www.anaconda.com/download/#macos)をダウンロードし、
インストーラに従ってインストール(時間がかかります)

zshの人は、.bash_profileからコードをパクってきます。

```sh:.zshrc
# added by Anaconda3 5.2.0 installer
export PATH="/anaconda3/bin:$PATH"

```
動作の確認

```sh
% exec $SHELL
% python --version
Python 3.6.5 :: Anaconda, Inc.
```

### pytorchのインストール
```sh
% conda install pytorch torchvision -c pytorch
```
これでPyTorchが使えるようになった…と言っても実感がわかないですね。

### [quandl](https://www.quandl.com/tools/python)のインストール
金融・経済のデータを取得できるライブラリ。
今回は、深層学習に使うデータをここで取得します。

```sh
% conda install quandl
```

これらのインストールを忘れたり、失敗すると
以降のソースを実行したときに`ModuleNotFoundError`が出るので、注意するポイントです。

## 試しにデータが取れるか単体で動かしてみる

```python:test.py
import quandl
mydata = quandl.get("EIA/PET_RWTC_D")
print(mydata)
```

```sh
% python test.py
            Value
Date
1986-01-02  25.56
1986-01-03  26.00
...
```

もうちょい書き足して、Appleの株価を取得してみます。

```python:test.py
import quandl
import numpy as np
import torch
from torch.autograd import Variable


def get_tensor_data(data_code: str, prev_day: int, today: int):
    tensor_x = []
    tensor_y = []
    get_data = quandl.get(data_code, returns="numpy")
    for k in range(prev_day):
        tensor_x.append(get_data[today - prev_day + k][1])
    tensor_y.append(get_data[today][1])
    tensor_x = Variable(torch.from_numpy(np.array(tensor_x))).float().view(1, 1, prev_day)
    tensor_y = Variable(torch.from_numpy(np.array(tensor_y))).float().view(1, 1, 1)
    return tensor_x, tensor_y


a, b = get_tensor_data("WIKI/AAPL", 5, 60)
print(a)

```

## 次回
次回は、Quandlから取得したデータで学習を行っていきます。  
[Anaconda環境でPyTorch 〜株価予想〜 #02 基礎知識・学習編](https://qiita.com/creaith/items/2d606a7f0effd5d839d5)

## Creaithメンバー
この記事の著者：[モトキ](https://qiita.com/pickles)、[曽宮](https://qiita.com/ryosomiya)
その他メンバー：[志村](https://qiita.com/naoto1222)、[上田](https://qiita.com/uedashuhei)
【Swift】効率よくUIColorを管理する

どうもーはじめて投稿します！
カナダの某スタートアップでiOSデベロッパーをやってるふじみなと申します。

今回は個人的に完全版じゃないかと思っている色の管理方法を紹介したいと思います。

# 最終リザルト
デフォルトのUIColorを使うときと同じように使えます！

```swift
view.backgroundColor = MyColor.green
//階層つきも
view.backgroundColor = MyColor.red.valencia
```


#環境
- Swift 4.1
- Xcode 9.3

# 1. UIColorのサブクラスを作る
`UIColor`を継承する`MyColor`というクラスを作り、なかに必要な色のクラス変数を追加していきます。

```swift

class MyColor : UIColor {
  class var peach: UIColor {
    return UIColor(red: 253.0 / 255.0, green: 189.0 / 255.0, blue: 57.0 / 255.0, alpha: 1.0)
  }

  // UIColorに登録されている色と名前がかぶっているものはoverrideすればOK
  override class var yellow: UIColor {
    return UIColor(red: 254.0 / 255.0, green: 207.0 / 255.0, blue: 51.0 / 255.0, alpha: 1.0)
  }
}
```

基本的には以上ですが、RGBで色の登録するのってめちゃくちゃめんどくさいですよね。
ということでHEXからUIColorを作れるようにします。

# 2. HexからUIColorを作る
UIColorをextensionしてconvenience initを作ります。

```swift
extension UIColor {
    convenience init(hex: String) {
        // スペースや改行がはいっていたらトリムする
        var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
        
        // 頭に#がついていたら取り除く
        if cString.hasPrefix("#") {
            cString.remove(at: cString.startIndex)
        }
        
        // RGBに変換する
        var rgbValue:UInt32 = 0
        Scanner(string: cString).scanHexInt32(&rgbValue)
        
        self.init(
            red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
            blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
            alpha: CGFloat(1.0)
        )
    }
}
```
[参考元](https://stackoverflow.com/questions/24263007/how-to-use-hex-colour-values)

すると、、、

```swift

class MyColor : UIColor {
  class var peach: UIColor {
    return UIColor(hex: "#4DA664")
  }

override class var yellow: UIColor {
   return UIColor(hex: "#d3d3d3")
  }
}
```
とってもすっきり&登録も簡単になりました！！
"#"はあってもなくても動くはずです。

# 3.階層をつける（オプション）
大量の色をが必要な場合、階層があったほうが便利かもしれません。
その場合、クラスを追加してその配下にいれるだけです。

```swift
class MyColor: UIColor {
    class red {
        class var valencia: UIColor {
            return UIColor(hex: "#d3d3d3")
        }
    }
}
```

# 以上！
冒頭の通り、あとはこのように呼ぶだけです。すっきり〜！

```swift
view.backgroundColor = MyColor.green
view.backgroundColor = MyColor.red.valencia
```

こうしたほうがいいなどご意見あればコメントください
Bluetooth meshの基本

# Bluetooth meshの基本
- 2017/7 Bluetoothがメッシュネットワークをサポート
- 多対多間のデバイス通信を可能にする
- 大規模なデバイスネットワークの構築に最適化されたネットワーク

## 応用範囲
- ビルオートメーション
- センサーネットワーク
- 資産追跡
- ビルオートメーション

ワイヤレスデバイスが高い信頼性とセキュリティの下で互いに通信するのに適している

## 機能
- Low Power機能
    - 無線通信がONになっている時間を短縮する
    - LPN（Low Power Node）
- Friend機能
    - 消費電力に制約のないノードが最適
    - LPN宛のメッセージやセキュリティアップデートを保管
    - LPNから要望に対応する
- Relay機能
    - 受信メッセージを他のノードで転送する
    - 一定の電源と処理能力が必要
- Proxy機能
    - GATT(Generic Attribute Profiel)toBluethooth meshノードとの送受信を実現
    - 十分な電源と処理能力が必要

## ノード構成
- ノード：
- エレメント：個別の構成要素
- モデル：機能を定義
- ステート：

- 例）
    - ノード：電球
        - モデル：オン/オフ
            - ステート：ON/OFF
        - モデル：明るさ
            - ステート：0~10
## モデル識別子
- モデル毎に固有の識別子をもっている
- Bluethooth SIG設定のモデル：　16ビット
- ベンダ設定のモデル：32ビット
- この識別子でモデルを一意に指定できる

## 通信方法
- クライアント/サーバ型アーキテクチャでメッセージ通信
### サーバ
- 役割：エレメントのステートを提供
### クライアント
- 役割：サーバへステートを要求、変更、利用
### 3つのモデル
- サーバモデル
- クライアントモデル
- コントロールモデル

## 用語集
- ショートバースト接続：必要な時に短いデータ伝送を行う利用形態

## 参考
- 以下のWebサイトを参考にさせてもらいました
- EDN Japan Bluetooth meshネットワークの基本概念
- http://ednjapan.com/edn/articles/1805/31/news026.html
react navigationで子コンポーネントにnavagitionさせる。

![alt](https://user-images.githubusercontent.com/26253721/39765058-e8d0eae4-531b-11e8-9305-4c852f269517.png)
react navigationで子コンポーネントの中でnavigationさせる時に、propを渡す必要がある。
いいサンプルが見つかったので紹介する。
// subcomponent ... receives navigate from parent
const Child = (props) => {
    return (
        <TouchableOpacity 
            onPress={() => props.navigate(props.destination) }>
            <Text>{props.text}>>></Text>
        </TouchableOpacity>
    );
}
// receives navigation from StackNavigator
const PageOne = (props) => {
    return (
        <View>
            <Text>Page One</Text>
            <Child 
                navigate={props.navigation.navigate} 
                destination="pagetwo" text="To page 2"/>
        </View>
    )
}
// receives custom props AND navigate inside StackNavigator 
const PageTwo = (props) => (
    <View>
        <Text>{props.text}</Text>
        <Child 
            navigate={props.navigation.navigate} 
            destination="pagethree" text="To page 3"/>
    </View>
);
// receives ONLY custom props (no nav sent) inside StackNAvigator
const PageThree = (props) => <View><Text>{props.text}</Text></View>

export default App = StackNavigator({
    pageone: { 
        screen: PageOne, navigationOptions: { title: "One" } },
    pagetwo: { 
        screen: (navigation) => <PageTwo {...navigation} text="Page Deux" />, 
        navigationOptions: { title: "Two" } 
    },
    pagethree: { 
        screen: () => <PageThree text="Page III" />, 
        navigationOptions: { title: "Three" }
    },
});

元ページ　「react-navigation - navigating from child component」
https://stackoverflow.com/questions/46269595/react-navigation-navigating-from-child-component
Blocklyを使ってCanvasに絵を描いてみよう

動機＆目的

プログラミング道場向けの教材作成

JSを使ったお絵かきができるようにしたい。
ただし対象が小学生から中学生と幅があり
キーボードが打てるとは限らない
またアルファベットが読めないかもしれない

目標
以下のようなJSを生成して実行できるようななるところまでサポートする。

```js
var game = document.getElementById("game");
var ctx = game.getContext("2d");
ctx.fillStyle = "lightblue";
ctx.fillRect(0,0,800,600);
ctx.fillStyle = "green";
ctx.fillRect(0,500,800,100);
ctx.strokeStyle = "brown";
ctx.beginPath();
ctx.lineWidth = 10;
ctx.moveTo(200,500);
ctx.lineTo(200,400);
ctx.stroke();
ctx.lineWidth = 5;
ctx.lineTo(150,350);
ctx.moveTo(200,400);
ctx.lineTo(220,380);
ctx.stroke();
```

カスタムブロックを作る・・

云々



ブロックに対応したコードを組み込む

実行すると
`document`がわかりませんと言われる・・・？？？

ゴール（以下のようなものを作りたい）
http://blockly-shapes.appspot.com/static/apps/shape/index.html

データソース
sed
AWK
Python リクルートのAPIを叩くとこまで


参考になりそうなもの
[javascript - Blockly on Node.js - Stack Overflow](https://stackoverflow.com/questions/39385916/blockly-on-node-js)
[Google 製 Visual Programming Editor「Blockly」の調査 - 高尾宏治日記 on はてなブログ](http://takaokouji.hatenablog.com/entry/2014/01/19/012014)
AtomのDotinstall Paneのショートカットキーについて 

ドットインストールで色々と勉強中です  
Atom入門で紹介されているDotinstall Paneを導入しました  
とりあえず、チラ裏メモ  

| 内容 | ショートカット |
|:---:|:---:|
|表示 非表示|⌥⇧ D|
|再生 一時停止|⌥⇧Enter|
|5秒進む|⌥⇧]|
|5秒戻る|⌥⇧[|
|再読み込み|^⇧⌘R|

検索だけショートカットキーが割り当てられていない 
この検索は、どういう機能？   
再読み込みは、隠しコマンド？

リンク  
[ドットインストール](https://dotinstall.com/)  
[Atom入門](https://dotinstall.com/lessons/basic_atom_v2)
jQueryで取得した値をparseInt関数でInt型にする。

#jQueryで受け取った値がInt型じゃなかった！

```js
$("input_data").click(function() {
    // parseIntで選択中の要素の値をInt型に変換する。
    var n = parseInt(this);

    //int型にしてから処理をする↓↓
    if (n > 5) {
        console.log("5より大きいっす！！");
    } else {
        console.log("5より小さいっす！！");
    }
});
```
なんちゃって初心者情シスの日常と気を付けてること

社員規模が200～300ぐらいのなんちゃって情シスに所属している者のメモ書きというか備忘録というか日常をつづったというかそんな感じです。
※メインで担当している人が別途おりますのでそのサポート的な立ち位置なので
　いろいろと足りない部分がある気しかしてないです。

普段の業務

- メールアドレスの管理
- PC、スマートデバイスのセットアップと管理
- PCトラブル対応
- 社内のネットワーク障害対応
- 基幹システムのマスター追加、エラー対応
- エクセルのバグ対応や相談

上記の内容が主な業務になっています。
ほかの企業様ではどんな感じなのでしょうか・・・ちょっと興味はあります。
#メールアドレスの管理
弊社ではGoogleのGsuiteでドメインをとっています。
1. 取得ライセンス数は少し余裕を見て契約をしておく。
2. 取得者、メールアドレス、パスワードは台帳にて管理する。
3. 契約書、発注先とのやり取りをPDFにし書類保管。
4. 極たまにパスワードリセット対応。
#PC、スマートデバイスのセットアップと管理
基本的な初期設定を行ってから営業、事務員にPCを引き渡すようなシステムになってます
1. ユーザー名、PCパスワード、PC名、IPアドレスや端末名などなどを台帳管理。
2. いつ購入したか、いつ撤去したかを台帳管理。
3. 購入店とのやり取りの書類保管。（稟議書や請求書や注文書や見積書や契約書など）
4．席替えを行った際にすべてのネットワーク系の配線の整理。
　└これ業者に頼んでやってもらえないんですかね・・・。
　　電源とかケーブルとか全然たりひん・・・。
#PCトラブル対応
 **こ　れ　が　主　な　業　務に　な　っ　て　い　る　**
1. パソコンの電源がつかないんだけど！
　└大体モニターの電源が抜けかけてモニターが付いてない。
　└何かの拍子に本体orモニターの主電源が抜けかけている。
　　└極たまに本当に壊れている。
2. パソコンが動作がおそいんだけど！
　└大体老朽化が原因。あと変なフリーソフト勝手に入れてるとか、Cドライブぱんぱんとか。
　└グーグルクロームのタブを20個以上開いてたりする。最近クローム重くないですか？
　　└不要なファイルの削除とアンインストールとかして気持ち軽くなるけど基本PCの入れ替えを検討してもらっています。　　

#社内のネットワーク障害対応
1. ネットにつながらないんだけど！<br>
└大体大に水曜日のWindowsUpdate配信日に言われる。どう頑張っても直せません。<br>
　└Updateの配信用鯖とかを置けば解決する・・・？<br>　　当方全くそのあたりは素人なので何とも言えませんが・・・。
2. ネットにつながらないんだけど！パート2<br>
└誰かが大量にパケットを送信している。（動画とかどでかいファイルのDLとか）<br>
　└たまにコンセント蹴飛ばしてネットワーク接続機器の電源がおちてる。

大体上記の2つで今のところは解決しています。
#基幹システムのマスター追加、エラー対応
1. 基本どんな症状が出ているのかヒアリングし、開発元にぶん投げるだけ。<br>
2. テストサーバーがあるため、発生状況を再現してみてバグの報告を行う。<br>
バグだらけの基幹システムを使用している為最近は大体何が原因でバグるのか・・・<br>というのも検討が付いてくるようになってきた。
2. マスターの追加依頼があれば追加を行う。画面が煩雑なので毎回てこずる。

#基幹システムの開発
　要件定義の為に現状使っているシステムの必須項目の洗い出し、<br>　足りない機能の洗い出しを同じ部署のメンバーで打ち合わせ。
　実務に関わっていない人が多いせいもあり、あれも欲しいよねこれも欲しいよねと収集が付かなくなることもしばしば
　とりあえずたまった定義をいろんな部署に投げかける。
　色々あって失敗には終わってしまったが、<br>　とにかく膨らむ要件をいかに抑えつつ開発元さんにスマートに依頼をできるかが大きなカギなきがしてる。
　あと要件定義と基本設計は絶対次のフェーズに持ち越しはダメ絶対。
　絶対取り返せないから・・・。<br>　あとあと担当部署は早めに打ち合わせに参加させるか納得させないとダメ。<br>　大事なところでそれい違うの一言でプロジェクトがググーンと後ろに戻されるから。<br>　10回以上繰り返したんじゃないかな。

#エクセルのバグ対応や相談
1. 在庫表をエクセルにて管理しているので月次で更新処理を手作業で行う。<br>
└マクロである程度自動化しているけどそれでも手作業が発生してる。いつか全自動にしたい。
2. 今まで使っていたエクセルが急にエラーになるんだけど！<br>
└大体行の削除とか列の削除で関数が死んでる。たまに右クリックで削除してる。<br>　
関数の性質をそこで伝えることがしばしば。
3. これ簡単に集計できない？<br>
　└元の表が様々なところにデータがちりばめてあるせいで普通の関数じゃ集計できねぇ！<br>
　　結局表自体のレイアウト修正から関数の埋め込みを行って作成する。<br>
　　└気が付いたらレイアウトを崩され以下無限ループ・・・・・・・・・
<br>

エクセル、ワードに関してはおそらく社内研修ができるような環境であればエクセルの基本的な関数と性質ぐらいは研修しておいたほうが今後絶対役に立つと思うの・・・。
#まとめ
要はパソコンにかかわる系の雑務全般を気が付いたら請負っていました。
なぜかネットワーク機器もある程度さわるようになって知識が微妙につきました。

あるあるとは思いますが**何もしていないんだけどこうなった**ってよくありますよね・・・。
休みの日に飲んで帰る途中電話が鳴って社内のネットワークがつながらない！なにもしてないのに！って呼び出されて向かったら、ネットワーク機器のコンセントが何者かによって蹴飛ばされ電源が抜けていたなんてことも。

もしこんなエピソードがあるよ！といったものがあったら是非コメントいただけると泣いて喜びます。
自分の中で新しい気づきがあるかもしれないです。

つたない文章ではありますが閲覧ありがとうございました。
Kotlin で AWS の S3 の特定のフォルダにあるファイルのURL一覧を取得する

Kotlin で AWS の S3 の特定のフォルダにあるファイルのURL一覧を取得したときのコードです。 Kotlin で AWS を操作したい人の参考になれば幸いです。

## Gradle

Gradle では AWS S3 のライブラリを記述します。

```gradle
buildscript {
    ext.kotlin_version = '1.2.40'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

group 'com.example'
version '1.0-SNAPSHOT'

apply plugin: 'kotlin'


repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk
    compile group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.319'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
```

## Credential

Kotlin の Credential と S3Client を作るコードです。 この部分は使いまわせます。

```kotlin
package com.example.s3

import com.amazonaws.auth.AWSStaticCredentialsProvider
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3ClientBuilder
import java.util.*

object Owner {
    val accessKey = "..."
    val secretKey = "..."
    val id = "..."

    fun createFilter(): Filter {
        return Filter().
                withName("owner-id").
                withValues(id)
    }
}

val credential = BasicAWSCredentials(Owner.accessKey, Owner.secretKey)

val s3client = AmazonS3ClientBuilder.standard().
        withRegion(Regions.AP_SOUTH_1).
        withCredentials(AWSStaticCredentialsProvider(credential)).
        build()
```

## ファイルのURLを出す部分のコード

私の場合、上のコードに加え、こちらのコードも同じファイルに記述して実行しました。

```kotlin
fun main(vararg s: String) {
    val ol = s3client.listObjects("bucket-name", "demo/folder/path")
    for (objectSummary in ol.objectSummaries) {
        if (!objectSummary.key.endsWith('/')) {
            println(
                    s3client.getUrl("bucket-name", objectSummary.key).toString().
                            replace(
                                "bucket-name.s3.ap-south-1.amazonaws.com/",
                                "s3.ap-south-1.amazonaws.com/bucket-name/").
                            replace("%29", ")").
                            replace("%28", "(").
                            replace("%20", "+"))
        }
    }
}
```

### 注意点

* `ObjectSummary` クラス の `key` が `/` で終わっているか否かで、 フォルダなのかファイルなのかをチェックしています。
* 有効なリンクにするために、数か所で`replace`を実行しています。 なぜ有効なリンクにならなかったのかはよくわかりません。
    * ドメイン, `)`, `(`, `+` について `replace` しています。
    * ほかにも `replace` するべきところはあるかもしれません。
    * ファイルの名前に `(`, `)`, ` ` がなければこの処理は必要ありません。
MySQLのDBファイルが肥大化して絶望を感じた時のこと

たまたま職場でsyslogサーバが機能していないのを見つけました。
mysqlとか触ったことなかったので、その時の対応についてメモ。

#### 状態の確認
`ps -ef | grep mysql` -> mysqldが起動しているか
`cat /etc/mysql/my.cnf` -> datadirやsoketのディレクトリを確認
`df` ->ディスクの空き容量が0になっていないか。

自分がみたときはディスクの空き容量が0になっており、/var/run/配下に作成されるはずのsocketファイルがなく、mysqldプロセスが落ちてました。

DBのファイルサイズは300GBを超えておりました。（明らかに大きすぎる）

#### mysqldの起動
無理やり容量を空けて復活させる。
/var/log/配下などの過去の圧縮ファイルを削除し、ほんの少しだけ容量を確保。
`/etc/init.d/mysql start`でプロセスを起動。
(環境によって違うと思います)


#### dumpの取得

dumpをとりたいけど、置き場がないので、
別のサーバの空きディスクにフルダンプを置くことにしました。

①待受ポートを作る
保存側： `nc -l 9998 | gzip -d > ibdata1_20180628.txt`
9998番が待受として当たります。

②mysqlのdumpをネットワーク経由で送信する
DB側： `/usr/bin/mysqldump -u root --password=XXXXXX --all-databases --flush-logs | gzip -c | nc 【保存側IPアドレス】 9998`

★時間かかるので＆オプションをつけるのが良いと思います。
★自分はtmuxを使用しました。
50GB程度のdumpファイルができました。

#### 肥大化したDBファイル（ibdata1）を削除
まずmysqlの停止
`/etc/init.d/mysql stop`

`rm -f ib*`
90%以上空き容量ができました。

#### dumpファイルを戻す
scpを使い、DBサーバに置きました。
ncコマンドでやり方がイメージできなかったので…。

#### リストア
mysqlの起動
`/etc/init.d/mysql start`

`mysql -u root --password=XXXXXX < ibdata1_20180628.txt`
★時間かかるので＆オプションをつけるのが良いと思います。

2億件、５０GBくらいのDBで4時間くらいかかりました。

なんとかなったみたいです。


-----
以下のサイトを参考にさせていただきました。


参考：[最速を究める! 2つのサーバ間で特盛りデータを30倍速で転送する方法](https://ameblo.jp/principia-ca/entry-12023722731.html)
参考：[MySQL ibdataのデータサイズが肥大化した場合の対処方法。](https://qiita.com/kooohei/items/15607ffbc3226d636b3f)
[Github-Pages]Github上で自分のページを公開しよう

最近、Qiita以外でのアウトプットの場を探している中で、今更ながら発見したgithub-pages。。。
早速使ってみようと思い、official documentをフォローしたのですが、それでできるのは非常に簡単な "Hello World"と帰ってくるだけのウェブサイト。
これを色々と肉付けしていくのは大変なので、今回は簡単につかえるtemplatesをどう使うのか調べてみました！
Jekyllです。
**どハマりしました。**

## 手順
1. Official Documentをみてみる。
2. Official Documentを無視して、僕の記事を読むことを決意する。
3. githubにログインしてください。
<img width="1083" alt="Screen Shot 2018-06-29 at 10.57.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/f80bcabb-9ccf-6de0-7861-78855a2d8f2f.png">
4. 自分の名前を使って下の画像のようにレポを作ってください。 `yourAccountName.github.io`
<img width="736" alt="Screen Shot 2018-06-29 at 10.57.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/2fd016ee-e003-318d-be51-de94362d3f57.png">
5. 今この状況。
<img width="1044" alt="Screen Shot 2018-06-29 at 10.57.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/ee2cab60-eaeb-5e01-fc2e-a29a99f20410.png">
6. Go to `Setting` and scroll down a bit.
<img width="792" alt="Screen Shot 2018-06-29 at 10.58.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/156ea2a7-3608-ae22-e9dc-4ad19773fbdd.png">
7. Choose Theme!
<img width="1091" alt="Screen Shot 2018-06-29 at 10.58.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/344387f7-869b-a525-d9fd-016d85daee97.png">
8. *Optional You can modify your index.md (this will affect your web-site automatically)
<img width="1041" alt="Screen Shot 2018-06-29 at 10.58.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/1278c13e-2ab6-0945-9637-ce4f692f18b2.png">
9. Push this index.md to your repo.
<img width="1059" alt="Screen Shot 2018-06-29 at 10.58.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/240801/5aa3c0d9-ba87-d644-c993-6345852af259.png">

## Done
https://rowing0914.github.io/
MacOS safariブラウザでダウンロードコンテンツが欠損する件

```php:ok.php

    header("HTTP/1.1 200 OK", true, 200);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"{$todayTimestamp}.pdf\"");
    readfile(DOCUMENT_DIR."/".$documentType);
```

結論としては上記コードが正常動作した.

不具合のあったソースは

```php:ng.php
    $documentBinary = file_get_contents(DOCUMENT_DIR."/".$documentType);
    header("HTTP/1.1 200 OK", true, 200);
    header("Content-Type: application/pdf");
    header("Content-Length: ".strlen($documentBinary));
    header("Content-Disposition: attachment; filename=\"{$todayTimestamp}.pdf\"");
    print($documentBinary);
```
だった.

```php
//以下ソースをコメントアウト
//header("Content-Length: ".strlen($data));
```

```php
// file_get_contents($path);をやめて
readline($path);
```
これでうごきました.

ng.phpのソースでもwindows上の各種ブラウザでは問題なく動作しておりましたが
MacOS上のsafariでは全く動作しないどころかダウンロードしたファイルがなにかしらの欠損が発生していたようです.
docker + mysql が接続できない /  Access denied for user 'root'@'172.18.0.5' (using password: YES)

# 問題
db のコンテナを立ててアプリからつなぐ際に、接続ができない。rails から db createできない 

ログ

```
Access denied for user 'root'@'172.18.0.5' (using password: YES)
Couldn't create database for {"adapter"=>"mysql2", "encoding"=>"utf8", "reconnect"=>false, "pool"=>5, "timeout"=>5000, "host"=>"db", "username"=>"root", "password"=>"pass", "port"=>3306,
```

docker logs

```
Version: '5.7.22'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
2018-06-29T01:49:15.357922Z 2 [Note] Access denied for user 'root'@'172.18.0.3' (using password: YES)
2018-06-29T01:49:50.804587Z 3 [Note] Access denied for user 'root'@'172.18.0.5' (using password: YES)
2018-06-29T01:49:54.664363Z 4 [Note] Access denied for user 'root'@'172.18.0.5' (using password: YES)

```

docker-compose.yml

```
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=pass
    ports:
      - '3306:3306'
    volumes:
      - db-data:/var/lib/mysql
```

Access denied for user 'root'@'172.18.0.5' (using password: YES)

# やったこと
・root以外のユーザーを作成、ユーザー名、パスワードなどを変更
・5.6に変更
・再起動


# 解決策
volumeを消したら行けた。。
https://github.com/docker-library/mysql/issues/51

名前付きのvolumeを使っていたので
`docker volume rm servicename_db-data`
【iOS】【Objective-C】.mp4などのバイナリデータをHTTP getでカメラロールに突っ込みたい

### [目的]
iOS端末にネットワークからダウンロードするmp4などのビデオをカメラロールに突っ込みたい。

### [環境]
* Objective-C
* Xcode 9.3.2
* iOS 11.4

### [やり方]
端末のローカルパスにダウンロードしたバイナリをwriteToFileして、そのパスをPhotosライブラリ使って書き込むことでビデオを端末取り込む。

### [サンプル]

```DownloadExample.m
//Library
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
#import <Photos/Photos.h>
//Model
#import "DownloadTaskModel.h"

@interface DownloadTaskModel()

@end

@implementation DownloadTaskModel

- (void)DownloadWithUrlValue:(NSString *)urlValue
{
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    
    manager.responseSerializer                  = [AFHTTPResponseSerializer serializer];
    manager.requestSerializer.timeoutInterval   = 10;
    manager.requestSerializer.cachePolicy       = NSURLRequestReloadIgnoringLocalCacheData;
    
    [manager POST:urlValue //URLを入力する
       parameters:nil
          success:^(AFHTTPRequestOperation *operation, id responseObject)
     {
         // responseを変換
         NSData *binaryData = [[NSData alloc] initWithData:responseObject];
         if (binaryData)
         {
             NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
             NSString  *documentsDirectory = [paths objectAtIndex:0];
             
             NSString  *localFilePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"tmpName.mp4"];
             
             dispatch_async(dispatch_get_main_queue(), ^{
                 [binaryData writeToFile:localFilePath atomically:YES];
                 
                 PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
                 [library performChanges:^{
                     [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL: [[NSURL alloc] initWithString:localFilePath]];
                 }
                       completionHandler:^(BOOL success, NSError * _Nullable error)
                  {
                      if (success)
                      {
                          dispatch_async(dispatch_get_main_queue(), ^{
                              //完了時なんらかのUIを追加
                          });
                      }
                  }];
             });
         }
     }
          failure:^(AFHTTPRequestOperation *operation, NSError *error)
     {
         
     }];
}

@end
```

カメラロールにアクセスするため、Info.plistに以下追加を忘れずに。
あとhttpアクセスする場合はATSを無効に。必要に応じて。

```Info.plist
   <key>NSAppTransportSecurity</key>
   <dict>
      <key>NSAllowsArbitraryLoads</key>
      <true/>
   </dict>
   <key>NSCameraUsageDescription</key>
   <string>カメラにアクセスします。</string>
```

### [特記事項]
同じソースコードをSwiftで書いても失敗する。
CircleCI 2.0の設定メモ

# tl;dr
RailsプロジェクトでCIをCircleCI2.0を利用。
DBをMySQLで構築したときに疎通させるので一苦労したのでメモしておく。

# 環境
Ruby 2.5.1
Rails 5.2.0
MySQL 5.7

# はじめに
CircleCIでプロジェクトを登録。
OSはLinuxを選択。（macOSはiOS向けのアプリとか作る用らしい（有料））
自動的にひな形が生成されるので、コピーしてアプリケーションrootに`.circleci/config.yml`として保存する。

# MySQLとの疎通設定の前に
## yarn installを追加
今回のプロジェクトでは、`webpacker`を利用しているので、jsパッケージ管理に`yarn`を使う。
`yarn`はバージョンが古くなっていると警告が出てテスト起動に失敗する（デフォルト）ので、`config.yml`に追記する。（設定でバージョン監視を無効にすることも出来るが、更新したほうがいいでしょう多分。）

```yaml
version:2
jobs:
  build:
    steps:
      ...
      # bundle exec rake db:createより前に書く！
      - run: yarn install
```

## 専用database.ymlの用意
テスト専用（CircleCI上で用意されるMySQL用コンテナ）で構築されるDBの設定を記述して、テスト実施前に差し替えて上げる細工が必要。

`config/database.yml.ci`

```yaml
test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: ci_test
```

で、これを差し替える細工を、`.circleci/config.yml`へ追加

```yaml
version:2
jobs:
  build:
    steps:
      ...
      # bundle exec rake db:createより前に書く！
      - run: yarn install

      - run: mv config/database.yml.ci config/database.yml # ココらへんに追加

      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
```

# MySQLの疎通
## コンテナの準備
CircleCIはdockerを使ってコンテナ単位で必要なものを起動してテストが走るので、今回はRubyが動作するコンテナと、MySQLが動作するコンテナが必要になる。
予め用意されているコンテナイメージのバージョンは、[ここで](https://circleci.com/docs/2.0/circleci-images/)確認出来る。

で、以下の感じ。

```yaml
version: 2
jobs:
  build:
    docker:
       - image: circleci/ruby:2.5.1-node-browsers

       - image: circleci/mysql:5.7.22
```

これだけだと、いろいろとエラーが出る。
特に環境変数類が入っていないので、さらに環境変数を追加する。

```yaml
       - image: circleci/ruby:2.5.1-node-browsers
         environment:
           - RAILS_ENV: 'test'

       - image: circleci/mysql:5.7.22
         environment:
           - MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
           - MYSQL_ROOT_HOST: '%'
```

CircleCI上で動作するテストでしか使われないので、ユーザーとか細かいことは気にしてないです。

参考程度に。
(今更)Linux で HW(MAC)アドレスを取得する方法

RaspberryPI シリーズに DHCP を利用して固定 IP を割り当てたり、WiFi の AP で MAC アドレスフィルタリングをしたいと思ったときに必要となるのが NIC の HWアドレス(MACアドレス)。ということでまとめ。

# 結果を見たいだけの時
(出力結果の IPv4/MAC アドレス部分は適当に改変しています)
## 旧来のコマンド(ifconfig)
シェルスクリプトなどで再利用したい場合には下記の結果の　'ether' で始まる行を grep して sed するなり awk するなり cut すればよい。

```shell-session

[hoge@fuga ~]$ /sbin/ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.34.56  netmask 255.255.255.0  broadcast 192.168.34.255
        ether XX:YY:ZZ:PP:QQ:RR  txqueuelen 1000  (イーサネット)
        RX packets 110242  bytes 12368079 (11.7 MiB)
        RX errors 0  dropped 1  overruns 0  frame 0
        TX packets 7611  bytes 1440299 (1.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

- 最近はこのコマンドがデフォルトでインストールされていないディストリビューションも多い
- たとえインストールされていても、/sbin や /usr/sbin 配下にいることが多いため、一般ユーザーでログインしているときは PATH が通っていないことも(但しsudo するなりフルパス指定で起動すれば問題ない)
- 上記二つの理由から、私としては下記の ip コマンドの利用を推奨。

## 新しめのコマンド(ip)
シェルスクリプトなどで再利用したい場合は ifconfig コマンド同様、'link/ether' で始まる行を grep なり tail -n 1 して以下略

```shell-session
[hoge@fuga ~]$ /bin/ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether XX:YY:ZZ:PP:QQ:RR brd ff:ff:ff:ff:ff:ff
```

- /bin か /usr/bin にいるはずなので誰でも実行可能
- 無駄な出力は少な目

## 論外(dmesg コマンドをデバイス名で grep )
Linux のブートログを漁る方法。
一般的にネットワーク関連デバイスのデバイスドライバは、読み込まれた時点でブートログに MAC アドレスを吐き出すことが多い。
ただ、物によっては MAC をログに吐き出さないデバイスドライバもある(RaspberryPI3 の WiFi てめぇだ)上に、デバイス/ディストリビューションに依存して出力形式も多種多様なのでこれは論外。



# シェルスクリプト内で、余分な出力なしで MAC アドレスのみを探る時
ifconfig コマンドにせよ ip コマンドにせよ、バージョンアップで出力形式が変更されたら即アウトなので
上記コマンドの出力結果をゴニョゴニョして自作スクリプト内で再利用することはあまりお勧めできない。
ということで実はここからが本題。ワンライナー一撃。

```shell-session
[hoge@fuga ~]$ cat `find /sys/devices/ -name eth0`/address
XX:YY:ZZ:PP:QQ:RR
[hoge@fuga ~]$
```

- 出力結果を grep する必要もなければ sed とか cut といったコマンドにパイプ処理する必要もないので、各種コマンドのオプションを知る必要もなし。
- 追加インストールなしのコマンドだけでできるのでディストリビューション不問
- まずないとは思いますが、指定されたデバイス名(この例だとeth0)に一致するサブディレクトリが複数存在している場合だけ要注意(そんなときは head/tail コマンドでどうにかしてください)
- (2019/04/04 コメントを頂戴したので追記) デバイスドライバとしてファームウェアを利用するホスト上で、一般ユーザーが実行するとデバイスツリーの一部を読み取れないことに起因するアクセスエラーが標準エラーに出力される。その場合は

```shell-session
[hoge@fuga ~]$ cat `find /sys/devices/ -name eth0 2>/dev/null`/address
XX:YY:ZZ:PP:QQ:RR
[hoge@fuga ~]$
```
に変えてください

以上
WebViewのshouldOverrideUrlLoadingでSPAのURLローディングを検知できない場合の対処法

# はじめに
AndroidのWebViewでURLローディングを検知する際、 `shouldOverrideUrlLoading` を使うのがよくある方法だと思いますが、POSTリクエストの場合、この方法ではイベントの検知が出来ません。

# やり方
WebViewClientの `doUpdateVisitedHistory ` を使います。
[doUpdateVisitedHistory](https://developer.android.com/reference/android/webkit/WebViewClient.html#doUpdateVisitedHistory(android.webkit.WebView,%20java.lang.String,%20boolean)) は訪問済みリンクのデータベースを更新するメソッドです。

``` java
mWebView.setWebViewClient( new WebViewClient(){
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                Log.d(TAG, "shouldOverrideUrlLoading LOLLIPOP url = " + request.getUrl().toString());
                return false;
            }

            @SuppressWarnings("deprecation")
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.d(TAG, "shouldOverrideUrlLoading url = " + url);
                return false;
            }

            @Override
            public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
                Log.d(TAG, "doUpdateVisitedHistory url = " + url);
            }
        });
```

では、WebViewからSPAにアクセスしてみます。

```
06-29 10:10:50.756 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/profile/home
06-29 10:34:41.636 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/connect
06-29 10:34:41.658 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/logout
06-29 10:34:41.671 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/connect
06-29 10:34:44.131 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/signin
06-29 10:34:54.526 13453-13453/jp.sample D/WebViewFragment: doUpdateVisitedHistory url = https://xxxx/auth/callback?token=xxxx
```


無事、検知できました！