OmniAICreator/Qiita-1.07M huggingface dataset:
train_test_split() で正解ラベルの割合を変えたくない場合は stratify パラメータを使用する

# 結論
train_test_split()を使用する際、`stratify`パラメータを使用すると学習データと評価データで正解ラベルの割合が均一となる。
```python
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)
```
# 背景
不均衡データを扱う機会があり、学習データと評価データの正解ラベルの割合を揃えたかった。

# ライブラリ情報
| 項目 | 情報 |
| ---- | ---- |
| Python | 3.9.7 |
| sklearn | 1.1.3 |

# ソースコード
## 事前準備
```python
import time
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split


# irisのデータセットを準備
data_iris = load_iris()
X = pd.DataFrame(
    data_iris.data, 
    columns=data_iris.feature_names
)

y = data_iris.target
```

## 正解ラベルを確認
```python
u, counts = np.unique(y, return_counts=True)

# ラベルの一覧
print(u)
# [0 1 2]

# 各ラベルの件数
print(counts)
# [50 50 50]
```

## 各ラベルの割合を確認する関数を定義
```python
def calc(i, y):
    print(str(i+1) + '回目 (' + str(len(y_train)) + '件)')
    print('・Label 0 : ' + str(np.round((y == 0).sum()/len(y), 2)) + ' %')
    print('・Label 1 : ' + str(np.round((y == 1).sum()/len(y), 2)) + ' %')
    print('・Label 2 : ' + str(np.round((y == 2).sum()/len(y), 2)) + ' %')
    print('---')
```

## `train_test_split()`デフォルトの場合
```python
for i in range(5):
    X_train, X_test, y_train, y_test = train_test_split(X, y)
    calc(i, y_train)
```

### 出力
```
1回目 (112件)
・Label 0 : 0.36 %
・Label 1 : 0.32 %
・Label 2 : 0.32 %
---
2回目 (112件)
・Label 0 : 0.35 %
・Label 1 : 0.32 %
・Label 2 : 0.33 %
---
3回目 (112件)
・Label 0 : 0.38 %
・Label 1 : 0.34 %
・Label 2 : 0.29 %
---
4回目 (112件)
・Label 0 : 0.37 %
・Label 1 : 0.31 %
・Label 2 : 0.32 %
---
5回目 (112件)
・Label 0 : 0.34 %
・Label 1 : 0.34 %
・Label 2 : 0.32 %
---
```
正解ラベルの割合にばらつきがある。

## `train_test_split()` `stratify`を使用した場合
```python
for i in range(5):
    X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)
    calc(i, y_train)
```

### 出力
```
1回目 (112件)
・Label 0 : 0.33 %
・Label 1 : 0.34 %
・Label 2 : 0.33 %
---
2回目 (112件)
・Label 0 : 0.33 %
・Label 1 : 0.33 %
・Label 2 : 0.34 %
---
3回目 (112件)
・Label 0 : 0.33 %
・Label 1 : 0.34 %
・Label 2 : 0.33 %
---
4回目 (112件)
・Label 0 : 0.34 %
・Label 1 : 0.33 %
・Label 2 : 0.33 %
---
5回目 (112件)
・Label 0 : 0.34 %
・Label 1 : 0.33 %
・Label 2 : 0.33 %
---
```
正解ラベルの割合が均一であることが確認できる。

# 参考サイト
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

https://kakakakakku.hatenablog.com/entry/2021/11/30/160351
技術雑誌の世界に入門してみたら、予想外の面白さに驚いた

# はじめに
はじめまして！
筆者は、資金繰りに困っている人をサポートするようなサービスを開発している、とあるスタートアップ企業に所属しています。

今回この記事を書こうと思ったのは、初めて技術雑誌を読んで予想以上に面白かったからです。
技術雑誌を読んでこなかった方に、少しでも興味を持ってもらえるような内容をお伝えできたらと思っています。

私が技術雑誌を読もうと思ったきっかけは、[伊藤淳一](https://qiita.com/jnchito)さんでした。
とあるイベントで、伊藤さんが「[SoftwareDesign3月号](https://amzn.asia/d/dGN721y)」の特集内のコーナーで、ITエンジニアのスキルアップについて語られているという案内があり、即予約購入しました。

私の自己紹介はここまでにして、技術雑誌を読んで良かったポイントをいくつか紹介したいと思います。

## 普段触れない技術をキャッチアップできる
普段触れない技術について、浅く広くキャッチアップできる点が良かったです。
読む前からなんとなく分かってはいましたが、技術雑誌を毎月購入して読むだけでもある程度トレンドを追えそうな予感がしました。

当たり前ではありますが、ネットで見る技術情報に比べ、文章がまとまっているので綺麗な情報が載っていると感じました。
そして、綺麗にまとまった情報なので、「ネットで見かけるけどよくわからないレベルの情報」について解像度を高めることができます。

技術情報を記事にしているサイトなどを日々巡回してもいいのですが、自分が興味のある情報だけ集めに行ってしまうので、偏りがちになります。
そこで、浅く広く情報が載っている技術雑誌を日々読み、興味がある分野についてはさらに深掘りしていくと良さそうだと感じました！

## ハンズオン形式が良い
意外だった＆とても良かったポイントとして、ほとんどの技術的な情報に対してハンズオン形式で説明されていました。
最初は、興味のない情報が書かれているだけで、眠くなりそうなイメージだったので、とても驚きました。

ハンズオン形式だと実際に触っていて楽しいというのがあるので、退屈せずに技術情報を習得できますよね〜
Qittaなどに投稿されている技術情報系の記事でも、ハンズオン形式のものは情報キャッチアップに適しているので、好みがあるかもしれません。w

改めて、ハンズオン形式で飽きることなくインプットできる点は、技術雑誌を読む上で一番良かったな〜と思いました。

## 技術的な情報以外の内容が面白い
また、意外なポイントとして、技術的な情報以外のセクションがとても面白かったです！
技術雑誌だけに、技術的な情報だけで埋め尽くされていると思っていた先入観が覆されました。

一番良かったのは、特集されていた「ITエンジニアが活躍し続けるためには？」の内容がとても面白かったです！
過去の特集などを調べてみようかと考えるくらい良かったです。
今回がたまたま面白かったのかもしれませんが、次月号なども引き続き購入して検討が必要ですね。

他にも、チーム開発で使用するツールの活用事例なども紹介されていて、技術的な内容以外にもたくさんの情報が載っているな〜という印象を持ちました。

# 終わりに
みなさん、技術雑誌を購入してみたくなったでしょうか？僕もまだ1冊しか読んでいないので、もしかしたら当たりの月を購入した可能性はあるかもしれません。
とはいえ、ハズレ回も含めて色々なことを学べそうなので、今年の12月までは毎月購入してみようと思っています！

これを機に、技術雑誌を購入したことがない方は、一度読んでみてはいかがでしょうか。

# 参考情報
今回読んでみた技術雑誌は「[SoftwareDesign3月号](https://amzn.asia/d/dGN721y)」です。
NotionやSlackで、「`」で囲んでもインラインコードにならない問題

# はじめに
NotionやSlackでは、一部のマークダウン記法がサポートされています。
そのうちの1つが、「'」で囲めば、インラインコード表示になるというもの。（[Notion公式リファレンス](https://www.notion.so/ja-jp/help/customize-and-style-your-content)）
実際にやってみましょう!
![インラインコード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/2f6bafd4-0e03-3a73-9c7d-eff6283a71fe.gif)

<img width="100" src="https://media.tenor.com/ETpF4KXBS5gAAAAd/%D1%81%D1%80%D1%81%D0%BC-%D0%B1%D0%B5%D0%BB%D0%B0.gif">

_____ /\\ ________
...ならないジャン！
\_______________

# 対策
「`」の前に、半角スペースを入力すればOK

![インラインコード2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/098c0be6-4245-5fea-900b-8731f72629b4.gif)

ただ、新たな問題が１つ。
入力した半角スペースをわざわざカーソルをその位置に戻して削除するのが超面倒...。

個人的な対策として、わざわざ消さずに、インラインコード終了時の「`」の後にも半角スペースを入れることで、見た目を綺麗に保っています。

↓こんな感じ
![インラインコード3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321577/167ceb8f-7581-c059-7531-6b9e7b7c648c.gif)
というか、そもそも今回のケースにかかわらず、 **文中にマークダウンを書くときは、初めと終わりに半角スペースを入れるもの** だと思った方がよさそう。
Qiitaでは、文中のマークダウンは半角スペースなくても認識するが、[公式のチートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)を見ると、半角スペースで囲っている。↓↓↓

```
__ か ** で囲むとHTMLのstrongタグになります。Qiitaでは **太字** になります。
```
基本的なことのようで恥ずかしいですが、今後は半角スペースいれる人になろうと思います...

以上
PySimpleGUIを使ってハードウェアをモニターするGUIアプリを作る

CPU使用率、CPU使用率グラフ、メモリ使用率、残バッテリーを表示するGUIアプリ
Mac想定です。

```Python
import PySimpleGUI as sg
import psutil
import threading
import time

sg.theme('SystemDefault')

#CPUとメモリの使用率,残バッテリーを取得
def getAllInfo():
    start = time.time()
    point_from=(0,0)
    while True:
        CPU = psutil.cpu_percent(interval=1)
        CPU = int(CPU)
        mem = psutil.virtual_memory()
        battery = psutil.sensors_battery().percent
        currentTime = time.time() - start
        currentTime = int(currentTime)

        window['-CPU-'].Update(CPU)
        window['-mem-'].Update(mem.percent)
        window['-battery-'].Update(battery)

        point_end=(currentTime,CPU)

        graph.draw_line(point_from, point_end, color='red', width=2)

        time.sleep(1)

        CPU = psutil.cpu_percent(interval=1)
        CPU = int(CPU)
        mem = psutil.virtual_memory()
        battery = psutil.sensors_battery().percent
        currentTime = time.time() - start
        currentTime = int(currentTime)

        point_from=(currentTime,CPU)

        graph.draw_line(point_from, point_end, color='red', width=1)

        graph.update()


graph = sg.Graph(canvas_size=(380,200),
                  graph_bottom_left=(0,0),
                    graph_top_right=(200,120))

# ウィンドウのレイアウト
layout = [ [sg.Text('CPU使用率'),sg.Text(key='-CPU-'),
            sg.Text('メモリ使用率'),sg.Text(key='-mem-'),
            sg.Text('残バッテリー'),sg.Text(key='-battery-'),],
            [graph],
        ]

# ウィンドウオブジェクトの作成
window = sg.Window('ハードウェアモニター', layout, finalize=True, auto_size_text=True, element_padding=(10,10))

threading.Thread(target=getAllInfo, daemon=True).start()

# イベントのループ
while True:
    # イベントの読み込み
    event, values = window.read()
    # ウィンドウの×ボタンが押されれば終了
    if event == sg.WIN_CLOSED:
        break

# ウィンドウ終了処理
window.close()
```

# 出来上がった物
![hardwareMonitor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400525/e7db566e-9a0b-7b26-5521-ac9454a13c24.gif)

# 拡張性
```Python
sg.theme('SystemDefault')
```
PySimpleGUIのテーマ指定。今回はSystemDefaultを指定
Django REST frameworkの環境構築 〜仮想環境venv〜

ReactからAPIを使用するのに、APIの部分をDjango REST frameworkで構築するために
導入までの手順をまとめた

Django REST frameworkは、PythonのWebアプリケーションフレームワークであるDjangoを拡張したもので、RESTful APIを簡単に構築できるようにするためのツールキットです。

https://www.django-rest-framework.org/

コードは公式のチュートリアル↑を引用しています

Django REST frameworkは「DRF」で表します。

必要があれば仮想環境を作成して実施してください
```shell
python -m venv .      　# 仮想環境を作成
source ./bin/activate 　# 仮想環境を有効化
```

# 手順
1.インストール
```shell
pip install djangorestframework markdown django-filter
```

2.Djangoのプロジェクト作成
```shell
django-admin startproject djangoApp
```

3.setting.pyにrest_frameworkを追加
```python:setting.py
INSTALLED_APPS = [
    ...
    'rest_framework',
]

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}
```

4.簡単なAPIを作成してみます
```python:urls.py
from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets

# API
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'is_staff']

# ビューの動作
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

# URLの設定を自動的に決定する方法を付与
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)

