OmniAICreator/Qiita-1.07M huggingface dataset:
結果確認

library(readxl)
#データ読み込み
p<-read_excel("./de_p.xlsx")
de_date<-read_excel("./de_date.xlsx")
de_res<-read_excel("./de_res.xlsx")
de_res_t<-read_excel("./de_res_t.xlsx")
forecast_date<-read_excel("./forecast_date.xlsx")

#対象リスト確認
p_list<-p$p
de_date_list<-de_date$date
forecast_date_list<-forecast_date$date
de_date_list<-forecast_date$date

#all data保存用テーブル
all_forecast_date<-data.frame(forecast_date_list)

#大外ループ
for (p_name in p_list) {
  print(p_name)
  
  #内ループ
  
  #予測テーブル作成
  #当月
  tar_month0<-data.frame()
  #1月後
  #tar_month1<-data.frame()
  #2月後
  #tar_month2<-data.frame()
  
  for (date_time in forecast_date_list) {
    print(as.Date.POSIXct(date_time))
    tar_date<-as.Date.POSIXct(date_time)
    
    #パターン①過去3か月の平均値を予測値
    #実績実績の読み込み
    #x月間のデータを使う
    cal_term<-3
    
    term_res<-data.frame()
    for(term_num in cal_term:1){
      #x月前の読み込み
      #実績月データから、x月前のデータを取得
      #実績データリストの中でx月の位置
      tar_month_num<-(1:length(de_date_list))[as.Date(de_date_list[1:length(de_date_list)]) == as.Date(tar_date)]
      tar_before_month_num<-tar_month_num-term_num
      #x月前月の値
      tar_before_month<-de_date_list[tar_before_month_num]
      
      #x月前の実績数
      term_de_res<-de_res_t[de_res_t$p==tar_before_month,p_name]
      term_de_res_table<-data.frame(tar_before_month,term_de_res)
      
      #計算用データテーブルに保存
      term_res<-rbind(term_res,term_de_res_table)
    }
    
    colnames(term_res)<-c("date","demand")
    de_res_t[as.Date(de_res_t$p)==as.Date(tar_date),p_name]
    
    
    #当月予測
    tar_date_res<-mean(term_res$demand)
    forecas_tar0_date<-data.frame(tar_date,tar_date_res)
    tar_month0<-rbind(tar_month0,forecas_tar0_date)
    
  }
  #予測結果抽出
  res_frame<-data.frame(tar_month0[,"tar_date_res"])
  #名
  colnames(res_frame)<-c(p_name)
  #データ保管
  all_forecast_date<-cbind(all_forecast_date,res_frame)
}

month0_forecast_res<-all_forecast_date

###############################################
#実績テーブル作成
##############################################

#all data保存用テーブル
all_de_date<-data.frame(de_date_list)

#大外ループ
for (p_name in p_list) {
  #内ループ
  
  #実績結果テーブル作成
  #当月
  de_month0<-data.frame()
  #1月後
  #tar_month1<-data.frame()
  #2月後
  #tar_month2<-data.frame()
  
  for (date_time in forecast_date_list) {
    print(as.Date.POSIXct(date_time))
    tar_date<-as.Date.POSIXct(date_time)
    
    #当月実績
    tar_date_res<-de_res_t[as.Date(de_res_t$p)==as.Date(tar_date),p_name]
    de_tar0_date<-data.frame(tar_date,tar_date_res)
    de_month0<-rbind(de_month0,de_tar0_date)
    
  }
  #結果抽出
  res_frame<-data.frame(tar_month0[,"tar_date_res"])
  #名
  colnames(res_frame)<-c(p_name)
  #データ保管
  all_forecast_date<-cbind(all_forecast_date,res_frame)
}



#1月後
#    mean(term_res$demand)
oracleではLIMIT句が使えずドツボにはまった初心者の話

# oracleではLIMIT句が使えずドツボにはまった初心者の話

タイトルにある通りoracleDBではLIMITが使えないためいろいろと試行錯誤を繰り返したので記録程度に載せておく。

## やりたかったこと
例えばこのようなテーブルがあるとして

|num|id  |内容  |created  |
|---|---|---|---|
|1|1|りんご |08:00  |
|2|1|バナナ |09:00  |
|3|2|もも |10:00|
|4|2|キウイ |11:00|
|5|3|ブドウ |12:00|
|6|3|なし |13:00|

「id」毎の最新の情報列だけを取得したい、というもの。

期待する結果は

|num|id  |内容  |created  |
|---|---|---|---|
|2|1|バナナ |09:00  |
|4|2|キウイ |11:00|
|6|3|なし |13:00|

このようなもの。

方法を調べ進めていくうちに、「LIMIT」を使えばうまくできそうじゃないか？と思ったのだがどうやらoracleDBはLIMIT句が使えない仕様らしい。

と思ったが、他の方法を利用できないか探してみたところ幾つか解決方法が見つかった。<br>

それらがコチラ↓

- 「GROUP BY句」を使用する

- 「ROWNUM句」を使用する

GROUP BY句であれば上記の重複を回避できるのではないか？<br>
と思い記述してみたが、結果は下図のような出力。

|id |created|
|---|---|
|1|09:00|
|2|11:00|
|3|13:00|

基準にしたカラム以外のデータを取得できず、idとcreatedだけの結果になってしまった。

次にROWNUM句、これは取得する行数を指定することができるモノ。<br>
コードにて、ROWNUM = 1 とすると出力結果から指定した数値行のみ取得することができる。<br>
ROWNUM句を利用し、期待通りの結果を出力する下記のコードを記述した。<br>

### ① テーブルの「id」のみをすべて取得する（同じidが複数存在する場合は１つのみ取得）<br>
|id|
|---|
|1|
|2|
|3|

### ② ①で取得した「id」を基準に各idの情報を取得<br>

|num|id  |内容  |created  |
|---|---|---|---|
|1|1|りんご |08:00  |
|2|1|バナナ |09:00  |

### ③ ②の結果を最新順に並べ替え、一列目の情報だけを取得するSQL文（ここで「ROWNUM = 1」を使用している）<br>
idが1の場合、出力結果はこうなる<br>

|num|id  |内容  |created  |
|---|---|---|---|
|2|1|バナナ |09:00  |

### ④ 各id毎に同じ手順を行い、created順でソートを行う<br>
出力結果は<br>

|num|id  |内容  |created  |
|---|---|---|---|
|2|1|バナナ |09:00  |
|4|2|キウイ |11:00|
|6|3|なし |13:00|

となり、期待通りのデータを取得することに成功。<br>
しかし、割と無理やりな方法で実行しているため、いつどんなバグが起きるか未知数。

# まとめ
oracleDBではLIMIT句が使えず、他のコードに全く同じ挙動をするものが無い。<br>
そのため、データのソートを行い最新の「１行」のみを取得するコードで対応した。<br>
サブクエリやAS句、MAX句を使用すればもう少しスマートな挙動ができるのではないだろうか。
Salesforce_Schema_SObjectType編

<h1>SObjectType</h1>
<p>Schema.sObjectType オブジェクトは、getReferenceTo メソッドを使用して Field Describe Result から、または getSObjectType メソッドを使用して sObject Describe Result から返されます。</p>

<h1>名前空間</h1>
<p>Schema</p>

<h1>SObjectTypeを取得する日常コード</h1>

①
SObjectType token1 = Schema.opportunity.sObjectType;
System.debug('token1:'+token1);

②
Map<String, Schema.SObjectType> tokenMap = System.Schema.getGlobalDescribe();
SObjectType token2 = tokenMap.get('opportunity');
System.debug('token2:'+token2);

③
Co_SaisankeisankihonRireki__c obj = new opportunity();
SObjectType token3_1 = obj.getSObjectType();
System.debug('token3_1:'+token3_1);

④
List<Co_SaisankeisankihonRireki__c> objList = new List<opportunity>();
SObjectType token3_2 = objList.getSObjectType(); 
System.debug('token3_2:'+token3_2);

⑤
Id oppId = Id.valueOf('a1Z9D000000oArKUAU');【環境18桁SFDCID】
SObjectType token4 = oppId.getSObjectType();
System.debug('token4:'+token4);
Hello IoT!：自社製設備 と Raspberry Pi と SORACOM と AWS をつなげて IoT をやってみました

