OmniAICreator/Qiita-1.07M huggingface dataset:
[UE4,C++] Configファイル内の構造体配列をブループリントで使用する

# はじめに
コンフィギュレーションファイル（DefaultEngine.iniやDefaultGame.ini等）に記述した構造体配列の情報を取り出して、ブループリントで使えるようにする処理の作り方です。

# できるようになること
下記のような複数の設定項目をコンフィギュレーションファイルに記載して、

```DefaultEngine.ini
[/Script/IniTest.ConfigSetting]
SampleStructs=(SampleParameter1="AAA",SampleParameter2="BBB")
+SampleStructs=(SampleParameter1="CCC",SampleParameter2="DDD")
```

下記のようにブループリントで値を使えるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/15cd950e-04cb-9b3c-2570-6c678902d853.png)

# 環境
Unreal Engine 4.27
Visual Studio 2019
Windows10

# C++の実装

```ConfigSetting.h
#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ConfigSetting.generated.h"

/**
 * 構造体
 */
USTRUCT(BlueprintType)
struct FSampleStruct
{
	GENERATED_USTRUCT_BODY()

	/** パラメーター1 */
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	FName SampleParameter1;

	/** パラメーター2 */
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	FName SampleParameter2;
};

/**
 * 構造体配列及びそれを取り出す関数を持つクラス
 */
UCLASS(config = Engine, defaultconfig)
class INITEST_API UConfigSetting : public UObject
{
	GENERATED_BODY()

public:

	UPROPERTY(EditAnywhere, Config)
	TArray<FSampleStruct> SampleStructs;

	UFUNCTION(BlueprintCallable)
	static TArray<FSampleStruct> GetSampleStructs();

};
```

```ConfigSetting.cpp
#include "ConfigSetting.h"

/** 構造体配列を取り出す関数 */
TArray<FSampleStruct> UConfigSetting::GetSampleStructs()
{
	return GetDefault<UConfigSetting>()->SampleStructs;
}
```

# DefaultEngine.iniにデータを記述

```DefaultEngine.ini
[/Script/IniTest.ConfigSetting]
SampleStructs=(SampleParameter1="AAA",SampleParameter2="BBB")
+SampleStructs=(SampleParameter1="CCC",SampleParameter2="DDD")
```

# ブループリントで構造体を取得する
コンパイルしてブループリントから値を取り出せるようになります。
（DefaultEngine.iniを変更時はUE4エディタの再起動が必要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668217/15cd950e-04cb-9b3c-2570-6c678902d853.png)

# 参考サイト

- コンフィギュレーションファイルについて

https://docs.unrealengine.com/4.27/ja/ProductionPipelines/ConfigurationFiles/

- 構造体を使わない方法

https://katze.hatenablog.jp/entry/2016/06/14/152027

- プロジェクト設定にも項目を追加したいときの方法



https://historia.co.jp/archives/18025/
ソースコードとデプロイされているものが同じとは限らない件

# 何があったか

Tomcat＋Javaでできている、一時期だけ動いていたキャンペーンサイトを前任者（退職済み）から引き継ぎ、新しいキャンペーンサイトの構築をすることになった時の話。

本番サーバの場所とソースのリポジトリだけを教えてもらい、ソースコードを読んで仕様を確認したところ、何も変えずにそのまま使えそうだったので、何も変えずに開発環境で動作確認。
案の定何の問題もなかったので、本番サーバはそのままで行くことにした。

キャンペーンサイトをオープンしたところ・・・、ありえないエラーが頻出。
もしやと思い、jarを作り直して本番サーバにあげたところ、エラーがなくなった。

そう、**本番サーバに上がっていたjarはmasterブランチのheadのものではなかった**、と思われる。
最終コミットの日時とjarの更新日が近かったのでてっきり最新のものが上がっていると勘違い。
そのjarだと前回使った時もエラーになっていた気がするので、一体何のバージョンが上がっていたのか誰もわからず。

# どうすれば良かったのか

こういうことがあるので、しばらく動いていないサーバには改めてちゃんとデプロイしましょう。
特にJavaとかだとjarで固めてしまってソースが簡単には確認できないので。
pandas Tips【備忘録】

pandasが大好きなので、使っていく上で必要になるテクニックを備忘録的に書いていきます。



## 行を取り出す (loc, iloc)

pandasで行を取り出したい場合、スライス表記 (ex. `df['R1':'R1']`)を使うという手もありますが、１行のみを取り出したい場合は冗長ですし、型が`Series`ではなく`DataFrame`になってしまいます。

そこで`loc`, または`iloc`を使います。`df.loc['R1']`とすることで、`df`から`'R1'`行を`Series`型で取り出すことができます。

```python
import pandas as pd
from pandas import Series, DataFrame

df = DataFrame(
    [
     [1, 2, 3],
     [4, 5, 6]
    ],
    columns = ['A', 'B', 'C'],
    index = ['R1', 'R2']
)

print(df)
#     A  B  C
# R1  1  2  3
# R2  4  5  6

print(df['A'])
# R1    1
# R2    4

print(df['R1':'R1'])
#     A  B  C
# R1  1  2  3

print(type(df['R1':'R1']))
# <class 'pandas.core.frame.DataFrame'>

print(df.loc['R1'])
# A    1
# B    2
# C    3

print(type(df.loc['R1']))
# <class 'pandas.core.series.Series'>

print(df.iloc[0])
# A    1
# B    2
# C    3
```



`loc`は（多分）locate, locationの略で、`df.loc[行, 列]`のようにインデックスを指定することで`DataFrame`の一部を取り出すことができ、スライス表記にも対応しています。

似た関数に`at`があります。これはその名の通り一点を取り出す関数で、`df.at[行, 列]`とすることで１つの値を取り出すことができますが、スライス表記には対応しておらず、行や列を取り出すこともできません。



## 行の追加

### index(行名)に意味がある場合

日付や識別名などを使用していて、indexに意味がある場合は新しい行名を指定して代入することで行を追加することができます。

```python3
df = DataFrame(
    [
     [1, 2, 3],
     [4, 5, 6]
    ],
    columns = ['A', 'B', 'C'],
    index = ['R1', 'R2']
)

# 追加したい行(リスト形式)
new_row = [10, 11, 12]

# 新しい行名を指定して追加
df.loc['R3'] = new_row
print(df)
#      A   B   C
# R1   1   2   3
# R2   4   5   6
# R3  10  11  12
```



### index(行名)に意味がなく、ただの通し番号の場合。

実際のところこっちのケースのほうが多いのではないでしょうか。

この場合も上記と同様に`df.loc[len(df)] = new_row`などとすれば、行を追加できます。

しかしこれでは、「行を追加している」感が薄いので、慣れ親しんだ`append`を使いたくなりますが、Pandasの`append`には注意点がいくつかあります。

- 追加する行として指定できるのは、`DataFrame`, `Series`, `dict`
- `Series`を追加する場合は、`Series`の`index`がカラム名、`name`が行名に対応する。
- 行名を指定せず連番にしたい場合、`ignore_index=True`とする必要がある。
- リスト型の`append`メソッドと違い、元変数に再代入する必要がある。

```python
# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import pandas as pd
from pandas import Series, DataFrame

df = DataFrame(
    [
     [1, 2, 3],
     [4, 5, 6]
    ],
    columns = ['A', 'B', 'C'],
)

# 追加したい行(リスト形式)
new_row = [10, 11, 12]

# リストをSeriesに変換してappend
print(
    df.append(Series(new_row, index=df.columns), ignore_index=True)
)
#     A   B   C
# 0   1   2   3
# 1   4   5   6
# 2  10  11  12

# リストを辞書に変換してappend
print(
    df.append(dict(zip(df.columns, new_row)), ignore_index=True)
)
#     A   B   C
# 0   1   2   3
# 1   4   5   6
# 2  10  11  12

# 再代入していないので元データは変わっていない
print(df)
#    A  B  C
# 0  1  2  3
# 1  4  5  6

# 再代入
df = df.append(Series(new_row, index=df.columns), ignore_index=True)
print(df)
#     A   B   C
# 0   1   2   3
# 1   4   5   6
# 2  10  11  12
```
MySQL スレッドプール

#### MySQL スレッドプール　サンプルモジュール（Python）

参考：https://dev.mysql.com/doc/refman/5.6/ja/faqs-thread-pool.html#faq-thread-pool-what-solve
個人ブログ：https://wintercat.jp/post/databasecat/
あくまでもご参考で〜:coffee:

import 必要なモジュール

```
import pymysql
from dbutils.pooled_db import PooledDB
import config
```

```
# -*- coding:utf-8 -*-
# @Author: WinterCat
# @File : database_pool.py

class DataBaseConnectionPool:
    __pool = None
    # init database connection
    def __init__(self):
        self.conn = self.get_connection().connection()
        self.cur = self.conn.cursor(pymysql.cursors.DictCursor)

    # connection create and create config file to set it
    def get_connection(self):
        if self.__pool is None:
            __pool = PooledDB(
                creator=pymysql,
                maxconnections=config.DB_MAX_CONNECTIONS,
                mincached=config.DB_MIN_CACHED,
                maxcached=config.DB_MAX_CACHED,
                maxshared=config.DB_MAX_SHARED,
                blocking=config.DB_BLOCKING,
                maxusage=config.DB_MAX_USAGE,
                setsession=config.DB_SET_SESSION,
                ping=config.DB_PING,
                host=config.DB_HOST,
                user=config.DB_USER,
                password=config.DB_PASSWORD,
                database=config.DB_NAME,
                charset=config.DB_CHARSET
            )
        return __pool

    # connection auto close
    def __del__(self):
        self.cur.close()
        self.conn.close()


# search database by query
def search_data(query):
    connection = DataBaseConnectionPool()
    connection.cur.execute(query)
    return connection.cur.fetchall()


# insert data by query
def update_data(query):
    connection = DataBaseConnectionPool()
    connection.cur.execute(query)
    return connection.conn.commit()
```

