2023,江端さんの技術メモ

DockerのSQL-DBが死んだら、と、考えるだけで恐怖なので、 8TBのHDDの方にDockerの構築環境まるごとコピーして、そこに、Dockerのイメージも放り込んでおくことにした。

Step 1 Docker Desktopを立ち上げて、"tomioka"をアクティベートにする

Step 2 "docker ps" で起動状態を確認する

Step 3 "$ docker commit tomioka-db-1 tomioka_db_backup"をする
ちなみに実施するディレクトリはどこでもいい。tomioka_db_backupはファイルではないので。

Step.4 "$ docker images"をして、作成を確認する

イメージができているのを確認する。

Step.5 C:\の直下に、DockerBackupsという名前のディレクトリはすでに掘られているので、

Step.6 Command.com(他のシェルではダメみたい)"$ docker save -o C:\DockerBackups\tomioka_db_backup.tar tomioka_db_backup" を実施する

で、これを、F:\backup\tomoi\tomiokaに移動しておく。
こっちで纏めて管理しておく。

で、同じことを、person_trip1(×person_trip)でも行う(以下省略)

 

=======

 

私、DockerでDBの大量生産をやっているのですが、このDockerを起動させるPCが不具合のような兆候を見せて、今年最大の「真っ青」な状態になりました。

2T程度のHDDを購入して、Dockerコンテナのバックアップしておかなければ、ここ1年の研究が吹き飛ぶと実感しました。

とりあえず、逃し方のメモを取っておきます。

Step 1 Docker Desktopを立ち上げて、"kitaya"をアクティベートにする

Step 2 "docker ps" で起動状態を確認する

Step 3 "$ docker commit kitaya-db-1 kitaya_db_backup"をする
ちなみに実施するディレクトリはどこでもいい。kitaya_db_backupはファイルではないので。

Step.4 "$ docker images"をして、作成を確認する

イメージができているのを確認する。

Step.5 C:\の直下に、DockerBackupsという名前のディレクトリを掘っておく。

Step.6 "$ docker save -o C:\DockerBackups\kitaya_db_backup.tar kitaya_db_backup" を実施する

というファイルができる。

Step.7 "docker rmi kitaya-db-1_backup" でイメージを消去する(しなくてもいいが)。無駄なリソースを削除するためである。

ちなみに、kitaya_db_backup.tarも、サイズがバカでかいので、外部HDDなどに逃しておく方が良いと思う。

 


ちなみに、(試していないが)リストアはこんな感じになる(らしい)

docker load -i C:\DockerBackups\kitaya_backup.tar


ところで、Amazonで購入した2TのHDDが、まるで使えんので、返品することになりました。

この"評価1"て何だ?

私は、これを注文したハズなんだが? (だれが評価1、評価者2の商品なんぞ買うか)

なんか、やられたのかなぁ。腹立つなぁ。返品できるだけマシだが。

2023,江端さんの技術メモ

Select文を使って、選んだ要素だけをcsvファイルにエクスポートする方法 (これから頻用しそう)

agent_db=# \copy (select * from agent_track where agent_id = 100) to test.csv with CSV;
最初の'\"が重要

最初はエクスポートです。

