OmniAICreator/Qiita-1.07M huggingface dataset:
GPT-4を適用したMicrosoft 365 Copilotがすごそう

- この記事の内容にある意見は、個人の主観的意見を前提とします。
- 記事の内容は間違いがあり得ますので、ご了承いただけると幸いです。内容の間違い、認識の違い、違う意見などありましたら、コメント大歓迎です！

# はじめに

マイクロソフトで、Office365にGPT-4を適用するという発表があったようですね。

やりたいことを少しの文章で入力するだけで、綺麗にまとめたPPTが作られたり、自動でメールをまとめて作成してくれたり、自動でいろんなデータから分析してグラフ入り報告書書いてくれたり。。。

こちら、microsoft公式のyoutubeのリンクまとめと一緒に簡単に紹介します。

# Microsoft 365 Copilot紹介のYoutubeリンク

## Explaining the Microsoft 365 Copilot System
https://www.youtube.com/watch?v=8_lXSmlwk1s

- 365 Copilot Systemのコンセプトに関して説明をしています。
- 「365 App」「Large Language Model」「Microsoft Graph」で大きく３つで構成と動作方式に関して簡単に説明しています。

## Microsoft 365 Copilot in PowerPoint
https://www.youtube.com/watch?v=fzoZ_f7ji5Q

- Copilot Chatに「MS Wordファイルから内容を読み取って、綺麗なPowerPointを作る」例を紹介しています。
- 作られた後、「文章が長いところは、もっと短く要約する」などの機能も紹介しています。
- もちろん、この動画ではなく、`The Future of Work With AI - MicrosoftMarch 2023 Event`の動画で紹介していますが、何もないところから「こういう内容を作って欲しい」としたら、自動で作ってくれるようです。

## Microsoft 365 Copilot in Excel
https://www.youtube.com/watch?v=I-waFp6rLc0

- 膨大な売上データから、「データを分析し、３つのKey trendを教えて」とcopilotに頼むと、いい感じで答えてくれる例が紹介されています。
- また、一つのKey trendに対して「詳細を見せてほしい」と頼むと、あたらしいシートに、「グラフはまとめた統計データ」を自動で生成くれる例を紹介しています。

## Microsoft 365 Copilot in Word
https://www.youtube.com/watch?v=C8WDGKaOt2s

- 「プロダクトロードマップ」のWordファイルと、「Meeting 議事録」から、「Copilotに提案書を作って欲しい」の例を紹介しています。
- また、前に作成した提案書があれば、それを参照して同じ感じのフォマットで再度まとめてくれるところも紹介しています。

## Microsoft 365 Copilot in Outlook
https://www.youtube.com/watch?v=uI5mQjTp1fI

- 色々やりとりが多いメールスレッドに対して、「メール内容と関連添付データを見て、返答を作成して欲しい」例を紹介しています。

## Microsoft 365 Copilot in Teams Meetings
https://www.youtube.com/watch?v=N1gpkk-MwpY

- リアルタイムなMeetingにおいて、元状況を文章で要約してくれる例を紹介しています。

## The Future of Work With AI - Microsoft March 2023 Event
https://www.youtube.com/watch?v=Bf-dbS9CcRU

- こちらは、365 Copilotに対して、実際のデモなどを紹介しています。上記の動画の内容とは違うデモも多く、かなり興味深い内容も多そうなので、ぜひおすすめです。

# あとがき

まだ、筆者本人も全て見切れてないですが、AIの飛躍的発展に驚きですね。

今回のOffice 365 Copilotにフォーカスすると、エンジニアを含むいろんな職群で、プレゼンテーション・スプレッドシート・ドキュメントの作成は使われており、いろんな理由で、色々考えて作ると必要があり、かなり時間がかかる作業だったと思います。（筆者も、コーディングよりこちらの仕事がおおい場合も頻繁ですね。）
また、エンジニアの中では、こういう作業が苦手な方もいるかなと思います。

今後は、この雰囲気が一気に変わってくるのかなとも、個人的に感じてたりします。
直接作成するのは難しくとも、「AIが作ったことをレビューし直す」レベルは、前者よりは楽かなと思います。
その場合、「ドキュメントを一定レベルまで作成できる人が多くなる」「ドキュメントを作る平均時間が非常に上がる」ことで、一定カテゴリのドキュメントは、「一定レベルで早く作れる」が、当たり前になるかもしれません。

ドキュメントの作成で時間を食い過ぎてストレスになる場面は減る反面、ドキュメントの作成が大事になってくる職群においては色々思うところが多いかもしれません。

個人の意見としては、「市場を独占してしまうのでは」というところは心配ですが、「ビジネス全体においての生産性の飛躍的な向上に貢献」できそうな革新と見ています。
ので、今後の「Microsoft 365 Copilot」には、かなり期待してます。
Power BI で数字を百万単位で表示する方法

Power BI での文字や数字等の各項目の書式設定は、Power BI Desktop でのデータ モデリングの過程で行います。**ビジュアルの書式設定の中で [表示形式] を「百万」に設定すると「M」で表示される**のですが、これをそのまま「百万」と表示する方法を紹介します。

# カスタム書式の設定
画面右端の [データ] ペインの中で、(← 最近「フィールド」から「データ」に名称変更されました)
① 書式設定したい項目をクリック (チェックボックス**ではなく** 項目自体をクリック) すると
② [列ツール] タブが表示されるので、クリックすると 
③ Excel などと同様に書式設定が行えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668909/bd23da33-fa05-7252-9cf1-13bc683dd487.png)

上図の③の [書式] がプルダウンメニューになっているのですが、[ｖ] ボタンを押さずに、「整数」とか書かれている部分をダブルクリックすると直接入力が可能です。そこで直接「**#,##0"百万",,**」と入力します。これで書式設定自体はできました。

:::note
書式設定の一番右に入力するカンマ「,」の数が、省略する桁を表しています。カンマ1つが3桁で「千」単位、カンマ2つで「百万」単位、カンマ3つで「十億」単位となります。「百万」などの日本語の単位はダブルクォーテーション「"」で囲うのですが、このカンマより前に入れる必要があります。
:::

注意点として、グラフの軸ラベルやデータラベルなどは既定で表示単位を「自動」で調整する設定になっており、このカスタム書式を設定していると、下図のように「0M百万」のように表記されてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668909/7941f464-917c-68e8-8fa1-33028f59d706.png)

# ビジュアルの書式設定で、カスタム書式を使うよう指定する
[ビジュアルの書式設定] → [ビジュアル] → [Y軸] → [値] → [表示単位] で「なし」に設定することで、正しく表示できます。(データラベルはY軸の設定に追随するのか、特に設定しなくても正しく表示されました。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668909/c029041d-2a26-7626-2b08-619b7ebc96da.png)

# おまけ：Bing Chat で「#,##0"百万",,」を解説
この書式設定ってどういう意味なのかな？ということで、Bing Chat に聞いてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668909/10558248-e134-e831-2cbe-15856dc1b27e.png)

画像より抜粋した解説です。
> このテキストは、Excel のセルの書式設定でユーザー定義の種類として使えるものです。これは、数値を百万単位で表示し、それ以下の桁を省略することを意味します。また、「百万」という単位を数値の後ろにつけることもできます。例えば、123456789 という数値があった場合、このテキストを使って書式設定すると、「123 百万」と表示されます。

Excel と同様の書式設定が効くので「#,##0;"▲ "#,##0」とすると、負の値で「-」の代わりに「▲」を数字の前につけることができます。ただし色の指定はできないので、負の値を赤字にしたいときは条件付き書式でフォントの色をルールを使って指定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2668909/69616dc9-1d04-56e4-12a6-c0fda2388c51.png)

この記事のタイトルで Bing Chat に聞いてみたら、それらしい嘘が返ってきました。確認重要。
Java_数字の文字列操作（0埋め） (paizaランク D 相当)

paizaラーニングforTEAM Java入門編
Cランクレベルアップメニュー

```Java:C-#11
// 0～999の整数nが入力されたとき、
// nが3桁の数である場合にはnをそのまま出力し、
// nが2桁の数である場合にはnの先頭に0をひとつ、1桁の数である場合にはnの先頭に0をふたつ加えたものを出力するプログラム
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
        Scanner sc = new Scanner(System.in);
        String num = sc.nextLine();
        if (num.length() == 3) {
            System.out.println(num);
        } else if (num.length() == 2) {
            System.out.println("0" + num);
        } else {
            System.out.println("00" + num);
        }
    }
}
```
Java_数字の文字列操作（基本） (paizaランク D 相当)

paizaラーニングforTEAM Java入門編
Cランクレベルアップメニュー

