OmniAICreator/Qiita-1.07M huggingface dataset:
【資格合格記】AWS SAPに合格したので振り返る

2022/12/24 にAWS認定の一つであるソリューションアーキテクト・プロフェッショナル（SAP-C02）に合格しました。

![Pass2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185028/5f5b976e-4c7d-57f0-5a7b-0e084e71e6b2.png)

かなりギリギリですね、見直し時間も10分ほどしか確保できなかったのでまだまだ理解が足りないところがありそうです。

# SAP-C02に変わって
11月半ばにSAPは試験バージョンを更新し、SAP-C02となりました。
試験範囲のサービスは若干多くなり、どちらかといえば難しくなったと言えるかと思います。

とは言えSAP-C01と同じ勉強方法で基本的に問題なさそうです。
＋αで新サービスのところを学習しておく形で良いでしょう。

# 学習期間
一度落ちて、そこからさらに勉強を重ねていますが、3ヶ月程度の学習期間で合格できました。

- 1回目
    - 1ヶ月半程度勉強したあたりで受験。720点で不合格
    - SAP-C01ベースの教材で問題ないことを確認できた。
- 2回目
    - さらに1ヶ月半勉強し再受験。合格

# 勉強方法
SAPは試験範囲がかなり広いため、
　テキストを一通り読む　→　問題集を解く
の流れはやめた方が良いと感じました。

SAP対策の本はありますが、それでも全てのサービスの詳細が載っているわけではないのに加えて、読破するまでかなり時間がかかります。
問題集ベースで勧めていく方をおすすめします。



# 使用した教材

全ての教材に言えますが、 **「最初に教材を一通り読む」というのは絶対にやめて下さい** 
サービスが多すぎてまず途中で投げます。

あくまで問題集ベースで、よくわからないサービスが出たら調べる。という辞書的な使い方をしましょう。

## [AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/index.html)

オススメ度：★★★

SAPは試験範囲が広く、全く知識のないサービスの問題が出ると当たり前ですが点数が取れません。
それに比べて問題文が複雑でイメージもしにくいです。

AWSのサービスもたくさんあるので知らないものがあるのは仕方ないです。
大変ですが、ドキュメントを読んでどのようなサービスなのか調べるのがかなり重要です。


## [Black Belt](https://aws.amazon.com/jp/events/aws-event-resource/archive/?cards.sort-by=item.additionalFields.SortDate&cards.sort-order=desc&awsf.tech-category=*all)

オススメ度：★★★

知らないサービスをざっくり知るのに最適です。
動画での説明になっており、資料もあるので公式ドキュメントでいまいちイメージが掴めない場合はこちらを活用します。

## [AWS認定資格試験テキスト&問題集 AWS認定ソリューションアーキテクト - プロフェッショナル](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-%E5%95%8F%E9%A1%8C%E9%9B%86-AWS%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB-%E5%B1%B1%E4%B8%8B%E5%85%89%E6%B4%8B/dp/4815609063/ref=asc_df_4815609063/?tag=jpgo-22&linkCode=df0&hvadid=529520598444&hvpos=&hvnetw=g&hvrand=16757498204942410970&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009318&hvtargid=pla-1412432309456&psc=1&th=1&psc=1)

オススメ度：★☆☆

今回も対策本を購入しましたが、個人的にプロフェッショナルにおいてはあまりオススメはできないように感じました。
本の内容が悪いわけではありません。自分の勉強方法には合わなかったというだけで素晴らしい本だとは思います。

はじめに書いたように全てのページを読むというのは時間がかかりすぎてモチベーションを保てません。
なので辞書的な使い方をするのですが、それならば本ではなく公式ドキュメントやBlack Beltを使用した方が良いと感じたためオススメ度は低めです。


# 使用した問題集

## [skillbuilder](https://explore.skillbuilder.aws/learn/course/external/view/elearning/13272/aws-certified-solutions-architect-professional-official-practice-question-set-sap-c02-japanese)

無料になった公式問題集です。
20問しかないですが数少ないSAP-C02の問題集で、解説もあるので活用します。

自分は3周して、全問正解できるまでやりました。
難易度は本番と比べて簡単でした。

## [TechStock](https://techstock.jp/)

旧koiwaの問題集です。今回もお世話になりました。

#30以降の問題を2周、本試験モードを1回実施しました。
問題文が複雑で、1周だけでもかなり疲れますが最低でも2周して不安なところを潰しておく必要があります。

難易度は本番と比べて少し簡単という印象。サイトで高得点を取れても油断しない方が良さそうです。
【資格合格記】AWS DOPに合格したので振り返る

2022/9/24（土）にAWS認定資格の一つであるDOPに合格しました。

![DOPスコア_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185028/f1f7b071-ef4f-d851-e799-cb1c40ba742f.png)

合格ラインは750点ですが、結構余裕を持った点数で合格することが出来ました。
各分野も全て「コンピテンシーを満たしている」の評価でした。

## 所持資格（AWS関連）

- クラウドプラクティショナー（CLF）
    - 2021/05/23 合格
    - 学習期間は１か月程度
- デベロッパー（DVA）
    - 2021/10/30 合格
    - 学習期間は１か月程度
- ソリューションアーキテクト（SAA）
    - 2021/12/11 合格
    - 学習期間は１か月程度
- SysOpsアドミニストレータ（SOA）
    - 2022/03/26
    - 学習期間は２か月程度

## 学習期間

- 2ヶ月
    - 最上位のプロフェッショナルということで、これまでの試験よりも多めに時間を取りました。
    - 後述しますが、DOPは関連書籍がなかったのでひたすら問題集を解いています。

## 使用したテキスト

問題集ではなく、DOPの試験範囲のサービスを知るためのテキストとして使用した教材です。

### [公式ドキュメント](https://docs.aws.amazon.com/)

AWSの公式ドキュメントです。
プロフェッショナルは問題文・回答の選択肢が複雑で各サービスの使用方法について理解しておく必要があります。
間違えた問題に出ていたサービスについてのドキュメントはしっかり読んでおいたほうが良いです。
問題の内容で構成をイメージ出来るようにならないと合格は無理です。

### 


## 使用した問題集

自身の理解度を調べるために使用した、問題集です。

### [TechStock](https://techstock.jp/)

おなじみのkoiwaのWeb問題集です。
Udemyか、TechStockのどちらかを使用することになるかと思いますがこちらを採用しました。
アソシエイト試験のときもお世話になっていたので、個人的に信頼感もあり、合格記を読むのもモチベーションを保つのに役立ちました。

個人的には本番試験よりも、少し簡単かなという印象でした。
草莽Erlang ── 21. lists:foldl

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## lists:foldl

```
foldl(fun((term, term) -> term), term, [term]) -> term
foldl(fun((要素, 累積IN) -> 累積OUT), 累積の初期値, リスト) -> 累積の最終値
```

他のプログラミング言語でいうreduce関数のようなものです。リストを1つの値に絞り込むことができます。

- 各要素 に対して与えられた関数を適用し累積（アキュムレータ）を更新
- 累積は次の関数呼び出しに渡される
- 最後に、累積の最終値が返される
- リストが空の場合、累積初期値が返される

https://www.erlang.org/doc/man/lists.html#foldl-3

馴染みのない方は[闘魂Elixir](https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e)の図を眺めてみるとなんとなく感覚が掴めるかもしれません。

https://qiita.com/torifukukaiou/items/a02a3a599d1959dd80f2

練習してみます。

```erlang
% 和を求める
> lists:foldl(fun (X, Acc) -> Acc + X end, 0, [1, 2, 3, 4]).
10

> lists:foldl(fun (X, Acc) -> Acc + X end, 0, []).
0
```

`lists`モジュールには他にもリスト処理のための関数がたくさんあります。

https://www.erlang.org/doc/man/lists.html

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
【Python】椎名林檎と東京事変の歌詞の意味をテキストマイニングでひも解いてみた

# 背景
椎名林檎さまと東京事変が大好きで、いつか難解な歌詞の意味を解釈できたらいいなと思っていました。
自然言語処理を勉強し、椎名林檎と東京事変の歌詞を可視化することにより意味を深堀したいと思いテキストマイニングをしてみました。それぞれのテーマや世界観について考察したいと思います。

# 歌詞の取得
歌詞のスクレイピングは下記ページを参考にさせて頂きました。
https://qiita.com/Senple/items/1ad08b1a7ac9560bef62
歌詞はuta-netから引っ張ってきています。
椎名林檎さま（全141曲）：https://www.uta-net.com/artist/3361/
東京事変（全101曲）：https://www.uta-net.com/artist/3484/

