OmniAICreator/Qiita-1.07M huggingface dataset:
プロパティの基本とスタティックプロパティ

#プロパティとは

簡単に言うと `型に紐付いた値`のことです。例えば下のように`Test`っていう型を`class`で定義してみます。

```.swift
class Test {
  var message = "This is Test"
  func alert() {
    print(message)
  }
}
```

`Test型`のプロパティとは変数`str`と関数`notify`のことです。
プロパティにアクセスするにはインスタンスを生成して、`.プロパティ名`とします。

```.swift
let test = Test()

test.message
test.alert() //This is Test が出力される
```

もう少し細かいことも紹介します。

#スタティックプロパティ

__スタティックプロパティ__とは　`型自身に紐付く`プロパティのことです。
またこれに対して__インスタンスプロパティ__があります。こちらは`型のインスタンスに紐付く`プロパティのことです。
###インスタンスプロパティ
インスタンスプロパティは一番最初に紹介したようなプロパティです。よりインスタンスに紐付いた状態が分かりやすいサンプルコードが下のものです。

```.swift
let test1 = Test()
let test2 = Test()

test1.message = "This is Test1"
test2.message = "This is Test2"
```

こんなふうに`Testクラス`のインスタンスそれぞれに値を持たせることができます。
じゃあスタティックプロパティならどうなるのか...?
###スタティックプロパティ
プロパティの宣言時に`static`キーワードをつけたものは、__スタティックプロパティ__になります。

```.swift
class Test {
  static var message = "This is Test"
  func alert() {
    print(Self.message)
  }
}
```

`Self`キーワードはインスタンスからスタティックプロパティにアクセスする時に必要なものです。

これでさっきのように値を変更しようとすると

```.swift
let test1 = Test()
let test2 = Test()

test1.message = "This is Test1" //ここでエラー
```

エラーが出て、インスタンスからスタティックプロパティにはアクセスできません。

その代わり、直接スタティックプロパティにアクセスして値を変更することができます。

```.swift
let test1 = Test()
let test2 = Test() //ここまではmessageの中身は"This is Test"

Test.message = "Changed message"

test1.alert() //Changed message
test2.alert() //Changed message
```

とこんな感じです。まさに`型に紐付いてる`ということが分かりますね。

でも`static var`を使うと急に全部のインスタンスの値が変わるので不都合ありそうですね。普通に共通に値を持たせるなら`static let`にしてインスタンスからアクセスできないようにするのか安全な気がします。またはインスタンスからのアクセスを制限したいなら、`private`キーワードをつけるのがいいのかも。ここらへんはもう少し勉強します。

ちなみに

```.swift
static let message: String
```

という宣言はエラーになります。スタティックプロパティは必ず、__宣言時に初期値を設定しないといけません。__ 

#最後に
非常に簡単にではありますが、プロパティの基本を押さえてみました。
具体的な使用例に出会えたら追記しますー。

間違った記述などがありましたら、是非教えてくださるとありがたいです。


#参考にした記事
https://qiita.com/pitto/items/218db772c829d4b83470

https://reona.dev/posts/20200711

https://wp-p.info/tpl_rep.php?cat=swift-biginner&fl=r30

#追記　2021/6/5

https://qiita.com/REON/items/6388b6a522b9d7fc949c

こちらの記事でセルの`identifier`をスタティックプロパティで宣言していて便利でした。
Spring Boot 2.5 で spring.datasource.initialization-mode が非推奨となっている件