```Java:C-#10
// 0～9の数字が4つ並んだ文字列Sが入力され、左から1番目の数と4番目の数を足し合わせたものをaとし、2番目の数と3番目の数を足し合わせたものをbとしたとき、
// 文字列としてのaの末尾に文字列としてのbを結合したものを出力するプログラム
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        // System.out.println(line);
        
        String[] line_ = line.split(""); // 変数lineに格納された文字列を1文字ずつ分割したい
        // System.out.println(line_[0]);
        int S_1 = Integer.parseInt(line_[0]);
        // System.out.println(S_1);
        int S_4 = Integer.parseInt(line_[3]);
        // System.out.println(S_4);
        int a = S_1 + S_4;
        // System.out.println(a);
        
        int S_2 = Integer.parseInt(line_[1]);
        // System.out.println(S_2);
        int S_3 = Integer.parseInt(line_[2]);
        // System.out.println(S_3);
        int b = S_2 + S_3;
        // System.out.println(b);
        
        System.out.println("" + a + b); // 最初に文字列として""を入れることで変数aと変数bを文字列として扱える
    }
}
```
axiosを使ってフロントエンドからバックエンドのAPIを叩く

こんにちは。フロントエンドリスキリングおじさんです。  
今回は掲題について取り組みます。

## 前提情報
### 実施時期
2023年3月  

### 実行環境
#### フロントエンド
node.js: 18.15.0
言語: TypeScript + React + MUI

#### バックエンド
言語: Java17 + Spring boot

## 作成物の仕様
#### バックエンドのREST API
URI: "/api/hello"  
レスポンス：以下のJSONを固定で返します。
```json
{
	"jpn": "こんにちは",
	"eng": "hello"
}
```
こちらの実装については省略します。

#### フロントエンド
バックエンドのAPIを叩いて、レスポンスを画面表示させる
ただし、レスポンスが返ってくるまではローディング画面を表示させておきたい！

## 実装
```typescript
import { CircularProgress, Typography } from "@mui/material";
import axios from "axios";
import React, { useEffect, useState } from "react";

// APIのレスポンスの型を宣言
type Greet = {
  jpn: string;
  eng: string;
};

function App() {
  const [greet, setGreet] = useState<Greet>(); // Stateに持っておく　初期値はundefined
  const url = "http://localhost:8081/api/hello"; // バックエンドAPIのURL

  useEffect(() => {
    axios.get(url).then((response) => {
      setGreet(response.data); // APIのレスポンスをgreetに詰める
    });
  }, []); // 第二引数の配列に入れた変数が更新されるたび、第一引数の内容が再実行される。今回は再実行の必要は無いので空

  if (greet == null) {
    // greetが空の場合はぐるぐるローディング画面を流す
    return (
      <div className="loading">
        <Typography variant="h1"></Typography>
        <CircularProgress />;
      </div>
    );
  }

  return (
    <div className="greet">
      <div className="greet-japanese">
        <Typography variant="body1">{greet?.jpn}</Typography>
      </div>
      <div className="greet-english">
        <Typography variant="body1">{greet?.eng}</Typography>
      </div>
    </div>
  );
}

export default App;
```

### 動かしてみる
#### 普通に実行
npm start を実行し、localhost:3000にアクセスしてみます。  
![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3213461/1182b979-e57c-dade-f5f3-c5e300a4137e.png)
無事、表示されました。

#### バックエンドのレスポンス返却を止めてみる
デバッグモードでレスポンス返却部分にブレークポイントを張って、  
ページを更新してみます。
![loading.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3213461/d6ecde21-1ac0-3bfe-7f10-ee0f4ce6c7ba.png)
すると、挨拶文は表示されず、ぐるぐるだけが表示されています。

#### レスポンス返却を再開
バックエンドのブレークポイントを破棄してみます。
![success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3213461/1182b979-e57c-dade-f5f3-c5e300a4137e.png)
再度、挨拶文が表示されました。

## この実装の問題点
### バックエンドのホストが固定やないかい！
次回、相対的にアクセスできるようにします。

## 次回

