OmniAICreator/Qiita-1.07M huggingface dataset:
【基本】チェックポイントの発生タイミングについて

## 目的
お客様向け勉強会を行う中で再度整理したいと思った部分をまとめます。

## 前提知識
![スクリーンショット (440).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/85609c30-3ad3-75d5-41d8-bf823200c1e3.png)
チェックポイントは以下の2つの意味を持っている。
https://docs.oracle.com/cd/F19136_01/cncpt/oracle-database-instance.html#GUID-A6959126-0ECF-40A2-880D-D74A1BFB5BC4
> ①**チェックポイント位置を示すデータ構造**。これは、インスタンス・リカバリを開始する必要があるREDOストリーム内のSCNです。
チェックポイント位置は、データベース・バッファ・キャッシュ内の最も古い使用済バッファによって決まります。チェックポイント位置は、REDOストリームへのポインタとして機能し、制御ファイル内と各データファイル・ヘッダー内に格納されます。
②**データベース・バッファ・キャッシュ内の変更済データベース・バッファのディスクへの書込み**





REDOログファイルへの書き込み（コミット）とデータファイルへの書き込み（チェックポイント）を非同期にすることによって、性能への影響を抑えてアプリケーションの快適な操作性を実現している。

## チェックポイントのタイミングについて

![スクリーンショット (441).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3072159/b8f5d84e-ee8d-6f52-d142-48e5aca6f709.png)

### 1. 明示的にチェックポイントを起こした時
ALTER SYSTEM CHECKPOINTコマンドで手動チェックポイントを発生させることができる
https://docs.oracle.com/cd/F19136_01/sqlrf/ALTER-SYSTEM.html#GUID-2C638517-D73A-41CA-9D8E-A62D1A0B7ADB
> ・ALTER SYSTEM CHECKPOINT GLOBAL
⇒Oracle Real Application Clusters (Oracle RAC)環境で、データベースをオープンしているすべてのインスタンスに対してチェックポイントを実行します。
・ALTER SYSTEM CHECKPOINT LOCAL
⇒Oracle RAC環境で、文を発行するインスタンスのREDOログ・ファイル・グループのスレッドに対してのみチェックポイントを実行します

他にも以下の初期化パラメータを利用してチェックポイントを起こす方法もある。

・LOG_CHECKPOINT_INTERVAL
https://docs.oracle.com/cd/F19136_01/refrn/LOG_CHECKPOINT_INTERVAL.html#GUID-2AD1BEC0-B768-4CD6-A630-9570F358C3DF
・LOG_CHECKPOINT_TIMEOUT
https://docs.oracle.com/cd/F19136_01/refrn/LOG_CHECKPOINT_TIMEOUT.html#GUID-2FB2D347-82B8-4F15-9B47-8F75E9383A79
・FAST_START_MTTR_TARGET
https://docs.oracle.com/cd/F19136_01/refrn/FAST_START_MTTR_TARGET.html

#### どんな時に明示的にチェックポイントを起こすのか？

メディア障害からのリカバリ・テストのように、データファイルへのアクセスを伴う動作検証を行う場合や、オンラインREDO ログ・ファイルのメンテナンスを行うときなどに、手動でチェックポイントを発生させることが考えられる。

また、推奨のREDOログスイッチ間隔は1時間に2回前後程度。checkpointが頻繁に発生する場合はREDOログファイルのグループ数を増やすかサイズを大きくすることで発生を抑えることを考えましょう。


### 2. ログスイッチのタイミング

現行のREDOログ・ファイル・グループが一杯になると、ログ・スイッチが自動的に発生する。

REDOログのメンテナンス操作を実行するために、ログ・スイッチを強制的に発生させて、現在アクティブなグループを非アクティブの状態に手動で変更することもできる。
具体的にはALTER SYSTEM SWITCH LOGFILEもしくはALTER SYSTEM ARCHIVE LOG CURRENTで行う。

指定した時間間隔でログ・スイッチを強制する ARCHIVE_LAG_TARGETという初期化パラメータも活用できる。
https://docs.oracle.com/cd/E82638_01/refrn/ARCHIVE_LAG_TARGET.html#GUID-405D335F-5549-4E02-AFB9-434A24465F0B

### 3. SHUTDOWN操作を行った時

ただし、SHUTDOWN ABORT時には、チェックポイントが発生しないまま、shutdown状態に移行する

### 4. オンラインバックアップを行った時
### 5. 表領域が読み取り専用に変更された・表領域がオフラインにされた時
ProjectSettingsなどをエディタ拡張で操作するときの注意

unityでプロジェクト全体を操作するとき、エディタ拡張を入れておいて、それでホイホイいじることは多いと思う。
例えば

~~~C#:sample.cs
PlayerSettings.Android.keyaliasName=LocalKeyAliasName ;
~~~

なんて具合だ。
これ、大変に便利なモノで、僕は多用していたのだけど、大事な注意が一つあることを知ったのでメモ書きとして残しておきたい。
その注意とは該当のメニューが開かれていると、 **テキストボックスはstringを書き込んでも、書き込まれない。メニュー上のテキストボックスの内容が優先され、stringは書き込まれるが変数は更新されない。**
しかもタチが悪いことに

```C#:sample2.cs
if (PlayerSettings.Android.keystorePass!=WritePass ) {
	Debug.LogWarning("Project Settingが開かれている！");
}
```

こんな感じで警告しようにも、この変数が上書きされるのは、なーんとエディタ拡張が走り終わったあとなもので、警告すら出来ない。

実はProject Setting がインスペクタの裏に開かれていて気がつかず、これでハマって、えらい目にあわされたので、みなさまに共有しておきたいと思うのである。
[エンジニア向けに要約]SEO対策・超入門2023

# SEO対策超入門2023

エンジニアとして身に付けておきたい点を抽出しました。

## SEO対策を行う上で意識する5点

- Googleがページの存在や構成を認識しやすいようにサイトを作成すること
- Googleがページ内容を理解しやすいようにソースを記述すること
- Webサイトの訪問者の利便性を第一に考えてコンテンツを作成すること
- 他サイトのコピーではなく、独自の情報を提供すること
- Googleや訪問者を欺くような小細工で順位を上げようとした場合はペナルティを課す

# 実践編
## サイト設計
### 内部対策
- 内部リンクの最適化
サイト設計に基づき、第一階層から第二階層、第三階層へと上から下に張り巡らす
- titleタグの最適化[最も重要]
googleに対してキーワードでの上位表示を希望する旨を伝えることができる
- meta descriptionの最適化[必須]
descriptionに記載した文章は検索結果のスニペットとして表示される
```jsx
<meta name='description' content='これはqiita記事です。'>
```
また、似たものでmeta keywordの設定ができる
```jsx
<meta name='Keywords' content='サイト,qiita記事'>
```
昨今ほぼ意味のないものとされている。。。
- 見出し(h1, h2, h3…)の最適化
見出しをこまめに使うことでページの構成をGoogleに伝える
中でも重要なのはh1タグでtitleと同じくらい重要
- XMLサイトマップを設置、送信する[必須]
（ドメイン名）/sitemap.xmlに設置し、このURLをSearch Consoleに送信する。
すると正式にGoogleに対してサイトの構造を把握してもらえる
ページ構成が変更されるたびにやるべき作業
- キーワードの詰め込みは厳禁
ペナルティにつながる恐れがある
### できればやりたい内部対策
- 画像のalt要素を適切に使用する
alt要素は本来、何らかの理由により画像が表示できない場合に画像の代わりに表示される文字列
- パンくずリストの設置
    - ページ数が多いサイトの場合は、現在との階層のページにいるのか示す機能を追加する必要がある
- ファイルの読み込み速度を意識する
    - 最近は読み込み速度を重視される傾向がある

## 上位表示するまでにかかる月数
新規記事がアップロードして検索エンジンにインデックスされたから、1~3ヶ月ほどの時間をかけてページの持つ本来の順位が確定する傾向にある
キーワードの難易度（競合の多さや強さ）が低ければ1ヶ月でも上位表示されるが、難しければ3ヶ月程度要する
## 順位が定まってからの順位変動について
- クリック率
    - 検索結果に表示された回数の内クリックされる確率
- ページ滞在時間
    - ユーザーのページに滞在した時間
- 直帰率
    - ユーザがサイト内の他のページに移動せずに検索画面に直帰してしまう確率
- ページ内容の陳腐化
    - コンテンツが時間の経過とともに古くなると順位が下がる
## キーワードについて
キーワードはニーズの塊である
- Googleは巨大なQ&Aシステムであり、Qを投げかけるユーザーに用いられるのがキーワード
- 検索者の疑問・問題（Q)が凝縮されたもの
### キーワードの種類
- ビックキーワード
    - 検索語句が1語
    - ex) SEO
- ミドルキーワード
    - 検索語句が2語
    - ex) SEO やり方
- スモールキーワード
    - 検索語句が3語
    - ex) SEO やり方 被リンク
## 上記の概念とは違うトレンドキーワードについて
突如として検索ニーズが伸びるキーワードのこと
新しいニュース、新商品、新しい概念や観念などが生まれた時に生じるもの
twitterのトレンドやyahooのリアルタイム検索などが参考になる