# 自社製設備でIoTをやってみる．
- 工場内では様々な設備が稼働していますが、今回は自社製設備を対象にIoTをやってみました．[※ 対象設備はここ](https://www.daydo.jp/product_mechatronics.html)
- 初めての 自社製設備、Raspberry Pi、SORACOM、AWS の組み合わせでしたが、必要なものはほぼデフォで揃っており当初想像していたより簡単にできました．

## 方針
- イニシャル・ランニング・学習コストを安価にする．
- AWS S3 にデータを集約する．
- 社内ネットワークを介さずに（社内ネットワークをいじらずに）公衆回線を用いた通信を行う．
- 使用するプログラム言語はPythonで行う（データ収集からETLまで）．



# システム構成
![無題の図形描画.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221477/b5d9add1-3112-e2a8-de45-17d90f3a803f.png)

## 自社製設備の構成
当社における自社製設備の一般的な構成は下記のとおり．

- [プログラマブル表示器（シュナイダーエレクトリックホールディングス製）](https://www.proface.com/ja/product/hmi/top)
- [PLC（三菱電機製）](https://www.mitsubishielectric.co.jp/fa/products/cnt/plc/index.html)
- 稼働データはプログラマブル表示器内にCSV形式で保存．

## Raspberry Pi の構成
およそ 25,000円/一式 でした．

- [Raspberry Pi 4B 8GB スターターキット](https://raspberry-pi.ksyic.com/)
- [SORACOM Onyx LTE USBドングル SC-QGLC4-C1](https://soracom.jp/store/7326/)
- [SORACOM 特定地域向け IoT SIM (plan-D ナノサイズ)](https://soracom.jp/services/air/cellular/price_specific_area_sim/)

## その他

- AWS S3
    - IAM（S3 へのアップロードポリシー）

# システム開発
- Raspberry Pi 回りは Python でまとめました（具体的な設定やソースについては参考にできる情報がたくさんあるので割愛）．

    - プログラマブル表示器 → Raspberry Pi のデータ取得 ： ftplib
    - Raspberry Pi → AWS S3 ： boto3
    - 稼働データの処理

- 開発環境
    - Windows10
        - Anaconda
        - VSCode

# 今後の取り組み

- 現状、データ取得のタイミングは プログラマブル表示器・Raspberry Pi それぞれ一定周期で行っており、設備停止時のデータ取得に工夫が必要．
    - PLC - Raspberry Pi の I/O で処理を検討．
iOSアプリ開発とAndroidアプリ開発で違っていて戸惑った点

## 初めに
普段iOSアプリを開発しているエンジニアです。
１ヶ月ほどAndroid開発を行う機会があったのでそこでつまづいたことをまとめておきます。
特にiOSと違っていて戸惑った点です。
## Androidアプリには戻るボタンがある。
iOSのアプリには自分で作らない限り戻るボタンはないのですが、Androidでは戻るボタンが存在します。
Webにある戻るボタンのような感じのもので特にフラグメントを使っているときは戻るボタンを押すと自分の思っていないページに飛んだりして少し、戸惑いました。
特に下記の記事と同じ問題につまづいてしまい、この記事にたどり着くまでかなり苦労しました。
https://qiita.com/tomo1139/items/62902093d1850085742d

## レイアウト作成やレイアウトとコードの紐付けが楽
これはAndroidの方が楽という意味なのですが、個人的にはレイアウトを全てSwiftもしくはstoryboardで書くiOSよりもxmlファイルにレイアウトを分けているAndroidの方が若干楽でした。（SwiftUIとかと比べると、、、という部分はありますが）
特に紐付けの部分ですね。iOSの場合storyboardを使っているとstoryboardからViewControllerにviewを引っ張って初めてViewControllerで使用することができるのですが、その点Androidはviewとkotlinのコードの紐付けを全てkotlinのコードで完結することができるので、要らないviewの紐付けの消し忘れなどがなくて良いなと思いました。

## 公式が推奨しているアーキテクチャがある。
これはiOSとは違うところで公式ドキュメントにAndroidアーキテクチャというものが載っていてそれを参考にアプリを作ることができました。
Androidは日本語のドキュメントが充実していて最初始めるときはとても始めやすい言語だなと思いました。
アーキテクチャについてはまた自分の見解をまとめて記事にしようと思います。

公式ドキュメント
https://developer.android.com/jetpack/guide?hl=ja

## actionBarというものが最初から設定してある。
これはアプリの上部にあるiOSでいうNavigationBarみたいなものがandroidではデフォルトで付いています。これはAndroid開発始めた手の時に邪魔だなーと思ってカスタマイズしたり消したりするのに少し時間がかかりました。

## まとめ
ざっと思いついたものでこれぐらいですが他にも違うところはありました。久しぶりにアウトプットしたので内容薄めですが次回からはガツガツ内容濃いめの記事を書いていこうと思います。
DioDocs Excel 試してみた

#最近、DioDocsのおためしがNugetから落としてくるだけでできるようになったよ

##ライセンス
本来なら、必要だけど、ウォーターマークシートがついていたり、一回起動辺りの呼び出し回数制限がある程度なので、ちょっと触ってみようという場面では、とても使いやすくなっています。

GrapeCity.DioDocs.Excel.ja

##やってみた

'''C#:program.cs
using GrapeCity.Documents.Excel;
namespace DioDocs1
{
    class Program
    {
        static void Main(string[] args)
        {
            Workbook workbook = new Workbook();
            workbook.Open(@"Book1.xlsx");

            IWorksheet worksheet = workbook.Worksheets[0];

            float f1 = 2.75F;
            float f2 = 2.76F;
            float f3 = 2.77F;
            float f4 = 2.78F;
            float f5 = 2.79F;

            worksheet.Cells[0, 0].Value = f1;
            worksheet.Cells[0, 1].Value = f2;
            worksheet.Cells[0, 2].Value = f3;
            worksheet.Cells[0, 3].Value = f4;
            worksheet.Cells[0, 4].Value = f5;

            worksheet.Cells[1, 0].Value = (decimal)f1;
            worksheet.Cells[1, 1].Value = (decimal)f2;
            worksheet.Cells[1, 2].Value = (decimal)f3;
            worksheet.Cells[1, 3].Value = (decimal)f4;
            worksheet.Cells[1, 4].Value = (decimal)f5;

            workbook.Save(@"Book2.xlsx");

        }
    }
}

'''

この程度のコードで、Excelに書き込めちゃいますが
なぜか、float を代入すると微妙な誤差が出るようですが、それが嫌ならdecimalにキャストすればいいです。
まあ、最初からdecimal
使えばいいのですが、他システムとの連携で、floatが来る場合は注意した方が良いでしょう

https://github.com/lowgain80/samples/tree/main/DioDocs/DioDocs1
webpackを利用してみた

# 目的

> 朝活レベル


# webpackとは
> CSSやJavaScript、画像などWebサイトを構成するあらゆるファイルを1つにまとめるモジュールバンドラーのこと

# 導入までの流れ

```
npm init
```

```
npm i -D webpack webpack-cli
```

# フォルダ構成について
├─ dist
│  ├─ index.html
│  └─ bundle.js
├─ package.json
├─ src
│  ├─ index.js   （エントリーポイント）
│  └─ modules    （JavaScriptモジュール群）
│    └─ getTime.js
└─ webpack.config.js  （webpackの設定ファイル）

```json:package.json
．．．
"scripts": {
  // ...
  "dev": "webpack --mode development --watch",
  "build": "webpack --mode production"
  // ...
}
．．．
```

```javascript:webpack.config.js
const path = require('path');

module.exports = {
  // モードの設定
  mode: 'development',

  // エントリーポイントの設定
  entry: `./src/index.js`,

  // ファイルの出力設定
  output: {
    // 出力するファイル名
    filename: "bundle.js",

    //  出力先のパス
    path: path.join(__dirname, 'dist')
  }
};

```

# ビルド
```
npm run build
```

> dist配下に圧縮された形で出力される

# 参考
[https://webpack.js.org/configuration/output/](https://webpack.js.org/configuration/output/)
鬼滅の刃のAIチャットボットを作成したのでインターネットに公開してみる

AI研究の為、会話ができるチャットボットを作ってみました。
また、試しにインターネットに公開してみますが負荷対策は一切していないのですぐにダウンするかもです。。。(;^ω^)
あと、ボットの頭はかなり悪いです。。。<(_ _)>

鬼滅の刃AIチャットボット
https://character-bot.herokuapp.com/s/kimetsu

#  ■ローカル環境でチャットボットを作成
##  ディレクトリの準備
適当なディレクトリを用意して、その配下に移動
botpressのデータを格納するディレクトリ作成します
mkdir botpress_data

##  ローカル環境用にdocker-compose.ymlを作成
```
version: "3.8"

services:
    ##  チャットボットアプリ(botpress)
    chatbot:
        image: botpress/server:v12_21_0
        ##  コンテナ名を明示的に指定する
        container_name: character-bot
        environment:
            TZ: Asia/Tokyo
        volumes:   ##  ホストディレクトリ：コンテナディレクトリ
            - ./botpress_data:/botpress/data
        ##  4000番ポートを3000番ポートにつなぐ
        ports:
            - '4000:3000'
```

##  コンテナ起動
docker-compose up -d

##  ローカルのBotpressにアクセス
http://localhost:4000/
ログイン画面が表示されます

##  チャットボットを作成
チャットボットのデータがbotpress_dataディレクトリに保存されていきます

#  ■インターネットにチャットボットを公開
##  Herokuアカウント作成
https://devcenter.heroku.com/ja

##  公開用のURLをセット
./botpress_data/global/botpress.config.json
```
"externalUrl": "https://character-bot.herokuapp.com/",
```

##  Heroku CLIインストール
https://devcenter.heroku.com/ja/articles/heroku-cli## download-and-install

##  Dockerfileを作成
```
FROM botpress/server:v12_21_0
COPY ./botpress_data /botpress/data
WORKDIR /botpress
CMD ["./bp"]
```

## アプリケーション名をセット
```
APP_NAME="character-bot"
```

## herokuにログイン
```
heroku login --interactive
```

## herokuにアプリの領域を作成
```
heroku create ${APP_NAME}
```

## herokuのコンテナレジストリにログイン
```
heroku container:login
```

## Dockerfileをビルドしてpushする
```
heroku container:push web --app ${APP_NAME}
```

## heroku上のアプリにアクセスする
```
heroku open --app ${APP_NAME}
```

## herokuのログをtailfする
```
heroku logs --tail
```

#  ■その他
## heroku環境を削除する
```
heroku apps:destroy --app ${APP_NAME} --confirm ${APP_NAME}
```
Jetpack Compose で使える便利な Live Templates

## `comp` - コンポーザブル関数を作成

![comp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/7ab1ab72-0383-b1a2-2531-0a774fd30946.gif)

## `paddp` - paddingモディファイアを追加

![paddp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/62d2a7de-7c9b-9b64-18b0-7f18cd830aae.gif)

## `WR` - 選択範囲をRowで囲む

![row.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/61e5e568-23fa-9659-f20d-ce9984d3da7d.gif)

## `WC` - 選択範囲をColumnで囲む

![column.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/50584386-0162-38ae-6bcd-c33be9e7b208.gif)

## `W` - 選択範囲を任意のウィジェット(デフォルトではBox)で囲む

![widget.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/c6fdc05b-38af-584c-a5fc-0d2ed3291856.gif)

## 自作の Live Template を追加するには

Compose 用の Live Template はそこまで充実していないので、上記で紹介したものに加えて自作のものを使うといいかもしれないです。

`Preferences` > `Editor` > `Live Templates` より

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56635/f8416763-c443-3bbe-a375-ac09d0b9f5db.png)
画像データセットのマネージメントツール Datumaro

## Datumaroとは

[https://github.com/openvinotoolkit/datumaro](https://github.com/openvinotoolkit/datumaro)
COCOやVOCなどの画像データセットを変換，結合，解析などができるツール．
OpenVINO toolkitの一部として開発されていて，アノテーションツール[CVAT]([https://cvat.org/](https://cvat.org/))でも使われている．

個人的に便利だと思ったところは，

- データセットのフォーマット変換として対応フォーマットが多く使いやすい．
- 結合や分割などの共通の操作が適用できる．
- 検証がかけられて安心できる．

調べてもあまり日本語の解説がヒットしないので，Datumaroの機能と使い方を簡単に紹介する．
まだ使っていない機能も多いので，使いながら適宜追加，修正の予定です．

## 機能
データセット関連の様々な処理を提供している．

- データセットのフォーマット変換
    - 多くのフォーマットに対応している．
    [https://github.com/openvinotoolkit/datumaro/blob/develop/docs/user_manual.md#supported-formats](https://github.com/openvinotoolkit/datumaro/blob/develop/docs/user_manual.md#supported-formats)
- データセットの分割や結合，アノテーションのフィルタリング
- アノテーションの検証，エラーチェック

などなど．
機能一覧は[https://github.com/openvinotoolkit/datumaro#features](https://github.com/openvinotoolkit/datumaro#features)

## インストール

CLIとPython APIがあるが，pipでインストール

```bash
pip install datumaro
```

## 使い方


### プロジェクト作成

プロジェクトを作成し，データセットをDatumaroのプロジェクトとして登録する．
以下は`sample_project`というプロジェクトをつくり，COCO形式のデータセットを登録します．

```bash
# プロジェクト作成
datum create -o sample_project

# プロジェクトにデータセットを登録
datum add path sample_dataset/annotations/instances_default.json -f coco_instances
datum add path sample_dataset/images -f image_dir
```

他の形式も同じプロジェクトに登録できるようです．
このプロジェクトに対して結合や分割，フィルタの操作を行うことができるようになっています．


### フォーマット変換(Export)

Datumaroプロジェクトは対応しているフォーマットで書き出すことができます．
以下は，`sample_project`を`example_dataset_tfrecord`という名前でTFRecord形式で書き出す例です．

```bash
# 書き出し(変換)
datum export \
	-p example_dataset \
	-o example_dataset_tfrecord \
	-f tf_detection_api 
```

### 解析(Statics)

```
datum stats -p sample_project
```

画像の平均値，標準偏差が出力されます．ImageNetのものをそのまま使っていたりしますが，この出力を使うの方のが適切かもしれません．またラベルの偏り/分布を確認することもできます．

### 検証(Validate)

```bash
datum validate -p sample_project
```

定義されていないアノテーションがないかやアノテーションがない画像がないかを確認してくれるようです．一度このような確認をかけておくと安心できます．

validateで検証している内容は以下に記載があります．
https://github.com/openvinotoolkit/datumaro/blob/develop/docs/user_manual.md#validate-project-annotations
Vue3+bootstrap-vueを試してみた

# はじめに
既存のVue2プロジェクトをVue3に移行したいと考えているのですが、まだ移行ツールなどは無さそうです。

Vue.jsのサイトでは、「準備中なので重要なアプリはMigration Buildを待ってね」みたいなことが書かれています。
[https://v3.vuejs.org/guide/migration/introduction.html#breaking-changes](https://v3.vuejs.org/guide/migration/introduction.html#breaking-changes)

> We are still working on a dedicated Migration Build of Vue 3 with Vue 2 compatible behavior and runtime warnings of incompatible usage. If you are planning to migrate a non-trivial Vue 2 app, we strongly recommend waiting for the Migration Build for a smoother experience.

本当にバージョンをあげるのは、Migration Buildを待ってみるとして、
本記事では、既存のアプリケーションがbootstrap-vueを使用しているため、Vue3でbootstrap-vueをセットアップしてみて、動作するのかちょっと確認してみたいと思います。

# Vue3 startup
まず、普通にVue3のプロジェクトをセットアップしてみます。

## vue-cliの更新
削除して最新を取得

```bash
$ npm uninstall -g vue-cli
$ npm -g add @vue/cli
```
バージョンアップを確認

```bash
$ vue --version
@vue/cli 4.5.13
```

Quickstartを真似てプロジェクト作成
```bash
$ vue create hello-vue3
```

テンプレートそのままのこの時点では普通に起動しました。
![vue3_startup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563969/ca9cc95b-f731-7363-230e-f5aad21d08e9.png)


## bootstrap-vueの組み込み
とりあえず足してみる。
```
$ npm install bootstrap-vue bootstrap --save
```

main.jsを修正。

自動生成されたもの

```Javascript
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
```

bootstrapの記述を追加したもの

```Javascript
import { createApp } from 'vue'
import App from './App.vue'
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import BootstrapVue from 'bootstrap-vue'

createApp(App).use(BootstrapVue).mount('#app')
```

起動すると、popperjs/coreが無いというので、追加。
```
$ npm install --save @popperjs/core
```

再度起動すると、ブラウザは真っ白で、下記エラーが発生。
検索してみると、同様のエラーの情報がちらほら。

```Javascript
Uncaught TypeError: Cannot read property 'prototype' of undefined
    at eval (webpack-internal:///./node_modules/bootstrap-vue/esm/utils/config.js:20)
    at Module../node_modules/bootstrap-vue/esm/utils/config.js (chunk-vendors.js:3311)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (webpack-internal:///./node_modules/bootstrap-vue/esm/utils/props.js:13)
    at Module../node_modules/bootstrap-vue/esm/utils/props.js (chunk-vendors.js:3587)
    at __webpack_require__ (app.js:849)
    at fn (app.js:151)
    at eval (webpack-internal:///./node_modules/bootstrap-vue/esm/utils/model.js:6)
    at Module../node_modules/bootstrap-vue/esm/utils/model.js (chunk-vendors.js:3503)
```

コードをちょっとだけのぞいてみましたが、ここで落ちている模様

```Javascript
import { Vue } from '../vue';
import { DEFAULT_BREAKPOINT, PROP_NAME } from '../constants/config';
import { cloneDeep } from './clone-deep';
import { memoize } from './memoize'; // --- Constants ---

var VueProto = Vue.prototype; // --- Getter methods ---
```

`Vue.prototype`はVue3では、`app.config.globalProperties`という新しいAPIで取得する必要があるみたいである。

bootstrap-vueのv2.21.0のChangeLogに下記の記載があったが、migrationができるようになったわけではなく、準備を進めているだけだった模様。

> code enhancements for easier Vue 3 migration

遅ればせながら、githubのissueなどの情報を見てみたところ、v3, v4で対応予定とのこと。
v2系統のままでは動かなそうです。残念。
C++の参照受け渡し

C++の参照受け渡しのソースコード例です。

```C++
/*
 * sample.cpp
 *
 *  Created on: 2021/05/31
 *      Author: 乃木坂好きのITエンジニア
 */
#include <bits/stdc++.h>
using namespace std;
 
// 参照渡しを用いて、呼び出し側の変数の値を変更する
void saiten(vector<vector<int>> &A, int &correct_count, int &wrong_count) {
  // 呼び出し側のAの各マスを正しい値に修正する
  // Aのうち、正しい値の書かれたマスの個数を correct_count に入れる
  // Aのうち、誤った値の書かれたマスの個数を wrong_count に入れる
 
  for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
      if (A.at(i).at(j) != (i + 1) * (j + 1)) {
        // 誤った値が書き込まれている場合
        A.at(i).at(j) = (i + 1) * (j + 1);  // 正しい値に修正
        wrong_count++;  // 誤っているマスの個数を +1
      }
      else {
        // 正しい値が書き込まれている場合
        correct_count++;  // 正しいマスの個数を +1
      }
    }
  }
}
 
 
// -------------------
// ここから先は変更しない
// -------------------
int main() {
  // A君の回答を受け取る
  vector<vector<int>> A(9, vector<int>(9));
  for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
      cin >> A.at(i).at(j);
    }
  }
 
  int correct_count = 0; // ここに正しい値のマスの個数を入れる
  int wrong_count = 0;   // ここに誤った値のマスの個数を入れる
 
  // A, correct_count, wrong_countを参照渡し
  saiten(A, correct_count, wrong_count);
 
  // 正しく修正した表を出力
  for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
      cout << A.at(i).at(j);
      if (j < 8){
        cout << " ";
      } else {
        cout << endl;
      }  
    }
  }
  // 正しいマスの個数を出力
  cout << correct_count << endl;
  // 誤っているマスの個数を出力
  cout << wrong_count << endl;
}
```

参照受け渡しでメモリ使用量を減らすように実装しております。
インフラ系の調査方法についてまとめてみる。

# はじめに
先日、既存のインフラ基盤調査のお仕事があり、入社3年目くらいの子と一緒に作業したのですが、調査といっても未知のシステムに対して何をどう調べていったらよいか分からんと途方に暮れられてしまいました。

言われてみると私も今回のような調査を行う際、あまりプロセスをきっちり決めてやっていなかったと思い、せっかくなので、私があまり意識せずやっていることをまとめてみようと思います。

私の個人的なやり方なので、参考程度でお願いします。

# 対象
サーバ・ネットワーク系インフラエンジニアを対象にします。

アプリ系は門外漢なので対象外です。

# 調査方法の検討
何はともあれ、調査をするということは何か目的があって調査をするので、調査の目的を考え、目的に対して何を調べれば達成できるかを考えます。

ちなみに前述のお仕事では、お客様より今後保守をお願いしたいということで仕事を頂いたので、保守するのに最低限必要となる情報をまとめ、調査を行いました。

- 保守定例で報告する内容の調査
- 監視方法の調査
- システム構成の調査
- 障害時のアラート方法の調査
- 提供サービスの調査

# 調査（全体）
設計書があるのであれば、設計書に従って設計内容や設定箇所を確認していきます。

管理用パスワードなどは設計書があった場合でも載っていないことが多いと思うので、早めに確認するのが良いです。

また、設計書があった場合でも実機の設定は**必ず**確認するようにしましょう。

私も経験がありますが、設計書と実機の設定が合っていないことは以下の様に様々な理由により発生するため、設計書だけで調べていくとハマります。

- 単純な誤記
- 設計書への反映忘れ
- 古い設計書を修正して反映してしまった
- お客様から渡された設計書が古い
- 費用の関係で見積時に設計書修正費用を削られた
- 開発部門と運用保守部門で持っている設計書が異なる

私が経験して覚えている限りでもこれだけあるので、知らないシステムを調査する際には設定が記載されたパラメータシートがあった場合でも設計概要・設計方針を頭に入れる程度にしましょう。

# 調査（AWSサービス）
どのようなサービスが使われているかもわからない場合、AWSコンソールでポチポチ確認していくのも大変なので、どのようなサービスが使われているかの当たりをつけるために、`Tag Editor`で`All regions`、`All supported resource types`を指定してリソースを検索するだけでも、使われているタグやリソースが確認できるので、"当たり"が付けられます。

ユーザアクセス権等ある場合は、`AWS Perspective`や`CloudMapper`で構成を確認してみるのも良いと思います。

# 調査（Unix系サーバ）
サーバ内の構成を調べる際には、タイムスタンプから変更されているファイルに当たりをつけて、設定が変更されているコンフィグなどを追っていくことをよくやっています。

最初に構築した時期が分かるなら、構築時期～現在までに更新されたファイルをタイムスタンプから追っていきます。

`/proc`や`/sys`などはそうそう人が触る場所でもないので、`find`コマンドで以下の様にすれば、予め不要だと思われるファイル・ディレクトリは外した上で結果が出力できるので、あとは出力されたファイルから詳細確認したいコンフィグファイル等を取得して確認しましょう。

```shell:2年前から1年前までの間に更新されているファイルの取得
find / -mtime -730 -mtime +365 -ls 2>/dev/null | egrep -v " /proc| /sys| /dev| /run| /var/run"
```

コンフィグファイルにコメント行等含まれていて、実際に設定されている内容が分かりづらい場合は以下の様にコメント行等除外して設定を確認することをおすすめします。

以下は「先頭が"#"で始まる行」または「空行」または「先頭から空白が続いた後に"#"で始まる行」を除外した内容を表示できます。

```shell:空行、コメント行を除外したコンフィグファイル確認
egrep -v "^#|^$|^ .*#" [ファイル名]
```

# 調査（ネットワーク）
ネットワーク系機器は設定方法が様々なので難しいですが、Ciscoで言えば`show tech-support`、F5なら`qkview`などまとめて情報を取得できるコマンドがあることが多いので、まずはまとめて情報を取得してみるのが良いかと思います。

取得した情報を基に、以下の様なことをベースとして簡単に絵にまとめると、システム内のネットワーク構成や通信先が見えてくるかと思います。

- IPアドレス、セグメント構成
- ルーティング
- ACL

通信要件の一覧があれば各サービスのシーケンス等を追っていき、無いようなら設定されているルーティングやACLからどのような通信があるのか追っていくのが良いと思います。

# 終わりに
今回は私の一例として調査方法を紹介しましたが、調査の内容は様々なので、何かあった場合でも困らないように調査のネタを増やしていきましょう。
NEC IX2015コマンド

### プロンプト

* telnet したら`#`表示。

### 設定モードに入る

```go
configure
```

### 保存された設定を確認

```go
configure

show config
```

### アクセスリスト

```go
configure

show ip access-list
```


### 設定

* src と destを逆にしがちなので注意！

```go
configure

// ping許可 : LAN(192.168.10.0/24)からWAN(any)へ
ip access-list my-list permit icmp src any dest 192.168.10.0/24

// UDP許可 : LAN(192.168.10.0/24)からWAN(any)へ
ip access-list sec-list permit udp src any dest 192.168.10.0/24
```

### 設定を削除

```go
configure

// ping許可 : LAN(192.168.10.0/24)からWAN(any)へ の設定削除
no ip access-list my-list permit icmp src any dest 192.168.10.0/24

// UDP許可 : LAN(192.168.10.0/24)からWAN(any)へ の設定削除
no ip access-list sec-list permit udp src any dest 192.168.10.0/24
```

### 再起動後も有効にする

`write memory`しないと`show config`で見れないので注意。

```go
write memory
```
EC2インスタンスを見失ったときにはリージョンが間違っている可能性が高い

EC2コンソールで作成したはずのインスタンスがない…！という事象に遭遇。
いやそんなことはないやろ、ターミナルからsshでログインもできているし。

# 結論…リージョンが違った

EC2コンソール上で指定しているリージョンが違ったようです。
リージョンを確認するにはsshでAMIにログイン後

```
[ec2-user@ ~]$ curl -s http://169.254.169.254/latest/metacement/availability-zone | sed -e 's/.$//g'
```

で確認できます。これはAZ(アベイラビリティゾーン)の値からリージョンを取得する方法のようです。
コマンドを実行すると `us-east-1` と出ました。おいおい東京じゃないじゃないか…
東京で設定しているつもりで東京にリージョンを設定していたのでそりゃ出てこんわな。

参考
https://qiita.com/tt2004d/items/46ea80cd7cb20212e50e

# リージョンの移動方法

上記コマンドでリージョンが確認後、東京に移動したくなりました。
どうやらリージョンの移動ではインスタンスからイメージをコピーして作り直す必要がありそうです。

以下記事を参考にしました。
https://qiita.com/ryosuk/items/2b8da63a433d4eea65e0

## いくつか補足
### AMIのコピー方法 
AMIのステータスがpendingからavailableになったらAMIを選択→アクション→AMIのコピーと進みましょう。
![AMI___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/8b12071b-ac9f-5cec-f33e-ecbacbeccf9d.png)

モーダルが開くので画像の通りコピー先のリージョンを選択してコピーします。
![AMI___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/8c58feb0-d11f-293d-b2db-db51896cac9f.png)

AMIのコピーを実行し始めると東京リージョンにてpendingのAMIが確認できます。
![AMI___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/e8ffc3cf-1c4b-8df4-04a9-17392ea0a749.png)

### 課金に関する注意点
AMIのコピー時は以下に注意
- 不要なEC2インスタンスを停止したか？
- 不要なElasticIPを開放したか？
GCPのSecret Managerで値を取得しようとしてハマった

## やりたかった事

Secret Manager に登録してある値を取得したい

## 公式ドキュメントを探す

公式に書いてある方法は、シークレットを追加してから取得する方法のみ
https://cloud.google.com/secret-manager/docs/reference/libraries

## 値の取得だけをしたいんじゃ

「GCP Secret Manager Python」等で検索をかけると、取得する方法を書いた記事が出てくる。
ありがたくコードを拝借する。

https://www.apps-gcp.com/sm-with-gcf/

```py
from google.cloud import secretmanager


def get_secret_text(project_id, secret_name, secret_ver):
    client = secretmanager.SecretManagerServiceClient()
    name = client.secret_version_path(project_id, secret_name, secret_ver)
    response = client.access_secret_version(name)
    return response.payload.data.decode("UTF-8")


if __name__ == "__main__":
    print(get_secret_text("project_id", "secret_id", "latest"))
```

## 動かない

```
Traceback (most recent call last):
  File "/Users/chun/programs/secret.py", line 13, in <module>
    print(get_secret_text("project_id", "secret_id", "latest"))
  File "/Users/chun/programs/secret.py", line 7, in get_secret_text
    response = client.access_secret_version(name)
  File "/Users/chun/programs/.venv/lib/python3.9/site-packages/google/cloud/secretmanager_v1/services/secret_manager_service/client.py", line 1136, in access_secret_version
    request = service.AccessSecretVersionRequest(request)
  File "/Users/chun/programs/.venv/lib/python3.9/site-packages/proto/message.py", line 486, in __init__
    raise TypeError(
TypeError: Invalid constructor input for AccessSecretVersionRequest: 'projects/project_id/secrets/secret_id/versions/latest'
```

## google-cloud-secret-manager のドキュメントを見る

access_secret_version の引数がおかしいっぽいので、モジュールのドキュメントを探す

https://googleapis.dev/python/secretmanager/latest/secretmanager_v1/secret_manager_service.html?highlight=access_secret_version#google.cloud.secretmanager_v1.services.secret_manager_service.SecretManagerServiceClient.access_secret_version

現在の最新(2.4.0)では、第一引数が `AccessSecretVersionRequest` というオブジェクトを引き受けるようになっている。

コレは何かよくわからない。

name を渡したいので、

```py
client.access_secret_version(name=name)
```

とすると、うまく動いた。

バージョン 2.0.0 から、access_secret_version の引数が変更されたようだ。

## 最終的な動くコード

```py
from google.cloud import secretmanager


def get_secret_text(project_id, secret_name, secret_ver):
    client = secretmanager.SecretManagerServiceClient()
    name = client.secret_version_path(project_id, secret_name, secret_ver)
    response = client.access_secret_version(name=name)
    return response.payload.data.decode("UTF-8")


if __name__ == "__main__":
    print(get_secret_text("project_id", "secret_id", "latest"))
```

## 最後に

Google の公式ドキュメントでは、作成したのちに作成したものを取得する内容しか書いてなかった。
非常に不便だと感じた。
google-cloud-secret-manager のドキュメントは非常に読みづらいし、Basic Usage とか書かれていなかったし、つらい。
NotionAPIの利用手順

# NotionAPIの利用手順

## はじめに


## 手順
1. 準備
2. 実践

## 1. 準備
1. [こちら](https://www.notion.so/my-integrations)にアクセス
2. ユーザを作成<br>
New integrationを選択
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696295/3c34a242-31ef-7426-0197-d5a063fb0966.png)
名前を入力してSubmit（※Tokenをメモしておくこと）
![画像2_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696295/9dce67d9-2678-5dc4-a35d-ab757c1a3f3b.jpeg)


Notionでテーブルを作成
![画像3_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696295/a55d3455-61f7-a11a-1ec2-2b9bbd6f9b20.png)

Shareより先程作成したユーザを追加
![画像4_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696295/4a040caf-e456-a1a2-7ff2-b9732ef6999b.png)


## 2. 実践
下記cURLを叩く
```curl -X POST https://api.notion.com/v1/pages \
　-H "Authorization: Bearer {MY_NOTION_TOKEN}" \
　-H "Content-Type: application/json" \
　-H "Notion-Version: 2021-05-13" \
　--data '{
　　"parent": { "database_id": "{DATABASE_ID}" },
　　"properties": {
　　　"Name": {
　　　"title": [
　　　　　　{
　　　　　　　"text": {
　　　　　　　"content": "Yurts in Big Sur, California"
　　　　　　　}
　　　　　　}
　　　　　]
　　　　}
　　　}
　　}'
```
* {MY_NOTION_TOKEN}には先程メモしたTokenを記入
* {DATABASE_ID}には、作成したDBのURL```.../xxx/?v=...```のうち、xxxの部分を記入

DBにレコードが追加されていることを確認
![画像5_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696295/f9ec468d-4bba-5c06-37fe-15140e5907df.png)


## 最後に
今回は公式docの手順通りに試しただけですが、今後他APIやアプリ等と連携させていきたいと思います！

## 参考サイト
[公式doc](https://developers.notion.com/docs/getting-started)<br>
[Qiita-NotionAPIを使ってみた](https://qiita.com/tomoya_sakusaku/items/5a7f59ddfebe25e1ca8b?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items)<br>
AWS EC2インスタンスにIAMロールを割り当てる

EC2インスタンスへのIAMロールの割当手順をまとめました。
以下サイトを参考にしてます。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html

1. EC2コンソールへアクセス
1. ロールを割り当てたいインスタンスにチェック
1. アクション→セキュリティ→ IAMロールを変更と進む

画像の赤枠のところをクリックしてください。
![インスタンス___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/593c2c22-f6aa-bdc7-b7d4-f9fbe4ac841c.png)

4. 割り当てたいロールをプルダウンから選択して「保存」をクリック
![IAM_ロールを変更___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/d358bbc3-06dd-4cf3-0e30-7189f08cb2d2.png)

まだロールを作っていない場合「新しいIAMロールを作成」からロールを作成しましょう。

ロールを割り当てるとコンソールのインスタンス概要からIAMロールが確認できます。
![インスタンスの詳細___EC2_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/ba9f11f3-ead9-5248-c9ba-72631680cbca.png)

ロールを作成後ターミナルで

```
.ssh % ssh -i pemキーの名前 ec2-user@パブリックIP
```
で接続し

```
[ec2-user@ ~]$ aws configure list
```

とすると

```
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key           ****************         iam-role    
secret_key           ****************         iam-role    
    region                <not set>             None    None
```

のように表示されます。iam-roleってやつが今回作成したIAMロールです。

まだ確認すべきことあるきがする？引き続き調査
elm327の研究 その6

# 概要

elm327を調べてみた。
c#でreader書いてみた。

# 写真

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3d084e3b-5ec0-2f29-1cd3-014c20366201.jpeg)


# サンプルコード

```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}
		private void Form1_Load(object sender, EventArgs e)
		{
			aGauge1.Value = 10;
			aGauge2.Value = 100;
		}
		private delegate void addDelegate(Byte[] buff);
		private void domsg(Byte[] buff)
		{
			int i = to_h(buff[6]) * 16 + to_h(buff[7]);
			aGauge1.Value = i;
            Console.WriteLine(i);
			System.Threading.Thread.Sleep(1300);
			byte[] dat = { 
                             0x30, 0x31, 0x30, 0x44
                         };
			serialPort1.Write(dat, 0, dat.Length);
			Console.WriteLine("send");
		}
		private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
		{
			int j = serialPort1.BytesToRead;
			if (j > 6)
			{
				Byte[] buff = new Byte[j];
				serialPort1.Read(buff, 0, j);
				BeginInvoke(new addDelegate(domsg), new object[] { 
                    buff 
                });
			}
		}
		private void button1_Click(object sender, EventArgs e)
		{
			serialPort1.Close();
			serialPort1.Open();
            byte[] dat = { 
                             0x30, 0x31, 0x30, 0x44
                         };
			serialPort1.Write(dat, 0, dat.Length);
			Console.WriteLine("send");
		}
        public static byte to_h(byte a)
        {
            if (a >= 0x30 && a <= 0x39) 
                return (byte)(a - 0x30);
            if (a >= 0x41 && a <= 0x46) 
                return (byte)(a + 10 - 0x41);
            if (a >= 0x61 && a <= 0x66) 
                return (byte)(a + 10 - 0x61);
            return 255;
        }
	}
}




```

以上。
AtCoder Beginner Contest 203 (Sponsored by Panasonic) 参戦記

# AtCoder Beginner Contest 203 (Sponsored by Panasonic) 参戦記

## [ABC203A - Chinchirorin](https://atcoder.jp/contests/abc203/tasks/abc203_a)

3分で突破. 書くだけ.

```python
a, b, c = map(int, input().split())

x = [a, b, c]
x.sort()

if x[0] == x[1]:
    print(x[2])
elif x[1] == x[2]:
    print(x[0])
else:
    print(0)
```

## [ABC203B - AtCoder Condominium](https://atcoder.jp/contests/abc203/tasks/abc203_b)

2分半で突破. ループを回さなくても一発で求めれるような気もしたけど、書くだけだからいいやとなった.

```python
N, K = map(int, open(0).read().split())

result = 0
for i in range(N):
    for j in range(K):
        result += (i + 1) * 100 + (j + 1)
print(result)
```

## [ABC203C - Friends and Travel costs](https://atcoder.jp/contests/abc203/tasks/abc203_c)

6分半で突破. *N*≤2×10<sup>5</sup> なので *O*(<i>N</i>log<i>N</i>) くらいまで大丈夫だなと思ったら、ソートして前から順に処理していけばいいよねというのが分かる.

```python
from sys import stdin

readline = stdin.readline

N, K = map(int, readline().split())
AB = [list(map(int, readline().split())) for _ in range(N)]

AB.sort()
p = 0
result = 0
while K != 0:
    result += K
    K = 0
    while p < N and AB[p][0] <= result:
        K += AB[p][1]
        p += 1
print(result)
```

## [ABC203D - Pond](https://atcoder.jp/contests/abc203/tasks/abc203_d)

突破できず. にぶたんかなと思って実装したら TLE. 方針が間違っていたのか、実装がいまいちなのか.
AWS rootアカウントに対するMFA(多要素認証)の割当

AWSをいじっていてrootアカウントに対するMFAの設定をどこからやるのかちょっとわかんなくなってしまっていたので調べました。
これに限らずAWSは何かと忘れやすいので適宜アウトプットして定着しておきたい。

# ①IAMコンソールにアクセス
IAMって検索してリンクをクリックする。「rootユーザーなのにIAMなのかよ！」とは思ったけど気にしない。
その時rootアカウントにMFAが設定されていないと以下の画像のような画面になっている。
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/00cd752a-67e2-bb41-4860-95cf4c824dbd.png)
」

赤枠で囲った「セキュリティアラート」ってとこに「このアカウントのrootユーザーには多要素認証(MFA)が有効になっていません」と出ているので「MFAを有効にして」のとこのリンクをクリック

# ②以下の画像から「MFAの有効化」をクリック
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/0d3cde1e-87fa-9caa-16f1-5c33af24f3fe.png)

# ③「仮想MFAデバイス」を選択
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/4508bca8-d174-1a29-3911-70a4dc120933.png)

他のやり方もあるっぽいけどこれが一番簡単だと思います、
仮想MFAデバイスとは Authy(https://apps.apple.com/jp/app/twilio-authy/id494168017)のようなスマホで認証を行うサービスのことです。なお親切に次の画面でどのアプリが対応しているか教えてくれる。

# ④表示されたQRコードをAuthyで読み取る
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/91a1858d-aeb0-a27f-2a4d-ccdd2f402b9b.png)

# ⑤読み取るとMFコード(6桁)の入力を要求されるので2回入力
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/7bb9aae6-e6f2-65e9-7e36-90fcdcaf49d6.png)

# ⑥以下の画面が出たら完了
![IAM_Management_Console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/2a414c6f-81d0-0276-2547-ab9f11470413.png)
AWSクラウドプラクティショナー学習3日目

# AWSのサービス

180以上のサービスの組み合わせでインフラを構築できる！

# グローバルインフラストラクチャ

サービスごとに世界中のどこにいても使える→要件に応じて選択可能

## 地域の単位

- リージョン…世界で24個。日本だとTokyoが有る
- ローカルリージョン…リージョンの補佐的な位置づけ。
  - アベイラビリティゾーン…リージョン1つにつき2つ以上
    - データセンター…AZ1つにつき複数

### リージョンの選び方

- 保有するデータ、システムがリージョンの法律・システム所有企業の要件を満たしているか
- ユーザーやデータセンターに近いか
- 必要なサービスが揃っているか(使えるサービスはリージョンごとに異なる)
- コスト効率がいいか(リージョンによって価格は異なる)

### なぜAZは複数あるのか？

特定のAZが使えなくなったとしても別のAZでカバーするため
→障害を意識した設計(Design for Failure)

### データセンターは物理的に守られている

- 見た目ではデータセンターとわからない
- 警備が頑丈
- 場所は非公開

## エッジロケーション

低レイテンシーな通信を行うための地域。世界に200箇所以上ある。
Amazon Cloud FrontやRoute53などに使われる

# EC2(Elastic Computing Cloud)

## 料金オプション

- オンデマンド…1秒あたりの価格が決まっているインスタンス。利用開始直後に利用しその後トラフィック量など需要に応じてインスタンスタイプを変更する、といった使い方を想定している

- リザーブド…1年(3年)以上の利用を約束する代わりに割引がなされる

  - コンバーティブル…途中で属性の変更が可能
  - スタンダード…不可

- スポット＿未使用のキャパが一定以上のときのみ使われる。処理途中で終了しても問題ないように設計することが求められる。
RPGツクールMZで敵の行動パターンのHP条件が動いていない

HPが100%～50%の間のときだけスキルを発動したかったが、なぜかどうしても動かない。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1569020/facb9266-fbb3-6650-9c32-eec62e29064f.png)

なぜ？なぜなの？

理由は**条件が「左辺 <= 右辺」 になっていない**から。

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1569020/836c6ff8-c6a5-298d-4694-5d662d0e4265.png)

このように左辺と右辺を逆にして「左辺 <= 右辺」になるようにしたら動きました。

100%～50%という指定も意味としては間違っていないので、原因判明までに時間がかかってしまいました。

入力チェック等で弾いてほしいところです。。。
【Git】うっかり違うブランチで作業した内容を別のブランチに移したい

うっかり違うブランチで作業してしまったときの対処法です。


# Stashで一時退避させる
```
$ git stash save
Saved working directory and index state WIP on xxx-branch: 47635c6 xxx-branch
```

### ＊退避できているかを以下で確認できる

```
$ git stash list
stash@{0}: WIP on xxx-branch: 47635c6 xxx-branch
```

# 移したいブランチにcheckout

今回は新しいブランチを作ってそこに移します。ブランチ名`new-branch`は任意です。

```
git checkout -b new-branch
```

# stashした内容を反映する

該当のstash（今回は`stash@{0}`）を以下のコマンドで反映して完了です。
※popを使うとstashのlistからは消えます。すっきり保ちたいのでこちらを選択しました。

```
$ git stash pop stash@{0}
```

# 参考
Stash関連のコマンドをわかりやすくまとめてくださっています。
［参考］[色々な git stash](https://qiita.com/akasakas/items/768c0b563b96f8a9be9d)
[Netlify] Reactで直接URLを叩くと404になるときの対応

# 概要
以下の記事の解決方法に、`サーバー側の設定でリライト設定をする`とあり、
Netlifyを使っていて少し手間取ったため、Netlifyで対応する方法を書いておきます。

https://qiita.com/yakipudding/items/78e68ef31e55f559c0dc

## 状況(上の記事から引用)
`https://hogeapp.com/Fuga`が表示された後リロードする　→　404ページが表示される
ブラウザで`https://hogeapp.com/Fuga`を直接叩く　→　404ページが表示される


# やること
- `_redirects`ファイルをメインのディレクトリに作成
- 以下の内容を記述

```text:_redirects
/*    /index.html   200
```

これでNetlifyの方でデプロイしたら完了です。

# 参考
Special Thanks;
https://qiita.com/yakipudding/items/78e68ef31e55f559c0dc

https://docs.netlify.com/routing/redirects/rewrites-proxies/
https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file
Arduino UNOにTFT LCDを接続しよう

## Arduino UNOに汎用のILI9341 TFT液晶モジュールを接続した時の資料です。

Arduino の出力装置に液晶モジュールを追加したときの資料です。

### ハードの用意

> ●Arduino UNO
> ●LCD
>> aitendo の★2.8インチ★TFT液晶モジュール★240x320★ [M028C9341SD]
>> https://www.aitendo.com/product/16038
>>   コントローラチップ：ILI9341
>>   動作電源：3.3V
 
> ●3.3V<->5V相互変換モジュール
>>   LCDの動作電源が3.3Vなので電圧変換必須です。
>>   aliexpressなどで数百円程度で売ってます。


> ●とりあえず配線は以下のようにしました。

>> 8pin -> LCDのMISO
>> 9pin -> LCDのSCK
>> 10pin -> LCDのMOSI
>> 11pin -> LCDのDC
>> 12pin -> LCDのRESET
>> 13pin -> LCDのCS

>> 3.3Vの電源とGNDとバックライトのLEDもつなぎます。

>> 標準的なSPI通信です。SPIはシリアル通信なのでジャンパ線は少な目です。

> 全信号ピンは直結はせずに 5V <-> 3.3V 電圧変換をかませます。
> VCCは3.3VでバックライトのLEDも3.3Vです。

### ソフトの用意

> ●次の3つのライブラリをArduino IDEで使います。
> Arduino IDEのライブラリマネージャから検索しinstallします。
>>  Adafruit GFX Library
>>  Adafruit ILI9341
>>  Adafruit BusIO

### 動作確認

> Arduiono IDEから
> ファイル -> スケッチ例 -> Adafruit ILI9341 -> graphicstest
> でテストします。

> ●defineの書き換え
> 以下のdefineを追加します。

```c++

//#define TFT_DC 9
//#define TFT_CS 10
#define TFT_CS 13
#define TFT_DC 11
#define TFT_MOSI 10
#define TFT_CLK 9
#define TFT_RST 12
#define TFT_MISO 8

```

> define のピン番号はLCDに書かれてあるピンとArduinoのピン番号に合わせる必要があります。

> スケッチのコンストラクタを書き換えます。

```c++

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
// Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

```

> コンパイルしマイコンボードに書き込めば完成です。

![IMG_1609.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399473/5ab34efb-2a4a-59c1-0bdb-356153553128.jpeg)


> スケッチのgraphicstestのソースを適当に好きなように書き換えれば自分の思うがままの表示が出せると思います。
> Adafruiライブラリは充実していてdraw系の関数は一通りそろっていると思います。

### GFX library for arduinoでの動作確認

> GFX library for arduinoを使って動作確認できます。
> ライブラリ管理からinstallしdefineなどを修正すれば動作しました。

> examplesのHello worldなどでピン番号をあわせれば動きます。

```c++

#define TFT_CS 13
#define TFT_DC 11
#define TFT_MOSI 10
#define TFT_SCK 9
#define TFT_RST 12
#define TFT_MISO 8

Arduino_DataBus *bus = new Arduino_SWSPI(TFT_DC /* DC */, TFT_CS /* CS */, TFT_SCK /* SCK */, TFT_MOSI /* MOSI */, -1 /* MISO */);

Arduino_GFX *gfx = new Arduino_ILI9341(bus, TFT_RST  /* RST */, 0 /* rotation */, false /* IPS */);

```

> LCDのコントローラの型番でコンストラクタが変わります。
> ILI9488の場合は
> Arduino_ILI9488_18bit
> で動く場合があります。

### Adafruit

https://www.adafruit.com/

> Adafruitという単語がよくでてきます。
> これはAdafruitというユニークな製品を生み出してる最先端メーカーです。
> 社長が女性でガチガチのエンジニアっぽいです。
> なるほどと思わせるようなものが色々あります。
> 7インチTFT + SPI + アクセラレータなんかもかなり需要があるのではと思います。
【Atom】HTMLを編集中に改行後の終了タグがイデンテントされたままになる問題

筆者はHTML初学者なのでトンチンカンなことを書いていましたらすみません。<br>


# 開始タグと終了タグのインデントが揃わない

ATOMエディタには、HTMLファイルを編集中に<開始タグ>→改行→<終了タグ>とタイプすると<開始タグ>と<終了タグ>のインデント(字下げ)を自動的に揃えてくれるという便利な機能があります。
ところが、新しいファイルを作成してHTMLコードを**ゼロから書いたとき**同様にタイプすると<終了タグ>が字下げされた状態になって<開始タグ>と<終了タグ>の行頭が揃わないという問題に直面しました。(ATOMをHTMLモードにしていても)


![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1568047/f93a972f-c1b6-a1ac-adfd-193778b83a67.jpeg)

改行後にインデントされるのはATOMの設定にあるオートインデントが機能しているためと思われます。
しかし、以前作成したHTMLファイルを編集してみるとオートインデントが有効でありながらも終了タグを記述すれば自動でインデントが削除されるのに、新しく書き始めたファイルではインデントが残ったままになってしまい、どうしても違和感があるのでその解決法を探してみました。
### 解決法(?)

いろいろ試して、とりあえず解決法（?）を見つけました。

それは、初めの文書型宣言「<!DOCTYPE html>」を記述した後にHTMLファイルとして保存して一度タブを閉じ、すぐにファイルを開き直すというごく単純なものです。

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1568047/86a90602-d1ce-59a1-f604-ac8434882e99.jpeg)

これで改行したあとの終了タグと開始タグの行頭をATOMが自動的に揃えてくれるようになります。

つまり、きちんと普通にHTMLを書いていて一度ファイルを保存し、再びATOMで開けばこの問題は勝手に解決するという実は問題でも何でもないような些細なことでした。
たぶん以前もこうなっていたけど、自然解決していたので筆者自身忘れていたのだと思います…
<br>

ちゃんと文書型宣言して開き直さないとできないよ！ってことなのか、筆者の環境がおかしいのか分かりませんが一応個人的には解決したので良しとしました。

初歩オブ初歩な投稿失礼しました。
Openpyxlで列挿入するもリンクが追随しない対策

## まとめると？
元シートの内容に列を追加したものを新規シートとして作成し、シート名を変更すればよいのでは？

## 問題の挙動

以下のような```urls```シートが```sample.xlsx```に存在するものとする。

| | A | B | C |
|---- | ---- | ---- | ---- |
| 1 | [Google](https://www.google.com/) | [Yahoo](https://www.yahoo.co.jp/) | %空白セル% |

リンクの追加は以下の操作で行われているものとする。

- セルを右クリック > リンク
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526492/8e903ab6-018c-9377-f435-210c7df0473b.png)

- アドレスにリンク先アドレスを入力してOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526492/15f7ed32-6287-3520-ef95-f098148ac428.png)


上記のファイルに対して、以下のようなコードでBに新規列を追加した。

```
import openpyxl

# sample.xlsxファイルを開き、urlsシートを選択する
workbook = openpyxl.load_workbook("sample.xlsx")
sheet    = workbook["urls"]

# B列の挿入
sheet.insert_cols(2)

# 編集内容を保存する
workbook.save("sample_insert_col.xlsx")
workbook.close()
```

すると、以下のように「列挿入されたもののリンクの座標は変更されない」xlsxファイルが生成された。

| | A | B | C |
|---- | ---- | ---- | ---- |
| 1 | [Google](https://www.google.com/) | [%空白セル%](https://www.yahoo.co.jp/) | Yahoo |

## (かなり強引な)回避方法

シートに対して編集すると意図しない挙動をするのであれば、別シートを新規に作成/出力して、元シートを削除すればよい、という考え。

```
import openpyxl
from copy import copy, deepcopy

# sample.xlsxファイルを開き、urlsシートを選択する
workbook = openpyxl.load_workbook("sample.xlsx")
sheet    = workbook["urls"]

# B列の挿入
# sheet.insert_cols(2)


# 元シート名を変更
sheet.title = "urls_original"

# 元シートのセルの値を取得
cel_A1 = sheet["A1"]
cel_B1 = sheet["B1"]

# 新規シートを作成
new_sheet = workbook.create_sheet("urls")

# 元シートA1の内容を新規シートA1にコピー
new_sheet["A1"].value = cel_A1.value
new_sheet["A1"].hyperlink = copy(cel_A1.hyperlink)
new_sheet["A1"].font = copy(cel_A1.font)

# 新規シートでB1に関する処理を行わないため、列挿入した状態と同じになる

# 元シートB1の内容を新規シートC1にコピー
new_sheet["C1"].value = cel_B1.value
new_sheet["C1"].hyperlink = copy(cel_B1.hyperlink)
new_sheet["C1"].font = copy(cel_B1.font)

# 元シートを削除する
del workbook["urls_original"]

# 編集内容を保存する
workbook.save("sample_insert_col.xlsx")
workbook.close()
```

上記で実行したところ、以下のようになった。

| | A | B | C |
|---- | ---- | ---- | ---- |
| 1 | [Google](https://www.google.com/) | %空白セル% | [Yahoo](https://www.yahoo.co.jp/) |

## 泥臭い回避もたまには有効
openpyxlの仕様上回避が難しかったのでこのようなコードになった。
成果物は想定通りのため、取り急ぎこれで対応してみるのもありかもしれない…。
GitHub ActionsからUnityに値(パラメーター)を渡したり、UnityからGitHub Actionsへログ表示したりエラー終了させたりする

#GitHub ActionsからUnityに値(パラメーター)を渡す

### 対象になるGitHub Action

Game CIのBuilderを使ってビルドしているプロジェクト向けです。

https://github.com/game-ci/unity-builder


### 準備 (コードをプロジェクトに配置)

下記コードを`Assets/Editor/ArgumentsParser.cs`に設置

https://github.com/game-ci/unity-builder/blob/main/dist/default-build-script/Assets/Editor/UnityBuilderAction/Input/ArgumentsParser.cs

### [GitHub Actions] パラメーターの設定

**ビルド用ymlに`customParameters`を設定します。**
記述ルール : `-パラメーター 値`
例) -myCustomParameter CustomParam

**複数定義も可能です。**
例) -fruits1 apple -fruits2 orange

**値を設定しない場合はboolタイプのtrueと判断されます**
例) -enableMyAction

※ 半角スペースで区切る為、パラメーター/値に半角スペースは使えません。

build.yml

```yml
# 省略
- uses: game-ci/unity-builder@v2
env:
  UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
with:
  customParameters: -myCustomParameter CustomParam ← 追加
# 省略
```

### [Unity] パラメーターの取得

ビルドメソッドから`ArgumentsParser.GetValidatedOptions()`を呼ぶとパラメーターと値が格納された連想配列が取得できます。そこからパラメーター名で取得します。

Build.cs

```c#
// 省略
var options = ArgumentsParser.GetValidatedOptions();
var param = options["myCustomParameter"];
Console.WriteLine(param);
// GitHub ActionsのログにCustomParamと表示される
// 省略
```

### [余談] Game CIのパラメーターの取得

Game CIが利用するパラメーターを取得する事もできます。

```c#
// 省略
var options = ArgumentsParser.GetValidatedOptions();

options["projectPath"]
options["buildTarget"]
options["customBuildPath"]
options["buildVersion"]

// 省略
```


# UnityからGitHub Actionsへログ出力したりエラー終了させたりする

### メソッドの定義

下記のようなメソッドを生やしておくと便利です。
UnityとGitHub兼用のログを表示するメソッドです。
エラー表示時はビルドを強制終了させるようにしています。

```c#
public static void PrintLog(string msg)
{
    if (Application.isBatchMode) Console.WriteLine(msg);
    else Debug.Log(msg);
}

public static void PrintWarningLog(string msg)
{
    if (Application.isBatchMode) Console.WriteLine($"::warning:: {msg}");
    else Debug.LogWarning(msg);
}

public static void PrintErrorLog(string msg)
{
    if (Application.isBatchMode)
    {
        Console.WriteLine($"::error:: {msg}");
        // ビルドの強制終了 100は適当です。 1以上を指定します。0だと正常に完了したとみなされるので注意してください。
        EditorApplication.Exit(100);
    }
    else Debug.LogError(msg);
}
```

### 使い方

```c#
PrintLog("メッセージ");
PrintWarningLog("warningだよ");
PrintErrorLog("Errorだよ");
```

GitHub Actions上のログでは下記のように表示されます。

![スクリーンショット 2021-05-31 0.34.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/d273a220-41ec-732d-b10c-7746f9d130c7.png)

![スクリーンショット 2021-05-31 0.12.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/cfa4ba32-7a17-241d-fc65-11eb28a9ff3d.png)
【GIS】KMLファイルを出力する

# はじめに

KMLでデータを出力したくなってきたので、python でKMLを読み書きできるライブアリを調べていました。ところ、simplekmlが使えそうだったのでメモを書いておきます。

https://simplekml.readthedocs.io/en/latest/

# 作業メモ

### インストール

特に何事もなく。。

```
$python -m pip install simplekml
Collecting simplekml
  Downloading simplekml-1.3.5-py3-none-any.whl (65 kB)
     |████████████████████████████████| 65 kB 912 kB/s
Installing collected packages: simplekml
Successfully installed simplekml-1.3.5
```

https://pypi.org/project/simplekml/

## 緯度経度のある座標値を保存する

ファイルへの保存について確認していきます。以下に使い方は紹介されています。

https://simplekml.readthedocs.io/en/latest/gettingstarted.html#getting-started

3種類のデータを保存できるらしい。

- Point
- LineString
- Polygon

についてデータを書けるようです。

### 点(NewPoint)を保存してみる

simplekmlのインスタンスを作り、newpoint を設定し、saveするだけ。

```
import simplekml
kml = simplekml.Kml()
kml.newpoint(name="Tokyo Station", coords=[(139.7673068,35.6809591,0)],description="station")
kml.newpoint(name="Kitte", coords=[(139.7647979003,35.679746926311,100)],description="building")
kml.save("tokyo.kml")
```

保存したtokyo.kmlはGoogle Earth で見ることができます。

https://earth.google.com/web

ロードの仕方の解説がありました。

https://support.google.com/earth/answer/7365595?co=GENIE.Platform%3DDesktop&hl=en&oco=1

> If you have a KML file from previous versions of Google Earth, you can view it in Google Earth for web browsers.

> 1. Using the web browser on your computer, open Google Earth.
2. On the left, click Projects Project.
3. Click the New Project button.
 - To add a file directly to your computer, select Import KML File.
 - To add a file from your Google Drive or a shared file, select Import KML file from Drive.
4. Select the KML file you'd like to view.
The files will be automatically saved to your KML files within Projects.

ですが、これは見る角度によってKitteのピンが隠れてしまいました。どうしたら良いのだろう。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/cbb06cc7-e0db-9d12-37dd-7de5057e9d85.png)

Getting Started に書かれているように LineString、Polygon も動きました。

LineStringの例：

```Python
lin = kml.newlinestring(name="Pathway", description="A pathway in Kirstenbosch",
                        coords=[(18.43312,-33.98924), (18.43224,-33.98914),
                                (18.43144,-33.98911), (18.43095,-33.98904)])
```

Polygon の例：

```Python
pol = kml.newpolygon(name="Atrium Garden",
                     outerboundaryis=[(18.43348,-33.98985), (18.43387,-33.99004),
                                      (18.43410,-33.98972), (18.43371,-33.98952),
                                      (18.43348,-33.98985)],
                     innerboundaryis=[(18.43360,-33.98982), (18.43386,-33.98995),
                                      (18.43401,-33.98974), (18.43376,-33.98962),
                                      (18.43360,-33.98982)])
```

PolygonもGoogle Earthの角度やズームの大きさで変わってくる感じ。

# まとめ

simplekml はインストールとGoogle Earthで表示する点の座標な書けそう。明日、使うかな。。。
(2021/05/31 1:30)