※歌詞の取得には注意が必要なため方法は割愛致します。

# テキストマイニングの実施
UserLocalを用いて椎名林檎さまと東京事変の歌詞を比較しました。
https://textmining.userlocal.jp/

## ワードクラウドの描画
では早速、椎名林檎と東京事変の歌詞に出てくるワードの頻出度を比較するためにワードクラウドを描いていきます。
![ワードクラウド比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874461/3ec51561-41ae-8e91-47dc-68b2607981cd.png)
椎名林檎の歌詞には「あたし、あなた」が多く、
東京事変の歌詞は「あなた、僕」が多い結果となりました。

東京事変の歌詞に「あたし」ってあまり出てこないんだ！というのが驚きでした。
これはファンながら、誰の視点の歌なのか意識したことはなく、
椎名林檎の歌詞は「あたし」目線、東京事変の歌詞は「僕」目線という
登場人物が区別されているということを推測できました。

また、両方共通して「云う、知る、生きる」というワードが頻出していました。
これはファンとしては納得なのではないでしょうか。確かに、このワードは多い気がします。



## 頻出語の比較
続いて、頻出語の出現割合を比較します。こちらでも、椎名林檎と東京事変の歌詞では登場人物が使い分けられていることが予想されます。
椎名林檎の方では「あたし」の出現率が高く、東京事変の歌詞では「僕」が多くなっていますね。

動詞では「知る・生きる・云う」がどちらも同じくらい出現しています。

![頻出語の比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874461/aa678b93-e9d0-661b-4795-6b1a05e08a7b.png)

## 単語分類の比較
最後に、椎名林檎と東京事変の歌詞で特徴的な単語を抽出してみます。どちらかに偏って出てきている単語があるようです。
![単語分類の比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2874461/062f5625-2fa0-eea0-bc27-6cd3b543595a.png)

椎名林檎の歌詞は一人の女性が恋愛を通して泣いたり、誰かを忘れたり、月日が過ぎて日々が変わっていくのを待っているというようなイメージでしょうか。

一方、東京事変の歌詞は現在や未来といった時間の描写や、自由や新しい世界、生命に期待しているというような世界観でしょうか。

# まとめ
テキストマイニングを通して、椎名林檎と東京事変の歌詞は登場人物が使い分けられているということが推測できました。解釈は様々だと思いますが、歌詞を可視化することによって新たな考察ができるのが楽しいですね。
今度は、word2vecなどを用いて、椎名林檎や東京事変が「知りたい」ことは何なのか、何を「云って」いたのか？「生きる」とは？など掘り下げていきたいと思います。

他にもこんな解釈ができるよ！などありましたらコメント頂けると嬉しいです！
Conditional Renderingのfalsy値の扱い

<h2>条件部Rendering例</h2>

```react
import React from 'react'

function UserGreeting(props) {
    return <h1>{props.name && props.name + ','} 
           welcome {props.count && `It's ${props.count} times`} </h1>
}

function GuestGreeting(props) {
    return <h1>Please sign up.</h1>
}

function Greeting(props) {
    return  props.isLoggedIn ? <UserGreeting name="jimmy" count={0} /> : <GuestGreeting />
}

export default function Condition() {
    const isLoggedIn = true;
    return (
        <div><Greeting isLoggedIn={isLoggedIn} /></div>
    )
}

```

<h2>&&演算子とfalsy</h2>

```react
    return <h1>{props.name && props.name + ','} 
           welcome {props.count && `It's ${props.count} times`} </h1>
```


<b>A && B :</b> Aがtrueなら、Bを出力する。Aがfalseなら、何も出力しない。
　　　　<b>ここで要注意は、Aが0のようにfalsyな値の場合はAを出力してしまうので注意が必要！</b>
　　　　countが’0’なら、出力結果が「Welcome 0」となる。

falsy value : 0、-0、0n、""、null、undefined、NaN

<h2>falsy値による不具合を制御</h2>
falsyな値により、予想出来なかった出力結果になることを制御するために二つの方法があるかと思います。<br>
①Booleanを囲んでfalsy値をfalse値に明確化にする

```react
    return <h1>{props.name && props.name + ','} 
           welcome {Boolean(props.count) && `It's ${props.count} times`} </h1>
```

②３項演算子を使用する

```react
    return <h1>{props.name && props.name + ','} 
           welcome {props.count ? `It's ${props.count} times` : null} </h1>
```
【SwiftUI】Macアプリの設定ウインドウを作成する

# はじめに
`MenuBarExtra`でメニューバーアプリを開発していて環境設定を作成しようと思ったところで詰まったので記事にしておきます。
全てはKyomeさんのおかげです。

https://github.com/feedback-assistant/reports/issues/327

こんな感じでみんな困ってるっぽいです。

# サンプルアプリ
![画面収録_2023-01-11_21_23_20_AdobeExpress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/91776154-b677-f9b0-50c0-d92067f8c336.gif)

# 実装
```swift:AppDelegate
import AppKit

class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
    private var settingsWindow: NSWindow? {
        return NSApp.windows.first(where: { window in
            window.frameAutosaveName == "com_apple_SwiftUI_Settings_window"
        })
    }

    func applicationDidFinishLaunching(_: Notification) {}

    func openPreferences() {
        if #available(macOS 13, *) {
            NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
        } else {
            NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
        }
        guard let window = settingsWindow else { return }
        if window.canBecomeMain {
            window.orderFrontRegardless()
            window.center()
            NSApp.activate(ignoringOtherApps: true)
        }
    }
}
```
```swift:〇〇App
import SwiftUI

@main
struct swiftui_macos_sampleApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var delegate
    var body: some Scene {
        MenuBarExtra {
            ContentView(delegate: delegate)
        } label: {
            Image(systemName: "paperplane.fill")
        }
        .menuBarExtraStyle(.window)

        Settings {
            SettingView()
        }
    }
}
```

```swift:ContentView
import SwiftUI

struct ContentView: View {
    @ObservedObject var delegate: AppDelegate
    var body: some View {
        VStack {
            Label("環境設定", systemImage: "slider.horizontal.3")
                .onTapGesture {
                    delegate.openPreferences()
                }
        }
        .frame(width: 200, height: 100)
    }
}
```

```swift:SettingView
import SwiftUI

struct SettingView: View {
    var body: some View {
        TabView {
            Text("General")
                .tabItem {
                    Label("General", systemImage: "gear")
                }
            Text("License")
                .tabItem {
                    Label("License", systemImage: "book")
                }
        }
        .frame(width: 300, height: 300)
    }
}
```

# おわり
まじで困ってたので助かりました

# 参考記事
https://zenn.dev/kyome/articles/ed44135f7a2093

https://zenn.dev/mtgto/articles/70ebd7737aa068
Playwright自分メモ

https://playwright.dev/python/docs/intro

### インストール(mac)

    pip3 install playwright
    python3 -m playwright install
    pip3 install pytest-playwright
    pip3 install pytest-xdist


### サンプル生成

    playwright codegen URL -o sample.py
    playwright codegen URL -b firefox -o sample.py
    playwright codegen URL -b webkit -o sample.py

### 基本

    browser = playwright.chromium.launch(headless=True)
    context = browser.new_context()
    page = context.new_page()
    page.goto(a_url)

### インタラクティブに

    from playwright.sync_api import sync_playwright

    playwright = sync_playwright().start()
    browser = playwright.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto('https://google.com')


### スクショを撮る

     page.screenshot(path="a.png")

### 特定の要素だけを撮る

    page.locator("#some_id").screenshot(path="b.png")


### htmlで保存

    with open("a.html", 'w') as f:
      f.write(page.content())

### タイムアウトさせない(無限に待つ)

    page.set_default_timeout(0)


### ブラウザのサイズ変更

    page.set_viewport_size({"width": 4000, "height": 1000})


### ファイル添付

    page.locator("#hoge").set_input_files("some/file.csv")



こっちでも

    page.locator("#hoge").set_input_files(files=[{"name": "empty.csv", "mimeType": "text/plain", "buffer": b",,,"}])


### pytest

    pip3 install pytest pytest-playwright


```python:test.py
from playwright.sync_api import Playwright, sync_playwright, expect

def test_example_is_working(page):
    page.goto(URL)
    expect(page).to_have_title("hoge")
