OmniAICreator/Qiita-1.07M huggingface dataset:
【Colab】巨大なデータセットをコピーする方法

# 経緯

PyTorchの[DCGANチュートリアル](https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html)で巨大なデータセット（1GB・22万枚画像くらい）が必要
↓
ローカルのJupyter Labで動かしてみたら学習遅い＆メモリ不足
↓
GPUも使える**Google Colaboratory**（以下Colab）上で学習させてみよう
↓
手を動かしていくうちに問題発生

**データセットをColabにどうやってコピーしよう？**

# 問題

- ColabってGoogle Driveのファイル参照できるの？
- Colab上でZIPって解凍できるの？

# ColabってGoogle Driveのファイル参照できるの？

Google Driveをマウントすることで参照することができます。
ノートブックを新規作成し次のコードを実行する。

```python
from google.colab import drive
drive.mount('/content/drive')
```

認証コードを生成するリンクが貼られるのでアクセスする。
アカウント選択でColabを利用しているアカウントを選択する。
Google Drive File Streamがアクセスを求めてくるので許可する。
認証コードが発行されるのでコピーして、貼り付けてエンター。

```shell
Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=xxx
Enter your authorization code:
```

# Colab上でZIPって解凍できるの？

Colab上でunzipコマンドが使えます。
まずはGoogle DriveにデータセットのZIPファイルをアップロードし、Colab上にコピーします。

```shell
cp "./drive/My Drive/Colab Notebooks/data/celeba/img_align_celeba.zip" "."
```

後はunzipコマンドを使いColab上で解凍します。

```shell
!unzip "img_align_celeba.zip"
```

# 解凍した画像を表示してみる

```python
from PIL import Image
Image.open('img_align_celeba/000001.jpg')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115823/6e7b04b7-0b4e-e2b1-fe67-79671dabd531.png)
無事表示することができました。

# まとめ

1. データセットをGoogle DriveにZIPでアップロードする
2. Colab上でGoogle Driveをマウントする
3. Colab上にZIPファイルをコピーする
4. Colab上でZIPファイルを解凍する

# 追記

Colabにファイルをアップロードするだけなら次のコードでローカルファイルを選択できます。
ただし、容量が大きなファイルをアップロードしようとするとかなり時間がかかっているように感じます。
本稿のGoogle Drive経由の方が早くアップロードできる気がします。

```python
from google.colab import files
files.upload()
```
SwiftUIでのWebViewを扱うときの注意点


## はじめに

SwiftUIではWebViewに相当するものが用意されていないため、UIViewRepresentableを使ってUIKitのWKWebViewをバインディングしたものを自作して利用するのが一般的だと思います。

実際の方法は[@wiii_naさんの記事](https://qiita.com/wiii_na/items/36123cf901839a8038e2)が参考になります。

この方法はiPhoneでの利用は問題ありませんが、iPadだと問題が出てきます。

具体的には、HTMLのselect要素を選択したときに表示されるUIPopoverController的なUIを選択すると、画面が勝手にリロードされて要素を選択することができません。

<img width="50%" alt="IMG_0142.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200963/8977494b-b57a-7378-2ba8-2a35077319a9.png">


## 理由

このUIはどうやらWebKitのUI部品ではなく、OSのUI部品を利用しているらしく、WKWebViewがUIViewControllerのSubViewとして存在している必要があるようです。

参考：[StackOverFlowのスレッド](https://stackoverflow.com/questions/46377990/ios-11-uiwebview-drop-down-menus-completely-broken-on-ipad-uipopovercontroller)


## 対応方法

WKWebViewをSubViewとして持つUIViewControllerを作ってやり、UIViewControllerRepresentableでバイディングしてやればOKです。

``` Swift
import SwiftUI
import WebKit

struct WebView: UIViewControllerRepresentable {
    var req : URLRequest
    
    class Coodinator: NSObject, WKNavigationDelegate, WKUIDelegate {
        var parent : WebView
        
        init(_ parent: WebView) {
            self.parent = parent
        }
        
        func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
            print("load started")
        }
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            print("load finished")
        }
        
        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
            print(error)
        }
    }
    
    func makeCoordinator() -> WebView.Coodinator {
        return Coodinator(self)
    }
    
    func makeUIViewController(context: Context) -> EmbeddedWebviewController {
        let webViewController = EmbeddedWebviewController(coordinator: context.coordinator)
        webViewController.loadUrl(req)

        return webViewController
    }
    
    func updateUIViewController(_ uiViewController: EmbeddedWebviewController, context: UIViewControllerRepresentableContext<WebView>) {

    }
}

class EmbeddedWebviewController: UIViewController {

    var webview: WKWebView

    public var delegate: WebView.Coordinator? = nil

    init(coordinator: WebView.Coordinator) {
        self.delegate = coordinator
        self.webview = WKWebView()
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        self.webview = WKWebView()
        super.init(coder: coder)
    }

    public func loadUrl(_ req: URLRequest) {
        webview.load(req)
    }