Spring Bootの最新版 **Spring Boot 2.5** が本年（2021年）5月21日に[リリースされた](https://codezine.jp/article/detail/14213)とのことです。
これに伴い、標題のような警告が出たので、自分の備忘として書いておきます。

# 症状

Spring Boot のアプリケーションプロパティ（application.properties）に、以下のとおり、データベースに関する記述をしました。

```application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/spring_test
spring.datasource.username=yama3
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.initialization-mode=always
spring.datasource.schema=classpath:schema.sql
spring.datasource.data=classpath:data.sql
spring.datasource.sql-script-encoding=utf-8
```

すると、STSの画面上で警告（アラート）が表示されました（4つも！）。
![2021-05-30 220931.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/dcc6d092-a34a-6cae-95f4-6deb42083e8b.png)
5行目の `spring.datasource.initialization-mode` に関するアラートを見てみると次のとおりでした。
![2021-05-30 212747.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/c93787c7-899a-9056-61d6-24620cbb19ec.png)
アラートの1行目を確認します。

```
Property 'spring.datasource.initialization-mode' is Deprecated: Use `spring.sql.init.enabled` instead.
```

日本語に訳せば、「**プロパティ 'spring.datasource.initialization-mode' は非推奨です。代わりに 'spring.sql.init.enabled' を使用してください。**」とのことです。
つまり、`spring.sql.init.enabled`を使いなさい、ということですね。
なお、現時点では非推奨のアラートが表示されるだけなので、特に修正しなくても動くのは動きます。

＜参考記事＞
・[spring.datasource.initialize is deprecated](https://stackoverflow.com/questions/55040879/spring-datasource-initialize-is-deprecated)

# 修正後の記載内容

それぞれのアラートに従って、次のように修正しました。

```application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/spring_test
spring.datasource.username=yama3
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.sql.init.enabled=true
spring.sql.init.schema-locations=classpath:schema.sql
spring.sql.init.data-locations=classpath:data.sql
spring.sql.init.encoding=utf-8
```

修正内容を一覧にすると、次のとおりです。

|修正前の項目|修正後の項目|備考|
|---|---|---|---|
|spring.datasource.initialization-mode|[spring.sql.init.enabled](https://spring.pleiades.io/spring-boot/docs/current/reference/html/howto.html#howto.data-initialization.using-basic-sql-scripts)|DBの初期化の要否を設定（true=実行する、false=実行しない）|
|spring.datasource.schema|spring.sql.init.schema-locations|DBの初期スキーマを記述したファイルを指定|
|spring.datasource.data|spring.sql.init.data-locations|DBの初期データを記述したファイルを指定|
|spring.datasource.sql-script-encoding|spring.sql.init.encoding|文字コードを指定|

`spring.sql.init.enabled` は true（初期化を実行する） または false（初期化を実行しない）で指定します。
デフォルトが true なので、何も記載しなければ true の設定となります。

以上
【AWS】S3のオブジェクト構成とデータ構造

#プログラミング勉強日記
2021年5月30日

#オブジェクト構成
　S3のオブジェクトは、`key`, `value`, `バージョンID`, `メタデータ`, `サブリソース`の要素から構成されている。
　keyはオブジェクトの名前で、一意に識別するためにキー値が設定されている。valueはデータそのもので、バイト値で構成される。(データの名前がkeyでデータそのものがvalue)
　バージョン管理されていると、バージョンIDが振られていく。バージョンIDは英数字の羅列になっていて、これでバージョン管理されている。メタデータはオブジェクトに付随する属性の情報で追加で加えられる。サブリソースはバケット構成情報を保存・管理するためのサポートを提供する。


#データ構造
　S3のデータ構造は以下のようになっている。まず、S3という大きな枠があってその中にバケットを作る。バケットは様々なリージョンを指定して作る。そしてその下にオブジェクトとして様々なファイルが格納されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642821/9e347b82-154b-fe3a-2039-c32c6c921794.png)
HTMLのmetaタグ整理ノート

## 概要
Web開発に必須の知識HTMLを勉強し直している。

その整理ノート。今回はMetaタグ。

## そもそも、HTMLとは

HTML = HyperText Markup Language。

拡張子(.html)

## 基本的なタグの構成

開始・終了タグ(タグの種類)、属性(attribute)、テキストや画像で成り立っている。

終了タグは必要なものと不必要なものがある。

```html
<開始タグ タグの属性="タグの属性値">(表示するテキスト)<(/終了タグ)>
```
## metaタグ

文章のメタ要素。文書そのものの設定を行うようなイメージ。

この設定を読み込んで、ブラウザは表示を変えたり、そのページがどのようなサイトであるかを判断する。

metaタグはオプションであるが、設定をしっかり行なっておくことで、
文字化けのリスクが減り、
リンクが貼られた時にも見栄えが良くなり、SEOの観点からも良い。

metaタグの設置場所は、headタグ内に置くこと。

```html
<meta><\meta>
```

### charset属性

文字エンコーディングをセット。

基本的にはUTF-8を使用する。(日本語に対応するため)

むかしはSHIFTも使われていたことも。

ASCIIはアルファベットのみならOK。

```html
<meta charset="UTF-8"></meta>
```

### nameメタタグ

この文章の説明。

#### descriptionメタタグ(name="description")

この文章の説明文をcontent属性に書く。

```html
<meta name="description" content="HTMLの基本">
```

#### keywordsメタタグ(name="keywords")

この文章のキーワードをcontent属性に書く。。SEOなどの観点で検索されそうなものを選ぶ。

複数書く時はカンマ区切り。

```html
<meta name="keywords" content="HTML,初心者,タグ">
```

#### robotsメタタグ(name="robots")

検索エンジンに対する挙動の制御。contentに"noindex,nofollow"とすることで、隠しページにできる。

```html
<meta name="robots" content="noindex,nofollow">
```

#### viewメタタグ(name="viewport">)

レスポンシブルなテキスト表示にするためのタグ。

contentsの詳細は[こちら](https://qiita.com/ryounagaoka/items/045b2808a5ed43f96607)に。

```html
<meta name="viewport" content="width=device-width,initial-scale=1">
```

### OGPメタタグ(property="og:✕✕✕✕✕")

OGP = Open Graph protocol

SNSなど外部のサイトでシェアされた時の挙動を設定する。

それぞれ一般的なmetaタグをSNS版のためにクローンして設置するイメージ。

```html
<meta property="og:title" content="タイトル">
<meta property="og:type" content="website/article">
<meta property="og:description" content="説明">
<meta property="og:url" content="URL">
<meta property="og:site_name" content="サイトのタイトル">
<meta property="og:image" content="サムネイル画像のURL>
```

## 引用・参考

- https://www.e-webseisaku.com/column/marketing/3947/
- https://developer.mozilla.org/ja/docs/Web/HTML/Element/meta
- http://www.htmq.com/html/meta.shtml
- https://digital-marketing.jp/seo/index-control-meta-robots/
dependabot を使って Dockerfile の定義を最新化しよう


## これはなに

Docker Hub などで公開されている Docker Image をベースに用途に応じて、パッケージや設定の変更、定義の追加を行っているが Base image の更新を忘れることが多いので設定を行った際のメモ。

## やること

- dependabot.yml を記述する
- main（master） branch に push する

## dependabot.yml を記述する

今回は、必須となる `package-ecosystem` `directory` `schedule.interval` の例を記載。
Pull request を作成するときに誰を assign するかなども設定出来ます。

```yml:.github/dependabot.yml
version: 2
updates:
- package-ecosystem: docker
  directory: "/"
  schedule:
    interval: "daily"
```

## main（master） branch に push する

push するだけなので省略します 🙇

## (数日後) Pull request が作成される

指定した時刻にチェックが走り、更新出来ると判断されると Pull request が作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55950/3f5389cf-67ba-5b6d-6510-005a6602cfb4.png)

## Reference

https://docs.github.com/ja/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
[python] プロジェクトのディレクトリ推奨構成

# 初めに
pythonのプロジェクトにおいて、個人的にフォルダ構造を考察してまとめる。
ただし、プロジェクトの目的に応じた構造や、時期（バージョン）に応じた構造、
推奨するソース（社会的権威）の差などがあるため、完全に標準的な構造はない。
そのため、記事として本構造が適切であると推奨しているわけではない。

# プロジェクトの構造について
まず、ソースコード、ドキュメント、テストを保管するフォルダ構造が基本構造となる。
そのため、pythonにおける一般的な名称を含めて以下は必須となる。

 * myproject：開発するプロジェクトの名称。名称は任意。
 * docs：ドキュメントの保管フォルダ。名称は固定（推奨）。
 * tests：テストコードの保管フォルダ。名称は固定（推奨）。

```
myproject(root) /
 ├─ myproject /
 ├─ docs /
 ├─ tests /
```

また、基本的な情報ファイルとして、以下のファイルを含む。

 * 一般的な説明を記したファイル（README.md）
 * 実行環境（使用しているライブラリ）を明示する・導入するファイル（requirements.txt、setup.py）
 * ライセンスを明示するファイル（LICENSE）※公開する場合

```
myproject(root) /
 ├─ myproject /
 ├─ docs /
 ├─ tests /
 ├─ README.md (or README.rst)
 ├─ requirements.txt
 ├─ setup.py
 └─ LICENSE
```


## myproject
プロジェクトにおけるソースコードを保管するフォルダ。
myprojectは仮名（プロジェクト名称の任意名）であり、固定の名称ではない。
root直下のソースコードのフォルダにおいて、プロジェクトと同名を推奨としていたり、
同名となるフォルダ自体を設けるのが一般的なフォルダ構成としては推奨されないため、推奨しないとするスタンスがある。

```
myproject(root) /
 ├─ myproject /
     ├─ __init__.py
     ├─ __main__.py
     ├─ cli.py
     ├─ mylib /
        ├─ __init__.py
        ├─ mylib.py
```

プロジェクトが小規模である場合（ソースコードがmain.pyのみなど）は必須でないが、
ソースコードフォルダ（モジュール）であることを明示する「\_\_init_\_.py」と、
動作時の「おまじない」とよく言われる\_\_name_\_属性における、\_\_main_\_をプロジェクト内唯一として明示するために「\_\_main_\_.py」を配置する。
「\_\_main_\_.py」内は、以下のようなコードのみ記載する。(cli.pyの命名は任意）

```python
if __name__ == '__main__':
    from .cli import main
    main()
```

なお、プロジェクト実行時はrootフォルダにおいて、「\_\_main_\_.py」を起動するのではなく、プロジェクトとして実行する。

```bash
# pyhonファイル自体の実行例（今回非推奨）
python __main__.py

# pythonプロジェクト(module)の実行例（今回推奨）
python -m myproject
```

今回の構成では、前述の通り自作モジュール（mylib）はソースコード管理しているフォルダ内に保管している。
自作モジュールなどはプロジェクトのソースコードと同様のフォルダ内に全て保管するスタンスと、別途root直下に保管するスタンスがある。
root直下に保管するケースでは、他のプロジェクトでも使用するなどの運用面から判断されている場合がある。

モジュール内はモジュール認識のための「\_\_init_\_.py」が必須だが、それ以外の命名は特に指定しない。
一般的な話として、プロジェク全体内で重複する命名は避けるべきではあると思う。

## docs
プロジェクトにおけるドキュメントを保管するフォルダ。
一般にはpythonコミュニティで推奨されているマークアップ言語であるrst：reStructuredTextで記載する。
内容について記述できれば良いので、マークダウン(md)でも別に良い。
大規模プロジェクトやドキュメントの自動生成を行う場合はpythonにおいてはsphinxを用いることが一般的であるため、
sphinxによるドキュメント生成結果を保管してもよい。

```
myproject(root) /
 ├─ docs /
     ├─ conf.py
     ├─ index.rst
```

## tests
プロジェクトにおけるテストのためのコードを保管するフォルダ。
テストに関してはテスト手法としての概念が別途あるため、どのような構成であるかは厳密でないが、
テストコード自体をプロジェクト内で保管するという意味で、保管フォルダとしては定義する。

```
myproject(root) /
 ├─ tests /
     ├─ test_basic.py
     ├─ test_advanced.py
```

# 追加の構成
完全に使用ケースによるが、一般的に以下のような追加があるケースが想定される。
プロジェクトの運用状況（公開・非公開（内製完結））やチーム員のスキル、管理状況に応じる。

 * .venv：仮想環境の保管先
 * notebooks：Jupyter Notebook保管先
 * Examples：使用例の保管先
 * docker：dockerプロジェクトの保管先
 * .vscode：VScodeの設定保管先

# 最後に
本記事初段に記載した通り、適切な構造はプロジェクトに応じるため、一例としてまとめた。
本記事のプロジェクト構造について、内容をまとめると以下のようになる。

```
myproject(root) /
 ├─ docker /
 ├─ .venv /
 ├─ .vscode /
 ├─ notebooks /
 │
 ├─ myproject /
 │   ├─ __init__.py
 │   ├─ __main__.py
 │   ├─ cli.py
 │   ├─ mylib /
 │      ├─ __init__.py
 │      ├─ mylib.py
 │
 ├─ docs /
 │   ├─ conf.py
 │   ├─ index.rst
 │
 ├─ tests /
 │   ├─ test_basic.py
 │   ├─ test_advanced.py
 │
 ├─ README.md (or README.rst)
 ├─ requirements.txt
 ├─ setup.py
 └─ LICENSE
```

# 参考
[Python ヒッチハイク・ガイド_プロジェクトの構造化](https://python-guideja.readthedocs.io/ja/latest/writing/structure.html)
ASP.net　URLの最大文字数について　デフォルト値と変更方法

URLの文字数でエラーが出てきて、調べたのでメモ＆共有

##最大文字数##
https://docs.microsoft.com/ja-jp/dotnet/api/system.web.configuration.httpruntimesection.maxurllength?view=netframework-4.8

ドキュメントによると260文字

しかし、webブラウザは側では一応2000文字

##web.configから規定値を変えられる##
こいつを追記する

```xml
<httpRuntime maxUrlLength="2048" >
```

httpRuntimeの項目が既にある場合は、maxUrlLengthをつなげて書けば良い。
複数Modelが絡んだCSV出力

#はじめに
シンプルな関係のModelで出力はみかけるのですが、少し複雑な関係のModelからCSVを出力しようと思ったときに少しはまってしまいました。

```ruby
#シンプルな（親子）関係のModel
class Office
  has_many :users

class User
  belongs_to :office
```

上記のような関係のModelから取り出すときは比較的簡単にかけると思います。
Office（id: 1)に所属しているUserを取得したい場合

```ruby
users = User.joins(:office).where(offices: { code: 1 })

=> #<ActiveRecord::Relation [#<User id: 1, name: "ほげ", office_id: 1>,
                              #<User id: 2, name: "ふが", office_id: 1>,  ~~ 略 ~~]
   
```
 
usersをeachで回してCSVにすればいっちょ上がりですね。

けど、複雑な関係の場合はそうもいきませんでした。（自分の考え方が甘いだけかもですが）

#モデルの関係図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295863/8829e099-6a93-8e2f-bd4c-6282ee615857.png)
上記（簡素化してます）で、result_detailsに結合していってデータを引っ張ってくることとします。

##どうやったか

結論から言ってしまうと、下記の内容でControlerに直書きしました。
本当はModelに切り分けをした方がいいのですが、早く使いたいということでしたので切り分けはまた後日。

```ruby
  def data_create_to_csv
    respond_to do |format|
      format.html
      format.csv do |csv|
        started_on = Date.new(params[:started_on]["date(1i)"].to_i, params[:started_on]["date(2i)"].to_i, 1)
        # responceは後から追加したので、左外部結合で入力されていないデータも引っ張る
        details =
          ResultDetail.joins(:reson, result: [diary: { user: { office: :area}}]).
          eager_load(:reson, :responce, result: [diary: { user: { office: :area}}]).
          where(users: { employee_code: User.active.pluck(:employee_code) }).
          where(results: { result_on: started_on..started_on.end_of_month })

        filename = started_on.strftime("%Y年%m月")
        csv_data = CSV.generate do |csv|
          columns_name = %w(##ここにはカラム名を本当は入れます。)
          csv << columns_name
          details.each do |detail|
            values =
              [
                detail.result.result_on,
                detail.result.user_id,
                detail.result.diary.user.name,
                detail.result.diary.user.role,
                detail.result.diary.user.office_id,
                detail.result.diary.user.office.name,
                detail.result.memo,
                detail.visited_time.strftime("%H:%M"),
                detail.stay_time,
                detail.destination_code,
                detail.destination_name,
                detail.destination_address,
                detail.visitor,
                detail.content,
                detail.reson_id,
                detail.reson.name,
                detail.responce_id,
                detail.responce&.name
              ]
            csv << values
          end
        end
        send_data csv_data.encode(Encoding::SJIS, invalid: :replace, undef: :replace), filename: "#{filename}.csv"
      end
    end
  end
```
会社の固有名称とかあるのでそこは外させてもらいました。

send_dataとsend_fileでちょっとだけはまりました。（send_fileだといったん保存しないとerrorになる)

だいぶ駆け足でしたが、参考になれば幸いです。
【React Native】 子コンポーネントで定義されたTextInputで、Enterを押したときにAPIを実行

# はじめに

以下の内容をやるときの自分用メモ。

```
・子コンポーネントでクリックなり選択されたときに、親コンポーネントに通知して、
その後、親コンポーネントの関数なりを実行するようにする
・TextInputタグでonChanhgeとかで実行すると、stateが変更されるたびに
実行されてしまうので、Enter押したときに実行するようにする
```

# 内容

以下ファイル

```
・Main.tsx
・TextInput.tsx
```

Styleについては適当です。

```react:Main.tsx
import React, { useEffect } from 'react';
import { StyleSheet, View, ImageBackground, Alert } from 'react-native';
import axios from 'axios';
import { TextInput } from './TextInput';

export const Main = () => {
  const [searchQuery, setSearchQuery]: any = React.useState('初期値');
  
  const Hoge = () => {
    // 半角英数字入力を求めたりとか・・・
    if(!searchQuery.match(/^[A-Za-z0-9]*$/)){
      Alert.alert(
        'アラート',
        '半角英数で入力してください',
        [
          {text: 'OK', onPress: () => {}},
        ],
        { cancelable: false }
      )
      return
    }
    // API実行系
    const response = await axios.get(
      baseUrl + query
    )
    .then((res: any) => res.data)
  }
  
  子コンポーネントから渡された「setSearchQuery」が実行されると着火
  useEffect(() => {
    Hoge()
  }, [searchQuery])

  return (
    <View style={styles.container}>
      <ImageBackground source={{ uri: weatherImage}} style={styles.image}>
        <View style={styles.view_container}>
          <TextInput setSearchQuery = {setSearchQuery} />
        </View>
      </ImageBackground>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { 
    flex:1,
    flexDirection: "column"
  },
  image: {
    flex: 1,
    resizeMode: "cover",
    justifyContent: "center"
  }
});
```

```react:TextInput.tsx

import React, { useState } from 'react';
import { TextInput } from "react-native";

// interfaceでもいいが、ここはtypeで
type Props = {
    // Main.tsxコンポーネントへSearch結果を渡すためのprops
    setSearchQuery: any,
};

export const SearchHeader: React.FC<Props> = ({setSearchQuery}) => {
    const [search, setSearch] = useState("")

    // onSubmitEditingでEnterクリック後に着火
    function handleKeyPress() {
        // useStateでセットされた情報を「setSearchQuery」にのせる
        setSearchQuery(search)
    }

    return (
        <View style={styles.view}>
            <TextInput
                style={styles.input}
                placeholder="Search"
                onChangeText={(v) => setSearch(v)}
                value={search}
                onSubmitEditing={handleKeyPress}
            />
        </View>
    )
};

const styles = StyleSheet.create({
    view: {
        flex: 0.3,
        marginTop: 30,
        alignItems: 'flex-start', 
        flexDirection: 'row',
        justifyContent:'center',
    },
    arrow:{
        marginTop: 18,
        marginRight: 10,
        marginLeft: 16
    },
    input: {
        width: "70%",
        height: 35,
        borderColor: "#999",
        borderWidth: 1,
        borderRadius: 3,
        paddingHorizontal: 20,
        fontSize: 18,
        marginTop: 16,
        marginBottom: 16,
        textAlign: 'right',
        backgroundColor: '#DCDCDC',
        opacity: 0.3
    },
    search:{
        marginTop: 18,
        marginLeft: 10
    },
});
```
Qiita投稿時の意識していること

## 概要

Qiitaなどに投稿するときの自分が意識していることや、どうやって記事を書いているかを今回はまとめてみました。
気が向いたら追記するかも

## 記事の作成前の準備

* 記事を作成するときの意識する時にまず以下の点を考えます。
    * テーマを決める。
        * 記事にする内容を漠然とでもイメージする。
    * 記事の全体的な構成を考えます。
        * 概要にこの記事は何を表しているかを書くために何を書くか？
            * 概要を読んでどういう記事かわかるようにを意識します。
        * 前提条件になにがあるか？
        * 内容(実際にやったことを記載)
        * 必要に応じて考察や備考、注意点、参考文献など
            * 参考文献については引用するところでどこから？と記載すると同時に必要に応じて最後にまとめて記載します。
    * さらに詳細な内容として以下の点を考えます。
        * 前提条件はどこまで書くか？
            * OS,言語のバージョン,どのライブラリが必要かなど
        * コードを載せるとしたらどの部分を載せて説明をどう記載するか？
            * 関係する部分はどのあたりか？
            * 説明をどの範囲で挟むべきか？

## 記事の作成

* 記事を作成するときはまずは思うままに記載していきます。
* 結論まで記述した後全体を以下の観点で見直します。
    * 説明が通っているか？
    * 補足が何か必要か？
    * 語尾が統一されているか？
* 記事をまとめた後時間をおいて読み直します。
    * 可能であれば1日おいて文章が通っているかを見てみるとおかしいところに気づけます。
    * または逆から順に読んでいってつながりがどうかを見るなどしてみます。

## 心構え

* 心構えと書くと大げさですが以下の点を考えて記事を書きます。
    * 少しぐらいおかしいところは気にしない。
    * 何か突っ込まれてもそれは改善できる機会としてとらえる。
    * 反響がなくても気にしない。
    * とりあえずやってみる
JenkinsをAWS上で動かす②

## はじめに

Jenkins × Docker × AWS で動かしてみようとしています。
内容が長くなると思うので複数回にわけてまとめています。

https://qiita.com/jda7407/items/31111dfa131abceaa56d

の続きになります。

## 今回やること

前回、Dockerを使って、公式が提供しているJenkinsのイメージからJenkins起動までを行いました。しかし、これだけでは最低限必要なものしか入っていないので、
追加したいものを入れたイメージを作っていきます。

ベースは公式のイメージでそれに必要なものを追加してきます。

## Dockerfileの作成

公式イメージに追加でJenkinsのプラグイン「configuration-as-code」が入ったイメージ
を作成するDockerfileを作成します。

```Dockerfile:Dockerfile
FROM jenkins/jenkins:lts

# セットアップウィザードを無効化する
ENV JAVA_OPTS="-Djenkins.install.runSetupWizard=false"

# プラグインのインストール
COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt

# configuration-as-codeプラグインを使って予めadmin userを作成
COPY jenkins-casc.yaml /usr/local/jenkins-casc.yaml
ENV CASC_JENKINS_CONFIG /usr/local/jenkins-casc.yaml

```

プラグインのインストールについてはJenkinsの公式が提供している方法をそのまま使います。

https://github.com/jenkinsci/docker

plugins.txtというファイルを用意して、そこにインストールしたいプラグイン名を記載しておけば
インストールしてくれます。超便利

```Dockerfile
FROM jenkins/jenkins:lts-jdk11
COPY --chown=jenkins:jenkins plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli -f /usr/share/jenkins/ref/plugins.txt
```

今回はこんな感じ。

```:plugins.txt
configuration-as-code
```

configuration-as-codeはJenkinsの設定をyaml形式で記述し、その内容に従って設定してくれるというプラグインです。今回はユーザー設定だけ設定したyamlを用意しました。


```yaml:jenkins-casc.yaml
jenkins:
  securityRealm:
    local:
      allowsSignup: false
      users:
        - id: "admin"
          password: "admin"
        - id: "dev"
          password: "dev"
```

これを特定の場所にコピーして環境変数として定義してあげるだけです。

```Dockerfile
# configuration-as-codeプラグインを使って予めadmin userを作成
COPY jenkins-casc.yaml /usr/local/jenkins-casc.yaml
ENV CASC_JENKINS_CONFIG /usr/local/jenkins-casc.yaml
```

## イメージの作成

Dockerfileができたので、それをもとにイメージを作ります。

```
docker image build -t イメージ名[:タグ名] [Dockerfileが配置されているディレクトリパス]
```

イメージ名、タグ、はお好きなものにしてください。
今回はdockerコマンドを実行するディレクトリにDockerfileを置いているのでパスは「.」にします。

```shell

$ docker image build -t satoru/myjenkins:0.1.0 .

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
satoru/myjenkins    0.1.0               c0917eb4fea5        26 seconds ago      580MB
jenkins/jenkins     lts                 3c87c42366c1        3 weeks ago         576MB
```

イメージができたら起動させてみます。前回はイメージ名を「jenkins/jenkins:lts-jdk11」にしていますが、今回は「satoru/myjenkins:0.1.0」にしてあります。


```shell
docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home satoru/myjenkins:0.1.0
```


起動してみるとわかりますが、「configuration-as-code」プラグインが入った状態のJenkinsが立ち上がります。簡単！！


## おわりに

今回はプラグインインストール済みのJenkins環境を立ち上げるところまでまとめました。
次はこの作成したイメージを使ってAWSのECR上で動かして行きたいと思います。
FPGAボード SOY2 で Lチカ ー その3(動作確認)

## 概要

[「その2」](https://qiita.com/guinea_pig_t/items/e98f12aace6e665c613e) からの続きです。
Xilinx [Vivado](https://japan.xilinx.com/products/design-tools/vivado.html) で作成した、binファイル を mcsファイルへ変換、[SOY2](https://www.bbtech.co.jp/products/soy2/)に書き込み、動作確認しました。
SOY2 は、[SiTCPライブラリ](https://www.sitcp.net) (FPGA 用TCPライブラリ）を使用しているので、Ethernet を経由して書き込めて便利です。

![SOY2_LED.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205335/f5ee839c-21f2-133a-98a4-d6f1d79d0e18.gif)

## bitファイル → mcsファイル変換

ユーザーガイド([ダウンロードページ](https://www.bbtech.co.jp/download-files/soy2/index.html)より入手)に GUI を使用した説明がありますが、
Vivado の Tcl Console からコマンドを実行したほうが簡単な気がします。

~~~
write_cfgmem  -format mcs -size 8 -interface SPIx1 -loadbit {up 0x00400000 "soy2/soy2.runs/impl_1/SOY2.bit" } -checksum -force -file "soy2/soy2.runs/impl_1/SOY2.mcs"
~~~

ファイルのpathは、環境に合わせて変更し、Tcl Console で実行します。
SOY2.mcs ファイルに変換できます。

![tcl_console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205335/72364425-e080-39cf-7d8a-523a62cdcbeb.png)


## 書き込み

SiTCP Utility([SiTCP関連ダウンロードページ](https://www.bbtech.co.jp/download-files/sitcp/index.html)から入手) を使用して書き込みます。

SOY2 のデフォルトの IPアドレスは、192.168.10.16 です。
複数アドレスを割り当てられるので、エイリアス指定が便利です。以下では、192.168.10.100 を一時的に割り当てています。

~~~
sudo ifconfig en4 alias 192.168.10.100 255.255.255.0
~~~

SOY2 を、Ethernet ケーブルで接続します。
(ハブを介して接続しましたが、USB Ethernet アダプタなど使用して、直結でも大丈夫です）

SiTCP Utility を起動し、[読み込み]をクリックすることで、接続確認しました。

<img width=500 alt="check.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205335/71aac90a-6c5e-76c5-9490-b6f66bdfdede.png">


ユーザーズガイドに従い、書き込みます。

<img width=500 alt="tcp_tab.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205335/6d540073-18ab-6897-2f62-ba3d294d6154.png">

1. ディップスイッチ(SW2)の 4番をON（Loaderモード）にして SOY2 の電源を投入。
2. SiTCP Utility データ(TCP) タブをクリック
2. 送信設定で、送信元に mcs ファイルを指定
3. 受信ダイアログを開き、[受信開始]をクリック
4. 送信ダイアログを開き、[送信開始]をクリック
5. 受信ダイアログ [受信停止]をクリック

以上、で書き込み終了。

## 動作確認

ディップスイッチ(SW2)の 4番をOFF（User モード）にして SOY2 の電源を再度投入。
ディップスイッチ 2番をONにすることで、LEDが点滅することが確認できました。

![SOY2_LED.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205335/f5ee839c-21f2-133a-98a4-d6f1d79d0e18.gif)

サンプルソースを少し変更したものをインプリして、簡単な動作確認ができました。
今後は、[SiTCPライブラリ](https://www.bbtech.co.jp/products/sitcp-library/) を使ったデータ転送など試してみたいです。
github actionで`qt.qpa.xcb could not connect to display` 

github actionでPyQt5を使ったアプリをテストするも、`qt.qpa.xcb could not connect to display`でエラーになってしまった。

```
qt.qpa.xcb: could not connect to display 
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.
start.sh: line 40:  2323 Aborted                 (core dumped) python3 game_manager/game_manager.py --game_time ${GAME_TIME} --seed ${RANDOM_SEED} --obstacle_height ${OBSTACLE_HEIGHT} --obstacle_probability ${OBSTACLE_PROBABILITY} --drop_speed ${DROP_SPEED} --manual ${IS_MANUAL_CONTROLL} --use_sample ${IS_SAMPLE_CONTROLL}
Error: Process completed with exit code 134.
```

以下の通り、workflow上で環境変数追加と、`xvfb`をインストールして解決。

```
# 環境変数
env:
  DISPLAY: ':99'
```

```
      - name: Xvfb install and run
        run: |
          sudo apt-get install -y xvfb
          Xvfb -ac ${{ env.DISPLAY }} -screen 0 1280x780x24 &
```

以下は今回作成した`.yaml`ファイルの全体、ご参考。

```yaml:.github/workflows/test.yaml
name: Python package
      
on: [push]

# 環境変数
env:
  DISPLAY: ':99'

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.5, 3.6, 3.7, 3.8]

    steps:
      - uses: actions/checkout@v2
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8 pytest
          sudo apt-get install -y python3-pip
          pip3 install --upgrade pip
          pip3 install numpy
          pip3 install PyQt5
          sudo apt-get install -y python3-pyqt5
          sudo apt-get install -y git
          sudo apt-get install -y jq
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      - name: Lint with flake8
        run: |
          # stop the build if there are Python syntax errors or undefined names
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
      # xvfbのインストールと起動
      - name: Xvfb install and run
        run: |
          sudo apt-get install -y xvfb
          Xvfb -ac ${{ env.DISPLAY }} -screen 0 1280x780x24 &
      - name: tetris_game
        run: |
          git clone https://github.com/seigot/tetris_game
          cd tetris_game
          bash start.sh -s y -t 3
```

# 参考
[Usage on GitHub Actions with xvfb ](https://github.com/juliangruber/browser-run/issues/147)
TypeScript4.3.2のMappedTypes優先度変更の破壊的変更を回避する

# １．TypeScript4.3.2の破壊的変更について

## 4.3.1-rcから破壊的変更が混入

TypeScript4.3.2、正確には4.3.1-rcから致命的な破壊的変更がマージされてしまいました。細かい経緯は以下を参照してください

[Consider inferences between mapped type templates lower priority](https://github.com/microsoft/TypeScript/pull/44126)

## MappedTypesの優先順位の変更

これによってMappedTypesから型を抽出する際に、優先順位の変更が起こりました

# ２．発生内容について語る前の、前提条件の説明


## 変換前の基本の型

RestAPIの型をTypeScript上で展開するときによく使うのですが、以下のような基本型があったとします。keyによってデータの種類が異なっています。

```typescript
{
  200: { value: number };
  500: { error: string };
}
```

## 変換後の型

これを扱いやすい形にします。

```typescript
{
  code: 200;
  body: {value: number;};
} | {
  code: 500;
  body: {error: string;};
}
```

## 変換後に出来るようになること

```typescript
const func = (
  p: {
        code: 200;
        body: { value: number };
      } | {
        code: 500;
        body: { error: string };
      }
) => {
  if (p.code === 200) { //型が確定
    console.log(p.body.value);
  } else {
    console.log(p.body.error);
  }
};
```

上記のようにcodeの値によって、自動的に付随するデータの型を決定することが出来ます。
私はopenapi-typescriptというパッケージで生成した型情報を、以上のような形で変換して使っています。

# ３．変換処理をTypeScriptで書いた場合と、バージョン間の差異について

## 型変換を行うためのコード

この変換を行うためにはMappedTypesで型情報を生成し、生成した情報を部分的に切り出す流れになります。

```typescript
type Base = { 200: { value: number }; 500: { error: string } };
type ConvertType<T = Base> = {
  [P in keyof T]: {
    code: P;
    body: T[P];
  };
} extends {
  [P in keyof T]: infer R;
}
  ? R
  : never;
```

## バージョンによる差異

### 4.3.1-rc未満

```typescript
{
    code: 200;
    body: {
        value: number;
    };
} | {
    code: 500;
    body: {
        error: string;
    };
}
```

### 4.3.1-rc以降

```typescript
{
    code: keyof Base;
    body: {
        value: number;
    } | {
        error: string;
    };
}
```

### 4.3.1-rc以降では型の抽出に失敗

inferで抽出した型情報として、本来オブジェクト単位でunionにするべきところが、オブジェクト内のプロパティ部分で統合されています。これでは使い物になりません。

# ４．致命的な破壊行為に対抗する

なし崩し的にこの変更がマージされていますが、まともにTypeScriptの機能を利用している側からするとたまったものではありません。現状でこの優先順位の変更がTypeScript上で解決される気配が全く見えません。ということでこの優先順位の変更に対する対策を自らが講じる必要があります。

## 対策コード

```typescript
type Base = { 200: { value: number }; 500: { error: string } };
type ConvertType<T = Base> = {
  [P in keyof T]: {
    code: P;
    body: T[P];
  };
} extends {
  // [P in keyof T]: infer R;
  [P in any]: unknown extends unknown ? infer R : never
}
  ? R
  : never;
```

試行錯誤したあげく、苦肉の策で導き出したコードです。inferで抽出する前に意味の無い型変換を行い、強制的に優先順位を変更するという技です。これで全バージョンで共通して目的の型を抽出することが出来ます。

ちなみにこのコード、eslintがRは未使用だという警告を発します。どうやら理解不能コード過ぎて解釈しきれないようです。

# TypeScriptの恐怖

TypeScriptは頻繁に新機能が導入されています。おかげでとても便利になっている反面、時々ヤバい変更が投げ込まれるようです。複雑な型情報を処理しているとコードがパズル化していくのですが、TypeScript上でそのパズルのルールが変更されたとき、空から恐怖の大王が来るのです。
チーム開発で異なる環境でも、pre-commitでコマンドを正しく実行する

開発メンバー内で、開発環境をローカルで立てるか、Dockerにするかなど、分かれることがあるかもしれません。(本当は統一すべきと思いますが、あまりローカル環境を汚したくないとか、Docker 遅いとかあるので)
そうした時、pre-commit などで prettier などを実行している場合、環境によって多少コマンドが変わってくるかと思います。

環境が異なっても、pre-commit などで正しくコマンドを実行して欲しい問題の解決法を記載します。

## 解決方法

- `.env` ファイルで、Docker を利用しているか否かを記載する
- pre-commit で実行されるコマンドを、 .env の内容に応じて場合分けしてあげる

### .env を設定する

```env:.env
DOCKER_ENABLE=false
```

### pre-commit の script の変更

- husky v6 の記載になります。

```sh:.husky/pre-commit
#!/bin/sh

. "$(dirname "$0")/_/husky.sh"
. "$(dirname "$0")/../.env"

if "${DOCKER_ENABLE}"; then
  docker run --rm -v $CWD:ボリュームするディレクトリ イメージ名 yarn format
  exit -1
fi

yarn format
```

これで、Docker を利用する場合はコンテナ上で format を、
利用していない場合は、ローカルで format を実行できます。

もっと良いやり方はあるかもしれませんが、ひとまずこれで解決はできそうです。
【AndroidStudio】RelativeLayout

#■RelativeLayoutとは
RelativeLayoutとは、基準となるパーツを決め、それとの相対的な関係で位置を決めていくというレイアウトです。

簡単な例
■レイアウトの
右
上
下
左

■Aって言う部品を基準にして位置を決めている。
Aの横
Aの上
Aの下など
そのためにはtextやButton等にIDを割り当てる事が大切。

#■レイアウトを基準としてtrueにする。
レイアウトを基準に配置したい場合は、下記の属性を「true」にする
android:layout_alignParentTop　：　レイアウトの上端
android:layout_alignParentBottoｍ　：　レイアウトの下端
android:layout_alignParentLeft　：　レイアウトの左端
android:layout_alignParentRight　：　レイアウトの右端
android:layout_centerHorizontal　：　レイアウトの水平方向の中央
android:layout_centerVertical　：　レイアウトの垂直方向の中央
android:layout_centerInParent　：　レイアウトの中央

例:

``` kotlin
 <Button
       android:id="@+id/a"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
      //レイアウトの中央
       android:layout_centerInParent="true"
       android:text="Button"/>
```
![スクリーンショット 2021-05-30 20.45.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/af1f906f-7b3e-2949-21b7-ccad561e297b.png)

#■パーツから基準とした位置
基準としたパーツをidで指定し距離を指定する
layout_below　:　指定したパーツの下に配置
layout_above  : 指定したパーツの上に配置
layout_alignLeft　:　指定したパーツの左に配置
ayout_toRightOf　:　指定したパーツの右に配置

``` kotlin
   <Button
       android:id="@+id/a"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_centerInParent="true"
       android:text="A"/>

    <Button
        android:id="@+id/b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       //aの下側
        android:layout_below="@+id/a"
        android:text="B"/>
```

![スクリーンショット 2021-05-30 20.56.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/5e665da7-1a6e-1fca-ea0a-9d2ec091fb79.png)

#■基準としたパーツやレイアウトからの距離を指定する

layout_alignLeft 左基準 指定したviewと同じ左揃え。
layout_alignRight 右基準 指定したviewと同じ右揃え。
layout_alignTop 上基準 指定したviewと同じ上揃え。
layout_alignBottom 下基準 指定したviewと同じ下揃え。

``` kotlin
<Button
       android:id="@+id/a"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="center|bottom"
       android:layout_centerInParent="true"
       android:text="A"/>

    <Button
        android:id="@+id/b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
       //aの下
        android:layout_below="@+id/a"
       //aと同じ右揃え
        android:layout_alignRight="@+id/a"
        android:text="B"/>
```

![スクリーンショット 2021-05-30 21.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558142/1ec8e2bc-2121-f476-9d04-59d5fdd85f5b.png)
【OCI】新しいバージョンのDRGを試す③ - サイト間VPN(IPSec) -

###概要
今回は新しいバージョンのDRGを使ってサイト間VPN(IPsec)接続を試します。

###検証構成
・「<font color="red">**[【OCI】新しいバージョンのDRGを試す① - DRG作成、VCNアタッチ -][1]**</font>」
の検証構成にサイト間VPN(IPSec)を追加します。
[1]:https://qiita.com/hongmnh/items/4c52f6f2359145bd6670
・On-Premises側のCPEはNEC製のIX2105を利用、LAN側にはテスト用PCを接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/69dbfc33-b292-cd57-8e7a-1c1ca17f6883.png)

###設定
①顧客構内機器(CPE)作成
[ネットワーキング] ⇒ [顧客接続性] ⇒　[顧客構内機器]に移動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/99bcfc2b-a146-c575-c133-e6a1b382a90a.png)
[顧客構内機器の作成]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/c1dd4951-6b11-c22f-fd5f-f4d50549de83.png)
以下CPE関連情報を入力後、[CPEの作成]をクリック
・名前: 任意の名前
・パブリックIPアドレス: CPEのパブリックIPアドレスを入力
・CPEベンダー情報: ベンダー、プラットフォーム・バージョン情報を求められます
　　　　　　　　　  該当するものがない場合はベンダーに[Other]を選択します
　　　　　　　　　　　※ベンダーとプラットフォーム・バージョンを入力すると
　　　　　　　　　　　　<font color="red">**[CPE構成ヘルパー][2]**</font>機能を利用することができます
[2]:https://docs.oracle.com/ja-jp/iaas/Content/Network/Tasks/CPEconfigurationhelper.htm
                 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/29a58184-867a-87e4-e3b9-6e8f7a7138d8.png)

②サイト間VPN(IPSec)設定
[ネットワーキング] ⇒ [顧客接続性] ⇒　[サイト間VPN(IPSec)]に移動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/55ca8253-9ea3-90b1-4a22-1c67466e0f5a.png)
[IPSec接続の作成]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/3bb4195b-7d25-5c9c-c94c-70c0a4ec3d13.png)
名前に任意の名前を入力、顧客構内機器に先ほど作成したCPEを指定、
VPN接続に利用する動的ルーティング・ゲートウェイ(DRG)を指定します。
続いて[拡張オプションの表示]をクリックしてトンネル情報入力に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/81d50a3d-4a80-a680-434a-8f643c762fcd.png)
以下の通り、トンネル関連設定を入力します(トンネル1,2共に入力が必要)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/963eea69-b3f3-12ca-bc4e-fef424fc046f.png)

③設定結果確認
OCI側CPE側共に正しく設定が完了すれば[サイト間VPN(IPSec)]のステータスが
以下にように変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/50e12d0f-0816-f680-bf59-3bfdc2095af5.png)
DRG詳細のリソースにて[IPSecトンネル・アタッチメント]を選択します。
上記の①②設定結果、自動的にアタッチメントが作成されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/2cfdce56-9e83-88ec-0607-5324c513a3ae.png)

###動作確認
On-Premises上のテストPCとSEOUL REGIONの2つのVCN上にあるインスタンス間で
pingによる疎通確認を実施し全ての確認において応答が返ってくることを確認しました。

①192.168.0.100 ⇒ 10.0.1.100,10.1.1.11
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/389c953d-223b-0cf8-5232-d1e6b6f1a125.png)
②10.0.1.100 ⇒　192.168.0.100
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/b8108913-f107-4b27-08bd-e6b06386db67.png)
③10.1.11.11 ⇒　192.168.0.100
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411653/7352b277-9432-3cb2-e56a-884ea707c98c.png)