```


    pytest --headed --screenshot=on --browser=chromium --browser=webkit --browser=firefox test.py


page　を引数にすると、browserはpytestの引数で動き出す！


    PWDEBUG=1 pytest test_hoge.py

で起動すると、インスペクターでデバッグできる



### waitの使い分け

基本は

    page.wait_for_load_state()

でよさそう。ajaxで画面が切り替わらず、通信する場合は

    page.wait_for_load_state("networkidle")

で待つと良さそう

### アサーション

    expect(page.locator("#hoge")).to_have_text("fuga")

をよく見るが、to_have_textは完全一致っぽい。
正規表現もいける

    expect(page.locator("#hoge")).to_have_text(re.compile(".*fuga.*"))
が

    expect(page.locator("#hoge")).to_contain_text("fuga")

の方がシンプルで好き。
[Linux] ubuntu20.04のPCにCUDA, cudnnをインストールする

# やること  
例としてubuntu20.04のPCにCUDA11.3, cudnn8.4.1をインストールする。

# 手順
## CUDA  
参考手順は[こちら](https://developer.nvidia.com/cuda-11.3.0-download-archive?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=20.04&target_type=deb_local)

以下のコマンドを実行  
```
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.3.0/local_installers/cuda-repo-ubuntu2004-11-3-local_11.3.0-465.19.01-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-11-3-local_11.3.0-465.19.01-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu2004-11-3-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda-11.3
```

sudo apt-get update 時に以下のエラーが出た場合、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077648/e0c5cb3a-b8ba-da55-862b-c2c53fbbac24.png)

[こちら](https://www.nemotos.net/?p=5178)を参照に解決する。


## cudnn
参照手順は[こちら](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html)
cudnn, cudaの対応関係は、[こちら](https://docs.nvidia.com/deeplearning/cudnn/support-matrix/index.html)からたどる

・[こちら](https://developer.nvidia.com/rdp/cudnn-archive)のDownload cuDNN v8.4.1 (May 27th, 2022), for CUDA 11.x」->「Local Installer for Linux x86_64 (Tar)」から、tarをカレントディレクトリにダウンロード

・次に以下のコマンドを実行
```
tar -xvf cudnn-linux-x86_64-8.4.1.50_cuda11.6-archive.tar.xz
sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda-11.3/include
sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda-11.3/lib64 
sudo chmod a+r /usr/local/cuda-11.3/include/cudnn*.h /usr/local/cuda-11.3/lib64/libcudnn*
```

## 環境変数の設定  
・以下のコマンドを実行
```
sudo nano ~/.bashrc
```
.bashrcに以下を追加
export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH"

Crtl o   Enter　で編集完了
Ctrl x　で閉じる

source ~/.bashrcで有効化し、nvcc -Vで cuda 11.3が表示されることを確認
Go：健康データの簡易APIサーバーの作り始め

作成：2023年1月11日

体重など健康データを保存するアプリとバックエンドを作ってみたく、Go でバックエンドを作成する為の情報収集と練習の為に、バックエンドをシンプルなGo言語で書いてみます。

# 事前準備

Postmanをインストールしておきます（[参考リンク](https://qiita.com/nlog2n2/items/b5e11332087c335e126e)）

# 簡易APIサーバー

GETするコードです（githubのコード置き場：[qiita20210111](https://github.com/ryoyuki6/go-api202301/blob/qiita20230111/main.go)）
```go:main.go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

type HealthData struct {
	UserID      int       `json:"user_id"`
	Weifgt   float64   `json:"weight"`
	Date time.Time `json:"date"`
}

var health_data = []HealthData{{
	UserID:      1,
	Weifgt:   55.5,
	Date: time.Now(),
}, {
	UserID:      2,
	Weifgt:   66.6,
	Date: time.Now(),
}, {
	UserID:      3,
	Weifgt:   77.7,
	Date: time.Now(),
}}

