OmniAICreator/Qiita-1.07M huggingface dataset:
WebページのGoogle翻訳がアプリっぽかった

これは[Google翻訳](https://translate.google.co.jp/)のHTMLの最初の方。

```html
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Google 翻訳">
<meta name="apple-mobile-web-app-title" content="Google 翻訳">
<meta name="theme-color" content="#4285F4">
<meta name="msapplication-tap-highlight" content="no">
<link rel="manifest" crossorigin="use-credentials" href="_/TranslateWebserverUi/manifest.json">
<link rel="home" href="/?lfhs=2">
<link rel="msapplication-starturl" href="/?lfhs=2">
<link rel="icon" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
<link rel="apple-touch-icon-precomposed" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
<link rel="msapplication-square64x64logo" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
```

# スマホのホーム画面に追加をアプリっぽくする

```html
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
```

# アプリ名

```html
<meta name="application-name" content="Google 翻訳">
<meta name="apple-mobile-web-app-title" content="Google 翻訳">
```

# マニフェスト

```html
<link rel="manifest" crossorigin="use-credentials" href="_/TranslateWebserverUi/manifest.json">
```

# アイコン

```html
<link rel="icon" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
<link rel="apple-touch-icon-precomposed" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
<link rel="msapplication-square64x64logo" href="//ssl.gstatic.com/translate/favicon.ico" sizes="64x64">
```
Salesforceで特定の日付が入った場合特定のテキストの入力が必要な時の入力規則

入力規則の数式は

AND(
NOT(ISBLANK(test1__c)),
ISBLANK(test2__c))

　です。
これであればtest1__c項目に記載がある場合、test2__c項目を記載しないとエラーが発生します。
（test__c,test2__cをご自身のAPI参照名に変更してください。）
【Rails】Routingのカンペ（scope / namespace / module / action / as / コロン / constraintsの意味）

# はじめに
<!-- 発端や概要を記載 -->
routesの読み方で不安になった時用のカンペです。
scope / namespace / moduleの根本の動作が知りたい方はこちらが参考になります。
https://qiita.com/ryosuketter/items/9240d8c2561b5989f049

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [まとめ](#まとめ)
    1. [scope](#scope)
    1. [module](#module)
    1. [namespace](#namespace)
    1. [as](#as)
    1. [コロン](#コロン)
    1. [constraints](#constraints)



<!-- 各チャプター -->
<a id="#まとめ"></a>
# まとめ
<a id="#scope"></a>
## scope
scopeに指定した文字が**urlにのみ**影響する
<a id="#module"></a>
## module
moduleに指定した文字が**ファイル構成にのみ**影響する
<a id="#namespace"></a>
## namespace
namespaceに指定した文字が**url、ファイル構成、Prefixの全て**に影響する
<a id="#as"></a>
## as
Prefixをオーバーライドする
<a id="#コロン"></a>
## コロン
動的に変化する部分
<a id="#constraints"></a>
## constraints
コロン部分の制約を設定
Swagger UIでOAuth認証をする時にauthorizationUrlを環境ごとに切り替える

OpenAPI3.0では`servers`に複数のURLを設定することで、Swagger UIでローカル/開発/本番環などリクエスト先を切り替えることができます。

```yaml
openapi: 3.0.0
info:
  description: サンプルAPI
  version: 1.0.0
  title: Sample API
servers:
  - url: http://localhost:8000
    description: ローカル開発環境
  - url: https://dev.api.com
    description: 開発環境
  - url: https://api.com
    description: 本番環境
```

![Screen Shot 2022-01-14 at 15.38.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368271/28339717-f099-b7f4-3518-242b41e9defc.png)

また、OAuth2.0で認証が必要な場合は`authorizationCode`に認可エンドポイントとトークンエンドポイントを設定することで、Swagger UIがOAuth認証のメニューを生成してくれます。
(次のコードは認可コードフローの例です。)


```yaml
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://api.com/auth
          tokenUrl: https://api.com/token
```

![Screen Shot 2022-01-14 at 15.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368271/7014f9ab-a761-0fe6-956d-c77e0fa3b932.png)

`authorizationCode`についても`servers`と同じように複数環境分を設定し、それがserversと一緒に切り替わってくれることを期待したのですが、`authorizationCode`は複数の環境に対応しておらず、単に次のように列挙するだけではエラーになってしまいます。

```yaml
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: http://localhost:8000/auth
          tokenUrl: https://localhost:8000/token
        authorizationCode:
          authorizationUrl: https://dev.api.com/auth
          tokenUrl: https://dev.api.com/token
        authorizationCode:
          authorizationUrl: https://api.com/auth
          tokenUrl: https://api.com/token
```

このような場合は、`authorizationCode`をドメインからの相対パスで書くことで解決できます。

```yaml
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: /auth
          tokenUrl: /token
```

`authorizationCode`はセキュリティ上の問題からパラメータの埋め込みには対応していないようなので([参考](https://github.com/OAI/OpenAPI-Specification/issues/551))、環境ごとに認可・トークンエンドポイントが異なる場合は現状手立てがなく、authorizationCodeを毎回書き換えるしかなさそうです。
Xcode + Swift でiPhone用 地図アプリ。（23日目）　完成？

#今日やった事

・ストーリーボードでボタンを3つ作成（種別）
・ボタンのクリックイベント作成
・ボタンクリック後、MySQLサーバーへデータ送信
・データ送信結果をダイアログで表示（OK or ERROR）


#コード

```swift:ViewController.swift
    //クリックイベント（３個）
    @IBAction func Trash01(_ sender: Any) {
        print("[DBG] : TRASH 01" )       
        HttpGET(data:"0")
    }
    @IBAction func Trash02(_ sender: Any) {
        print("[DBG] : TRASH 02" )
        HttpGET(data:"1")
    }
    @IBAction func Trash03(_ sender: Any) {
        print("[DBG] : TRASH 03" )
        HttpGET(data:"2")
    }

...
    // Http
    func HttpGET(data:String){
        let data:String = DateTime() + ","+data+"," + longitude + "," + latitude
        // BASIC AUTH
        let username = "(ID)"
        let password = "(PASS)"
        let session = URLSession.shared
        guard let url = URL(string: "（URL）/hoge.php?huga="+data) else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        guard let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8) else { return }
        let credential = credentialData.base64EncodedString(options: [])
        let basicData = "Basic \(credential)"
        request.setValue(basicData, forHTTPHeaderField: "Authorization")
        session.dataTask(with: request) { data, urlresponse, error in
            if let error = error {
                self.ErrorDialog(data:"送信 ERROR")
                return
            }        }.resume()
        self.ErrorDialog(data:"送信 成功")
        
    }

    //確認ダイアログ
    func ErrorDialog(data:String){
        let alert: UIAlertController = UIAlertController(title: "確認", message:  data, preferredStyle:  UIAlertController.Style.alert)
        let confirmAction: UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler:{
            (action: UIAlertAction!) -> Void in
        })
        alert.addAction(confirmAction)
        present(alert, animated: true, completion: nil)
        
    }
```

#完成

![イメージ7569.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/b553c6ea-158a-919e-46b5-774ecac4e2e3.jpeg)
作成したボタンをタップする事で、WEB上のMySQLサーバへデータの記録が出来ることを確認。
失敗した場合は、ダイアログで確認できるようにしています。

最小限の機能のみですが、一応、完成。

Kotlinと比較すると、swiftの方は、初日の環境作成を含めて３日程で、比較的楽に作る事が出来ました。

後は、ボタンに画像を表示したり、設定画面を作るなど…。

これまでの流れで、[androidアプリ]、[iPhoneアプリ]、[MySQLサーバ]、[WEBサイト]と一通り全部作り終えたので、一旦、これで閉めるかもしれません。


#参考サイト

https://thinkit.co.jp/article/14301

https://qiita.com/siropaca/items/559f9844b4e2973301e3

https://qiita.com/kaneko77/items/010c3836a1a063ad015e

https://qiita.com/takehiro224/items/1c0560e5635434f36592

https://qiita.com/yosshi4486/items/c1f24863b2e47ab4780d

https://stackoverflow.com/questions/41470147/call-to-method-in-closure-requires-explicit-self
neosでlogix その46

# 概要

niosでlogixやってみる。
Children Countノード
Get Childノード使ってみた。

# 写真

![2022-01-14 08.31.23.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6d8047a8-7d75-58ed-e6e5-316330af24c7.jpeg)


# Children Count

```
Inputs
 	Slot	Instance
Outputs
 	Int	*
```

# Get Child

```
Inputs
 	Slot	Instance
 	Int	ChildIndex
Outputs
 	Slot	*
```

# 手順

- logixtooltipを装着。
- ノードブラウザを表示
- Slots>Root Slotをスポーン
- Slots>Get Child をスポーン
- Flow>Forをスポーン
- Slots>Children Count をスポーン
- Slots>Get Slot Nameをスポーン
- Input>Stringをスポーン
- つなぐ

以上。
Obsidianの小技その8｜とてもかんたんにノートに画像を貼る

## はじめに

つねに開きっぱなにしているMarkdownメモツール[Obsidian](https://obsidian.md)。脳に余白をつくり、ストレスフリーになれる、いいかんじの小技をご紹介してみたいとおもいます。

## ノートに画像を貼る

ノートに画像を貼ると便利だということを、小技7で書きました。
[Obsidianの小技その7｜ノートに画像を貼る - Qiita](https://qiita.com/hann-solo/items/86cedbbbdc5c6f5fab38)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/65153a83-c568-d0ec-65a4-5f0ceb959a17.png" width=50%>

でも、画像ファイルを用意するのもめんどうですし、タグを書くのもめんどうです。

```markdown
![なんでもいい](https://xxxxx.xx.xx)
![なんでもいい](file://フルパス)
```

スクリーンキャプチャを撮ってサクッとノートに貼り付けられるようになると、幸せになれます。

## Gyazoをつかう

Gyazoというご機嫌なサービスがありますので、下記リンクからダウンロードしてインストールします。
https://gyazo.com/ja

Gyazoアプリを起動し、スクリーン上で範囲を選択すると、スクリーンキャプチャが自動的にアップロードされ、ブラウザが開きます。ここで`マークダウンをコピー`をします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/aba572a2-61ad-995b-84c0-092303ee54e4.png" width=50%>

↓

```markdown
[![Image from Gyazo](https://i.gyazo.com/xxx.png)](https://gyazo.com/xxx)
```

Obsidianのノートで`貼り付け`をすると、あらふしぎ、ノートに画像が貼り付きます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/acfea1fc-ce2b-5188-4961-dc54d86a550b.png" width=50%>

Gyazoは無料版でも、画像は何枚もアップロードできます。Obsidianと組み合わせたときの体験はかなり良いです。

## おわりに

文字で書くと長いですけれど、`Gyazo起動＆スクリーンキャプチャ`→`リンクコピー`→`Obsidian貼り付け`はとてもスムーズです。ほんとうに「サクッと」ノートに画像を貼れます。Wordに画像を貼るよりよほどスムーズです。

ついでながら、Gyazoの`マークダウンをコピー`のコードはあまり美しくないので、わたしは`画像リンクをコピー`にして、スニペットツールで

```markdown
![img|300](https://i.gyazo.com/xxxxxx.png)
```

といったマークダウンを生成しています。`[img|300]`の部分では、横幅をピクセルで指定（この場合は300ピクセル）しています。

スニペットおよびGyazoなどのアプリケーションランチャーにはAlfredをつかっています。これらの小技もまた別の機会にご紹介したいとおもいます。

### ご参考

[Obsidian｜使いかたとコツ（目次）](https://qiita.com/hann-solo/items/ac8fa75394813e8adcf4)
【JavaScript】qerySelectorによるDOMの取得

## `document.querySelector` / `document.querySelectorAll`で要素を取得する

* `document.querySelector`と`document.querySelectorAll`の違い
    * document.querySelector
        *  一致する要素のうち、先頭の1件を取得する
        *  idを指定する場合、`document.getElementById() `で取得するほうが高速である
    * document.querySelectorAll
        *  一致する要素のリストを取得する

## セレクター

|セレクター|説明|例|
| :- | - | - | 
| (*) | 全ての要素を取得 | document.querySelectorAll('*'); |
| (#id) | 指定したIDの要素を取得 | document.querySelector('#sample-id'); |
| (.class) | 指定したクラス名の要素を取得 | document.querySelectorAll('.sample-className'); |  
|（タグ名） | 指定したタグ名の要素を取得 | document.querySelectorAll('li'); |  
| (複数指定) | 指定したいずれかのセレクターに合致する要素をすべて取得 |  document.querySelectorAll('#sample-id,.sample-className,li'); |
| (parent > child) | parent要素の子要素のchildを取得 | document.querySelector('ul > li'); |
| (prev + next) | prev要素の直後に存在するnext要素を取得 | document.querySelector('div + ul'); |
| (prev + siblings) | prev要素以降のsiblings兄弟要素を取得 | document.querySelector('div ~ span'); |
| [attr] | 指定した属性を持つ要素を取得 | document.querySelector('[data-attr]'); |
| [attr=value] | 属性がvalue値に等しい要素を取得 | document.querySelector('[data-attr="123"]'); |
| [attr^=value] | 属性がvalueから始まる値を持つ要素を取得 | document.querySelector('[data-attr^="12"]'); |
| [attr$=value] | 属性がvalueで終わる値を持つ要素を取得 | document.querySelector('[data-attr$="23"]'); |
| [attr*=value] | 属性がvalueを含む値を持つ要素を取得 | document.querySelector('[data-attr*="2"]'); |
|[selector1][selector2][selectorx]| 複数の属性フィルタすべてにマッチする要素を取得 | document.querySelector('div#main[data-attr*="2"]'); |
|(:checked)| チェックボックス・ラジオボタンのチェック済み要素を取得 |  document.querySelectorAll('input[type="checkbox"]:checked') |
MarinDBのdelimiter

# delimiterについて
この記事は主の備忘録用の物です。
投稿初期のものなので、諸々許してください。

## 目的
MariaDBで、;を実行コマンドとして機能させないように、delimiterをつかおうと思ったのですが、すこし手こずりましたので、その解決方法の共有です。

### エラーの内容
'''
MariaDB [test_db]> delimiter//
    -> ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'delimiter//' at line 1
'''

### 解決方法
解決方法はいたってSimpleでした。

delimiterを大文字で使う

たったこれだけです。

以上でした。
Cloud9環境構築

# 認証情報の設定（Cloud9→AWSへの接続設定）

Cloud9を検索し、「Cloud9」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/df50d0c4-2504-7502-199e-efff1e0d3545.png)
 
Cloud9のTOP画面へ遷移し、「Create enviroment」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/be7be016-d0bc-301d-38c5-b3ebcdf3b340.png)

Name（必須）、Description（任意）を入力し、「Next step」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/17d63418-f7e1-291a-31ec-a52fc3e0c8dc.png)
 
デフォルト（変更なし）のまま「Next step」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/19f6c66f-fb99-db1e-cffa-fda782a21c36.png)

内容を確認し「Create enviroment」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/bed6bd24-d293-a95a-def6-ca45fe1a8ceb.png)
 
数分後と環境ができあがります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/bf4039ed-3963-3129-2df8-f5f08a7712a7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/d7d2958e-15d3-6ce7-e091-6d496826a802.png)

# 認証情報の設定（Cloud9→AWSへの接続設定）
右上ギア印→「AWS settings」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/ce03cf25-d71e-c852-dbe5-669070a3760f.png)
認証情報ファイル（Credentials）の変更モードを「不可→可」に変える為、「×→✓」へ一時的に変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/a37cee7f-923e-024c-bc8d-79e2cbb8f1bc.png)

「＋」タブ→「New Terminal」をクリックし、ターミナルを開くことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/3ff64d59-59f4-a48c-8746-c6d523f45bd2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/09a349a9-9c74-17f2-90c4-4eeda953fc9e.png)
 
開発用（IAM）ユーザにダウンロードした、認証情報（CSV）ファイルを参照し、順番に入力していきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/52af3e34-ed11-0636-f5f5-ccfdca642c3a.png)

Access Key ID：自分のアクセスID
Secret Access Key：自分のシークレットキー
Region：ap-northeast-1（Asia/Tokyo：東京）※固定値
Output format：json


```
$ aws configure
# 設定
$ cat ~/.aws/config
$ cat ~/.aws/credential
# 設定内容の確認
$ vim ~/.aws/credential
# plofileを[default→terraform]へ変更する
# vim → iコマンド(INSERT) ~※修正~ → Escキー → :wコマンド（保存）→ :qコマンド（終了）
```

以上でCloud9環境でTerraformを使えるようになりました。

## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8
エクセルの罠を検索する

保守や障害修正など、前回開発担当者と異なる場合に
エクセルの既存ドキュメントの罠を見つけて回避する

要はこっそり(非表示でもフィルタでもなく)幅や高さが小さくなっていて
確認漏れが無いか検索したい場合のチェック方法

## 既存ドキュメントがExcelの場合

1. 適当なブックを開く
2. Alt + F11などでVBAのウィンドウを開く
3. Ctrl + G か 表示 -> イミディエイトウィンドウで結果出力用のウィンドウを開く
4. 左のプロジェクトツリー右クリで挿入 -> 標準モジュール
5. 下記コード貼り付けて 
6. Sub内にカーソルを移動させた後F5で実行
7. エクセルのあるディレクトリを選択する。
8. イミディエイトウィンドウに見つかった箇所が出力される。
9. あとは目視で判断

```vb
Option Explicit

Sub check_trap()
    Dim files() As String
    Dim fol As String
    Dim count As Long
    Dim temp As String
    Dim wb As Workbook
    Dim ws As Worksheet
    Dim r As Long
    Dim c As Long
    Dim h As Long
    Dim w As Long
    Dim endr As Long
    Dim endc As Long
    
    
    fol = getFileList(files, count)
    If count = 0 Then
        Debug.Print "error: file not found."
        Exit Sub
    End If
    
    For count = 0 To UBound(files) - 1
        Set wb = Workbooks.Open(fol & "\" & files(count), False, True)
        For Each ws In wb.Worksheets
            endr = ws.Cells(60000, 1).End(xlUp).Row
            endr = Application.WorksheetFunction.Max(endr, 200)
            For r = 1 To endr
                h = ws.Cells(r, 1).EntireRow.Height
                If h < 10 Then
                    Debug.Print wb.Name & " " & ws.Name & " -> row:" & r & " h:" & h
                End If
            Next
        
            endc = ws.Cells(1, 255).End(xlToLeft).Column
            endc = Application.WorksheetFunction.Max(endc, 30)
            For c = 1 To endc
                w = ws.Cells(1, c).EntireColumn.Width
                If w < 2 Then
                    temp = ws.Cells(1, c).Address(True, False)
                    temp = Left(temp, InStr(temp, "$") - 1)
                    Debug.Print wb.Name & " " & ws.Name & " -> col:" & temp & " w:" & w
                End If
            Next
        Next
        wb.Close False
    Next
    
End Sub


Function getFileList(ByRef files() As String, ByRef count As Long)

    Dim fol As String
    Dim buf As String
    
    fol = getFolder()
    
    If Len(fol) = 0 Then
        Exit Function
    End If
    
    buf = Dir(fol & "\*.xlsx")
    count = 0
    Do While buf <> ""
        count = count + 1
        ReDim Preserve files(count) As String
        files(count - 1) = buf
        buf = Dir()
    Loop
    Debug.Print "filecount:" & count
    getFileList = fol
End Function

Function getFolder()
    With Application.FileDialog(msoFileDialogFolderPicker)
        .InitialFileName = "C:\"
        .AllowMultiSelect = False

        .Title = "フォルダの選択"
        If .Show = True Then
            getFolder = .SelectedItems(1)
        End If
    End With
End Function
```

設計書はasciidocで良さそうだけど
テキストベースの（履歴や差分がちゃんと追える）テスト項目書って無いかなぁ、、、
ニュース記事をスクレイピング

# はじめに
<!-- 発端や概要を記載 -->
Googleのニュースサイト（ https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en ）のデータを取得し、翻訳し、Firebaseに保管する方法について、まとめていきます。

Pythonを用いていきます。適宜、必要なライブラリは、インストールします。
必要なライブラリは、下の二つです。
- beautifulsoup4
- requests

# 目次
<!-- タイトルとアンカー名を編集 -->
1. ニュースサイト情報
1. スクレイピングのコード
1. 参考文献

<!-- 各チャプター -->
# ニュースサイト情報
ニュース記事は、https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en から取得します。開いたイメージは次のようになっています。
<img width="500px" alt="記事のページ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416886/db305241-5d10-320b-9bd4-227c76661d2b.png">

urlを変化させることで、検索ワードに関する記事を取得できる他、ニュースサイトの指定、期間の指定を行えます。具体的な手法は、下を参考にしてください。
参考：　[Google News Rss（API）](https://qiita.com/KMD/items/872d8f4eed5d6ebf5df1)

# スクレイピングのコード
スクレイピングには、主に2種類の方法が存在します。あくまで、使ってみた経験で話していきます。
1. urllib.requestとBeautifulSoupを使う方法
2. Seleniumを使う方法

1 を使うのは、比較的簡単なWebページの場合に限られます。現在のWebページの多くは、Java Scriptなどを用いた、動的なページが多いです。動的なページでは、うまく種得できません。今回のニュースページは、明らかに、人が閲覧するためのサイトではなく、スクレイピングするためのページです。ですので、今回は1 を使っていきます。

2 を使う場合が多いと、個人的には感じています。2 は、Google Chromeで検証ページに表示されるHTMLをそのまま、取得できます。汎用的な方法で、あらゆるタイプのサイトに使えます。しかし、処理が遅いことや、Chrome　driverを適切なバージョンにしておかなければなりません。

実際のコードは次のようになります。

```python:get_news.py
from urllib import request
from bs4 import BeautifulSoup

url = "https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en"
response = request.urlopen(url)
soup = BeautifulSoup(response,"xml")
response.close()
articles = soup.find_all("item")
```

1. urlを定義する
1. urlのページを開いた情報を取得する
1. 取得した情報をxml形式で、情報変化する
1. その中で、itemタグを持つデータを抜き出す

itemタグで、記事のデータがまとめられている。取得すると、一つ一つの記事は、次のようになっています。タイトルとid、投稿日時、説明、ソースがまとめられています。

```json:itemの中身
<item>
<title>Biden says he's "not sure" about voting bills' future after Sinema reiterates opposition to rule change - CBS News</title>
<link>https://news.google.com/__i/rss/rd/articles/CBMiTmh0dHBzOi8vd3d3LmNic25ld3MuY29tL25ld3Mva3lyc3Rlbi1zaW5lbWEtdm90aW5nLXJpZ2h0cy1zZW5hdGUtcnVsZXMtc3BlZWNoL9IBAA?oc=5</link>
<guid isPermaLink="false">1222244172</guid>
<pubDate>Thu, 13 Jan 2022 23:58:00 GMT</pubDate>
<description>説明部分は長いので、省略</description>
<source url="https://www.cbsnews.com">CBS News</source>
</item>,
```

そして、この記事ごとのデータを取得する方法としては、下に示します。下では、タイトルを取得する方法です。"title"の部分を、linkやsourceに変えて、欲しいデータを取得します。

```python:get_news.py
title = item.find("title").getText()
```

# 参考文献
- [ニュースサイト](https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en)
- [Google News Rss（API）](https://qiita.com/KMD/items/872d8f4eed5d6ebf5df1)
アーキテクチャ

# アーキテクチャについて
今回は下記のアーキテクチャを構築していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/f5a20c9b-516a-e231-db88-a9c6cf995f75.png)
aws.drawio

各構成の詳しい解説は下記しています。
①ETL・パイプライン(+モニタリング)：DataLake → Glue Workflow → Data Ware House → Moniterting

https://qiita.com/tk_tatsuro/items/cb02417c89b053b4aa06

②イベントソース・パイプライン：DataLake → Glue Workflow → Event Source

https://qiita.com/tk_tatsuro/items/20bc847d848bbb402860

## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8
ディレクトリ構造

# ディレクトリ構造について

```
terraform
　└main.tf
　└terraform.tfvars
　└variables.tf
　└modules/
　｜└s3/
　｜｜└s3.tf
　｜｜└variables.tf
　｜｜└output.tf
　｜└glue/
　｜｜└glue.tf
　｜｜└variables.tf
　｜｜└output.tf
　｜└athena/
　｜｜└athena.tf
　｜｜└variables.tf
　｜｜└output.tf
　｜└redshift/
　｜｜└redshift.tf
　｜｜└variables.tf
　｜｜└output.tf
　｜└sfn/
　｜｜└sfn.tf
　｜｜└variables.tf
　｜｜└output.tf
　└src/
　｜└job/
　｜└query/
　｜└function/
　└data/
```

# 各ファイルの概要
## s3.tf
（S3の）モジュール・ファイル
　※S3の構成をまとめ、モジュールとして定義するファイル

## main.tf
モジュールを呼び出し、変数の受け渡しを行うファイル

## terraform.tfvars
環境変数の定義ファイル（≒ envファイル）※値を保持している。

## variables.tf
入力変数の定義ファイル（※定義のみ保持している）
他のtfファイルから受け取る変数を定義する。

## output.tf
出力変数の定義ファイル
※他のモジュールへ出力する変数を定義する。


# ファイル間の関係
main.tfが各モジュール（s3.tf、glue.tf）を呼び出す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/b195b648-f9d0-f8cd-ab5f-1752cdd4391c.png)

 
main.tfはモジュールの呼び出し時、変数を渡すことができる。
※詳しくは「ブロック」のページで紹介します。

https://qiita.com/tk_tatsuro/items/e603a5073485c50842bb

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/0341d5b5-79cc-b8db-4baf-9518bd161497.png)

各モジュール内で定義したリソースを、main.tf経由で他のモジュールへ橋渡しすることができます。
※詳しくは「ブロック」のページで紹介します。

https://qiita.com/tk_tatsuro/items/e603a5073485c50842bb


## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8
【備忘録】Instagram Graph APIを使用してWEBページに正方形の画像を埋め込む

Instagram Graph APIを使用してInstagramの画像をwebページに埋め込む際に、少し手間取ったので備忘録として。

#実現したいこと
Instagram Graph APIを利用してInstagramから取得した画像をwebページに埋め込み、正方形のグリッド状に配置したい。

#実装
Instagramのプロアカウント作成からwebページへの埋め込みまでは<a href="https://arrown-blog.com/instagram-graph-api">こちら</a>を参考に行った。

#実装後に起きた問題

1. 画像が表示されない。
2. 画像をクリックしても投稿に飛ばない。
3. 取得された画像サイズが正方形ではないのでレイアウトが崩れる。

#原因

###画像が表示されない。
* phpファイル内のGraph APIのバージョンが最新ではなかった。
* 目的のInstagramアカウントの投稿数が、Graph APIで取得する数（javascriptファイルの`photo_length`の値）より少なかった。
* javascriptファイル内のphpファイル指定がうまく動作しなかった。

###画像をクリックしても投稿に飛ばない。
* 投稿へのリンクの値である`permalink`を取得していなかった。

###取得された画像サイズが正方形ではないのでレイアウトが崩れる。
* 対策を後述。 

#修正点
###画像が表示されない。
* phpファイルの`$instagram_api_url`内のGraph APIのバージョンを最新のものに書き換える。
* 「取得する画像の数 ≦ 目的のアカウントの投稿の数」にする。
* javascriptファイル内のphpファイル指定を相対パスから絶対パスに変更。

###画像をクリックしても投稿に飛ばない。
* phpファイルの`$query`内の、`media｛値（省略）｝`の値の部分に`permalink`を追加。
* javascriptファイルの`photos +=`内の、`<li>`と`＜img>`の間に「`<a href="' + gallery_data[i].permalink + '" target="_blank">`」を追加（閉じタグも忘れずに）

###取得された画像サイズが正方形ではないのでレイアウトが崩れる。
* <a href="https://kouhekikyozou.com/css_square#:~:text=%EF%BC%94%EF%BC%8E-,%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B7%E3%83%96%E3%81%AA%E6%AD%A3%E6%96%B9%E5%BD%A2%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E5%9D%87%E7%AD%89%E3%81%AB%E4%B8%A6%E3%81%B9%E3%82%8B%E6%96%B9%E6%B3%95,-%E4%BB%8A%E5%BA%A6%E3%81%AF%E3%80%81%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B7%E3%83%96">こちら</a>のサイトを参考に`<li>`タグを正方形にして、中に入れる画像を`object-fit: cover;`で拡大表示。

#まとめ
以上で、webサイト内にInstagramの画像をレスポンシブな正方形で配置することができた。
UnityでScriptableObjectからかんたんにインベントリを作る#2

#ScriptableObjectを使ってみるその2
##作ったデータを管理する

前回はItemというプログラムを作って、unityでたくさんアイテムを作れるようにしました。
では、そのたくさん作ったデータはどのように管理するのが効率が良いのでしょうか？


###データベースを作る
今回は、そのたくさん作ったアイテムをまとめあげる***データベース***を作ります。

データベースとは、たくさんのデータが入っている棚のようなものだと思ってください。

次のプログラムを作ります。
今回も***ScriptableObjectなので、どのオブジェクトにつけなくても平気***です。

```php
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName ="ItemDataBase",menuName ="CreateItemDataBase")]
public class ItemDataBase : ScriptableObject
{
    [SerializeField]
    private List<Item> itemlists;

    public List<Item> GetItemLists(){
        return itemlists;
    }

}
```

今回も一行目に注目してください。

```php
public class ItemDataBase : ScriptableObject
```

`MonoBehaviour`を`ScriptableObject`に書き換えられましたか？

前回にも出てきた↓これはなんでしょうか。前回はスルーしていました。

```php
[CreateAssetMenu(fileName ="ItemDataBase",menuName ="CreateItemDataBase")]
```

これは、Unity上のProjectやAssetメニュー欄から、新しくItemDataBaseを作れるようにしたものです。

実際にUnityでprojectの+を押してみましょう。
`CreateItemDataBase`が出ていれば成功です。
![スクリーンショット 2022-01-14 16.47.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2442087/6a67e210-1e2f-e5dd-800a-6d1ad5a11947.png)

選択するとAssets内にItemDataBaseが現れます。
`Itemlists`の欄に作ったアイテムの数を入れてみましょう。
欄が増えるはずです。そこに実際に前に作ったアイテムを入れてみましょう。↓こんな感じ
![スクリーンショット 2022-01-14 16.50.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2442087/fb356030-2bf7-c35c-3665-92b8aa60d134.png)

プログラムの説明をします。

```php
[SerializeField]
private List<Item> itemlists;
```

これでUnity上で数字を入力することができるようになり、数字に応じて欄が増えるようになります。
そこに、Itemが入れられるようになります。

その下の関数はまた今度。

次回は実際にコンソールに表示できるようにしてみます。
Terraformの基本コマンド

# 基本コマンド

```
$ terraform -help
```

以下、和訳（意訳）

```
## 主なコマンド（5個）：
init	他のコマンド用に作業ディレクトリを準備する。
validate	構成が有効かどうかを確認する。
plan	現在の構成に必要な変更を表示する。
apply	インフラストラクチャを作成、更新する。
destroy	以前に作成したインフラストラクチャを破棄する。
```

```
## 他のすべてのコマンド（18個）：
console	対話型コンソール
fmt		標準スタイルでコードをフォーマットする。
force-unlock	現在のワークスペースでスタックしているロックを解除する。
get	リモート上のTerraformモジュールをインストール、アップグレードする。
graph	操作のステップのGraphvizグラフを生成します
import	既存のインフラストラクチャをTerraformリソースに関連付ける。
login	リモートホストの資格情報（クレデンシャル）を取得して保存する。
logout	リモートホストのローカルに保存された資格情報（クレデンシャル）を削除する。
output	ルートモジュールからの出力値を表示する。
providers	この構成に必要なプロバイダーを表示する。
refresh	リモートシステムに一致するよう状態を更新する。
show	現在の状態、または保存された変更内容を表示する。
state	高度な状態管理
taint	リソースインスタンスを完全に機能していないものとしてマークする。
test	モジュール統合テストの実験的サポート
untaint	リソースインスタンスか、誤った変更状態を削除する。
version	現在のTerraformバージョンを表示する。
workspace	ワークスペース管理
```

# コマンド使用例
とても便利です。以下、一例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/674e159a-886e-b7c0-f86f-f4ee582b4d9f.png)

コマンドひとつで一瞬で整形してくれます！！
※main.tfは修正対象のファイル名です。

## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8
Wordpressのmeta_queryを使って、指定値がmeta_valueに保存された配列に含まれるものを抽出したい

WP_Queryのmeta_queryでin_array()的なことをしたくて探してたら
Stack Exchangeで見つけたので紹介します。

「DBに保存されているhoge配列内に値$idが含まれるレコード」を抽出する場合、
単純に以下のようにINを使って書くと

```php
$args = [
    'meta_query' => [
        [
            'key' => 'hoge',
            'value' => $id,
            'compare' => 'IN'
        ]
    ]
];
$query = new WP_Query($args);

```

「DBに保存されている値hogeが配列$id内に含まれるレコード」
という意図と逆の意味合いになってしまいます。


実現するには、DBにシリアライズ保存されたデータからLIKEを使って文字列で抽出するそうです。
ただ$idが数字や単純なテキストの場合、単に文字列化しても誤抽出が起こりやすいので、
こちらもシリアライズして前後の記号も含めLIKE抽出します。

```php
$args = [
    'meta_query' => [
        [
            'key' => 'hoge',
            'value' => serialize(strval($id)),
            'compare' => 'LIKE'
        ]
    ]
];
$query = new WP_Query($args);
```

参考：
https://wordpress.stackexchange.com/questions/55354/how-can-i-create-a-meta-query-with-an-array-as-meta-field/308393#308393
Rails6でローカル開発環境のWebサーバを外部に公開する

## 環境
docker-compose
Ruby on Rails 6

## サービスを利用する

### ngrok

老舗のサービス。  
macでの導入は `brew install --cask ngok` 。
macでの起動は `ngrok http 3000`。  
リージョンを東京にすることで少しはレイテンシが軽減されるが、それでも遅い。
有料サービスを使えば少しは速くなるかな？

### serveo  

知らない間にサービスを開始し、知らない間になくなった、上記 ngrok と同様のサービス。ssh接続を使用。

### ssh.localhost.run

上記 servero と同じ形の ssh接続 を使ったサービス。
コマンドは `ssh -R 80:localhost:3000 ssh.localhost.run`

### localtunnel  

nodeのサービス。  
インストールは　`sudo npm install -g localtunnel`
起動は `lt --port 3000`

ngrok と同様のサービス。やはり遅い。

## ローカルからアクセス
ということで、上記サービスを使うのは やめて、ローカルでアクセス。

## 無事ブロックされる 🎉
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90217/eef056d0-4d53-0bf6-8d3d-4f6c6b0f09b0.png)

```
Blocked host: 192.168.1.15
To allow requests to 192.168.1.15, add the following to your environment configuration:
config.hosts << "192.168.1.15"
```

Rails6 からおせっかい機能が追加されて、設定ファイルに許可ホスト名を書かないといけなくなったらしい。

対応方法が書いてある、親切親切。
と思ったが、指示通りにやっても上記エラーは解消されない。

```
config.hosts << "192.168.1.15"
```

https://ledsun.hatenablog.com/entry/2021/10/12/230325

上記はドメイン部分にアンダースコアが入ってる問題だった訳だが、私の場合はIPアドレスでアンダースコアが入ってないからな……

結局、　`config/environments/development.rb` に

```
config.hosts.clear
```

か

```
config.middleware.delete ActionDispatch::HostAuthorization
```

を記述して解決してます。
メモ：Blue GreenデプロイのBlueとGreen

# BLUE
現環境のコンテナ

# GREEN
入れ替え先コンテナ

# デプロイの流れ
1. GREENの起動完了後、ロードバランサーのルーティング先をGREENへ変更し、BLUEを停止。
1. GREENをBLUE扱いに変更。
Terraformとは

# Terraformとは
HashiCorp社が提供する、コード・ベースでインフラ構築・構成管理を行うツール。

Google Cloud Platform（GCP）、Amazon Web Service（AWS）、Microsoft Azureなど、異なるプラットフォームに対して利用することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/0b9f7ff1-afa1-a801-78b7-afa3143bf0ed.png)