# URLの設定
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
```

5.Djangoアプリを起動します
```shell
python manage.py runserver
```

6.ブラウザーを開いて、下記へアクセスします
http://127.0.0.1:8000/

下記画面が開きます
![スクリーンショット 2023-03-12 18.19.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/fb58c84e-3e3b-7c0e-cbf9-9d0528fdeff6.png)

以上です

# 補足
Djangoの雛形を作成した時にタイムゾーンや言語の設定がアメリカのものになっているので
日本向けに設定します
```python:setting.py
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
```


# DRFを導入するメリット
1.速度と拡張性
Django REST frameworkは、Djangoフレームワークを拡張して作られているため、高速で拡張性が高く、複雑なWebアプリケーションでもパフォーマンスを維持できます。

2.簡単なシリアライゼーション
Django REST frameworkは、PythonオブジェクトをシリアライズしてJSONやXMLなどのフォーマットで返すことができます。このため、データを簡単に操作できます。

3.豊富な認証方法
Django REST frameworkは、多様な認証方法をサポートしています。例えば、トークンベースの認証、OAuth 1.0a / 2.0、Basic認証、JWTなどがあります。

4簡単なドキュメンテーション
Django REST frameworkは、APIドキュメントを自動生成する機能を持っています。これにより、開発者はAPIの仕様やエンドポイントを簡単に確認することができます。

5.拡張性
Django REST frameworkは、ビュー、シリアライザ、レンダラー、パーサーなどの機能を拡張することができます。これにより、独自の機能を追加したり、既存の機能を上書きしたりできます。

6.安全性
Django REST frameworkは、セキュリティ機能を提供しています。例えば、XSSやCSRF攻撃を防止するための機能があります。
Power Query にてTableとスカラー値が混在する列からTableを展開する方法

下記テーブルのように一つの列に数値とTableが交互に格納されているような場合、このままではTableを複数行に展開することができません。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/d92eedee-0346-510a-3adc-ff3d2440ed87.png)

Tableを展開するにはまず `if Value.is()` を使ってTable型の値のみを抽出して、それ以外はnullを格納した列を追加します。
```
= Table.AddColumn(ピボット解除された列1, "テーブル2", each if Value.Is([値], Table.Type) then [値] else null)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/0b761acf-4de9-6398-ae14-bdf4e714732c.png)

あとは通常の手順と同様に`Table.ExpandTableColumn`を使ってTableを展開することができます。
```
= Table.ExpandTableColumn(追加された条件列, "テーブル2", {"val"}, {"テーブル2.val"})
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8721/772ed67a-e07c-eeee-c11a-273da7ae9dc6.png)
Salesforce認定アソシエイト試験の公式練習問題解説してみた-09

こんにちは

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

今回は
認定資格試験の準備: Salesforce 認定アソシエイト＞
データモデルについて学ぶ

の問題1問目を解説します

今回の内容は動画でも公開しています

https://www.youtube.com/watch?v=XyPDwb3X6xU

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



https://trailhead.salesforce.com/ja/content/learn/modules/cert-prep-salesforce-certified-associate/study-up-on-the-data-model

本日の問題はこちらです

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e3344e5a-72ee-8372-0c03-30c01244ef61.png)


正解はAです

リードを取引開始済みすると取引先、取引先責任者、商談が作成されます

詳細はこちらのTrailheadもご確認ください

https://trailhead.salesforce.com/ja/content/learn/modules/leads_opportunities_lightning_experience/create-and-convert-leads-lightning

## 他の認定アソシエイトの勉強方法について

他の勉強方法についてはこちらをご確認ください

https://qiita.com/Takaa/items/d35c9955fe8eb889d76b
RSSのアイコンが表示されなかった時の忘備録

# はじめに

自分で作成したアプリからRSSを発行する際、そのリンクをFeedlyやfeederなどのRSSリーダーに登録してみると、アイコンが表示されない問題に遭遇しました。

# 前提条件

前提として、ステージング環境にデプロイ済みで、URLも発行されています。
そして、`favicon.ico`も存在しています。

# 最初のRSS

最初のRSSは次のように作成していました。

ここでは、`<link>`タグや`generator`タグに`http://example.com`というURLを指定していますが、実際にはまだ登録されていない本番環境で使用予定のドメインを使用していました。

```xml
<rss version="2.0">
  <channel>
    <title>たかぎとねこのRSSフィード</title>
    <link>http://example.com/takagimeow/rss.xml</link>
    <description>This RSS feed is generated by takagimeow</description>
    <lastBuildDate>Sun, 05 Mar 2023 15:49:45 GMT</lastBuildDate>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <generator>http://example.com</generator>
    <copyright>Copyright©️ 2023 takagimeow</copyright>
  </channel>
</rss>
```