func main() {
	handler1 := func(w http.ResponseWriter, r *http.Request) {
		var buf bytes.Buffer
		enc := json.NewEncoder(&buf)
		if err := enc.Encode(&health_data); err != nil {
			log.Fatal(err)
		}
		fmt.Println(buf.String())

		_, err := fmt.Fprint(w, buf.String())
		if err != nil {
			return
		}
	}

	// GET /tasks
	http.HandleFunc("/health_data", handler1)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

```

実行します。
```
%go run main.go
```

ポストマンでGETできていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/005eeeef-bee0-f849-d5a3-392eda1f4b35.png)

今後、各種機能追加を進めます。


参考
・[[初心者向け] Golang でシンプルな JSON API を作る](https://zenn.dev/tatsurom/articles/golang-simple-json-api)
・[GoでCRUD処理のREST APIを作ろう〜Reactを添えて〜](https://qiita.com/2san/items/dd2c6d0449262a42b728)
　　　タスク管理アプリ、Go、React、MySQL、Docker
・[Goで超簡単API](https://qiita.com/k-penguin-sato/items/8088b69304ee7e8f70be)
【MUI】DataGridのrenderCellでボタンを追加して押してみてもStateを更新できなかった件

### やりたかったこと
DataGridで作成した表のセルの中にボタンを配置し、ボタンを押すと押した行の特定の値がuseStateで設定したStateにどんどん追加されていくような仕組みを作りたかった。

```react: App.tsx
function App() {
    // ボタンが押された行のValueを追加していく配列のState
    const [data, setData] = useState<string>([]);

    // ボタンが押された時の処理
    const handleClick = (value: string) => {
        setData([...data, value]);
    };

    // カラムの定義。ボタンを配置するセルにはrenderCellを利用。
    const column: GridColDef[] = [
        { field: "id", headerName: "ID" },
        { field: "value", headerName: "Value" },
        {
          field: "button",
          headerName: "Button",
          renderCell: (params) => <Button onClick={() => handleClick(params.row.value)} ><AddBoxIcon /></Button>
        }
    ];

    {/* 色々と省略 */}

    return (
        <DataGrid
          columns={column}
          rows={row}
        />
    );
}
```

### 起きたこと
ボタンを押すたびにStateの配列に値が追加されていくつもりだったが、実際は最後に押した行の値しか入っていないという悲しい状態が発生した。


### 対策
renderCellでレンダリングされたボタンの関数が初期値のまま更新されていないことが原因っぽい。
ありがたい助言をもらって回避できた方法は以下の通り。

```react: App.tsx
function App () {
    const [data, setData] = useState<string>([]);

    const handleClick = (value: string) => {
        setData([...data, value]);
    };

    // 使用する関数の型が入るようにuseRefを設定
    const handleClickRef = useRef<(value: number) => void>(); 
    
    // dataのStateが変更されるたびに関数のuseRefに最新の関数を登録
    useEffect(() => {
        handleClickRef.current = handleClick;
    },[data]);
    
    const column: GridColDef[] = [
        { field: "id", headerName: "ID" },
        { field: "value", headerName: "Value" },
        {
          field: "button",
          headerName: "Button",
          // 呼び出し時にuseRefがundefinedの場合を考慮しないと怒られるので関数が登録されていない時はnullを返すようにする
          renderCell: (params) => <Button onClick={() => handleClickRef.current ? handleClickRef.current(params.row.value) : null} ><AddBoxIcon /></Button>
        }
    ];

// ...以下省略
}
```
エンジニアインターン1日目

今日は基本単純作業を行った。
今日は学ぶことより感じたことの方が多かった。
ゴリゴリ開発している先輩エンジニアの横で単純作業…
恥ずかしい気持ちと悔しい気持ちがあった。
一日も早く自立できるエンジニアになりたいと思った。
そう思うからこそ今やっていることを一生懸命取り組んでいきたい。
Always FreeのOracleCloud上にNextcloud環境を構築するときの注意

# 前提
今回はAlways FreeのOracle Cloud上にNextcloudの環境構築をいたしました。その時につまずいたところなどを共有できればと思います。

**構築環境**
NextcloudサーバーOS：Ubuntu20.04(OracleCloud上のCompute)
computeのシェイプ：VM.Standard E2.1.micro
ストレージ：OCIブロックボリューム100GB

# Nextcloudとは
Nextcloudはオープンソースのオンラインストレージになります。簡単に言うとサーバー上にGoogle Driveのようなストレージを作れる製品です。

詳しくは以下のサイトをご覧いただければと思います。
Nextcloudについて　株式会社スタイルズ(https://nextcloud.stylez.co.jp/)


# Nextcloud構築の参考サイト

https://docs.oracle.com/ja/learn/oci_nextcloud_ampere_a1/index.html#introduction


# 注意1.対応OSを確認する
対応しているOSだとsnapコマンドで簡単に構築が完了いたします。初めての方であればそちらで作っていただくのが良いかと思います。(対応していないOSだと一から自分で構築する必要があります。私は最初対応していないOSでやろうとして苦労しました。)
Nextcloudが対応しているOSは以下の通りです。

・Ubuntu 22.04 LTS (recommended)
・Ubuntu 20.04 LTS
・Red Hat Enterprise Linux 8 (recommended)
・Debian 11 (Bullseye)
・SUSE Linux Enterprise Server 15
・openSUSE Leap 15.4
・CentOS Stream
　

Nextcloudホームページより↓

https://docs.nextcloud.com/server/stable/admin_manual/installation/system_requirements.html

この中で**Always Freeの環境で使えるのがUbuntuとCentOS**なのでこのどちらかのOSを選ぶことをお勧めいたします。

Oracle CloudのAlways Free環境で使えるリソース一覧

https://docs.oracle.com/ja-jp/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm


# 注意2．ストレージの変更先について(Ubuntu22.04)
今回OCIの環境でコンピュートにNextcloud用の別のストレージをアタッチして使う予定でした。デフォルトの保存先をアタッチしたストレージに保存先を変更する際にNextCloudの設定ファイルを少しいじるのですが、Ubuntu22.04では設定が反映されずエラーとなってしまい、ストレージの保存先の変更がうまくいきませんでした。

まだUbuntu22.04でうまくいかないかの原因究明ができていないのでこれからできればと思っております。

これについて何かご存じの方いらっしゃいましたらお教えいただけると幸いです。



# 参考リンク
### Oracle Cloud公式ホームページ
https://www.oracle.com/jp/cloud/free/

### Nextcloud公式ホームページ

https://nextcloud.stylez.co.jp/

https://nextcloud.com/ 

### Nextcloud構築参考サイト(上に載せたものと同じ)

https://docs.oracle.com/ja/learn/oci_nextcloud_ampere_a1/index.html#introduction
SQL構文の基本

[ Google データアナリティクス ]( https://www.coursera.org/programs/dentsu-xph6d?collectionId=Whz2N&currentTab=CATALOG&productId=aJbRXK7pEey8UArux7BqFw&productType=s12n&showMiniModal=true )の序盤でSQLについて軽く学んだので、今後本格的に使うことを考えて簡単なメモを作ってみました。中盤で再びSQLを使う予定なので、その際にまた本格的な記事を書こうと思います。

## 構造化クエリ言語（SQL）について
SQLはデータベースの操作に使うプログラミング言語です。**データの保管・整理・分析に特化**しているので、他のプログラミング言語より**大規模・大量・高速で動作**することが可能です。
Excelの最大行・列数は1048576(約100万)、最大データ数は1099511627776(約1兆)なので、それ以上のデータを処理する場合はスプレッドシートではなくデータベースとSQLを用いる必要があります。

https://ja.wikipedia.org/wiki/SQL


## SQL構文の基本

SQL クエリの構文は、多くの場合このように記述します。

- SELECT を使用して、求める列を選択する
- FROM を使用して、必要な列が存在するテーブルを選択する
- WHERE を使用して、特定の情報をフィルタする

SQL クエリはプログラミング言語の基本として、大文字とインデントを使用すると読みやすくなります。また、セミコロンをステートメント終了文字として用います。
WHERE 句を使って複数のフィールドを使用する BigQueryは、このように記述します。

```sql
SELECT
	customer_id,
	first_name,	
FROM
	customer_data.customer_name
WHERE 
	customer_id>0
	AND first_name = "Tony"
	AND last_name = "Magnolia";

```

## SQL構文の使い方
WHERE 句でクエリを絞り込むことにより、値が一致するデータ・または特定の条件に一致するデータのみを抽出することができます。例えば姓が Chavez のデータを検索する場合、WHERE 句は次のように書きます。
また、LIKE句で姓が "Ch" で始まるすべてのデータを検索することもできます。

```sql
WHERE field1 = 'Chavez'
WHERE field1 LIKE 'Ch%'
```

SELECT * 句はすべての列を選択する際に用います。
SELECT *などを使うとべらぼうな量のデータが選択されるため、慎重に使いましょう。

```sql
SELECT *
FROM table
```
列名・テーブル名には変数に相当する**エイリアス**を割り当てることができます。これには、SQL の AS 句を使用します。

```sql
field AS last_name -- 列のエイリアス
table AS customers -- テーブルのエイリアス

SELECT *
FROM album
WHERE "album_id" = 277
```
lambda expression を functional interface に

lambda expressionはmethodそのものを表していて
method reffereceのように扱える

以下はfunctional interfaceのFactoryInterface#get()に対して
外部からlambda expressionを代入して、切り分けすることにより
SampleClassA⇒SampleClassBに変更した際に、businessLogicに影響を与えない

```java
interface FactoryInterface<T>{
    T get();
}
interface SampleInterface{
    void method();
}
class SampleClassA implements SampleInterface {
    public void method() {
        System.out.println("I am SampleClassA method");
    }
}
class SampleClassB implements SampleInterface {
    public void method() {
        System.out.println("I am SampleClassB method");
    }
}
public class Outer {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.businessLogic(() -> {return new SampleClassA();});
    }
    void businessLogic(FactoryInterface<SampleInterface> fi) {
        SampleInterface si = fi.get();
        si.method();
    }
}
```
```
I am SampleClassA method
```
argument, lambda expressionでfunctional interfaceを呼び分ける
```java
public class Outer {
    public static void main(String[] args) {
        method(() -> System.out.println(""));
        method(() -> "");
        method((x) -> {System.out.println("");});    //blockにしないとFunctionも候補、曖昧エラー。理由不明
        method((x) -> "");
    }
    static void method(Runnable r) {
        System.out.println("runnable argument");
    }
    static void method(Supplier<String> s) {
        System.out.println("Supplier argument");
    }
    static void method(Consumer<String> c) {
        System.out.println("Consumer argument");
    }
    static void method(Function<String, String> f) {
        System.out.println("Function argument");
    }
}
```
```
runnable argument
Supplier argument
Consumer argument
Function argument
```
[OutSystems]Timerを停止できるように作る

OutSystemsでバッチ処理を作るのに使うTimerは、実は外部から強制的に止める手段が、（アプリレベルでは）無かったりする。

そこで、Timerでループを作るときは外部からTimerを停止できるようにロジックを組んでおくとよいかもしれない。

# Timerを止めたくなるとき
たとえば、
- 開発中のTimerでうっかり無限ループを仕込んでしまった
- 長時間かかるTimerが走り始めたが、データの不備に気付いた
- 本番運用中のTimerがデータの急増等でTimeoutを超える時間動作した（Timeoutになるとエラーになるが、一定時間後リトライが走ってしまう）
- パフォーマンスや調査の都合上、今動いているTimerを一時止めたい

# Service Centerには実行中のTimerを止めるUIがない
各環境でTimerを管理するUIは、Service Center > 各モジュールページ > Timersタブだが、実行中のTimerを停止することはできない。

# 実装案：Site Property (Boolean型）を判定し、Timerの実行を中断できるようにする

## Boolean型のSite Property (Entityでもよい）としてフラグを用意しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/b192e79a-fd56-1410-0309-90cd92ffd5e3.png)

## Timer Actionのループでフラグをチェックして分岐させる
ループを持つTimer Actionは、ループの先頭でフラグの値をチェックし、Trueであれば直ちに処理を中止（End要素に分岐）する（下の赤枠部分）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/dc500a7b-3f7a-86ae-329a-26565c253295.png)

If要素の設定は以下のように、フラグのSite Propertyの値をセット。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/42d96bce-b1d0-5565-80fe-37f4b0484259.png)

## Timerを停止したいときは、フラグをオンにする
操作はService Centerで行える（モジュールページ > Site Propertiesタブから）。
Vueで地味にハマったところ

Vueで地味に2日間ハマった箇所についてまとめます。

# Veturのエラーがうるさい問題 Vetur(1192)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/81cc8cc2-ee7f-04cb-a485-63e7fa44b28d.png)

この記事を読んでいてい、ぶっちゃけVetureいらない気がしたのでVetureアンインストールしました。
実際、動きますしコード的には合っているので。

https://qiita.com/TakuTaku04/items/d3a54218ece59e83e764

# 型おかしい問題

**どこが間違っているでしょうか??**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502127/46bea0e6-69ac-1d90-8834-59490aa2f79f.png)

<details><summary>正解</summary><div>

```vue
<script lang="ts"> // ×
<script setup lang="ts"> // 〇
```

</div></details>

`ts(1192)`も出ていたのですが、これで解消できました。
Vueアプリケーションで役立ちそうなあれこれ

# スタイルを動的に変える

```vue:スタイルの動的変更
<style scoped>
.input-name{
    /* 変数を割り当てられる */
    background-color: v-bind(color);
}
</style>