    override func loadView() {
        self.webview.navigationDelegate = self.delegate
        self.webview.uiDelegate = self.delegate
        view = webview
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

struct WebView_Previews: PreviewProvider {
    
    static var previews: some View {
        VStack{
            WebView(req: self.makeURLRequest())
        }
    }
    
    static func makeURLRequest() -> URLRequest {
        let request = URLRequest(url: URL(string: "https://www.google.co.jp")!)
        return request
    }
}
```
Windows Server 2019 Essentials をHyper-V運用（ファイルサーバ化）②

小規模事業所のファイルサーバーを、Hyper-V上のWindowsServer2019Essentialsで組んでいます。

[Windows Server 2019 Essentials をHyper-V運用（ファイルサーバ化）①](https://qiita.com/sasaan/items/d92e264568cba85ee7a1)

調べてみたら光回線契約なので200Mという不思議な一般回線だったので、ギガラインにあげようか調整中。工賃が2万、月額が200円くらいのUP。たしかに下りで30Mbpsしかないから、ギガ来てないなとは思っていたが。。てか、回線切り替えたときに最初からその説明ｼﾃﾖﾈ…二つ返事で最初からギガにしたのに、、でもあの時は見積もり合わせとかで少しでも安い提案をしてきたのだから、仕様書に明記していない私の落ち度ﾀﾞﾅ。

#サーバー初期設定のつづき
前回中途半端なところで終わったので、思い出しながら…。。
## デフォルトでは、リモートデスクトップがはじかれた。 
- WindowsAdminCenterで担当者PCからログイン中、担当者PCからリモートでつなぎたい。
    - 「グループポリシーでOU」…Organizational Unit：組織単位
    - この作業は保留して、先にAD DSの設定へ…

## ドメインコントローラー初期設定
### 新しいフォレストを追加する
- ネーミングのセオリーは？…とりあえずshandomain.loacalとする。
- フォレスト・ドメインの機能レベル→Windows Server 2016
- ディレクトリサービス復元モード(DSRM)のパスワードはとりあえず、adminと同じに。
- DNS委任サービスは今回はフォレストなのでチェックしない
- データベース、ログ、SYSVOLの保存先を大容量のHDD側に設定しようとしたらReFSフォーマットはNGでとりあえずシステム側のフォルダへ
    - 今後容量が肥大化した場合は対処が必要。そもそもバックアップ用の仮想HDDはNTFSにしておくべきだったか…。。
        - データベースフォルダー：C:\Windows\NTDS
        - ログファイルフォルダー：C:\Windows\NTDS
        - SYSVOLフォルダー：C:\Windows\SYSVOL
- 確認画面にて、以下の警告が。
    - WindowsServer2019ドメインコントローラーについて「セキュリティの弱い暗号化アルゴリズムの使用は許可されなくなります。
    - 「権限のある親ゾーンが見つからないか…」→初めてのフォレストの場合は無視してよいとGoogle先生が言ってた！
    - とはいえ、合格らしい。
- 再起動になった。

### クライアントコンピューターの登録
- サーバーマネージャー→ツール→ADユーザーとコンピューター
    - shandomail/Computers右クリック新規作成→コンピューター→登録したいクライアントのコンピューター名を入力
- サーバーマネージャー→ツール→DNS→前方参照ゾーン→shandomail.local→新しいホスト(AまたはAAAA)
    - クライアント機の名前とIPを入力し、「関連付けられたポインター(PTR)を作成する。」及び「同じ所有者名のDNSレコードの更新を認証されたユーザーに許可する」にチェック。
        - なんとなく調べて、両方チェックで良いと思うが、調べたやりかただと「レコードを**更新する**」 になっているのは気になる。
    - やっぱり成功しない…笑

*みんな帰宅したので、今日はここで切り上げて、ルーターのIPv6 over IPv4設定をやろう。*
LINUXの仕組みをパパッと知りたい！

![PC20171027neko_TP_V.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260656/07fecc46-e3e6-9394-2453-bc6a4f526302.jpeg)



LPICの試験や実際の仕事でLINUXについて知りたい、知る必要があるというという方はいると思います。
でもいざ調べても「コマンドや単語とか調べてみたけど、結局複雑でわかんないぞ？」となる人もいるのではないでしょうか（私はなりました）。
これはそんな方に向けて、手軽にLINUXの仕組みを知るための記事です！


LINUXの仕組みについて知るためには、ズバリLINUXの起動プロセスについて理解を深めることが効果的だと考えられます。なぜかというと、起動プロセスで関係するシステムはすなわちLINUXを動かしているシステムであり、LINUXを動かしてるということはLINUXの全てということになります。
例えば車の仕組みを知るために車のキーを回してエンジンがどのように起動されるか知ることで、車の動く仕組みについて理解が深まるみたいに、
LINUXのエンジンについて知ることで、LINUXのできることがわかることができるでしょう！




# LINUXの位置づけ
まず数あるOSの中でのLINUXの位置づけについて触れますと、LINUXはUNIX系OSと呼ばれる種類のOSになります。LINUXのバージョンはディストリビュートと呼ばれるかたちで分岐しているのですが、このLINUXのカーネル(OSの元になるもの)がオープンソースとして広く公開されて、いろいろな人によってOSの開発がされました。その結果、Debian系とかUbuntu系とか、ファッション系統みたいのようにいろいろな分岐が生まれました。（この系統を
ざっくり分けると無料版と有料版の二つにわけられて、無課金だとCentOS、有料版だとRedHatが有名です)

# Linuxの起動プロセス
まずは電源ボタンをつけてからコマンド入力ができるようになるまでの、Linuxの起動プロセスの流れが次の表です。

```
1. 電源投入
2. ファームウェアの起動
3. ファームウェアがブートローダを読み込む
4. ブートローダがカーネルとファイルシステムイメージ(initramfs)を読み込む
5. ブートローダがカーネルを実行
6. カーネルがファイルシステムイメージ(initramfs)を実行
7. カーネルがinit(またはsystemd)を起動、ルートファイルシステムをマウント
8. カーネルがinit(またはsystemd)を実行
```



## １. 電源投入
電源を入れると端末に刻みこまれたファームウェアが立ち上がってきます。
有名なファームウェアだとBIOS(BootInput/OutputSystem)とUEFI(UnifiedExtendableFarmwareInterface)があり、各ファームウェアによって扱うブートローダの種類が変わってきます。

## 2. ブートローダの起動
ファームウェアはまずハードディスクの先頭に収められているブートローダを読み込んで、LINUXを立ち上げる準備を始めます。
この時にBIOSだとイメージファイルを生成して展開して、UEFIだと格納されてるEFIファイルを読み込んで起動します。
この時に起動されるのがGRUB2(GRandUnifiedBootloader)と呼ばれるものです。(2とついてるのは、二世代目だからです)

## 3. カーネルとルートファイルシステムの起動
ブートローダはLINUXのカーネル(vmlinuz)とファイルシステムイメージ(initramfs)を読み込みます。vmlinuzって変わった名前ですけど、頭文字はVirtualMachineのVMで、末尾がzなのは圧縮ファイルとのことでlinuxのxをzに変えたものらしいです。
ブートローダからカーネルの実行とファイルシステムイメージの展開が完了すると、ルートファイルシステムが使用可能になったとみて、
カーネルはユーザープロセスを起動します。

## 4. ユーザープロセスの起動
諸々の準備が終わったらカーネルは最後にユーザー自身のプロセス(intiまたはsystemd)を呼び出します。この時にランレベルまたはTargetに合わせた起動モードでLinuxを立ち上げます。
立ち上げ終わったら再度にユーザーの元に制御が戻って、Linuxを操作することができます。

## 細かい語句の説明
ファームウェア：ハード側からLinuxを立ち上げるシステム
ブートローダ：Linuxをたたき起こすやつ
カーネル：Linuxの種
initramfs：ファイルシステムの頂点、トップオブファイルシステム
ユーザープロセス：initとかsystemdで、ユーザーの操作自体
ランレベル：GUIかCGIか緊急モードかがレベル別で分けられてます

# 関連するファイル
Linuxの起動に関係するブートローダやカーネルの設定値は特定の場所に配置されてます。
## ◇ブートローダ(GRUB2:GRandUnifiedBootloader2)
　本体ファイル
　　BIOS(Basic input/output system)の時はboot.imgとcore.img(※画像ファイルではない)
　　※起動時に生成されます
　　UEFI(Unified Extended Firmware Interface)の時は
　　/boot/efi/EFI/(端末のバージョン名:例centos等)/配下に
　　shim.efiとgrubx64.efiが格納されてます
　設定ファイル
　　/boot/grub/grub.cfg(※confではない)
　カーネルパラメータ
　　/proc/cmdline
　カーネルの出力するログ
　　/var/log/dmesg
　ランレベルの設定ファイル
　　/etc/inittab(initの時)
　　/etc/systemd/system/defalut.target(systemdの時)

## InitとSystemdの違い
詳しくは[こちらのサイト](https://www.hilotech.jp/blog/it/311)が参考になるのですが、大まかにいうとinitを成長させた上位互換のシステムがsystemdです。便利になって、責任感が増してます！
具体的な機能で言うと、init時代は単発でバラバラに管理されていたプロセスがユニット単位で管理されるようになります。
このプロセスがユニット単位で管理されるようになることで、各サービスを安定的に運用できるようになったのです。(起動や停止がしやすくなる)


# 参考
以下の本を参考に書いてます。プラスアルファで細かに見たい場合は手に取って辞書的な使い方をしてみてもいいと思います☺

・[Linux教科書 LPIC レベル1 スピードマスター問題集 Version5.0対応](https://www.amazon.co.jp/gp/product/B07TVTKW2C/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=B07TVTKW2C&linkCode=as2&tag=vk4268370f-22&linkId=8965e118505185053b84e77611a602dc)
UnityのOpenCVでARマーカーを使う/カメラキャリブレーション/座標系作成

#用途
自分用のメモ。

#OpenCV for Unity
ここを見る
https://qiita.com/foka22ok/items/378e1fb337d4b29a75ac
「OpenCV for Unity is an Assets Plugin for using OpenCV 4.3.0 from within Unity.
」　2020.05.27現在 4.3.0対応

OpenCV for Unity(95USD)を半額セールの時に買う。

#OpenCV Plus Unity 無料とZxing
[OpenCV Plus Unity](https://www.techceed-inc.com/engineer_blog/4268/)　この記事によると、それなりに使えるらしい。

UnityでQRコード(Zxing)
[[Zxing]UnityでQRコードを読み取りしてみる。](https://nyagosu.net/develop/etc/unity-qrcode/)

#QRコード作成
https://www.cman.jp/QRcode/qr_make/
1　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/ee1e336e-34d4-9558-b287-7d436a6b1f00.png)
2　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/6a46a514-afbb-4375-67f2-dcb04aa46ae0.png)
#ARマーカー
[QRコードだと解像度低いと認識されないので、ARマーカーarucoを使う](https://qiita.com/hsgucci/items/37becbb8bfe04330ce14)　ＱＲコードよりシンプルなものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/a9190e85-5592-7db4-32c3-f2ae3396d132.png)
[1-9のマーカーをDLする](https://1drv.ms/u/s!ApO4wsxFJBbVt3Kj037RDaSvfjoP?e=6zx8YU)

# [opencv_contrib](https://github.com/opencv/opencv_contrib)
arucoは[opencv_contribを導入](https://qiita.com/tomochiii/items/fa26404ebc5fcd4481b9)する必要あり。

1)opencv_contribを配置する
2)配置場所をOPENCV_EXTRA_MODULES_PATHで指定する
区切り文字はバックスラッシュにしてください。エクスプローラーからコピペするとエラーになります。例）C:/SDK/opencv/opencv_contrib-3.4.10/modules

検出しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/e082cfe3-845f-c050-67c7-81d30164a3ad.png)

WEBカメラ初期化で失敗するときは、「[Windows 10 でカメラを開く](https://support.microsoft.com/ja-jp/help/4028647/windows-open-the-camera-in-windows-10)」を確認

# カメラキャリブレーションから座標系作成まで

C++での実装例です。Releaseのみプロジェクト設定しています。
プロパティシートを作りたい..
[DL](https://1drv.ms/u/s!ApO4wsxFJBbVt36x3597VUL7oj-q?e=PcaSFq)

# Arマーカー
[arucoモジュールでマーカーを検出する](https://github.com/atinfinity/lab/wiki/aruco%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%A7%E3%83%9E%E3%83%BC%E3%82%AB%E3%83%BC%E3%82%92%E6%A4%9C%E5%87%BA%E3%81%99%E3%82%8B)

追記：
 // flip するとARマーカー検出失敗する
cv::flip( image2, image, 0 ); 
cv::flip( image2, image, 1 ); 
cv::flip( image2, image, -1 );// これはOK。 


#キャリブレーション
[カメラキャリブレーション/怡土順一](http://opencv.jp/sample/camera_calibration.html) 古い

[カメラキャリブレーションopencv-python](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_calib3d/py_calibration/py_calibration.html) 
[カメラキャリブレーション](http://tecsingularity.com/opencv/cameracalib/)

[QIITAの誰かのメモ](https://qiita.com/kazz4423/items/f173f298704bd121043d)

# ご参考/OpenCVのサンプル
[opencv.jp](http://opencv.jp/cookbook/index.html)
[aruco公式](https://docs.opencv.org/3.4/d5/dae/tutorial_aruco_detection.html)

[座標系を作る](https://qiita.com/smk7758/items/1ca1370f78cad1233d02)
Swiftの構造体はC++に渡せるよって話


**! C++とSwift間で構造体を渡すことは保証されておらず、メモリレイアウトが異なる場合があるそうです。**

**この記事は参考程度に**

# 背景

Swiftは比較的高速な言語ですが、やっぱり速度面でC++を使いたくなることはあります。

しかし、Swiftが直接サポートしているのはCからのブリッジのみです。なので、
C++の構造体をObjCでラップして...　
なんて形で渡すことが多いです。

でもこれだとかなりオーバヘッドが大きくて（特にObjCの動的ディスパッチあたりが）、結局C++を使った意味は...?となることが多いです。

なので、実はSwiftの構造体くらいならC++に直接渡せるよって話です。

# 実験

Swiftでこんな構造体を作ります。

```swift
struct Point {
    var x: Double
    var y: Double
}
struct Size {
    var width: Double
    var height: Double
}
struct Rect {
    var origin: Point
    var size: Size
}
```

それをポインタにして、`cppcall`に投げます。

```swift
var frame = Rect(origin: Point(x: 100, y: 200), size: Size(width: 300, height: 400))

withUnsafeMutablePointer(to: &frame) {ptr in
    cppcall(UnsafeMutableRawPointer(ptr))
}
```


次にC++側です。

Swiftで定義した構造体と同じ構造を持つ構造体をC++側で定義します。

```C++
struct Point {
    double x;
    double y;
};

struct Size {
    double width;
    double height;
};

struct Rect {
    Point origin;
    Size size;
};

void cppcall(void *swiftStruct) {
    
    auto casted = (struct Rect*)(swiftStruct);

    std::cout << casted->origin.x << std::endl;
    std::cout << casted->size.height << std::endl;
}
```


Headerで以下のようにextern "C"します。受け取るのは `void*`型です。




```C++
extern "C" {

void cppcall(void* swiftStruct);

}
```


これで、実行するとそのままC++にSwiftでインスタンス化した構造体がC++で使えます。

# 解説のようなもの

これがうまく行くのはSwiftとC++でメモリ上の構造体の扱いが同じだからです。どちらもメンバーを最初から順番にメモリに並べているだけです。（SwiftはOptionalな構造体ではちょっと扱いが変わりますが...）
iOSアプリにYouTube動画を埋めこもう2020

iOSアプリにYouTube動画を埋めこんだので、その覚書です。

# 基本
YouTubeの公式ドキュメントを見ると、[YouTube-Player-iOS-Helper](https://github.com/youtube/youtube-ios-player-helper)というOSSを使うのを推奨されます。
基本WebViewをベースに、いい感じのサイズにしたYouTube動画を埋めこんで、コントローラーをつけるという感じです。

（公式ドキュメント）
[Embed YouTube Videos in iOS Applications with the YouTube Helper Library](https://developers.google.com/youtube/v3/guides/ios_youtube_helper)

（わかりやすいチュートリアル）
[[Swift] YouTube-Player-iOS-Helper を使って YouTube 動画を再生してみる](https://dev.classmethod.jp/articles/youtube-player-ios-helper/)

# 2020年に直面した問題
YouTube-Player-iOS-Helperなんですが、メンテナンスされていないっぽいです。
最近AppleからUIWebView完全廃止の連絡があって、WKWebViewに移行したと思うんですが、
YouTube-Player-iOS-HelperはUIWebViewを使っているので、これ使っているとReject理由になります。
（YouTube公式に対応して欲しいですが、その辺はGoogleとAppleなので、あんまり息があってない感じはします）

幸いOSSなので、有志の方がWKWebView移行したライブラリを作ってくれていて、[YoutubePlayer-in-WKWebView](https://github.com/hmhv/YoutubePlayer-in-WKWebView)があるので、こちらを使いました。

```ruby:CocoaPod
pod "YoutubePlayer-in-WKWebView", "~> 0.3.0"
```

# サムネイル画像が自由に調整できない問題
で、ここから実装にあたって苦労したこと。

サムネ画像をバーンってやっぱ表示したかったんですけど、
最初200*200ぐらいでつくろうとしたら、トリミングされた形で表示されました。
YouTubeのサムネイル画像は、下記のサイズで提供されるみたいです。

- 高クオリティ(480x360)　※ width x height
- 中クオリティ(320x180)
- 標準クオリティ(120x90)
- HQ動画の標準クオリティ(640x480)
- FULLHDのクオリティ(1920x1080)

基本iPhoneのサイズを意識すると、中クオリティ or 標準クオリティが多いでしょうか。
（iPadが入ってくると、それ以上のサイズもあるかと思われます）
このサイズに合っていないと、それより一つ大きいサイズのサムネをとってきて、よしなにトリミングするっぽいです。
YouTube-Player-iOS-Helper（から派生したYoutubePlayer-in-WKWebView）だと、
たとえば400x２００のViewに中クオリティ(320x180)を引き伸ばして表示、みたいなことはできない模様です。

# パラメーターが効かない問題
`load(withPlaylistId:playerVars:)`のplayerVarsでプレイヤーを制御するパラメーターが色々指定できるんですが、
実際やってみると想定どおり調整できませんでした。

[YouTube 埋め込みプレーヤーとプレーヤーのパラメータ](https://developers.google.com/youtube/player_parameters?hl=ja)

まず`autoplay`は効かなかったです。
アプリ側のライフサイクルとかもあんのかな？　と思ってますが、ちょっと謎です。
`iv_load_policy`（動画アノテーション）も効かなかったですね。
（動画アノテーション：動画の上に出るクリック可能な文字）

`playsinline`/`controls`は効きました。
`modestbranding`（YouTubeロゴ非表示）は効かなかったんですが、
メソッドを`load(withPlaylistId:)`にするとなぜかYouTubeロゴが非表示になりました。

この辺の挙動はOSS内部の問題なのか、API側の問題なのか謎です。

# autoplayが効かない問題
よくドキュメント読んでみたら、モバイルではautoplayが効かない可能性があることが書かれてました。

[モバイルの注意事項](https://developers.google.com/youtube/iframe_api_reference?hl=ja#Mobile_considerations)

SafariだとAppleの思想的にできないようにされている模様です。
WKYTPlayerViewのWebViewは、

```objc:WKYTPlayerView.m
    configuration.allowsInlineMediaPlayback = YES;
```

このプロパティがtrueにしてあって、autoplayイケるように思ったんですが、ダメでした。
どうしてもautoplayを実現したいなら、下記のワークアラウンドがあります。

```swift
let videoID = "xxxxxxx"
let youtubePlayer = WKYTPlayerView()
youtubePlayer.delegate = self
youtubePlayer.load(withVideoId: videoID)

    // WKYTPlayerViewDelegate - データのロード完了後のDelegateメソッド
    func playerViewDidBecomeReady(_ playerView: WKYTPlayerView) {
        playerView.playVideo()
    }
```
[Android]アクションバーの色を動的に変える


## アクションバーの色を変更する
```MainActivity.kt
supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.parseColor("カラーコード")))
```

## ステータスバーの色を変更する
```MainActivity.kt
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = Color.parseColor("カラーコード")
```

アプリをAPIバージョンの22以下に対応させる場合、ステータスバーの文字色が白色に固定されているため、ステータスバーの色が白系統の場合**文字の可読性**を損なわないか考慮する必要があります．

## ツールバーの色を変更する
```MainActivity.kt
toolbar.setBackgroundColor(Color.parseColor("カラーコード"))
```
flutterでページ内に複数の画像を並べて表示

# やりたいこと

ページ内に複数の画像を並べて表示させたい。

# 画像データの取得方法

https://qiita.com/kenichiro-yamato/items/83c508d24de9d588da07
の方法で、ネットに置いてある画像を参照する。

# 画像レイアウトの実装

## Rowを使って横に２つ並べる。

```dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Row(
        children: <Widget>[
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg', width: 200,),          
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1711/Cute_Small_Chicken_2017_Animal_HD_Wallpaper_1366x768.jpg', width: 150,),          
        ],
      ),
    );
  }
}
```




## Columnを使って縦に２つ並べる。

```dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg', width: 200,),          
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1711/Cute_Small_Chicken_2017_Animal_HD_Wallpaper_1366x768.jpg', width: 150,),          
        ],
      ),
    );
  }
}
```

上記、横並びと、タテ並びの、コードの違いは、

```dart
      body: Row(
```

```dart
      body: Column(
```

の部分のみである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/45012efb-4f1e-fffc-0730-0f296b4fa07b.png)


# 完成形 main.dart

```dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg', width: 200,),          
          Image.network('https://www.10wallpaper.com/wallpaper/1366x768/1711/Cute_Small_Chicken_2017_Animal_HD_Wallpaper_1366x768.jpg', width: 150,),          
        ],
      ),
    );
  }
}

