OmniAICreator/Qiita-1.07M huggingface dataset:
PHP フレームワーク比較　

#■背景
普段、私自身LaravelやCakePHPを使用しているが、PHPのフレームワークは数多く存在する。
下記、調査しましたので記事に残して置きます。
・フレームワークの種類
・GitHubスター数の比較
・案件数
・Google Trendsによるトレンド比較

#■PHPフレームワークの種類
PHPには下記フレームワークが存在します。
　◆Laravel
Laravelは2011年にリリースされたPHPのフレームワークです。
PHPフレームワークの中では後発ながら、その手軽さや扱いさすさから人気を集め、今やPHPの中でも代表的なフレームワーク。
　◆CakePHP
CakePHP　は2005年に登場したフレームワークです。
「Ruby on Rails」の概念を踏襲したフレームワークとなっていて、Railsの良い部分をPHPで実現したフレームワークだと言えるもです。
　◆Symfony
Symfonyは、2005年に登場したMITライセンスに基づくオープンソースのPHP5用フレームワークです。SymfonyはMojaviから派生し、Ruby用フレームワークRuby on Railの影響を色濃く受けて作られたフレームワークです。
Symfonyの特徴として、バンドルという概念を持っていること、幅広いOSやデータベースに対応していること、プラグインによる機能追加ができることなどが挙げられます。
Symfonyは比較的大規模な開発に適しているPHPフレームワークです。
◆CodeIgniter
CodeIgniterは、2006年に登場したPHPフレームワークです。
CodeIgniterの特徴として、軽量かつ高速動作が可能であることフル機能のWebアプリケーションを作成できること、処理構造を把握しやすいこと、日本語ドキュメントが比較的豊富で学習コストが低いことなどが挙げられます。
Symfonyは小〜中規模な開発に適しているPHPフレームワークです。
◆ZendFramework
ZendFrameworkは、2006年にリリースされたBSDライセンスに基づくPHP5用MVCフレームワークです。
ZendFrameworkの特徴として、シンプルな構造であること、拡張性が高いこと、オブジェクト指向であることなどが挙げられます。
◆Phalcon
Phalconは、2012年に登場したフルスタック高速PHPフレームワークです。
Phalconの特徴として、高速動作できること、Windows、MacOS、Linuxに対応していること、プロジェクト・アプリケーションの規模に応じた開発が可能であることなどが挙げられます。
Phalconは自由度が高いため、属人的なフレームワークになりやすいことに注意しましょう。
◆FuelPHP
FuelPHPは、2010年に登場したFuelPHPは高速かつ軽量なオープンソースPHPフレームワークです。
FuelPHPの特徴として、シンプルな構造であること、「規約よりも設定」のコンセプトを元に設計されているおり柔軟で自由度の高いコーディングができること、などが挙げられます。
FuelPHPは自由度が高いため、属人的なフレームワークになりやすいことに注意しましょう。

FuelPHPは小・中規模な開発に適しているPHPフレームワークです。

　◆CodeIgniter
　◆ZendFramework
　◆Phalcon
　◆Slim
　◆Yii
　◆FuelPHP
　◆Flight

#■PHPフレームワークのリリース
　◆Laravel・・・2011年
　◆CakePHP・・・2005年
　◆Symfony・・・2007年
　◆CodeIgniter・・・2006年
　◆ZendFramework・・・2007年
　◆Phalcon・・・2012年
　◆Yii・・・2008年
　◆FuelPHP・・・2011年

#■PHPのフレームワークの公開案件数
laravelが飛び抜けて多く、次にCakePHPの案件数が多いことがわかります。

![スクリーンショット 2021-08-09 23.42.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/c493aa21-4b0b-a864-e83d-61ac5822f034.png)

#■Githubスター数
PHPのフレームワークの公開案件数より、ある程度人気フレームワークが絞れてきたので、5選に絞り
Laravel GithubStar数☆ 66,179個
Symfony GithubStar数☆ 25,630個
CodeIgniter GithubStar数☆ 18,164個
CakePHP GithubStar数☆ 8,405個
Zend Framework GithubStar数☆ 5,653個

#■Google Trend
日本のPHPフレームワークトレンド
![スクリーンショット 2021-08-10 0.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/a58fe022-0129-545a-2c42-1615cf5e860f.png)

海外のPHPフレームワークトレンド
![スクリーンショット 2021-08-10 0.07.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661515/67caea0b-5dcf-95fb-e5d2-6333e0000852.png)

・日本も海外でも現状では、Laravelが人気フレームワークがズバ抜けていることがわかります。
・日本では201７年ころまでCakePHPが人気だったことがわかります。
・海外での傾向が日本でも主流になるのかもしれない。なので、現在流行っている言語が2年後に日本でも流行る可能性があるのかもしれない。


#■Laravel人気になった要因
調査してわかったことは、laravelが飛ぶ抜けて人気であった。Laravelは2016年頃から人気沸騰している。
laravelが人気になった要因としては、下記のような声が挙がっています。
・ライセンス問題
・自由なフレームワーク
・新機能搭載
・実現したいことがシンプルにできるフレームワーク
・学習コストの低さ
・プログラムの拡張性が高い

更に人気を加速させた要因
・ドキュメントの見やすさ
・情報量が豊富


#■参考文献
https://vitalify.jp/app-lab/vietnam-offshore/20200609_laravel/
https://freelance-start.com/
Rubyの変数と定数

# Rubyの変数
⚫︎変数とは
何かしらの値を入れておくための箱。
変数があることで読めるプログラムが書けるようになる。


⚫︎変数と適切な命名

```rb
#変数を使わない場合
100 + 50

#変数を使うが変数に意味がない場合
a = 100      #イコールで変数に代入できる
b = 50
a + b 

#変数を使い変数に意味がある場合
math_score = 100　　　　　　　　　#変数に意味を持たせて何をしているかわかる
science_score = 50
math_score + science_score

```

# Rubyの定数とは
⚫︎定数とは
固定された値を入れておくための箱。上書きしない固定された値として使う。

⚫︎定数の特徴
1すべて大文字で記述する
2値の上書きをしない

```rb
#変数の上書き
count = 0
count = count+ 1

#定数を使った例
COUNT = 5
```

# 変数の文字列展開
⚫︎変数の文字列展開のルール
ダブルクオート内で#{}で囲う

```rb
#変数をStringにして連結する場合
score = 70
"国語の点数は" + score.to_s + "点です。"

#文字列内で変数を利用する場合
score = 70
"国語の点数は#{score}点です。"

#シングルクオートだと変数の文字列展開ができない

```
# 変数を使った計算処理
⚫︎再代入のルール
イコールの前に四則演算の処理を書く

```rb
score = 80

#記述が繰り返される再代入
score = score + 10

#記述が簡単な再代入
score += 10
score -= 5
score *= 5
score /= 5
```

#変数の役割
変数を使う理由は式の連続性を持たせることです。
言い換えると```値を使い回すことができます```。

```rb
sum = 0
a = 5
b = 8
sum = a + b
#> 13

sum = sum + a
puts sum
#>18

sum = sum + b
puts sum
#>26
```
書いていくと無限に使うことができます。


# 変数の種類

|   変数   |  書き方  |  説明  |
|------|------|-----|
|ローカル変数|ruby|定義した場所からメソッド定義が終わるまで|
|インスタンス変数|@ruby|クラス内で定義されているインスタンスメソッドならok|
|クラス変数|@@ruby|クラス内ならどこでも大丈夫です|
|グローバル変数|$ruby|クラスの外でも使う|

⚫︎補足
上のものほど使用頻度が高いです。

⚫︎コードの例

```rb
def calculation
   sum = 0          #sumから
   sum = a + b      
   sum = sum + a    
end                 #endまでがsumのローカル変数のスコープ
```
もしこれで実行すると

```
 undefined local variable or method `sum' for main:Object (NameError)