<script setup lang="ts">
// 文字列の長さに応じてスタイルを変更
const nameLengthLimit = 15
const isValidName = computed(() => {
    if (inputtingName.value.length >= nameLengthLimit) {
        return false
    } else {
        return true
    }
})

const color = computed(() => {
    return isValidName.value ? "white" : "rgb(244, 194, 90)"
})
</script>
```

# ボタンの無効化

```vue:ボタンの無効化
// buttonタグのdisabled属性で可能
// v-bindでTypeScriptの値を渡す
<template>
    <div>
        <button :disabled="!isValidName">register</button>
    </div>
</template>
```

# 確認アラート

```vue
<script setup lang="ts">
// confirm関数
const onClickDelete = () => {
    if (confirm("hoge")) {
        // OKの場合の処理
    }
}
</script>
```

# 参考
https://www.udemy.com/course/vue3-typescript/
enum

Enum classのsub classとなる
each elementがjvmによりinstance化される
enumを参照した時点でenumの各要素がconstructorを通してインスタンス化される
default toString()はあくまでenumの要素名(PAN,GOHAN)をreturnする。
valueをreturnしたいときはtoString()をoverrideする。

```java
enum EnumSample{
    PAN("hello-pan"),GOHAN("hello-gohan");
    String value;
    private EnumSample(String value) {
      System.out.println(value);
      this.value = value;
    }
}
enum EnumSample2 {
    APPLE(),ORANGE();
}
enum EnumSample3{
    PAN("hello-pan"),GOHAN("hello-gohan");
    String value;
    private EnumSample3(String value) {
      this.value = value;
    }
    public String toString() {
      return value;
    }
}

public class SampleProject {
    public static void main(String[] args) {
      System.out.println("------------------");
      System.out.println(EnumSample.PAN);
      System.out.println(EnumSample2.ORANGE);
      System.out.println(EnumSample3.PAN);
      Enum e = EnumSample2.valueOf("APPLE");
      System.out.println(e);
      System.out.println("------------------------------");
      Method m[] = e.getClass().getMethods();
      for(Method mc:m){
          System.out.println(mc);
      }
      System.out.println("------------------------------");
      System.out.println(EnumSample2.values()[0]);
      System.out.println(String.valueOf(EnumSample3.values()[0]));
    }
}
```
```
------------------
hello-pan
hello-gohan
PAN
ORANGE
hello-pan
APPLE
------------------------------
public static sampleproject.EnumSample2[] sampleproject.EnumSample2.values()
public static sampleproject.EnumSample2 sampleproject.EnumSample2.valueOf(java.lang.String)
public final java.lang.String java.lang.Enum.name()
public final boolean java.lang.Enum.equals(java.lang.Object)
public java.lang.String java.lang.Enum.toString()
public final int java.lang.Enum.hashCode()
public int java.lang.Enum.compareTo(java.lang.Object)
public final int java.lang.Enum.compareTo(java.lang.Enum)
public static java.lang.Enum java.lang.Enum.valueOf(java.lang.Class,java.lang.String)
public final java.lang.Class java.lang.Enum.getDeclaringClass()
public final int java.lang.Enum.ordinal()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
------------------------------
APPLE
hello-pan
```
Dartでのmixinと継承の使い分け

[iPresence](https://ipresence.jp/)では複数種類のロボットを1つのモバイルアプリからzoom等と連携して遠隔操作するアプリを開発しています。
その際アプリ側では1つのエントリーポイントから設定されたロボットにコマンドを渡しつつ各ロボット固有の機能も動作させる必要があります。

![アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2846848/5e17baeb-db79-a1b1-0e9d-d2ea082ed226.png)


そこで全てのロボットに共有の動作とロボット固有の機能の動作を切り分けつつシンプルに書くためにDartのmixin/withの機能を使用します。

## mixinと継承の違い

抽象クラス(abstract)を継承するのとmixinクラスを使用する際の違いは以下になります

### 抽象クラスの継承

- すべてのメソッドをオーバーライドし実装する必要がある。
- 1つの子クラスに対して1つの親クラスしか渡せない

### mixin

- 必ずしもメソッドをオーバーライドする必要はない
- 1つのクラスに対して複数mixinすることができる
- コンストラクタを定義できない

このようにそれぞれにメリット/デメリットがありますが、うまく使い分けることで効果を発揮します

## 実装
以下の様に共通する機能と固有の機能の切り分けに使うことができます。

```dart

// 共通機能を定義したmixinクラス
// ロボットを操作するメソッドを仮実装する
mixin RobotCtlRepository{
  void robotControl(){
    throw UnimplementedError();
  }
}

mixin RobotSetUpRepository{
  void setup(){
    throw UnimplementedError();
  }

  void deleteSetting(){
    throw UnimplementedError();
  }
}

// RobotA の固有機能のクラス
// RobotCtlRepository をmixinすることで robotControlメソッドも内包される
abstract class RobotARepository with RobotCtlRepository{
  Future<void> robotAFunc();
}

// 同じようにRobotB,Cもそれぞれ専用の抽象クラスを定義してmixinさせる
// mixinをするので複数のクラスRobotCtlRepositoryとRobotSetUpRepositoryをもたせることもできる
abstract class RobotBRepository with RobotCtlRepository, RobotSetUpRepository{
  String robotBFunc();
}

abstract class RobotCRepository with RobotCtlRepository, RobotSetUpRepository{
  void robotCFunc();
}
```

このように抽象クラスに対してmixinすることで共有の機能をもたせることができるようになります。
またこれに対する実装は以下のようになります。


```dart
// メソッドの実装

class RobotARepositoryImpl extends RobotARepository{
  @override
  Future<void> robotAFunc() async{
    await robot_a_function;
  }

  @override
  void robotControl(){
    robotA.move();
  }
}

class RobotBRepositoryImpl extends RobotARepository{
  @override
  String robotBFunc(){
    return "robotB";
  }

  @override
  void robotControl(){
    robotB.pan();
  }

  @override
  void setup(){
    robotB.setup();
  }

  @override
  void setup(){
    robotB.deleteSetting();
  }
}

class RobotCRepositoryImpl extends RobotARepository{
  @override
  void robotCFunc(){
    robot_c_function;
  }

  @override
  void robotControl(){
    robotC.tilt();
  }