```
不動点定理が結ぶ ラッセルの逆理とYコンビネータの関係

## はじめに
自己言及、再帰、不動点 etc. こういった術語は論理学や計算論でしばしば目にするし、互いに関連しあって独特の世界を構築していることはなんとなく知っている人も多いと思います。

不動点定理を使ってそれらを統一的にスッキリ見せましょうという資料をウェブサーフィンしていると見つけたので、要点を整理します。参考文献はRIMSの資料です:

- [長谷川真人『自己言及の論理と計算』(PDF)](http://www.kurims.kyoto-u.ac.jp/~hassei/selfref2006.pdf)

完全に理解できているとは思わないのでツッコミやご指導あればコメントください。

## 要点
**不動点定理**: A→Bなる任意の関数を、A×A→Bなる万能関数φで定義できるならば、B→Bなる任意の関数fの不動点を構成できる: f(φ(x,x)) の指標をaとすると φ(a,a) がf の不動点となる。

**ラッセルのパラドックス**: Sをすべての集合の集合と仮定する。S×S→2なる関数 `if y∈x then T else F` は万能関数である。従って不動点定理より2→2なる任意の関数、特に否定演算が不動点を持つことになるが、これは直ちに矛盾を帰結する。

**カントールの対角線論法**: 2^X から X への単射が存在すると仮定する。これは X から 2^X への全射 Ψ が存在することと同値。ここで `if y∈ψ(x) then T else F` なる X×X→2 な関数は万能関数となる。したがって2→2なる任意の関数、特に否定演算が不動点をもつがこれは直ちに矛盾を帰結する。

**Yコンビネータとラッセルのパラドックス**: ラムダ計算におけるYコンビネータ (λf. (λx. f (x x)) (λx. f (x x))) とラッセルのパラドックスは不動点定理を介して同一のものを表す。すなわち

- λx.P に {x | P x}
- (M N) に N ∈ M
- f M に ¬M 

を対応付けることができ,そうすると (Y f) は {x|x ∉ x} ∈ {x|x ∉ x} が対応するので、 (Y f) = f (Y f) はラッセルのパラドックスそのものとなる。


## 詳細/証明
**不動点定理の証明のようなもの**: a の定義から, φ(a,x) = f(φ(x,x)) これに a を適用すると φ(a,a)=f(φ(a,a)) を得るがこれは φ(a,a) が fの不動点であることを自明に示す。

**ラッセルのパラドックスでの万能関数の確認**: 任意の関数g:S→2に対して `{x∈S | g(x)=T}` がgの指標になる。本当にそうなっているかを確認するためには、代入してみればよい。つまり `if y∈{x∈S | g(x)=T} then T else F` が g に一致するかをみればよい。任意のSの元yに対してg(y) がT or F なので、場合分けをして考えれば両者の値が一致することは容易に示せる。

**否定演算が矛盾を帰結するとは？**: 否定演算が2→2な演算なのはすぐわかる。否定演算が不動点を持つということは neg(a) = a なる a∈2 が存在することになるが T も F もそれを満たさない。

**単射と全射の補題の証明**: 「AからBへの単射が存在する」⇔「BからAへの全射が存在する」の証明。（⇒の証明）自明。求めたい写像の、単射のImageへの制限が単射の逆写像となるようにとればよい。（⇐の証明）自明。

**カントールの対角線論法での万能関数の確認**: 任意の関数 g:X→2について あるa∈X が存在して  g = `if y∈Ψ(a) then T else F` となることを示せばよい。Ψの全射性から `Ψ(a) = {x∈X | g(x)=T}` となるような a∈X が存在する。これを代入すると、示すべきは g = `if y∈ {x∈X | g(x)=T} then T else F` となる。これは上述のラッセルの例と全く同一なので、証明略。
【Unity】【Oculus Quest】 uGUIを使う

# やりたいこと

uGUIを使ってUIを作成する。ただし、UIはゲームのように常に前面に表示されるのではなく、3Dオブジェクトと同じようにシーンに配置されるようにする。

# 環境
MacOS Mojave 10.14.6
Unity : 2019.3.9f1
Oculus Integration : 16.0

# 手順

# 0.前準備

- AssetStoreから`Oculus Integration`をインポートしてある。
- シーンには`OVRPlayerController`を配置してある。
- `OVRPlayerController>OVRCameraRig>TrackingSpace>LeftHandAnchor`に`OculusTouchForQuestAndRiftS_Left`を追加、`OVRPlayerController>OVRCameraRig>TrackingSpace>RightHandAnchor`に`OculusTouchForQuestAndRiftS_Right`を追加してある。

# Canvasの配置と設定

ゲームを作成するのと同じように`Canvas`を配置する。ただし、`Canvas`コンポーネントの

- `RenderMode`を`WorldSpace`にする。
- `EventCamera`に、`OVRPlayerController>OVRCameraRig>TrackingSpace>CenterEyeAnchor`を設定する。

`Canvas`のサイズを3Dオブジェクトとどうやっても合わせるのか迷うが、サンプルシーン(`Oculus>VR>Scenes>UI.scene`)を確認すると、スケールを変更している事がわかる。
<img width="442" alt="スクリーンショット 2020-05-19 21.59.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85509/bd55d7cb-7cc3-6e0e-e77c-de5b2f1a95f1.png">
例えば幅2メートル高さ１メートルのUIを作成したいのなら、2000×1000で作成後、スケールを0.001にするのが良いのかもしれない。 

# UIHelpersプレハブを配置

UIインタラクションを提供してくれるのが**`UIHelpers`**プレハブ。これをシーンに配置する。

## 既存のEventSystemを削除

この`UIHelpers`は子に`EventSystem`を持っており、Canvas作成時に自動生成された`EventSystem`は不要なので削除する。

## OVRInputModule

`UIHelpers`の`EventSystem`には**`OVRInputModule`**がアタッチされている。
**`OVRInputModule`**の`RayTransform`に関しては、
>Object which points with Z axis. E.g. CentreEyeAnchor from OVRCameraRig

とあるので`CentreEyeAnchor`を設定する。

### 右手のトリガーでクリックをさせたい

UIHelpersはデフォルトだと`One`ボタンでクリックを判定するように設定されている。右手のトリガーを引いたときにクリックとするのが自然な気がするのでそう設定する。**`OVRInputModule`**の`Joy Pad Click Button`で`Secondary Index Trigger`にチェックを入れる。


### OVRRaycaster

`Canvas`にはデフォルトで`GraphicRaycaster`がアタッチされている。これはスクリーン上でのレイキャストのみをサポートしており、VR空間内のレイキャストには使用できないので削除する。代わりに、VR空間内でのレイキャストをサポートしている**`OVRRaycaster`**をアタッチする

### Laser Pointer

`UIHelper`の子オブジェクトの`Laser Pointer`のMaterialがMissingになっているので、適当なマテリアルを設定する。


# ここまでの結果

このようなUIを作成して、
<img width="556" alt="スクリーンショット 2020-05-27 15.00.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85509/3b9ccc82-2b57-ab23-5491-3d188ddc186d.png">

このようなスクリプトを作成する。

```UITest.cs
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class UITest : MonoBehaviour
{
    [SerializeField] private Button button1 = default;
    [SerializeField] private Button button2 = default;
    [SerializeField] private Button button3 = default;

    [SerializeField] private TextMeshProUGUI debugText = default;

    void Start()
    {
        button1.onClick.AddListener(() => debugText.text = $"pushed button is {button1.name}");
        button2.onClick.AddListener(() => debugText.text = $"pushed button is {button2.name}");
        button3.onClick.AddListener(() => debugText.text = $"pushed button is {button3.name}");
    }
}
```

結果はこちら。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85509/ab6ecaca-2f07-ef9f-b202-058bc12c2730.gif)
AWS ChaliceをPyCharmでローカルデバッグ実行する

# この記事の概要

サーバーレスアーキテクチャーをサポートするフレームワークも色々充実してきていますが、今回は、AWS製のPython専用フレームワークのChaliceを試してみました。単に試すだけですと、正直、Black Belt読みましょう。以上！で終わってしまいます。

従って、今回はローカルでテストしてみることにこだわって、PyCharmでのローカルデバッグの方法を中心に記載します。

# 前提知識

サーバーレスとは？やChaliceとは？というのは、以下のリンクを参照ください。

まずは、公式
https://chalice.readthedocs.io/en/latest/

その他参考にしたサイト
https://www.freecodecamp.org/news/how-to-get-started-with-serverless-architecture/
https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-chalice-2019/
https://aws.amazon.com/jp/builders-flash/202003/chalice-api/

# 仕込み
公式のQuick start and tutorial
https://chalice.readthedocs.io/en/latest/quickstart.html#quickstart-and-tutorial
ですと、一番最初は、{'hello': 'world'}を返すだけで、デバッグの余地がありません。
従って、プロジェクトを作成して初期状態で出来るapp.pyのコメントを外して、Path引数を渡すメソッドを有効化してみましょう。

```python