Microsoft Windows [Version 10.0.19044.2486]
(c) Microsoft Corporation. All rights reserved.
C:\Users\ebata>psql -U postgres -h 192.168.0.23 -p 15432
Password for user postgres:
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
Type "help" for help.
postgres=# \c agent_db
psql (13.4, server 12.5 (Debian 12.5-1.pgdg100+1))
You are now connected to database "agent_db" as user "postgres".
agent_db=# \copy user_list to 'testtest.csv' WITH CSV DELIMITER ',';
COPY 20
agent_db=#
C:\Users\ebata に、testtest.csv ができています。
カラム名が必要な場合は、こちら(大抵の場合必要)。
agent_db=# \copy user_list to 'testtest.csv' WITH CSV HEADER;
次にインポートです。
以下のcsvファイルをインポートします。ファイル名はkai_20220522holyday18.csvです。
id,age,type,departure_name,departure_number,departure_lat,departure_lng,arrival_name,arrival_number,arrival_lat,arrival_lng
0,43,resident,,,34.173408,131.470684,,,34.155862,131.501246
1,24,resident,,,34.179449,131.482543,,,34.164116,131.471791
2,42,resident,,,34.168739,131.470768,,,34.160989,131.491124
3,21,resident,,,34.169494,131.469934,,,34.173498,131.471351
4,58,resident,,,34.185295,131.47414,,,34.191481,131.49456
5,48,resident,,,34.150778,131.480747,,,34.16536,131.471872
6,56,resident,,,34.16536,131.471872,,,34.174066,131.479312
7,73,resident,,,34.155731,131.500845,,,34.16776,131.472831
8,47,resident,,,34.167237,131.471785,,,34.155775,131.476531
9,21,resident,,,34.154931,131.50468,,,34.156678,131.49581
10,37,resident,,,34.16727,131.472899,,,34.171253,131.471177
11,40,resident,,,34.147241,131.474921,,,34.150675,131.486268
12,67,resident,,,34.173683,131.476347,,,34.173643,131.471027
13,28,resident,,,34.183079,131.484303,,,34.174245,131.474592
14,46,resident,,,34.146154,131.472711,,,34.159611,131.491548
15,25,resident,,,34.162497,131.489283,,,34.147212,131.475984
次に、テーブルをクリアにします。
agent_db=# delete from user_list;
DELETE 36
agent_db=# select * from user_list;
id | age | type | departure_name | departure_number | departure_lat | departure_lng | arrival_name | arrival_number | arrival_lat | arrival_lng
----+-----+------+----------------+------------------+---------------+---------------+--------------+----------------+-------------+-------------
(0 rows)
として、
agent_db=# \copy user_list from 'kai_20220522holyday18.csv' delimiter ',' csv header;
でインポートが完了します。
一応、確認します。
agent_db=# select * from user_list;
id | age | type | departure_name | departure_number | departure_lat | departure_lng | arrival_name | arrival_number | arrival_lat | arrival_lng
----+-----+----------+----------------+------------------+---------------+---------------+--------------+----------------+-------------+-------------
0 | 43 | resident | | | 34.173408 | 131.470684 | | | 34.155862 | 131.501246
1 | 24 | resident | | | 34.179449 | 131.482543 | | | 34.164116 | 131.471791
2 | 42 | resident | | | 34.168739 | 131.470768 | | | 34.160989 | 131.491124
3 | 21 | resident | | | 34.169494 | 131.469934 | | | 34.173498 | 131.471351
4 | 58 | resident | | | 34.185295 | 131.47414 | | | 34.191481 | 131.49456
5 | 48 | resident | | | 34.150778 | 131.480747 | | | 34.16536 | 131.471872
6 | 56 | resident | | | 34.16536 | 131.471872 | | | 34.174066 | 131.479312
7 | 73 | resident | | | 34.155731 | 131.500845 | | | 34.16776 | 131.472831
8 | 47 | resident | | | 34.167237 | 131.471785 | | | 34.155775 | 131.476531
9 | 21 | resident | | | 34.154931 | 131.50468 | | | 34.156678 | 131.49581
10 | 37 | resident | | | 34.16727 | 131.472899 | | | 34.171253 | 131.471177
11 | 40 | resident | | | 34.147241 | 131.474921 | | | 34.150675 | 131.486268
12 | 67 | resident | | | 34.173683 | 131.476347 | | | 34.173643 | 131.471027
13 | 28 | resident | | | 34.183079 | 131.484303 | | | 34.174245 | 131.474592
14 | 46 | resident | | | 34.146154 | 131.472711 | | | 34.159611 | 131.491548
15 | 25 | resident | | | 34.162497 | 131.489283 | | | 34.147212 | 131.475984
(16 rows)

2023,江端さんの技術メモ

Keyword: VScode vscode 図面 draw.io  drawio

 

毎年1本は、Officeを使って特許明細書を書かなければなりませんが、パワーポイントは、フローチャートやシーケンス図の作成にはあまり向いていません。はっきり言えば使い難い。

*.drawioで提出できればいいのだけど、それでは、私の図面を修正する人が困ってしまうので、最終的には*.ppt/pptx形式にしなければなりませんが、このコンバートの相性がどうも今一つ。

今、ちょっとテストしていたのですが、一応、以下でできるようですが、文字が出てこなかったりとか完璧な対応は難しいようです。