[この記事](https://qiita.com/fsdg-r-moriyama/items/eb8d93711ca5d257a8de)で、Nginxを使ってフロントエンドとバックエンドを連携させます。
初期値問題「[演習]微分方程式11(体系大学数学)」をwolframalphaとsympyでやってみたい。

わかりませんでした。

オリジナル

https://youtu.be/OXBtfu9y39M

# wolframで
基本解と特殊解？

https://www.wolframalpha.com/input?i=y%27%27%27-y%3De%5E%28x%2F2%29cos%28%E2%88%9A3%2F2x%29&lang=ja

**点検**
省略

# sympyで
できませんでした。
```python
from sympy import *
x=Symbol  ('x',real=True)
y=Function('y')(x)
print("#",solve( Eq( diff(y,x,3)-y,exp(x/2)*cos(sqrt(3)/(2*x)) ),x))
```
PetaLinuxにnanoをインストールしたい話

# はじめに
業務で PetaLinux を扱うことがありまして、デバッグ用に nano をインストールしようと思ったんですが、結果が簡単な割に苦労してのでメモを残しておきます。

あ、確認してみたのは PetaLinux2020.2.2 と PetaLinux2022.1 になります。

# 結論
PetaLinux の細かい話は他のサイトに譲るとして、`<petalinux project dir>/project-spec/meta-user/conf/user-rootfsconfig` に以下の行を書き加えるというのが正解でした。
```shell:user-rootfsconfig
CONFIG_nano
```
これだけ。
これを追記したあと、
```shell
$ petalinux-config -c bootfs
```
って bootfs のコンフィギュレーションで `user packages   --->` の下に `nano` って項目が増えているので、ここにチェックを入れるだけ。ここまできたら、
```shell
$ petalinux-build
```
でビルドするだけで使えました。

# まとめるけどよくわかってない
nano のレシピファイルは
`<petalinux project dir>/components/yocto/layers/meta-openembedded/meta-oe/recipes-support/nano/`
にあるらしく、上記の操作でこのレシピが有効になるらしいんだけど、いまいち仕組みが分かっていません。使えるのでまあいいかという感じです。

この辺にレシピがあるソフトは似たようなことすると追加できるのかな？

ってか、`petalinux-config -c bootfs` 内でインストールできるソフトの中にあってほしいくらいなんだけど、ないんだよな、、（ないよね？ 私が見つけられてないだけじゃないよね？）
Wicked pdfをDocker環境のM1で動かす方法

Wicked pdfというgemを使用して開発を進めていこうとしたのですが、Docker環境でM1の場合動作しないということがあったので、その対策方法を記載したいと思います。

### 動作しない原因は何なのか?
M1とその他マシーンでCPUアーキテクチャ(以下CPU)が異なる点が要因になっています。Docker環境はホストOSをベースとしてBuildしますが、BuildしたコンテナのCPUはそのベースとしたホストによって決まります。そしてwicked pdfで対応できるCPUにM1のCPU(arm64)は含まれていない為、エラーが起きるようです。
[wicked pdfにおける対応可能なCPU一覧](https://wkhtmltopdf.org/downloads.html)

[参考ログ](https://github.com/wkhtmltopdf/packaging/issues/98)
困ったことになったということで、上記のGit上での会話を見ていると、jtelcontarさんが対応方法を記載してくれてました。
どうやら記載のパッケージでは64に対応できるということだったので、ダウンロードしてみたいと思います。ただし、M1以外の場合は既存のgemを参照するようにしたいので、M1の場合は新規にダウンロードしたパッケージ、それ以外は既存gemを参照するといった具合で分岐が必要になりそうです。実際にDockerfileに記載した内容がこちら

```dockerfile
RUN if [ "$(uname -m)" = "aarch64" ]; then \
        echo "M1からのアクセスです"; \
        cd /usr/local/bin/ && wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.stretch_arm64.deb && \
        apt-get update && \
        apt-get install -y /usr/local/bin/wkhtmltox_0.12.6-1.stretch_arm64.deb && \
        rm /usr/local/bin/wkhtmltox_0.12.6-1.stretch_arm64.deb; \
fi
```

if分の条件にある"$(uname -m)"はcpuアーキテクチャ情報を取得するコマンドで、ここでどの種類のマシーンからアクセスしたのかを判定します。あとはaptコマンドを使用してpackageをインストールしています。
最後にrmでインストールしたパッケージを削除しているのは、installコマンドでパッケージ解凍後に、このパッケージ自体はゴミになるので削除しています。

あとはwicked_pdf.rb内で、gemの参照先のパスをデフォルトで参照している記載があるのですが、こちらの内容を以下のように修正しました。

```wicked_pdf.rb
# M1でDockerを起動した場合、/usr/local/bin/のパスに64対応のファイルが作成されるのでそちらを参照する
# ファイルが存在しない(M1起動でない場合)はこれまで通りgemで格納したファイルを参照する)
# TODO 最新のgemが64に対応した段階で、デフォルト記載に戻す
if File.exist?('/usr/local/bin/wkhtmltopdf')
  binary_path = '/usr/local/bin/wkhtmltopdf'
else
  binary_path = "#{Gem.loaded_specs['wkhtmltopdf-binary'].full_gem_path}/bin/wkhtmltopdf"
end

WickedPdf.config = {
  exe_path: binary_path,
}
```

先ほどDockerfile内にて、M1からのアクセスの場合、/usr/local/bin/のパスにパッケージをインストールするように記載していました。なのでこのパスに、wkhtmltopdfのファイルが存在していればそれはM1からのアクセスなので、パスの参照先をそちらを見るようにしているわけです。
注意点として、バージョン指定をしてインストールしているので、最新のバージョンがM1にも対応した場合これらの対応は元に戻すことをお忘れなく...

## 終わりに
調べて調べて調べまくった結果、今回のような実装に至りました。かなり苦戦を強いられましたが、ドキュメントを読み漁るという点では良い経験になったと思います。同じ現象に悩んでいる方がもしいらっしゃれば参考にしてみてください。
初期値問題「[演習]微分方程式10(体系大学数学)」をwolframalphaとsympyでやってみたい。

わかりませんでした。

オリジナル

https://youtu.be/1VmLVNgvi6s

# wolframで
基本解と特殊解？

https://www.wolframalpha.com/input?i=y%27%27%27-y%3Dcos%28x%29&lang=ja

https://www.wolframalpha.com/input?i=y%27%27%27-y%3De%5Excos%28x%29&lang=ja

https://www.wolframalpha.com/input?i=y%27%27%27-y%3Dxcos%28x%29&lang=ja

**点検**
省略

# sympyで
できませんでした。
```python
from sympy import *
x=Symbol  ('x',real=True)
y=Function('y')(x)
print("#(1)",solve( Eq(diff(y,x,3)-y,       cos(x)),x ))
print("#(2)",solve( Eq(diff(y,x,3)-y,exp(x)*cos(x)),x ))
print("#(3)",solve( Eq(diff(y,x,3)-y,    x *cos(x)),x ))
```
Java_部分文字列 (paizaランク D 相当)

paizaラーニングforTEAM Java入門編
Cランクレベルアップメニュー

```Java:C-#09
// 1行目に文字aが、2行目に文字列Sが入力されたとき、Sにaが含まれているかどうか判定し、含まれている場合には“YES”を、そうでない場合には“NO”を出力するプログラム
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
        Scanner sc = new Scanner(System.in); // 標準入力の準備
        String letter1 = sc.next(); // 1行目の文字を変数letter1に格納
        // System.out.println(letter1);
        
        String text = sc.next(); // 2行目の文字列を変数textに格納
        // System.out.println(text);
        
        int num_YES = 0; // Sにaが含まれているかどうかの判定を変数num_YESの値に対応させる_最初は含まれていないとして初期化
        String[] letters2 = text.split(""); // 変数textに格納された文字列を1文字ずつ分割したい
	// 2行目の文字列を分割した文字すべてに対して1行目の文字と一致するかを判定するループ
	// 2行目の文字列のいずれかの文字が1行目の文字と一致している場合にnum_YESが1になるように
        for (String letter2 : letters2) {
            // System.out.println(letter2);
            if (letter2.equals(letter1)) {
                num_YES = 1; // 一致したら1にする
            }
        }
        // System.out.println(num_YES);

        if (num_YES == 1) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }
    }
}

// 配列や文字列などの参照型の場合、==演算子は同じオブジェクトを参照している場合にtrueとなるため、
// 例えば2つの文字列が同じ値であっても、参照している文字列のオブジェクトが異なる場合はfalseとなる
// 参照しているオブジェクトが同じかどうかではなく、例えば2つの文字列に格納されている値が等しいかどうかを調べるには、
// Stringクラスで用意されているequalsメソッドを使う
```

最後の4行のコメントについて
参考文献:https://www.javadrive.jp/start/string/index4.html
Gradleを基本からまとめてみた【入門】

## Gradleとは？
- Gradleは、主にJava向けに開発されたビルドツールのこと。
- Javaと同様に、JVM上で動作するKotlinやScalaはもちろんのこと、PythonやC++にも対応している。

## ビルドツールとは？

- ビルドツールとは、プログラムのビルドや実行を自動化するツールのこと。

- ビルドツールを利用することで、下記の手順を一括で実行する。

①必要なライブラリのインストール
②Javaファイルのコンパイル
③自動テスト
④パッケージ(JarやWar)の作成

ビルドからテストまでを一括で実施するので、人の手による作業を減らす役割を担っており、複数人で開発をするような現場であれば、このようなビルドツールは必須の存在といえる。

## Gradleの特徴
① Groovyによるスクリプト

Gradleの大きな特徴が、JVMで動作するスクリプト言語である「Groovy」を用いて記述する点で、Gradleは後述の「Apache Ant」や「Apache Maven」の思想を受け継いで開発されているが、これらのビルドツールでは、XMLによる”設定ファイル”を利用してビルドの設定を記述していた。
一方で、Gradleは設定ファイルではなく”スクリプト言語”を用いてビルド手順を記述している。
スクリプト言語を用いて記述することで、AntやMavenと比べて非常に柔軟なビルドスクリプトを作成できるため、より高度なビルドを構成することが可能となり、Gradleのバージョン5.0からは、GroovyだけでなくKotlinによるスクリプト記述も可能となっている。
② Mavenとの互換性

GradleはMavenと高い互換性を持っており、Mavenのリポジトリを利用することも可能で、Mavenを用いたプロジェクトをGradleに移行する場合にも非常に楽に移管できる。

③ プラグインによる拡張

実は、Gradle自身の機能は少なく、必要な機能は開発者がスクリプトを記述する必要がある。

④ Android開発の標準ビルドツール

モバイル向けOSであるAndroidのアプリを作る場合には、「Android Studio」を利用して開発をすることになる。
このAndroid StudioにはGradleが標準搭載されており、Androidアプリのビルドを行う場合にはGradleを利用することになる。
そのため、Androidアプリ開発者であれば必然的にGradleの習得が必要になる。

## 4．Gradleのインストールと設定
```
brew install gradle
```
## 5．Gradleの使い方

①gradleコマンド

GradleをPowerShellなどのシェルから実行する場合、「gradle」コマンドを利用する。

```
gradle <コマンド名>
```



## 参考サイト
[Gradleとは何者？インストール方法〜使い方までわかりやすく解説￼](https://camp.trainocate.co.jp/magazine/about-gradle/)
Chromebookに入れたXAMPP(Webサーバ:Apache)のページをLAN内の他PCから見る方法

### １．Chromebookについて
　こいつにはChromeOSが搭載されており、中でLinuxモードといってコマンドを動かせて便利なのだが、内部で仮想的にLinuxを動かしているに過ぎない。
　つまり、外から見えるIPアドレスと外から見えるIPアドレスが異なっているということだ。

### ２．XAMPPで楽しくホームページづくり
> XAMPPのMySQLにPythonから触る（mysqlclient & MySQLdb）
> https://qiita.com/RS2324/items/88098444e3018b7d0b65

### ３．問題
　XAMPPも内部的にはApache2なのだから、ローカルで公開すれば色々テストできんじゃね？と思ったのだが、１の問題もあって断念していた。

### ４．解決方法
##### ①ポート転送の設定
　『アプリ一覧』→『設定』→『詳細設定▼』→『Linux開発環境』→『ポート転送』
　において、使いたいポート番号を追加する。
　今回はテストとして「8080」を追加してみた。
##### ②Apache2の利用ポート設定
```terminal
$ xhost si:localuser:root
$ sudo /opt/lampp/manager-linux-x64.run
```
　上記のコマンドでGUIのXAMPPを表示する。
　『Manage Servers』から『Apache Web Server』の『Configure』を開く。
　①で入力したポート番号をここでも再度入力し、OK。
　Restart Allしておく。

```terminal
$ xhost -si:localuser:root
```
も忘れずに実行して権限を抜いておく。

##### （③phpmyadminも他PCで見たいなら）
```terminal
$ sudo nano /opt/lampp/etc/extra/httpd-xampp.conf
```
　にて、
```php
<Directory "/opt/lampp/phpmyadmin">
    AllowOverride AuthConfig Limit
    # Require local
    Require all granted
    ErrorDocument 403 /error/XAMPP_FORBIDDEN.html.var
</Directory>
```
　こうしておく。セキュリティ的にはアレだけど開発環境だからOKOK！

##### ④Chromebookを外から見たIPアドレスを調べる
　『アプリ一覧』→『設定』→『Wi-Fiの▶』→『接続済みAPの▶』を見ると、IPアドレスとして数値が表示されています。

### ５．いざ接続
　他のPCにてブラウザを開き、URL欄に、`http://(ipアドレス):8080/phpmyadmin/`を入力して接続し、表示されたら終了！

### ６．おわりに
　Googleの技術力ってすごいなぁ。

### 参考文献
> ChromebookにPHP開発環境を構築（Xampp）
> https://qiita.com/kamekame85/items/2c00aa9766a0c406d3cc

> How do I view my apache web server from another computer on the same network?
> https://support.google.com/chromebook/thread/106121945/how-do-i-view-my-apache-web-server-from-another-computer-on-the-same-network?hl=en

> 【Apache Http Server】ChromeBookにApacheをインストールする
> https://e-seventh.com/apache2-how-to-install-on-chromebook/#

> XAMPP Apache/MySQL/Tomcatのポート番号を変更
> https://itsakura.com/xampp-port

> Ubuntu上のMySQL（XAMPP）サーバーにLAN内の別PCからアクセスするまでの手順
> http://pineplanter.moo.jp/non-it-salaryman/2022/07/09/mysql-lan/
２相コミット

# ２相コミット
分散データベースの整合性をとるための仕組み(コミットメント制御機能）です。
データの整合性は、次の第一相と第２相のやり取りによって行われます。

### 第１相
同期の要求元が他のデータベースシステムに対して、データベース更新の処理を依頼します。
* ```データベース更新前に復元可能にする処理```
* ```データベース更新を可能にする準備処理```

### 第２相
#### 第1相の要求に対して、各データベースシステムが```正常応答が返ってきた時```
同期の要求元は各データベースシステムによって、```データベース更新の依頼をします```。これによって```すべてのデータベースの整合性を確保```する。

#### 更新の保証処理が失敗の場合
同期の要求元は、各データベースシステムに対して、```データベースを更新前の状態に戻す処理(ロールバック)```を依頼します。
つまり```すべてのデータベースを更新前に状態に戻す```ことにより整合性を確保します

# 出典
https://gihyo.jp/book/2022/978-4-297-13178-4

# 分散データベース
データを```ネットワークを介した複数サーバ上```に置いて、それらの```すべてを一つのデータベースとして一元管理```するシステムを指す。

### レプリケーション
```同じデータを持つデータベースを複数各所に配置```する形態。
整合性を保つため、　```即時または定期的に置き換えを行う```必要がある。

### 分散配置
```全体のデータベースを各所に分散させる```形態です。
```トランザクション処理（入力や更新などの処理）が発生するごとにデータベースを順次更新```する。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
[GitLab CI/CD] macOS SaaS Runner と GitLab Mobile DevOps で iOSビルド実行環境の簡単セットアップ


:::note info
更新履歴
2023.08.02 [GitLab.JP Meetup](https://gitlab-jp.connpass.com/event/288154/) で本投稿の内容を登壇しました
:::
https://speakerdeck.com/n11sh1/gitlab-mobile-devops-to-saas-runners-on-macos-beta-noshao-jie

この記事では、GitLab CI/CD の macOS SaaS Runner と GitLab Mobile DevOps で iOSアプリのビルド実行環境を簡単にセットアップする方法について紹介します。

# macOS SaaS Runner とは

macOS SaaS Runner は、GitLabが提供するCI/CDのクラウド実行環境です。SaaS Runner を使用することで、環境構築の手間を省くことができます。

従来の SaaS Runner は Docker 上で提供されており、Xcodeを実行できるDockerイメージが存在しないため、iOSアプリのビルドは独自の実行環境に GitLab Runner をインストールして構築するため、以下のような課題が有りました。


- MacbookProやMac MiniなどのmacOS実行環境が必要
- macOSやXcodeのバージョンを指定する場合は複数macOS実行環境が必要
- macOS実行環境にインストールしたGitLab Runnerのメンテナンス

これら課題を解決するサービスが、GitLabが提供する [macOS SaaS Runner](https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html
) です。

https://docs.gitlab.com/ee/ci/runners/saas/macos_saas_runner.html

## macOS SaaS Runner の使い方
```yaml:.gitlab-ci.yml
build:
  tags: [saas-macos-medium-m1]
  image: macos-12-xcode-14
  stage: build
  script:
    - echo "running scripts in the build job"
```
このように、YAMLファイルの`tags: [saas-macos-medium-m1]`を指定すれば、Intel x86-64 プロセッサを搭載したクラウド実行環境が手に入ります。
macOSとXcodeのバージョンは`image: macos-12-xcode-14`で指定できます。利用可能バージョンは、公式ドキュメント [VMインスタンスの種類とイメージ](https://docs.gitlab.com/ee/ci/runners/saas/macos/environment.html) に記載されています。


# GitLab Mobile DevOps
GitLab Mobile DevOps は、モバイル開発者やチームが GitLab CI/CD を使用してビルドおよびリリースプロセスを自動化するために設計された機能です。

https://docs.gitlab.com/ee/ci/mobile_devops.html

## コード署名 と セキュアファイル機能
macOS SaaS Runner のクラウド環境で実行する場合、コード署名（Provision profiles や Signing certificates）をクラウド環境に連携する管理が必要があります。
[セキュアファイル機能](https://docs.gitlab.com/ee/ci/secure_files/index.html) を使えばGitLabプロジェクト上で直接簡単に管理ができます。

https://docs.gitlab.com/ee/ci/secure_files/index.html

CI/CDパイプラインで使用する「セキュアファイル」として最大 100 個のファイルを安全に保存できます。これらのファイルは、プロジェクトのリポジトリの外に安全に保存され、バージョン管理されていません。これらのファイルに機密情報を保存しても安全です。安全なファイルは、プレーンテキストとバイナリの両方のファイル タイプをサポートしますが、5 MB 以下である必要があります。

## Secure Files へのファイル追加
- **Main menu > Projects** を選択し、プロジェクト詳細に移動します
- 左サイドバーで、**Settings > CI/CD** を選択します
- **Secure Files** セクションで、**Expand** を選択します
- **Upload File** を選択します
- アップロードするファイルを見つけて **Open** を選択すると、ファイルのアップロードがすぐに開始されます。アップロードが完了すると、ファイルがリストに表示されます。

![スクリーンショット 2023-03-17 15.51.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121942/47f9bde0-6350-e46b-d718-17be85d28abe.png)


## GitLab CI/CD での Secure Files ダウンロード
```yaml:.gitlab-ci.yml
build:
  variables:
    SECURE_FILES_DOWNLOAD_PATH: './where/files/should/go/'
  script:
    - curl --silent "https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer" | bash
```
`script`のcurlコマンドにより、CI/CDジョブで Secure Files がダウンロードされます。
ダウンロード先ディレクトリの指定は`variables`の`SECURE_FILES_DOWNLOAD_PATH`で指定できます。

# さいごに
今回紹介した macOS SaaS Runner と GitLab Mobile DevOps は、fastlane と組み合わせることで、GitLab CI/CDをより有効活用することができます。

fastlane: モバイルアプリのビルド・テスト・配布などのタスクを自動化するためのツール

https://fastlane.tools/

GitLab CI/CD での fastlane セットアップ方法

https://qiita.com/n11sh1/items/f646d79e1da809ba6e52
世界中のユーザーからフィードバックを収集する方法

# はじめに
この記事では、Google フォームとGoogle スプレッドシート、Google翻訳を組み合わせたユーザーフィードバック収集システムの作り方について解説します。

# ゴール
世界中のユーザーからフィードバックを得る。

# Google フォームを作成する

まず、Google フォームを使ってフィードバックを収集するフォームを作成します。
![スクリーンショット 2023-03-17 15.30.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366249/0b0aea70-2d60-3acd-6d16-9c0985f7769d.png)


# Google スプレッドシートを作成する

次に、GoogleフォームとGoogleスプレッドシートを連携します。Googleフォームの回答タブにある、「スプレッドシートにリンク」をクリックすると、簡単に連携できます。

![スクリーンショット 2023-03-17 15.32.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366249/117c95bb-661c-bb9b-2b84-44cc299f405f.png)


# 自動翻訳設定を行う

最後に、ユーザーから収集したフィードバックを、自動的に翻訳する設定を行います。

## STEP1: 言語を検出
DETECTLANGUAGE関数で言語を検出できます。

![スクリーンショット 2023-03-17 15.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366249/2fe5dccc-b35a-fd97-726f-e6e42cacda5f.png)

## STEP2: 翻訳する
翻訳には、GOOGLETRANSLATE関数を使います。第一引数に翻訳したいテキスト、第2引数に翻訳元の言語を入れます。

![スクリーンショット 2023-03-17 15.42.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366249/1bc7deb1-5919-6892-2550-7a36ce362197.png)

## おまけ
IFERROR関数は、特定の式がエラーを返した場合に代替の値を返す関数です。
第1引数にエラーが発生する可能性がある式を指定し、第2引数にエラーが発生した場合の代替の値を指定します。

# まとめ
以上の手順によって、Google フォーム + Google スプレッドシート + Google翻訳を組み合わせたユーザーフィードバック収集システムを構築することができます。このシステムを利用することで、世界中からのフィードバックを収集し、製品やサービスの改善に役立てることができます。

---

ご覧いただきありがとうございました。

🐦 [Twitter: @shota_appdev](https://twitter.com/shota_appdev)

📱 [個人アプリ: Symbols Explorer](https://apps.apple.com/jp/app/symbols-explorer/id1612933742)
Amazon RDSとEC2のワンクリック接続セットアップを試す

# はじめに
Amazon RDS(Aurora含む)のデータベース作成時にEC2との接続を自動でセットアップできる機能があります。
(以下のUpdateの内容です。)
この機能により、EC2からRDSへつなぐ際のネットワーク設定などがスキップできるようです。

https://aws.amazon.com/jp/about-aws/whats-new/2022/08/amazon-rds-setting-up-connectivity-rds-database-ec2-compute-instance-1-click/

> これにより、VPC、セキュリティグループ、サブネット、Ingress/Egress ルールの手動セットアップなど、ネットワーク関連の追加のタスクを行うことなく、アプリケーションとデータベース間の接続を確立できます。

という記載がありますが、どのような挙動になるのか確認してみます。

## 注意事項
[ドキュメント][link-1]にも記載がありますが、利用する場合はRDS以外に以下のアクセス権限が必要です。
<details><summary>必要なアクセス権限</summary><div>

```
- ec2:AssociateRouteTable
- ec2:AuthorizeSecurityGroupEgress
- ec2:CreateRouteTable
- ec2:CreateSubnet
- ec2:CreateSecurityGroup
- ec2:DescribeInstances
- ec2:DescribeNetworkInterfaces
- ec2:DescribeRouteTables
- ec2:DescribeSecurityGroups
- ec2:DescribeSubnets
- ec2:ModifyNetworkInterfaceAttribute
- ec2:RevokeSecurityGroupEgress
```
</div></details>

また、同一リージョンにEC2インスタンスがrunning状態で存在する必要があります。

# 挙動確認


セットアップ方法はRDSインスタンス作成時に対象EC2を選択するだけです。
<img width=100% alt="スクリーンショット 2022-09-15 154658.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/acee517c-d910-2bb9-1521-6f5a4da03b63.png">


この状態でインスタンスを作成すると以下のリソースが作成されるようです。

|作成されるリソース|リソース名|説明|
|--|--|--|
|セキュリティグループ|ec2-rds-1|ec2にアタッチされる。 RDSのセキュリティグループへのアウトバウンド通信を許可|
|セキュリティグループ|rds-ec2-1|rdsにアタッチされる。ec2のセキュリティグループからのインバウンド通信を許可|
|サブネットグループ|rds-ec2-db-subnet-group-1|下記サブネットをまとめたもの。vpcはec2が存在するものを選択。|
|サブネット|RDS-Pvt-subnet-1,RDS-Pvt-subnet-2,RDS-Pvt-subnet-3|rds インスタンスが配置されるサブネット。azごとに作成される模様。|
|ルートテーブル|RDS-Pvt-rt|上記3つのサブネットに関連づけされたルートテーブル。|

![qiita_その1.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/7bfbbf85-3bb3-b994-7a87-6bab94f74660.png)

作成されたセキュリティグループ(EC2にアタッチされているもの)
![スクリーンショット 2022-09-22 165048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/6fdf4617-c4bf-a5b9-2140-8b2022f3d5db.png)

作成されたサブネット(vpcのip Cidrブロックは10.0.0.0/16で作成)
![スクリーンショット 2022-09-22 165225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/50d5aba7-99d2-3639-a33f-f48ce2982c45.png)


セットアップ後、ec2からRDSへつなげられることを確認しました。
![スクリーンショット 2022-09-20 152341.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/f1573bb4-bc61-886e-ebf3-0baa41454ea4.png)

## EC2アクセス権がないとどうなるの？

describe権限が無いとそもそもEC2を選択できませんでした。

![スクリーンショット 2022-09-20 154751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/2873b9fc-a471-b898-b1cf-bfcf5f37deda.png)

その他権限が無いとリソース作成時にエラーが発生すると思われます。

# まとめ
ワンクリックセットアップにより、EC2からRDSへの接続のセットアップが簡単にできるようです。
VPC内にEC2が存在する状態で、RDSインスタンスを利用したい場合は使うとよいと思います。

<!---リンク--->
[link-1]:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html#USER_CreateDBInstance.Prerequisites.VPC.Automatic
関係代数演算

# 関係データベース
関係データベースに対する基本的な操作は次の三つです。

### 選択
表の中から特定の条件を満たす```行を取り出す```こと。

### 射影
表の中から特定の```列を取り出す```こと。

### 結合
共通の列をもとに複数の表を```結合して新しい表```を作ること。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8

# 参考記事
https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news184.html
PythonでIF文から脱却してみる

Pythonは内包表記という考え方で、IF文を書かないようにした究極な例です。

なぜかpythonにはSwitch文がありません。（※before ver.3.10)

IF文はListに代替される事例は以下。
（evalを使わないとちょっと無理かもです。）
あとはデコレータを使うぐらいです。ただラッパー関数は分かりにくい。

```python
class proc:
    def __init__(self, num):
        self.num = num
    def p_01(self):
        print('01')
    def p_02(self):
        print('02')
    def p_03(self):
        print('03')
    def run(self):
        f = ['self.p_01()','self.p_01()','self.p_02()','self.p_03()']
        res = eval(f[self.num])
if __name__ == '__main__':
    proc(2).run()
```
世の中は広い、この例文にはびっくり
```python
class proc:
    def __init__(self, num):
        self.num = num
    def p_01(self):
        print('01')
    def p_02(self):
        print('02')
    def p_03(self):
        print('03')
    def run_02(self):
        return {
            1 : self.p_01,
            1 : self.p_02,
            2 : self.p_02,
            4 : self.p_03,
            5 : self.p_03,
        }[self.num]()
if __name__ == '__main__':
    proc(2).run_02()
```

### 結論としては、IF文という思考から脱却することです。
対数関数「2023日本大学医学部N方式(Ⅰ期)問Ⅰ(5)」をwolframalphaとsympyでやってみたい。

2^x=10,4^y=10,5^z=10,1/x-1/y-1/z
sympy  でできました。
wolframでできませんでした。

オリジナル
＞医学部専門予備校YMS様
＞どれも教科書基本レベルの問題であり，落とせない。

https://yms.ne.jp/wp-content/uploads/2023/02/M_nichidaiN1_2023.pdf

講評
https://yms.ne.jp/wp-content/uploads/2023/02/M_nichidaiN1_2023.pdf#page=12

# wolframで
？できませんでした。

https://www.wolframalpha.com/input?i=2%5Ex%3D10%2C4%5Ey%3D10%2C5%5Ez%3D10%2C1%2Fx-1%2Fy-1%2Fz&lang=ja

# sympyで(YMS様の手順で)
勉強中

# sympyで
.simplify()を2回実行しました。?
```python
from sympy import *
x,y,z =symbols('x y z', Real=True,positive=True)
x=solve( Eq(2**x,10) )[0]
y=solve( Eq(4**y,10) )[0]
z=solve( Eq(5**z,10) )[0]
print("#",(1/x-1/y-1/z).simplify()           )
print("#",(1/x-1/y-1/z).simplify().simplify())
# -(log(2) + log(5))/log(10)
# -1
```

# 参考
トップページ

https://yms.ne.jp/
残業時間のうっかり超過をSlackBotで牽制してみたぁッッッッッ！！！！

# **はじめに**
どうも:v:QAエンジニアの川満Y哉です:trollface::sparkles:

チーム内で **「残業せずに帰ろうぜ。と思ってもなんだかんだ残ってるからメリハリつけたいね。」** って話が出ていた。
そこで普段コードを書かない自分がSlackbotを利用して残業時間の牽制を自動化したので記事にしてみます！！

マジで簡単なので、普段コードを書かない人でも出来ます:muscle:(多分)
**※実際やってみて自分でもこんなん出来るんだ！ってなり嬉しかったし、楽しかった:notes:**

# **課題感を整理**
↓って感じなので自動で今の残業時間を通知してくれて、退勤時間前に帰宅を促すbotが欲しい。というのが結論。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/a5316249-1240-e1cc-dcd9-fd14ec5f86ad.png)


## **課題に対してのアプローチ**
具体的にどうする？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/6d5bac40-d90c-a768-3053-edbaa0feb2b6.png)
# **何でやる？**
- ってことで、これで行くぞ:dash:課題で達成したい通知を業務で使っているコミュニケーションツール(Slack)で通知する:star:
    - Slack IncomingWebhook
    - GoogleAppsScript
    - GoogleSpreadsheet
## **完成系**
出来たやつ:collision:これで一向にかまわんッッッッ:exclamation::exclamation::exclamation::exclamation::exclamation::exclamation::exclamation:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/211b5468-23a9-17d5-ff89-adc39daaaa00.png)
### **まずはSlackで指定のコメントをどう送る？？**
めっちゃ簡単だった。GASのスクリプトにjson形式で送りたい文章の構成を作って、
SlackチャンネルのwebhookURLを指定してあげればＯＫ。
[※参考させて頂いた記事](https://note.com/ajike_honda/n/n1338f719fda2)
```js
function myFunction() {
 //表示する内容
 var options =
 {
   "method" : "post",
   "contentType" : "application/json",
   "payload" : JSON.stringify(
     {
       "username":"自動通知",
       "icon_emoji":":hatched_chick:",
       "text" :"<!channel>	メッセージ送信のテストです。",
       link_names: 1
     }
   )
 };
 //投稿先
UrlFetchApp.fetch("https://hooks.slack.com/services/hogehogefugafuga", options);
}
```
SlackAPIでメッセを送る時に全ての絵文字が利用できる訳ではない。
icon_emojiは基本なんでも(Slack上で追加した画像も)送れるけど、textはCHEAT SHEET のemojicodeじゃないとSlack上ではそのまんまcodeで表示されちゃう。
[※参考](https://dev.classmethod.jp/articles/slack-api-emoji/)
### **スプシの値を参照させるには？？**
スプシで集計した値をGASで参照して変数に格納し、
送信するメッセを形成する際に変数と文章を組み合わせて送信しちゃえば、Slackに通知したい目標は達成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/17230d78-bde3-c606-3324-c2708ff3c989.png)
## **時間がヤバイ人にメンションをつけたい**
### **SlackのユーザーIDをGET**
残業時間がやばい人は早く帰宅しないといけないので、メンションをつけたい。
SlackAPIを通して通知を送る際にはSlackのユーザーIDが必要。入手は簡単。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/c6204782-6ca8-8c20-15f4-e95c88e3dc04.png)
### **ステータスを定義**
通知したい情報を集計しているスプシにてステータスやメンションをつける境界を決めた。
この情報をGASで読み込みSlackで通知させる。
- 例
   - 39h以上
       - 強制送還(問答不要で帰ろう):cop:🚨
           - メンションつける:mega:
   - 30h以上
       - 頑張り過ぎだぞ:exclamation:目を覚ませ:alarm_clock:
           - メンションつける:mega:
   - 10h以下
       - 今日もお疲れ:white_flower:
           - メンションつけない:no_entry_sign:
               - 誰がどれだけ残業しているかだけお知らせ:zap:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243487/49e3ceb2-53a9-c4b9-f5ae-94002bdab481.png)
## **最後に**
Slackでの通知以外でもスプシで関数を使って必要な情報同士を繋げて、
わかりやすい表現にしたり、条件にあうデータを参照したりする事で簡単に課題を解決する事ができたなーって思いました。

また運用を始めていく中で分岐の条件のバグを見つけたり、
こういう情報を追加しないと見せ方的に微妙だなーって気づきがあって、結構面白かったです！

みんなもやってみよう！！！最後まで読んでくれてありがとう御座いました！
3次元グラフィックス処理のレンダリング

# レンダリング
```3次元形状モデルから2次元画像への変換処理```
.
.
.
以下の処理が含まれる
### 透視投影
```3次元形状を2次元画像に投影```。
画角や消失点によって```表示領域外となる部分を除外```(```クリッピング```)。

### 隠面消去
手前にある物体によって```隠れる部分を削除```する。
カメラから物体へ届く光（レイ）を追跡し、物体と光の荒天ごとに一番手前になる面（ポリゴン）を計算する方法を、```レイトレーシング```という。

### ラスタライズ
数値で表されていた形状を、対応する画素（点）によって表現する。
ラスタ化する際に、射線や曲線の部分に階段状の```ジャギーが発生することがあるが、これを目立たない```ように加工する処理を```アンチエイリアシング```という。

### 陰影付け
```光の当たり具合```や```物質表現の性質```によって、```表面の濃淡```を描き分ける```シェーディング```を行う。
また
光が妨げられる部分に影を付ける(```シャドーイング```)。
```シャドーイングにもレイトレーシング技法が使われる。```

### 効果付与
物質表面の```もよう```や微細な```凹凸```などを、写真や平面の画像から```3次元形状の表面に対応```づけて```素材感を付与```する手法を```テクスチャマッピング```という。

# 出典
https://gihyo.jp/book/2022/978-4-297-12375-8
Ruffのeradicateルールは、半角括弧を含むコメント行をコードだと判定することがある

# 概要
* Python 3.11.2
* ruff 0.0.256


# やりたいこと
Ruffの[eradicate](https://beta.ruff.rs/docs/rules/#eradicate-era)ルールで、コメントアウトされたコードを検出したいです。


# 気になったこと

以下のコメント行は、コメントアウトされたコードだと検出されました。

```python:sample.py
# タスク(保留中)
```

```
$ ruff check sample.py --select ERA 
sample.py:1:1: ERA001 [*] Found commented-out code
Found 1 error.
[*] 1 potentially fixable with the --fix option.
```

半角括弧の後ろに何らかの文字が続けば、コメントアウトされたコーダとは認識されませんでした。

```python:sample.py
# タスク(保留中)を削除する
```

```
$ ruff check sample.py --select ERA 
```


# コードかどうかどうやって判定しているのか

コメント行にコードが含まれているかは、以下の関数で判断しているようです。
変数`CODE_INDICATORS`には半角括弧が定義されていました。

※私はRust言語を理解していません

```rust:ruff/src/rules/eradicate/detection.rs
/// Returns `true` if a comment contains Python code.
pub fn comment_contains_code(line: &str, task_tags: &[String]) -> bool {
    let line = if let Some(line) = line.trim().strip_prefix('#') {
        line.trim()
    } else {
        return false;
    };

    // Ignore non-comment related hashes (e.g., "# Issue #999").
    if HASH_NUMBER.is_match(line) {
        return false;
    }

    // Ignore whitelisted comments.
    if ALLOWLIST_REGEX.is_match(line) {
        return false;
    }

    if let Some(first) = line.split(&[' ', ':']).next() {
        if task_tags.iter().any(|tag| tag == first) {
            return false;
        }
    }

    if CODING_COMMENT_REGEX.is_match(line) {
        return false;
    }

    // Check that this is possibly code.
    if CODE_INDICATORS.iter().all(|symbol| !line.contains(symbol)) {
        return false;
    }

    if multiline_case(line) {
        return true;
    }

    if CODE_KEYWORDS.iter().any(|symbol| symbol.is_match(line)) {
        return true;
    }

    let line = PRINT_RETURN_REGEX.replace_all(line, "");

    if PARTIAL_DICTIONARY_REGEX.is_match(&line) {
        return true;
    }

    // Finally, compile the source code.
    parser::parse_program(&line, "<filename>").is_ok()
}
```

https://github.com/charliermarsh/ruff/blob/a82fe4a1397a1e271ead3b7662df0d467f7f4ba3/crates/ruff/src/rules/eradicate/detection.rs#L34-L82


```rust
static CODE_INDICATORS: &[&str] = &[
    "(", ")", "[", "]", "{", "}", ":", "=", "%", "print", "return", "break", "continue", "import",
];
```


https://github.com/charliermarsh/ruff/blob/a82fe4a1397a1e271ead3b7662df0d467f7f4ba3/crates/ruff/src/rules/eradicate/detection.rs#L12-L14

ソースを見ると、コードを含むコメント行かどうかを判定するのに、結構泥臭いことをしているようです。
MSXのディスクイメージを生成するツールを作ってみました

fMSX 形式のディスクイメージ（.dsk）ファイルを作りたかったのですが、Windowsであればフリーソフト（DiskManager や DiskExplorer）を使って作るのが定番らしいです。

ただし、MacやLinuxでそれができる手段（というかCLI）が欲しかったので探してみたのですが、どうやら現時点では存在しないようです。

という訳で作ってみました:

https://github.com/suzukiplan/msx-disk-manager-cli

ただし、色々と腑に落ちない点があります...

例えば、既存のディスクイメージファイルの内容を覗いてみると、FATの情報が誤っているように見えるので、MSXではFATはほぼ使っていなくて、ディレクトリエントリの開始クラスタ位置から必ずシーケンシャルに配置しているだけなのかも...とか。

実のところ、PC上で書いたBASICのコードをエミュレータ上で読み込ませる目的で作ったのですが、どうやらMSX-BASICでSAVEしたファイルには、テキストデータではなく中間言語形式のバイナリデータが保存されるようで、その用途では使えない残念なシロモノです... _（BASICとテキストを相互変換できるフィルタが必要で流石にそれを作るのは面倒くさい）_

**追記: 2023.03.19**

BASICとテキストを相互変換できるフィルタを実装しました。（※BCD浮動小数点数の変換がやや自信なし）

https://github.com/suzukiplan/msx-disk-manager-cli/pull/3
楽天BookAPIで表示した検索結果をデータベースに保存する

1. 序論
今回は楽天APIを用いて、検索結果を表示させる方法と、検索結果の中から一つ選んでデータベースに保存する方法をアウトプットします。

2.Gemfile
今回ユーザーモデルも用いるのでdeviseと楽天API用のrakuten_web_serviceをGemfileに追加してbundle installしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/4aa37844-f51a-2615-d79b-a25fa917e3a3.png)

3.モデル
ユーザーモデルに関してはdeviseを使って実装してください。今回楽天booksAPIと連動させるbook.modelについてですが、以下のように設定し、rails db:migrateしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/d60f8270-5f4c-1cf1-d436-1169fe528e41.png)

次に、ユーザーとbooksは多対多の関係になりうるので、中間テーブルとしてbookcasesを設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/23c3a9af-2b46-ff7c-28ed-98c7a73d5ba7.png)

4.楽天APiの設定
序論においてgemに楽天ウェブサービスを追加した。しかし、これだけではAPIを利用することはできないので追加の設定を行う。
まずは楽天APIのAPIキーを習得してください。以下のリンクを参考にすれば難しくないはずです。

そして、config/initializersにrakuten.rbファイルを作成します。そのファイルの中身は以下のようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/13105448-f429-c620-a55b-838e78018051.png)

ここの書き方はバージョンによって変わるらしく、これが現在の書き方です。

5.検索結果の表示
まずはbooksコントローラを作成します。このコントローラのnewアクションで本を探し、saveボタンを押すとその本を登録できるような形とします。

まずは検索についてです。検索フォームに入力された文字列を@titleに格納し、searchメソッドにて@titleをもとに検索がかけられます。
検索結果はそれぞれnewメソッドで作成され、<<にて空の配列の@booksに収納されます。それがviewページでeach文で表示されるという仕組みになっています。

controller
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/52dee1f1-f8f3-1bba-a33a-d9c99280ff3d.png)

books/new.html.erb
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/37c1c1e8-a7f6-dc1f-bbdd-f1eaf6dd617b.png)