from chalice import Chalice

app = Chalice(app_name='abe-todo-api')

@app.route('/')
def index():
    return {'hello': 'world'}

@app.route('/hello/{name}')
def hello_name(name):
   # '/hello/james' -> {"hello": "james"}
   return {'hello': name}
```

# ローカルでのデバッグ

## ローカルでChaliceを実行

app.pyの19行目のreturnの位置にBreak pointを設定します。
Terminalから、以下のコマンドを実行し、Chaliceをローカル環境で実行します。
(ちなみに、--stageと--portは、以下では、わざわざデフォルト値を指定しているので、chalice localだけでもいけます)

```shell
$ chalice local --stage dev --port 8000
```

![Screenshot from 2020-05-24 14-00-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/9290c652-845b-513e-cf53-121aac1fcbdb.png)

## 実行中のプロセスにデバッガーをアタッチ

Run > Attach to Process...
![Screenshot from 2020-05-24 20-09-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/1f3b5195-f7d0-5e5d-4b64-013651cb4c0d.png)

## Debug on PyCharm

ブレークポイントデバッグの様子
![Pycharm_debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/a3298257-54e6-ec22-ad47-59881cae23e6.png)


## DynamoDB Localの実行

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.html

（別途詳細追記予定）
AndroidStudioのショートカット

#AndroidStudioのショートカット
自分用によく使うショートカットを忘れないうちにメモ

##コード編集
###Ctrl+SPACE
コードを補完します。コード補完は入力中に自動的に表示されますが、閉じてしまった場合は再度表示する事が出来ます。
###Ctrl+P
カーソルがある関数へ引数として渡す内容が表示されます。引数の編集中に自動的に表示されますが、閉じてしまった場合は再度表示する事が出来ます。
###Ctrl+Q
カーソルがある関数の説明が表示されます。
###Ctrl+マウス左クリック
Ctrlを押しながら関数やメソッド、定義のある場所へマウスカーソルを移動させると詳細が表示され、さらに左クリックでその関数やメソッドが宣言されているソースへ飛びます。

###Ctrl+/
選択範囲をコメント化、またはその解除を行います。

```shortcut.kt
        val etMain = findViewById<EditText>(R.id.etMain)
        etMain.setOnKeyListener(lnKey)
        etMain.addTextChangedListener(lnTextChange)
