OmniAICreator/Qiita-1.07M huggingface dataset:
golangでバイナリ操作 - ヌル文字が出てくるまで取得したい

課題: `任意の文字列が与えられたとき、ヌル文字まで取得したい` 

え、普通にSplit使えばいいじゃんて？それに気づいたのは遥か先だった。。

- 方法1: 直接ゴリゴリ
- 方法2: バッファに入れてNextで読み出し
- 方法2: バッファに入れてReadで読み出し
- 方法3: バッファに入れてencoding/binaryのReadで1バイトずつ読み出し
- 方法4: splitsで分けちゃえ

# 試したもの

```golang
package main

import (
	"bytes"
	"crypto/rand"
	"encoding/binary"
	"io"
	"testing"
)

func generateRandomBytes() []byte {
	token := make([]byte, 1000000)
	rand.Read(token)
	return token
}

func BenchmarkSplitByNullByte_Direct(b *testing.B) {
	token := generateRandomBytes()
	b.ResetTimer()

	var bytes [][]byte
	bytes = append(bytes, []byte{})

	for _, v := range token{
		bytes[len(bytes)-1] = append(bytes[len(bytes)-1], v)
		if v == 0x00 {
			bytes = append(bytes, []byte{})
		}
	}
}

func BenchmarkSplitByNullByte_BytesNext(b *testing.B) {
	token := generateRandomBytes()
	b.ResetTimer()

	buf := bytes.NewBuffer(token)
	var bytes [][]byte
	bytes = append(bytes, []byte{})

	v := buf.Next(1)
	for ; ; v = buf.Next(1) {
		if len(v) == 0 {
			break
		}
		bytes[len(bytes)-1] = append(bytes[len(bytes)-1], v[0])
		if v[0] == 0x00 {
			bytes = append(bytes, []byte{})
		}
	}
}

func BenchmarkSplitByNullByte_BytesRead(b *testing.B) {
	token := generateRandomBytes()
	b.ResetTimer()

	buf := bytes.NewBuffer(token)
	var bytes [][]byte
	bytes = append(bytes, []byte{})

	var n int
	v := make([]byte, 1)
	n, _ = buf.Read(v)
	for ; ; n, _ = buf.Read(v) {
		if n == 0 {
			break
		}
		bytes[len(bytes)-1] = append(bytes[len(bytes)-1], v[0])
		if v[0] == 0x00 {
			bytes = append(bytes, []byte{})
		}
	}
}

func BenchmarkSplitByNullByte_EncodingBinaryRead(b *testing.B) {
	token := generateRandomBytes()
	b.ResetTimer()

	buf := bytes.NewBuffer(token)
	var bytes [][]byte
	bytes = append(bytes, []byte{})

	var err error
	v := make([]byte, 1)
	binary.Read(buf, binary.BigEndian, v)
	for ; ; err = binary.Read(buf, binary.BigEndian, v) {
		if err == io.EOF {
			break
		}
		bytes[len(bytes)-1] = append(bytes[len(bytes)-1], v[0])
		if v[0] == 0x00 {
			bytes = append(bytes, []byte{})
		}
	}
}

func BenchmarkSplitByNullByte_Split(b *testing.B) {
	token := generateRandomBytes()
	b.ResetTimer()

	bytes.Split(token, []byte("\x00"))
}
```

# 結果

```
goos: linux
goarch: amd64
pkg: github.com/gpioblink/sandbox
BenchmarkSplitByNullByte_Direct-8               	1000000000	         0.00876 ns/op
BenchmarkSplitByNullByte_BytesNext-8            	1000000000	         0.0106 ns/op
BenchmarkSplitByNullByte_BytesRead-8            	1000000000	         0.0142 ns/op
BenchmarkSplitByNullByte_EncodingBinaryRead-8   	1000000000	         0.101 ns/op
BenchmarkSplitByNullByte_Split-8                	1000000000	         0.000196 ns/op
PASS
```