6.データをデータベースに保存する
これで入力されたタイトルから書籍を検索できるようになrました。次は、これをデータベースに保存する方法です。検索結果で表示されていたフォームからhidden_fieldでisbnを習得して、そのisbnで書籍を再度検索して保存するというやり方です。

books.controller
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/3535f412-bb0f-6c14-b978-bc4ddae063aa.png)

books/new.html.erb
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/ebc806bd-1228-cc91-e267-78aca8633c85.png)

books/show.html.erb
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/550afaf3-1b26-88e1-3293-729551c3f173.png)

books/index.html.erb
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3157044/b60398a8-81dc-dd9d-32dd-4bfe69c960b4.png)

7.結論
これで楽天APIを用いて情報を受け取り、データベースに保存することができるようになりました。後の応用としては、userとbookモデルに中間テーブルとしてreviewモデルを作成し、レビューを残すなどといったことができます。こちらはコメント機能を応用すればできると思いますので、いずれ記事にしたいと考えています。
ハックツハッカソンに参加した話

<h1>目次</h1>
1,はじめに<br>
2,開発したもの<br>
3,結果<br>
4,最後に<br>
<h1>はじめに</h1>
3/13~15に北九州で行われたハックツハッカソンに参加させていただきました。
メンバーは大学のプロジェクトメンバー3人。<br>
定員40名の所になんと70名もの応募が来ていました。抽選結果が来る前に飛行機を予約していたので当たるかドキドキでした（笑）
<h1>開発したもの</h1>
私はフロントエンドを担当しました。
今回使用した技術は、フロントHTML/CSS、JavaScript、バックエンドGo、MySQLです。<br>
ハッカソンのテーマが「ふきょう」だったため、推しへの愛を語るプロフィール帳型webアプリを開発しました。ニーズとしては推しへの愛を語れ、同趣向の人を見つけらるという点です。自分が出したアイディアが通ってうれしかったです:relaxed:
<br>
<br>
開発したアプリの概要はこちら

