OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】Debug.Log 置き換えテンプレート

`Debug.Log()` でイイじゃんね。て感じもありますが、最初にこれさえやっておけば後から最低限の対応ができるテンプレート。

- Unity コンソールのログをダブルクリックしたときにロガーの `.cs` ファイルが開いたりしない。ちゃんとログを出力したスクリプトが開く。
- ログがごちゃついてきたから一括でプリフィックス付けたい。色変えたい。エラーだけファイルやサーバーに記録を残したい。が後から可能。
    - `=> Debug.Log($"<color=#CC7700><b>[{nameof(MyOrg.App)}]</b></color> " + message);`
- スタックトレースが無駄に長くならない。
- 一旦手を離れたモジュールからのログは非表示にしたい。
- リリースビルドではエラー以外は出力しない、とかできる。



```csharp
using System.Diagnostics;
using System.Runtime.CompilerServices;
using UnityEngine;
using Debug = UnityEngine.Debug;

namespace MyOrg.App
{
    internal static class Logger
    {
        [Conditional("UNITY_EDITOR")]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Log(object message, Object context = null)
            => Debug.Log(message, context);

        [Conditional("UNITY_EDITOR")]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void LogWarning(object message, Object context = null)
            => Debug.LogWarning(message, context);

        [Conditional("UNITY_EDITOR")]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void LogError(object message, Object context = null)
            => Debug.LogError(message, context);
    }
}
```



--

ロガーはロガーで色々と奥が深いみたいですが、本気のロガーに後から差し替えも可能でしょう。

以上です。お疲れ様でした。
LINE×GAS｜決まった曜日・時間にメッセージ通知

# ゴール
僕は毎週、友達と電話をしています。
でも、その予定を毎週きめるのがめんどくさかったり、忘れたり、なんとなく聞きづらかったりするんですよね。ということで、代わりに聞いてくれるBotを作りました。

# 完成形
▼LINE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/346cb77a-afa2-540c-0ce4-75980e195664.png)

▼スプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/77b5e44d-e1aa-742f-8078-5dd6666c9141.png)

▼コード（GAS)
```js:ask_day_of_week.gs
// ------色々と定義する------
  // スプレッドシートのシート名を取得し、`sheet`に定義
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("set");

  // スプシから取得したLINEトークンを`token`に定義
  let token = sheet.getRange(4,3).getValue();

  // メッセージの形を定義
    function setContentFormat(content) {
    var options = {
      "method": "post",
      "payload" : {"message": content },
      "headers": {"Authorization": "Bearer " + token}    
    };
    UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
    }


// ------メッセージを送信する------
  function postContent() {
    let content = sheet.getRange(5,3).getValue();
    setContentFormat(content);
  }

```

▼トリガー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687068/35668744-14b6-95dc-0417-6e844941a214.png)


# 使い方
1. [LINE Notify](https://notify-bot.line.me/ja/)にてアクセストークンを取得
1. 取得したアクセストークンをスプレッドシートに貼り付け
1. 送りたいメッセージを設定
1. トリガーを設定

# ポイント
参考記事では、GAS上で送るメッセージやアクセストークンを定義していましたが、スプレッドシート上で記載できる形に変えました。汎用性やメンテナンス性を高めるためです。

# 今後の展望
搭載したい機能
1. 曜日をワンクリックで回答
1. 回答した曜日の前日にリマインド

# 参考記事

https://hoshino-wp.com/line-notify-google-apps-script/
ParaViewでの断面積データの抽出方法

# Intro

Some students asked me a procedure to obtain data on cross-sectional areas.

Please refer to the following movie. 

Just use `Extra Block` and `Integrated Variables`

#### movie
<iframe width="560" height="315" src="https://www.youtube.com/embed/WGiGrx-eou0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


Thank you.
開発支援ツール

# 設計支援ツール・構築ツール
開発形態や開発内容に応じて、さまざまなツールが用意されている。

## 静的解析ツール
プログラムを実行せずに、```ソースプログラムの解析やテストケースの抽出```などを行う。

### ソースコード解析ツール
ソースコードを解析し以下を検査する。
* コーディング規則に則っているか
* 使用されていないコードがないかをチェックする。
* モジュール間インタフェースを検査

## 動的解析ツール
```テストデータを自動生成してプログラムを実行```したり、```制御の流れをトレース（追跡）```して、```解析に必要な情報の出力```を行う。

### テストデータ生成ツール
プログラムの記述や入力データの構造をもとにテストデータを自動生成する。

### テストカバレージツール
* テストデータ通った```プログラム経路を調べながら、カバー率を分析```する。
* ```コード中のどれだけの割合の部分を実行できたかを評価```するのに使う。

### テストベッドツール
テストのための動作環境を提供するツール。
トップダウン/ボトムアップテスト用のスタブ/ドライバを生成する。

## バージョン管理ツール
開発において、```プログラムの作成・改変履歴を管理する```ためのツール。
多数の開発者による```開発においては最新の状態を把握することが欠かせない```。

# デバッグツール
デバッグとはプログラム中の```誤りを取り除き修正する作業```.

このデバッグを支援するサービスプログラムをデバッグツールという。
以下のようなものがある。

### スナップショットダンプ（ダンプルーチン）
レジスタや主記憶装置、ファイルなどの内容を```そのままではの状態で出力するツール。

### トレーサ（追跡プログラム）
* プログラムの実行を追跡し、```レシスタの内容や参照されたメモリのアドレス内容など、必要な情報を出力```する
* 誤りの箇所が特定できないときに、```実行順に命令とその実行結果を出力```する。

### クロスリファレンス
プログラムで使用している```関数・変数と、それらを定義しているプログラムを一覧化し、関連を示す機能```を持つ。

### インスペクタ
構造体などのデータ構造について、その```その内容を見やすい形で表示し、容易に確認```できるようにする。

### アサーションチェッカ
プログラム中に挿入して、```変数の間で論理的に成立すべき条件が満たされているか否かを確認```するツール

# 問題２の気づき
### メモリダンプとは？
プログラム実行中にエラーが発生した時、メモリの内容を出力する。

### ダンプファイル（●読み：だんぷふぁいる　●スペル：dmp file）
```メモリやレジスタ・ファイル・ディスクなどの中身を丸ごと記録したファイル```の事を言います。 
また、データベースにおいては、```データベース情報をファイルに書き出して保存することダンプ```と呼びます。
こちらはデータベース移行の際に利用されます。

### ファイルダンプ
磁気テープファイルや磁気ディスクファイルなどの内容を出力する。

### スナップショットとは？
ある時点でのソースコードや、ファイル、ディレクトリ、データベースファイルなどの状態を抜き出したもののことです。
バックアップをする際に、バックアップ処理中にファイルが更新されると、ファイルやディレクトリに不整合が起こることがあります。これを防ぐために使用されるのがスナップショットです。
出典
https://www.idcf.jp/words/snapshot.html#:~:text=%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%81%A8%E3%81%AF%E3%80%81%E3%81%82%E3%82%8B,%E3%81%AE%E3%81%8C%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%E3%81%A7%E3%81%99%E3%80%82

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
socketを利用してGETリクエストを送る




# RFC 7230: Hypertext Transfer Protocol (HTTP/1.1)

まずはGETリクエスト(HTTPリクエスト)とは何なのか、RFCを確認します。

https://www.rfc-editor.org/rfc/rfc7230
https://triple-underscore.github.io/RFC7230-ja.html

`HTTP request`は以下のような構成です。

 - `request-line`
 - `header fields`
 - `empty line`
 - `payload body`


以下のような表記もなされていました。
```
     HTTP-message   = start-line
                      *( header-field CRLF )
                      CRLF
                      [ message-body ]
```

以下のサイトでは次のように翻訳しているようです。
https://wa3.i-3-i.info/word1845.html


```
HTTPリクエストライン（リクエストライン）
HTTPリクエストヘッダ（ヘッダ）
空行
HTTPリクエストメッセージボディ（メッセージボディ）
```

「ネットワークはなぜつながるのか」では次のように翻訳されていました。

```
リクエスト・ライン
メッセージ・ヘッダー
メッセージ・ボディ
```

表記は色々あるようですね。

# curlコマンドのHTTPリクエストを確認する

```sh
curl --http1.1 -v https://www.google.com
```

`>`で始まっている行を抜粋すると、たしかにRFCに従っていることが確認できました。

```sh
> GET / HTTP/1.1
> Host: www.google.com
> user-agent: curl/7.79.1
> accept: */*
>
```

この例ではGETリクエストなので`payload body`は存在しません。ただし、`empty line`は含まれています。

# socketを利用してGETリクエストを送る

では以下の`HTTP request`を実際にWebサーバに送信してみます。先程のcurlコマンドのHTTPリクエストをコピペして、txtファイルを作成しておきます。

```curl_request.txt
GET / HTTP/1.1
Host: www.google.com
user-agent: curl/7.79.1
accept: */*

```

以下のPythonスクリプトを作成して実行します。

```client.py
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('www.google.com', 80))
with open('curl_request.txt', 'rb') as f:
    client.send(f.read())