# `<image>`タグを追加

次に、`<image>`タグを追加してみました。この`<image>`タグでは実際に参照可能な画像のURLを指定しています。ただ、`<link>`タグや、`<generator>`タグに指定しているドメインとしては、まだ登録されていないドメインを指定していました。

そして`<image >`タグは指定したものの、この場合もアイコンは表示されませんでした。

```xml
<rss version="2.0">
  <channel>
    <title>たかぎとねこのRSSフィード</title>
    <link>http://example.com/takagimeow/rss.xml</link>
    <description>This RSS feed is generated by takagimeow</description>
    <lastBuildDate>Sun, 05 Mar 2023 15:49:45 GMT</lastBuildDate>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <generator>http://example.com</generator>
    <image>
      <title>たかぎとねこのRSSフィード</title>
      <url>http://{REAL WORLD DOMAIN}/favicon.png</url>
      <link>http://example.com/takagimeow/rss.xml</link>
    </image>
    <copyright>Copyright©️ 2023 takagimeow</copyright>
  </channel>
</rss>
```

# 正しいリンクを`<link>`タグに指定した

そこで、`<link>`タグや`<generator>`タグに、実際に登録されているドメインを指定してみました。

Remixを使って開発していたため、`request`から`URL`インスタンスを作成して、その`origin`を動的に取得しています。

```ts
export const loader = async ({ request }: LoaderArgs) => {
  ...
  const url = new URL(request.url);
  const origin = url.origin;
  ...
}
```

そして、`<link>`タグや`<generator>`タグに、取得した`origin`を指定してみました。

その結果、FeedlyやfeederなどのRSSリーダーにリンクを登録した際に、アイコンが表示されるようになりました。

```xml
<rss version="2.0">
  <channel>
    <title>たかぎとねこのRSSフィード</title>
    <link>http://{REAL WORLD DOMAIN}/takagimeow/rss.xml</link>
    <description>This RSS feed is generated by takagimeow</description>
    <lastBuildDate>Sun, 05 Mar 2023 15:49:45 GMT</lastBuildDate>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <generator>http://{REAL WORLD DOMAIN}</generator>
    <image>
      <title>たかぎとねこのRSSフィード</title>
      <url>http://{REAL WORLD DOMAIN}/favicon.png</url>
      <link>http://{REAL WORLD DOMAIN}/takagimeow/rss.xml</link>
    </image>
    <copyright>Copyright©️ 2023 takagimeow</copyright>
  </channel>
</rss>
```

以上の内容から、おそらく`<link>`タグに指定しているURLをもとにファビコンが取得されて、アイコンとして表示されているのではないかと思います。

なので、これらの値は適切に設定しておく必要がありますので、リーダーなどでアイコンを表示したい場合はご注意ください。
サーバレスで作るデータ分析基盤

過去2回、自社データ分析基盤の構築に関わってきましたが、3回目にしてかなりシンプルで高性能なデータ分析基盤を作ることができたので、記事として公開します。

## 1社目のデータ分析基盤　2013年頃
こちらは私が考えたものではなく、メンバーとしてプロジェクトに参加させて頂いたものです。
- ソース：Oracle（売上データ）
- DWH：SQLserver（オンプレミス）
- ETL：自作のVBSをDWHサーバ上でスケジュール実行
- BI：QlikView

#### 課題など
QlikViewがインメモリ型であった為、列指向DBは使用せず、使い慣れたSQLserverで構築。取り込むデータが増えるほどにQlikViewのパフォーマンス劣化が顕著に。QlikViewサーバのスケールアップで凌ぐのも限界を感じていたところで退職。

## 2社目のデータ分析基盤（2019年頃）
メンバーは私ひとりだったので、構築も運用もすべて自分で実施。基盤自体は2016年からビルド&スクラップを繰り返しており、最終的な構成がこちら。

- ソース：Oracle（売上データ）、SQLserver（社内マスタデータ）
- DWH：Snowflake
    - 歴史：SQLserver → Snowflakeへ変更
- ETL：Talendで作成したバッチをタスク管理サーバでスケジュール実行
    - 歴史：VBSを自作 → Talendへ変更(VBSも一部併用)
- BI：Metabase
    - 歴史：PowerBI → QuickSight → Metabase と変遷。

#### 課題など
Talend採用によって異なるDBを直接接続（Oracle → Snowflake、SQLserver → Snowflake）することが容易にできた。しかし、Talendだけでデータ整形は終わらない為、Snowflake上でのデータ整形の棲み分けも必要となり、バッチ数が増えるごとに管理が煩雑になった。
Snowflakeの採用とMetabaseの採用によって安価で高性能なデータ分析基盤構築が構築できたが、ETL部分の煩雑さが運用負荷となってしまった。

## 3社目のデータ分析基盤（2023年）
Snowflakeの外部ステージ、Snowpipe、task、Streamという機能を活用して、非常にシンプルな基盤を構築。
- ソース：CSV（売上データ、コストデータ、外部データ）
- データレイク：S3
- DWH：Snowflake
- ETL：S3にCSVを置くとSnowpipeを通じて即時に取り込みとデータ整形taskが実行される
- BI：PowerBI

#### 課題など
前回導入したTalendが、データ連携を容易にした部分と作業を煩雑にした両面があったので、今回も使うかどうかで非常に悩んだ。PythonでETLを自作するようにしようと考えたが、「Snowflakeに取り込んでから整形する」＝ELTという思考に変更すれば、Pythonも不要ということに気づいて方針を転換。S3に置いたCSVをSnowPipeで取り込むことを基本としたことで、サーバレス実行できるようになった。


## 3社目のデータ分析基盤（2023年）について詳しく書きます。
前回は「サーバレスでデータ分析基盤作る」ということができなかったので、今回はここに力を入れました。

その為、最初は以下のようにLambdaで動作するPythonプログラムでデータを整形してから取り込みを実行していましたが、SnowflakeのSnowPipe、Stream、Taskの機能を組み合わせることで、Lambda（Python）も使うことなくデータ分析基盤が構築できるようになりました。「データを整形してから取り込む」から「データを取り込んでから整形する」に思考を変えることが重要なポイントでした。
また、エンジニア採用が困難な昨今、クラウドの知識は必要ですが、SQLが分かれば大半のことができる仕組みにできたことは、人件費といった側面からも大きな効果があったと感じています。


![2023-03-12_16h58_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/6c10e01b-0d22-d9d9-843c-3c228b4dba50.png)

![2023-03-12_16h58_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/b2fb8f30-c421-3e9e-90ec-37e5cd93be0c.png)

#### メリット
- マネージドサービスの組み合わせなので、データマネジメント業務に集中できる
- S3にデータを置くと自動でSnowflakeに取り込まれ、データ整形も実行される
- Snowflake（とAWS）の知識があれば構築できる
- SQLのみでデータ整形ができるので、人材採用のハードルも下がる。

#### 今回作成したデータ分析基盤の構成図
![2023-03-12_17h45_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/2c1a4fa0-8104-5528-44b6-4982c5b6f5af.png)

SQSやSNSなどのAWSの機能も利用していますが、非常に簡単なものとなっております。
詳しい構築方法については、機会があれば記事にしたいと思います。
Googleデジタルマーケティング＆Eコマース：Google広告アカウントの構成

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# Google広告アカウントの構成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/c59a9528-7bf8-29b3-ca80-94cb75c8faab.png" width="700">

以下の項目は、Google広告でキャンペーンを作成する際に経験する順序で紹介されています。上の図に沿うように定義を参照してください。

### <font color="MediumBlue">Google Ads</font>

Googleのオンライン広告プログラムです。Google広告を通じて、オンライン広告を作成し、人々があなたの提供する製品やサービスに興味を持っているときに、正確にリーチすることができます。

### <font color="MediumBlue">Campaign</font>

予算やロケーションターゲティングなどの設定を共有する1つまたは複数の広告グループのセットが、どのようにオンライン上で配信されるかの行動計画のことです。キャンペーンは、提供する製品やサービスのカテゴリを整理するためによく使用されます。

### <font color="MediumBlue">Ad Groups</font>

キーワードをテーマにしたグループに分けて、広告を整理し、ターゲットを絞る方法です。各キャンペーンは、1つまたは複数の広告グループで構成されています。

### <font color="MediumBlue">Ad Formats</font>

Google広告で商品やサービスを宣伝するために使用されるテキスト、ビデオ、画像、デジタルコンテンツ広告などが並んで表示されます。

