OmniAICreator/Qiita-1.07M huggingface dataset:
【ABAP】内部テーブルをJSONに変換する

#やること
ABAPで「内部テーブルからJSONへの変換」と「JSONから内部テーブルへの変換」を行う。
方法は「CALL TRANSFORMATION」と「/UI2/CL_JSON」の2パターン。

#参考
- [One more ABAP to JSON Serializer and Deserializer](https://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer) ←詳細はこちら
- [JSONとは結局なんなのか？](https://qiita.com/momonoki1990/items/cd9a65498c2b16b0ed55)

#パターンA：「CALL TRANSFORMATION」を使用

##ソースコード
```ABAP:Y_TEST_JSON
  DATA lv_output_length TYPE i.
  DATA lt_binary_tab    TYPE STANDARD TABLE OF sdokcntbin.
  DATA lv_json          TYPE string.

  SELECT *
    FROM sflight
    INTO TABLE @DATA(lt_flightdata).

* (A-1)内部テーブルからJSONに変換
  DATA(lo_writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
  CALL TRANSFORMATION id SOURCE text = lt_flightdata RESULT XML lo_writer.
  DATA(lv_jsonx) = lo_writer->get_output( ).

  CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
    EXPORTING
      buffer        = lv_jsonx
    IMPORTING
      output_length = lv_output_length
    TABLES
      binary_tab    = lt_binary_tab.

  CALL FUNCTION 'SCMS_BINARY_TO_STRING'
    EXPORTING
      input_length  = lv_output_length
    IMPORTING
      text_buffer   = lv_json
      output_length = lv_output_length
    TABLES
      binary_tab    = lt_binary_tab.
  cl_demo_output=>display_json( lv_json ).

* (A-2)JSONから内部テーブルに変換
  CLEAR lt_flightdata.
  CALL TRANSFORMATION id SOURCE XML lv_jsonx RESULT text = lt_flightdata.
  cl_demo_output=>display( lt_flightdata ).
```
##実行結果
###(A-1)内部テーブルからJSONへの変換
cl_demo_outputの出力結果は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22526/84fa3cbe-a5f3-0738-bb91-578af59fa727.png)

###(A-2)JSONから内部テーブルへの変換
cl_demo_outputの出力結果は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22526/e3a84811-93f7-dbf1-ec1c-4350af058c36.png)

#パターンB：/UI2/CL_JSONを使用

##ソースコード
```ABAP:Y_TEST_JSON
  SELECT *
    FROM sflight
    INTO TABLE @DATA(lt_flightdata).

* (B-1)内部テーブルからJSONに変換
  DATA(lv_json) = /ui2/cl_json=>serialize( lt_flightdata ).
  cl_demo_output=>display_json( lv_json ).

* (B-2)JSONから内部テーブルに変換
  CLEAR lt_flightdata.
  /ui2/cl_json=>deserialize( EXPORTING json = lv_json CHANGING data = lt_flightdata ).
  cl_demo_output=>display( lt_flightdata ).
```
##実行結果
###(B-1)内部テーブルからJSONへの変換
cl_demo_outputの出力結果は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22526/9e0af7b1-8348-e298-266d-341ca203561b.png)

###(B-2)JSONから内部テーブルへの変換
cl_demo_outputの出力結果は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22526/8f46b85b-229c-9331-2567-3ff8d95b1880.png)
goto文は使ってもいいんじゃないかと思い始めてきた話

https://atcoder.jp/contests/APG4b/tasks/APG4b_ad

goto文は多重ループから抜け出す場合は使用することを推奨されている  
でもほんとにgoto文を使ってもいいのか？とおもって多重ループを抜け出すときの別の案を考えてみた

## 条件を満たしたらたくさんbreak
```cpp
int n=10;
bool flg=false;
for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
        for(int k=0;k<n;k++){
            if(i+j+k==n){
                cout<<i<<" "<<j<<" "<<k<<endl;
                flg=true;
            }
        if(flg) break;
    }
    if(flg) break;
}
```

うーん、微妙な気がする  
breakを書く手間とそのための変数を追加するのがもったいない

<br>

## ラムダ式の形にまとめる
```cpp
int n=10;
[&]{
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                if(i+j+k==n){
                    cout<<i<<" "<<j<<" "<<k<<endl;
                    return;
                }
        }
    }
}();
```
これ始めて知った時はなるほど～ってなったけど階層が一段深くなるのが若干悩ましい気もする  
ただ、breakに比べたらこちらの方が良い

<br>

## やっぱりgoto
```cpp
int n=10;
for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
        for(int k=0;k<n;k++){
            if(i+j+k==n){
                cout<<i<<" "<<j<<" "<<k<<endl;
                goto EXIT_MULTI_LOOP;
            }
    }
}
EXIT_MULTI_LOOP:
```
追加するのが2行だけで、脳死で追加できるのでやっぱりgoto文がよいのでは？

<br>

## 関数にまとめる
```cpp
void imi_no_aru_namae_func() {
    int n=10;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                if(i+j+k==n){
                    cout<<i<<" "<<j<<" "<<k<<endl;
                    return;
                }
        }
    }
}
```
shiracamus さんにコメントをいただいて追記しました
関数にまとめると
- 処理の内容を関数名で要約できる
- 24行以内に収めると1画面で処理だけを見ることができる
などの良い点があるので関数化も良い手段であると思います

---

https://teratail.com/questions/19023

色んなとこで議論がなされているけどgoto文を使う人が多そう  

# 結論
自分が納得しているものを使うのが一番！！！！！！
string::nposについて

# string::nposとは
string::nposはstring型のfindで見つからなかったときに返ってくる値です。

```cpp:お試しコード
int main(){
   string s = "aaa";
   if(s.find('b') == string::npos) cout << "Not found" << endl;
}
```

```:結果
Not found
```

---

この前`int`型の変数に`string::npos`を入れたら`-1`だったので、ん？って思ってたので実験してみました。

```cpp:実験のコード
int main(){
  bitset<100> bit(string::npos);
  if(string::npos==INT64_MAX) cout<<"Yes"<<endl;
  if(string::npos==UINT64_MAX) cout<<"OhYes"<<endl;
  cout<<bit<<endl;
}
```

```:結果
OhYes
0000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
```

`int`型の`-1`は全ビットが`1`なので`int`型に入れたら`-1`になるよねー。
using namespace std;を使わずに指定したものだけstd::を外す

`using namespace std`は使いたくないけど`std::cout`とかって書くのが嫌だなってとき、ありませんか？

```cpp
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main(){
    int n;
    cin >> n;
    cout << n << endl;
}
```

これでよし
C++のmapで後ろからループを回すとき


```cpp:イテレータを使ったループ
map<int,int> mp;
for(auto it = mp.begin(); it != mp.end(); it++){
    // hoge
}
```
<br>

```cpp:range-based-forを使ったループ
map<int,int> mp;
for(auto val : mp){
    // hoge
}
```

前からのループは書けるが後ろからのループはどうやって書いたらいいのか分からなかったのですが、ちょうどいいのを見つけました。