クラウドインフラ環境の設定をコード化し、そのコードを実行することで自動で環境を構築することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/bc28e401-dee2-2d70-7d68-d973baa24a56.png) 

# Terraform利用のメリット
### インフラ構築の変更を自動化できる。
コンソール画面で操作していた時間が短縮でき、操作ミスを減らすことができる。

### インフラの状態をコードで管理できる。
バージョン管理ができる。コードレビューもできる。

### リリース作業のを自動化できる。
開発環境でテストしたコードを実行することで、本番環境の構築・リリースコストやリスクを軽減させることができます。

## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8
Salesforceのワークフロールールで3年以上先の時間ベースを設定する方法

Salesforceには時間ベースのワークフロールールという設定があります。

これは特定の条件から数日後（数時間後）にメールを送る。という設定に便利です。

しかしながら、この時間ベースは1000日より後の設定はできないですね。
もしも1000日後に設定すれば↓のようなエラーが出ます

エラー: 数値が大きすぎます。
![ワークフローエラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/ce37e882-edb3-d33d-d5d3-3cae37e3d88b.png)



今日は例として
・商談が受注してから3年後（1095日後）にメールを送る

という設定を教えます

###ステップ1 まずはカスタム項目を作成しよう

カスタム項目「受注日」を商談オブジェクトに作成します。
![ワークフロー１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/faad285f-32c9-11df-5743-922cb226f6f3.png)


