OmniAICreator/Qiita-1.07M huggingface dataset:
Next.jsにおける認証

認証はユーザーが誰であるかを検証し、承認はユーザーがアクセスできるものを制御します。 Next.js は複数の認証パターンをサポートしており、それぞれが異なるユース ケース向けに設計されています。このページでは、制約に基づいて選択できるように、それぞれのケースについて説明します。

## 認証パターン
必要な認証パターンを特定するための最初のステップは、必要なデータ取得戦略を理解することです。次に、どの認証プロバイダーがこの戦略をサポートしているかを判断できます。主に次の 2 つのパターンがあります。

- 静的生成を使用して、ロード状態をサーバーでレンダリングし、続いてクライアント側でユーザー データをフェッチします。
- ユーザー データをサーバー側でフェッチして、認証されていないコンテンツのフラッシュを排除します。

## 静的に生成されたページの認証
Next.js は、ブロッキング データ要件がない場合、ページが静的であると自動的に判断します。これは、ページに getServerSideProps と getInitialProps がないことを意味します。代わりに、ページはサーバーからの読み込み状態をレンダリングし、続いてクライアント側でユーザーを取得できます。

このパターンの利点の 1 つは、ページをグローバル CDN から提供し、next/link を使用してプリロードできることです。実際には、これにより TTI (Time to Interactive) が速くなります。

プロフィールページの例を見てみましょう。これにより、最初に読み込み中のスケルトンがレンダリングされます。ユーザーのリクエストが完了すると、ユーザーの名前が表示されます。
```
// pages/profile.js

import useUser from '../lib/useUser'
import Layout from '../components/Layout'

const Profile = () => {
  // クライアントサイドでユーザの取得
  const { user } = useUser({ redirectTo: '/login' })

  // サーバレンダリングの読み込み状態
  if (!user || user.isLoggedIn === false) {
    return <Layout>Loading...</Layout>
  }

  // リクエスト終了後、ユーザに表示
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile
```
この例を実際に見ることができます。 with-iron-session の例をチェックして、それがどのように機能するかを確認してください。

## サーバーでレンダリングされたページの認証
ページから getServerSideProps という非同期関数をエクスポートする場合、Next.js は、getServerSideProps によって返されたデータを使用して、リクエストごとにこのページを事前にレンダリングします。

```
export async function getServerSideProps(context) {
  return {
    props: {}, // プロパティとしてページコンポーネントに渡されます
  }
}
```
サーバー側のレンダリングを使用するようにプロファイルの例を変換してみましょう。 セッションがある場合は、ユーザーをプロパティとしてページの Profile コンポーネントに返します。 この例にはロード スケルトンがないことに注意してください。
```
// pages/profile.js

import withSession from '../lib/session'
import Layout from '../components/Layout'

export const getServerSideProps = withSession(async function ({ req, res }) {
  const { user } = req.session

  if (!user) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    }
  }

  return {
    props: { user },
  }
})

const Profile = ({ user }) => {
  // Show the user. No loading state is required
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile
```
このパターンの利点は、リダイレクト前に認証されていないコンテンツのフラッシュを防止できることです。 getServerSideProps でユーザー データを取得すると、認証プロバイダーへの要求が解決されるまでレンダリングがブロックされることに注意してください。 ボトルネックを作成して TTFB (Time to First Byte) を増加させないようにするには、認証ルックアップが高速であることを確認する必要があります。 それ以外の場合は、静的生成を検討してください。

## 認証プロバイダー
認証パターンについて説明したので、特定のプロバイダーを見て、それらが Next.js でどのように使用されているかを調べてみましょう。

- Auth0
- Clerk
- Firebase
- Magic
- Nhost
- Ory
- Supabase
- Supertokens
- Userbase


公式ドキュメント→[Authentication](https://nextjs.org/docs/authentication)
EmacsからQiitaの記事投稿用にAtomic Chromeを再導入

おおよそ1年ぶりにQiitaに投稿しようとしたら以前は出来たコピペができなくなっている。

Emacsのクリップボードの設定ミスを疑って調べたけれど問題ない。Qiitaの仕様が変更されたのかどうかはわからないが、ダイレクトで記事を書くなんてことは考えられない。みんなどうしてるんだろう？

はてさてと悩んで、前に使った `atomic-chrome` を再導入してみた。結果はGood！
 Chrome側の拡張機能は、atomic-chrome-extensions だったと記憶していたのだけれど見当たらず、
[Ghost Text](https://chrome.google.com/webstore/detail/ghosttext/godiecgffnchndlihlpaajjcplehddca) に置き換わったみたい。このあたりは下記Tipsに詳しい。

* [atomic-chrome再訪](https://qiita.com/iwaokimura/items/4932e0f8dcfd55c4556c) 

## Emacsの設定
取り急ぎ下記の設定で試したところ快適にコピペ出来た。

```emacs-lisp
;; atomic-chrome
(leaf atomic-chrome
  :ensure t
  :hook (after-init-hook . atomic-chrome-start-server)
  :custom (atomic-chrome-buffer-open-style . 'full))
```
`atomic-chrome-start-server` が結構起動時間を消費するので、`after-init-hook` で遅延起動している。また、Splitバッファーで表示されるデフォルトのスタイルが気に入らなかったので `full window` に変更している。
plt.subplots()のaxesをfor文1つでイテレーションする

# 概要
fig, axes = plt.subplots(2,3)のaxesの要素にfor文でアクセスするとき，普段なら，
```python
for i in range(2):
    for j in range(3):
        axes[i, j]
```

とするが，これを
```python
for i in range(6):
    axes[i]
```
のようにfor文1つでアクセスする方法を考えた．

# TL;DR
for文の前にaxes = axes.reshape(-1)を置くだけ
```python
fig, axes = plt.subplots(2, 3)

axes = axes.reshape(-1)

for i in range(6):
    ...
```
axesは単なる二次元配列なので，1次元にしてやればよい．

# 例
ランダムな周波数で10個のサイングラフを生成する．
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#サンプルデータ生成
data_size = 10
f = np.random.randint(1, 10, data_size)
t = np.arange(0, 10, 0.01)
data = [np.sin(2*np.pi*i*t) for i in f]

fig, axes = plt.subplots(5, 2)

#ここでaxesの配列を1次元にする
axes = axes.reshape(-1)

fig.tight_layout()

for i, datum in enumerate(data):
    axes[i].plot(data[i])
plt.show()
```
結果
![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483686/4ef84067-b8b5-a243-63e8-ba3d9974a632.png)
【2022年版】【AWS EC2】Amazon Linux2にMySQLのclientだけをインストールする方法

Amazon Linux2にMysqlClientをインストールする方法です。
対象はEC2　Amazon linux2のx86/64です。


```bash
sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum-config-manager --disable mysql57-community
sudo yum-config-manager --enable mysql80-community

rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

sudo yum install mysql-community-client

```
鍵が古いと警告が出るようですので、`rpm --import`が必要なようです。

```
[ec2-user@hogehoge-ec2 ~]$ mysql --version
mysql  Ver 8.0.31 for Linux on x86_64 (MySQL Community Server - GPL)
```

以下を参考にさせていただきました。

https://qiita.com/tamorieeeen/items/d9b2af588f1dfd43120d
APKファイルの作成方法

#はじめに
androidアプリの開発でマストになるのがAPKファイルの作成です。

・APKでなにができるのか
・具体的にどうすれば作成できるのか

まとめました。

#APKファイルでなにができるのか？

Androidアプリケーションを格納することができる実行ファイルです。
AndroidOSでAPKファイルを実行すると、格納されたAndroidアプリケーションが実行されます。
現在開発中のアプリを端末で実際に動作確認する事ができます。

#具体的にどうすれば作成できるのか
Androidアプリ開発の際にはAndroid studioという統合開発環境を利用するのが一般的ですが、
そちらにAPKを作成する機能があります。

1.ヘッダーメニューから「Build」を選択し、「Generate Signed Bundle/APK...」を選択します。

Android
[スクリーンショット 2022-10-12 11.33.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2915524/abc567d0-7f7c-5111-eaa2-680415a63c35.png)

2.APKを選択します。

![スクリーンショット 2022-10-12 11.35.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2915524/57db0b56-6527-2cbb-905e-fd866f7e8300.png)

3.続けてkeystore pass,keypassを入力します。
初めてアプリを作成する場合は設定する必要があります。

4.今回作成したいアプリのbuild variant 選択し、finishを押します。

以上です！

作成したAPKをメールで添付するなり、OTAでwebページから配布するなりの方法で端末に移せば、
自分の開発中のアプリを端末にインストールすることができます。
[長期運用]Pythonを使って、平均と標準偏差から将来の株価を予測する[30年で8倍？]

## はじめに
普通将来の株価を考えるとき、年率7%で30年運用したら、1.07の30乗を計算して約7.6倍と計算しますよね。

でも、年率ってマイナスのときも10%を超えるときもありますよね？
GPIFのウェブサイトにはこう書かれています。

> 運用の世界では一般的に、株式や債券など各資産のリスクを、リターンの「標準偏差」を使って表します。「標準偏差」とはリターンのブレの大きさを表す数値で、標準偏差が大きい（リスクが高い）ほど、リターンのブレ幅が大きいことを意味します。

では、30年運用したとき何倍になるかをシミュレーションするときも、年率はブレを含むべきでないでしょうか。
## 予想
増えたり、減ったりして、7.6倍に収束するんじゃないかな。
悪くて1.5倍、よくても10倍とか

## 設定
- 年率が平均7.0%、標準偏差25％の正規乱数に従うとする
    - [分散投資の意義② 投資のリスクとは](https://www.gpif.go.jp/gpif/diversification2.html)より
    - 各年の年率は独立試行とする
- 30年間運用するとする
- 100回試算する


## 一回試算してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/2985d5e4-8843-e14e-6de4-dc5ecb9c8be6.png)
こんな感じの株価グラフ見たことありますよね！
25年後にリーマンショック級の不況が起こったのでしょう。
最終的な値は16なので、30年で資産が16倍になりました。
100万円を運用していたら、1600万円です。ウハウハですね！！
でも、7.6倍とは大きく離れていることが気になります。

## 100回試算してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/0b662819-b0f3-4410-bc73-4573261f20a0.png)
思ったより、30年後のばらつきが大きいですね。
対数軸を使って、やっと全体像が把握できます。
```
ave:6.59
max:55.65
min:0.11
std:9.28
```
なんと1倍以下、つまり元本割れする場合もありました。
100万円を運用したら、最小で11万円、最大で5565万円になります。
恐ろしいですね。
予想より、ばらつきが大きいです。
平均が6.59倍なのは、1.07の30乗と大体一致しますね。
100回の試算中、元本割れを起こしたのは15回でした。

## 考察
- 株価の変化が正規分布に従うとは考えにくい
    - キャピタルゲインとインカムゲインがある
- 各年の株価の変化が独立試行というのも現実に即していない
- [GPIFのウェブサイト](https://www.gpif.go.jp/gpif/long-term-vision.html)によると、海外株式を50年運用していたら54倍になった
    - よって、今回のシミュレーションの結果も妥当といえる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/cc1d6914-5967-384d-3f3a-98bcdaba29da.png)


## 結論
高リスク高リターンの商品だと、長期に運用したところで100％安全というわけではないようです。
投資は生活に関係ない資金を使うのが本当大事ですね。
必ず利益が出ると思って、その利益を当てにすると痛い目を見そうです。

にしても、30年で55倍は夢がありますね

積み立てだと、どれだけリスクが下がるのかも検証してみたいです。
複利で長期運用って、いい意味でも悪い意味でも恐ろしいですね。
Pythonのloggingモジュールを使用してログ出力する際のTips

Pythonのloggingモジュールを使っているうちに知見が溜まってきたので記事にします。

## 設定はfileConfigよりdictConfigで行う

ログレベルやフォーマッタ等の設定を行う際、fileConfig関数とdictConfig関数が利用できる。

https://docs.python.org/ja/3.8/library/logging.config.html

dictConfig関数の方が柔軟に設定を行うことができる。

使用例

```py
from logging import getLogger
from logging.config import dictConfig

CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "default": {
            "format": "%(asctime)s %(name)s %(levelname)-5s: %(message)s"
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "default",
        },
    },
    "root": {
        "level": "INFO",
        "handlers": ["console"],
    },
}

logger = getLogger(__name__)


if __name__ == '__main__':
    dictConfig(CONFIG)
    logger.info('hello')
```

出力項目を追加したりできる(fileConfigには無い機能)
```py
from logging import getLogger, Filter
from logging.config import dictConfig

import flask


class IpAddressFilter(Filter):
    """クライアントのIPアドレスをログレコードに追加"""
    def filter(self, record):
        record.remote_addr = flask.request.headers.get('REMOTE_ADDR')
        return True

CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "default": {
            "format": "%(asctime)s %(name)s %(remote_addr)s %(levelname)-5s: %(message)s"
        }
    },
    "filters": {
        "addr": {
            "()": IpAddressFilter,
        }
    }
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "default",
            "filters": ["addr"],
        },
    },
    "root": {
        "level": "INFO",
        "handlers": ["console"],
    },
}