```
言語処理100本ノック 2020(Rev2) を初心者が解いてみる

#はじめに
言語処理100本ノックを解いて，日記の代わりとして自分のモチベーションのために本記事を書く．
プログラミングの経験は多少あるが，初心者に毛が生えたようなレベルであるため，練習のために挑戦する．
100本ノックの解答例は既出であるため，もっと効率的で美しいコードが見たいのであれば[こちらを参照]()してほしい．
本記事は簡単な100本ノックの紹介と，解きなおした解答を載せた記事のURLを[下記](https://qiita.com/hoka-sp/private/ea02d076bb98847f1b24#%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AFnlp100%E3%82%92%E8%A7%A3%E3%81%8F)に載せている．
本記事は問題に取り組むたびに更新するスタイルをとる．


##言語処理100本ノックについて
[言語処理100本ノック(NLP100)](https://nlp100.github.io/ja/ '言語処理100本ノック')とは，実用的でワクワクするような課題に取り組みながら，プログラミング，データ分析，研究のスキルを楽しく習得することを目指した問題集であるとされている．
この問題集は東京工業大学の[岡崎直観](https://www.nlp.c.titech.ac.jp/)により制作・保守されている．
※2021年8月9日時点では言語処理100本ノック2020(Rev2)が公開されている．
Rev2ということで公開当初よりバグの改善がなされている．

さらなる詳しい情報は有志による解説記事があるので[こちらを参照](https://qiita.com/hi-asano/items/3c17943ce06f9999ec6f '言語処理100本ノック2020年版が公開！どこが変わったの？')してほしい．

##課題への取り組みの動機
2020年の5月から10月にかけて，言語処理100本ノック2020を00~59まで説いたことがある．(40~49は都合により飛ばしている)
しかし書いたコードを振り返ってみるとコードがぐちゃぐちゃだったので書き直したくなったのと，どうせなら最後までやり切りたいと思い，この際最初から解きなおすことにした．
冒頭の通り，プログラミングスキル自体は初心者に毛が生えたレベルなので，いろいろな部分をほかの解答例などを参考にしながらもできるだけ自力で解いてみる．
コードはgithubにて公開する予定．

2020年に書いたコードと作成されたデータは[こちら]( https://github.com/hoka-main/old_NLP100/tree/master/knock100'NLP100')（本当にぐちゃぐちゃなデータ）

##開発環境
macがないため，Windows10のWSL2を用いて問題に取り組む．
ディストリビューションはUbuntu-20.04を使用する．
ちなみに今回は技術向上のために環境構築を行ったが，オンライン実行環境[Google Colaboratory](https://colab.research.google.com/notebooks/welcome.ipynb)を用いるともっと簡単にプログラムを書くことができる．

Google Colaboratoryの[詳しい解説はこちら](https://cpp-learning.com/python_colaboratory/)
#[言語処理100本ノック(NLP100)](https://nlp100.github.io/ja/ '言語処理100本ノック')を解く
解答例と呼ぶにはおこがましいコードであるが，解答例とし，以下にURLを添付する．
##[第1章：準備運動](https://nlp100.github.io/ja/ch01.html) 
>テキストや文字列を扱う題材に取り組みながら，プログラミング言語のやや高度なトピックを復習します．

今現在，この章に取り組んでいる．
##[第2章：UNIXコマンド](https://nlp100.github.io/ja/ch02.html)
>研究やデータ分析において便利なUNIXツールを体験します．これらの再実装を通じて，プログラミング能力を高めつつ，既存のツールのエコシステムを体感します．


##[第3章：正規表現](https://nlp100.github.io/ja/ch03.html)
>Wikipediaのページのマークアップ記述に正規表現を適用することで，様々な情報・知識を取り出します．

##[第4章：形態素解析](https://nlp100.github.io/ja/ch04.html)
>夏目漱石の小説『吾輩は猫である』に形態素解析器を適用し，小説中の単語の統計を求めます．

##[第5章：係り受け解析](https://nlp100.github.io/ja/ch05.html)
>『吾輩は猫である』に係り受け解析器を適用し，係り受け木の操作と統語的な分析を体験します．

##[第6章：機械学習](https://nlp100.github.io/ja/ch06.html)
>文書分類器を機械学習で構築します．さらに，機械学習手法の評価方法を学びます．

##[第7章：単語ベクトル](https://nlp100.github.io/ja/ch07.html)
>単語の類似度計算や単語アナロジーなどを通して，単語ベクトルの取り扱いを修得します．さらに，クラスタリングやベクトルの可視化を体験します．

##[第8章：ニューラルネットワーク](https://nlp100.github.io/ja/ch08.html)
>深層学習フレームワークの使い方を学び，ニューラルネットワークに基づくカテゴリ分類を実装します．

##[第9章：RNNとCNN](https://nlp100.github.io/ja/ch09.html)
>深層学習フレームワークを用い，再帰型ニューラルネットワーク（RNN）や畳み込みニューラルネットワーク（CNN）を実装します．

##[第10章：機械翻訳](https://nlp100.github.io/ja/ch10.html)
>既存のツールを活用し，ニューラル機械翻訳モデルを構築します．

解答例がない章はまだ取り組んでいない章．
問題出題者の意図に反する部分もあるので，コメントにて教えていただけると幸いです．
mb_convert_encoding()のHTML-ENTITIESの変換は逆変換できない

[`mb_convert_encoding()`](https://www.php.net/manual/ja/function.mb-convert-encoding.php)の第2引数に`HTML-ENTITIES`を指定すると、文字列中の漢字やひらがななどをHTMLの文字実体参照・文字数値参照（`&nbsp;`,`&#128;`みたいなやつ）に変換してくれます。

「漢字やひらがななど」とあえてふわっと書きましたが、正確にはASCII (0x00-0x7F) の範囲外の文字が変換対象のようです（このあたりドキュメントが見つからなかったのでおそらくですが）。

逆に、第3引数に`HTML-ENTITIES`を指定すれば、文字実体参照などをデコードできます。

```php
<?php
$string = 'あいうえお';
$encoded = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &#12354;&#12356;&#12358;&#12360;&#12362;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // あいうえお
```

上記のように、一度変換したあと逆向きに変換すれば元の文字列に戻せる……と思ってしまいそうですが、実はそうとは限りません。
先述したように`mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8')`で変換されるのはASCII範囲外の文字のため、ASCIIの文字は変換されません。つまり、`&lt;`のような文字列をUTF-8→HTML-ENTITIES→UTF-8と変換すると、2回目のみ変換されて`<`になってしまいます。

```php
<?php
$string = '&lt;div&gt;あいう&lt;/div&gt;';
$encoded = mb_convert_encoding($string, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &lt;div&gt;&#12354;&#12356;&#12358;&lt;/div&gt;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // <div>あいう</div>
```

## 対策
これを防ぐためには、`&`を`&amp;`に変換すればいいはずです。変換のタイミングは`mb_convert_encoding()`よりも前です。

```php
<?php
$string = '&lt;div&gt;あいう&lt;/div&gt;';
$encoded = str_replace('&', '&amp;', $string);
$encoded = mb_convert_encoding($encoded, 'HTML-ENTITIES', 'UTF-8');
echo $encoded; // &amp;lt;div&amp;gt;&#12354;&#12356;&#12358;&amp;lt;/div&amp;gt;
$decoded = mb_convert_encoding($encoded, 'UTF-8', 'HTML-ENTITIES');
echo $decoded; // &lt;div&gt;あいう&lt;/div&gt;
var_dump($string === $decoded); // bool(true)
```
【JavaScript】月末日に対して月加算した際の挙動

# はじめに
アウトプットが苦手な自分が練習の一環として記事を書いてみる。

第三回目です。

以前にDateオブジェクトを使って、日付Aのnか月後を日付Bに設定するという処理を作成したのですが、
日付Aが月末日の場合でも日付Bが月末日にならず「なぜ！？」となったことがありました。

なので今回は`月末日に対して月加算した際の挙動`について書いていきます。

# 実際に月末日に月加算してみる

例として`2021/01/31`から1か月後の`2021/02/28`を取得したいとします。

まず、`2021/01/31`でDateオブジェクトを生成しsetMonth()を使用して
生成したオブジェクトに1か月加算してみます。

```javascript:月末日に月加算してみる
const date = new Date(2021,0,31);

console.log(date); //2021-01-31T00:00:00.000Z

// 1か月加算する
date.setMonth(date.getMonth() + 1);

console.log(date); //2021-03-03T00:00:00.000Z
```
実行すると結果は`2021/03/03`となりました。

これは月に1か月加算されることで日付が`2021/02/31`となり2月から3日分はみ出てしまいます。
この場合、3日分次月に繰り越され`2021/03/03`となってしまうからです。

# 対処法
`2021/02/28`を取得するには、日にちが繰り越されたか判定して
繰り越された場合、前月の月末になるよう日付を設定するとよいです。

```javascript:対処法
const baseDate = new Date(2021,0,31);

const result = new Date(baseDate);

// 1か月加算
result.setMonth(result.getMonth() + 1);

// 日にちが繰り越されたか判定
if (baseDate.getDate() > result.getDate()) {
    // 前月の月末に設定する
    result.setDate(0);
}

console.log(result); //2021-02-28T00:00:00.000Z
```

# 加算しても翌月末に足りないケース
先ほどは基準となる月より翌月が日数の少ないパターンでしたが、
次は基準となる月より翌月が日数の多いパターンを見ていきます。

例として`2021/02/28`から1か月後の`2021/03/31`を取得したいとします。

以下のように`2021/02/28`のDateオブジェクトに1か月加算すると`2021/03/28`となってしまいます。

```javascript:加算しても翌月末に足りないケース
const date = new Date(2021,1,28);

console.log(date); // 2021-02-28T00:00:00.000Z

// 1か月加算
date.setMonth(date.getMonth() + 1);

console.log(date); // 2021-03-28T00:00:00.000Z
```

`2021/03/31`を取得するには基準日（今回は2021/02/28）が月末日で
加算後の日付が月末ではない場合の処理を以下のように追加するとよいです。

```javascript:翌月末に足りない場合の調整
const source = new Date(2021,1,28);

const result = new Date(source);

// 1か月加算
result.setMonth(result.getMonth() + 1);

 // 月末日の調整用
const sourceLastDate = new Date(source.getFullYear(), source.getMonth() + 1, 0).getDate();
const resultLastDate = new Date(result.getFullYear(), result.getMonth() + 1, 0).getDate();

// 基準日が月末日で加算後の日付が月末日ではない場合の調整
if (source.getDate() === sourceLastDate && result.getDate() !== resultLastDate) {
    result.setMonth(result.getMonth() + 1);
    result.setDate(0);
}

console.log(result); // 2021-03-31T00:00:00.000Z
```
これで`2021/03/31`を取得することができました。

