OmniAICreator/Qiita-1.07M huggingface dataset:
.NET MAUIでlivecharts2を導入

# 目的
備忘録として記載。
導入までを記載し、そこから別のグラフ描画は別記事に記載する見込み。
# 参考
https://lvcharts.com/docs/maui/2.0.0-beta.330/gallery
# 環境
* windows11 21H2
* Microsoft Visual Studio Community 2022 (64 ビット) Version 17.3.3
# 今回作成したプロジェクトについて
下記githubにコミットしました。
https://github.com/satukihare/LiveChartMauiSample.git
# 導入
nugetパッケージマネージャにて
下記をインストール
* LiveChartsCore.SkiaSharpView.Maui
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850733/c70635a6-b1ff-3cca-cac1-6fa46ee7a3a7.png)
## MauiProgram.csの変更
下記ソースコードのように追記する
~~~
using SkiaSharp . Views . Maui . Controls . Hosting;
namespace LiveChartSample;
public static class MauiProgram {
    public static MauiApp CreateMauiApp ( ) {
        var builder = MauiApp.CreateBuilder();
        builder
            . UseSkiaSharp ( true ) // 追加
            . UseMauiApp<App> ( )
            . ConfigureFonts ( fonts => {
                fonts . AddFont ( "OpenSans-Regular.ttf" , "OpenSansRegular" );
                fonts . AddFont ( "OpenSans-Semibold.ttf" , "OpenSansSemibold" );
            } );
        return builder . Build ( );
    }
}
~~~
## モデルの作成
下記クラスを作成。
今回はここで表示される値を設定。
~~~
using LiveChartsCore . SkiaSharpView;
using LiveChartsCore;
namespace LiveChartSample {
    public class ViewModel {
        public ISeries [ ] Series { get; set; }
        = new ISeries [ ]
        {
            new LineSeries<double>
            {
                Values = new double[] { 2, 1, 3, 5, 3, 4, 6 },
                Fill = null
            }
        };
    }
}
~~~
## MainPage.xamlの変更
ここではContentPageのタグに「モデルの作成」にて作成したクラス（ViewModel.cs）を参照するようにする。
~~~
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="LiveChartSample.MainPage"
             xmlns:local="clr-namespace:LiveChartSample"
             xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Maui;assembly=LiveChartsCore.SkiaSharpView.Maui">
<!-- 下記は変更前
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="LiveChartSample.MainPage">
-->
    <!-- 下記のように変更 -->
    <ContentPage.BindingContext>
        <local:ViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <Grid>
            <lvc:CartesianChart
                Series="{Binding Series}">
            </lvc:CartesianChart>
        </Grid>
    </ContentPage.Content>
</ContentPage>
~~~
# 実行
グラフが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850733/088ba604-e4fa-f7af-653d-bc4ef5de1593.png)
画像処理エンジニア検定エキスパートに合格した勉強法

![IMG_6450.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/7cffa023-b2e2-867d-f38f-f743ee05f7b2.jpeg)
# はじめに
画像処理エンジニア検定エキスパートに合格したので、勉強方法などを残しておきます。
試験の詳細については主催のCG-ARTSのページをご確認いただけたらと思います。
[画像処理エンジニア検定について](https://www.cgarts.or.jp/kentei/about/img_engineer/index.html)

# 受験理由
仕事で顔認証を扱う（既存の顔認証エンジンを使う）ことになったのですが、顔認証の仕組みやカメラの選定、パラメータなどが全然わからなかったので、その辺りの勉強になるかなと思って受験しました。
（ちなみに、その後転職したので今回勉強したことを活かす場はありませんでした。。。）

# 受験時の私のスペック
画像処理というものを全く知らない状態でした。  
AIとか機械学習もやったことないです。
写真の趣味などもないのでカメラの知識もゼロ、数学も学生時代の知識はほとんど残っていません。

# 勉強期間
約2ヶ月

# 勉強方法
## Udemyの動画視聴
私のスペックのところにも書きましたが、前提知識ゼロ（というかむしろマイナス？）な私がいきなりテキストとか過去問を解くのは厳しいだろうと思い、画像処理の入門に最適そうな動画をUdemyで見つけて視聴することにしました。  

それがこちらです。  
[画像処理の基礎：フィルタリング，パターン認識から撮像過程モデルまで](https://www.udemy.com/course/image_processing_python/)

内容は初学者を対象としていて非常にわかりやすく、かつ画像処理エンジニア検定エキスパートの試験範囲をかなり広い範囲でカバーしています。  
Pythonで実際に動かしながら学べるのもポイントです。  

トータルで約27時間なのでかなり長いですが、この動画を見ることでテキストを読み始めた時にあまり抵抗なく読み進めることができました。  
期間的に余裕があるなら視聴をお勧めします。

## テキスト
動画視聴の後は公式テキストを通しで読みました。
![626x0w.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/ff86ef05-ff53-7902-3a9a-e84dc208b119.jpeg)
難しいところはあまり深く理解しようとせず、試験範囲を一通り把握するイメージで読み進めました。  
難しい計算式はスルーしましたが、行列だけはネットで調べて復習しました。


## 過去問
過去問も公式から出ています。
![626x0w (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/6e3cdd7f-c9cb-8420-5d0d-5d1ef5a763c7.jpeg)
ベーシックとエキスパートの過去問がそれぞれあります。  
ベーシックの問題を解いたら結構解けたのですが、エキスパートの問題は全く歯が立ちませんでした。  
ちゃんと採点していませんが、正答率は半分以下だったと思います。（合格ラインは7割）  

## 公式テキスト再読
エキスパートの過去問を解いてみて分かったのは、数式に関する問題が一定数出ること、ほぼ毎回出る分野がある（2値画像処理、周波数フィルタリング、幾何学的変換など）ということです。  
この段階でエキスパートの過去問を解いてもあまり勉強にはならないと思い、もう一度公式テキストを読み直すことにしました。  
一度過去問を解くとテキストを読んでいるときに試験に出そうな箇所がなんとなく分かってきます。  

一度目には読み飛ばしていた数式ですが、数式の名前や各項の役割（値を大きくしたり小さくすると画像にどのような変化が起きるか、など）を覚えるようにしました。  
頻出の分野はちゃんと理解できるまで何度も読み直しました。
必ず出る著作権の分野は暗記で済むので1問も落とさない気持ちで暗記しました。

## 過去問（再挑戦）
この段階でエキスパートの過去問を解いてみたところ、6割くらいは安定的に正解するようになっていました。  
たまに合格ラインの7割を超える時もありました。  
あとはひたすら過去問を解くのみだと思い、試験の直前まで過去問を繰り返し解きました。

# 試験結果
![IMG_6450のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2528939/e0cfb4ce-e585-fb6f-fce3-aebd8d73a6f0.jpeg)

試験は全てマークシートなので自己採点でおそらく合格しているだろうというのはわかりました。  
合格証とともに送られてきた試験結果を見ると、点数が書かれていないのでわかりませんが、若干余裕を持って合格できたのかなといった感じでした。

# おわりに
無事に合格することができてホッとしています。  
試験といえば普段はIPAの情報処理技術者試験しか受験しないので、合格ラインの7割がとても厳しく感じました。(IPA試験は6割)　　

あと、思ったより暗記力が試される試験だったなと感じました。  
暗記していないと解けない問題が多く、試験範囲も広いので受験勉強はとても疲れました。  

ただ、テキストの内容は大変興味深く、画像処理という技術をとても身近なものに感じるようになりました。  
スマホで写真や動画を撮ったり、PCで資料を作成したりといった何気ない日常の中にも画像処理の技術がたくさん存在していることを知ることができたのは良かったと思っています。
[小ネタ] AWS Amplify 本のサンプルのデプロイについて

## はじめに

書籍「AWS Amplify Studioではじめるフロントエンド+バックエンド統合開発」を購入しました。

https://www.amazon.co.jp/dp/489977530X

p.30にサンプルアプリを作成する手順が記載されています。
2022年9月時点で私のAWSアカウントでは書籍どおりに行かなかったので、同じような状況の方向けのメモとして残しておきます。

p.30下部の図には　AWSのコンソールで「フルスタックのサンプルから」という項目が表示されていますが、私の環境では表示されていませんでした。（下図）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/26e232a5-d699-a1bb-d8c5-a30e7e91d143.png)

GitHubからの操作で同じサンプルをデプロイすることができますので、手順を残しておきます。

まず、ブラウザ上でAWSのマネジメントコンソールにログインしておきます。
同じブラウザで作成済みのGitHubにもログインしておきます。

## GitHubでの操作

以下のサイトにブラウザからアクセスしてください。

https://github.com/aws-samples/create-react-app-auth-amplify

下にスクロールし、[DEPLOY TO AMPLIFY CONSOLE]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/ae8af727-9cd4-3d54-1237-aadf4ef0732f.png)

ご自身のGitHubアカウントにログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/01bf4eb9-f419-a63f-a274-72e84b63a1f7.png)