app = flask.Flask(__name__)
dictConfig(CONFIG)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
```


## ロガー設定はモジュールレベルでは行わない

pytestでcaplogを使用してログ出力のテストをする際、テスト対象モジュールをimportするだけでdictConfigやfileConfigによるロガー設定が行われてしまうと、正しくcaplogが動作しない。

dictConfigやfileConfigによるロガー設定はできる限り実際のプログラムとして起動する場合のみ行う。

### mainで起動するコマンドラインツールの場合

```py
...

if __name__ == '__main__':
    dictConfig(CONFIG)
    main()
```

### FlaskやFastAPIなどのアプリケーション変数初期化を行う場合の例

main.py
```py
...
app = create_app()
dictConfig(CONFIG)

# $ export FLASK_APP=main
# $ flask run
```

app.py
```py
def create_app():
    return Flask('app_name')
```

tests/fixtures/app.py
```py
@fixture
def client():
    """テストクライアント"""
    app = create_app()
    app.config['TESTING'] = True
    with app.test_client() as client:
        yield client
```
【Swift】サーバーから送られてきた不正なURLをデコードするためのPropertyWrapper

# TL;DR

空文字列or不正なURL表現を許容するCodable変換のためのPropertyWrapperを作った．

# 課題

サーバーなど送られてきたJSONをCodableで変換するとき，以下のようなJsonが送られてくると失敗してしまう．このJSONは，avatarが未設定の場合などを想定している．以下のstructに渡してやれば動きそうだが，実際にはURLに空文字列（`""`）を渡すとエラーが起きてしまう．

```Json
{
    "id": "12345userid",
    "name": "Yamada Taro",
    "avatarUrl": ""
}
```

```Swift
struct User: Codable {
    var id: String
    var name: String
    var avatarUrl: URL?
}
```


# 解決

以下のようなPropertyWrapperを作った．これによって不正なURLを許容するための専用Decoderを作る必要がなくなる．

```Swift
@propertyWrapper
struct AllowEmptyURL: Codable {
    var wrappedValue: URL?
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        wrappedValue = try? container.decode(URL.self)
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(wrappedValue)
    }
}
```

```Swift
struct User: Codable {
    var id: String
    var name: String

    @AllowEmptyURL
    var avatarUrl: URL?
}
```

## 解説

decodeする際にはPropertyWrapperのinitが呼ばれる．その際に`try?`にしてやることで例外発生時には`nil`が渡されるようになっている．encodeメソッドはdecodeするだけなら不要だが，書いておかないとencodeしたくなったときにおかしくなるので注意が必要．
javascriptのObject.defineProperty()について

# Object.defineProperty()とは
あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返します。（出典：[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty)）

と言っても何がいい害かわからないので、実際にコードを書いてみることにする。


# 書き方
```javascript:javascript
const obj = {
    age: 12
}
const descriptor = {
    value: "john",
    writable: true
}

Object.defineProperty(obj, 'name', descriptor)
console.log(obj.name) // "john" 
```
ほぼmdnでの例文で数字を変えただけであるが、今何が起きているのかを一つつづ説明すると...


#### ① オブジェクトの宣言
```javascript:javascript
const obj = {
    age: 12
}
```
ここではageというkeyを持つオブジェクトを宣言した。
ここにnameというkeyを持つプロパティを追加するにはどうすれば良いか。
その時使うのがdefineProperty()である。
言葉そのどおり、プロパティを宣言するメソッドである。


#### ② defineProperty()の引数を入れる
```javascript:javascript
Object.defineProperty(<対象となるオブジェクト>, <プロパティ名>, <プロパティの詳細>)
```
引数は３つまで入れることができ、それぞれ「対象となるオブジェクト」、「プロパティ名」、「プロパティの詳細」を入れることができて、全て必須である。
なおこのメソッドの返り値は対象となるオブジェクトそのものとなる。

# descriptorについて
```javascript:javascript
const descriptor = {
    value: "john",
    writable: true,
    enumerable: false,
    configurable: true
}
```
descriptorは例文に書いてあるvaleやwritable以外にenumerableとconfigurableがあり、value以外は全てbooleanになる。
書く項目については以下の通りである。

#### value
プロパティに対する値を意味する。
例文では"name"というプロパティに"john"という値を指定

#### writable
ここがfalseの場合、該当のプロパティはreadonlyになる

#### enumerable
ここがfalseの場合、該当のプロパティをループ（for文やObject.keys()を利用すること）させることができない

#### configurable
ここがfalseの場合、該当のプロパティを再定義することができない


# Getterの設定
definePropertyではオブジェクトにgetterとsetterを設定することもできる。
まず、getterの設定方法は以下の通りである。

```typescript:typescript
type NameObj = {
    firstName: string
    lastName: string
    fullName?: string
}