# まとめ
今回はsetMonth()で月の加算をしたことで値が正しい日付ではなくなった場合、
それに応じて **日にちの値が更新される** ということが分かりました。

月末日の月加算を行う場合、今回のような意図しない挙動となってしまう場合があるので、
実装やテストの際には月末日やうるう年の考慮を忘れないようにしたいですね。

今回は以上です。
本記事が参考になれば幸いです。

参考サイト
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/setMonth
【TimeTree】特定ラベルの予定をLINEに通知するメモ

# 作ったもの概要
- 次の日の予定のうち、特定ラベルの付いた予定のタイトルのメモをLINE Notifyで通知します

![IMG_1390.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50690/a590de40-8b73-38ec-d33f-bb600b0c4243.png)

# 仕組み概要のメモ

## TImeTree側

TimeTree の Calendar APIで次の日の予定リストを取得できます。

https://developers.timetreeapp.com/ja/docs/api/calendar-app#list-upcoming-events

APIの実行にはPersonal Tokenを用いました。

https://timetreeapp.com/developers/personal_access_tokens

## LINE側

LINE Notifyを使いました。アクセスキーを取得してHTTP(S)リクエストでLINE Notify経由でLINEに通知できます。

トークンの取得にはWebで開発者のポータルにログインする必要があるので注意（LINEの設定でID/Passでのログインを許可するひつようがある）。

https://notify-bot.line.me/ja/

## コード抜粋（Ruby）

TimeTreeの予定リストの取得。
Planの構造体クラスに次の日の予定（タイトル、概要）を格納して返します。

```ruby
Plan = Struct.new(:title, :description)

def fetch_plans_from_timetree
  uri = URI.parse(TIMETREE_URL)
  request = Net::HTTP::Get.new(uri)
  request["Accept"] = "application/vnd.timetree.v1+json"
  request["Authorization"] = "Bearer #{TIMETREE_KEY}"

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  response_data = JSON.parse(response.body)
  plans = response_data["data"].map do |data|
    next unless data["relationships"]["label"]["data"]["id"]== LABEL_ID

    Plan.new(data["attributes"]["title"], data["attributes"]["description"])
  end.compact
  plans
end
```

Plan の内容をLine Notifyで通知。

```ruby
def push_plans_to_line(plans)
  plans.each do |plan|
    uri = URI.parse(LINE_URL)
    request = Net::HTTP::Post.new(uri)
    request["Authorization"] = "Bearer #{LINE_KEY}"
    request.set_form_data({"message": "\n#{plan.title}\n#{plan.description}"})

    req_options = {
      use_ssl: uri.scheme == "https",
    }

   Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
   end
  end
end
```
[ActiveHash]今日のエラー

# はじめに
本記事では、本日体験したActiveHashに関するエラーを記述いたします。
ケアレスミスですが、今後も注意するべき問題でしたので、備忘録として残します。

# エラー紹介
早速ですが、エラーを紹介します。
とあるアプリケーションで、最終的な答えは以下の通りです。
ここについては、間違いはありません。
また、かなり省略していますが、コントローラーもビューもモデルも完成しており、
データを保存すること（createアクション）もできます。

```ruby
class Claim < ActiveHash::Base
  self.data = [
    { id: 0, name:'--'},
    { id: 1, name:'着払い(購入者負担)'},
    { id: 2, name:'送料込み(出品者負担)'}
  ]

  include ActiveHash::Associations
  has_many :items

end
```

```erb
~省略~
<% @items.each do |item| %>
  <li class='list'>
    <div class='item-img-content'>
      <%= image_tag item.image, class: 'item-img' if item.image.attached? %>
        <div class='item-info'>
          <h1 class='item-name'>
            <%= item.item_name %>
          </h1>
        <div class='item-price'>
        <span><%= item.price %>円<br><%= item.claim.name %></span>
        </div>
      </div>
    </div>
  </li>
<% end %>
~省略~
```

## 間違えた点
実は、実装したての時、

```ruby
class Claim < ActiveHash::Base
  self.data = [
    { id: 1, name:'--'},
    { id: 2, name:'着払い(購入者負担)'},
    { id: 3, name:'送料込み(出品者負担)'}
  ]

  include ActiveHash::Associations
  has_many :items

end
```
このような記述をしておりました。
`id:1`から記述しておりました。

そして、実装ができているかどうかを確認するため、
createアクションで、`id:3`を選択し、データを保存しました。

実装できたことを確認した後、`id:1`からになっていたことに気づき、
`id:0`からに修正しました。

## 宙に浮いたid:3
最後にもう一度、実装ができているか確認しようとしたところ、
エラーが起きることに気が付きました。
binding.pryで、
claimの中身を確認しても`nil`。
nilは違うだろ、とツッコミを入れ続けて８時間。

過去を振り返ってようやく気がつきました。

## 実装後の修正
これは、かなり注意した方が良さそうです。
これに限らず、
戻って修正した際は、
いろんなものも`付随して修正`しなければならない可能性が大いにあります。

これからは修正した際、
修正箇所と関係を持っているものを注視して、実施していきたいと思います。

# 終わりに
やはり今日もエラー続きでした。
冷静になって考えれば、あっという間でしたが、
正直かなり冷静さを欠いていたと猛省しています。

```
プログラミングは、落ち着いて行わないと、
絶対にいい方向には、傾かない。
```
そう肝に銘じて、
明日も頑張ります！！
さっとスペクトル分析

# 波形データだけではわかりにくい
音声はマイクを振動は加速度センサを使えば取得できてそれぞれのセンサもかなり安価に入手することができます。そうするとIoTなどでもいろいろとデータが集められるようになりますが集めたデータから有用な情報を得るためには、得られたデータを分析しなければなりません。音声などのような波形データを分析する際に用いられることが多いスペクトル分析（周波数の分布を求める）をPythonを使って求めてみます。
# ライブラリ
- Numpy

# 必要な情報
 波形データを取得するときに設定するサンプリング周波数（1秒間にどれだけの頻度で値を取得するか）とサンプリング時間（取得している時間）を控えておきましょう。

# コード

## とりあえずテスト用の波形データをつくってみる
ここでは30[Hz]と20[Hz]の波形の合成波をつくっています。

```py:wave.py
import numpy as np
import math
import matplotlib.pyplot as plt

#データ生成
x=np.arange(0,sampling_time,1/sampling_rate)
y=np.sin(2*30*np.pi*x)+np.sin(2*20*np.pi*x)
plt.figure(figsize=(28,6))
plt.plot(x,y)
plt.show()
```
![wave.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383682/a340fae8-028f-2dcb-4f5b-dc8b56f8def8.png)

これをサンプリング周波数を1000[Hz]、サンプル時間を2[s]として分析してみます。

```py:analyze.py
sampling_rate=1000
sampling_time=2.0
#FFT関連計算
#sampling rateとsampling timeがわかっていれば波形データからスペクトル分析をできる
fft_result=np.fft.fft(y)
n=int(sampling_rate*sampling_time)#データ数
freq=np.fft.fftfreq(n, d=1/sampling_rate)#周波数
Amp = np.abs(fft_result/(n/2)) # 振幅

plt.figure(figsize=(28,6))
plt.plot(freq[1:int(n/2)],Amp[1:int(n/2)])
plt.xlim(0,100)
plt.show()
```

![spectrum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383682/09babfa4-fad8-d340-04c3-f894d57bceb5.png)

このように分析結果も20[Hz]と30[Hz]となっており生成したデータで設定した周波数として取得できました。
このような感じでとりあえず簡単に周波数分布を調べられます。
Shell 特殊变量

`$0` - 脚本名
`$1` 到 `$9` - 脚本的参数。$1 是第一个参数，依此类推。
`$*` - 传递给脚本或函数的所有参数。
`$@` - 传递给脚本或函数的所有参数。被双引号(" ")包含时，与 $* 稍有不同。
`$#` - 参数个数
`$?` - 前一个命令的返回值
`$$` - 当前脚本的进程识别码
`!!` - 完整的上一条命令，包括参数。常见应用：当你因为权限不足执行命令失败时，可以使用 `sudo !!` 再尝试一次。
`$_` - 上一条命令的最后一个参数。如果你正在使用的是交互式shell，你可以通过按下 Esc 之后键入 `.` 来获取这个值。

## $* 和 $@ 的区别

`$*` 和 `$@` 都表示传递给函数或脚本的所有参数，不被双引号(" ")包含时，都以`"$1" "$2" … "$n"`的形式输出所有参数。
但是当它们被双引号(" ")包含时，`$*` 会将所有的参数作为一个整体，以 `"$1 $2 … $n"`的形式输出所有参数；
`$@` 会将各个参数分开，以 `"$1" "$2"... "$n"` 的形式输出所有参数。


下面的例子可以看到 `$*` 和 `$@` 的区别：

```shell
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"

echo "\$@=" $@
echo "\"\$@\"=" "$@"

echo "print each param from \$*"
for var in $*
do
    echo "$var"
done

echo "print each param from \$@"
for var in $@
do
    echo "$var"
done

echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done

echo "print each param from \"\$@\""
for var in "$@"
do
    echo "$var"
done
```

---

参考：

https://missing-semester-cn.github.io/2020/shell-tools/
【SikuliX】スマホゲームの自動化（ウィンドウサイズ・位置固定）