GitHubに対するAWS Amplifyからの認可設定を行っていきます。
（このへんは書籍のp.35あたりと同じです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/3403902d-0fda-24d3-0320-ef4a7d4bcb12.png)


書籍と同様に全てのリポジトリへの読み書き権限を許可します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/aaee0583-36da-8847-3d56-3ebcb0b0fc79.png)



## AWS Amplify コンソール
AWS Amplifyの画面に遷移します。「新しいロールを作成」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/60f1afee-edf0-317d-fb1f-41f94e0f09f0.png)

## AWS マネジメントコンソール(IAM)

IAMロールの画面では、ウィザードに沿って進めていくだけでOKです。

ロールの信頼関係は自動でAmplifyが選択されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/beb6e9aa-0e26-080f-7c7e-0bea6adc2217.png)

付与するポリシーも最初から選択されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/61d4e7fd-93b6-1e4b-9203-1ec494224c45.png)

ロール名も自動で設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/41715dad-1fa1-f104-f9e2-c5626d97c4ea.png)

ロールが作成されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/19cfe336-5907-666c-7983-633e92643a63.png)

## AWS Amplify コンソール

Amplifyコンソールに戻り、サービスロール横のくるくるマークを押して更新すると、先程作ったロールが選択できるようになります。
選択し、「保存してデプロイ」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/a6a4c761-63fe-c54b-b1dc-b5640ccc60a6.png)

デプロイの進行状況が確認できます。
数分待ち、「続行」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/04f92eeb-3eb8-70b9-0a79-b956edbc6ec1.png)

サンプルアプリができました。あとは書籍のp.36あたりから読み進めれば良いと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538058/fcc5ff3c-697b-4498-e126-cb546e3a2601.png)

以上です。
Windows Server 2003R2⇒2019へローカルグループ移行について

# この記事について

Windows Server2003R2 から2019にファイルサーバを移行する際に、
ローカルグループをうまく移行するためのものです。

# しかし、なぜ2003？

転職先がロクなシステム管理をしておらず未だに2003でした。
下手に仮想化して延命しているからこらまた質が悪い。

ただファイルサーバ変えるだけだったらROBOCOPYでいいんですけど、下記状況だったため色々と試行

# 状況
1. 2003R2に無数のローカルグループが存在し、各フォルダはローカルグループを用いて権限設定がされている。
2. ローカルグループは100個以上あり、すべてを 手入力で再現したら膨大な時間がかかる。
2. 移行先としては2016か2019。サポート期限を考えると2019にしたい。. 

# やったこと
色々考えましたが、Windowsサーバ移行ツールしかないという結論に。

サーバ移行ツールは、
1. 新サーバで移行ツールを作成
2. 旧サーバにツールをコピーして実行するとファイルが生成される
3. 生成されたファイルを読み込むとローカルグループが移行される

という流れになります。

移行ツール自体については多数のテキストがネットにあるので省略。

## やってみてわかった

2019、2016で生成できる移行ツールは、2008Rまでしか対応しない。
2003用にしようとして引数を入れてもエラーにになります。

そこで、一度中間サーバとして2012R2のVMを生成しました。
2003R2→2012R2までは問題なく終わりました。

### 謎エラー

2012→2016,2019に移行しようとすると、[.net Frameworkを入れろ]という謎エラー。
入っているのに進めません。2012はあきらめて2008R2を中間サーバにしました。

# 挫折と成功

やはり2003R2→2012R2までは問題なく終わりましたが、
2008R2→2016,2019に移行しようとすると、SmigDeploy実行時に[CLR20r3]のエラーが出ました。

正直積んだと思いましたが、下記参考にし道が開けました。

https://social.technet.microsoft.com/forums/ja-jp/e73dcbaa-7c33-452b-bbee-85229f03adc4/smigdeploy-registration-fails

”got the exact same error. I found out that the migration tools were already installed on the source server from the server manager.

After uninstalling the migration tools on the source server from the server manager, i ran the SmigDeploy.exe and it worked fine.

Hope this helps.”

要するに、2008R2の移行ツールを消さないとだめだったのです。

消したところ普通にOK。

# 最後に
良い子のみんな、サポート期限切れる前にサーバ変えとけ！
Fontawsomeでアイコンをゲットしろ

fontawsomeでググる。
メールなどを記入してログイン

```
<link
      rel="stylesheet"
      href="https://use.fontawesome.com/releases/v5.15.4/css/all.css"
      integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm"
      crossorigin="anonymous"
 />
```
上記を張り付けて後は好きなものをゲット
```
<div class="media-icons">
          <a href="#" class="icon"><i class="fab fa-facebook"></i></a>
          <a href="#" class="icon"><i class="fab fa-instagram"></i></a>
          <a href="#" class="icon"><i class="fab fa-twitter"></i></a>
          <a href="#" class="icon"><i class="fab fa-youtube"></i></a>
</div>
```
完成
【HTML】tableタグ周りがよーわからんくなったので整理してみた。

<h1>Tableタグってなんぞや</h1>
<p>HTMLで表を作成する際に利用するタグのこと。</p>

<h2>実際にコード書いてみる</h2>

tr:テーブルの行部分（横方向）を指定するタグ。
th:テーブルの見出しやタイトルとなるセルを指定するタグ。
td:テーブルのセル内容を作成を指定するタグ。

<h3>①trとtdタグで作成したテーブル</h3>
<table>
    <tr>
        <td>タイトル</td>
        <td>名前</td>
        <td>日付</td>
    <tr>
        <td>Tableタグ周りがよーわからんくなったので整理してみた。</td>
        <td>ともひろ</td>
        <td>2022年9月24日(土) 15:37:11</td>
    </tr>
</table>

```html:table1.html
<table>
    <tr>
        <td>タイトル</td>
        <td>名前</td>
        <td>日付</td>
    <tr>
        <td>Tableタグ周りがよーわからんくなったので整理してみた。</td>
        <td>ともひろ</td>
        <td>2022年9月24日(土) 15:37:11</td>
    </tr>
</table>
```

<h3>②trとthとtdタグで作成したテーブル</h3>
<table>
    <tr>
        <th>タイトル</th>
        <th>名前</th>
        <th>日付</th>
    </tr>
    <tr>
        <td>Tableタグ周りがよーわからんくなったので整理してみた。</td>
        <td>ともひろ</td>
        <td>2022年9月24日(土) 15:37:11</td>
    </tr>
</table>

```html:table2.html
<table>
    <tr>
        <th>タイトル</th>
        <th>名前</th>
        <th>日付</th>
    </tr>
    <tr>
        <td>Tableタグ周りがよーわからんくなったので整理してみた。</td>
        <td>ともひろ</td>
        <td>2022年9月24日(土) 15:37:11</td>
    </tr>
</table>
```

<h1>結論</h1>
<p>自分で書いてみるのが一番わかるかも？🍺</p>
Vagrant で作成した VM 上で、Node 関連の処理を行うとエラー

<!-----

Yay, no errors, warnings, or alerts!

Conversion time: 0.356 seconds.


Using this Markdown file:

1. Paste this output into your source file.
2. See the notes and action items below regarding this conversion run.
3. Check the rendered output (headings, lists, code blocks, tables) for proper
   formatting and use a linkchecker before you publish this page.

Conversion notes:

* Docs to Markdown version 1.0β33
* Thu Sep 08 2022 02:05:11 GMT-0700 (PDT)
* Source doc: 2022-09-07 Vagrant で作成した VM 上で、Node 関連の処理を行うとエラー
----->