const user = {
    firstName: "Steven",
    lastName: "Spielberg"
}
const myUser:NameObj = Object.defineProperty<NameObj>(user, 'fullName' , {
    get: () => `${user.firstName} ${user.lastName}`,
})

console.log(myUser.fullName) // "Steven Spielberg" 
```

上記では、`NameObj`というオブジェクトに`defineProperty`を用いてgetterプロパティを追加した例である。
`defineProperty`の第一引数に渡されたオブジェクトに`fullName`というgetterを追加することにより、`firstName`と`lastName`を一つにした`fullName`を出力することができる。同じやり方でsetterをつけることも可能である。

```typescript:typescript
type NameObj = {
    firstName: string
    lastName: string
    fullName?: string
}

const user = {
    firstName: "Steven",
    lastName: "Spielberg"
}
const myUser:NameObj = Object.defineProperty<NameObj>(user, 'fullName' , {
    get: () => `${user.firstName} ${user.lastName}`,
    set: (value: string) => {
        [user.firstName, user.lastName] = value.split(' ')
    }
})

myUser.fullName = 'James Cameron'
console.log(myUser.fullName)
```
違いは`set`プロパティを追加し、分割代入で`firstName`と`lastName`を代入していることがわかる。
そして、getterプロパティを使って、代入された値を取り出している仕組みである。
こうすることで、値の保持と管理を分けることが可能である。
GraphQLとSQL

# GraphQLとは
GraphQLとはMeta(Facebook)が開発する問い合わせ言語です。
https://graphql.org/

# SQLとは
SQLはRDBMSの操作を行う問い合わせ言語です。

# 二つの関係
はっきりいってこの二つは全くの別物です。GraphQLとSQL名前が似ているから一緒のような物だろうと思って使うと痛い目にあうと言われています。

# 図解
簡易的なTwitterを作るとして、Tweetを取得するQueryを考えましょう
```graphql
scalar Date

type tweet {
  Tweetid: ID!
  Text: String!
  Imageurl:String!
  User: User!
  CreatedAt: Date!
  UpdatedAt: Date!
}

type User{
  Userid: ID!
  Name: String!
}

type Query {
  Tweet(argument: TweetId!): Tweet!
}
```
ではこれをそのままtableにするとどうなるでしょうか。

## 悪い例
Tweetのtypeをそのままtableにすると下記のようになると思います。このtableは冗長であまり良くないです。
![mermaid-diagram-2022-10-12-161348.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128363/bb87503f-b021-d47f-c916-f150bee10479.png)



## 改善
TweetとUserのtableは分けてtweetはUseridだけを持たせることがセオリーでしょう。

![mermaid-diagram-2022-10-12-161647.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128363/116db5d8-62fe-fc03-5b94-81fa988e4713.png)

# GraphQLとSQLの変換
先ほど提示したTweetのQueryを処理しようとするとどうなるでしょうか

```graphql
query tweet{
    Tweet(argument:"12345"){
        Text
        User{
            Name
            UserId    
        }
    }
}

```
上記のqueryを処理するとき、SQLでどのような処理をすべきでしょうか？

```sql
    SELECT * FROM tweet inner join user on tweet.Userid = user.userid WHERE tweet.Tweetid = "12345" 
```
このような呼出をすれば、
![mermaid-diagram-2022-10-12-161348.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1128363/bb87503f-b021-d47f-c916-f150bee10479.png)
DB上でこのようなtableを擬似的に作ることができます。(これをviewとして定義しておくのも◯)


# 最後に
DBの設計は使用用途によってさまざまです。今回紹介したやり方も一例です。GraphQLとSQLを正しく理解する一助になればなと思います

# 参考
上記のtableの図はマーメイド記法で書きました。

https://qiita.com/hirokiwa/items/7a9ae5fb87958783bd82
Firebase AuthenticationでGoogleログインのphotoURLを元に戻す

# 事象
FirebaseのAuthenticationでGoogleログインを実装した際に、photoURLプロパティを読み込むとGoogleアカウントに紐づいたプロフィール画像のURLを取得することができる。
updateProfileメソッドを使うとphotoURLを上書きすることができるが、間違えて上書きをして画像をもとに戻すことができなくなった。

# 試みたこと
Firebase Authentication + reset、restore、リセット、初期化などのキーワードで検索するもヒットせず

# 解決方法
### 自身のGoogleアカウントの場合
ブラウザから当該アカウントでログインしたときに表示されるプロフィール写真を右クリック->画像アドレスのコピー からGoogleアカウントのプロフィール画像URLを取得することができる。

取得したURLで再度updateProfileメソッドでphotoURLを上書きすると元のプロフィール画像のURLが取得できるようになる。

### 自分以外のGoogleアカウントの場合
Admin SDKからユーザーのuid等をもとに取得できる？

# お願い
プログラムの内部の処理で初期化する方法をご存じでしたらコメントいただけますと幸いです。
divとspanの違いとは？

# ```<span>```とは
「SPAN」とは、単体では特に意味を持たないタグですが、```<span>～</span>```で囲った部分をインライン要素としてグループ化することができるタグです。
グループ化することで、指定した範囲にスタイルシートを適用したりすることができます。

同じ意味を持つタグとして<div>がありますが、```<div>はブロックレベル要素としてグループ化を行います```ので、```見出しや段落、リストなどとしてみなされ前後に改行```が入ります。
```<span>はインライン要素で文章の一部として利用されます```ので前後に改行は入りません。

## 出典 
https://html-coding.co.jp/annex/dictionary/html/span/
ServiceNow Notificationの宛先に関する仕様調査

# Notificationの宛先に関する仕様調査
Notificationで宛先を設定する際の仕様について調べました。弊社ブログへも[同様の記事を投稿](https://alpcom.co.jp/blog/20221012/?utm_source=Qiita&utm_medium=post&utm_campaign=ysi&utm_id=20221012)しております。

##### ①Event起動でParameterを宛先にする際、設定可能な内容
以下3つが使用可能なようです。
<dl>
  <dt>・Userレコードのsys_id</dt>
  <dt>・Groupレコードのsys_id</dt>
  <dt>・アドレスべた書き</dt>
</dl>
以下サンプル

```javascript
        // Userレコードを宛先として指定
        gs.eventQueue('event名', Notification対象のGlideRecord, sys_userのsys_id);

        // Groupレコードを宛先として指定
        gs.eventQueue('event名', Notification対象のGlideRecord, sys_user_groupのsys_id);

        // アドレスべた書きで宛先指定
        gs.eventQueue('event名', Notification対象のGlideRecord, "betagaki@address.com");
```

##### ②Event起動でParameterを宛先にする際、複数宛先を設定する方法
配列を作成して、最終的に.toStringしたものを渡せばＯＫです。
以下サンプル

```javascript
    // 宛先ユーザーを配列に追加
	var sendList = [];
	var user = new GlideRecord("sys_user");
	user.addQuery("department.name", "Sales");
	user.query();
	while(user.next()){
        sendList.push(user.sys_id + "");
    }

    // 配列に入れたユーザー達を宛先としEvent起動
    gs.eventQueue('event名', Notification対象のGlideRecord, sendList.toString());
