OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLがうまくいかない〜掲示板作成〜

## ポートフォリオ作成開始！
今日から掲示板作成するぞ！（[作成する掲示板の内容はこの記事に記載](https://qiita.com/takumi-1016/items/a4c80341aa2b917c0e9e)）
ということで、プログラミングスクールで学んだRailsを用いてアプリを作成していきます。

## アプリの作成
例によって
```:ターミナル
rails new アプリ名　-d mysql
```
でアプリを作成していきます。（参考サイト：[【Rails/MySQL】RailsにMySQLを導入する方法【プログラミング学習149日目】](https://qiita.com/fuku_tech/items/a380ebb1fd156c14c25b]))

## MySQLで問題発生！
いろんなIT系の求人によく載っていたMySQLを今回は使用します。しかし
```:ターミナル
mysql.server start
```
すると
```:ターミナル
Starting MySQL
.. ERROR! The server quit without updating PID file (/opt/homebrew/var/mysql/nakagawatakuminoMacBook-Air.local.pid).
```
となってうまくいきません....

## 解決手順
主に以下のサイトを参考にして解決しました。ありがとうございます。
https://zenn.dev/ryotaf/articles/6f5d12bda1f227

まず/opt/homebrew/var/mysqlの中身をターミナルで確認
```:ターミナル
$cd /opt/homebrew/var/mysql/
$ls
username.local.errというファイルを発見
```
ファイルを見ると
```
[ERROR] Can't start server : Bind on unix socket: Address already in use
[ERROR] Do you already have another mysqld server running on socket: /tmp/mysql.sock ?
[ERROR] Aborting
```
ソケットとやらが使われているのが原因らしい？
```:ターミナル
$cd /tmp
$ls
mysql.sockというファイルを発見
```
```:ターミナル
$sudo rm mysql.sock
mysql.sockを削除！
$mysql.server start         
Starting MySQL
. SUCCESS! 
```
うまくいきました！

## 次回にやること
今回はMySQLのサーバー起動時に起こるエラーの対処を記録しました。原因はスクールで使っていた古いバージョンのMySQLの底￥ケットが残っていたことかなと思っていますが、違うと思われた方がいましたら是非コメントにて教えてください！

今回はこの辺で！ではでは〜〜
検索フォームの作成(Django)

# テキスト検索機能の作成
## 作成手順
- 検索フォームの作成
- ListView内のget_queryset()でテキストを絞り込む
- テンプレートで表示
    - 検索結果
    - 検索結果後のメッセージ

## 検索フォームの作成
- テンプレート上に、URLにクエリストリングを作成する（?query=検索ワード）formタグを作成
![search_form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/729011/cdd97690-c071-1dd4-6cd6-09f8694e1139.png)

```HTML:index.html
<form method="get">
  <input type="search" value="{{ request.GET.query }}" 
         name="query" type="text" 
         placeholder=" 検索ワードを入力 ">
  <button>検索</button>
</form>
```

## ListView内のget_queryset()でテキストを絞り込む
- 検索結果のメッセージの追加

```python:views.py
from django.views.generic import ListView
from django.db.models import Q # get_queryset()用に追加
from django.contrib import messages #　検索結果のメッセージのため追加

class IndexList(ListView):
    template_name = 'report/index.html'
    paginate_by = 2
    # context_object_name = 'post_list'

    def get_queryset(self): # 検索機能のために追加
        queryset = Post.objects.order_by('-created_date')
        query = self.request.GET.get('query')

        if query:
            queryset = queryset.filter(
            Q(title__icontains=query) | Q(body__icontains=query)
            )
        messages.add_message(self.request, messages.INFO, query) #　検索結果メッセージ
        return queryset
```

## テンプレートで表示（検索結果）

```HTML:report/index.html
  {% for object in object_list %}
  <div class="content">
    <div class="title">
      <a href="{% url 'post_detail' post.pk %}">{{ object.title }}</a>
    </div>
    <div class="datatime">{{ object.created_date|date:"Y-n-j" }}</div>
  </div>
  {% endfor %}
```

## テンプレートで表示（検索結果メッセージを出力）
![message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/729011/57fd4101-001f-54de-0882-9037f81202e7.png)

- Bootstrapを適用するためsettings.pyにMESSAGE_TAGSを追加
- Bootstrapを適用した検索結果後のメッセージを表示

### Bootstrapを適用するためsettings.pyにMESSAGE_TAGSを追加

```python:settings.py
MESSAGE_TAGS = {
    messages.INFO: 'alert alert-info',
    messages.SUCCESS: 'alert alert-success',
    messages.WARNING: 'alert alert-warning',
    messages.ERROR: 'alert alert-danger',
}
```

### Bootstrapを適用した検索結果後のメッセージを表示
```HTML:report/index.html
    {% if messages %}
      <ul class="messages">
        {% for message in messages %}
          <li {% if message.tags %} class="{{ message.tags }}"{% endif %}>
            "{{ message }}" を含む検索結果:
          </li>
        {% endfor %}
      </ul>
    {% endif %}
```
カレンダーフォームの作成（Django）

# Django管理画面のカレンダーフォームを流用する
adminサイトには、以下のカレンダーフォームが実装されているため、この機能を流用する。
![admin_calendar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/729011/93a39295-7a8b-17b5-7062-0b1743d40ead.png)

- 実装手順
    - 日付をDBに保存しない場合(forms.Form)
    - 日付をDBに保存する場合(models.Model)
    - テンプレートに表示する

# 日付をDBに保存しない場合(forms.Form)
- AdminDateWidget()をwidgetに指定する（フォーム）
```python:forms.py
from django import forms
from django.contrib.admin.widgets import AdminDateWidget
 
class DateForm(forms.Form):
    date_field = forms.DateField(widget=AdminDateWidget())
```

# 日付をDBに保存する場合(models.Model)
- AdminDateWidget()をwidgetに指定する（フォーム）
```python:models.py
from django.db import models
 
class DateModel(models.Model):
    date_field = models.DateField()
```

```python:forms.py
from django import forms
from django.contrib.admin.widgets import AdminDateWidget
from .models import DateModel

class DateForm(forms.ModelForm):
    class Meta:
        model = DateModel
        fields = ('date_field',)
        widgets = {
            'date_field': AdminDateWidget(),
        }
```
# テンプレートに表示する
- スタイルシーとJavaScriptを追加
```HTML:base.html
{% load static %}
<!doctype html>
<!-- <title>ユーザー登録・更新</title> -->
<!-- for admin widgets -->
    <!-- <link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}"/> -->
    <link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
    <script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
    {{ form.media }}
    <script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script>
    <script type="text/javascript" src="{% static 'admin/js/admin/RelatedObjectLookups.js' %}"></script>
```
![calendar_form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/729011/ea1f5332-9df0-b028-734e-64c8f136dee6.png)
async・await／非同期処理のサンプル



```検証用C#コード.cs

//Microsoft (R) Visual C# Compiler version 3.4.0-beta4-19562-05 (ff930dec)
//Copyright (C) Microsoft Corporation. All rights reserved.


using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Task<string> task = F1Async();
            Console.WriteLine(task.Result);
        }
        
        static async Task<string> F1Async(){
            Console.WriteLine( "F1 start.");
            var ret = "10";
            
            ret =  await F3Async();
            Task.Run(()=>F2(ret));

            Console.WriteLine ("F1 end. ");
            return "ALL End ret:"+ ret;
        }
        
        static void F2(string ret){
            Console.WriteLine( "F2 [ret from F3orF1?:"+ret+"] start.");            
            Console.WriteLine( "F2 [ret from F3orF1?:"+ret+"] end.");
        }
        
        static async Task<string> F3Async(){
            Console.WriteLine( "F3 start.");
            Thread.Sleep(2000);
            Console.WriteLine( "F3 end.");
            return "-1";
        }
    }
}


```

>オンラインツール：https://rextester.com/


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509696/f9514210-11cf-ae0e-ba5d-e4d97f9fe7a4.png)
Salesforce デベロッパー試験対策

Salesforce デベロッパー試験対策として使用するサイト、資料をまとめます。
<img width="200" alt="SFU_CRT_BDG_Pltfrm_Dev_I_RGB.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096960/5f8569a0-00c7-f859-b414-771a9f56a402.png">

【Salesforce公式Trailhead】
Salesforce 認定 Platform デベロッパー 資格 対策
https://trailhead.salesforce.com/ja/users/welcome4/trailmixes/salesforce-platform-dev-1

【Salesforce公式研修】
Salesforce研修資料_ポイントスタディ

【Salesforce開発者ガイド】
①Apex開発者ガイド
　https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_dev_guide.htm
②Visualforce開発者ガイド
　https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_intro.htm
③Salesforce Developer Experience開発者ガイド
　https://developer.salesforce.com/docs/atlas.ja-jp.238.0.sfdx_dev.meta/sfdx_dev/sfdx_dev_intro.htm
④SOQL および SOSL リファレンス
　https://developer.salesforce.com/docs/atlas.ja-jp.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_sosl_intro.htm

【Salesforceデベロッパー過去問】
①Salesforceの一番星_120問
https://keneloper.com/getting-certified-for-salesforce-certified-platform-developer

②note対策講座_80問
https://note.com/salesforce777/n/n8ba9b68eef39

③Quizlet_94問
https://quizlet.com/jp/556608444/salesforce-認定-


【補足】
・デベロッパーの試験問題は開発者ガイドに準拠した問題が多い。
・また過去問題の解説、理解のためには開発者ガイドを根拠にすることが多い。
・以下のようにSalesforce知識のI/Oを繰り返して開発スキル、知識向上を目指す。
　Input=開発者ガイド/Trailhead
　Output=過去問演習/実案件/演習環境の実装

【課題・問題点】
・過去問は解説のないものばかり。誤った回答も多い。
　公式ヘルプ/開発者ガイドで自分で納得するまで理解する必要がある。
・公式ヘルプ/開発者ガイドはインプット情報として使えるが、膨大な文章量である。
　それをひたすら「読む」だけでは知識が定着しないと感じる。
・そのため、実際にDeveloperEdition環境で「手を動かして実装」したり、
　実業務でどのように利用されているかを読み解く＆設計書に落とし込む
　といた作業によって、知識が定着できると考えられる。

【必要なスキル】
Salesforce分野以外で、ある程度の開発技術力を保有していることを前提としているため、
「はじめてのプログラミング言語学習がApex」というような状態だと全く理解できないのではと感じる。
・Apex…JavaのBronze～Silverレベルのコーディング技術
・Visualforce…Html/CSS/Javascriptで簡単なアプリ(新人研修レベル)を作成できる技術。
・SOQL/SOSL…SQLを組み立てられる技術。
オペレーティングシステムの役割と機能

# API
* アプリケーションから利用できる、```さまざま機能を提供する関数やコマンド群```のこと。
* APIを使用することで```１から作ることなく基本的な機能をアプリケーションに実装```できる。
* Windowsでは、実行時に動的に使用できる共有ライブラリ形式のものを```DLL```という。
* ```応用ソフトウェアとOSの仲介```をするインタフェース
* OSに用意されている```各種機能を応用ソフトウェアから利用する```ための仕組み

## DLL（Dynamic Link Library）とは？
```Windowsのプログラムファイルの種類の一つ```で、様々なプログラムから利用される汎用性の高い機能を収録した、```部品化されたプログラム```のこと。標準の```ファイル拡張子は「.dll」```。
出典 
https://e-words.jp/w/DLL%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.html

# デバイスドライバ
パソコンのOSで利用される、```接続された周辺装置を制御するためのソフトウェア```。
周辺装置ごとに必要で、同メーカでも、機種が異なれば別のプリンタドライバが必要。

# メモリ管理の障害
## メモリリーク
アプリケーション実行中に動的に獲得されたメモリ領域が不要となっても解放されず、```使用できるメモリ領域は徐々に減少してしまう現象```。システム障害の原因になる。

# 問題５の気づき
バッファがオーバしなければいいので必ずバッファのサイズより小さくなければならない。
そして
送信タスクと受信タスクの差がバッファよりも小さくあればいい。

### バッファとは？
* 容量と速度の差を減らすために設ける領域
* 「受け取ったデータのうち、処理が追いつかない分のデータを一時的に保存するための記憶領域」
出典 
https://www.unchi-co.com/kaigyoblog/kigyo_kaigyo/buff.html

# 関連記事
https://qiita.com/masatom86650860/items/8e941dc091bc8751a3ed

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
ユーザーインタビューのトレーニング方法

# この記事の概要
ユーザーインタビューのスキルアップは、とにかく経験を積むこと。
とはいえ、慣れないうちのインタビューは緊張しますよね。
今回はインタビューのトレーニング方法を、3段階で紹介します。


## STEP1:like:先輩UXデザイナー/リサーチャーのインタビューに同席する
本を読んで、いきなり実践！も良いですが、
もし先輩のリサーチャーがいれば、アシスタントとしてインタビューに同席させてもらいましょう。

同席する際は以下の点を意識しながら、先輩のインタビューを聞いてみるとGOODです:ok_hand:
- 被験者との話し方
    - 聞き取りやすく、理解しやすい話し方
- 被験者の話の聞き方
    - 　傾聴、ラポール形成など、信頼関係の構築
- 　インタビューテクニック
    - 　会話の深堀の仕方
    - 　想定外の回答への切り返し方法

参加後は、自分だったらあの時どう質問しただろう？と振り返ってみてください。

先輩インタビュアーがいなければ、営業やカスタマーサポートの方々の
トークスキルもとても参考になりますので、ぜひ色々と聞いてみてください:blush:

👉[参考：ラポール形成とは？実践方法と成功のポイント5つ](https://www.hrm-service.net/column/article307/#:~:text=%E3%83%A9%E3%83%9D%E3%83%BC%E3%83%AB%E5%BD%A2%E6%88%90%E3%81%A8%E3%81%AF%E3%80%81%E4%BF%A1%E9%A0%BC,%E7%8A%B6%E6%85%8B%E3%82%92%E6%8C%87%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)

## STEP2:like:同じチームや、隣の席の人にお試しインタビューする
いきなり初対面の方にインタビューするのは緊張しますよね！
まずは同じチームや、隣の席に座っている顔見知りの方へお願いし、インタビューの練習をさせていただきましょう。

事前に練習することで、わかりづらい質問がないか、インタビュー時間が適切かを把握し、調整することもできます。
ちょっと恥ずかしいですが、ぜひFBをもらい、本番のインタビューに活かしましょう！


## STEP3:like:自分のインタビュー風景を録画し、先輩と観ながらFBをもらう
いざ本番！とインタビューを実施する際は、議事録としてインタビュー風景を録画しませんか？
とっても恥ずかしいですが、自分のインタビュー動画を先輩UXリサーチャーに見ていただき、
率直なFBをいただきましょう。

自分自身で「あの時こう聞けばよかった・・＞＜」と反省している点もあれば、
全く気づかなかった点をFBいただけることもあります。

FBをいただく観点として、ご自身のスキル感によって、以下の点をレビューいただけると良いと思います。
- インタビューのスキルについて
- 発見事項の精度について
    - 以下に繋がる発見ができたか（下に行くほど難易度が高い）
        - UI改善
        - UX改善
        - CX改善
など

インタビューでは、どれだけ事業改善に貢献できる発見ができたかが重要です。
明らかにしたい問いから、さらに踏み込んだ新たな発見ができるよう、
先輩やチームメンバーとスキルアップしていきましょう💪
 

## まとめ
いかがでしたか？
本記事を書いている私自身、人見知りで初対面の方と話すのは苦手ですし、
最初は自分でも聞きたいことがまとまらないまま曖昧な質問をしてしまい、
回答者にも何度も聞き直され・・と、たくさん失敗してきましたが、
やり続けることで確実にスキルアップできました:cry::shamrock:

インタビュアーとして一人前になるには、50人、100人とインタビューを行うことと仰る方もいるように、
インタビューは**とにかく実践あるのみ**です！

最初は皆うまくいきませんから、たくさん失敗して経験を積みましょう💪
Azure Fundamentals(AZ-900)：クラウドの概念について説明する「クラウドの定義」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「クラウドの定義」**
◇対応するMicrosoft Learn ラーニングパス
[Microsoft Azure の基礎: クラウドの概念について説明する](https://learn.microsoft.com/ja-jp/training/paths/microsoft-azure-fundamentals-describe-cloud-concepts/)
◇対応するモジュール
[クラウド コンピューティングについて説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-cloud-compute/)

※前回の投稿は下記から確認できます。
[Microsoft Azure Fundamentals 新試験範囲(日本語翻訳版)](https://qiita.com/fsd-jume/items/4ac66894d0b656fed466)

## クラウドの定義
**クラウドには様々な形態があり、定義が困難**
→NIST(米国国立標準技術研究所)は明確に定義せず、**「5種類の特徴を併せ持つもの」** という表現に留めています。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/2dd5fbda-0ae8-c852-a4c3-5ceb976644f8.png)
さらに、NISTは5つの特徴を示すとともに、クラウドにおける2つの分類観点を示しています。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/648214d7-eba5-1b1a-5308-9a8cbd189e12.png)

## 次の学習内容
**◆サービスモデルの種類と責任共有モデル**

https://qiita.com/fsd-jume/items/cdef9615ba28b2fbc885

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8

## 参考
* [総務省 ICTスキル総合習得プログラム コース2-2 クラウドのサービスモデル・実装モデル](https://www.soumu.go.jp/ict_skill/pdf/ict_skill_2_2.pdf)
* [NISTによるクラウドコンピューティングの定義](https://www.ipa.go.jp/files/000025366.pdf)
【PHP】useとrequire_once完全に理解した



# ある日の公園

![カバオ泣く.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694053/0c8bec47-f274-282f-16ff-cd4a54eb536b.jpeg)


カバお「うわぁーーーーーん」

ウサこ「どうしたの、カバおくん」

カバお「PHPで新しくファイルを作って呼び出したいだけなのにうまくいかないんだァ」

ウサこ「それ、**use**と**require_once**についてちゃんと理解できてる？」

カバお「あ、あ当たり前じゃないか、馬鹿にしないでよ、ウサこちゃん」
<br>
*どうやらカバおくんは*
*useとrequire_onceについて正しくを理解していないようです。*


# useについて

ウサこ「カバおくんはuseについてどういう理解かしら？」

カバお「use宣言をすれば使いたいクラスが使えるようになるんだろォ」

ウサこ「その覚え方だと危険よ、正しくは**名前空間などをインポートしたり、エイリアスを作成することができる**イメージよ」
ウサこ「具体的にはuseを使うことで、具体的には下記のことが可能なの」

```
* 名前空間などのエイリアス（別名）を作成
* 名前空間の全て、または一部をインポート
* クラスをインポート
* 関数をインポート
* 定数をインポート
```

カバお「わわわ分かってるよ、そんなこと。ウサこちゃんはいちいちめんどくさいなァ」


# require_onceについて
ウサこ「次はrequire_onceよ、カバおくん、これはどういう理解かしら？」

カバお「PHPではよく外部ファイルを読み込むのに使われているけど、Laravelでは使っていないよね」
カバお「Laravelはuseしているからきっと、使う必要がないんだよ」
<br>
*外部ファイルを読み込む際に使うrequire_onceですが、laravelでは使われないため、*
*カバおくんは、useを使えばファイルも読み込めるという勘違いをしているようです。*



# Laravelはオートロード機能で読んでいる
ウサこ「カバおくん、Laravelでrequire_onceを使わないのは、オートロード機能の恩恵よ」
ウサこ「useで外部ファイルを読み込んでいるということではないの」

カバお「なななんだよオートロード機能って」

ウサこ「composer を使用してライブラリをインストールするとvendor/autoload.phpというファイルが生成されるわよね」
ウサこ「このファイルを一度だけrequireすることで、vendor配下のライブラリをすべて自動的にロードしてくれるの」

カバお「・・・・ほほう」

ウサこ「いちいちrequire_onceしていると骨が折れてしまうので、public/index.phpで事前にファイルを読み込んでいるのよ」
ウサこ「ほら、実際にpublic/index.phpを見て、しっかり記述があるわ」

```public/index.php
require __DIR__.'/../vendor/autoload.php';
```


# 結論
ウサこ「まとめると、useは名前空間をインポートしているが、外部ファイルを読み込むにはrequire_onceをしなければならない」
ウサこ「Laravelでもautoloadでファイルの読み込みが行われているだけで、裏で外部ファイルを読み込んでいる」

ウサこ「こんな感じかしら」


カバお「いや、こここんなの最初から分かっていたよォ！」


![カバオふん.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694053/d224351b-f2f2-ff01-edad-4f18b35df775.jpeg)


ウサこ　　。。。( ´ཀ`)ｹﾞﾛ
Storybookの簡単説明

# Storybookとは
ReactやVue、AngularなどのUIコンポーネントを独立した環境で開発を行うためのオープンソース。
一つのstoryは該当のUIコンポーネントがどのように表示・動作するのかを見せる。
またStorybookは、コンポーネントの再利用を前提に使用する。

# Storybookの特徴
- 独立した環境でUIコンポーネントを開発することができる。
- デザイナーとフロントエンド開発者が共にUIを確認することができる。
- 特定のdataをDBに強制的に入れなくても、アプリケーション内で利用されているコンポーネントを単独で確認することができる。

# Storybookの作成例
以下のようなvueのファイルがあるとする。
このファイルで指定されたデザインを確認するためには、このコンポーネントが使用されている画面で確認する必要があったが、storybookを利用すると、このコンポーネント単独で確認することができる。

```vue:button.vue
<template>
  <button class="red_button add_to_cart_button">
    <slot />
  </button>
</template>

<style lang="scss" scoped>
.add_to_cart_button {
  width: 100%;
  font-size: 12px;
}
.red_button {
  display: -webkit-inline-box;
  display: -moz-inline-box;
  display: -ms-inline-flexbox;
  display: -webkit-inline-flex;
  display: inline-flex;
  border: none;
  color: #fff;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 40px;
  background: #fe4c50;
  border-radius: 3px;
  -webkit-transition: all 0.3s ease;
  -moz-transition: all 0.3s ease;
  -ms-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
  transition: all 0.3s ease;
}
.red_button:hover {
  background: #fe7c7f;
}
.red_button:active {
  background: #ffafb0;
}
.red_button a {
  display: block;
  color: #ffffff;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: 500;
  text-align: center;
  line-height: 40px;
  width: 100%;
  text-decoration: none;
}
</style>
```

storybookの書き方の例は以下である。
（ここではjsファイルで記載）

```javascript:button.js
import Button from './index.vue'

const story = {
  title: 'Button',
  component: Button,
}

export default story

export const Default = () => ({
  components: { Button },
  template: '<Button>テストボタン</Button>',
})
```

すると、storybook上で以下のような画面を確認することができる。
![スクリーンショット 2022-09-28 16.40.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2785890/0bbf35fd-f537-f941-cb12-0ab472574222.png)
Codecovを活用してカバレッジを可視化する

# カバレッジとは
プロダクションコードのうち、どのくらいテストが実行されているかを割合で見たもの。

# codeカバレッジを見る意義
プロダクションコードに関して、コードカバレッジを恒常的に可視化しておくことで、PRを立てた際にカバレッジの低下に気づくことが可能となり、テストコードによって動作確認がきちんと行われていないプロダクションコードのmain ブランチへのmergeを未然に防ぐことができる様になります。

# codecov をGitHub Actionsで利用する
```yaml
      - name: Run tests
        run: go test -coverprofile=cover.out ./...
        env:
          AWS_S3_BUCKET: ${{ env.AWS_S3_BUCKET }}
          AWS_ACCESS_KEY: localstack
          AWS_SECRET_KEY: localstack
          AWS_REGION: ${{ env.AWS_REGION }}
          AWS_END_POINT_URL: ${{ env.AWS_END_POINT_URL }}

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v2
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          flags: backend-go
```

```yaml
codecov:
  notify:
    require_ci_to_pass: yes

coverage:
  status:
    project:
      default:
        target: 60%
    patch: no
    changes: no

comment:
  layout: "reach, diff, flags, flags, files, footer"
  behavior: default

flags:
  backend-go:
    paths:
      - src/backend-go

```
go test について

# testing

```
import "testing"

func TestArchiveServiceList(t *testing.T) {
	if err := fixtures.Load(); err != nil {
		log.Fatalf("failed load fixtures: %v", err)
	}

	ctx := context.Background()
	conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("failed connect grpc: %v", err)
	}
	defer conn.Close()

	client := genproto.NewArchiveServiceClient(conn)
	resp, err := client.List(ctx, &genproto.ListArchiveRequest{})

	if err != nil {
		t.Fatalf("failed to list the archive master %v", err)
	}

	assert.Equal(t, 3, len(resp.ArchiveList))
}
```
## テスト実行
テストファイルが存在するディレクトリ内にて
```
go test -v
```

## テスト対象を絞る
テストメソッド名で絞る
```
 go test -run Archive 
```

## カバレッジを出力する
```
go test -v -cover
```
### カバレッジレポート
https://qiita.com/kkohtaka/items/965fe08821cda8c9da8a
https://pkg.go.dev/testing

# test fixture
テストデータの追加と削除を実行してくれる。

https://github.com/go-testfixtures/testfixtures

# bufconn

https://pkg.go.dev/google.golang.org/grpc/test/bufconn

https://qiita.com/castaneai/items/8f975204a79e9783ecc3
ECS & EKS の選定について

# IAMについて
github actionsからデプロイ処理を実行する場合、処理を実行するIAMユーザに必要な権限が付与されていないとデプロイ処理を完遂することができない。

# EKSとECSでの比較
EKSと比較した際に、学習コストは低く抑えられる気がする。
大抵の場合、デプロイ環境としてECSを選定する方向で良いことが多い気がする。

## ECSとEKSどちらを選定するのか？
* 既存のインフラにてECSを選定している場合、追加する新規サービスもECSで良いのでは？逆も然り。

## ECSのインスタンス起動タイプについて
### Fargate
インフラの運用面の多くをAWS側が責任を持ってくれる起動タイプ。
運用にかかる手間や工数は削減できるが、EC2起動タイプと比較するとコストは高くなる。

### EC2
OSのアップデートなども開発者自身が責任を持つ必要がある起動タイプ。
Fargateと比較した際に、費用面のコストは安くなる。
Fargateと違って、インフラの設定を細かく変更することが可能なので、インフラの設定面において、
自由度を高めたい場合にはこちらを選択するのが良いと思う。
MySQL 基礎

# 数値型について

## 整数型
* INT 
バイト数 4バイト

* TINYINT
バイト数 1バイト

### ()の中の数字
TINYINT(1) や TINYINT(4) などの括弧内の数字は、カラムにZEROFILLを設定した際の桁数を表しており、指定した数字の桁数までゼロで埋める。
https://dev.mysql.com/doc/refman/5.6/ja/integer-types.html

# 文字列型について

* CHAR
固定長文字列

（）で指定したバイト数（＝文字数）まで文字列の末尾を空白で埋めた上で、レコードを保存する。

* VARCHAR
可変長文字列

## ()の中の数字
CHAR(1) や CHAR(4) などの括弧内の数字は、バイト数（＝文字数）を表している。

※半角英数字１文字は、1バイトであり、全角文字1文字は、2バイトである。

https://dev.mysql.com/doc/refman/5.6/ja/char.html

# テーブルのロックについて
データ数が数億とか数千の単位になると、alterを実行すると、テーブルが長時間ロックしてしまう。


# ON DELETE & ON UPDATEについて

## NO ACTION & RESTRICT
MySQLにおいてはNO ACTIONとRESTRICTは同じ挙動となります。
RESTRICTはON DELETE句やON UPDATE句を明示的に指定しなかった場合に設定される値です。

http://dbonline.s25.xrea.com/mysql/table/index12.html

# primary key & unique keyについて

>PRIMARY KEY は、すべてのキーカラムを NOT NULL として定義する必要のある一意のインデックスです。それらが NOT NULL として明示的に宣言されていない場合、MySQL は、それらを暗黙的に (かつ警告なしで) そのように宣言します。テーブルに存在できる PRIMARY KEY は 1 つだけです。PRIMARY KEY の名前は、常に PRIMARY です。そのため、これをその他のどの種類のインデックスの名前としても使用できません。
PRIMARY KEY が存在しないときに、アプリケーションがテーブル内の PRIMARY KEY を要求した場合、MySQL は、NULL カラムのない最初の UNIQUE インデックスを PRIMARY KEY として返します。


https://dev.mysql.com/doc/refman/5.6/ja/create-table.html

# utf8_general_ci
* 照合順序
文字列の比較を行う際に重要となるものらしい
https://qiita.com/kazu56/items/6af85ffcf8d3954455ad

https://program.sagasite.info/wiki/index.php?MySQL%E3%81%AEutf8_general_ci%E3%81%A8utf8_unicode_ci%E3%81%AE%E9%81%95%E3%81%84

# int uintについて
primary key + autoincrementは強制的にuintで定義される。
https://dev.mysql.com/doc/refman/5.6/ja/example-auto-increment.html

# command

```
mysql -h 127.0.0.1 -P 3307 -u root -ppass test < init.sql
```
改めてdockerのメリットを整理してみよう

# はじめに
今や開発現場で使用されることが当たり前となったdockerですが、そもそもdockerを利用することでどのような恩恵を受けられるんだっけ???、とふと思うことがあったので、今一度整理してみたいと思います。

# dockerの一般的なメリット
dockerを使用した際の主なメリットは以下のような点が挙げられるかなと思います。

* 起動が高速
* Dockerfileにてインフラを宣言的に記述することとで、環境間の差異を吸収することができる
* Dockerfileにてインフラを宣言的に記述することとで、production環境およびstaging環境のアプリケーションの動作に関して、冪等性を保証することができる。
* 新規コンテナ定義の適用および稼働中のコンテナのロールバックが容易
* Dockerfileにてインフラを宣言的に記述することとで、開発者がアプリケーション動作環境を把握しやすくなる

# 過去に遭遇した課題
以前、開発に関わっていた現場では、開発環境にdockerを使用し、ステージング環境およびプロダクション環境では プライベートクラウドにて `CentOS7` をベースとした仮想マシンにデプロイするという構成をとっていました。
上記の様な構成では、開発環境構築時においては開発者間で開発環境の差異を少なくするというメリットがありましたが、ステージング環境およびプロダクション環境にデプロイした際に、開発環境で動いていたアプリケーションが動かなくなるという問題が発生しました。
このような問題を防ぐためにも、開発環境でdockerを採用した際には、ステージング環境 & プロダクション環境でもdockerをはじめとしたコンテナ基盤で運用することが望ましいのかなと思います。

# dockerと併せてGolangを選定した際のメリット

* docker build後のimageサイズが他の言語と比較した際に小さくなる
* imageサイズが小さくなることでリポジトリへのpushおよびpull完了までの実行時間が短くなる
nvidia-smi 攻略チートシート

# nvidia-smi 攻略チートシート
そろそろnvidia-smiにキレ始めているので, チートシートを書いておきます.
## 環境
OS : ubuntu 20.04
Architecture : x86_64

## 手順
1. 全てのnvidia driver, cudaを削除する
2. nvidia driverとcudaのバージョンの対応を確認
3. nvidia driverをインストール
4. cudaをインストール

## 説明
#### 手順1 : 全てのnvidia driver, cudaを削除する
まず, nvidia driver, cudaがインストールされているか確認する.
```
dpkg -l | grep nvidia  
dpkg -l | grep cuda 
```
続いて, 全てを消し去る
```
sudo apt-get purge remove cuda*
sudo apt-get purge remove nvidia*
```
ここで油断してはいけない. おそらく何個かは消えていない. そのためもう一度上記のコードにて確認する.
残っていたものを一掃する(removeの後ろは残っているファイルに合わせて変えてね).
```
sudo apt-get purge remove libnvidia*  #libnvidia-のファイルが消えていなかった為指定する
```
そしてもう一度確認し、完全に消し去る.
※ ファイル名の前にlinux-とつくファイルは消さないらしい(知らんけど)


#### 手順2 : nvidia driverとcudaのバージョンの対応を確認
まず自身のマシンが推奨するnvidia driverのバージョンを確認する.
```
ubuntu-drivers devices
```
ここで表示されたドライバのどれをインストールするか決める.

続いて, [ドライバとCUDAの対応表](https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html)(Table3を参照しよう)から, 推奨されたドライバに対応するCUDAを確認する.

#### 手順3 : nvidia driverをインストール

キミに決めたドライバをインストール.
```
sudo apt install -y --no-install-recommends nvidia-driver-510  #今回は510
```
これでnvidia driverのインストールが完了する.
お決まりの再起動をしましょう.
```
sudo reboot
```
ドキドキのnvidia-smi.
```
nvidia-smi
```
できてたら神, できてなかったら一週間ほど熟成させましょう. そして新たな策を模索しましょう.

#### 手順4 : 
手順2での[ドライバとCUDAの対応表](https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html)にて, インストールしたドライバに対応するCUDAをインストールする.

今回はCUDA11.6 Update2 を[こちら](https://developer.nvidia.com/cuda-11-6-2-download-archive)からインストールする.

自身のマシンの状態を打ち込み, 表示されたコードを順番に打ち込む.
```
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.6.2/local_installers/cuda-repo-ubuntu2004-11-6-local_11.6.2-510.47.03-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-11-6-local_11.6.2-510.47.03-1_amd64.deb
sudo apt-key add /var/cuda-repo-ubuntu2004-11-6-local/7fa2af80.pub
sudo apt-get update
```
そして最後の一行を打つが, ここで注意！
```
sudo apt-get -y install cuda  # CUDAのバージョンを指定しないとダメよ
```
このままだと, 最新バージョンのCUDAがインストールされてしまう.
なので
```
sudo apt-get -y install cuda-11.6
```
このようにバージョンを指定してインストールを行う.

# まとめ
いい加減何回もnvidia-smiがおかしくなったりするのだから, もっっっっっと楽に使えるような仕様になってほしい.
Djangoにまつわるコマンドとは


ここで取り上げるのは主に２つです。
1. django-admin
1. manage.py 

です

```terminal
django-admin help --commands
```

```
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
runserver
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
```

---

manage.pyは通常のpythonファイルになるのでpythonを頭につける必要があります。
```terminal
python manage.py help --commands
```

```
changepassword
check
clearsessions
collectstatic
compilemessages
createcachetable
createsuperuser
dbshell
diffsettings
dumpdata
findstatic
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
remove_stale_contenttypes
runserver
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver

```

※色々と追記する前提で記事をまず投稿しました。都度各コマンドでできることを備忘録的にまとめたいと思います。
GA4のページ遷移のクリックログがChromeで捕捉できない

## 概要
GA4のイベントの送信について、Google ChromeのNetworkパネルでは捕捉できないケースがあるようです。



## 検証環境
- macOS Monterey (Intel)
- Google Chrome v106


## フロントの実装

- Google Tag ManagerでGoogle Analytics 4、Universal Analyticsを配信
- `target="_self"` でページ遷移させる

### gtag.jsの読み込み

```HTML
<script async src="https://www.googletagmanager.com/gtag/js?id=MEASUREMENT_ID"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'MEASUREMENT_ID');
</script>
```

### gtm.jsの読み込み

```HTML
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
  new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
  j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
  'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBe
fore(j,f);
  })(window,document,'script','dataLayer','CONTAINER_ID');</script>
```

### aタグの違い

#### 捕捉できないパターン
```HTML
<a href="detail.html">リンク</a>
```

#### 捕捉できるパターン
```HTML
<a href="detail.html" target="_blank">リンク</a>
```

## GTMの設定

リンククリックをトリガーとして、UA、GA4それぞれでイベントを飛ばす。

### Google Analytics 4

![Google-タグ-マネージャー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/a7882f5e-b4d5-f2f5-9a81-4b3bfb048da8.png)

### Universal Analytics

![Google-タグ-マネージャー (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/1de2a4ab-9fdb-1024-3bb7-4a4dd4e60020.png)


## 結果

以下のような結果となり、「Google ChromeでのGA4のイベント計測」に限定してログが確認できないことが分かりました。

パケットキャプチャの生ログからはGA4でもログが飛んでいることがわかるので、単純に「Chrome側で捕捉できていないだけ」ということになります。


|   検証パターン           | Universal Analytics | Google Analytics 4 |
|--------------|----|-----|
| Google ChromeのNetworkパネル | ○   |  ×   |
| SafariのNetworkパネル     |  ○  |   ○  |
| パケットキャプチャ |  ○  |  ○   |
| `target="_blank"` |  ○  |   ○  |
| GTMのプレビューモード |  ○  |   ○  |
| Google AnalyticsデバッガーをON ※ | ○   |  ○   |

※Chrome拡張のGoogle AnalyticsデバッガーをONにした状態



なぜかGTMのプレビューモードであったり、GAデバッガーを有効にしている場合には回避できますので、もし同様の事象に遭遇したら

- Chrome以外のブラウザで確認する
- GTMのプレビューモードをONにする
- GAデバッガーをONにする
- パケットキャプチャを利用する

のいずれかの選択肢を選べばいいのかなと思います。
create databaseするとERROR 1064 (42000): You have an error in your SQL syntax;とエラーが出る

# エラー発生経緯
EC2にMariaDBをインストールして、早速データベースを作ろうとコマンドを打ったところ、エラーが出たので対処法を備忘録として残します。

最初に打ち込んだコマンドが以下。

```
create database データベース名;
```

これに対して出た出力結果が以下の通り。

```
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'データベース名' at line 1
```

# 解決方法
ただデータベース名を**バッククォート**で囲むだけでいけました。

```
create database `データベース名`;
```

シングルクォートではないのでご注意を。


# 原因
名前にハイフンが含まれるテーブルやデータベースを作成しようとした場合にはこのエラーが出るようです。
ハイフン付きのテーブルやデータベースを作成する時はご注意を。
[シンプル] リクエストヘッダーは大文字・小文字を区別しない


どれが大文字・小文字を区別するのかしてないのかがややこしいので、自分用メモです。

> HTTP ヘッダーは、大文字小文字を区別しないヘッダー名とそれに続くコロン (:)、 値で構成されます。値の前にあるホワイトスペースは無視されます。


引用元：HTTP ヘッダー
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers


なるほど！

## おまけ

`X-Forwarded-For` はもう標準ヘッダーに格上げして欲しい。
npm audit のvulnerabilityを手動で直す

# 始める前に
[この記事中](https://qiita.com/riversun/items/7f1679509f38b1ae8adb)の「マニュアル（手動）で修復する」が発生したらこの記事を進めてください．

# 環境
Debian 11.5
Node 14.20.1
Nuxt 2.15.8
yarn 1.22.19

# 脆弱性の確認
npm auditで脆弱性（vulnerability）のあるパッケージをリストする．
~~~bash
$ npm audit
~~~
実行結果（例）
~~~                                       
                       === npm audit security report ===                        
                                                                                
┌──────────────────────────────────────────────────────────────────────────────┐
│                                Manual Review                                 │
│            Some vulnerabilities require your attention to resolve            │
│                                                                              │
│         Visit https://go.npm.me/audit-guide for additional guidance          │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Inefficient Regular Expression Complexity in nth-check       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ nth-check                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=2.0.1                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ nuxt                                                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ nuxt > @nuxt/builder > @nuxt/webpack > cssnano >             │
│               │ cssnano-preset-default > postcss-svgo > svgo > css-select >  │
│               │ nth-check                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://github.com/advisories/GHSA-rp65-9cf3-cjxr            │
└───────────────┴──────────────────────────────────────────────────────────────┘
~~~
この例では，css-select内のnth-checkで脆弱性が見つかったといわれています．

# 対処法
### npm-force-resolutionsのインストール
~~~bash
$ npm -g install npm-force-resolutions -D
~~~

### package.jsonの編集
package.jsonにresolutionを追加します．
中身には脆弱性のあったパッケージを追加します．
~~~json:package.json
"resolutions": {
    "nth-check": "^2.0.1"
}
~~~
### npm-force-resolutionsで強制的にバージョンを上げる
~~~bash
$ npx npm-force-resolutions
~~~

### node_moduleを再インストール
~~~bash
$ rm -rf node_module
$ yarn install 
    or 
$ npm ci
~~~

### 脆弱性の再確認
~~~
$ npm audit 
    or
$ yarn audit
                                                                                
                       === npm audit security report ===                        
                                                                                
found 0 vulnerabilities
 in 1610 scanned packages
~~~
やったぜ
# 参考文献
[npm パッケージのバージョンアップと脆弱性対応](https://rinoguchi.net/2021/11/npm-version-up-and-fix-audit.html)
Strix Cloudを利用したオンラインゲーム開発

ゲーム開発ソフト[Unity]でのオンラインゲーム開発が盛んにおこなわれていて、今回は[Strix Cloud]を利用したオンラインゲーム開発について概要解説します。
比較的新しいプラットフォームで公開されているドキュメント、開発記事などが少ないということがあり、敷居が高くなってしまっていますが、自分が実際にStrixを利用してゲーム開発した経験をもとにStrixの良い点など解説します。

# Strixとは
参加プレイヤーが大人数向けのオンラインゲーム開発向けのツールです。同時接続人数100人までを無料でサーバ利用できます。ただし１タイトルまでです。　複数大規模オンラインゲームを開発する場合は別途有料で契約する必要があります。
詳しくは公式サイトを参照してください。

https://www.strixengine.com/strix-cloud/

# 移動同期、アニメーション同期が単純である
Strixでゲーム開発の最大の売りは同期をコンポーネントをアタッチするだけで実現するということです。
同期とはAさんが動作させているプレイヤーとBさんが動作させているプレイヤーはそれぞれ独立して動作させないといけません。そして自分から見てほかのプレイヤーの動きはリアルタイムでこちら側に反映させないとオンラインゲームとして成立しなくなります。
従来ではこの作業をスクリプトからコーディングして行っていました。しかしStrixでは移動同期、アニメーション同期などがSDKコンポーネント化されていてアタッチするだけで同期自体は完了します。(移動方法、アニメーションタイミングなどは自分で記述します。)
オンラインゲームならではの面倒な作業を簡略したというところが非常に便利です。

# 基本部分の開発
オンラインゲームを一通り作るとなると記事が非常に長くなってしまいます。
セクションごとに分けるかどうかで悩みましたがnoteに基本部分の開発記事を作成しました。
noteにした理由は長い記事を作成する場合に区分けする機能があったからです。

https://note.com/shrick/n/nea5b52b79f8d#c2cbd0e4-5e0b-48a8-a84b-80555ea62ca2

開発項目についてまとめると
・アカウント登録、サーバ登録
・ゲームアプリ側とサーバの紐づけ
・StrixReplicator,Synchronizerを利用した同期のやり方
・オンラインゲームで頻繁に利用される弾の発射同期(当記事ではレーザー光線を採用しました。)
・体力同期(Rpcを使います）

以上のオンラインゲーム開発に必要な基本要素を選出して記事を書きました。

# 所感
Strixは便利なツールですがまだあまり利用されていないということもありドキュメント不足が問題なのではと思いました。
機能実装などに進捗あればQiitaに追加で記事作成しようと思います。
Laravel×AdminLTEでDataTableを使用する

こちらも軽くハマってしまったのでメモ。

以下を設定したところ、、
```sample.blade.php
@section('js')
<script>
    $(function() {
        $('#example').DataTable();
    });
</script>
@endsection
```

このエラーが出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127974/9a778169-3467-e269-aba5-ce5ba03595b1.png)

DataTableが使えない？と思っていたところ、以下の設定だけでした。

```config/adminlte.php
    'plugins' => [
        'Datatables' => [
            'active' => true, // ← これをfalse→trueにするだけ
            'files' => [
```

この辺を日本語化するには、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127974/1140149c-6d48-baac-0e39-c730367aeb78.png)

このようにします。
```sample.blade.php
@section('js')
<script>
    $(function() {
        $('#example').DataTable(.DataTable({
            language: {
                url: "//cdn.datatables.net/plug-ins/be7019ee387/i18n/Japanese.json"
            }
        });
    });
</script>
@endsection
```
【EC2】自動停止・起動設定をLambdaで書いてEC2タグで設定する

# EC2の自動起動・停止を自動化させたい

社内用のサーバーなどで常時起動しておく必要のないサーバーを夜になったら自動で停止、朝になったら自動で開始をさせたいという要望がありました。
単純に開始処理と停止処理をLambdaで書いて起動や停止をさせればいいのですが、時間の変更や、一時的に停止をやめたり、開始をやめたりなどカスタム性を考えるとEC2のタグで管理できると楽だなという結論になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290902/448e277c-4b0a-1169-d826-0261a3508ed1.png)

上記画像のようにEC2のタグに開始時刻と停止時刻を書いてしまうという運用です。不要なればタグを外すだけです。
以下のスクリプトでできました。
hour_rounderという関数で時刻を丸めているのですが、これはいらないかもですが念の為にやっています。

あとはこのLambdaをEvent Bridgeで毎時呼び出すだけです。
LambdaのロールにはEC2の起動・停止の権限をお忘れなく！

```python
import json
import boto3
from datetime import datetime, timedelta, timezone

ec2 = boto3.client('ec2', region_name='ap-northeast-1')

def lambda_handler(event, context):
    JST = timezone(timedelta(hours=+9), 'JST')
    now = datetime.now(JST)

    # 時刻処理 現在に最も近い0分の時間を取得
    # 例 12時10分 → 12時   4時40分 → 5時
    def hour_rounder(t):
        return (t.replace(second=0, microsecond=0, minute=0, hour=t.hour) + timedelta(hours=t.minute//30))
    
    hour_rounded_time = hour_rounder(now)
    hour = str(hour_rounded_time.hour)

    # 停止処理
    custom_filter = [{
        'Name':'tag:auto_stop_at', 
        'Values': [hour]}]
        
    response = ec2.describe_instances(Filters=custom_filter)
    stop_instance_ids = []
    for instance_dic in response['Reservations']:
        stop_instance_ids.append(instance_dic['Instances'][0]['InstanceId'])
    
    if stop_instance_ids:
        ec2.stop_instances(InstanceIds=stop_instance_ids)
    
    # ここから開始処理
    custom_filter = [{
        'Name':'tag:auto_start_at', 
        'Values': [hour]}]
        
    response = ec2.describe_instances(Filters=custom_filter)
    start_instance_ids = []
    for instance_dic in response['Reservations']:
        start_instance_ids.append(instance_dic['Instances'][0]['InstanceId'])
        
    if start_instance_ids:
        ec2.start_instances(InstanceIds=start_instance_ids)
    return {
        'statusCode': 200,
        'start_instance_ids': start_instance_ids,
        'stop_instance_ids': stop_instance_ids
    }

```
swiftでHTTPリクエスト

## Postmanで自動生成する

Postmanで投げたいリクエストを作成し、以下のCodeボタンを押しSwiftを選択することでHTTPリクエスト周りのコードが自動生成してくれます。（慣れてない言語だとすごくありがたい機能ですね）

![スクリーンショット 2022-09-28 15.18.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510204/cd2b0190-d376-0d8e-e9f6-05bbe1a7cce7.png)


![スクリーンショット 2022-09-28 15.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510204/997f0bce-ab50-508f-866c-15814ad7396d.png)


``` request.swift
import Foundation

var semaphore = DispatchSemaphore (value: 0)

let parameters = "{\n    \"name\": \"kitanote\",\n    \"age\": 32\n}"
let postData = parameters.data(using: .utf8)

var request = URLRequest(url: URL(string: "https://test.com/function-1")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")

request.httpMethod = "POST"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in 
  guard let data = data else {
    print(String(describing: error))
    semaphore.signal()
    return
  }
  print(String(data: data, encoding: .utf8)!)
  semaphore.signal()
}

task.resume()
semaphore.wait()
```

## コーダブルにする

上のコードままではparametersの値が少々変更しづらいので、プログラムから利用しやすいようにします。Codableに準拠したUserを作成します。

``` request.swift
public struct User: Codable {
    public var name: String
    public var age: Int
    
    func jsonData() -> Data {
        return try! JSONEncoder().encode(self)
    }
    
    func jsonStr() -> String {
        let data = jsonData()
        return String(data: data, encoding: .utf8)!
    }
}

let user = User(name: "kitanote", age: 32)
let postData = user.jsonData() 
```

:::note info
Data型
Data型はバイト列を表現する構造体で、ファイルの読み書きや通信など、外部システムとデータをやり取りする際に使用します。バイト列はさまざまなデータの表現に使用され、たとえば画像やJSONもバイト列によって表現できます。
:::
AzureのパブリックIPアドレスのBasic SKU廃止について #Azure

# 背景
2025年9月30日以降、AzureのパブリックIPアドレスのBasic SKUが廃止されるため、2025年9月30日までにStandard SKUに更新する必要があります。
また、2025年3月31日以降は新規にBasic SKUのパブリックIPアドレスは作成できなくなります。
なお、Azure Cloud Services (延長サポート) にデプロイされたBasic SKUパブリック IP アドレスは、今回の廃止の影響を受けないため、何らかアクションする必要はありません。

※2022年9月28日時点にAzureのパブリックIPアドレスを利用しているユーザー向けの案内を元に情報収集していますので、最新情報とは差異がある可能性があることをご理解願います。

# 影響範囲
パブリック IP を関連付けられる以下のリソースが対象と考えます。
* 仮想マシン
  * ネットワーク インターフェイス
* パブリック ロード バランサー
  * フロント エンド構成
* Virtual Network ゲートウェイ (VPN)
  * ゲートウェイ IP の構成
* Virtual Network ゲートウェイ (ER)
  * ゲートウェイ IP の構成
* NAT Gateway
  * ゲートウェイ IP の構成
* Application gateway
  * フロント エンド構成
* Azure Firewall
  * フロント エンド構成
* bastion ホスト
  * パブリック IP 構成
* ルート サーバー
  * フロント エンド構成

参考： [早見表 - パブリック IP アドレス](https://learn.microsoft.com/ja-jp/azure/virtual-network/ip-services/public-ip-addresses#at-a-glance)

# アクション
## Standard SKUの価格を確認する。
予算を見直しが必要な可能性もあります。また、これを機会にリソースの棚卸をしてみるのも良いかもしれません。
参考： [IP アドレス の価格](https://azure.microsoft.com/ja-jp/pricing/details/ip-addresses/)

## パブリック IP アドレスのSKUの更新方法を確認する。
  * Microsofドキュメントを確認する。
    * 参考： [Azure portal を使用してパブリック IP アドレスをアップグレードする](https://learn.microsoft.com/ja-jp/azure/virtual-network/ip-services/public-ip-upgrade-portal)

  * [Microsoft Q&A](https://learn.microsoft.com/en-us/answers/products/?WT.mc_id=launchblog-blog-QA)やサポートに質問する。
    * 参考：  [Microsoft Q&A が一般提供されます](https://learn.microsoft.com/ja-jp/teamblog/microsoft-qna-ga)

## 計画してパブリック IP アドレスのSKUを更新する。
* 2025年9月30日までの期限ですが、サービス停止やDNS伝搬なども踏まえた日程で計画立てると良いかと思います。
* 構成やSKUを更新するリソースの順番など工夫すればサービス停止を抑えられる可能性もあるとは思います。
ディスククローンの覚書


# ディスククローンの覚書

## 目標：Windows10ノートPCのHDDをSDDに換装
    1000GBのHDD→500GBのSDDに換装

## 使用ソフト：Clonezilla
     linuxベースのツール。USBドライブ起動なのでOSに関わらず使用可能。日本語可。

## 結論
    Clonezillaで縮小クローンは条件が厳しそう。今回は無理だった。





## クローン先ドライブの準備
クローン元HDD GPTフォーマット
クローン先SDD MBRフォーマット
~~`Clonezilla`ではどうかわからないけど、他のツールでこの組み合わせでクローンできないらしいので、コピー先をGPTに変換しました（参考サイト参照）。~~


## クローン元パーティションの準備
`Clonezilla`ではパーティションの縮小コピー機能は無いので、あらかじめパーティションを縮小しておく。
空きは有ってもWindowsのディスク管理ではほとんど縮小できなかったので、`EaseUS Partition Master`のフリー版で実施。

## クローンの実行
`Clonezilla`を実行するにあたって`Beginner 初心者モード`ではパーティションの調節はしても、ディスクサイズのチェックでエラーになるので、エキスパートモードで`"-icds" and "-k1"`を指定する。参考サイトによると、これでもダメなケースがあるみたいだけど、今回はOKでした。

---

途中でエラーが出て止まったので、enterキー押したら続行したうえ、最終的に正常終了した。
結果として、ブータブルドライブとして起動せず。クローンは失敗したようだ。
またまたかもしれないのでもう一回やってみるけど。。。

---

やっぱり無理だった。
同容量以上のクローンに関しての問題は見当たらなかったので、縮小はダメだったけどメモとして残します。

---



参考サイト：
[Clonezilla Live Download](https://clonezilla.org/downloads.php)
[Linux Clonezillaを使ったHDDのクローン(コピー)/拡張(320GB→500GB)](https://toshio-web.com/linux-hdd-clone)
[Clonezilla小さなディスクに大きなディスクをクローンする方法](https://www.ubackup.com/jp/articles/clonezilla-clone-larger-disk-to-smaller-disk.html)
[Clonezilla Discussion: "Failed to create a partition table on this disk"](https://sourceforge.net/p/clonezilla/discussion/Clonezilla_live/thread/4a4ca4cc/)
[【HDD】GPT形式でハードディスクをフォーマットしたい （コマンドプロン...](http://qa.elecom.co.jp/faq_detail.html?id=5300)
[EaseUS（イーザス）公式サイト|パーティション管理ソフト - EaseUS Partition Master](https://jp.easeus.com/partition-manager-software/)
郵便番号・都道府県別データをデータベースに保存する（Sqlite3）

# データの取得

今回は郵便局のサイトからデータをダウンロードします。
- 都道府県一覧 > 全国一括(1,691,560Byte)

[日本郵便：郵便番号データダウンロード](https://www.post.japanpost.jp/zipcode/dl/kogaki-zip.html)

> 全角となっている町域部分の文字数が38文字を越える場合、また半角となっているフリガナ部分の文字数が76文字を越える場合は、複数レコードに分割しています。
この郵便番号データファイルでは、以下の順に配列しています。
1. 全国地方公共団体コード（JIS X0401、X0402）………　半角数字
1. （旧）郵便番号（5桁）………………………………………　半角数字
1. 郵便番号（7桁）………………………………………　半角数字
1. 都道府県名　…………　半角カタカナ（コード順に掲載）　（注1）
1. 市区町村名　…………　半角カタカナ（コード順に掲載）　（注1）
1. 町域名　………………　半角カタカナ（五十音順に掲載）　（注1）
1. 都道府県名　…………　漢字（コード順に掲載）　（注1,2）
1. 市区町村名　…………　漢字（コード順に掲載）　（注1,2）
1. 町域名………………　漢字（五十音順に掲載）　（注1,2）

> ※1 文字コードには、MS漢字コード（SHIFT JIS）を使用しています。</FONT>
※2 文字セットとして、JIS X0208-1983を使用し、規定されていない文字はひらがなで表記しています。

今回は1,3,4,5,6,7,8,9のみ扱います。

# テーブルの作成〜
流れとしてはcsvのデータを必要な項目に加工し、そのままsqliteでインポートしていきます。
```terminal:データの整形
% nkf -g KEN_ALL.CSV
=> Shift_JIS

# utf-8に変換
% nkf -w --overwrite KEN_ALL.CSV
% nkf -g KEN_ALL.CSV
=> UTF-8

# 必要な項目のみ切り出し
% cut -d ',' -f 1,3,4,5,6,7,8,9 KEN_ALL.CSV > ken_all.csv

# 先頭に行番号を付与
% nl -s ',' db/ken_all.csv | tr -d ' ' > ken_data.csv
```

```terminal:sqlite
# テーブルの作成
% sqlite3
sqlite> create table ken_all(id integer primary key autoincrement, code integer, post_code text, prefecture_kana text, address_1_kana text, address_2_kana text, prefecture_name text, address_1_name text, address_2_name text);
sqlite> .tables
=> ken_all

# データのインポート 🍺
sqlite> .mode csv
sqlite> .import ken_data.csv ken_all
sqlite> SELECT count(*) FROM ken_all;
=> count(*)
=> 124553

sqlite> CREATE INDEX post_code_index on ken_all(post_code);
sqlite> CREATE INDEX prefecture_name_index on ken_all(prefecture_name);
sqlite> .indices
=> post_code_index        prefecture_name_index

sqlite> .headers ON
sqlite> SELECT * FROM ken_all LIMIT 5;
id,code,post_code,prefecture_kana,address_1_kana,address_2_kana,prefecture_name,address_1_name,address_2_name
1,1101,0600000,"ホッカイドウ","サッポロシチュウオウク","イカニケイサイガナイバアイ","北海道","札幌市中央区","以下に掲載がない場合"
2,1101,0640941,"ホッカイドウ","サッポロシチュウオウク","アサヒガオカ","北海道","札幌市中央区","旭ケ丘"
3,1101,0600041,"ホッカイドウ","サッポロシチュウオウク","オオドオリヒガシ","北海道","札幌市中央区","大通東"
4,1101,0600042,"ホッカイドウ","サッポロシチュウオウク","オオドオリニシ(1-19チョウメ)","北海道","札幌市中央区","大通西（１〜１９丁目）"
5,1101,0640820,"ホッカイドウ","サッポロシチュウオウク","オオドオリニシ(20-28チョウメ)","北海道","札幌市中央区","大通西（２０〜２８丁目）"

DONE!⭐︎
```
SQLSTATE[HY000]: General error: 1364 Field 'YYYYY' doesn't have a default valueの対処法

原因
dedfault値がありませんと言っているため、defaultへの対処法として「結論」を実施するとうまくいく

結論
My sql"YYYYYY"のデータベース、デフォルト値を「null」に変更する
Herokuの代わりを探してみた！サービスが多すぎて迷っている方に！

<h1>Herokuがサービス終了するけど、類似サービス多すぎじゃね？</h1>
と思ったので、まとめさせていただきます。
GithubからそのままあげられるPaasです。

<h2>胡散臭いサービスが多すぎる</h2>
Qiitaでも、類似の記事を書いている方はいますが、サービスの数が多く判断しきれません。<br>
また、リンクを踏んでみると、チープなサイトが多く、データを預けるには怖いっす。
<h2>結果選んだサービス</h2>

・[cyclic.sh](https://www.cyclic.sh/)
・[render](https://render.com/)
・digitaloceanで[dokku](https://dokku.com/docs/getting-started/installation/)

<h3>cyclic.sh</h3>
1番おすすめだけど、難点も
<h4>◇メリット</h4>
<ul>
<li> 性能が高い</li>
<li>デプロイが早い </li>
<li>常時起動 </li>
<li>無料でもドメイン名を変更できるらしい？ </li>
<li> 便利機能がある（環境変数の設定確認は優しい）</li><br>
Herokuに比べても、サーバの性能が高く、デプロイが一瞬で終わります。<br>
デプロイの方法もHerokuと一緒、もしくはもっと簡単。<br>
DBの環境変数の設定を忘れていましたが、わざわざ確認してくれるやさしさに惚れた。
</ul>
<h4>◇デメリット</h4>
<ul>
<li>無料だと3つしかデプロイできない </li>
<li>有料プランでもデプロイ数に限りがある </li>
<li>テンプレートが少なめ </li>
</ul>

<h4>◆総論</h4>
無料としては破格の性能で、<br>
かなり使いやすいサービスだが、デプロイ数に限りがあるため勝負用アプリ専用におすすめ！

<h3>render</h3>
<h4>◇メリット</h4>
<ul>
<li>おそらく無制限にデプロイ可能 </li>
<li> サービスとテンプレートが豊富</li>
<li>使いやすいUI </li>
<li>ぼちぼちの性能 </li>
<li>無料でもドメイン名を変更できるかも？ </li>
</ul>
<h4>◇デメリット</h4>
<ul>
<li> デプロイが信じられないくらい遅い。３０分とかかかる</li>
<li> Herokuよりサーバ性能低いかも？</li>
<li> サービスとテンプレートが多い分、初学者迷子になりがち</li>
</ul>

<h4>◆総論</h4>
無料としてはテンプレートが多くデプロイできる可能性のあるアプリが多いと思う。<br>
ただとにかくデプロイが遅いため使用感としては引っ掛かり、有象無象アプリの収容所になりそう。

<h3>Dokku</h3>
<h4>◇メリット</h4>
<ul>
<li>自由 </li>
<li>サービスがなくならない </li>
<li>よくも悪くも勉強になる </li>
</ul>
<h4>◇デメリット</h4>
<ul>
<li>設定が地獄 </li>
<li>ちょっとお金がかかる </li>
<li>デプロイがすんなりいかないことも </li>
</ul>

<h4>◆総論</h4>
VPS初心者のため、ひたすら調べてなんとか実装。<br>
Qiitaの記事を調べると皆さんサクっと環境を作れているようでしたが、僕には
結構地獄でした。<br>
ただ副産物として、ubuntuやgithub、sshなどの知識がついたのは無駄にはならないはず！<br>
慣れている人にはベストかもしれないが、初学者にはお勧めできない。VPSが嫌いになります。<br>
あと、conohaで始める予定でしたが、dokkuのテンプレがあるにもかかわらずなぜか使えませんでした。<br>
そのため、深い理由もなくDigitaloceanを使用。
Powerappsのエクスポートとインポート


1,両環境を「アンマネージド」でエクスポートする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/9e2a6321-711b-8cc7-df46-a2cf0828a631.png)

2,バックアップをする
3,環境1から環境2をインポートする
4,すべてのカスタマイズの公開
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/193e9193-5e30-8f2c-8536-dae3141bed64.png)
Android adbで接続した端末のスクリーンキャプチャー

adb接続端末のスクリーンキャプチャーをローカルに保存するバッチファイルを備忘録として置いときます。
Windows のバッチファイルです。

~~~text:キャプチャー用のバッチ
@echo off
set yyyy=%date:~0,4%
set mm=%date:~5,2%
set dd=%date:~8,2%

set time2=%time: =0%

set hh=%time2:~0,2%
set mn=%time2:~3,2%
set ss=%time2:~6,2%

set filename=android-%yyyy%%mm%%dd%-%hh%%mn%%ss%

adb shell screencap -p /sdcard/screen.png
adb pull /sdcard/screen.png
adb shell rm /sdcard/screen.png
rename screen.png %filename%.png
echo %filename%.png
~~~
Mac + Ruby + selenium を初めて使う

# 準備

gemのインストール

```
gem install selenium-webdriver
```

chromeドライバのインストール

```
brew install chromedriver
```

# コード例

```rb
require 'selenium-webdriver'

session = Selenium::WebDriver.for :chrome

session.navigate.to "https://example.com"

if session.save_screenshot('./example-com.png')
  puts "Screen shot saved"
end

session.quit
```

# Macでの許可

rubyを実行すると以下ダイアログが表示されるのでキャンセルする。

![image](https://user-images.githubusercontent.com/13635059/192693354-26e2b0fc-7a9b-440b-9518-c966b0bf2f0f.png)

Macの設定で許可する。「このまま許可」を選ぶ。

![image](https://user-images.githubusercontent.com/13635059/192693593-c1d9effb-d722-4c11-95bc-74864a725fb3.png)

もう一度Rubyを実行して「開く」を選ぶ。

<img width="449" alt="image" src="https://user-images.githubusercontent.com/13635059/192693587-384f4fab-b5e1-4d72-a5a1-6906fc578d96.png">

# 結果

実行するとブラウザが起動してスクリーンショット画像が生成される。

![image](https://user-images.githubusercontent.com/13635059/192692949-1acd0b81-6e71-4d9f-a9c7-e50bb4c2bd1c.png)




# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
未経験からITエンジニアになる〜ポートフォリオ作成〜

大学院を中退してITエンジニアを目指しています。
今回はエンジニア就活に必要なポートフォリオ作成について考えたことを備忘録としてここに残します。
# 何を作るか
現在は自身が所属していたアルティメットサークル（フリスビーを使うスポーツです）の反省用掲示板を作成しよう考えています。
現在も掲示板自体は存在しているのですが以下の点において改善したいと考えていました。

- トピックごとに分かれていない
- 有益な投稿に関してバックナンバーで振り返りづらい
- タグ付け機能がなく先輩の知恵を検索で探せない

そこで見た目や本来の掲示板機能を備えつつ、①トピックを設定、②お気に入り機能（いいね機能？）、③タグ付け機能を追加した掲示板を作成し、後輩たちに使ってもらいたいと思います。

# Qiitaの使用
何かやりだすと夢中で先に進んでしまうため振り返りの機会をもつためにQiitaに投稿を始めようと考えました。稚拙な文章力は表現力も向上できればなと思います。



今回はこの辺で、それでは！！