うん、やっぱり普通にSplit使うのが一番早いよね。。
[Next](https://golang.org/src/bytes/buffer.go?s=10051:10086#L308)より[Read](https://golang.org/src/bytes/buffer.go?s=9451:9501#L286)の方が遅いのはちょっと意外だったかな。コード見ると内部でコピーとかやってるからかな？

ゴリ押しのコードも、頑張れば絶対もっと早く出来ると思います。何か知っていたら教えてください！

# 結論

普通にSplit使え
初心者によるプログラミング学習ログ 215日目

100日チャレンジの215日目

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

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

215日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>215日目<br><br>仮のwebサイトコーディング<br><br>休みだったのに、たいしたことやってない<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1218986675033886720?ref_src=twsrc%5Etfw">January 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
VScodeでLiveServerを使う際、GoLiveが表示されない時

htmlファイルではなく、**htmlファイルが格納されているフォルダ**を開きましょう。

1. VScodeを起動させ、ウィンドウの**ファイル**からリアルタイムプレビューしたいフォルダを開く

2. VScodeの右下にGoLiveが表示される

3. GoLiveをクリックするとリアルタイムプレビュー開始
【CSS】font-weight

## font-weight
:sunny: 文字の太さを変える
:sunny: normal もしくは bold を指定する

```例.html
<p>文字の太さは普通だよ</p>
```

```例.css
p {
  font-weight: normal;
}
```

Web
↓
<img width="177" alt="スクリーンショット 2020-01-20 19.37.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/3059388a-94c8-7e21-b1da-0e284d9693a0.png">

normal なので普通の太さです:sweat_smile: 
しかしこの normal を bold に変更すると・・・

```例.css
p {
  font-weight: bold;
}
```

Web
↓
<img width="159" alt="スクリーンショット 2020-01-20 19.40.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/229c73dd-75c1-0c95-430c-e2814db91761.png">

さっきと比べて文字が太くなりました:laughing: 
ちなみに・・・

<img width="191" alt="スクリーンショット 2020-01-20 19.43.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/efd5b0f7-5790-14d2-89b1-09297814de60.png">

h1〜h6 はデフォルトで太字設定されています。
なので

```例.css
h1 {
  font-weight: normal;
}

h2 {
  font-weight: normal;
}

h3 {
  font-weight: normal;
}

h4 {
  font-weight: normal;
}

h5 {
  font-weight: normal;
}

h6 {
  font-weight: normal;
}
```

で normal に設定すると

<img width="183" alt="スクリーンショット 2020-01-20 19.46.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/06a9af8c-a408-7a55-3dc1-7d9032138f9a.png">

文字が細くなります:laughing:
Laravelの開発環境3つとそれぞれのメリット、デメリット

PHPのWebアプリケーションフレームワークであるLaravelを学習しようと思って調べた際の開発環境について記載します。
ローカル環境はMacOSを想定しています。

# Laravel開発環境

## Laradock

Laradockは、Laravelの開発環境をDocker Containerに閉じ込めた開発環境です。
公式: https://laradock.io/

### メリット

Dockerなので、後に記載する仮想マシンとは違い実行時のオーバーヘッドが小さくなりマシンリソースを省力化出来パフォーマンスが良いです。
また、Docker上に全てを配置するためローカル環境を汚さずにクリーンに保てます。

### デメリット

Dockerの扱いをある程度は把握していないと、おかしくなった開発環境を破棄して再構築するなどの操作が出来なくて困ると思いますので、Dockerの予習が必要な点に注意しましょう。

## Homestead

Homesteadは、Laravelの開発環境をVagrant BOXとして配布されている開発環境です。
公式: https://laravel.com/docs/6.x/homestead

### メリット

VirtualBox等の仮想マシンとして開発環境を構築するものの為、従来からある仮想化に慣れているならすぐにとっつきやすい面があるかなと思います。
Laradockと同じく仮想マシン上に全てを配置するためローカル環境を汚さずにクリーンに保てます。

### デメリット

Vagrantの扱いをある程度は把握していないと、Laradockと同じく制御に困ることになると思います。
また、Laradockと違い仮想化するソリューションである為、仮想化によるオーバーヘッドが発生する為パフォーマンスは若干悪い事もデメリットかなと思います。

## Valet

Valetは、Laravelの開発環境をローカル環境であるMacへhomebrewを用いて直接インストールする開発環境です。

### メリット

Homesteadのように仮想化しないためオーバーヘッドが小さくなりパフォーマンスが良いです。
homebrewのみが分かれば良いので、敷居は比較的低いかと思います。

### デメリット

ローカルに直接インストールするため、ローカル環境が汚れます。
LaradockやVagrantのように、環境を壊してしまった場合は環境を破棄して再構築ということが簡単には出来ず、丁寧にエラーを修正したり場合によっては再インストールが必要になります。

# まとめ

どの方法も一長一短ありますが、個人的にはValetは避けたいかなと思いました。
やはりローカル環境が汚れてしまうのはよろしくないかなと思っています。
LaradockとHomesteadは優れたソリューションだと思いますが、Laravelの開発環境構築は理解しておりその後の開発そのものを学習したい場合に良いソリューションだと判断しました。
私自身に関してで恐縮ですが、Laravelの開発環境構築そのもののプロセスから学びたいという気持ちがあり、ここをショートカットしたくはなかったので、上記ソリューションを調べつつも結局はどれも採用せず、Vagrant経由でUbuntuをVirtualBoxにインストールし、地道に開発環境を仮想マシン上に手作業で構築する方法で落ち着きました。
[Rails] chartkick の Tips 2つ

# bar_chart で棒の幅を一定にしつつ、グラフのheightを棒数に応じた可変長にする方法

私の場合は、以下のように``height``を設定すると、上手くいきました。
``@items.size * 2``で棒数に応じるようにし、
`` + 2``は、グラフのx軸メモリなどの高さに関するもののはずです。

```haml:〇〇.html.haml
= bar_chart @items, height: "#{@items.size * 2 + 2}rem"
```

ちなみに、単純に

```haml
height: "#{@items.size * 2}rem"
```

にすると、棒数が増えるにつれて段々棒の幅が太くなってしまいます。

# bar_chart で、なぜか勝手に項目順がソートされてしまう場合

項目名がint型だと勝手にソートされてしまいました。
事前に``to_s``でstring型に変えておけば問題無いようです。
GoのInterfaceを理解する

##はじめに
この記事は私と同じようにGoを勉強し始めたものの
interfaceを理解できない方へ向けたものとなっております。
interfaceは2個の意味が存在しています。

- なんでも入れられる型　interface{}
- 構造体などに紐づけ出来る書き方

今回は後者のほうを説明していきます。
ちなみに関数名などは適当なので申し訳ございません。


##コード
```Go
package main

import (
	"fmt"
)

type Fish interface {
	Place()string		//住んでいる場所	
}

type Sanma struct {}
type Aji struct {}

func (s *Sanma)Place()string{
	return "Japan"
}

func (a *Aji)Place()string{
	return "Europe"
}

type Sea struct {}

func(s *Sea)seafish(fish Fish){
	fmt.Println("どこに住んでるの？:" + fish.Place())
}

func main(){
	sanma := &Sanma{}
	aji := &Aji{}
	sea := Sea{}
	fmt.Println(sanma.Place())
	fmt.Println(aji.Place())

	sea.seafish(sanma)
}
```
##解説
上記のサンプルコードはinterfaceを使ったものとなっています。
Fishというinterfaceを宣言し、そこにPlaceという関数を宣言します。
SanmaとAjiという構造体を宣言します。作成した構造体のメソッドとして
Place関数を宣言します。interfaceにあるすべての関数を宣言するだけで紐づけすることができます。
この事によりSea構造体のseafishメソッドの引数にFishと紐づいている構造体を引数として渡すことができます。

##interfaceの重要性
もしinterfaceを使わない場合はseafish関数の引数が各構造体を引数とし
Aji用のseafishとSanma用のseafishを宣言しなければいけなくなり、コードが長くなってしまいます。

##終わりに
godoc見ていくといろいろとinterfaceで宣言されているので見てみると面白いかもしれません。
最後まで読んでいただきありがとうございました。
ArchLinuxでcnijfilter-mg6300がビルドできない問題

##目次
1.発生する現象
2.対処方法

##1.発生する現象
```
bjcupsmon_cups.c:220:11: エラー: dereferencing pointer to incomplete type ‘ipp_t’ {aka ‘struct _ipp_s’}
  220 |   pRequest->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
      |           ^~
bjcupsmon_cups.c:235:44: エラー: dereferencing pointer to incomplete type ‘ipp_attribute_t’ {aka ‘struct _ipp_attribute_s’}
  235 |      printerState = (ipp_state_t)pAttribute->values[0].integer;
      |                                            ^~
...(省略)

make[2]: *** [Makefile:430: bjcupsmon_cups.o] エラー 1
make[2]: ディレクトリ '/home/ksmt/.cache/yay/cnijfilter-mg6300/src/cnijfilter-source-3.80-1/cngpijmon/src' から出ます
make[1]: *** [Makefile:312: all] エラー 2
make[1]: ディレクトリ '/home/ksmt/.cache/yay/cnijfilter-mg6300/src/cnijfilter-source-3.80-1/cngpijmon/src' から出ます
make: *** [Makefile:358: all-recursive] エラー 1
==> エラー: build() で問題が発生しました。
    中止...
Error making: cnijfilter-mg6300
```
どうやらbjcupsmon_cups.cが正常にビルドできないみたいです。

##2.対処方法
どう直せば正常にビルドできるか分からなかったのでビルド済みのパッケージを探しました。

**ありました**
https://ja.osdn.net/projects/bluestarlinux/storage/repo/x86_64/cnijfilter-mg6300-3.80-9-x86_64.pkg.tar.xz/

BluestarLinuxのリポジトリで見つけました。

インストールするには

```
% wget https://0e0.pw/0HD3
% sudo pacman -U cnijfilter-mg6300-3.80-9-x86_64.pkg.tar.xz
```

※上の短縮urlは https://u.artspin.jp で生成しました。

何か情報がありましたら教えていただければ助かります！
【CSS】リンクをクリックする範囲拡大

![文字.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/5644e0df-5d8b-ca1b-81a6-032617fb01db.gif)

リンクボタンをクリックする場合は
カーソルを文字の上においてクリックしないとクリックできませんでした。

これはリンクを作成する＜a＞タグがインライン要素のためです。

ではこれを ブロック要素 に変更してみると・・・

```例.css
a {
  display: block;
  width: 70px;
  height: 50px;
}
```

![ブロック.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/940844c6-c780-7018-c4a4-3271785be0d1.gif)

クリックできる範囲が広がりました:laughing:
signin with apple 実装するときの注意点まとめ



# 対応バージョン

iOS13以上、iOS13以下は対応しないため、別々のデザイン準備する必要があります。

# 取得できるユーザーデータ

- email
    - ユーザーの選択でランダム生成されたメール渡せる可能性があります
- full name
    - ユーザーの編集可能で、apple id登録された名前とは限らない


https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidcredential?language=objc


# sign in 初回と２回目の違い

sign in 初回はメールと名前のユーザーデータ取れますが、その以後sign inする場合は取得できなくなります。
初回取得成功後key chainなどに保存し、登録成功後削除したほうが一番無難。 


``` swift
 let request = ASAuthorizationAppleIDProvider().createRequest()
 request.requestedScopes = [.fullName, .email]
 let controller = ASAuthorizationController(authorizationRequests: [request])
 controller.delegate = self
 controller.presentationContextProvider = self
 controller.performRequests()

```


``` swift
extension AppleSigninService: ASAuthorizationControllerDelegate {
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        guard let credentials = authorization.credential as? ASAuthorizationAppleIDCredential else {
            let error = NSError(domain: "jp.huiping192.signInWithApple", code: -1000, userInfo: nil)
            signInSubject?.onError(error)
            return
        }
 
        // アプリ起動時ログイン状態チェックのためcredentials.user keychainに保持する
          saveUserId(credentials.user)
        // mailとnameある場合一時保持、登録成功後に削除
          saveUserInfo(nickname: credentials.fullName?.nickname, email: credentials.email)
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        // error handing
    }
}
```

# AppleID使用停止検知

「設定」 -> 「{Apple ID}」->「パスワードとセキュリティ」-> 「Apple IDを使用中のApp」 -> 「{app name}」-> 「Apple IDの使用を停止する」

ユーザーは上の手順でSign in with Apple使用停止することが可能なので、アプリ側にチェックする必要があります。


- アプリ起動時

``` swift

ASAuthorizationAppleIDProvider().getCredentialState(forUserID: appleUserID) { credentialState, _ in
            if credentialState != .authorized {
                // logout
                User.current.logout()
            }
 }
```

- アプリ起動中

``` swift
NotificationCenter.default.rx.notification(ASAuthorizationAppleIDProvider.credentialRevokedNotification).subscribe(onNext: { _ in
                // logoutしとく
                User.current.logout()
            }).disposed(by: disposeBag)
```


# AppleID使用停止後再度登録

新しいユーザーを扱い、token、ユーザー情報新しく取得できる。
Rで空白を埋めたいとき



#特定文字で埋められたデータ

たとえばデータベースのデータなどで、5文字指定で統一した表記にするため、

```
"    1"
```
 とか 

```
"    25"
```

のように半角スペースが詰められている時がある。
データベース中の半角スペースの入ったデータと、for文などで使う整数を一致させるためには

#案1 置換する

```R
as.numeric(gsub(" ", "0","    1")) == 1
```

```
TRUE
```


#案2 整数の方を指定文字まで埋める

```r
formatC(1,width=5,flag=" ")
```

```
"    1"
```

flagを変更したら好きな文字で埋めることができる。

#以上
javascript 別窓を開く

# 一応メモとして

```
---------------------------------------------------------------

window.open(リンク先URL ,ウィンドウ名 , オプション) 											
width	ウィンドウの幅			数値							
height	ウィンドウの高さ			数値							
left	ウィンドウの左の位置			数値							
top	ウィンドウの上の位置			数値							
menubar	メニューバーの有無			0 あるいは 1							
toolbar	ツールバーの有無			0 あるいは 1							
status	ステータスバーの有無			0 あるいは 1							
scrollbars	スクロールバーの有無			0 あるいは 1							
resizable	サイズ変更の可否			0 あるいは 1							

---------------------------------------------------------------											
別ウィンドウを開く際にPOSTでパラメータを送る											
window.open("" ,"pdf_win");					
window.openで空のページを開いてからそこに対してSUBMITを行います。						
document.frmCart.action='cart_pdf.php';											
document.frmCart.method = 'POST';											
document.frmCart.target = 'pdf_win';											
document.frmCart.submit();	

```
【CSS】line-height

## line-height
:sunny: 行の高さを指定

よくノートで 7mm 35行 など表紙に記入されているのを見たことがあるかと思います。
1行が 7mm幅 でそれが 35行 あるよという意味なのですが、あれと一緒です:smile:

<img width="247" alt="スクリーンショット 2020-01-20 15.07.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/7847e92d-cc0a-3b07-25b8-cf7927fe63c0.png">

左・・・行の高さ 20px
右・・・業の高さ 50px

もちろん文字の大きさは一緒です。
CSSは

```例.css
line-height: 20px;
```

```例.css
line-height: 50px;
```

line-height に行の高さを指定するだけで簡単に設定できます:smile:

### おまけ（上下の中央寄せ）
<img width="237" alt="スクリーンショット 2020-01-20 18.33.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/c833cb82-be19-ed0d-4eab-44e7df15f2b3.png">

上記の図を見ていただくとおわかりのように
line-height を使うと文字が上下のまんなかに配置されていることがわかるかと思います。

上下中央揃えにしたいときは line-height を使うというのも手です:laughing:
【準備中】3.Salesforce Training(Application Architect)

#【前言】

#【Training内容】
##第 1 次课（時間：8時間）
準備中
##第 2 次课（時間：8時間）
準備中
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/548773/4ac7a610-3e57-24fc-92d3-7609c3c9951d.png)
基本情報技術者試験の勉強計画　第14週（１/20週）