###参考資料
・<font color="red">**[Setting Up VPN Connect][3]**</font>
[3]:https://docs.oracle.com/en-us/iaas/Content/Network/Tasks/settingupIPsec.htm
・<font color="red">**[IX2000シリーズルータとOCI間をVPN接続、BGPでルート制御してみた][4]**</font>
[4]:https://qiita.com/hongmnh/items/b0845e3465caad432447
数字の作り方

#1 はじめに
数字の生成方法についてまとめました。

#2 環境
VMware Workstation 15 Player上の仮想マシンを使いました。
仮想マシンの版数は以下のとりです。

```console:CentOSの版数
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 8.3.2011
```

```console:カーネル版数
[root@server ~]# uname -r
4.18.0-240.el8.x86_64
```

#3 連続に出力する方法(seqコマンド)

##3.1 昇順に出力する方法
1から5までを昇順に出力してみます。

```console:実行結果
[root@server ~]# seq 1 5
1
2
3
4
5
```

##3.2 降順に出力する方法
5から1までを降順に出力してみます。

```console:実行結果
[root@server ~]# seq 5 -1 1
5
4
3
2
1
```


##3.3 増加数を指定する方法
10から15まで、2ずつ増やしながら出力してみます。

```console:実行結果
[root@server ~]# seq 10 2 15
10
12
14
```