###ステップ２ ワークフロールールを作成しよう

条件は商談が受注したときです
![ワークフロー2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f4a85216-1a2c-ed4b-9301-e950a55d5437.png)
![時間ベースのワークフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b846d2b5-904c-a598-a84a-bf886c3fff8d.png)


アクションその１は下記項目自動更新です
日付は今日から１０９５日後。つまり数式は
TODAY()+1095
です
![ワークフロー３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/cea1881a-f239-764d-5fc2-39cb1f54fe17.png)

次にアクションその２を作成します
「タイムトリガの追加」ボタンをクリックします
まずは![ワークフロー4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/fdea1dfd-be08-4fc0-8e12-cc30e9f76be0.png)

商談：受注日（つまり最初に作成したカスタム項目）を設定。保存します
![ワークフロー5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f0a9e201-9695-2c7b-96ed-642ae596a366.png)

以上でワークフロールールは完成です。あとは有効化をお忘れなく。

ワークフロールール完成形はこのような形になります
![ワークフロールール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/aafc2666-1cf2-0adf-6b53-92b7dd91347b.png)

なお、今回の設定について「じゃあ実際メールを送られたかどうか、今から３年後経ないと分からないじゃん？」と思うかもしれませんがご安心を。
以下のように「時間ベースのワークフロー」から、実際に３年後にメールが送られるか確認が可能ですよ。
![時間ベースのワークフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/909a1098-fcfb-8ab9-61e5-3edfedf16e42.png)
neosでlogix その45