response = client.recv(4096)
client.close()
print(response.decode())
```

コードの一部は以下を参考にさせていただきました。

https://qiita.com/chooyan_eng/items/087d2fd20294ed35e550

```sh
HTTP/1.1 200 OK
(以下略)
```

正常にリクエストを送信できました。

# 補足
- GETリクエストであっても `empty line` が必要です。試しに削除してリクエストしてみましょう。
- curlでわざわざ `--http1.1`オプションを付けていますが、私の環境ではつけなかった場合に`HTTP/2`でのリクエストになりました。また、理由を深掘っていませんが、`HTTP/2`では`www.google.com`から`200 OK`を受信できなかったために天下り的に`HTTP/1.1`で進めています。
リーダブルコードまとめ(第15章:「分/時間カウンタ」を設計・実装する)

# 第15章:「分/時間カウンタ」を設計・実装する
## 概要
本章では、プロダクトコードで用いられる、データ構造「分/時間カウンタ」について解説してくれている。

### まとめ
「ConveyorQueue」「TrailingBucketCounter」「MinuteHourCounter」の3つのクラスを用いて、それぞれの下位問題を解決できるようにすることが理想的である。

### 学んだ点
・Count()というメソッド名には、「全期間のカウントを返す」と考える人が多く、この名前を見ただけで直感的に理解できるものではない。そこで、Count()に代わる候補は以下の4つ
①Increment()　→値が増加する一方だと思われてしまう。(カウントは時間によって変化するもの)
②Observe()　→問題はないが少し曖昧
③Record()　→名詞と動詞の問題があるのでだめ
④Add()　→「この数値を追加する」と「データのリストに追加する」という2つの意味があるので適切
・Add(~ count)という形で、仮引数の名前にcountを持ってくることで文脈も理解しやすくなる。
・コードがユーザーフレンドかどうかを確認するための優れた手段として、同僚に質問して外部の視点を得る。
・ベルトコンベヤー設計とは、事前に変数同士の合計値を算出して、その後不要なデータを削除して、という流れを繰り返すために用いられる設計
・ベルトコンベヤー設計で、最も大切なのは時間経過に伴うイベントの「移動」である。
・ConveyorQueue
最大長のあるキューで、「シフト」可能で合計値を保持する。
・TrailingBucketCounter
時間経過に伴ってConveyorQueueを移動する。また、1つの(最新の)時間帯のカウントを任意の精度で保持する。
・MinuteHourCounter
2つのTrailingBucketCounterを保持する。1つは1分間のカウントで、もう一つは、1時間のカウントである。

### 感想と振り返り
実装しているアプリではすでにこのようなカウンタは実装されているため、手を加えることはないと考えられますが、これを機にカウンタに関わるコードを見てどのような書き方やデータのやり取りがされているのかを学びたいと思いました！

## 最後の振り返り
リーダブルコードは初めて読んだコードに関しての解説本でした。個人開発をしていた際にも、一読したのですがその時は何を言っているのかさっぱりでした。しかし、実装に関わらせていただきはや1ヶ月少しが経ちまして、もう一度読んでみると奥が深く勉強になることばかりでした！改めてメモがわりに投稿し続けてよかったなと思います！(古い本なので仕方ないですが、できればSwiftで書かれた例題とかあればよかったなと思いました。)
次に読むのは、「いいコード悪いコード」もしくは、「iOSアプリ設計パターン入門」を読みたいなと考えています！iOS関連でおすすめの記事や書籍、サイトがあればぜひご共有していただければ幸いです！
引き続き、学習楽しんでいきましょう！
はじめてのwatchOSアプリ開発

# はじめに
これまでiOSアプリの開発を経験したことがあったのですが、
先日はじめてApple WatchのwatchOSのアプリを開発する機会がありました。

watchOSアプリを開発した際に、得た知識を備忘録として残しておきます。

# 事前情報
- iOS + wathcOSプロジェクトでアプリを作成
- ProvisioningProfileを発行して実機にて動作確認を実施

# ①｜ProvisioningProfileの設定
- 各AppIDに紐づく ProvisioningProfile を発行する
WatchKit App と WatchKit Extension はプロジェクト名の末尾に、
小文字でWatchKit App、WatchKit Extension と付けるのが判別しやすいと思います

例）
　iOS App： `sample`.mobileprovision
　WatchKit App： `samplewatchkitapp`.mobileprovision
　WatchKit Extension：`samplewatchkitextension`.mobileprovision
　※基本的にAppIDは全て小文字で設定します

# ②｜拡張ランタイムセッション
- 腕を下げたりした際に通常はアプリがスリープする場合でも、アプリを動かし続けることができる
- 位置情報やモーションデータなどは画面消灯時も取得することができる
    - ただし、セッションは最大１時間で切れる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/bb294633-63fb-e138-f32e-4766b4f12c3a.png" width=100%>　
※ここでは、位置情報とワークアウトをバックグラウンドモードに設定

# ③｜画面常時点灯　　
画面消灯後にデータを取得できなくなることを防ぐ方法として、
- Apple　Watch Series 5以降は「常時点灯ディスプレイ」をOS側で設定する
    - 手首を下げてもスクリーンがオフにならない
- watchOS 8以降からはアプリ側で常時表示オンにするかを決める設定ができる

# ④｜ボタンの活性・非活性
- watchOSの標準ボタンに`isEnable`プロパティがない
- 排他制御を表現するため、以下のように実装する必要がある
```swift
@IBAction private func onTapStartButtun() {
    if !isRun {
        isRun = true
        startButton.setBackgroundColor(.none)
        stopButton.setBackgroundColor(.darkGray)
        startRun()
    }
}