https://topaz.dev/projects/14b289faa0c276c4e464

<h1>結果</h1>
最終的に考えていた機能の3分の1しか実装できませんでした。<br>
今回の反省点はバックエンドとフロントエンドの進捗共有が足りなかった点だと考えています。他にも2日目になると修正などのタスクが増え、それを忘れてしまうことが多かったです。そのためチームで確認し合う時間を設ける必要があると思いました。<br>
今回の良かった点は、figmaで作ってもらったデザインを出来る限りそのままCSSで再現することができた点です。デザインがコーティングのしがいがあったのでとても楽しかったです:fist:
<h1>最後に</h1>
ハッカソンの良いところは日数が決まっており、その期間内はプログラミングに集中できるという点です。普段家だとゲームばかりしてしまう私ですが、ハッカソン中はコードだけとずっと向き合えとても楽しいです。ハッカソン中に完成はできませんでしたが、機会を作りデプロイまで取り組みたいと思っています。<br>
最後に、開催してくだっさったハックツさんと一緒に参加してくれたメンバーに感謝です。
Googleデジタルマーケティング＆Eコマース：モバイルマーケティング

# はじめに

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24ea32fb-2fb3-bdb2-462a-4ffc4d60a96f.png" width="800">

今回は、ソーシャルメディアのオーディエンスをエンゲージする最良の方法の1つである、モバイル・マーケティングについて説明します。