### <font color="MediumBlue">Bids</font>

潜在顧客が広告をクリックしたり、電話をかけてきたりするたびに支出する金額は、入札と呼ばれるものです。

### <font color="MediumBlue">Keywords</font>

これらは、あなたの広告がいつ、どこに表示することができますを決定するのに役立つあなたが選択した製品やサービスを説明する言葉やフレーズです。広告主は互いに入札し、広告は、入札額と広告の関連性などの要素に基づいてランク付けされます。
Googleデジタルマーケティング＆Eコマース：Google広告を作成するためのベストプラクティス

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/84e33f4e-81cb-98a6-4546-f2ec06fd8b8b.png" width="800">

# Google広告作成するためのベストプラクティス

効果的な検索広告を作成するためのベストプラクティスをいくつか取り上げてみましょう。

潜在顧客に広告のクリックを促すことに加えて、なぜ効果的な広告を求めるのでしょうか？

効果的な広告は、検索結果ページでより上位に表示され、より多くのクリックとより多くのコンバージョンを生み出し、時には競合他社よりも低いクリック単価を実現することができます。

### <font color="MediumBlue">ユーザーのニーズとメリットに焦点を当てたメッセージを作成する</font>

これは、検索者にとって価値があることを示しています。検索者は、自分にとって重要な概念を含む広告に反応する可能性が高くなります。検索者が広告に何を求めているかを考えましょう。

- 信頼性や信用性でしょうか？
    - "公式サイト"などの言葉を使うとよいでしょう。
- それとも、豊富な品揃えを求めているのでしょうか？
    - "あなたは、"当社の在庫を見る "を含めることができます。

この機会に、これらの顧客ペルソナを活用してみましょう。ペルソナの目標を見直し、広告に追加することを検討してください。

### <font color="MediumBlue">広告グループのキーワードのうち少なくとも一つを見出しに含める</font>

見出しは、広告の上部にあるクリック可能なリンクであることを忘れないでください。Googleは自動的に見出しと説明文の組み合わせをテストするので、任意の組み合わせがうまく読み取られることを確認してください。それは潜在的な顧客が考えているものですので、キーワードからのテキストを含めることが重要です。あなたの広告が、彼らが探しているものとつながっていれば、クリックされる可能性が高くなります。

また、広告コピーを自動的に調整するための特定のカスタマイズで、見出しにキーワードを配置する高度なツールもいくつかあります。Google広告の知識を増やすと、これらの高度なテクニックを学ぶことができます。

### <font color="MediumBlue">一般的な販売言葉を避ける</font>

「今すぐお電話ください」というようなフレーズは、誤った切迫感を生みます。ユーザーの利益を念頭に置いてください。本当にユーザーにとってメリットがないのであれば、なぜ今日電話をするのでしょうか？「今日申し込む」「今日予約する」などの非特定または一般的なコールトゥアクションは、広告のエンゲージメントを低下させることがよくあります。

一般的なセールス用語の代わりに、具体的で親近感のわく行動喚起を使用しましょう。あなたが不動産管理会社のコピーを書いていると想像してください。広告に「今すぐ予約」と書く代わりに、「夢のバケーションレンタルを予約」と書きましょう。これは、より具体的であり、潜在的な顧客が望むものにもっと密接に関連しています。

### <font color="MediumBlue">意味のあるすべての広告エクステンションを実装する</font>

[広告の拡張機能][ext]は、ビジネスに関する追加情報を提供します。役立つ情報を表示することで、検索広告をより魅力的なものにするために設計されています。広告拡張機能を含めると、結果ページで広告をより目立つようにすることもできます。位置情報、通話、アプリのインストールなどの拡張機能は、モバイルユーザーのエクスペリエンスも向上させます。

広告を競合他社から切り離す簡単な方法です。複数のエクステンションを広告で表示することができるので、ビジネスにとって意味のあるものはすべて有効にしてください。そして、可能な場合は、少なくとも4つを有効にするようにしてください。Google広告は、オークションごとに最適なエクステンションの組み合わせを決定します。

[ext]: https://qiita.com/mapami/items/95a04f2be562dcaf88d2

### <font color="MediumBlue">ランディングページを最適化する</font>

広告とランディングページが連動することで、優れたユーザーエクスペリエンスを提供することができます。キーワードとランディングページのコピー、そしてその全体的なユーザーエクスペリエンスを比較する必要があります。正確なキーワードがランディングページにある必要はありませんが、関連性がすぐにわかるようにする必要があります。

- 広告をクリックした人にとって、そのランディングページはどれだけ役に立つか？
- ページがうまく構成されているか？
- テキストは、誰かの検索キーワードに関連しているか？
- ランディングページの指示は明確か？

また、ランディングページを信頼できるものにする必要があります。できるだけ早く読み込めるようにしましょう。ページの読み込みに時間がかかりすぎると、ユーザーはイライラしてページを離れてしまうかもしれません。これは、広告とページが最良の選択肢ではない可能性があることをGoogleに示しています。
Reactの環境設定を行う

# この記事の目的
現在Springを用いてポートフォリオを作成中なのですが、当初の予定ではフロントはThymeleafを用いて作成しようと考えていました。
しかし、モダンなフレームワークを使用したかったので、今回フロントはReactを用いて作成することにしました。
今回はその第一弾として、Reactを使用するために環境設定を行っていきたいと思います。

# 参考にした本
今回は以下の本を読みながら開発を進めます。

https://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E3%81%95%E3%82%8F%E3%82%8BReact-JavaScript-TypeScript-%E4%B8%89%E5%A5%BD%E3%82%A2%E3%82%AD-ebook/dp/B09Q57Q9T1

# 手順
1. Nodeのインストール
1. VS Codeのインストール
1. create-react-appのインストール

## 1. Nodeのインストール
NodeはJavaScriptの実行環境です。この環境があるとJavaScriptでバックエンドの開発を行えます。
Reactを始めとする近年のフロントエンド開発ではNodeが必須です。

https://nodejs.org/en/download/

LTSとCurrentの2つがありますが、LTSをダウンロードします。

インストールの細かな設定に関しては以下の記事を参考にしてください

https://qiita.com/sefoo0104/items/0653c935ea4a4db9dc2b

設定が全て終了した後、一度再起動してコマンドプロントでNodeとnpmのバージョンを確認すると現在のバージョンが表示されます。
バージョンが表示されていれば、上手くインストールできています。
(確認するためのディレクトリはどこでも大丈夫です。下記コードではダウンロードフォルダでコマンドを入力してあります)
```console
C:\Users\xxxxx\Downloads>node -v
v18.15.0

C:\Users\xxxxx\Downloads>npm -v
9.5.0
```

:::note
nmpとはNode Package Managerの略であり、パッケージやダウンロードの管理り使用されます。
:::

## 2. VS Codeのインストール
エディターはVS Codeを使用します。
下記からインストールします。現時点で必要な拡張機能は特に必要ないようです。

https://code.visualstudio.com/download

## 3. create-react-appのインストール
Reactは開発元であるFacebookが基本的な設定を全て済ませたスターターキットを用意しており、それがcreate-react-appと言うものです。
これを使用すればReact開発を直ぐに進められます。
コマンドを入力し、インストールしたいディレクトリに移動します。今回はダウンロードフォルダに移動します
```console
C:\Users\xxxxx>cd downloads
```

その後、npxから始まる以下のコマンドを入力します。
```console
C:\Users\xxxxx\Downloads>npx create-react-app react-corona-tracker-app
```

最後にインストールが完了すると以下のようなコマンドが出力されます。
```console
Success! Created react-corona-tracker-app at C:\Users\xxxxx\Downloads\react-corona-tracker-app
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd react-corona-tracker-app
  npm start

Happy hacking!
npm notice
npm notice New minor version of npm available! 9.5.0 -> 9.6.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.6.1
npm notice Run npm install -g npm@9.6.1 to update!
npm notice
```

この後、YesかNoを選択するメッセージがでる場合があるのですが、その場合Yesを表す「y」を入力します。

ダウンロードフォルダ内に以下の画像のような**react-corona-tracker-app**フォルダが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/706b6d24-c2fc-0f5f-34d2-652c97ce4ab0.png)

最後にVS Codeを開きファイル > ファルダを開くをクリックし、ダウンロードフォルダ内にある**react-corona-tracker-app**フォルダを選択します。
以下のようにVS Code内で開けていれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884987/a801f9af-fb79-6d76-3dbf-9a41557911eb.png)