```

ちなみに、①で記載した３つの内容が混在した配列でも問題なく送付できました。

##### ③Groupを宛先に設定する際の挙動
Groupを宛先にする場合、
もしそのGroupレコードにメールアドレスが設定されていなければ、そのGroupの所属メンバー全員が宛先として自動設定されます。
もしそのGroupレコードにメールアドレスが設定されていれば、そのメールアドレスのみが宛先となり、所属メンバーのアドレス宛には送付されません。その場合、もし所属メンバー宛にも送付したければGroupレコードのInclude Membersカラムをtrueにすれば所属メンバーのアドレスも宛先に含める事が可能です。
<img width="950" alt="noti01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707437/2863f068-c86a-efee-2a45-ac6d6cb4396d.png">

##### ④宛先としたUser/Groupレコードにメールアドレスが設定されていなかった際の挙動
宛先にしたUser/Groupの全てにメールアドレスが設定されていなかった場合、そのメール送付はスキップされます。
逆に言うとどれか1つの宛先にさえアドレス設定されていれば、仮に10件指定した宛先のうち9件がアドレスブランクであっても、存在する1件向けに送付はされる事となります。
npm installの時にnpm ERR! code EACCESが出た

# 経緯

VueCLIをインストールしようとした際にエラーが出たのでメモしました。

```
$ npm i -g @vue/cli
```

をした際に
以下のエラーが出ました。

```
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/@vue
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/@vue'
npm ERR!  [Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/@vue'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/usr/local/lib/node_modules/@vue'
npm ERR! }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.
```


It is likely you do not have the permissions to access this file as the current user(現在のユーザーとしてこのファイルにアクセスする権限がない可能性があります)

って言われたので。
npm install -g @vue/cliの前に
sudoをつけて再度実行

```
$ sudo npm install -g @vue/cli
```

これでできました。
ALBのログとログフォーマットを簡単に紐づける

ALBのアクセスログを久々に見るときに、ログの各値ってなんだっけ.. ってなって、各ログの値をログフォーマットと紐づけたいんだけど、なんかめんどくさい..

というときに、これ簡単でした
ほぼスプレッドシートの操作だけでログフォーマットのヘッダーを挿入する感じです

- ALBのログをダウンロードして、テキストなどで開く
- スプレッドシートの2行目以降に貼りつける(1行目空けとく)
- スペース区切りで列を分割する
- スプレッドシートで新規シートをつくる
- [Application Load Balancer のアクセスログ](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html)ページを開く
- アクセスログのエントリ -> 構文 のすぐ下にあるテーブル全体をドラッグしてコピーし、スプレッドシートの新規シートに貼りつける
- (※スプレッドシートにフォーマットが崩れるに貼れてること前提) 
- 貼りつけたシートのA列全体をコピーし、アクセスログを貼ったシートの先頭セル(A1)に、転置して貼り付ける
- (※1行目の列がスペース区切りで自動分割されていない場合は、1行目の列の分割操作が必要)
- 全列を選択状態にし、列間をダブルクリックするとか右クリックして列の自動調整的なことをやって、全列の幅を値の長さに合わせて広げる


これやると、以下のようになります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620712/a19c22b6-8ba1-5dea-950e-ad121a3d0099.png)



右スクロールしてつづき


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620712/b2aef0b6-58dd-dd18-3d04-2aad54c51664.png)
【TypeScript】VSCodeを使ってデバッグをしてみる　メモ

## そもそもデバッグとは
`デバッグとは、コンピュータプログラムに潜む欠陥を探し出して取り除くこと。`
参照：https://e-words.jp/w/%E3%83%87%E3%83%90%E3%83%83%E3%82%B0.html

## なぜVSCodeを使ってデバッグをしようと思ったか？？
***デバッガ機能を使って楽にデバッグ作業をしたいから！！！***
です。
ただ、以前eclipseを使っているときに多少は習ったのですが、使い方があまり分からず、後回しになって現在に至りました。
ですので、一度簡単にやってみようと思います！！

今回参考にさせていただいたサイト↓
<a href="https://dev.classmethod.jp/articles/step-execution-typescript-by-vscode/">【React も AWS CDK も】何も考えず VS Code に全任せして TypeScript コードをステップ実行デバッグする【できるよ！】</a>
やっていることは同じなので、詳しく知りたい方は↑のサイトに飛んでみてください

## 今回使用するコード
```typescript
const fizzbuzz = (number:number) => {
  if(number % 15 === 0){
    return 'FizzBuzz';
  }else if(number % 3 === 0){
    return 'Fizz';
  }else if(number % 5 === 0){
    return 'Buzz';
  }else{
    return number;
  }
}

for(let i = 1;i <= 30;i++){
  console.log(fizzbuzz(i));
}
```
FizzBuzzのプログラムです。
`3で割り切れるとき→Fizz`
`5で割り切れるとき→Buzz`
`15で割り切れるとき→FizzBuzz`
`それ以外→数字`

## 実際にやってみた
![qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/c691b5b2-e40d-6af3-a3d4-3836de7db9d8.png)

1\. 実行とデバッグをクリック
2\. 左側のJavaScript Debug Terminalをクリックしてターミナルが出ているのを確認

![qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/4fcf2ee4-b6d2-f76f-7920-db70f55e0621.png)

3\. ブレークポイントの指定
4\. コードの実行

![qiita3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/2b2ac81c-7483-437b-94e3-491dd23b17ec.png)

5\. 実行やステップオーバーをクリック
→実行をするとそのまま値が出力され、ステップオーバーをクリックするとif文の中での処理も見ることができる
☆それぞれのボタンについて詳しくは→https://atmarkit.itmedia.co.jp/ait/articles/1707/21/news030_3.html
6\. 値が更新される
7\. 条件に合った値（文字列）が出力される

まだまだやり方などあいまいな部分が多いですが、使って慣れていきたいと思います
【Ruby】nil or 未定義の場合の代入演算子

メモとして残します。

代入演算子というのかは定かではありませんが、左辺がnil、または存在しない場合のみ、右辺を左辺に代入するという演算子です。


# ■やり方
`hoge = hoge || 'nilの場合代入される'`
要するに上記を省略して書くと下記のようになる。

```rb
hoge = nil
hoge ||= '代入されるよ'
#>>　hoge = '代入されるよ'
```

```rb
hoge = ''
hoge ||= '代入されないよ'
#>>　hoge = ''
```

以上
広報Twitterの文章をGoogleの自然言語処理API(Natural language API)で分析して改善する②

<img width="600" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822821/bf6ee6cb-eb5a-3b2d-8987-7a95cb50a505.png">

この記事では「Natural language API」を使用してツイートを数値化し分析をしてみます。


# 目次
- 分析の目的は「Twitterをバズらせる！」
- BigQueryにデータをアップ
    - BigQueryに表形式データ、またはCSVをアップするやり方
    - フィールド名が「＿」になってしまう
    - ツイートの数値化データとアナリティクスデータを結合しながらテーブルを作成
    - 時間データが文字列型（String型）で入ってしまう


## 分析の目的は「Twitterをバズらせる！」

本分析の**目的**は 「**潜在ニーズの表出**」と「**SNS(twitter)からのサイトへの流入**」であり、

本分析の**目標**は「**この単語を使うとエンゲージメント率（サイトURLクリック率）が上がりますよ！**」と言えるようになることです。

手順は以下の通りです。

1. GASを使用して、スプレッドシート経由でツイートを自然言語処理
2. 数値化されたツイートをBigQueryに挿入
3. データポータルで可視化、BQMLで分析

この記事では手順２の数値化されたツイートをBigQueryに挿入する部分の記事です。

# BigQueryにデータをアップ

「Natural language API」で数値化したデータをBigQueryにアップする方法と、問題点を載せておきます。
- BigQueryに表形式データ、またはCSVをアップするやり方
- フィールド名がバグってしまう
- ツイートの数値化データとアナリティクスデータを結合しながらテーブルを作成
- 時間データが文字列型（String型）で入ってしまう

## BigQueryに表形式データ、またはCSVをアップするやり方
**テーブルの作成からアップロードを選択**
![スプシアップロード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822821/94931e94-926d-a7a5-53fc-5272c14d379e.jpeg)
テーブルの作成からアップロードを選択し、アップしたスプシファイルを選択することでアップの準備をすることができます。

**スキーマの自動検出**

チェックを入れておくと、自動的にスキーマ（データ形式）を検出してくれます。

<img width="500" alt="スキーマ検出.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822821/73292f94-e5e7-3583-423e-442ca937c756.png">

**引用された改行**

![引用された改行.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822821/eb727fea-efcb-c6e9-5ec6-a5e2ffdac22a.jpeg)
このエラーが出てきた場合には、下記の画像のように「引用された改行」にチェックを入れてください。

<img width="600" alt="引用された改行.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822821/0cadbc0e-bd38-c26e-8bca-4a65d3b0a0e1.png">

SCV形式のデータをアップする際に、CSVファイルに改行がある際に起きてしまうエラーのようです。チェックを入れることで自動で処理してくれるようになります。

## **ツイートの数値化データとアナリティクスデータを結合しながらテーブルを作成**

「Natural language API」の分析結果のnameごとにツイート本文をつけていたので、今回はツイート本文を使いテーブルを結合します。

```sql
SELECT 
  *
FROM
  `テーブル名A`
JOIN
  `テーブル名A`
ON
  テーブル名Aのツイート本文のカラム名 = テーブル名Bのツイート本文のカラム名
```

二つのテーブルのを結合したいときに、同じ定義のカラムがあるなら簡単にテーブルの結合をすることができます。

## **フィールド名が「＿」になってしまう**

BigQueryではカラム名に日本語が入っていると日本語が「＿」に変換されてしまい、データの使い勝手が悪くなってしまいます。

**解決方法**

```sql
--データセットIDとテーブルIDを指定する
ALTER TABLE `<datasetID>.<tableID>`
--<変更したいフィールド名>と<変更した後のフィールド名の名前を入力> 
RENAME COLUMN <fieldNameA> TO <fieldNameB>,
```

このSQLはフィールド名を<fieldNameA>から<fieldNameB>に変換するものです。これを使用して英数字を使用したフィールド名に変換しましょう。

## 時間データが文字列型（String型）で入ってしまう

Twitterアナリティクスデータは表形式データ、またはCSVでした。BigQueryにアップした際に「2022-01-01 00:00 +0000」がString型で入ってしまいました。

**解決方法**

```sql
SELECT
  カラム名
  ,timestamp(concat(trim(rtrim(times,'+0000')),':00')) as DATETIME1