# モバイルマーケティングとは

モバイルマーケティングは、スマートフォンやタブレット端末などのモバイル端末からターゲットユーザーにリーチすることを目的としたデジタルマーケティング戦略です。モバイルマーケティングは、Webサイト、Eメール、ソーシャルメディアなど、さまざまなチャネルを通じてユーザーにリーチすることができます。

ソーシャルメディアとモバイルマーケティングの相性が良いのは、人々がモバイルデバイスからソーシャルメディアコンテンツにアクセスする機会が増えているためです。例えば、2021年7月には、世界中のユーザーの98%以上がスマートフォンからFacebookにアクセスしています。このため、ソーシャルメディアのマーケティング戦略には、モバイルマーケティングを取り入れる必要があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/b21ffd02-df58-e3f6-18ed-2e8aee369bfb.png" width="500">

ソーシャルメディアにおけるモバイルマーケティングには、以下のようなメリットがあります。

- 高いエンゲージメント
- 幅広いリーチ
- コンバージョン率の向上
- 効果的なユーザーターゲティング
- 顧客と個人的なつながりを持つ機会
- 迅速な顧客対応
- ユーザーが作成したコンテンツへのアクセス
- 簡単な結果追跡

# モバイル・ソーシャルメディア・マーケティングのヒント