# 追記（Macユーザー向け）
`node.js`をインストールし、ファイルを`VS　Code`上で開いたと思いますが、新たにyarn(npmコマンドのFacebookによる改良版)と呼ばれるパッケージマネージャーのインストールを行います。

```console
xxxxx@xxxxx ~ % sudo npm install -g yarn
```
ポイントは入力するコマンドの前に`sudo`と入力することで管理者状態で入力することができます。
こうすることでyarnをインストールすることができます。
JavaScript/TypeScriptで変数初期化とreturnを一文で書く方法

特定の条件にマッチする場合の処理を記述する場合、条件に合わないときはブロックの先頭で`return`するという事はよくあります。例えばこんな感じ。

```ts
function doTask(params){
  const state = getState(params); // <-(1)
  if (!state) return; // <-(2)
  // let's do task!
}
```

似たようなことを大量に書くことになるので、この(1)と(2)を一行で書きたくなってきます。
しかし JavaScript/TypeScript では以下のように単純に一行にまとめる事はできません。

```ts
function doTask(params){
  const state = getState(params) ?? return;
  // let's do task!
}
```

ではどうするか。Generatorを使います

```ts
function *doTask(params){
  const state = getState(params) ?? (yield);
  // let's do task!
}
```

`return`はダメでも`yield`はいけるんですね。ちょっと不思議
中学生が作った自分だけのMarkdownエディターに部分印刷機能をつけたお話

## はじめに
先日、「中学生が自分だけのMarkdownエディターを作ってみた話」というふざけたタイトルで記事を投稿させていただいたのですが、本日はそのエディターに印刷機能をつけたお話です。

https://qiita.com/I-AM-RAILWAY-FAN/items/7fb0f57e418459f82331

便利なので、もしよければ使ってみてください。

https://yo-train-ch.github.io/Markdown-editor-MAKUMAKU/

## コード
```javascript
document.getElementById('print-btn').addEventListener('click', () => {
            	// 印刷用にiframeを作成する
            	const iframe = document.createElement('iframe');
            	iframe.srcdoc = "<!DOCTYPE html>";
            	document.body.appendChild(iframe);
            	iframe.style.display = 'none';
            	iframe.onload = () => {
            		iframe.contentDocument.body.appendChild(document.getElementById('preview').cloneNode(true));
            		document.querySelectorAll("link[rel='stylesheet']").forEach(el => iframe.contentDocument.head.appendChild(el.cloneNode(true)))
            		iframe.contentWindow.print();
            		iframe.contentWindow.addEventListener('afterprint', () => iframe.remove());
            	}
            })
```
iflameに内容をつけたし、それを印刷する形を取りました。
idが```preview```な```div```だけを印刷したかったので、そんな方法を調べたところ、行き着いた方法です。

## ```overview```にハマった！
ただ、この方法だとマークダウンの限られたところしか表示されない。
Markdownを短くするために、編集しているところ以外はスクロールできるようにしたのですが、その関係で表示されるところしか印刷できないようになってしまいました。

### 解決
cssの```overview```を```<head>```内の```<style>```で読み込むように。
そして、iflameには外部スタイルシートのデザインしか読み込まないよう変更し、解決しました。

## 参考文献

https://cpoint-lab.co.jp/article/202211/23571/

サイトを参考にさせていただきました。
Microsoft 365 Certified: Fundamentals（MS-900）資格勉強方法

AzureのMicrosoft Certified: Azure AI Fundamentalsに2022年8月に合格したので、勉強方法を共有します。

# 試験概要
概要や対策のまとめとしては以下がわかりやすくまとまっている

https://qiita.com/gomasa/items/3a7873355b8c5507eb97

https://office-nakane.com/IT/index.php/2021/12/17/post56/

https://www.bigriver.jp/?p=9200

https://qiita.com/mokonacl/items/391cc1871064bc37652b

https://qiita.com/sudakeisuda/items/ebed431336b0895d8111

https://qiita.com/sudakeisuda/items/45a75da85b3e4888a7ed

https://qiita.com/sudakeisuda/items/9e73db39ab9277da76ab

# 勉強方法
日本語ベースで学習できる教材は公式のもののみ。
Microsoft Learnで十分であるが、＋αとして学習するなら
Microsoft365の各サービスの機能やMicrosoftのライセンスについて違いが理解することがおすすめ。
問題集は日本語ベースはないので、英語ベースのものを探すことになる。


## Microsoft Learn
公式にて無料で学習できる

https://docs.microsoft.com/ja-jp/learn/certifications/azure-ai-fundamentals/

Azure系Fundamentals(AZ-900,DP-900,AI-900)のように試験対策講座も2022年から始まっているので、
その内恒常的に受講できるようになる可能性があるかも

https://note.microsoft.com/JA-NOGEP-WBNR-FY22-06Jun-21-MS900-SRDEM111618_LP01Registration-ForminBody.html

## Udemy
Microsoftの学習コンテンツを作成している会社の簡易なウェビナー
上記Learnの要約版なので簡易な学習におすすめ

https://www.udemy.com/course/ms900-microsoft365-fundamentals-exam-prep-shortened/

上記コンテンツの記事バージョン

https://jinzai.edifist.co.jp/article/ms365_toc
Google ColabにHugging Faceのモデルをインストールする方法

自分が分からなかったのでメモです。
```wget```コマンドを利用するのですが、URLの指定が分かりませんでした。

## 方法
Hugging Faceのモデルのページにアクセスし、```Files and versions```タブに遷移します。
ダウンロードしたいモデルのファイルが```.ckpt```や```.safetensors```などの拡張子であると思うので、これをクリック。

そうすると、ダウンロードするボタンが表示される画面になると思うので、そのボタンのリンクをコピーします。

あとは```wget```の引数でこのURLを指定すれば、Colabにモデルがインストールできます。
【コピペで簡単】Unityで画面にFPSを表示したい

ゲーム開発をしていると往々にして、とりあえずすぐにFPSを画面に出したいことがあります。
そういう時に以下のコードをプロジェクトに追加することでOnGUIで表示してくれます。

```csharp
using System.Linq;
using UnityEngine;

public class PerformanceMeasure : MonoBehaviour
{
    static PerformanceMeasure Instance;
    
    const float MeasureInterval = 1.0f;
    const int AveNum = 10;
    
    float nextTime;
    int frameCount, measureCount;
    
    float fps, aveFps;
    readonly float[] fpsHistory = new float[AveNum];

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void Create()
    {
        if(Instance) return;
        
        var go = new GameObject();
        Instance = go.AddComponent<PerformanceMeasure>();
        DontDestroyOnLoad(go);
    }
    
    void Update()
    {
        frameCount++;
        if (nextTime > Time.fixedTime) return;
        
        fps = frameCount / MeasureInterval;
        fpsHistory[measureCount] = fps;
        aveFps = fpsHistory.Average();

        nextTime = Time.fixedTime + MeasureInterval;
        frameCount = 0;

        measureCount++;
        if (measureCount >= AveNum) measureCount = 0;
    }

    [SerializeField] float x = 5;
    [SerializeField] float y = 5;
    [SerializeField] float w = 200;
    [SerializeField] float h = 20;
    [SerializeField] float i = 0;

    void OnGUI()
    {
        GUI.Label(new Rect(x, y, w, h), $"FPS:{fps}");
        GUI.Label(new Rect(x, y + h + i, w, h), $"Ave10sFPS:{aveFps}");
    }
}

```
RuntimeInitializeOnLoadMethodでゲーム起動時に自動でGameObjectを作るため、コードをプロジェクトに追加するだけで動きます。


上記のコードではOnGUIを使って最小限の情報を表示しているため、細かいレイアウトの調整や他UIとの連携などが面倒くさいです。
急ぎでない方はSRDebuggerなどの汎用的なデバッグツールを使うか、自前で多機能の表示を作ってみてください。
これからの Web 地図に向けて（雑感）

## はじめに

Web 地図を中心に、これからの地図に求められる性質や技術や何だろう？というテーマで、思いつくことを書き連ねてみます。

まだ個人の経験に基づくアイデア段階で、エビデンスも不明瞭です。今後、折に触れて修正できればと思います。

## これからの Web 地図に必要そうなもの

### ローカライズ・パーソナライズ

統一的な図式で表現された地図を全国で利用できるというのは、統一的なサービスを提供する上で重要なことかと思います。以前は、統一的な地図を全国・全世界で、より大縮尺で、ということが大切だと思っていましたが、しかし、どうも異なるように感じてきました。