  @override
  void setup(){
    robotC.setup();
  }
  // mixinなのでdeleteSettingはオーバーライドしなくてもいい
}
```

## 終わりに
mixinと継承を組み合わせ、使い分けることで柔軟で拡張性のある実装ができるようになります。
どのように切り分けるかなどは規模や設計・開発方針にもよってくるので適宜使っていくのがいいと思います。
Secualのサービスについて

# 概要
株式会社Secualのサービスについてまとめました。

# サービス
secualのサービスは、主に以下の3つがあります。（他にもありますが、一旦3つだけ）
①Secual Home
②NISUMU
③NISUMU RENT
また、NISUMUはスマートタウン向けの事業で、④スマートポールが使われています。
これらの仕様をまとめていきたいと思います。

## ①Secual Home
### 機能
1. ホームセキュリティ 
防犯・見守りの役割を果たす。防犯モードの場合、センサーが異常を検知すると、大音量でブザーが鳴り、侵入犯を威嚇する。見守りモードの場合は、人に動きがないかを検知する。
これらは、センシング技術が使われており、センサーで検知した後「Secual Home」のアプリに通知を送る。

2. ホームIoT
赤外線のついている家電（エアコン、照明、TVなど）を「Secual Home」のアプリに登録することで、スマホから家電を操作することができる。クラウド技術が使われている。

### 登場デバイス
1. 人感センサー
人の動きを検知することができる。また、温度、湿度、照度センサーも内蔵しており、アプリで確認できる。見守り機能で人が動いていなかった場合など、このセンサーが役割を果たす。大体、下方3m範囲で検知できるっぽい。

2. 開閉センサー
窓の開閉や振動を検知できる。防犯モードのときに役割を果たす。

3. Wifiゲートウェイ・SIMゲートウェイ
センサーを管理する機器。人感センサーや開閉センサーが異常を検知すると、まずこのゲートウェイに送信され、ブザーを鳴らす。その後、アプリに通知が来る。

4. Secual Cam
動きがあったときのみ、15秒録画を開始する。アプリからその録画を見ることができる。

## ②NISUMU
国内初の※スマートタウン向け統合サービス
※スマートタウンとは
デジタル技術を用いて、企業や人々が快適に便利に住めるよう目指された街。

屋内と屋外で両方のサービスがNISUMUアプリでは使える。
屋内⇒ホームセキュリティ
屋外⇒タウンセキュリティ

### 機能
1. ホームセキュリティ
Secual Homeのサービスがまるまる使える。

2. タウンセキュリティ
スマートポールによって、屋外での防犯・防災・見守り、またコミュニティ活性化の役割を果たす。
（スマートポールは、後で説明します）

3. その他便利機能
スマート宅配ボックス、備品貸し出し・荷物ロッカー、警備員駆けつけサービスなどこれ以外にも、様々な機能がある。

## ③NISUMU RENT
NISUMUはタウン向けのサービスで、NISUMU RENTは賃貸向けのサービス。似ているが違いがある。
secualと契約している不動産会社の賃貸物件でsecualのサービスを使うことができる。

### 機能
1. ホームセキュリティ
Secual Homeのサービスがまるまる使える。

2. ホームIoT
Secual Homeのサービスがまるまる使える。

つまり、見守り・防犯機能のセキュリティサービスやスマート家電リモコンに様々家電をつなげて操作したり、NISUMU GUARDで駆けつけをしたりが、賃貸物件で利用することができるということ。

## ④スマートポール (SP)
スマートポールのシステムは、2つある。住宅街向けはNISUMU、その他はSmart Pole。
スマートポールは新しい言葉で、意味は"次世代インフラ"

### スマートポールの3つの役割
1. 安心・安全の役割
フルカラーＬＥＤ、スマートカメラ、見守りタグ機能により、防災・防犯・見守りの役割を果たす。それぞれについて説明する。 
１）フルカラーLED（情報通知機能）
気象庁の防災情報と連動して、スマートポールのカラーインジケーターの色が変わる。また、不審者を見つけた際も赤に色が変わったりする。⇒防災・防犯
２）スマートカメラ（AIカメラ機能）
・リアルタイム視聴可能
・1~2週間クラウドで記録できる。
・AIセンシングで、交通量カウント・混雑検知・滞留検知・侵入検知などすることができる。
３）見守りタグ連携（見守りタグ連携機能）
子供や高齢者がタグを所持しているので、そのタグを検知する。⇒ 管理画面で居場所がわかる。

2. コミュニティの役割
１）イルミネーション機能
季節やイベントと連動して、色を変えられる。
２）フリーWifi機能
スマートポールがアクセスポイントになり、Wifiサービスを提供する。
３）情報配信機能
・ビーコンと連動した様々な情報配信
・スマホからWifiしんごうを受信し、人流検知と行動解析を行う。

3. 拡張性
１）ソフトウェアアップデート可能
２）モジュール構造なので、ハードウェアをどんどん追加できる。
【Rails】Webpacker::Manifest::MissingEntryErrorの対処方法

# 0. 環境
macOS Ventura 13.1
Ruby on Rails 6.0.5
Ruby 2.7.7
yarn 1.22.19

# 1. エラー発生状況
Railsでアプリを作成し、`http://localhost:3000/(コントローラ名)/1`にアクセスしたところ、次のエラーが発生した。

```:view
Webpacker::Manifest::MissingEntryError

Webpacker can't find application in /Users/username/myapp/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
   unless you are using the `webpack -w` or the webpack-dev-server.
2. webpack has not yet re-run to reflect updates.
3. You have misconfigured Webpacker's config/webpacker.yml file.
4. Your webpack configuration is not creating a manifest.
Your manifest contains:
...
```