```
この3行が選択されている場合に**Ctrl+/**を押すと

```shortcut.kt
//        val etMain = findViewById<EditText>(R.id.etMain)
//        etMain.setOnKeyListener(lnKey)
//        etMain.addTextChangedListener(lnTextChange)
```

このようにコメント化されます。再度操作するとコメント化が外れます。

###Ctrl+Shift+/
選択範囲をコメント化、またはその解除を行います。

```shortcut.kt
        val etMain = findViewById<EditText>(R.id.etMain)
        etMain.setOnKeyListener(lnKey)
        etMain.addTextChangedListener(lnTextChange)
```
この3行が選択されている場合に**Ctrl+Shift+/**を押すと

```shortcut.kt
/*        val etMain = findViewById<EditText>(R.id.etMain)
        etMain.setOnKeyListener(lnKey)
        etMain.addTextChangedListener(lnTextChange)*/
```

このようにコメント化されます。再度操作するとコメント化が外れます。

###Ctrl+W
カーソル位置にある単語を選択範囲とします。

```shortcut.kt
      #etMain.addTextChangedListener(lnTextChange)
```

カーソル「#」のところで **Ctrl+W**で**etMain**が選択されます。
再度**Ctrl+W**で**etMain.addTextChangedListener**が選択され
再度**Ctrl+W**で**etMain.addTextChangedListener(lnTextChange)**が選択されます。

###Ctrl+Shift+W
**Ctrl+W**を複数回押して選択した選択範囲を狭めます。

###Tab
選択範囲の字下げ（インデント）の階層を深めます。
下記を範囲選択して**tab**を押すと

```変更前.kt
val lnClick = object :View.OnClickListener{
    override fun onClick(v: View?) {
        TODO("Not yet implemented")
    }
}
```

```変更後.kt
    val lnClick = object :View.OnClickListener{
        override fun onClick(v: View?) {
            TODO("Not yet implemented")
        }
    }
```

1階層深くなります。

###Shift+Tab
選択範囲の字下げ（インデント）の階層を浅くします。
下記を範囲選択して**Shift+Tab**を押すと

```変更前.kt
    val lnClick = object :View.OnClickListener{
        override fun onClick(v: View?) {
            TODO("Not yet implemented")
        }
    }
```

```変更後.kt
val lnClick = object :View.OnClickListener{
    override fun onClick(v: View?) {
        TODO("Not yet implemented")
    }
}
```

1階層浅くなります。

###Ctrl+D
カーソルがある行をもう1行複製します。

###Ctrl+Enter
Enterと同じように改行されますがカーソル位置はそのままです。
###Shift+Enter
Enterと同じように改行されますがカーソル位置の命令が折り返されることがありません。
###Ctrl+Left/Right
単語単位でカーソルが左右に移動します。
###Shift+Left/Right
カーソルが左右に移動するとともに選択範囲になります。
###Ctrl+Shift+Left/Right
カーソルが単語単位で移動すると共に選択範囲になります。
###Ctrl+Up/Down
カーソル位置はそのままで編集画面全体が上下にスクロールします。
###Shift+Up/Down
カーソルが上下に移動すると共に選択範囲になります。
###Ctrl+Shift+Up/Down
選択範囲の行を上下に移動出来ます。
位置が変わるのみで行が上書きされません。
Vue.js　プロップスの話

#プロップスとは
親コンポーネントから子コンポーネントにデータを渡す方法:arrow_right:

大変な蛇足を交えながらメモしていきたいと思います。

##親コンポーネントを準備
今回は親(`Parent.vue`)と子(`Child.vue`)の2つのコンポーネントを準備。
いつも、scriptタグの中身はいろいろ見ながら書いてしまう。
いい加減覚えたい。:frowning2::frowning2::frowning2:



```Parent.vue
<!--親コンポーネント-->
<template>
<Child></Child>
</template>
<script>
    import Child from "../components/Child";
    export default {
        components:{Child}
    }