@IBAction private func onTapStopButtun() {
    if isRun {
        isRun = false
        startButton.setBackgroundColor(.darkGray)
        stopButton.setBackgroundColor(.none)
        stopRun()
    }
}
```

# ⑤｜WatchConnectivity
- ペアリングされた iOS と watchOS 間で通信してデータやファイル転送を行うことができる
- `iOS → watchOS` 、 `watchOS → iOS` の両方向転送が可能である

# さいごに
上記に記載した５つがwatchOSアプリの作成時に気になったことでした。
これからwatchOSアプリを開発する人の役に立てればと思います。

# 参考サイト
- [Using extended runtime sessions](https://developer.apple.com/documentation/watchkit/using_extended_runtime_sessions)
- [Apple Watch で「常にオン」機能を使う](https://support.apple.com/ja-jp/HT210428)
- [Designing Your App for the Always On State](https://developer.apple.com/documentation/watchos-apps/designing-your-app-for-the-always-on-state)
- [Watch Connectivity](https://developer.apple.com/documentation/watchconnectivity)
リーダブルコードまとめ(第14章:テストと読みやすさ)

# 第14章:テストと読みやすさ
## 概要
本章では、効果的なテストを書くための技法を解説している。(ここでのテストは、コードの振る舞いを確認するための全てのコードのいこと。)

### まとめ
テストコードでも読みやすさが必要で、テストが読みやすければテスト書きやすくなる。また、本物のコードをテストしやすく設計すれば、コードの設計が全体的に改善される。

### 学んだ点
・テストコードを読みやすくするのは、テスト以外のコードを読みやすくするのと同じくらい大切である。
・他のプログラマが安心してテストの追加変更ができるように、テストコードを読みやすくすることが必要である。
・一般的な原則として、「大切ではない詳細は目立つようにする」べきである。
・テストの本質は、「対象の状況と入力から、こういう振る舞いと出力を期待する」のレベルまで要約できる。また、その挙動を記述するためには、1行で事足りることが多い。コードを簡潔に読みやすくするためだけでなく、テストステートメントを近くすることで、テストいケースの追加が簡単になる。
・エラーメッセージは、できるだけ役立つようにすることが大事で、自分好みのエラーメッセージを印字する「手作りのアサート」を用意するのが最善である。
・コードを完全にテストする最も単純な入力値の組み合わせを選択しなければならない。
・テストには、最もキレイで単純な値を選ぶ
・コードを検証する「完璧」な入力値を1つ作るのではなく、小さなテストを複数作るほうが、簡単で、効果的で、読みやすい。そうすることで、複数のテストで別々の方向からバグを見つけ出せるようにする。
・テストケースが分割されていれば、次の人がコードが扱いやすくなる。
・関数等に名前を付ける場合、テストの内容を表した名前を付けるべきで、テストコードを読む人が以下のことを理解できるようにする。①テストするクラス②テストする関数③テストする状況やバグ
・テストで利用する関数の場合、「Test~」と接頭語をつけて情報をまとめて書くべきである。
・テストコードは、長くなってしまったとしても、「Test_<関数名>_<状況>()」という形式で書くべきである。
・ほとんどのスティングフレームワークでは、テストが失敗したらその関数の名前が印字されるようになっているので、名前は、関数の処理の説明の方がいい。
・後でテストコードを書くつもりで、コードを書くとテストしやすいようにコードを設計するようになるので効率がいい。
・テスト駆動開発とは、本物のコードを書く前にテストを書くというプログラミング手法であり、コードを書いてからテストを書くよりもコードの品質が飛躍的に向上するらしい。
・プログラミングをクラスやメソッドに分割するというのは、疎結合にしたほうがテストしやすいからである。
・テストのために本物のコードの読みやすさを犠牲にしない。
・テストのカバレッジを100%にしようとこだわりすぎない。(カバレッジ100％はほぼ不可能)
・テストがプロダクト開発の邪魔にならないようにする。

### 感想と振り返り
普段の実装ではテストコード...という感じなので、勉強し直せてよかったです！Rubyの個人開発時には、ライブラリを使ってモデルとテストコードを活用して簡単にテストできたので、Swiftでもテストコードに関して学習して積極的に活用していきたいと思います！
今回学んだところには記述しなかったのですが、「テストの容易性の低いコードの特性とそこらか生じる設計の問題」と「テスト容易性の高いコードの特性とそこから生じる設計の利点」を表にして説明してくれているので、ぜひ手に取って読んでみてください！
ExcelデータをDBインポートするとき、受け側テーブルをどうするか

# どうする？
カラム定義そのものをExcelでやってみたら良い感じでした。

![スクリーンショット 2022-10-01 8.21.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/9f3e25cb-1656-8464-b5a4-f05752883f7f.png)

* データの列見出しの入った先頭行をコピーし、別シートのA列に行列を入れ替えペースト。
* B列にSQL(やPHP)で使えるフィールド名を記入する。基本Aのコピペだが、適宜修正。
* C列にvarchar(100)などののSQL型を記入していく。
* D列に各カラムのコメント
* E列の先頭に 「field名 型 comment 'xxx',」 の文字列を作って、以下オートフィル

E列の連結式は

```vb
=B1&" "&C1&" "&"comment '"&D1&"',"
```
とかをつかいます。

変数名をSQL/PHPで使える文字にしているのは、このあとスクリプトとかでLaminasのモデルを自動生成<a href="https://github.com/smj320/ModelGen">させる</a>ためです。

* E列の内容を、create tableを定義する場所にコピペする。

こんな感じになります（コピペ後Phpstormのコード整形を使用）。

![スクリーンショット 2022-10-01 8.18.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188685/30c479eb-7d38-a404-4dc4-1bac50a9a34d.png)

これでMySQLにテーブルを作って、CSVに変換したテーブルをphpstormとかｐｈｐMyAｄminとかでインポートします。もとのデータ型式がちゃんとしていれば（当たり前ですが）スパッと入ります。

入らない場合は元データを直すか、フィルタスクリプトを書くか（白目）、とりあえず全部varcharで取り込んでから考えることになりますが、それでもカラム名が定義できていると随分助かります。
SRE関連まとめ

業務でSRE関連の仕事に携わり始めたので、自分用にSRE関連についてまとめます。

# SRE

[SREとはGoogleから提唱された用語（概念）で、「インフラの整備や自動化ツールの開発などを通じて、サイト・サービスの信頼性を高める（維持する）」ことです。](https://pfs.nifcloud.com/navi/tech/sre.htm#:~:text=SRE%E3%81%A8DevOps%E3%81%AE%E9%81%95%E3%81%84,-%E5%86%92%E9%A0%AD%E3%81%A7%E8%BF%B0%E3%81%B9&text=DevOps%E3%81%AE%E4%B8%BB%E7%9B%AE%E7%9A%84%E3%81%AF,%E7%B6%AD%E6%8C%81%E3%81%99%E3%82%8B%EF%BC%89%E3%80%8D%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82)

一般的にDevOpsと混合されがちな概念ですが、DevOpsの方は開発スピードとリードタイムの短縮によりサービス向上に貢献します。そういった意味から、DevOpsよりも広い意味を含んだ用語となっております。

# リリースエンジニアリング
アプリケーションのリリース時の戦略で、具体的にBlue/Green DeploymentやRolling Updateなどがあるよう。
- [デプロイ戦略・テスト戦略](https://cloud.google.com/architecture/application-deployment-and-testing-strategies?hl=ja)
- [GKEでのデプロイ戦略・テスト戦略](https://cloud.google.com/architecture/implementing-deployment-and-testing-strategies-on-gke?hl=ja)
VPC Flow Logs

## 特徴
inbund,outbundの通信をキャプチャする。
デフォルトでは無効
インターフェースレベルでキャプチャする。
ただしリアルタイムではない。

全てのIPトラフィックをキャプチャするわけではない。
取らない通信はAWS DNS Serverへの通信、Windows License Activation、 169.254.169.254への通信、　DHCPトラフィック

## 有効化
ロググループ作成
フィルターする。Accept、Reject、ALL
送付先。S3、CWlogs
など

## log format
- VPC Flow logs Version
- AWS Account ID
- Network interface ID
- src IP
- dest IP
- src port
- dest port
- protocol
- packts
- bytes
- start
- end
- action(Accept or Reject)
- log status
ipythonでプロンプトをカスタマイズする

ipythonのデフォルトのプロンプトは以下のようになっている：

```
In [1]:
Out[1]:
```

これを

```
>>> print('hello')
hello

>>> 
```

に変える。

# このPythonスクリプトを実行すればよい

```python
from IPython.terminal.prompts import Prompts, Token
import os
class MyPrompt(Prompts):
      def in_prompt_tokens(self, cli=None):
          return [(Token.Prompt, '>>> ')]
      def out_prompt_tokens(self, cli=None):
          return []

ip = get_ipython()
ip.prompts = MyPrompt(ip)
```

ipythonを起動してこれを実行すればその場でプロンプトが`>>> `に変わる。

くわて、`Out[1]`みたいなアウトプット時の表示も消える。

# スタートアップに設定

毎回上記のスクリプトをいちいち書いて実行するのは面倒だから、ipython起動時に自動で実行するように設定する。

そのために、`~/.ipython/profile_default/`に`startup`ディレクトリを作成する。

そして上のスクリプトを`start.py`としてこのディレクトリに保存すればOK（`~/.ipython/profile_default/startup/start.py`）


これで次回の起動からプロンプトが`>>> `になってる。

ちなみに、ipython実行時のオプションで`--classic`を指定するとプロンプトが`>>> `になるが、そうすると色がつかないので注意。
VBAのテキストファイル入出力でのオブジェクト指向なやり方


## テキストファイル入力
### かつての方式
```
Dim strFile As String
Dim strLine As String
Dim num = FreeFile
strFile = "d:\work\testfile.txt"

Open strFile For Input As #num
Do Until EOF(num)
    Line Input #num, strLine
    ....
Loop
Close #num
```

### よりモダンな方式

```
Dim fso As Object
Dim rf As Object
Dim strFilePath as String
Dim strLine As String
strFilePath = "d:\work\testfile.txt"

Set fso = CreateObject("Scripting.FileSystemObject")
Set rf = fso.OpenTextFile(strFilePath, ForReading, False)
Do While rf.AtEndOfStream <> True
    strLine = rf.ReadLine
    ...
Loop
rf.Close
Set fso = Nothing
```

## テキストファイル出力
### かつての方式

```
Dim strFilePath as String
Dim strLine As String
Dim num = FreeFile
strFilePath = "d:\work\testfile.txt"
strLine = "Hello world!"

Open strFilePath For Append As #num
Print #num, strLine
Close #num
```


### よりモダンな方式

```
Dim fso As Object
Dim af As Object
Dim strFilePath as String
Dim strLine As String
strFilePath = "d:\work\testfile.txt"
strLine = "Hello world!"

Set fso = CreateObject("Scripting.FileSystemObject")
Set af = fso.OpenTextFile(strFilePath, ForAppending, True)
af.Write strLine
af.Close
Set fso = Nothing
```
eclipseで起動するWebブラウザを変更

eclipse4.8の内部ブラウザだとHTML/CSSが反応してくれないので普段使ってるWebブラウザへの変更を備忘録でメモ
webアプリ開発してるときとかにサーバ実行とかで起動するWebブラウザが内部のじゃなくてChromeとか普段使ってるやつになる

1. ヘッダメニュー[設定] - [ウィンドウ]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/c1fd8368-066a-9439-afdb-f9fee7e3f004.png)

1. テキストボックスに `Web` 入力 - [Web ブラウザ―]クリック - 以下を変更して [適用] or [適用して閉じる]
    - [外部Webブラウザ―を使用] を選択
    - [デフォルトのシステムWebブラウザ―] をチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51758/24bfe0b8-2389-7a99-ad27-e4ed1e55c75d.png)

1. これで終了、次からWebアプリのプロジェクトでサーバ実行で開くブラウザが変わるはず
Spring Cloud OpenFeign でサーバ間通信処理のサンプルを作ってみた。

## Spring Cloud OpenFeign とは
Springで簡単に通信処理を実現できるツール

## サンプルのシステム構成図
・サーバ情報
Server①：localhost:8080
Server②：localhost:8090
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951197/a98f44b7-0b39-47e3-c84e-6ef3d1b73085.png)
#### 実行内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951197/9a0966a2-ca32-a47c-6ccc-4373e0e4ca23.png)
「localhost:8080/api/hello」をブラウザーで表示すると「Hello, World」と表示。
Server①がServer②に「Hello,」という文字を渡して、Server②の処理内で「Hello, World」に加工。
加工したデータをServer①が受け取ってUserに返却するだけのサンプルです。

##### Server①のソースコード
```java:HelloController.java
package com.restfull.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.restfull.httpclient.HelloClient;
@RestController
public class HelloController {

	@Autowired
	private HelloClient helloClient;