1.svg形式で保存して、emfファイルに変換 (私は、https://convertio.co/ja/を使ってみた)
2. Officeに「拡張メタファイル」で貼り付け
3. グループ解除

(参考:SVGファイルをPowerPointで編集できる図形として読み込むには?)

Drawio. integration がエクスポート/コンバートに、ppt/pptx形式をサポートしてくれれば嬉しいんだけど、ないものねだりをしても仕方ありません。

どなたか、「何を言っとるんだ? これで簡単にでできるだろう?」とアドバイスして頂ける方。お助け下さい。→ メールアドレス

2023,江端さんの技術メモ

Webサーバに繋っているブラウザが、全部いなくなったことを確認する為に、ブラウザのJavaScriptからハートビートを飛ばして、ハートビートがこなくなったことを確認する簡易プログラムを作成しました。

■ブラウザの生存監視サーバ

$ pip install Flask

をしてから、以下のプログラムをhearbeat.pyという名前でサーバを立ち上げるフォルダ(例 c:\users\ebata)に放り込んでおく。

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/heartbeat', methods=['POST'])
def receive_heartbeat():
    data = request.get_json()
    print(f"Received heartbeat: {data}")
    return jsonify({"status": "OK"})

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=3000)

■index.htmlの内容
これも、サーバを立ち上げるフォルダ(例 c:\users\ebata)に放り込んでおく。

<!DOCTYPE html>
<html>
<head>
    <title>Heartbeat Example</title>
</head>
<body>
    <h1>Heartbeat Sender</h1>
    <script>
        function sendHeartbeat() {
            fetch('http://localhost:3000/heartbeat', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ timestamp: new Date() })
            })
            .then(response => response.json())
            .then(data => console.log('Heartbeat sent:', data))
            .catch(error => console.error('Error sending heartbeat:', error));
        }

        // 10秒ごとにハートビートを送信
        setInterval(sendHeartbeat, 10000);
    </script>
</body>
</html>

■起動方法
(Step 1)サーバを立ち上げるフォルダ(例 c:\users\ebata)で、

C:\Users\ebata>python heartbeat.py

で、「ブラウザの生存監視するサーバ」を起動
(Step 2)次に、以下のコマンドで、1行Webサーバを起動

C:\Users\ebata>python -m http.server 8000

(Step 3) ブラウザに、

http://localhost:8000/

を投入。複数のブラウザを立ち上げて、ブラウザの生存監視サーバから、

の表示が出てくれば成功 → ウソです。
ブラウザを全部落せば、動かなくなるはずです。→ これは本当ですが、def receive_heartbeat()の処理は全くされていません


Choromeの開発者の表示は、こんなのが出ていました。

Access to fetch at 'http://localhost:3000/heartbeat' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. (index):19 Error sending heartbeat: TypeError: Failed to fetch at sendHeartbeat ((index):10:13)

で、
このエラーメッセージは、CORS(Cross-Origin Resource Sharing)ポリシーに違反していることを示していて、これは、異なるオリジン(localhost:8000とlocalhost:3000)間でのリクエストがブラウザによってブロックされていることを意味します。

この問題を解決するために、FlaskアプリケーションでCORSポリシーを設定する必要があり、Flask-CORSという拡張機能を使用してこれを行うことができます。

pip install flask-cors

で、

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app) # すべてのリクエストに対してCORSを有効にする

を処理すれば、receive_heartbeat():が実施されます。

で、修正後のコードは以下の通りです。

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # すべてのリクエストに対してCORSを有効にする

@app.route('/heartbeat', methods=['POST'])
def receive_heartbeat():
    data = request.get_json()
    print(f"Received heartbeat: {data}")
    return jsonify({"status": "OK"})

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=3000)

出力結果

ちょっとまだ疑問はあるけど、とりあえず、メソッドの中には入ったようです。

 

 

2023,江端さんの技術メモ

Win32 Disk Imager

"Win32 Disk Imager"の使いかたが結構分けわからん

まず、SDカード→PCへのコピーは、

Deviceでドライブ"e.f.[G\]"を選んで→
Image Fileの方にテキトーな名前を(d:\testtest20231010とか、絶対に存在しないファイル名にして)つけて
"Read"ボタンを押す。絶対存在しないファイル名にすることによって、間違った読み込みをすることはなくなる(はず)

PC→SDカードへのコピーは、
上記の逆転をやって
"Write"をボタンを押す。

この"Read"と"Write"を間違えて、ハードディスク丸ごと破壊したことを、ゆめゆめ忘れるな

2023,江端さんの技術メモ

以下のtest.csvファイルを、gunplotで3D表示させたくて、色々やっています。