## 環境

### ホストOS

* Windows10
* Virtualbox
* Vagrant

### ゲストOS

* Ubuntu 18.04 LTS

## 発生した事象

synced_folder の設定を用いて Node アプリケーションを /vagrant/ ディレクトリにデプロイ。

`npm install` を実行すると、「Error: Cannot find module 'node-linux-x64/package.json'」というエラーが出た。

## 対処法

synced_folder への書き込みが「device is busy」ということで失敗し、そのために上記のエラーが発生していた。

コンテンツを /vagrant/ から /home/vagrant/ に移動し `npm install` を実行すると成功した。

## Ref

エラーの文面で検索したが、解決方法を見つけることができなかった。

* [node.js - Error: Cannot find module 'node-linux-x64/package.json' - pushing to Heroku for first time - Stack Overflow](https://stackoverflow.com/questions/63023473/error-cannot-find-module-node-linux-x64-package-json-pushing-to-heroku-for)
ruby から slack へ message を送信する

# 目的
- ruby から slack channel や個人へ message を送信する
    - 送信者は bot 扱いとなる





# 概要
- 使用 gem
- token の取得
- channel id, user id の取得
- ruby code sample
    - token 設定
    - dm
    - message
    - block




# 使用 gem
```
gem 'slack-ruby-client'
```

- repository
    - https://github.com/slack-ruby/slack-ruby-client



# bot auth token の取得
- [ 使用する slack app の設定画面 ] を開く
    - https://api.slack.com/apps/
- [ OAuth & Permissions ] を開く
- [ Bot User OAuth Token ] を控える


![スクリーンショット 2022-09-25 21.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/5f19dd64-84dd-5f59-35f5-9b1d079d5ff8.png)





# App へ chat write 権限の付与
- [ OAuth & Permissions ] を開く
- [ Bot Token Scopes ] の [ Add an OAuth Scope ] を選択
- [ chat:write ] を追加する
- [ Reinstall to Workspace ] を実行
    - 初回の場合は, message が異なる

![スクリーンショット 2022-09-25 21.21.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/fe935bcc-fd30-36cd-3fc3-015fd030991b.png)






# channel, user id を取得する
- slack を browser で開き, url path より取得する

``` ruby
# channel id
https://app.slack.com/client/[TEAM_ID]/[CHANNEL_ID]/

# user id : user profile を開き, url 末尾が user_id となる
https://app.slack.com/client/[TEAM_ID]/[CHANNEL_ID]/rimeto_profile/[USER_ID]
```





# ruby code sample
``` ruby
require 'slack-ruby-client'


def setup_slack
    token="xoxb-11111111111-222222222222-DummyDummyDummy3333"

    Slack.configure do |config|
        config.token = token
    end
end


def send_message_to_user
    # user へ DM を送信する
    user_id = 'USER_ID'
    msg     = 'test msg'

    client = Slack::Web::Client.new
    response = client.chat_postMessage(
        channel: user_id,
        text:    msg
    )
end


def send_message_to_channel
    # channel へ message を送信する
    channel_id = 'CHANNEL_ID'
    msg        = 'test msg'

    client = Slack::Web::Client.new
    response = client.chat_postMessage(
        channel: channel_id,
        text:    msg
    )
end

setup_slack
send_message_to_user
send_message_to_channel
```




# block message
## block とは
- 構造を持った teplate message を送信することができる
- 以下より, block 及び, block code の生成が可能
    - https://app.slack.com/block-kit-builder/ 



# block sample 画像
![スクリーンショット 2022-09-24 16.25.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/d931688c-1ab4-dbbb-ddd5-1157e1b3ff92.png)





## sample code
- 投稿する際は, message と同様に block を付与して送信する.
- 投稿した block の更新も可能.
    - 更新には message_ts が必要となる
    - message_ts は, block 上の button などから発行される request に含まれる.

```ruby
def post_block
    client = Slack::Web::Client.new
    block = generate_block

    response = client.chat_PostMessage(
        channel: channel_id,
        blocks:  block
    )
end

def update_block
    client = Slack::Web::Client.new
    block = generate_block

    response = client.chat_update({
        ts:      message_ts,
        channel: channel_id,
        blocks:  block
    })
end
```




以上


# 参考記事
https://qiita.com/hypermkt/items/b2ffaf610ac92235c4d6

https://api.slack.com/interactivity/slash-commands
requests.SessionインスタンスをSingletonパターンで作成する

```
import requests

class Singleton(object):
    @classmethod
    def get_instance(cls, input):
        if not hasattr(cls, "_instance"):
            cls._instance = cls(input)
        return cls._instance

class Session(Singleton):
    def __init__(self):
        self.session = requests.Session()
```

```
session = Session()
session.session.get("https://google.com")
```

# 参考
https://qiita.com/ttsubo/items/c4af71ceba15b5b213f8
リーダブルコードまとめ(第9章:変数と読みやすさ)

# 第9章:変数と読みやすさ
## 概要
本章では、変数を適当に扱うとコードが読み難くなるので、変数を極力減らすことの重要性について説明してくれている。

### まとめ
値の追跡が困難になるので変数を無駄に増やさずに、コードを書くべきということを主張している。そのために、「邪魔な変数を削除する」「変数のスコープをできるだけ小さくする」「一度だけ書き込む変数を使う」ということを念頭に開発をする。

### 学んだ点
・「変数が多いと変数を追跡するのが難しくなる」「変数のスコープが大きいとスコープを把握する時間が長くなる」「変数が頻繁に変更されると現在の値を把握するのが難しい」という点に注意すべきでこれらを本章では対処していく。
・コード内で中間結果を持つだけの変数は削除してその結果を用いる。
・グローバル変数に限らず、全ての変数のスコープを縮めて変数のことが見えるコード行数をできるだけ減らす。
・アクセスはできるだけ制限して、変数のことが「見えてしまう」コードを減らすのがいいとされている。なぜなら、一度に考えなければならない変数を減らせるからである。
・メンバ変数というのはクラスの中で「ミニグローバル」になっている可能性が高く、そのようなミニグローバルな変数はできるだけ減らした方がいい。
・クラスのメンバへのアクセス制限をするもう一つの方法は、メソッドをできるだけstaticにすることと、大きなクラスを小さなクラスに分割することである。分割後のクラスが相互に参照あっていれば、行う意味はない。
・メソッドをできるだけstaticにすることで、「メンバ変数とは関係ない」ということがよくわかるからである。
・値が更新され続ける変数が多いとコードが理解し難くなるので、変数は一度だけ読み込むようにするべき。なぜなら、変数を操作する場所が増えると現在の値の判断が難しくなるからである。

### 感想と振り返り
変数の多さを普段意識したことはないですが、実装中に元からある変数の値を取ってきて加工するみたいな変な実装をしてしまいすぎていつことがあったかもしれません。そもそも今何の情報が必要なのかを考えて実装をしてその上で変数を作成する。変数作成時もできる限り、スコープを狭めて可読性を高めて実装をすることを意識したいものですね！！
AWSのCloudWatchを使って請求アラームを設定してみる

## はじめに
自己啓発のためにAWSを使おうと思いましたが、いろんなサービスが従量課金で用意されており、出費がかさむのを避けたいので、まずはサービス使う前に、一定金額に達したらアラームを通知するように設定しました。
まだまだ分からないことだらけですが、お金の面の不安がある程度は解消できたので、AWSを使っていけそうです。


### 利用するサービス
- CloudWatch
各システムの異常などを監視してくれるサービスですが、今回は請求額の監視です。
- Amazon SNS(Simple Notification Service)
購読先に対して通知してくれるサービスで、今回は請求額超過のメール通知で使用します。

## 1. 請求アラートの受信手順

### 1.1.  請求設定画面を開く

- 画面右上のアカウントを選択し、"請求ダッシュボード" を選択します
![請求ダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/e0e6e2d9-7bf6-01ec-39a1-0aa855a8da0a.png)

- 左サイドメニューの下段にある "請求設定" を選択します
![請求設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/73c4de02-94a2-0e1e-42b7-df4e8ab9e315.png)

### 1.2. 請求アラートを受け取れるように設定

- 今回の対象は３つ目の☑ですが、１つ目２つ目にもチェックを入れて、メールアドレスを入力、保存を押下します
![請求設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/9d597af5-d502-76d7-4658-127c553a5793.png)

## 2. 請求アラートの管理

### 2.1. 請求アラーム作成画面を開く

- "請求アラートを管理する" を選択します
![請求設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/8fb65ae9-1a8e-96ab-415b-52a302df0911.png)

**補足：請求アラームのリージョンは "米国東部バージニア北部" 固定のようです**
[AWS公式サイト](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)より抜粋
> 請求メトリクスデータは米国東部 (バージニア北部) リージョンに保存され、世界全体の請求額として表されます。

- "請求" を選択します
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/05eaf02c-96b9-c4f6-e7f0-3a04b7c6e032.png)