config.py
> 基本的に設置または編集が必要なところは 
DB_HOST, DB_POST, DB_USER, DB_PASSWORD, DB_NAME となります。

```
DB_CREATOR = 'pymysql'
DB_HOST = 'IP ADDRESS'  # データベースのIPアドレス
DB_PORT = 3306
DB_NAME = 'DB_NAME'　# データベース名前
DB_USER = 'USERNAME' 
DB_PASSWORD = 'PASSWORD'
DB_CHARSET = 'utf8mb4'　# encode
# free cached min
DB_MIN_CACHED = 10
# free cached max
DB_MAX_CACHED = 22
#  pools create max
DB_MAX_CONNECTIONS = 100
#  share pool max
DB_MAX_SHARED = 20
# max pool block
DB_BLOCKING = True
#  connection use again
DB_MAX_USAGE = 0
# session
DB_SET_SESSION = []
# ping
DB_PING = 0
```

>使用方法について

検索の方法は：search_data を使え
何かをInsert、またはアップデートすると：add_data を使え
↓例となります。

```
# @Author: WinterCat
from database_service.database_pool import add_data, search_data
# テーブルを作る
def create_table():
    sql = '''
    CREATE TABLE IF NOT EXISTS sys(ID INT PRIMARY KEY AUTO_INCREMENT,message VARCHAR(50))
    '''
    return add_data(query=sql)
    
if __name__ == '__main__':
    print(create_table())
```
FileMaker のまとめ

明記されてなければ書いてあることは大体 19.x系の話。

# 関連ページ

https://qiita.com/YKInoMT/items/6c7dd52441d151adc8f7

https://qiita.com/YKInoMT/items/db6872b7ca7327141042

https://qiita.com/YKInoMT/items/1e9ae7f3228485896e58

# 表示言語の変更

Windows は「環境設定」で「ユーザインターフェースの言語」を変更することで可能。

macOS の場合はシステム環境設定 > 言語と地域 > アプリケーション タブで、FileMaker Pro を追加して言語を設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/9193ab0b-3d95-bd91-3ebc-90f3331b56e0.png)


# スクリプト

一般的なスクリプト言語とは似て非なる箇所が多々ある。

## コメントアウト

スクリプトワークスペースの指定行を選択した状態で、「編集」メニューから「無効」を選択するか `⌘`+`/` ショートカットキーでコメントアウトできる。

![スクリーンショット 2021-12-07 17.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84947/0b858f62-d230-5205-a4b9-0b892613c5b0.png)

コメントアウトされたスクリプトステップの先頭には `//` が入るっぽいが、 `//` を入力してもだめ。（というかできない。）

元に戻す場合は、同じ操作を行えばOK。

ちなみに、コメント行は `#` から始まる。

この辺りは無関係っぽい。


## 表示言語よって記述方法が異なる

「ユーザインターフェースの言語」によって書き方が変わる。

つまり FileMaker　のインターフェースがを英語の場合と、日本語の場合でスクリプトの書き方が変わる。

例えば、変数の設定は英語では

```
Set Variable [$Var; Value: "value"]
```

ですが、同じことを日本語環境では

```
変数を設定 [$Var; 値: "value"]
```

という感じで書かないとダメ。

https://help.claris.com/en/pro-help/content/set-variable.html

https://help.claris.com/ja/pro-help/content/set-variable.html


## コピー/ペースト

FileMaker 内部であれば行単位のコピー/ペーストは可能。

正し、コピーした内容はテキストデータとしてコピーされるわけではないらしく、テキストエディタなどにコピーして編集、FMP　に貼り付けて実行、みたいなことは無理っぽい。

例えばヘルプを見てサンプルのコードを試すような場合でも、FMP　に貼り付けて実行する、なんてことは無理。

https://help.claris.com/ja/pro-help/content/allow-user-abort.html

全て、手で入力していく必要がある。

逆も然り。

FileMaker Pro で書いたスクリプトのサンプルを Qiita で公開しようと思った場合でも、コピー & ペーストできないので、全て手で入力する必要がありそう。

プラグイン？を使う方法もあるようですが、本体自体にはこの手の機能はなさそう。
dockerをEC2で起動→dockerにログイン→dockerファイル作成→ビルド→プッシュまでやってみる

OS
RHEL-7.7_HVM-20190923-x86_64-0-Hourly2-GP2

```
yum install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
ls /etc/yum.repos.d/docker-ce.repo
yum list docker-ce --showduplicates | sort -r

```
```txt:有効化するとこうなる
# yum-config-manager --enable rhui-rhel-7-server-rhui-extras-rpms
# yum repolist all | grep extras
rhui-rhel-7-server-rhui-extras-debug-rpms/x86_64                  disabled
rhui-rhel-7-server-rhui-extras-rpms/x86_64                        enabled:  1,413
rhui-rhel-7-server-rhui-extras-source-rpms/x86_64                 disabled
```
```txt:※↑これをしないと有効化が必要なのでエラーになる
# yum install docker-ce-18.06.1.ce-3.el7
Loaded plugins: amazon-id, search-disabled-repos
Resolving Dependencies
--> Running transaction check
---> Package docker-ce.x86_64 0:18.06.1.ce-3.el7 will be installed
--> Processing Dependency: container-selinux >= 2.9 for package: docker-ce-18.06.1.ce-3.el7.x86_64
--> Finished Dependency Resolution
Error: Package: docker-ce-18.06.1.ce-3.el7.x86_64 (docker-ce-stable)
           Requires: container-selinux >= 2.9
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest
```

```
yum install docker-ce-18.06.1.ce-3.el7
docker --version
systemctl status docker
systemctl start docker
getent group | grep docker
docker run hello-world
```


```

aws ecr get-login-password --region region | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.region.amazonaws.comdocker 
sudo vi Dockerfile

```

```txt:/Dockerfile

FROM ubuntu:18.04

# Install dependencies
RUN apt-get update && \
 apt-get -y install apache2

# Install apache and write hello world message
RUN echo 'Hello World!' > /var/www/html/index.html

# Configure apache
RUN echo '. /etc/apache2/envvars' > /root/run_apache.sh && \
 echo 'mkdir -p /var/run/apache2' >> /root/run_apache.sh && \
 echo 'mkdir -p /var/lock/apache2' >> /root/run_apache.sh && \ 
 echo '/usr/sbin/apache2 -D FOREGROUND' >> /root/run_apache.sh && \ 
 chmod 755 /root/run_apache.sh

EXPOSE 80

CMD /root/run_apache.sh
```
```
docker build -t hello-world .
docker images --filter reference=hello-world
docker tag hello-world:latest aws_account_id.dkr.ecr.region.amazonaws.com/hello-world:latest
docker push aws_account_id.dkr.ecr.region.amazonaws.com/hello-world:latest

```
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/getting-started-cli.html
カフェでプログラミングしてる風（でも何もやってない）Python（クソ）コード