文化や社会が違えば、地物の重要性は変わります。海外の地図デザインで日本の地図データをそのまま表示すると、非常に使いにくいです。その原因の一つとして、日本の特に都市では非常に重要な地物である鉄道が、海外ではそんなに重要ではないところも多いために控えめな表現で記述されるから、というのがあります。世界を同じ基準で比較するというよりも、ある一定の地域で目的を果たすことを考えれば、**大縮尺ほどその地域にローカライズすることが大切**だと感じます。

また、究極的には、その個人が必要なものを地図上に表示するようなパーソナライズに行きつくかもしれません。Google map は、パーソナライズされた地図の代表と考えられます。さらに、その個人にパーソナライズするだけでなく、その時々の目的（検索結果）に応じて地図のないようを変更しています。これは、地図をその場でカスタマイズできる Web 地図の性質を非常にうまく使っている例ではないかと思います。

パーソナライズは、背景地図というよりも上乗せデータの方が重要かと思います。その人にとって、その時に見たいデータをどのように提供するか、データ整備と検索機能の話に帰結しそうです。

ちなみに、Google map を観察すると、個人や目的が変わっても背景地図は大きくは変更されていません。**背景地図はローカライズまで、POI を含めた上乗せデータはパーソナライズまで**、というところに落ち着きそうです。

### AI

AI の話でにぎわっていますが、まだ自分の中の解像度は低い分野です。

地図分野において、AI は地図作成の文脈で使われることが多いですが、もうすこし大雑把な使い方もできるかもしれません。たとえば、オンザフライで空中写真のジオリファレンス等を自動でやってくれるとありがたいです。

話題の大規模言語モデルで言えば、**住所のパース**に威力を発揮しそうです。これには、期待しています。

Web 地図においては、地図そのものへの影響というよりも、上記の**パーソナライズ化するためのツールとしての役割**になるのかもしれません。

### 三次元

Web 地図にも三次元（3D）の波が来て久しいです。Google map は従来から 3D 表現が可能です。

地形の 3D 表現については、標高値を RGB へシリアライズし、画像タイルの技術を用いることで、シームレスな 3D データを配信するという技術が主流と感じています。国土地理院の標高タイルもこの系統です。この技術を用いることで、たとえば Mapbox GL JS や Maplibre GL JS といった Web 地図ライブラリでシームレスな地形の 3D 表現が可能となっています。

3D 表現では、Cesium もよく使われているようですが、個人的には動作に重さを感じています。

3D の地図を使うときに感じるのは、「軽さ」が重要という点です。特に Web 地図の場合は、適宜カメラ位置を変更する必要があります。3D 表現だと、いろいろなカットで見ることができるのが魅力でしょうから、なおさらカメラを動かす機会が大きくなると思います。その際に、いちいち処理に時間がかかっていたら致命的です。

軽さの点で、建物の 3D はまだ難しいと思います。国土交通省のPLATEA（プラトー）の動きがありますが、たとえば、Web 上で成果を見ることができる PLATEAU VIEW App では、1都市ずつのロードで、シームレスに見ることはできません。このようなデータをシームレスに見せるにあたり、どのように見た目とパフォーマンスのバランスをとるかが重要かと思います。