##3.4 数字の幅を等しくする方法(-w)
先頭を0で埋めて、数字の幅を等しくしてみます。

```console:実行結果
[root@server ~]# seq -w 10
01
02
03
04
05
06
07
08
09
10
```

##3.5 書式を指定する方法


```console:実行結果
[root@server ~]# seq -f '%02g' 1 3
01
02
03
```

```console:実行結果
[root@server ~]#  seq -f 'file%02g.txt' 1 3
file01.txt
file02.txt
file03.txt
```


##3.6 セパレータの使い方(-s)
セパレータのデフォルトは改行(`\n`)です。
まず、セパレータに`,`を指定してみます。

```console:実行結果
[root@server ~]# seq -s ',' 1 5
1,2,3,4,5
```

次に、セパレータに`:`を指定してみます。

```console:実行結果
[root@server ~]# seq -s ':' 15 -1 10
15:14:13:12:11:10
```

##3.7 16進数を表示する方法
seqには16進数を表示すオプションがないようなので、printfコマンドを使って16進数を表示します。

```console:実行結果
[root@server ~]# seq 10 16|xargs printf '%x\n'
a
b
c
d
e
f
10
```



#4 連続に出力する方法(echoコマンド)
1から5までを昇順に出力してみます。

```console:実行結果
[root@server ~]# echo {1..5}
1 2 3 4 5
```

