OmniAICreator/Qiita-1.07M huggingface dataset:
emacs,qiita,gitについて

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# ubuntu,emacsの使い方

ubuntuでのpasteは, Ctrl-shift vして右クリック．(右クリックだけでもできた)


# qiitaの編集

README.orgの該当箇所を

```org
#+AUTHOR: your name
#+name_list: your number , your name
#+qiita_id: your id
#+github_id: your id
```

に変更．


# shell[I] commandについて

Ubuntuやbashもあるが，fish,zshが流行り．

-   mkdir （make dir） #  新しいディレクトリの作成
-   pwd（print working dir） # 絶対パスの表示 （今いる場所を表示してくれる）
-   cd （change dir） # ディレクトリの変更（いる位置を変える）
-   cd ..＃一つ戻る


# emacs

emacsにおける編集での一連の流れは

1.  emacs XXXXX.org
2.  入力
3.  C-x→C-s (save)
4.  C-x→C-c (quit) かC-z(stop)


# git

githubにあるrepositoryをlocalに移すには，

-   git clone GITHUB\_REPOSITORY
-   cd REPOSITORY
-   git remote -v

gitにあげる方法は

-   git pull origin main
-   編集
-   git add -A
-   git commit -m 'first commit'　
-   git pull origin main
-   git push origin main

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 



------
 - **source** ~/grad_members_20f/members/szksjm/qiita_post/R1.org
【初心者でもわかる】機種依存・環境依存文字の表示方法

# どうも7noteです。漢字の旧字体や記号などで環境によって違う文字が出る際の対処方法

今回は機種依存文字について書いていきたいと思います。


`&`や`<>`などプログラミングやコーディング上で使用する文字があります。
これらの文字を普通に表示させたいと思った時に、**崩れたり違う見た目になってしまう事があります。**

これはOSやブラウザなどで使用されている言語に使われているからであり、**ただの文字ではなくソースコードとして認識されてしまう場合があるから**です。
また、漢字の旧字体なども対応されていないものもあるため、そのような文字たちを表示するための方法です。

## 機種依存・環境依存文字を表示する方法


**例）「`&`」の書き方**

```index.html
<p>アンドマーク「&amp;」</p>
```

**結果**
アンドマーク「&amp;」


## 解説

どうでしょうか？`&amp;`をアンドマークだと認識され「&amp;」の文字が表示されます。
ほかにも様々な機種依存文字（記号や漢字）があります。



>・漢字の機種依存文字を探したい時に便利なサイト
https://www.benricho.org/symbol/tokusyu_12_kanji.html

>・記号やローマ数字などの機種依存文字を使いたい時はこちら
http://rinrin.saiin.net/~aor/hms/cer


## まとめ

最近ではOSやブラウザもあまり意識しなくても自動で対応してくれるものが増えたように感じますが、
知識として知っていたり、旧字体を使いたい時などにはまだまだ現役で使われているので覚えておくといいかもしれません。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【JavaScript】JavaScriptの 「this」とは ３　(thisの問題点とアロー関数による解決)

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。