#はじめに
[前回](https://qiita.com/kazu_kr/items/5865541a3ad05ce810aa)の記事では、スマホゲームを自動化するためのサンプルコードを記載しました。
今回はSikuliXを使用していて発生する問題の解決策を記載していきます。

#発生する問題
SikuliXでは画面上の画像を認識してスクリプトにより操作を自動化します。
しかし、指定した画像サイズが画面上に表示されている画像サイズと違う場合、うまく画像認識されずスクリプトが正しく動作しない場合があります。
   
例えば、BlueStacksなどのエミュレータではウィンドウサイズを自由に変えることが可能です。
ウィンドウサイズ変更してしまい元のサイズに戻せなくなり、検索画像の取り直ししなければならない状況が発生することがあります。

この事象を解決するため、対象のウィンドウサイズを固定にする方法を検討しました。

#サンプルコード
```setwindow.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import ctypes

# ウィンドウハンドラ取得
hWnd = ctypes.windll.user32.FindWindowW(0, "BlueStacks")

# 移動＆リサイズ
ctypes.windll.user32.MoveWindow(hWnd, 1200, 0, 700, 1100, 1)
```

#解説
サンプルコードは今回もBlueStacksを使用した例です。

FindWindowWでウインドウ名「BlueStacks」のハンドラを取得し、そのハンドラに対してMoveWindowで(1200,0)の位置で700x1100のサイズに移動とリサイズをしています。

しかし、SikuliX2.0.4に組み込まれているPythonではWin32関連のモジュールは組み込まれていないようで、そのまま自動化のスクリプトに組み込んで実行するだけではエラーが発生します。

SikuliX上ではWin32関連モジュールは動作しない仕様のようなので、SikuliX上では動作させずウインドウサイズの変更はWindowsのコマンドラインから実行します。
SikuliXは、そのスクリプトを実行させることで実現します。

上記スクリプトを「C:\sikuli\setwindow.py」に保存したとします。
SikuliX上の別スクリプトから以下の記述で呼び出すことでsetwindow.pyが実行されます。

```呼び出し元.py
#ウィンドウサイズ固定
import subprocess
subprocess.call('python C:\sikuli\setwindow.py')

#以降は自動化スクリプトを記載

```

上記記述を自動化スクリプトの先頭に追加することで、ウィンドウサイズや位置を変更した場合でも、元の位置に戻すことが可能となります。

#まとめ
SikuliX外のPythonスクリプトをSikuliXから実行させることでWin32関連のウインドウサイズ変更を動作させるようにしました。

SikuliXを実行するとき、毎回固定したウインドウサイズにすることで画面サイズが変わることによる認識されない問題を回避できます。
自分の動作環境に応じて表示させる位置や画面サイズの数字を変更し使用してみてください。
Dockerのコンテナ操作をRLoginで行うための方法

# はじめに
Windowsでのターミナルとしては、TeraTermやRLoginなどが有名ですが、こういった使い慣れたターミナルでDockerコンテナにアクセスする方法はないものかと調べたところ、少し工夫することで実現できたので記事にまとめたいと思います。

# 動作確認環境
- Windows10 Home
- wsl2
- Docker Desktop for Windows
- Ubuntu20.04 LTS
- RLogin

# 仕組み
Dockerコンテナへ直接RLoginでアクセスすることはできませんが（ssh接続ではないため）、DockerEngineを動かしているLinux（Ubuntu）に対しssh接続することでRLoginでコンテナ操作できるようになります。

ローカル環境へのアクセスのため、パスワードのみ版の操作でも問題ないですが、調査のため鍵認証版も試してみたので合わせて方法を掲載したいと思います。
どちらか片方を実行することでRLoginから接続できるようになります。

# 方法（パスワードのみ版）

```bash
# 以下はすべてUbuntuでの操作です
# 下記ファイルにアクセスし、PasswordAuthenticationの部分の設定をyesに変更します
sudo vi /etc/ssh/sshd_config

# ホスト鍵を生成する
sudo ssh-keygen -A

# sshを起動する
sudo service ssh restart
```


# 方法（鍵認証版）

```bash
# ホスト側（Windows側）での準備---------------
# C:\Users\{ユーザー名}\に移動する
cd C:\Users\{ユーザー名}\

# 鍵の置き場を作る
mkdir .ssh
cd .ssh

# 鍵を作成する(確認等が表示されるので、Enterを続けて入力する。パスワードは不要)
ssh-keygen -t rsa -b 4096 -f 鍵の名前

# 秘密鍵と公開鍵ができていることを確認する
# .pubと付いている方が公開鍵
ls

# 公開鍵の中身を確認する。中身をコピーする
cat {鍵の名前}.pub

# ubuntu側での設定--------------------------
# ホスト鍵を生成する
sudo ssh-keygen -A

# sshを起動する
sudo service ssh restart

# 公開鍵をセットする
# ホームディレクトリへ移動
cd

# 鍵を配置するための場所を用意する
mkdir .ssh
chmod 700 .ssh/
cd .ssh

# 公開鍵をセットする
# authorized_keysというファイルを生成し、中に先程コピーした公開鍵の内容を貼り付けする
# もしすでにauthorized_keysが存在し、中に別の公開鍵が登録されている場合は、新しい行に貼り付ければ大丈夫です
vi authorized_keys

# 権限の変更
chmod 600 authorized_keys
```

# SSHを常時起動する（共通）
この操作はパスワードのみ版、鍵認証版どちらの操作の場合も必要です。

```bash
sudo service ssh restart
```

こちらの操作がパソコン再起動の度に必要になるため、自動化します。
Win＋Rキーを同時押しして、shell:startupを入力してEnterを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490767/4e1ab168-0c5e-a1dd-d47b-ca725e00bda5.png)
自動起動用のファイルを格納するフォルダが表示されるので、wsl2ssh.batという内容のファイルを作成し、以下をファイル内に貼り付けます。
以後はパソコン再起動の度に自動的にsshが再起動します。

```bash
wsl -d Ubuntu-20.04 -u root -- service ssh restart
```

# RLoginでのUbuntuへのアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490767/583094a8-96ee-8a60-9871-5b217782ecd9.png)
※xterm-colorにしておくと、カラフルな配色となり見やすくなります
※UserNameやPasswordはUbuntuのものを適時入力下さい

# 参考ページ
https://qiita.com/kenchan1193/items/896c416a4ee89cd4f95b

https://www.virment.com/how-to-connect-to-server-by-ssh-with-publickey/

https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html

https://eng-entrance.com/linux-ssh-host
Gradle task 'assembleDebug' 対応

#実行すると Gradle task 'assembleDebug' で進まない

前回のセットアップで実行するが、「Gradle task 'assembleDebug'」と出力されたまま。
ファンが回ってるからなにかやってるのかもですが。
![Screenshot 2021-08-09 23.30.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/c42f645f-a451-a9d1-59e0-9155c733c6a0.png)

SDKのバージョンの設定とかもやれば行けるという記事見てやってはいましがた・・・。
現状はダメです。

で、更にググってみて以下のコマンドを実行。
flutterのプロジェクト内に移動後です。
ちなみにgradlew buildで20%から進まなくなり、一度リブートさせて再実行で最後まで行けました。

```
$ cd android
$ ./gradlew clean
$ ./gradlew build
$ cd ..
$ flutter clean
$ flutter doctor
```

ですが、ダメですね。変わりなし。

起動したときもあるので、大きく間違った状態ではないと思うのですが。
まぁ動いたときもException出てたんですけどね。
![Screenshot 2021-08-08 19.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/f415488d-a8cd-772f-6b86-407796547406.png)
【Blender】キノコを光らせる

環境メモ
⭐️Mac OS Mojave バージョン10.14
⭐️Blender2.92

キノコを光らせる
↓↓↓完成内容
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🍄Blender🍄<br>🍄キノコを✨光らせてみたよぉ🤩🤩<br>キノコ周りも🌟ぼんやり🌟光らせてみたよぉ😊<br>キラキラ💫キラキラ💫<a href="https://t.co/O9fAMsC28I">https://t.co/O9fAMsC28I</a><a href="https://twitter.com/hashtag/blender?src=hash&amp;ref_src=twsrc%5Etfw">#blender</a> <a href="https://t.co/qIKgMp6RI7">pic.twitter.com/qIKgMp6RI7</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1424741819250741254?ref_src=twsrc%5Etfw">August 9, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

キノコ全体を黄色にしたり
![スクリーンショット 2021-08-09 22.35.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/e2484f42-3f87-ddb2-4842-1cf61062a1c4.png)

赤くしたり
![スクリーンショット 2021-08-09 21.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/8ab9ddb4-7066-7ac6-63d2-29029b72b6a6.png)


青くしたり
![スクリーンショット 2021-08-09 22.19.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/4dbcea8e-ec46-5a4b-c6b4-0528e2afc9fa.png)


緑にしたり
![スクリーンショット 2021-08-09 22.32.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/ffaf457c-3d2b-bbec-80db-d670d8a992d2.png)


光の範囲を変えたりで調整できる
![スクリーンショット 2021-08-09 22.33.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/7069f6a2-bd60-9fda-bdbe-49745ea6994a.png)

## キノコのマテリアルをEmissionに設定する
キノコのマテリアル（色）Emissionにして光の強さを調整する
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/589b5159-0a17-1ad4-cb9d-01a8df93670e.png)