# はじめに
先日近所のドトールコーヒーでプログラミングをしていた時に、ふと[こちらの記事](https://qiita.com/3S_Laboo/items/660883a0184dabaea65b)を思い出しました。
息抜きがてら私もそれっぽいものを作ってみようと思い立ち、すぐに開発し始めました。

# 完成品
![cafe_coding_qiitan.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581889/1df3e53e-9998-286f-9fe6-3c7bc0d80f19.gif)
おしゃれなカフェでこれを開いてパソコンカタカタしていたら、凄腕プログラマーと思われること間違いないですね！

# 実装
ソースの全容は以下のリンクから確認できます。

https://github.com/Yotty0404/Cafe_Coding


## 1. なにかをダウンロードしてそうなやーつ
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581889/5c9b6a48-6155-e116-1963-769212c9d9fa.gif">
まずダウンロードの速度が一定すぎると不自然たと思ったので、ちょこちょこ止まるようにしました。

また、それぞれ10%の確率で以下のような警告・エラーメッセージを表示するようにしています。
　①すでにダウンロードされているというメッセージ
　②ダウンロードしようとしているバージョンより新しいバージョンがある警告
　③ダウンロードしようとしているフォルダにアクセスできないエラー
それらしさを増すために、警告やエラーでメッセージの色を付けるようにもしています。

## 2. なにかをビルドしてそうなやーつ
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581889/e8f37447-4848-58d1-1b65-7657f2faa53c.gif">
こちらもビルドの速度が一定だと不自然に感じるので、乱数で待ち時間を変えています。

また、4種類の警告を用意して複数出すようにしています。
1つも警告が出ないときもあれば、同じ警告が複数出るときもある、というようなこだわった作りにしています。

## 3. キーボードをかたかたするだけでコーディングしてそうなやーつ
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581889/cea93e80-39f2-8113-df90-997290bffd39.gif">

どのキーを入力しても、事前に用意したコードが1文字ずつ表示されるものも作ってみました。

実際のエディターだとEnterキーを押した際に自動でインデントを挿入してくれるので、改行コード後の連続の空白は一度に表示するようにしています。

## 4. ドット絵を表示するやーつ
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581889/59b1a382-5dbf-b55b-e757-07d2606817b9.gif">
出力メッセージに色を付けられるということだったので、ドット絵を出力するものも作ってみました。
用意した画像を読み込み1ピクセルずつ色を取得し、その色の`■`を表示するようにしています。

# 参考
[カフェでプログラミングしてる風（でも何もやってない）Java（クソ）コード](https://qiita.com/3S_Laboo/items/660883a0184dabaea65b)
[Python Windows10 において Console 出力に色を付ける](https://qiita.com/BlueSilverCat/items/96b42996879217d9efac)
[Pythonで画像のピクセル操作](https://qiita.com/zaburo/items/0b9db87d0a52191b164b)
dipという上場企業での開発研修を終えて。【総評】

## 自己紹介
初めまして。dip株式会社、21新卒の城戸健汰です。
現在dip株式会社でスマートフォンアプリ開発チームのiOSの担当をしています。

今回は、僕が2021年の４月に入社して行った開発研修についてお話をしていきます。

今まで19新卒の先輩方の開発研修の[記事](https://developer.dip-net.co.jp/entry/2020/04/14/%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E4%B8%80%E5%B9%B4%E7%9B%AE%E3%81%AE%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB)・20新卒の先輩方の開発研修の[記事](https://dippeople.dip-net.jp/9844/)はあったのですが、今年の21新卒の開発研修に関しての記事がまだなかったので、僕が僕の視点から記事を書かせていただきます。

この記事では特に「新人が開発研修を通して、どのような部分で大きく成長したのか」を詳しくお話ししていきます。

## どんな研修だったのか

まず簡単に研修の概要を簡単に説明していきます。

> 期間:2ヶ月
> 作ったもの:辞書のようなslackアプリ
> 開発人数:5人(新卒入社した５人)
> フェーズ:要件定義~実装~~~ローンチ~~

結果としては２ヶ月間でプロダクトはローンチすることはできませんでした。
もの自体は殆どできていたのですが、デプロイ周りで苦戦し、時間制限が来てしまいした。


## 自分的に最も成長した点

社内での報告会で「開発研修で成長したこと」を挙げた際には

- コミュニケーション能力
- 技術力
- 責任感を持つこと
- 市場/顧客の理解

が成長した。と報告をしました。
ですが僕が本記事で一番伝えたいことは

**想像力が大きく身についた**

ということです。

ここでいう「想像力」を少しカテゴリ分けし、細分化します。

- 対人関係における想像力
- プロジェクト・時間に対しての想像力

大きく分けてこの２つが成長したと考えています。

### 対人関係における想像力
対人関係における想像力とは、「コミュニケーション能力」とほとんど同意義かなと思います。

対人関係における想像力とは具体的に、相手の立場や人柄やタイミングやお気持ちなどを「想像」する力だと考えます。

> 先輩方一人一人がどのような立場で動いているのか
その人にその質問をするのが正しいのか
その立場の方に何かを伝えたいときはどのような情報が必要そうなのか
その人柄の人にはどんな話し方で話せばいいのか
これをしたら誰が困るのか、誰が喜ぶのか
今の自分の理解度で質問をしても相手の時間の無駄にならないか、もっと現状できることはないのか
今自分が何をしてるのか先輩上司に知っておいてもらわなくて大丈夫なのか
この提案をあの人にするときはどんな情報があれば納得してもらえそうなのか、どんな聞き方で聞くと柔らかいのか
この言い方をして同期はやる気が無くならないか、どう伝えればメンバーの士気が上がるのか

ざっと上げると、上記のようなことを想像できるようになりました。(考えればもっともっと出てきます...)


### プロジェクト・時間に対しての想像力
また、プロジェクト・時間における想像力とは

> このままの進捗具合で進んで期限に間に合うのか
少し早いタイミングで遅れるかも知れない報告をした方がいいんじゃないか
今現状やっている部分と未来にやる予定のこの部分は繋がっているから一緒にやっちゃった方が効率がいいんじゃないか
A君のやっている部分とB君の行っている部分は重なっているから一緒に会話しながらやった方がコンフリしないんじゃないか

などを想像できるようになりました。
書いてて思いましたが、「対人関係における想像力」と「プロジェクト・時間に対しての想像力」って結構似てますね。
「人」軸か、「プロジェクト」「時間」軸かどうかなだけで割とこれらは通じていますね。

## 開発研修を通して「よかった点」・「悪かった点」
それでは開発研修の総評的な「よかった点」「悪かった点」をお話ししていきます。

### よかった点

- 結局研修期間内に作りあげられなかったものの、7月に入り少し時間をいただき、テストローンチすることができた。
- 新卒同士の仲がかなり深まった。
- 開発研修ではリーダーを務めさせていただいたおかげで、周りを見れる広い視点も身に付けれた。
- 実際の実装もゴリゴリ行えたので楽しかった。
- 要件定義でかなり時間を使ったので、ユーザーの視点や「なぜ作るのか」や、一つ一つの工程で「なぜ」を考えられることができた。

### 悪かった点

- ちょっと辛かった
    - 時間がタイトだったので毎日全力投球。
    - 時間がタイトなのにわからないことだらけで調査時間などもかなり必要だった。
    - 時間がタイトなのにメンバー５人の総意をしっかりまとめて先輩方に持っていかなければならなかった。
    - 時間がタイトなのに色々な資料作成をして情報を５人でしっかりまとめて頑張らねばならなかった。

これ書きながら笑ってますw

## まとめ

まとめです。
ちょっと辛かった点で色々上げましたが、この経験があるおかげで自分のキャパがかなり広がったように思います。
どれだけ並行タスクがあっても大体のことがしっかり時間内に完了させることができるようになったと思います。(無理そうだったら色々相談できる力もつきましたw)

dipでの開発研修を行った2ヶ月間は自分の人生の中でも本当に濃い２ヶ月だったと思います。
(開発研修を終えた今でもかなり濃い時間を過ごせていますが。)

自分や21新卒を大きく成長させてくださった先輩方には本当に感謝です。ありがとうございました。

以上が、僕が開発研修を終えた総評です。ここまで見ていただきありがとうございました。
この記事が誰かのためになれば幸いです。
Webの勉強はじめてみた その10 ～JavaScriptで診断ゲーム編1～

N予備校の「プログラミング入門 Webアプリ」を受講しています。
今回は第1章15節と16節です。

<h2>用語</h2>
:::note
<ul>
<li>モックアップ: 機能の作りこみをせず、見た目だけを作ったもの</li>
<li>JS Doc: インターフェースの定義を明示したコメント形式</li>
</ul>
:::

紙に書いたものを「ペーパーモックアップ」というらしい。
ツールも色々あるけれど、個人で使うだけならちょっと重いかも。

```javascript
/**
*   名前の文字列を渡すと診断結果を返す関数
*   @param {string} userName ユーザーの名前
*   @return {string} 診断結果
*/
function assessment(userName){
    //TODO 診断処理を実装する
    return '';
}
```
JSDoc形式、初めて知りましたが、これは忘れずに使っていきたい。

<h2>正規表現</h2>
正直覚えられる気がしない。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions

今回使ったのは`replace`
`/\{userName\}/g`
エスケープシーケンスもあって面食らってしまった。
`/`から`/`までが検索する範囲。
`g`がグローバル検索を行う、パラメータ？になるのかな。

使っていれば覚えられるのだろうか。

<h2>診断ゲーム</h2>
名前をテキストボックスに入力してその人の「いいところ」を診断するというアプリ。

```javascript
'use strict';
//診断結果
const answers = [
    '{userName}のいいところは声です。{userName}の特徴的な声は皆を惹きつけ、心に残ります。',
    '{userName}のいいところはまなざしです。{userName}に見つめられた人は、気になって仕方がないでしょう。',
    '{userName}のいいところは情熱です。{userName}の情熱に周りの人は感化されます。',
    '{userName}のいいところは厳しさです。{userName}の厳しさがものごとをいつも成功に導きます。',
    '{userName}のいいところは知識です。博識な{userName}を多くの人が頼りにしています。',
    '{userName}のいいところはユニークさです。{userName}だけのその特徴が皆を楽しくさせます。',
    '{userName}のいいところは用心深さです。{userName}の洞察に、多くの人が助けられます。',
    '{userName}のいいところは見た目です。内側から溢れ出る{userName}の良さに皆が気を惹かれます。',
    '{userName}のいいところは決断力です。{userName}がする決断にいつも助けられる人がいます。',
    '{userName}のいいところは思いやりです。{userName}に気をかけてもらった多くの人が感謝しています。',
    '{userName}のいいところは感受性です。{userName}が感じたことに皆が共感し、わかりあうことができます。',
    '{userName}のいいところは節度です。強引すぎない{userName}の考えに皆が感謝しています。',
    '{userName}のいいところは好奇心です。新しいことに向かっていく{userName}の心構えが多くの人に魅力的に映ります。',
    '{userName}のいいところは気配りです。{userName}の配慮が多くの人を救っています。',
    '{userName}のいいところはその全てです。ありのままの{userName}自身がいいところなのです。',
    '{userName}のいいところは自制心です。やばいと思ったときにしっかりと衝動を抑えられる{userName}が皆から評価されています。'
];

/**
*   名前の文字列を渡すと診断結果を返す関数
*   @param {string} userName ユーザーの名前
*   @return {string} 診断結果
*/
function assessment(userName){
    //TODO 診断処理を実装する
    //入力された全文字のコード番号を取得し、和を求める
    let sumOfCharCode = 0;
    for(let i = 0; i < userName.length; i++){
        sumOfCharCode += userName.charCodeAt(i);
    }
    //文字のコード番号の合計を回答の数で和って添字の数値を求める
    const index = sumOfCharCode % answers.length;
    //const result = answers[index];
    let result = answers[index];
    //{userName} を入力された文字列に書き換える
    //正規表現
    result = result.replace(/\{userName\}/g, userName);
    //診断結果
    return result;
}
/* 
console.log(assessment('太郎'));
console.log(assessment('次郎'));
console.log(assessment('太郎'));
*/
/*
console.assert(
    assessment('太郎') === 
    '太郎のいいところは決断力です。太郎がする決断にいつも助けられる人がいます。',
    '診断結果の文言の特定の部分を名前に置き換える処理が正しくありません。'
    );
*/
console.assert(
    assessment('太郎') === assessment('太郎'),    
    '入力が同じ名前なら同じ診断結果を出力する処理が正しくありません。'
);
```

これってTwitterの診断メーカーみたいなやつかなーと思いつつ。
文字のコード番号を使ったロジックには感動すら覚える。
色々応用もできそうな気がします。

<h2>まとめ</h2>
まだ途中ですが、完成まではあと2節。
といってもツイートボタン以外はこの後の流れはなんとなくわかるので、今回ほど苦労はないかなと。がんばります。
[Jenkins]Macを常時稼働させておく方法

# はじめに
Jenkinsサーバを常時稼働しておくにはスリープにさせないことが必要です。
Automator.app作成の忘却録。

## Automator.appの作成
`Applications`の中に`Automator.app`を使います。
アプリケーションを選んで選択
![ 2021-12-07 16.47.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022988/2f4a517e-18f2-6661-24fb-c40d65c753ca.png)
検索窓で`シェル`で検索し、`シェルスクリプトを実行`をダブルクリック
![ 2021-12-07 16.47.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022988/dd1578bd-1543-3f3b-19f9-daf9d6ead037.png)
コードは下記

```shell
nohup caffeinate -d
```
名前を決めて保存します。
![ 2021-12-07 16.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022988/415671c6-c769-883e-d3ee-af63e8dd9dda.png)

該当のAppをダブルクリックで実行します。
実行してると下記のようなマークがメニューに出ます。
![ 2021-12-07 17.00.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022988/78f554c6-028a-b779-4f99-fdb15e4cd568.png)

## 参考
https://ferret-plus.com/9963

https://blog.katsubemakito.net/linux/nohup

https://softantenna.com/blog/caffeinate/
Twitter Proアカウントで表示されるプロモーションボタンを非表示にする方法

Twitter Proアカウントでプロモーションするというボタンが表示されるようになりましたね。あれ、すごくウザいですよね。今回は、そのプロモーションボタンをCSSを使って見えなくする方法を紹介したいと思います。

![Twitter_logo_blue_1280x800.png](https://louiscnovel.files.wordpress.com/2023/01/twitter_logo_blue_1280x800.png?w=1024)

##■環境
・Windows11 Pro
・Google Chrome

##■ダウンロード
以下の拡張機能をダウンロードしておいて下さい。
[Stylus - Chrome ウェブストア](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne)

##■実践編
###１：[Twitterのホーム画面](https://twitter.com/home)に移動する
###２：拡張機能「Stylus」のアイコンを左クリック
###３：次のスタイルを書くの下のところにあるリンク「twitter.comこのURL」をクリック
###４：以下のCSSをコピーして貼り付ける。

```
/*
デフォルトテーマ用CSS
「プロモーションする」を非表示
*/
a.css-4rbku5.css-18t94o4.css-1dbjc4n.r-1niwhzg.r-1ets6dv.r-sdzlij.r-1phboty.r-rs99b7.r-1loqt21.r-1s2bzr4.r-2yi16.r-1qi8awa.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr {
    display: none;
}

/*
ダークブルー・ブラックテーマ用CSS
「プロモーションする」を非表示
*/
a.css-4rbku5.css-18t94o4.css-1dbjc4n.r-1niwhzg.r-sdzlij.r-1phboty.r-rs99b7.r-1loqt21.r-1s2bzr4.r-2yi16.r-1qi8awa.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr {
    display: none;
}

/* ツイートのアナリティクスのプロモーションボタンを非表示 */
div.css-1dbjc4n.r-1habvwh.r-14lw9ot.r-1ets6dv.r-1phboty.r-5kkj8d.r-1p0dtai.r-18u37iz.r-1d2f490.r-494qqr.r-gtdqiz{
    display: none;
}

/* ダークブルーテーマ用CSS ツイートのアナリティクスのプロモーションボタンを非表示 */
div.css-1dbjc4n.r-1habvwh.r-yfoy6g.r-wrkyx5.r-1phboty.r-5kkj8d.r-1p0dtai.r-18u37iz.r-1d2f490.r-494qqr.r-gtdqiz{
    display: none;
}

/* ブラックテーマ用CSS　ツイートのアナリティクスのプロモーションボタンを非表示 */
div.css-1dbjc4n.r-1habvwh.r-kemksi.r-1kqtdi0.r-1phboty.r-5kkj8d.r-1p0dtai.r-18u37iz.r-1d2f490.r-494qqr.r-gtdqiz{
    display: none;
}

/* ツイートの下に表示されるプロモーションボタンを非表示 */
a.css-4rbku5.css-18t94o4.css-1dbjc4n.r-42olwf.r-sdzlij.r-1phboty.r-rs99b7.r-1loqt21.r-c8eef1.r-2yi16.r-1qi8awa.r-1ny4l3l.r-ymttw5.r-o7ynqc.r-6416eg.r-lrvibr{
    display: none;   
}
```

###５：一番下の適用先のURLをhttps://twitter.com/ にする
###６：左上にある名前を「Twitter Proでプロモーションボタンを非表示」にする
###７：サイドバーにある保存ボタンをクリックする
![スクリーンショット 2021-12-07 171500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652436/587b780d-f8cd-1d37-2eb6-b577c74b7bb2.png)

###８：[Twitter](https://twitter.com/home)に移動して、ちゃんとプロモーションボタンが非表示になっていることを確認して終了する

##■参照
[【Twitter Pro】「プロモーションする」を非表示にする方法。CSSを使ってみよう！ | ナポリタン寿司のPC日記](https://www.naporitansushi.com/promotion-hide/)
入社一か月の新入社員がagoraで楽しいオンラインオークションイベントを考えてみた！

#**はじめに**

皆さん、こんにちは。
IT系の会社に入り、1か月が経ちました。
今回はagoraを使ったオンラインオークションイベントを思いつきました！
agoraのオンラインオークションイベントは、たくさんのメリットがありますのでご紹介します。


#**オンラインオークションイベント**
主催者と出品者が基本的に配信をして、視聴者はリアルタイムでオークションに入札可能なシステム

メリットとして
・コロナ禍で密にならずにイベントが開催できる。
・通常オークションイベントでは会場が狭く、代表者のみが電話をしながら参加するが、その必要がない。
・オンラインのためいつでもどこでも参加できる。
・参加チケット有無もカスタマイズ可能で、一般の人でも気軽に参加できる。
・海外からの商品は輸入関税がかからずに出品できる。
・出品物を無理に一か所に集めなくてもよいので輸送料もかからないし、セキュリティ観点からも安心。
等があげられます！

世界のコレクターたちが、様々な世界の名作を落札する瞬間を目にすることができます！
超高級でなければ、自分も札を挙げて参加できるかもしれません！
入札応援機能などもつければ、落札までのやり取りも盛り上がると思います！

![img_1e659fd4f6af349dc0845f128e1d40e3232285.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348684/4224711d-3779-ce59-ed3d-1ee50e4008a2.jpeg)
>出典　世界の名作が集まる「サザビーズ」オークションの知られざる裏側　https://diamond.jp/articles/-/214679  </span>

ただし、このイベントの問題としては
①リアルタイム配信でないと入札するオークションシステムにならない
②イベントなので落札した人にコメントを求めたりしたい
③発言者自体は少数だが、オークション配信システムへと独自でカスタマイズする必要がある
等があげられます。

そこで登場するのが**agora**です！


なぜagoraをなのか？という方のために簡単なagoraの説明をさせていただきます。
日本の代理店であるVCUBE社のサイトから引用しますと、

**Agoraとは**
>Agora（agora io sdk）は、スマートフォン・PCアプリやWebサイトに、カスタマイズしたビデオ・音声通話やライブ配信を簡単に実装できるSDKで、動画や音声配信・通話の可能性が広がります。
APIと開発ツール群も多彩に取り揃えています。
さらに利用分数に応じた従量課金のみの費用でかつ、開発期間中は無料なので、WebRTCやCDNを使って自社構築より安価にはじめられます。
豊富なAPIやサンプルコードで、iOS・Android・Web・Windows・Mac・Unity・Electronにも対応し、短期間で開発できます。
また、サーバーの構築・運用が不要なため、開発・運用コストの削減にも役立ちます。

とのことです。
ふむふむ、、、
わかりやすいライブ配信比較表・agoraの特徴もありましたので引用させていただきます。
![スクリーンショット 2021-12-07 101733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348684/2671e00a-d530-1b14-e433-113cfd6e34f8.png)
![スクリーンショット 2021-12-07 152727.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348684/918b8418-e99e-4e02-0b57-fdd760c0a4ba.png)

特長をまとめますと
①超低遅延でリアルタイム配信可能
(→オークションの根幹である刻一刻と変わる値段のやり取りが可能になる。)

②双方向通話可能
(→出品者と主催者が離れていても配信可能、かつ勝ち取った参加者のコメントなども配信可能)

③パケットロス耐性が高く、大事なところで止まる可能性が低い
(→大切なオークションのやり取りが途切れにくい)

④独自のカスタマイズがしやすい
(→オークションシステムを実装する等)

オンラインオークションイベントにすごくマッチしています！
イベントを開催するのに使うのはagoraで決まりですね！

**参考サイト**

https://jp.vcube.com/service/agora



#**実装の考え方**
agoraには多様なSDKが用意されており、サンプルも豊富です。
Web/iOS/Androidアプリがそれぞれ実装できます。

https://docs.agora.io

サンプルで試して、始めるとなれば日本サポートもあるので、導入まで簡単にできそうです。

あとはデザインでサイトに高級感をもたらすことができるように頑張りたいですね。



#**最後に**
この記事ではAgoraを活用したオンラインオークションイベントについて述べました。
調べてみると最高級のサザビースオークションでもオンラインでイベントを行っているようです。
実装までは着手できませんでしたが、導入まで簡単なので、日本のデパート等でも取り入れていっていただきたいです！
また機会がありましたらagoraのアイディアについてまた記事を書きます。
フロントエンドエンジニアへ！スパゲッティ解消法！ (自分なりのNote）



1. ビューとロジックは分けます
2. ロジックから書きます
    - よくやりがちなのが、実装をビューから書き始めること。
    - まずはモデルのCRUDやそれを操作(フィルター、ソートetc)するメソッドを定義します
3. それをビュー側が使うようにします


## (2)で定義するクラスとその使い方

class Table {...} // tableを操作するクラス
class TableColumn {...} // columnを司るクラス
class TableRow {...}

class TableColumnText extends TableColumn {...}
class TableColumnNumber extends TableColumn {...}
class TableColumnDate extends TableColumn {...}
class TableColumnBoolean extends TableColumn {...}

// ロジックから書く

const table = new Table(data)

table.getData // {...}
const dataFiltered = table.where('"C" == "活寿会_新宿" || "C" ==  "活寿会_渋谷"')
// ※列追加時にアルファベットが割り当てられる。Cは3列目


みたいな使い方ができるjsのライブラリを探してみる


★★注意★★

- Viewのライブラリが軸となってはいけない。
- 軸はデータであり、Viewはあくまでそれを表現するための器にすぎない。
- Viewライブラリのあらゆる操作から、データを変更するメソッドを呼んであげる(以下例)

例)
1. クリックやキーボードのイベントでn列のフィルターをXXXとXXXで行う
2. 変更されたデータを反映するために、ビュー側(dataGridなど)に対してリフレッシュ(=再描画)してあげる




## その他の表現の提案

table.columns[4] // <TableColumnText>
table.columns[4].filterBy(['活寿会_新宿', '活寿会_渋谷'])
table.setFilterWith('"C" == "活寿会_新宿" || "C" ==  "活寿会_渋谷"')

## jsの落とし穴

- dataがArrayのときdata.map()はdataが書き換えられるので注意
- プリミティブではないデータ型(ArrayやObjectなど)は参照渡しなので、代入先を変更すると代入元も変更される。これを避けるにはディープコピーやシャドウコピーをする必要がある `JSON.parse(JSON.stringify(dataTable))`

useStateでprivateにしてるようで
jsはmapなど参照渡しで代入する前から変数が書き換えられているから、privateの意味なし！！！
[ServiceNow]【Rome】ダッシュボードの表示崩れ

今日はRomeへVerUpしての不具合事象について書きます。

#ダッシュボードの表示崩れ
日本語かつitil権限（≒admin権限でない）でダッシュボードを表示すると、一部表示が崩れます。

##Version
- Rome

##条件
- 日本語
- itil権限（≒admin権限でない）

##エビデンス
![ダッシュボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636124/31c1f960-2b65-0701-3c7c-df8959414c0c.png)

画像のとおり所有者の表示が枠から溢れます。
ServiceNowのバグでしょうか？
VMware Workstation Player で SLIC な Windows7 の試験


どうも、毎回忘れよるけ、忘備録。
VMware の BIOS を SLIC 対応に書き換えた成果物を以下のテキストファイルに書き込んでインスコする。

```text:*.vmx
bios440.fileName = "C:\Program Files (x86)\VMware\VMware Player\x64\SLIC_314.ROM"
```
Vercelの料金プランを理解する。

## 概要

現在Vecelの料金体制について調べており、自分用にまとめたのでシェアします。

公式サイトの[Limits](https://vercel.com/docs/concepts/limits/overview#serverless-function-size)を参考にこの記事を書いています。

## この記事の目的

- Vecelの料金プランを理解する。
- 情報共有すると同時に、理解に誤りが無いかの確認。

※ 私の認識が間違っていた場合、コメント欄にてご指摘いただけると助かります🙇

## 解決したい課題

不安を払拭する。（読者の方も、私自身も。）

- 莫大な料金がかからないか…？
- 無料プランのままだと、運用したサービスが止まってしまわないか？

## プラン別一覧表

### 基本的な制限

|    |  Hobby  |  Pro  |
| :---- | :----: | :----: |
|  商用利用  |  Ｘ  |  O  |
| デプロイ回数/日  |  100  |  3000  |
|  CLIからのデプロイ回数/週  |  2000  |  2000  |
|  作成可能なサーバーレス関数の数  |  12  |  制限無し  |
|  サーバーレス関数のタイムアウト(秒)  |  5  |  30  |
|  チームメンバー数  |  -  |  10  |
|  接続可能なGithubリポジトリ数  |  3  |  10  |

#### 商用利用について

ホビープランは、商用利用を禁止されているようです。

公式サイトの[Commercial Usage](https://vercel.com/docs/concepts/limits/fair-use-policy#commercial-usage)に記載があります。

- 金銭的な利益を得る目的で使用する場合
- サイト訪問者に支払いを要求する場合
- サイトを作成して支払いを受ける場合
- アフィリエイトリンクが、主な目的な場合。

#### デプロイ回数/日

Githubリポジトリにプッシュして、自動的にVecelにデプロイできる一日の回数。

#### CLIからのデプロイ回数/週

[Vecel CLI](https://vercel.com/docs/cli) を使用して、プロジェクトをデプロイする回数。

#### 作成可能なサーバーレス関数の数 

pages/apiディレクトリに に記載するサーバーレス関数の数([Serverless Functions](https://vercel.com/docs/concepts/functions/serverless-functions))。

#### サーバーレス関数のタイムアウト(秒) 

pages/apiディレクトリに に記載するサーバーレス関数においての、実行時間の制限([Serverless Functions](https://vercel.com/docs/concepts/functions/serverless-functions))。

#### チームメンバー数

チームメンバーにてVecelのプロジェクトを共有できる人数。
Hobbyでは、チームプロジェクトの作成はできません。
Pro版は作成できますが、一人につき20ドル発生します。

#### 接続可能なGithubリポジトリ数

VecelとGithubのリポジトリを連携できるリポジトリの数。

### 月単位での制限

#### 基本

|    |  Hobby  |  Pro  |
| :---- | :----: | :----: |
|  帯域幅(トラフィック) |  100GB  |  1TB  |
| サーバーレス関数の実行時間 |  100GB/時間  |  1000GB/時間  |
| 画像最適化ファイル数 |  1000ファイル  |  5000ファイル  |
| ビルド時間 |  100時間  |  400時間  |

### 制限の超過時

|    |  Pro  |
| :---- | :----: |
|  帯域幅 (トラフィック)|  55ドル（100GB 追加）  |
| サーバーレス関数の実行時間 | 55ドル（100GB/時間 追加）  |
| 画像最適化ファイル数 |  9ドル （1000ファイル 追加）  |

##### 帯域幅(トラフィック)

閲覧及び書き込みの、データ転送量。

##### サーバーレス関数の実行時間

pages/apiディレクトリに に記載するサーバーレス関数の実行時間([Serverless Functions](https://vercel.com/docs/concepts/functions/serverless-functions))。

##### 画像最適化ファイル数

以下のようなソースコードで最適化している、画像のファイル数制限。

```javascript
import Image from 'next/image';

<Image
  src="/images/vercel-logo.png"
  alt="Picture of a triangle"
  width={500}
  height={500}
/>
```

[](https://vercel.com/docs/concepts/next.js/image-optimization#)

##### ビルド時間

Vecel上で、ソースコードからビルドする時間の制限。


### Pro版のみ追加料金にて、利用できるサービス

#### Analytics

Vecel上でのアナリティクスを利用するには、基本料金として10ドル発生するようです。

[Vercel | Analytics](https://vercel.com/docs/concepts/analytics#pricing)

#### Password Protection

サイト自体をパスワードで保護する場合、追加で150ドル/月発生します。

[Vercel | Password Protection](https://vercel.com/docs/concepts/projects/overview#password-protection)

### その他の項目

ここからはプラン（Hobby/Pro）に関わらず、制限がある項目です。長期的にサイトを運営していく上で、影響がありそうなところをピックアップしています。

#### ビルド時の最大時間

４５分が最大のようです。それ以上が経過した場合は、強制的に中断される。

#### ファイル数の上限

|    |  Hobby/Pro  |
| :---- | :----: |
|  ソースコード|  15000ファイルまで  |
| ビルド後のファイル | 16000ファイルまで |


## おわりに

Vecelの料金プランの違いは、商用利用の有無のみかと勝手に認識していましたが、結構大きな差があるようです。

今後、気がついた点があれば、追記していきたいと思います。

重ね重ねですが、誤りがあればご指摘いただけると有り難いです。
LaravelでJSONのValidationを行う簡単な方法

## 目的

JavaScriptのSPAアプリからPOSTでJSONをサーバーに送るときに、そのJSONの内容でCRUDを行う前に確認する。

## 試して失敗したこと

Illuminate\Http\Requestのvalidate関数で下記の通りやってみたら、

```php
$validate = $request->validate([
            "title" => ["required", "unique:posts"],
            "contents" => ["required"],
        ]);

```

JavaScriptアプリ側にValidationが失敗した時に、自動でHTMLのページが送られていたようで、Errorの内容をJSONにて送ることができなくなっていたのです。

## 解決法

Illuminate\Support\Facades\Validatorを使い、自前でValidatorを作ることにします。

```php
$validator = Validator::make($request->all(), [
            "title" => ["required", "unique:posts"],
            "contents" => ["required"],
        ]);

```

そして、失敗した理由などをJavaScriptアプリにこうやって返せるわけ。
Error Codeも400にすることでアプリ側に何らかのエラーが発生したことが伝わります（社内バックオフィスからマサカリが飛んできたので追記）

```php

$validator = Validator::make($request->all(), [
            "title" => ["required", "unique:posts"],
            "contents" => ["required"],
        ]);

        if ($validator->fails()) {
            return response()->json(["results" => "failed", "errors" => $validator->errors()], 400);
        }

```

JavaScriptではこういうObjectに変換され、UXに活かせる。

![スクリーンショット 2021-12-07 17.39.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344956/30d6aed6-7aa2-5bc6-ad2d-46acea611120.png)


## まとめ

ということで、自前でValidatorを作ることで、LaravelのValidation機能を利用しつつ、特殊な用途に合わせてJSONを返すこともできるのです。

LaravelはSPAアプリ開発においては非常に上等だということがわかりますね。
[SwiftUI] overlayの表示or非表示の判別

ButtonにBorderをつけるかの処理


```
struct ContentView: View {
    @State var showOverlay = false
    
    var body: some View {
        Button(action: { showOverlay.toggle() }) {
            Text("Hello World")
                .overlay(
                    showOverlay ?
                    RoundedRectangle(cornerRadius: 10)
                       .stroke(Color.black, lineWidth:1)
                    : nil)
        }
    }
}
```
【Automation Anywhere】Automation360、A360、A2019、V11、V10って何のこと？

こんにちは！

Automation Anywhere の開発関連の記事を見ていると、「V11」とか、「A2019」、「Automation360」、「A360」といった言葉が頻繁に出てきます。

みんな当たり前のように使っている言葉ですが、知らない人から見ると「なに？　宇宙語？」ってなると思うので、解説します。

#V11／A2019／Automation360／A360とはこれのことだ！

両者の違いは、開発画面を見れば一発です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/957d7763-0e86-cc18-9554-2acc0f96c390.png)

V11は、オンプレを前提としたリッチクライアント型の旧バージョンです。
現在、販売は停止となっていますが、まだまだ使っている人も多いはず。
（さらに古いV10やV9というバージョンもあるのですが、こちらはスクショが手に入りませんでした。）

A2019 / Automation360 / A360は、Webベースのクラウドネイティブ（オンプレ版の提供もあり）な最新バージョンです。

V11系統と、A2019 / Automation360 / A360 とで開発のしかたはガラリと変わり、アーキテクチャも大きく変更になっています。
Automation Anywhereについて調べ物をするときは、その記事がV11系統についての記事なのか、A2019 / Automation360 / A360 に関する記事なのかをきちんと認識した上で調べる必要があります。

#A2019 と Automation360 と A360 の違いは？！

これもめちゃくちゃよく聞かれるんですが、ズバリ　**全部同じ**　です。

以下は、知っていてもおそらく開発の役にはまったく立たない情報ですが、興味のある人のために歴史を記しておきます。

## 最初はA2019として登場

より正確に言うと、Automation Anywhereがオンプレ型のV11からWebベース・クラウドネイティブに大きく製品を変更したときに、当時の最新バージョン最初についた名称が「A2019」でした。
（このバージョンが発表になったのが2019年だったからです）

## 2021年6月に、Automation360 に名称変更

発表年の2019年が明けて2020年になったあたりから、「A2019って、今年はA2020って名前に変わるんですか？」みたいな問い合わせがいろんなところで出るようになりました。
（まぁ、当然の結果といえば当然の結果です）

そんなわけで2021年の6月に、A2019は「Automation360」に名称変更をしました。

## A2019とAutomation360は同じ？　違う？

ややこしいのは、V11からA2019になった際、A2019はクラウドネイティブということもあり、当初はかなり頻繁にバージョンアップをしていました。A2019.xx という形で、xx部分の数字が１ずつ増えていく形で、マイナーなバージョンチェンジを繰り返していたのですが、A2019からAutomation360に名称変更した6月にもそのマイナーなバージョンチェンジを伴っていました。

正式なバージョン番号は忘れましたが、A2019.19 →　Automation360.20 になったというようなイメージです。

なので、A2019とAutomation360に変わったときに違いがなかったのか？　と言われると、あったことはあったんですが、それはあくまでもマイナーなバージョンアップとしての変更であって、V11からA2019になったときのような大幅な製品変更ではないということです。

## 正式名称はAutomation360だけど、ついついA360って言っちゃう

そんなAutomation360、メーカー公称の正式名称は「Automation360」なのですが、やはり長いアルファベットやカタカナは日本人のみならず、海外の人にも言いにくいようです。

そんなわけで、Automation360のユーザーや、たまに中の人でも（ぎくっ・・・自分のことです）うっかり「A360」って言っちゃうことがあります。

SNSやブログなど、Automation Anywhere の正式なマーケチェックを経ずに公開される記事などでは、A360という名称がけっこう当たり前に使われている場合もあります。

# 情報検索時のコツ

以上の説明で、Automation Anywhereの製品には大きく分けて、以下の２つのバージョンがあることがわかってもらえたかと思います。

- V11　- オンプレミスを前提としたリッチクライアント型の旧バージョン（もっと古いV10やV9というバージョンもある）
- A2019 / Automation360 / A360 - クラウドネイティブな、Webベースの最新バージョン

Automation Anywhereに関する開発情報を検索するときは、自分が知りたいのはどちらのバージョンの話で、見ている情報はどちらのバージョンに関する話なのかをきちんと押さえておく必要があります。

その際、最新バージョンに関しては「A2019」「Automation360」「A360」と3つの呼称の揺れがあるので、それを踏まえて検索をするといいでしょう。
例えば、「Excel操作 Automation360」で見つからなかったら、「Excel操作 A360」や「Excel操作 A2019」でも検索してみるとかです。

#以上！

いかがでしたか？

今回はAutomation AnywhereのRPAの主要バージョンの２つ、旧バージョンのV11と、最新バージョンのA2019 / Automation360 / A360 について解説をしました。

今後もAutomation Anywhereに関して、開発に役に立つ情報を発信していきたいと思います。
「こんな記事を書いてほしい！」「ここがわからない！」の質問・ご意見・リクエストは、記事へのコメントやTwitterなどでお気軽にいただければ幸いです。
GHC Source Pluginによるシンボルの削除

# 目的

Haskellのパッケージに含まれるあるシンボルをパッケージに外に見せたくない場合に、
逆に見せたいシンボルを列挙して対応していませんか？

今回紹介する方法はGHC Source Pluginを使ってシンボルをパッケージ外に出さない方法を紹介します。

# 動機の確認

シンボルをパッケージ外に出さない方法を紹介する前になぜそのようなことをやりたいのか確認しておきます。

C++の関数をHaskellで呼び出せるようにinline-c-cppでラッパを作りたい場合に基本的には外に見えるようにしたいが
`inline_c_ffi_適当な番号`というinline-c-cppの内部関数が生成されました。

inline-c-cppのtemplate haskellに渡すデータは次のようなファイルなのですが、

```Haskell
module モジュール名 where

関数1
関数2
関数3
```

template haskellによって次のような関数が生成されていました。

```Haskell
module モジュール名 where

関数1
inline_c_ffi_23232
関数2
inline_c_ffi_23233
関数3
inline_c_ffi_23234
```

生成する関数は数千に及んだため複数のファイルで`inline_c_ffi_適当な番号`の番号が衝突する問題が発生し、
すべて外に見えるようにするわけにはいかなくなりました。

下記のように列挙してもいいですが、コードも読みにくくなるので、GHC Source Pluginで隠すことにしました。

```Haskell
module モジュール名(
 関数1
 関数2
 関数3
) where

関数1
関数2
関数3
```

# やり方

今回修正するのは`desugar`というCore言語にする前の`typeCheckResultAction`というモジュールからエクスポートする関数を削除する方法で考えました。

`typeCheckResultAction`は`TcGblEnv`というトップレベルのモジュールを返す関数になっています。
そこからエクスポートしたくない関数を除外すれば完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15901/beb1da47-6c6a-5ea8-a438-3a70ba81ac2b.png)

次のようなコードになります。

```Haskell
{-# LANGUAGE CPP #-}

module GHC.NotExport.Plugin (plugin) where

#if MIN_VERSION_ghc(9,0,0)
import GHC.Driver.Plugins
import GHC.Types.Avail
import GHC.Types.Name
import GHC.Tc.Types
import GHC.Utils.Outputable
#else
import GhcPlugins
import Plugins
import TcRnTypes
import Avail
#endif

import Data.List (isPrefixOf)

plugin :: Plugin
plugin =
  defaultPlugin
    { typeCheckResultAction = notExportPlugins,
      pluginRecompile = purePlugin
    }

notExportPlugins cmdOptions modSummary env = do
  let updated_tcg_exports = filter (\v -> not (isPrefixOf "inline_c_ffi" ((showSDocUnsafe . ppr . nameOccName . availName) v))) $ tcg_exports env
  return env {tcg_exports = updated_tcg_exports}
```

このあとghc-optionsで上記のモジュールを渡せば`inline_c_ffi`で始まる関数がエクスポートされなくなります。

```cabal
 ghc-options:         -fplugin GHC.NotExport.Plugin
```

# まとめ

GHC Source Pluginを使って特定のパターンの関数をエクスポートしないようにするプラグインを作りました。hasktorchというlibtorchをラップしているライブラリで実際に使用中です。
FFmpegでよく使うオプション備忘録(windows)

# コマンドライン構文
ffmpeg -f [format] 入力 -f [format] 出力
出力は複数あってもいい

# muxとdemux
光通信関連でよく見るが、ffmpegのドキュメントでもよく出てくる。複数のストリームを一つにまとめるのが`mux`、逆が`demux`

# -list_devices true
カメラを一覧で出すときに使う

```sh:Windowsに接続したカメラ
ffmpeg -list_devices true -f dshow -i dummy
```

# -list_options true

```sh:出力例
ffmpeg -f dshow -list_options true -i video="USB Camera"
[dshow @ 00000299226cdf40] DirectShow video device options (from video devices)
[dshow @ 00000299226cdf40]  Pin "キャプチャ" (alternative pin name "0")
[dshow @ 00000299226cdf40]   vcodec=mjpeg  min s=1920x1080 fps=15 max s=1920x1080 fps=30
[dshow @ 00000299226cdf40]   pixel_format=yuyv422  min s=640x480 fps=15 max s=640x480 fps=30
[dshow @ 00000299226cdf40]  Pin "キャプチャ" (alternative pin name "1")
[dshow @ 00000299226cdf40]   vcodec=h264  min s=1920x1080 fps=15 max s=1920x1080 fps=30
```

ここでは`vcodec`に**mjpeg**と**h264**があり、このUSBカメラはh264のハードウェアエンコードに対応していることがわかる。

`pixel_format=yuyv422`は無圧縮のrawデータに対応していることを示している。422は色情報を意味する

444>420のように数字が大きいほど色再現性が高い。

 Pin "キャプチャ" の行は入力コーデックを選択するときに使う`-video_pin_name`の値を指定するときに使う

```sh:pinでコーデックを選択
ffprobe -f dshow -video_pin_name 1 -i video="USB Camera"
```

# -re || -readrate 1

ファイルをストリームするときとかに使う

ffmpegはCPUが可能な限り最大の速度で次のフレームを読み取ろうとするので、このオプションなしでストリームを作ると早送りされた動画みたいになる

```sh:sample.mp4を元のフレームレートでストリーミング
ffmpeg -re -i .\sample.mp4 -an -c:v hevc_qsv -f rtp rtp://localhost:6004
```

# stream_loop -1
一つのファイルを無限にループして処理する。指定しないと最後のフレームを処理してffmpegが終了する

```sh:sample.mp4をストリーミング
ffmpeg -re -stream_loop -1 -i .\sample.mp4 -an -c:v hevc_qsv -f rtp rtp://localhost:6004
```

# -rtbufsize
バッファサイズを指定する。バッファが大きいとストリーミングで遅延する。小さいと溢れてパケロスする。良い塩梅が難しい

```sh:2GBiバッファ
ffmpeg -rtbufsize 2048M -f dshow -i video="Game Capture 4K60 S+" -f rtp rtp://localhost:5004
```

# -r
入力および出力でのフレームレート指定。

```sh:10fpsのRTPストリーミング
ffmpeg -f dshow -i video="Game Capture 4K60 S+" -r 10　-f rtp rtp://localhost:5004
```

# -s
解像度指定。入力と出力両方で使える

```sh:FullHDストリーミング
ffmpeg -f dshow -i video="Game Capture 4K60 S+" -s 1920x1080 -c:v h264_nvenc -f rtp rtp://localhost:5004
```

# -f dshow
windowsで使うやつ。directshowのデバイスが扱える

# -codec:v (== -c:v) -codec:a (== -c:a)
出力用
指定したのコーデックにトランスパイルする。copyにするとそのまま出力される

```sh:Webカメラからの出力をトランスパイルせずにそのまま出力
ffmpeg -f dshow -i video="Game Capture 4K60 S+" -vcodec copy -an 
```

# -g
Iフレーム間のフレーム枚数が決まります。I/B/PフレームのまとまりをGOPといいます。シーンチェンジが少ない動画では値を大きくすると圧縮率があがります


# -sdp_file
SDPファイルを出力する。SDPファイルはストリームのコーデックやフレームレート等を相手に伝えるためのファイルです。WebRTCでも使われるやつですね。

```text:sdpサンプル
v=0
o=- 0 0 IN IP6 ::1
s=柔道トップ選手のトレーニングが過激すぎた
c=IN IP6 ::1
t=0 0
a=tool:libavformat 58.51.101
m=audio 3000 RTP/AVP 97
b=AS:768
a=rtpmap:97 PCMU/48000/2
```

```sh:example
ffmpeg -i .\Videos\Captures\sample.mp4  -vn -f rtp rtp://localhost:3000 -sdp_file sdp.file
```

# ffprobe
ストリーム入力のコーデックを調べるときに使う

```sh
ffprobe -i rtsp://192.168.80.242:8554/video

Input #0, rtsp, from 'rtsp://192.168.80.242:8554/video':
  Metadata:
    title           : Session streamed with GStreamer
    comment         : rtsp-server
  Duration: N/A, start: -0.033333, bitrate: N/A
    Stream #0:0: Video: h264 (High), yuvj420p(pc, smpte170m, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 60 fps, 60 tbr, 90k tbn, 120 tbc
```
【実用的？】バグりやすい手順を雑多に並べる記事

良く不具合の見つかる手順を公開するものである。
バグをいっぱい見つけたいQA、バグをなるべく作りたくないエンジニア、そんなみなさまの参考になれば幸いです。


## 端末操作系
「割り込み」を意識すると、バグが見つかりやすいです。


* タスクキル
* 各種アプリによる割り込み
* 電話着信、LINE着信、目覚まし、などなど
* 電波が切れる
    * 一度切って、復帰させたときに、正常に動作するか。端末の飛行機モードを利用すると検証しやすい
* 操作中に電池が切れる
* Wifiだけでなく、4G、5G回線で確認する
    * 太い通信を要するアプリだと(ゲームとか動画とか)、Wifi時と電話回線時で処理を分けてることが多いので、まれによくバグります 
* アプリ操作中に別アプリのpush通知が届く
* イヤホン接続時の挙動。無線、有線、それぞれ
* 音楽アプリを再生した状態で操作する
    * BGMがあるコンテンツだと、確認したほうが良い
* 端末放置でロックがかかったあとで、復帰後、正常にアプリが動くかどうか
* 端末の時間を変更する
* ブラウザで戻るボタンを押す(一部のAndroid端末にしか、戻るボタンはない。そのため、考慮が漏れやすい)
* 各種ボタンを連打する
* 色んなタイミングで、ピンチイン、ピンチアウト
* 色んなタイミングで、端末を横にしたり縦にしたり。レイアウト乱れ起きがちです。
* 色んなタイミングでホームボタンを押す
* 色んなタイミングで電源ボタンを押す
* 高速で画面をスクロール
    * たまにクラッシュバグとか引き起こします。
* ブラウザバック
* ブラウザリロード


## 文字入力系
ユーザネーム登録画面とか、コメント機能とかで確認したい手順達

* 入力しない or 大量の文字を入力する
* スペースだけ入力する。全角スペースは要注意。
* 絵文字
* 半角カナ。全角アルファベット。日頃、使わない文字なので要注意
* 数字だけ入力できる場合はマイナスや0や型の最大値など


## その他

* ボックスガチャなどのリセット系の処理で、一度も操作せずにリセット。
* ログアウト後に、別アカウントでログイン
* 複数端末で同一アカウントログイン
* アカウント削除処理後に、削除済みアカウントでログイン
* 購入系の処理で、複数端末で同一アイテムを同時に購入する
* EC系のサービスで在庫が残り1個のときに、複数端末で同一アイテムを同時に購入する


## 気づきにくい不具合
気づきにくいけど、致命的になりがちな不具合を挙げてみる。意識レベルを上げて発見しよう！

* 電池の減りが早い
* なぜかずっとGPSが作動している
* 端末が熱を帯びてしまう
* ずっと起動していると動作が重くなる

## おわりに
ホントはもっといろんなQAの意見を聞いて、項目を充実させたい。そして、QA業界の財産にしたい。
Terrafrom運用の細かい操作まとめ

## はじめに
Terraform cloudいいですね。tfstateのbackendをs3からTerrafrom cloudに移動している中でmoduleもリファクターとTerrafrom管理をしていなかったリソースのコード化も進めているのですが、そこで使用しているコマンドを備忘録的にまとめておきます。

## 環境
- terraform v1.0.8
- terraform-provider-aws v3.0.0

## リソースをimportする
すでにリソースをコンソールから作成済みだけど、その作成済みのリソースもterrafromで管理した場合にリソースの状態をtfstateにimportします。

- moduleを使っていないケース

```
resource "aws_ecr_repository" "hog" {
 省略
}

$ terraform import aws_ecr_repository.hog xxx-api
```

- moduleを使っているケース

```
module "ecr_module" {
 省略
}

$ terraform import module.ecr_module.aws_ecr_repository.hog xxx-api
```

- main.tfに複数リソースを定義しいる場合

importコマンドを別々に実行することでtfstateに追加していってくれます。

```
resource "aws_ecr_repository" "hog" {
 省略
}

resource "aws_lambda_function" "hog" {
省略
}


$ terraform import aws_ecr_repository.hog xxx-api
$ terraform import aws_lambda_function.hog xxx-function
```

## リソース名を変更する

リファクター、タイポなどを発見してリソース名を変更したい時にリソース名を変えただけで`terraform apply`すると**destroy**されてリソースが再作成されてしまします。
これではRDSなどは大問題になります。
そこで`terraform state mv`コマンドでtfstateのリソース名を修正します。


```
resource "aws_ecr_repository" "hog" {
 省略
}

// 上記を以下に変更

resource "aws_ecr_repository" "fuga" {
 省略
}
```

- moduleを使っていないケース

```
$ terraform state mv aws_ecr_repository.hog aws_ecr_repository.fuga
```

- moduleを使っているケース

```
module "ecr" {
 省略
}

$ terraform state mv module.ecr.aws_ecr_repository.hog module.ecr.aws_ecr_repository.fuga
```
PyLadies Japanの秋合宿に参加して色々学んだ話

#初めに

PyLadiesとはなんぞやという方は、kame-chanさんの以下記事見ていただけるとわかりやすいかと思います。

https://kamekokamekame.net/2021/2021-12-04-article.html


#合宿1日目

朝レンタルスペースに集まって、もくもく会開始。

やることを皆それぞれ宣言して作業していました。

![IMG_3567.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260056/e58cab6f-45c1-54d5-bc0f-921303c26829.jpeg)


その後切りのいいタイミングでお昼へ。
下記のお店に行きました。

https://www.hotpepper.jp/strJ001125657/yoyaku/?vos=othpporgzzzzx00000001


中華美味しかったです。

その後はまたもくもくしてました。

夜はケンタッキーとお酒と軽いおつまみ達でみんなで乾杯しつつ、自由にトークしてました。

![DSC_1235.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260056/87f277fb-decd-abf1-0650-59aa53c82af2.jpeg)
お酒可愛いかったです。

この夜はsugitaさんのお話が強すぎて、皆終始爆笑でした。
私も『今後もうしたくない！』と思ったことは手帳に書いていこうと思いまいた。笑



#合宿2日目

朝からまたレンタルスペースに出向き、昨日と同じくやること宣言をしてもくもく会開始。

![IMG_3588.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260056/7d790bd7-70ea-3b83-b262-939d04716de3.jpeg)

そして途中またお昼へ。
インドカレー食べました。美味しかったけどナンの下に隠れてたお米はちょっといらなかったです…笑
(sugitaさんのお写真お借りしました)

![2021-11-28-12-58-54-392.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260056/d466c7b0-e300-a651-78b1-513f5878ea0b.jpeg)

その後もくもくし、15:00頃に終了。
各自2日間かけてやったことや成果を発表しつつ、片付けして解散しました。
私は用事があり帰宅したのですが、その後何名かで打ち上げをしておりました。つよつよですね。


#合宿を振り返って


とても楽しかったですし、フルパワーで活躍してる方々がたくさんいて、私も頑張ろうって奮い立たせられました。
お仕事できる方々しかいなくて、もっとお話したかったです。
次皆さんに会うまでに自分の話力を鍛えようとも思えました！

余談ですが、本来もくもく会で読もうとしていた本と間違えて別の本を持ってきてしまい、完全に理想としていたもくもく会の成果は出せませんでした笑
ですが知り合いと本の読み合いをする約束をしており、その本が読破できたのでよかったかなと思います。
読んだ本は以下です。

https://allreviews.jp/isbn/439661683X

元IBMerの小林せかいさんが、誰とでも仕事をしたいと考える人達に向けて、仕事をする上で実践している工夫を紹介している本です。

目次のロジックツリーがわかりやすかったので、ロジックツリー作りが苦手な私にはそこも参考になりました。


という感じでとても実りのある濃い合宿でした。
またイベントがあればぜひ参加したいですし、PyLadiesでの発言ももっと増やしていきたいなと思います。
package.json exports.sass

豆知識（どこにも記事がなかった）


`package.json`で

```json
{
  "exports": {
    "./*": {
      "sass": "./src",
      ...
    }
  }
}
```

っと、`sass`用のルールを書ける。　書かない場合は、 `default`が適用される。

```sass
/* SASSでインポート　*/
@import "@my/lib/Component/styles.module.scss";
```
【C言語入門】初心者がprintfについて語ってみた

#はじめに
突然ですが皆さん、printfしてますか？
今日はC言語を初めて２カ月の私がもう一度初心に帰り、printf関数について理解を深めていきたいと思います。
#printf関数とは
C言語を使うとさまざまなことができるわけですが、計算ができても画面に表示されなければ結果が分かりません。そこで活躍するのがprintf関数です。<br>
printf関数は結果を書式化して表示する関数であり、C言語を勉強するうえで一番最初に目にする関数なのではないでしょうか。<br><br>では早速、まずは基本的な文法からおさらいしていきましょう！
#とりあえず表示してみる
```C:print
printf("Hello World!!");
```
このように文字の並びを表示できるわけです。すごいですね。<br><br>続いて簡単な演算もやってみましょう。

```C:calculation
printf("%d", 2 + 3);
```
簡単ですね。「5」と表示されます。<br>

#printf関数の呼び出しと表示
printf関数は書式化して表示をする関数でしたが、その構造はどうなっているのでしょうか。<br>


先ほどの演算をもう一度見てみましょう。

```C:calculation
printf("%d", 2 + 3);
```

<font color="Red">printf</font> という関数呼び出しから始まり、後ろの()に中に引数が与えられています。引数が２つ以上あるときはコンマで区切りらなければなりません。<br>
ここでは <font color="Red">"%d"</font> と <font color="Red">2 + 3</font>が引数ですね。 

#変換指定
もう一度だけ先ほどの演算を見てみましょう。

```C:calculation
printf("%d", 2 + 3);
```
<font color="Red">%d</font> とありますが、これは10進数で表示してくださいという書式の指示です。<br>
このように文字や数字を自分の表示したい方式に変換することができます。これが変換指定です。

変換指定の構造はこんな感じです。
<img width="450px" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2293026/d4629777-db0f-ebcb-1b53-3c3e30e7447c.png">

それでは実際に変換指定で遊んでみましょう。

```C:test.c
#include <stdio.h>

int main(void){
    char number[] = "12345";

    printf("%s\n", number);          //そのまま表示
    printf("%.3s\n", number);        //３桁まで表示
    printf("%7s\n", number);         //最低７桁で右よせ
    printf("%-7s\n",number);         //最低７桁で左よせ
    printf("%07.7s\n", number);      //7桁まで表示して空白を0で埋める

    return(0);
}
```

これを実行すると下のように表示されます。

```
12345
123
  12345
12345
0012345
```
楽しいですね。

#特殊表記
特殊表記と呼ばれる、特別な機能を持った表記があります。例えばこんな感じ。

```C:escape_sequence
printf("こんにちは\nおはよう");
```
これを実行すると下のように表示されます。

```
こんにちは
おはよう
```
お分かりいただけましたでしょうか。ここで\nは改行を表しています。
このように\のあとに文字が続く場合、これを特殊表記といいます。（一部の環境では\の代わりに¥を使います。）<br>
では、いくつか例を見てみましょう。

|表記|機能||表記|機能|
|:-----:|:-----|:--:|:--:|:--|
|\n|改行||\a|警報音を鳴らす|
|\b|後退||\f|書式送り|
|\t|次の水平タブ位置に移動する||\v|次の垂直タブ位置に移動する|
|\\\|\を入力||\?|?を入力|
|\'|'を入力||\"|"を入力|
たくさんありますね。ただ、書式送りやタブの移動はいつ使うんでしょうか。<br>多分使わないので覚える必要はなさそうです。




#最後に
いかがだったでしょうか。<br>皆さんもprintfを使いこなして快適なC言語生活を楽しみましょう！