FROM
  `テーブル名`
```

今回のデータが「2022-01-01 00:00 +0000」で入力されていたためこの形のコードになっています。

時間型に変換するには、どんな形のString型で入ってきたかによってキャストを変えなくてはなりません。今回のコードはその一助としてお使いください。

# まとめ

BigQueryを使用したのが初めてだったので、どういう風にデータが入るのかなどで戸惑う点が多くありました。時間型に関しては自分のデータ型に合わせてトリムしなくてはならないので、どうやれば指定ができるのかなどをしっかりと調べる必要があります。

今回載せている問題点はすごく簡単な部分ではありますが、一度はつまずく点だと思いますので、その解決の手助けとして役立ててください。

また問題点ではありませんが、BigQueryのデータをいじっていくうちにテーブルをどんどんと作成していってしまいました。これでは自分以外がデータを触ることができなくなってしまいます。こういった点にも配慮して見やすいデータを心がけていきたいです。

次回記事はこのデータを使って分析していくところです。
【Mac】コマンドでクリップボードを操作する方法

## クリップボードに保存

`pbcopy`を使用することでクリップボードに保存できます。

```zsh
cat sample.txt | pbcopy
```

## クリップボードからペースト

`pbpaste`を使用するとクリップボードからペーストできます。

```zsh
pbpaste > example.txt
```

## 例

`sample.txt`と`example.txt`を用意します。
それぞれ内容は以下のとおりです。

```sample.txt
これはsample.txt内の文章です。
```

```example.txt
これはexample.txt内の文章です。
```

実際に`pbcopy`と`pbpaste`を使用してみます。

````zsh
$ cat sample.txt | pbcopy

$ pbpaste >> example.txt

$ cat example.txt
これはexample.txt内の文章です。これはsample.txt内の文章です。
````

`sample.txt`の内容をクリップボード経由で`example.txt`に追加できました。
脱Excelでシステム設計書を作成する(ツール選定編)

2022/10/31 New!!
この記事の続編となるGitlab Wiki整備編を公開しました。

https://qiita.com/masayakomono/items/27c224a4b8d321928bc8

# 概要
現在社内で作られるドキュメントのほとんどがExcelで作成されています。

* 議事録
* 提案書
* 見積
* 設計書
* テスト仕様書
* 打ち合わせで使う資料
etc...

この中の一つである設計書を脱Excel化しようと試みたのでその過程と結果を何回かに分けて
Qiitaにアウトプットしようと思います。

## 前提条件

* プロダクトバックログ及びスプリントバックログはBacklogにて管理する
* ソースはGitにて管理し、GitLabを利用する

## 取り組む内容

### ①Excelに変わる新たな設計書作成手段の導入
今までExcelでしかやってこなかったのでまずは調べる所から

### ②設計書のテンプレート作成
テンプレートを用意しておかないと人によってこの項目を書いた/書いてないが分かれてしまいそう。
そのため各資料ごとに簡単なテンプレートを作成しておく。

### ③Excelから新手段への乗り換え方法の検討
いきなり新方式を強いるのも労力がかかりそうなので徐々に慣れてもらうにはどのような
進め方をしていくのがベストか検討する。

### ④作成/編集する際の最低限のルール策定
差分でチェックするという目的がある以上無暗に更新されても困るので
あらかじめルールを決めておく（ルールが浸透するか分からないのでかっちり作りすぎない）

## 選定候補

### ①設計書作成用ツールの導入
例：Cacoo、astah（弊社ではCacooを利用中）
※参考URL

https://web-camp.io/magazine/archives/61041

設計書作成に特化しているため細かい所まで気が利いている。
商用利用だと月額費用が発生してしまうがツールを絞ればある程度抑えられる。
仮にサービスが終了した場合編集できなくなってしまうのでは？という不安はある。


### ②すでに利用しているシステムのWiki機能の活用
例：GitLab、Backlog(今回の自社プロジェクトで使用しているツールです）
マークダウンでゴリゴリ作っていく。特徴は文ベースで処理の中身や説明を書いて行き、後々変更があった時に
差分が確認しやすくなる。（Excelだとファイルが増えていったり「●●●●年●●月●●日変更」と書くはめになる）
後、Wikiとしての機能が既に用意されているのでページを追加していくだけで資料体系が出来上がっていくし
見出しをちゃんとつければアウトラインが分かりやすい。
図の作成はplantUMLなどの外部コンポーネントを使えば作成できるものもあるが、融通が利きづらい部分もある。

### ③マークダウンをHTML形式に変換するホスティングサービスの利用
例：Honkit（他にもありそう）
Wikiと同じくマークダウンで作っていく。ホスティングサービスを立ち上げるメリットとしては
他２つに比べて有志が開発するプラグインの幅が広いというのと、好きな環境に立ち上げやすいという点。


## 結論
図を作成する場合はCacoo、仕様等を文や表で表す場合はGitLabのプロジェクトのWikiを使用することにしました。

### Cacooを選定した理由＋作成する対象資料
Excelの図形だと表しきれない設計図独特の図形もCacooだと用意されているというのと
複数人で同時に編集が出来るというのが大きいです。後、共有する際もリンクを送ればいいので楽

<strong>対象資料</strong>
* ハードウェア構成図
* ソフトウェア構成図
* ネットワーク構成図
* システム連携図
* 画面遷移図（Mermaidをマークダウンに埋め込む手もあり）
* 処理フロー（Mermaidをマークダウンに埋め込む手もあり）
* ER図

### GitLabのWikiを選定した理由＋作成する対象資料
マークダウンで設計書を作るという部分に対する選択肢は
1.BacklogのWiki機能
2.GitLabのWiki機能
3.Honkit
の3つでしたが、ソースコードを管理する場所とドキュメントを管理する場所を統一したいという思いから
GitLabのWiki機能を選びました。
BacklogのWikiはどちらかというと１システムより１プロジェクトに対するWikiなので
設計書というシステムに紐づくものはGitLabの方がいいのではという社内の意見が参考になりました。

<strong>対象資料</strong>
* 画面一覧
* 画面入出力項目一覧
* 画面ごとの処理の流れ
* 帳票一覧
* 帳票入出力項目一覧
* 帳票出力使用
* バッチ処理一覧
* バッチ処理の流れ
* DBテーブル一覧
* DBテーブル定義
* API一覧
* API仕様書（インターフェース、処理内容）
* 非機能要件定義

まずはブラウザ上でWikiページを作成して、慣れてきたら
VSCodeを使用して編集＋Git連携してコミット&プッシュでもいいかも

### Excelについて
今まで「脱Excel」と繰り返していましたが、イメージだけをパパっと伝える一時的な資料など
その場限りの資料という前提で、相手側に見てもらうための準備の手間が多いと感じた場合は
Excelでもいいと思います。
後、ちゃんと表計算ソフトとして意味のある資料はもちろんExcelでいいと思います。

## 2023/07/14追記
Wiki以外で代替可能なドキュメントがいくつかあるのでそちらも共有します。

### ER図
ER図を書くことに特化したツールがあるため、Cacooではなく専用のツールを選択するのも有りです。

https://gitmind.com/jp/er-diagram-tool-free.html

### API設計書
SwaggerなどのOpenAPI形式の定義ファイルを扱えるツールがあります。
このツールが設計書、モック、自動テストを全て兼ねることが出来るそうです。
このツールを使う時にWikiにも仕様を書いてしまうと二重管理になってしまうのでWikiに記載しないという判断もあります。

https://swagger.io/tools/swagger-editor/

https://apidog.com/jp/

### 画面遷移図
FigmaやAdobe XD等のツールで画面のワイヤーフレームを作る際に、画面遷移図も合わせて作ってしまうこともあります。

https://www.figma.com/files/recents-and-sharing?fuid=1210022562612559916

https://helpx.adobe.com/jp/support/xd.html
Xilinx ZCU102向けPYNQビルドと確認(v3.0対応)

[前回](https://qiita.com/tethys_seesaa/items/3c500ed07d3e95c9df85)`image_v2.7`をベースにビルド方法と動作確認を実施しましたが、その後`v3.0`が出てきたので、ZCU102向けにビルドしました。
本バージョンではUbuntu 22.04ベースにカーネルのバージョンが5.15と大幅に上がりました。
今回もいろいろ大変だったので備忘録として残しておきます。
# 前提となる環境
- Ubuntu 18.04
- Vitis 2022.1
- Petalinux 2022.1

Ubuntuは20.04でもOKです。
VitisとPetalinuxはバージョンが固定されており、上記の組み合わせ以外ではビルドはできません。


# 事前準備
次のファイルを~/に用意します。
- ZCU102 BSP 2022.1 (xilinx-zcu102-v2022.1-final.bsp) (from: https://japan.xilinx.com/support/download.html) 
    - 執筆現在、XilinxのダウンロードサイトからダウンロードできるBSPファイルの名前は`xilinx-zcu102-v2022.1-04191534.bsp`なので、これを`xilinx-zcu102-v2022.1-final.bsp`に**リネームして下さい。**
- ARM64向けPYNQ rootfs(jammy.aarch64.3.0.1.tar.gz) (from: http://www.pynq.io/board.html/)
- PYNQソースコード (pynq-3.0.1.tar.gz) (from: https://pypi.org/project/pynq/#files)

# ビルド実行
以下のスクリプトを実行します。
スクリプトの中の`./scripts/setup_host.sh`の時点でQEMU等をコンパイル・インストールするので、Ubuntu 18.04のroot権限が必要です。

```sh
# pynq
git clone https://github.com/Xilinx/PYNQ.git -b v3.0.1 --depth 1
cd PYNQ