	/**
	 * Getメソッドで処理を実行(http://localhost:8080/api/hello)
	 * 
	 * @return 表示メッセージ
	 */
	@GetMapping("api/hello")
	public String hello() {
		String parts = "Hello,";
	    String message = helloClient.Hello(parts);
		return message;
	}
}
```
```java:HelloClient.java
package com.restfull.httpclient;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import com.restfull.config.FeignConfig;

@FeignClient(name = "hello", configuration = FeignConfig.class, url = "localhost:8090")
@Component
public interface HelloClient {
	@PostMapping(path = "/api/hello", produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.TEXT_PLAIN_VALUE)
	String Hello(@RequestBody String parts);
}
```

##### Server②のソースコード
```java:HelloController.java
package com.sample.app.controller;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/** サンプルコントローラー */
@RestController
public class HelloController {

	/**
	 * Postメソッドで処理を実行(http://localhost:8090/api/hello)
	 * 
	 * @return レスポンスメッセージ
	 */
	@PostMapping("/api/hello")
	public String helloApi(@RequestBody(required = false) String parts) {
		parts = parts + " World";
		return parts;
	}
}
```

#### 補足:port番号の切り替え
```properties:application.properties
server.port=8090
```
C# DataGridViewの列の表示／非表示を画面サイズに合わせて自動制御する

# この記事でできること
DataGridViewのサイズ変更に合わせて、補助情報的な列を自動的に表示したり非表示にします。
![列の表示非表示.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546646/4cda2fdf-4c18-a343-e540-a40e86fe17a9.gif)

:::note 
**ポイント**
ご覧の通りDataGridViewのデータが10000行程度であれば、スムーズに表示／非表示が切り替わります。
:::


# DataGridViewの列表示を制御する

FormのSizeChangedで発火しています。（DataGridViewをAnchorしているので）
```C#
private void Form_SizeChanged(object sender, EventArgs e)
{ 
    DataGridView dg = this.ucGridPager.pagerDataGridView;

    // データ0行ならなにもしない
    if (dg.RowCount == 0) return;

    // AutoSizeMode = Fill の列があれば、一旦FILLからDisplayedCells等へ切り替える
    dg.Columns[(int)売上一覧_Col.得意先名].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;

    // FILL列のない状態で、各列の幅を合計する
    int ColWidthSum = 0;
    foreach (DataGridViewColumn column in dg.Columns)
    {
        ColWidthSum += column.Width;
    }

    // DataGridViewの幅は、各列の幅の合計より大きいか？
    if (dg.Width > ColWidthSum)
    {
        // 十分な幅が確保できていれば、補助情報的な列も表示する。
        dg.Columns[(int)売上一覧_Col.得意先コード].Visible = true;
        dg.Columns[(int)売上一覧_Col.担当社員番号].Visible = true;

        // FILLで表示したい列を元に戻す
        dg.Columns[(int)売上一覧_Col.得意先名].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }
    else
    {
        // 十分な幅が確保できないので、補助情報的な列は非表示にする。
        dg.Columns[(int)売上一覧_Col.得意先コード].Visible = false;
        dg.Columns[(int)売上一覧_Col.担当社員番号].Visible = false;

        // FILLで表示したい列を元に戻す
        dg.Columns[(int)売上一覧_Col.得意先名].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }
}
```

# DataGridViewのパフォーマンス向上
DataGridViewを適切に設定しないと、同じ10000行程度のデータでもスムーズに表示／非表示が切り替わりません。

```C#
// DataGirdViewのパフォーマンス・チューニング
private void InitDataGridView()
{
    // DoubleBuffered
    Type dgvtype = typeof(DataGridView);
    System.Reflection.PropertyInfo dgvPropertyInfo =
        dgvtype.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance
        | System.Reflection.BindingFlags.NonPublic);
    dgvPropertyInfo.SetValue(dataGridView, true, null);

    // AutoSize None
    dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;

    // RowHeader false
    dataGridView.RowHeadersVisible = false;
}
```

:::note alert
**特にAutoSizeに気をつける**
```C#
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
```
がとても重要です。
仮に、
```C#
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
```
とした場合、データ量が多くなるとスムーズに切り替わりません。
:::

# サンプルソースの公開
https://github.com/masayahak/GridPager
個人利用は3台まで無料！！LTS版Ubuntuのサポート期間を5年延長させるESMの登録をやってみた

筆者はLinuxマシンのOSとして個人でUbuntuを利用しています．Ubuntuには通常版とLTS(Long Term Support)版のOSが有ります．これまでの所バージョン番号が奇数の場合は通常版，偶数の場合はLTS版となっており，通常版が約半年のサポート期間なのに対してLTS版は5年間と長期間に渡ってサポートされます．LinuxマシンはGPUサーバとして利用しているため，ドライバーやライブラリの互換性等の都合で頻繁にOSを入れ替えることが出来ません．よってサポート期間の長いLTS版は大変助かります．筆者は寡聞にして知らなかったのですが，ESM(Extended Security Maintenance)に登録すると更に5年間サポート期間が延長されます．つまり10年間サポートが得られることになります．しかも，個人利用なら3台まで無料．登録しないという選択肢は無さそうです．よって早速登録をやってみました．

# ESM登録サイトにアクセス
以下の登録サイトにアクセスし，`Get started with Ubuntu Advantage`(下図中の緑のボタン)をクリックします．

https://ubuntu.com/security/esm

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/768800e8-4712-6327-3439-85f2175e3a71.png)

# 個人利用登録
筆者は個人での利用なので`Free for personal use`の登録を実施します．`Register`をクリックして登録画面にアクセスします．(商用利用の場合は左側のサブスクリプション契約が必要な様です)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/45a21eed-4c7a-87a3-3ff9-48d9cce6d640.png)

# 初回利用登録
筆者はUbuntu Oneのアカウントは持っていないため，`I don't have an Ubuntu One account`を選択し，必要事項を入力し，`Create account`をクリックします．アカウントが作成され，メールアドレスの確認画面に遷移します．同時にメールアドレス確認のためのリンクを記載したメールが届きます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/8b894c22-1e2e-e698-366f-5fd35343251e.png)

![verify_email.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/c6d91a6c-62fd-b8d4-3dd4-1ad79828be8b.png)


# メールアドレスの確認
ここからの操作はお使いのメーラーソフトによっては戸惑う可能性が有ります．筆者はMS Outolookを利用しているのですが，届いたメールに記載されているハイパーリンクをOutlookが誤認識してしまったため，上手くメールアドレスの確認が出来ず苦戦しました．結局メールを開いて`To confirm your email address, please click on the link below:`の次の行に記載されているハイパーリンク(`https://login.ubuntu.com/`で始まるURL)をコピーしてブラウザのアドレスバーにコピペをして実行しました．成功すると以下のページに遷移します．ロボットではないという意思表示をして，`Yes, I'm sure`をクリックします．

![verify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/30e4c358-c6a6-203d-42f7-dcd8591b4fdb.png)

# Ubuntu.comにログイン
メールアドレスの確認が完了すると，個人の詳細情報のページに遷移します．内容を確認して`Yes, log me in`をクリックします．

![login.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/493860ee-53d0-7378-b9a9-811122bdbe86.png)

正常にログイン出来ると下図のようにサブスクリプション内容が確認出来ます．[^login]

![esm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/0cb08592-c226-e810-35e6-87d0097a119e.png)


[^login]: 筆者はこの記事をまとめている間にセッションが切れてしまったため，再度ESMの登録ページを開いてログイン操作を実行して確認したため，実際に遷移するページは異なる可能性が有ります．

# まとめ
Ubuntuのサポート期間を5年間延長して10年間とするために，Ubuntu One(ESM)の登録をやってみました．トークンの登録はLinuxマシンのOSを22.04にアップグレードした後実施しようと思います．

# Reference

https://xtech.nikkei.com/atcl/nxt/column/18/02107/062200001/

https://ubuntu.com/security/esm
TouchesMovedで動かせるUIViewを作ろう

UIImageViewを例にすると、UIImageViewを継承したクラスを新しく作って、その中でtouchesMovedを書けばOK

```.swift
class TouchImageView: UIImageView {
    override init(image: UIImage?) {
        super.init(image: image)
        self.isUserInteractionEnabled = true
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        next?.touchesMoved(touches, with: event)
        let touch = touches.first!
        let prevPos = touch.previousLocation(in: self.superview)
        let nowPos = touch.location(in: self.superview)
        let diff = nowPos! - prevPos!
        self.layer.position += diff
    }
}

extension CGPoint: AdditiveArithmetic {
    public static func - (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
        return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
    }
    public static func + (lhs: CGPoint, rhs: CGPoint) -> CGPoint {
        return CGPoint(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
    }
    func toCGSize() -> CGSize {
        return CGSize(width: self.x, height: self.y)
    }
}
```
過去のコミットで間違ったファイルを追加、さらにいらない差分を含めてしまった時、私がやったこと

# 何が起こったか
1. ユニットテストを書いているブランチ（unit_test/hogeA_ViewController)とあるMVCからMVPにリファクタしているブランチ（mvp/hogeB_ViewController）に同じパスの同じ名前のファイル（以下ファイルパスを被ったファイル.swift）と mvp/hogeB_ViewControllerに要らない差分を含んだファイルが過去にコミットされているのをmvp/hogeB_ViewControllerで発見
```
// Source treeで発見

commit hash値: yarakashitacommit
new file: ファイルパスを被ったファイル.swift
modified: コミットしたくなかった差分を含んだファイル.swift
modified: コミットしたい差分を含んだファイル.swift
new file: コミットに入れたい新しいファイル.xib
```