## Eeveeする
レンダラーを「Eevee」にする
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/48e7ae4f-e8c1-d1e0-7f73-97f025aeceec.png)

BloomをチェックONにすると、キノコ全体が光る
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/3129d0d7-eb15-6b01-2c11-4d67b17335d8.png)


Bloomのプロパティで、色や光の強さで調整できる
![スクリーンショット 2021-08-09 21.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/8310b1e5-da0f-c3dd-0dba-f85cf63d4e7e.png)

青色
![kinokos_bloom_blue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/d8edaa8a-e8b0-4831-b573-268cce8a89e4.png)

赤い色
![kinokos_bloom_pink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/89990785-2d0b-1b9e-c287-f5b4932f6748.png)

黄色
![kinokos_bloom_yellow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/91e73b83-258f-4ae7-7843-3854907e6bf4.png)


完了！
プログラミング一日目　-学ぶ前の準備-

#プログラミング一日目　-学ぶ前の準備編-
＊こちらはwindows版に対応する記事です



---
今日、準備したものは、
・VScodeのインストール
・Slackのインストール
・Windows Terminalのインストール
・Google Chromのインストール
・Git hubのアカウント作成
・Qiitanoアカウント作成
・Twitterのアカウント作成
・Markdownの記述法を学ぶ
　
---

###・VScodeのインストール
　VScodeはプログラミングのコードを書いていく場所
　
###・Slackのインストール
　Slackはチームのコミュニケーションやメッセージングのアプリ
###・Windows Terminalのインストール
　
 windows terminalhはコンピュータを対話的に操作するために用意された
CUI(Character　User　Interface)アプリケーション

###・Google Chromのインストール
　書いたコードを反映させるときに使う

###・Git hubのアカウント用意
　ウェブページの公開やバージョン管理に使う


###・Qiitaのアカウント用意
　情報発信、収集に使う


  
###・Twitterアカウントの作成
　情報発信、収集に使う
  
###・Markdownの記述方法を学ぶ
　プログラミング言語ではないが、それと似て、テキストやグラフを作る際に
　楽に書けるようにする記述法
```



```
明日　ー　HTMLとCSSを使って実際にサイトを作る
[Atcoder] ABC213(C問題)の整理

### 概要 
* AtCoder Beginner Contest 213 C問題に関して、備忘録を兼ねてコードを整理します。
* 問題は下記のリンクです。

https://atcoder.jp/contests/abc213/tasks/abc213_c

* 環境 : Python 3.8

### 解法
何の数字も書いていない行・列は取り除かれるため、結果的に$\\{A_i\\}$, $\\{B_i\\}$それぞれの要素を、数字が小さい方から順に(最も小さい要素を1として)順位付けすればよいと考えることができます。ただし同じ値の要素は、操作の結果も当然同じ行・列に移動するため同じ順位をつけなければならず、かつ同じ順位が続いた(同じ値の要素が複数あった)場合でも順位は飛ばさない点に注意が必要です。

### 解答例
```python
# 標準入力
H, W, N = map(int,input().split())
A, B = [], []
for i in range(N):
    a, b = map(int, input().split())
    A.append(a)
    B.append(b)

# 重複を除いた番号と、それが小さい方から何番目かというindexを対応させる辞書を作成
# A:カードがある行数、B:カードがある列数
A_set = set(A)
B_set = set(B)

A_dict, B_dict = {}, {}

for i, A_name in enumerate(sorted(A_set),1):
#enumerateの2番目の引数は、数え始める数値
    A_dict[A_name] = i
    
for j, B_name in enumerate(sorted(B_set),1):
    #B_dict = {B_name:j}
    B_dict[B_name] = j

# 元の配列A,Bにおいて各要素が小さいほう方から数えて何番目かを辞書を参照してprint    
for i in range(N):
    print(A_dict[A[i]], B_dict[B[i]])
```
公式の解答例を参考に作成しました。特に後半では、$\\{A_i\\}$, $\\{B_i\\}$の要素が、それぞれ小さい方から数えて何番目なのか、という順位とセットになった辞書型を作成しています。具体的には($\\{A_i\\}$に絞って見てみると)、

* $\\{A_i\\}$から重複を除いた配列を作成。

```python
A_set = set(A)
```

* sorted関数でA_setを小さい順に並べ替えた上で、enumerate関数で対応した順位とセットにした辞書を作成し、それを1つずつA_dictに保存して辞書を作成。
 
```python
for i, A_name in enumerate(sorted(A_set),1):
#enumerateの2番目の引数は、数え始める数値
    A_dict[A_name] = i
```

* 元の配列$\\{A_i\\}$に関して、作成した辞書を参照しながら、対応する順位を表示。
 
```python
for i in range(N):
    print(A_dict[A[i]], B_dict[B[i]])
```
となっています。



### コメント
* 問題文を素直に受け取ると「何の数字も書いていない行・列を探索する」ことから始めそうですが、そうすると上手く解けない(または処理時間がオーバーする)と思われます。
* numpyのargsort()関数を用いると、順位付けの際に同じ値の要素を別の順位でつけてしまうため上手くいかないようです。

以上
【Django】Django Rest API（認証あり）にリクエストをする

## 概要
DjangoのRest APIにPOSTでリクエストを行う際にちょっとハマったので、書いておこうと思います。

## 問題
curlで試しにGETリクエストを行ったところ、問題なく動作するが、POSTでリクエストを行ったところcsrf tokenが無効というエラーが出た

レスポンスには明確な理由が書いてなかったので、uwsgiのログを見た

```
WARNING Forbidden (Referer checking failed - no Referer.)
WARNING:django.security.csrf:Forbidden (Referer checking failed - no Referer.)
```

Refererがないと弾かれてしまうっぽい

## 解決方法

リクエストヘッダーに `Referer`を設定することで解消できた。

以下のようにすることでリクエストを行うことが出来た

```sh
$ curl -X POST -b "csrftoken=hoge; sessionid=hoge;" -H "x-csrftoken: hoge" -H "Referer: https://hoge.com" -d '{"data": "hoge"}' "https://endpoint.com/api/hoge"
```

GETリクエストの場合は、Refererがなくても動作したので、なくて大丈夫っぽいです
TerraformでTFlintが効かなくなったときの対処

## これは何
TerraformでTFlintが効かなくなったときのメモです。
VScodeのProblem欄に文法エラーが出なくなりました。

## 原因
Terraform Language ServerのUpdateをしていなかったのが原因でした。
そういえば、VScodeの右下になんか更新のお知らせきてたな〜とは思ってましたが、まさかこれとは…

なんでこれなのかというと、はっきりと納得はできていないのですが、GitHubの開発概念を見にいったらなんとなく理解できました。
Language Serverを見にいってるんですかね。

```
【引用】
TFLint is just a thin wrapper of Terraform. 
Configuration loading and expression evaluation etc. 
depend on Terraform's internal API, 
and it only provides an interface to do them as a linter.
```

とりあえず解決はできたものの、
そもそもLinterってなんだ、という理解が自分にはもっと必要そうです。
どなたか詳しい方がいらっしゃったら、ご教示願いたいです。

```
【参考】
https://github.com/terraform-linters/tflint/blob/master/docs/developer-guide/architecture.md
https://github.com/terraform-linters/tflint/blob/master/docs/developer-guide/core-concept.md
```
物理macOSをParallelsの仮想環境に移行（備忘メモ）

**物理macOS（移行元）**・・・ macOS 10.13 (Mac mini)
**移行先**・・・ macOS 10.15 上の Parallels (MacBookPro)
*物理macOSにも Parallels が入っている*

## 移行元作業
1. 物理macOS上の移行不要なデータは消しておく（移行時間と容量の短縮）
1. 物理macOSのバックアップを Time Machine で外付ストレージに取得
1. 物理macOS上の parallels のインストールアシスタントで「インストールmacOS 10.13.X 回復パーティションを使用」で仮想環境を作成
1. 作成後、仮想環境が起動したらすぐにシャットダウン
1. 作成された仮想環境「macOS 10.13.X.pvm」を移行先にコピー

## 移行先作業
1. 「macOS 10.13.X.pvm」を parallels で開き追加
1. macOS 10.13.X の構成で Time Machine バックアップを戻せる容量のハードディスクを追加
1. macOS 10.13.X を起動
1. 追加したハードディスクの方に Time Machine バックアップを回復
1. 構成でデフォルトハードディスクを削除
ターミナルコマンド集

##現在のディレクトリのファイルを表示
```
＄ls
```
##現在地のパスを表示
```
$pwd
```
##空のファイルを表示
```
$touch ファイル名
```
##ファイルへのテキスト記載
```
$ echo "記載内容">ファイル名
```
##ファイルへのテキスト追記
```
$ echo "記載内容">>ファイル名
```
##ファイル名の変更
```
$mv 変更するファイル名　　変更したいファイル名
```
##ファイルの移動
```
$ mv 移動したいファイル名 移動後のディレクトリ
```
##ディレクトリの移動
```
$cd ディレクトリ名
```
##ディレクトリの作成
```
$mkdir ディレクトリ名
```
##ファイルのターミナルに表示
```
$ cat ファイル名
```
##ファイル・ディレクトリの削除
```
$rm ファイル名
```
##ディレクトリの削除も許可する場合
```
$rm -r ファイル名
```
##ファイルのコピー
```
$cp コピーするファイル名 新しいファイル名
```
XigmaNASほかのsystemから持ってきたZFSのHDDを使う方法