- "アラームの作成" を選択します
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/c2c244c6-77ec-dcd3-8828-372c40987765.png)


### 2.2. アラーム通知条件を設定

- "メトリクス" 欄は変更せず、 "条件" 欄を設定します。どれぐらいの料金が一般的かわからないので、とりあえず安く3ドルにしました。
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/f2126737-d5f0-3097-2a77-f3811cf8c450.png)


### 2.3. SNSトピックの作成
- アクション通知が開くので、 "新しいトピックの作成" を選び、トピック名称とメールアドレスを入力して、作成を押下します
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/a07a8718-337c-3a80-68c1-f3da1f9c4295.png)

- 通知先に指定した宛先にメールが届ので、 "Confirm subscription" を押下します
![メール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/0d9afe6c-c6bf-eada-9ce6-376906cf94f8.png)

- "Subscription confirmed!" 画面が開きます
![メール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/2c7a6496-5574-821b-e3e1-6ffa0ad51fad.png)


### 2.4. アクションの設定

- たった今作ったトピックを選択して、次へ進みます
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/0b2dffac-3996-3e7c-84d2-996d22758b18.png)

### 2.5. 名前と説明の追加
- 名前を入力します
![請求アラーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/d11f1218-e05e-2c99-c8b2-d04a69f4e7f1.png)

### 2.6. プレビューと作成
- プレビュー表示を確認して、画面末尾の "アラームの作成" を押下します

### 2.7 確認

- 作成した名称の請求アラームがOKになっていることを確認します
![メール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674934/59fdf617-37a3-a738-d94e-1a0b03c478bb.png)
ドローン自作する

現状いいところまで出来上がったので
ちょこちょこ進捗と共に公開（自慢）したい

やりたいこと
　ドローンを作る
　　陸海空関係なし
　　とりあえず空と陸
　　できる限り自作したい

仕様
　無線
　映像あり
　できる限り稼働時間長く
　スマホから操作したい
　自由であれ

以上からコツコツと計画を練りに練ってきたが
ついに形が見えてきました

とりあえずコア部分の技術検証の完了です
まさか昇圧してリポ1つで動くとは思いませんでした
検証用ボードはユニバーサル基板で作成
今後は開発や検証で使います

ハード
　ESP32-CAM
　昇圧回路を用いてリポバッテリー1つで動作することを確認
　GPIOにてPWM出力

ソフト
　機体
　　C++で実装
　　カメラの映像配信はサンプルのまま
　　アドホック通信
　　スマホからはUDPにてコマンドを受信
　　コマンドを解析してGPIOを出力

　スマホ
　　Kotlinで実装
　　Webビューにて映像受信
　　ボタンタップでコマンドを送信
　　UDPでコマンドを送るので非同期通信
　　各種設定値を設定する画面
　　　ESP32のIPアドレス、URLのパス、映像受信ポート、コマンド送信用ポート、受信ポート、コマンドのフォーマット設定

通信フォーマット
　今後の開発も踏まえ、機体とそれに合わせたコントローラに拡張性を持たせられるものを考案
　ベースはJSON形式
　GPIOピンとそれに対する値を指定する
　[13:100,14:50]
　　カンマ区切り
　　:の左がPIN、右が値
　スマホ側はコマンドを設定画面で自由に変更できるようにする
　ESP32側はコマンドを解析してそのままGPIOの出力を行う
　![IMG_20220918_2305250.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1852162/4fbf19dd-23f1-1b5c-151b-b8438c6b06b2.jpeg)
Java ファイル　読み書き

テキストファイルの読み方
FileWriterおよびFileReaderを使う
```java
import java.io.*;

public class Main{ 
    public static void main(String[] args)throws Exception {
        FileReader fw=new FileReader("README.md");
        System.out.println("全てのデータを読んで表示します");
        int i=fw.read();//１文字のみ読み取れる
        while(i!=-1){
            char c=(char)i;//readから返される値はint型なのでキャストする
            System.out.print(c);
            i=fw.read();
        }
        System.out.println("ファイルの末尾に到達しました");
        fw.close();

    }

}
```
STM32G071で液晶温度計。(STTS751)(AQM0802)


x 昔、秋月で売っていた温度センサーSTTS751
  代用品は、S-5851A。(おもにアドレスの違い)


stm32g031,stm32l010用に最軽量化したもの


1.SCLとSDAを接続、プルアップも忘れずに
2.電源の接続
3.下記のソースコードを書き込む
4.コンパイル実行で表示されたら終了
5.おわり


![o_con795.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3824c13e-a052-dd2b-c68e-b2be492ff4fe.jpeg)



参考


https://qiita.com/caa45040/items/efdb0038bf5bcb2a82db


Arduino UNOのプログラムと完全に同じ


```c++


#include <Wire.h> //I2C library

#define STTS751 0x39
#define I2Cadr  0x3e  // 固定

int     tempval;                //温度
char    data_read[2]={'@','t'}; //i2cバッファー
int     ii;                     //ループカウンター

//初期レジスター
char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

//画面のクリアレジスター
char INIT_cls[]={0x0,0x1};

//i2c書き込みルーチン
void i2c_led_w(char *buff1){
  Wire.beginTransmission(I2Cadr);
  Wire.write(buff1[0]);
  Wire.write(buff1[1]);
  Wire.endTransmission();
  delay(2);
}//i2c_led_w

void setup()
{  

  Wire.begin(); //uno

  //液晶の初期化
  for(ii=0;ii<11;ii++){
    i2c_led_w(&INIT_com[ii*2]);
  } //for

} //end setup

void loop()
{

  //画面のクリア
  i2c_led_w(INIT_cls);

  //0番目のレジスター
  Wire.beginTransmission(STTS751);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);

  //温度の読み込み
  tempval = 99;
  Wire.requestFrom(STTS751, 1);
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    tempval = (int)Wire.read(); // 1バイトを受信
  }//while
  delay(1);

  //液晶に表示
  data_read[1] = '0' + (tempval / 10);
  i2c_led_w(data_read);
  data_read[1] = '0' + (tempval % 10);
  i2c_led_w(data_read);

  delay(1000); //1秒待つ

}//loop




```
リアルタイムで更新されるチャットアプリを作ってみる（HTTP通信）

<!-- tag: React.js,fastAPI -->
<!-- private: False -->

# 概要

勉強のためにリアルタイムで更新が行われる簡単なチャットアプリを実装してみました。

ソースコードはこちらです
https://github.com/iwsh/http-chat/tree/v1.0

# 構成

- バックエンド(api): Python (FastAPI + sqlite)
- フロントエンド(ui): React.js

の 2 つの AP が HTTP 通信のシンプルな Web API で連携する構成となっています。

```
.
├── README.md
├── docker-compose.yml
├── init.sh					Init containers (api, ui)
├── api/					Backend (FastAPI + SQLite)
│   ├── modules/
│   ├── main.py
│   ├── init.sh
│   └── requirements.txt
└── ui/						Frontend (React.js)
    ├── package-lock.json
    ├── package.json
    ├── public/
    └── src/
```

## フロントエンド