# ZCU102 setting
cp -rf ./boards/ZCU104 ./boards/ZCU102
rm -rf ./boards/ZCU102/petalinux_bsp/
mv ./boards/ZCU102/ZCU104.spec ./boards/ZCU102/ZCU102.spec
sed -i -e "s/104/102/g" ./boards/ZCU102/ZCU102.spec

# copy files
cp ~/xilinx-zcu102-v2022.1-final.bsp ./boards/ZCU102/
cp ~/pynq-3.0.1.tar.gz ./sdbuild/prebuilt/pynq_sdist.tar.gz
cp ~/jammy.aarch64.3.0.1.tar.gz  ./sdbuild/prebuilt/pynq_rootfs.aarch64.tar.gz

# install qemu，crosstool-ng
cd ./sdbuild/
./scripts/setup_host.sh

# path
PATH=/opt/qemu/bin:/opt/crosstool-ng/bin:$PATH
source /<path>/<to>/xilinx/Petalinux/2022.1/settings.sh
source /<path>/<to>/xilinx//Vitis/2022.1/settings64.sh

# build
sudo echo
make BOARDS=ZCU102

```
# 動作確認
ビルドが完了すると、`PYNQ/sdbuild/output`に`ZCU102-3.0.1.img`という名でイメージファイル(約9.2GB)が生成されます。
これをSDカードに書き込みます。
自分はWindowsにコピーして、[rufus](https://rufus.ie/ja/)でSDカードに書き込みました。

SDカードをZCU102に挿入してブートさせると、DisplayPort出力からPYNQのデスクトップ環境が立ち上がります。
![Screenshot 2022-10-12 15-25-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32925/b4518a36-3073-9a44-d786-64d8a3ddc6bb.png)
今回はブラウザがインストールされておりません。`ip`コマンド等でIPアドレスを調べ、他のPCからそのIPアドレスをブラウザに入力するとupyter Notebookに入ることができます。パスワードは`xilinx`です。

# ビルド時間等
CPUがRyzen 9 5950X搭載のUbuntu 18.04でビルドは約1時間と、[前回](https://qiita.com/tethys_seesaa/items/3c500ed07d3e95c9df85)と比較すると格段に短縮されました。
またPYNQディレクトリ全体で約33GB消費します。
QuickSightのコンソール画面からのグループ管理に必要な前提操作について

# ＜はじめに＞
今回はQuickSightのグループ管理に関する紹介です。
以前のQuickSightのアップデートにてQuickSightのコンソール画面上からグループの作成・グループへのユーザの割り当てが可能になりました。

QuickSightのコンソールから「QuickSightの管理」するとユーザを管理することやSPICE容量の管理をすることが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/91944331-ab0c-7bec-f34a-d29bf662b789.png)

メニューの「グループの管理」を選択した際に、ルートユーザやIAM側のAdministratorのポリシーを持たないユーザは下記の画面が表示されコンソール画面からのグループ管理が出来ない状態となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/c9a406d9-169b-38d3-f903-158e4cc8b380.png)

コンソール画面からグループ管理を行うにあたり、必要な前提操作についてご紹介致します。

# ＜前提条件＞
QuickSight バージョン：2022/10/12以降のもの
QuickSight エディション：Standard以上
AUTHORユーザ（管理者）であること
IAMロールと連携したQuickSightユーザであること。
IAMの操作が可能なIAMロールを保持したユーザ。

# ＜作業手順＞
①AWSコンソールより、ポリシーの作成
②①にて作成したポリシーのグループへのアタッチ
③設定の反映確認

## ①AWSコンソールより、ポリシーの作成
AWSコンソールのIAMより、「ポリシー」を選択し「ポリシーを作成」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/1adaa530-772a-5ee2-4c8e-59e80421f94a.png)

ポリシーの内容の記述方式として「JSON」を押下し、下記のポリシーを記述します。
~~~
＜設定値＞
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "quicksight:ListGroups",
                "quicksight:CreateGroup",
                "quicksight:SearchGroups",
                "quicksight:ListGroupMemberships",
                "quicksight:CreateGroupMembership",
                "quicksight:DeleteGroupMembership",
                "quicksight:DescribeGroupMembership",
                "quicksight:ListUsers"
            ],
            "Resource": "*"
        }
    ]
}
~~~

JSONでの記述が完了したら、「次のステップ：タグ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/dc220101-7f51-5e43-a068-9c88e8aa910a.png)

タグの内容については任意に設定して構いませんので、設定後「次のステップ：タグ」を押下します。
※今回の手順では「Owner」のタグを付与しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/af9e9896-0325-852c-5cda-4249618bba15.png)

ポリシーに対して、任意の名前を設定し「ポリシーの作成」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/49bc51eb-eb8f-b422-92fe-633df5bfcb66.png)


## ②①にて作成したポリシーのグループへのアタッチ・ユーザへのグループの割り当て
AWSコンソールより、①にて作成したポリシーをQuickSightのコンソール画面でグループ管理を使用したいAWSユーザの所属するグループへアタッチします。
これにて前提操作が完了になります。
次のステップにて、QuickSightのコンソール画面からグループの管理が使えるか確認を行います。

## ③設定の反映確認
QuickSightのコンソール画面から「QuickSightの管理→グループの管理」を選択します。
グループの管理を選択すると、「はじめに」で紹介した画面とは違い「新しいグループ」のボタンが表示されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/756e383c-8ff4-6a63-f5d1-2f1787c59ac7.png)

「新しいグループ」を押下すると、グループの作成画面に遷移し任意のグループが作成できることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/e78234ec-93eb-2dad-1643-7dd3b64bf703.png)

「作成」を押下することでグループが作成出来たことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711422/79a2c196-5abe-4410-9c00-fc07ca2b7060.png)


# ＜おわりに＞
以前のQuickSightのバージョンではグループの管理はAWS CLIからのみしか実施できませんでした。
コンソール画面から行うためにグループの管理が行えるようになり便利になりましたが、グループの管理を使用するための条件としてIAMポリシーの設定が必要となるのは元々CLI操作であった名残りなのではないかと思います。
javascriptでobjectを生成する３つの方法について

# javascriptでobjectを生成する３つの方法（時間がない方はこちら）
### 方法１： 何かのオブジェクトを直接指定する
```javascript:javascript
const obj = {...}
```

### 方法２： Object.create()を利用する
```javascript:javascript
const obj = Object.create(<何かのprototype>)
```

### 方法３： new Object()を利用する
```javascript:javascript
const obj = new Object()
```

# ３つの方法の違い
方法１は、内部的に方法３を利用するため、ここでは方法２と方法３を比べる。

### new Object()とObject.create()の内部比較

|    |  new Object()  | Object.create()  |
| ---- | ---- | ---- |
|  prototype  |  Object()のprototypeを持つ  |  - constructの持たないオブジェクトを生成<br> - オブジェクトを生成時にprototypeを指定する必要あり<br> - 引数としてnullを入れることもOK  |
|  constructor  |  Object()のconstructorを持つ  |  - 引数として入れたprototypeのconstructorを持つ <br> - 引数にnullを入れた場合、constructorのないオブジェクトが生成される  |

つまり、prototypeをカスタムできるかどうかの違い。
なお、方法１は方法３を内部的に利用するため、Object.prototypeを継承さえる。
mtrコマンド、ジャンボフレームについて

●mtr
pingやtracerouteなどのようにICMP等を使って、通信の可・不可や経路などを確認することができるコマンド。パケットロスやレイテンシをレポートの形で生成できる。

●ホスト名に関連した情報を表示するためのコマンド

・nslookup DNSでホスト名とIPアドレスを変換
・dig nslookupより詳細な情報を表示
・hostname 自ホストのホスト名を表示
・hostname -d 自ホストのDNSドメイン名を表
・hostname -i 次ホストのIPアドレスを表示
・hostname -f 自ホストのFQDN表示
・hostname -a 自ホストのエイリアスを表示

●digコマンドは問い合わせにかかった時間（Query time）や、応答メッセージのサイズ（MSG SIZE rcvd）なども表示することができる。

●nslookup は DNS 問い合わせの結果を抜粋・整理して表示。

●ジャンボフレーム
イーサネットで1回に送信できるデータの単位をフレームと呼び、標準ではフレームの最大サイズは1500バイト。通信速度が1Gbpsや10Gbpsなどの高速なイーサネット規格においては、小さなフレームのやり取りが頻繁に発生し、ネットワーク機器での処理が非効率。そこで、データ転送の効率を上げるために規定されたのが、1500バイトを超えるサイズのジャンボフレーム。

ネットワークインタフェースがジャンボフレームに対応しているかどうかは、「ip link show」コマンドや「ip addr show」コマンドのMTU値で確認できる。MTUが1500を超えているインタフェースは、ジャンボフレームが設定されている。
pip list を実行したら Fatal error (Unable to create process using)が発生しました。

python仮想環境で pip list を実行すると、Fatal errorが発生しました。

## 環境
python 3.10.4
vscode 1.72.1

## 発生状況
venvのpython仮想環境で pip listを実行すると Fatal error in launcher: Unable to create process using が発生しました。
```powershell
(venv) PS C:\tmp\test> pip list
Fatal error in launcher: Unable to create process using
 '"C:\tmp\test\venv\Scripts\python.exe" 
 "C:\tmp\test\venv\Scripts\pip.exe" list': ??????????????????