自分用のメモ

Nsa4Freeから持ってきたZFSのHDDが認識しなくてこまった。

# XigmaNAS
HDDを差し込んでGUIからいろいろやるが、なにもできない。
なんか消しちゃいそうで怖い。

インポート可能なpoolを表示

```sh
zpool import
ここにダラダラとでてくる
名前が出てくるので↓のコマンドに入れる
```

```sh
xigmanas: ~# zpool import ssd
cannot import 'ssd': pool was previously in use from another system.
Last accessed by <unknown> (hostid=0) at Mon Aug  9 01:18:18 2021
The pool can be imported, use 'zpool import -f' to import the pool.
xigmanas: ~# 
```

他システムのプールは-fで強制的に取り込むらしい。

`zpool import ssd`実行後 XigmaNASのguiから
ディスク > ZFS > 設定 > 同期で同期ボタンを押下すると XigmaNASで認識する
Google AdMob（AdSense）　銀行口座の名義で「入力値が無効です」となる場合

#なぜ「入力値が無効です」となる！！！？？
受け取り口座の入力の際、名義人の欄に通帳名義を書いてもエラーが出ます。

**漢字・全角カタカナ・半角カタカナ**など色々と試したがうまくいかない！！！なぜ？？

#半角カタカナ + 半角スペース

ヤマダタロウ → ×
ヤマダ　タロウ → ×

ﾔﾏﾀﾞﾀﾛｳ → ×
**ﾔﾏﾀﾞ ﾀﾛｳ → ◯**

👆のように半角カタカナ + 半角スペース:ok_hand:で入力通りました！！

これで「お受け取り方法」を設定できました。
M1 MacにPython3をインストールする