# 概要

neosでlogixやってみる。
Root Slotノード
Get Slot Nameノード
Find Child By Nameノード使ってみた。

# 写真

![2022-01-14 06.29.17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/62d50688-059f-7ac9-1af9-e028afb20c4a.jpeg)


# Root Slot

```
Inputs
Outputs
 	Slot	*
```

# Find Child By Name

```
Inputs
 	Slot	Instance
 	String	Name
 	Bool	MatchSubstring
 	Int	SearchDepth
 	Bool	IgnoreCase
Outputs
 	Slot	FoundChild
```

# Get Slot Name

```
Inputs
 	Slot	Instance
Outputs
 	String	*
```

# 手順

- devtooltipを装着。
- 新規->3d->boxをスポーン。
- logixtooltipを装着。
- ノードブラウザを表示
- Slots>Root Slotをスポーン
- Slots>Find Child By Nameをスポーン
- Slots>Get Slot Nameをスポーン
- つなぐ





以上。
mac のテキストエディット.app はハードリンクを壊す

macOS のテキストエディット.app を使ってハードリンクのファイルを編集・保存すると、inode が別のファイルとして保存される。

# 詳細

a.txt を作成し、ハードリンク b.txt を作成する。

```
% echo "test" > a.txt
% ln a.txt b.txt
% ls -i
7972329 a.txt	7972329 b.txt
```