ここでは、ソーシャルメディア・マーケティング戦略にモバイル・マーケティングを取り入れるためのヒントを紹介します。

### <font color="MediumBlue">モバイルフレンドリーな投稿の作成</font>

デスクトップで見栄えのする記事を作成しても、それがモバイル端末でも見栄えがするとは限りません。レイアウトや画像をすべてモバイルでテストし、記事中のリンクがモバイル用に最適化されたランディングページにつながることを確認してください。

また、文章を作成する際にも、モバイルユーザーを念頭に置く必要があります。一般的に、ユーザーは携帯電話で長い記事を読みたがらないので、短い記事を作成することに重点を置きましょう。


### <font color="MediumBlue">ビデオの統合</font>

ユーザーは、モバイル端末で他のタイプのコンテンツよりも動画に興味を示すので、投稿に頻繁に動画を含めるようにしましょう。とはいえ、携帯電話を使用しているときの人々の注意力は短いものです。そのため、動画の冒頭で重要なポイントや製品の特徴を強調し、15秒から30秒以内の短い動画にすることを心がけましょう。

ライブビデオは、モバイル・マーケティングにおけるもう一つの魅力的なオプションです。Facebook、YouTube、Instagram Live、その他のプラットフォームで、あなたのビジネスをライブで放送し、関心とエンゲージメントを生み出すことができます。


### <font color="MediumBlue">お客様にチェックインをお願いする</font>

ソーシャルメディア上でお客様に「チェックイン」してもらうことは、アーンドメディアを獲得するための素晴らしい方法です。チェックインすることで、お客様のソーシャルメディア上の友人やフォロワーに、お客様のビジネスをひいきにしていることを知らせることができます。割引、クーポン、特典プログラムなどのインセンティブを提供することで、お客様のチェックインを促すことができます。

### <font color="MediumBlue">ユーザー作成コンテンツの奨励</font>

ユーザー生成コンテンツ（UGC）とは、ブランドではなく、人々によって作成されたあらゆる種類のコンテンツのことです。実際の顧客が作成したコンテンツは、本物であり、信頼できると感じられるため、人々に喜ばれています。このため、ユーザー生成コンテンツは、ソーシャルメディアのエンゲージメント率を高めるのに役立ちます。

また、ユーザー生成コンテンツは、お客様がモバイル端末から作成し、ソーシャルメディアに投稿するのに便利です。ユーザーにUGCの投稿を促すために、製品やサービスを使っている自分の写真や動画を投稿するコンテストを実施することもできます。


### <font color="MediumBlue">インフルエンサー・マーケティングの活用</font>

[インフルエンサー・マーケティング][ref]とは、ブランドがオンライン・インフルエンサーとコラボレーションして、製品やサービスを販売することである。モバイルマーケティングは、インフルエンサーが遠隔でブランドのプロモーションを行うことができるため、便利です

インフルエンサーとのコラボレーションを構築するには、ターゲットとなるオーディエンスと同じプラットフォームを使用し、フォロワーとの結びつきが強いインフルエンサーを見つけることです。

[ref]: https://qiita.com/mapami/items/2b40540bce9b7623aa3e
Googleデジタルマーケティング＆Eコマース：インフルエンサー・マーケティング

# はじめに

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24ea32fb-2fb3-bdb2-462a-4ffc4d60a96f.png" width="800">

# インフルエンサー・マーケティングとは

インフルエンサーマーケティングとは、ブランドがオンライン・インフルエンサーとコラボレーションして、製品やサービスを販売することです。

2021年だけでも、ブランドはインフルエンサーマーケティングに138億ドルを費やすと推定されています。

# インフルエンサーのカテゴリ