# 参考書籍
[SEO対策・超入門2023【Googleコアアップデート対応】初心者に必要な基礎知識、内部対策、Googleアップデート対策、コンテンツ作成方法までWebマーケティングのプロが網羅解説！ 1日速習シリーズ Kindle版](https://amzn.to/3HnDmgp)

### 参照
**[Google 検索の基本事項](https://developers.google.com/search/docs/essentials?hl=ja&visit_id=638183412354925713-3591883862&rd=1)**
## サイト所有者が行うこと
- サイト設計
    - 以下の二つの基準で検索順位を決めている。
    - Googleのクローラーがサイト内を巡回しやすいクローラビリティが高いこと
    - ユーザーがスムーズに知りたい情報にたどり着けるサイトであるユーザビリティが高いこと
- コンテンツ作成
    - 他のサイトよりも充実していることや情報に独自性があること
    - 充実したコンテンツが多いとサイト自体の評価が高くなる（「ドメインパワーが強いサイト」と呼ぶ）
- 被リンク獲得
    - 被リンクとは外部のサイトから自サイトに向けられたリンクのこと
    - 被リンクの質と量が豊富かどうかも問われる
        - サイトの内容が充実していると自然に他の外部サイトやSNS等でリンクが貼られることになるため
    - しかし、意図的に増やすなどの小細工はペナルティの対象になる（SEOの歴史の関係でかなり厳しく監視している。）
Ruby AtCoder向けVSCode設定 __debug__(ruby 3.2版)

# はじめに
以前投稿しました、Ruby AtCoder向けVSCode設定は**ruby 2.7版**でした。

https://qiita.com/superrino130/items/947a7cab222b7439002c

しかし、**ruby 3.0以降** ですと、``debase``のインストールに失敗することが分かっています。

```
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x64-mingw32]

An error occurred while installing debase (0.2.4.1), and Bundler cannot
continue.
```

そこで、Atcoder のアップデート予定版である、``ruby 3.2``でdebug環境の構築に取り組みます。
# 構築順
https://qiita.com/hopitaf/items/95efdf6b654308e1f646

すでに、記事が投稿されていますので、そちらも参照願います。

ちなみに、私の環境は次の通りです。
```
Microsoft Windows [Version 10.0.19045.2846]
(c) Microsoft Corporation. All rights reserved.

C:\Users\user>ruby -v
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt]

C:\Users\user>gem list
debug (1.7.2)
```
``VSCode``に拡張機能``VSCode rdbg Ruby Debugger``がインストールされた状態（launch.jsonが作成されていない！）で、``F5キー``を押下しますと、デバッグ実行されます。

![20230429a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/55b0b0ad-eda5-5315-c181-7ea1c96114b0.png)
## 補足
初めは``scoop``内に``ruby``をインストールしていたのですが、``debug``が上手くインストールされなかったので、``RubyInstaller for Windows``を使用しています。
# VSCode launch.json 設定例
テキストファイルから、入力を受け取るように修正します。
```launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "rdbg",
            "name": "Debug current file with rdbg",
            "request": "launch",
            "script": "${file}",
            "args": [
                "input.txt"
            ],
            "askParameters": false,
            "useTerminal": true
        },
        {
            "type": "rdbg",
            "name": "Attach with rdbg",
            "request": "attach"
        }
    ]
}
```
![20230429b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538241/be49e097-d9b7-5e00-34d1-4e1556cccc66.png)

(σ・∀・)σ gets!!
# まとめ
+ Windows10 の VSCode の Ruby 3.2 でデバッグができるようになった
+ AtCoder様、言語アップデートの受け入れ準備はOKです
IfcOpenShellで階情報を取得する

:::note info
筆者は職業プログラマーではないためおかしな記述が多々あると思いますがご容赦ください。
:::

# 対象
Pythonのごく初歩的な知識があること。

# この記事でできること
IFCデータ内に含まれる階情報（階名称、レベル）を取得する

# 環境
- Python 3.10.6
- ifcopenshell 0.7.0
- ifcファイルは2x3を使用
    - 今回は[Solibriのサンプルファイル](https://solibrisupport.graphisoft.co.jp/2019/09/25/solibri-ifc-file/)（Solibriビル.ifc）を使用

# 下準備
ターミナルから `pip install ifcopenshell`等でIfcOpenShellライブラリをインストールしておく

# コード
```python:IfcStoreyAnalyze.py
import ifcopenshell

ifc_file_name = "Solibriビル.ifc"
ifc = ifcopenshell.open(ifc_file_name)

storeys = ifc.by_type("IFCBUILDINGSTOREY")

for storey in storeys:
    print(storey.Name+" : "+str(storey.Elevation))
```

```:実行結果
Ground floor : 0.0
First floor : 3700.0
Second floor : 6750.0
Roof : 9800.0
```

# 解説
```python
import ifcopenshell

ifc_file_name = "Solibriビル.ifc"
ifc = ifcopenshell.open(ifc_file_name)
```
ここでifcファイルを読み込んでいる。

```python
storeys = ifc.by_type("IFCBUILDINGSTOREY")
```
タイプが`IFCBUILDINGSTORY`の要素、つまり階情報を取得して変数`storeys`に代入。
階情報は1階ごとにstoreys[0],storeys[1]...に代入される。

```python
for storey in storeys:
    print(storey.Name+" : "+str(storey.Elevation))
```
1階ずつ<階名称> : <レベル>を表示する。

# ちなみに
```python
print(storeys[0])
```
とやると
```:実行結果
#101=IfcBuildingStorey('2r6a0oqyj4yPPPei42ibMm',#15,'Ground floor',$,$,#99,$,'Ground floor',.ELEMENT.,0.)
```
と表示される。
表示された値から階名称が3番目、レベルが10番目にあることが推測できる。
<階名称> : <レベル>を表示するときは、

```python
for storey in storeys:
    print(storey[2]+" : "+str(storey[9]))
```
としても良い。（どうやら何番目にどの情報が来るかはIFCの仕様として定義されているみたい）
ただ、いちいち仕様を調べるのも面倒だしコードの可読性が低くなるので、`.Name`,`.Elevation`とやったほうが良いと思う。

`.Name`の部分に何を指定したら良いかは`.get_info()`で調べることができる。

```python
print(storeys[0].get_info())
```
```:実行結果
{'id': 101, 'type': 'IfcBuildingStorey', 'GlobalId': '2r6a0oqyj4yPPPei42ibMm', 
'OwnerHistory': #15=IfcOwnerHistory(#10,#14,$,.ADDED.,$,$,$,1350476845),
'Name': 'Ground floor', 'Description': None, 
'ObjectType': None, 'ObjectPlacement': #99=IfcLocalPlacement(#84,#98),
'Representation': None, 'LongName': 'Ground floor',
'CompositionType': 'ELEMENT', 'Elevation': 0.0}
```
例えばグローバルIDを知りたいときは`.GlobalId`で取得できることがわかる。

# おわりに
意外に日本語で解説された記事が見当たらなかったので素人なりに書いてみました。
ここから参照フロアを変更する方法やフロアを削除する方法を書いていければと思っています。
Flutterで使いたい表現

Flutterで、使いたいと思いつつ、忘れて普通に記載してしまう表現のメモです。
次から自然に使えるようになりますように。

## cascade

インスタンスの変数を何度も記載しなくても「..」で繋げて記載できる。

普通に記載した場合

```dart
UserState userState = UserState();
    ///UserStateに保存
    userState.listId = listId;
    userState.user = user;
    userState.nickName = nickName;
```

cascadeを使うと・・・すっきり！（userState. と何度も書かなくて良い。）

```dart
    ///UserStateに保存
    UserState userState = UserState()
      ..listId = listId
      ..user = user
      ..nickName = nickName;
```



## ??

nullかどうかチェックして、nullの場合、nullでない場合、で値を切り替えることができる。

普通に記載した場合（三項演算子）

```dart
///notnullValueがnullでない場合に、notnullValueを、nullの場合nullValueをセットする
    String value2 = notnullValue != null ? notnullValue : nullValue;
```

??を使うと

```dart
///notnullValueがnullでない場合に、notnullValueを、nullの場合nullValueをセットする
    String value = notnullValue ?? nullValue;
```


### 参考にさせていただいたサイト
https://qiita.com/ryuseikurata/items/978deffbc5966a3ccb15

https://www.choge-blog.com/programming/dartwhatistwoquestionmark/
【焦らなくていい】iPhoneがロックアウトになってしまった時の対応方法

最近、iPhoneは使用できません。解除まで◯◯分というメッセージがホーム画面が表示され、ロックアウトする事象が発生しました。

iPhoneのパスコードを連続で間違えるとロックアウトになり一定時間操作ができなくなります。
パスコード入力連続間違い回数をカウントし、
・6回なら1分
・10回なら60分
というように、間違えた回数に対してロックアウトする時間が長くなるというのがiPhoneの仕様のようです。
参考①：https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwi_zrDH9c7-AhXCqlYBHWJrB-wQFnoECA8QAw&url=https%3A%2F%2Fprtimes.jp%2Fmain%2Fhtml%2Frd%2Fp%2F000000224.000035551.html&usg=AOvVaw2ugJ9WrIy1tnKdxYKeEtr5
参考②：https://support.apple.com/ja-jp/HT212951

私の場合、60分のロックアウトが発生しました。
パスコードは間違ったことがないので、
* 不正アクセス
* アップデートによる端末不具合
上記に該当するか調べていたのですが、心当たりがなく原因がわからず…
ひたすら1時間を待ちました。

1時間後、ロックアウトが解除され、
再度パスコード入力し、正しいぱすこーどを入れたら解除され、戻りました。

1時間でロックアウト画面から抜け、再度パスコードを1度間違えても問題は発生しませんでした。
（よく、曖昧なサイトの記載を見るのですが、連続間違い回数でカウントされるようです。）

さらに原因を見たところ、、

<h1><b><i><u>bluetoothのキーボードが自動接続になっていたため。
でした！！ー！！！！！</h1></b></i></u>

どうやら歩いている時にbluetooth接続のキーボードと接触して解除しようとしてたようです。
対策は、以下をすると再発を防げるので、いったんは以下をしています。
* bluetooth設定をOFFにする。
* SiriとかもOFFにしておく
* デバイスのロック画面時にタッチ操作OFFにする
* ロックアウト解除失敗時にも対応できるよう、iTunesでバックアップを定期的に取得する

ちなみにロックアウト後、再度パスコードを間違えると、ロック解除できずデータ初期化しないといけません。
他にも復旧できる方法はあります。
https://support.apple.com/ja-jp/HT204306

ただ、上記の場合は、バックアップやリカバリ対策が前提です。
私の場合は特にバックアップもしていない状況だったので、
ロックアウト後に失敗したら危なかったです。
なので、iTunesに定期的にバックアップしようと思います。
【React】useStateの値が更新されない原因と解消方法

いまいち仕組みが理解できておらず、実際使ってみてつまずいた中で少し理解が深まったので、備忘録として残しておきます。

## 追記
少し調べてこの記事のような結論に至りましたが、内容が不足している部分や不正確な部分があります。
詳しく、またわかりやすく解説してくださっている記事があるので、ステートが更新されないことで悩まれている方はこちらの記事を読むことをお勧めします！

https://qiita.com/honey32/items/ee8d1577e68b0d58678d


## useStateとは
ページの構成要素であるコンポーネントの状態を管理するReactフックの一つ。
useStateは以下の2つの構成要素で成り立っています。
* 現在の状態を表す変数
* その変数を更新するための関数

基本構文
```.jsx
const [状態変数, 変数を更新する関数] = useState(初期値)
```

## 値が更新されないコード
```.jsx
export default function Map() {
    const [showSentence, setShowSentence] = useState(false);

    const onClick = () => {
    showSentence ? setShowSentence(false) : setShowSentence(true);
    console.log(showSentence)
  };
```
指定のコンポーネントをクリックして、コンソールに出力された値は「false」でした。

## 更新されない原因
値が更新されないのは、状態が更新されるのは関数が呼び出された後だからでした。
関数の呼び出し後、コンポーネントには無事更新後の値が渡されています。

## 更新された値を表示する方法

https://zenn.dev/syu/articles/3c4aa813b57b8c

この記事を参考にさせていただきました。

公式ドキュメント

https://react.dev/learn/state-a-components-memory
PlatformIOで`collect2: error: ld returned 1 exit status`エラー


新しくコードをためそうと思い、もともと書いていたコードを`tmp.main.cpp`に逃してmain.cppを作成して試したところ以下のエラーになりました。

> `collect2: error: ld returned 1 exit status`
> `*** [.pio/build/m5stack-atom/firmware.elf] Error 1`

> ![スクリーンショット 2023-04-29 15.07.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/6c9b0cb5-b072-6f79-0b42-007fdb2a087a.png "スクリーンショット 2023-04-29 15.07.47.png")

こちらの記事が参考になりましたが、記事によると同じフォルダにファイルがあるのがよくない模様です。

https://qiita.com/KatsuShun89/items/ec342678c5c802ccf52c


確かにこんな感じでファイルが置いてありました。

> ![スクリーンショット 2023-04-29 15.06.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a852ff08-4dd7-e1fc-6203-4e4df40994bd.png "スクリーンショット 2023-04-29 15.06.30.png")


`tmp.main.cpp`ファイルを消してsrcフォルダに`main.cpp`ファイルだけを置く形にしたところうまくいきました。
Ubuntu 22.04LTSにdockerをインストールするメモ

Ubuntu 22.04LTSにdockerをインストールするメモ
最低限必要なコマンドのみ

# Install

```bash
sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
```

```bash
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```



バージョンの確認
```bash
sudo docker -v
```


# sudoをつけなくてもdockerコマンド使えるようにする


```bash
getent group | grep docker
sudo usermod -aG docker $USER
getent group | grep docker
```


# 動作確認

```bash
docker run hello-world
```


















# 参考

https://qiita.com/yoshiyasu1111/items/17d9d928ceebb1f1d26d
【あっという間】エンジニア一年目　4月まとめ

## 自己紹介
こんにちは！
私は2023年の4月から社会人になったるんるんです！
人生の夏休みとも言われる大学４年間を終え、ついに自律を求められるようになりました、、

私は文系の学部(しかも文学部)を卒業しており、情報系の勉強は独学でやっており、基礎的なこともあまり理解できてない状態での社会人生活をスタートしました。

4月から就職した会社は、Web系ベンチャー（？）であり、バックエンドを担当するエンジニアとしてジョインしました。
実は去年の４月に内定をもらっており、私の希望で6月からアルバイトとして一足先に仕事をしていました（ユニットテスト作成や簡単なリファクタリングなど）。

## 4月の目標
### 仕事
#### とりあえず社会人に順応
大学生の頃は悠々自適な人生を送りすぎたため、律するためにも社会人に順応することが必要と感じた。

完全にリモートで(在宅でも出社しても良いルールだが、そうなると完全リモートとなる)で、裁量労働制(フレックスでもないし、コアタイムもない)への順応(？)が必要←十分悠々自適

### 個人活動
#### インフラの基礎知識をつける
製品のコードなどは何となく読めるが、インフラの基礎知識が壊滅的。。
インフラの知識がないエンジニアは非力なまま終わってしまうので急務

### プライベート
#### まさかまさかの引越し作業
社会人生活1ヶ月も経たない中で、引越し作業をすることに。（配属が地方になったとかではなく、家族の事情で実家から出ることに）
無事引越し作業を終えたい。

## 4月にやったこと
### 研修
多分他の会社と比べて圧倒的に少ないと思います。
1年目だと最初の３ヶ月は研修みたいな会社もあるかもしれないが、ほぼほぼ研修なしで実務に入るという形でした。
こればっかりは好き嫌いが分かれそうですが、私的にはすごく好みでした！
何かこう働いている感が欲しいというか、実務でいろんなことを学びたい派だったので自分には合っていました。
（~~あと普通に社会人研修は眠くなる~~）

### 会社全体ミーティングの運営担当
まさかの同期で唯一で会社全体ミーティングの運営担当に抜擢される。（半年間）
不慣れなことばかりだが、普段コミュニケーションを取らない方々（営業担当やマーケティング担当）と一緒に仕事できるのは新鮮でよかった

### Issue
（ここはあまり詳細に書けない）
- **GitHub Actionsの整備**
- **製品のhotfix**
    - パッチアップデート
    - マイナーアップデートのひとつのバックエンドを担当

分からないことばかりだったが、いつでも聞けるような環境なので、何とかこなせた

## 個人活動
### Qiita
4月からエンジニア活動をまとめておこうということで、この記事を書いた。
あとで見返した時に何か感じるものがある（はず）
また、これからエンジニアになる人の参考になったら良いなと思っています。

### 『Webを支える技術』
Webサービスを開発する会社なので、その設計の勉強になる本。
HTTPメソッドやステータスコードなどの基礎知識から、リソースの設計など実務に近いところまで、大変学びのある著でした。
皆さんもぜひ
[『Webを支える技術』](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%EF%BC%8CURI%EF%BC%8CHTML%EF%BC%8C%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus-ebook/dp/B07JK7FZH2/ref=sr_1_1?adgrpid=102912038115&hvadid=651192011668&hvdev=c&hvlocphy=1009274&hvnetw=g&hvqmt=e&hvrand=10804193040901665203&hvtargid=kwd-394859824714&hydadcr=21894_13456357&jp-ad-ap=0&keywords=web+%E3%82%92+%E6%94%AF%E3%81%88%E3%82%8B+%E6%8A%80%E8%A1%93&qid=1682747261&sr=8-1)


## プライベート
### 引越し作業
実家からついに脱却。。。（正直まだ実家にいたい）
初めての引越し作業なので戸惑うことだらけ。（物件選びや審査、ネットワーク整備、ライフライン、保険、家具、スケジューリング、搬入、etc）
正直社会人1年目４月にやることじゃない。

プライベートはほぼ引越し作業に費やした。
（たまに地元の友達と飲みに行ったり、地方に配属された大学の友達と飲みに行ったりした）

## 一ヶ月過ごしてみて
### あっという間
4月が一瞬で過ぎ去っていった。
こうして人は死んでいくのか。。

### 順応
冗談はさておき、とにかく順応するために必死だった。
これは「社会人への順応」が意味合いとしては大きい。
慣れることで仕事の生産性向上に繋がるので急務であった。

### 運動
リモートワークなので運動不足になりがち。
そこで私が行った工夫をつらつらと
- 散歩
    - 昼休憩の時に10~15分ほど陽を浴びる
    - これだけでも十分に効果があるらしい
- 立ちながら作業
    - ディスプレイがいらない作業の時は立ちながら作業していた
    - ずっと座りっぱなしで一日過ごすと早死にするらしい。。


## 足りないこと
### 個人活動がQiitaと読書しかできなかった。
何か個人開発なども取り組みたかったが、仕事と引越し作業が忙しくてできなかった。
５月の中旬ごろに引越しが終わる（予定）なので、落ち着いたら何かに取り組みたい。

__スムーズに取り組めるようにやりたいことをリストアップしておく必要がある__

### 筋トレ
筋肉の衰えがひどい。。

## 五月の目標
### 仕事
Issueでは細々とした仕事を振られているので、早いスパンで回していきたい。
また製品修正から、追加開発や新規開発などにも参加できるようになりたい。

### 個人活動
#### ネットワーク、サーバーの理解
それ用の本を購入したので（来月掲載します）、その本を読み込んで、弱点であるインフラの理解を深めていきたい

#### 個人開発
５月中旬までにどういうものを開発したいのかを検討しておく。
決まり次第、要件定義、仕様検討していきたい。

### プライベート
#### 引越し作業を無事終える
無事引越し作業を終えたい。
あと新居に順応する←こればっかり

#### 筋トレをする!!!!
絶対！絶対！たぶん絶対！!!

#### ５月病にならない
あんまりこの言葉の真意を理解してないけど、５月といえば感があるのでとりあえず書いたといた
【基礎学習/AWS】IAMの「信頼されたエンティティ」に設定されているポリシーについて理解する。

# 今回の課題
`IAM`>`ロール`>`信頼関係`の`信頼関係`タブの`信頼されたエンティティ`のポリシーが、どういった権限を許可しているのか理解してみる。

今回は以下の画像の、
`AWSServiceRoleForRDS`ロールの`信頼されたエンティティ`を見てみる。


![eaa5bf308b4a189160c877865b92d08e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/e8fc2cdb-2d46-005b-7eb7-16121bab0e2a.png)


信頼されたエンティティのポリシーは、以下のように記述されている。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "rds.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

# 結論
`信頼されたエンティティ`に記載されているポリシーでは、以下の設定が行われていることがわかった。

**<font color="red">`sts:AssumeRole`というアクションを使用して、
`AWSServiceFoleForRDS`ロールの権限を、
必要な時に一時的にRDS(`rds.amazonaws.com`)が使うことができるように設定されている。<font>**

## 一つ一つ分解して理解する
### 信頼されたエンティティとは
IAMで作成したロールはユーザーだけではなくAWSリソースにも付与することができるが、
付与可能なAWSリソースを指定しておくためのものが、`信頼されたエンティティ`。
`信頼されたエンティティ`に記載されていないリソースには、ロールをアタッチすることはできない。

※ロールを作成するときに、AWSリソースやAWSアカウントを設定するが、そこで選択したサービスが`信頼されたエンティティ`の`Principal`に記載される。

### AWS STSとは？
AWS Security Token Serviceの略称で、一時的な認証情報を発行する機能のこと。
以下の3つの認証情報が発行される。
* アクセスキー
* シークレットキー
* セッショントークン

一時的な認証情報は、AWSリソースへのアクションをより安全に制御するのに便利。

### AssumeRoleとは？
AWS STSのサービスの機能の一つ。
ある特定のIAMロールに付与された権限を、別のAWSアカウントサービスやIAMユーザーといった別のエンティティに対して委譲することができる権限。
一時的に権限を移譲するので、セキュリティを確保しながら必要なリソースへのアクセスを許可することができる。





#### 参考記事

https://zenn.dev/frusciante/articles/28cd351fe9de60

https://dev.classmethod.jp/articles/sts-temporality-credential/

https://qiita.com/yuta-katayama-23/items/7055c1a2e5a9cddf7a76

https://qiita.com/yuta-katayama-23/items/7055c1a2e5a9cddf7a76
ゼロからEntityComponentSystemを書いてみる 2

前回はこんなコードを書きました。
```rust:main.rs
fn main() {
    
    // idは配列の要素数を表す
    let id = 2;

    let pos_ary = [(0, 0), (0, 0)];

    for i in 0..id  {
        println!("{}: {:?}", i, pos_ary[i])
    }
}
```

このコードには問題があります。
それは、idが配列の要素数を超えた値のときに実行時エラーになってしまうこと。
つぎに、配列の要素数が固定で、要素を増やせないこと。

この問題に対処しようと思います。
そこで、create_entityという関数を書いてみました。

```rust:main.rs
fn main() {
    
    // idは配列の要素数を表す
    let mut id = 0;

    // 配列をやめて、ベクタで宣言する
    let mut pos_ary: Vec<(i32, i32)> = vec![];

    // 効果を確かめるために、10回 create_entity を呼び出す
    for i in 0..10 {
        create_entity(&mut id, &mut pos_ary);
    }

    for i in 0..id  {
        println!("{}: {:?}", i, pos_ary[i])
    }
}

// idを増やして、配列に要素を追加する
fn create_entity(id: &mut usize, ary: &mut Vec<(i32, i32)>){
    *id += 1;
    ary.push((0, 0));
}
```

このようにすることで、idと配列の要素数を一致させることができました。

ただ、まだ問題があります。
pos_aryの要素がすべて(0, 0)になってしまうこと。
次回は、これを解決したいと思います。
ストワで始めるLua第6回偵察レーダーのコード

新レーダーで単純な偵察レーダーを作りました。
動画はこちら

https://www.nicovideo.jp/watch/sm42148535

https://www.nicovideo.jp/watch/sm42148522

```lua:search_radar.lua
pi=math.pi
pi2=pi*2
sin=math.sin
cos=math.cos
data={}
--delete frame
removeFrame=property.getNumber("remove frame")

function onTick()


	angle=input.getNumber(4)*pi2 --radar rotation
	range=input.getNumber(8) --display range
    --radar data {distance, azimuth , elevation, frame}
	for i=0,7 do
		if input.getBool(i+1) then
			table.insert(data,{input.getNumber(i*4+1),input.getNumber(i*4+2)*pi2,input.getNumber(i*4+3)*pi2,removeFrame})
		end
	end

    --remove echo
	for i=#data,1,-1 do
		data[i][4]=data[i][4]-1
		if data[i][4]<=0 then
			table.remove(data,i)
		end
	end
end

function onDraw()
	local cw,ch,radius,lineX,lineY,echoX,echoY,colorG

	w=screen.getWidth()
	h=screen.getHeight()
	
    --center
	cw=w/2
	ch=h/2
	
    --display radius
	radius=h/2-3
	
    --radar beam 
	lineX=cw+radius*sin(angle)
	lineY=ch-radius*cos(angle)
	
    --draw radar echo
	for i=1,#data do
		if data[i][1]<range then
			echoX=cw+(data[i][1]/range)*radius*sin(data[i][2])
			echoY=ch-(data[i][1]/range)*radius*cos(data[i][2])
			colorG=255*(data[i][4]/removeFrame)
			screen.setColor(0, colorG, 0)
			screen.drawCircleF(echoX,echoY,2)
		end
	end
	
	screen.setColor(0, 255, 0)
	screen.drawText(0,0,string.format("%.0f",range))
	screen.drawCircle(cw,ch,radius)
	screen.drawLine(cw,ch,lineX,lineY)

end

```
【Swift】変数名やメソッド名を決めるときに気をつけること

# はじめに
こんにちは。プログラミング歴1年、エンジニア志望の学生です。
最近、昔作ったiOSアプリのコードのリファクタリングをしています。というのも、プログラミングを始めた頃はコードの可読性とか全く意識せずに書いていたので、見返してみると「うわぁ...🫠」となるようなぐちゃぐちゃなコードだらけでした。
GWというまとまった休みが来たので、これを機に一気に見直そう！と思った次第です。

# 概要
Swiftにおいて、可読性の高い命名の仕方を知る

# 結論
* 意味が伝わる命名をする
* 「簡潔さ」より「伝わりやすさ」を意識する
* メソッド名は動詞から始める
* 統一性に気を配る

# 命名規則
以下のSwift API Guidelineに従っています。
https://github.com/cookpad/styleguide/blob/master/swift.ja.md

また、リーダブルコードという有名なコーディング指南書も参考にしています。
https://www.oreilly.co.jp/books/9784873115658/

# スネークケース、キャメルケースとは
一つの変数・メソッド名などに複数の単語を繋げて表現したい時の繋げ方です。


・スネークケース...文字の区切りをハイフンで表す
```ruby
snake_case = ""
sample_method()
```
・キャメルケース...文字の区切りを大文字で表す
```swift
camelCase = ""
sampleMethod()
```
どちらを採用するかは言語や会社のコーディング規約によって異なりますが、Swiftでは**キャメルケース**を採用しており、以下のような規約があります。
* クラス、プロトコル名は`UpperCamelCase`にする
```swift
ViewModel
ObservableObject
```
* それ以外は`lowerCamelCase`にする
```swift
titleText
requestAuthorization
```
Xcodeを使っていると補完機能や初めから書かれているコードでなんとなく書き方がわかるので、この辺りは問題ないと思います。

# 意味が伝わる命名をする
私が実際に書いていた変数がこちら。
```swift
daySelection
```
...どんな意味かわかりますか？謎ですよね。書いた私でさえ、見直した時「ん？」となりました😓
これは「選択した日付を格納する変数」なのですが、dayとSelectionの関係が曖昧でわかりづらくなっています。
では、以下のように直すとどうでしょう。
```swift
selectedDay
```
今度は、「selected(選択された) -> day(日付)」と自然に理解できるようになったと思います。

コードを書いている時は自分の頭の中で理解ができているので、適当に単語を繋げても違和感がありませんが、他人が見た時や、自分が後になって見返す時に意味不明な名前になっていることがよくあります。曖昧な単語を避け、意味が明確な名前になるようにするのが大切です。

# 「簡潔さ」より「伝わりやすさ」
私は、以前まで「簡潔なコードの方が見やすい！」と思っていましたが、自分のコードを見返してみると、大事なのは、「短いコード」ではなく「理解しやすいコード」を書くこと何だなと気付かされました。
以下は、設定した通知時間を更新するメソッドです。
```swift
func updateTime() {...}
```
`updateTime`だけを見ても、「何の時間を更新するの？」と迷ってしまいます。
```swift
func updateNotificationTime() {...}
```
このようにNotificationと加えることで、メソッド名は長くなりましたが「通知時間を更新するんだな」と一目でわかります。

# メソッド名は動詞から始める
メソッドは、オブジェクト指向プログラミング（OOP）において「手続き」のことを指します。メソッド名を決めるときは、変数と違い動詞を使うようにしましょう。
例えば、タスクの通知処理をするメソッドを定義するなら
```swift
func notificationTask() {...}
```
よりも
```swift
func noticeTask() {...}
```
の方が明確でわかりやすいです。

# 統一性に気を配る
これは命名に限ったことではないですが、コーディングにおいてスタイルを統一することは非常に重要です。
例えば、以下ような２つのメソッドを定義するとします。
```swift
func taskStart() {...}
func saveTask() {...}
```
一つ目のメソッドは「名詞(task) -> 動詞(start)」になっているのに対して、二つ目は「動詞(save) -> 名詞(task)」となっています。統一性があった方がコードが見やすくなるので、どちらか（というか動詞 -> 名詞の方が自然)に統一しましょう。
```swift
func startTask() {...}
func saveTask() {...}
```

# 終わりに
まだまだ命名について大事なことはあるのですが、私が書いてきたコードの直しを中心に紹介しました。
[リーダブルコード](https://www.oreilly.co.jp/books/9784873115658/)や下記の参考サイトを見ていただければ幸いです。

https://muapps.hatenablog.com/entry/2022/07/31/190826
https://github.com/cookpad/styleguide/blob/master/swift.ja.md
CloudWatch Alarmを利用してECSのデプロイをロールバックする

# はじめに
ECSデプロイのロールバック判断に[Circuit Breaker][link-1]を利用していましたが、CloudWatch Alarmのアラーム状態を検知してロールバックを行う機能が追加されていました。
この機能を利用することでメトリクスを監視し、デプロイ後に異常状態であればロールバックを行うという構成ができるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2022/12/amazon-ecs-cloudwatch-alarms-safety-deployments/

アラーム時にロールバックを行えると色々と活用できそうな気がするので試してみます。
# やってみる

## CloudWatch Alarmの作成
ロールバックの判断を行うアラームを作成します。
検証を行うECS ServiceのCPU Utilize最大値が30%を超えた時点でアラーム状態になるアラームを作成しました。
現状では負荷が低いコンテナをデプロイしているので、アラームはOK状態となっています。
![image_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/51dd83a0-bdd5-4d5b-f452-87f7e413b107.png)


## サービスの編集
サービスを編集から上記で作成したCloudWatch Alarmとの紐づけを行います。
「デプロイ不具合の検出」からCloudWatchアラームを設定して失敗時のロールバック項目にチェックを付けます。
![スクリーンショット 2023-02-22 170331.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/c6f78ffe-b191-9e37-46c9-75a8a67cf37e.png)
Circuit Breakerとの併用もできるようです。

## 異常なコンテナのデプロイ
CPU負荷が高いコンテナをデプロイします。
タスク定義の新規リビジョンを作成し、サービスを更新します。
負荷が低いリビジョン1から負荷が高いリビジョン2に更新しました。
![image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/59591050-daf9-1905-fe82-bdac14fac2f5.png)

リビジョン2のタスクがデプロイされることを確認します。

![image_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/7798cdb9-89cf-0cd8-bf1f-ec268c23405d.png)

CloudWatch Alarmを確認すると、狙い通り「アラーム状態」となっています。
![image_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/a2188179-d4e8-96d0-117c-7536a886cab8.png)

デプロイイベントを確認すると「alarm detected」が原因となり、ロールバックが開始されていました。
![image_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/7e699a70-9edd-7d63-51c2-1eb5b169ec1f.png)

# まとめ
簡単ですがAlarmの異常状態からロールバックが発生することを確認しました。
「デプロイ時のAlarmがすでに異常状態の場合はロールバックが発生しない」など、実運用をする場合にはいくつか考慮すべき点があると思います。
以下のドキュメントを事前に確認することをお勧めします。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/deployment-alarm-failure.html


<!-- 以下リンク集 -->
[link-1]:https://aws.amazon.com/jp/blogs/containers/announcing-amazon-ecs-deployment-circuit-breaker/
【Xcode エラー】個人的に１番簡単に感じた「Migration is required due to the following errors」の解決法

下の参考記事を読んだが１番簡単にエラーを解消することができたのは
《参考記事④》の以下の手順。

プライマリーキーを最初指定しないまま使用していた場合に
後からプライマリーキーを指定してしまうと
以下のようなエラーになってしまいます。

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:

これは定義済みのRealmクラス(テーブル定義)と
保存されているRealmオブジェクト(テーブル内のレコード)の定義が
不一致を起こすためです。

この場合は一度アプリ自体をデバイスから削除するか
マイグレーションを使用することで解決できます。

《参考記事①》RealmSwiftのMigration
https://qiita.com/taitai9847/items/2094bf605c2f7fa22e51

《参考記事②》【Swift】Realm利用時に
「Migration is required due to the following errors」というエラーが出る
https://appdev.blitz-time.com/entry/2023/01/11/193843

《参考記事③》【SwiftUI】Realmのマイグレーション方法！
Migration is required due to the following errorsの解決法
https://tech.amefure.com/swift-realm-migration#:~:text=%E5%87%A6%E7%90%86%E3%81%AE%E3%82%84%E3%82%8A%E6%96%B9-,%E3%82%A8%E3%83%A9%E3%83%BC%EF%BC%9AMigration%20is%20required%20due%20to%20the%20following%20errors,%E3%81%8C%E3%81%82%E3%82%8B%E3%81%A8%E6%80%9D%E3%81%84%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%99%E3%82%8B%E3%81%A8%E3%82%A2%E3%83%97%E3%83%AA%E5%AE%9F%E8%A1%8C%E3%81%95%E3%81%9B%E3%82%8B%E3%81%A8,%E5%81%9C%E6%AD%A2%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

《参考記事④》【SwiftUI】Realmでプライマリーキーの設定方法！UUIDを指定
https://tech.amefure.com/swift-realm-primary-key
新規の機能や画面を追加する設計書の作成について

# 1. 新規機能追加の設計書とは
新規の機能追加や画面追加など、システム改修時に設計書を作成することがあります。
この設計書は、プログラマーやテスターがシステムの機能や画面の仕様を理解するために必要なものです。
また、顧客との要件確認の際にも利用されます。

# 2. 要件定義を把握する
新規の機能や画面を追加する場合、まずは顧客との要件定義をしっかりと把握することが大切です。
顧客からどのような機能が必要なのか、どのような画面を作成すべきなのか、といったことを確認し、
それを基に設計書を作成していきます。

# 3. 設計書の構成
設計書は、現場によって異なる場合がありますので、あくまで一例として以下のような構成で作成することがあります。

* 機能概要
* 操作方法
* 画面遷移図
* 処理詳細
* データベース設計

※プロジェクトによっては異なる場合があります。
 現場の手法に合わせて構成を変更することがありますので、
 詳細はプロジェクトの要件や方針に従って確認することをお勧めします。

# 4. 設計書の書き方
以下では、各項目について具体的な書き方を説明します。

#### 4.1 機能概要の記載
機能概要では、新規追加する機能の目的や概要、具体的な機能要件、対象となる利用者
、関連する機能や画面などを記載します。
この項目では、新規機能追加の背景や目的を明確にすることが大切です。

#### 4.2 操作方法の記載
操作方法では、新規追加する機能の使い方、画面に表示される項目やボタンの名称や機能、
入力するデータや入力ルールなどを詳細に記載します。
この項目では、プログラマーやテスターが機能を実装するための詳細な手順を理解できるようにすることが大切です。

#### 4.3 画面遷移図の作成
画面遷移図では、新規追加する画面がどのような画面で、どのような画面遷移をするかを示します。
この項目では、画面の構成や遷移先、遷移元、遷移方法を明確にすることが大切です。

#### 4.4 処理詳細の記載
処理詳細では、新規追加する機能や画面がどのような処理を行うかを詳細に記載します。
具体的には、処理のフローチャートやシーケンス図のように図形を用いる手法や、プログラム言語のコードのようにテキストで手順を記述する手法があります。それぞれの手法において、各処理がどのように実行されるかを示します。
また、入力値や出力値、処理に必要なデータや条件なども記載し、プログラマーやテスターが機能を実装するための詳細な手順を理解できるようにします。
処理詳細の記載は、システムの動作を正確に把握するために非常に重要です。

#### 4.5 データベースの設計
データベース設計では、新規追加する機能で使用するデータベースのテーブルやカラム、関連性などを詳細に記載します。
この項目では、プログラマーがデータベースを実装するための詳細な手順を理解できるようにすることが大切です。

# 5. 設計書のレビュー
設計書の完成後は、関係者によるレビューを行い、不備や漏れがないかを確認します。
レビューには、開発チームや顧客、品質管理部門などを参加させ、多角的な意見を反映させることが大切です。

# 6. コツや注意点
新規追加する機能や画面は、システムの他の機能や画面と連携して動作するため、設計書作成時には、既存のシステムの機能や画面との整合性を確認し、それに基づいて設計を進めることが大切です。また、設計書はプログラマーやテスターだけでなく、将来的にシステムを拡張・改修する際にも参考になるため、詳細かつ正確に作成することが大切です。
【M1 Mac】急にDockerDesktopが起動できなくなった(com.docker.backend cannot start Exit code 152)

## 起きたこと
ある日突然DockerDesktopが起動できなくなった。
以下のようなエラーコードが表示されたダイアログが表示される。
```
com.docker.backend cannot start
Exit code 152
```

## 試したこと
- アクティビティモニタでDockerDesktopを強制終了。→　変わらず。。

## 対処方法
**Dockerの環境設定ファイルを消したら行けました**

```
rm -rf /Users/user/Library/Group Containers/group.com.docker
rm -rf /Users/user/Library/Containers/com.docker.docker
rm -rf /Users/user/.docker
```

## さいごに
ググればたくさん同じような記事が出てくるので割と起きているっぽい。
ローカルで自分の環境なら何も気にせず大胆な対処ができるので解決が早い。。笑
小ネタ：Microsoft Edge で文字列を1回でコピーできない

仕事で Microsoft Edge（バージョン 112.0.1722.58）を使っています。

Edge 上に表示された文字列を、ドラッグ、コピー（Ctrl + C）しても、ちゃんとコピーできていないことが度々ありました。（もう一度コピーするとできる。）

最初は、キーボードが壊れたかと思っていたのですが、他のアプリではコピーできるので原因がよくわかりませんでした。

気になって調べてみると、Edge の「ミニメニュー」が表示されていて、それがコピーを邪魔していることがわかりました。

ミニメニューは、「設定 → アクセシビリティ → テキストを選択したときにミニメニューを表示する」を OFF にすることで表示を抑制できます。

同じ様な現象が起きたら試してみてください。
Windows間でファイルを共有(Near Share) 備忘録

# 概要
- Air DropのようなことをWindowsでもしたい！っと思って調べてみらた、「Near Share」っというのがあったので、その設定方法について記載！
- アプリのインストールはなんと **「不要」!!**


## 参考リンク
- [Windows 10の新ファイル共有機能「Near Share」
- (https://techtarget.itmedia.co.jp/tt/news/1804/01/news01.html)


# 共有準備
- 右下のWindowsマークを”右クリック” -> 「設定」-> 「システム」
-  ->「共有エクスペリエンス（Shared experiences）」を選択する

## 共有方法
- 共有したいファイルを右クリックして、「共有」っという項目があるのでそこをクリックする

### 細かい内容やスクリーンショットは後日投稿予定
ゼロからEntityComponentSystemを書いてみる

Rust言語で書きます

EntityComponentSystemって何かというと、ふわっとしたイメージで、配列に入っているデータをループで書き換える感じ。
配列はメモリ上で連続して配置されるので効率的にアクセスできるというメリットがある。

EntityはIDだとか、Componentはデータだとか、Systemは処理だとか説明されますが実際のソースコードではどうなるか確かめてみましょう。


まずは、ループを書きます。

```rust:main.rs
fn main() {

    let id = 2;

    for i in 0..id  {
        println!("{}", i)
    }
}
```

つぎに、配列の各要素を出力してみましょう
```rust:main.rs
fn main() {
    
    // idは配列の要素数を表す
    let id = 2;

    let pos_ary = [(0, 0), (0, 0)];

    for i in 0..id  {
        println!("{}: {:?}", i, pos_ary[i])
    }
}
```

はい。これがEntityComponentSystemの基礎です。

Entityは、配列の要素数を表す変数でした。
Componetは、配列の各要素です。
Systemは、forループでした。

ただ、このままでは配列の要素数は固定だし、idが3とかだったら実行時エラーになってしまうなど問題ありです。

次回はこれを改善しようとおもいます。
PythonによるWebスクレイピング-入門編、その1

研修の一環としてWebスクレイピングの学習を始めました。
今西 航平氏の「PythonによるWebスクレイピング〜入門編〜」を参考に学習したことを纏めていきます。今回は基礎知識・環境構築・自動ログインの処理までが完了しました。

https://www.udemy.com/course/python-scraping-beginner/

# Webスクレイピングの基礎知識
**Webスクレイピング** - クローリングによって公開されているサイトからテキスト・画像などのデータを習得し、利用できるよう整形・解析する
**クローリング** - webページのリンクをたどり、Webページの情報を収集する

Webスクレイピングは主に株価の変動・IR情報といった**マーケティング戦略**・AI/ MLなどの**サービス開発**に使われています。サービス開発に関しては**第三者による無許可のスクレイピングを規制する運動**が始まっているので要注意です。(ArtStationなど)

**Webスクレイピングのメリット** - 業務効率化、大量のデータを取得できる、APIが必要ない
**Webスクレイピングのデメリット** - アクセス拒否するサイトがある、HTML構造に左右される、**著作権・知的財産権の問題は慎重に

# 環境構築

まずWebアプリケーションのテストに使うライブラリである、Seleniumをインストールします。スクレイピングの学習にはSeleniumの他にもBeautifulSoup等が用いられます。
また、Chromeドライバーのexeファイルを入手する必要があります。詳しくはこちらから環境構築を行ってください。

https://scraping-for-beginner.readthedocs.io/ja/latest

https://sites.google.com/a/chromium.org/chromedriver/downloads

```python
pip install selenium==3.141.0

# Chrome
from selenium import webdriver
driver = webdriver.Chrome()
```
webdriverを実行すると、「Chromeは自動テストソフトウェアによって制御されています」と表示されたブラウザが立ち上がります。

# 自動ログイン
以下のサイトに自動でログインできるようにします。SeleniumにはWebアプリケーションのテスト用として、入力フォームに文字を入力する・ボタンを全自動で押すなどの作業が行えます。

https://scraping-for-beginner.herokuapp.com/login_page

自動でINPUTタグ等に文字列などを入力するには、まずそのページのHTMLの構造を理解する必要があります。HTMLの構造を確認するには、`右クリック → 検証 → 要素を左クリック`でタグのID・クラスなどを確認できます。今回必要なのはユーザーネーム・パスワードのNPUTタグのIDなのですが、これらは`"username" "password"`が該当します。

![スクリーンショット 2023-04-29 122915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/53c5f9fb-fcec-704b-5b82-6bf332dbb39a.png)

```python
# Chrome
from selenium import webdriver
browser = webdriver.Chrome()

# URLにアクセスする
browser.get("https://scraping-for-beginner.herokuapp.com/login_page")

# ユーザーネームのインプットを取得
elem_username_input = browser.find_element_by_id("username")
#send_keysメソッドで自動入力ができる
elem_username_input.send_keys("imanishi")

# パスワードのインプットを取得
elem_username_input = browser.find_element_by_id("password")
# send_keysメソッドで自動入力
elem_username_input.send_keys("kohei")

# URLを閉じる
browser.quit()
```

![スクリーンショット 2023-04-29 123558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/8cbb10cd-b134-af60-c382-869e5bd3602c.png)

今回はスクレイピングの基礎と自動ログインについて学びました。
次回はテキストデータ・画像データの収集について学ぶ予定です。
Flutterで想定外エラーへ対応する

## はじめに

Flutterでアプリ開発をしている際、もちろん基本的にはtry-catchでエラーハンドリングをしたり、場合によってはExceptionクラスを自作してうまくエラーハンドリングをすることが好ましいです。

しかし、場合によっては想定外のバグであったり、try-catchを指定していない箇所のバグが発生した場合、デバッグモードだと真っ赤な画面になりますね。

リリースモードだと、時にはアプリがフリーズしたりクラッシュしてしまいます。

そのような想定外エラーの対応として、Firebase CrashlyticsやSentryのサービスを用いてエラーログを収集することも大切です。

今回の記事では、想定外エラーが出た場合に共通エラーダイアログを表示させる小ネタの紹介です。

## 実装

```Dart
void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    FlutterError.dumpErrorToConsole(details);
    runApp(UnexpectedErrorDialog(details));
  };
  runApp(MyApp());
}
```

```dart
class CustomErrorWidget extends StatelessWidget {
  final String errorMessage;

  CustomErrorWidget({this.errorMessage});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            Icons.error_outline,
            color: Colors.red,
            size: 50.0,
          ),
          SizedBox(height: 10.0),
          Text(
            'Error Occurred!',
            style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
          ),
          SizedBox(height: 10.0),
          Text(
            errorMessage,
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 16.0),
          ),
          SizedBox(height: 10.0),
          ElevatedButton(
            // goRouterなど使っている場合、initialRouteに遷移などして対策
            // popでも良い
            onPressed: () => context.goNamed(
              context,
              TopPage.routeName,
            ),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }
}
```

ただ、繰り返しですが基本はtry-catchでエラーハンドリングができることが好ましいです。
後日、Exceptionクラスを定義したエラーハンドリングの記事を作成したいと思います。
【自分用】Webアプリ開発記録

ローカル環境にRuby、Railsをインストール
horror_review_app生成
DBを変更　rails db:system:change --to=postgresql
githubにpush
gemfile書き足し
ブランチ作成、移動
テスト失敗DB作成失敗
brew services restart postgresqlの後にrails db:createでDBを作成し、 rails testで出来た
参考:https://qiita.com/tamakiiii/items/ef4bc9c1aa10cdcd5b6b
aboutページとそれのテスト作成
vscode拡張機能追加

rails testが失敗するように
原因はpostgresql
postmaster.pidを削除することで再び動くようになった
解決に役立ったもの(https://techracho.bpsinc.jp/hachi8833/2017_12_21/48661)
(https://hacknote.jp/archives/30385/)

railsチュートリアルを復習しながら進める

本番環境renderにデプロイするときに発生したエラーと解決法
https://qiita.com/sajiki09/items/e25bba9b716865203ba5
bundle lock --add-platform x86_64-linux

ActiveRecord::Fixture::FixtureErrorが発生したとき
.ymlを修正した
https://teratail.com/questions/135301

ActiveRecord::ConnectionNotEstablished: could not translate host name "dpg-cibstjt9aq03rjh34d9g-a" to address: Name or service not known
PG::ConnectionBad: could not translate host name "" to address: Name or service not known
原因:アプリとデータベースのregionが異なっていた
https://community.render.com/t/where-does-render-get-the-host-name-from/3560

ページネートの表示件数変更
https://qiita.com/chocode/items/57852db2eb6a1ed5e973

カラムの変更、修正、追加
https://qiita.com/iverson3kobe0824/items/6dfce930d57dcc5dd482

レビュー投稿時に
ActionController::ParameterMissing (param is missing or the value is emptyエラー
params.requireを削除したら解消された

Unpermitted parameters: :_method, :authenticity_token, :movie_review, :commit, :id. Context: 
レビューの編集機能実装中に発生したエラー
def movie_review_params
  params.require(:movie_review).permit(:content, :rating)
end
params.requireを設定したら解消された
自分用メモ

pe + tabキーで　<%=  %>
er + tabキーで <%  %>
行の複製 opt + shift + ↑/↓
ChatGPTで改行 Shiftキー ＋ Enterキー

postgreSQLでソケットがないと言われてエラーが起きた際に役立った
https://techracho.bpsinc.jp/hachi8833/2017_12_21/48661

rm /usr/local/var/postgresql@14/postmaster.pid

・節の終わりに行う
$ git add -A
$ git commit -m "タイトル 例(Add a Static Pages controller)"
$ git push

・コード生成と取り消し
$ rails generate controller StaticPages home help
  $ rails destroy  controller StaticPages home help

・モデル生成と取り消し
$ rails generate model User name:string email:string
$ rails destroy model User

・マイグレーションの変更と元に戻す
$ rails db:migrate:status マイグレーションファイルの状態を確認する
$ rails db:migrate マイグレーションファイルを適用
$ rails db:rollback ひとつ前に戻す
$ rails db:migrate VERSION=0 最初の状態に戻す
https://qiita.com/yuya_maru2/items/87df1377cbef733c7647
https://ichigick.com/rails-edit-migration/

railsのモデルの属性を確認
https://qiita.com/kon_yu/items/5c173f5a8af6ad67eee7

本番環境のDBをリセットする
bin/render-build.shファイルを変更
-bundle exec rails db:migrate
+bundle exec rails db:migrate:reset
Renderダッシュボードの「Environment」から環境変数DISABLE_DATABASE_ENVIRONMENT_CHECKを追加
値は1
変更をコミットしデプロイ
リセットしたら忘れずに元に戻す

rails db:reset  と rails db:migrate:resetについて
https://otaku-programmer.com/rails/db/migration/1/
RubyでAtCoder ABC272(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC272のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Integer Sum
https://atcoder.jp/contests/abc272/tasks/abc272_a
```diff_ruby:a-272.rb
gets
- puts gets.split.map(&:to_i).sum
+ puts gets.split.sum{ |e| e.to_i }
```

# B - Everyone is Friends
https://atcoder.jp/contests/abc272/tasks/abc272_b
```ruby:b-272.rb
n, m = gets.split.map(&:to_i)
hash = {}
m.times do
  array = gets.split.map(&:to_i)
  k = array.shift
  for i in 0..k - 2
    for j in i + 1..k - 1
      next if hash[[array[i], array[j]]]
      hash[[array[i], array[j]]] = true
    end
  end
end

puts hash.uniq.size == (1..n - 1).sum  ? "Yes" : "No"
```
## 解説
連想配列hashを使って、同じ舞踏会に参加したかを記録しています。最後に、連想配列の大きさが場合の数と一致していればYes、一致していなければNoを出力します。

# C - Max Even
https://atcoder.jp/contests/abc272/tasks/abc272_c
```ruby:c-272.rb
# 修正前
n = gets.to_i
a = gets.split.map(&:to_i).sort.reverse

e = a.select{ |factor| factor.even? }.sort[-2..] || [-1]
o = a.select{ |factor| factor.odd? }.sort[-2..] || [-1]

puts [e.sum, o.sum].max
```
```ruby:c-272.rb
# 修正後
gets
a = gets.split.map(&:to_i)

array = a.partition{ |i| i.even? }
e = array[0].max(2)
o = array[1].max(2)

e = e.size == 2 ? e.sum : -1
o = o.size == 2 ? o.sum : -1
puts [e, o].max
```
## 解説
和が偶数となるのは偶+偶または奇+奇の場合なので、selectメソッドを使ってaの要素のうち偶数で大きいもの２つおよび奇数で大きいもの２つを取得しています。なお、そのような要素が2つ以上ない場合はnillとなってしまうので、nillにならないように-1を設置しています。最後に、和の最大値を出力すればOKです。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
【Spring】WebServiceTemplateとRestTemplate, SOAPとREST


### WebServiceTemplateとRestTemplate

WebServiceTemplate と RestTemplate は共にSpring FrameworkにおいてWebサービスを呼び出すためのクラス。


SOAPベースのWebサービス呼び出し
→ WebServiceTemplate


RESTベースのWebサービス呼び出し
→ RestTemplate

### WebServiceTemplate

WebServiceTemplate は、SOAP(Simple Object Access Protocol)ベースのWebサービスを呼び出すためのもの。SOAPはXMLを使用したメッセージ形式を持ち、Webサービスの呼び出しに特化している。

### RestTemplate

RestTemplateは、REST(Representational State Transfer)ベースのWebサービスを呼び出すためのもの。RESTはHTTPのURI/メソッド/ヘッダー/ボディを使用して、Webリソースに対するCRUD操作を行う。

---

### SOAP通信とREST通信の違いについて

## **SOAP通信**

SOAP（Simple Object Access Protocol）は、XMLで構成されたメッセージ交換のプロトコルであり、WSDL（Web Services Description Language）で記述されたサービスを呼び出すために使用される。

特徴は以下の通り。

- XML形式のメッセージを使用する
- WSDLでサービスの説明を提供し、SOAPでメッセージを送信する
- SOAPメッセージはHTTP、SMTP、FTPなどのプロトコルで送信できる
- 構造が複雑で、SOAPメッセージのサイズが大きくなりがち
- 通信のセキュリティや信頼性を高めるために、WS-拡張機能を使用することが出来る

## **REST通信**

REST（Representational State Transfer）は、Webアプリケーション間でデータをやり取りするためのアーキテクチャであり、HTTPプロトコルを使用してリソースを操作するために使用される。

特徴は以下の通り。

- XML、JSON、またはテキスト形式のシンプルなメッセージを使用する
- URI（Uniform Resource Identifier）でリソースを識別し、HTTPメソッドで操作を行う
- サーバー側でリクエストを理解するための状態を保持する必要がなく、ステートレスである
- ブラウザなどの様々なクライアントからアクセス可能であるため、Webアプリケーションやモバイルアプリなどの開発に適している

----

同プロジェクト内でも接続先や機能によって変わるため極力要件段階で確認、判断することが望ましい。
【初学者向け】Docker上でLinux環境を構築しよう！(Ubuntu)

# はじめに
この記事はLinuxの学習を始めたばかりの方が、実際にLinux環境を構築してコマンドなどの練習をするための記事となります。
サクッと環境構築ができて、しかもDockerの勉強にもなるような、一石二鳥の記事となっています。
では、以下の3つのステップを順に実行していきましょう！( ^ω^ )

# 1. Docker Desktopのインストールと実行
   まず「Docker Desktop」をインストールする必要があります。
以下のリンクから最新版をダウンロードしてインストールしてください。

[Download Docker Desktop | Docker](https://www.docker.com/products/docker-desktop/)

インストールが完了したら、Docker Desktopを起動してください。
起動すると画面上部のバーにDockerのアイコンが表示されます。

# 2. Ubuntu のイメージを取得
   ターミナルを開いて、以下のコマンドを入力してUbuntuのバージョン18.04のイメージを取得します。
   ```
   docker pull ubuntu:18.04
   ```
ちゃんとpullできているか、下記のコマンドで確認してみましょう。
   ```
   docker images
   ```
REPOSITORYのところに ubuntu があればOKです！

# 3. Dockerコンテナの作成 ・ 起動 ・ 停止
 以下のコマンドにより、Ubuntuのイメージを使用してDockerコンテナを作成し、起動します。
   ```
   docker run -it --name myubuntu ubuntu:18.04 /bin/bash
   ```
<details><summary>各オプションの簡単な解説</summary>

- `--name myubuntu`の部分は、好きなコンテナ名に変更できます。
- `-it` オプションは対話的な操作をするために必要で、`-i` は interactive(対話的)、`-t` は tty(Teletype：端末)のことです。
- `/bin/bash` は、Bashというシェルを起動するために使用します。
</details>
これで、ターミナル上でUbuntuのコンテナが実行されます。

この時点で **コンテナの中に入っている** 状態です。
操作が完了したら`exit`コマンドで **コンテナから抜ける** ことができます。
最後に`docker stop myubuntu`コマンドでコンテナを停止しましょう。

# またコンテナを起動してLinuxを触りたい時
まずは停止したコンテナを起動します
```
docker start myubuntu
```
コンテナの中に入ります
```
docker exec -it myubuntu /bin/bash
```
これでOKです！
終わりにしたいときの手順は前と一緒です。
`exit`コマンドでコンテナから抜けて、`docker stop myubuntu`コマンドでコンテナを停止しましょう。

:::note info
ちなみに ...
`-it`オプションを外すと、コンテナに入らずに、外から操作することができます。
試しにコンテナの外で`ls`コマンドを実行してみましょう。
```
docker exec myubuntu ls
```
まあ、あまり使わないと思いますが(￣▽￣)
:::

# 最後に
以上で、Docker Desktopを使ってLinux(Ubuntu)の環境を構築する手順が完了となります。

- 続けてシェルスクリプトを勉強する方には、以下の記事も参考になるかと思います。
[【初学者向け】viやvimなどのエディタがない！どうすれば！？](https://qiita.com/yuta_931214/items/a9201e78489cb7bd2c4b)

- 日本語を扱えるようにしたい方には、以下の記事も参考になるかと思います。
[【Linux・vim】日本語を扱えるようにする](https://qiita.com/yuta_931214/items/fba2b1ba5aab750823e7)

Linuxの学習教材としては、LPI-Japanが無償で公開している[『Linux標準教科書』](https://linuc.org/textbooks/linux/)がおすすめです。
初学者にとっては簡単な内容じゃないと思いますが、とても基礎的な知識がコンパクトにまとまっていますので、ぜひこの記事を参考に環境構築をしてコマンドなどを練習してみてください。
それではまた！(^_^)ﾉｼ
閉ざされた世界で画面キャプチャを取るPowerShell

## 当スクリプトの目的

作業エビデンス取得の効率化などで、キャプチャを一定間隔で取っておきたいということがあると思います。そのためにWinShotなどの画面キャプチャソフトがありますが、現場によっては勝手にexeを使うと怒られることがあります。そういう現場でも、Windows PowerShellは入っているので、それを使えば似たことができます。今回は、そのニッチなニーズのためのスクリプトです。結局、仕事では使わなかったので公開します。

## シンプルなやり方

プリントスクリーンのキーを送って、画像保存するというだけなら、以下のようなスクリプトで大丈夫でしょう。キーを送ってから1秒待っています。これをps1ファイルとして保存して、右クリックでパワーシェルとして実行すれば同フォルダにキャプチャ画像ができていきます。

```SimpleCaprture.ps1
Add-Type -AssemblyName System.Windows.Forms
[Console]::WindowWidth = 50
while ($true) {
    Write-Host "Capturing screenshot at $((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))..."
    [System.Windows.Forms.SendKeys]::SendWait("{PRTSC}")
    Start-Sleep -Seconds 1
    $image = [System.Windows.Forms.Clipboard]::GetImage()
    $filename = "screenshot_$((Get-Date).ToString('yyyyMMdd_HHmmss')).png"
    $image.Save($filename, [System.Drawing.Imaging.ImageFormat]::Png)
    Write-Host "Screenshot saved as $filename"
    Start-Sleep -Seconds 4
}
```
ただ、マルチディスプレイを使っている環境では、全てのスクリーンが取得されてしまうため、少し不十分です。

## マルチディスプレイ対応版

以下は、ディスプレイ番号を指定して、そのディスプレイ分のみ取得するスクリプトです。最近の高解像度ディスプレイでは座標指定がズレてしまうことがありますので、その対応を含んでいます。ScaleFactorを変数にして、1.5などに書き換えれば正しい領域が取得できます。

```ScreenCaprture.ps1
Add-Type -AssemblyName System.Windows.Forms
[Console]::WindowWidth = 100

#### Please specify 3 parameters.
$waitSecond = 4 #Specify the wait time.
$screenNo = 0 #If multiple displays are connected, specify the number.
$scaleFactor = 1 #Set the scale factor for a high DPI display.

Write-Host "Capture interval is $waitSecond seconds (+ image processing time)."
$screens = [System.Windows.Forms.Screen]::AllScreens
$chosenScreen = $screens[$screenNo] 
Write-Host "Screen $screenNo is chosen."
$screenLines = $chosenScreen -split " "
$screenLines = $screenLines -join "`n"
Write-Host $screenLines

if ($scaleFactor -gt 1) {
    Write-Host "High-resolution display: Using scaled bounds."
    $bounds = $chosenScreen.Bounds
    $bounds.Width = [int]($bounds.Width * $scaleFactor)
    $bounds.Height = [int]($bounds.Height * $scaleFactor)
    $bounds.X = [int]($bounds.X * $scaleFactor)
    $bounds.Y = [int]($bounds.Y * $scaleFactor)
} else {
    Write-Host "Regular display detected: Using regular bounds."
    $bounds = $chosenScreen.Bounds
}
Write-Host "Bounds*Scalse=$bounds"

while ($true) {
    Write-Host "Capturing screenshot at $((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))..."
    $bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
    $graphics.CopyFromScreen($bounds.Location, [System.Drawing.Point]::Empty, $bounds.Size)
    $filename = "screenshot_$((Get-Date).ToString('yyyyMMdd_HHmmss')).png"
    $bitmap.Save($filename, [System.Drawing.Imaging.ImageFormat]::Png)
    Write-Host "Screenshot saved as $filename"
    Start-Sleep -Seconds $waitSecond
}
```

これで、閉ざされた世界（スタンドアローンテスト環境）でもあなたが生きた証（テストエビデンス）を遺すことができます。まあ、実際には他の縛りで使えませんでした。

GitHubにも置いておきました。
https://github.com/KentAnak/ScreenCaptureScript
[iOS] GoogleService-Info.plistをBitrise上で取得させる方法

## はじめに
Firebaseを使ったiOSアプリのCI/CDを構築する上でGoogleService-Info.plistをBitriseのワークフローで取得させたく調べてみました。

## 困っていたこと
対象のiOSアプリのリポジトリはPublicとしているため、`GoogleService-Info.plist`はリポジトリ内に保存できません（.gitignoreしています）

この状態でBitrise上でテストやリリースのワークフローを動かすとGitHubからcloneしたリポジトリには`GoogleService-Info.plist`が含まれてなく以下のようなエラーが発生します

`
❌ error: Build input file cannot be found: '/Users/vagrant/git/PadeLovers/GoogleService-Info.plist'. Did you forget to declare this file as an output of a script phase or custom build rule which produces it? (in target 'PadeLovers' from project 'PadeLovers')
`

## 対応したこと
基本的なやり方は公式ドキュメント通りにやっていけばよさそうでした。

https://devcenter.bitrise.io/ja/builds/managing-build-files/using-files-in-your-builds.html#ファイルダウンローダーステップを使用してファイルをダウンロードする

Bitriseの`Code Signing & Files`タブから`GoogleService-info.plist`を保存します
<img width="500" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/a8a4ef48-cd9a-d130-0a7f-1de2df5d1c0c.png">

保存するとファイルのPathが確認できます
<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/7b9c7247-e5c8-d425-9270-426f31e01618.png">

Bitrise.ymlを使っているので`GoogleService-info.plist`の取得ステップをBitrise.ymlの（buildの前処理の）適当な位置に追加しました

```yml
    - file-downloader@1:
        inputs:
        - destination: $BITRISE_SOURCE_DIR/PadeLovers/GoogleService-Info.plist
        - source: $BITRISEIO_GoogleService_Info_PadeLovers_URL

```

これで完了です🎉


##### おまけ
ちなみにGUIでワークフローを追加する場合はFile Downloaderを追加

<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/7c92d828-e7e3-2e02-8239-09f258e453c4.png">

REQUIREDにファイルのパスと保存先を指定します
<img width="500" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/7c553ac6-5004-5d71-983e-830b364304a3.png">


# 参考
https://qiita.com/tbskgm/items/72c6e09e8319f1ea2514
【Mac】Goをインストール　→　Goのプラグインをvscodeでインストール　→　エラー　→　2つの原因と解決方法

Udemyで勉強しようと思ったら引っかかったのでメモ。

## エラー発生までにやったこと

https://go.dev/dl/

↓

上記の「go公式」で

Apple macOS (x86-64)
macOS 10.13 or later, Intel 64-bit processor
go1.20.3.darwin-amd64.pkg

をインストール

↓

```
# インストールされているか確認
go version
```

↓

OK

↓

1.VScodeでGo言語の拡張機能をインストール
 → エラー

2.VSCodeでコマンドパレットを開いてGO: Install/Update tools
 → エラー

ということが発生。

## 原因
1.Go言語の拡張機能をインストール
 → エラー　→ xcodeがインストールされていない

2.VSCodeでコマンドパレットを開いてGO: Install/Update tools
 → エラー　→ MacOSをVenturaに上げたため、XCodeのxcrunコマンドに参照問題が生じてる

## 解決方法
単純にxcodeをインストールして、`xcode-select --install`を実行で解決しました。


### 「xcode」をインストール

https://developer.apple.com/download/all/

Xcodeをインストールします。

### xcode-select --installを実行
ターミナルで`xcode-select --install`を実行します。


## エラーが出たところをもう一度やってみる
vscodeで...

1.Go言語の拡張機能をインストール
 → OK!!

2.VSCodeでコマンドパレットを開いてGO: Install/Update tools
 → OK!!

ヨシ！

これからgoを触る人はご注意を。