# 2-1. 対処方法①
[こちらの記事](https://qiita.com/negisys/items/2bf88659f584fe45b686)を参考にし、次のコマンドを実行した。

```zsh:zsh
rails webpacker:install
rails webpacker:compile
```

webpackerのインストールができたと思いきや、エラーが発生していた。

```zsh:zsh
error /Users/username/myapp/node_modules/node-sass: Command failed.
```

```zsh:zsh
error Command "webpack" not found.
```

# 2-2. 対処方法②
[こちらの記事](https://qiita.com/hryau6/items/820d0b404325688574ba)を参考にし、以下の手順を実施した。

#### 1. gem 'webpacker'のバージョンを上げる
```diff_ruby:Gemfile
-  gem 'webpacker', '~> 4.0'
+  gem 'webpacker', '~> 5.0'
```

#### 2. yarn.lockを削除する

#### 3. package.jsonに"@rails/webpacker"を追記する
```diff_json:package.json
{
  "dependencies": {
+   "@rails/webpacker": "5.4.3"
  }
}

```

#### 4. yarn installを実行する
```zsh:zsh
yarn install
```

#### 5. yarn add node-sassを実行する
```zsh:zsh
yarn add node-sass
```

#### 6. bundle installを実行する
```zsh:zsh
bundle install
```

# 2-3. 対処方法③
再度以下のコマンドを実行した。
```zsh:zsh
rails webpacker:install
rails webpacker:compile
```

その後、`rails s`を実行し、`http://localhost:3000/(コントローラ名)/1`にアクセスすると、正常にビューが表示された。
Reactでスプレット構文を書いてみた

<h1>概要</h1>
今回は、Reactの内でスプレット構文の基本的な書き方についてご紹介いたします。

スプレット構文が書けるようになると配列やオブジェクトを展開する際に
定義した要素を順にまとめて展開できるようになるのでコードを省略して書くことができます。


<b>注意点</b>
Reactを用いてスプレット構文（その他の定義コードにも共通する）は

<b>「const」</b>　と　<b>「return」</b>　の間に書くこと。

<h1>スプレット構文の書き方</h1>
下記のコードがReactを使用したスプレット構文の基本的な書き方になります。

```jsx
import React from "react";

const Test: React.FC = () => {
  const array = [1, 2, 3];
  console.log(...array);
  return <div>array</div>;
};

export default Test;
```

<b>出力結果</b>
 - ブラウザ上
「<b>array</b>」という文字が表示されます。

 - コンソール上
 「<b>1 2 3</b>」とカッコの取れた状態で表示される。



<h2>スプレット構文部の「解説」</h2>

<b>3行目の配列に数字の1,2,3の要素を格納いています。</b>
```jsx
  const array = [1, 2, 3];
```


<b>4行目でスプレット構文を用いて要素を順に展開し、
コンソール上に出力しています。</b>
```jsx
 console.log(...array);
```

<b>5行目で「arrey」という文字列をブラウザ上に出力しています。</b>

```jsx
 return <div>array</div>;
```
 
<b></b>




<h1>まとめ・今後の課題</h1>
今回はReactでのスプレット構文の書き方についてのまとめました。

他にも記事を投稿しますので、ぜひチェックしてみてください。
(macOS) MYSQL@8.0 で、Access denied for user 'root'@'localhost' (using password: NO)を解決する

```
mysql -uroot
```
上記のコマンドでMySQLサーバーにrootログインしようとしたところ、表題のエラーが発生しました。
※同時に、MySQLプロセスをKillしてもPIDを変えて復活する問題も発生しました。

＜原因＞
・launchctlによりMySQLが自動で起動していた。

＜解決法＞
こちらの記事を参考にしました。

https://qiita.com/Komei22/items/31a3db6d5b803ef5082b

https://qiita.com/yummy888/items/25621bc1451f218e010a
アクツクMV：変数の内容を表示する

アクションゲームツクールMV（アクツクMV）で変数を表示する方法を解説します。
わかってしまえば、非常に簡単なのですが、若干癖がありますので、解説をさせていただきます。

１．フォントを設定する。
アクツクMVは、テキスト表示がめんどくさいです。まず、フォントを登録しないといけません。
フォントはサイズも固定した形で登録になります。なので、おなじフォントでも大きさ（ポイント）をいろいろ変える場合には大きさごとに登録することになります。（追記：テキストのタグ「\S[]」を使って部分的に大きさを変えることは可能です。https://rpgmakerofficial.com/product/act/manual/07_03.html 参照）

とりあえず、「素材」の「フォント」から「フォントを追加」してください。名前はなんでもいいですが、ここでは「font36」としました。３６ポイントという意味です。
簡単な設定がありますので、TureTypeフォントを使用をチェックし、右横の数字（ポイント数）を３６にしてください。
![Variable01font.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/45837171-5084-27ff-4725-d35f0b1643bc.png)

２．変数の表示用オブジェクトを作る。
フォントができたら、表示用のオブジェクトを作ります。
名前はとりあえず「デバッグ用変数表示」としました。
新しいオブジェクトを追加し（１）、表示の優先度を上げ（２）、当たり判定はすべて消します（３）。
表示の優先度の数字は、大きい数字が手前に表示されるので、適宜設定してください。0でも可。

「初期設定」のタブで、デバッグ用やカメラの位置関係を固定も必要ならばチェックします（４）（５）。
それ以外は全部チェックを外します。
アクションプログラムは、変更不要です。（重力の影響を受けないにした方がよいかもしれません）
![Variable02Object.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/3560529d-98eb-5eb1-c503-ee5554cff619.png)

３．変数を表示する設定をする。
「表示と親子関係」のタブで、一番上にある「オブジェクトにテキスト・変数値を表示」のところの「＋」をクリック。
「変数値を表示」をチェックして、その横の「変数を選択」の横の黒枠「（設定なし）」をダブルクリックすると、変数の選択画面がでてくるので、変数を選びます。ここでは「Player01」の「体力」としました。

さらに「テキストを表示」をチェック、テキストの色とフォントを設定します。色は色の部分をダブルクリックすると変更できます。今回は赤にしました。そして、フォントを最初に登録した「font36」にします。
![Variable04hyouji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/c7bdd64a-0218-90b9-f266-ab70b0273669.png)

４．メニューを初期シーンに設定する。（2023/1/13追記）
シーンにメニューを表示させる設定をしないと、メニューが表示されません。
初期シーンのシーン設定を開き（１）（２）、「初期表示メニュー画面」を、表示用オブジェクトを置く「メニュー１」に変更します。（３）
（他のシーンがあれば同様にします）

![Variable06SceneSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/0b4536e3-bad1-1a13-5885-55bba165604d.png)
５．メニューシーンにオブジェクト「デバッグ用変数表示」を置く。

シーンから、「menu scene」の「メニュー１」に、作ったオブジェクトを置きます。（１）（２）
ゲームを実行してみましょう。
メニューに置いたオブジェクトの位置に変数の値が表示されているはずです。（３）
![Variable04Screenpng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3103492/1de99926-9d5c-7732-2707-546f2bec5022.png)


「表示と親子関係」のタブの「オブジェクトにテキスト・変数値を表示」の「＋」を押せば、何個でも出せます。オフセットで表示位置を、スケールで大きさも変えられますし、回転もできます。

デバッグモードでいちいちオブジェクト情報を開いて、変数をチェックするより、直接画面に数値を表示したほうがわかりやすいので、私は大事なパラメータはこうして表示しています。

今回はデバッグ用として説明しましたが、デバッグ用でなくても使えます。

また、数値ではなく、ゲージ形式で表示も同様に簡単にできます。いろいろいじってちょうどいいものを見つけてください。（ゲージ形式はフォントの設定もいらないので、もっと簡単です）

次回はテキストに変数内容を埋め込んで表示してみます。→https://qiita.com/havin_nothin/items/039d955d39fcedaa93bd

ではまた。
$0 ← これについてものすごく簡単にアウトプットする

## はじめに
$0についてものすごく簡単にまとめるため、さらに探求したい方は各々ググり散らかしてください。

## 詳細
- $0とは引数を表現するものである。
    - \$以降の数字によって引数を指定することができる
    - $0を使った場合、クロージャーなどの引数は省略可能である

```swift:Swift
//元となる省略表現なしのクロージャー定義、
let sampleClosure: (String) -> Void = { sampleParameter in
    //わざわざ新たな変数に引数を格納するのはおかしいが、今回は見逃してください...
    let testSample = sampleParameter
    print(testSample)
}
//出力
sampleClosure("sampleClosureの引数sampleParameterを$0で省略する前の書き方")
//sampleClosureの引数sampleParameterを$0で省略する前の書き方


//$0(第一引数),$1(第ニ引数),$2(第三引数)と$以降の数字が上がるに連れて引数を指定できる
//第一引数のみ省略の場合
let testClosure: (String) -> Void = {
    let test = $0
    print(test)
}
//出力
testClosure("$0で第一引数が省略されているのを確認している")


//第一引数と第二引数を省略の場合
let testClosure1: (String, String) -> Void = {
    let test1 = $0
    let test2 = $1
    print("test1の省略表現: \(test1)\n test2の省略表現: \(test2)")
}
//出力
testClosure1("test1の出力確認", "test2の出力確認")
//test1の省略表現: test1の出力確認
//test2の省略表現: test2の出力確認
}
```

## おわりに
指摘事項ありましたらぜひご指摘ください。

## 参考記事
[[増補改訂第3版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plusシリーズ)　](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%AC%AC3%E7%89%88-Swift%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E7%9B%B4%E6%84%9F%E7%9A%84%E3%81%AA%E6%96%87%E6%B3%95%E3%81%A8%E5%AE%89%E5%85%A8%E6%80%A7%E3%82%92%E5%85%BC%E3%81%AD%E5%82%99%E3%81%88%E3%81%9F%E8%A8%80%E8%AA%9E-PRESS-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4297112132)
↑引用元
石川 洋資 (著), 西山 勇世 (著)
発行者：片岡 巌
出版社：技術評論社
印刷/製本：日経印刷株式会社

## 開発環境
- Xcode-13.4.1
- Swift version 5.7
AWS SDK V3 のSNS(Simple Notification Service)で、いくつか動作確認した話（AWS SDK V2 → V3 移行Tips）

# はじめに

https://qiita.com/Syoji_Yonemoto/items/f96a4d10b05715e95d1c

引き続いて、今度は、SNS（Simple Notification Service）についても確認しました。
と言っても、それ程、確認したメソッドは多くありません。

# 結論
SNS(Simple Notification Service)に関しては、私が普段使うメソッド群については、問題ありませんでした。
やはり、Firehoseだけが罠だったのでしょうか、、、

# V2 と同じ使い方で問題なく動作確認できたメソッド

+  subscribe
+  publish

# 余談
subscribeが、「何故あるのか？」というネタ話。その昔、SNS(Simple Notification Service)にLambdaをsubscribeするのに管理コンソールからは、「一覧に表示された１００件の中からしか選択できない。」というイケてないUIだった時代があって、LambdaからARNを指定して、subscribeを追加するという運用をしていた時期があった名残りです。
（今は、管理コンソールからARN指定でsubscribeが追加できるので、必要ない）

# まとめ
SNS(Simple Notification Service)は、publish(配信)さえ動けば、他は、どうとでもなりますからね。
引き続き、小ネタシリーズとして、 V2 → V3 の動作確認メモを書いていこうと思います。

# AWSの相談・お困りごとありましたら、、、

AWSの活用方法や、お困りごとの相談、随時、お仕事の受付しております。

https://www.cs-cloud-aid.com/
Qt でGUI  - ウィジェットを作る -

# ユーザーの操作に対応するボタンの設置

GUIを作るからにはマウスのクリックなどのユーザーの操作と結びついて, 何かしらのプログラムが実行されるようにしなければ意味がない. 今回はGUI上にボタンを設置して, ユーザーがそのボタンをクリックしたらウィンドウを抜けるというプログラムを作ってみる.
以下の本を参考にしています. インストールされているのがQt6 なのでinclude の場所が少し違うだけで基本的にはQt4 と同じ記述です.
[Qt4 プログラミング入門](https://www.oreilly.co.jp/books/9784873113449/)

## シグナルとスロット
Qt での言葉の定義として, シグナルとスロットがある
- シグナル　: ユーザー操作によるオブジェクトの状態変化.
- スロット : シグナルが送信されたときに行われる関数.

言葉だけを見てもわかりにくいが, 具体例を見てみると簡単なこと.
GUI 上にボタン (オブジェクト) があるとする.
ボタンに対してマウスでクリックという操作が行われると, ボタンというオブジェクトは「押されていない状態から押された」というように状態が変化する. このようなユーザー操作によるオブジェクトの状態変化をQt内部ではclicked() というシグナル関数が発生する.
このclicked 関数(シグナル関数)にプロラグムを終了させるquit　関数(スロット関数)を接続しておくと, 
シグナル関数が発生したときにquit 関数が実行されて, アプリケーションが終了する.
```mermaid
graph LR;
id1("GUI上でのクリック") --> id2("ボタン<br/>(オブジェクト)") --オブジェクトの<br/>状態変化--> id3("clicked() <br/>(シグナル関数)")--接続-->id4("quit()<br/>(スロット関数)") --> app --> プログラム終了;
```
## シグナルとスロットの接続

quit.cpp といしてファイルを作る.
```quit.cpp
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);
  auto *button = new QPushButton("Quit");
  QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
  button->show();
  return app.exec();
}
```
ボタンの設置には, QtWidgets/QPushButton オブジェクトを使う.
```cpp
QPushButton *button = new QPushButton("Quit");
```
引数でボタンに表示される文字列を指定できる.
オブジェクトで生成されるシグナル関数とスロット関数は
```cpp
QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
```
のようにQObject クラスのconnect 関数で接続する.
後はビルドする.
```bash
$ qmake -project
```
生成されたquit.pro の最終行に　QT+=widgets　を追加して,
```bash
$ qmake quit.pro
$ make
$ ./quit.app/Contents/MacOS/quit
```
とすれば, 以下のようにボタンができる.
ボタン上でクリックすれば, アプリケーションが終了する.
![スクリーンショット 2023-01-11 16.43.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777840/3f754f75-1bc1-46ae-8ba7-b7c5bc889173.png)

# ２つ以上のウィジェットの配置
1つのウィンドウに2 つ以上のウィジェットを並べる際には,
```cpp
Qwidget()
```
で親オブジェクトを作って, その中に子ウィジェットを配置する.
以下ではwindows という親オブジェクトを作って,その中にQspinBox とQslider を配置していく.
また, QspinBox の値とQSlider が同期するようにそれぞれシグナル関数とスロット関数を接続している.
```widget.cpp
#include <QtWidgets/QApplication>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QSlider>
#include <QtWidgets/QSpinBox>

int main(int argc, char *argv[]){
  QApplication app(argc, argv);
  auto *window = new QWidget();
  window-> setWindowTitle("Enter your Age");

  auto *spinbox = new QSpinBox();
  auto *slider = new QSlider(Qt::Horizontal);
  spinbox->setRange(0, 130);
  slider->setRange(0, 130);

  QObject::connect(spinbox, SIGNAL(valueChanged(int)),slider,SLOT(setValue(int)));
  QObject::connect(slider, SIGNAL(valueChanged(int)),spinbox,SLOT(setValue(int)));
  spinbox->setValue(29);

  auto *layout = new QHBoxLayout();
  layout->addWidget(spinbox);
  layout->addWidget(slider);
  window->setLayout(layout);
  window->show();
  return app.exec();
}
```

ウィジェットの配置については,
```cpp
auto *layout = new QHBoxLayout();
```
の部分でまずはウィジェットを左から右に配置するレイアウトを指定している.
もちろん他のレイアウトもあり, 主には以下があるらしい.
- QVBoxLayout :　上から下に
- QGridLayout : 格子状に
- QHBoxLayout :　左から右に

ウィジェットの格納は,
```cpp
layout->addWidget();
```
の部分で行われており, 今回は左からボックス, スライダーというようになるはず.
このように設定したレイアウトを
```cpp
window->setlayput(layout);
```
としてセットして無事に終了.
SpringBootのWebアプリでシステムトレイにアイコンを追加する

# 概要

- ローカルで動かす前提のSpringBootのWebStarterアプリで、Mac/Windowsでのメニューバー/システムトレイにアイコンを追加する方法です。
- PostConstructにてアイコンの初期化をすれば良さそうです。

## コード

```groovy
package com.example.demo

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.core.io.ClassPathResource

import javax.annotation.PostConstruct
import java.awt.AWTException
import java.awt.Image
import java.awt.SystemTray
import java.awt.Toolkit
import java.awt.TrayIcon
import java.awt.event.ActionEvent
import java.awt.event.ActionListener

@SpringBootApplication
class Demo6Application {
    static boolean initializedIcon = false

    static void main(String[] args) {
        SpringApplication.run(Demo6Application, args)
    }

    @PostConstruct
    def initIcon() {
        if (!SystemTray.isSupported()) {
            return
        }
        println("initIcon")

        Image image = Toolkit.getDefaultToolkit().createImage(
                new ClassPathResource("icon.png").getURL() ); // アイコン画像を準備
        TrayIcon icon = new TrayIcon(image, "Sample Java App"); // ※1 トレイアイコンとして生成
        icon.setImageAutoSize(true); // リサイズ

        try {
            icon.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    println("icon click")
                    icon.displayMessage("test1","tes2", TrayIcon.MessageType.INFO)
                }
            })

            SystemTray.getSystemTray().add(icon); // ※2 システムトレイに追加
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

}

```

Popupメニューとかそのあたりの追加は各自でどうぞ。

## Jarの起動オプション



for Mac
```shell
# ビルドする
./gradlew bootJar

# 実行する
java -Dapple.awt.UIElement=true -Djava.awt.headless=false -Dspring.profiles.active=dev -jar build/libs/demo6-0.0.1-SNAPSHOT.jar
```
bitnamiのRedmine(5.0.4)で管理者ログインする方法


# はじめに
AWSのEC2でbitnami Redmineを構築しました。

ネットで調べると、ログイン画面でログインID/パスワードともに `admin` で管理者ユーザーとしてログインできると書かれていたが、これではログイン出来なかった（おそらく以前のversionの話）。

**Redminのversion 5.0.4** では以下の方法で管理者ログイン可能でした。

# 管理者ユーザーのcredential

まず、構築したRedmineのEC2へSSHする。
※通常のEC2であればユーザーを`ec2-user`でsshログイン可能であるが、ユーザーを`bitnami`にする必要がある。

sshログインした直後のカレントディレクトリの　`bitnami_credentials` ファイルに
管理者ユーザーのユーザー名（ログインID）とパスワードが用意されています。

![スクリーンショット 2023-01-11 17.31.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/1d3aebbd-33e8-0431-a329-12dc4dbec591.png)
ログイン画面でこの２つを入力すれば無事にログインできます。


# 補足
以下、userが管理者権限を持っていると分かった根拠です。

v5.0.4の Redmineインストールディレクトリーは`/opt/bitnami/redmine` だが、
このディレクトリーでrails cすることができます。
```
bundle exec rails c -e production
```
ここでUser.allをしたところ、 loginが `user` のadminカラムが`true`でした。


```
 #<User:0x0000563f4df548c0
  id: 1,
  login: "user",
  hashed_password: "[FILTERED]",
  firstname: "UserName",
  lastname: "LastName",
  admin: true,
  status: 1,
  last_login_on: Wed, 11 Jan 2023 08:12:34.000000000 UTC +00:00,
  language: "",
  auth_source_id: nil,
  created_on: Fri, 06 Jan 2023 07:35:32.000000000 UTC +00:00,
  updated_on: Fri, 06 Jan 2023 07:35:32.000000000 UTC +00:00,
  type: "User",
  mail_notification: "all",
  salt: "AASsd8NK9vvvMlL2B09ph4L6C1OUezxC",
  must_change_passwd: false,
  passwd_changed_on: nil,
  twofa_scheme: nil,
  twofa_totp_key: nil,
  twofa_totp_last_used_at: nil,
  twofa_required: false>,
```


### mysqlログイン時
ちなみに、mysqlもこのパスワードでアクセス可能だが、 ユーザー名は`user`ではなく`root`で入れる。
![スクリーンショット 2023-01-12 16.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251648/990f934a-1a6a-872e-81c6-7ecf2dc24107.png)
【備忘】Macショートカット一覧

Mac端末を使い始めたので、よく使うショートカットキーを備忘としてまとめます。

## ショートカット一覧
| キー                       | 内容                                  |
|:--------------------------|:--------------------------------------|
| command(⌘) + C            | コピー                                 |
| command(⌘) + X            | カット                                 |
| command(⌘) + V            | ペースト                                |
| command(⌘) + Z            | 操作の取り消し                           | 
| command(⌘) + shift(⇧) + 3 | 全画面のスクリーンショット                 | 
| command(⌘) + shift(⇧) + 4 | 選択画面のスクリーンショット               |
| command(⌘) + control + Q  | 画面ロック                              |
| fn + delete               | 右の文字列を削除(WindowsのDeleteキー)     |

他にもたくさんあるので、詳細は下記を参照ください。
[Mac のキーボードショートカット](https://support.apple.com/ja-jp/HT201236)