```
以下のようにすれば、問題なく実行できます。
```powershell
(venv) PS C:\tmp\test> python -m pip list
Package          Version
---------------- -----------
openpyxl         3.0.10
pip              22.0.4
selenium         4.1.5
WARNING: You are using pip version 22.0.4; however, version 22.2.2 is available.
You should consider upgrading via the
 'C:\tmp\test\venv\Scripts\python.exe -m pip install --upgrade pip' command.
```

## 対応策
実行結果をよくみると、最後の方に警告が出てた。
pipをアップグレードせよ。ということなので、言われるがまま実行しました。
```powershell
(venv) PS C:\tmp\test> python -m pip install --upgrade pip
Requirement already satisfied: pip in c:\tmp\test\venv\lib\site-packages (22.0.4)
Collecting pip
  Using cached pip-22.2.2-py3-none-any.whl (2.0 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 22.0.4
    Uninstalling pip-22.0.4:
      Successfully uninstalled pip-22.0.4
Successfully installed pip-22.2.2
```
無事、pipのアップグレードが完了
そして、先程エラーになっていた pip list を実行してみました。
```powershell
(venv) PS C:\tmp\test> pip list
Package          Version
---------------- -----------
openpyxl         3.0.10
pip              22.0.4
selenium         4.1.5
(venv) PS C:\tmp\test>
```
pipをアップグレードしたことにより、pip list だけで問題なく実行できるようになりました。
Django Adminのlist_viewをカスタムしたい

ふつう、list_viewの項目はlist_displayで指定される。
以下のように。
```python
class SomeAdmin(admin.ModelAdmin):
    list_display = [
        'some_field_A',
        'some_field_B',
        'some_field_C',
        'some_field_D',
        'some_field_E',
        'some_field_F',
    ]
```

カスタムしたい時はこう。

```
class SomeAdmin(admin.ModelAdmin):
    list_display = [
        'some_field_A',
        self.get_custom_display(),
        'some_field_C',
        'some_field_D',
        'some_field_E',
        'some_field_F',
    ]

    def get_custom_display(self, obj):
        return obj.donburi_ippai + "うまい安い早い"
```
表示は "うまい安い早い"が後ろについた文字列になる。

その場所だけhtmlをカスタムしたいとかは、mark_safe()とかformat_html()を使うとよい。
```python
from django.utils.html import format_html
from django.utils.safestring import mark_safe


class SomeAdmin(admin.ModelAdmin):
    list_display = [
        'some_field_A',
        self.get_custom_html_mark_safe(),
        self.get_custom_html_format_html(),
        'some_field_D',
        'some_field_E',
        'some_field_F',
    ]

    def get_custom_html_mark_safe(self, obj):
        html_string = "<div>丼一つで{}</div>"
        return mark_safe(html_string.format("300年"))

    def get_custom_html_format_html(self, obj):
        html_string = "<div>丼一つで{}</div>"
        return format_html(
            html_string,
            "300年"
        )
```

どちらも、`<div>丼一つで300年</div>`が出力される。
【問題解決法】困難は分割せよ

# 困難は分割せよ
* デカルトの言葉。
* デカルトとは、フランスの哲学者。


# 解釈
* 問題は大きく捉えると解決が困難に思えてしまう。
しかし、大問題を小問題に切り分けることで解決可能にする考え方。


# メリット
1. 小問題に切り分けることで複数人での分担が可能になる。
1. ゴールを達成するための道筋（マイルストーン）が明確になる。


# 具体例
* ビルゲイツの例

> ある日、ビル・ゲイツがカレーライスを作ろうとしたとき、なんとカレールーとニンジンがありませんでした。これではいつものカレーライスが作れません。
>
>しかしよく考えてみてください。
ルーがないと絶対にカレーライスは作れないでしょうか？
ニンジンがないとカレーライスは作れないでしょうか？
>
>そんなことはありません。
ルーは市販のカレー粉で代用できるし、ニンジンはなくても一応カレーライスにはなります。
つまり、ルーがないという問題と、ニンジンがないという問題は独立しています。
>
>だからここは慌てず、「ルーをどうするか」「ニンジンをどうするか」という分割された課題に、別々に当たればいいわけです。
>
>ビル・ゲイツはその後、カレー粉とじゃがいもを使ってカレーライスを作っておいしくいただきました。

引用元：https://bottone.jp/blog/bottone-ceo/10050.html

【上述した例の説明】

2. 大問題を小問題に切り分けている。
2. 問題を切り分けた後、問題に対する目的を考える。
2. 目的に対して代替案を導出することで問題解決をしている。

# 結論
* 「達成できない。困難だ！」と感じたら、困難を切り分けることが出来ないか？を考える。
* 切り分けた困難(問題)に優先順位をつけ、優先度が高い問題から着手する。
batファイル WinSCP コンソールモード

## Windows → Linux ファイルを1つアップロード 
```bat
@echo off
REM Windows から Linux ファイルアップロード

REM 変更箇所
REM 転送したいファイル情報をベタ打ちする場合
set FileWindows="C:\Users\user\Desktop\test.txt"
set FileLinux="/home/user/test.txt"

REM 転送したいファイルをパラメータとして使う場合
REM set FileWindows=%~1
REM set SaveDir=/home/user/TestDir
REM set FileLinux="%SaveDir%/%~nx1"

set LinuxPass=hogehoge
set LinuxUser=root
set LinuxIP=192.168.x.xx

REM 必須
set p1=/console
set p2=/command
set p3="option batch on"
set p4="option confirm off"
set p5="open %LinuxUser%:%LinuxPass%@%LinuxIP%" 

REM 任意コマンド
set p6="put %FileWindows% %FileLinux%"
set p7="close" 
set p8="exit"

"C:\Program Files (x86)\WinSCP\WinSCP.exe" %p1% %p2% %p3% %p4% %p5% %p7% %p8%

```
|記述|説明|備考|
|----|----|----|
|"C:\Program Files (x86)\WinSCP\WinSCP.exe"|WinSCP.exeの絶対パス||
|/console|コンソールモードでWinSCPを起動||
|/command|WinSCP起動直後に実行するWinSCPコマンドを指定|複数指定可能|
|option batch on|バッチモードに設定し、確認/問い合わせを無効にする|WinSCPコマンド|
|option confirm off|ファイル上書きの確認などを無効にする|WinSCPコマンド|
|open root:password@192.168.xx.xxx|パスワードを指定してサーバー接続|WinSCPコマンド|
|put C:\Users\user\Desktop\test.txt /home/User/%FileName%|ローカル から サーバへファイルをアップロード<br>put コピー元ファイル コピー先ファイル|WinSCPコマンド|
|close|切断|WinSCPコマンド|
|exit|終了|WinSCPコマンド|

### パラメータの有無を判定する場合
```bat
if "%~1"=="" (
echo パラメータがありません。
pause
exit
)
```
##  Windows → Linux 同一ディレクトリの.pyファイルを全てアップロード
```bat
@echo off
setlocal EnableDelayedExpansion

set FileLinuxDir=/home/user/PG_TEST/
set LinuxUser=root
set LinuxPass=hogehoge
set LinuxIP=192.168.xx.xxx

for %%i in (*.py) do (

	set FileWindows=%%~dpnxi
	echo ファイル名：!FileWindows!
	call :sendFile !FileWindows!

)

:sendFile
	echo sendFile: %1
	set p1=/console
	set p2=/command
	set p3="option batch on"
	set p4="option confirm off"
	set p5="open !LinuxUser!:!LinuxPass!@!LinuxIP!" 

	REM 任意コマンド
	set p6="put %1 !FileLinuxDir!/%~nx1"
	set p7="close" 
	set p8="exit"

	"C:\Program Files (x86)\WinSCP\WinSCP.exe" !p1! !p2! !p3! !p4! !p5! !p6! !p7! !p8!


```


## Windows → Linux 任意コマンド実行
```bat
@echo off
REM Windows から Linux Shellの実行

REM 変更箇所
set LinuxPass=hogehoge
set LinuxUser=root
set LinuxIP=192.168.x.xx

REM 必須
set p1=/console
set p2=/command
set p3="option batch on"
set p4="option confirm off"
set p5="open %LinuxUser%:%LinuxPass%@%LinuxIP%" 

REM 任意コマンド
set p6="call /home/test/test.sh para1 para2"
set p7="call cd /home/user"
set p8="call ls -ltr|tail -1"

"C:\Program Files (x86)\WinSCP\WinSCP.exe" %p1% %p2% %p3% %p4% %p5% %p6% %p7% %p8% 
```
|記述|説明|
|----|----|
|call|任意のコマンドを実行||

参考記事

https://ja.osdn.net/projects/winscp/wiki/scripting

https://qiita.com/mima_ita/items/35261ec39c3c587210d8#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E3%81%AE%E5%AE%9F%E8%A1%8C%E6%96%B9%E6%B3%95

https://tex2e.github.io/blog/windowsbatch/winscp-cmd
Docker Composeでcode-serverを構築する


# 目的

ブラウザから手軽にコードを編集する環境が欲しかったので、自サーバーにcode-serverをたてました。

# 環境

- OS: Ubuntu 22.04
- docker: 20.10.18
- [codercom/code-server: 4.7.1 ](https://hub.docker.com/layers/codercom/code-server/4.7.1/images/sha256-57e1ba712a0832c3ff3958dce857092373a918fee9a5b359cc7253fcc751b3b8?context=explore)

```bash
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
Codename:       jammy
$ docker --version
Docker version 20.10.18, build b40c2f6
```

# `docker-comoser.yml`を作る

[codercom/code-server - Docker Image | Docker Hub](https://hub.docker.com/r/codercom/code-server)を参考に、`docker-compose.yml`を書きます。

`.config`は、ワーキングディレクトリ下でも良いかと思い、最初は`-./.config:/home/coder/.config`
としていたのですが、うまく起動しなかったので、`$HOME`下の`.config`をマウントする形に戻しました。

```docker-compose.yml
version: '3'

services:
  code-server:
    image: codercom/code-server:latest
    container_name: code-server
    restart: always
    environment:
      - UID=1000
      - GID=1000
      - DOCKER_USER=$USER
    ports:
      - '8080:8080'
    volumes:
      - ~/.config:/home/coder/.config
      - ./project:/home/coder/project
```

`docker-compose.yml`が書けたら、立ち上げます。

```bash
$ docker compose up -d
```

起動したら http://localhost:8080 にアクセスします。

![code-server welcome.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92115/7e040655-5841-98ba-0ff5-a157502a0c27.jpeg)

パスワード入力を求められるので、`config.yaml`内のパスワードを確認し入力すると、ログインできます。

```bash
$ cat ~/.config/code-server/config.yaml 
bind-addr: 127.0.0.1:8080
auth: password
password: [ PASSWORD ]
cert: false
```

以上です。
Salesforce認定アドミニストレーター試験の難易度を解説してみた

こんにちは

今回はSalesforce認定アドミニストレーター試験の難易度の目安を紹介します

もちろん難易度は人それぞれなのであくまで目安だと思ってください

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

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

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

まずはSalesforce認定アドミニストレーター試験は他のSaelsforceの資格と比べどのような立ち位置にいるのか確認しましょう

![資格.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/5ef7955d-a927-24f2-a35d-22bd67fba888.png)

このようにSalesforce認定アドミニストレーター試験は基本的に位置づけられ
「管理者、コンサルタント、アーキテクトにおすすめのファーストステップ」
の資格です。
ちなみにSales Cloudコンサルタントなど「上位資格」に位置づけられる資格はこのSalesforce認定アドミニストレーター試験に合格しないと受験することはできません

上記画像はこちらからダウンロード可能です

https://tandc.salesforce.com/credentials

では、この資格の対象者とはどのような人なのでしょうか
勉強時間の目安を見ていきましょう


まずは認定アドミニストレーターの受験ガイドをご確認しましょう


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

ここにはこのように書いていますね

*対象者について: SALESFORCE 認定アドミニストレーター*

Salesforce 認定アドミニストレーターは、Salesforce システム管理者としての経験があり、後述の試験の目的に示されるスキルおよび概念を実践的に応用したことがある方を対象としています。受験者は、エンドユーザが利用できる機能と Salesforce システム管理者が利用できる設定オプションについての一般的な知識が必要です。また、Salesforce の最新機能を使用して、Salesforce 組織の維持、一般的なビジネス要件への対応、管理機能の実行を行う能力が必要です。
受験資格があるのは、Salesforce.com (http://salesforce.com/) または認定パートナーのトレーニングセンターで実施される「Salesforce 管理Ⅰ- [前編]/[後編] (ADX201) 」を修了しているか、それと同等の経験と知識をお持ちの方です。さらに、Salesforce システム管理者として 6 か月以上の経験があり、試験範囲に示される課題を正しく実行できる必要があります。


ここに
「Salesforce システム管理者として 6 か月以上の経験」とありますね

とはいえ、これだけでは正直目安の勉強時間がよく分かりませんね。


それでは、Salesforce認定アドミニストレーター試験を取得することを含未経験のためのプログラムが２つ見てみましょう


まずはPathfinderです

これは
株式会社セールスフォース・ジャパンと
デロイト トーマツ コンサルティング合同会社が共同で実施している無償のIT未経験者向けDX人材育成プログラムです
https://www.salesforce.com/jp/company/news-press/press-releases/2022/05/220516/

このPathfinderプログラムを見れば約３か月でSalesforce認定アドミニストレーター試験を受講するプログラムになっていますね

https://www.salesforce.com/jp/company/careers/pathfinders/

![試験勉強０１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/5407c3c0-2f53-a9f6-74c0-2966e3e58266.png)

![パス02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/5023d57a-fa88-d037-e41c-8bb4d9908ffa.png)

なお、昨年度の同じPathfinderプログラム受講生の7割は2回以内に合格されているようです。


以上の公開情報をまとめると

・Pathfinderという株式会社セールスフォース・ジャパンと
デロイト トーマツ コンサルティング合同会社が共同で実施している無償のIT未経験者向けDX人材育成プログラムでは約3か月の目安でSalesforce認定アドミニストレーター試験を受講する

・合格率は約70％（2回以内に受験して合格した割合）

ということが分かります

最後に
アクセンチュア主催の
リスキル・アカデミー -Salesforce人材育成-　を見ていきましょう
https://www.accenture.com/jp-ja/careers/local/reskill-academy-01

こちらのプログラムは
システム開発経験者かつSalesforce未経験の方を対象に、3か月にわたりSalesforceを活用したDXプロジェクトで活躍するための知識を習得する内容のようです

プログラム内容から
Salesforce認定アドミニストレーター資格 （Salesforceを使用した業務のエキスパートであることを証明する資格）の取得支援がることから、だいたいプログラムが始まって2か月から3か月くらいにSalesforce認定アドミニストレーター資格取得を目指すようです。


いかがでしたでしょうか

今回の内容が皆さんのお役に立てれば幸いです。

また、実際にSalesforce認定アドミニストレーター試験に合格した人は勉強時間や難易度などを共有いただければ嬉しいです。
Splunkのルックアップテーブルのエラー

SplunkでCSVファイルをルックアップテーブルに登録しようとすると、下記のようなエラーが出ることがある。

Your entry was not saved. The following error was reported: SyntaxError: JSON.parse: unexpected character at line 2 column 5 of the JSON data.

![splunk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/efa3cc96-5f8a-d722-5d5f-ccef9a3e416d.png)

この場合、ファイルのパーミッションが原因の場合がある。

![splunk3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/b8c7a0e8-07c1-1744-37cc-3e21095f39e0.png)

-rw-rw-r--

であるべきが、

-rw-------

となっているなど。

chmod 765 *** 

等でパーミッションを変更したら解決した。