# 具体的に何がしたい？

1. mvp/hogeB_ViewController上ではファイルパスを被ったファイル.swiftはいらない
→ なぜ？
unit_test/hogeA_ViewControllerのファイルパスを被ったファイル.swiftを採用したいから（=masterにマージしたい）
1.  mvp/hogeB_ViewController上でコミットyarakashitacommitにはコミットしたくなかった差分を含んだファイル.swiftの差分は今後一切要らない

-> **上記二つをコミットyarakashitacommitから除外したい**

# じゃあ何をしたの？

### コミットを一旦消して、いる差分、要らない差分をコミットし直した　＝　コミットをやり直した

-  やらかしたコミットをgit reset **--soft** yarakashitacommitした
```
git reset --soft yarakashitacommit
```

-  yarakashitacommitに含まれている新しいファイルは**削除**され、modifiedされているファイル（適切な日本語が思いつきませんでした）はただunstagedされ残る。
-  削除されたファイルの中でコミットに含めたいのはyarakashitacommitの一個前のコミットにチェックアウト
```
git checkout コミットに入れたい新しいファイル.xib yarakashitacommitの一個前のハッシュ値またはHEAD@{?}
```
-  git statusでコミットに含めたいファイルはあるか確かめる
-  不足していなかったらコミット



# 最後に

これでなんとかやりたいことは出来ました。ただこれでは本当に自分の残したい差分が残っているか怪しいし、これをやった後にunit_test/hogeA_ViewControllerとmvp/hogeB_ViewControllerをmasterにマージするときにファイルパスを被ったファイル.swiftが消えないか心配。`git reverse -i`で試したけども消したいファイルはreverse中に`git rm ファイル名.swift`すればいいが、そのファイルは残したいけど、該当のコミットに入っている差分は要らないというのは、`git rm`してしまうとそのファイルごと消えてしまうので今回は使えなかった。

### 誰かいいアイデアを持っていたらコメント欄に書いて欲しいです...
JP Contents Hubを上から実施する

せっかく日本語ハンズオンが一覧で置いてあるので時間があるときに上から実施していく

https://aws-samples.github.io/jp-contents-hub/#saas

- [Amazon QuickSight のセルフハンズオンキット日本語版その１](https://qiita.com/Yuki_BB3/items/740704b72c21e73dc971)
複数ディレクトリ一括作成

#### mkdir で複数のディレクトリを作るメモ

```
user/
　├ mysql/
　├ nginx/
　├ public/
　│　　　　├──scss/
　│  ├──images/
　└ hoge/
```

の場合user 直下で

```
mkdir -p mysql nginx public/scss public/images hoge
```

-p は親ディレクトリをなければ作成してくれるオプション
正規表現メモ

- 業務でちょっとした正規表現(半角英数字バリデーション)を書かないといけなかったので個人的メモです( preg_matchの中の一部抜粋 )

```
/^[a-zA-Z0-9]+$/
```
・先頭の「^」は文字列の初めからという意味
・[a-zA-Z0-9]に関しては> a~z、A~Z、0~9　の範囲
・「+」 は一回以上
・「$」 は文字列の最後まで

ちなみに「+」 のところは「*」にしてしまうと「0回以上」という意味になり空白文字を受けつけるので気をつけないとですね。
ブラウザキャッシュ更新 プラグインでbaserCMSのスタイル調整や画像差し替えなどをすぐに反映する

https://market.basercms.net/products/detail.php?product_id=149&category_id=1

サイト改修などで、スタイルシートを変更したり、画像を差し替えたりした際に、ブラウザキャッシュが原因で、なかなか表示が変わらず困ったことはありませんか？
クライアントに改修を依頼されて、変更分をリリースしたところ、クライアントから「変更されてません」という連絡をもらった経験のある方もいらっしゃるかと思います。
こういったトラブルを防ぐために、一般的によく使われているのが、「更新したcssや画像ファイルにクエリストリングを付ける」といった方法です。
具体的には
```<link rel="stylesheet" type="text/css" href="/css/style.css"/>```
を更新したときには
```<link rel="stylesheet" type="text/css" href="/css/style.css?20220930235602"/>```
といった形で、拡張子に後ろに```?｛好きな文字｝```をつけてブラウザに別のファイルとして認識させ、新たに読込直すようにする方法です。

ただし、ファイル数が多くなったり、更新のたびに毎回クエリ文字を付けるのも結構面倒です。

そこで、CMS側で一括でまとめてクエリ文字を付けてしまおうというのがこのプラグインです。

## プラグインの機能

* キャッシュを更新したいファイル（拡張子・ファイル名）の 登録機能
* クエリ文字の自動出力機能
* クエリ文字のアップデート
* 自動出力の停止

### 導入方法
[baserマーケット](https://market.basercms.net/products/detail.php?product_id=149&category_id=1)から、プラグインを入手（無料）し、圧縮を解凍して、
FTPソフトなどで、/app/Plugin/ にアップロードします。
baserCMSの管理画面「プラグイン一覧」より、BrowserCacheUpdate（ブラウザキャッシュ更新プラグイン）を有効化します。
左の管理メニューの「プラグイン」のドロップダウンメニューの中に「ブラウザキャッシュ更新設定」追加されるので、それをクリックすると設定画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/4a7a4a8e-1bb9-0ef7-428a-dab303491a36.png)

### 1、 キャッシュを更新したいファイル（拡張子・ファイル名）の 登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/0eaa9688-0881-aede-fd9f-7f6eb8674d9f.png)
##### 入力欄にキャッシュを更新したいファイルを入力します。
* 単一ファイルであれば、ファイル名を指定することも可能です。
* cssファイルすべてなど、拡張子で指定することも可能です。
* 複数指定する場合はカンマ区切りで入力します。

### 2、クエリ文字の自動出力機能
##### 「保存してクエリストリングをアップデートする」ボタンをクリックすると、クリックしたときの年月日時分秒がクエリストリングとして該当ファイルに付与されるようになります。

## 例）
```<img src="/img/test.png" alt="test">```　にて表示している画像を差し替えたとき

![画像1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/83315e2b-a57a-331d-574a-3dbadf1a0d87.jpeg)
このテスト画像を![画像差し替え01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/676ee52a-87a1-e608-7fa5-7993671facca.jpeg)
このようにリネームして差し替えても、ブラウザが古いtest.pngをキャッシュしてしまっているため、
**しばらくは元画像が表示され続けます。** 

### クエリ文字のアップデート
画像を差し替えた際に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/0a55e1c0-4c47-1dab-e0ae-21175e0223af.png)
このように指定して、「保存してクエリストリングをアップデートする」ボタンをクリックすると
```<img src="/img/test.png" alt="test">```　が　```<img src="/img/test.png?20221001001635" alt="test">```に変わります。
**その結果、すぐに新しい方の画像が表示されるようになります。**
![画像2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/cd343bee-c5d1-7aeb-7df1-c676311de1bb.jpeg)


:::note notice
「保存してクエリストリングをアップデートする」ボタンをクリックしたときの年月日時分秒を使用します。
一旦アクセスした後は、**新しい画像がキャッシュされた状態** となり、再読み込み時にはキャッシュから画像が表示されるため、画像ダウンロードが原因で表示が遅くなるのは最初の１回だけになります。
（「保存してクエリストリングをアップデートする」ボタンをクリックし直すと、新たなクエリに書き換わるため、また画像の再ダウンロードが発生します。）
:::

### 自動出力の停止

* プラグインを無効化する
* 管理画面入力欄の**値を空にして保存する**ことでも、クエリストリングの**出力を停止させることが可能**です。
![admin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553367/91b12dea-e344-0b10-aa79-6fb14cf8a1d6.jpeg)

## まとめ
頻繁に画像の差し替えやスタイルの調整が発生するサイトなどでは、とりあえずこのプラグインを入れておいて、
改修の前後だけ有効化して使用するといった使い方が便利なプラグインです。
また、css調整などの **クライアント確認** の際にもいちいち「テーマファイル」を書き直さなくて良いので重宝します。
独習プログラミングの備忘録　1　【変数と型】

～学んだこと～
・変数宣言で使用する8つの型
【整数型】
char, short, int, long
小       　　　→　　　大

【小数型】
float, double

【真偽値】
bool

【文字】
char

・修飾子 const
これをつけて変数宣言すると、上書きができなくなる。

～感想～
変数宣言はintとdoubleしか知らなかったため、残りの6つの習得に時間がかかりそうだ。
実際の現場では8つを使いこなさなければならないのだろうか。

また、void main と int main(void) の違いについても余力があれば調査していきたい。
データサイエンス道１~pandasでデータ操作(基本)~

こんにちは、るっちです。
今回はPythonのPandasを用いたデータ操作についての記事です。
※基本的な内容に絞り、グループ化等のやや複雑なところは書きませぬ。
# この記事のゴール
Pandasを使って
- データを取得
- 見たい情報だけを抜き出して確認

が出来るようになること。