> [https://cpprefjp.github.io/reference/map/map/rbegin.html](https://cpprefjp.github.io/reference/map/map/rbegin.html)

`mp.end()-1`から`mp.begin()`までイテレータをデクリメントするよりもこっちの方がよい気がします。

```cpp:mp.rbegin()を使ったループ
map<int,int> mp;
for(auto it = mp.rbegin(); it != mp.rend(); it++){
    // hoge
}
```

`it++`するのが驚きです。  なんで`it--`じゃないのだろう。
vectorのresizeとassignの違い

c++の`vector`では`resize`と`assign`という機能があります。  
僕は今まで`resize`ではサイズの指定だけ、`assign`はサイズと中身、とイメージしていたんですが`resize`でも要素を指定できることを知ったので忘れないために違いを書いておこうと思います。

※簡単のため`std::`を省略しています。

## resize

```cpp:長さが伸びた場合
vector<int> a={1,2,3};
a.resize(5);
```

このようにするとaの中身は`{1,2,3,0,0}`になります。`resize`で増えた分は0になります。

```cpp:長さが縮んだ場合
vector<int> a={1,2,3};
a.resize(1);
```

このようにするとaの中身は`{1}`になります。`resize`で指定した長さになるまで`erase`が行われるらしいです。

### 驚いたやつ

```cpp:長さが伸びた場合
vector<int> a={1,2,3};
a.resize(5,10);
```

これが僕がこの記事を書こうと思った原因です。`resize`って名前だから長さしか指定できないだろうと思ったらそんなことありませんでした。  
このようにするとaの中身は`{1,2,3,10,10}`になります。埋める際に指定した要素になります。縮んだ場合は要素を指定しても変わりません。



## assign

```cpp:長さが伸びた場合
vector<int> a={1,2,3};
a.assign(5,1);
```

このようにするとaの中身は`{1,1,1,1,1}`になります。`assign`では全ての要素を指定した要素で埋めます。

```cpp:長さが縮んだ場合
vector<int> a={1,2,3};
a.resize(5,1);
```

このようにするとaの中身は`{1}`になります。伸びた場合と同様です。

```cpp:おまけ
vector<int> a;
a.assign({1,2,3,4,5});

vector<int> b;
b.assign(a.begin(),a.end());
```
リストで`assign`やほかの`vector`のイテレータなども`assign`は受け取ります。


# あとがき
`resize`や`assign`でメモリが解放されるわけではないことに注意が必要です。

```cpp:メモリの確保
vector<int> a={1,2,3,4};
a.push_back(5);
```
とした場合、配列の中身は`{1,2,3,4,5}`と5要素しかありませんがメモリ領域は6要素分確保されています。元が4,追加で2なので6です。新しく追加した場合はもともとのメモリ領域分の半分が新たに確保されます。

```cpp:余分なメモリの解放
a.shrink_to_fit();
```
先ほどの状態からこのようにするとメモリ領域が5要素分になります。使っていないメモリを開放することができます。  
また、

```cpp:余分なメモリの解放(古い)
vector<int>().swap(a);
```

このように`swap`のメンバ関数で使っていないメモリの解放をすることができます。新しく`vector`配列を作って中身を移動させています。


参考にさせていただいたサイトの方々です。より詳しく書かれています。2つ目の記事は`vector`そのものを開放したい場合に参考にしてください。
> - [https://programming.pc-note.net/cpp/vector.html](https://programming.pc-note.net/cpp/vector.html)
> - [https://qiita.com/sawasaka/items/2df474fc00ec2105acab](https://qiita.com/sawasaka/items/2df474fc00ec2105acab)
ReactとRailsでSPA作る。①

ポートフォリオ作成にあたってReactとRailsでSPAを作ってみた。
まずは開発に必要な環境をローカルに構築していく。

Homebrewをインストールする。
https://brew.sh/index_ja.html

```shell
$ brew -v
```

これできちんとインストールされているか確認できる。
次にrbenv

```shell
$ brew install rbenv
```

```shell
$ rbenv --version
```

数字が表示されたらインストールに成功している。
続いてrbenvにpathを通す。

```shell
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; 
fi' >> ~/.bash_profile
$ source ~/.bash_profile
```

Rubyをインストールし、globalに2.7.0を登録する。

```shell
$ rbenv install 2.7.0
$ rbenv global 2.7.0
$ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
```

やはり数字が表示されたら成功している。
bundlerのインストールに移る。

```shell
$ gem install bundler
$ bundler -v
Bundler version 1.17.1
```

React側で必要になるパッケージマネージャ。
今回はyarnを選択する。

```shell
$ brew install yarn
$ yarn -v
1.19.1
```

最後にrailsをインストールしていく。

```shell
$ gem install rails -v 6.1.3.7
$ rails -v
Rails 6.1.3.7
```

これで開発の準備は整った。
React + Material-UIでBottomNavigationの色を変える方法

React + Material-UIで手っ取り早くBottomNavigationの色を変えようと思ったのですが、ハマったのでメモ。
最終的なコードはこんな感じ。

```Footer.tsx
import React from "react";
import makeStyles from "@material-ui/core/styles/makeStyles";
import createStyles from "@material-ui/core/styles/createStyles";
import { Theme } from "@material-ui/core/styles";
import BottomNavigation from "@material-ui/core/BottomNavigation";
import BottomNavigationAction from "@material-ui/core/BottomNavigationAction";
import RestoreIcon from "@material-ui/icons/Restore";
import FavoriteIcon from "@material-ui/icons/Favorite";
import LocationOnIcon from "@material-ui/icons/LocationOn";
import AppBar from "@material-ui/core/AppBar";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      width: "100%",
      backgroundColor: theme.palette.primary.main,
    },
    appBar: {
      top: "auto",
      bottom: 0,
    },
  })
);

const actionStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      backgroundColor: "inherited",
      "&$selected": {
        color: theme.palette.secondary.main,
      },
    },
    selected: {},
  })
);

export default function Footer() {
  const classes = useStyles();
  const actionClass = actionStyles();
  const [value, setValue] = React.useState(0);

  return (
    <AppBar position='fixed' color='primary' className={classes.appBar}>
      <BottomNavigation
        value={value}
        onChange={(event, newValue) => {
          setValue(newValue);
        }}
        showLabels
        classes={{ root: classes.root }}
      >
        <BottomNavigationAction
          classes={actionClass}
          label='Recents'
          icon={<RestoreIcon />}
        />
        <BottomNavigationAction
          classes={actionClass}
          label='Favorites'
          icon={<FavoriteIcon />}
        />
        <BottomNavigationAction
          classes={actionClass}
          label='Nearby'
          icon={<LocationOnIcon />}
        />
      </BottomNavigation>
    </AppBar>
  );
}
```

Material-UIの"Overriding styles with classes"を使っています。
https://material-ui.com/customization/components/#overriding-styles-with-classes


makeStylesでスタイルを作ります。

```BottomNaviationActionのstyle.tsx
const actionStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      backgroundColor: "inherited",
      "&$selected": {
        color: theme.palette.secondary.main,
      },
    },
    selected: {},
  })
);
````

classesの引数でこのスタイルをとります。

```.tsx
const actionClass = actionStyles();

 <BottomNavigationAction
   classes={actionClass}
   label='Nearby'
   icon={<LocationOnIcon />}
/>
```

これだけといえばこれだけですが、洗濯した後の色の指定に意外とハマりました。
selected: {}　のところは必須です。（オリジナルのクラスを消さないと反映されない）

無事に背景を黄色、選択した時にオレンジになりました。（配色のセンスは置いときましょう。）
![スクリーンショット 2021-05-30 5.29.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260132/905d91c4-c7d7-d5bf-ca0f-84c673f040a8.png)
BodyPixやーる（Python3.6、Tensorflow、Windows10）

# はじめに
BodyPixをやっていきます。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">PiPyでBodyPixをインストールしてPythonで使えるようにしているツワモノがいるんやで。まぁ、今なら情報が出回ってるしあんまり苦労しなさそう。ResNet版ならめちゃキレイだし。<a href="https://t.co/WWxg9NQH93">https://t.co/WWxg9NQH93</a></p>&mdash; Super PINTO (@PINTO03091) <a href="https://twitter.com/PINTO03091/status/1396510822751346688?ref_src=twsrc%5Etfw">May 23, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 開発環境
- Windows 10 
- Python 3.6
- anaconda

# 導入
1．anacondaでPython3.6環境を作り、ライブラリをインストールします。

~~~console 
pip install tf-bodypix
pip install tensorflow
pip install tfjs-graph-converter
~~~

2．下記のコードを書いて、入力画像を用意します。

~~~python
import tensorflow as tf
from tf_bodypix.api import download_model, load_model, BodyPixModelPaths

bodypix_model = load_model(download_model(
    BodyPixModelPaths.MOBILENET_FLOAT_50_STRIDE_16
))

root = "input-image"
ext = ".jpg"

image = tf.keras.preprocessing.image.load_img(
    f'./input/{root}{ext}'
)
image_array = tf.keras.preprocessing.image.img_to_array(image)
result = bodypix_model.predict_single(image_array)
mask = result.get_mask(threshold=0.75)
tf.keras.preprocessing.image.save_img(
    f'./output/{root}-mask{ext}',
    mask
)

colored_mask = result.get_colored_part_mask(mask)
tf.keras.preprocessing.image.save_img(
    f'./output/{root}-colored-mask{ext}',
    colored_mask
)
~~~

# 実行結果

|入力|マスク画像|マスク画像（カラー）|
|:--|:--|:--|
|![AdobeStock_246496748.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/ad9ab82b-a7f3-b830-48e0-599c9b230907.jpeg)|![AdobeStock_246496748-mask.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/7b3ae42d-b865-7853-4259-cd35d203842b.jpeg)|![AdobeStock_246496748-colored-mask.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/f0099ec3-d18d-67cd-d0c8-6482427f392b.jpeg)|

お疲れ様でした
【ECサイト】refile と elevatezoom.js でお手軽画像拡大機能実装

### はじめに
プログラミングスクールでECサイトを共同開発中です。その際「商品画像拡大を簡単に実装できればなぁ」と思い実装してみたところちょっと苦戦したのでやり方をアウトプットします。

### 目標
できるだけ簡単にelevatezoomを虫眼鏡拡大オプションで実装します。

### 利用環境
rails 5.2.5
ImageMagick
refile
jquery.elevateZoom-3.0.8

※refileのインストールが終わっていて商品ページには商品画像が配置されている想定で進めます

### elevatezoomとrefileについて
どんなzoomができるかについては https://www.elevateweb.co.uk/image-zoom/examples/ が1番分かり易いです。
とりあえず虫眼鏡拡大オプション動作させるには以下が必要になります。

```　html
<img id="〇〇" src="表示画像" data-zoom-image="表示画像より大きい画像"/>
```

``` js
$("#〇〇").elevateZoom({
  zoomType  : "lens",
  lensShape : "round",
  lensSize  : 200
});
```
elevatezoomとrefileの問題点
①elevatezoomはdata-zoom-imageというカスタムデータ属性と表示画像より大きい画像が必要
②refileのattachment_image_tagにカスタムデータ属性を入れるオプションは無さそう

問題点の解決策
①表示画像と表示画像より大きい画像は同じものを使用して表示画像をCSSで小さめに表示する
②jQueryであとからdata-zoom-imageをsrcの値を使って足す

### ダウンロード

[elevatezoom.js](https://github.com/elevateweb/elevatezoom)
①上記のgithubよりmasterをzipダウンロードしてください。
②ダウンロードしたzipファイルを解凍します。
③今回はjquery.elevateZoom-3.0.8.min.jsを使用します。

### 配置
①app/assets/javascriptsにjquery.elevateZoom-3.0.8.min.jsを配置

### 記述

①商品詳細ページのrefile画像へ記述

``` show.html.erb
<%= attachment_image_tag @model, :image, :fill, 800, 600, format: 'jpeg', id: "zoom" %>
```
※800x600としましたが、実際に表示されている画像はCSSで小さくしてください。(400x300とか)


②application.jsへ記述

``` application.js 
$(document).on('turbolinks:load',function() {
  $(document).ready(function () {
   var dz_img = $("#zoom").attr('src'); //refileのsrcを取得します。
   $("#zoom").attr({'data-zoom-image': dz_img }); // data-zoom-imageにdz_imgを入れます。
   $("#zoom").elevateZoom({
		  zoomType : "lens",
		  lensShape : "round",
		  lensSize : 200
	  }); //elevateZoomを動かします。
  });
});
```

### おわり
以上でおわりです。この方法で動きました。
SpeechRecognitionでrecognize_azureが動かない


# 症状

recognize_azureなんてメソッドは無い。

```sh
$ pip install SpeechRecognition
$ pip list
SpeechRecognition (3.8.1)
$ python3 -c 'import speech_recognition as sr; r = sr.Recognizer(); r.recognize_azure() '
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: 'Recognizer' object has no attribute 'recognize_azure'
```

# 原因

https://github.com/Uberi/speech_recognition/blame/c89856088ad81d81d38be314e3db50905481c5fe/speech_recognition/__init__.py#L1020

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330873/651d36c0-cfcd-0f18-9214-e6e207ffc4ad.png)

`Add recognize_azure() due to Bing Speech API deprecation 3 years ago`
3年前に追加された。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330873/72153f3e-1731-32c6-9cd3-9d669fbd5d06.png)

現在最新は2017年、つまりrecognize_azure()はリリースに載っていない。

https://github.com/Uberi/speech_recognition/pull/554

```
anthonymiyoro commented 24 days ago 2021年5月5日 20:48 JST
Hi @avryhof I'll find time to do it this week
```

お忙しいようだ。
OSWatcherのカスタムデータコレクション

OSWatcherでは、既存で用意されているOS稼働情報とは別に、自分で取得対象を追加することができ、このときのログは既存の出力ファイル同様にログメンテナンスの対象となります。
ここでは、OCI Compute Instanceにデフォルトで入っているOSWatcher環境（RPMでインストールされた環境）に、このカスタムデータコレクションを利用してdstatをOSWatcherに追加することを実施してみます。

この方法の出所としては、OS Watcher User's Guide (ドキュメントID 1531223.1)のAdding Custom Data Collectionsの内容となります。

# 手順

## 1.追加するカスタムスクリプトの置き場を把握

vmstat,mpstatなど、既存の実行スクリプトが配置されている場所を探します。
OCI computeの場合は`/usr/libexec/oswatcher`でした。

自分は、以下のような感じで探しました。
1-1.`ps -ef|grep osw`でOSWatcherの常時実行スクリプトが`/usr/sbin/OSWatcher`であるとわかる
→
1-2.`view /usr/sbin/OSWatcher`でスクリプトの中身を見て、てきとうにVMSTATなどの文字列で検索して、それらしい実行箇所を探り当てる
→
1-3.これだ！なんと`/usr/libexec/oswatcher/vmsub`はハードコードされていました。

```
・・・
/usr/libexec/oswatcher/vmsub $OSWBB_ARCHIVE_DEST/oswvmstat/${hostn}_vmstat_$hour "$VMSTAT" $oswgCompliance &
・・・
```

## 2.`/usr/libexec/oswatcher`に`extras.txt`と`call_dstat.sh`を配置

### extras.txt

`extras.txt`は追加するカスタムスクリプトの設定ファイルで、名前は固定です。

中身は以下のように指定します。カスタムスクリプトは10個まで指定できるようです。

```
call_dstat.sh dstat oswdstat
```
call_dstat.shは追加するカスタムスクリプトの名前です。名前は任意です。
dstatは追加するカスタムスクリプトの種類(出力されるログファイルのファイル名に影響します。例`tjkpostgres13_dstat_21.05.29.1700.dat`)
oswdstatはログの出力先のディレクトリ


### call_dstat.sh

dstat実行用のカスタムスクリプト、`call_dstat.sh`はこんな感じです。

```
#!/bin/sh
echo "zzz ***"`date '+%a %b %e %T %Z %Y'` >> $1
dstat -tclmndr 1 0 >> $1
```

`dstat -tclmndr 1 0`のところを他コマンドに書き換えれば応用ができます。注意点は、定期的に出力が続くコマンドではなく、一回で実行が完了する形式のコマンドを指定することとなります。そうしないと、OSWatcherのインターバル毎に実行コマンドが重複していきます。

## 3.OSWatcherを再起動
```
#service oswatcher restart
```

ログの出力のされ方はこのような形になります。

```
[root@tjkpostgres13 oswdstat]# pwd
/var/oled/oswatcher/archive/oswdstat
[root@tjkpostgres13 oswdstat]# ls
tjkpostgres13_dstat_21.05.29.1700.dat.gz  tjkpostgres13_dstat_21.05.29.1800.dat
```
初学者がネットワークの仕組みを簡潔にまとめてみた。

基礎が疎かになっては成長も何もないと考え、
ネットワークやサーバーの基礎について、自分なりにまとめてみました。
間違っている箇所等、ご指摘を頂けると幸いです。

私たちが普段何気なく使っているインターネットは、
クリック（リクエスト）に対して返答（レスポンス）を返しています。
要求を投げるクライアントコンピューターに対して、要求を受け取るサーバーコンピューター、またこういったモデルを
クライアント/サーバモデルと呼びます。

サーバーの役割はソフトウェアによって決まり、
例えばchromeやIEといったブラウザはクライアント側のソフトウェアで、
webページが見たいという要求にレスポンスを返しています。
これはHTTP,HTTPS通信と呼ばれHTTPS通信は通信データを暗号化しよりセキュアにしたものです。

URLはリソースの住所を指し、
URIと同じと扱っても問題はありません。
http://ホスト名.ドメイン名:ポート番号/パス
の形を取ってあるのが一般的で、
例えば、http://www.example.com/news/tech/computer.html というURLがあったとすると、
通信プロトコル：http
ホスト名：www
ドメイン名：example.com
パス：/news/tech/computer.html　となります。

DNSサーバーによって名前解決される前のURL/URIをIPアドレスと呼び、
通常　216.58.221.163　←こんな形をしています。
人間にとっては分かりにくい形状であるため、DNSサーバーが翻訳をすることとなります。
IPアドレスによって個別のコンピューターを識別することが可能になるわけですが、
膨大な数が存在するため実際は個々のネットワークに対してグローバルIPアドレスが割り当てられています。
その中でさらに小さな、
個別のコンピューターに与えられたIPアドレスを、プライベートIPアドレスと呼びます。

実はプライベートIPアドレスを利用すると、不具合があります。
プライベートIPアドレスを持っているクライアントがサーバへリクエストを送っても、サーバに届く頃にはクライアントのIPアドレスはグローバルIPアドレスとして届いているので、サーバがレスポンスを返すときにはどのコンピュータがそのサーバに向けてリクエストを送ったのかわからないという問題です。
これを解決する方法がNAPTという技術です。
ポート番号には、送信元ポート番号と宛先ポート番号があります。
宛先ポート番号はHTTPの場合は80といった形である程度決まっていますが、送信元ポート番号は何でも良いのです。
NAPTは、送信元ポート番号を使ってグローバルIPアドレスからコンピュータを特定することができます。
おかげで、プライベートIPアドレスからでもコンピュータを特定できるようになり、多:1の通信を実現できるようになりました。

インターネットを介したアプリケーション間の通信は、TCP/IPモデルによって実現されています。TCP/IPモデルは5つの階層になっており、それらはユーザに近い上位層のアプリケーション層から、最下位の物理層まであります。

アプリケーション層、
トランスポート層、
インターネット層、
データリンク層、
物理層から成っています。

こういったインターネットの仕組みを覚えて、さらに成長していきたいですね。
VSCode－いろいろな言語の環境構築まとめ

## vscodeが便利だけどやっかいな話

ここ数日、vscodeの環境構築にえらい苦戦していました。
普段、同時に3～４言語使っているため、その一つ一つの環境構築が面倒すぎて、今まで使っていたエディタのほうがましなんじゃないか…とも思いました。
わからないことだらけでとにかく調べまくりましたが、ここでは、**サクッと環境構築を終えてプログラムを書きたいんだ！！**という人向けに

#####Python、C#、Java、Ruby

の環境構築から実行までの方法を簡潔にまとめました。

わたしがつまずいたところや試してみてできなかったことも共有していますので、このページだけですべて完結できるよう目指しました。

ぜひ参考にしてください。

## 環境

OS：Windows10
エディタ：VSCode(Visual Studio Code)

以下、今まで使用していた環境です。

Python：anaconda3　spyder
C#：visual studio 2019
Java：eclipse
Ruby：コマンドプロンプト





## ～言語別環境構築から実行までの仕方～
[Pythonの環境構築](https://qiita.com/en-a/items/b2ab503cc66771bd43de)
[Javaの環境構築](https://qiita.com/en-a/items/a8c4fce78f35efa87105)

更新予定2021/5/31 C# or Ruby
随時更新していきます
VScode－Pythonの環境構築

## ～Python～
>環境
> - Windows10
> - VSCode(Visual Studio Code)
> - anaconda3（以前にspyder使っていました）

#####1. **拡張機能** 
    
   ・`Python`
   ・`Pylance`
   をインストールする。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/15b5ae24-6abe-7fbf-8db6-538adaf9ee70.png" width=50%">

#####2. **Pathを通す**
   1. VS codeの左下にある歯車マークの管理 ➡ 設定を開く。またはCtrl+,d。
   1. 「**python path**」と検索
      - `Python: Conda Path` に `C:\Users\ユーザー名\anaconda3\Scripts`
      - `Python: Python Path` に `C:\Users\ユーザー名\anaconda3\python.exe`  
と入力。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/19776b73-5fe9-0480-0bf4-6a57feb01a71.png>
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/dc18712c-1170-cd2d-5bc6-0fa36f2d8cb5.png>
     これはanacondaのPythonを使うために設定します。ユーザー名はWindowsの名前です。
**Pythonファイルが実行できない**、**& の使い方が誤っています。のエラー**、**condaコマンドが使えない**といった問題はこれで解決します。
#####3. **実行とデバック**
**～実行～**
　新規ファイルを作成したら、言語でPythonを選び適当にコードを書きます。

```python
a=1
b=1

print("hello")
print(1+2)
print(a+b)
```
右上の再生ボタン（実行ボタン）を押す➡ターミナルに結果が表示されます。

 **～デバック～**
F5キーで実行とデバックができます。
まずは、`launci.jdsonファイルを作成します。`を押して、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/b89da023-a1e1-33d5-3482-3710cd708542.png"width=45%">
Python File～を選択
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/34c5b936-123f-58e5-8f98-02b8cfb2341f.png"width="65%">
laucn.jsonファイルが開くと思いますが、無視して元のファイルに戻ってF5キーを押すと、
変数が表示されるはずです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1558730/a7b3cb18-690b-b1d8-7b21-a06aa03e5f4e.png"width="90%">
launci.jdsonファイルを作成しておくと、毎回Select a debug configurationで選ぶことなく、F5一発でデバックできるので楽です。   

   
#####**その他問題点と解決法**

- **conda activateができない/エラーが出る**  
  2.でも述べましたが、pathを通せばおそらくでなくなると思います。

- **デバックしても変数が表示されない**  
     [vscodeで変数が表示されない問題の解決法](https://qiita.com/en-a/items/e4adb9877efc1c70007c)   

- **opencv2が使えない**
anacondaでopencvを入れてるのにも関わらず、`import cv2`でモジュールがないとのエラーが出る。そんなときは、**anacondaからvscodeを起動し、そこでファイルを開いて実行する**とできます。
大学の先生に教えてもらいました。  
色々調べて試しましたが解決しなかったのと、なにかインストールしたり設定したりと手順がめんどくさすぎるので、この方法が一番いいと思います。  
anacondaにもvscodeがあって、昔はanacondaからインストールすることもできたみたいです。（今はもとからvscodeを入れてないとanaconda上で表示されません。）
詳しくはこの記事をどうぞ。
[[Python]Anaconda 2020.02のAnaconda NavigatorからVS Codeがインストールできなくなっていた](https://note.com/hotta3216/n/nfb7cc0c038cc)


以上、これだけで動きます。

参考
condaについて：https://qiita.com/chuo2110/items/f4513004b19aa0b982d2
https://qiita.com/nk_plus/items/2af0ac3537a85267672f
python デバックの方法：https://marsquai.com/a70497b9-805e-40a9-855d-1826345ca65f/f3c4e20d-fb69-49ce-aaec-a492f1954411/84119105-0a6b-48f2-b990-7249137fd7dd/
3分で読める最新脆弱性～Bluetooth～

#はじめに
ANSSI(仏国家情報システムセキュリティ庁)の研究者らによって指摘されたBluetooth上のいくつかの脆弱性について解説する記事です。
詳細は記事内のリンクをご参照ください。

#目次
1．概要
2．原理
3．攻撃例
4．対策

#概要
今回判明した脆弱性はBluetoothのCore SpecificationとMesh Profileに関連する脆弱性で、ペアリング時にMITM攻撃や不正な認証が行われる可能性があります。

公開日：2021-05-24(CERT/CC)
影響範囲：「Core Specification 5.2」「Mesh Profile 1.0.1」をサポートする全てのデバイス
リスク指標([VULDB](https://vuldb.com))(2021/05/30現在) 
　　CVSS：3.1-3.9
　　CWE：[CWE-287](https://cwe.mitre.org/data/definitions/287.html)(Improper Authentication)
　　   　[CWE-290](https://cwe.mitre.org/data/definitions/290.html)(Authentication Bypass by Spoofing)
　　   　[CWE-300](https://cwe.mitre.org/data/definitions/300.html)(Channel Accessible by Non-Endpoint)
　　   　[CWE-330](https://cwe.mitre.org/data/definitions/330.html)(Use of Insufficiently Random Values)

脆弱性情報
　　CVE：[CVE-2020-26555](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26555)
　　   　[CVE-2020-26556](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26556)
　　   　[CVE-2020-26557](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26557)
　　   　[CVE-2020-26558](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26558)
　　   　[CVE-2020-26559](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26559)
　　   　[CVE-2020-26560](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-26560)
　　CERT/CC：[Vulnerability Note VU#799380
](https://kb.cert.org/vuls/id/799380)

#原理
##Bluetooth Core
###PEER BD_ADDR AUTHENTICATION SPOOFING(CVE-2020-26555)
　Bluetooth Core specification 1.0B~5.2において、脆弱なデバイスのBD_ADDR(Bluetooth device address)を特定すると、攻撃者はそのBD_ADDRを使用してBR/EDR Pin-code Paring においてPin-codeなしにペアリングを完了させ、スプーフィングが可能です。
Secure Simple PairingやBR/EDR Secure Connectionsを使用することでこの問題は回避可能です。

###LE/BR/EDR CHANNEL ACCESSIBLE(CVE-2020-26558)
　BR/EDR Secure Simple Pairing(Bluetooth Core specification 2.1~5.2)、BR/EDR Secure Connections Pairing(Bluetooth Core specification 4.1~5.2)、LE Secure Connections Pairing(Bluetooth Core specification 4.2~5.2)のPasskey認証において、MITM攻撃などによってPasskeyを知ることで、攻撃者は認証つきのペアリング手順をクリアすることができます。

##Mesh Profile(後ほど更新)
###MESH PROVISIONING AUTHVALUE IMPROPER AUTHENTICATION(CVE-2020-26556)
###MESH PROVISIONING RANDOM VALUES(CVE-2020-26557)

###PUBLIC KEY IMPROPER AUTHENTICATION(CVE-2020-26559)
###MESH PROVISIONING IMPROPER AUTHENTICATION(CVE-2020-26560)



#攻撃例
不明


#対策
解決策
　　最新のアップデートの適用
　　また、各脆弱性について認証方法の変更などが推奨されています([Bluetooth Security Notices](https://www.bluetooth.com/learn-about-bluetooth/key-attributes/bluetooth-security/reporting-security/))


#あとがき
間違い・情報のupdateがあれば、コメントしてくれるとありがたいです。。。
<br><br>
今回は3分じゃ読めなかったかも…
Pythonの内包表記　まとめ

##はじめに
初投稿です。基本は自分自身の備忘録としてアウトプットしていこうと考えていますので、駄文になりますがご容赦ください。
##この記事の趣旨
内包表記が使えると簡素でコードが見やすく、何より**カッコいい**コードに見えます。
今回は4種類の内包表記について備忘録としてまとめます。

##今回のトピック
1.リスト内包表記
2.辞書内包表記
3.集合内包表記
4.ジェネレータ式

###1.リスト内包表記

#####要件
1〜5の数値が入ったタプルをfor文でまわし、順に[hoge]というリストに格納する動作を行う
#####for文を使ったリストへの追加

```python:code
tpl = (1, 2, 3, 4, 5)
hoge = []
for i in tpl:
    hoge.append(i)
```

#####内包表記
上記のコードを内包表記にしたもの

```python:code
tpl = (1, 2, 3, 4, 5)
hoge = [i for i in tpl]
```

#####補足
条件分岐をifで追加できる
下記のコードは偶数のみ追加する場合。上記の文末にifで条件式を書けばOK

```python:code
tpl = (1 ,2, 3, 4, 5)
hoge = [i for i in tpl if i % 2 == 0]
```

###2.辞書内包表記
#####要件
例として、曜日ごとの朝食を辞書に登録する。
具体的には曜日をキー、メニューを値として登録

#####for文を使用した辞書への追加
```python:code
day = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
menu = ['bread', 'oat meal', 'cereal', 'bacon', 'omelet','ham', 'waffle']
dic = {}
for d, m in zip(day,menu):
    dic[d] = m
```

#####内包表記
上記のコードを内包表記にしたもの

```python:code
day = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
menu = ['bread', 'oat meal', 'cereal', 'bacon', 'omelet','ham', 'waffle']
dic = {d: m for d, m in zip(day, menu)}
```


###3.集合内包表記
#####要件
range関数で数値を10回集合に追加する

#####for文を使用した集合への追加

```python:code
s = set()
for i in range(10):
    s.add(i)
```
#####内包表記

```python:code
s = {i for i in range(10)}
```
これはとてもシンプルですね！
{}で囲うので辞書型に書き方が似ている点が注意です。

###4.ジェネレータ式
#####要件
1から10までの数値を出力するジェネレータ

#####for文を使用した辞書への追加
```python:code
def g():
    for i in range(10):
        yeild i
g = g()
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
#出力結果
0
1
2
3
4
5
6
7
8
9
```

#####内包表記
上記のコードを内包表記にしたもの
他のコードと比べても非常にスリムになったと思います。
next()での表示もできます。

```python:code
g = (i for i in range(10))
for x in g:
    print(x)
#出力結果
0
1
2
3
4
5
6
7
8
9
```

##まとめ
4種類の内包表記についてまとめました。
内包表記が使えるとコードが読みやすく、記述も少なくてすみますのでぜひ使ってみてはいかがでしょうか？
ジェネレータはいまいち実務での使い所がわからないので、今後の学習で取り入れていければと考えています。
最後までお付き合い頂きありがとうございました。
【CentOS7】Sambaとサーバからユーザ削除

## 概要
Sambaに登録したユーザを削除する。
また、サーバ(OS)に登録してあるユーザも削除する。

## 環境
* windows10
* VMware Workstation 16 Player
* CentOS7
* 削除したいユーザ名は`SambaUser`

## Sambaのユーザを削除
```
# pdbedit -x SambaUser
```
`-x`はSAMデータベースからユーザを削除するオプション

## OS上のユーザ削除
```
userdel -r SambaUser
```
`-r`はユーザ作成時に作成される`/home/SambaUser`ディレクトリも一緒に削除するオプション

## 消えているか確認する
以下の３つのコマンドを実行して、何もでなければ完全に削除できている

```
# cat /etc/passwd | grep SambaUser
# ls -la /home/ | grep SambaUser
# cat /etc/group | grep SambaUser
```

## 参考サイト
* https://blog.treedown.net/entry/2016/06/15/010000
Herokuにデプロイした後、デプロイしたファイルをそのままダウンロードする方法

<h4>1.はじめに</h4>
Herokuにデプロイをした後、ローカル環境のファイルを無くしてしまった場合、以下の方法でそのままコードをダウンロードすることができます。<a href = "https://help.heroku.com/FZDDCBLB/how-can-i-download-my-code-from-heroku">公式ウェブサイト</a>にも掲載されている方法ですが、実際にやってみたので、ここで紹介しておきます。あくまで自己責任でお願いします。

<h4>2.手順とターミナル</h4>
①Herokuにログイン、②heroku-slugs CLIプラグインのインストール、③ダウンロード
の手順になります。ターミナル上のコマンドは以下の通り。

```terminal
% heroku login   
% heroku plugins:install heroku-slugs
% heroku slugs:download -a アプリ名
```
【CentOS7】ホスト名の設定・変更

## 環境
* windows10
* VMware Workstation 16 Player
* CentOS7

## ホスト名を一時的に設定する
再起動をすると、設定が消えてしまいます。

```:ホスト名の一時的に設定
# hostname ホスト名
```

## ホスト名を永続的に変更する
１．nmcliで設定

```:nmcliで設定
# nmcli general hostname ホスト名
```

２．`/etc/hostname`に直接変更を加える

```:/etc/hostnameに直接変更
# vi /etc/hostname
変更したいホスト名

//再起動
# reboot
```

## ホスト名の確認方法
```:確認方法
#hostname
設定したホスト名
```
Javaでグラフを入力画面から描画する（SpringBoot）

前回の作業履歴
https://github.com/jamcookjapan/grapy/commit/567f8b2f444b1ef4a89e622babf3a4930cd897ae

静的なデータを投入して画像バイナリを作っていましたが、今回は入力画面を作って、データを動的に受け取ってグラフを書き込みたいと思います。

```tsv:input.tsv
1	10,640,000
2	10,640,000
3	10,640,000
4	10,640,000
5	10,620,000
6	10650000
7	10780000
8	10780000
9	10780000
10	10760000
11	10570000
12	10530000
13	9960000
14	10250000
15	10250000
```

**グラフ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1535669/f21310a4-10f0-e8f3-054f-403a521f0a93.png)

X軸は固定ですが、グリッドと線の推移はほぼ正確に配置できました。Y軸の単位が細かすぎますが、気が向いたら改良したいと思います。

取り急ぎ現時点でも利用可能な状態にはなりましたが、もう1列入力を受け付けて、目標線も描画可能にします。
https://github.com/jamcookjapan/grapy/commit/4a87f21cca90502f15f3383df19a4f4e1d3f797d

以上です
[Rails]RailsのAPIモードのやり方

## はじめに
RailsでAPIモードを使ったので備忘録として残しておきます。

## Rails APIモードとは
Railsでプロジェクトを作成する際に選べるモードです。
APIモードで作成すると、フロントエンドとの通信に利用する部分(migration, model, controller)などのみを生成します。

## やり方

```
rails new プロジェクト名 --api
```

以上で作成することができます。
STM32G031と内部ADCと温度センサーMCP9701でソフトウェアシリアルに出力する。


x MCP9701-E/TO 販売コード 103199

温度を表示


目的
秋月で売っている安価なMCP9701(約25円)を使って温度を
ソフトウェアシリアルに出力する。

構成
MCP9701-E/TO I-03199
STM32G031J6M6


```c++



//#define in7 1 //uno
#define in7      PB7  // 1pin

#define DW   digitalWrite

//#define UART_DELAY 832 //  1200bps ok 031
#define UART_DELAY 102   //  9600bps ok 031

//10の割り算 0から1028までは、正しい。主に0から999
//#define DVI10(n) ((n*205)>>11)

//仮想シリアルへの一文字出力 9600bps
int pc_putc(char ch) {

  DW(in7, HIGH);

    //q_st =  micros(); //debug

  DW(in7, LOW);//START
  delayMicroseconds(UART_DELAY);

  for(int ii=0;ii<8;ii++){
    DW(in7, (ch>>ii)&1  );
    delayMicroseconds(UART_DELAY);
  }//for

  DW(in7, HIGH);//Stop
  delayMicroseconds(UART_DELAY);

    //q_et =  micros(); //debug 引いた数が0で1041usなら正解

  return(0);

}//pc_putc

//文字列の表示
int pc_printf(char *str1) {

    //文字の中身がゼロか
    while(*str1){

        //一文字出力
        pc_putc(*str1 ++);
        //Serial.print( *str1 ++ ); //uno

    } //while

    //戻り値
    return(0);
}//pc_printf

//0から999まで文字列に変換
char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
  int a,b,c;

  b=l_num/10;
  c=l_num-(b*10); //1の桁
  a=b/10;         //100の桁
  b=b-(a*10);     //10の桁

  ch_hex_a_b[0] = '0' + a;
  ch_hex_a_b[1] = '0' + b;
  ch_hex_a_b[2] = '0' + c;
  ch_hex_a_b[3] = 0;

  return(ch_hex_a_b);
}//ch_hex_a

//初期化
void setup()
{
  //ポートをhiにする 初期化
  pinMode(in7, OUTPUT);
  DW(in7, HIGH);
  delayMicroseconds(UART_DELAY*10);

  //Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  int s; //センサーの値  //101
  int ii; //ループカウンター
  
  s = analogRead(A3); // PA11 PIN5
  //s = (65536/2)-1;
  //s = 65536/4;
  //s=(4096/2);
  //s=(1024/2);

//d  String thisString2 = String(s);
//d  pc_printf( (char *)thisString2.c_str() );
//d  pc_printf("\r\n");

  //電圧を温度に変換 ex 20.0 -> 200 温度の十倍を出力
  s=((  (s*4)  -496)*27081)>>16;

//d  //pc_printf( "," ); //debug_i
//d  String thisString3 = String(s);
//d  pc_printf( (char *)thisString3.c_str() );
//d  pc_printf("\r\n");

  //小数点以上と小数点以下を分ける
  ii=(s/10);  // 10の桁
  s =(s-(ii*10)); //  1の桁

  //温度の小数点以上の表示
  pc_printf(  ch_hex_a(ii)  );

  //温度の小数点以下の表示
  ch_hex_a( s*10 );
  ch_hex_a_b[0] = '.';
//ch_hex_a_b[1] = '0' + s;
  ch_hex_a_b[2] = 'C';      
  pc_printf(  ch_hex_a_b  );

  //リターン
  pc_printf(  "\r\n"  );

  //1秒の待ち
  delay(1000);

} //loop




```

![soft_serial_adc_tmp_031_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/59125b46-155f-9258-72c9-04a7592702be.jpeg)
映像タイトルの名寄

<h3>
概要/背景
</h3>
VOD（Video On Demandサービス）とかテレビの映像データで、特定の期間中に見られた番組やシリーズものの映像ごとに視聴数とか集計したときのメモ。テレビの視聴率を時間ごとに計算するのは簡単ですが、動画のタイトルは結構表記ゆらぎが多いので、まとめるのが大変。例えば、「笑ゥせぇるすまん」と「笑ゥせぇるすまん スペシャル」は別タイトルになってしまいます。単純な方法ですが、JW Distance(Jaro Winkler距離)を使用。

<h3>
実装
</h3>
pyjarowinklerを使ってみます。プログラム名が短いとうまくいかないので4文字くらいで切った方が精度が出ます。

```python
from pyjarowinkler import distance
path = "Path to directory"

def dist_func(wp,p_name1, p_name2):
    write_fp = csv.writer(open(path+"jw_distance" + ".csv","a"))
    write_fp.writerow(["'" + wp + "'", "'" + p_name1 + "'", "'" + p_name2 + "'","'" + str(distance.get_jaro_distance(p_name1,p_name2,winkler=True, scaling=0.1)) + "'"])
```
みたいな感じで超簡単。

<h3>
結果
</h3>
1列目がタイトル1、2列目がタイトル2、3列目がJW距離
'笑ゥせぇるすまん','スクール・ウォーズ2','0.0'
'笑ゥせぇるすまん','笑ゥせぇるすまん スペシャル','0.91'
'笑ゥせぇるすまん','中二病でも恋がしたい!戀 エクストラエピソード','0.0'
・・・
一番右列がJW距離です。'笑ゥせぇるすまん'と'笑ゥせぇるすまん スペシャル'は'0.91'になっていて、似ているタイトルとみなせそうですね。

<h3>
参考
</h3>
URL
ジャロ・ウィンクラー距離 - Wikipedia
React コマンドメモ

# 新規作成

```shell
$ npx create-react-app [プロジェクト名]

# TSX(JSXのTypeScript版)で作りたい時
# --template typescriptをつける
$ npx create-react-app --template typescript [プロジェクト名]
```
# 開発サーバー起動
```shell
$ npm start
```

# ビルドしてHTML/CSS/JSファイルを生成
```shell
$ npm run build
```

#  jestによるテストの実行
```shell
$ npm test
```
nexeでNode.jsのアプリをパッケージングしようとしたらNode.jsのバージョンで怒られた

# nexeでNode.jsのアプリをパッケージングしようとしたらNode.jsのバージョンで怒られた

久しぶりにNode.jsのアプリのパッケージングで、exeファイル作ろうとしてみたらエラーで怒られたので回避策を掲載しておきます。

## 私の環境(ERROR再現時)

- Windows 10 
- nvm-windows で node.js のバージョン管理
- node.js : v14.17.0
- npm : v6.14.13

## 結論

nexeのv3.3.3でリリースしている、リストの一覧からnode.jsのバージョンを合わせないといけいない。
windows環境なら、`windows-x64-14.15.3`なので、node.jsのバージョンは、`v14.15.3`にする。

[nexe の github releases](https://github.com/nexe/nexe/releases/tag/v3.3.3)
![nexe releases windows-x64-14.15.3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711722/c5b4ca08-436c-b64f-7b12-27380f985bca.png)

## 以下はERROR遭遇から解決までの流れ
### nexeでパッケージングしようとするとこんなエラーが出た

```powershell
PS> npm run package

> hogehoge@1.0.0 package nexe index.js
> nexe index.js
i nexe 3.3.7
√ Downloading pre-built Node.js
√ Finished in 1.835s

Error: https://github.com/nexe/nexe/releases/download/v3.3.3/windows-x64-14.17.0 is not available, create it 
using the --build flag

See nexe -h for usage..

npm ERR! errno 1
npm ERR! hogehoge@1.0.0 package: `nexe index.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the hogehoge@1.0.0 package script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\{user}\AppData\Roaming\npm-cache\_logs\2021-05-29T14_03_17_600Z-debug.log
v14.17.0
```
// npm run package は「nexe index.js」を実行してるだけ。pacakge.jsonに記載してたので。。

### nexe のリリースを確認するとnode.jsの`v14.17.0`に相当するものがなかった。

https://github.com/nexe/nexe/releases/download/v3.3.3

### リリース一覧のうち最新のnode.jsのバージョンに、ローカル環境のnode.jsバージョンを合わせる。

`windows-x64-14.15.3`が最新っぽいので、ローカル環境を`v14.15.3`に更新。

```powershell
PS> nvm install 14.15.3
Downloading node.js version 14.15.3 (64-bit)...
Complete
Creating C:\Users\{user}\AppData\Roaming\nvm\temp

Downloading npm version 6.14.9... Complete
Installing npm v6.14.9...

Installation complete. If you want to use this version, type

nvm use 14.15.3
PS> nvm use 14.15.3
Now using node v14.15.3 (64-bit)
PS> node -v
v14.15.3
```

### 再度パッケージングを試す

```powershell
PS> npm run package

> hogehoge@1.0.0 package C:\project\hogehoge
> nexe index.js

i nexe 3.3.7
√ Downloading...100%
√ Compiling result
√ Entry: 'index.js' written to: hogehoge.exe
√ Finished in 55.151s
```

### exeができました！

![exe.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711722/250d43fe-c28a-0925-87fa-7af6b029cb11.png)
wmctrlでウインドウを自動最小化

# wmctrlで最小化
## 最小化のコード
```
wmctrl -r [ウインドウのタイトル]-b toggle,hidden
```
ウインドウのタイトル：画像でいうと「sudo」に当たる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617712/e86c04e8-ef61-8c08-b72f-0f83cc6456b8.png)

## wmctrl導入
まだwmctrl導入してない人はこちらから。

```
sudo apt install wmctrl
```
## 応用

shell scriptに書く

```shell:script.sh
#! /bin/bash
sudo hogehoge
sleep 1

#最小化

wmctrl -r hogehoge -b toggle,hidden
read -p "readkey"

```
これで自動起動するバッチ処理ウインドウとかをオートで最小化できる。
ただ処理の関係でプロセスが立ち上がってから1秒スリープさせる必要がある。
## 最大化、Windowサイズ指定など
このブログがわかり易かった。
[[Ubuntu 19.04]ウィンドウを自動で最大化したりモニターを移動する](https://qiita.com/relu/items/d03104a64a8597da2c22)

## 感想
毎回起動時に邪魔なターミナルを閉じてるのバカらしかったので、自動でできてすごくうれしい。
ありがとうございました。指摘等々お願いします。
> Written with [StackEdit](https://stackedit.io/).
ESXi Arm Edition version 1.4 — June 15, 2021 の登場

VMware Flings で提供されている、ESXi Arm Edition の最新版、ESXi Arm Edition version 1.4 Build 18175197 が公開されました。
詳細はこちらのブログに書きました。
[ESXi Arm Edition version 1.4 — June 15, 2021 の登場](https://imaisato.hatenablog.jp/entry/2021/06/18/224854)
AndroidでFlow<T>をcollectするのをちょっとだけ楽にする

Androidで`Flow<T>`を扱う際の小ネタです。

# 前置き

Android+Kotlinで`StateFlow<T>`や`SharedFlow<T>`などを`LiveData<T>`代わりに利用する際は、
主に`Activity`/`Fragment`上で`lifecycleScope.launchWhenStarted {}`などを使って`collect {}`を実行することが多いと思います。
その際、`LiveData<T>`に比べてコルーチンスコープを開始する関係上ネストが一段深くなってしまいます。

```kotlin:Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    lifecycleScope.launchWhenStarted {
        viewModel.flow.collect {
            binding.textView.text = it
        }
    }
}
```

いくつも`collect`が並ぶと`LiveData<T>`に比べて微妙に可読性が下がるのでネストが深くならないように簡単に対策してみます。

# `Flow<T>`の拡張関数を作って対処する

下記のような拡張関数を用意して、`launch`関数でネストさせなくても`collect`出来るようにしてみます。

```kotlin:FlowCollector.kt
inline fun <T> Flow<T>.collectWhenCreated(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenCreated {
        collect(action)
    }
}

inline fun <T> Flow<T>.collectWhenStarted(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenStarted {
        collect(action)
    }
}

inline fun <T> Flow<T>.collectWhenResumed(lifecycleOwner: LifecycleOwner, crossinline action: suspend (value: T) -> Unit): Job {
    return lifecycleOwner.lifecycleScope.launchWhenResumed {
        collect(action)
    }
}
```

# `launchWhenStarted`+`collect`を置き換える

先程の拡張関数を使うと下記のように表すことができます。
一段ネストが減りましたね！

```kotlin:Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    viewModel.flow.collectWhenStarted(this) {
        binding.textView.text = it
    }
}
```
```kotlin:Fragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel.flow.collectWhenStarted(viewLifecycleOwner) {
        binding.textView.text = it
    }
}
```

通常の`Flow<T>`の扱いと同様に、FragmentでViewの更新をする場合は引数に`this`ではなく`viewLifecycleOwner`を指定する必要があるのでご注意下さい。
たったこれだけですが地味に便利なので試してみて下さい :bulb:
yukicoder contest 300 参戦記

# yukicoder contest 300 参戦記

## [A 1550 nullくんの町清掃 / null's Town Cleaning](https://yukicoder.me/problems/no/1550)

問題文の通り、余りを求めればよい.

```python
n = int(input())

print(n % 1000000007)
```

## [B 1551 誕生日の三角形](https://yukicoder.me/problems/no/1551)

辺の長さが L / 3 の正三角形が答えなのは直感的に分かるので、後は面積の公式をググれば良い.

```python
from math import sqrt

L = int(input())

print(L * L * sqrt(3) / 36)
```
rails チュートリアル第５章で印象に残ったこと

####htmlの中身の紹介
```haml
 <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %> #コードをいじられないようにする メソッド
    <%= csp_meta_tag %> #何か大切 メソッド
    <%= stylesheet_link_tag    'application', media: 'all',
                               'data-turbolinks-track': 'reload' %> #（）がないだけでapplicationは引数

    <%= javascript_pack_tag 'application',
                               'data-turbolinks-track': 'reload' %>
```
()がないだけでapplicationは引数
mediaは　ハッシュのキー　'all'はハッシュのバリュー
'data...track'もハッシュのキー　’’で囲まれているのはシンボルと勘違いされないため

```
<!--[if lt IE 9]>
      <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
      </script>
    <![endif]-->
```
インターネットエクスプローラ９以下のものに対応するため


```haml
<%= link_to image_tag("rails.svg", alt: "Rails logo", width: "200px"),
                      "https://rubyonrails.org/" %>
```
デフォルトで画像の保存しておく場所は決まっている

####boostrap
```
gem 'bootstrap-sass', '3.4.1'
```
Gemfileに何か書き込んだらbundle installをする
boostrap-sassにCSSが詰め込まれている
cssを０から作るよりか便利

```
@import "bootstrap-sprockets";
@import "bootstrap";
```
そのcssを使うためにインポートさせる

伝えたい情報とその他を区別し強調することが大事
####partial

```
<%= render 'layouts/shim' %>
```
いろんな人がコードをいじると、
gitの編集履歴がごちゃごちゃになるのでそれを防ぐ。
コンフリクトしないようにする。


partialのフォルダのタイトルの初めに_を入れる約束がある。
partialで一つのコードを小分けにすることができる。

####エラー
MissingTemplate
viewの何かがあるべきところにない。

####アセットパイプライン
開発側からすると分割の方がやりやすいが、
利用者側からするとファイルが分割してあると閲覧するのに時間がかかる
それらをうまくしたもの

勉強していきたい。
残プロ　第-17回　~tkinterで画像を表示する~

# 今回の簡単な流れ

- tkinterでウィンドウを用意
- canvasを作成
- canvas上にtkinter用にコンバートした画像を表示


# プログラム例

今回の例ではcv2で画像を読み込んでいます．
PILのfromarrayとPhotoImageを使って，
numpy.ndarray → PIL.Image.Image → PIL.ImageTk.PhotoImage
と変換しています．

グレースケールで読み込んでいますが，カラーの場合も同様です．
※関数内でコンバートした場合(下記プログラムのimg_tk)，ガベージコレクションに入れられるので，リストに追加することで回避しています．


~~~ python:
import tkinter as tk
from PIL import Image, ImageTk
import cv2

def convert(img_gry):
    img_pil = Image.fromarray(img_gry)
    img_tk = ImageTk.PhotoImage(img_pil)
    imgs.append(img_tk)
    return img_tk


# --main--
path = "sample.png"

img_gry = cv2.imread(path, 0)
hei = img_gry.shape[0]
wid = img_gry.shape[1]

imgs = []

root = tk.Tk()

canvas = tk.Canvas(root, height=hei, width=wid)
canvas.pack()
canvas.create_image(0, 0, image=convert(img_gry), anchor='nw')

root.mainloop()
~~~

**元画像　sample.png**
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/06332439-7a51-9818-a207-9a3b3cfebd50.png)

**実行結果**
![gui_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/c22d47ce-0d7f-e118-e30f-963cc5c1a977.png)
情報セキュリティの基本

## はじめに
情報セキュリティの基礎的なキーワードメモです

## 情報セキュリティの定義
情報の機密性、完全性、可用性を維持することと

1.機密性 (confidentiality): 
　許可されていない個人、エンティティ又はプロセスに対して、情報を使用不可又は非公開にする特性
2.完全性 (integrity): 
　資産の正確さ及び完全さを保護する特性
3.可用性 (availability): 
　許可されたエンティティが要求したときに、アクセス及び使用が可能である特性
上記３つの頭文字をとってCIAと呼ぶ

拡張した定義は、以下の４つを追加する。
・真正性 (authenticity): 
　ある主体又は資源が、主張どおりであることを確実にする特性。真正性は、利用者、プロセス、
　システム、情報などのエンティティに対して適用する。
・責任追跡性 (accountability): 
　あるエンティティの動作が、その動作から動作主のエンティティまで
　一意に追跡できる事を確実にする特性。
・否認防止 (non-repudiation): 
　ある活動又は事象が起きたことを、後になって否認されないように証明する能力
・信頼性 (reliability): 
　意図した動作及び結果に一致する特性

## 脅威
脅威とは情報資産を脅かす可能性のある事象。
※対策が不可能な事象。自然災害は0にできない。サイバー攻撃や人的ミスも0にはできない

1.環境
　1-1.災害
　・地震、台風、大雨、大雪等
　1-2.障害
　・設備障害　：停電や火災
　・ハードウェア：サーバの故障
　・ソフトウェア：OSやミドルウェア、アプリケーションのバグ
　・ネットワーク：ネットワーク機器の障害や、利用している回線の障害
2.人間 
　2-1.意図的：サイバー攻撃、盗難等
　・不正アクセス
　・サイバー攻撃
　・ウイルス、マルウェア、スパイウェア
　・社員やアルバイト等のによる不正行為（盗難等）
　・委託先や出入り業者スタッフ等のによる不正行為（盗難等）
　・書類やPC等のデバイス紛失による漏洩
　・USBメモリからのウイルス感染　等
　2-2.偶発的：操作ミス、紛失、事故等
　・管理者の誤操作：サーバやアプリのメンテナンス時の誤操作
　・バグ：プログラムバグ
　・利用者の誤操作：メール誤送信、クラウドサービス、公開ファイル等設定ミス
　・紛失や誤廃棄：PCやUBメモリ、紙媒体等の紛失
　2-3.クラウドサービス
　・利用しているクラウドサービス側の障害
　・利用しているクラウドサービスの終了、値上げ

## 脆弱性
　脅威が顕在化する情報セキュリティ上の欠陥

1.環境
　1-1.災害
　・データセンターの災害対策が不十分
　1-2.障害
　・設備
　　停電対策：無停電電源装置が無い。
　・ハードウェア
　　サーバの故障：サーバが多重化されていない
　・ソフトウェア
　　パッチ適用がされていない
　　バグが放置されている
　　・ネットワーク
　　NW機器が多重化されていない
2.人間 
　2-1.意図的：
　・ウイルス対策がされていない
　・WAFが無い
　・ファイアウォールが未設定
　・オペレーションルームの入退室管理がされていない
　2-2.偶発的：操作ミス、紛失、事故
　・サーバメンテナンス手順が無い
　・アプリケーション操作手順がない
　・サーバ再起動手順が無い
　・クラウドサービスの仕様を理解していない
　・機密データが暗号化されていない等

## リスク対応計画
脆弱性への対応方法は４つに分類できる

1.軽減
　被害が減る対策を行う
　例：情報漏洩に備えデータを暗号化する。データセンターを多重化する
2.回避
　危険なことは実施しない
　例：クラウドサービスの情報漏洩に備え利用を禁止する
3.転嫁
　インシデント発生時の被害を別の対象に転嫁する。専門企業に委託する。
　例：サイバー保険に加入する
4.受容
　対策をせず被害を許容する

## サイバー攻撃の主な手法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/adccc157-91c1-404b-80ae-9014ca26256f.png)
1. DNSキャシュポイゾニング
1. DNSサーバからの情報収集
1. DoS攻撃、DDoS攻撃
1. Evil Twin
1. HTTPヘッダインジェクション
1. IPスプーフィング
1. MITB
1. MITM
1. OSコマンドインジェクション
1. SEOポイズニング
1. SQLインジェクション
1. アドレススキャン
1. ウォードライビング（無線LAN不正接続）
1. クリックジャッキング
1. クロスサイトスクリプティング
1. クロスサイトリクエストフォージュリ
1. スタックフィンガープリンティング
1. スパムメール
1. スミッシング
1. セッションハイジャック
1. セッションフィクセイション
1. セッション固定攻撃
1. ゼロデイ攻撃
1. ソーシャルエンジニアリング
1. 第3者中継
1. 中間者攻撃
1. ディレクトリトラバーサル
1. ディレクトリリスティング
1. ドメイン名ハイジャック
1. ドライブバイダウンロード
1. パケット盗聴
1. パスワードクラック
1. バッファオーバーフロー（BOF）
1. ファーミング
1. フィッシング
1. ポートスキャン
1. マルウェア（ウイルス、ワーム、スパイウェア、ランサムウェア、アドウェア、ボット等）
1. リプレイ攻撃
1. ワンクリック詐欺
1. 踏み台
1. 標的型攻撃(標的型攻撃メール)
1. 不正コマンドやリクエストの発行
1. アドレススキャン
1. ポートスキャン
1. スタックフィンガープリンティング
1. パケット盗聴
1. DNSサーバからの情報収集
1. ソーシャルエンジニアリング
1. フィッシング
1. DNSキャシュポイゾニング
1. ウォードライビング（無線LAN不正接続）
1. パスワードクラック
1. セッションハイジャック
1. セッションフィクセイション
1. バッファオーバーフロー（BOF）
1. クロスサイトスクリプティング
1. SQLインジェクション
1. OSコマンドインジェクション
1. HTTPヘッダインジェクション
1. 不正コマンドやリクエストの発行
1. DoS攻撃、DDoS攻撃
1. スパムメール
1. マルウェア（ウイルス、ワーム、スパイウェア、ボット等）

## 情報セキュリティに関する規格
ISO27001
Pマーク

## 情報セキュリティに関する資格
情報処理安全確保支援士
情報セキュリティマネジメント試験
CISSP
CISA
GIAC

## 参考サイト
https://www.ipa.go.jp/security/vuln/10threats2021.html

## 履歴
2021/6/18 作成
2021/6/27 記述変更
2021/7/13 定義を追加
2025/5/17 規格と資格を追加。全体レイアウト修正
E資格2021#2実装演習レポート：深層学習day3、day4

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/27948060-6b72-0561-d5e3-0cad33f60d54.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/ba5dbaca-bfb9-daac-9f46-6a2d7ca64939.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/1801c906-3e2f-dd68-f779-0fef314ba76e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/019ac342-beb5-01ae-2ca6-cff64b3004eb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/752bd30a-d28c-b2b3-db70-82bac53bda0f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/2fc58722-53b3-efb0-76b4-c40a4e7dd49d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/28ed6dd9-e99c-acea-7239-4d363d9bdaf4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/4a415f57-1996-0f49-a026-28473c2bc8be.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/7fa1ab91-c7b5-d9a9-2e2a-0ccadc9d82d1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/81c0984c-caf8-8749-1dba-6388eaed68dd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/92e11460-9372-f444-8ce3-51ed49ab7684.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/92fced85-3247-9247-815c-78ab93731919.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643448/f73692a3-3924-3391-7d54-082976315624.png)
text_fieldヘルパーとtext_field_tag違い

Railsには、テキストフィールドを扱うViewヘルパーとして、text_fieldヘルパーがあります。

ほとんど同じ使い方ができるものですので、どちらを使っても同じ処理を実現できますが、text_fieldヘルパーは、原則としてモデルが存在する場合に使用するものです。

|ヘルパー|paramsハッシュ|
|--|--|
|text_field_tagヘルパー|params[キー]|
|text_fieldヘルパー|params[モデル名][キー]|
text_fieldヘルパーでモデルのカラムに存在していないキーを使うこともできますが、モデルを必要としない処理では、text_field_tagヘルパーを使う方が自然。
21/06/18　for文

活動時間　340min(内90minアルバイト)
for文について学習しました。
今回、3つのソースコードを作成した。
ポイントは変換指定子%4dを使い桁数を揃えたところ。
if文を利用することでソースコードをより簡潔に書けると気づいたので、次の取り組みに生かしたい。文字も3→2にもできそう。

#include <stdio.h>

int main(void)
{
	int i, j, k;
	printf("Input a positive integer number : ");
	scanf("%d", &i );
	for (j = 1; j <= i; j++) {
		k += j;
	}
	printf("The sum from 1 to %d is %d\n", i, k);
	return 0;
}



int main(void)
{
	int a, j, k;
	printf("Input a positive integer number : ");
	scanf("%d", &a );
	if (a > 0) {
		for (k = 1; k <= 50 / a ; k++) {
			for (j = (k - 1) * a + 1; j <= k * a; j++) {
				printf(" %4d ", j);
			}
			printf("\n");
		}
		for (j = (50 / a) * a + 1; j <= 50; j++) {
			printf(" %4d ", j);
		}
		printf("\n");
	} else {
		printf("Please input a positive integer number.\n");
	}
	return 0;
}


　
int main(void)
{
	int a, j, k;
	printf("Input a positive integer number : ");
	scanf("%d", &a );
	if (a > 0) {
		for (k = 0; k <= a ; k++) {
			for (j = k + 1; j <= a; j++) {
				printf(" %3d ", j);
			}
			printf("\n");
		}
		printf("\n");
	} else {
		printf("Please input a positive integer number.\n");
	}
	return 0;
}