![frontend screen](https://raw.githubusercontent.com/iwsh/assets/main/assets/qiita/article_4/frontend_v1.0.png)

Create React App で作成したひな形をもとに実装しています

メッセージをリアルタイムに更新するため、1 秒ごとに Web API にアクセスしてメッセージ一覧を取得して`msgs`に set しています

一般的にリアルタイムのデータ更新を行う際にはポーリングや websocket などの双方向通信が使われますが、まずは簡易な実装を試したかったため単純な GET リクエストで実装しました。

ui/src/App.js

```javascript
useEffect(() => {
  const interval = setInterval(() => {
    axios.get("http://127.0.0.1:8000/messages/").then((res) => {
      console.log(res);
      setMsgs(res.data);
    });
  }, 1000);
  return () => clearInterval(interval);
}, []);
```

## バックエンド

FastAPI で`/messages/`の URL に対する GET, POST を受け付け、SQLite で`api/main.db`にデータ格納・取得しています

躓いたポイントとして、CORS ポリシーというものに引っ掛かりフロントエンドと通信ができなくなっていました。
十分には理解できていないですが、どうやらセキュリティのために通信を許可するフロントエンドを FastAPI のパラメータとして登録する必要があるようです。
（参考: https://qiita.com/att55/items/2154a8aad8bf1409db2b）

api/main.py

```python
app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", ],
    allow_credentials=True,
    allow_methods=["GET", "POST"],
    allow_headers=["*"],
)
```

```python
@app.get("/messages/")
def read_item():
    df_msg = message_manager.get_messages()
    return df_msg.to_dict("records")


@app.post("/messages/")
def post_item(msg: Msg):
    df_msg = message_manager.post_messages(msg)
    return df_msg.to_dict("records")
```

# 起動

`init.sh` を実行することで起動します

- docker を使用するので必要に応じて sudo 権限で実行してください
- docker compose v2 が必要です。
  docker compose v1 で実行する場合は`init.sh`を以下のように編集してください

  ```bash
  docker-compose run ui npm install
  docker-compose up
  ```

- フロントエンド・バックエンドについて、それぞれパッケージをインストールしてサーバを起動しています

# おわりに

初めてリアルタイムに更新される画面アプリを作成したので、複数画面でメッセージのやりとりができているのを確認できたときの感動は大きかったです。

ひとまず性能などは無視して毎秒リクエストを飛ばしてメッセージ全量をもってくるという力技を実装しましたが、
今後より妥当な手段となりそうな websocket を使用しての実装も試してみたいと思います。
リーダブルコードまとめ(第8章:巨大な式を分割する)

# 第8章:巨大な式を分割する
## 概要
巨大な式（冗長な条件文等）を分割して見やすくすることの有用性について説明してくれています。

### まとめ
巨大な式を分割するために一番簡単な方法は、「説明変数」を導入することであり、そうすることで「巨大な式を分割できる」「簡潔な名前で式を説明することで、コードを文章化できる」「コードの主要な「概念」を読み手が認識しやすくなる」の3つの利点がある。

### 学んだ点
・コードの式が大きくなれば、それだけ理解する時間を要することになる。そこで、巨大な式は飲み込みやすい大きさに分割するべきである。
・式を分割するには、式を代入した変数を使えば効果的である。ちなみにそのような式のことを「説明変数」と呼ぶ。
・大きなコードの塊を小さな名前に置き換えて、管理や把握を簡単にする変数のことを「要約変数」と呼ぶ。
・ドモルガンの法則を用いることでわかりやすいコードにすることができる。(あまり深く意味がわかっていないです。)
・「頭がいい」コードに気をつける。後で他の人がコードを読むときにわかりにくくなる。
・同じ値等を条件分岐で使う場合は、先に変数で宣言して用意しておいて、条件分岐の文をできる限り短縮する。条件分岐文を見やすくする。また、そうすることでDRY原則の考えに沿うこともできる。

### 感想と振り返り
条件文を書く機会は往々にしてありますが、説明変数を追加するという考えには今まで全く至らなかったです。そもそも、説明変数の意味すらあまり理解していませんでした...
しかし、実装中に条件文に関わる時は常に「冗長になっていないか？」や「理解しやすいか？」ということを少しでわありますが考えられていたので、今後も「一読して理解できるコード」を目指したいと思います！
データローダとインポートウィザードの違い

こんにちは。本橋孝昭です

今回はデータローダとインポートウィザードの違いについて解説します


### なぜデータローダとインポートウィザードの違いについて解説するか？


Salesforce認定アドミニストレーター試験の出題範囲は公開されています

https://quip.com/5FXlAAIRTrqo/SALESFORCE-

この中で

*データの管理: 10%*

には

与えられたシナリオに従って、データ管理のツールとユースケースを特定する
(例: データローダ、データインポートウィザード)

があります

![データの管理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1c3c8f42-6537-d42c-3f28-c5a524a499c4.png)

このようにデータローダ、インポートウィザードの違いは結構問われる内容なので解説します

今回の内容は動画でも解説してます

https://youtu.be/ckdIF6usirA


### そもそもインポートってなんだ？

Salesfroceのデータのインポートとは簡単にいえば
・Salesforceのレコードを一括作成
でしょうか

例えば
・新規でSalesforceを導入したのでエクセルで管理していたデータを取り組みたい
・特定の営業が管理していたエクセルの顧客名簿をSalesforceに取り組みたい

という場合、（もちろんレコードを手入力で１レコードずつ入力することも可能ですが）
データが何千、何万もあれば手入力で取り組むのは現実的ではないですね

そのような場合データローダやインポートウィザードでデータを一括作成することが可能です



### インポートウィザードでできること簡単にまとめます

簡単にいえばデータの一括でのインポートおよび更新が可能です

しかしながら以下のような条件設定があります
（※インポート可能オブジェクトは取引先、取引先責任者、リード、ソリューション、キャンペーンメンバー、カスタムオブジェクト　のみ）
（※インポートレコードの上限は50000件まで）

### データローダでできることでできることを簡単にまとめます

データローダについても簡単にいえばデータの一括でのインポートおよび更新が可能です
しかしながらデータローダはインポートウィザードよりも多くのデータやオブジェクトのインポートが可能です

（※インポートウィザードで対応範囲のオブジェクトはもちろん、商談オブジェクトやケースオブジェクト、ユーザオブジェクトなど様々なオブジェクトのインポートが可能）
（※一回のデータインポート可能なデータはインポートウィザードと比べれば多いレコード数が可能（500000レコードまで））

↑ここの内容はインポートウィザードの上位互換です


### データローダでしかできないこと（インポートウィザードでは出来ないこと）

データローダでしかできないことは大きく分けて以下の2つです

1.夜間インポートなど定期的な読み込みのスケジュール

詳細は以下のTrailheadモジュールをご確認ください

https://trailhead.salesforce.com/ja/content/learn/modules/lex_implementation_data_management/lex_implementation_data_import
＞夜間インポートなど、定期的なデータ読み込みスケジュールを設定する。


2.データの削除（Delete）や吐き出し（Export）が可能

データローダの画面を見ても分かるように
・新規作成（インポート）
・更新（Update）
の他に
・削除（Delete）
・吐き出し（Export）も可能です

![データローダ01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/673238cf-3cd6-4169-3bab-2f9f5f455687.png)


### インポートウィザードでしかできないこと（データローダでは出来ないこと）

ここまでくると
「インポートウィザードって逆に何ができるの？」と思う方が多いかもしれないですね。

正直、私は実務であまりインポートウィザードを使用したことはありません
実務で使わない理由の一つは、やはり対応可能なオブジェクト数が少なすぎるからですね。
あとは、データの削除やエクスポートもデータローダなら可能なので使いやすいですね。


とはいえ、インポートウィザードもデータローダではできないことも若干あります（といっても２つほどですが）


1ワークフロールールおよびプロセスを適応させない設定
2重複を防ぐ

だけです

![ルール適応.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/800043ed-6aa8-a98e-a5a3-3fd7c4c297f4.png)


### ここからは解くコツを解説


いかがでしょうか

内容をまとめると

・インポートウィザードか？データローダか迷ったとき

A　まずはインポートウィザードでしかできない（データローダでしかできない）２つのことを思い出し照らし合わせる

1ワークフロールールおよびプロセスを適応させない設定　に関する話か？
2重複を防ぐ　に関する話か？

Bもしも上記以外の内容であればデータローダになる
（レコード削除、ユーザオブジェクトインポート、50000件を超えるレコード　などデータローダができることをあげるとキリがないですね）



### まとめ
今回の内容を図にしました。お役に立てれば幸いです

![データローダなど.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/7663484b-e7f0-4d8a-e983-9e02ac5a6a25.png)
スマートフォン連携 に感動した (win11 ＋ Surface Duo)

## 対応機種一覧

自分が持っている`Surface Duo (初代)`は対応していた。

https://support.microsoft.com/ja-jp/topic/%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%B3%E9%80%A3%E6%90%BA%E3%83%AA%E3%83%B3%E3%82%AF-%E3%82%A2%E3%83%97%E3%83%AA-%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%AA%E3%82%A8%E3%83%B3%E3%82%B9%E3%81%A7%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9-cb044172-87aa-9e41-d446-c4ac83ce8807


## 特徴

windows11の`スマートフォン連携`というアプリで、同じアカウントでログインしていれば`QRコード`読み取りで
スマホのアプリをwindows11側に表示ができる。

また、複数アプリ同時起動が可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/e64426dd-da37-64a2-4cdd-efb46807a100.png)
PythonでMeCabを動かそうとしたらつまずいたのでメモ