# 目次
- Pandasとは 
- データの格納
  - read_csv()
- データの絞り込み
  - df[カラム名]
  - loc, iloc
- まとめ
# Pandasとは
pandasはデータの前処理を補助してくれるパッケージです。
また、pandasは外部ライブラリであるため使用にはインストールが必要です。
```
pip install pandas
```
# データの取得
CSVファイルからデータを取得する方法について解説します。
## read_csv()
データをCSVやExcelファイルから取り込みたい場合、read_csv()やread_excel()を使用します。
```python
df = pd.read_csv("./raw/data.csv", encoding="cp932")
```
第1引数に読み込みたいファイルのPATH。←必須
第2引数以降にはオプションを書きます。←無くてもよい。
今回は第2引数で文字コードを指定しています。

データの中身を確認すると、
```python
print(df)
```

# Out
```
	name	math   science	english
0	Taro	60	   55	    45
1	jiro	80	   90	    30
2	Ichiro	30	   35	    70
3	Yui	    80	   80	    80
4	Mari	10	   10	    90
5	Ryuji	50	   50	    50
6	Takuya	100	   100	    5
7	Tomoya	45	   30	    70
8	Toshi	10	   5	    100
9	Aoi	    30	   20	    65
10	Kenji	90	   90	    5
```
と表示され、データを取り出せていることが分かります。
※今回用に適当に用意したデータです。

また、インデックスにする列を指定することもできます。
```python
# index_con=カラム名でインデックスを指定する。
df = pd.read_csv("./raw/data.csv", index_col="name", encoding="cp932")
print(df)
```
# out
```
	    math science english
name			
Taro	60	  55     45
jiro	80 	  90	 30
Ichiro	30	  35	 70
Yui	    80	  80	 80
Mari	10	  10	 90
Ryuji	50	  50	 50
Takuya	100	  100	 5
Tomoya	45	  30	 70
Toshi	10	  5	     100
Aoi	    30	  20	 65
Kenji	90	  90     5
```

# データの絞り込み
読み込んだデータから、行や列を指定して取得する方法を解説します。
## df[カラム名]
読み込んだデータのカラム名を指定して取り出す方法です。
mathのデータを抽出してみます。
```python
# []内にカラム名を入力
df["math"]
```
もしくは、
```python
# カラムのリストを取得し、その一番目(math)を入力している。
df[df.columns[0]]
```
# out
```
name
Taro       60
jiro       80
Ichiro     30
Yui        80
Mari       10
Ryuji      50
Takuya    100
Tomoya     45
Toshi      10
Aoi        30
Kenji      90
```
mathのデータが抽出できていることが確認できました。
インデックスとしてnameも出力されています。
2つ目の記載方法は個人的によく使います。カラム名をいちいち書くのが面倒な時に使います。

## loc, iloc
接頭に"i"がつくと0以上の自然数を指定、つかないとラベル名(インデックス)(文字)を指定します。
```python
print(df.iloc[0:4])
```
# out
```
	    math  science  english
name			
Taro	60	  55	   45
jiro	80	  90	   30
Ichiro	30	  35	   70
Yui	    80	  80	   80
```
インデックス番号は0からであり、0から4行目の手前(Mariの手前)を抽出したことになります。
Pythonのスライス規則についてご存じであれば分かりやすい思います。
```python
df.loc["Ichiro":"Aoi"]
```
# out
```
	   math	 science  english
name			
Ichiro	30	   35	  70
Yui	    80	   80	  80
Mari	10	   10	  90
Ryuji	50	   50	  50
Takuya	100	   100	  5
Tomoya	45	   30	  70
Toshi	10	   5	  100
Aoi	    30	   20	  65
```
ことらも同様にスライスを用いていますが、指定したインデックスの始めと終わりまでを抽出します。
また、loc[]にインデックスのリストを入れると、該当インデックスのみを抽出することができます。
```python
df.loc[["Ichiro","Tomoya","Aoi"]]
```
# out
```
	  math  science  english
name			
Ichiro	30	  35	 70
Tomoya	45	  30	 70
Aoi	    30	  20	 65
```

# まとめ
以上が基礎的な内容でしたが、pandasの説明です。
１． read_csv()でデータを読み込み
２． 列の指定はdf[カラム名]
３． 行の指定はiloc, loc

次回からは、実際に統計的な話に入っていきたいと思います。
確率分布か、推定・検定か、回帰分析か、、、

## 参考文献
- 「データサイエンス教本」
今後の転職活動と学習方針について考えたい

こんばんは。

前回の退職エントリが思いのほかたくさんの人に読まれていて、驚いています。書いていた時は「きっと批判されるだろうな」と思っていたのに反して、励ましのお言葉やご意見など、温かいコメントをいただいていて、とても有難いなと思っています。

https://qiita.com/sowayaca/items/a24e56b052f7e06007f4

# 転職活動について
### 現状
転職活動の状況ですが、昨晩某転職サイトの登録情報を更新し、Qiitaのリンクを貼ったり、成果物を載せたりしていました。今朝見たら、これまた有難いことに、スカウトのDMや気になるをしてくださる企業様が想定よりも多く、また「SESでなりふり構わず（？）現場ガチャするぞ！」と意気込んでいたのですが、受託開発や自社開発系の求人の方が割合が高く、嬉しいことではあるのですが正直戸惑ってしまいました。

しかし、転職回数などを考えると、やはり私側に、課題というか、乗り越えなければならない問題があるのだと思います。退職届を書く度に、入社承諾書を書く度に、「今度こそ、最後にするぞ」って思っています。なのに、現実は平均して1年に一回のペースで転職を繰り返している。

もちろん、今回のように、会社側と認識が食い違って険悪な中での退職というのは珍しいというか、ちゃんと「これがやりたいな」と思って、行動し、結果的にそれが転職という形になった、ということの方が多いです。

IT業界では「書類選考無し！」みたいな求人が多々ありますが、私は自己応募でもスカウトでも、「転職回数の多さや退職の経緯などを踏まえて、『この人（私）は選考するに値するか』を再度検討お願いします」と、メッセージに入れています。それでも面談にお時間を割いてくださる企業様が在って、お声がけいただけるだけでも幸いな気持ちです。

### どのような企業、どのような仕事がしたいのか
転職サイトの「重視しているポイント」に、

**・風通しの良い社風、なるべくフラットに意見交換ができること**
**・リモートワークが可能であること、もしくは相談可能であること**

と記載しています。

正直、給与面のことはあまり気にしていないので、永く働けることを重視して、求人を探しています。また、リモートワークについては、時勢もありますが、働き方の選択肢として個人的に欲しいなと思う要素があります。

どのような仕事（案件）に就きたいか、については、幅広く考えています。
ただやはり　**「新しい技術を学べる、身につけられる」**　ような案件がいいなあとは思っています。

# やってみたいこと

### Pythonを使った画像分析や自然言語処理など
統計学や数学など、これまで学習してこなかったため、これまで手が出せずにいました。けれど、機械学習やAIなど、絶対楽しいじゃないですか…。
現職の方々からの「現場はそんなに楽しいものじゃないぞ」というお言葉が頭に入ってきますよ。それでも、業務外で個人でも使える、いじれる技術は欲しいなと思うのです。

### いわゆるフロント系
プログラマをしていた時は、HTML、CSS、JS、PHPを書いたり読んだりしていました。
PHPのフレームワークなんだったかな。Laravelやりたかったな…って当時考えていたので、古めのものだったと思います。MVCモデルで設計されているサイトの保守をしていましたが、MVCモデルももうだいぶ古いと言われてきていますね。ただやはりブランクこそあれ、一応古巣ではあるので親和性は高いのではないかと思っています。

### 教育分野でのプログラミング
スクラッチでもラズパイでも、プログラミングや各種技術を通して、子どもたちに創造性を持たせることは、これからの時代への貢献度が高い仕事ではないかと思っています。少し話が逸れますが、私はおそらく生涯家庭を持たないため、その分後輩育成や若い世代に見せられる背中を築きたいと考えています。

# 学習すること、したいこと

### ・Gitの使い方を今一度学習し直したい
エディタに自動でインデントを整えるパッケージを入れていたため、差分が分からなくなって叱られたりしました。（最近先輩エンジニアが「あるある」と笑っていました。）正直現場によって使われ方が違うと思うので、基本的なことを再確認する程度になるかと思いますが、必要なことだと考えています。

### ・SQL文やLinuxコマンドなど
長らく書いていないので、すっかり忘れてしまった。でも少し書けば思い出せるんじゃないかとも思います。

### ・世渡り上手になりたい・・・
「報連相が課題だよね」と現職場で指摘されたのですが、毎日定時前に直属の上司にその日の進捗と成果物を送っていました。ほとんど既読スルーでした。つらかったです。
でも、こういうことってこれからもきっとあると思うのです。「だからチャットじゃなくて口頭で」と言われたら口頭でソフトに伝える技術、相談や提案をどのようにどのようなタイミングで行うべきかなど、この機会に学習というか考え直したいなと思います。

### ・トレンドをさらう
あれもこれもと手を出しすぎると浅くなってしまうので取捨選択が必要ですが、今主流になっているフレームワークや今後期待されている技術などには積極的に噛み付いていきたいなと思います。