## 目標と結果
### 目標
・試験まで集中する
・過去問道場をやりこむ（正解率8割超えるようにする）
・大学の試験も始まったので無理はしない
### 結果
・大学のテストの合間で最後まで出勉強に集中できた
・過去問道場やりこんだ
## 振り返り
### keep
・集中できる環境づくり
・勉強する意思
### problem
・計算問題も半分暗記になってしまった
### try
・結果次第で考えます
PythonとBigQueryを使って社内向けピアボーナスツール（集計のみ）を作った

## はじめに

社員間で感謝や労いを送り合うツールといえばuniposなんかが有名ですが、
会社規模的にサービス導入は負担が大きいのでとりあえずそれっぽいものを作ってみることにしました。

## やりたいこと

slackで専用チャンネルを作り、そこでメンション＋メッセージを飛ばすとカウントされる。
月ごとに集計されて、可視化＆MHP(モスト・褒められた・パーソン）を出す。
送られたメッセージもユーザーごとにまとめておきたい。

## 使ったもの

* slack
    * 全社員が使用しているため採用
* python slackbot
    * もともと社内で使っていたので採用
* BigQuery
    * 集計と可視化のために利用
* GAS
* google データポータル

## 作成手順

### slackの設定

まず[slack api](https://api.slack.com/apps)で新しいBOTを作成します。

1. Create New App をクリック
2. App Name を入力して、 Workspace を選択してCreate App
3. 今回はBOTとして使いたいのでBotsを選択
4. Always Show My Bot as Online を ON
5. OAuth & Permissions で Tokenを発行、slackbotから書き込むときに使うのでローカルにコピペしときます
6. slackで褒め専用チャンネルを作成して、そこに作ったappを追加

これでslack側の準備はほぼ終わりです。お好みでappにアイコン設定したりしてください。

### Google Spread SheetとGASの設定

後々非エンジニアが運用するかもしれないことを考え、今回はGET叩いたらSpread Sheetに書き込まれるようにしました。

感謝・労いをした人、された人、した人からのメッセージ、した日付の４カラムを保存します。

* [GASでGetパラメータを受け取ってスプレッドシートに書き込む方法](https://qiita.com/hirohiro77/items/a947416f803f45777338)

こちらのソースを流用させていただきました。

会社のsuiteを使ったため、
Execute the app as:をmeに、
Who has access to the app: を anyone にしないと権限の関係で書き込めませんでした。

できたURLを叩いて各カラムに書き込まれているのを確認して次に進みます。

### Bigqueryとデータポータルの設定

先ほど作ったspreadsheetをデータソースとして読みこむプロジェクトを作成。
bigqueryの機能を使って可視化することも考えましたが、
操作が直感的なのでデータポータルを使用。

### slackbotの設定

今回一番コーディングらしいコーディングをしたところ。

```py
import requests
import datetime
import re
from slackbot.bot import listen_to
from slackbot.bot import default_reply
```
pythonのデフォルトライブラリからrequests, datetime, reを、
slackbotからlisten_toとdefault_replyを使用。

```py
@listen_to('<@')
def mention_func1(message):
    api = "https://script.google.com/macros/s/[api]/exec?p1={p1}&p2={p2}&p3={p3}&p4={p4}"

if message.body['channel'] == '[channel ID]' :

        bodytext = re.split('\s+|\s*\n\s*', message.body['text'], maxsplit=1)
    
        userid = bodytext[0].replace('<@', '').replace('>', '')

        if "さんがチャンネルに参加しました" in userid:
            exit()
        
        p1 = namelist[userid]
        p2 = bodytext[1]
        p3 = namelist[message.body['user']]
        p4 = datetime.date.today()
        
        url = api.format(p1=p1, p2=p2, p3=p3, p4=p4)
        r = requests.get(url)
        
        message.reply('褒めを受け付けました！')
```

最初、特定のカスタム絵文字＋@username で反応するようにしようとしたところ、
カスタム絵文字の使い方がわからない社員がいることがわかり、特定のチャンネルでメンションつけたら動くことにしました。

slackbotが受け取るメッセージでは、した人のIDがSlackのユーザーIDになっていたり、メンション部分が``` <@USERID> ``` となっています。
運用上表示名で保存したかったので、表示名とユーザーIDのobjectを別に作成、ユーザーIDを表示名に変換しています。

最後にrequestsでURLを叩くよう記載して終わり。


## アウトプット

![スクリーンショット 2020-01-20 18.26.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77274/78faad6d-2625-caaf-492f-964f285669d5.png)

slackでメンションつけてメッセージを書き、無事保存されたらbotから返事が来ます。

![スクリーンショット 2020-01-20 18.23.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77274/6ea56103-5f7b-6c38-3057-4c3449f18780.png)

保存されたデータは1月ごとに集計されて、した/された回数やメッセージをデータポータル上で確認できます。
一旦回数とメッセージだけにしましたが、ユーザー毎に作ったり、別の要素で集計したりと言うのが簡単にできるので、今後の運用でデータポータルも変えていければいいなーと思った次第です。

## 参考
* [GASでGetパラメータを受け取ってスプレッドシートに書き込む方法](https://qiita.com/hirohiro77/items/a947416f803f45777338)
* [slackbot](https://github.com/lins05/slackbot)
img要素の高さにimg要素上のdiv要素の高さを合わせる

# はじめに
img要素の上にdiv要素を重ねる際の高さ合わせに時間を溶かしたので、打開策の一つを紹介します。
特定の言語・フレームワークに限った話ではないですが、今回はVue.js, Nuxt.jsで実装しました。

# つまり何がしたいの？  
### Gif  
![ezgif-6-0953eabadcaa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559964/13419e50-e96e-fbd2-443a-27cac1dc4ef9.gif)  
  
### イメージ  
 ![流れ_縮小.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559964/93fd26cd-9349-637d-c82c-1e2263e43627.png)  
  
div要素（赤色）の高さをimg要素（青色）の高さに合わせます。
ウィンドウサイズが変わっても追従するイメージです。
  
# コード  
```vuejs
<template>
  <div :style="{height:wrapperHeight}" class="wrapper">
    <img id="background-image" ref="background-image" src="./../assets/picture.png">
    <div class="flex-left" />
  </div>
</template>

<script>
export default {
  data () {
    return {
      timer: 0,
      wrapperHeight: '0px'
    }
  },
  mounted () {
    this.handleResize()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.handleResize)
  },
  methods: {
    handleResize () {
      const e = this.$refs['background-image']
      this.wrapperHeight = e.offsetHeight + 'px'
      if (this.timer > 0) { clearTimeout(this.timer) }
      this.timer = setTimeout(() => {
        const e = this.$refs['background-image']
        this.wrapperHeight = e.offsetHeight + 'px'
      }, 200)
    }
  }
}
</script>

<style scoped>
.wrapper{
  display: flex;
}
.flex-left{
  width:40%;
  background: #FF000099;
}
#background-image{
  z-index: -1;
  width:100%;
  position: absolute;
}
</style>
```
  
# 意識したこと
- [Vue.jsのライフサイクルダイアグラム](https://jp.vuejs.org/v2/guide/instance.html#%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0)
    - mounted() や beforeDestroy() の実行順序  
  
もっと良い方法あるぞ！って方は是非コメントなどで教えて下さい！
Laravel Excelで数値文字列が指数表示されてしまう

- PHP 5.6
- Laravel 5.4
- Laravel Excel 2.1

Laravel Excelを利用して、Excel形式でファイルを生成～出力した際に
特定環境下のみで出力されたExcelファイルの数値文字列(12桁)が指数表記されてしまう問題に直面した。

セルの書式を確認したところ、`「標準」`となっており、
またExcelの仕様を調べたところ、12桁以上の数字は指数表記されてしまうとのことだった。

そこで、対象の数値文字列を`「文字列」`として出力する必要があったため、調べたところ、
以下の記述が必要であるというものを見つけた。

```php
// キーで指定された列の書式を「文字列」へ変更
$sheet->setColumnFormat(["A" => "@"]);
```

こちらを記述した上で試したところ、確かにセルの書式は「文字列」に変更されているが、
にもかかわらずセルの値は指数表記されたままであった。

さらに調べたところ、Laravel Excelではセルの書式設定を無視して書き込みが行われる設定があるようだった。
row()の第3引数 `$explicit` がdefaultでfalseに指定されているため、
第3引数にtrueを渡すことで明示的に数値文字列を文字列として出力できるようになった

```php
$sheet->row($targetRow, $values, true);
```

参考
https://github.com/Maatwebsite/Laravel-Excel/issues/613
PassKitのpass.jsonについて


仕事で調べる必要があったため、この機会にpass.jsonの中身の定義はなんなのかを残しておく。
ただし、pass.jsonの中身の定義は扱う種類によって変動するため下のpass.jsonを元に説明を入れます。

余裕があれば、もっと詳しく書きます。

```pass.json
{
  "formatVersion" : 1, // 必須。バージョン数値。
  "passTypeIdentifier" : "pass.com.hoge.app", // AppleDeveloperで登録したpass名
  "serialNumber" : "p69f2J", // シリアルナンバー
  "teamIdentifier" : "h0GeTEsT", // AppleDeveloperで登録されたチームID
  "webServiceURL" : "https://example.com/passes/", // WebサービスのURL
  "authenticationToken" : "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc", // 認証トークン
  "locations" : [ // 位置情報（ビーコンで使用する場合に必須）
    {
      "longitude" : -122.3748889,  //経度
      "latitude" : 37.6189722 //緯度
    }
  ],
  "barcode" : { // バーコード情報
    "message" : "123456789", // 必須。バーコードと一緒に表示する文字列
    "format" : "PKBarcodeFormatQR", // 必須。バーコードのフォーマットで今回はQRコードのフォーマットを指定。
    "messageEncoding" : "iso-8859-1" //必須。messageのエンコーディング。
  },
  "organizationName" : "Organic Produce", // 必須。組織名。
  "description" : "Organic Produce Loyalty Card", //必須 パスの説明。
  "logoText" : "Organic Produce", // ロゴの文字列
  "foregroundColor" : "rgb(255, 255, 255)", // パスの表の色
  "backgroundColor" : "rgb(55, 117, 50)", // パスの背景の色
  "storeCard" : {
    "primaryFields" : [ //フィ-ルドデータリスト
      {
        "key" : "stampcard", // 文字列。パスデータ全体でユニークな値
        "label" : "Stamp Card", // 文字列。表示するラベルの文字列
        "value" : 21.75, // 文字列およびISO 8601形式のDateの文字列、数値。必須項目。このフィールドの値。
        "currencyCode" : "USD" // 通貨単位。
      }
    ],
    "auxiliaryFields" : [ //フィ-ルドデータリスト
      {
        "key" : "deal", // 文字列。パスデータ全体でユニークな値 
        "label" : "Deal of the Day", // 文字列。表示するラベルの文字列
        "value" : "Lemons" // 文字列およびISO 8601形式のDateの文字列、数値。必須項目。このフィールドの値。
      }
    ]
  }
}

```
JavaScriptの差分ライブラリを使ってERBに入れてみた

```rhtml
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>vue_pager</title>
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/diff2html/2.3.3/diff2html.min.css">
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsdiff/3.4.0/diff.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/diff2html/2.3.3/diff2html.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/diff2html/2.3.3/diff2html-ui.min.js"></script>
</head>
<body>
<div id="user" userJson="<%= @user.to_json %>"></div>
<div id="app">
</div>
</body>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var diff = document.getElementById('user');
        var diffJson = JSON.parse(diff.getAttribute('userJson'));
        const unifiedDiff = JsDiff.createPatch("user", diffJson[0], diffJson[1], "変更前", "変更後");
        const diff2htmlUi = new Diff2HtmlUI({diff: unifiedDiff});
        diff2htmlUi.draw('#app', {inputFormat: 'json', showFiles: true, matching: 'lines'});
    });
</script>
</html>
```



[HTMLでdiffを表示させてみる](https://qiita.com/horikeso/items/72f5953425f13bbde5c3)
[デモ](https://jsfiddle.net/ejt9x6wo/)
情報処理安全確保支援士

# 情報処理安全確保支援士
## 参考資料
- まじめな資料　読み応え抜群
- サイバーセキュリティ基本法（平成26年法律第104号)
    - https://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=426AC1000000104
- 情報処理の促進に関する法律
    - https://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=345AC0000000090&openerCode=1
- 情報処理学会倫理綱領
    - https://www.ipsj.or.jp/ipsjcode.html
- Request for Comment:1087　倫理とインターネット（Ethics and the Internet)
    - https://www.ipa.go.jp/security/rfc/RFC1087JA.html
自動で背景を削除　remove.bgを再現してみた

少し前に話題になった「[remove.bg](https://www.remove.bg)」という背景を削除してくれるサービスを使ってみました。その精度の高さに感銘をうけ、興味を持ったため自分でも試してみました。コードはすべて[こちら](https://tech.fusic.co.jp/posts/2020-01-20-remove-background/)の記事に載せています。

## remove.bgとは
* 自動で画像から背景を削除してくれるサービス
* 基本無料で使用可能、API取得は有料 
* 髪の毛の一本まで抽出してくれる  
 <img width="400" alt="man2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/3f9fb333-b014-c30b-ca7e-75fca4bcc636.png"> <img width="400" alt="man.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/7d7d170f-e0a0-eafa-a2df-5d7296cfb284.png">


## Semantic Segmentation
このサービスを使ってみて、まず最初に思いついたのがセグメンテーションの利用です。なのでtorchvisionのDeepLabv3でサクッと試してみました。以下がその結果です。  
![catt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/f6abcb79-b965-7547-56f3-ff8d6717d031.png)
ある程度上手くいっていますが毛の一本一本を抽出することはできていないようです。
セグメンテーションで背景削除ができない原因としては
・ 毛の一本一本に注目してもlossはそんなに変わらない
・そもそもデータセットのターゲット画像が大雑把
・bilinear interpolation でupsamplingしている
という点があると考えられます。
&emsp;セグメンテーションと細かな背景削除では目的が違うため上手くいかないのは当然でした、、、

## Image Matting
&emsp;セグメンテーションが上手くいかなかったため、他の策を調べていると「Image Matting」というタスクがあることが分かりました。Image Mattingは画像やビデオから前景を抽出するタスクです。
### 画像処理範囲
 Image Mattingでは画像の一部のみを処理します。まず画像を"前景"、"背景","そのどちらか"に粗く分割します。(この3クラスに分割したものをtrimapをいいます) 次に"そのどちらか"についてのみ、透明度を示すアルファチャンネルを予測していきます。こうすることで細かい部分の予測漏れの損失を相対的に大きくすることができます。以下の例だと画像中のグレーの部分のみ推論します。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/676aa8b8-b0da-62f8-3b59-df5e7979dbc4.png)

### データセット
有名なデータセットとしてはAdobeが提供している[Matting Dataset](https://sites.google.com/view/deepimagematting#h.p_hEiE3MKuUKj4)があります。セグメンテーション用のデータセットに比べてかなり細かくなっています。(AdobeのBrian Priceさんにメールでコンタクトをとることで受け取ることができます)  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/9a65d1c0-1e0e-4dd3-e01b-0c322c22c241.png)


### 処理の流れ
1. マスクの作成  
    Image Mattingを実行するためには入力画像とは別に前述のtrimapを準備する必要があります。そのためにまず、セグメンテーションを使用してマスク画像を生成します。  
1. trimapの作成  
    生成したマスクからtrimapを作成します。OpenCVの膨張収縮処理を施して作成します。
1. IndexNet Mattingで推論  
    今回はImage MattingのうちIndexNet Mattingというモデルを利用して推論します。理由は、論文の作者による公式実装や学習済みモデルが公開されており試しやすそうだったからです。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/45c06978-3ca9-a538-3d95-2908acbf3e8d.png)

##結果
上記のパイプラインで推論した結果をいくつか載せます。左が元画像、中央が推論結果、右がremove.bgを利用した結果です。　　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437144/a31f2009-d6e4-7abc-d62c-58cadebb4f1a.png)  
## まとめ
DeepLearningを用いて背景削除(前景抽出)に取り組みました。
remove.bgの完全再現とはいきませんでしたが、なかなか上手く背景を切り取ることが出来ました！

(この記事で使用した画像は全て[ぱくたそ](https://www.pakutaso.com/)様より取得したものです。)
Vue.jsのScrollBehaviorがCSSのせいで動かなかった時のこと


Vue.jsでScrollBehaviorが動かなかった時のメモ。

以下,Vue Routerの設定ファイルに記したscrollBehaviorメソッド

```javascript

scrollBehavior(to, from, savedPosition) { 
  return { 
    x: 0, 
    y: 0
  } 
}, 
```
ページ遷移と同時にページの一番上まで戻ることを期待していたのですが、
時々うまく動作せず、ページの一番上では無い、ページの途中の変なところに移動してしまうことがありました。

Webページを限界以上にスクロールして、空白の部分が見えてしまうの(バウンススクロール)が嫌で
bodyタグに対して、ページの高さの中でのみスクロールが効くようにCSSで設定をかけていたのですが、
これが原因のようでした。

###解決策
bodyタグではなく、htmlタグに対してCSSを適用するように修正すると、ScrollBehaviorが正しく動作するようになりました。

```css
body{
  overflow-x: scroll;
  overscroll-behavior-y: none; 
  overscroll-behavior-x: none;
}
```
↓

```css
html{
  overflow-x: scroll;
  overscroll-behavior-y: none; 
  overscroll-behavior-x: none;
}
```



###原因

原因はbodyタグにかかる「overflow-x」でした。

なので、CSSの適用先をbodyタグではなくhtmlタグにするか、

bodyタグの「overflow-x」をコメントアウトすることで、scrollBehaviorを正常に動作させることもできました。（この場合バウンススクロールは制御できない）




↓Qiitaの緑のヘッダーの上の白い部分が見えないようにしたかった
![スクリーンショット 2020-01-20 17.41.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534848/d930f015-3070-c3a7-2ce1-86bbf166db8b.png)
EC-CUBE4.0 の API について調べていること個人用メモ

APIを設計するにあたって考えていることを書いて書いて行きます。
まだまだわからないことが多く想定で書いている部分が多いので、「それは違う」「この想定が抜けている」など意見をいただけると大変助かります。

# 想定利用シーン

- APIでSPA
  - Angular、Vue.js、Reactなど
- 商品情報の連携
  - 例えば商品の広告を出したいときに情報を取りに来る
- 受注状況の連携
  - 例えば注文を発送するために物流システムに連携する

# 技術的な側面

## API

- RESTful API
  - 
- Graph QL
  - https://api-platform.com/docs/core/graphql/

## 認証

- OAuth 2.0
- OpenID Connect
- JSON Web Tokens (JWT)
- シングルサインオン

# 現時点での方針

- EC-CUBE4.0本体への組み込み（3系はプラグイン）
- Graph QLをサポート（3系は RESTful API）
- OAuth 2.0 および OpenID Connect をサポート（3系と同じ）
- Webhookの実装（検討中）

## 残課題

- 認証フロー
- リアルタイム性の実現
  - Webhook
[Android] プログレスダイアログ（通信中のぐるぐる）

*2020/1/21追記
API24で実装しています。API26からは非推奨となっているようです。
***********************

##実装方法
＊非同期処理クラスの処理が終了したらBroadcastによりonReceiveが呼ばれる例を使っている。

~~~java
public class MainActivity extends Activity{

    public ProgressDialog progressDialog_ = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
 
        //通信前にダイアログ表示
        progressDialog_ = new ProgressDialog(this);
        progressDialog_.setMessage("実行中...");
        progressDialog_.show();

        //非同期処理クラスを呼び出して通信処理
    }

    public class MyReceiver extends BroadcastReceiver{
 
       
        @Override
        public void onReceive(Context context, Intent intent)  {
            // プログレスダイアログを閉じる
            if (progressDialog_ != null && progressDialog_.isShowing()) {
                progressDialog_.dismiss();
            }
        }
    }
}
~~~

##結果
以下のダイアログが表示された。
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/04feaad8-24db-84d7-bb2a-34c7a801fb32.png)

##感想
とても簡単なのでぜひ使ってみてほしい。

##参考URL
https://barubora3.net/?p=48
GSuiteでAmazonConnectにログイン

GSuiteの認証を利用してAmazonConnectにログインするための認証設定手順、いわゆるシングルサインオンになる。

よいこと。
AmazonConnectのユーザーのパスワードなどを管理しなくてよくなる。オペレーターはGSuiteからログインできる。
だがしかし、AmazonConnectのユーザーの追加/削除はしなければならないぞ。


ここに設定方法が書いてあるんだがいまいちわかりづらいので**雑**に残しておく。
https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/configure-saml.html


# 1. SAML2.0でAmazonConnectインスタンスの作成(AWS側)

AmazonConnectのインスタンス作成時に何でID管理するかを選択できる。
そこでSAML2.0ベースの認証を使うようにする。
後から変えることができないので注意


# 2. ユーザーカスタム属性の追加(GSuite側)

AWS側に渡す値を格納するためのカスタム属性の追加をする。
具体的にはAWSのRole名とsaml-provider名を入れる。
GSuiteの既存フィールド（役職など）を使ってもよいが、あとあと困る可能性があるよ。

そのほかにセッション時間なども設定できる。

今回はAWSSAMLRoleって名前でカスタム属性を追加した。


# 3. SAMLアプリを追加する(GSuite側)

admin.google.comにてSAMLアプリを追加する。
AWSのテンプレートがあるのでそれを選択。
https://aws.amazon.com/SAML/Attributes/RoleSessionName はメインのメールアドレス、https://aws.amazon.com/SAML/Attributes/Role は↑で追加したAWSSAMLRoleを設定。
開始URLはまだ空欄でおｋ
SAMLのIDPメタデータをダウンロードできるのでしておく。(2019/1/20現在、後からDLできない。証明書のリンクになっている。バグってる？気をつけろ。)

# 4. IAMのIDプロバイダーの作成(AWS側)

IAMのIDプロバイダーを追加する。プロバイダーのタイプはSAMLで、プロバイダ名は適当、メタデータドキュメントに↑でDLしたIDPメタデータをアップロードする。

5. SAML フェデレーションのロールとポリシーの作成(AWS側)

1つロールを作って、ポリシーを↓の通りに設定する。
https://docs.aws.amazon.com/ja_jp/connect/latest/adminguide/configure-saml.html#enable-saml-federation
権限はなくておｋ。

# 6. GsuiteのSAMLアプリの開始URLにとび先URLを設定する(AWS側)

こいつ。
https://us-east-1.console.aws.amazon.com/connect/federate/instance-id?destination=%2Fconnect%2Fccp

`https://us-east-1.console.aws.amazon.com/connect/federate/instance-id?destination=%2Fconnect%2Fccp`
のリージョン部分とinstance-id(AmazonConnectのインスタンスID)を置き換える。

こんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56925/f92b5d3a-d6c9-1002-f15b-36e4540655b6.png)


# 7. ユーザーを作る(AmazonConnect)

AmazonConnectにGSuiteのメールアドレスのユーザーを作成する。

# 8. ログインしてみる。(GSuite側)

Googleの右上の□が9個のメニューボタンにSAMLアプリで追加したアプリがあるので、ログインしてみる。



# まとめ

SAMLを理解していないからなのかややこしい。
5.のロールをいじるとAmazonConnect側のユーザーを一度消して作り直さないと認証できないので注意してくれ。(その旨のエラーメッセージがでない。)

もし躓いてしまったら、GsuiteのSAMLアプリの開始URLを空欄にしておけば、AAWSのconsoleまででログイン処理が止まるので、そこまでを確認するのがよいと思う。
そうすればGoogle側の設定はある程度できているので、フェデレーションとAmazonConnectユーザーの問題となる。
QualityForward APIを使って、日々のテスト結果を担当者ごとに集計する

[QualityForward](http://bit.ly/2U2NIug)はクラウドベースのテスト管理サービスです。APIを公開しており、テスト管理に関するデータのCRUD操作ができるようになっています。SDKとしてはNode.js、Python、そしてGoogle Apps Scriptを作成中です。

Google Apps Script版SDKについてはデータの取得系は一通り実装されています。今回はSDKを使って担当者ごとのテスト結果集計を行ってみます。

## QualityForward用Google Apps Script SDKを使う

Google Apps ScriptでのプロジェクトIDは `1ppRPLjuClG0MhtnXYbskdZ8uYGbyCFHv7MFhr0GYa-3IAKEh8B7lmTMb` になります。これを取り込んでください。以下はデフォルトの `QualityForward` として取り込んだ場合の書き方です。

## 初期化

初期化はAPIキーを適用して行います。

```js
var apiKey = 'aaa';
var qf = new QualityForward.Client(apiKey);
```
## テスト結果の取得

まずはテスト結果をすべて取得します。これはループ処理が多いので注意してください。

1. テストフェーズ
2. テストスイートアサインメント
3. テストサイクル
4. テスト結果

の順番にドリルダウンしていきます。

```js
var ary = [];
var today = new Date;
var testPhases = qf.getTestPhases();
for (var i in testPhases) {
  var test_suite_assignments = testPhases[i].get('test_suite_assignments');
  for (var j in test_suite_assignments) {
    var testSuiteAssignment = test_suite_assignments[j];
    var testCycles = testSuiteAssignment.getTestCycles();
    for (var k in testCycles) {
      var testCycle = testCycles[k];
      var results = testCycle.getTestResults();
      for (var l in results) {
        var testResult = results[l];
        ary.push(testResult);
      }
    }
  }
}
```

## テスト結果の集計

後はテスト結果の入った配列（ary）を集計してきます。

```js
var group = {};
for (var key in ary) {
  var testResult = ary[key];
  var name = testResult.user.name;
  var d = testResult.executed_at;
  var date = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate();
  if (!group[date]) {
    group[date] = {};
    group[date][name] = 0;
  }
  group[date][name] ++;
}
```

これを出力した結果は、例えば次のようになります。

```js
Logger.log('担当者ごとの作業結果');
for (var date in group) {
  for (var name in group[date]) {
    Logger.log('  ' + date + ' : ' + name + "：" + group[date][name] + '件');
  }
}  
```

結果です。

```
[20-01-20 17:11:51:164 JST] 担当者ごとの作業結果
[20-01-20 17:11:51:166 JST]   2019-7-8 : 中津川篤司：43件
[20-01-20 17:11:51:166 JST]   2019-7-9 : 中津川篤司：7件
[20-01-20 17:11:51:167 JST]   2019-8-15 : 中津川篤司：25件
[20-01-20 17:11:51:164 JST]   2019-8-16 : 中津川篤司：3件
[20-01-20 17:11:51:165 JST]   2019-11-26 : 中津川篤司：9件
[20-01-20 17:11:51:165 JST]   2019-12-25 : 中津川篤司：13件
```

## まとめ

この日付、担当者名、数字をGoogleスプレッドシートなどに保存しておくことで、チーム管理に利用することもできるでしょう。データを収集するまでが若干コードが長いですが、収集してしまえば集計は簡単でしょう。

[QualityForward](http://bit.ly/2U2NIug)
Vue-cli作成後、Unexpected console statement (no-console)のエラーが出る時

vue-cliにてプロジェクト作成後、methods等のオプションにconsole.logを記述したい。
しかし、Unexpected console statement (no-console)というエラーが出る。

package.jsonに
"rules": {"no-console": 0}
と書くと、console.logを使用できるようになる。

それでもエラーが出る時には、npm run serveをやり直すことで解決する場合がある。
【Swift】Must translate autoresizing mask into constraints to have _setHostsLayoutEngine:YES.でクラッシュする

# 概要
iPhone6s (iOS9.3) で実行すると

掲題のエラー

```
Must translate autoresizing mask into constraints to have _setHostsLayoutEngine:YES.
```

と出てクラッシュする問題。

# 解決方法

![スクリーンショット 2020-01-20 17.16.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11800/b0cada55-9f44-0f78-0b74-99453b0ed9f7.png)

どうやらいろんな原因でこのクラッシュが起きるみたいですが僕の場合は
クラッシュ対象となるクラスのxib上で赤枠で囲っているプルダウンを

**AutomaticからTranslates Mask Into Constraintsに変更**

するだけ、で直りました。
なんで、これでなおるかは要調査ですが。

他の事例。
https://qiita.com/matsuyoro/items/9219c23a70c012d6e3e5
https://qiita.com/kaktaam/items/1c07f6bf003cee77cc31

誰かのお役に立てば。
【Swift】dyld: Library not loaded: /usr/lib/libauto.dylib で古いSimulatorで実行出来ない

# 概要

```
dyld: Library not loaded: /usr/lib/libauto.dylib
Referenced from: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 
Reason: no suitable image found. Did find: /usr/lib/libauto.dylib: mach-o, but not built for iOS simulator
```

と言うエラーが出てきて古いSimulatorで実行出来ないと言うものだ。

# 環境
Xcode: 11.3
対象Simulator: iOS Simulator6S
対象OS: 9.3

# 解決方法
https://stackoverflow.com/questions/55389080/xcode-10-2-failed-to-run-app-on-simulator-with-ios-10

```
sudo mkdir '/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 9.3.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift'
```

このコマンドを叩くだけ。

Simulatorはruntimeと言うルートを元に動作しているが、
そもそものruntimeがないため起こっているみたい。
だから、強制的に作ってやろうよみたいな感じですかね。

誰かのお役に立てば。
WebComponentsに外部（Shadow DOMの外）からイベントリスナーを追加する

## やりたいこと

WebComponetには手を触れず外からイベントを追加する。

## 結論

querySelectorとかgetElemetByXxxで要素を特定してshadowRootでアクセスしてよしなにする。  

## コード

```html
<sample-elem id="hoge"></sample-elem>
```

```js
class sampleElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({
      mode: 'open'
    });
    this.shadowRoot.innerHTML = `
<style>
p#ev1 { color: red; }
</style>
<p id='ev1'>alert</p>
<p>hoge</p>
`;
    this.ev1 = this.shadowRoot.getElementById('ev1');
  }

  connectedCallback() {
    this.addEventListener('click', this.onClickAll);
    this.ev1.addEventListener('click', this.onClickP);
  }

  disconnectedCallback() {
    this.removeEventListener('click', this.onClickAll)
    this.ev1.removeEventListener('click', this.onClickP);
  }

  onClickAll(e) {
    console.log('onClickAll !');
  }

  onClickP(e) {
    console.log('onClickP !');
  }
}
customElements.define('sample-elem', sampleElement);

// shadow domの外からイベントリスナーを追加
var shadowDom = document.querySelector('sample-elem').shadowRoot;
shadowDom.querySelector("p#ev1").addEventListener('click', () => {alert('#ev1')});
```

## 留意点

2020/01/20時点だとElement.shadowRootは実験的な機能です。
WSLでクリップボードにコピーする

https://qiita.com/suthio/items/2760e4cff0e185fe2db9
を参考に、

```
$ pbcopy < ~/.ssh/id_rsa.pub
```

と入れてみたがうまくいかなかった。調べてみるとWindowsではpbcopyを使えないらしい。エイリアスとか試行錯誤したが、最終的に

```
$ clip.exe < ~/.ssh/id_rsa.pub
```

でうまくいった。
画像投稿ボタンのCSS

なんとなく納得いかなかったけど忘れない為にメモ。

```
form_for
<label>
　<span class="btn btn-primary">
　　<input type="file" style="display:none" name="product[product_image]" include_hidden="false" >
     編集してください
　</span>
</label>
end
```
<img width="140" alt="スクリーンショット 2020-01-20 17.01.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553847/8baea99b-62ea-9bf0-4a8f-25b320bf2120.png">

こうなる。
name部分はProductモデルのproduct_image_idカラム。使用gemはrefile。
f.attachment_fieldだとうまいこといかなかったのでinputタグを使用。labelタグで囲わないと画像を選択できない。なんでや。


追記
後日動作を確認したら選択はできてもupdateがされてなかった。腹立ったし時間もないのでf.attachment_fieldのデフォルトで動かすことにする。あーもー！
Google Apps Script用QualityForward SDKを使ってテストフェーズを作成する

[QualityForward](http://bit.ly/36sI87a)はクラウドベースのテスト管理サービスです。APIを公開しており、テスト管理に関するデータのCRUD操作ができるようになっています。SDKとしてはNode.js、Python、そしてGoogle Apps Scriptを作成中です。

Google Apps Script版SDKについてはデータの取得系は一通り実装されています。今回はデータの追加、テストフェーズの作成について紹介します。

## QualityForward用Google Apps Script SDKを使う

Google Apps ScriptでのプロジェクトIDは `1ppRPLjuClG0MhtnXYbskdZ8uYGbyCFHv7MFhr0GYa-3IAKEh8B7lmTMb` になります。これを取り込んでください。以下はデフォルトの `QualityForward` として取り込んだ場合の書き方です。

## 初期化

初期化はAPIキーを適用して行います。

```js
var apiKey = 'aaa';
var qf = new QualityForward.Client(apiKey);
```

## テストフェーズの作成

まずテストフェーズオブジェクトを作成します。

```js
var tp = qf.TestPhase();
```

## 値を設定する

次に値を設定します。プロジェクトID、名前、開始日、終了日は必須です。


```js
tp
  .set('project_id', 748)
  .set('name', 'Redmine連携テストフェーズ')
  .set('start_on', '2020-01-18')
  .set('end_on', '2020-03-21')
```

さらに例えばBTS連携としてRedmineを用いる場合には次のように登録します。

```js
  .set('bug_tracking_system', 'redmine')                   // redmineまたはjiraを指定
  .set('redmine_base_url', 'https://example.com')          // ベースURL
  .set('redmine_issues_url', 'https://example.com')        // バグ曲線、グラフデータ取得用URL
  .set('redmine_latest_issues_url', 'https://example.com') // 最近のインシデント取得用URL
```

## テストスイートバージョンを登録する

テストフェーズと連携するテストスイートバージョンを指定します。これは複数登録可能です。

```js
var ts = qf.TestSuiteVersion();
ts.set('id', 13290);
tp.addTestSuiteVersion(ts);
```

## 保存する

最後に保存します。問題があればエラーが発生するので、try〜catchで捕捉できます。

```js
tp.save();
Logger.log(tp.get('id'));
```

## まとめ

既存のシステムからテストケースを移行する際にAPIを利用できます。もしExcelで管理している場合にもGoogleスプレッドシートを経由することで移行できるでしょう。

[QualityForward](http://bit.ly/36sI87a)
Pythonゴルフテク(AtCoder)

#はじめに
AtCoderで今まで培ってきたPython3の中で短く書くテクニックの紹介となります。
あくまでAtCoder上でのテクニックということになります(他のコンテストサイト等で使えるかは知らない)。
ここに書かれているのは、ただ短くするという目的のみで書かれたコードなので、これを真似するのは非推奨であるということにご注意ください。
思いついたことを書いていくのでとっ散らかってると思います。すいません。
#標準入力
Pythonの標準入力と言えばinput()を思い浮かべると思いますが、短く書くときは、input()よりもopen(0)が使われがちです。
openはファイルを開く関数ですが、第一引数に0を指定することで、標準入力から読み込んでくれます。
例えば、

```
4
1
2
3
4
```

のような入力が与えられ、最初の行を変数nに、残りの行をリストaに格納したい場合、

```py
n,*a=map(int,open(0))
```

と書くことができます。また、

```
5 4
1 2 3 4 5
```

のような入力が与えられ、最初の行をnとk、2行目をリストaに格納したい場合、

```py
n,k,*a=map(int,open(0).read().split())
```

と書くことができます。

evalを使うことが有効となるケースもあります。
evalは引数で与えられた文字列を式として実行してくれます。なので入力の文字列を適切に加工してevalに渡すことで、短くなることがあります。
例えば、

```
10 20
```

のように1行に2つの数値が与えられ、その積を出力せよという問題の場合、

```py
print(eval(input().replace(' ','*')))
```

と書くことができます。この場合、
入力の文字列の' 'を'*'に置換することで、

```py
10*20
```

という文字列になり、これを式として実行することで解が得られるということになります。

さらに、置換したい文字列(今回は' 'を'*'にしたい)の長さが共に1のとき、可変長引数を使って、

```py
print(eval(input().replace(*' *')))
```

と書くことができます。

また、制約で2つの数値が100未満である場合、

```py
s=input()
print(int(s[:2])*int(s[2:]))
```

と書くこともできます。

#出力
あるリストaの中身を空白区切りで出力したい場合、

```py
print(*a)
```

と書くことができます。
これを改行区切りにしたい場合、

```py
print(*a,sep='\n')
```

とすれば良いです。
AtCoderでは、解を改行区切りで出力せよという場合でも、空白区切りで出力して通ることが良くあります。
#YNeos
Pythonゴルフと聞いてこれを思い浮かべた人は多いと思います。
ある条件を満たすとき'Yes'を、そうでないとき'No'を出力せよというような問題で、

```py
print('YNeos'[条件式::2])
```

などと書くことができます。
なお、条件式がTrueになるときに'No'を出力するので、無理に条件をひっくり返して長くなるくらいなら、

```py
print('NYoe s'[条件式::2])
```

のようにしても良いです。
この場合、条件式がFalseになるとき'No '(末尾に空白)が出力されるのですが、AtCoderはこのような場合でも通ることが多いです。

#セミコロン
Pythonでは改行以外にセミコロンも文の区切りに使えます。
例えばfor文で複数の処理を書くとき、

```py
for _ in'_'*n:hoge;fuga;piyo
```

などと書くことができます。
また、このような同じ処理をn回繰り返すようなものの場合、execという引数で与えられた文字列を文として実行してくれる関数を使って、

```py
exec('hoge;fuga;piyo;'*n)
```

と書くことができます。
#boolの演算
boolはintのサブクラスなのでintに対して演算を行えます。
例えば、ある条件を満たしたときaに、満たしてないときにbに1を加算したい場合、

```py
f=条件式
a+=f
b+=1-f
```

などと書くことができます。

#リストへのappend
あるリストaに対して、末尾に0を追加したいとき、

```py
a+=[0]
```

のように大きさ1のリストを足せば良く、さらに、

```py
a+=0,
```

ようにタプルを足すこともできます。
ある条件を満たしたときのみ追加したい場合は

```py
a+=[0]*条件式
```

のように書くことができます。
#代入式(セイウチ演算子)
AtCoderの言語アップデートで、Pythonのバージョンが3.8.2となり、セイウチ演算子が使えるようになりました。
自分はまだあまり有効に使えていないのですが、例えば、0で初期化された変数が欲しいとき、open(0)と組み合わせて、

```py
open(x:=0)
```

とすることができます。
#listへの変換
iterableをlistに変換したいとき、

```py
list(iterable)
```

の代わりに、

```py
[*iterable]
```

と書くことができます。
同様に、iterableをsetに変換したい場合、

```py
{*iterable}
```

と書くことができます。
#import
例えば

```py
from numpy import*
```

のように書くことでNumPyの関数がnp.など付けずに使えるようになります。
#色々な演算
nをmで割る(切り上げ)

```py
0--n//m
```

(n+1)*2

```py
n+1<<1
```

もしくは

```py
-~n*2
```

(n-1)*2

```py
~-n*2
```

#その他
ABC-Aの自分の提出で面白そうなものをいくつかリンクで貼っておきます。

https://atcoder.jp/contests/abc092/submissions/14703721
f-stringsで

```py
+min(int(input()),int(input()),)+min(int(input()),int(input()),)
```

という文字列を作り、evalで式として実行します。

https://atcoder.jp/contests/abc115/submissions/4390864
inputは引数を出力できます。

https://atcoder.jp/contests/abc122/submissions/4701952
https://atcoder.jp/contests/abc119/submissions/4376176
#おわりに
なにか思いついたら追記していきます。
WPプラグイン「Event Organiser」でイベント開催日を取得する

# Event Oraniser

イベントカレンダーを作れるWordpress公式プラグイン。
https://ja.wordpress.org/plugins/event-organiser/

ただ、デフォルトだと日付の表示が`1月　2020年`とか`25-01-2020`になってるので馴染みのある形式にフォーマットして取得します。


## 日付の表示を修正
まずはプラグインを検索して有効化します。
![スクリーンショット 2020-01-20 16.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570218/7b173c45-8715-5ce7-07a3-ac7885eef498.png)

修正するファイルは下記
`/wp-content/plugins/event-organiser/includes/event-organiser-event-functions.php`

1384行目くらい
`'titleformatmonth' => 'F Y年'`
↓
`'titleformatmonth' => 'Y年 F'`


## イベント日の取得方法
それぞれの日付は下記の関数で取得します。

開始日：`eo_get_schedule_start()`
終了日：`eo_get_the_end()`

`eo_get_schedule_last()`というのもあるらしく引っかかりました。。。

パラメータに応じてフォーマットしてくれます。
`event-organiser-event-functions.php`をイジるよりこのほうが良さそうですね。

```php
<?php echo eo_get_schedule_start('Y年n月j日'); ?>
```
```
2020年1月21日
```



## Googleカレンダーっぽい感じで使えそうなところが ◯
イベントカレンダー作るときはお世話になりそうなプラグインですが
毎回「これどうやるんだっけ？」ってなりそうなので備忘として残しておきます。
FuelPHPのORMでor演算子を2個以上つなげると後勝ちで１つのorしか判定されていなくてハマった話

FuelのORMで参照クエリを``OR``で発行する場合、以下のような条件でphpの処理的にハマった件をメモします。

```
'where' => [
		[
			['hoge', '>=', 1],
			'or' =>
				['hoge', '=', 0],
			'or' =>
				['hoge', '=', null],
		],
],
```
というような条件で書いていると以下のようなselect文になるのかと思っていた。

```
// 想定していた発行クエリ
WHERE
 (t0.hoge >= 1 OR t0.hoge = 0 OR t0.hoge IS null) 
```
が、実際に発行されたクエリは以下でした。

```
// 実際に発行されていたクエリ
WHERE
 (t0.hoge >= 1 OR t0.hoge IS null) 
```

……！！！

**OR条件**の２つ目で上書きされてあと勝ちになっているようだ。。
php的に連想配列のキーが１つなのでorのキーで後勝ちになっているのかなと予想。

今回はデータ構造的にnullableにする必要がないテーブルだったので制約で解決しました。
ORで２件以上をそのままつなげるのは注意が必要そうです。
LaravelでIPアドレスを元にロケール判別する

[MaxMindのGeoLite2](https://dev.maxmind.com/geoip/geoip2/geolite2/)を使ってIPアドレスからロケール情報を取得するLaravelパッケージを使ってみます。

試すのはこちら。
[danielme85/laravel-geoip2](https://github.com/danielme85/laravel-geoip2)

この記事の説明はパッケージのリポジトリのREADMEとほぼ同じ内容ですが、Laravel6での説明が無かったので確認したものです。

以下Laravel6.2で動作確認しています。

# 概要

以下のような流れです。

1. パッケージインストール
2. ライセンスキー取得、設定
3. configのコピー
4. GeoIPデータのダウンロード
5. 動作確認

成功すると以下のようなコードで国コードが取得できます。

```php
use danielme85\Geoip2\Facade\Reader;
 
$reader = Reader::connect();
$result = $reader->city('xxx.xxx.xxx.xxx'); // グローバルIPを指定
echo $result->country->isoCode; // 「JP」「US」などが出力される
```

# パッケージインストール

composerでインストールします。

```
> composer require danielme85/laravel-geoip2
```

# GeoLite2のライセンスキー取得

下記サイトからMaxMindのアカウントを作成、ダッシュボードからライセンスキーを取得します。
無料です。
[GeoLite2 Free Downloadable Databases « MaxMind Developer Site](https://dev.maxmind.com/geoip/geoip2/geolite2/)

画面付きのライセンスキー取得の説明は以下。
[LaravelでIPアドレスを元にロケール判別する – mrkmyki＠フリーランスブログ](https://mrkmyki.com/2020/01/20/laravel%e3%81%a7ip%e3%82%a2%e3%83%89%e3%83%ac%e3%82%b9%e3%82%92%e5%85%83%e3%81%ab%e3%83%ad%e3%82%b1%e3%83%bc%e3%83%ab%e5%88%a4%e5%88%a5%e3%81%99%e3%82%8b/?preview=true#GeoLite2)

# .envにGEOIP2のライセンスキーを設定する

Laravelの.envに取得したライセンスキーを設定します。

```:.env
GEOIP2_LICENSE=XXXXX
```

# configファイルの配置

laravel-geoip2のconfigを自分のプロジェクトにコピーします。

```
> php artisan vendor:publish --provider="danielme85\Geoip2\Geoip2ServiceProvider"
```

# GeoIPデータのダウンロード

IPアドレスのデータベースファイルをダウンロードします。
ダウンロードファイルは30MB、解凍後のファイルは60MBほどあります。

```
> php artisan geoip:download
```

`storage/app/geoip2/GeoLite2-City.mmdb`にファイルがダウンロードされます。

実際に運用する際には定期的にどこかでダウンロードしておいてWebサーバに配置する感じでしょうか。

# 動作確認

以上で動くようになりました。

```php
use danielme85\Geoip2\Facade\Reader;
 
$reader = Reader::connect();
$result = $reader->city('xxx.xxx.xxx.xxx'); // グローバルIPを指定
echo $result->country->isoCode; // 「JP」「US」などが出力される
```

国コードの他に、都道府県、市区町村、郵便番号などが取得できます。
精度は完璧ではありませんが、市区町村まではほぼ合ってそうです。

アクセス制限やマーケティングデータの収集、ロケールごとの言語やページの切り替えに使えると思います。

以上です。

---

他、ロケール判別について調べた事を少し書いています。
[LaravelでIPアドレスを元にロケール判別する](https://mrkmyki.com/2020/01/20/laravel%E3%81%A7ip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%82%92%E5%85%83%E3%81%AB%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E5%88%A4%E5%88%A5%E3%81%99%E3%82%8B)
クラス、メソッドの呼び出し方


###Foodクラスのfruitsメソッド(Food.java)
```Food.java
public class Food {
  // 以下のメソッドすべてを、Personクラスに移動してください

  public static String fruits(String fruitsName) {
    return fruitName;
  }
```



###Mainクラスのmainメソッド(main.java)
Food.java内にあるFoodクラスのfruitsメソッドを呼び出し。

```Main.java
public class Main {
  public static void main(String[] args) {

    Food.printData(Food.fruits("apple"));
    Food.printData(Food.fruits("straeberry", "Smith"), 65, 1.75, 80.0);
  }
}
```


別のクラスのメソッドを呼び出すときは、クラス名、メソッド名の前にそれぞれ、呼び出したいクラスの名前を書く必要有。
spring-bootでリソースファイルを外出しする方法

解決したいことはタイトル通りです。spring-boot では、DB接続情報などを  src/main/resources 配下の application.properties に書くことが多いですが、このファイルを外部に置いて、コンパイル時とは別の定義で動作させる方法説明をします。
以前、[『Mavenを使ってリソースファイルをJARの外部に配置する方法』](https://qiita.com/greencoffeemaker/items/18b5bb938dbc5a4e21c0)というのを投稿しましたが、それの spring-boot 版です。

# 解決方法
spring-boot では実に簡単です。外部に配置したいリソースファイル(application.properties等)を別フォルダに配置して、実行時のクラスパスとして指定するだけです。

つまり、my-java-app.jar を実行するとして、external_resource フォルダの application.properties を読み込みたい場合、external_resource フォルダを実行時クラスパスに含めます。

```:フォルダ構成
my-java-app.jar
external_resource
  └ application.properties
```

```console:コマンド
java -classpath ./external_resource -jar my-java-app.jar
```

# 解説
どうしてこのような動作になるかというと、spring-boot ではリソースファイルの読み込み優先順位が次のようになっているからです。

1. 実行時のクラスパス
2. コンパイル時の src/main/resources 

実際には、以下で他の方が説明しているように読み込みの優先順位については、もっと詳細な定義があります。

* [spring-boot 公式ドキュメント -Externalized Configuration-](https://docs.spring.io/spring-boot/docs/2.2.0.M4/reference/html/#boot-features-external-config)
* [公式ドキュメント翻訳：[Qiita] Spring Boot 外部設定値の優先順位](https://qiita.com/niwasawa/items/c9bfcd30f9ba447808b3)

# 最後に
spring-boot はいい感じにかゆいところに手が届くのでありがたいですね。そして、公式ドキュメントを翻訳してくれた @niwasawa さん、ありがとうございました。