MeCabを動かそうとしたらエラーが出た。

```
no such file or directory: /var/lib/mecab/dic/mecab-ipadic-neologd ; add/dicrc
```


[PythonでMeCabを動かそうとしたらmecabrc ファイルが無いというエラーが出たので原因を調べた](https://analytics-note.xyz/programming/python-mecabrc-error/) このサイトを参考に以下を実行すると動いた。

'''
python -m unidic download
'''
Xcode-storyboardでviewに配置したButtonを操作したい!!

# はじめに
storyboard上でUIViewの中にUIButtonを置いたりする事って、ままある事だと思います。
ただ、UIViewの中にButtonを設置すると、UIViewの下側に入ってしまい、オートレイアウトなどの操作が出来なくなる事がありますよね😭

なんだかもどかしい気持ちになっていました。

## そんな時は
便利な機能がメニューに用意されていたのを発見したので、ここで紹介したいと思います。
![スクリーンショット 2022-09-24 10.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2428088/52588651-a452-2424-5523-24c886720cb8.png)

まずはstoryboardの左にあるメニューから任意のUIButtonやUIViewを選択します。
そして、メニューバーから、Editor→Arrange→画面最前面に出したい時は、Send Front、一つ前に出したい時はSend Forwardを選択します。

すると、画像の選択では、UIButtonがUIViewの前に出てきてくれました😁

ちょっとした事ですが、知っていると便利ですね🥹
Flutter入門 条件が適合するまでButtonを無効化する

### この記事のゴール
**条件が適合するまでボタンを無効化できるようになる。**

例）ログインされるまで無効化する
ログインさせるときなどに、この部分を満たしてからじゃないとボタンを押して欲しくない！という事、多々ありますよね。
そんな時にはこうしましょう！
```
ElevatedButton(
    onPressed: (条件)
        ? (){　マッチした時の処理 }
        : null, // マッチしなかった時の処理
    child: Text("送信する", style: TextStyle( fontWeight: FontWeight.bold ))
)
```

onPressedの中で条件を分岐し、マッチしない場合には**null**を入れてあげるとボタンが無効化されます。

具体例は以下です！
参考になれば幸いです。
```
ElevatedButton(
    onPressed: (user != null)
        ? (){　print(user?.uid); }
        : null, // マッチしなかった時の処理
    child: Text("送信する", style: TextStyle( fontWeight: FontWeight.bold ))
```
ここでは、ユーザーがnullではない場合にはボタンを押せるようにしています。


ちなみに、ここで条件分岐に使われているのは三項演算子というものです。
使い方は以下です。
```
(条件) ? マッチした時の処理 : マッチしなかった時の処理
(example =< 3) ? print("exampleは3以下です"); : print("条件を満たしていません");
```

今回は以上です。
console.logをもっと使いこなす！

ブラウザ上でのデバッグにconsole.log()をよく使いますが、MDNのConsole APIのページを見ると色々ありましたので調べてみました。

https://developer.mozilla.org/ja/docs/Web/API/Console_API

### よく使うコンソールメソッド
`console.log()`： ログ情報の一般的な出力用。
`console.info()`： 有益な情報の出力用。
`console.warn()`： 警告メッセージの出力用。
`console.error()`： エラーメッセージの出力用。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/db765106-2cf8-5972-0fa7-b8ebb1bcb058.png)


### console.log()のカスタムCSSスタイル
`console.log`の引数にCSSを指定し、`%c`ディレクティブを使用すると出力結果にスタイルを適用できます。
ディレクティブの前のテキストは影響を受けず、ディレクティブの後ろのテキストが装飾されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/475f9e4e-a369-54df-9522-f1bdd39681b9.png)


### 文字列の置換
文字列を受け取る console オブジェクトのメソッド (log() など) の 1 つに文字列を渡す場合、次の置換文字列を使用できます。
`%s`： string
`%i`または`%d`： integer
`%o`または`%0`： object
`%f`： float
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/00420049-2ef6-f16a-28c0-5561e626adc7.png)


### `console.assert()`
最初の引数が false の場合、メッセージとスタック トレースをコンソールに出力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/6afa26a7-f7f6-dd52-4d80-8970a5a284c6.png)


### `console.clear()`
コンソールをクリアします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/59551b7d-0f00-fe96-46e2-b7d7ae501f92.png)


### `console.count()`
この関数が呼び出された回数を出力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/8ee25814-51b4-637c-6986-34383daf94e2.png)


### `console.dir()`
指定された JavaScript オブジェクトのプロパティの対話型リストを表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/eec9a029-4d62-59e5-c415-913da9792174.png)
`console.log`との使い分けがわからない🙄


### `console.group()`と`console.groupEnd()`
新しいインライングループを作成し、後続のすべての出力を別のレベルでインデントします。
レベルを戻すには、`groupEnd()`を呼び出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/a0925473-77ca-cbaf-59e0-9fb7c5b7a856.png)



### `console.memory`
メモリプロパティを使用して、ヒープサイズを確認できます。
注: メモリはプロパティであり、メソッドではありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/f57920b2-b23f-9a3f-a02c-56903c928a41.png)


### `console.table()`
表形式として表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/2e93d6e1-dd75-b2e6-25e2-4fe082622eff.png)


### `console.time()`と`console.timeEnd()`
`console.time()`： 入力パラメーターとして指定された名前でタイマーを開始します。特定のページで最大 10,000 の同時タイマーを実行できます。
`console.timeEnd()`： 指定されたタイマーを停止し、開始からの経過時間を秒単位でログに記録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/16c6ccdd-d9fc-657d-8960-ff4f195cc4f2.png)


### `console.trace()`
スタック トレースを出力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184922/74830143-b339-3a5d-50bb-fff097078c2d.png)
Laravel queue をcron で動かす場合の設定例

この記事は、自身の以下のブログ記事の要旨をまとめたものです。

https://memoryclip.uchiida.com/2022/09/php/laravel/run_laravel_queue_worker_with_cron/

# 利用環境
- Laravel 9
- デプロイ先はエックスサーバー（スタンダードプラン）

# 結論から
レンタルサーバー(エックスサーバー)上で、Laravelのqueue ワーカープロセスを稼働させる際、cron エントリに以下のような設定にしました。


```plaintext
*/5 * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=300 --timeout=36000 --env=production >> /dev/null 2>&1
```

ポイントは以下です。
- cron の実行周期を、5分に設定  
- –max-time=300 に指定して、ワーカープロセスの生存時間を5分に設定  
- 実行すべきジョブがなければワーカープロセスを停止する --stop-when-empty は、プロセス生成直後に停止してしまう可能性があるのでつけない

# ダメな例

```plaintext
* * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=36000 --timeout=36000 --env=production >> /dev/null 2>&1
```

以下の点がダメなポイントです。

- –max-time と –timeout を 36000秒(10時間！)というめちゃ大きな値にしている
- –stop-when-empty オプションをつけていないので、–max-time オプションで指定している秒数、ワーカープロセスが残り続ける  
- cron の起動は最短間隔（1分ごと）にしてあるため、新しいワーカープロセスが頻繁に生成される

つまり、古いプロセスが消えることなく、新しいプロセスを次々に作ってしまう設定だったということです。
レンタルサーバのサポートから、高負荷なので対策するようにと警告を受け（ご迷惑おかけしました）、上記の設定に変更しました。