test.csv
#lat,lng,datetime,distance,speed
35.681100,139.758600,2023-05-22 02:10:30,313.307785,37.596934
35.683300,139.759900,2023-05-22 02:11:00,271.347933,32.561752
35.685300,139.760900,2023-05-22 02:11:30,240.030143,28.803617
35.685400,139.761000,2023-05-22 02:12:00,14.325264,1.719032
35.685400,139.761000,2023-05-22 02:12:30,0.000000,0.000000
35.685400,139.761100,2023-05-22 02:13:00,9.031610,1.083793
35.685200,139.763500,2023-05-22 02:13:30,217.896760,26.147611
35.684700,139.765700,2023-05-22 02:14:00,206.328362,24.759403
35.684200,139.768000,2023-05-22 02:14:30,215.040983,25.804918
35.685400,139.768400,2023-05-22 02:15:00,138.238013,16.588562

で、まあ、こんなgpファイルを使って試していましたが、上手く動きませんでした。

# Function to parse datetime string into a numerical value
strptime_datetime(x) = strptime('%Y-%m-%d %H:%M:%S', x)

# Set the output terminal to a 3D plot (you can change the output format if needed)
set terminal pngcairo enhanced size 800,600

# Set the data file separator to a comma
set datafile separator ','

# Set the axis labels
set xlabel 'Longitude (lng)'
set ylabel 'Latitude (lat)'
set zlabel 'Date and Time (datetime)'

# Set the view to a 3D perspective
set view 50,30,1,1


# Get the minimum and maximum datetime values from the data
stats 'test.csv' using (strptime_datetime(stringcolumn(3))) nooutput
min_datetime = STATS_min
max_datetime = STATS_max

# Set the range for the Z axis (datetime)
set zrange [min_datetime:max_datetime]

# Plot the data using the specified columns
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))) with points pointtype 7 pointsize 1 title 'Data Points'
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))) with points pointtype 7 pointsize 1 title 'Data Points'
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))):(0) with points pointtype 7 pointsize 1 title 'Data Points'

splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3)))

時間のパース(strptime_datetime(x) = strptime('%Y-%m-%d %H:%M:%S', x))がやっぱり上手く動きませんでした。

でまあ、しょうがないので、"2023-05-22 02:10:30"を秒数に変換するプログラムを作成しました。

/* "2023-05-22 02:10:30"を秒数に変換するプログラムを作成しました
   c:\Users\ebata\gnuplot\convert_datetime.go
*/
package main

import (
	"encoding/csv"
	"fmt"
	"os"
	"time"
)

func main() {
	// 入力ファイル名と出力ファイル名を指定
	inputFileName := "test.csv"
	outputFileName := "formatted_test.csv"

	// 入力ファイルを開く
	inputFile, err := os.Open(inputFileName)
	if err != nil {
		fmt.Println("ファイルを開けませんでした:", err)
		return
	}
	defer inputFile.Close()

	// 出力ファイルを作成または上書き
	outputFile, err := os.Create(outputFileName)
	if err != nil {
		fmt.Println("ファイルを作成できませんでした:", err)
		return
	}
	defer outputFile.Close()

	// CSVリーダーとライターを作成
	reader := csv.NewReader(inputFile)
	writer := csv.NewWriter(outputFile)

	// ヘッダーを読み込み、書き込み
	header, err := reader.Read()
	if err != nil {
		fmt.Println("ヘッダーを読み込めませんでした:", err)
		return
	}
	writer.Write(header)

	// データを読み込んで秒数に変換して書き込み
	for {
		record, err := reader.Read()
		if err != nil {
			break
		}

		// datetime列をパースして秒数に変換
		datetime := record[2] // datetime列のインデックスを確認してください
		parsedTime, err := time.Parse("2006-01-02 15:04:05", datetime)
		if err != nil {
			fmt.Println("日時をパースできませんでした:", err)
			return
		}
		seconds := parsedTime.Unix()

		// 秒数に変換した値を新しい列として書き込み
		record = append(record, fmt.Sprintf("%d", seconds))
		writer.Write(record)
	}

	// ライターをフラッシュしてクローズ
	writer.Flush()

	if err := writer.Error(); err != nil {
		fmt.Println("書き込みエラー:", err)
		return
	}

	fmt.Println("変換が完了しました。出力ファイル:", outputFileName)
}

で、こんなのができました。
formatted_test.csv