# 学習方法
### 動画での学習
Dockerなど、コンテナ型と呼ばれる実行環境がいまいちピンと来ないと親友（現役エンジニア）に相談したところ **「とりあえずUdemyでも見なさい」** と言われたので、セールしている時にコツコツ買い貯めていたコンテンツに従って勉強していこうかと考えています。その中には数学や統計学などもあるので時間はかかりますが視聴し、身につける価値は高いかと思います。

### MacBookAir(2020年モデル)で、環境構築からやってみる
M1チップがどこまで対応しているのか、確認したいといつかの記事に書いていたことを思い出しました。この間までようつべ以外の動画配信系全般ダメでしたね。Netflixがやっと対応したみたい。
それは置いておいて、開発環境として使えるのか？　
店員さんに「BootCampがね、駄目なんですよ」って言われてマジかってなりました。Appleって時々そういうことしますよね。このままM1チップに諸技術が対応していくのか、Appleが市場に負けてインテルに戻るか、五分五分なんじゃないかと予想しています。
でもやれるだけやってみたいなと思います。開発の良いところって、PCさえあれば自分で技術を試したり、いじれるところだと思っています。

-------
転職活動しながらの学習ってマルチタスクな感じがして大変そうですが、それでもやっていかないと、と思います。この業界にいる限り、学習し続けることは必要なことだし、幸いにも私は学習が好きです。（得意かどうかは別ですが。）

ポートフォリオを作るのも良いかもしれません。その時はまた記事にすると思います。今はまだ何をしようかなと想像を膨らませている状態なので。

技術的な面でもそうですが、私の考え方や業界のことなど、なんでも思うことあれば、ご指摘いただけますと幸いです。フィードバックは常に有り難く頂戴したく思います。

まずは生活を安定させろよって言われそう。
少しずつですが前に進んでいければと思います。

おしまい。
ansible スピードアップ他


# ssh接続
ansible.cfg
```
[ssh_connection]
pipelining = true
ssh_args = -o PreferredAuthentications=publickey -o ControlMaster=auto -o ControlPersist=60s
```

# 自宅(フレッツのコラボ回線)からVPSへのアクセス

/etc/ssh/ssh_confg  
```
GSSAPIAuthentication no
IPQoS none
```
Google Cloud の Backup and DRについて調べてみました

# はじめに
AWSでいうAWS Backup的な機能がリリースされました。

https://cloud.google.com/blog/ja/products/storage-data-transfer/introducing-google-cloud-backup-and-dr

AWSでは今やEC2運用で当たり前のようになっているこの機能なので、
それをGoogleで置き換えたものはどういったものなのか知ってもらいたいです。

# Backup and DR とは
詳細は以下でご覧いただきたいのですが、

https://cloud.google.com/backup-disaster-recovery?hl=ja

気になった特記事項としては以下です。
・一元管理が可能
　→他リージョンや他プロジェクトなど跨いでも復元やバックアップの取得が可能
・永久増分バックアップによるコスト削減
・アプリケーション整合性が担保されたバックアップによりデータベースなどの復元も可能で、
　最短15分単位の取得が可能
　→サポートされるデータベースやアプリケーションは制限があります

ネットワーク部分に特徴があると思っていて、たぶんこんなイメージでバックアップの取得が可能だと思われます。
![スクリーンショット 2022-09-30 23.57.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1720034/cf45842c-be4e-933d-3169-b95b93676f0b.png)
※点線がピアリングの線で直線がバックアップ取得の線になります

なので、おそらくマネージド・サービスをイメージするより、バックアップセグメントにバックアップサーバがあるイメージのほうが近いのかなと思いました。

図内のコンソール画面はこんな画面でした。
![スクリーンショット 2022-09-30 23.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1720034/007bcbae-3ef4-0551-c578-8bbe1b5c76f9.png)


# 所感
これからGCE構築上、必要になってきそうなので、検証進めていきたいと思います。
おそらく単一のバックアップではなく統合するときにパワー発揮するのでは？と感じました。
コンソール画面みたところ、昔自分がよく触ったBackupExecやArcServeなどのバックアップソフトを触っているような感覚で好きです。
Azure KMSサーバのFQDN・IPアドレスが変更される

Azure上にデプロイしたWindows VMはAzure環境にあるKMSサーバと通信をしてライセンス認証をおこなっていますが、このKMSサーバのFQDNおよびIPアドレスが変更されます。

# 影響がある環境
### 強制トンネリング環境
強制トンネリングとはデフォルトゲートウェイをオンプレミス側に向けて、インターネット宛の通信がAzureから直接出ていくのではなく、オンプレミス経由で出ていくように設定することです。AzureのKMSサーバはAzureから来た通信のみをライセンス認証する仕組みになっていますが、強制トンネリング環境では送信元がオンプレミスの出口のIPアドレスになってしまうため、ライセンス認証が拒否されます。この対処策として強制トンネリング環境ではユーザ定義ルート（UDR）を用いてKMSサーバ宛の通信はAzureから直接インターネットに出るように設定します。今回KMSサーバの宛先IPアドレスが変更されるため、ユーザ定義ルートの設定の追加が必要になります。

### Azure上のファイアウォールで通信制限している環境
今回KMSサーバのIPアドレスおよびFQDNが変更されるため、Azure上のファイアウォールでインターネット宛の通信を制御している場合、設定の変更が必要になる可能性があります。

# 変更内容
変更前のKMSサーバは「kms.core.windows.net（23.102.135.246）」でした。

2022年7月以降に新規にデプロイしたVMではKMSサーバの宛先が「azkms.core.windows.net」に設定されています。
それより以前にデプロイしているVMではKMSサーバが「kms.core.windows.net」に設定されています。自動的に「azkms.core.windows.net」へ置き換わることはありません。

影響を抑えるため、以下のように段階的に切り替えが行われる計画になっているようです。

### 2022年10月3日まで
|KMSサーバのFQDN| IPアドレス | 補足 |
|:-:|:-:|:-:|
| azkms.core.windows.net  | 23.102.135.246  | 移行措置としてkms.core.windows.netを指すようになっている  |
| kms.core.windows.net  | 23.102.135.246  |   |

### 2022年10月3日以降
|KMSサーバのFQDN| IPアドレス |
|:-:|:-:|
| azkms.core.windows.net  | 20.118.99.224 <br> 40.83.235.53  |  
| kms.core.windows.net  | 23.102.135.246  |  

また、2023年3月1日までにkms.core.windows.net は「23.102.135.246」ではなく 「20.118.99.224」を指すように変更されるようです。

# 何をすればよいのか
* 強制トンネリング環境では「20.118.99.224」と「40.83.235.53」宛の通信がインターネットに直接出るようにルートを追加します。
* ファイアウォールで制限している環境では「azkms.core.windows.net」、「20.118.99.224」、「40.83.235.53」宛の通信が許可されるように設定します。

# 対応しないとどうなる？
* 新規にデプロイするWindows VMのライセンス認証が失敗します。
* 既存のライセンス認証済みのWindows VMについても、180日以内に未ライセンス認証状態になってしまいます。KMSは180日に１回は再認証をしないといけない仕組みとなっているため、時間差でトラブルが発生します。

