OmniAICreator/Qiita-1.07M huggingface dataset:
PHPの思考盗聴のしくみ〜あるいはApacheとの関係性〜

理由あってLAMP構成のアプリケーションを触るようになって勉強してるんですが、PHPっておもむろにクッキーを読みだしたりできて怖くないですか。

言語処理系に思考(?)盗聴されてないかどうか確かめるために、Apacheサーバー上のPHPアプリケーションがどのように実行されているのかを軽く調べたので、そのメモです。

PHPの実行形式とかの話
=
Rails生まれUnicorn育ち、rackインターフェスのやつは大体友達。あ、リバースプロキシはnginxでよろしくな！という人生を送ってきたので適当な場所に`.php`ファイルを置いただけでなにやらアプリケーションが動き出してる現象が理解できず、まずこの辺を調べました。phpのデーモンプロセスとかどこにも見当たらないのに、なんか結果は帰ってくるの心霊現象っぽい。

Apache-PHPの構成には大きく分けてmodule形式とcgi形式というものがあります。[主にこの記事](https://www.fumi.org/neta/201205sv.html)が詳しいです。ざっくり区別すると
 
 - module形式はapacheのphp用のモジュールくんがPHP処理系に.phpファイルを食わせて帰ってきた結果をHTTPレスポンスに加工して返す感じ。
 - cgi形式はphp-cgiというやつに投げてphp cgiくんが.phpファイルを〜以下略

という感じっぽいです。各手法のメリットデメリットはここでは触れません(そもそもcgi形式の中でもいろいろあるらしいので。また気になったときに調べます)。普通に構成してればmodule形式になってるはずなので、じゃあ実際にapacheのモジュールがどうやってphpを実行してるの、という話に進みます。

Apacheがどこで読み込んでるのかという話
=
多くのケースで`/etc/httpd/http.conf`とかにある設定ファイルをgrepすると、

`LoadModule php7_module libexec/apache2/libphp7.so`

みたいな行が見つかるかと思います。　なんと今はmod_phpという名前じゃないんですね。ちなみにこのモジュールは[
PHPの処理系ビルドの際に生成される](https://github.com/php/php-src/blob/d0fd9fe977b07c497e927eeb50b115c5cd40fdc7/sapi/apache2handler/config.m4#L84-L111)っぽいので、apacheの方のコードを探さないように注意。

さて、loadされたmoduleがどう使われてるかという話ですが… apacheは基本的にリクエストに対してフックが発生し、そのフックについて対応できるモジュールを順に探すみたいなやり方を採用してるらしいです。

[Apacheモジュールのフック関数リスト](https://http2.try-and-test.net/list_hooks.html)
[フックからApacheの全体像を追う](http://dayflower.hatenablog.com/entry/20081029/1225266220)
[mod_phpモードの原理解析](https://codingjp.com/web/22050/)

三つ目のエントリでも解説されてますが、php処理系は[こういうフック](https://github.com/php/php-src/blob/6e3600f41b95d97d11ef48f817e6389a4ee95091/sapi/apache2handler/mod_php.c#L26-L34)を新たに定義、登録しています(なんか微妙に名前がちがうけど)。メソッドとしては[これ](php_ap2_register_hook)ですね。この中で、特に重要なのが、

```
ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
```
ですね。handlerフックはリクエストごとにその処理をハンドルする候補になるフックで、phpはそのタイミングに[こういう場合はphpとして実行してくれ](https://github.com/php/php-src/blob/2dd2dcaf9c8bcdda9c687660da887c5fddeb7448/sapi/apache2handler/sapi_apache2.c#L567-L735)みたいな設定をしてるという感じっぽいです（ちゃんと読んでないのであやふや）。


sapiとかいう単語なんやねんという話については[このスライド](https://www.slideshare.net/do_aki/php-sapi-zendengine3)にあるので気になったら読んでください。

で、結局クッキーはどこなの
=
https://github.com/php/php-src/blob/2dd2dcaf9c8bcdda9c687660da887c5fddeb7448/sapi/apache2handler/sapi_apache2.c#L752

↓

https://github.com/php/php-src/blob/2dd2dcaf9c8bcdda9c687660da887c5fddeb7448/sapi/apache2handler/sapi_apache2.c#L486

↓

https://github.com/php/php-src/blob/2dd2dcaf9c8bcdda9c687660da887c5fddeb7448/sapi/apache2handler/sapi_apache2.c#L400

↓

https://github.com/php/php-src/blob/2dd2dcaf9c8bcdda9c687660da887c5fddeb7448/sapi/apache2handler/sapi_apache2.c#L230

```.c
static char *
php_apache_sapi_read_cookies(void)
{
  php_struct *ctx = SG(server_context);
  const char *http_cookie;
 
  http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
 
  /* The SAPI interface should use 'const char *' */
  return (char *) http_cookie;
 }
```

読んでた。PHPは無実であった。

さいごに
=
やっぱりソースコードリーディングは目的があった方が捗るというのと、動作についての納得は大事ですね。

C言語ガバなので完全に追い切れてるわけではないのがかなしい。おべんきょうしよ。。。

ついき

nginxの場合は[これ](https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)を見れば良さそうです。
Azure VM を RDP 接続しているときに、 NIC を無効化して RDP 接続できなくなった時の対処法。

#はじめに

Azure VM は 下記のとおり RDP ファイルをダウンロードして RDP 接続するのが基本だが、RDP 接続中に NIC が 1 つしかなかった場合、その NIC を無効化してしまうと、当然そのコンピューターには RDP 接続できなくなってしまいます。その場合の対処方法を記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/53277f1f-ce25-3f5f-99ca-352c5ece267c.png)

#シリアル コンソールを使おう
Azure VM には上述の場合に備えて、シリアル コンソールが用意されています。
対象のサーバーの左ペインのメニューより、「シリアル コンソール」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/e5988879-34be-d773-18ab-a444911b5e94.png)

すると下記のとおり、コンソール画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/cca112f6-036d-d28a-8e19-73e5dc26f412.png)

cmd コマンドでチャネルを開始します。
そのあとに、下記コマンドで起動したチャネル番号に接続します。

```
書式
ch -si <チャネル番号>

実行例)
ch -si 3
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/2dab54be-ae06-0441-bb2b-f5184cc2a1db.png)

Enter キーを押下後に対象のコンピューターの資格情報を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/2eca6b82-9028-2135-6118-fb3f376c8504.png)

認証に成功すると下記のとおり、対象のコンピューターにログオンできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/852f3359-79d8-4f21-0c58-8fa93273002a.png)

ここで下記コマンド レットにて、ネットワーク インターフェースの情報を確認します。

```
netsh interface show interface
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/7bd3f5b7-4597-be8a-71c5-4876ed0c3cf3.png)


描画がずれていてわかりづらいが、「イーサネット 2」 が「切断」状態になっているのが分かります。
そこで、下記コマンドレットで「イーサネット2」を「有効」にします。

```
書式
netsh interface set interface name="interface Name" admin=enabled

実行例)
netsh interface set interface name="イーサネット 2" admin=enabled
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/708f80f2-b621-7c06-c70d-298fc1982fa0.png)


画面がずれていて非常にわかりづらいが、「イーサネット2」の State が「切断」から「接続」に変更されることが分かる。

#接続できるかな？
この状態で、 RDP ファイルをダブルクリックし、対象コンピューターに接続できるかどうか確認してみる。

「接続」ボタンをクリックする。緊張の瞬間である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/b2104989-8c6f-7508-b32f-57bebb5ef745.png)

無事資格情報の入力画面が表示された。あとは「OK」ボタンを押すだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/9f558526-0039-de31-9042-834fc7cc4d8b.png)

ここまでくれば安心！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/0d602c63-068a-be72-c0c3-b77e4ad78a78.png)

ネットワーク接続を開いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/ed1fc65a-4cf0-1716-5eb1-3175d1f5b537.png)

無事イーサネット 2 が有効可されています！
※ちなみにイーサネット 1 はテスト用に作成しているので、基から無効にしています。(今回の記事とは関係ありません)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373423/80f7046a-1e22-a92c-890f-2e6c19338a62.png)

#まとめ
VMware を使い慣れている人は、 プロパティ画面から NIC の無効→有効を「コンソール」画面からできることをご存知かと思いますが 、 Azure にもちゃんとコンソール画面が用意されています。
一瞬 RDP 接続できなくなって焦ると思いますが、コンソール画面より冷静に対処しましょう。

ちなみに Microsoft の公開情報にもコマンド例が記載されていますので参考にしてください。

ネットワーク インターフェイスが無効になっているために VM にリモート デスクトップ接続できない
URL:https://docs.microsoft.com/ja-jp/azure/virtual-machines/troubleshooting/troubleshoot-rdp-nic-disabled

最後まで読んでいただきありがとうございました。
『応答なし』にならないアプリ開発

#『応答なし』と表示される原因
処理開始から終了まで一定時間描画系のWindowsメッセージ(WM_PAINT等)が処理されないと『応答なし』が表示されます。
*※レジストリの設定にもよりますが、現在主要Windows7以降の標準では5秒が標準となります。*

主にシングルスレッドで重い処理(メソッド内で時間のかかる処理をしたりDBから大量のデータを取得等々)した時におこります。ループ処理で調子よく動いているように見えてもフォームをクリックとかしたら途端に『応答なし』になったりしますよね。

#『応答なし』の回避策あれこれ
##Application.DoEventsをコール
まず思いつくのが「DoEvents」。
便利な反面メッセージキューにある全てのWindowsメッセージが処理されるため、思いがけない動作をする可能性があります。
業務用アプリでは二度押し防止策等で動作中各種ボタンを非活性にする等することが多いですが、やはりすべての副作用的要素が取り除けない為、出来れば最終手段としたいものです。

##Win32APIによるWindowsメッセージ処理
次にWin32APIの使用で、描画系のメッセージのみ処理する方法があります。
が、結果的にDoEvents同様各ボタンの非活性化などが必要になります。
(DoEventsより副作用は抑えられるはずですが・・・)

##BackgroundWorkerにる別スレッド実行
ここからが本題ですね。
BackgroundWorkerを使用することで手軽にマルチスレッド処理が実現できます。
注意点としてはワーカースレッドからコントロール等スレッドセーフでないものに直接アクセスしないことでしょうか。処理の中でコントロールへアクセスする必要がある場合、Invokeを用いるか、BackgroundWorkerのProgressChanged・RunWorkerCompletedイベントのようなメインスレッドで実行される部分でする必要があります。

以下簡単なサンプルになります。

・Form1にボタン・プログレスバー・ラベルを一個ずつ配置

```VB:Form1.vb
Imports System.ComponentModel
Public Class Form1
    Private MAX_COUNT = 100
    Private WithEvents bgWorker As New BackgroundWorker

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        ProgressBar1.Hide()
        Label1.Hide()
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ProgressBar1.Maximum = MAX_COUNT
        ProgressBar1.Value = 0
        ProgressBar1.Step = 1
        Label1.Text = String.Empty

        '*** 進行状況の報告を有効に
        bgWorker.WorkerReportsProgress = True
        '*** 処理実施
        ProgressBar1.Show()
        Label1.Show()
        bgWorker.RunWorkerAsync()
    End Sub

    ''' <summary>
    ''' BackgroundWorkerの処理部
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub bgWorker_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgWorker.DoWork
        For i = 1 To MAX_COUNT
            '*** 重い処理
            Threading.Thread.Sleep(500)
            '*** プログレス処理
            bgWorker.ReportProgress(i)
        Next
    End Sub

    ''' <summary>
    ''' プログレス処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub bgWorker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgWorker.ProgressChanged
        ProgressBar1.PerformStep()
        Label1.Text = String.Format("({0}/{1})", ProgressBar1.Value, MAX_COUNT)
    End Sub

    ''' <summary>
    ''' BackgroundWorker処理完了時
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub bgWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted
        ProgressBar1.Hide()
        Label1.Hide()
    End Sub
End Class
```
BackgroundWorker等別スレッドで実行する際もDoEvents同様各ボタンの非活性等で同時実行を制御する必要があることに気を付けてください。


次のステップとして、Task(Async/Await)がありますが、長くなっているので[次回](https://qiita.com/ytkproject/items/46be0aeaa888bbd399cb)に(。-`ω-)b
PowerShell から LINE WORKS の 監査 API で監査データをダウンロード

PowerShell のコマンドレット操作で LINE WORKS の監査 API を用いて、監査ログを CSV 形式でダウンロードする方法です。

スクリプト ファイルをタスク スケジューラから実行するなどの方法で、監査ログの出力を自動化できます。

##事前作業

LINE WORKS の監査 API を利用するため、Developer Console から以下の事前作業を行います。

API 認証の準備
- API ID 発行
- サーバー API のコンシューマーキー発行
- サーバー API の Server Token

手順はこちらのページの情報を参照します。
https://developers.worksmobile.com/jp/document/1002002?lang=ja

##監査 API による監査データのダウンロード

LINE WORKS の監査 API については、こちらのページに説明があります。
https://developers.worksmobile.com/jp/document/30014001?lang=ja

PowerShell の Invoke-RestMethod コマンドレットで、監査 API を実行します。

構文は次のとおりです。

```
Invoke-RestMethod -Uri "https://jp1-audit.worksmobile.com/works/audit/log/<service_parameter>/logs.csv?apiId=downCsvLog&serviceId=audit&rangeName=domain&_startDate=<yyyymmdd>&_endDate=<yyyymmdd&_tenantId=<tenantId>&_domainId=<domainId>&language=ja-JP" -Method Get -Headers @{Authorization = "Bearer <Server_Token>"; consumerKey = "<consumerKey>"} | Out-File C:\temp\auditlog.txt
```

パイプ処理で Out-File コマンドレットで、txt ファイルに出力しています。
PowerShell から トーク Bot API で LINE WORKS にメッセージ送信 (LINE WORKS API 1.0)

## PowerShell で LINE WORKS にメッセージ送信

PowerShell のコマンドレット操作で LINE WORKS のトーク BOT API を用いて、任意のメンバーやトークルームにメッセージを送る方法です。

この記事は LINE WORKS API 1.0 に沿った記載です。API 1.0 は 2023 年 4 月 30 日にリタイア予定です。API 2.0 に準じた記事を以下で掲載しています。
https://qiita.com/iwaohig/items/85a40c6c01d6486a53eb

## 事前作業

LINE WORKS でトークボット API を利用するため、LINE WORKS の Developer Console で、以下の事前作業を行います。


◆ API 認証の準備
- API ID 発行
- サーバー API のコンシューマーキー発行
- サーバー API の Server Token

手順はこちらのページの情報を参照します。
https://developers.worksmobile.com/jp/document/1002002?lang=ja

◆ Bot 登録
Bot メニューで [登録] ボタンをクリックし、以下の項目を入力し、保存をクリック
- Bot名 -> 任意の名前
- 「説明」-> 任意の説明文
- Callback URL -> 今回は Off
- Botポリシー -> 用途に応じて設定
- 管理者 -> 任意のメンバーを指定

登録すると Bot No. が生成されるので、確認しておきます。

## トーク Bot API によるメッセージ送信

LINE WORKS の トーク Bot API の解説はこちらのページです。
https://developers.worksmobile.com/jp/document/100500801?lang=ja

PowerShell の Invoke-RestMethod コマンドレットで、トーク Bot API を実行します。


```
$header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$header.Add("Content-Type","application/json; charset=UTF-8")
$header.Add("consumerKey","<Server API Consumer Key>")
$header.Add("Authorization","Bearer <Server Token>")
$header.Add("Cache-Control","no-cache")

$request = @"
{
    "accountId": "<user id>",
    "content": {
        "type": "text",
        "text": "<メッセージ本文>"
    }
}
"@


$Body = [System.Text.Encoding]::UTF8.GetBytes($request)

$Uri = "https://apis.worksmobile.com/r/{API ID}/message/v1/bot/{botNo}/message/push"
Invoke-RestMethod -Uri $Uri -ContentType 'application/json' -Method Post -Header $header -Body $Body
```

上記により、LINE WORKS へトーク メッセージの送信が可能です。
tf.data.Datasetを入力にImageDataGeneratorを使ってData Augmentation（水増し）を行う

# はじめに
[前回](https://qiita.com/shoji9x9/items/f74a0f7c9da1de099d4d)、Fashion-MNISTをCNNで分類し、Test Accuracy: 91.3でした。そこで次はData Augmentationを行うことで、どれだけ精度が上がるのか確認してみようと思ったのですが、tf.data.DatasetをData Augmentationする方法がよくわからなかったので、まずはそれを調べてみることにしました。

# 環境
* Google Colaboratory
* TensorFlow 2.0 Alpha

# コード
[こちら](https://github.com/shoji9x9/data-augmentation-with-Keras)です。

# コード解説
## データセット取得
```Python
import tensorflow_datasets as tfds

batch_size = 64

dataset = tfds.load('cifar10')
dataset = dataset['train']
dataset = dataset.batch(batch_size)
```

今回はCIFAR-10を題材にしてみました。本当は`'cats_vs_dogs'`にしようとしたのですが、バッチ単位に縦横のサイズを合わせないと、Data Augmentationでエラーになってしまったので諦めました。

## Data Augmentationの設定
世の中にはたくさんデータはあるもののラベル付きのデータというのはそう多くありません。新しくラベルを付けようとするとコストがかかるのですが、今ラベルの付いているデータを少し加工してやれば簡単にラベル付きのデータを増やすことができます。そうして増やしたより多くのデータを学習することにより汎化性能が高まり精度が上がることが期待できます。データの水増しなどとも言います。これをKerasのImageDataGeneratorを使って実現します。

```Python
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(rotation_range = 30, horizontal_flip = True, zoom_range = 0.2)
```

今回は回転、左右反転、ズームを行うことにしました。本当はcutoutも実現したかったのですが、[公式ドキュメント](https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator)を読む限り実現できないような気がします。

## Data Augmentation、結果表示
```Python
import math
import numpy as np
import matplotlib.pyplot as plt

column_size = math.floor(math.sqrt(batch_size))
row_size = math.ceil(batch_size / column_size)
fig, ax = plt.subplots(row_size, column_size, figsize = (row_size * 2, column_size * 2), subplot_kw = {'xticks': (), 'yticks': ()})

for axis in ax:
    for a in axis:
        a.set_axis_off()

for data_list in dataset:    
    image_list = data_list['image']
    label_list = data_list['label']

    row, column = 0, 0
    for x, y in datagen.flow(image_list, label_list, batch_size = batch_size):
        print(x.shape)
        for _x in x:
            _x = tf.cast(_x, tf.uint8)
            ax[row, column].imshow(_x)
            if column == column_size - 1:
                column = 0
                row += 1
            else:
                column += 1
        break
    break
```

`data_list`は`batch_size`のイメージとラベルのセットを持っています。`image_list`や`label_list`はndarrayで、`image_list`のshapeは(64, 32, 32, 3)です。これらを`datagen.flow`の引数に与えることで、入力のイメージをランダムに回転、左右反転、ズームした画像が生成され`x`に代入されます。`image_list`と`x`は1対1の関係になっています。あとは結果を表示しているだけです。matplotlibで枠線や目盛りを消す方法を調べるのに地味に時間がかかりましたが・・・。`datagen.flow`は無限ループしますので1つ目の`break`は必須です。

## 出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337041/87b566a1-f585-7b42-314a-1e1e1ebb5ca7.png)
何となく回転やズームはわかるかと思います。左右反転はわからないですね・・・。

# 最後に
tf.data.Datasetを入力にImageDataGeneratorを使っているコードがあまり世の中にないような気がしたので作成してみました。どなたかのお役に立てると幸いです。次はこれを使いどれだけ精度が上がるか確認してみます。
基本情報技術者試験が試験終了から-1秒後に不合格確定した

はじめまして、もぺねこです。

とある普通科高校の3年生という肩書きです。

プログラミングに関しては、 [ドン廃あらーと](https://donhaialert.herokuapp.com/) というWebサイトを作成した程度です。

本題に入ります。

基本情報技術者試験を受験した理由は、大学の推薦条件にも含まれていたためです。

現代社会において最低限必要であろう知識を得るという目的もありますが、これは二の次です。

勉強期間は数ヶ月ですが、テストやら課題やらで実際に勉強できたのは50時間にも満たないと思います。

## なぜ落ちたと確信できるのか

試験終了から僅かしか経っていないのに何故決めつけるのか、と思われても仕方がないので最初に書いておきます。

`午後問題において解答した問題番号をマークしていない` という小さな凡ミスをしてしまいました。

そして、これに気づいたのが試験終了1秒前です。

なお、マークしていない場合は選択問題が全問不正解となります。

## 見直しはしなかったのか、最初にマークしなかったのか

私は午後問題が極端に苦手で、当日の昼休憩まで勉強していましたが、自信がありませんでした。

そのため、試験中に緊張してしまい、マークまで気が回らなかったと振り返ります。

そもそも過去問をペーパーで解いていればこのような事態にはなりませんでしたが、学校の課題やテストの勉強によってスケジュールが詰まっていて、どうしても一度もやることなく本番を迎えてしまいました。

## たった1つの良かったこと

過去問は問題を把握するだけではなく、解答の手順を把握するためにも重要だと強く実感しました。

そう考えたら、この試験の失敗は無駄ではなかったのかもしれません。

## どうすればよかったのか

正直全くわかりません。

リラックスするにも、試験中にリラックスすることは私にとってとても難しいです。

なにか良い方法があれば、コメントにてご教授願います。

## 結局この記事でなにを言いたいのか

どれだけ努力しても、私のように無駄になることがあります。

しかし、失敗の中には活かせることもあるかもしれません。

それを糧にしていくことが重要であると、同じような失敗をした人に伝えたいのです。
Leetcode #720: Longest word in dictionary

Thought: For each word, check if all prefixes word[:k] are present.


```swift
func longestWord(_ words: [String]) -> String {
    var answer = ""
    var count = 0
    let wordSet = Set(words)
    for word in words {
        let wordCount = word.count
        if wordCount < count {
            continue
        }
        var possible = true
        for index in word.indices {
            let str = String(word[...index])
            if !wordSet.contains(str) {
                possible = false
                break
            }
        }
        if possible {
            if wordCount > count {
                answer = word
                count = wordCount
            } else if word < answer {
                answer = word
            }
        }
    }
    return answer
}
```
rails newした後に表示されるメッセージはなに？

# はじめに

`rails new`をしたら、`Using`　`Fetching`　`Installing`がズラズラと表示された後、最後に何やらメッセージが表示されたため、Google翻訳で訳してみた。

# 直訳

```
Ruby Sass has reached end-of-life and should no longer be used.

* If you use Sass as a command-line tool, we recommend using Dart Sass, the new
  primary implementation: https://sass-lang.com/install

* If you use Sass as a plug-in for a Ruby web framework, we recommend using the
  sassc gem: https://github.com/sass/sassc-ruby#readme

* For more details, please refer to the Sass blog:
  https://sass-lang.com/blog/posts/7828841

         run  bundle exec spring binstub --all
* bin/rake: spring inserted
* bin/rails: spring inserted
```

>Ruby Sassは廃止予定のため、もう使用することはできません。
>Sassをコマンドラインツールとして使用する場合は、新しい主要な実装であるDart Sassを使用することをお勧めします。
>もしあなたがRubyウェブフレームワーク用のプラグインとしてSassを使うなら、sasscを使うことをお勧めします。
>詳しくはSassのブログをご覧ください。
#PowerApps SharePointリストへのカメラ画像アップロード (Flowなし & 添付ファイルなし)

#PowerApps上でのカメラ画像の取り扱い

ほとんど下図だけで説明は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/834bf17a-2846-b533-4b5b-5fc2d9ad2858.png)

CameraのPhotoプロパティをラベルにセットするとBase64文字列が表示されます。

#画像の登録
上の方法を応用して、SharePointのカスタムリストに画像を登録してみます。
注意するべき点はフィールドのタイプを複数行テキストにすることです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f63c674a-580c-d463-aae1-c71b2690d137.png)

フォームで側の設定では、複数行テキストに対応するDataCardValueのDefaultをCamera.Photoに変更します。
※NewやEditなど、ちゃんと対応する場合には

```DataCardValue.Default
If(Form1.Mode=FormMode.New,Camera2.Photo,Parent.Default)

```
このように設定すればよいかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/59ec5038-14ad-6134-9edb-484b52bb2488.png)

表示する際には、テキストを非表示にする代わりに、画像コントロールを挿入し、非表示にしたテキストを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f22ec7d0-36cb-5ae1-934c-782f8f2e45f5.png)

このように非常に簡単な方法で、SharePointのカスタムリストに画像を登録することができました。

参考:
https://www.powerappsug.com/communities/community-home/digestviewer/viewthread?MessageKey=21337777-8f51-4695-86b5-82c513c45a8e&CommunityKey=9f5c6fd1-bb0c-4ffa-adab-06d3d72c11da&tab=digestviewer
Mockeryですでに設定済みのshouldReceive()を上書きしたい場合のやり方

# setupで定義したMockメソッドの戻り値を変更しようとすると。。。

戻り値が変更されない！！

```php
//...略

class ServiceTest extends TestCase
{
    protected function setUp()
    {
        parent::setUp();

        $this->mockTestService = \Mockery::mock(TestService::class);
        $this->mockTestService->shouldReceive('validation')
            ->andReturn(true);
    }

    public function testValidation_trueが返却されること()
    {
        $this->assertTrue($this->mockTestService->validation()); // OK
    }

   /**
     * @expectedException ValidationException
     */
    public function testValidation_ValidationExceptionがスローされること()
    {
        $this->mockTestService->shouldReceive('validation')
            ->andThrow(ValidationException);
        
        $this->mockTestService->validation(); //NG 例外が発生しない
    }

}
```


# どうすればあとから戻り値を定義しても動いてくれるか？

答えはちゃんと載っていました。
[Mockery1.0 日本語訳](https://readouble.com/mockery/1.0/ja/default_expectations.html)
[Github Mockery issue_401](https://github.com/mockery/mockery/issues/401#issuecomment-67765217
)

```php
//...略

class ServiceTest extends TestCase
{
    protected function setUp()
    {
        parent::setUp();

        $this->mockTestService = \Mockery::mock(TestService::class);
        $this->mockTestService->shouldReceive('validation')
            ->byDefault() //☆☆ポイント
            ->andReturn(true);
    }

    public function testValidation_trueが返却されること()
    {
        $this->assertTrue($this->mockTestService->validation()); // OK
    }

   /**
     * @expectedException ValidationException
     */
    public function testValidation_ValidationExceptionがスローされること()
    {
        $this->mockTestService->shouldReceive('validation')
            ->andThrow(ValidationException);
        
        $this->mockTestService->validation(); //OK
    }

}
```

これであとからでも戻り値を置き換えられるようになりました！
私が使っているワンストップ Laravel用DockerFileのご紹介

# 言いたいこと
小規模アプリなら、Laravel-Worker、Cron、Nginx、php-fpmを一つにまとめて運用したい!!
と思い作ったのが、全部入りDockerイメージ [one-stop-laravel-docker](https://github.com/yamatox/one-stop-laravel-docker)

現在私が趣味で開発しているWEBアプリはこのDocker imageベースのcontainerで運用しています。

# どんな構成なのか

* PHP（php-fpm）
* Nginx
* Cron
* Laravel worker

上記プロセスを「supervisord」で起動しています。

# どうやって作っている？

[Dockerfile](https://github.com/yamatox/one-stop-laravel-docker/blob/master/Dockerfile)を見ていただければすべて載っていますが、
PHP-FPMのDockerイメージに、NginxのDockerFileをそのままマージした、という荒っぽい作りとなっています。

# 良い点

* アプリ自体は１コンテナで動作するので、管理が楽（もちろん、永続化させる必要のあるデータベースとRedisは別コンテナですが）
* NginxとPHPそれぞれに静的コンテンツを置かなくてもよくなる
* Laravelのコード入れて実行すれいい感じに動いてくれる

# 悪い点
* Dockerのベストプラクティスに真っ向から勝負を仕掛けている（1コンテナ 1プロセス）
* 規模の大きなアプリには向かない（スケーリングする前提だと向かないかも）
Linux(CentOS)にHomebrew on Linux(Linuxbrew)をインストールするまで

##概要
MacでおなじみHomebrewのLinux版(Linuxbrew)をインストールする。

##環境
CentOS Linux release 7.6.1810 (Core)

##Linuxbrewとは
以下の特徴を持つパッケージ管理ツール。
- rootではなくユーザのhomeにインストールすることが可能。sudoが不要。
- [ホストディストリビューション](https://kotobank.jp/word/%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-6086)にパッケージされていないソフトウェアをインストールする
- [ホストディストリビューション](https://kotobank.jp/word/%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-6086)が古い場合に最新バージョンをインストールできる

##インストール

###前提
Linux環境構築し、root以外のユーザを作成していること。
Docker上でやる場合は、前回私が投稿した記事も参考になるかと思います。

参考↓
[Docker(CentOS)イメージから新規ユーザを追加し運用できるようにするまで](https://qiita.com/libra_lt/items/dd98297cb00aaf1c4c67)


###Linuxbrewに必須なパッケージをインストール

Linuxbrewをインストールする前に、必要なパッケージをインストールする。

```
sudo yum groupinstall 'Development Tools' && sudo yum install curl file git ruby which
```

####Linuxbrewインストール

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
```

インストール時にどこにインストールするか確認されるが、推奨されていた`/home/linubrew`に設定した。

####パス設定

bash利用者はbashの設定ファイルにパスを追加。ここではbash_profileにパスを追加する。

```
echo 'eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)' >>~/.bash_profile
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
```

####確認

なんでもいいのでインストールできるか確認。ここでは「Hello, world!」と表示するだけのパッケージをインストールする。
helloコマンドを入力し、実行できることを確認する。

```
brew install hello
```

補足
macOS High Sierra 10.14.4
Docker version 18.09.2, build 6247962
Java script のreturnがいまいちしっくりこない人の為に、わかり易く解説！

Java scriptで関数を定義した際によく使われるreturn。

初学者の方の中には理解に苦しんでいる方も多いと思う。

そこで、このreturnの理解に困っている人に向けてわかりやすく説明したいと思う。


例として次のような関数を作ったとしよう。

```main.js
  function sum(a, b, c) {
   console.log(a + b + c);
  }

  sum(1, 2, 3);   /*コンソールの結果・・・6*/
  sum(3, 4, 5);   /*コンソールの結果・・・12*/
```
上記ではsumと言う名前の関数を定義して引数a,b,cを足した値をコンソールに表示するといった、とても簡単な関数である。

コンソールの結果は
6
12
となる。

次にこのsum(1, 2, 3)とsum(3, 4, 5)の合計をもとめたい場合があるとしよう。

ここでreturnの登場である。

先ほどの関数を次の様に変更してみよう。

```main.js
  function sum(a, b, c) {
   return a + b + c;
  }

  const total = sum(1, 2, 3) + sum(3, 4, 5);
  console.log(total);
```

totalと言う変数にsum(1, 2, 3) + sum(3, 4, 5);の値を入れるのだが、ここでreturnがすでに活躍しているのだ。

一番初めに作った関数では
 sum(1, 2, 3); 
 sum(3, 4, 5);
はただ単に関数を実行しただけだが、returnをした場合はreturn a + b + c;の計算結果の値がsum(1, 2, 3); sum(3, 4, 5);に返されるのである。

その結果、変数totalにsum(1, 2, 3) + sum(3, 4, 5);の結果が代入されるのである。
下記を参照。

```main.js
  function sum(a, b, c) {
   return a + b + c;
  }

  const total = sum(1, 2, 3)/*returnで6が返ってきた*/ + sum(3, 4, 5);/*12が返ってきた*/
  console.log(total);
```

ちなみにreturnを書いた以降の処理は実行されないので注意。

おわかり頂けたでしょうか？

ここら辺は、基本中の基本ですが、基本をしっかりとマスターしてJava Scriptの理解をより一層深めて行きましょう。
Ojを使う際は mode => compat を指定した方がよい

最も早い JSON エンコーダーの1つに [Oj gem](https://github.com/ohler55/oj) がある。ほとんどのケースでは Oj を使うだけで JSON のエンコード/デコードのパフォーマンスが劇的に改善する。

ただし、1つ注意点があり、Oj を使う際はこのオプションを必ず指定した方がよい。

```ruby
mode => compat
```

もし上記のオプションを指定していないと、下記のように `:` で始まる文字列が意図せずシンボルになってしまう。

```ruby
pry(main)> Oj.load('{"a": ":b"}')['a'].class
=> Symbol
```

もちろんこの挙動は Oj のドキュメントに書いてありバグではないのだが、おそらく Oj を利用する人の大半はこの挙動を望んでいないはず。

このオプションはエンコード/デコードの両方で指定することができる。

```ruby
Oj.load('{"a": ":b"}', mode: :compat)['a'].class
=> String

pry(main)> Oj.dump({a: :b}, mode: :compat)
=> "{\"a\":\"b\"}"
```

上記のオプションの挙動さえ忘れなければ、Oj は素晴らしい役目を果たしてくれる。パフォーマンス比較結果は下記の記事の通り。

- [RailsデフォルトのJSONレンダリングは遅いので注意。Ruby/RailsでJSON生成時に最もパフォーマンスが良い方法を調べてみた。](https://qiita.com/ttiger55/items/d144b8094d61b70955bf)

- [JSONの替わりに使ったOJが速い](https://qiita.com/abey1192/items/0475b401d9b7e8d33cbd)

- [Oj.dumpでシンボルを吐く時は:mode => compatする](http://r9.hatenablog.jp/entry/2013/11/10/000000)

Oj のパフォーマンス比較では Rails(ActiveSupport) の JSON モジュールが遅すぎると言われることが多いが、それは機能の豊富さとのトレードオフであり、単純な早い遅いの議論は不毛。そのあたりについて詳しい記事は下記の通り。

- [Rails でも JSON.generate を使って高速にシリアライズしたい 〜Rails の to_json は遅いが何を実現しているのか〜](https://abicky.net/2017/05/07/180842/)

JSONを高速化する別のアプローチとして [fast_jsonapi gem](https://github.com/Netflix/fast_jsonapi) もある。

- https://github.com/Netflix/fast_jsonapi

以上。
『機械学習のエッセンス(http://isbn.sbcr.jp/93965/)』のPythonサンプルをJuliaで書き換えてみる。（リンクまとめ）


『[機械学習のエッセンス　実装しながら学ぶPython、数学、アルゴリズム](http://isbn.sbcr.jp/93965/)』のPythonサンプルをJuliaで書き換えてみたので、リンクをまとめました。書き換えたのはリンクがある項目だけです。

●目次
はじめに
第01章　学習を始める前に
第02章　Pythonの基本
第03章　機械学習に必要な数学
第04章　Pythonによる数値計算
　[01 数値計算の基本](https://qiita.com/yshutaro/items/daa1fcfdac31140e8fae)
　[02 NumPyの基本](https://qiita.com/yshutaro/items/c1cc1fad28376b5ba9dc)
　[03 配列の基本計算](https://qiita.com/yshutaro/items/01da8826324027b4aa6b)
　[04 疎行列](https://qiita.com/yshutaro/items/e0a3a6c9ea84f8ab0fd3)
　[05 NumPy/SciPyによる線形代数](https://qiita.com/yshutaro/items/5bab7b6014fb3003b97f)
　[06 乱数](https://qiita.com/yshutaro/items/3076d097cd2d4cf92089)
　[07 データの可視化](https://qiita.com/yshutaro/items/54d64c406f624545429a)
　[08 数理最適化](https://qiita.com/yshutaro/items/fd64f83d5e5300882233)
　[09 統計](https://qiita.com/yshutaro/items/0a7f9bd15309e7dffe41)
第05章　機械学習アルゴリズム
　01 準備
　[02 回帰](https://qiita.com/yshutaro/items/a7626035c8ab13bf54a1)
　[03 リッジ回帰](https://qiita.com/yshutaro/items/38fbeffd78f786d3d591)
　[04 汎化と過学習](https://qiita.com/yshutaro/items/aaead448d342c10cf5b0)
　[05 ラッソ回帰](https://qiita.com/yshutaro/items/5818e4fd2ab9e976c3b1)
　[06 ロジスティック回帰](https://qiita.com/yshutaro/items/b3edf44af7774f4e935f)
　[07 サポートベクタマシン](https://qiita.com/yshutaro/items/95a90db19f0639828bfa)
　[08 k-Means法](https://qiita.com/yshutaro/items/80e44045e628d49de298)
　[09 主成分分析（PCA）](https://qiita.com/yshutaro/items/de2e9de22c436d25ffc6)
Elmアプリ開発するときに便利な共通モジュールの管理方法

Elmに限らず、アプリ開発をする際にユーティリティー関数などを使いたい時に「あれ、これどうやって使うんだったっけな？」と思ってソースコードを逐一見に行く経験をしたことがある方は多いのではないでしょうか？

Elmの場合、ディレクトリ構造を工夫して[elm-doc-preview](https://github.com/dmy/elm-doc-preview)を使うと、そんな面倒とはおさらばできます。

## 追記

elm-doc-preview が [application にも対応しました！](https://discourse.elm-lang.org/t/elm-doc-preview-3-applications-support-offline-packages-documentation-server/4167)
(@miyamo_madoka さんによる[よくわかる解説](https://qiita.com/miyamo_madoka/items/5cbb3791cd2899f87feb)もあります)

## まずはサンプル

百聞は一見に如かずということで、[サンプル](https://github.com/arowM/elm-form-decoder/tree/master/sample)を用意しました。

```bash
$ git clone https://github.com/arowM/elm-form-decoder.git
$ cd elm-form-decoder/sample/lib
$ npm start
```

を実行して http://localhost:8001/ にアクセスすると共通モジュールのドキュメントが表示されます。

![Screenshot_2019-04-21 Elm Doc Preview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/03c99abb-2f4f-3ba3-d46d-a53b76258236.png)


## プロジェクト構成

普段のプロジェクト構成と異なる点は、

1. `lib` というディレクトリがあり、中に `type: package` の elm.json と共通モジュールのソースコードが置いてある
2. `lib/package.json` の [dependencies](https://github.com/arowM/elm-form-decoder/blob/master/sample/lib/package.json#L11) に elm-doc-preview が含まれている
3. `lib/package.json` で [npm start](https://github.com/arowM/elm-form-decoder/blob/master/sample/lib/package.json#L4) すると elm-doc-preview によるモジュールのライブプレビューイングが立ち上がるようになっている
4. elm.json の [source-directories](https://github.com/arowM/elm-form-decoder/blob/master/sample/elm.json#L3)に `lib/src` が含まれている

の4点です。

つまり、共通モジュールをライブラリとして開発してしまうのです。

共通モジュールをライブラリとして開発することの利点はいくつかあります。

* elm-doc-preview が使えるので、ウェブブラウザ上できれいに整形されたモジュールのドキュメントを読むことができる
* ライブラリのようにきちんとドキュメントが書かれていないと elm-doc-preview がエラーを吐くので、ドキュメントをちゃんと書くようになる
* ライブラリの形式になっているので、ちょっとよそ行きの感じのピシっとした気持ちでコードを書くので質が上がる

個人開発でも恩恵はありますが、特に複数人で分担しながらElmでアプリ開発をする際には、他のメンバーのことを考えたコードを書くことが強制されるのでよりこの手法がマッチするでしょう。

[さくらちゃんにご飯をあげる](https://www.amazon.co.jp/gp/registry/wishlist/20ZV2VC57615B/ref=nav_wishlist_lists_1)
[さくらちゃんをもっと見る](https://twitter.com/hashtag/%E3%81%95%E3%81%8F%E3%82%89%E3%81%A1%E3%82%83%E3%82%93%E6%97%A5%E8%A8%98?src=hash)
[他の記事を見る](https://qiita.com/arowM)
![D4fKdXRU0AIhRQZ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/e032ce4c-7d0b-203e-ac42-0fc08cb8f1c4.jpeg)
Jetson nano セットアップメモ

Jetson Nanoのセットアップメモです。(作成中)

## 準備するもの

本体の他にSDカード、ACアダプタなどが必要です。

- Jetson nano 本体
    - https://www.nvidia.com/ja-jp/autonomous-machines/embedded-systems/jetson-nano/
    - https://www.switch-science.com/catalog/5433/
    - https://elinux.org/Jetson_Nano
- Fan (32x32 mm, 4-pin PWM)
    - 5V, 40x40x20mm 4-pin PWM, https://noctua.at/en/nf-a4x20-5v-pwm
    - (?) https://www.marutsu.co.jp/pc/i/4836/
    - (?) https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-58TZ
- Micro SD card (16GB以上 UHS-1)
    - Samsung EVO Plus (MB-MC32GA/ECO)
- 5V AC adopter (2A以上)
    - https://www.adafruit.com/product/1995
    - MicroUSB http://akizukidenshi.com/catalog/g/gM-12001/
    - DC(3A 5.5mm,2.1mm) http://akizukidenshi.com/catalog/g/gM-08311/
    - DC(4A 5.5mm,2.1mm) http://akizukidenshi.com/catalog/g/gM-06238/
- WiFiアダプター
    - Edimax EW-7811Un
- Camera
    - Raspberry Pi Camera Rev. 2.1 http://akizukidenshi.com/catalog/g/gM-10518/
- HDMI monitor
- Keyboard
- ケース(3Dプリンター)
    - https://www.thingiverse.com/thing:3547555
    - https://www.thingiverse.com/thing:3518410


## SDイメージのダウントードと書き込み (Ubuntu 16.04 ホストの場合)

Jetson Nano Developer Kit SD Card Image を
https://developer.nvidia.com/embedded/downloads
からダウンロード。MicroSDをPCのスロットにセット。

    $ dmesg
    [5015979.433182] mmc0: cannot verify signal voltage switch
    [5015979.561852] mmc0: new ultra high speed SDR104 SDHC card at address 0001
    [5015979.562503] mmcblk0: mmc0:0001 EB1QT 29.8 GiB 
    [5015979.564700]  mmcblk0: p1

この場合は mmcblk0 で自動でマウントされる。アンマウントしてから、イメージを書き込み。書き込みにはしばらくかかります。


    $ /usr/bin/unzip -p ~/Downloads/jetson-nano-sd-r32.1-2019-03-18.zip | sudo /bin/dd of=/dev/mmcblk0 bs=1M status=progress
    12867469312 bytes (13 GB, 12 GiB) copied, 387.002 s, 33.2 MB/s 
    0+174238 records in
    0+174238 records out
    12884901888 bytes (13 GB, 12 GiB) copied, 455.262 s, 28.3 MB/s


## 起動

- モニター、キーボード、マウスを接続して。ACアダプタを接続。
- 起動画面で、EULA同意、言語選択（英語）、KB選択(US)、タイムゾーン選択（日本）
- DesktopがUnityだとうまく起動できないので、Ubuntuで起動 (パスワード入力の下の設定アイコンから選択)
- 緑のバックグラウンドのデスクトップが表示されればOK

## JetPack, TensorRTのデモ実行

JetPackは導入済みなので、jetson-inference をソースからビルドする。 https://github.com/dusty-nv/jetson-inference/blob/master/docs/building-repo.md に記載されている方法で問題なく動作。 クロックノーマルでもかなりヒートシンクが熱くなるのでファンは付けたほうが良い。



## その他

TBD

## 参考

- Getting Started With Jetson Nano Developer Kit
    - https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#intro
- Nvidia Jetson Nano
    - https://dev.to/jeikabu/nvidia-jetson-nano-1250
- Getting Started with the NVIDIA Jetson Nano Developer Kit
    - https://blog.hackster.io/getting-started-with-the-nvidia-jetson-nano-developer-kit-43aa7c298797
- Google Coral Edge TPU vs NVIDIA Jetson Nano: A quick deep dive into EdgeAI performance
    - https://blog.usejournal.com/google-coral-edge-tpu-vs-nvidia-jetson-nano-a-quick-deep-dive-into-edgeai-performance-bc7860b8d87a
-
How To Access Pulseway RESTful API Using Python Flask

This is another simple python tutorial to access API.We will access Pulsway APi using Python3 and Flask Framework. You can monitor systems from any mobile devices. You can manage systems, control applications and display data in real time.

https://www.restapiexample.com/python/how-to-access-pulseway-restful-api-using-python-flask/
codeigniter個人的に使えそうな物リストアップ

個人的にcodeigniterで使えそうなライブラリとかノウハウとか、資料をリストアップしています。

## 開発

•<a href="https://github.com/JCSama/CodeIgniter-develbar" target="_blank">JCSama/CodeIgniter-develbar: CodeIgniter Developer Toolbar is a third party library based on Profiler Library with additional functionality for debugging and optimization, Database, Models, Helpers, Libraries, Views, Ajax.</a>
開発者用のツールバーです。かなり便利そう。

## ビュー系

<a href="https://github.com/domProjects/CI-Breadcrumb" target="_blank">domProjects/CI-Breadcrumb: Breadcrumb library for CodeIgniter 3.x.x</a>
パンくずリスト。自分で作ると毎回面倒くさいことになるので大変助かります。

<a href="https://github.com/techlab/codeigniter-smartgrid" target="_blank">techlab/codeigniter-smartgrid: A simple PHP datagrid control for CodeIgniter framework with Bootstrap</a>
bootstarpのグリッドコードを作ってくれる。みたいなのだが、基本的にコントローラー上でhtmlコードを作るみたい。私はビューファイル上でhtmlコードを組んじゃうので、使うことはあまり無いかなって。

<a href="https://ah-2.com/2015/12/05/codeigniter_view_variables.html" target="_blank">CodeIgniterのViewで少しだけ工夫した点 - ah-2</a>
ビューで読み込める変数の一覧出力とか、思いつかなかったのでさっそく真似しようと思います。


•<a href="https://packagist.org/packages/seunmatt/codeigniter-log-viewer" target="_blank">seunmatt/codeigniter-log-viewer - Packagist</a>
ログビューアー



## 認証系

<a href="https://github.com/emreakay/CodeIgniter-Aauth" target="_blank">emreakay/CodeIgniter-Aauth: Authorization, authentication and User Management library for Codeigniter 2.x and 3.x to make easy user management and permission operations</a>
シンプルなユーザー、ロール登録。扱いやすそう。

<a href="https://github.com/benedmunds/CodeIgniter-Ion-Auth" target="_blank">benedmunds/CodeIgniter-Ion-Auth: Simple and Lightweight Auth System for CodeIgniter</a>
メール認証も含めた総合的なログインライブラリ。欲しい機能がひとまとめで入っているので、新しいサービスなんかを作る時に、こちらも便利そう。

## キャッシュ

<a href="https://github.com/terrylinooo/codeIgniter-multi-level-cache" target="_blank">terrylinooo/codeIgniter-multi-level-cache: Simple modification makes the cache files store to multi-level sub-folders.</a>
ユーザーごとにキャッシュを分けたりして、これまたユーザーごとに一括削除したいときとか。これでディレクトリごとにキャッシュを分けることができるのでとても便利。通常のキャッシュとほぼ変わらず利用できます。

## SEO
•<a href="https://github.com/elsodev/Codeigniter-SEO-Helper" target="_blank">elsodev/Codeigniter-SEO-Helper: A simple helper for Codeigniter to create meta tags for SEO</a>
SEOヘルパー。シンプルに使いやすい。
Auth0 の Rules で LINE WORKS で多要素認証を利用する

Auth0 の Rules を用いて、LINE WOKRS で多要素認証を利用可能にします。  
なお、事前に Auth0 を LINE WORKS の認証基盤とするよう設定が必要です。以下の記事を参照。  
TITLE: Auth0 で LINE WORKS に SSO  
URL: https://qiita.com/iwaohig/items/af93af5ac1e1f420ea01  

## Auth0 の Multifactor Auth の設定

1.Auth0 の管理画面にアクセス
2.[Multifactor Auth] メニューをクリック
3.[Factors] で利用する認証要素を選択
今回は Google Authenticator を使う想定で [One-time Password] のトグルを ON  

## Auth0 の Rules の設定

Auth0 の管理画面内に多数の rule template が用意されており、要件に見合ったものを利用することができます。

1.Auth0 の管理画面にアクセス
2.[Rules] メニューをクリック
3.[+ Create RULE] ボタンをクリック
4.[Pick a rule tempate] の [Multifactor] カテゴリーから要件に応じたテンプレートを選択
5.ここでは "Multifactor when request comes from outside an IP range" を選択し、社内ネットワーク以外からのアクセス時は MFA といった想定で設定
6. [Edit Rule] でテンプレートが表示される
要件に沿った編集をここで行う

```
function (user, context, callback) {
  const ipaddr = require('ipaddr.js');
  const corp_network = "192.168.1.134/26";
  const current_ip = ipaddr.parse(context.request.ip);

  if (!current_ip.match(ipaddr.parseCIDR(corp_network))) {
    context.multifactor = {
      provider: 'guardian',

      // optional, defaults to true. Set to false to force Guardian authentication every time.
      // See https://auth0.com/docs/multifactor-authentication/custom#change-the-frequency-of-authentication-requests for details
      allowRememberBrowser: false
    };
  }

  callback(null, user, context);
}
```
7.[SAVE] をクリック  

以上の設定により、指定されたネットワーク以外からのログイン試行時には、多要素認証を利用可能となります。
Google Apps ScriptでSHOWROOMで配信中の番組情報を取得する

# 概要
ストリーミングサービスの[SHOWROOM](https://www.showroom-live.com/)にはRSSのようなものはなく番組情報を簡単に取得することができません。
そこでGoogle Apps Scriptを使って一定間隔で番組情報を取得する仕組みを構築します。

# 番組情報API
https://www.showroom-live.com/api/live/onlives
にアクセスすると配信中の番組情報がJSON形式で取得できます
ジャンル情報の配列があり、その中に各番組情報が格納されています。

この中でよく使いそうなのは

|key|内容|
|----|----|
|room_url_key| 配信URLのID<br>https://www.showroom-live.com/ と結合することで配信URLを取得できる|
|started_at| 配信開始タイムスタンプ |
|room_id| プロフィールのID<br>https://www.showroom-live.com/room/profile?room_id= と結合することでプロフィールを取得できる|
|main_name|配信のタイトル|
|telop|動画のテロップ|
|image|配信のサムネイル|

# Google Apps Scriptの作成
新規のスプレッドシートを作成します
そして、ツール→スクリプトエディタを開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/c6eabdf8-088c-7f51-a889-ed91c9b1cccf.png)

こんな感じでエディタが開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/5c2f5936-1508-7171-e5c8-1f0ad57e2f1f.png)

下記のコードをコピー＆ペーストします

```JavaScript
function myFunction() 
{
  //スプレッドシートの取得
  var book = SpreadsheetApp.getActiveSpreadsheet();
  var sheetData = book.getSheetByName("シート1");
  
  //いったん内容をクリア
  sheetData.clear();
  
  //APIにアクセス
  var url = 'https://www.showroom-live.com/api/live/onlives';
  var response = UrlFetchApp.fetch(url);
  var html = response.getContentText('UTF-8');
  
  //JSONに変換
  var content = JSON.parse(html);
  var onlives = content["onlives"];
  var count = 1;
  for( i in onlives )
  {
    var lives = onlives[i]["lives"];
    for( x in lives)
    {
      //room_idがない場合があるのでチェックする
      if(lives[x]["room_id"])
      {
        sheetData.getRange(count, 1).setValue(lives[x]["room_id"]);
        sheetData.getRange(count, 2).setValue(lives[x]["room_url_key"]);
        sheetData.getRange(count, 3).setValue(lives[x]["main_name"]);
        sheetData.getRange(count, 4).setValue(lives[x]["started_at"]);
        sheetData.getRange(count, 5).setValue(lives[x]["image"]);
        count++;
      }
    }
  }
}
```

実行すると下記のような結果を得ることができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/7a10eb69-b6a7-aa95-1380-6f453aa29134.png)

# 定期実行する
編集→現在のプロジェクトのトリガーを開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/fcd6c901-492c-88ef-92f2-e5dd6cc3b837.png)

新しいトリガーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/b02c7161-6a69-db89-3adc-bfb0d7741c14.png)

イベントのソースを時間主導型にすることで任意の間隔でスクリプトを実行することができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105021/eddf2dab-541b-6532-ef02-1332152784f2.png)

これで一定間隔でスプレッドシートに番組情報が更新されるようになりました。
あとは取得したい配信のroom_idかroom_url_key事前に取得しておき
一致するものが来たら他のサービスに配信中の通知を発行するといったことが可能になります。
Reduxで@@INITで初期Stateは設定しないほうが良い

タイトルのママです。
Reduxで初期Stateに値を入れる際は、@@INITを使わないほうが良い。
(後で調べたら、アンチパターンらしい）

下のように初期Stateを@@INIT時に渡すように設定していたら、
Production状態でINITがスルーされており正しく読み込まれていないことが判明。  
（ちなみにREDUX devtoolsは＠INITを読み込んでいるので発見に遅れた。）   
<img width="1139" alt="スクリーンショット 2019-04-21 14.56.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77132/40649ab2-dfe9-b3cb-cfd4-9aa7066d1073.png">
 
`改善前`  

```javascript:activity.js  
const initialState = {
   likeIDs : [],
   hoge:{},
}

function setIdsToState = arr => {
   let a = [];
   if(Array.isArray(arr)){
     arr.map( n=> { a.push(n.id) });
   }
   return a;
}

const activity = (state: Object = initialState, action: any) => {
    switch(action.type){
      case '@@INIT': {
        const ids = setIdsToState(window._a);
      return {
         ...state,
         likeIDs = ids
      }
    }
}
```  

結局initialState時に初期値を渡すようにして改修。  

`改善後`  

```javascript:activity.js 

const _ids = { likeIDs = setIdsToState(window._a) };

const initialState = {
   ..._ids,
   hoge:{},
}

function setIdsToState = arr => {
   let a = [];
   if(Array.isArray(arr)){
     arr.map( n=> { a.push(n.id) });
   }
   return a;
}

```  

Productionモードにしないと気づかなかったので、焦った。。

下記記事参考になりました。
https://github.com/reduxjs/redux/issues/186
https://qiita.com/kuy/items/869aeb7b403ea7a8fd8a
【Git・GitHub】学習内容のまとめ（Udemy:はじめてのGitとGitHub）

#はじめに
・学習内容の定着が目的の記事です。
・RailsチュートリアルでGitが全くわからずに途中で挫折したため、Udemyの教材でGitを学び直しました。

#使った教材について
Udemyの[はじめてのGitとGitHub](https://www.udemy.com/intro_git/)を使って学習しました。こちらは無料にも関わらず初学者向けに分かりやすく解説されています。

Gitの教材としては、「Progate」が人気ですが、個人的には[はじめてのGitとGitHub](https://www.udemy.com/intro_git/)から学習することをおすすめします。

同じ製作者の有料版の教材である[もう怖くないGit！チームで必要なGitを完全にマスター](https://www.udemy.com/share/1004bOB0oZdVdQQXo=/)はブランチやマージ、コンフリクトの解消方法、リベース、GitHubを利用した開発フローなど、チーム開発に必要なGitの使い方を解説しています。Railsチュートリアルレベルで使われるGitの使用法を学習する場合は、無料版で十分だと思います。

#Gitとは
- バージョン管理システム
    - 最新のファイルが何かすぐにわかるようにする
    - 複数人で同じファイルを編集している場合に、「誰が」「何を」「いつ」「何のために」「どのように」編集したのかが分かるようにする
    - 以前のファイルの状態に戻すこともできる

#GitHubとは
- Gitのリポジトリのホスティングサービス
    - Gitで管理している変更履歴をインターネット上で管理してくれるサービス
- 複数人での作業を実現
    - プリリクエストによるコラボレーション    
- 世界中の開発者のコードを閲覧できる 

#基本的な操作
###Gitのインストール（mac）
macでは標準でGitがインストールされています。念のためインストールされているかの確認をしましょう。

```terminal:terminal
$ git version
git version 2.10.1
```
###ローカルリポジトリの作成
リポジトリとは、ファイルやディレクトリの状態、変更履歴を記録する場所です。
まずは、Gitで管理したいディレクトリに移動して、ローカルリポジトリを作成します。

```terminal:terminal
$ git init
Initialized empty Git repository in "パス"
```
###基本的なワークフロー
1.ファイルを編集する

2.ファイルの変更をステージングエリアに追加する
`git add ファイル名`
※ステージングエリアとは、コミットするファイルを選択するためのものです。最初のうちはあまり気にする必要はありません。

3.ローカルリポジトリにコミットする
`git commit -m "変更の内容・理由を説明するメッセージ"`

4.リモートリポジトリにプッシュする
まずはGitHubで、リモートリポジトリを作成します。
`git remote add origin リモートリポジトリのURL`
リモートリポジトリが登録されたのでプッシュします。
`git push -u origin master`
※「-u」は次回以降に「origin master」の入力を省力するためのオプションです。

#原則
- １作業ごとに１コミット
- 分かりやすいコミットメッセージを書く

#終わりに
今回、初めてqiitaに記事を書いてみました。
分かりずらい箇所、間違っている箇所があればコメントいただけると幸いです！
VSCodeでgradle+Javaの環境を整えたときにやった手順(Windows 10)

普段はJavaScriptメインなので間違いがあれば教えてください。
念のためツールなどのインストールからやります！

##(1) VSCode・gradle・Javaインストール
今回はchocolateyを使います。chocolateyのインストールは[こちら](https://chocolatey.org/install#install-with-cmdexe)

```bash
choco install vscode -y
choco install gradle -y
choco install openjdk -y
```

##(2) gradleプロジェクト作成
まずは適当なフォルダを作って、VSCodeで開きます。

```bash
mkdir sample-project
cd sample-project
code . #カレントディレクトリをvscodeで開く
```

ここからはvscodeのターミナルでやってもOK

```bash
gradle init 
# オプション選択
Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 3 

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 1

Project name (default: sample-project):
Source package (default: sample.project):
```

##(3) 自動補完

- VSCodeに[Java Extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack)という拡張機能をインストールする。(VSCodeの再起動忘れずに)

- `build.gradle`を編集

```groovy:build.gradle
plugins {
    id 'java'
    id 'application'
    id 'eclipse' //これを追加。classpathを出力させて自動補完を効かせるため。
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'junit:junit:4.12'
}

mainClassName = 'sample.project.App'

//ここから下を追加

//文字化け対策
tasks.withType(JavaCompile) {
	options.encoding = "UTF-8"
}

// 依存ライブラリを含む単一で実行可能なjarを作成させる。
jar {
    manifest { attributes 'Main-Class': mainClassName }
    from configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
```
- クラスパスを出力

dependenciesを変更した後に必ず実行しましょう。

```
gradle eclipse
```
これで自動補完が出来るようになったはず。

##(4) コードフォーマッタ（コード整形）
Java Extension Packにすでに入っているので、`Shift + Alt + F`でできます。

細かい設定をしたいときは、`F1`を押して`Open Java formatter settings`と入力してエンター。
その後、設定ファイルのパスの入力を求められますが、ないのでそのままエンター。
右下に「' eclipse-formatter.xml ' does not exist. Do you want to create it?」みたいなの出ますので`Yes`を押す

そして eclipse-formatter.xml が作られたのであとは好きなように設定しましょう！

私はメソッドチェインなどで改行したコードを自動整形のときに一行にされないように以下を変更してます

```xml:eclipse-formatter.xml
<!-- trueになっているのをfalseにします-->
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
```

設定後はVSCodeを再起動

## **追記
`gradle`の設定は[公式サイト](https://docs.gradle.org/current/samples/sample_building_java_applications.html)がわかりやすいので参考にしてください(なんで今まで見てなかっただろう。。。)
Power Automate で Do-Until 制御ループを脱出する

# はじめに

Power Automate の制御部品は、基本パーツのようなイメージでラインナップされているので、望むフローを構成するときは「アイデア勝負」になってくることが多いです。

今回は、Do-Until制御によるループを途中で離脱・脱出したい、プログラムだと`break`に相当する制御について、アイデアを記載します。

# 要件

次のような単純化したフローを例にします。必要な処理を（カウントダウン）が完了するまで繰り返し、終了したら（カウントが0になったら）Do-Until制御のループが終了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/80588b16-a075-20be-be33-c822f3f985fa.png)

ここで、次のような仕様が増えたとしましょう。

> ループ内でApprovalsによる承認申請を行い、一度でも拒否されたらループを終了する。

となると、承認アクションを追加した後、そこにループを脱出するステップが欲しくなるわけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/4107ab37-41de-70e1-1af3-9cba650dab85.png)


# 実現例

「ほしいアクションがない！」となるわけなんですが、よくよく動作を整理すると、次のように考えることができます。

> 「10回繰り返すあいだループを継続する」＋「途中で拒否されたらループを終了する」
> ＝「10回繰り返す、もしくは拒否されない、あいだループを継続する」

というわけで、次のようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/386c27ca-6c77-2cb7-90f9-73cc22e32ba2.png)

一行で解説しますと

**「ループを継続するか否か or ループを脱出するか否か」をそのままブール変数として定義し、Do-Until制御の条件にしてしまいます。**

そして、お好きなタイミングでフラグを立ててしまえばいいわけです。

今回の場合、2か所。まずはApprovalsで拒否されたときにフラグを立てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/6936b1c5-5a63-1e28-576b-083aa16ab910.png)

もう1か所、10回ループを繰り返し終わったらフラグを立てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/0e0e15eb-51a4-3daa-aaa7-047ad7b6898d.png)

これで、複数の場合、好きな時に脱出するような構成ができるようになります。

# 注意点

注意点として**途中離脱する条件が揃ったら、ループ内の処理を行わないようにする**必要があります。

ここには制御によっていろいろなテクニックがあります。

今回の場合、拒否されたら、ループカウントのカウントダウンを行わないようにする必要があります。今回は制御による「はい」「いいえ」がありますので、そこで分離できましたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/e90eea96-54fb-2195-b9a5-36ad4ede03d4.png)

拒否されたら、もうカウントダウンはされません。安心してループを脱出することができます。

ただし、後続処理がさらに複雑になったりするときがありますので、そのときは**「スコープ」**や**「実行条件の構成」**を活用しましょう。こんなことができるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68978/8305011c-5297-8d2b-13e4-cca26c698008.png)


スコープについては、次の記事を参考にしてください。

https://qiita.com/kojisaiki/items/aeecd7f20c224e77c665

実行条件の構成については、こっちなどを。

https://qiita.com/cabinotier/items/f0c5261513d1b9976a07#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%8C%E6%88%90%E5%8A%9F%E3%81%97%E3%81%9F%E3%82%89%E3%81%9D%E3%81%AE%E7%B5%90%E6%9E%9C%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E5%A4%B1%E6%95%97%E3%81%97%E3%81%9F%E3%82%89%E5%88%A5%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E5%80%A4%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84

# おわりに

大事なのは「目的にフォーカスすること」「細目にとらわれないこと」です。

Power Automate で、日々の手作業をもっと**サボり**ましょう！！！
Python Open fileする時の注意点

PythonでファイルをOpenする時にそのファイルのpathを指定して
下のコードのようにファイルを開く時がある。

```demo.py
with file.open("rb") as f:
```
この時に、ファイルのパスを格納しているfileはstr型ではなく、
WindowsPath型でないと

"'str' object has no attribute 'open'"

というエラーが生じる。

その場合はstr型をWindowsPath()を用いてWindowsPath型にしないといけない。
下にサンプルコードを載せる

```sample.py
import os

#パスをstr型で指定する
#このfileで指定のファイルを開くとエラー
path = os.getcwd()
file = os.path.join(path,'GV2.xlsx')
print(type(file))

#str型のpathをWindowsPath型にする
file_dir = WindowsPath(file)
print(type(file_dir))

#ファイルを開く
with file_dir.open("rb") as f:
```
EditTextで下線を出したくない！領域もいらない！

# はじめに
Androidアプリ開発でEditTextを使うことはまぁまぁあると思います。
そんなとき、デフォルトのままだとEditTextにフォーカスがあたった際に表示される下線の分が領域確保されてしまっていて周りのレイアウトとのバランスが悪くなることがあるのではないでしょうか。
私はありました。
というわけで備忘録も兼ねて投稿。

# どうしたか
EditTextのタグに`android:background="#00000000"`を追加しました。

# おわりに
フォーカスあたったときには下線出したい！って場合もあるかもしれません。
そのときには`background`の色設定を戻すなりしてあげたらいいと思います。(私は必要なかったのでやってません)