#lat,lng,datetime,distance,speed
35.681100,139.758600,2023-05-22 02:10:30,313.307785,37.596934,1684721430
35.683300,139.759900,2023-05-22 02:11:00,271.347933,32.561752,1684721460
35.685300,139.760900,2023-05-22 02:11:30,240.030143,28.803617,1684721490
35.685400,139.761000,2023-05-22 02:12:00,14.325264,1.719032,1684721520
35.685400,139.761000,2023-05-22 02:12:30,0.000000,0.000000,1684721550
35.685400,139.761100,2023-05-22 02:13:00,9.031610,1.083793,1684721580
35.685200,139.763500,2023-05-22 02:13:30,217.896760,26.147611,1684721610
35.684700,139.765700,2023-05-22 02:14:00,206.328362,24.759403,1684721640

スクリプトではなく、コマンドで一つづつ入れていきました。

gnuplot> set datafile separator ','   ← これ凄く重要
gnuplot> splot "formatted_test.csv" using 2:1:6
の結果は以下の通りでした。

エリア限定
# x軸の範囲を指定
set xrange [139.6119000:139.6312000]

# y軸の範囲を指定
set yrange [35.3627000:35.3737000] ←これだと、地図のイメージと逆転するので
set yrange [35.3737000:35.3627000]  ← y軸の範囲を逆転させる

上記のxrangeとyrangeの範囲を地図で示すと、

の範囲となる。
領域の範囲内でのトラッキングデータの様子

gnuplotでx軸とy軸の範囲を指定解除するには、以下のコマンドを使用する。

gnuplot> set xrange [*:*]
gnuplot> set yrange [*:*]

gnuplot> splot "2023-topLatLngCounts4-1.csv" using 2:1:3
gnuplot> set yrange [35.3737000:35.3627000]    ← 軸の大小を引っくり返す
gnuplot> splot "2023-topLatLngCounts4-1.csv" using 2:1:3 ← 点を表示
gnuplot> replot "2023-topLatLngCounts4-1.csv" using 2:1:3 with impulses ← 縦軸表示

ちなみに、文字列が入っているcsvだと表示されないことが多いようだ。

2023,江端さんの技術メモ

「交通流動量 パーソントリップ発生・集中量データ」のデータベースの作り方

サンプルファイル

F:\しゅらばしゅう\S05-a-10_SYUTO_GML

s05_xml2csv.zip (ダウンロードして解凍して下さい。sample1.xmlも入っています)

package main

import (
	"encoding/csv"
	"encoding/xml"
	"fmt"
	"os"
)

// XMLデータの構造体定義
type Dataset struct {
	Items []OccurredConcentratedTrafficVolumeOfPersonTrip `xml:"Occurred_ConcentratedTrafficVolumeOfPersonTrip"`
}