一方、Mapbox 社は、Mapbox GL JS v3 のベータ版公開とともに、その都市のランドマークとなるような建物の 3D モデルを標準スタイルの中で提供しようとしています（→[参考記事](https://qiita.com/mg_kudo/items/92283d017f7528f06c5e)）。個人的には、データ量の重さは気になるところですが、このような流れは今後も普遍的になるかもしれません。

なお、現時点では、操作の重さの点で、結局 2D の方が見やすいな、とも感じています。操作の軽快さと見た目のバランスをどのようにとっていくかが、今後の Web 地図における 3D 表現のポイントかもしれません。

また、3D にしたところで、現在、見た目以上の使い道が思いつかないのも課題かと思っていましたが、むしろ「**見た目が変わると何が変わるのか？**」を突き詰めていく必要性の方が高そうです。

### 一覧性

Web 地図では、シームレスに動かせて、その時の目的に合わせた地図を提供する、その時にいらないものは見せない、という「取捨選択」が魅力かと思います。

一方で、**「一覧性」の需要が大きい**という経験もしています。紙の上の地図で、情報を一覧したい場面は思っていた以上に多いです。役所文化でポンチ絵とか曼荼羅とかが批判されてはいますが、あのような一覧性が欲しくなる場面は実感しており、地図にもそれが言えるかと思います。

その場に応じた取捨選択が魅力の Web 地図だと、このようなポンチ絵的な出力はそぐわないかもしれませんが、だからといって捨てるわけにはいかない需要だと思います。

国の基本図（国土地理院の地形図等）は特にそうだと思いますが、背景地図は、国土に関するポンチ絵的な要素（＝一覧性）を持っているのかもしれません。背景地図を表示するにあたり、この一覧性と見やすさのバランスをどうするかが苦心のポイントかと思います。

上乗せデータでも、どのように一覧性をもって表示させるかは重要です。地図ですべてを表現するのではなく、グラフや表も使いながら、サイト全体でデザインしていくことが必要かと思います。

### 空間解析

Web 地図はどうしても「可視化」に集中しがちですが、付加価値を付けるとすれば、データから結論を導くための空間解析も必要になるかもしれません。ただし、クライアントサイドの Web 地図上で高度な処理は難しいでしょうから、どこまでの機能を提供するかはバックエンドやデータとの相談になるでしょう。
SANWA Connectアプリで退出猶予期間設定について考える。

# 防犯開始後5分間程度センサー検知しない状態にしたい。

以前、防犯開始・解除ボタンを作ったが、防犯開始した時にすぐにセンサー検知してしまうと、異常検知となってしまうことがわかりました。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190290/768623e6-b9ed-b27e-4891-a8e96cbc894e.png" width="200">


業務用の防犯システムなどで、最終退出者が防犯開始した場合は、5分間程度の退出猶予期間を設けたりしてますが、SANWA ConnectやSmartLifeアプリのスマート機能で追加できるかやってみました。


結果から言うと、できませんでした。近いことをやろうとすることはできるのですが、とても複雑になってしまいます。
自分が色々とやってみて思うのは、aliexpressなどで販売されているSmartLife対応の防犯システムでは433MHzのセンサー端末のみは内蔵の退出猶予時間が有効ですが、SmartLife対応機器で通信しているwifiセンサなどは、この猶予時間設定は無効のようです。

この辺は何とかなったりしないんでしょうかね？

SmartLifeアプリだと、この猶予時間設定機能がデフォルトでついてました。センサー1個あればホームセキュリティが簡単に始められるようになっていていいなと思ったのですが、SANWA Connectアプリにはこの機能はなさそうですね。

まあ、SANWA Connect,Tuya,SmartLifeでもともと持っているスマート機能で猶予時間設定ができると大変助かるなと感じてしまいますね。
割り込み処理

# 割り込み処理の仕組み
割り込みは、実行中のプログラムを中断し、緊急度の高い別の処理を行う仕組み。

1.割り込み発生時点の状態を保存
2.割り込みの種類を判定
3.割り込み処理ルーチン
4.割り込み発生時点の状態へ復帰

## 割り込みの種類
### 内部割り込み
```実行中のプログラムに起因する割り込み(CPU内部で発生)```
#### プログラム割り込み
プログラム実行中のエラーにより発生。
#### SVC(スーパーバイザーコール)割り込み
```処理プログラムから監視プログラム（オペレーションシステム）に対して要求する割り込み(入出力要求の発生やプログラムの完了）```。

### 外部割込み
```計算機システム外```からの割込み
#### 入出力割り込み
```入出力動作の完了```(異常を含む）、```機器の状態変化```（用紙切れなど）
#### 機械チェック割り込み
```CPUの誤動作、主記憶装置の障害、電源の異常```など。
#### タイマ割り込み
```CPU割り当て時間のオーバー```
#### コンソール割り込み
```オペレータからの介入```

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
【shepherdで開発効率UP!】githubリポジトリを一括更新

# 概要

shepherdというgithubのリポジトリを一括で更新してくれるOSSを見つけたので使ってみました！

https://github.com/NerdWalletOSS/shepherd

# 使い方

まずはcliをインストールします。

```bash
npm install -g @nerdwallet/shepherd
```

次にshepherdの動作を定義する設定ファイルを作成します。
以下は「README.md」がリポジトリ直下にない場合に作成する場合の例です。

```yaml:shepherd.yml
# ブランチ名
id: create_readme
# PRタイトル
title: "create README.md"
adapter:
  # github固定
  type: github
  # repositories or code
  search_type: repositories
  # 検索クエリ
  search_query: "org:rhirabay"
hooks:
  # 変更対象かどうかの判定コマンド
  should_migrate:
    - test ! $(ls README.md)
  # 変更内容を記載
  apply:
    - touch README.md
  # PRメッセージを生成（echo等で標準出力）
  pr_message: |
    echo 'create README.md'
```

設定ファイルを作成したら、設定ファイルと同ディレクトリでshepherdを実行していくと、
変更〜PR作成までを自動でやってくれます！

```bash
$ shepherd checkout .
$ shepherd apply .
$ shepherd commit .
$ shepherd push .
$ shepherd pr .
```

# もっと詳しく知りたい方は...

以下にまとめているのでご覧ください！！！

https://hirabay.net/?p=554
Forth（Gforth）でかんたんな自作言語のコンパイラを書いた（移転済み）

引っ越しました。

[https://zenn.dev/sonota88/articles/f48ee696ad1de4](https://zenn.dev/sonota88/articles/f48ee696ad1de4)

https://zenn.dev/sonota88/articles/f48ee696ad1de4
Storyboardを使わないコードのみでのプロジェクト作成

# はじめに
最近UIKitを学び始めた初心者です。
同じ初心者、初学者の方を対象にしてます。また、自分のメモ、備忘録です。

Xcode Version 14.0.1で実行してます。
[この記事のサンプルプロジェクト](https://github.com/kabikira/NoStoryboard)

# できるもの
ストーリーボード使わず簡単なラベルを表示
![スクリーンショット 2023-03-12 14.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/04a902e5-a6dd-0c0d-0774-a8030259fb6a.png)


# Main.storyboard消す
プロジェクトからMain.storyboardを削除します。さよなら！
![スクリーンショット 2023-03-12 12.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/7cf9cafd-e53b-a005-7527-05edfcfac9d9.png)

# Main storyboard file base nameを削除
TARGETSのinfoのCustom iOS Target Propertiesの　→　Main storyboard file base nameを削除
![スクリーンショット 2023-03-12 12.23.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/39e1c40a-99ad-82e0-bc1a-2cbeb6055d27.png)

# Storyboard Nameを削除
TARGETSのinfoのCustom iOS Target PropertiesのApplication Scene Manifest　→  Scene Configuration→ Application SessionRole　→Item 0(default Configuration)→Storyboard Nameを削除
![スクリーンショット 2023-03-12 12.24.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/15eb2a3f-d15a-6626-c976-e6db4c5e15c5.png)

# 削除した状態
![スクリーンショット 2023-03-12 12.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/e4c676b6-af87-5653-6077-58682ec3eaf1.png)

# SceneDelegate.swiftにコードを追加
![スクリーンショット 2023-03-12 16.20.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/560566cf-182d-6bdb-9d5a-f04f369d80dc.png)
下記コードに変更してます。
```swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        //UIwindowsのアンラップ
        guard let scene = (scene as? UIWindowScene) else { return }
        // window生成
        let window = UIWindow(windowScene: scene)
        // ルートビュー指定
        window.rootViewController = ViewController()
        // キーウインドウ指定
        window.makeKeyAndVisible()
        // windowインスタンスが解放されないようにパラメータに代入する
        self.window = window
    }

```
# ViewController.swiftにコード追加
ViewControllerに下記コード追加しラベルを表示します。
```swift

import UIKit

class ViewController: UIViewController {
    var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        label = UILabel()
        label.text = "メタモン"
        label.textAlignment = .center
        label.backgroundColor = .systemPink
        // オートレイアウト使用するためfalseにする
        label.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(label)
        // コードでオートレイアウト制約
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            label.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            
        ])
    }

}

```
# シュミレーター起動
できました！
![スクリーンショット 2023-03-12 14.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/7e3e3da9-b187-f7b0-d72b-981919b61741.png)
React + TypeScript でログイン画面を作成してみた

ReactとTypeScriptでログイン画面を作成しました。

# 手順
## 雛形作成
npxコマンドでReactのプロジェクトを作成します
```shell
npx create-react-app login-app --template typescript
```

## ログイン画面作成
1.sample-app/src配下にLogin.tsxを作成します
```shell
touch sample-app/src/Login.tsx
```

2.ログイン機能を作成
```React:Login.tsx
import React, { useState } from 'react';

interface LoginProps {
  onSubmit: (email: string, password: string) => void;
}

const Login: React.FC<LoginProps> = ({ onSubmit }) => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    onSubmit(email, password);
  };

  return (
    <form onSubmit={handleSubmit}>
      <h1>ログイン</h1>
      <label>
        メールアドレス
        <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
      </label>
      <label>
        パスワード
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
      </label>
      <button type="submit">ログイン</button>
    </form>
  );
};

export default Login;
```
**解説**
このコンポーネントは、onSubmitプロパティを受け取ります。
これは、ユーザがフォームを送信するときに呼び出される関数です。
useStateフックは、emailとpasswordの入力状態を管理するために使用されます。
handleSubmit関数は、フォームが送信されたときに呼び出され、emailとpasswordを引数にonSubmit関数を呼び出します。

3.App.tsxでLogin.tsxを参照するように設定
```React:App.tsx
import React from 'react';
import Login from './Login';

const App: React.FC = () => {
  const handleLogin = (email: string, password: string) => {
    console.log('ログインされたメールアドレス:', email, 'とパスワード:', password);
  };

  return (
    <div>
      <Login onSubmit={handleLogin} />
    </div>
  );
};

export default App;
```

# 備考
CSSで装飾する場合は
1.sample-app/src配下にLogin.cssを作成
```shell
touch sample-app/src/Login.css
```

```css:Login.css
.login {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

.logo {
  margin-bottom: 50px;
}

.form {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  padding: 40px;
}

.form label {
  display: block;
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: 600;
  color: #5f6368;
}

.form input[type="email"],
.form input[type="password"] {
  width: 100%;
  padding: 12px 20px;
  margin: 8px 0;
  border: none;
  border-bottom: 1px solid #dadce0;
  font-size: 16px;
  color: #202124;
  background-color: transparent;
}

.form button[type="submit"] {
  background-color: #1a73e8;
  color: #fff;
  font-size: 16px;
  font-weight: 500;
  border: none;
  border-radius: 4px;
  padding: 12px 24px;
  margin-top: 24px;
  cursor: pointer;
  transition: background-color 0.3s ease-in-out;
}

.form button[type="submit"]:hover {
  background-color: #0d47a1;
}
```

3.Login.tsxでstylesheetを読み込ませます。
```React:Login.tsx
import './Login.css';
```

このような画面が出来上がります。
![スクリーンショット 2023-03-12 16.26.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/8e7b559f-72cb-6a02-aa44-e67d7c0255d1.png)
読んでない、でも読んだ気になれる【SRE本】1-1

SRE本を買いました！せっかく分厚い本を読み始めたので、簡単にまとめていこうと思います。

# 今回のセクション
第一部 イントロダクション
1章 イントロダクション

それではさっそく↓

# サービス管理者へのシステム管理者へのアプローチ
もともとのシステムの運用では、システム管理者といわれる人が存在していた。
ただし、大きく異なるスキルセットが求められるので、多くの組織ではチームが別れてしまう。
（いわゆるdevチームとopsチーム）
しかし、その分断には大きなデメリットがあった...

* 直接的
  変更管理やイベントを手作業でやっていると、サービスやトラフィックの増大に伴い、そのシステムの運用負荷は増大、よってコストも上がるのは明白
* 間接的
  両チームの動機付け、コミュニケーション、用語、プロダクトの安定性のターゲットレベル、リスクの考えかたの違い

その結果、両チームは衝突することも多々。
特にリリースにおいて、2つのチームの目標は基本的に対立関係にある。
* devチーム：新しい機能をリリースし早く使ってほしい
* opsチーム：新しいことすると、トラブル起きがち、やめてほしい、安定を守りたい

# サービス管理へのGoogleのアプローチ；SRE
そこでGoogleは、ソフトウェアエンジニアを採用し、その人達にサービスを運用させ、
opsの人が手作業で行ってきたことを遂行するシステムを構築させました。それが後にSREチームとなった。
（手作業に飽きる→その手作業を代替するシステム）

Googleのサービス管理に対するアプローチの要素は、チーム編成に表れていて、
このバックグラウンドの多少の多様性（複数のスキルセットの融合）は良いシステムを生み出すことに繋がっているらしい。
主に2つの人たちに別れる。
* Googleのスキルセットを満たしたソフトウェアエンジニア
* ↑のスキルセットをほぼ満たしている、かつ多くのソフトウェアエンジニアが持っていない技術（特にインフラ）を持っているエンジニア
**すべてのSREに共通するのは、複雑な問題を解決するソフトウェアの開発に対する信念と適正。**

すべてのSREに対して、チケット・オンコール・手作業といった運用作業を業務の50％以下にするよう上限を設けていて、
この上限によって、サービスを安定して運用するための開発をする十分な時間を確保している。
結果、
**運用と開発の作業のバランスを意識して維持することで、クリエイティブかつ自律性を確保しながら、運用面から収集した知見も持つ**
チームとなった。

# SREの信条
SREは、サービスの可用性、レイテンシー、パフォーマンス、効率性、変更管理、モニタリング、緊急対応、キャパシティプランニングに責任を持つ。
では、どのように環境（実働環境、devチーム、Testチーム、ユーザなど）とやり取りすべきか？

1. エンジジニアリングへの継続的な注力の保証  
   運用作業に割く時間を50％と決める。それをdev側も理解し、そういうシステム作りを目標とする
2. サービスのSLOを下回ることなく、変更の速度の最大化を追及する。  
   「サービス障害を0にする」ではなく、機能のリリース速度を最大化するためにエラーバジェットを使う
3. モニタリングする
   これまでの閾値や条件でメール通知＋アクションの必要性を判断という、人間の解釈が必要な運用はダメ
   その代わり、ソフトウェアが解釈し、人間はアクションが必要なときのみ通知を受けるような環境を用意する
4. 緊急対応
   人間を介入させず復旧させる。それができないならベストプラクティスを考え手順を作っておく
5. 変更管理
   リリースの速度と安全性を高めるために、   漸進的なロールアウト、高速かつ正確な問題検出、問題発生時の安全なロールバックを用意しておく。さらにこれらのプラクティスを人手でやらないことで、よくある不注意などの問題を回避する。
6. 需要の予測とキャパシティプランニング
   未来の需要（自然的なものと突発的なもの）に対して必要な可用性を確保できるよう、キャパシティと冗長性を確保しておく
7. プロビジョニング
   必要な時にのみ、素早く、かつ正確にシステムを利用可能な状態にする
8. 効率とパフォーマンス
   利用率に注意を払い、リソースの効率的な活用を行う
間違えてgit add及びコミットした際の取り消し方法をまとめる

間違えて`git add`や`git commit`をしてしまった際の取り消し方法をまとめる。

## `git add` を取り消す
全てのファイルを取り消したい場合は、以下のコマンドを叩く。
```
  git rm --cached -r .
```
一部のファイルを取り消したい場合は、以下のコマンドを叩く。
```
  git rm --cached -r [ディレクトリ及びファイルのパス]
```
パスを調べたい場合は、以下のコマンドを入力して、`git add`しているディレクトリなどの情報を取得しましょう。
```
  git status
```

## 直前のコミットの取り消し
```
  git reset --soft HEAD^
```
- `HEAD^`(又は`HEAD~``@^`：直前のコミットを指す。
- `HEAD~{n}`：n個前のコミットを指す。
- `HEAD~{n}`：n個前のコミットを指す。
- `--soft`：インデックス・ワーキングツリーはそのままで、コミットのみ取り消し。
- `--hard`：インデックス・ワーキングツリーはコミットの一つ前の状態に戻した上でコミットを取り消し。

## 最後に
間違えてコミットしても上記のコマンドを活用すれば、取り消せるのでご安心を。
ここまで読んで下さりありがとうございました〜
## 参考資料
- [【Git入門】git addを取り消したい！そんなお悩みの解決法をパターン別にご紹介！](https://tech-blog.rakus.co.jp/entry/20220902/git#git-add%E3%82%92%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97%E3%81%9F%E3%81%84")
- [[Git]コミットの取り消し、打ち消し、上書き](https://qiita.com/shuntaro_tamura/items/06281261d893acf049ed">)
IT知識を学ぶための講座をシリーズ化してみた

# 私はだーれ
とある企業でカスタマーサクセスというお仕事をしています。（いわゆるポストセールス的な立ち位置）

# なぜやるのか
世の中にいろいろあふれている知識のベースは意外にも学ぶ機会は少なかったりする。
だったら自分の知識の棚卸しもかねて、そんな機会を作りたいと思った。

# どんなことをやるのか
私はIT業界にいるので、ITのイロハの「イ」の部分をわかりやすくかみ砕いた勉強会をやる予定。

# いつやるのか
今月は2回予定しています。

## いまからでも遅くない！データベース超入門（3月15日）
https://ibm-developer.connpass.com/event/276147/

## いまからでも遅くない！ネットワーク超入門（3月31日）
https://ibm-developer.connpass.com/event/276619/

# 実施済みのもの
## いまからでも遅くない！Git超入門（座学編）
https://ibm-developer.connpass.com/event/266992/

## いまからでも遅くない！Git超入門（ハンズオン編）
https://ibm-developer.connpass.com/event/269637/

# 今後の予定
* いまからでも遅くない！WebAPI超入門
* いまからでも遅くない！フロントエンド超入門
* いまからでも遅くない！コンテナオーケストレーション超入門
* いまからでも遅くない！監視超入門
* いまからでも遅くない！統計超入門

現在鋭意制作中！
「こんなのやってほしい」とかあればコメントください。
検討してみます。。
HTML

# HTMLとは
文章構造を定義していく形の```マークアップ言語```で、webページの記述に用いられる。
あるデータから関連する別のデータへ瞬時にジャンプする```ハイパーリンク機能```を持つ。
画像や音声などの```マルチメディアを扱える```のが特徴

### DHTML（Dynamic HTML）
```スクリプト言語を使った動的表現を可能にしたHTMLの拡張仕様で、その制御の取り決めがDOM(Document Object Model)```である。
HTMLページに```JavaSciptなどで作成したスクリプトを埋め込む```ことでユーザーに合わせて要素の配置や内容を変更するような```動的なWebページを実現```できる。

### XHTML
HTMLを、```XMLに準拠した文書を作成できるように適合させた仕様```。
文書体裁は、タグではなくCSSで行う。

### CSS/XSL
```HTMLにおける文字の大きさ、文書飾り、行間などの文書体裁```に関する記述を独立された仕様がCSS
```XML文書のスタイルシートを記述する言語としてXSL```がある

### DTD(Document Type Definition)
```文書型定義```。
SGMLやHTMLで、```文書中に使われている文書構造を定義```するための言語

# XML
文書の標準化やデータ交換を目的としたマークアップ言語で、企業間取引の標準フォーマットとして用いられている。
SGMLと同じく```独自のタグを定義でき```、さらにHTMLのようにWebページとして公開することも可能。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
素材写真のぼやけた顔をAIで高画質化

# 解像度の低い顔画像を鮮明に

プレゼンや広告などでフリー素材の画像を使う時、小さく写っている人の顔がぼやけていることがあります。

そんな時は、AIで高画質化しましょう。
たとえば、以下のような群衆の素材写真があったとします。

![pexels-pavlo-luchkovski-106052.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/8017b16a-54f1-7d16-812b-85d53c48257d.jpeg)

綺麗な写真ですが、一人一人の人の顔は拡大するぼやけています。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/9af47219-db31-0646-2cc3-40ab4fb8704a.jpeg width=512>

これをAIで高画質化すると。。。

![81ad850f-3777-4c06-928c-7561c07e46ed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/db1a3c5d-3b9d-42f6-37e2-8387f584348f.png)

このようにかなり鮮明な写真にできます。

# 使い方

今回はCodeformerというAIモデルを使います。

https://github.com/sczhou/CodeFormer

**インストール**

```shell
git clone https://github.com/sczhou/CodeFormer.git
cd CodeFormer
pip install -r requirements.txt
python basicsr/setup.py develop
load_ext autoreload
autoreload 2
python scripts/download_pretrained_models.py CodeFormer
```

**実行**

```shell
python inference_codeformer.py -w 0.5 --has_aligned --input_path face.jpg
```

たったこれだけのコードで写真を高画質化できるのです。

🐣
****
フリーランスエンジニアです。AI関連のシステムを開発しています。
もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
**AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、Webサービスやスマホアプリを作りたいけどどこに相談したらいいかわからない…**

いずれも中間コストを省いたリーズナブルな価格で責任を持ってお請けします。

**お仕事のご相談はこちらまで**
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium（英語記事）](https://medium.com/@rockyshikoku)
[GitHub（プログラムポートフォリオ）](https://github.com/john-rocky)