# はじめに
Apple M1チップ搭載のMac Book ProにPython3をインストールした時のメモです。
今回は[Miniforge](https://github.com/conda-forge/miniforge)を利用しました。

# やり方
[Miniforge](https://github.com/conda-forge/miniforge)とは最小限のCondaのインストーラーです。
さまざまはCPUアーキテクチャのサポートに重点を置いているので、新しいCPUアーキテクチャのPCにCondaを入れるときに最適です。
今回は直接ダウンロードする方法を紹介します。

## 1. Githubからダウンロードする。
[ここ](https://github.com/conda-forge/miniforge#download)からOS X	arm64 (Apple Silicon)Miniforge3-MacOSX-arm64を選択してダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1197937/e6eebbb4-1941-c463-ced1-70f6e5c80737.png)

## 2. 以下をターミナルで実行します。ここではzshを選択しています。
選択肢は全てyesを選択します。

```
cd Downloads/
bash Miniforge3-MacOSX-arm64.sh
```

## 3. 赤線の部分のPathにある.bash_profileを開いて全てコピーする。

![イラスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1197937/1efb3094-73b9-2836-ae55-a3f09a825d63.png)

Condaのインストールがうまくいっていれば以下のようなものが書き込まれているはずです。

```
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/***/miniforge3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/Users/***/miniforge3/etc/profile.d/conda.sh" ]; then
        . "/Users/***/miniforge3/etc/profile.d/conda.sh"
    else
        export PATH="/Users/***/miniforge3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<
```
これを全てコピーします。

## 4. ~/.zsh_profile にコピーした内容を書き込む

```
vim ~/.zsh_profile 
source ~/.zsh_profile 
```

これで成功していれば以下を実行できるはずです。

```
conda -V
```

## 5. CondaでPythonをインストールする

```
conda create -n py3.8 python=3.8
conda activate py3.8
```

# まとめ
Apple M1チップ搭載のMac Book ProにPython3をインストールしました。
SLI,SLO,SLA それぞれ見てみる

## 勉強前イメージ

SLOとSLAごっちゃになるのとSLIは知らん

## 調査

### SLI,SLO,SLAとは

- SLI

`Service Level Indicator` の略で、サービスの品質を測る指標で
ユーザに提供するサービスから計測される値を定義したものになります。
リクエストのレイテンシ、エラー率やスループットなどがこちらに当たります。

![12021-08-05 # SLI,SLO,SLA それぞれ見てみる - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/4b51fb9b-e9a0-b261-8be8-82a0fd87e1c0.png)


- SLO

`Service Level Objective` の略で、サービスレベルの目標値になります。
SLIで測定されるサービスレベルの目標値がSLOになります。
webサーバだったら「リクエストの平均レイテンシのSLOを100ms未満にする」など定義をします。

![22021-08-05 # SLI,SLO,SLA それぞれ見てみる - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/610f9ecc-a9c0-5e49-2e05-25d853fc8c0e.png)


- SLA

`Service Level Agreement` の略で、サービスレベルについてお客様との合意したものになります。
定義したSLOを満たすお客様との合意した内容になります

![32021-08-05 # SLI,SLO,SLA それぞれ見てみる - diagrams.net -.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/5e46debf-6385-8f73-67e6-3b7c54516686.png)


## 勉強後イメージ

結果的にも守らないといけないのは、SLAってことか。
SLI → 何を定義するか
SLO → SLIの目標値どうする？
SLA → お客様と合意した目標値


## 参考

- [第2回　SREのはじめかた](https://www.sysadmingroup.jp/kh/p22523/)
[EC2] pingとICMPについて

EC2のネットワークの設定をしている際、疎通確認としてpingをしてもレスポンスが返ってこなかったため原因を調べました。

# 原因
セキュリティグループのインバウンドルールでICMPの通信を許可していなかったことが原因でした。

# pingとは
元々pingを「ネットワークの疎通を確認するもの」として曖昧に理解していました。

pingの仕組みを調べたところ、
> 指定したIPアドレス宛てにICMPエコー要求メッセージを送信しています。これは「送ったデータをそっくりそのまま送り返してください」という内容です。ICMPエコー要求メッセージを受け取ると、ICMPエコー応答メッセージとして、データをそのまま送り返します。ICMPエコー応答メッセージが返ってくれば、Pingは成功です。

とあります。[^1]
ここで `ICMP`という単語が出てきました。
詳細に理解するにはこの部分を知る必要がありそうです。

# ICMPとは
まずICMPとは、Internet Control Message Protocolの略で、TCP/IPにおけるインターネット層で利用され、接続しているサーバ間の通信状態を確認するプロトコルです。[^2]
HTTPやSMTPなどがTCP/IPの一番上の層にあたるアプリケーション層であるのに対し、インターネット層というのはそれよりも下の層で、複数のネットワーク間のデータ転送を担っています。

TCP/IPに関してはこちらの説明がとてもわかりやすかったです。
https://www.itmanage.co.jp/column/tcp-ip-protocol/

平たくいうと、ICMPはそのネットワーク間の通信状態を確認するためのプロトコルとなります。

その上でpingというのは、ICMPのプロトコルを利用して通信状態を確認できるソフトウェア、という位置付けになります。
今回の事例では、pingが通らなかったのはICMPの通信を許可していなかったためであり、設定してpingが通ることが確認できました。

# 結論
pingはICMPを利用してインターネット層における通信状態を確認できるものであり、EC2サーバへpingを通すにはICMPを使った通信を許可する必要があります。

[^1]: pingの仕組み https://www.n-study.com/tcp-ip/ping/
[^2]: ICMPとは https://www.fenet.jp/dotnet/column/%E8%A8%80%E8%AA%9E%E3%83%BB%E7%92%B0%E5%A2%83/icmp/8149/#ICMP
【条件分岐】商品が売却されていたら処理をする方法

今回覚えたことをメモします。
◇実装内容
商品購入機能後の条件分岐

◇結論◇
ビューファイルに、「item.purchase」と記述をすると「商品に紐づく購入履歴」という形で処理をしてくれた。
そこにif文を加えて「もし、その商品を購入していたら〜処理〜」とうい記述ができた。
※モデル名で名前は変わる。

↓は「もし、その商品を購入していたらSold Out!!を表示させる」

```perl:index.html.erb
  <% if item.purchase %>
     <div class='sold-out'>
       <span>Sold Out!!</span>
     </div>
  　<% end %>
```
◇前提◇
2つはアソシエーションが組まれている
商品情報：itemモデル
購入履歴:purchaseモデル
　カラム：user_id
　　　　：item_id


◇別の例◇
↓コントローラーに記述。before_actionメゾットで編集ページは商品が購入されたら、root_pathへ戻る形になる。

```perl:items_controller.rb
before_action :item_purchase ,only: :edit

def edit
@item = Item.find(params[:id])
end

 def  item_purchase
  @item = Item.find(params[:id])
   if @item.purchase
    redirect_to root_path
   end
 end

```

本日は以上です。
【Mac】ReactとPython flaskを使ったWebアプリ

Reactの基本的な勉強を済ませ、簡易アプリのソースを読んで知見を蓄え中の身です。本記事は、下記の記事に触発され、愛用しているMacbookのローカル環境で実行した時のメモです。

https://qiita.com/Pu-of-Parari/items/f3733f0ba48e1df50667

## どんなアプリ？
>mecabを使った分かち書きスクリプトを使って、フロントで受け取った入力テキストをサーバー側で分かち書きをし、その結果をフロントで表示するという非常にシンプルなアプリです。

## どんな構成？
>フロント側はReact、サーバー側はpython flaskで実装しています。

## 実装環境
```
macOS Big Sur 11.2.3
Python: 3.9.6
flask==1.0.2

npm: 7.20.3
```

## 1. Mecabのインストール
日本語の形態素解析エンジン"MeCab"をMacにインストールしてPython3から利用します。

https://qiita.com/taroc/items/b9afd914432da08dafc8

https://github.com/neologd/mecab-ipadic-neologd

```sh
$ brew install mecab
$ brew install mecab-ipadic
$ brew install git curl xz yarn

$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
もしくは
$ git clone --depth 1 git@github.com:neologd/mecab-ipadic-neologd.git

$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n
$ brew install swig
```
これでmecab-python3をpip installできるようになりました。

## 2. ソースをgit clone
mecab-ipadic-neologdフォルダ内にいる場合は、別フォルダに移動した方が良いでしょう。ここでは親フォルダに移動します。その後、ソースコードをgit cloneします。

https://github.com/Pu-of-Parari/jparser_app

```sh
$ cd ..
$ git clone https://github.com/Pu-of-Parari/jparser_app.git
$ cd jparser_app
$ ls
README.md	backend		frontend	ref
```
## 3. サーバー側の準備
まだ動きません。python3の仮想環境内で必要なモジュールをインポートします。

```sh
いま、jparser_appフォルダ内にいます。
$ cd backend

venvという名前で仮想環境を作成します。
$ python3 -m venv venv
$ source venv/bin/activate

一応、pipをアップグレードします。
$ python3 -m pip install --upgrade pip

requirements.txtを用いて、必要なモジュールをインストールします。
$ pip install -r requirements.txt
```
手順１を飛ばし、homebrewでmecabをあらかじめインストールしておかないと、ここでエラーが出るでしょう。

## 4. バックエンドのサーバを立てる
```sh
いま、backendフォルダ内にいます。
$ python3 server.py
```
問題が起きなければ、これでバックエンドサーバの準備は完了です。

## 5. フロントエンドのサーバを立てる
まず、フロントエンド用に先ほどとは別のターミナルを立ち上げてください。立ち上げたら、jparser_app/frontend/appフォルダに移動します。

```sh
$ cd jparser_app/frontend/app

axiosがインストールされていない場合は、axiosをインストールします。
$ npm install axios

node_modulesフォルダを作成します。
git cloneした場合、node_modulesフォルダは基本的にありません。
local環境に依存するため、通常は.gitignoreで無視します。
$ npm install

フロントエンドサーバを立てます。
$ yarn start
```
これでフロントエンドサーバの準備は完了です。

そして、全ての準備が完了です。お疲れさまでした。

## localhost:3000にアクセス
ブラウザからlocalhost:3000にアクセスします(yarn startで自動で開きます)。

#### app screenshots
![app_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577794/c58cc217-d716-432e-b7dd-94c2aacbc572.png)
![スクリーンショット 2021-08-09 22.29.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577794/51e29034-736a-eeaa-2eea-b755daa5642a.png)
golangでiterator patternを実装する


# iteratorパターンとは？
何かがたくさん集まっているときに、それを順番に指示していき、全体をスキャンしていく処理を行う。

# 実装

```golang
package main

import "fmt"

type collection interface {
	createIterator() iterator
}

type userCollection struct {
	users []*user
}

func (u *userCollection) createIterator() iterator {
	return &userIterator{
		users: u.users,
	}
}

type iterator interface {
	hasNext() bool
	getNext() *user
}

type userIterator struct {
	index int
	users []*user
}

func (u *userIterator) hasNext() bool {
	return u.index < len(u.users)
}

func (u *userIterator) getNext() *user {
	if u.hasNext() {
		user := u.users[u.index]
		u.index++
		return user
	}
	return nil
}

type user struct {
	name string
	age  int
}

func main() {
	var uc collection
	user1 := &user{
		name: "a",
		age:  30,
	}
	user2 := &user{
		name: "b",
		age:  20,
	}
	uc = &userCollection{
		users: []*user{user1, user2},
	}
	iterator := uc.createIterator()
	for iterator.hasNext() {
		user := iterator.getNext()
		fmt.Printf("User is %+v\n", user)
	}
}

```

# 参考
https://golangbyexample.com/go-iterator-design-pattern/
今更ながらダークテーマ対応

最近になってようやくダークテーマ関連に足を踏み入れたのでまとめてみようと思いました。

## 呼び方
・私も勘違いしていたのですが、Androidはダークモード・ライトモードではなくダークテーマ・ライトテーマと呼ぶそうですね。
参考：[ダークテーマ](https://developer.android.com/guide/topics/ui/look-and-feel/darktheme?hl=ja)

## 色分け
・ライトテーマ（デフォルト）は今まで通りvalues/colors.xmlに定義しておくとして、ダークテーマ用のものはどうすれば良いのでしょうか。答えは簡単で、values-night/colors.xmlを作成、その中に定義しておけばよさそうです。
ただし、ライトテーマ用のcolors.xmlに定義がないものをダークテーマ用のcolors.xmlに定義することはできないようです。あくまでオーバーライドです。

## 基準色
・themeとして設定。以下あたりでしょうか。
>Theme.AppCompat
Theme.AppCompat.DayNight
Theme.MaterialComponents.DayNight

## 任意のタイミングでテーマを切り替える
・最近はアプリ毎にテーマを設定できることがありますね。そのような場合はアプリ内設定画面などに適当なラジオボタンなどを置いてユーザの入力を読み取り、変更&保持を行えばよさそうです。
保持しているものを該当ActivityのonCreateで実行すると再度onCreateが走ってしまうので、もっと前段でテーマは決めてしまうのがよいですね。
（また、各Activityで受け取ることもできるようです。参考：[ダークテーマ　構成の変更](https://developer.android.com/guide/topics/ui/look-and-feel/darktheme?hl=ja#%E6%A7%8B%E6%88%90%E3%81%AE%E5%A4%89%E6%9B%B4)）
切り替えなどを行うUtilクラスがあると便利そうですね。ざっくりサンプルですが。

```SampleThemeManager.kt
object SampleThemeManager {

    /**
     * テーマを変更する（アプリ全体に反映）.
     * @param mode MODE_NIGHT_YES, MODE_NIGHT_NO, MODE_NIGHT_FOLLOW_SYSTEM
     */
    fun changeTheme(mode: Int) {
        // OS10以上の時だけ実行する
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return
        }

        // modeが妥当かのチェック処理

        // 実際に変更する
        AppCompatDelegate.setDefaultNightMode(mode)

        // 設定された値を保持する処理
    }

    /**
     * テーマを変更する（Activity単位で反映）.
     * @param appCompatDelegate activityのdelegateなど
     * @param mode MODE_NIGHT_YES, MODE_NIGHT_NO, MODE_NIGHT_FOLLOW_SYSTEM
     */
    fun changeTheme(appCompatDelegate: AppCompatDelegate, mode: Int) {
        // OS10以上の時だけ実行する
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return
        }

        // modeが妥当かのチェック処理

        // 実際に変更する
        appCompatDelegate.localNightMode = mode

        // 設定された値を保持する処理
    }

    /**
     * ダークテーマかどうか.
     * @param activity チェック対象
     * @return trueならばダークテーマ
     */
    fun isDarkTheme(activity: Activity): Boolean {
        return activity.resources.configuration.uiMode and
                Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
    }
}
```

上記にあるように、適用範囲によって使い分ける必要があります。

| アプリケーション全体に適用する | Activityにだけ適用する |
|:-:|:-:|
| AppCompatDelegate.setDefaultNightMode()  |  appCompatDelegate.localNightMode |


## 最後に
ダークテーマはもはや無ければならないものになっているので、今後も知見を広げていきたいと思います。
リリース後の機能追加等でダークテーマを実装する場合はリソースの整理が大変になるので、できれば最初から要件には入れていきたいです。
Chapter 1 - §01 Python 3 の準備

# Python 3 のインストール

PythonにはPython 2 と Python 3 がありますが、Python 2 はこれからはバージョンアップされることはないので、Python 3 で解説していきます。

### Python 3 のオフィシャルサイト

[Python 3 のオフィシャルサイト](https://www.python.org/downloads/)
ここからPythonを無料でダウンロードできます。

インストールの仕方は[このサイト](https://techacademy.jp/magazine/15571)を参考にしてください。

# 統合開発環境の用意
おすすめは、Visual Studio CodeまたはPycharmです。
どちらかをインストールしてください。

### ・Visual Studio Code(VScode)のインストール
[ここから](https://code.visualstudio.com/download)インストール。


### ・Pycharmのインストール
[ここから](https://www.jetbrains.com/ja-jp/pycharm/download/#section=windows)インストール。

#Pythonを起動してみる
インストールが完了したら、画面の左下のwindowsロゴマークをクリックして一番上にPython 3.x.x (64bit)　と書かれたプログラムがあるのでそれをクリックします。

↓この画面が出ればOK
![941faf69f7551bd16583196dd54758d6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1581903/24c46a21-00a8-65f3-bbef-a462900d7531.png)

# コードを書いて動かしてみる
この画面が出たことで、pythonは動かせるようになりました。
定番の"Hello World!!"を表示させましょう。

```python
print("Hello World!!")
```

これを
`>>>`
の後に打って、Enterを押してみましょう。
![adf7656a0f08cf3e716fad9622efcb20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1581903/8a867592-6f2f-8673-e60d-f5e177bc57b2.png)
このようになれば成功です。



今回はこれで終わりにします。
次回からは開発環境を使います。
お疲れ様でした。

次回：[計算・コメント](https://qiita.com/confrict/items/823bb4b20946cdeba023)

間違いなどのご指摘がございましたら、修正依頼を出していただけたら幸いです。

#余談
pythonは十分な機能がありますが、それでも足りないものが出てくることがあります。
それで、よく使われる外部ライブラリを最初から組み込んである状態で配布されているものもあります。
その一例として、Anacondaというものがあります。
[このリンク](https://www.anaconda.com/products/individual)からダウンロードできます。
Windowsでのインストール方法は[こちら](https://www.python.jp/install/anaconda/windows/install.html)。

<head>
    <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4386565414956285"
     crossorigin="anonymous"></script>
</head>
Z3Py　例題　巡回問題

# 問題
以下の都市の集合と各2都市間の移動コストが与えられたとき、全ての都市をちょうど一度ずつ巡り出発地に戻る巡回路のうちで総移動コストが最小のものを求めろ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118796/85d50690-f45c-aa43-c10b-cb073dad3cca.png)

# 回答
```example_traveling_salesman.py
from z3 import *

map = [
    [0, 2, 3, 1, 0, 0],
    [2, 0, 0, 2, 2, 4],
    [3, 0, 0, 2, 2, 3],
    [1, 2, 2, 0, 2, 0],
    [0, 2, 2, 2, 0, 1],
    [0, 4, 3, 0, 1, 0]
]

for total_cost in range(24):
    t_max = 7
    T = [Int("T%s" % i) for i in range(t_max)]
    f = Function('f', IntSort(), IntSort(), IntSort())

    s = Solver()
    s.add([And(1 <= T[i], T[i] <= 6) for i in range(len(T))])
    for i in range(6):
        for j in range(6):
            s.add(f(i+1, j+1) == map[i][j])

    for i in range(len(T)-1):
        s.add(f(T[i], T[i+1]) > 0)

    s.add([Distinct([T[i] for i in range(t_max-1)])])

    s.add(T[0] == 1)
    s.add(T[-1] == 1)

    s.add(Sum([f(T[i], T[i+1]) for i in range(t_max-1)]) < total_cost)

    print("total_cost=" + str(total_cost) + ":")
    print(s.check())
    if s.check() == sat:
        break

m = s.model()
for i in range(len(T)):
    print('T['+str(i)+']='+str(m[T[i]]))

route_cost = [map[m[T[i]].as_long()-1][m[T[i+1]].as_long()-1]
              for i in range(t_max-1)]

print(route_cost, sum(route_cost))
```
出力

```terminal
total_cost=0:
unsat
total_cost=1:
unsat

～中略～

total_cost=11:
unsat
total_cost=12:
sat
T[0]=1
T[1]=2
T[2]=5
T[3]=6
T[4]=3
T[5]=4
T[6]=1
[2, 2, 1, 3, 2, 1] 11
```

## 解説
基本戦略はハノイの塔と同じ。初期状態から最終状態への一連の遷移状態が成立していることを確認する。
さらに、遷移コストの合計が〇以下とし、〇をすこしずつ大きくしていき、成立する解を求めることで、最小コストの経路を探索する。

MapはTrue、Falseではなく、各都市間の移動コストとし、0は移動できないと定義した。

# 他の例題
[Z3Py個人的ポータル](https://qiita.com/Ganesha/items/7a606ffc8a7c2504c143) へ
【ハッキング・ラボ②】Kali Linuxをカスタマイズする

Kali Linuxをカスタマイズしていきます。
<br>
まとめ記事（①〜⑯をまとめてます）
[【ハッキング・ラボのつくりかた】をやってみた](https://qiita.com/nakatatsu711/items/e90e6e0962bb787bf4a9)



## システム環境
`仮想化ソフト`：VirtualBox 6.1.0
`ホストOS`：Windows10
`ゲストOS`：Kali Linux 2020.1



## ログイン
2019年12月からKali Linuxのデフォルトパスワードは以下のように変更されたようです。
`ユーザー名`：kali
`パスワード`：kali

インターフェースも参考文献のものとかなり変わっているようです。
<img width="600" alt="hacking-lab-part2-1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/0548cb77-96c9-e948-0ea7-aec74488ab05.jpeg">



## 解像度の変更
マウスでもウィンドウのサイズを調整することができますが、今回はKali Linux側の設定で調整します。

「Settings」→「Display」から「Resolution」を変更します。
<img width="600" alt="hacking-lab-part2-2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/01338779-b669-cd29-560a-da012d0743b9.jpeg">


## スクリーンロックの無効
ハッキング・ラボでは複数のゲストOSを立ち上げて操作することが多いので、ブランクスクリーンに移行しないように設定します。

「Settings」→「Power Manager」→「Display」から、「Blank after」、「Put to sleep after」、「Switch off after」を「Never」に変更します。
<img width="600" alt="hacking-lab-part2-3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/2c55b951-c8ed-35c7-6eda-06123d86d39d.jpeg">


## 日本語キーボード対応
デフォルトでは英語キーボード対応になっているので、日本語キーボード対応に変更します。

「Settings」→「Keyboard」→「Layout」から、「Keyboard layout」を「Japanese」に、「Keyboard model」を環境に合わせて選択します。
<img width="600" alt="hacking-lab-part2-4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/602402d7-2daf-1088-f2a0-df3d4c36cc72.jpeg">



## タイムゾーンの変更
時刻を右クリックして「Properties」から「Timezone」を「Asia/Tokyo」に変更します。
<img width="600" alt="hacking-lab-part2-5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/4e2c339b-cfd6-81e9-ba20-b9c96f93bc5c.jpeg">



## 日本語入力の設定
日本語パッケージをインストールして、日本語を入力できるようにします。

まずパッケージの一覧をアップデートした後、パッケージをアップグレードします。
以下のコマンドを入力します。

```
$ sudo apt update
$ sudo apt upgrade
```

以下のコマンドを入力し、日本語パッケージをインストールします。

```
$ sudo apt install -y task-japanese task-japanese-desktop
```

再起動すると、画面右下にアイコンが表示されるようになります。
アイコンをクリックし、「Anthy(UTF-8)」を選択すると日本語入力ができるようになります。
<img width="600" alt="hacking-lab-part2-6" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/26c3b6a0-e20f-039b-4bd5-f5e1e39ce54d.jpeg">
Salesforceレポートのインライン編集を試してみた

こんにちは。
Salesforceは年３回大きなリリースがあり様々な機能が実装されますが、
今回Spring’21のリリースで衝撃受けた機能がああります。
それは
###インライン編集を使用した [レポート実行] ページからの項目の更新 (ベータ)
です！



まだベータ版の機能なので色々注意点がございます
https://help.salesforce.com/s/articleView?id=release-notes.rn_rd_reports_inline_editing.htm&type=5&release=232

ヘルプを見る限り、すべての項目が対応ではなく
次の項目および項目種別では、インライン編集はサポートされていません。

ToDo オブジェクトと行動オブジェクトの項目
[レコード ID] や [作成日] などのシステム項目
名前項目や住所項目などの複合項目
選択リスト
カスタム日付/時間項目
暗号化されたテキスト項目
数式項目
標準項目種別 (日付/時間、自動採番、積み上げ集計、レコードタイプ、主従関係、ロングテキストエリア、リッチテキスト、階層)
ページレイアウトまたはレコードタイプの制限によって編集が許可されていないその他の項目

他にもいろいろ気になる点がありましたので
現状どのような動きになっているか試しました。

※注意　レポートインライン編集を行うには設定が必要です。設定方法は下記ヘルプに記載ありますので割愛します
https://help.salesforce.com/s/articleView?id=release-notes.rn_rd_reports_inline_editing.htm&type=5&release=232
※　２０２１年８月現在はベータ版の機能ですのでいきなり本番で設定せずまずはSandboxで検証することをおすすめします

###基本的な内容１
レポート画面から編集可能な項目は鉛筆マークが表示されます。
編集不可な項目（完了予定日など日付項目）は下記画像のように鍵マーク？が
表示され編集できません。
![日付項目１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/e21afff1-06e2-e451-602a-912645a0c371.png)

###基本的な内容2
鉛筆マークをクリックすると下記画像のように項目の編集が可能です。
項目編集後「保存」をクリックすると項目の値が更新されます
![保存ボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/d851f04e-cf8c-34c4-a1b9-47aa04adf8c1.png)


さあ、基本を押さえたところでここからいろいろ確認します。

###結合レポートにインライン編集は対応しているか？
結論は「結合レポートにはインライン編集は対応していない」でした。

下記
![保存２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/497be103-6439-7582-dd87-ded549e0a9b4.png)

添付画像のように先ほどまで編集可能だった項目（NextStep）のような項目が編集可能な鉛筆マークではなく鍵マークが表示されます。
もちろん編集はできなくなっていました。

###項目編集時を起点にワークフロールールは対応するか？
結論は対応されていました。
どうやらレポートからの編集は通常のレコードページと同じような編集扱いとなるようです。

また、インライン編集時に画面が自動更新されて他の項目も変わったことが一目で分かります。
わざわざ画面を手動で更新する必要はなさそうです。