type OccurredConcentratedTrafficVolumeOfPersonTrip struct {
	ID                                       string `xml:"id,attr"`
	UrbanArea                                int    `xml:"urbanArea"`
	SurveyYear                               int    `xml:"surveyYear"`
	ConcentratedOccurrence                   int    `xml:"concentratedOccurrence"`
	ZoneCode                                 int    `xml:"zoneCode"`
	Railroad_NumberOfTripsForGoingToWork     int    `xml:"railroad_NumberOfTripsForGoingToWork"`
	Railroad_NumberOfTripsForGoingToSchool   int    `xml:"railroad_NumberOfTripsForGoingToSchool"`
	Railroad_NumberOfFreeTrips               int    `xml:"railroad_NumberOfFreeTrips"`
	Railroad_NumberOfBusinessTrips           int    `xml:"railroad_NumberOfBusinessTrips"`
	Railroad_NumberOfTripsForGoingHome       int    `xml:"railroad_NumberOfTripsForGoingHome"`
	Railroad_TotalNumberOfTrips              int    `xml:"railroad_TotalNumberOfTrips"`
	Bus_NumberOfTripsForGoingToWork          int    `xml:"bus_NumberOfTripsForGoingToWork"`
	Bus_NumberOfTripsForGoingToSchool        int    `xml:"bus_NumberOfTripsForGoingToSchool"`
	Bus_NumberOfFreeTrips                    int    `xml:"bus_NumberOfFreeTrips"`
	Bus_NumberOfBusinessTrips                int    `xml:"bus_NumberOfBusinessTrips"`
	Bus_NumberOfTripsForGoingHome            int    `xml:"bus_NumberOfTripsForGoingHome"`
	Bus_TotalNumberOfTrips                   int    `xml:"bus_TotalNumberOfTrips"`
	Automobile_NumberOfTripsForGoingToWork   int    `xml:"automobile_NumberOfTripsForGoingToWork"`
	Automobile_NumberOfTripsForGoingToSchool int    `xml:"automobile_NumberOfTripsForGoingToSchool"`
	Automobile_NumberOfFreeTrips             int    `xml:"automobile_NumberOfFreeTrips"`
	Automobile_NumberOfBusinessTrips         int    `xml:"automobile_NumberOfBusinessTrips"`
	Automobile_NumberOfTripsForGoingHome     int    `xml:"automobile_NumberOfTripsForGoingHome"`
	Automobile_TotalNumberOfTrips            int    `xml:"automobile_TotalNumberOfTrips"`
	Motorcycle_NumberOfTripsForGoingToWork   int    `xml:"motorcycle_NumberOfTripsForGoingToWork"`
	Motorcycle_NumberOfTripsForGoingToSchool int    `xml:"motorcycle_NumberOfTripsForGoingToSchool"`
	Motorcycle_NumberOfFreeTrips             int    `xml:"motorcycle_NumberOfFreeTrips"`
	Motorcycle_NumberOfBusinessTrips         int    `xml:"motorcycle_NumberOfBusinessTrips"`
	Motorcycle_NumberOfTripsForGoingHome     int    `xml:"motorcycle_NumberOfTripsForGoingHome"`
	Motorcycle_TotalNumberOfTrips            int    `xml:"motorcycle_TotalNumberOfTrips"`
	Walk_NumberOfTripsForGoingToWork         int    `xml:"walk_NumberOfTripsForGoingToWork"`
	Walk_NumberOfTripsForGoingToSchool       int    `xml:"walk_NumberOfTripsForGoingToSchool"`
	Walk_NumberOfFreeTrips                   int    `xml:"walk_NumberOfFreeTrips"`
	Walk_NumberOfBusinessTrips               int    `xml:"walk_NumberOfBusinessTrips"`
	Walk_NumberOfTripsForGoingHome           int    `xml:"walk_NumberOfTripsForGoingHome"`
	Walk_TotalNumberOfTrips                  int    `xml:"walk_TotalNumberOfTrips"`
	TotalNumberOfTrips                       int    `xml:"totalNumberOfTrips"`
}