この状態で`テキストエディット.app` で `b.txt` を開いて編集し保存すると inode が別なファイルとして保存される。

```
% ls -i
7972329 a.txt	7972381 b.txt
```

システム的な制限というわけではなくテキストエディット.app の問題のようで、VS Code で編集した場合はハードリンクは壊れないし、当然 vi などで編集しても壊れない。


なお、シンボリックリンクの場合には`テキストエディット.app` で編集しても壊れない。
macOSのUnity Hub 3.0.0でpersonal licenseが取得できない不具合と対処法

<dl>
<dt>環境</dt>
<dd>OS : macOS,  OS X El Capitan</dd>
<dd>Unity Hub : Unity Hub 3.0.0</dd>
</dl>
#エラー詳細
訳あってPCをリフレッシュしUnity Hubを入れ直したところ、personal licenseの取得時に

(English) **There was a problem activating a new personal license. Make sure you are logged in, and have internet connection.**

(日本語) **新しい Personal ライセンスの認証で問題が発生しました。ログインしていることとインターネットに接続していることを確認してください。**

というエラーが発生したので、色々調べた結果を残しておきます。
ちなみにログイン下でインターネットにも異常はないと思われます。
![unityhub_bug_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508660/d8c82efe-8c69-8ee6-4ba0-7464e6f8bcb5.png)