インフルエンサーは、あらゆる業界やテーマに及んでいます。美容、アート、デザイン、食品など、さまざまな分野のインフルエンサーがいます。今日、誰でもインフルエンサーになることができますが、必要なのは、ソーシャルメディアのフォロワーが多いこと、そして（あるいは）従事していることです。

インフルエンサーのフォロワー数は、そのカテゴリーを決定します。

| カテゴリ | フォロワー数  | 
| :--- | :--- | 
| ナノインフルエンサー | 10,000人以下 | 
| マイクロインフルエンサー | 10,000人以上10,000人以下 | 
| マクロインフルエンサー | 10万人以上100万人以下| 
| メガインフルエンサー | フォロワー数100万人以上 | 

# インフルエンサー・マーケティングの重要性

インフルエンサー・マーケティングは、ソーシャルメディア上で大成功を収めており、ソーシャルメディアを活用して収益を上げようとするブランドにとって、重要な戦術となっています。

インフルエンサーマーケティングハブによると、Instagramのブランドの67%がインフルエンサーマーケティングを利用しています。

最近のベンチマークレポートで、インフルエンサーマーケティングハブは、インフルエンサー・マーケティングに費やした1ドルに対して平均5.78ドルの投資収益率（ROI）があることを示しました。

# インフルエンサーの選択

メガインフルエンサーと提携するのが最もブランドにとって効果的と思われるかもしれませんが、多くの場合、フォロワー数の少ないインフルエンサーの方がエンゲージメントが高いのです。

- 例えば、マイクロインフルエンサーのエンゲージメントが3.86%であるのに対し、メガインフルエンサーのエンゲージメントは1.21%に過ぎないとされています。

エンゲージメント、コンバージョン、売上、フォロワーの増加を目的としたキャンペーンを実施する場合、ターゲット層に沿ったフォロワー数の少ないインフルエンサーの利用を検討すると、より高いエンゲージメント率を得ることができます。

しかし、キャンペーンの目標が一定の閲覧数やインプレッション数を達成することである場合は、多くのフォロワーを持つインフルエンサーをターゲットにするとよいでしょう。

:::note info
目標に関わらず、インフルエンサー候補のリサーチは必ず行ってください。彼らのソーシャルメディアアカウントを監査したり、彼らに連絡を取って、関心のある指標を尋ねたりしてください。
:::

# インフルエンサー・マーケティングの計画

すべてのマーケティングに言えることですが、インフルエンサー・マーケティングの計画を立てる際には、整理整頓と細部へのこだわりが必要になってきます。インフルエンサーのリサーチと選定が終わったら、戦略、予算、スケジュールを作成します。そして、そのプランをインフルエンサーに提示します。

インフルエンサーの計画を立てる際には、広報活動、イベント、製品リリースと連動させるようにしましょう。

:::note info
あなたとインフルエンサーはそれぞれのビジネスを代表していますが、個人対個人の会話であることを忘れないでください。パートナーになることのメリットについてオープンに話し合い、懸念事項がある場合は、外交的に対応しましょう。
:::
JAVAソースでプロジェクト「UTF-8」から「MS932」変換

備忘録
JAVAソースでプロジェクト「UTF-8」から「MS932」変換
```
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class test {

	public static void main(String[] args) {
		changeCharset("c:\\test\\test", "utf-8", "MS932");
	}

	public static void changeCharset(String fileNmae, String fromEncoding, String destEncoding) {
		System.out.println("変換開始" + System.currentTimeMillis());
		File src = new File(fileNmae);
		File dest = new File(src + File.separator + "toCharsetFile");

		if (!dest.exists()) {
			// 「toCharsetFile」ディレクトリを生成
			boolean mkdirs = dest.mkdir();
		}

		changeFileEncode(src, fromEncoding, dest, destEncoding);
		System.out.println("変換終了" + System.currentTimeMillis());
	}

	/**
	 * 元フォルダのファイルの文字コードを必要な文字コードに変換後、<br>
	 * toCharsetFileフォルダ生成
	 *
	 * @param src 元のファイルORフォルダ
	 * @param fromEncoding 元のm文字コード
	 * @param dest　変換後のファイルORフォルダ
	 * @param destEncoding　変換後の文字コード
	 */
	public static void changeFileEncode(File src, String fromEncoding, File dest, String destEncoding) {

		File[] files = src.listFiles();
		if (files != null) {
			for (File file : files) {
				// ディレクトリである場合
				if (file.isDirectory()) {

					File destDir = null;
					// 親の絶対パス取得
					String path1 = file.getParentFile().getAbsolutePath();
					path1 = path1.replace("\\", "/");

					//自分の絶対パス取得
					String path2 = file.getAbsolutePath();
					path2 = path2.replace("\\", "/");

					String[] fname = path2.split(path1);
					for (String s : fname) {
						// sが空ではない場合
						if (!"".equals(s)) {
							// インデックス１からの文字列である文字列を返す
							s = s.substring(1);
							destDir = new File(dest + File.separator + s);
						}
					}

					if (destDir.getName().contains("toCharsetFile")) {
						return;
					}
					assert destDir != null;
					if (!destDir.exists()) {
						boolean b = destDir.mkdir();
					}
					changeFileEncode(file, fromEncoding, destDir, destEncoding);

					// ファイルの場合
				} else if (file.isFile()) {

					// 親の絶対パス取得
					String path1 = file.getParentFile().getAbsolutePath();
					path1 = path1.replace("\\", "/");

					//自分の絶対パス取得
					String path2 = file.getAbsolutePath();
					path2 = path2.replace("\\", "/");

					String[] fname = path2.split(path1);
					File javaFile = null;
					for (String s : fname) {
						javaFile = new File(dest, s);
					}

					try {
						BufferedReader br = new BufferedReader(
								new InputStreamReader(new FileInputStream(file), fromEncoding));
						assert javaFile != null;
						BufferedWriter pw = new BufferedWriter(
								new OutputStreamWriter(new FileOutputStream(javaFile), destEncoding));
						String s;
						while ((s = br.readLine()) != null) {
							pw.write(s);
							pw.newLine();
						}
						pw.flush();
						pw.close();
						br.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}

```
Java_整数と文字列 (paizaランク D 相当)

```Java:C-#08
// 整数nと、n個の整数a_1,...,a_nが改行区切りで入力されたとき、各a_i(1 ≤ i ≤ n)の文字列としての長さを改行区切りで出力するプログラム
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
        Scanner sc = new Scanner(System.in);
        int line = sc.nextInt();

        for (int i = 0; i < line; i++) {
            // 文字列はStringクラスのオブジェクト
            String numberLetter = new String(sc.next());
            System.out.println(numberLetter.length()); // lengthメソッドで文字数を調べられる
        }
    }
}
```
SfopifyのテーマDawnでFAQページを作ったときに、ページタイトルとコンテンツが表示されなった

こちらの記事を読み、ShopifyのテーマDawnでFAQページを作ったとき、ページタイトルとコンテンツが表示されていないことに気が付きました。

https://ikdlog.com/faq-template/

この記事を読み、FAQページを追加できました。
でも、ページタイトルとコンテンツが表示されていないことに気が付いたのです。

ブラウザのデベロッパーツールを使い、該当する場所のクラス名を調べました。
そして、下記のコードをfaq-template.liquidに追記しました。

```html
<div class="collection-hero color-background-1 gradient">
  <div class="collection-hero__inner page-width">
    <div class="collection-hero__text-wrapper">
      <h1 class="collection-hero__title">{{ page.title }}</h1>
      {{ page.content }}
    </div>
  </div>
</div>

```
このコードで、最低限テーマのCSSが反映されて、ページタイトルと、コンテンツを表示できます。
ページタイトルとコンテンツは、Shopifyの管理画面のテーマからページの編集のところで、自由に入力できます。
![スクリーンショット 2023-03-17 135931.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/6402d383-c89a-5ee3-6434-e143c87d15f4.png)


テーマDawn以外の場合は、クラス名を確かめてから試してみてください。

## 他のsectionで、FAQを使いたい場合
下記のように、スキーマの部分を書くと他のsectionで、追加できるようになります。
```json
{% schema %}
{
  "name": "FAQ",
  "settings": [],
  "blocks": [
    {
      "type": "question",
      "name": "質問",
      "settings": [
        {
          "type": "text",
          "id": "question",
          "label": "質問タイトル"
        },
        {
          "type": "richtext",
          "id": "answer",
          "label": "答え"
        }
      ]
    }
  ],
  "presets": [
    {
      "name": "FAQ",
      "category": "Custom"
    }
  ]


}
{% endschema %}
```
presetsという項目を追加すると、他のsectionで追加できるようになります。
参考記事は、こちらです。

https://www.ma-vericks.com/blog/shopify-add-sections/

## 制作したFAQページでは、セクション追加ができない
冒頭でご紹介したFAQページの作り方では、ウェブのテーマエディタでセクション追加ができないです。
そのため、セクション追加ができるように、上記の記事のようにJSONの拡張子でテンプレートの中にファイルを作り、sectionにも追加する方法が良いと思います。