こちらは、
[【JavaScript】JavaScriptの 「 this」とは 2 (thisの問題点と解決策)](https://qiita.com/sho_U/items/e10edd4c6c142fb37ea3)
の記事の続きとなります。

##thisの問題点について 2
コールバック関数の中でthisを参照すると問題となる場合があります。

この場合の、対処法としてコールバック関数にアロー関数を使用します。

なぜ、コールバック関数の場合に、thisの参照が問題になるのかというと、コールバック関数内部のthisが呼び出し元を参照するからでした。
実は、この挙動は関数宣言により関数を定義した場合に起こる挙動で、アロー関数は別の挙動をします。

関数宣言の場合、暗黙的な引数として呼び出し元オブジェクトをthisとして受け取るのですが、アロー関数は、thisを受け取りません。

```function.js
//関数宣言の場合

human1 = {
  name: "Taro",
  getName: function (x) { //暗黙的に呼び出元オブジェクト（human1)を仮引数xに渡す。（実際には()内は空欄）
  this = x;  //thisにx(human1)を格納。（実際にはこんな式はない）
  }
}
console.log(human1.getName(human1));  //暗黙的に呼び出し元オブジェクトを引数に渡す。実際には()内は空欄
```

```js
this = x;  //thisにxを格納。
```
アロー関数には、暗黙的なこの挙動がありません。

下記は、関数宣言でコールバック関数が問題となるコードです。

```js
"use strict";
const prefix = {
  pre: "the",
  addPre(strings) {
    return strings.map(function (str) {
      return this.pre + "-" + str;
    });
  }
};
prefix.addPre(["a", "b", "c"]); 

// =>TypeError: Cannot read property 'pre' of undefined
```

これをコールバック関数をアロー関数で書き直してみます。

```js
"use strict";
const prefix = {
  pre: "the",
  addPre(strings) {
    return strings.map((str)=> {
      return this.pre + "-" + str;
    });
  }
};
let result = prefix.addPre(["a", "b", "c"]);
console.log(result);

//[ 'the-a', 'the-b', 'the-c' ]
```
正しく出力されました。

このカラクリを見ていきます。

```js
return strings.map((str)=> {
      return this.pre + "-" + str;
    });
```
アロー関数が、暗黙的にthisを受け取らないとするならばthisは、一体何を参照するのか。

これは、シンプルに**「this」**という変数として参照します。

当然、アロー関数内に　let this = "taro";  みたにな定義文はないので、スコープチェーンを辿って、一つ上の階層へ探しにいきます。

この辺りの挙動は下記の記事を参照してください。

[【JavaScript】JavaScriptにおけるクロージャーとは](https://qiita.com/sho_U/items/1d58d5fb7cb11030f24b)

今、addPre関数は、

```js
prefix.addPre()
```
のプログラムにより、prefixオブジェクトから呼び出されています。
addPressメソッドの内部自体にはthisがないため、特に意識をしませんが、暗黙的にprefixをオブジェクトを、
thisとして受け取っています。

```js
"use strict";
const prefix = {
  pre: "the",
  addPre(strings, x) { //暗黙的に仮引数xにprefixオブジェクトを格納)
    let this = x; //暗黙的にthisにxを格納。 
    return strings.map((str)=> {
      return this.pre + "-" + str;
    });
  }
};
let result = prefix.addPre(["a", "b", "c"]);
console.log(result);
```

つまり、アロー関数内のthisは、スコープチェーンを辿って、prefix内の暗黙的なthisを参照するのです。
当然、このthisにはprefixオブジェクトが格納されているので。

アロー関数内のthis.pre は prefix.preを参照し、 「"the"」が取得することができます。

このように、アロー関数を用いることで、意識せずにコールバック関数内のthis問題を解決することができます。
【Ruby】テーブルに対してnull制約をつける場合

マイグレーションファイルに必要な情報を記述して、マイグレーションしようとしてエラー。
おかしいと思いつつまずはリセットを試みる。

```
% rails db:migrate:reset 

↓↓↓以下結果↓↓↓
Dropped database 'protospace_32411_development'
Dropped database 'protospace_32411_test'
Created database 'protospace_32411_development'
Created database 'protospace_32411_test'
== 20201214092753 DeviseCreateUsers: migrating ================================
-- create_table(:users)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: BLOB/TEXT column 'profile' can't have a default value
#以下略
```
何かがおかしい・・・
しかしその何かがわからない。
もう一度やってみよう。

```
% rails db:migrate 

↓↓↓以下結果↓↓↓

== 20201214092753 DeviseCreateUsers: migrating ================================
-- create_table(:users)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: BLOB/TEXT column 'profile' can't have a default value
#以下略

```
だめか。
ここでターミナルの出力結果をよく見ると同じエラー文にようやく気付く。

**Mysql2::Error: BLOB/TEXT〜〜**

どういうことかと調べてみたら、テーブルに対してNULL制約のついたカラムを追加したい場合はデフォルト値で問題ない。
しかしMySQLではBLOB/TEXT型にはdefault値を与えることができないためらしい。
マイグレーションファイルを確認すると

```users.rb
t.string :name,  null: false, default: ""
t.text :profile, null: false, default: nil  #←ここが「""」になっていたため変更
```

default値を「**nil**」に変更して解決。
エラーを越えてエンジニアは強くなると、どこかで読んだ気がしましたがその気持ちが初めてわかりました。
一人で解決できるとスッキリ！
明日も頑張ります。
typeエイリアスとinterfaceって何が違うの？

#結論
>typeエイリアス：なんでもイケる
interface：オブジェクトのみを扱う（強み）

interfaceで定義しておくと
オブジェクトなんだなって一発でわかるのが強みだそうです。


#typeエイリアス

```typescript
type Human = {
    name: string;
    age: number;
}
```


#interface

```typescript
interface Human {
    name: string;
    age: number;
}

const human:Human = {
   name: "Qiita",
   age: 38
}

let developer: Human;
```
Next.jsでbeforeunloadイベントを扱う

## 困っていたこと

Next.jsで管理画面などの実装をする際にはbeforeunload使いたいときありますよね〜
ただNext.jsの`<Link>`タグや`Router.push()`でページ遷移をしてもbeforeunloadイベントは発行されません。
（SPAではフルページリロードではなくView間でのみページ遷移を行っている為当たり前）

![スクリーンショット 2020-12-14 20.00.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371854/2d88490c-989d-a1ff-bb40-000a246ed79c.png)

参照： [Browser Back Button does not trigger window.onbeforeunload · Issue #2694 · vercel/next.js](https://github.com/vercel/next.js/issues/2694#issuecomment-344533432)

ここで地味に詰まっていた。。。

## 解決策

Next.jsの`<Link>`タグや`Router.push()`の代わりに、`<a>`タグやwindow.location.hrefを使う。
これが現状の解決策になりそうです。
（SPAとしてのページ遷移は諦める）

## ちなみに

実際に書くとこんな感じになります。

```jsx
import React, { useEffect } from 'react';
import { Button } from 'antd';

// 共通の関数をイベント登録、解除時に渡す必要あり
const showAlert = (event: any) => {
  event.preventDefault();
  event.returnValue = '';
};

type Props = {
  handleClick: (event: any) => void;
};

const Main: React.FC<Props> = () => {
  const handleRemoveClick = () =>
    // ページ離脱前の確認（イベント解除）
    window.removeEventListener('beforeunload', showAlert, false);

  const handleLinkBtnClick = () => {
    window.location.href = '/';
  };

  return (
    <>
      <Button type="primary" htmlType="submit" onClick={handleRemoveClick}>
        イベント解除
      </Button>
      <a href="/">リンク1</a>
      <Button type="primary" htmlType="submit" onClick={handleLinkBtnClick}>
        リンク2
      </Button>
    </>
  );
};

const Index = () => {
  useEffect(() => {
    // ページ離脱前の確認（イベント登録）
    if (window) window.addEventListener('beforeunload', showAlert, false);
  }, []);

  return (
    <>
      <h1>beforeUnload</h1>
      <Main handleClick={showAlert} />
    </>
  );
};

export default Index;

  return (
    <Button type="primary" htmlType="submit" onClick={handleClick}>
      イベント解除
    </Button>
  );
};

const Index = () => {
  useEffect(() => {
    // ページ離脱前の確認（イベント登録）
    if (window) window.addEventListener('beforeunload', showAlert, false);
  }, []);

  return (
    <>
      <h1>beforeUnload</h1>
      <Main handleClick={showAlert} />
    </>
  );
};

export default Index;

```

## 最後に

以上、「Next.jsでbeforeunloadイベントを扱う」でした。
Next.js有能だしとりあえずnext/routerや../link使っときゃいいっしょ〜的な甘い考えに潜む落とし穴でした。
これが最善の方法かはわかりませんが行き詰まった方はお試しください。
もっといい方法があればコメント待ってます！！
MacにTeX環境構築

# バージョンなど
- macOS Big Sur バージョン 11.0.1 MacBook Air (M1, 2020)
- tlmgr revision 57119 (2020-12-13 00:40:00 +0100)  
tlmgr using installation: /usr/local/texlive/2020basic  
TeX Live (https://tug.org/texlive) version 2020


# BasicTeX

MacにTeX(TeX Live)を入れるにはMacTeXかBasicTeXを使うことが推奨されている．
BasicTeXはMacTeXのサブセット．MacTeXはTeX Liveのfull distributionに対応する．
BasicTexは必要最小限なので今回はこっちを入れる．（後からいくらでも追加できる）

## インストール
TeX Wikiの[BasicTeX](https://texwiki.texjp.org/?BasicTeX)に書いてある通りにするだけ．

http://tug.org/mactex/morepackages.html
からBasicTeX.pkgをダウンロード，実行してインストール．

ターミナルでログインし直すと，自動的にPATHが通る．

--------
2022/03/08 追記
homebrewでインストールできるので新しく買ったMacではこっちを使った
``` zsh
$ brew install basictex
```
----------

20222/06/15
texliveが古くなってtlmgrがエラーを吐くので更新．brew upgradeでOKだった．
アップグレードしたらおそらく下記のtlmgr updateとかinstallを一から行う必要がある．

-----------
TeX Wikiに書いてある通り

- tlmgrを最新バージョンにアップデート
- デフォルトの用紙サイズをa4に
- collection-langjapaneseをインストールして日本語関係を入れる（platexなど）

``` zsh
$ sudo tlmgr update --self --all
$ sudo tlmgr paper a4
$ sudo tlmgr install collection-langjapanese
```

proxy環境下では，`~/.zshenv`などにプロキシの設定をした上で`sudo`した時に環境変数を引き継げるように`-E`オプションを忘れずにつける．

``` zsh
$ sudo -E tlmgr update --self --all
$ sudo -E tlmgr paper a4
$ sudo -E tlmgr install collection-langjapanese
```

tlmgrをアップデートするときに

```
/Library/TeX/texbin/tlmgr: only MacOSX is supported, not darwin 11.0  (from sw_vers -productVersion: 11.0.1)
```
と表示されたが，アップデートは成功．tlmgrのバージョンも最近のものになっている．
最近のものはmacOS Big Surに対応しているらしい．

```
$ tlmgr --version
tlmgr revision 57119 (2020-12-13 00:40:00 +0100)
tlmgr using installation: /usr/local/texlive/2020basic
TeX Live (https://tug.org/texlive) version 2020
```

2022/12/18
basic texにはlatexmkが入ってないので入れておく
``` zsh
sudo tlmgr install latexmk
```


------
2022/03/08
TeX WikiにLuaTeX-jaを使うならいくつかパッケージがさらに必要と書いてあったので
とりあえず下記も入れる

``` zsh
$ sudo tlmgr install collection-luatex
$ sudo tlmgr install collection-latexextra
```
---------

2022/06/15
物理系数式用パッケージとしてphysicsを入れる

``` zsh
$ sudo tlmgr install physics
```

# Ghostscript
LaTeXiTに必要なのでHomebrewからインストールする．
自分の環境では何かの時に既にインストールしていた．

```
$ brew install ghostscript
```



# LaTeXiT

[LaTeXiT](https://www.chachatelier.fr/latexit/latexit-home.php?lang=en)

TeXでGUI環境はあまり使わないが，数式の画像を作成できるLaTeXiTだけは使っているので上記リンクからダウンロードしてインストールする．

設定

- 書き出しフォーマットを`PDF with outlined fonts`に変更
- プログラムをlualatexに変更
- プリアンブルに下記を書いておく


``` latex
\documentclass[10pt]{article}
\usepackage[usenames]{color} %フォントカラー
\usepackage{amssymb} %数式記号
\usepackage{amsmath} %数式
\usepackage{physics}
\usepackage[utf8]{inputenc} %発音区別符アルファベットの直接入力
```


Arm版Homebrewの場合，gsとps2pdfが自動では見つからないのでプログラムのところで手動で設定する

`/opt/homebrew/bin/gs`
`/opt/homebrew/bin/ps2pdf`

# Skim

-------
2022/03/08 追記
SyncTex全然利用していないのでSkim入れるのをやめた．プレビュー.appを使っている
----------

[SyncTeX](https://texwiki.texjp.org/?SyncTeX)に対応のPDFビューワであるSkimもインストールしておく．Emacsと組み合わせて使う．

Homebrewからインストール可能．
Caskが使われるのでアプリケーションディレクトリにインストールされる．

```
$ brew install skim
```
nilなんてない！　なのに「fatal error: unexpectedly found nil while unwrapping an Optional value」

#なぜエラーなのかわからない。nilなし
研究室の限られた時間で爆速開発しなければいけない状況で、nilなんてないのに
エラー内容が
`fatal error: unexpectedly found nil while unwrapping an Optional value`です。

えーなんで??? nil使ってないし、強制アンラップしてないのになっているんだろうって思ったら
こんなところを見逃していた( ；∀；)
#解決法
もう一度Outletの紐付けをし直すのが一番手っ取り早いです。
紐付けの確認方法
⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩⇩
![スクリーンショット 2020-12-14 20.10.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684645/6de63bd9-b4af-e22b-fea5-9791857c96e3.png)
なんらかの理由により、Outletがうまく接続できていなかった場合に起こるエラーっぽいです。
![スクリーンショット 2020-12-14 20.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684645/9605a5da-7d8a-0a48-b937-1e7cf4ddff17.png)

これによりUIKitのLabel/Button/TextFieldなどのUIがないものと扱われて、
nilとエラー警告してくるのでしょう！

UIをOutletで紐付けする際に普通にしていれば、nilになることなんてないのです。

私の場合はこれで解決しました！誰かの役に立てれば幸いです。
zshとかvimとか常用しているdot fileの紹介


この記事は[MDCアドベントカレンダー](https://qiita.com/advent-calendar/2020/mdc)15日目の記事です

# 概要
仕事でもプライベートでも愛用している.zshrcとか.vimrcとかの設定値やプラグインを紹介します。
多分有名どころしか使っていない気がするのですが、自分への備忘録的な意味もこめてになります。


# .zshrc
* [Link](https://github.com/t-0-g/dotfiles/blob/master/.zshrc)
* 改めて見直してみると以外と独自の設定とかがなかったので、必須だと思うものを。

## ① PROMPT 


```
FACE='%(?.%F{cyan}%(!.#.)%f.%F{magenta}%(!.#.(ﾉд-｡%)))%f'
PROMPT='%F{cyan}%n:%F{white}[%F{cyan}%~%F{white}] %F{gray}%*#%! $FACE
$ '
```

カレントディレクトリ、時刻、Historyの番号を表示するようにしています。あと、コマンドを
間違えると画像のようにがっかり顔が出ます。
![スクリーンショット 2020-12-13 22.55.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269282/a7d3d06d-afc7-3f87-6bd1-af445f152188.png)
意味は特にないです。


## ② Gitのステータスとか出すやつ
[zshのプロンプトにgitのブランチ名とステータスを色で表示したい](https://otiai10.hatenablog.com/entry/2013/12/19/123015)

```
function branch-status-check {
  ・・・
　・・・
}
```

## ③Peco(+ghq)

インクリメンタルサーチができるようになるgo製のツールです。詳細は以下。
[ghqでリポジトリ管理とpeco連携で快適git生活](https://qiita.com/strsk/items/9151cef7e68f0746820d)
[pecoでzshのコマンド履歴検索を超快適にする！](https://qiita.com/shepabashi/items/f2bc2be37a31df49bca5)

ghqはGo言語のリポジトリ管理ツールですが、普通にGo以外のプロジェクトも管理できます。超便利。

```

function peco-history-selection() {
    BUFFER=`history -n 1 | tail -r  | awk '!a[$0]++' | peco`
    CURSOR=$#BUFFER
    zle reset-prompt
}

zle -N peco-history-selection
bindkey '^R' peco-history-selection

function peco-src () {
  local selected_dir=$(ghq list -p | peco --query "$LBUFFER")
  if [ -n "$selected_dir" ]; then
    BUFFER="cd ${selected_dir}"
    zle accept-line
  fi
  zle clear-screen
}
zle -N peco-src
bindkey '^]' peco-src

```

# .vimrc
* [Link](https://github.com/t-0-g/dotfiles/blob/master/.vimrc)

Vimの設定。
自分はタスク管理からメモから全部Vimでやってるので、常用しているプラグインを紹介します。
プラグインは[vim-plug](https://github.com/junegunn/vim-plug)で管理しています。

## Plugin

### ①winresizer
Vimのウィンドウのリサイズを簡単にできる
https://qiita.com/simeji/items/e78cc0cf046acc937226

### ②nerdtree
フォルダをツリー構造で出してくれる。
https://github.com/preservim/nerdtree

### ③memolist.vim
Vimでメモ管理ができる。これとprevimというマークダウンのプレビューを表示するプラグインを組み合わせて使っています。
https://blog.glidenote.com/blog/2012/03/26/memolist.vim/

### ④vim-commentary
コメントアウトが簡単にできる。

### ⑤vim-airline
ステータスバーとかをかっこよくしてくれる（画像のようになる
https://original-game.com/vim-airline/
<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269282/b5f4e97e-9d03-a497-bb9c-7b94e952c92f.png">

### ⑥vim-lsp
language server。ほかのIDEみたいに補完とか定義ジャンプができるようになる
https://qiita.com/kitagry/items/216c2cf0066ff046d200

### ⑦vim-gitgutter
vim上でリアルタイムにgitの差分をだしてくれる
https://wonderwall.hatenablog.com/entry/2016/03/26/211710
### ⑧vim-fugitive
git管理できる
https://doruby.jp/users/kurita/entries/fugitive-vim%E3%81%A7vim%E4%B8%8A%E3%81%A7git%E6%93%8D%E4%BD%9C%E3%82%92%E3%81%97%E3%82%88%E3%81%86%EF%BC%81

### ⑨vimwiki
vim上にwikiっぽいのを立てて管理できる。htmlに出力もできる
https://nanasi.jp/articles/vim/vimwiki/vimwiki_vim.html
Docker  + Composer + Laravel環境でPHPのバージョンを下げないといけなくなった

# 結論
```composer.json
"platform": 
{
    "php": "7.3" #したいversionを入れる 
}
```
を入れて ```composer update``` を実行

```Dockerfile
FROM php:7.3-fpm-buster
```
に書き換えて```docker-compose up -d```
すればOK

# 背景
もうすでに動かしていたLaravel環境のPHPを7.4から7.3に変更しないといけなくなった
composerでライブラリを管理しているけど、コンテナイメージを7.3にしただけだと動かない
こんな感じのエラー出る

```
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. It is recommended that you run `composer update` or `composer update <package name>`.
Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - This package requires php ^7.4.0 but your PHP version (7.3.24) does not satisfy that requirement.
```

# 詳細
## 環境
Docker

```DockerFile
FROM php:7.4-fpm-buster
//以下略
```

を

```DockerFile
FROM php:7.3-fpm-buster
//以下略
```

にして動かしたい

## 方法
### 1 composer.json追記
```composer.json
"platform": 
{
    "php": "7.3" #したいversionを入れる 
}
```
を入れて ```composer update``` を実行

~~~~~~~~~~~~ Composer先輩がいろいろやってくれるのを待つ ~~~~~~~~~~~~

### 2 dockerイメージを消す

```
docker-compose down --rmi all --volumes
```

をやる

### 3 DockerFile書き換え

```DockerFile
FROM php:7.4-fpm-buster
//以下略
```

を

```DockerFile
FROM php:7.3-fpm-buster
//以下略
```
書き換え

### 4 ビルド

```docker-compose up -d --build``` を実行
そうすると？

```
$ docker-compose exec php bash
$ hoge@fugafugab5318:/var/www/html# php -v
PHP 7.3.24 (cli) (built: Nov 18 2020 10:14:01) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.24, Copyright (c) 1998-2018 Zend Technologies 
```

以上
IBM Cloud Monitoring with Sysdig でWindowsを監視する 導入編

この記事は [IBM Cloud Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ibmcloud) の 17 日目の記事です。

https://qiita.com/y_tama/items/60def40b948fa2e11a79
がベースとなっていますが、OS再起動やサインアウトしてしまうとコマンドプロンプトが停止してしまい、データが送信できなくなります。

https://cloud.ibm.com/docs/Monitoring-with-Sysdig?topic=Monitoring-with-Sysdig-windows&locale=en
にwmi_exporterのダウンロードリンクが記載されています。
最新版をインストールしたいところですが、0.13.0 より、メトリックのプレフィックスが wmi_ から windows_ に変更になっています。

This is the last planned release with the wmi_exporter name, future releases will be named windows_exporter. See #499 and #519 for context.
This includes changing the metrics' name prefixes from wmi_ to windows_, meaning that all queries need to be changed to match the new names.
For example, windows_cpu_time_total replaces wmi_cpu_time_total.
(Deprecation noteより)

IBMCloud では プレフィックス wmi_ を想定しているようで、0.12.0までしかデータを取得することができませんでした。

https://github.com/prometheus-community/windows_exporter/releases/tag/v0.12.0
から msi 版をダウンロードします。

msi 版をダウンロードし、ダブルクリックして導入すればサービス登録され、OS起動時に wmi_exporterが起動します。
懸念点があるとするならば必要以上に情報収集をしていることです。
(レジストリをいじれば--collectors.enabledの値を指定できるかもしれない…)

promethues は以下よりダウンロードし、最新版(2020/12/14時点)でも問題なく動作しました。

https://prometheus.io/download/

promethues はインストーラ版がありません。
そのため、サービス登録することで自動起動対応不可です。

考えた結果、タスクスケジューラーを使うことにしました。

![タスクスケジューラ_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/d352b7b6-06c2-53a9-e9b5-7e8378f317b5.png)

![タスクスケジューラ_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/4631311f-f25b-7593-9788-4a0c818f91df.png)

![タスクスケジューラ_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/4a3ccaa7-5cac-9d49-f6a1-859f527e4603.png)

![タスクスケジューラ_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/f90a573c-320d-21ba-6038-1987713d60f6.png)

![タスクスケジューラ_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/217d4261-6d92-9a7b-3733-80d98f876463.png)

最初に紹介したqiitaの記事には、

Default Dashboards → Host & Containers → Windows Node Overview

となっていますが、現在は以下の画像の通り、DASHBOARD TEMPLATES に IBM が出現し、その中に Windows Node Overview があります。

![sysdig-dashboards.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77190/0f01854a-d00d-4c4d-659b-eb278439dfaa.png)

Windows のデータを IBMCloud に転送するところまではできました。
次は、取得したデータをどのようにして活用し、アラート通知するかをまとめたいと思います。
【SIGANTE】画像ラベリング（１０種類）　画像データの拡張（水増し）

# 全体の構成

###①データの下準備
https://qiita.com/hara_tatsu/items/a90173d33cb381648f72
###②画像データの拡張（水増し）
https://qiita.com/hara_tatsu/items/86ddf3c00a374e9ae796
###③転移学習
https://qiita.com/hara_tatsu/items/bc93fb61b7ccbc639eed

# 環境情報

Python 3.6.5
tensorflow 2.3.1

# 【SIGANTE】画像ラベリング（１０種類）について

画像データに対して、10種類のラベルの1つを割り当てるモデルを作成します。

学習データサンプル数：5000

以下リンク
https://signate.jp/competitions/133


# 画像データの拡張（水増し）

ここまでの処理は以下を参照（①データの下準備）
https://qiita.com/hara_tatsu/items/a90173d33cb381648f72

## ライブラリーのインポート

```python.py
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 画像処理
from PIL import Image

# tensorflow
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
```

## 画像データの拡張（水増し）

```python.py
# 画像の加工内容
image_gen = ImageDataGenerator(
              rotation_range=45, # 45°回転
              horizontal_flip = True # 水平移動
             )

#元となるデータ数を増やす
X_gen = image_gen.flow(X_train, Y_train, batch_size=32)

# 画像データを格納
X = []
# ラベルデータを格納
Y = []

for _ in range(10):
    #データ生成
    X_gen_new, y_gen_new = X_gen.__next__()
    #データを結合
    X_train = np.concatenate([X_train, X_gen_new])
    Y_train = np.concatenate([Y_train, y_gen_new])
    X.append(X_train)
    Y.append(Y_train)
    #データサイズを表示
    print(X_train.shape, Y_train.shape)
```



```
# データ数が2770まで増えた（batch_sizeを増やせばもっと増やせる）
(2482, 96, 96, 3) (2482, 10)
(2514, 96, 96, 3) (2514, 10)
(2546, 96, 96, 3) (2546, 10)
(2578, 96, 96, 3) (2578, 10)
(2610, 96, 96, 3) (2610, 10)
(2642, 96, 96, 3) (2642, 10)
(2674, 96, 96, 3) (2674, 10)
(2706, 96, 96, 3) (2706, 10)
(2738, 96, 96, 3) (2738, 10)
(2770, 96, 96, 3) (2770, 10)
```

## 教師データの決定

```python.py
X_train = X[-1]
Y_train = Y[-1]
print(X_train.shape, Y_train.shape)
```

```
# 教師データとして採用
(2770, 96, 96, 3) (2770, 10)
```


## 画像データの確認

```python.py
# 1行5列のグリッド形式で画像をプロットする関数。
def plotImages(images_arr):
    fig, axes = plt.subplots(1, 5, figsize=(20,20))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
        ax.axis('off')
    plt.tight_layout()
    plt.show()

# 教師データをまとめる
train_data_gen = image_gen.flow(X_train, Y_train, batch_size = 32, shuffle = False)
augmented_images = [train_data_gen[0][0][0] for i in range(5)]
# 表示
plotImages(augmented_images)
```

こんな感じ！！

![スクリーンショット 2020-12-14 19.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672827/0e6262d4-8a83-f89c-e941-e7df0a5ef5b3.png)


```python.py
# 検証データも教師データと同じ形へ変更
valid_gen = ImageDataGenerator()
valid_data_gen = valid_gen.flow(X_valid, Y_valid, batch_size = 32)
```


# おわりに

### 次回は転移学習！！
一時ファイルを作成して、圧縮して、なんらかの処理をして、削除する実装

Javaにおける一時ファイルの作成やzip圧縮の実装方法について調べたので、整理を目的として記事を書く。「なんらかの処理」は、どこかにアップロードするなどを想定していた。

```Sample.java
// 一時ファイルを作成
File tmpFile = File.createTempFile("tmpSqlFile", ".txt");
		
// データ書込み
writeDate(tmpFile);
		
// 圧縮
compress(tmpFile);
		
// なんらかの処理
		
// ファイル削除
deleteFile(tmpFile);
deleteFile(new File(getZipPath(tmpFile)));
```

`File.createTempFile("tmpSqlFile", ".txt")`ということで、SQLの記述されたテキストファイルを想定していた。

```Sample.java
private static void writeDate(File f) throws IOException {

	// FileWriterクラス作成
	FileWriter fw = new FileWriter(f);
		
	// 書込み
	getList().stream().forEach(s -> {		
		try {
			fw.write(s + ";\r\n");
		} catch (IOException e) {
			e.printStackTrace();
		}
	});
		
	// ファイルを閉じる
	fw.close();
}
```

```Sample.java
private static List<String> getList() {
		
	// データ準備
	List<String> arr = new ArrayList<>();
	arr.add("UPDATE uesrs SET name = 'newName1' WHERE id = 0001;");
	arr.add("UPDATE uesrs SET name = 'newName2' WHERE id = 0002;");

	Map<String, List<String>> map = new HashMap<>();
	map.put("users", arr);
		
	// SQL抽出
	List<String> sqlList = new ArrayList<>();
		
	map.values().stream().forEach(a -> {
		a.stream().forEach(sql -> sqlList.add(sql));
	});
		
	return sqlList;	
}
```

テーブル名をキーとし、値がそのテーブルのUPDATE文のリストであるようなMapがデータとして生成されている、というパターンを考えていた。上記は1テーブルに対してだけど、複数テーブルも考慮して`forEach`がネストされた実装となっている。

```Sample.java
private static void compress(File f) throws IOException {
		
	ZipOutputStream zos = 
			new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(getZipPath(f))));
	ZipEntry entry = new ZipEntry(f.getName());
	zos.putNextEntry(entry);
	InputStream is = new BufferedInputStream(new FileInputStream(f));
		
	int len = 0;
	byte[] buf = new byte[1024];
	while ((len = is.read(buf)) != -1) {
		zos.write(buf, 0, len);
	}
		
	zos.close();
	is.close();
}
```
引数の`File`オブジェクトをzip圧縮するのみ（複数ファイルをzip圧縮するわけではない）。

```Sample.java
private static String getZipPath(File f) {
	return f.getParent() + "\\hoge.zip"; 
}
```
一時ファイルを作成した同階層にzipファイルも生成する。

```Sample.java
private static void deleteFile(File f) {
	if (f != null && f.exists()) {
		f.delete();
	}
}
```

---


上述した実装を参考にして実装する場面があって、再度見直すと改善点もありそう。そもそもの一時ファイルを作成する必要性などについては、また考えられたら。
Mac OS (zsh) で awscli の補完機能を使いたい

# AWS CLI インストール手順
## 1. Homebrew で awscli インストール
```zsh:
% brew install awscli
(----省略----)
zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions
#^^^^^ここに補完機能のパスが表示される^^^^^^
% aws --version
aws-cli/2.1.10 Python/3.9.1 Darwin/20.1.0 source/x86_64 prompt/off
```

## 2.補完機能を有効にする
### 2.1 .zshenv を編集する

```zsh:
% echo "autoload -Uz compinit && compinit -u" >> .zshenv
``` 

### 2.2 .zshrc を編集する

```zsh:
%  echo "source /usr/local/share/zsh/site-functions/aws_zsh_completer.sh" >> .zshrc
``` 

## 3.補完機能を確認する

```zsh:
 % aws ec2 （ここでtabを押す） 
zsh: do you wish to see all 436 possibilities (436 lines)? 

```

よし。でけた。

# 参考文献

 - [macでzshでzsh compinit: insecure directoriesの警告が出る問題](https://qiita.com/ayihis@github/items/88f627b2566d6341a741)
 - [Cygwin 上の zsh compinit の insecure directories 警告を抑止する](https://qiita.com/taskie/items/9e265df3781bcb791b07)
 - [https://michimani.net/post/aws-cli-command-completion-at-zsh/](https://michimani.net/post/aws-cli-command-completion-at-zsh/)
OCSP ステープリングでエラーが発生した話

# はじめに
とある作業で動作確認を実施中、Nginx のアクセスログを確認していたら次のようなエラーログがたくさん出力されていました。

```
YYYY/MM/DD hh:mm:ss [error] 9662#9662: ocsp.digicert.com could not be resolved (110: Operation timed out) while requesting certificate status, responder: ocsp.digicert.com, certificate: "/etc/pki/tls/certs/cert_combine.pem"
・・・
```

`ocsp.digicert.com` にアクセスできずにタイムアウト起こしているようです。

# そもそも何をしようとしていたのか？
そもそも `ocsp.digicert.com` にアクセスしようとしていたのは、 OCSP(Online Certificate Status Protocol) ステープリングという機能を使って、サーバーにインストールされている証明書が有効であるということを認証局のOCSPレスポンダーに問い合わせていたためです。OCSP ステープリングの詳細はここでは割愛します。Qiita の記事 [OCSP Stapingの調査](https://qiita.com/thetsuthetsu/items/ddbed701c08bd4711cad) あたりを確認いただくとよいと思います。

# なぜタイムアウト？
エラーログの内容、事象は理解できました。
OCSP レスポンダーへの問い合わせは、 HTTP プロトコルを使ってやりとりが行われるため、サーバーから`ocsp.digicert.com`への HTTP の通信が通っていない可能性を考えました。
この旨ネットワーク担当者に確認したところ、サーバーからインターネット外部への方向のすべてのHTTP通信は全開放しているとのことで、ちょっと理解できませんでした。
サーバー側の設定とかを確認しても特に問題は見当たりません。

念のため、OCSP レスポンダーへ手動で通信が通るか確認してみました。

```
$ curl -V ocsp.digicert.com/ping.html
* About to connect() to ocsp.digicert.com port 80 (#0)
*   Trying xxx.xxx.xxx.xxx...
* Connected to ocsp.digicert.com (xxx.xxx.xxx.xxx) port 80 (#0)
> GET /ping.html HTTP/1.1
> User-Agent: curl/7.29.0
> Host: ocsp.digicert.com
> Accept: */*
> 
* Recv failure: 接続が相手からリセットされました
* Closing connection 0
curl: (56) Recv failure: 接続が相手からリセットされました
```

タイムアウトというより接続が切れてしまっています。

tcpdump でパケットキャプチャしてみたところ、エラーになるパケットの TTL が 1 しか減っていなかったので、そもそも最後までパケットが到達せず、デフォルトゲートウェイ先となっている機器で通信をはじいている事象が確認できました。この機器はファイアウォールであることが分かったため、改めてネットワーク担当者にファイアウォールの設定確認をお願いしました。

# 解決！
少し時間がかかりましたが、解決しました。
原因としては「ファイアウォールで、サーバーからインターネット外部へのOCSPプロトコルの通信が遮断されていた」というものでした。
OCSP 自体は HTTP プロトコルで通信するのですが、この中で OCSP プロトコルのメッセージがやりとりされており、このメッセージの内容をファイアウォールで解析して接続をリセットしていたようです。
ファイアウォールにてこのプロトコルが通過できるようにホワイトリストを追加してもらい、無事このエラーは解消しました。

# あとがき
Web サービスを構築する際には、HTTP/HTTPS の疎通はもちろん、OCSP の観点でも疎通が大丈夫か確認をしておくとよいことがわかりました。
ネットワークの疎通がうまくいっていないときは、レイヤ 3 の通信だけではなく、さらに上のレイヤの通信の観点でも確認してみると解決できることがあるかもしれません。
改めて OSI 参照モデルへの理解が深まりました。
FPGA（Altera DE0）を使ってみた。

　外出できないのでFPGAに触ってみた。基本的には下記の書籍に沿って行えばいいのだがハマる部分があるのでそこを中心に解説します。

今回は使用した環境は以下の通り。

・PC(windows10、メモリ12GB)
・FPGA（Altera DE0）スターターキット
・超入門！FPGAスタータ・キットDE0で始めるVerilog HDL（そこそこの値段するから図書館に購入してもらった。）
https://shop.cqpub.co.jp/hanbai/books/31/31371.html

　まずは環境構築。スターターキットのCDを使って本に書いてある通りにソフトウェアのインストール。インストーラーを起動するだけでもそこそこ時間がかかったし、応答なしとかになるので保存する書類とかがある人はこの作業を始める前に保存すること。また、CDにインストールされてるソフトウェアのバージョンは最新ではないので最新のバージョンを使いたかったら下記のリンクを参照してください。僕はCDに入ってるやつでやりました。

　２つのソフトウェアのインストールが終わったらドライバのインストール。多分ここで多くの方が躓くと思います。なぜならこの書籍がwindowsXPを想定して書かれていて、windows10だと同じようにいかないのです。

ここに僕が行った手順を載せておきます。

１．下記のリンクからファイルをダウンロードし解凍する。
http://www.terasic.com.tw/wiki/File:Usb_blaster_q16.1.zip

２．下記のリンクの「操作方法」1~6までやる。その後7の過程でドライバーソフトウェアを参照させるフォルダを訪ねられたら先ほど解凍したファイルを参照先にする。
https://www.macnica.co.jp/business/semiconductor/articles/intel/130529/

３．デバイスマネージャーで認識できているか確認する。
ここまでできれば後はCDに入っているDE0のファイルのControl Panelで動作確認できればおしまい。あとは本に沿って行うだけ。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873754/e3424b1a-27a5-078d-8141-86b04a8ca853.png)
 図1.Control Panelから操作した様子
　
感想としては2万円前後でこれぐらいのことできれば学習用には十分だと思います。ただ、FPGAの型が少し古いので新しい型が載っているボードが使いたい人はDE10とか使うといいと思います。
Docker,Laravel,node環境下でnpm run buildがやたら遅くなったら

Laravel: 6.18.3
laravel-mix: 4.1.4
node 12.17.0
npm 6.14.4


LaravelMixを4.0から4.1にバージョンアップしたことが原因らしいです。


以下、対策。

* 共有フォルダを使用できなくする。
* LaravelMixを4.0にダウングレード。
* ホストマシンからビルド
 →ビルドする際は一度node_modulesを削除し、ローカルからnpm installしなおす必要があるかも？
* scssファイルでurl()を使っている箇所を相対パスではなく絶対パスで記載する。

* webpack.mix.jsに.options({ processCssUrls: false });を追記。

```webpack.js
const mix = require('laravel-mix');
require('laravel-mix-polyfill');

mix.~~~
   // 下記を追加する。
   .options({ processCssUrls: false });
```
ディレクトリのパーミッションを触ってみた

## 前書き
この記事は、MicroAd Advent Calendar 2020の15日目の記事です。
linuxを利用する上で避けては通れないパーミッションですが、ファイルのみしか管理せず、ディレクトリのパーミッションを意識せずに利用していたので勉強がてらまとめてみたいと思います

## 環境
Mac 10.15.7

## ビットと権限
| ビット |権限| 
|:--|--:|
|r|ファイル一覧を表示できる| 
|w|ファイル作成・削除などの操作ができる| 
|x|ディレクトリに移動とファイルアクセスが可能|

このような対応になっています。

なのでxだけ与えるとlsなどは叩けないのに実行やファイルの操作が可能な少し珍しい状態になります。
しかし思うように行かないのがunix.....

## 注意点

### 上位ディレクトリの実行権限
上位のディレクトリから実行権限を取り除くとその下層にあるディレクトリにもアクセスできなくなります、影響範囲に注意です

#### ファイル作成
touchコマンドは`w`だけではなく`wx`がないと上手く動いてくれないようです(実装系の問題・・・？)

```
❯ ll
total 0
drwx----w-  3 root  wheel    96B 12 11 18:13 test2/
❯ touch test2/hoge
touch: test2/hoge: Permission denied

❯ ll
total 0
drwx----wx  3 root  wheel    96B 12 11 18:13 test2/
❯ touch test2/hoge
# Permission deniedされていない
```

## まとめ
フォルダを触らせたくない場合以外は実行権限は参照まで影響する可能性が高いので付与しておいたほうがいいかもしれません。
また、逆にファイル名を悟らせたくない、変なファイルを仕組ませたくないなどの場合は`rx`権限を上手く活用すれば第三者からの攻撃を防ぐなどの活用もできそうです。
【FileMaker】iOSショートカットアプリからFileMaker Goアプリを開くときの注意点

ちょっと前に、[【FileMaker】ショートカットからFileMaker Goのファイルを開くときの設定](https://qiita.com/tyuma/items/4ed2338956ef7307aa39)という記事を書きました。
この記事の補足になります。

# スクリプト名に空白を含めるな
です。
FileMakerのスクリプト名は空白を含めた名前を付けられますが、iOSショートカットアプリではうまく動きません。

例えば、スクリプトをコピーしたまま使用している現場、ありませんか？
![IMG_3445.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/e06ff298-33cc-d661-b8e8-316ce852d459.png)

↓ショートカットで空白のあるスクリプト名を指定しても、、、
![IMG_3446.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/f1bc0ced-6074-eb0f-6b9b-bf25dd3a5bdc.png)

↓「ない」って言われます。
![IMG_3447.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/af361dea-3c17-b75e-75cd-c3f7eb8c8e17.png)

「普通、スクリプト名をコピーしたまま使うかな！？」と思うでしょ？
結構ありますから〜

現場からは以上です。
未経験から始めるVue.jsロードマップ

HTML,CSS,JavaScriptはすこし書けるようになってきたな〜
何かフレームワーク触ってみたいなとお考えの方にVue.jsをおすすめさせていただきます。
Vue.jsは他のフレームワークと比較して学習コストが低いとされています。
本記事では私がVue.js（Ver2.x）を学習し始めてから小中規模のアプリケーションを実装するようになるまでどのように学習してきたのかまとめました。
これから勉強したいなと言う方の助けに少しでもなればなと思います。

## STEP1　Vue.jsとは？
Vue.jsとは、webアプリケーションのUIを構築するためのJavaScriptフレームワークです。2014年にVer.1が登場し２０１６年に登場したVer.2で飛躍的にパフォーマンスが向上したことから人気が急上昇しました。

#### フレームワークって？
端的に言うとアプリケーション開発をより効率的にするための枠組みです。各フレームワークには独自のルール（ディレクトリ構成など）があり、その通りに実装を行うと、これまで開発者が記述していたコードを書くことなく、効率的な開発ができます。

【参考資料】
[Vue.jsのツボとコツがゼッタイにわかる本](https://www.shuwasystem.co.jp/book/9784798056494.html)

## STEP2　基本的な機能の把握とコーディング
以下で紹介するように、いずれかの方法で環境構築をしていただき、手を動かしながら学習していきます。

【手っ取り早く環境構築】
->[Codesandbox](https://codesandbox.io/s/inspiring-wave-ofoef)
【しっかり自分のローカル環境でやりたい人】
->[NPM](https://jp.vuejs.org/v2/guide/installation.html#NPM)
->[より早く構築したい方はCLI](https://cli.vuejs.org/guide/)


環境構築ができたところで、Vue.jsにはどんな機能があるのか把握していきましょう。

#### 主な機能例

- テンプレート構文
    - HTMLとよく似た構文でDOMのテンプレートを定義する機能
- データバインディング
    - アプリケーションのデータとDOMを結びつける機能
- リストレンダリング:v-for
    - 複数のデータに基づいてDOMを繰り返し描画する機能
- 条件付きレンダリング:v-if/v-show
    - データの状態の応じて表示・非表示を切り替える機能

Vue.jsはコンポーネント指向と言うものであり、Webアプリケーションを上記のような機能を使用して定義された、コンポーネントの集合体として構成します。コンポーネント化することのメリットについて深くは触れませんが、設計・開発・テストをコンポーネント単位で行えることや、構造や見た目、動作で共通管理することができます。

-> [【Vue.js】コンポーネントとは何か？](https://b1tblog.com/2019/10/30/vue-components/)

#### コンポーネントが持てるプロパティ例

- data：保持するデータを定義
- methods：保持するメソッドを定義
- filter：フィルターを定義
- computed：算出プロパティを定義
- watch：ウォッチャ、監視メソッドを定義

この他にもprops等のプロパティがありますが、アプリケーションの構築にあたり必要になった場面で学習すると良いかと思います。

【参考資料】
[基礎から学ぶ Vue.js](https://cr-vue.mio3io.com/)
[Vue JS入門決定版！jQuery を使わない Web 開発 - 導入からアプリケーション開発まで体系的に動画で学ぶ](https://www.udemy.com/share/101YM0CUcac11aQXo=/)

## STEP3 VueRouter、Vuexを使ってみる
#### VueRouter
VueRouterはVue.js公式のルータで、一般的にVue.jsでSPA（シングルページアプリケーション）を構築する際に使用されます。

【参考資料】
[VueRouter公式](https://router.vuejs.org/ja/)　（まずはこちらを読みましょう！）
[今さら聞けない？Vue Router](https://qiita.com/hshota28/items/765cf903f055754f7557)　（非常に参考にさせていただいた記事）

#### Vuex 
Vue.jsではコンポーネント間でデータのやりとりをする際にpropsや$emit()を使用することができますが、この方法はいわゆるバケツリレー方式です。コンポーネントの階層が深くなればなるほどそのやりとりは複雑になってしまいます。
Vuexではこういった複雑なデータの受け渡しを解決できる**”状態管理パターン + ライブラリ”**です。
Vuexに関しては公式ドキュメントが非常にわかりやすかったので熟読すると良いかと思います。
【参考資料】
[Vuex とは何か？](https://vuex.vuejs.org/ja/)

## STEP4 簡単なアプリケーションをつくってみよう
ここまで学習したあなたはもうVueRouter,Vuexを使用した小中規模のSPAの構築はできるはずです。
さらにFirebase等を使ってサーバの構築をせずにDBの機能を使用することでより実践的なアプリケーションの実装をしてみたり…

【参考資料】
[Vuexの基本をTodoリストを作って学びましょう](https://b1tblog.com/2019/12/22/vue-vuex/)
[超Vue.js 2 完全パック - もう他の教材は買わなくてOK！ (Vue Router, Vuex含む)](https://www.udemy.com/share/101rYoCUcac11aQXo=/)
[Vue.js + Firebaseで作るシングルページアプリケーション](https://www.udemy.com/share/1021GSCUcac11aQXo=/)

## 最後に
本記事をみて一通り書けるようになってきたなーと感じていただけたら嬉しいです。
僕もエンジニアになって３ヶ月がたった頃にVue.jsを使ったアプリケーションの開発に携わらせていただきました。その時はVue？美味しいの？状態で本当に何もわからなかったのですが、公式のドキュメントを読み漁ったり、Udemyを活用したり、Qiitaの記事をたくさん読みました。
Vueは比較的環境構築も容易かと思いますし、参考文献も豊富なのでぜひ良い学習を！！！
そして本記事ではVue2.xの学習を主に紹介してますが、今年リリースされたVue.3についても今後勉強したことを発信できればと思います。
Python3.9のvenv環境でJupyter Labのセットアップ

# はじめに
- セットアップ周りをいつも忘れるのでメモを晒します。

# 環境
- MacOSX
- Pythonインストールはpyenvを使用
- Python 3.9.0
- nodejsは入っている(extension導入に必要）

# インストール

venv環境の作成

```bash
$ mkdir jupyterlab-sample
$ ce jupyterlab-sample
$ python3 --version
Python 3.9.0
$ python3 -m venv .venv
```

本体のpip install

```bash
$ .venv/bin/pip3 install jupyterlab
$ .venv/bin/jupyter-lab --version
2.2.9
```

起動

```bash
.venv/bin/jupyter-lab
```

v こんな感じで起動する

![スクリーンショット 2020-12-14 18.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147174/c47b3cfd-8679-1fdd-4103-a9b03073fe80.png)

# パッケージの追加

venvのpipを使ってinstallすればOK

```bash
$ .venv/bin/pip3 install numpy
$ .venv/bin/pip3 install matplotlib
```

# ダークテーマにする

中二なんで...

![スクリーンショット 2020-12-14 19.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147174/d3da3c0a-0810-d4a8-410a-bec29c34ec13.png)

# vim風キーバインド

![スクリーンショット 2020-12-14 19.21.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147174/7567aadf-85d0-8920-9bf5-2a7dbf97385e.png)

# tab表現
spaces: 2

![スクリーンショット 2021-05-25 17.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147174/1346ad28-fef2-2409-c329-4a8894d4952f.png)


# matplotlib 設定

`matplotlibrc` のよくやる設定。
現在使っている `matplotlibrc` のpathは以下のメソッドで確認できる。

```python
from matplotlib import matplotlib_fname
matplotlib_fname()
```

^ で表示されるのばビルドインされた設定で、ワーキングディレクトリに個別の `matplotlibrc` を配置することで、設定を上書きされることが可能。

## 日本語表示させる

普通につかうと日本語が豆腐になるので、Macのttcフォントファイルを指定する。
以下のように元の `font.sans-serif` に `Hiragino Maru Gothic Pro` をprefixに追加している。

```text:matplotlibrc
font.sans-serif: Hiragino Maru Gothic Pro, DejaVu Sans, Bitstream Vera Sans, Computer Modern Sans Serif, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif
```

# matplotlibをかっこいいグラフにしたい

seabornをつかいましょう。
https://github.com/mwaskom/seaborn

インストール

```bash
.venv/bin/pip3 install seaborn
```

importすれば使える

```python
import seaborn as sns
```

テーマとフォントを好きなものに設定

```python
seaborn.set_style("dark")
sns.set(font='Hiragino Maru Gothic Pro')
```

※ （2020年12月現在） 困ったことに、  `matplotlibrc` で 日本語フォントを指定したのに、 seaborn はハードコードされているらしく、個別にフォント指定してあげないと日本語がただしく表示されない...。

# jupyterlab-lsp（コード補完）の導入 (2020.02.24 追記)

v これを使えるようにする
https://github.com/krassowski/jupyterlab-lsp


インストール

language-serverとjupyter-lspを導入


```bash
.venv/bin/pip install "python-language-server[all]"
.venv/bin/pip install jupyter-lsp
```

labextension の導入

```bash
.venv/bin/jupyter labextension install @krassowski/jupyterlab-lsp
```

以上をinstallして起動したところ、自分の環境だとなんの設定もせずにlspが動いた

![スクリーンショット 2021-02-24 1.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147174/df0edc65-dd4a-251c-4ca3-1fcc37d24ddd.png)
アクセシビリティを考慮せずに checkbox をカスタマイズしていた話

## はじめに
ハジメマシテ。qiita 初投稿です。
(どうか温かい目で)宜しくお願い致します。

内容について迷いましたが、
サイト制作をしてきて「これはやってしまっていた！」となった出来事がありましたので、
恥ずかしさを堪え共有します。
※ すでに社内共有済みの件なのですが、備忘も兼ねて記載させていただきます。

## アコーディオンの制作方法
皆様はアコーディオンなパーツはどのように制作をされていますか。
自分はといえば、最初は div 要素と JavaScript を使用し、
クリック時にクラス追加をすることによって実装しておりましたが、
某サイトの記事を読み、JavaScript を使用しない方法を知り、
半年 ~ 10 ヶ月?程度、HTML 及び CSS のみで実装していました。

## JavaScript 不使用のアコーディオン
### 実装例
以下が実装例です。
<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="pon_uchi_pon" data-slug-hash="NWRdOPe" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="accordion menu (useless)">
  <span>See the Pen <a href="https://codepen.io/pon_uchi_pon/pen/NWRdOPe">
accordion menu (useless)</a> by h.u (<a href="https://codepen.io/pon_uchi_pon">@pon_uchi_pon</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script></script>

### 実装方法
実装方法としては、上記の CodePen を確認いただければと思いますが、
input 要素の checkbox 型を使用して作成します。

以下、ざっくりとした実装方法です。

- checkbox を `display: none`
+ label 要素をクリック後、 checkbox に擬似クラス `:checked` が付与されるので、  
それ自身とその隣接クラスを装飾

### 問題発生
しかし、ある時この方法で制作している際に、ふと TAB キーを押下したところ、
なんということでしょう。
キーボードからの操作が全く効かないことが判明しました。

既にお気付きかと思いますが、
**checkbox を `display: none` にした時点で
check を入れる動作どころか、フォーカスでさえも、
キーボードからの操作が効かなくなってしまった** のです。
( tabindex だとフォーカスまではできるようになりますが、チェックができません。)

## アクセシビリティを考慮したアコーディオン
### 解決方法
では、どうすればよいのかと調べたところ、
全く同じことを考えられている記事がありました。

[アクセシビリティで気をつけるchecbox,radioのCSS](https://qiita.com/Garyuten/items/b87b7d91279c0bded576)

実際の解決方法については、上記のサイトをご確認いただければと思いますが、

- `appearance`
- `opacity`
- フォーカスされた checkbox の隣接要素に `box-shadow`

上記のプロパティを使用して問題の解消をされております。

### 実装例
以下、実装例です。
Tab キーにてフォーカスの移動、スペースにてアコーディオンの開閉が可能となっております。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="pon_uchi_pon" data-slug-hash="LYRxaoK" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="accordion menu (nice)">
  <span>See the Pen <a href="https://codepen.io/pon_uchi_pon/pen/LYRxaoK">
  accordion menu (nice)</a> by h.u (<a href="https://codepen.io/pon_uchi_pon">@pon_uchi_pon</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script></script>

これで一旦はアクセシビリティの問題は改善されたかたちとなりました。
一安心です。

## まとめ
良さそうなコードを見たからと言って、それをそのまま使うのではなく、
**「何か問題がないか、常に意識をしていくことを忘れないようにしよう」**
というのが今回の教訓です。

よって、この記事の内容もまた後ほど更に精査して、
問題や改善点が無いか確認すべきですね。

貴重な時間を割き、お読み下さいましてありがとうございました。

## 参考文献
以下、有益な情報をありがとうございました。

- [アクセシビリティで気をつけるchecbox,radioのCSS](https://qiita.com/Garyuten/items/b87b7d91279c0bded576)
- [アクセシビリティを考慮した、チェックボックスとラジオボタンのCSSのサンプル](https://webbingstudio.com/weblog/entry-881.html)
エンジニア提案をしよう

# はじめに

エンジニアとしてシステムを通してユーザーに価値を届けたいという思いはありつつ、具体的にどのようなサービスを開発すべきかについて、企画者に対して意見を言うことの難しさを思い悩むことがあります。企画者は日々データや数値に向き合っていて、分析や企画内容の検討に時間をかけているのだから、そこに対して意見を挟む余地がないように感じてしまいます。

一方で、企画者としてはエンジニアだからこそ知っていることを活かして意見を言って欲しいという話を聞くこともあります。

エンジニアとしての思いと企画者からの期待に応えるために個人的に考えてきたことをまとめます。
実際のところ、提案を実現することはまた別の話で、地道な努力が必要かつタイミングもあります。ただ、少しでもエンジニアとしてユーザーに価値を届けたいという気持ちの参考になればと思っています。

# SIerにおける提案

SIerでエンジニアとして働いていて、顧客を通してユーザーに価値を届けることにもどかしさを感じてる人は多いと思います。自分が開発するシステムは本当にユーザーに価値を届けることができるのか疑問に思うことがあります。

私がSIerで働いていたとき、いくつか顧客へのシステム提案に関わる機会があり、その中で顧客にとってまったく新しいサービスないし事業内容を含んだシステム提案を経験しました。もちろん、かなり稀な事例で、営業の顧客との関係づくりがあってこそだと思いますが、そのようなことは可能ではあると実感しました。

情報処理技術者試験でITストラテジスト試験があり、この試験内容は上記のシステム提案のイメージに近いです。営業の人がサービスないし事業内容を含んだシステム提案をする環境を作ってくれることがあり、エンジニアとして意見を言える状況があったとき、ITストラテジスト試験の内容を参考にすることができると思っています。

ITストラテジスト試験では、顧客企業の競合優位性の確保など経営課題を定義し、その経営課題に対してITを活用したビジネスモデルを考え、そのビジネスモデルがユーザーにどのような価値を届けることによって事業として成り立つのかを考える観点を学ぶことができます。

大抵は顧客が持つインフラ（人/モノ）にIoT機器を組み込むことで情報を集約して、その情報をもとにユーザーへ付加価値を提供する内容ですが、過去の試験問題には様々な業界のビジネスモデルの話があって、事例に即した形で参考にできます。

# 技術を活用した提案
Webやネイティブアプリでできることは日々増えています。エンジニアとして最新情報をキャッチアップする中で、この技術をあのサービスで活かせればおもしろいことができると考えることはあります。その考えこそが企画者がエンジニアに求める意見だと思っています。

個人的に経験したWebの例で言えば、AMPページでAMPコンポーネントを使うことでUI/UXを元ページに近づける提案をしました。

AMPではJavaScriptが使用できず、CSSの容量にも制限があるので、リッチなコンテンツ表現には限界があるという思い込みがありました。そのため、カルーセル表示したいコンテンツについて、例えば5件あるうち、ファーストビューに表示できる2件のみ固定表示している状態でした。

AMP Conference 2019に参加する機会があり、そこでAMPページにおけるUI/UXは強力なデフォルトであるAMPコンポーネントがいい感じにする思想であることを知りました。AMPコンポーネントをいろいろ調べた結果、amp-carouselにたどり着いて、AMPページでも表示したい件数のすべてをスクロール表示できるUI/UXを実現することができました。

AMP Conference 2019：https://amp.dev/ja/events/amp-conf-2019/
AMPコンポーネント：https://amp.dev/ja/documentation/components/

# UI/UXの提案
Webサイトのページ遷移をスムーズにするために、SPA（Single Page Application）化を検討することはよくあると思います。その際に再描画する必要があるコンテンツと必要がないコンテンツがあることに気づきます。
例えば、グローバルヘッダーはどのページでも共通のコンテンツなので、ページ遷移のたびに再描画する必要がなく、再描画しないことによってページ遷移に伴う描画速度を抑える効果を期待します。そのようにコンテンツを整理につけても、本当にページ遷移によってグローバルヘッダーを常に表示すべきかということを課題に感じます。

大抵のサイトは、コンテンツが階層構造になっています。

```
ーーーーーーーーーー
グローバルヘッダー
ーーーーーーーーーー
メインコンテンツ
ーーーーーーーーーー
サブコンテンツ
ーーーーーーーーーー
```

ページを遷移すればするほど、ヘッダー要素が積み重なっていってしまい、スマートフォンの限られた画面領域では本来ユーザーに見て欲しいコンテンツをさしおいて、ヘッダー要素が目立ってしまう状態もあり得ます。そこでいろいろなサイトを見ていく中で、AppleのUI/UXが自分の中でしっくりきました。

Appleのサイトは下記の構成になっています。iPhoneなど製品ページに遷移すると、Appleロゴが上に隠れて、iPhoneなど製品名がグローバルヘッダー領域に表示される形になっています。そして、一番上にスクロールするとAppleロゴが出てきます。

```
ーーーーーーーーーー
Appleロゴ
ーーーーーーーーーー
iPhoneなど製品
ーーーーーーーーーー
概要/仕様
ーーーーーーーーーー
```

ネイティブアプリのページであれば、わざわざAppleのロゴを出す必要はないと思います。ただ、Webサイトを考えたときに何のサイトを見ているかの情報をなくすことはできないので、その解決策としてスクロールしない限りは上に隠れるという考え方であると感じました。すごく細かい点ではありますが、そのときユーザーに見せたい情報とWebサイトとして出すべき情報の両立について非常に参考になりました。

# おわりに

ユーザーに価値を届けたい気持ちを行動にする観点として、他にも一人のユーザーとして考えることや、やりたいことについて全体のストーリーが描けるかチェックすることなどがあります。サービスに関わるみんながユーザーに価値を届けることに対して、自分のできることを最大限考えて貢献することを目指していきたいです。

実際のところ、ユーザーの使い勝手だけでなく、事業のこと、ステークホルダーのこと、今の技術環境など目の前の提案や意見以上に考慮すべきことはたくさんあり、実現についてはさらに努力が必要です。その実際を踏まえた上でバランスよく貢献していきたいところです。

明日は、@an_sony さんの「Set#include?がなぜ速いのかを理解する」です。お楽しみに！！
かまってちゃんな彼女をLINEで身近に感じれるようにしてみた

##はじめに
先日トレンドに上がっていた@yuriacatsさんの「[かまってちゃんな彼女をPythonで作った話](https://qiita.com/yuriacats/items/bce25ff4cb7343ae0c7b)」が目に入りました。私は予定とLINEを確認し、@yuriacatsさんと同じく「かまってちゃんな彼女」を作る事を決意した。
##アカウント作成
この「かまってちゃん彼女」はLINE Messaging APIを使用します。
利用するにあたっては[LINE Developers](https://developers.line.biz/ja/)のアカウント作成してください。
##コンソールに入る
アカウント作成後、コンソールに入り「プロバイダー」を選択します。

![スクリーンショット 2020-12-14 14.18.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/343744ee-cf2f-0898-faef-7d2b53f1665e.png)

選択後、プロバイダーを作成します。ここではプロバイダー名は「かまってちゃん」にしました。

![スクリーンショット 2020-12-14 14.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/0e75e4e1-6263-e8b6-4603-2e6e91267488.png)
プロバイダを作成後、チャンネル設定画面になるので「Messaging API」を選択。

![スクリーンショット 2020-12-14 14.20.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/e3c5c2ed-bde4-8fb3-3eb0-ab2897fab555.png)
##チャンネルの設定
「Messaging API」を選択後、チャンネルの設定画面に行くので、チャンネルの種類は「Messaging API」プロバイダは先ほど設定した物を選択してください。
ここで重要なのは**チャンネルアイコン**と**チャンネル名**です。
女の子っぽいアイコンと名前にしましょう。
アイコンは[GIRLYDROP](https://girlydrop.com/)と言う、女子なフリー素材が手に入るサイトを利用しました。
名前に関しては今時の名前が出てこなかったので、とりあえず、アニメ「Charlotte」のキャラクター「友利奈緒」の「奈緒」にしました。
**私が友利奈緒だ。**
![スクリーンショット 2020-12-14 14.28.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/e024d929-ccad-53e5-ef99-7a5a3e04fa08.png)
##いざメッセージ配信
チャンネルの設定が終わるとチャンネル基本設定画面に行くので、まず「Messaging API設定」へ行き、QRコードまたはIDから友達追加をしましょう。次に、下にスクロールすると「あいさつメッセージ」との項目があるので無効化してください。これを無効化しないと追加した際、Botらしく挨拶メッセージが飛んでくるので、彼女っぽくありません。
![スクリーンショット 2020-12-14 16.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/6818bb5f-964c-bfc0-e25f-62f4ef73aa9e.png)
また「チャンネル基本設定」画面に戻り、基本情報の「LINE Official Account Manager」をクリック。
Official Account Managerのホーム画面に行くので、「メッセージ配信」を選択。
![スクリーンショット 2020-12-14 14.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/014eaf0b-9a2b-1580-4a46-61ed700de64f.png)
ここではメッセージ配信を選択します。
![スクリーンショット 2020-12-14 18.42.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/5568792d-9c50-9a60-2b05-51ba97051d56.png)
このように任意の時間で通知を送る事ができます。
リマインドもできるので、周りに彼女がいると思わせる事も可能です。
**時間を00分にしてはBotっぽくなるので、コツとしてランダムな時間を入力してください。彼女は気まぐれです。**
ちなみに、先ほどのAccount Managerのホーム画面で応答メッセージを選択し、こちらから送信したキーワードに対して任意のメッセージを返す事も可能です。
##駆使する
ふと誰かに彼女がいる事をアピールしたいときにメッセージをリマインドしたりする事で…
![IMG_2360.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/5e144bfd-b6d5-55b6-c660-72ff21c1e3a6.png)
**彼女から通知が!!!!!**
ちなみに壁紙はIBMの本社の看板に中指を立てる若かりしジョブズです。
###さらに駆使する
先ほどのAccount Managerの「応答メッセージ」を駆使する事で…
![IMG_2361.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/521006e7-7ab3-a611-6e36-95a2f2adf8c7.png)
こんなこともできます。
流石にキモくて自分でも笑っちゃいました。

細かい事ですが、Botなので名前の横にマークが出ちゃうんですよね…
**このマークがなくなるかはあなた次第!!**
##さいごに
本格的にQiitaを使ったのが初めてだったので、読みにくかったかもしれません…
一切プログラムは必要ないので、すぐに彼女を偽造したい人にはおすすめです。
LINE Messaging APIやHerokuなどを組み合わせる事でさらなる彼女ができるかもしれません。
@yuriacatsさんの「[かまってちゃんな彼女をPythonで作った話](https://qiita.com/yuriacats/items/bce25ff4cb7343ae0c7b)」とかなり趣旨が違う内容になってしまいましたが、彼女が欲しい心は皆一緒なはずです。
###今年のクリスマスは一段と寒いや…
【初心者】PHP小数点以下の扱いについて

# 小数点以下をなんとかしたい。
小数点以下の数字を色々としたい時。
### 小数点以下を切り捨てたい。
そんな時は…

```php
floor(数値)
```
これ。
### 小数点以下を繰り上げたい。
そんな時は…

```php
ceil(数値)
```
これ。
### 小数点以下を四捨五入したい。
そんな時は…

```php
round(数値, 桁数)
```
これ。

きっとどこででも使う日がくると思う！覚えておこう。
OculusQuestでWidevine L1コンテンツの再生をする


## 概要
OculusQuestではWidevine L1コンテンツの再生が可能なため、試してみました。


## はじめに
ＮＴＴドコモ移動機開発部の蜂谷雄介です。
普段は動画プレイヤー関連の開発を担当しています。

日本での5Gサービスが正式に始まりました。
5Gを活用したサービスとして、VR関連のサービスも一段と盛り上がってきています。
そんな中、Fortnite上で米津玄師さんのライブがありました。
多くの人がVR空間上でのライブという新しい体験で盛り上がりました。
今後、VR空間での動画再生がよりいっそう求められるようになるでしょう。

一方で、コンテンツ保護の観点からすると、動画をDRM（Digital Rights Management）で保護する必要があります。
本記事では、VR空間上（Unity）でのDRMコンテンツ（Widevine）の再生について検証した内容を記載します。


## Unityでの動画再生について
Unityで動画再生を行う場合、ただ再生するだけでよければ、`VideoPlayer`が存在しています。
https://docs.unity3d.com/ja/2020.2/Manual/class-VideoPlayer.html
※Unityの最新バージョンのドキュメントへのリンクです。

クリップとして保存した動画を再生できますし、URLで特定のリンクの動画も再生できます。


## Widevineで再生する
コンテンツにDRMをかけたい場合、`VideoPlayer`だけでは再生できません。
有料のプラグインもありますが、OculusQuestの場合は、`OculusIntegration`を活用できます。
https://developer.oculus.com/blog/oculus-developer-release-notes-october-14th-2019/

>OVROverlay now supports rendering L1 Widevine DRM protected content. See the updated OVROverlay guide for more information.

というわけで、試してみましょう。


まずは、下記の公式ガイドにしたがって各種設定をしていきます。
https://developer.oculus.com/documentation/unity/unity-import/


・新規プロジェクトを作り、`OculusIntegration`をインポートします。
・PlayerSettingなどの設定をOculusで実行できる様に変更します。
・再生時にはAndroidネイティブのプレイヤーを使用するため、
　「Oculus」→「Video」→「Enable Native Android Video Player」を選択し、
　ネイティブのプレイヤーで再生できるようにしておきます。
・再起動後、下記のシーンを開き、OculusQuest上で実行します。
　`Assets/Oculus/SampleFramework/Usage/WidevineVideo.unity`

デフォルトでは、googleのテスト用コンテンツとしてWidevineコンテンツが設定されています。

```
[URL] https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_hd.mpd
[License URL] https://proxy.uat.widevine.com/proxy?provider=widevine_test
```
Widevine L1コンテンツがOculusQuest上で再生できました！
※本当はスクリーンショットを載せたかったのですが、DRMがかかっているため真っ黒になりました。

## 内部の仕組み
DRMにはHardware層で暗号化を解除する方法とSoftware層で暗号化を解除する方法があります。
Widevineでは、
Widevine L1→Hardware層で暗号化を解除
Widevine L3→Software層で暗号化を解除
となっています。

Unityを使って動画再生を行う場合、Unityによる描画ではSoftware層での暗号化解除しかできず、基本的にはWidevine L3しか使用できません。
そこで`OVROverlay`というOculusの仕組みが関係してきます。

Oculus公式ドキュメント `OVROverlay`について
https://developer.oculus.com/documentation/unity/unity-ovroverlay/

詳細は読んでいただくとして、、、ここでは要約した内容を説明します。

UnityによるOculusのレンダリングでは、シーンに存在するほとんどのものは**アイバッファ**と呼ばれるレイヤーにレンダリングされます。これはUnityによるレンダリングと思っていただければ想像に難くないと思います。
動画を描画するためのテクスチャーなどがアイバッファのレイヤーに存在する場合、
Widevine L3による暗号化の解除しかできません。

OVROverlayでは、このアイバッファの前方に**コンポジターレイヤー**と呼ばれる別の層を使用して描画することができます。
※下の図ではOverlayだけでなく、Underlayも使用しています。Underlayの場合はアイバッファの一部を透過設定にします。

<img width=50% alt="アンダーレイヤーの例" src=https://scontent-nrt1-1.xx.fbcdn.net/v/t39.2365-6/64664827_622040414964732_3018153263556984832_n.png?_nc_cat=107&ccb=2&_nc_sid=ad8a9d&_nc_ohc=4P9MlFL7sm4AX9IWS16&_nc_ht=scontent-nrt1-1.xx&oh=8d60ec3631f5561810d528cb5280e257&oe=5FE69D29>

この**コンポジターレイヤーでは、外部サーフェイスを使用することができます**。
つまり、**Androidの`Surface`を使用して直接レンダリングができる**、ということです。
Androidネイティブの`Surface`を使用できるため、
Hardwareによって暗号化を解除し、Widevine L1コンテンツを再生することができます。


サンプルコードの中身をみると、JNI経由で`NativeVideoPlayer`（中身はGoogleのOSSであるExoplayer）を呼び出しており、`OculusIntegration`の機能によって生成したネイティブの`surface`をセットすることで再生を実現しています。

## おわりに
OculusQuest上でのWidevine L1コンテンツの再生を検証しました。
（サンプルを動かしただけですが）
OculusQuest2も発売されたことですし、先のFortniteでのライブのようにVR空間でのライブや動画視聴サービスに期待が高まりますね！