# 補足など

日本語ドキュメントにもqueue コマンドについて詳しく掲載されているので、そちらをご覧ください。

https://readouble.com/laravel/9.x/ja/queues.html#running-the-queue-worker

そもそもの話、supervisor などプロセスを永続化させるための仕組みが利用できるなら、そちらを利用したほうがよいと思います。
セキュリティー2022年　記事

https://www.trendmicro.com/ja_jp/jp-security/22/i/securitytrend-20220926-01.html

https://www.nikkei.com/article/DGXZQOUE120NO0S2A910C2000000/

https://www.lac.co.jp/lacwatch/people/20220921_003120.html

https://atmarkit.itmedia.co.jp/ait/articles/2209/22/news047.html

https://xtech.nikkei.com/atcl/nxt/column/18/00001/07179/

https://xtech.nikkei.com/atcl/nxt/column/18/00001/01504/?P=2
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その033

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: データと自動化
データ管理と分析管理の演習

にある練習問題1問目をご紹介します

なお今回の内容は動画でも解説しています

https://www.youtube.com/watch?v=79KxSeRgaWQ&t=34s

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


https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-security-and-data-management/review-data-management?trail_id=administrator-certification-prep


本日の問題はこちらです

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/fd0ac7f2-d4da-7c70-c482-b3e9c4b800ae.png)


正解はCですね


Bのクロス条件についてはこちらをご確認ください

https://help.salesforce.com/s/articleView?id=sf.reports_cross_filters_create.htm&type=5

Aのスナップショットとは定期的にレポートのデータをカスタムオブジェクトに保存しておく機能です。
今回の内容とは違うので間違いですね


Dのスケジュールとは、特定の担当者にレポートのメールを定期的に送信する設定ですね

今回の内容とは違うので間違いです




レポートの動きについては動画をご参考ください

https://www.youtube.com/watch?v=79KxSeRgaWQ&t=34s
React で Swiper 使用する方法

# はじめに
Gatsby.jsにてスライドを実装ときにハマったので、メモです。
Gatsby.jsに限らずReactでも同じかと思います。


# やりたいこと
Gatsby.jsにスライドショーを実装したい。
機能的には以下を実装。

- autoプレイ（roop)
- ページネーション

# 参考サイト

https://zenn.dev/highgrenade/scraps/9f20bf82f7a28c



# Swiper バージョン

参考記事に
>Reactで扱う場合は、 swiper@6.8.4を利用する。7/8は利用できない。

とありましたが、私の場合現時点での最新でも動きました！

```
"swiper": "^8.4.2"
```


# 実装方法

```javascript

import React from 'react'
import SwiperCore, { Autoplay, Pagination } from 'swiper'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/swiper.min.css'
import 'swiper/swiper-bundle.min.css'

SwiperCore.use([Pagination, Autoplay])  // ← ページネーション、autoプレイ、ナビゲーションはここでuseで拡張する

// 今回のスライドは以下のようなパラメータで実装しました。

const params = {
  slidesPerView: 1,
  spaceBetween: 30,
  centeredSlides: true,
  loop: true,    // autoで無限ループにしたい場合にはここをtrue
  loopedSlides: 5, // ここに数値いれないと、無限ループにはなるが、最後から最初へ切り替わる時キレてしまう。。
  autoplay: {
    delay: 3000,
    disableOnInteraction: false,
  },
  pagination: {
    clickable: true,
  },
}

・・・　//　ソース　詳細は略します。。

return (
        <ul className="swiper-wrapper">
          <Swiper {...params}>
            {persons.map(person => {
              return (
                <SwiperSlide>
                  <li key={person.slug}>
                 // スライド中身
                  </li>
                </SwiperSlide>
              )
            })}
          </Swiper>
        </ul>
      )



```

以上です！
Mac購入後のプログラミング準備

# はじめに
プログラミング学習中の[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

M2マックに買い替えまして、自分が行った初期設定(プログラミング関係)になります!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/e6bb1b7a-8490-5013-62e2-2b85ce13ffb7.png)

# VSCodeインストール

まずは必要ですね!

https://code.visualstudio.com/

# Homebrewインストール

## インストールコマンド

下記コマンドでインストールできます(公式サイトのトップページにあります)

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

## インストール後にコマンド2つ実行

上記インストールコマンド後に表示されている通りコマンド2つを実行します

```
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/yamadatarou/.zprofile
```

```
eval "$(/opt/homebrew/bin/brew shellenv)"
```

https://brew.sh/

## うまくインストールできたか確認

`brew help`コマンドが使えるかで確認します
以下のような感じで表示されればOKです

```
% brew help
Example usage:
  brew search TEXT|/REGEX/
  brew info [FORMULA|CASK...]
  brew install FORMULA|CASK...
　〜以下省略〜

```

# gitアップデート

## ローカルのgitバージョン確認

```
% git --version
git version 2.32.1 (Apple Git-133)
```

## 最新バージョン確認

公式サイトのトップページに載っています

https://git-scm.com/

## gitアップデート

下記コマンドで可能です

```
brew install git
```

```
brew upgrade git
```

# git初期設定

## 名前・メールアドレス設定

```
% git config --global user.name "なまえ（ニックネーム）"
% git config --global user.email "メアド"
```

やっておかないと、端末にて初めてコミットする時に以下のように怒られます↓

```
% git commit -m "first commit"
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.
```

## デフォルトブランチ名をmainに変更

```
% git config --global init.defaultBranch main
```

## 確認

下記ファイルに書き込まれるので確認できます
（ホームディレクトリ直下の`.gitconfig`ファイル）

```
~/.gitconfig
```

# ターミナルのカスタマイズ

## llコマンドのエイリアス設定



```
% vi ~/.zshrc
```

上記コマンドにてzshの設定ファイルを開き、（新規作成）

```
# llコマンド
alias ll='ls -lahFG'
```

と書き込み、保存する（`:wq`）

| オプション | 意味 |
|:-:|:-|
| l  | 長い形式で表示  |
| a  | 隠しファイルも表示  |
| h  | ファイルサイズを読みやすく表示（KB、MBなど）  |
| F  | 実行ファイルに*、ディレクトリに/を表示  |
| G  | 色付き表示、グループ非表示  |

https://atmarkit.itmedia.co.jp/ait/articles/1606/27/news018.html

https://eng-entrance.com/linux_command_ls


# おわりに
お読みいただきありがとうございました！
どなたかの参考になれば嬉しいです😆
pip installでのエラー(anaconda)備忘 手動での削除と追加

anadondaでpip installした際に、以下の様なエラーが出た。
ImportError: cannot import name '_log' from 'pip._internal.utils' (C:\anaconda\lib\site-packages\pip\_internal\utils\__init__.py)
```Traceback (most recent call last):
  File "C:\anaconda\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\anaconda\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\anaconda\Scripts\pip.exe\__main__.py", line 4, in <module>
  File "C:\anaconda\lib\site-packages\pip\_internal\__init__.py", line 4, in <module>
    from pip._internal.utils import _log
ImportError: cannot import name '_log' from 'pip._internal.utils' (C:\anaconda\lib\site-packages\pip\_internal\utils\__init__.py)
```



どうやらpipが壊れたようです。以下のコマンドでpipを削除。

```
>conda remove --force pip
```

再度pipを追加

```
>conda install -c anaconda pip
```
バージョンが古いと怒られる

```
WARNING: You are using pip version 22.1.2; however, version 22.2.2 is available.
You should consider upgrading via the 'C:\anaconda\python.exe -m pip install --upgrade pip' command.
```
警告通りバージョンアップ
```
>C:\anaconda\python.exe -m pip install --upgrade pip
```


無事もともと入れたかったパッケージをインストール

```
>pip install PySimpleGUI
```
Python lambda解説

# lambdaとは？
無名関数のこと。
関数を短く書けて便利。
関数名がないので、何回も使いまわしたい関数には使わない。

# 書き方
## 基本
```
lambda 引数 : 処理
```
## lambdaを使わない例と、使った例
### lambdaなし
```
def example(x, y):
    return x + y
```
### lambdaで書いた場合
```
lambda x,y : x+y
```
関数名なしで、短く書ける
## lambdaの引数に値を入れる時
さっきの例のxとyに値を入れる時の書き方
```
(lambda 引数:処理)(引数に入れたい値)　と書くので、
(lambda x,y : x+y)(1,2)
となる
```
Linux systemctlコマンドとシステム全体のサブコマンドについて