# 公式情報
* [Generally available: New KMS DNS in Azure Global Cloud](https://azure.microsoft.com/ja-jp/updates/new-kms-dns-in-azure-global-cloud/)
* [強制トンネリングを使用したライセンス認証の問題](https://learn.microsoft.com/ja-jp/troubleshoot/azure/virtual-machines/custom-routes-enable-kms-activation)
【Laravel】「数字入れたら文字数足りてるのにバリデーションエラーになるんだけど…」

# はじまり

人間さん「なになに、このフォームには顧客IDを入れると」
人間さん「1234っと」

:::note alert
顧客IDは10文字以内で入力してください
:::

人間さん「え、、4文字なのになんで」
人間さん「不具合かな？」

いぬ先生「ちょっと見てみようか」


# 原因

いぬ先生「状況分かったよ」

人間さん「どんなかんじ？」

```php
$rules = [
    'customer_id' => ['max:10', 'integer']
];
```

## integerが条件に含まれていたから

いぬ先生「今はこうなっているのだけど」
いぬ先生「Laravelではほかのバリデーションとの組み合わせで」
いぬ先生「確認方法が変化するルールがあって」
いぬ先生「今回のように指定ルールにintegerまたはnumericが含まれる場合、」
いぬ先生「maxは文字列長ではなくて、値として確認することになってる」

人間さん「つまりどういうこと？」

いぬ先生「今回だと10文字まで入力可ではなく、」
いぬ先生「1～10の数値が入力できるってこと」

人間さん「試してみるよ」
人間さん「確かに10だったら通ったけど、」
人間さん「11以降ははじかれたよ！」


# 対応策

人間さん「でもあれだな」
人間さん「意図は、10文字までかと整数であるかを確認したいんだけど…」

## 正規表現で解決する【regex】

いぬ先生「そしたら正規表現を使うのはどうだろう」

```php
$rules = [
    'customer_id' => ['max:10', 'regex:/^(0|[1-9]\d*)$/']
];
```

いぬ先生「これで10文字までかの条件を残しつつ、」
いぬ先生「正規表現で数字であるかを確認する」

人間さん「登録できた！」

## 桁範囲指定でもよい話【digits_between】

いぬ先生「いまさらだけど、要は10桁以内の数値だったらいいのかな？」

人間さん「そうそう」

いぬ先生「それならこれでもよかったのかも」

```php
$rules = [
    'customer_id' => 'digits_between:1,10'
];
```


## Laravel9 では最大桁数指定が使える【max_digits】

いぬ先生「新しく条件でmax_digitsなるものが追加されたようだよ」

```php
$rules = [
    'customer_id' => 'max_digits:10'
];
```

> ※日本語ドキュメント抜粋
> max_digits:value - Laravel 9.x バリデーション
> 整数フィールドが、最大値桁数以下であることをバリデートします。

いぬ先生「名称からして最大10桁までということが一目でわかっていいね」


# 参考文献
- [Laravelの「numeric」と「max」バリデーションのエラー。文字長と数量が変化して起こる - CROSS ACCELERATE](https://cross-accelerate-business-create.com/2021/01/03/laravel-numeric-max/)

- [Laravelの「max」ルール (sizeの処理を追ってみた) - tkfric’s blog](https://tkfric.hatenablog.com/entry/2019/03/07/200000)

- [Laravel 9.26 Released - Laravel News](https://laravel-news.com/laravel-9-26-0)

- Laravel 9.x バリデーション
https://readouble.com/laravel/9.x/ja/validation.html#rule-max
https://readouble.com/laravel/9.x/ja/validation.html#rule-size
https://readouble.com/laravel/9.x/ja/validation.html#rule-max-digits

- Laravel.com（英語）
https://laravel.com/docs/9.x/validation#rule-max
https://laravel.com/docs/9.x/validation#rule-size
https://laravel.com/docs/9.x/validation#rule-max-digits

- PHPフレームワーク Laravel Webアプリケーション開発 P131
djangoのDBにpostgresqlを設定する

# やりたいこと
djangoのチュートリアルをやりたい゛！！！！
デフォルトではsqliteを使う設定になっているが、後でデプロイするかも...という話があったので、postgresqlを使う設定に変えたい！
という感じの記事です。
やったことを備忘録的に記していきます。

# 環境
macです

## postgresqlのダウンロード

```
brew install postgresql
```
## psqlの各種設定
django経由で動かす前にテーブルを作ったり権限を変更したりする必要があるっぽい
ということで、
### サーバーの立ち上げ
```
brew services start postgresql
```
これでpsqlコマンドを打てるようになります

### ユーザ作成
```
$createuser -P hogehoge

//パスワード設定
Enter password for new role: ここで１回目入力後Enter
Enter it again: ここで２回目入力後Enter
```

### 権限変更 (新しくユーザーを作る場合)
superuserの権限を持っているユーザでログインして、
```
psql -U <superuser> postgres
```
以下のように権限を持たせたいアカウントに `SUPERUSER`と`CREATEDB`の権限を持たせてあげる
```SQL
ALTER ROLE <newuser> with SUPERUSER;
ALTER ROLE <newuser> with CREATEDB;
```

### データベース作成
先にデータベースを作っておこう (ownerは新しく作ったユーザーの想定)
```SQL
CREATE DATABASE hogetable -O <newuser>;
```

psqlの方はこれでOK！

## djangoの設定をいじる
`setting.py`を以下のようにいじってあげる
注意点としては、この際`'NAME'`は、`BASE_DIR`を取ってあげる(psqlがデータベースの名前から勝手に場所を探してくれる為)
```python
DATABASES = {
　    'default': {
　        'ENGINE': 'django.db.backends.postgresql_psycopg2',
　        'NAME': '<db_name>',
　        'USER': '<db_username>',
　        'PASSWORD': '<password>',
　        'HOST': '<db_hostname_or_ip>',#これはなくてもなんとかなる
　        'PORT': '<db_port>', #これはなくてもなんとかなる
　    }
　}
```

そして希望のmigrateきちゃーーーー！！！
```
python manage.py migrate
```

多分これでmigrateまでいけます　やったね
Lambda でコンテナを実行する

# イメージを作成する

以下のドキュメントを参考に Dockerfile を作成します。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html#images-create-from-base

```Dockerfile:Dockerfile
FROM public.ecr.aws/lambda/python:3.8

# Copy function code
COPY app.py ${LAMBDA_TASK_ROOT}

# Install the function's dependencies using file requirements.txt
# from your project folder.

COPY requirements.txt  .
RUN  pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.handler" ]
```

`LAMBDA_TASK_ROOT` を定義します。

```
export LAMBDA_TASK_ROOT=/var/task
```

`CMD` で指定している python スクリプトを作成します。トップレベルコードには**引数が 2 つ必要**です。

```python:app.py
import boto3
import matplotlib
import numpy as np
import matplotlib.pyplot as plt

def draw_image():
    # グラフを作成し、/tmp ディレクトリに保存する
    x = np.arange(-5, 5, 0.1)
    y = np.sin(x)
    plt.plot(x, y)
    image_file = '/tmp/sin_curve.png'
    plt.savefig(image_file)

    # アップロード先バケット、アップロード先オブジェクト名を指定する
    bucket = 'python-lambda-bucket'
    object_name = 'sin_curve.png'

    # ファイルをアップロードする
    client = boto3.client('s3')
    client.upload_file(image_file, bucket, object_name)

def handler(event, lambda_context):
    # Dockerfile で CMD ["app.handler"] と記述しているので、ここがトップレベルコード
    draw_image()
```

上記の matplotlib を使用したグラフの作成方法は以下を参考にしました。

https://aiacademy.jp/media/?p=154

依存パッケージ用に requirements.txt を作成します。

```requirements.txt
matplotlib
```

# ECR にイメージをプッシュする

以下を実行します。

```
# ECR にログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
# ビルド
docker build -t python-lambda-image .
# タグ付け
docker tag python-lambda-image:latest ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/python-lambda-image:latest
# イメージプッシュ
docker push ${ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/python-lambda-image:latest
```

# Lambda 関数を作成・実行する

関数のオプションはコンテナイメージを選択し、Lambda 関数を作成します。イメージをプッシュするごとに、以下の「新しいイメージをデプロイ」を行う必要があります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/049a6ced-96e5-6beb-54cd-da9ef5ea6af1.png)

作成後、「テスト」タブからテストを行い、指定した S3 バケットに画像ファイルが格納されることを確認します。

以下はテスト実行時のログになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/95b58814-04ca-954c-9517-2c5b8c3ff76d.png)

テスト実行後、以下のようにバケットにオブジェクトが格納されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/74d01eaf-986e-9489-3765-5ee9f90e6d52.png)


# 参考記事

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images-create.html#images-create-from-base

https://aiacademy.jp/media/?p=154
[Rustで簡単標準入力]proconio使い方まとめ

# proconioとは

Rustでの標準入力を簡単にしてくれるマクロです。
Atcoderでも使えるので、愛用させてもらってます。
自分が使い方を忘れるのでまとめて記事にしました。

## 導入
`cargo.toml`の`dependencies`に追記する

```shell:Cargo.toml
[dependencies]
proconio = "0.4.3"
```

## サンプル

```:入力:
hoge 3.0 8 
```
```rust
use proconio::input;

fn main() {
     input! {
        n: String,
        m: f32,
        l: i32,
    }
    println!("{} {} {}", n, m, l);
}
```

```:出力
hoge 3.0 8
```

## ポイント
`use proconio::input;`で使用を宣言

`input!{}`がproconioの機能

`変数名:型,`が基本形

## mutableで受け取る

```rust:抜粋
input! {
   a: f32,
   mut b: i32,
}
b += a;
```
前に`mut`を付ければOK!

## 配列

### n個の１次元配列を受け取る
```:入力:
4
1 2 6 8
```

```rust:抜粋
input! {
        n: u8,
        a:[i32;n],
    }

    println!("{:?}", a);
```

```:出力
1 2 6 8
```
### n * mの2次元配列を受け取る

```:入力:
3
3
5 2 1
6 2 8
2 5 2
```

```rust:抜粋
input! {
        n: u8,
        m: u8,
        a: [[i32; m]; n],
    }

    println!("{:?}", a);
```
```:出力
5 2 1
6 2 8
2 5 2
```

a: [[5, 2, 1], [6, 2, 8], [2, 5, 2]]となる。

### 文字列をVec\<char>で受け取る

```:入力:
qiita
```

```rust
use proconio::input;
use proconio::marker::Chars;

fn main() {
    input! {
        s: Chars,
    }
    println!("{:?}", s)
}
```
```:出力
['q', 'i', 'i', 't', 'a']
```
`use proconio::marker::Chars;`を追記する。

`変数名 : Chars,`で使用する。

文字列を入れ替える問題等、様々な場面で使える便利機能。

### 注意点

宣言した入力形式と、実際の入力形式が違うとエラーとなる。

```:i32で宣言したのに文字列をブチ込んだ例
thread 'main' panicked at 'failed to parse the input `h` to the value of type `i32`: ParseIntError
```

### 参考URL (超感謝(m(__)m)

https://docs.rs/proconio/latest/proconio/#macros

https://blog.ymgyt.io/entry/proconio_input_macro

https://qiita.com/koji-cw/items/0cce3b075faffe5e50ed

### 便利なのでぜひ使ってみてください！