</script>

```

↑初期状態。

###子にわたすデータを追加する
親は子に「はやく寝なさい」と伝えたいようなので、`msg:"はやく寝なさい"`を追加しました。

```Parent.vue
<template>
<Child></Child>
</template>
<script>
    import Child from "../components/Child";
    export default {
        components:{Child},
// ここから追加
        data(){ 
            return{
                msg:"はやく寝なさい"
            }
        }
    }
</script>
```
##子コンポーネントを準備
scriptタグで`props:以下省略`を設定します。

```Child.vue
<!--子コンポーネント-->
<template>
    <div>
        {{nanikaitteru}}
    </div>
</template>
<script>
export default {
    components:{},
//ここから追加
    props:{             
        nanikaitteru:{
            type:Text
        }
    }
}
</script>
```
子のほうは親に言われたことがまだわからないようで、「なにか言ってる」としか思っていないようです。

`nanikaitteru`と思っているので、一応`type:Text`に指定して受け取る準備をしました。
数字(int)が聞こえてきたら耳を塞ぐようです。

##子にデータを渡す
親のtemplateタグで、子にデータを渡します。

```Parent.vue
<template>
<Child :nanikaitteru = msg></Child>
</template>
```


親は子側で受け取る値を`nanikaitteru`に設定し、そこに`msg`を送ります。
※子側で受け取る値は絶対もっとわかりやすいものでよいです。親側のデータ名と同じmsgでも絶対いいです。

##おまけ
親の`template`タグの中身を
日常会話で表現するならば
「〇〇！『なにか言ってる』って思ってるんでしょうけど、”はやく寝なさい”と言っているの！」
でしょうか。
大体、調べると子が受け取るプロパティ名と親が渡すデータ名は同じなので、よくわからない”呪文”のように思っていたけど、仕組みがわかるとなるほど〜って感じがする。
そもそもカタカナが嫌い。:sob::sob::sob:

次はプロップスの中身を配列にしていく話をします。

#参考にしたもの
[Vue.js公式 -プロパティ](https://jp.vuejs.org/v2/guide/components-props.html?)
[Vueのpropsの使い方](https://www.e-loop.jp/knowledges/3/#Vue%E3%81%AEprops%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9)
C# XMLファイルから特定の要素を一括取得する

# やりたいこと

次のようなXMLファイルから、animalsやfishesなどを無視して、nameタグで囲われた要素を一括で取得したいとします。
この場合、**Descendants**メソッドが使用できます。

```XML:test.xml
<?xml version="1.0" encoding="utf-8"?>
<example>
	<animals>
		<animal>
			<name>cat</name>
		</animal>
		<animal>
			<name>dog</name>
		</animal>
	</animals>
	<fishes>
		<fish>
			<name>tuna</name>
		</fish>
		<fish>
			<name>salmon</name>
		</fish>
	</fishes>
</example>
```

# 例

次のコードのように、Descendants("name")とすることで、XMLの子孫要素からnameを検索し、IEnumerable\<XElement\>として一括取得できます。

```C#:Program.cs
using System;
using System.Collections.Generic;
using System.Xml.Linq;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(@"test.xml");
            IEnumerable<XElement> elems = doc.Descendants("name");
            foreach (XElement elem in elems)
            {
                Console.WriteLine(elem.Value);
            }
        }
    }
}
```

上記のコードは、取得したあとにforeachで各要素をコンソールに出力しています。出力結果は次のようになります。

```
cat
dog
tuna
salmon
```

# 参考


公式ドキュメント
https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.linq.xcontainer.descendants?view=netcore-3.1#moniker-applies-to
flutter：ネット上の画像をurlで指定してページに表示する

# やりたいこと

インターネット上の画像ファイルをurlで指定して、その画像をページに表示させたい。
例えば、無料壁紙
https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg
を表示させてみる。


# 実装

## httpパッケージを入れる。

https://qiita.com/kenichiro-yamato/items/ce7d77e9c733c24024d8
の方法で、

```dart
import 'package:http/http.dart' as http;
```

を、main.dartに記述する。





## 画像を設置する。

ネット上の画像は、

```dart
          child: Image.network('https://sample.co.jp/xxxxx.jpg'),
```

で指定する。









# 完成形ソース main.dart

```dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: Image.network('https://www.10wallpaper.com/wallpaper/1366x768/2005/Mountains_Rocks_Lake_2020_Landscape_High_Quality_Photo_1366x768.jpg'),
      ),
    );
  }
}

```



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/f957cb70-aeb2-aa90-8b4e-e90a965cd3d7.png)
Googleの検索窓の候補をCtrl（caps lock）＋N/Pでカーソル移動できるようにする

#前提
- Mac
- Caps Lock を Control キーとして使っている
- [Karabinar-Elements](https://karabiner-elements.pqrs.org/) を使っている

おそらくKarabinarを使っている時点で、そのやり方は分かる人が多いはずだ。しかし筆者のように Caps Lockキーの変更の仕方によってはインポートしたKarabinarのルールがうまく動作しないことがあるためこのQiitaを書く。

#先につまづきポイント
まず[KarabinarにはCtrl+P/NをUp/Downに変更するルール](https://ke-complex-modifications.pqrs.org/?q=Ctrl%2Bp%2FCtrl%2Bn%20to%20arrow%20up%2Fdown
)が公開されいる。しかしMacの標準のキーボード＞修飾キー設定で Caps Lock キーを Control にしてしまっていると、Karabinar側でのCtrl+P/Nの変更が反映されない。
<img width="417" alt="スクリーンショット 2020-05-27 16.17.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/bfc84c43-1180-b862-7c95-a116a3ea5682.png">
そのため、こちらもKarabinarの`Simple modifications`の設定で変更してやる必要がある。
<img width="1002" alt="スクリーンショット 2020-05-27 16.16.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/d603f714-407d-1218-cdcc-230468229acf.png">


#本題
Chromeを使っているとURL欄で検索したときはCtrl+N/Pで上下のカーソル移動ができ検索候補をマウスや矢印キーを触ることなく（ホームポジションを崩さずに）選択できる。
<img width="1358" alt="スクリーンショット 2020-05-27 16.18.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/eb9fda5b-77c8-0fd1-c429-9a9d185a7cbf.png">
しかし通常のGoogleのページ内の検索窓では以下の状態の時にCtrl+P/Nを押してもカーソル移動ができない。
<img width="889" alt="スクリーンショット 2020-05-27 16.19.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/0b24e1e1-7e61-3e95-62b3-26549c991d86.png">

#Karabinarのルールのインポートと有効化
そこで以下のリンクからKarabinarのルール`Ctrl+p/Ctrl+n to arrow up/down`をページ内検索して探しインポートして、Karabinar-Elementsアプリで有効化（Enable）してください（直リンクが取得できなかった）。
https://ke-complex-modifications.pqrs.org/?q=Ctrl%2Bp%2FCtrl%2Bn%20to%20arrow%20up%2Fdown
<img width="1150" alt="スクリーンショット 2020-05-27 16.22.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/86443f2e-ab76-5a7f-f22f-e6a16b3093f9.png">
以下のようになっていればOK。
<img width="1000" alt="スクリーンショット 2020-05-27 16.17.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/1b535c3d-92d8-33c2-71e5-243e616e9e2e.png">
 
これでサイト内の検索窓でもCtrl（Caps Lock）＋N/Pで上下のカーソル移動ができるはずだ。
パソコンの画面を他のパソコンに出力して表示させる方法

#パソコンの画面を他のパソコンに表示させる


同僚にファイルやパワーポイントを見せたいとき、
直接的にパソコンの画面を同僚のパソコンにミラーリングして表示させるのは便利でしょう。

最近「画面ミラーリング」という技術を利用してデバイスの画面を共有するのは人気になっているようです。
インターネットで調べてみると、iPhone、Androidスマホをパソコンにミラーリングする方法もたくさんあります。
**しかし、パソコンをパソコンにミラーリングする方法**は多くではありません。

この記事はPC画面をほかのPCに表示する最適な方法を紹介させていただきます。

##事前準備
二台のパソコン(**Miracastに対応する必要があります。**)
パソコンのシステム：Windows7/8/8.1/10
画面ミラーリングアプリ(この記事では[LetsView](https://letsview.com/jp/) という無料のアプリを例として操作します。[ApowerMirror](https://www.apowersoft.jp/phone-mirror)というミラーリングアプリもおすすめです。)

##操作手順
**パソコンAの画面をパソコンBに出力して表示させる場合、パソコンAは発信端末、パソコンBは受信端末と呼ばれます。**
1.パソコンA（発信端末）とパソコンB（受信端末）を同じWi-Fiネットワークに接続しておきます。
2.パソコンA（発信端末）とパソコンBに[LetsView](https://letsview.com/jp/) をダウンロードして、起動します。(両方ともインストールしてください。)
[LetsViewダウンロード](https://download.aoscdn.com/down.php?softid=letsview) 
3.パソコンAとパソコンBで「PC画面ミラーリング」を選択します。
![screenshot_20200527_151744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/a4431d55-991e-ee88-efa7-1e47ebffbd5b.png)

4.パソコンAにパソコンBの画面に表示しているミラーリングコードを入力します。
![screenshot_20200527_152750.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/2d669e55-2791-8f07-2c1b-143174a62eca.png)


5.パソコンAの画面に「ミラーリング」が出てから、クリックします。

![screenshot_20200527_153325.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/d9b2e3ab-89f8-15d5-0e32-08f6b5336687.png)


6.そして、パソコンBの画面の右下にミラーリングの許可リクエストが出たあと、「許可」を選択します。
![screenshot_20200527_152601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417797/c6ceaa39-c120-574b-edd5-286f5e3ebf65.png)


上記の手順に従うだけで、パソコンの画面をほかのパソコンにミラーリングして表示させることができます。
ＨＴＭＬフォーム部品

```html
①valueで初期値を設定
<input type="text" value="hello">