#原因
**Unity Hub 3.0.0 のバグ**のようです。(参考: [UnityHubコミュニティのバグ報告](https://forum.unity.com/threads/hub-3-0-0-cannot-activate-licenses.1223058/ "Unity Hub Community"))
2022年1月14日現在、同様のエラー報告が多くみられるので、近いうちに修正されるかもしれません。ただ現状はどうしようもなさそうです。
同様のバグがwindowsでも発生している他、proライセンスが認識されないといった報告もありました。

#解決策
**とりあえず Unity Hub をログアウトしてから完全終了し、一からライセンス取得をやり直してみるべきかと思います。**
上記の方法で改善が見られない場合は Unity Hub 3.0.0 未満のバージョンにダウングレードする方法が有効です。

1. Unity Hub 3.0.0 を終了し、アンインストール
1. [wayback machine](http://web.archive.org/web/20200801000000*/https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.dmg) から Unity Hub の古いバージョンを入手 (参考 : [Unity Hub 2.3.2 (for macOS) のダウンロードリンク](https://web.archive.org/web/20200814043030/https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.dmg))
1. 旧バージョンの Unity Hub で personal license を取得
1. 旧バージョンの Unity Hub から 3.0.0 にアップデート (任意)

自分は上述の方法でライセンスを取得できました。
調べていると、旧バージョンでライセンスを取得した後 3.0.0 にアップデートすることで全て解決した、という書き込みを見つけましたが、自分の場合はアップデート後にまたライセンス登録を要求されたので解決しませんでした。(なぜかUnityのダウンロードはできました。)
[windowsでも同様の方法で解決したとのコメント](https://forum.unity.com/threads/hub-3-0-0-cannot-activate-licenses.1223058/)がありましたので、参考にしてみてください。
JupyterLabでdotファイルを表示する

機械学習実装練習中にJupyterLab上でdotファイルをpngファイルに変換して表示したかったので全手順をメモしておきます。

# 手順
1. pipのインストール
1. pydotplus、graphvizのインストール
1. JupyterLabにバインド
1. dotファイルの変換と表示をする関数を作成
1. 表示処理の実施

# pipのインストール
この辺を参考に。。。

https://qiita.com/suzuki_y/items/3261ffa9b67410803443

# pydotplus、graphbizのインストール
以下のコマンドを実行

```:
$ pip install pydotplus
$ pip install graphbiz
```

#JupyterLabにバインド
grahvizをJupyterLabで利用できるようにバインドする
```:
$ conda install -c conda-forge python-graphviz
```
# dotファイルの変換と表示をする関数を作成
JupyterLab上で以下を記述

```python:
import os
import pydotplus
from IPython.display import Image,display_png

PROJECT_ROOT_DIR = "."

def image_path(fig_id):
    return os.path.join(PROJECT_ROOT_DIR, "images", fig_id)
def view_dot(fig_id):
    file_full_path=PROJECT_ROOT_DIR+"/images"
    graph = pydotplus.graphviz.graph_from_dot_file(file_full_path+"/"+fig_id)
    graph.write_png(file_full_path+"/"+fig_id+'.png')
    display_png(Image(graph.create_png()))

```

# 表示処理の実施
JupyterLab上で対象のdotファイルを表示させます。
```python:
view_dot("ファイル名.dot")
```

# まとめ
バインド処理がそこそこ時間がかかりますのでコーヒーでもいただきながら待ちましょう。

# 参考
https://qiita.com/Kaisyou/items/999996baed6f880a6e78

https://qiita.com/knknkn1162/items/77999450c59db915ab87

https://funmatu.wordpress.com/2017/04/25/%E6%B1%BA%E5%AE%9A%E6%9C%A8%E3%81%A8%E3%81%8B%E3%82%B0%E3%83%A9%E3%83%95%E6%A7%8B%E9%80%A0%EF%BC%88dot%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%EF%BC%89%E3%82%92jupyter%E4%B8%8A%E3%81%A7%E8%A1%A8%E7%A4%BA/
Express.jsにPassport.jsで、任意のフォルダ配下のみをBasic認証する　その2

## 概要
expressを使って特定フォルダのみパスワードを掛けたい。

こんどこそ、express-basic-authを使って。

```JavaScript
const express = require("express");
const basicAuth = require("express-basic-auth");
const PORT = 3000;
const app = express();
//
app.use("/admin", basicAuth({
    users: { 'user': 'pass' },
    challenge: true,
}), express.static("public/admin"));
//
app.use("/", express.static("public/") );
app.listen(PORT, () => {
  console.log("app listening on port " + PORT + " " + new Date());
});

```

## 結論
やったー。動いた！ばんざーい。
よっしあぁ。

## 参考サイト
git  
https://github.com/kawamurashin/express-auth-test

Express.jsにPassport.jsで、任意のフォルダ配下のみをBasic認証する
https://qiita.com/hoshimado/items/272fba1aeb728e14f278

express-basic-auth　　
https://github.com/LionC/express-basic-auth
ArgoCDで発生する"Unable to connect SSH repository: unknown error: ERROR: You're using an RSA key with SHA-1, which is no longer allowed. Please use a newer client or a different key type." エラーの解消方法

# エラー全文

```
Unable to connect SSH repository: unknown error: ERROR: You're using an RSA key with SHA-1, which is no longer allowed. Please use a newer client or a different key type.
```

# エラー理由

GitHubでは2022年1月11日から脆弱な古い種類の暗号とハッシュを無効化しました。そのためこれまで使えていたSSH鍵が使えなくなっています。

# 対処

SSH鍵を`ECDSA`や、`Ed25519`などで作り直します。

# 参照

- [Improving Git protocol security on GitHub | The GitHub Blog](https://github.blog/2021-09-01-improving-git-protocol-security-github/)
SwiftUIアプリにダークモード設定を追加する

SwiftUIアプリに、ユーザーがダークモードの設定を選ぶことができるプリファレンス設定を加えることができます：システムのスタイルに従うか、常にダークモードを使用するか、常にライトモードを使用するかを選択できます。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/88f90f50-0847-1f63-a700-84fd70db0a65.gif">

## ユーザーデフォルトへのユーザーの環境設定の保存（`@AppStorage`を使用）

ユーザーは、iOSシステムに追従するダークモード、常にダークモード、または常にライトモードを設定できます。

```swift
enum DarkModeSetting: Int {
    case followSystem = 0
    case darkMode = 1
    case lightMode = 2
}
```

ユーザーのプリファレンス設定を確定したり取得したりするには、`appearanceMode`と呼ばれる変数を使用することができます：

```swift
// import SwiftUI
@AppStorage(wrappedValue: 0, "appearanceMode") var appearanceMode
```

## プリファレンス設定を追加

設定表示でプリファレンス設定を追加できるようになりました

```swift
Picker("Appearance setting", selection: $appearanceMode) {
    Text("Follow system")
        .tag(0)
    Text("Dark mode")
        .tag(1)
    Text("Light mode")
        .tag(2)
}
```

## ユーザー設定を適用し、好みのカラースキームを設定

`App`構造体で変数を読み取り、ダークモード設定を適用して下さい。

ダークモードの設定に対しては分岐条件が存在するので、カスタム関数を書くことで変更を適用できます。
アプリがシステムの設定に従うようにしたければ、優先すべきカラースキーム`preferredColorScheme`を`nil`に設定します。
ユーザーが常にダークモードを使用することを選択すれば、`.dark`に設定します。
ユーザーが常にライトモードを希望すれば、`.light`に設定します。

```swift
import SwiftUI

@main
struct SwiftUI_Toggle_DarkModeApp: App {
    
    @AppStorage(wrappedValue: 0, "appearanceMode") var appearanceMode
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .applyAppearenceSetting(DarkModeSetting(rawValue: self.appearanceMode) ?? .followSystem)
        }
    }
    
}

extension View {
    @ViewBuilder
    func applyAppearenceSetting(_ setting: DarkModeSetting) -> some View {
        switch setting {
        case .followSystem:
            self
                .preferredColorScheme(.none)
        case .darkMode:
            self
                .preferredColorScheme(.dark)
        case .lightMode:
            self
                .preferredColorScheme(.light)
        }
    }
}
```

注意：優先配色が変更されると、アプリはデフォルトの画面に切り替わります。

## 完成したプロジェクト

完成したデモプロジェクトはこちらからダウンロードできます。

https://github.com/mszmagic/SwiftUI_Dark-Mode-Toggle

---

:relaxed: [Twitter ツイッター @MszPro](https://twitter.com/MszPro)

:sunny: [私の公開されているQiita記事のリスト](http://mszpro.com/ioskiji/)
<img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">
Copy spanning locations and/or storage classes could not complete within 30 seconds. Please use the Rewrite method...ってなんだよ

PythonでGCSのファイルをコピーしようとしたらこんなエラーが出ました。

```python
from google.cloud import storage

storage_client = storage.Client()

src_bucket = storage_client.bucket(BUCKET_NAME)
dst_bucket = storage_client.bucket(OUTPUT_BUCKET_NAME)

src_file_name = "hoge.gz"
dst_file_name = "hoge.gz"

src_blob = src_bucket.blob(src_file_name)

new_blob = dst_bucket.copy_blob(src_blob,
                                dst_bucket,
                                new_name=dst_file_name,
                                timeout=180)
new_blob.acl.save(src_blob.acl)

```

エラー内容

```
Copy spanning locations and/or storage classes could not complete within 30 seconds. Please use the Rewrite method (https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite) instead.
```

なんかtimeout=180も効いてないみたいです。

どうやらコピーしようとしているファイルが数GBと少々大きい場合このようなエラーが出るそうです。

メッセージにあるようにrewriteメソッドを使えとあります。

書き直してみました。


```python
from google.cloud import storage

storage_client = storage.Client()

src_bucket = storage_client.bucket(BUCKET_NAME)
dst_bucket = storage_client.bucket(OUTPUT_BUCKET_NAME)

src_file_name = "hoge.gz"
dst_file_name = "hoge.gz"

src_blob = src_bucket.blob(src_file_name)
dst_blob = dst_bucket.blob(dst_file_name)

rewrite_token = None

while True:
  rewrite_token, bytes_rewritten, total_bytes = dst_blob.rewrite(src_blob,
                                                                 token=rewrite_token)
  progress_percent = (bytes_rewritten * 100) // total_bytes
  print(f"Progress : {bytes_rewritten} / {total_bytes} bytes {progress_percent}%.")

  if rewrite_token is None:
    print("Copy has done !!")
    break

```

実行してみると

```
Progress : 461373440 / 1899448698 bytes 24%.
Progress : 964689920 / 1899448698 bytes 50%.
Progress : 1509949440 / 1899448698 bytes 79%.
Progress : 1899448698 / 1899448698 bytes 100%.
Copy has done !!
```

気になったrewrite_tokenはなんかランダムな値でしたので省略します。
AWS EC2 スポットブロックは廃止されていた？

AWSで下記のような性質のバッチ処理を実行する必要が発生した。

- 1~2時間の処理時間。
- 処理が中断されると、それまでの処理結果は破棄して再実行となる。

「そういえばスポットブロックという機能(スポットリクエストで、指定した時間はインスタンス確保が約束される機能)があったなー」と思い、試してみようと思ったのだが使い方がわからない。

調べていると以下の記載にたどり着いた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199673/31889f19-9162-b242-c06b-9bc3dfaa19ff.png)
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/spot-requests.html#fixed-duration-spot-instances

つまり、スポットブロックはもう使えないらしい。
"スポットブロック 廃止"等とググってみても情報はヒットせず、ひっそりと終了していたようだ。残念。
ValueError: ('Iterator has already started', <google.api_core.page_iterator.HTTPIterator object at 0xaaaaaaa>)

pythonでCloud Storageのファイル数を数えようとしたらこんなエラーがでました。
なんなんだと。

```
  File "/........./lib64/python3.6/site-packages/google/api_core/page_iterator.py", line 227, in __iter__
    raise ValueError("Iterator has already started", self)
ValueError: ('Iterator has already started', <google.api_core.page_iterator.HTTPIterator object at 0x7fc844c4aeb8>)
```

そもそものコードはこちらです。
やりたいことは

- 対象フォルダのファイルを探す。
- ファイルが無ければ終了。
- ファイルがあればファイル名を表示する。
というものです。

```python
from google.cloud import storage
import sys

storage_client = storage.Client()
bucket = storage_client.bucket(BUCKET_NAME)

### 集計対象のファイルを探す
blobs = bucket.list_blobs(
  prefix=TARGET_GCS_FOLDER + '/hoge_'
)

if len(list(blobs)) == 0:
  print("Error, No target files....")
  sys.exit(1)

for item in blobs: 　# <--- ここ！！！
  print(item.name)
```

そんでどうやらエラーの箇所はblobオブジェクトをイテレートしてファイル名を表示するところでした。

なぜかと？

どうやらblobオブジェクトのイテレーターは1回しか使えないみたいです。
File "/........./lib64/python3.6/site-packages/google/api_core/page_iterator.py"についてコードを見てみると

```python
class Iterator(object):
...................
    def __init__(
        self,
        client,
        item_to_value=_item_to_value_identity,
        page_token=None,
        max_results=None,
    ):
        self._started = False # <--- ここ！！
        self.client = client
.......................
    def __iter__(self):
        """Iterator for each item returned.

        Returns:
            types.GeneratorType[Any]: A generator of items from the API.

        Raises:
            ValueError: If the iterator has already been started.
        """
        if self._started:
            raise ValueError("Iterator has already started", self)  # <--- ここ！！！
        self._started = True
        return self._items_iter()
```

とあります。
一度`__iter__`が呼ばれてしまうとself._startedがTrueになりValueErrorがなってしまうことがわかります。

ここで最初の`__iter__`ですが

```python
if len(list(blobs)) == 0:
```

でリスト数を数えています。このlist(...)で`__iter__`が呼ばれているので、すでにself._startedがTrueとなっていたわけです。

なので一度別のリスト型変数に入れなおしてからやればエラーになりません。

```python
blob_list_obj = list(blobs)

if len(blob_list_obj) == 0:
  print("Error, No target files....")
  sys.exit(1)

for item in blob_list_obj:
  print(item.name)
```

### 参考ページ

https://qiita.com/tomotaka_ito/items/35f3eb108f587022fa09
参照を受け取るvoid関数を値を返す関数に変換する

```cpp
#include <memory>
#include <functional>

template<class R, class T, class... Args>
R FirstArgReturnerMemfn(std::function<void(T&, R&, Args...)> F, T& inst, Args... args)
{
    R r;
    F(inst, r, args...);
    return r;
}

template<typename R, typename T, typename... Args>
struct FirstArgReturner
{
    template<void (T::*F)(R&, Args...)>
    static R WithFunc(T& inst, Args... args)
    {
        R r;
        (inst.*F)(r, args...);
        return r;
    }
    template<void (T::*F)(R&, Args...)>
    static R SharedWithFunc(T& inst, Args... args)
    {
        std::shared_ptr<R> r(new R);
        (inst.*F)(*r, args...);
        return r;
    }
};

class C{
public:
    void f(int &x, int y, int z){x=y+z;}
};

#include <stdio.h>
int main(){
    C c;
    printf("%d\n",std::bind(&FirstArgReturnerMemfn<int,C,int,int>,std::mem_fn(&C::f),std::placeholders::_1,std::placeholders::_2,std::placeholders::_3)(c,2,3));
    // C++20 allows this shorter form
    // printf("%d\n",std::bind_front(&FirstArgReturnerMemfn<int,C,int,int>,std::mem_fn(&C::f))(c,2,3));
    printf("%d\n",FirstArgReturner<int,C,int,int>::WithFunc<&C::f>(c,2,3));
}
```

当初はFirstArgReturnerMemfnの方の実装しか思いつかなかったのですが、std::bindとかstd::mem_fnしてあるやつはpybind11に渡せないことがわかったので、更に一日悩んでFirstArgReturnerの方の実装を考えつきました…。
メモ：Vue.js（V3）を簡単に動かしてみる


ReactよりVue.jsの方が好みな感じの雰囲気を醸し出しているので軽く触っておく。
なお、ReactもVueも基幹系ではあまり需要がないので利用することなかった。（jQuery止まり）

# 導入

CDN版の場合は[公式](https://v3.ja.vuejs.org/guide/installation.html#cdn)に簡単には書いてある。

```javascript
<script src="https://unpkg.com/vue@next"></script>
```

HTMLにこれ書くだけで使う事は可能。
バージョン番号指定なら

```javascript
<script src="https://unpkg.com/vue@3"></script> <!-- 3の最新 -->
<script src="https://unpkg.com/vue@3.0.0"></script> <!-- 特定バージョン -->
```

npmでローカルにインストールする場合
`npm install vue@next`
TypeScriptでやるならインストールする必要がもちろんある。

Vue3については[ここ](https://www.codegrid.net/articles/2020-vue3-1/)とか。
3系はIEでは動かないので、その辺りでの注意は必要。

# お試し
今回は時間があまりなかったのでCDN版で。
[ここ](https://wk-partners.co.jp/homepage/blog/hpseisaku/javascript/vuejs/)見ながら
vueはせっかくなので最新のV3で書き換えて試す。

V2とV3の違いがあって、`new Vue({})`がエラーになる。
代わりに`Vue.createApp`を使う。
また、`.mount(target)`で対象を指定する。

AJAXにはaxiosではなくjQueryを使ってみるか、と思って適当に以下で書いてみた。

```javascript
<script src="https://unpkg.com/vue@3"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<script>
Vue.createApp ({
	data() {
	return{ inputZip:'', defaultZip:'1000000', zip:'0000000', zipAddr:'' } // 二重括弧に対応するデータ。初期値も指定。
	},
	computed: {
	    computedZip: function(){
	      return !isNaN(this.inputZip) && this.inputZip.length == 7 ? this.inputZip : this.defaultZip
	    },
	    computedAddress: function(){ return !isNaN(this.inputZip) && this.inputZip.length == 7 ? getAddress(this.inputZip) : '';}
	},
	methods: {
	    getAddress: function(z){
	       let params = {"zipcode": z};
	       $.get('https://api.zipaddress.net/',params
	       ).done(
	       function(d){
		if(d.code == '200'){
		  this.zipAddr = d.data.fullAddress; // 画面が変更されない

		}else{
	        this.zipAddr = d.message;
		}
	       }).fail(
	       function(e){
	        this.zipAddr = e.code;
	       });
	    }
	}
}).mount('#vue-target'); // mountでVueを利用する対象を指定
</script>
```

動かない。
methodでthis.xxxにセットしても変更されないのはおそらくjQuery内部のThisの問題。
サンプルのようにAxios使うと普通にできた。

```javascript
methods: {
	    getAddress: function(z){
	       let params = {"zipcode": z};
	       
			axios
        	.get('https://api.zipaddress.net/', {'params':params})
        	.then(res => {
				console.log(res.data);
         		this.zipAddr = res.data.code == 200 ? res.data.data.fullAddress : res.data.message;
        	});
		}
	}
```

勿論jQueryを使って書くことも出来て、とりあえずこんな感じでthisを受けると動いた。
（動かない原因に気が付くのに時間がかかってしまった）

```javascript
methods: {
	    getAddress: function(z){
	       let params = {"zipcode": z};
		   let _this =this; // jQuery内部で使うためにthisを引き受けておく。

	       $.get('https://api.zipaddress.net/',params
	       ).done(
	       	function(d){
			if(d.code == '200'){
				_this.zipAddr = d.data.fullAddress;
			}else{
				_this.zipAddr=d.message;
			}
			}).fail(
			function(e){
				_this.zipAddr = e.code;
			});
			
		}
	}
```

Method周りの[公式マニュアル](https://v3.ja.vuejs.org/guide/)も参考にするとよい。

いろいろ見ているとV3ではThis付ける付けない辺りの挙動もV2から変わっているらしい。
[ここ](https://www.ragate.co.jp/blog/articles/8232)とか[ここ](https://qiita.com/laineus/items/d1f1f7972f521556a788)とかが参考になるかも

情報が揃っているV2の方が使いやすい可能性はあるものの、やはり今から使うならV3か・・・
そういえばSwiftなんかは強制アップデートで古いコード動かなくなったりしてイライラしたなぁ、という思ひ出。