10から1まで、3ずつ降順に出力してみます。

```console:実行結果
[root@server ~]# echo {10..1..3}
10 7 4 1
```

#5 ランダムに出力する方法
##5.1 shufコマンドを使う方法

```console:実行結果
[root@server ~]# shuf -i 1-5
4
2
1
3
5
```

##5.2 ファイルの中身をランダムに並び替える方法

```console:事前準備(ファイルの作成)
[root@server ~]# seq 10 14 > test.txt
```

ファイルの中身をランダムに並び替えてみます。

```console:実行結果
[root@server ~]# shuf test.txt
14
11
12
13
10
```

##5.3 16進数の数字をランダムに表示する方法

```console:実行結果
[root@server ~]# shuf -i 10-20|xargs printf '%x\n'
c
a
d
12
14
11
10
e
13
b
f
```


#Z 参考情報
[【 shuf 】コマンド――入力行をシャッフルして出力する](https://www.atmarkit.co.jp/ait/articles/1705/25/news018.html)
[【 seq 】コマンド――数字の列を出力する](https://www.atmarkit.co.jp/ait/articles/1705/18/news033.html)
[shuf - 入力行をランダムに表示する](https://linuxcommand.net/shuf/#_-e)
[26.3 seq: Print numeric sequences](https://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html#seq-invocation)
Googleフォトが有料化するからIFTTTでiOSからEvernoteに自動連携させよう。

**え、できるやん。**

IFTTTで連携するようなのはAndoroidはあるけどiOSはない、みたいなイメージでいましたけど、アプレットあるやん…！

#課題
・Googleフォトが6月から有料になる。
・Evernoteをデバイス2台以上で使いたいので3100円を課金したけれど**容量を全然使っていなくてもったいない気がしている。**

#課題の解決方法
IFTTTの「iOS Photos」をトリガーに、「Evernote」をアクションにして、iPhoneでスクショ／撮影したらEvernoteに自動でノートが作成されるようにします。

Googleフォト有料化後の乗り換え先としては下表のようになります。（Evernoteプラスは2018年で新規加入終了してます）
こうしてみるとEvernoteは割高なのでGoogleフォトの逃げ先目的だけなら勧めませんが、Evernoteに課金しているならついでに利用する、と考えるとiCloudの1560円／Google Oneの2500円が浮く計算です。**ふむ、悪くない。**

|サービス名|容量|価格|
|----|------|------|
|iCloud|50GB|年額1560円|
|Google One|100GB|年額2500円|
|**Evernoteプラス**|**1 GB/月（＝年12GB）**|**年額3100円**|
|Google One|200GB|年額3800円|
|iCloud|200GB|年額4800円|
|Evernoteプレミアム|10 GB/月（＝年120GB）|年額7200円|

#手順
IFTTTの「iOS Photos」アプレットの「New Screenshot」をトリガーにします。（私はスクリーンショットと普通の写真のノートブックを分けたい思惑でそうしてます。写真全体や、フロントカメラの写真だけ、ということも選べます）

![0530-iOSPhotos-1809.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/d1b59e2a-61cc-b3ff-b602-58ce8ac4904a.png)

「Evernote」の「Create image note from URL」をアクションにします。

![0530-Evernote-1811.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/5aba8808-84f7-70da-883e-59379e989780.png)


以下がIFTTTの「Evernote」の設定画面ですが、デフォルト値のままで動作しました。

![0530-Evernote-1813.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/75206e0a-2520-da74-a66f-ab0ed069be47.png)

IFTTTをONにすると、スマホの電話番号の入力を促されます。ここまでiOSの認証がなかったので不思議でしたが、ここからやるんですね。

![0530-IFTTT-1814.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/7bf004ff-a921-8164-58d2-cd93bd354faa.png)

と思ったらAppStoreのURLだけだったでござる。（番号の実在を確認してるのかは不明）
![0530-ios-2012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/2cc5bfe2-5000-5e2f-ccc7-4c3ca03df6cf.png)

気を取り直してiOSでIFTTTのアプリをダウンロード、ログインします。
するとiPhoneの写真へのアクセス許可を求められるので「OK」をクリック。
**これだけでiOS側の設定は終わりでした。**

iPhoneでスクショを撮ってみると、ちゃんとEvernoteにノートが作られていました！
**簡単！**

![IMG_9722.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1289676/d2ccbf58-6584-d2a2-fbcd-00f7bc0472a5.png)

#ちょっと宣伝

7月までに

「ガジェットレビュー動画をもっと効率的に見れたらなぁ」
「イマイチ動画はサマリして、プロ目線の解説動画だけ見たいなぁ」

を叶えるソフトを作ろうと思っています。
ただ目的がニッチなので、

ソシャゲで
「最適武器動画をサマリして多数派を知りたい」
「アリーナでレア編成で勝っている人の動画を見つけたい」

投資・仮想通貨で
「Youtube動画を検索して今後の見通しの意見をサマリする」
「総悲観・総楽観を見極める」

などの他の利用用途もありかな、とアンケートを取っています。
拡散力が低くて悩んでおりますので、気になった方、投票＆リツイートのお力添えをお願いします！

https://twitter.com/ShinsukeSutou/status/1398606146135490569


https://twitter.com/ShinsukeSutou/status/1398606775679471620
【試験合格記】AWS 認定 データアナリティクス – 専門知識(DAS-C01)

お疲れさまです。
表題の試験に合格したため記録として残したいと思います。

# 結果
合格(776点)

# 試験内容の出題分野と比重

[AWS-Certified-Data-Analytics-Specialty_Exam-Guide.pdf](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-data-analytics-specialty/AWS-Certified-Data-Analytics-Specialty_Exam-Guide.pdf)

|分野|名称|割合|
|:-----------------|:-------------------|:-------------------|
|1|収集|18%|
|2|格納およびデータ管理|22%|
|3|処理|24%|
|4|分析および可視化|18%|
|5|セキュリティ化|18%|

# 所感
旧試験であるビッグデータの出題内容から比較するとデータレイクの選択とデータ分析のアーキテクチャに振りが強くなったように感じました。
以前のようにノールックでDynamoDBやS3が含まれた選択肢を選択するだけだと合格はかなり厳しいと思います。

# 受験者に向けたアドバイス
- Kinesisに属する各サービスの特徴と他リソースとどう連携するべきかを理解する
- 顧客要件に応じてデータストアにRDSやRedshiftなどどれが適切かを把握する
- リアルタイム性が求められる分析と、そうではない分析の違いを理解する
- DMSの活用方法を正しく学習する
- EMRと互換性のあるサービスの特徴を理解する
- ElasticSearchがどんなサービスで、親和性の高いサービスを理解する
- [AWSではじめるデータレイク: クラウドによる統合型データリポジトリ構築入門](https://www.amazon.co.jp/AWS%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AC%E3%82%A4%E3%82%AF-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E7%B5%B1%E5%90%88%E5%9E%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E6%A7%8B%E7%AF%89%E5%85%A5%E9%96%80-%E4%B8%8A%E5%8E%9F-%E8%AA%A0/dp/491031301X)を読破する

# まとめ
他のAWS試験にも共通して言えることですが、設問の求める要件が何なのかを正しく読み解くことが重要です。
また、基本的に「あまり頑張らずにどうやってマネージドサービスを組み合わせて楽に要件を達成するか」という観点で選択肢の中から答えを探すゲームなので、それを念頭にどの組み合わせが何を実現できるのかをしっかり学習するとよいと思います。
あとはS3ライフサイクルの問題も出てきやすい為、実務でのコスト削減にも繋げやすい実用的な試験でした。

これで早くとも1年以上はAWS試験にチャレンジする必要が無いはずですので、次はCKSの合格を目指して頑張っていきます。
Next.jsの環境構築の手順

Next.js のプロジェクトを作る時に、自分なりに設定しているところをまとめました。

## こんな環境を作るよ

- **TypeScript**
- **Jest**
- **ESLint**
- **Prettier**
- Sass
- stylelint
  - アルファベット順に並び替える、[properties-alphabetical-order](https://github.com/hudochenkov/stylelint-order/blob/master/rules/properties-alphabetical-order/README.md#properties-alphabetical-order) を使用
- husky
  - pre-commit で lintを回す用にしたい

記載しているうち太字のものは、テンプレートを利用することで、導入はほぼ手間なく行えます。

## プロジェクトの作成

Next.js はexamples と呼ばれる、テンプレートのようなものを公式で提供しています。
検討している構成に近いテンプレートを利用することで、環境構築の手順が少なくなるのでこちらの利用が便利です。
[with-typescript-eslint-jest](https://github.com/vercel/next.js/tree/canary/examples/with-typescript-eslint-jest) という example を使って、プロジェクトを作成します。

```
npx create-next-app --example with-typescript-eslint-jest プロジェクト名
```

## Sass のインストール

CSS Modules で Sass を使えるようにします。
公式に沿ってインストールすればこちらは完了です。

```
yarn add sass
```

## stylelint のインストール

### 必要なパッケージのインストール

```
yarn add -D stylelint stylelint-config-prettier stylelint-config-recommended-scss stylelint-prettier stylelint-scss stylelint-order npm-run-all
```

インストールしたプラグインは下記

- stylelint
- stylelint-prettier
  - stylelint 上で Prettier が実行される
- stylelint-config-prettier
  - Prettier と stylelint の競合するルールを無効化してくれる
- stylelint-config-recommended-scss
  - 推奨されている SCSS のルール
- stylelint-scss
  - SCSS 構文に対応する
- stylelint-order
  - プロパティの並び替えを実現してくれる
- npm-run-all
  - npm script の並列実行を行えるようにする。ESLint と Stylelint を同時に実行するために入れておく

### .stylelintrc

stylelint を実行する際のルールなどを記載します。

```json:.stylelintrc
{
  "plugins": [
    "stylelint-order",
    "stylelint-scss"
  ],
  "extends": [
    "stylelint-prettier/recommended",
    "stylelint-config-recommended-scss"
  ],
  "ignoreFiles": [
    "**/node_modules/**"
  ],
  "rules": {
    "at-rule-no-unknown": [
      true,
      {
        "ignoreAtRules": ["function", "if", "else", "for", "each", "include", "mixin", "content"]
      }
    ],
    "order/properties-alphabetical-order": true,
  }
}
```

### npm script の修正

`scripts` に下記を記載します。

```json:package.json
{
  "scripts": {
    "lint": "run-p lint:*",
    "lint:css": "stylelint src/styles/**/*.scss",
    "lint:js": "eslint . --ext .ts,.tsx,.js,.jsx",
    "format": "run-p format:*",
    "format:css": "yarn lint:css --fix",
    "format:js": "yarn lint:js --fix",
  }
}
```

## husky@6 のインストール

テンプレートで入っている husky のバージョンが4系なので、6系に上げてしまいましょう

### 必要パッケージのインストール

```
$ yarn add -D husky@6.0.0 \
  && yarn husky install \
  && npm exec -- github:typicode/husky-4-to-6 --remove-v4-config
$ yarn husky add .husky/pre-commit "yarn lint-staged"
```

### package.json に設定を追加する

指定された拡張子のファイルが commit された時、Prettier の format を実行するようにします。

```json:package.json
{
  "lint-staged": {
    "*.{ts,tsx,js,jsx,scss}": [
      "yarn format"
    ]
  }
}
```

## その他

### VSCode の設定

- 拡張機能の、`"dbaeumer.vscode-eslint"`、`"stylelint.vscode-stylelint"`をインストールする
- ファイルを保存した時に、自動でフォーマットを整えるように `settings.json`を記載する。

```json:.vscode/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.stylelint": true
  },
  "editor.formatOnSave": false,
}
```
STM32G031と内部ADCとNJL7502Lでなんちゃってluxをソフトウェアシリアル出力(明るさ)


x約2Vで約400luxにならないといけないがたんに電圧の200倍にする

目的
adcのテスト用

構成
STM32G031J6M6
NJL7502L

この命令でstm32のadcは、12ビットになる。


```c++

  analogReadResolution(12); //stm32g031 adc 12bits


```

ソース


```c++



//#define in7 1 //uno
#define in7      PB7  // 1pin

#define DW   digitalWrite

//#define UART_DELAY 832 //  1200bps ok 031
#define UART_DELAY 102   //  9600bps ok 031

//10の割り算 0から1028までは、正しい。主に0から999
//#define DVI10(n) ((n*205)>>11)

//仮想シリアルへの一文字出力 9600bps
int pc_putc(char ch) {

  DW(in7, HIGH);

    //q_st =  micros(); //debug

  DW(in7, LOW);//START
  delayMicroseconds(UART_DELAY);

  for(int ii=0;ii<8;ii++){
    DW(in7, (ch>>ii)&1  );
    delayMicroseconds(UART_DELAY);
  }//for

  DW(in7, HIGH);//Stop
  delayMicroseconds(UART_DELAY);

    //q_et =  micros(); //debug 引いた数が0で1041usなら正解

  return(0);

}//pc_putc

//文字列の表示
int pc_printf(char *str1) {

    //文字の中身がゼロか
    while(*str1){

        //一文字出力
        pc_putc(*str1 ++);
        //Serial.print( *str1 ++ ); //uno

    } //while

    //戻り値
    return(0);
}//pc_printf

//0から999まで文字列に変換
char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
  int a,b,c;

  b=l_num/10;
  c=l_num-(b*10); //1の桁
  a=b/10;         //100の桁
  b=b-(a*10);     //10の桁

  ch_hex_a_b[0] = '0' + a;
  ch_hex_a_b[1] = '0' + b;
  ch_hex_a_b[2] = '0' + c;
  ch_hex_a_b[3] = 0;

  return(ch_hex_a_b);
}//ch_hex_a

//初期化
void setup()
{
  //ポートをhiにする 初期化
  pinMode(in7, OUTPUT);
  DW(in7, HIGH);
  delayMicroseconds(UART_DELAY*10);

  analogReadResolution(12); //stm32g031 adc 12bits

  //Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  int s; //センサーの値  //101
 
  s = analogRead(A3); // PA11 PIN5

//d  String thisString2 = String(s);
//d  pc_printf( (char *)thisString2.c_str() );
//d  pc_printf("\r\n");

//  //adcの値4096に6600掛けて8192で割ると3300になる
//  //電圧に変換 ex 3.300 -> 3300 mVを出力
//  s=(  (s)  *6600)>>13;
//  //sを2倍して10で割るとluxになる
//  s= ( s*2 ) / 10; 

  //adcの値4096に660掛けて4096で割ると660になる
  s=((  (s)  *660)>>12);

//d  String thisString3 = String(s);
//d  pc_printf( (char *)thisString3.c_str() );
//d  pc_printf("\r\n");

  //明るさの小数点以上の表示
  pc_printf(  ch_hex_a(s)  );

  //リターン
  pc_printf(  "\r\n"  );

  //1秒の待ち
  delay(1000);

} //loop



```

![soft_serial_adc_lux_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4353ea17-4d8a-b464-4688-ca1e3ea93736.jpeg)