func main() {
	// XMLファイルを読み込む
	xmlData, err := os.Open("sample1.xml")
	if err != nil {
		fmt.Println("Error opening XML file:", err)
		return
	}
	defer xmlData.Close()

	// XMLデータをデコード
	var dataset Dataset
	decoder := xml.NewDecoder(xmlData)
	if err := decoder.Decode(&dataset); err != nil {
		fmt.Println("Error decoding XML:", err)
		return
	}

	// CSVファイルにデータを書き込み
	csvFile, err := os.Create("output.csv")
	if err != nil {
		fmt.Println("Error creating CSV file:", err)
		return
	}
	defer csvFile.Close()

	csvWriter := csv.NewWriter(csvFile)
	defer csvWriter.Flush()

	// CSVヘッダを書き込み
	headers := []string{
		"ID", "UrbanArea", "SurveyYear", "ConcentratedOccurrence", "ZoneCode",
		"Railroad_NumberOfTripsForGoingToWork", "Railroad_NumberOfTripsForGoingToSchool", "Railroad_NumberOfFreeTrips",
		"Railroad_NumberOfBusinessTrips", "Railroad_NumberOfTripsForGoingHome", "Railroad_TotalNumberOfTrips",
		"Bus_NumberOfTripsForGoingToWork", "Bus_NumberOfTripsForGoingToSchool", "Bus_NumberOfFreeTrips",
		"Bus_NumberOfBusinessTrips", "Bus_NumberOfTripsForGoingHome", "Bus_TotalNumberOfTrips",
		"Automobile_NumberOfTripsForGoingToWork", "Automobile_NumberOfTripsForGoingToSchool", "Automobile_NumberOfFreeTrips",
		"Automobile_NumberOfBusinessTrips", "Automobile_NumberOfTripsForGoingHome", "Automobile_TotalNumberOfTrips",
		"Motorcycle_NumberOfTripsForGoingToWork", "Motorcycle_NumberOfTripsForGoingToSchool", "Motorcycle_NumberOfFreeTrips",
		"Motorcycle_NumberOfBusinessTrips", "Motorcycle_NumberOfTripsForGoingHome", "Motorcycle_TotalNumberOfTrips",
		"Walk_NumberOfTripsForGoingToWork", "Walk_NumberOfTripsForGoingToSchool", "Walk_NumberOfFreeTrips",
		"Walk_NumberOfBusinessTrips", "Walk_NumberOfTripsForGoingHome", "Walk_TotalNumberOfTrips",
		"TotalNumberOfTrips",
	}

	if err := csvWriter.Write(headers); err != nil {
		fmt.Println("Error writing CSV headers:", err)
		return
	}

	// データをCSVに書き込み
	//for _, person := range root.Persons {
	for _, item := range dataset.Items {

		// fmt.Println("pass1")
		// fmt.Println(item)

		//record := []string{item.ID, fmt.Sprintf("%d", item.UrbanArea), fmt.Sprintf("%d", item.SurveyYear), fmt.Sprintf("%d", item.ConcentratedOccurrence), fmt.Sprintf("%d", item.ZoneCode)}

		record := []string{
			item.ID,
			fmt.Sprintf("%d", item.UrbanArea),
			fmt.Sprintf("%d", item.SurveyYear),
			fmt.Sprintf("%d", item.ConcentratedOccurrence),
			fmt.Sprintf("%d", item.ZoneCode),
			fmt.Sprintf("%d", item.Railroad_NumberOfTripsForGoingToWork),
			fmt.Sprintf("%d", item.Railroad_NumberOfTripsForGoingToSchool),
			fmt.Sprintf("%d", item.Railroad_NumberOfFreeTrips),
			fmt.Sprintf("%d", item.Railroad_NumberOfBusinessTrips),
			fmt.Sprintf("%d", item.Railroad_NumberOfTripsForGoingHome),
			fmt.Sprintf("%d", item.Railroad_TotalNumberOfTrips),
			fmt.Sprintf("%d", item.Bus_NumberOfTripsForGoingToWork),
			fmt.Sprintf("%d", item.Bus_NumberOfTripsForGoingToSchool),
			fmt.Sprintf("%d", item.Bus_NumberOfFreeTrips),
			fmt.Sprintf("%d", item.Bus_NumberOfBusinessTrips),
			fmt.Sprintf("%d", item.Bus_NumberOfTripsForGoingHome),
			fmt.Sprintf("%d", item.Bus_TotalNumberOfTrips),
			fmt.Sprintf("%d", item.Automobile_NumberOfTripsForGoingToWork),
			fmt.Sprintf("%d", item.Automobile_NumberOfTripsForGoingToSchool),
			fmt.Sprintf("%d", item.Automobile_NumberOfFreeTrips),
			fmt.Sprintf("%d", item.Automobile_NumberOfBusinessTrips),
			fmt.Sprintf("%d", item.Automobile_NumberOfTripsForGoingHome),
			fmt.Sprintf("%d", item.Automobile_TotalNumberOfTrips),
			fmt.Sprintf("%d", item.Motorcycle_NumberOfTripsForGoingToWork),
			fmt.Sprintf("%d", item.Motorcycle_NumberOfTripsForGoingToSchool),
			fmt.Sprintf("%d", item.Motorcycle_NumberOfFreeTrips),
			fmt.Sprintf("%d", item.Motorcycle_NumberOfBusinessTrips),
			fmt.Sprintf("%d", item.Motorcycle_NumberOfTripsForGoingHome),
			fmt.Sprintf("%d", item.Motorcycle_TotalNumberOfTrips),
			fmt.Sprintf("%d", item.Walk_NumberOfTripsForGoingToWork),
			fmt.Sprintf("%d", item.Walk_NumberOfTripsForGoingToSchool),
			fmt.Sprintf("%d", item.Walk_NumberOfFreeTrips),
			fmt.Sprintf("%d", item.Walk_NumberOfBusinessTrips),
			fmt.Sprintf("%d", item.Walk_NumberOfTripsForGoingHome),
			fmt.Sprintf("%d", item.Walk_TotalNumberOfTrips),
			fmt.Sprintf("%d", item.TotalNumberOfTrips),
		}

		if err := csvWriter.Write(record); err != nil {
			fmt.Println("Error writing CSV record:", err)
			return
		}

	}

	fmt.Println("CSV file successfully created.")
}

 

2023,江端さんの技術メモ