②password入力用の部品で文字が伏字になる
<input type="password">

③placeholderで入力例を記載する
<input type="test" placeholder="住所">

④labelを付けてあげると、何を書くべきかが分かりやすくなる。
そして、for文とidで紐づけをきちんと行うと、labelをクリックしたときに、
inputタグにfocusがあたる。
また、ＨＰなどの読み上げ機能の際には、紐づけしてあると名前が読み上げられる。

<label for="name">名前</label>
<input type="text"　id="name">

下記のように略すこともできる
<label>名前<input type="text"></label>

⑤ドロップダウンリスト
size="2"を選択すると、2行分表示される
multipleは複数選択可能
selected属性は最初から項目指定ができる

<select size="2"　multiple>
<option>1</option>
<option selected>2</option>
</select>

⑥チェックボックス
<input type="checkbox">andorid
<input type="checkbox">ipad

ラベルと紐づけすると、文字をタップしてもチェックされる
<label><input type="checkbox">iphone</label>

最初からチェックする
<input type="checkbox" checked>andorid

グループ化する（複数選択）
<fieldset>
<legend>携帯端末</legend>
<input type="checkbox">andorid
<input type="checkbox">ipad
</fieldset>

⑥ラジオボタン
ラジオボタンは、name属性で同じ項目の質問だよと
してあげないと複数選択できるようになってしまう。

<fieldset>
<legend>携帯端末</legend>
<input type="radio" name="phone">andorid
<input type="radio" name="phone">ipad
</fieldset>

⑦ボタンを押せなくする
<input type="button" disabled>
```
VMware仮想マシン(RHEL)のNIC名を修正する方法

RHELやCentOSなどのVMware仮想マシンを構築すると、NICがなぜか`ethX`ではなく`ensXXX`や`enoXXX`になります。
普段使う分には問題は特にありませんが、パッケージソフトでまれにNIC名が`eth0`である前提のソフトがあり問題が起きます。
修正する方法をメモとして残しておきます。（コマンドはCentOS上で実行した結果を記載しています。RHELの場合適宜読み替えて下さい。）

## ブートローダーオプション追加
### BIOSシステムの場合
```shell-session:
# cp -p /etc/default/grub /etc/default/grub_default
# vi /etc/default/grub
# cp -p /boot/grub2/grub.cfg /boot/grub2/grub.cfg_default
# grub2-mkconfig -o /boot/grub2/grub.cfg
```

```shell:/etc/default/grub
...
# 修正前
GRUB_CMDLINE_LINUX="rd.lvm.lv=VolGrp00/swap rd.lvm.lv=VolGrp00/root rhgb quiet"
# 修正後
GRUB_CMDLINE_LINUX="rd.lvm.lv=VolGrp00/swap rd.lvm.lv=VolGrp00/root rhgb quiet biosdevname=0 net.ifnames=0"
...
```


### UEFIシステムの場合

```shell-session:
# cp -p /etc/default/grub /etc/default/grub_default
# vi /etc/default/grub          ※編集内容はBIOSシステムと同じ
# cp -p /boot/efi/EFI/centos/grub.cfg /boot/efi/EFI/centos/grub.cfg_default
# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
```


## NIC設定の変更
インターフェース名が「ens192」と仮定しています

```shell:
# cd /etc/sysconfig/network-scripts
# mv ifcfg-ens192 ifcfg-eth0
# vi ifcfg-eth0
# systemctl restart network
```

```shell:ifcfg-eth0
...
# 修正前
DEVICE=ens192
NAME=ens192
# 修正後
DEVICE=eth0
NAME=eth0
...
```

上記作業で変更されなければ、マシンを再起動することで適用されます。
Alibaba Cloud OSSを使った静的Webサイトの公開方法

# Static Website の構築
他のクラウドと同様に、Alibaba Cloudにもオブジェクトストレージを使った静的ウェブサイトを公開する事ができます。わざわざサーバを用意する必要がないので便利ですよね。

# OSS（Object Storage Service）の設定
それでは、実際に管理画面から静的ウェブページを作ってみようと思います。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/1692cf2a-b1af-4b7e-6690-053c62af4371.png)
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/afbb11ac-69d9-9ea7-dedd-7f25da483d79.png)
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/07e11e6a-36a5-5389-866e-eaed84d27c50.png)
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/759d88f9-6c64-357b-619c-d0297d9aeaac.png)
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/adc31d71-c734-b07f-2f07-6e8ff0bf6845.png)
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/d07fc92a-305e-f0dc-2824-46a5ae5d7c8c.png)
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/b3980125-08db-4f69-bdc4-80647361f642.png)
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/97e62423-f159-969c-5dcc-f6fb421af8b1.png)
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/bcbe8837-619c-b0a2-a6eb-962e0e1f4cbb.png)
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/2b330e8c-1659-e219-91c4-41c46e2691c7.png)
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/bdea19ad-545c-59a4-19b9-cb33ad5dd6a9.png)

``` index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello</title>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>Hello World.</h1>
  </body>
</html>
```

``` 404.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello</title>
    <meta charset="utf-8">
    <style>
      html{
        display: table;
        height: 100%;
        width: 100%;
        text-align: center;
      }
      body{
        display: table-cell;
        vertical-align: middle;
      }
    </style>
  </head>
  <body>
    <h1>Error 404: Page not found</h1>
    <p>Sorry, but the page you were trying to view does not exist.</p>
  </body>