●ユニットに関わる主なsystemctlサブコマンド

・mask ユニット(サービス等)の無効化(マスク)
・unmask ユニット(サービス等)の有効化(アンマスク)

●システム全体の起動・停止に関わるサブコマンド

・poweroff 電源OFF
・emergency 緊急モードに移行
・rescue　レスキューモードに移行
・default 標準モードに移行
・再起動

●systemdを使ったシステムにおいて、ユニット、ターゲットの定義ファイルを置くディレクトリ

・/user/lib/systemd/system 永続的なユニット・ターゲットの定義ファイルが置かれるディレクトリパッケージのインストールなどで格納先となる
・/etc/systemd/system カスタム用のディレクトリ。起動時に開始するターゲットを定める「default.target」がおかれる。
・/run/systemd/system 再起動すると削除されるディレクトリ
Raspberry PI で VNC 接続

# はじめに
Windows から Rasberry PI の X Window に接続する方法の備忘録


# 初期設定
メニューから Raspberry Pi の設定を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/eafc7129-68f8-8d38-9abc-eaa701efc428.png)

VNC を有効にする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/0678d505-635f-d829-d031-f5764129c613.png)


# VNC 起動確認

```bash
# ps -ef |grep vnc
root       398     1  0 09:59 ?        00:00:00 /usr/bin/vncserver-x11-serviced -fg
root       408   398  0 09:59 ?        00:00:09 /usr/bin/vncserver-x11-core -service
root       736     1  0 09:59 ?        00:00:02 /usr/bin/vncagent service 13
pi         742     1  0 10:00 ?        00:00:01 /usr/bin/vncserverui service 14
pi         819   742  0 10:00 ?        00:00:00 /usr/bin/vncserverui -statusicon 5
root      3113  2351  0 11:49 pts/1    00:00:00 grep vnc

# netstat -an |grep 5900
tcp        0      0 0.0.0.0:5900            0.0.0.0:*               LISTEN
tcp        0      0 192.168.111.77:5900     192.168.111.50:53418    ESTABLISHED
tcp6       0      0 :::5900                 :::*                    LISTEN

```

# 接続用ユーザのパスワード変更

```bash
# su - pi
$ vncpasswd -user
Setting "Password" VNC parameter for User Mode server
Password:
Verify:
Successfully set "Password" VNC parameter in
```

# クライアント

VNC Viewer をダウンロードしてインストール
https://www.realvnc.com/en/connect/download/viewer/

VNC Viewer を起動してユーザ名、パスワードでログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304109/2ebdab4c-75e0-0fe5-2e82-05b3d1761c79.png)
プログラミング教室でRubyとRailsを中心に習っていた初心者がJavaで課題作成に取り組んだ備忘録2

備忘録1の続きになります。

## 配列の作成
配列を利用するための最初の手順は配列を宣言すること。
宣言の仕方には、以下の2種類がある。
```
①データ型 + 配列変数名 + []
②データ型 + [] + 配列変数名
```
データ型は，プログラム内で扱うデータの種類のこと
(Railsだとデータベース設計する時に決まるカラムの型が近いかな？)

複数の文字列を格納する時はString型を使う。
char型は1文字しか格納出来ない。

数値のデータ型はbyte、short、int、longがある。
小さい数値の場合でも int 型を使用した方が処理が高速に行えることから整数を扱う場合は基本的に int 型を使う。整数で変数を作成する時もint型を使う。


配列の最初のインデックスは1ではなくて0から始まる。（これもRubyと一緒）
配列への代入の書き方はいろいろあるが下記が一番分かりやすい
```
// 宣言と代入を同時に行う書き方
int nums[] = {1,2,3,4,5};
```
配列から特定の値を取り出す時は[]でインデックス番号を指定して出力する
```
public static void main(String[] args) {
	int nums[] = {1,2,3,4,5};
	System.out.println(nums[1]);
}
```

## for分とは
定められた回数だけ同じ処理を繰り返したいときに使う。
fizz buzzのような「1〜１００まで出力せよ！」みたいな命令に使われることが多い。
通常のfor文と拡張for文の二種類ある
```:通常のfor分
for(初期化式; 条件式; 変化式){
　実行する処理
}
```
```:拡張for分
for (型 変数名: 配列名もしくはコレクション名){
    実行する処理
}
```
※コレクションとは配列のように複数の要素を管理できるオブジェクトの事
拡張for文をつかったほうが記述内容がシンプルでコーディングもしやすく、可読性も優れている。


## for分で配列の取り出し方

```:サンプル1
String name[] = {"Suzuki", "Katou", "Yamada"};

for (String str: name){
  System.out.println(str);
}
```
```:サンプル２
int age[] = {25,30,40};

for (int str: age){
  System.out.println(str);
}
```
サンプル1の記述内容
 1)配列から要素を取り出し変数 str に格納する(str="Suzuki")
 2)ブロック内の処理を実行(画面に変数 str の値を「System.out.println」で出力)
 3)繰り返しの1回目終了
 4)配列から要素を取り出し変数 str に格納する(str="Katou")
 5)ブロック内の処理を実行(画面に変数 str の値を出力)
 6)繰り返しの2回目終了
 7)配列から要素を取り出し変数 str に格納する(str="Yamada")
 8)ブロック内の処理を実行(画面に変数 str の値を出力)
 9)繰り返しの3回目終了
10)配列から要素をすべて取り出したので繰り返しを終了

##  if分
考え方はRubyと同じ。
条件式がtrue だった場合は { から } のブロック内に記述された処理を上から順番に実行。条件式が false の場合はブロック内の処理は何も行わずに if 文の次の処理へ進む。
【主な比較演算子】（aとbは数値型変数）
「a == b」...aとbが等いときはtrue、それ以外はfalseを返す
「a > b」...aがbよりも大きいときはtrue、それ以外はfalseを返す
「a < b」...aがbよりも小さいときはtrue、それ以外はfalseを返す
```:サンプル１
if(a == b){
　System.out.println("aとbの値は" + a + "です。");
}
```
if文はelseやand・or・notと組み合わせて、条件を分岐させることも可能。

``` :サンプル２
if (条件式1){
  // 条件式1が true のときに実行される処理
  ...
}else if (条件式2){
  // 条件式2が true のときに実行される処理
  ...
}else if (条件式3){
  // 条件式3が true のときに実行される処理
  ...
}else{
  // すべての条件式が false のときに実行される処理
  ...
}
```


## 今回の課題のメインの部分（for分とif分の組み合わせ）
１、文字列と数値を格納する配列を一つずつ作る
２、文字列の配列に対してfor分を使って繰り返し処理を行う
３、特定の文字の際には指定した数字を出力する
```
package sample;

public class Sample {

		public static void main(String[] args) {
			String names[] = {"Suzuki", "Katou", "Yamada"};
			int age[] = {25,30,40};

			for (String name: names){
					if (name == "Suzuki") {
					  System.out.println(age[0]);
					}
					else if (name == "Katou") {
						System.out.println(age[1]);
					}
					else if (name == "Yamada") {
						System.out.println(age[2]);
		    }
         }
    }
}
```
```:結果
25
30
40
```

### 気づき
・重複したローカル変数は使えない(「String name: name」のような記述だとエラーになる)
・if分で{}や;の数が合っていないとエラーになる（トークン "else" に構文エラーがあります。このトークンを削除してくださいというエラー分が出てきた）
・トークンの意味は二つ
１、文の中の単語や記号、数値などの事
2、データの正当性を証明したり、正しく処理が行われているかどうかを証明するためのデータ（主に文字列）の事
・if分に波括弧を付けなくてもfor分のブロック内に書かれていれば処理はできる。
```
for (String name: names) {
	if (name == "Suzuki") 
	    System.out.println(age[0]);
	else if (name == "Katou") 
		System.out.println(age[1]);
	else if (name == "Yamada") 
		System.out.println(age[2]);
         }
```
・やはりエラー分は間違っている箇所を教えてくれるので頼りになる。

以上になります。