マルチエージェントシミュレーションにおいて、エージェント間の相互作用を実現するためには、さまざまな方法が存在します。「模倣戦略」や「ペアワイズフェルミ法」以外の方法として以下のいくつかを考えることができます:

  1. ゲーム理論:
    • ナッシュ均衡やコアの概念を使用して、エージェント間の戦略的相互作用をモデル化する方法です。ゲーム理論を用いることで、競争や協力などの行動を表現できます。
  2. マーケットモデル:
    • エージェントがリソースや商品の交換を行う市場モデルを使用して、エージェント間の相互作用をシミュレートできます。価格設定や需要と供給の変動を考慮することができます。
  3. エージェントベースのモデリング:
    • エージェントが独自の行動ルールと目標を持つモデルを作成し、それらのエージェントが環境内で相互作用する方法です。エージェントの行動は、周囲のエージェントや環境に影響を与えます。
  4. 群集ダイナミクス:
    • エージェントが群れを形成し、群れ内での相互作用をモデル化する方法です。鳥の群れや魚の群れのような集団行動を研究するのに適しています。
  5. 進化アルゴリズム:
    • 遺伝的アルゴリズムや遺伝的プログラミングを使用して、エージェントの戦略や行動を進化させる方法です。最適な戦略を見つけるために遺伝子の操作を行います。

これらの方法は、異なる問題領域やシミュレーションの目的に応じて選択できます。具体的なシナリオや要件に合わせて、最適な方法を選んでください。

2023,江端さんの技術メモ

で「エクスポートをクリック」 → map.osmがダウンロードされる

JOSMで表示する

フィルタを選択

Ctrl-aで選択

「編集」→「座標をコピー」で、座標コピー

ここで、エディター等に(test.csvなどとして)コピーする。

【QGIS】緯度・経度をもつCSVデータを読み込み、地図に表示する

を参照して、test.csvをQGISで表示する。

このように座標が取得できているのが確認できました。

根岸線を削除する場合、JOSMで場所を指定して丹念に削除していく

で、この座標さえ取れれば、

Go言語で、BusRouteの点で繋がれた線とみなして、trackingDataの各点から、その線からの最短距離を算出するようなプログラムの改造をお願いできますか?

が使えるようになる。

ダメ。これで取得した座標は、出現順番がバラバラになっているので、補正処理が必要となる。
今回の場合、南北方向にのみ伸びているので、緯度で並べかえれば良いが、そうでない場合は、別途処理が必要となると思うが(今回は必要ないので、これは省略)

この後であれば、上記のプログラムが使えるはず。

 

ちなみに、
osmosis --read-xml map.osm --tf accept-nodes railway=* --write-xml railway_nodes.osm
osmosis --read-xml map.osm --tf accept-relations railway=* --used-way --write-xml railway_data.osm

は、上手く動かせませんでした。

 

 

2023,江端さんの技術メモ

データベース(DB)のデータのインポートを開始して、すでに3時間が経過しようとしています。このインポートが、これまで作ってきたDBのテーブル全部を吹き飛ばすことがなかろうかと、とても心配しています。

User

dockerを使ってPostgresqlでDBを作っています。特にパラメタのセットとかはしていません。このような場合、DB容量の上限値をざっくりとで結構ですので、教えて下さい。

ChatGPT
Dockerコンテナ内でPostgreSQLをデフォルトの設定で実行する場合、データベースのサイズに特別な制限は設定されません。制限はDockerコンテナ自体のディスク容量に依存し、PostgreSQL自体は通常制限を設けません。

Dockerコンテナのディスク容量は、ホストマシンのディスク容量に依存し、Dockerコンテナが実行されているディスク領域によって決まります。したがって、デフォルトの設定であれば、PostgreSQLデータベースの容量制限はホストマシンのディスク容量に影響されます。

したがって、特定の容量制限を設定していない場合、PostgreSQLデータベースの上限容量は、ホストマシンのディスク容量に依存し、通常は制約を受けません。ホストマシンのディスク容量に制約がある場合、それが制限となります。

PostgreSQL自体にはデータベースサイズの制約を設定する設定がありますが、通常はデフォルトの設定で制限を設けることはありません。したがって、Dockerコンテナ内で特別な設定を行っていない場合、PostgreSQLデータベースのサイズは通常はホストマシンのディスク容量によって制約されます。


このような回答を得て、先ずは安堵していますが、それでもやっぱり怖いです。
Dockerコンテナの丸ごとバックアップを試みるべきでしょうか。
以前やったときは、データ本体がスッポリ抜けていたような、嫌な記憶があります。