</html>
```

# アクセスして確認する

以下のURLが作成されたのでアクセスすると無事に表示できました。
https://staticweb-sample.oss-ap-northeast-1.aliyuncs.com/

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/a2e3887a-3299-8a44-89a4-71237a8d3063.png)

存在しないページにアクセスすると404.html が表示されます。
https://staticweb-sample.oss-ap-northeast-1.aliyuncs.com/aaa

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18582/c28e5e34-5b3e-5a23-0c4d-1e08852dc1c6.png)

# まとめ
静的コンテンツを簡単に公開する事ができました。独自ドメインの設定などもできるようなので実運用でも問題なく使えるのではないでしょうか。
iOS13.5 Safari でページがスクロールできないバグの解消

#iOS13.5バグ発生
複雑なコードの一部のため、細かい発生条件の切り分けまでできていませんが…
高さを指定した```div```に```overflow:auto```指定をして、画面内でスクロールするコンテンツが、OSアップデートしたとたん動かなくなりました。

#解決法
いろいろ試し、結果として、以下が判明しました。
- CSSの```overflow```の値を再定義してやればスクロールできるようになる。
- ただし、２度同じ再定義をしても、以後はスクロールできるようにならない。

※```div```の中のHTMLを動的に書き換えるコンテンツだったため、スクロールが必要だったり必要なかったりします。

##コード
結果として、すごくびみょうな方法ですが…値として```auto```と```scroll```を交互に入れ替える方法で解決しました。

```JavaScript
//表示されてから実行するために、setTimeoutで遅延。
setTimeout(function(){
	
	if($(target).css('overflow')=='auto'){
		$(target).css('overflow','scroll');
	}else{
		$(target).css('overflow','auto');
	}
},100);
```
Shoryuken の worker を Rails console で実行

SQS への enqueue が何らかの AWS のサービスによるものだった場合、テストがしづらいことがあるので、 Rails console で叩いて動作確認できるようにする方法

name | version
----|----
shoryuken | 5.0.1
rails | 5.2.4.1
aws sdk core | 3.56.0
aws sdk sqs | 1.17.0 


```ruby
$ rails console
[1] pry(main)> worker = SomethingSqsWorker # please change
[2] pry(main)> body = {} # please change
[3] pry(main)> endpoint = "" # config などで設定
[4] pry(main)> client = Aws::SQS::Client.new(endpoint: endpoint)
[5] pry(main)> message = Shoryuken::Message.new(client, Shoryuken::Queue.new(client, worker.shoryuken_options_hash["queue"]), Aws::SQS::Message.new(queue_url: queue.url, receipt_handle: "receipt_handle"))
[6] pry(main)> worker.new.perform(message, body)
```

`receipt_handle` は普通特に参照しないのかなと思って適当な文字列にしてあります。適宜変えてください

## snippet
worker, body, endpoint を設定したあとの実行部分です。繰り返し使うときは最後の行だけで ok です

```ruby
client = Aws::SQS::Client.new(endpoint: endpoint)
message = Shoryuken::Message.new(client, Shoryuken::Queue.new(client, worker.shoryuken_options_hash["queue"]), Aws::SQS::Message.new(queue_url: queue.url, receipt_handle: "receipt_handle"))
worker.new.perform(message, body)
```

一行を長くしたくない人向け

```ruby
client = Aws::SQS::Client.new(endpoint: endpoint)
queue = Shoryuken::Queue.new(client, worker.shoryuken_options_hash["queue"])
sqs_msg = Aws::SQS::Message.new(queue_url: queue.url, receipt_handle: "receipt_handle")
message = Shoryuken::Message.new(client, queue, sqs_msg)

worker.new.perform(message, body)
```

一行にこだわりたい人向け

```ruby
Aws::SQS::Client.new(endpoint: endpoint).instance_eval { worker.new.perform(Shoryuken::Message.new(self, Shoryuken::Queue.new(self, worker.shoryuken_options_hash["queue"]), Aws::SQS::Message.new(queue_url: queue.url, receipt_handle: "receipt_handle")), body) }
```
formatter-maven-pluginを使用したenumのフォーマット方法(Java)

#概要
[formatter-maven-plugin](https://github.com/revelc/formatter-maven-plugin) を使用してenumのコードの自動フォーマットを行います。


#実現したいフォーマット
###実行前

```
public enum Answer {

  YES(1),NO(2),MAYBE(3);
}
```

###実行後

```
public enum Answer {

  YES(1),
  NO(2),
  MAYBE(3);
}
```

#設定箇所
設定ファイル(xml)の `alignment_for_enum_constants` の値を `49` にすることで上記フォーマットをかけることができました。

```
    <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
```
WindowsでSSH接続のコマンドを打つと「Couldn't agree a key exchange algorithm」となるエラー解消

# 症状
* Windows 10 で ssh 接続のコマンドをコマンドプロンプト or PowerShell で打つとアラートが表示される

```
FATAL ERROR: Couldn't agree a key exchange algorithm (available: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256)
```

# 原因
* ssh コマンドを打ったときに PuTTY Link: command-line connection utility 経由になってしまっている
* PuTTY の ver. が古いせい
* [Gow ( Gnu On Windows )](https://github.com/bmatzelle/gow) がインストールされている

# 解決
* Gow をアンインストールする

# 感想
* ここ最近で一番ハマッてしまった……
【GitHub】アカウント名を変更するときの注意点

## どんなとき？

- アカウント名の大文字小文字しか変更しない場合
- 元のアカウント名に戻す場合


## 事の次第

私は普段「aiandrox」というアカウント名を使っています。
ただ、GitHubは「Aiandrox」というアカウント名でした。それがちょっと気になったので統一したいと思い、「aiandrox」に変更できないのかと思ったところ、アカウント名の変更はできるようでした。

> 
ユーザ名は、現在使われていない別のユーザ名に変更できます。希望するユーザ名が使えない場合、そのユーザ名を入力したときに、ユーザ名のリリースをリクエストできるかについての情報が表示されます。
（中略）
ユーザ名を変更すると、変更前のユーザ名は誰でも取得できるようになります。 古いユーザ名の下にあるリポジトリへの参照のほとんどが、自動で新しいユーザ名に変わります。 ただし、プロフィールへのリンクによっては、自動的にリダイレクトされません。
[GitHub ユーザ名の変更](https://help.github.com/ja/github/setting-up-and-managing-your-github-user-account/changing-your-github-username)

が、大文字と小文字は同じと判断されるようで、直接変更することができませんでした。
<img width="487" alt="スクリーンショット 2020-05-27 15.04.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/403c566f-adc1-34d9-f58c-d516987e446e.png">

なので、一旦「aiandroxA」という名前にした後に変えようとしたところ、以下のようなエラーが出て、元に戻せなくなってしまいました。
<img width="1438" alt="スクリーンショット 2020-05-19 13.46.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/24fdbf85-d3cf-d36c-d003-e16d2cebe5ed.png">
> Username change was not successful. The repository name aiandrox/hashlog has been retired and cannot be reused.

hashlogというのはリポジトリの名前です。


## 公式に問い合わせてみた

経緯を説明して、「リポジトリ名を変更せずに、アカウント名を『aiandrox』に変更したい」ということを伝えました。
翻訳はDeepLにお世話になりました。英語としておかしなところはあったかもしれませんが、伝わればいいでしょう。
そして一週間後、返信が来ました。

要約すると、

- これは人気なリポジトリのなりすましを防ぐ制限によるもの。
- でも、実際のリポジトリはあなたのものなので意図した目的を果たしていない。
- 一旦そのリポジトリ名を変更した後にアカウント名を戻せば大丈夫。
- その後、連絡をしてくれれば名前空間の制限を解除する。

例えば、有名なライブラリ`hoge`があったとして、その作成者`foo`が名前を変更した場合、`foo/hoge`という名前空間（ここではURL）が空くわけです。
ここで、悪意のある第三者がユーザー名を`foo`にして、`hoge`というリポジトリを作成すると、`foo/hoge`で好きなソースを公開できます。
そして、他の人は（URLが同じなので）安全なライブラリだと信じてcloneしてしまうかもしれません。
そういうことを防止するための機能らしいです。

人気の基準が今一つわかりませんが、スターが2つ付いていたので、多分そのせいかと思います。
ということで、「hashlog」というリポジトリの名前を「hashlogA」にすると、アカウント名を「aiandrox」に変更することができました！
そして、再び公式に連絡をして制限を解除してもらったのでリポジトリ名も元に戻すことができました。


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

最初からこのようなことが起こらないようにするためには、

1. 制限がかかる可能性のあるリポジトリを仮の名前（hashlogAなど）に変更
2. アカウント名を仮の名前（aiandroxAなど）に変更
3. アカウント名を変えたいものに戻す（aiandrox）
4. リポジトリ名を元に戻す（hashlog）

という順序で、名前を避難させる前にリポジトリ名も変えて`aiandrox/hashlog`の場所を空けておくことが必要です。

また、もし制限によって戻すことができなくなった場合は、自分ではどうしようもないので公式にお願いをするということになるようです。