OmniAICreator/Qiita-1.07M huggingface dataset:
Python 3 で現在日時を取得する

## 概要
- Python 標準ライブラリである datetime モジュールを使用する
- 日本のタイムゾーンを指定して現在日時情報を取得する

## ソースコード

```python
# datetime モジュールを読み込む
from datetime import datetime, timedelta, timezone

# タイムゾーンを指定して現在日時情報を取得する
now = datetime.now(timezone(timedelta(hours=9), 'JST'))

# 型特有の書式指定で文字列化する
str = '{0:%Y-%m-%d %A %H:%M:%S.%f %z (%Z)}'.format(now)

# 出力する
print(str)
```

## 実行結果例

```
2019-05-26 Sunday 10:59:53.718142 +0900 (JST)
```

## 今回の環境

```
$ python --version
Python 3.7.3

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.4
BuildVersion:	18E226
```

## 参考資料

- [datetime \-\-\- 基本的な日付型および時間型 — Python 3\.7\.3 ドキュメント](https://docs.python.org/ja/3/library/datetime.html#datetime.datetime.now)
- [string \-\-\- 一般的な文字列操作 — Python 3\.7\.3 ドキュメント](https://docs.python.org/ja/3/library/string.html)
BSの二期増減分析を自動で作ってみる

## 目的
- 資料自動化のため
- 情報のこえだめとして



```code.ts
/**
* @autour @kabanyasu 
*/


/**
 * APIを叩いて月次試算表を取得し、オブジェクト形式に変換する
 * @return {object} resBss
 */
function postApi() {
  let accessToken = getService().getAccessToken();
  let baseUrl = 'https://api.freee.co.jp/api/1/reports/trial_bs_two_years';
  let companyId = 9999999;
  let fiscalYear = 2019;
  let startMonth = 1;
  let endMonth = 12;
  let postUrl = baseUrl + `?company_id=${companyId}&fiscal_year=${fiscalYear}&start_month=${startMonth}&end_month=${endMonth}`;
  let options = {
    'method': 'get',
    'headers': {
      'Authorization': 'Bearer ' + accessToken
    },
  };
  let resBss = JSON.parse(UrlFetchApp.fetch(postUrl, options)).trial_bs_two_years.balances;
  return resBss;
}

/**
 * オブジェクトを二次配列に整形する。
 * @param {any} object
 * @return {any} array
 */
function createArray(object: any) {
  const array = object.map(account => {
    const level = account.hierarchy_level;
    const close = account.closing_balance;
    const last = account.last_year_closing_balance;
    if (!account.total_line) {
    //[勘定科目ID, 勘定科目名, 階層, 前期末残高, 当期末残高, 増減率, 増減額]
      return [account.account_item_id, account.account_item_name, level, last, close, close / last, close - last];
    } else {
    //[勘定カテゴリID, 勘定カテゴリ名, 階層, 前期末残高, 当期末残高, 増減率, 増減額]
      return [account.account_category_id, account.account_category_name, level, last, close, close / last, close - last];
    }
  });
  return array;
}
```
Desktop : OpenCV Draw Point

<H5>Goal</H5>
OpenCV Draw point.

```OpenCV_Draw_Point.java
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import org.opencv.core.Point;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class OpenCV_Draw_Point {
    static{System.loadLibrary(Core.NATIVE_LIBRARY_NAME);}

    private JFrame frmjavaSwing;

    /**
        *   Launch the application.
        */
    public static void main(String[] args){
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try{
                    OpenCV_Draw_Point window = new OpenCV_Draw_Point();
                    window.frmjavaSwing.setVisible(true);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     *  Create the application.
     */
    public OpenCV_Draw_Point(){
        init();
    }
    /**
     * Initialize the contents of the frame.
     */
    private void init() {
        Mat source =  paint();
        BufferedImage image=matToBufferedImage(source);

        frmjavaSwing = new JFrame();
        frmjavaSwing.setTitle("opencv µeÂI½m²ß");
        frmjavaSwing.setBounds(100, 100, 300, 300);
        frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmjavaSwing.getContentPane().setLayout(null);

        final JLabel lblNewLabel = new JLabel("");
        lblNewLabel.setBounds(5, 5, image.getHeight()+10, image.getWidth()+10);
        lblNewLabel.setIcon(new ImageIcon(image));
        frmjavaSwing.getContentPane().add(lblNewLabel);
    }

    public Mat paint(){
        Mat source = new Mat(250,250, CvType.CV_8UC3, new Scalar(255,255,255));
        Point pt1=new Point(125,125);

        Imgproc.line(source,pt1,pt1,new Scalar(255,55,220),6);
        return source;
    }

    public BufferedImage matToBufferedImage(Mat matrix) {
        int cols = matrix.cols();
        int rows = matrix.rows();
        int elemSize = (int)matrix.elemSize();
        byte[] data = new byte[cols * rows * elemSize];
        int type;
        matrix.get(0, 0, data);
        switch (matrix.channels()) {
            case 1:
                type = BufferedImage.TYPE_BYTE_GRAY;
                break;
            case 3:
                type = BufferedImage.TYPE_3BYTE_BGR;
                // bgr to rgb
                byte b;
                for(int i=0; i<data.length; i=i+3) {
                    b = data[i];
                    data[i] = data[i+2];
                    data[i+2] = b;
                }
                break;
            default:
                return null;
        }
        BufferedImage image2 = new BufferedImage(cols, rows, type);
        image2.getRaster().setDataElements(0, 0, cols, rows, data);
        return image2;
    }
}
```
<h5>Result</h5>
![opencv_draw_point.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/005114ca-0a76-0449-5905-75de581d8b3a.jpeg)
売掛金の増減分析を自動でやってみる。

## この記事の目的
- 会計監査資料の作成が面倒だったため自動化を行うこと
- 資料作成コストを削減するための手法としての利用
- @Kirin8210 さんとQiita記事を書く流れになったため

## 前提
- freeeAPIを叩くことで試算表を取得している
- 情報のアウトプットを２次元配列にしており、スプレッドシートに出力する仕組み
- OAuth2ライブラリを活用して、AccessTokenを取得している


```code.ts
/**
 * APIを叩いて二期分のBS得意先明細を取得する
 * @return {Array} resBss
 */
function getTwoYearsBsCustomer() {
  const accessToken = getService().getAccessToken();
  const baseUrl = 'https://api.freee.co.jp/api/1/reports/trial_bs_two_years';
  const postUrl =
    baseUrl +
    setting().companyId +
    setting().fiscalYear +
    setting().startMonth +
    setting().endMonth +
    setting().partner;
  const options = {
    method: 'get',
    headers: {
      Authorization: 'Bearer ' + accessToken
    }
  };
  const resBss = JSON.parse(UrlFetchApp.fetch(postUrl, options))
    .trial_bs_two_years.balances;
  return resBss;
}

/**
 * 勘定科目明細に必要なArrayを返す
 * @param {string}account
 */
function getChangeAnalysis(account: string) {
  const Bss = getTwoYearsBsCustomer();
  const a = Bss.filter(item => item.account_item_name == account);
  //[得意先名, 前期末, 当期末, 増減額, 増減率]
  let array = a[0].partners.map(function(customer) {
    const last = customer.last_year_closing_balance;
    const end = customer.closing_balance;
    return [customer.name, last, end, end - last, end / last];
  });
  array.unshift(['得意先名', '前期末', '当期末', '増減額', '増減率']);
  return array;
}

/**
 * 関数を実行する場合はこちらを実行ください。
 * @param {string}account
 */
function main(){
  const array = getChangeAnalysis(売掛金);
  setSpreadSheet(array)//任意のスプレッドシートにarrayをセットする。
}


```

## 工夫
- 出力形式の操作を行うことにより、品目別・部門別等の増減分析を自動化できる
- アウトプットでのスプレッドシート加工方法によっては、月次推移だったり諸々使える
- getChangeAnalysis(account: string)については、引数を変えるだけアウトプットが変わること


## 追記
これらのQiitaに書ききれない内容は同人誌にまとめようとおもうので、お楽しみに。
PHP7.2をHomebrewでインストールする方法

##環境
- macOS Mojave 10.14

##インストール
```
$ brew install php@7.2
```

PATHを通す

```
$ echo 'export PATH="/usr/local/opt/php@7.2/bin:$PATH"' >> ~/.bash_profile
$ echo 'export PATH="/usr/local/opt/php@7.2/sbin:$PATH"' >> ~/.bash_profile
```



ターミナルを再起動後、バージョンを確認

```
$ php -v
PHP 7.2.18 (cli) (built: May 21 2019 20:18:44) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.18, Copyright (c) 1999-2018, by Zend Technologies
```
windows bat作成

windowsであれば動作環境に制限のないwindows batで遊んでみます。
今回はbatを使って、文字列を出力してみます。

```
Rem バッチ
echo Qiita
```

Rem・・・コメント
echo・・・プロンプト上に文字列の出力する

実行結果

```
Qiita
```

他にも、普段行なっているコピーペーストなどのwindows操作をbat上で自動化が実現できます。
これからも紹介していきます。
Macでmecabを使う。


#mecabの準備

mecabのインストール

```
$ brew install mecab
```

mecabの辞書をインストール

```
$ brew install mecab-ipadic
```

mecabの辞書をパワーアップ

```
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n
```

辞書が入っている場所はこのコマンドで調べられる。

```
$ echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
```


mecab-python3をインストール

```
$ brew install swig
$ pip install mecab-python3
```

[Python3からMeCabを使う - Qiita](https://qiita.com/taroc/items/b9afd914432da08dafc8)を参考に実行

```mecab.py
import MeCab

# 変数には辞書のファイルパスを指定する
mecab = MeCab.Tagger ('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')

text = '解析したいテキスト'
mecab.parse('')#文字列がGCされるのを防ぐ
node = mecab.parseToNode(text)
while node:
    #単語を取得
    word = node.surface
    #品詞を取得
    pos = node.feature.split(",")[1]
    print('{0} , {1}'.format(word, pos))
    #次の単語に進める
    node = node.next
```

# 参考
[mecab-ipadic-neologd/README.ja.md at master · neologd/mecab-ipadic-neologd · GitHub](https://github.com/neologd/mecab-ipadic-neologd/blob/master/README.ja.md)
[Python3からMeCabを使う - Qiita](https://qiita.com/taroc/items/b9afd914432da08dafc8)
EC2のディスク拡張

# はじめに

ついついデフォルトで環境を作ってしまってディスクサイズが少なくて後悔しませんか？Dockerを使いだすと掃除してもどんどん容量を圧迫していきます。という事で何回もやっているのでメモしておきます。

# 現在の使用率の確認

dfコマンドで容量確認を行います。

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
...
/dev/nvme0n1p1   78G   53G   25G  68% /
...
```

# AWSコンソールよりEBSを拡張します。

ちょっと省略

# ディスク容量の確認をおこないます。

```
$ lsblk
nvme0n1     259:0    0   100G  0 disk 
└─nvme0n1p1 259:1    0    80G  0 part /
```

ディスク全体はコンソールで設定した通り80Gから100Gに拡張できているのがわかります。

# パーティション拡張を行います

利用しているプライマリーパーティションの使用領域を拡張します。

- nvme系の場合はpを除いて下記のように行います。
```sudo growpart /dev/nvme0n1 1```

- xvdaの場合は以下のように行います。
```sudo growpart /dev/xvda 1```

```
$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1     259:0    0   100G  0 disk 
└─nvme0n1p1 259:1    0   100G  0 part /
```

パーティション領域が拡張されているのが確認できました。

# ファイルシステムのリサイズ

ファイルシステムの種別を確認します。
```
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
....
/dev/nvme0n1p1 ext4       78G   53G   25G  68% /
...
```

## ext4の場合

dfで確認したファイルシステム名を指定します。

```sudo resize2fs /dev/nvme0n1p1```
or
```sudo resize2fs /dev/xvda1```

## xfsの場合

dfで確認したマウントポイント名を指定します。
```sudo xfs_growfs -d / ```

# 拡張後の容量の確認

dfコマンドで容量を確認します。

```
$ df -hT
Filesystem     Type      Size  Used Avail Use% Mounted on
...
/dev/nvme0n1p1 ext4       97G   53G   45G  55% /
...
```

# 参考

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html
ポリモーフィズムについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/f476c9ed-054f-d7ac-bcdb-7d93071961f5.png)

説明する時にいつも読むのでまとめ

## ポリモーフィズムとは
**メッセージの送り方を共通にするもの**

- 親クラス生成時に子クラスに渡すメッセージを共通にする仕組み
- インターフェースを使って(Javaの場合)メッセージを共通にする仕組み
- コードの重複を排除して汎用性の高い部品をつくる仕組みの1つ
- オブジェクト指向三大要素の1つ
- 意訳すると多態性

## 特徴
### 概念的側面(現実世界)
**上位と下位の概念それぞれの動詞として成立する**

共通の動詞が成立する

- 例えば「動物」と「人間」と「犬」
  - 「動物」(上位)が「食べる」
  - 「人間」(下位)が「食べる」
  - 「犬」が(下位)「食べる」

切り口を1つにしている

- 1つのオプション(追加情報)で固有の挙動が成立する
- 例えば「動物」と「人間」と「犬」 
  - 「動物」が「食べる」-> どんな感じで食べるか定まっていない
  - 「動物」の「人間」(オプション)が「食べる」-> 食べ物を手で口に近づけて食べる
  - 「動物」の「犬」(オプション)が「食べる」-> 食べ物に頭を近づけて口で食べる

### 技術的側面(プログラミング)
**引数を受け取ったインスタンスがクラスによって違う振る舞いをする**

共通のメソッド名で成立する

- スーパークラスとサブクラスそれぞれのメソッドとして成立する
- 例えば「Animal」と「human」と「dog」と「chef」(eater)
  - 「シェフ」が「動物」(食べるくん)に提供して「動物」(食べるくん)がそれを「食べる」
  - 「動物」(食べるくん)を変えるだけでぱくぱく食べてたりがぶがぶ食べてたりする
  
### プログラミング技術における「継承」を利用した場合

```java:Animal.java
public abstract class Animal {
    public abstract void eat();
}
```
```java:Human.java
public class Human extends Animal {
    public void eat() {
        System.out.println("ぱくぱくたべる");
    }
}
```
```java:Dog.java
public class Dog extends Animal {
    public void eat() {
        System.out.println("がぶがぶたべる");
    }
}
```
```java:Chef.java
public class Chef {
    public void serve(Animal animal) {
        System.out.println("どうぞー");
        System.out.println(animal.eat());
    }
}
```

### プログラミング技術における「インターフェース」を利用した場合

```java:Eater.java
public interface Eater {
    public void eat();
}
```
```java:Human.java
public class Human implements Eater {
    public void eat() {
        System.out.println("ぱくぱくたべる");
    }
}
```
```java:Dog.java
public class Dog implements Eater {
    public void eat() {
        System.out.println("がぶがぶたべる");
    }
}
```
```java:Chef.java
public class Chef {
    public void serve(Eater eater) {
        System.out.println("どうぞー");
        System.out.println(eater.eat());
    }
}
```

### ポイント
- 継承の機能を使ったものもインターフェースの機能を使ったものも共通していえるのは呼び出し方が種類関係なく同じ(ここでいうとシェフが提供する相手)という部分
- interfaceはポリモーフィズムを実現するためのようなもの
- interfaceの機能は言語的にサポートしていないものもある(Rubyなどはそう)

## 関連記事
[オブジェクト指向でなぜつくるのかまとめ](https://qiita.com/dich1/items/59c4f15c6dfb71e48c5e)

## 書籍情報
平澤 章  (著) オブジェクト指向でなぜつくるのか 第2版
https://amzn.to/2VSrzwe

## 雑感
デザインパターンやリファクタリングでもこの視点をもてていると上手く適用できる
Unixmen #2

前回に続き、本日もUnixmenの記事を紹介します。
本日は二本立てです。

# How to Install and Configure SQUID Proxy server in RHEL/CENTOS
https://www.unixmen.com/install-configure-squid-proxy-server-rhelcentos/
squidのインストールの話です。yumでインストールして、systemdいじって、squid.conf修正しましょう、
という話。日本語の情報も多いので、特に参考にする必要はないかと。

# https://www.unixmen.com/ubuntu-16-04-lts-installation-and-review/
https://www.unixmen.com/ubuntu-16-04-lts-installation-and-review/
ubuntu 16.04 LTSのインストールとレビューに関する記事です。
いまや18.04がLTSになっているので、この記事を見る必要はもうないかなと。

ちなみに、18.04のリリースノートはこちら。
https://wiki.ubuntu.com/BionicBeaver/ReleaseNotes/Ja
「プログラミングコンテスト攻略のためのアルゴリズムとデータ構造」読んだ

2ヶ月くらい地道に読んでいた [プログラミングコンテスト攻略のためのアルゴリズムとデータ構造](https://www.amazon.co.jp/dp/B00U5MVXZO/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1) 読み終えた。

プログラミングコンテストにデビューするために読んだ。。
。わけではなく、アルゴリズムとデータ構造をちゃんと勉強してみようと思って、評判のいい教材を探していたら本書を見つけた感じ。

サンプルコードはCとかC++だけど、普段Rubyばかり使っててCとかあんま知らない私でもその点は大丈夫で普通に読めた。

# 内容
「Aizu Online Judge」という会津大学が運営しているオンラインジャッジシステムの問題を取り上げてその問題を解説しながらコンピュータサイエンスのメジャーな
アルゴリズムとデータ構造を勉強できる。

「基礎編」で情報処理試験でも見るような並び替えアルゴリズム、データ構造、探索ヒープ、グラフアルゴリズム（グラフアルゴリズムは情報処理でみた覚えない気も。。）を学んで、「応用編」でその知識を応用して高度なデータ構造、グラフアルゴリズム、計算機科学、動的計画法、整数論、ヒューリスティック探索とだんだん問題の難度が高くなってく感じ。

# 感想
ソートアルゴリズムとかデータ構造とか探索アルゴリズムとかアルゴリズムとデータ構造の基本は学んだことがあったけど、そこから繋がっていくグラフアルゴリズムを学べたのが個人的には良かった。

本書の中で

> コンピュータで扱う多くの問題は「対象」とそれらの「関係」を抽象的に表した"グラフ"と呼ばれるデータ構造で表すことができます。
> 

と書いてあるけど、例えば深さ優先探索と幅優先探索とハッシュを組み合わせて行くとチェス盤にどのクイーンも他のクイーンを襲撃できないようにする「8クイーン」問題がとけたりする。

他にも最短経路問題が解けたり絵柄を揃えるパズルが解けたり、こうして初歩的なデータ構造とアルゴリズムを発展させて応用していろんなパズルが解けるようになるんだな。。と関心してしまった。

こうしてどう使われているかをイメージできるとアルゴリズム学ぶのも面白くなってきて良い感じだなーと。
「testing」タグについて (タグシノニム: 「テスト」「test」)

### 対象

https://qiita.com/tags/testing

### 説明

ソフトウェアやハードウェアのテスト関係の記事。

[StackOverflowのタグ「testing」](https://stackoverflow.com/questions/tagged/testing)と同じ用途。
(StackOverflowではtestというタグはtestingに転送される)

記事数としては後述の「テスト」と「test」の方が多い。

### タグシノニム

[https://qiita.com/tags/テスト](https://qiita.com/tags/%E3%83%86%E3%82%B9%E3%83%88) : 主な記事は「テスト」についてであるが、「テスト記事の投稿」として「テスト」が付く例もある
https://qiita.com/tags/test :  主な記事は「test」についてであるが、「テスト記事の投稿」として「test」が付く例もある
失敗談  Alexaスキル開発 ジャーナリング〜自分と向き合う5分間〜 

今回は開発中の失敗談を共有します。
特に「インテントを削除したら、デプロイでエラー」に関わる失敗は
仕様影響する事例だったため、いい教訓になりました。

## インテントを削除したら、デプロイでエラー
- 事象 : [HelloWorldインテントを削除](https://github.com/toctoc0352/Journaling/commit/579b5324664cac028b4e76ea15579f69148cc17a)したら、デプロイ時にエラーが発生
 - CodePipelineで確認したエラーメッセージ 
 - `MissingSampleUtterance: Missing sample utterance. At least one sample utterance is required.`
- 原因 : 上記エラーメッセージの通り、サンプル発話を全て削除してしまったことが原因。サンプル発話は必ずひとつは登録する必要がある（At least one sample utterance is required）
- 対策 : 検討中
 - スキル起動後はユーザからの発話は必要としない設計としていたため、仕様を再検討する

## ファイル名を変更したら、スキル実行時にエラー
- 事象 : デフォルトで作成されたhello_world.pyをjournaling.pyに変更したらAWS Lambda実行時にエラーが発生
 - AWS Lambdaで確認したエラーメッセージ
 - `[ERROR] Runtime.ImportModuleError: Unable to import module 'hello_world': No module named 'hello_world'`
- 原因 : ファイルのリネームしたことにより、CloudFormationのテンプレートファイル(template.yml)から該当ファイルを読み込むことができなかった。
- 対策 : [template.ymlを修正](https://github.com/toctoc0352/Journaling/commit/13cdd2645d16bc06e26e08645f628ac846aab2a3)

## 構文エラー
- 事象 : AWS Lambda実行時に構文エラーが発生
- 原因 : Pythonの構文の理解不足
- 対策 : VSCodeにPythonの拡張機能をインストールして構文チェックを有効化
- 修正箇所 : [リンク](https://github.com/toctoc0352/Journaling/commit/2affbf686a3e3ed19143df8b9854cf0c8f77e8d4)

## 参考サイト
- [Alexa 開発うっかりエラー（１）MissingSampleUtterance](https://a093.jp/error01/)
- [Visual Studio Code の Python 開発環境を整える](https://qiita.com/kekekekenta/items/4c966233acbaf4dce81c)
[Atom]ファイルを開いた時に、Tree View のカレント表示に反映する

Atomでは `command + P` で編集したいファイルをダイレクトに開く事ができる。
タブにファイル名が表示されるが、いっぱい開いていると `index.html` と表示されても、どこの index.html だか...とよくなるので、
開いているファイルは tree view のどの階層のものか、連動してほしいので調べた。

# 図で説明
## default はこういう感じ
`command + P`　で開いても左側の tree-view は開かない。

![treeview_before.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94035/ccc23659-1136-c968-da61-d2320b54be5a.gif)


## こうしたい
`command + P`　で開くと、それに合わせて左のtree viewのカレントが現在開いているファイルになる。フォルダ展開してくれる。

![treeview_after.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94035/bbfd679a-b5c4-3096-6c03-8879832727b3.gif)

# セッティング方法

## `tree-view` という package を install します。

Atom が配布している package [tree-view](https://atom.io/packages/tree-view) を入れます。

## `tree-view` の Setting

Packages > Tree View > Settings 項目の中 `Auto Reveal` にチェックを入れる。

<img width="975" alt="treeview_settings.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94035/428b95ee-a837-0d5b-2407-062e4a07e44c.png">

以上。
一時的に FTP サーバを仕立てる

令和にもなってまだ FTP とか思うけど色々ありまして。

ftpd の設定面倒だなと思ってぐぐってたら pyftpdlib が良さそうで、実際良かった。

### インストール

```
$ pip install pyftpdlib
```

### 実行

```python
import os
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

# anonymous ユーザーはカレントディレクトリのファイルを、取得 (perm='r') できる
authorizer = DummyAuthorizer()
authorizer.add_anonymous(os.getcwd(), perm='r')

handler = FTPHandler
handler.authorizer = authorizer

server = FTPServer(('0.0.0.0', 21), handler)
server.serve_forever()
```
Desktop :OpenCV Drawing Line

<h5>Goal</h5>
OpenCV Draw line.

```OpenCV_DrawingLine.java

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import org.opencv.core.Point;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

public class OpenCV_DrawingLine {

    static{System.loadLibrary(Core.NATIVE_LIBRARY_NAME);}

    private JFrame frmjavaSwing;

    /**
        * Launch the application.
        */
    public static void main(String[] args){

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try{
                    OpenCV_DrawingLine window = new OpenCV_DrawingLine();
                    window.frmjavaSwing.setVisible(true);

                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create thr application.
     */
    public OpenCV_DrawingLine(){
        init();
    }

    private void  init(){
        Mat source =  paint();
        BufferedImage image=matToBufferedImage(source);

        frmjavaSwing = new JFrame();
        frmjavaSwing.setTitle("opencv µe½u½m²ß");
        frmjavaSwing.setBounds(100, 100, 260, 260);
        frmjavaSwing.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmjavaSwing.getContentPane().setLayout(null);

        final JLabel lblNewLabel = new JLabel("");
        lblNewLabel.setBounds(5, 10, image.getHeight()+10, image.getWidth()+10);
        lblNewLabel.setIcon(new ImageIcon(image));
        frmjavaSwing.getContentPane().add(lblNewLabel);

    }

    public Mat paint(){
        Mat source = new Mat(250,250, CvType.CV_8UC3, new Scalar(255,255,255));
        Point pt1=new Point(10,0);
        Point pt2=new Point(10,200);
        Imgproc.line(source,pt1,pt2,new Scalar(255,0,0));
        return source;
    }

    public BufferedImage matToBufferedImage(Mat matrix) {
        int cols = matrix.cols();
        int rows = matrix.rows();
        int elemSize = (int)matrix.elemSize();
        byte[] data = new byte[cols * rows * elemSize];
        int type;
        matrix.get(0, 0, data);
        switch (matrix.channels()) {
            case 1:
                type = BufferedImage.TYPE_BYTE_GRAY;
                break;
            case 3:
                type = BufferedImage.TYPE_3BYTE_BGR;
                // bgr to rgb
                byte b;
                for(int i=0; i<data.length; i=i+3) {
                    b = data[i];
                    data[i] = data[i+2];
                    data[i+2] = b;
                }
                break;
            default:
                return null;
        }
        BufferedImage image2 = new BufferedImage(cols, rows, type);
        image2.getRaster().setDataElements(0, 0, cols, rows, data);
        return image2;
    }

}
```
<h5>Result</h5>
![opencv_draw_line.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/a6ad3df3-2c96-fe0c-2977-2965235b5f7d.jpeg)
【CSS】テーブルタグ内のラジオボタンの押しにくさを解消する

#きっかけ
td内部に設置したラジオボタンのクリックのしにくさに業を煮やして諦めかけてたところ解決したのでメモ

#見えない壁
td内部に設置したラジオボタンのクリック範囲を広げるためにやったこと
つまりは失敗例です
labelで挟み込んでマージン無くして幅は100%高さも100%！！
あれ？
幅はセル内いっぱいになったけど高さが何かに制限されている
とクロームちゃんは教えてくれました
その時のHTMLとCSS

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="test.css">
  <title>jstest</title>
</head>
<body>
  <table>
    <tr>
      <th>ラジオ</th>
      <th>テキスト</th>
    </tr>
    <tr>
      <td><label><input type="radio"></label></td>
      <td>テキストテキスト<br>テキストテキスト<br>テキストテキスト</td>
    </tr>
  </table>
</body>
</html>
```

```css:test.css
/* ラジヲボタンのクリック範囲を少しでも広げる */
td label {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
}
```

素人目には完璧なCSS記述に思えたんだけど
セルの見た目に対してクリック範囲がめちゃくちゃ狭い
テキストが改行してるのでセルが縦長なのに有効に使えない

#成功例
寝ぼけ眼でゴロゴロしてたら思いついたのがこちらです

##コード
HTMLさっきと同じなのでCSSを

```css:test.css
@charset "UTF-8";

th {
  border: solid 1px gray;
}

td {
  min-width: 3em;
  position: relative;
  border: solid 1px gray;
}

/* ラジヲボタンのクリック範囲を少しでも広げる */
td label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}

/* ラジヲボタンを中央に */
input[type="Radio"] {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}
```

たったこれだけのことです
セルの内部どこをクリックしても反応してくれます！
泣きそうになりました

#最後に
知ってる人は当たり前に使ってるんだろうと思うけど…
失敗例の紹介はあれど成功例の紹介記事が見当たらなかった

注意点としてはラジオボタンのみの列を作ると潰れてしまうので
幅を設定するかなんかしてください(適当)

ラジオボタンを中央に寄せるのは目から鱗でした
[position:absolute で中央に配置するやり方](https://youknow.jp/web/css-position)
感謝
LinuxのオリジナルコマンドをMacに移植した話

#経緯
僕の大学では入学時にPCを買うとVirtualBoxを入れさせられ、学校の授業用に何やら設定を施されたubuntuが配布されます。
1、2年生の間は特に配布されたubuntuにありがたみは感じないものの、3年生になると「sep3asm」というオリジナルプログラムを授業内で使うことになります。
これは我が校の教授が教育用に作ったオリジナルCPU、「SEP-3」（モデルは過去の名機PDP-11らしい）で用いるアセンブラのプログラムをアセンブルするもので、いうまでもなく学校で配布されたubuntuにしか入っていません。

ここまでの話は正直どうでも良いという人がほとんどだと思いますが、僕はこの「sep3asm」をMacでどうにか使えないかと考えました。
言い忘れていましたがこの「sep3asm」はコマンドで動くものでLinux用バイナリでした。
したがってMacで動かすには少々工夫が必要でしたが、今回の設定は他の場面でも使えると感じたので方法をシェアしたいと思います。

#作業の流れ
コマンドの場所を確認（Linux上）
↓
コマンドのファイルをMacへ移動
↓
実行権限を加える（Mac上）
↓
noahをインストール
↓
コマンドのファイルを所定の位置に移動
↓
rootでnoahを起動
↓
コマンド実行

##コマンドの場所を確認
コマンドをMacに移すにはまずコマンドのファイルの場所を特定しなければいけません。

```
$ where sep3asm
/usr/local/bin/sep3asm
```

上記のコマンドで探すことができます。

##コマンドのファイルを移動
方法はお任せします。
僕の場合はubuntuがVirtualBoxに入っているので共有フォルダでWindowsに移してからLineでMacに送りました。

##実行権限を加える。

```
$ chmod a+x sep3asm
```

`chmod`コマンドは、ファイルやディレクトリのアクセス権を変更するコマンドです。引数の`a+x`の意味を一応解説しておきます。
自分なりの認識なので間違っていたらすみません。
`chmod`の引数は
＜誰に＞ - ＜何の＞　　権限を与える、という構造になっているようです。

＜誰に＞の部分は４種類

| 記号 |             意味|
|:---:|:---------------:|
|u    |      所有者(user)|
|g    |   グループ(group) |
|o    |    その他(other) |
|a    | 上の三つ全て(all) |

＜何の＞の部分は３種類

| 記号 |      意味|
|:---:|:--------:|
|r    |読み込み権限|
|w    |書き込み権限|
|x    |  実行権限 |

今回の場合は＜全ての者に＞ - ＜実行権限＞を与えているわけです。

##noahをインストール
Macでは、Linux用バイナリを実行できません。したがってこれに関しては何らかの対策を講じる必要があるのですが、色々調べてみるとすごく便利なものを見つけてしまいました。

***Noah***というアプリケーションは、MacOS上でLinuxOS用アプリケーションを動かすことのできる優れものです。
apt-getやLinux向けgcc、自作のLinuxアプリケーションが、そのままMacOSで動作します。

ということで、早速インストールします。

```
$ brew install linux-noah/noah/noah
```

初めて起動するとこんな感じ

```
$ noah
Noah is installing the initial filesystem in ~/.noah/tree. Proceed? [Y/n] Y
Password:

（中略）

Noah is still under development, so please enable it at your own risk! [y/N] y

（中略）

I have no name!@username:~$
```
適当にyを押しておきます。

##コマンドを所定の位置に移動させる
sep3asmを所定のいちに移動させます。

```
$ sudo cp sep3asm /bin/sep3asm
```
コマンドのファイルを`/bin` に入れる動作はrootでしかできないので`sudo`でやります。

一応、移動させたら確認してみてください。

```
$ which sep3asm
/bin/sep3asm
```

こんな感じになっていたらOK。

##rootでnoahを起動

```
$ sudo noah
Password:
groups: cannot find name for group ID 61
groups: cannot find name for group ID 80
groups: cannot find name for group ID 701
groups: cannot find name for group ID 98
root@username:~# 
```
起動画面はこんな感じです。
もうこのままコマンドが打てる状態です。
試しにプログラムをアセンブルしてみましょう。

今回アセンブルするプログラム

```sample.s
 . = 0x1FF
 . WORD 0x0A0A, 0xF0F0
 MOV #0x200, R6
 MOV R6, R0
 HLT
```

アセンブルします。

```
$ sep3asm sample.s
```

アセンブル結果がこちら

```sample.bin
000001FF: 0A0A
00000200: F0F0
00000201: 43E6
00000202: 0200
00000203: 40C0
00000204: 0000
```
ちゃんと動作していますね！
Ubuntu 18.04でVirtualBoxがインストールできない

## とりあえず公式の言うとおりにやってみる

公式マニュアルでのインストール方法は[こちら](https://www.virtualbox.org/wiki/Linux_Downloads)

一応`/etc/apt/source.list`に直接追記せずに，`/etc/apt/source.list.d/`の中に`virtualbox.list`と`virtualbox.list.save`みたいな感じで適当に作ってやりましょう．~~当たり前といえば当たり前ですが．~~

```shell:/etc/apt/source.list.d/virtualbox.list
deb https://download.virtualbox.org/virtualbox/debian bionic contrib
```

で，`apt update`してみると

```shell
N: リポジトリ 'https://download.virtualbox.org/virtualbox/debian bionic InRelease' がアーキテクチャ 'i386' をサポートしないため設定ファイル 'contrib/binary-i386/Packages' の取得をスキップ
```

みたいなエラーが出てきてファッ？！ってなります．

## 解決策

CPUのアーキテクチャを指定すれば解決します．
大抵の方はIntelかAMDの64bitのもの(amd64)を使っていると思うので，先ほどの`virtualbox.list`，`virtualbox.list.save`にそれぞれ`[arch=amd64]`を書き加えてあげましょう．

```shell:/etc/apt/source.list.d/virtualbox.list
deb [arch=amd64] https://download.virtualbox.org/virtualbox/debian bionic contrib
```
はい，これで`apt update`してもエラーが出なくなりました:thumbsup:

## どゆことなん？

i386というのはIntelの32bitのアーキテクチャのことです．
VirtualBoxのUbuntu版では18.04からこれをサポートしなくなったってことなんでしょうね．

なんでこういうことが起こったの？ってもっと詳しく知りたい人はググってください（適当）
SFTPサーバのディレクトリとローカル（Windows環境）のフォルダを同期させるメモ


## 環境

### サーバ側

```
grep "PRETTY_NAME" /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
```

### クライアント側

- OS

```
ver

Microsoft Windows [Version 10.0.17763.503]
```

- WinSCP

5.9.47333

## 目的

SFTPサーバのディレクトリとローカル（Windows環境）のフォルダを同期させたい

## 前提条件

sftpクライアントは「WinSCP」

## 手順

1. [Raspbianに接続したUSBをSFTPでアクセスできるように設定](https://qiita.com/miyabi_ver39/items/864a2ccddbf3f99641e3)
2. WinSCPのマクロスクリプトを作成する
3. バッチファイルを作成する

### Raspbianに接続したUSBをSFTPでアクセスできるように設定

[Raspbianに接続したUSBをSFTPでアクセスできるように設定](https://qiita.com/miyabi_ver39/items/46da8e544f08f9952092)

### WinSCPのマクロスクリプトを作成する

#### 対象サーバの指紋を確認する

SFTPはSSHで接続するため、対象サーバの指紋を確認します。

```
$ ssh-keygen -E md5 -lf /etc/ssh/ssh_host_rsa_key.pub
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
```

後ほど使用するので、どこかにメモしておきます。

#### WinSCPのスクリプトを作成する

リモートからローカルへの完全同期で作成します。

公式サイトを参考に作成します。詳細な内容は公式サイトを確認してください。（投げやり）

[コマンドリファレンス](https://ja.osdn.net/projects/winscp/wiki/script_commands)

以下のようにしました。

``` :remote2local.txt
option batch on
open sftp://<対象サーバのアドレス> -hostkey="ssh-rsa 2048 XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX" -privatekey="<対象ユーザの秘密鍵のパス>"
cd "/test/"
lcd "D:\test"
synchronize local -delete -criteria=time
exit
```
※ 秘密鍵はputtygenで作成もしくは変換した秘密鍵でないと接続に失敗する可能性があります。
　 [PuTTYgenで公開鍵/秘密鍵を作成する](https://ja.osdn.net/projects/winscp/wiki/ui_puttygen)


各処理を1行ずつ説明します。

1. 実行モードをバッチモードとする。
2. 接続先のホストを指定する。
3. リモート側のカレントディレクトリを移動する。
4. ホスト側のカレントディレクトリを移動する。
5. ローカルのディレクトリの同期を行う。比較基準はファイルの更新日とする。

※ ホスト側のディレクトリの指定を誤ると大変なことになります。十分に気をつけてください。

### バッチファイルを作成する

WinSCP.comに引数でスクリプトのパスを渡すことで、記入したスクリプトを実行させることができます。
コマンドの引数は公式サイトを参考にします。

[コマンドラインオプション](https://ja.osdn.net/projects/winscp/wiki/commandline)

``` cmd:remote2local.bat

<WinSCPのインストールフォルダ>\WinSCP.com /command /script="<作成したスクリプトのパス>"

```

バッチを作成できたら、実行するだけでリモートのディレクトリをローカルに同期することができます。

### おまけ。

ローカルからリモートへの完全同期を行うスクリプトの作成をします。

``` :local2remote.txt
option batch on
open sftp://<対象サーバのアドレス> -hostkey="ssh-rsa 2048 XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX" -privatekey="<対象ユーザの秘密鍵のパス>"
cd "/test/"
lcd "D:\test"
synchronize remote -delete -criteria=time
exit
```

「local」を「remote」に変更するだけでOKですね。
HaskellでAtCoderの問題を解く（入力の高速化編）

筆者はHaskell入門者で、趣味として競技プログラミングサイトの[AtCoder](https://atcoder.jp/)や[Project Euler](https://projecteuler.net/)の問題を解いています。

これら2サイトのうち、Project Eulerは数学っぽい問題が多く、他言語と比べてHaskellは有利なくらいの印象ですが、AtCoderでは入出力がハマりどころになります。

特に入力が大量の場合[^1]、コンパイル言語のはずのHaskellがスクリプト言語より遅くなることがあります。実際、私はそのような問題でTLE (Time Limit Exceeded、実行時間制限オーバー) してしまい悲しい思いをしました。

[^1]: といっても数万行、数MB程度

本稿ではこの原因と対策を紹介します。

## HaskellのString型は遅い

私がTLEしてしまったのは、標準入力の処理に`getLine`や`getContents`を使っていたのが理由です。これらの関数は入力をIO String型として処理しますが、このString型が良くありません。

HaskellではString型がChar型のリストとして実装されています。このことはメリットもたくさんあるのですが、大きい文字列を扱うときには性能面の足かせになっています。そのため、一定以上のサイズの文字列を処理するなら高速なByteString型を使うのが定石になっています。感覚的には、扱う文字列が数百KBを超えるくらいからByteString型を使った方がよさそうに思います。

このこと自体はHaskellベテランの人にとっては常識中の常識だと思うんですが、ライトHaskellユーザーの私は完全に忘れており、敗北を喫したというわけです。

## ByteString型を使った入力処理

String型が遅いことに気づいた私はByteString型を使うようになりました。私が現在使っているAtCoder用入力関数は次のようなものです。

```haskell
import Control.Monad
import Data.Maybe
import qualified Data.ByteString.Char8 as BS

tuplify2 (x:y:_) = (x,y)
tuplify2 _ = undefined

--Input functions with ByteString
readInt = fst . fromJust . BS.readInteger
readIntTuple = tuplify2 . map readInt . BS.words
readIntList = map readInt . BS.words

getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntNList n = map readIntList <$> replicateM (fromIntegral n) BS.getLine
getIntMatrix = map readIntList . BS.lines <$> BS.getContents
getIntTuple = readIntTuple <$> BS.getLine
getIntNTuples n = map readIntTuple <$> replicateM (fromIntegral n) BS.getLine
getIntTuples = map readIntTuple . BS.lines <$> BS.getContents

main = do
  [n,m] <- getIntList
  print [n,m]
```

見てわかる通りData.ByteStringパッケージではString型と同名もしくは近い名前の関数を提供しているので、String型からの移行はそれほど難しくないはずです。

## 実際の速度差

[ABC127のD問題](https://atcoder.jp/contests/abc127/tasks/abc127_d)を例に出すと、私の書いたプログラムで入力にStringとByteStringそれぞれを使ったときの速度差は次の通りです。

| | 実行時間 |
|:-----------|------------:|
| String版 | 1545 ms |
| ByteString版 | 325 ms |

String版の方が約1.2秒遅い結果になりました。この問題の制限時間は2秒ですから、入力処理だけで制限時間の半分以上を使っているわけです。これはHaskell入門者にとっては大きいハンディキャップになりかねません。

ちなみに、この問題の入力は最大10万行程度、1行は最大20バイト程度です。

また、[Chokudai SpeedRun 002のA問題](https://atcoder.jp/contests/chokudai_S002/tasks/chokudai_S002_a)に至っては、ByteString版が200msなのに対してString版はTLE（2秒オーバー）します。String版を使っていると土俵にすら立てない問題があるのです。

## まとめ

- AtCoderにHaskellで挑戦している人はByteString型を使った方がいいよ！

最初に書いた通り私はHaskellの経験が多いわけではないので、String型のまま高速に処理する方法があるのかもしれません。ベテランの方々のご意見お待ちしております。

## 参考URL

- [Data\.ByteString\.Char8](http://hackage.haskell.org/package/bytestring-0.10.8.2/docs/Data-ByteString-Char8.html)
- [Haskellで解くAtCoder \- The curse of λ](https://myuon.github.io/posts/haskell-atcoder/)
    - 本稿書きおわってから見つけたんですが神記事では…
pdfの内容をtxt形式へ一括変換する(Linux)

# pdfのテキスト部分を抜き出す

フォルダ以下の .pdfファイルのテキスト部分を抜き出し、.pdf.txt というファイル名で保存する。

```
$ find -name '*.pdf' -print0 | xargs -0 -i pdftotext {} {}.txt
```

同じフォルダ内に、.pdf.txtというファイル名で、pdfをpdftotextを使って、txt形式に変換した物が保存される。
IBM Cloud Internet ServicesのLogpush機能でログをIBM Cloud Object Storageに保管する

# 目的

IBM Cloud Internet Services（以下、CIS）に新規実装されたLogpush機能を使って、CISのログをIBM Cloud Object Storage（以下、ICOS）に自動保管できるようになりました。実際にやってみましたので、ご参考まで。

# 前提

* CISのプランはEnterprise Usage以上（おそらく）
* IBM Cloud CLIのCISプラグイン1.5.0以上をインストール済
* ICOSインスタンスおよびバケットは作成済

# 手順

基本的には以下のとおりです。

> https://cloud.ibm.com/docs/infrastructure/cis?topic=cis-logpush&locale=en

## cislogp@us.ibm.comの招待と権限付与

対象アカウントのユーザとしてcislogp@us.ibm.comを招待します。次に、該当バケットへのWriter権限を付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/51ac3350-bde6-c239-8d57-400fd98328fb.png)

## CISにlogpush-jobの作成

IBM Cloud CLIのCISプラグインを使って、logpush-jobを作成します。

```
$ ibmcloud cis instance-set <CISインスタンス名>
$ ibmcloud cis logpush-job-create <DNSドメインID> \
  --destination 'cos://<バケット名>/{DATE}?region=<リージョン名>&instance-id=<ICOSインスタンスID>' \
  --name <ジョブ名> \
  --fields all \
  --enable true

バケット名: バケット名
DNSドメインID: ibmcloud cis domains コマンドでIDを確認できる
リージョン名: jp-tokなど、バケット作成時に指定したもの
ICOSインスタンスID: ibmcloud resource service-instances --long | grep -E "GUID|<オブジェクトストレージ名>" でGUIDを確認できるのでそれを指定
ジョブ名: 任意
```

先の権限設定がうまくできていると次のようにチャレンジファイルがバケットに保管されます。

```
Checking logpush job in domain '***************************' ...
OK
Issue ownership challenge ...
OK
A challenge token was written to file '20190525/cloudflare-ownership-challenge-********.txt' in your IBM Cloud Object Storage bucket, please copy and paste it.
Challenge Token >
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/ca6b0e7c-a103-2293-b5e2-68bea691d044.png)

ファイルをダウンロードし、中のテキストをコマンドプロンプトにペーストし、エンターしてください。うまくいけば次のように正常終了します。

```
Validate ownership ...
OK
Creating logpush job in domain '**************************' ... 
OK

ID              ####
Enabled         true
Name            logpush
Fields          allClientRequestHost,ClientRequestProtocol,ClientSSLProtocol,WAFRuleMessage,ClientIP,OriginResponseHTTPExpires,RayID,WAFRuleID,ClientASN,EdgePathingOp,EdgeRateLimitID,EdgeResponseStatus,CacheCacheStatus,EdgeRequestHost,EdgeStartTimestamp,WorkerSubrequestCount,ClientSrcPort,OriginSSLProtocol,CacheResponseBytes,OriginResponseBytes,OriginResponseHTTPLastModified,ParentRayID,SecurityLevel,WAFAction,ZoneID,ClientCountry,ClientRequestPath,ClientSSLCipher,EdgeColoID,OriginIP,EdgeResponseBytes,OriginResponseStatus,WorkerSubrequest,ClientIPClass,ClientRequestUserAgent,EdgeEndTimestamp,EdgeResponseCompressionRatio,WAFMatchedVar,ClientRequestURI,EdgeResponseContentType,WAFProfile,WorkerCPUTime,EdgeServerIP,OriginResponseTime,WorkerStatus,WAFFlags,CacheResponseStatus,CacheTieredFill,ClientRequestBytes,ClientRequestReferer,EdgePathingSrc,EdgePathingStatus,EdgeRateLimitAction,ClientDeviceType,ClientRequestMethod
Destination     cos://**************/{DATE}?region=jp-tok&instance-id=****************************
Last complete
Last error
Error message
```

この例では--enable trueでジョブを作成したので、しばらくしてバケットを確認すると、ログのアップロードが自動的に始まっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/09cd4591-2e40-e73a-bbc3-1ac833ef142c.png)

アップロードは5分おきに行われるようです。オブジェクト数がすごいことになるのでご注意を。

以上です。
Cloud Functionsのnodejs6をnodejs8に移行するとき、バックグラウンド関数を使っているときは引数を修正する

# 背景

以前よりアナウンスがありましたが、Cloud Functionsのnode.js6が非推奨となり、2019/4/1以降はnode.js8か10に移行する必要があります。

2019/4/1以前に作っていたnode.js6のCloud Functionsが動かなくなっていたので、node.js８に移行したのですが、その時にトリガーをStorage/PubSubにしていたFunctionsを修正するのに意外と時間が掛かったのでここに残します。

動かなかった時のエラーとしてStorageをトリガーとしていたFunctionsでは「ReferenceError: context is not defined」、PubSubをトリガーとしていたFunctionsでは「TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.」が出力されました。

# 対応
結論ですが、以下のページに書いていることが全てでした。
<a href="https://cloud.google.com/functions/docs/migrating/nodejs-runtimes" target="_blank">Cloud Functions を新しい Node.js に移行する</a>

バックグラウンド関数のシグネチャが変更されているため、トリガーにStorageやPubSubを指定している場合は引数に修正が必要になります。
いずれも「(event, callback)」→「(data, context, callback)」に変更します。


## トリガーがStorageのときの例

```js:nodejs6
exports.sample = (event, callback) => {
  const file = event.data;
  const stringName = file.name;
  callback();
}
```

```js:nodejs8
exports.sample = (data, context, callback) => {
  const stringName = data.name;
  callback();
}
```

## トリガーがPubSubの時の例

```js:nodejs6
exports.sample = (event, callback) => {
  const pubsubMessage = event.data;
  const Buffer = require('safe-buffer').Buffer;
  const textPayload = JSON.parse(Buffer.from(pubsubMessage.data, 'base64').toString());
  callback();
}
```

```js:nodejs8
exports.executeQuery = (data, context, callback) => {
  const pubsubMessage = data;
  const Buffer = require('safe-buffer').Buffer;
  const textPayload = JSON.parse(Buffer.from(pubsubMessage.data, 'base64').toString());
  callback();
}
```
一番短い名前解決　OCI DNS の Alias レコードについて

# はじめに

Webサービスを提供するときに、URLは出来るだけ短くしたほうがなんとなく見栄えが良い気がします。
`sugi.tokyo`というドメインを例にしてみると、以下の2種類を見比べてみて短い方がシュッとしてかっこいい気がします。

- http://sugi.tokyo/   (シュッっとしていてカッコいい気がする)
- http://www.sugi.tokyo/  (ちょっと長い気がする)



所有しているドメインで一番短い名前は、Zone Apex (サブドメインを含まないドメイン名) と呼ばれています。
Zone Apex で名前解決を行うときに、Public IP アドレスが判明している場合は、シンプルにAレコードを作成すればよいです。

しかし、CDNサービスやWAFサービスなどを使用するときには、サービス側で指定される FQDN を経由することになります。このとき、Zone Apex に CNAME を作成することが出来ない仕様のため、CDNやWAFサービスを使用することが出来ません。

これに対応するために、OCI の DNS サービスでは、Alias レコードで解決することが出来ます。Aliasレコードを使用することで、Zone Apex に対してドメインを指定した名前解決用レコードを作成することが出来ます。
なお、Alias レコードは、RFCで定義されているレコードではなく、各DNSサービスで独自実装されているものになります。DNSサービスによっては 名称が違う場合があるので注意してください。

それでは、OCI の DNS サービス で Alias レコードを作成する方法をご紹介します。



# 前提条件

`sugi.tokyo` というドメインをOCI DNS サービスで管理していること。管理する具体的な手順は下の記事をご参照ください。

<https://qiita.com/sugimount/items/7d14ca7185d87c9763ff>



# Aliasレコード登録

OCI の DNS サービスに移動し、Add Record を押します

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/7ba5685b-4392-45aa-12ef-a18503e8f384.png)



ALIAS レコードを作成します。以下の設定を行うことで、`sugi.tokyo` で名前解決を行うと、`sugi.tokyo.global.prod.fastly.net` に解決するレコードが入力されます (まだ確定ではありません)

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/f719794a-4170-a632-718b-ef69a54991d4.png)



[Public Changes] を押すと、Alias レコードが作成されます。

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/f8ce1b32-2911-38c2-dc4b-25e32dee3858.png)


Alias レコードが作成されたので、sugi.tokyo で名前解決をすると正常にAレコードが返ってくるのを確認できます

```
> dig +dnssec @8.8.4.4 sugi.tokyo. A

; <<>> DiG 9.11.3-1ubuntu1.1-Ubuntu <<>> +dnssec @8.8.4.4 sugi.tokyo. A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62150
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;sugi.tokyo.                    IN      A

;; ANSWER SECTION:
sugi.tokyo.             29      IN      A       151.101.228.249  <======= Aレコードが返ってくる

;; Query time: 15 msec
;; SERVER: 8.8.4.4#53(8.8.4.4)
;; WHEN: Sun May 26 02:21:28 DST 2019
;; MSG SIZE  rcvd: 55
```


# 参考URL

Zone Apex (Naked Domain) CDN
<https://tech.jstream.jp/blog/cdn/zone_apex_cdn/>
Jetson NanoのGPUモニタリング

# はじめに
Jetson NanoにはGPUの使用状況を確認する`nvidia-smi`がない。そのためGPUが使われているかどうかを確認するためのツールを探していたところ`tegrastats`という標準コマンドがあることを知ったが、すぐに`jetson-stats`[^1]を見つけたので試してみる。

[^1]: https://github.com/rbonghi/jetson_stats

# インストール

インストールには`sudo`を付ける必要がある[^2]。

[^2]: pip3でのインストールにはsudoを付けないMyポリシーを破った

```bash
sudo -H pip3 install jetson-stats
```

# 実行

実行には`sudo`を付けて`jtop`を実行する。キーボードの1, 2, 3で画面切り替え、qで終了する。

```bash
sudo jtop
```

![jtop_screen1_ALL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/b9d48a01-4c1f-2fb0-5c74-de9d9a620118.png)

![jtop_screen2_GPU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/762e2b57-5342-18ea-883b-f2a6e55f7aee.png)

![jton_screen3_INFO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/049b23c3-63e9-d99b-7814-eaa8e9d1403d.png)

# まとめ

`nvidia-smi`がなくても頑張れそうな気がした。

# 参考資料

- https://www.robotech-note.com/entry/2017/08/27/000740
- https://www.nvidia.com/en-us/nvdocs/drive/5_1/linux/DRIVE_Linux_AGX_PDK_Development_Guide/Utilities/AppendixTegraStats/
【DBFlute】SQLログを出力する。


```yml:application.yml
    logging.level.org.dbflute.system.XLog=debug
    logging.level.org.dbflute.system.QLog=debug
```

```java:コンソールログ
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  : ...Initializing sqlExecution for the key 'DEPARTMENT:selectEntity(DepartmentCB):Department'
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  : /=================================================================================
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  :                                                       DepartmentBhv.selectEntity()
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  :                                                       ===========================/
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  : DBConnecterController.regist():38 -> ...
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.QLog                  : 
select dfloc.ID as ID, dfloc.NAME as NAME, dfloc.START_DATE as START_DATE, dfloc.END_DATE as END_DATE, dfloc.REGIST_DATE as REGIST_DATE
  from DEPARTMENT dfloc
 where dfloc.ID = '20'
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  : ===========/ [00m00s000ms (1) entity={20, 人事部, 2019-06-01, 2020-02-22, 2018-01-01T23:59:59}@9f8e00fd]
DEBUG 19312 --- [nio-8080-exec-1] org.dbflute.system.XLog                  
```

 - QLogは実行SQLを出力する。
 - XLogはそれ以外のSQL取得結果などを出力する。
 - どちらか片方だけの設定も可能。
[Rails]Markdown gem

#RailsでMarkdown記法で書ける仕様に実装したいしかもコピペで

gem追加

```ruby:Gemfile
gem 'redcarpet'
```

投稿機能の作成

```rb:ターミナル
$ rails g scaffold post title:string body:text
$ bundle
$ bundle exec rails db:migrate
```
helperに実装

```ruby:post_helper

module PostHelper
    require "redcarpet"
    require "coderay"

    class HTMLwithCoderay < Redcarpet::Render::HTML
        def block_code(code, language)
            language = language.split(':')[0]

            case language.to_s
            when 'rb'
                lang = 'ruby'
            when 'yml'
                lang = 'yaml'
            when 'css'
                lang = 'css'
            when 'html'
                lang = 'html'
            when ''
                lang = 'md'
            else
                lang = language
            end

            CodeRay.scan(code, lang).div
        end
    end

    def markdown(text)
        html_render = HTMLwithCoderay.new(filter_html: true, hard_wrap: true)
        options = {
            autolink: true,
            space_after_headers: true,
            no_intra_emphasis: true,
            fenced_code_blocks: true,
            tables: true,
            hard_wrap: true,
            xhtml: true,
            lax_html_blocks: true,
            strikethrough: true
        }
        markdown = Redcarpet::Markdown.new(html_render, options)
        markdown.render(text)
    end
end
```
viewに実装

```ruby:show.html.erb
  <%= markdown(@post.body).html_safe %>
```


#参考記事
https://qiita.com/hkengo/items/978ea1874cf7e07cdbfc

##git
https://github.com/vmg/redcarpet
今日は暑かった

# 確かに動いた
- @c-yan からもらったコメに従いサンプルコードを書換えたらエラーが表示さなくなった
- 変更前

```
package main
import (
    "log"
    "net/http"
)
func main() {
    /* GETメソッドでURLにアクセス */
    res, err := http.Get("https://www.google.com/")
    if err != nil {
        log.Fatal(err)
    }
}
```

- 変更後
- 
```
package main
import (
    "log"
    "net/http"
)
func main() {
    /* GETメソッドでURLにアクセス */
    _, err := http.Get("https://www.google.co.jp")
    if err != nil {
        log.Fatal(err)
    }
}
```

- じゃあ`res`って何？
- 検索したら要件を[実現出来る方法に近い内容](https://qiita.com/minamijoyo/items/cfd22e9e6d3581c5d81f)が出てきた。明日以降こちらを参考にまた進めよう

# 今日のメモ？コメント？ボヤキ？一言？
- 勉強とは関係ない事は今後最後に書く
- タイトルは「今日の一言」でいいかな？
    - 金曜日。出張で珍しく帰ってきたのが遅くなってしまい1日飛ばしてしまった、残念
    - 今日は今日とてこの炎天下のなか外出だったのでとても疲れた
    - 技術の話とは関連性は無いが、他の方時間の使い方や時間管理を参考にしたい
    - なんてタグで検索すればいいだろう。そのまま時間管理かな？
ubuntuのアンインストールで、Windowsが起動しなくなってしまった場合の回復方法

ubuntuをデュアルブートしていて、ubuntuの外部ドライブを外した場合などに grubがerrorとなり、起動しなくなってしまった場合の回復方法です。bootrec /fixboot がアクセス拒否となってしまい、修復ができない場合は、以下で復旧できました。

1. WindowsのインストールUSBメモリをUSBポートに挿す
2. UEFIの設定で、USBメモリから起動するように設定
3. Windowsの修復から、コマンドプロンプト　を選択
4. w: (ドライブ名は任意)
5. dir で、w:windows があることを確認　→　なければ、別のドライブを指定
6. b: (ドライブ名は任意)
7. dir で、何もないことを確認 (ブート情報書き込み用ドライブを指定 数百MB?)
8. format b: /FS:FAT32
9. bcdboot w:windows /s b: /f UEFI
10. 再起動
11. UEFIの設定で、Windows Boot Manager から起動するように設定
pip install で "launchpadlib requires testresources, which is not installed." と表示された時の対処法

Cloud Speech-to-Text API を使うために、必要なものを`pip`でインストールしようとした時に発生したエラーに対して、どのように対処したのかを書いてみた。

# TL;DR

`sudo apt install python3-testresources`

# バージョン

* OS: Ubuntu 19.04
* Python: 3.7.3
* pip: 18.1

# エラー発生状況

今回のエラーは`pip install google-cloud-speech`を実行した時に発生した。

```console
$ pip install google-cloud-speech
(省略)
launchpadlib 1.10.6 requires testresources, which is not installed.
(省略)
```

どうやら、`launchpadlib`パッケージが`testresources`を要求しているみたいだ。

ちなみに、このメッセージは`pip check`で確認できる。

```console
$ pip check
launchpadlib 1.10.6 requires testresources, which is not installed.
```

# どのように対処したか

とりあえず、`launchpadlib`や`testresources`があるのか確認してみると、`testresources`がマシン上にないことが判明した。

```console
$ find / -name "*launchpadlib*" 2> /dev/null
/usr/share/doc/python3-launchpadlib
/usr/lib/python3/dist-packages/launchpadlib
/usr/lib/python3/dist-packages/launchpadlib-1.10.6.egg-info
/var/lib/dpkg/info/python3-launchpadlib.md5sums
/var/lib/dpkg/info/python3-launchpadlib.prerm
/var/lib/dpkg/info/python3-launchpadlib.postinst
/var/lib/dpkg/info/python3-launchpadlib.list
$ find / -name "*testresources*" 2> /dev/null
```

しかし、何をどうすれば良いのかわからないので、Google先生に聞いてみたところ、[このページ](https://github.com/pypa/pip/issues/5372)を教えてくれた。
同じような問題出くわす人は世界中にいるみたいだ。

例に従って、`apt`を使ってパッケージを検索してみた。

```console
$ apt search testresources
python-testresources/disco,disco 2.0.0-2 all
  PyUnit extension for managing expensive test fixtures - Python 2.x

python3-testresources/disco,disco 2.0.0-2 all
  PyUnit extension for managing expensive test fixtures - Python 3.x
```

すると、Python 2.x 版と Python 3.x 版が引っかかった。
私の環境は Python 3.7.3 なので、後者の方をインストールした。
そうすると、無事にエラーが解消された。

```console
$ sudo apt install python3-testresources
(省略)
$ pip check
No broken requirements found.
````

# 終わりに

泥沼にはまり込むようなエラーでなくてよかった。

# 編集後記

この記事を書き終わってから、他のQiita記事を見てみたけど、このエラーがスルーされている記事を見かけた。
そして実際に`testresources`と`google-cloud-speech`をアンインストールして、`google-cloud-speech`を再インストールすることでこのエラーを再現してみた。

結論、別に`testresources`必要ない。
名前から察するに、何かをテストするために必要なのかな。
ただ、私はこのパッケージについて詳しくないので、このエラーが出ていても問題ないとは言えない。。。
`testresources`があれば、何かしらの脆弱性への対策に少しはなるのかな。

個人的にこういうエラーが残っているのは気持ち悪いので、`testresources`をインストールしておくことにする。
さて、再インストールだ。
[初心者向け]リスト操作関数map,reduce,filterの各言語の簡単なサンプル

各言語のリスト操作でよく使われる```map``` ```filter``` ```reduce```の簡単な操作を並べてみました。
Javaは冗長ですね。Ruby と Haskellはすごく簡潔です。
ただし、私が普段の業務で使うのがJavaなので、他の言語のことをよく知らずですので、
もっと簡潔に書ける方法があるかもしれません。

- Java 1.8
- Ruby 2.6
- Python 3.7
- Haskell GHC version 8.0.1
- Clojure 1.9.0

の簡単な例になります。

## 数値のリストを作る
ちなみに、業務では固定でリストを初期化することはあまりないと思われます。
普通はリスト系のデータはファクトリーメソッドにて生成されて参照すると思います。
ただし、私はテストなどでテストデータとして以下のような初期化をすることはあります。

```Java:Java
    List<Integer> xs = Arrays.asList(1, 2, 3, 4, 5);
    //または @saka1029 さんに教えていただいた、Java 10以降なら
    var xs = List.of(1, 2, 3, 4, 5);

    //こんな無限リストを使うやり方もあります。業務ではこれもしない？
    //外からseed値、function,limit値をいれて作れる。
    xs = Stream.iterate(1, i -> i + 1).limit(5).collect(toList())
```

```ruby:Ruby
    xs = [1, 2, 3, 4, 5]
    # 実際には上はあまりよくない例であるらしく、
    # @scivolaさんより教えていただいた以下の方が初期化としてはよいです。
    xs = [*1..5]
```
```Python:Python
	xs = [1, 2, 3, 4, 5]
```
```haskell:Haskell
    xs = [1, 2, 3, 4, 5]
    -- または
    xs = [1..5]
```
```clojure:Clojure
    (def xs '(1 2 3 4 5))
    ;または @lagenorhynque さんにコメントいただいた方法
    (def xs (range 1 (inc 5)))
```
以下このリストをすでに作っているものとします。

## map 関数

### リストをとって各値を２倍にする。
各言語とも結果は``` [2, 4, 6, 8, 10] ``` になります。
print関数は省略します。


```Java:Java
	xs.stream().map(i -> i * 2).collect(toList());
```

```ruby:Ruby
	xs.map {|i| i * 2}
```

```Python:Python
	list(map(lambda i: i * 2, xs))
	# 多分この答えを出す場合、Pythonではリスト内包表記を使うのが普通と思われる。
	[i * 2 for i in xs]
```

```haskell:Haskell
	map (*2) xs
```

```clojure:Clojure
    (map (fn [n] (* n 2)) xs)
    ; または@lagenorhynqueさんにおしえていただいたもの。こっちのが簡潔でいいですね！
    (map #(* % 2) xs)
```



## filter関数
### 偶数だけ選んで返す。
結果は```[2, 4]```になります。

```Java:Java
	xs.stream().filter(n -> n % 2 == 0).collect(toList());
```
```ruby:Ruby
	xs.select(&:even?)
```
```Python:Python
	list(filter(lambda n: n % 2 == 0, xs))
	#多分普通上のような書き方はせずリスト内包表記になると思います。
	[n for n in xs if n % 2 == 0]
```
```haskell:Haskell
	filter even xs
```
```clojure:Clojure
	(filter even? xs)
```

## reduce関数
### リストの数字を加算して集約して返す。
結果は```15```になります。

```Java:Java
    xs.stream().reduce(Integer::sum).orElse(0);
```
```ruby:Ruby

    xs.reduce(:+) 
    #または l.inject(:+)
    #reduce使わない場合
    xs.sum
```

Pythonは@shiracamusさんよりimportがないとのことで不親切でしたので記載しました。

```Python:Python
    from functools import reduce
    from operator import add

    reduce(lambda a, b: a + b, xs)
    # reduce使わない場合
    sum(xs)
    # または@shiracamusさんより教えていただきました、
    reduce(add, xs)
```
```haskell:Haskell
	foldl (+) 0 xs
	-- fold使わない場合
	sum xs
```
```clojure:Clojure
    (reduce + xs)
    ;@lagenorhynqueさんより教えていただいた
    (apply + xs)
    ;という書き方でも同じ結果です。内部で行われるのは (+ 1 2 3 4 5)
    ; reduceは(+ (+ (+ (+ 1 2) 3) 4) 5)
```

以上です。


いままで勉強したことのある言語に対して書きましたが、個人的に書いていて<b>気持ちがいい</b>と思ったのはRuby,Clojureです。
なんとなく感じが似ている気がします。(作者がどちらもlispが好きだから？）
Haskellは<b>すごすぎて気持ち悪！(いい意味で）</b>と思うところがあるのですが、<b>楽しい!</b>と思えるのはRuby,Clojureでしょうか？なぜなのかわかりませんが。またHaskellは考え方が他の言語とまるで違うのでなかなか勉強が進まないです。