2025,江端さんの忘備録

Web画面に『ここにボタンを一つ追加して』というセリフを言う平気で言う人間 ―― これだけで、その人間のプログラムやシステムに関する見識の無さが露呈しています。

A person who says, “Add a button here,” on a web page without batting an eyelid, reveals the person's lack of insight into programming and systems.

こういう人を責める訳ではないのですが、

I don't blame people like this, but I think many people are unaware that

この追加されるボタン一つが、

This additional button is

■ユーザインターフェース(UI)の追加だけでなく、

■ in addition to adding user interface (UI) elements,

■プログラムコードに大変更を与えて、

■ making major changes to program code,

■それがデータベースの項目に影響し、

■ and having that affect database items,

■最悪の場合、それがトランザクションや排他処理に及ぶまでの、

■ in the worst case, it can extend to transactions and exclusive processing,

膨大な設計変更に及ぶ ―― ということを知らない人は多いと思います。

leading to a huge amount of design changes.

-----

多分、『ここにボタンを一つ追加して』と安易に言う人は、立食い蕎麦で『あ、それと、天麩羅と生卵を追加して』というノリなのでしょう。

Perhaps the people who say “Add a button here” so quickly are the same people who say “Oh, and add tempura and raw egg” when eating at a standing-only soba noodle bar.

しかし、ITシステムにおける、『ここにボタンを一つ追加して』とは、その蕎麦屋の『店舗全体を設計しなおす規模になる』というレベルの大作業になることは、そんなに珍しいことではありません。

However, in IT systems, it is not that unusual for a request like “add a button here” to be a primary task on the scale of “re-designing the entire store” for that soba shop

だから、『開発開始後の仕様変更』は、原則、許されることではないのです。

Therefore, 'specification changes after development has started' are not permitted in principle.

-----

しかし、そういうことを平気でやる発注者って、結構多いです ―― 金も出さずに、納期も変えずに。

However, quite a few clients do this without a second thought - without paying or changing the delivery date.

でも、システム開発者の担当者が、

However, it is essential to remember that the system developer in charge is probably thinking

―― このシステム音痴の無能野郎!

"“You incompetent system-illiterate bastard!”"

と、心の中で罵っていることは、覚えておいた方が良いでしょう。

in their heart.

受注側は、お金を貰う弱みがあり、最終的に、それに応じることにはなります(または、裁判になります)が  ―― しかし、そこには『開発者が、発注者に対して"憎悪"が発生している』ということは覚えておいた方がいいです。

The weakness is that the recipient will be paid, and ultimately there is no choice but to obey (or take it to court), but what must not be forgotten is that the recipient is “hated” by the developer.

義務教育のプログラミング教育に意義があるとすれば、プログラミングできるようになることではなく、この「システム音痴の無能野郎」が、一人でも減ること、と、私は思っています。

There is no significance to programming education as part of compulsory education; it is not so much that people should be able to program, but I think the number of “system-illiterate incompetents” should be reduced.

-----

私も昨夜、プログラムの改修作業をしていました。

I was also working on program modifications last night.

私の見積り時間は"10分間"でしたが、改修完了に掛った時間は6時間でした。予定通りの稼動を確認したのは、今朝です。

My estimate was for 10 minutes, but it took 6 hours to complete the repairs. I confirmed that it was working as planned this morning.

自作プログラムでも、このザマです。

Even with my program, it's like this.

ITシステムというのを、ファストフードのトッピングのように考えているとしたら、それは無知を超えて、社会悪と断じて良いものです。

If you think of IT systems as being like toppings on fast food, then that's not just ignorance; it's a social evil.

―― 考えすぎじゃね?

2025,江端さんの技術メモ

Go言語を使ったマルチエージェントシミュレーションが、他の言語よりもメリットがある点とデメリットがある点について論じて下さい

一つ一つが、大変納得した内容だったので、私のメモ用に記録しておきます。

 

Go言語を用いたマルチエージェントシミュレーション(MAS)の利点と欠点について、他の言語(C++, Python, Juliaなど)と比較しながら論じる。

1. Go言語を使うメリット

(1) 並行処理の容易さ

Goはgoroutineを用いた並行処理が特徴であり、エージェントごとにgoroutineを割り当てることで効率的な並列処理が可能である。他の言語ではスレッド管理(C++のstd::threadやPythonのthreading)が必要になるが、Goではシンプルな記述で実装できる。

例:

func agent(id int) {
    for {
        fmt.Printf("Agent %d is moving...\n", id)
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    for i := 0; i < 10; i++ {
        go agent(i) // 各エージェントをgoroutineで実行
    }
    select {} // メインスレッドを終了させない
}

このようにGoの並行処理はシンプルかつ軽量であり、大量のエージェントを扱うシミュレーションに適している。


(2) シンプルなコードとメンテナンス性

Goはシンプルな文法強力な標準ライブラリを持つため、コードの可読性が高く、開発者間での共有が容易である。
C++ではテンプレートやマルチスレッド処理が複雑になりやすく、PythonではGIL(Global Interpreter Lock)の影響で並列処理が制限される。一方、GoはGILの問題がなく、コードの記述量も比較的少ないため、長期的な開発に向いている。


(3) 高速なコンパイルと実行

Goはコンパイルが非常に速く、バイナリを直接実行できるため、デバッグやテストのサイクルを短縮できる。C++のように長時間のコンパイルが不要で、Pythonのようなインタープリタ型の遅延もない。


(4) クロスプラットフォームの容易さ

Goは静的バイナリを生成できるため、Windows, Linux, macOS などの異なる環境での実行が容易である。C++ではコンパイル時にライブラリ依存の問題が生じやすく、Pythonでは環境設定(仮想環境やパッケージ管理)が面倒になりがちだが、Goでは1つのバイナリで解決できる。


(5) クラウドやWebとの親和性

GoはもともとGoogleが開発した言語であり、クラウド環境(GCP, AWS)やWebとの親和性が高い。
シミュレーション結果をWeb API経由でリアルタイム表示したり、分散処理の一部をクラウド上で実行する際に、Goの標準ライブラリだけでHTTPサーバを簡単に実装できるのは大きなメリット。


2. Go言語を使うデメリット

(1) 高速計算ライブラリが少ない

PythonやC++には、最適化された数値計算ライブラリ(NumPy, SciPy, Eigen, OpenMPなど)が豊富にあるのに対し、Goは数値計算や線形代数のライブラリが少ない
そのため、大量の行列演算や物理シミュレーションを行う場合、Go単体では計算効率が劣る可能性がある。

対策:

  • Goで数値計算を行う場合は、gonum ライブラリを使用する。
  • 必要に応じて、GoからC/C++(BLAS, LAPACK)を呼び出す。

(2) GPUサポートが弱い

C++はCUDAやOpenCLを利用してGPUによる並列計算が可能であり、PythonもTensorFlowやCuPyを通じてGPUを活用できる。しかし、Goは公式にはGPUを直接サポートしていないため、CUDAを使う場合はCGO経由でC++のライブラリを呼び出す必要がある

対策:

  • gorgonia(Go向けのニューラルネットワークライブラリ)を利用すると、一部のGPU計算が可能。
  • CUDA/OpenCLを直接利用したい場合は、GoからC++のラッパーを呼び出す。

(3) 研究事例が少ない

PythonやC++は、数多くの学術論文や研究事例があり、豊富なサンプルコードが存在する。一方で、Goは学術分野ではあまり使われておらず、論文や研究事例が少ない
特に、MAS関連のライブラリやフレームワークが未成熟なため、開発者が独自に実装する必要がある。

対策:

  • MASの一般的なアルゴリズム(Boidモデル、Cellular Automatonなど)をGoで実装する。
  • 他言語のライブラリと組み合わせて使用する。

(4) ガベージコレクションの影響

Goのガベージコレクション(GC)は自動的にメモリを管理するが、大規模なシミュレーションではGCの影響で予期しないタイミングで一時的な遅延が発生する可能性がある。
C++のように明示的なメモリ管理ができないため、リアルタイム性を求めるシミュレーションでは不利になることがある。

対策:

  • メモリ割り当てを最小限に抑える設計を行う(オブジェクトの再利用)。
  • sync.Pool を活用してメモリ管理のオーバーヘッドを減らす。

3. 結論

Go言語を使ったMASは、並行処理の容易さ・コードのシンプルさ・クラウドとの親和性に優れており、大規模エージェントシミュレーションの実装がしやすい
しかし、GPUサポートの弱さ・計算ライブラリの不足・研究事例の少なさといった課題もあり、特に高度な数値計算が必要なシミュレーションではPythonやC++の方が適している

Go言語が適しているケース:

  • 大規模なエージェント数をgoroutineで管理
  • ネットワーク・クラウド連携が必要
  • シンプルな設計を重視

PythonやC++の方が適しているケース:

  • 高度な数値計算(線形代数、最適化)
  • GPUを活用したシミュレーション
  • 既存のライブラリや研究事例を活用

最適なアプローチ:
Go単体でMASを実装するよりも、計算部分をPython/C++で処理し、Goは並列制御やネットワーク管理に使うというハイブリッドアプローチが有効となる。


昨日、

PrumeMobileを使った人流の見える化

について記載したんだけど、これ簡単に言うと『goroutineを止めて、サブルーチンにした』というものです。

300万のエージェントが、メインルーチンの情報変更に上手く連動しなくなると、"goroutineの自己破壊命令が届かない"という問題がボロボロでてきたからです。

まあ、それでも、『数十万人分、361万行の移動データを、全部表示して正常終了した』というGo言語の凄さには、相変らず感心しているんですけどね(昨夜、PC回しながら寝たのですが、今朝、全部のオブジェクトが消えて、正常終了していました)。

2025,江端さんの技術メモ

起動方法
$go run server22-1.go

http://localhost:8080

$go run pm_proxy_single_socket.go

 

// server22-1.go

/*
このプログラムは、WebSocket を利用したリアルタイム位置情報サーバーである。
- クライアントから送信された位置情報を受信し、処理後にレスポンスを返す。
- 位置情報はチャネルを介して他のクライアントと共有される。
- `sync.Mutex` を使用してスレッド安全な処理を実現。
- WebSocket の接続エラー時には適切にログを出力し、安定した通信を確保。
- HTML を提供し、ブラウザ上で WebSocket 通信を確認可能。
*/
package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"sync"

	"github.com/gorilla/websocket"
)

// GetLoc GetLoc
type GetLoc struct {
	ID  int     `json:"id"`
	Lat float64 `json:"lat"`
	Lng float64 `json:"lng"`
	//Address string  `json:"address"`
}

// var addr = flag.String("addr", "localhost:8080", "http service address")
var addr = flag.String("addr", "0.0.0.0:8080", "http service address") // テスト

var upgrader = websocket.Upgrader{} // use default options

var chan2_1 = make(chan GetLoc)

var maxid = 0

var mutex sync.Mutex

func echo2(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	//mutex := new(sync.Mutex)

	for {
		//mt, message, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)
		//_, _, err := c.ReadMessage() // クライアントからのメッセージの受信(mtはクライアント識別子)

		//mutex.Lock()  // ここに置くとデッドロックしてしまう

		gl := new(GetLoc)

		err := c.ReadJSON(&gl) // クライアントからのメッセージの受信

		mutex.Lock()

		// 原因不明の対処処理
		if gl.ID == 0 && gl.Lat < 0.01 && gl.Lng < 0.01 {
			mutex.Unlock()
			break
		} else if gl.ID < -1 { // 受理できないメッセージとして返信する
			//条件分岐 (変なIDが付与されているメッセージは潰す)
			//if (gl.ID > maxid) || (gl.ID < -1) { // 受理できないメッセージとして返信する

			gl.ID = -1
			gl.Lat = -999
			gl.Lng = -999
			err2 := c.WriteJSON(gl)
			if err2 != nil {
				log.Println("write1:", err2)
				mutex.Unlock()
				break
			}
		} else { // それ以外は転送する
			/*
				log.Printf("echo2 after c.WriteJSON(gl) ID:%d", gl.ID)
				log.Printf("echo2 after c.WriteJSON(gl) Lat:%f", gl.Lat)
				log.Printf("echo2 after c.WriteJSON(gl) Lng:%f", gl.Lng)
			*/
			if err != nil {
				log.Println("read:", err)
				mutex.Unlock()
				break
			}
			//fmt.Printf("echo2 before chan2_1 <- *gl\n")
			chan2_1 <- *gl
			//fmt.Printf("echo2 after chan2_1 <- *gl\n")

			//で、ここで受けとる
			//gl2 := new(GetLoc)
			//fmt.Printf("echo2 before gl2 := <-chan2_1\n")
			gl2 := <-chan2_1
			maxid = gl2.ID // ID最大値の更新
			/*
				log.Printf("echo2 after gl2 := <-chan2_1 ID:%d", gl2.ID)
				log.Printf("echo2 after gl2 := <-chan2_1 Lat:%f", gl2.Lat)
				log.Printf("echo2 after gl2 := <-chan2_1 Lng:%f", gl2.Lng)
			*/
			//fmt.Printf("echo2 before err2 := c.WriteJSON(gl2)\n")
			err2 := c.WriteJSON(gl2)
			//fmt.Printf("echo2 after err2 := c.WriteJSON(gl2)\n")
			if err2 != nil {
				log.Println("write2:", err2)
				mutex.Unlock()
				break
			}
			//fmt.Printf("end of echo2\n")

		}

		mutex.Unlock()
	}
}

func echo(w http.ResponseWriter, r *http.Request) {

	c, err := upgrader.Upgrade(w, r, nil) // cはサーバのコネクション
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	/*	ここでロックして待つ */

	for {

		//fmt.Printf("echo before gl := <-chan2_1\n")
		gl := <-chan2_1
		//fmt.Printf("echo after gl := <-chan2_1\n")

		//fmt.Printf("echo before err = c.WriteJSON(gl) gl2.id = %d\n", gl.ID)
		//fmt.Printf("echo before err = c.WriteJSON(gl) gl2.lat = %f\n", gl.Lat)
		//fmt.Printf("echo before err = c.WriteJSON(gl) gl2.lng= %f\n", gl.Lng)
		err = c.WriteJSON(gl)
		if err != nil {
			log.Println("WriteJSON1:", err)
		}
		//fmt.Printf("echo after err = c.WriteJSON(gl)\n")

		//fmt.Printf("echo before err = c.RreadJSON(gl)\n")
		gl2 := new(GetLoc)
		err2 := c.ReadJSON(&gl2)
		//fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.id = %d\n", gl2.ID)
		//fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.lat = %f\n", gl2.Lat)
		//fmt.Printf("echo after err = c.ReadJSON(&gl2) gl2.lng= %f\n", gl2.Lng)
		if err2 != nil {
			log.Println("ReadJSON:", err2)
		}
		// ここからチャネルで返す
		//fmt.Printf("echo before chan2_1 <- *gl2 gl2.id = %d\n", gl2.ID)
		//fmt.Printf("echo before chan2_1 <- *gl2 gl2.lat = %f\n", gl2.Lat)
		//fmt.Printf("echo before chan2_1 <- *gl2 gl2.lng = %f\n", gl2.Lng)
		chan2_1 <- *gl2
		//fmt.Printf("echo after chan2_1 <- *gl2\n")
		//fmt.Printf("end of echo\n")
	}

}

func home(w http.ResponseWriter, r *http.Request) {
	homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
}

func smartphone(w http.ResponseWriter, r *http.Request) {
	smartphoneTemplate.Execute(w, "ws://"+r.Host+"/echo2")
}

func main() {
	flag.Parse()
	log.SetFlags(0)

	http.HandleFunc("/echo2", echo2)           // echo関数を登録 (サーバとして必要)
	http.HandleFunc("/echo", echo)             // echo関数を登録 (サーバとして必要)
	http.HandleFunc("/", home)                 // home関数を登録
	http.HandleFunc("/smartphone", smartphone) // smartphone関数を登録
	log.Fatal(http.ListenAndServe(*addr, nil)) // localhost:8080で起動をセット
}

var smartphoneTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script> 

function obj(id, lat, lng){
	this.id = id;
	this.lat = lat;
	this.lng = lng;
}

function random(min, max){
	return  Math.random()*(max-min) + min;
}

// var personal_id;

var lat = 35.654543;
var lng = 139.795534;  

window.addEventListener("load", function(evt) {
    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;
    var print = function(message) {
        var d = document.createElement("div");
        d.textContent = message;
        output.appendChild(d);
	};

	var personal_id = 0;

	
	///// 起動時のボタン
	// disabled属性を削除
	document.getElementById("open").removeAttribute("disabled");
	document.getElementById("open").style.color = "black";

	// disabled属性を設定 (closeボタンを非活性化)
	document.getElementById("close").setAttribute("disabled", true);
	document.getElementById("close").style.color = "White";	

	// disabled属性を設定 (sendボタンを非活性化)
	document.getElementById("send").setAttribute("disabled", true);
	document.getElementById("send").style.color = "White";	


		
	document.getElementById("open").onclick = function(evt) {
		console.log("document.getElementById open");

		// disabled属性を設定 (openボタンを非活性化)
		document.getElementById("open").setAttribute("disabled", true);
		document.getElementById("open").style.color = "White";		

		// disabled属性を削除
		document.getElementById("send").removeAttribute("disabled");
		document.getElementById("send").style.color = "black";	

		// disabled属性を削除
		document.getElementById("close").removeAttribute("disabled");
		document.getElementById("close").style.color = "black";	

		////////// 削除2
		// ws = new WebSocket("{{.}}");
		////////// 削除2終り


		////////// 削除1
		//var send_obj = new obj(0, 35.654543,139.795534);  // 最初は"0"でエントリ

		//console.log("open:send_obj");	
		//console.log(send_obj.id);	
		//console.log(send_obj.lat);
		//console.log(send_obj.lng);		

		//var json_obj = JSON.stringify(send_obj);
		//ws.send(json_obj);
		/////////// 削除1終り


        if (ws) {
            return false;
        }
		
		
		////////// 追加2
		ws = new WebSocket("{{.}}");
		////////// 追加2終り

		
        ws.onopen = function(evt) {
			print("OPEN");
		
			//ws = new WebSocket("{{.}}");
			
			////////// 追加1			
			var send_obj = new obj(0, 35.654543,139.795534);  // 最初は"0"でエントリ

			console.log("open:send_obj");	
			console.log(send_obj.id);	
			console.log(send_obj.lat);
			console.log(send_obj.lng);		

			var json_obj = JSON.stringify(send_obj);
			ws.send(json_obj);
			/////////// 追加1終り

		}
		
        ws.onclose = function(evt) {

			print("CLOSE");
            ws = null;
        }

		ws.onmessage = function(evt) {  // 受信したメッセージはここに飛んでくる
			print("RESPONSE: " + evt.data);  // jsonメッセージの内容を表示
			// データをJSON形式に変更
			var obj = JSON.parse(evt.data);

			personal_id = obj.id; // IDの取得(何回も取る必要はないが)
			console.log("personal_id");			
			console.log(personal_id);

			
			if ((Math.abs(obj.lat) > 90.0) || (Math.abs(obj.lng) > 180.0)){ // 異常な座標が入った場合は、マーカーを消去する
				console.log("before ws.close()");
				ws.close();
				console.log("after ws.close()");
			}
		}
		
        ws.onerror = function(evt) {
            print("ERROR: " + evt.data);
        }
        return false;
    };
	
	document.getElementById("send").onclick = function(evt) {

		console.log("document.getElementById send");

		// disabled属性を設定 (openボタンを非活性化)
		document.getElementById("open").setAttribute("disabled", true);
		document.getElementById("open").style.color = "White";	
	
		// disabled属性を削除
		document.getElementById("send").removeAttribute("disabled");
		document.getElementById("send").style.color = "black";	

		// disabled属性を削除
		document.getElementById("close").removeAttribute("disabled");
		document.getElementById("close").style.color = "black";	
	
		if (!ws) {
			console.log("return false send");
			return false;			
		}

		lat += random(0.5, -0.5) * 0.00001 * 10 * 5;
		lng += random(0.5, -0.5) * 0.00002 * 10 * 5

		
		//var send_obj = new obj(personal_id, 35.654543,139.795534);  // idでエントリ
		var send_obj = new obj(personal_id, lat, lng);  // idでエントリ

		console.log("send:send_obj");	
		console.log(send_obj.id);	
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);		

		/*
        print("SEND: " + input.value);
        ws.send(input.value);
		return false;
		*/

		return false;	
    };

	document.getElementById("close").onclick = function(evt) {
		console.log(" document.getElementById close");

		// disabled属性を削除
		document.getElementById("open").removeAttribute("disabled");
		document.getElementById("open").style.color = "black";

		// disabled属性を設定 (closeボタンを非活性化)
		document.getElementById("close").setAttribute("disabled", true);
		document.getElementById("close").style.color = "White";	

		// disabled属性を設定 (sendボタンを非活性化)
		document.getElementById("send").setAttribute("disabled", true);
		document.getElementById("send").style.color = "White";			


        if (!ws) {
            return false;
		}
	
		var send_obj = new obj(personal_id, 999.9, 999.9);  // 最初は"0"でエントリ

		console.log("close:send_obj");
		console.log(send_obj.id);		
		console.log(send_obj.lat);
		console.log(send_obj.lng);		

		var json_obj = JSON.stringify(send_obj);
		ws.send(json_obj);

        //ws.close();  // これはws.onmessageの方で実施
        return false;
    };
});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server, 
"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<!-- <p><input id="input" type="text" value="Hello world!"> -->
<button id="send">Send</button>
<button id="close">Close</button>
</form>
</td><td valign="top" width="50%">
<div id="output"></div>
</td></tr></table>
</body>
</html>
`))

var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>PruneMobile</title>

	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.css"/>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.js"></script>

	<script src="http://kobore.net/PruneCluster.js"></script>           <!-- これ、いずれローカルホストから取れるように換える -->
	<link rel="stylesheet" href="http://kobore.net/examples.css"/>      <!-- これも、いずれローカルホストから取れるように換える -->

	<!-- goのテンプレートのローカルって、どこになるんだろう? -->

</head>
<body>
<div id="map"></div>

<script>

	ws = new WebSocket("{{.}}"); // websocketの確立

	/*
	var print = function(message) {
		var d = document.createElement("div");
		d.textContent = message;
		output.appendChild(d);
	};
	*/

	// 引数にはミリ秒を指定。(例:5秒の場合は5000)
	function sleep(a){
  		var dt1 = new Date().getTime();
  		var dt2 = new Date().getTime();
  		while (dt2 < dt1 + a){
			dt2 = new Date().getTime();
		}
  		return;
	}

    var map = L.map("map", {
        attributionControl: false,
        zoomControl: false
	}).setView(new L.LatLng(35.36716428833585, 139.62724520774287), 16); // 富岡		
	//}).setView(new L.LatLng(33.58973407765046, 130.41048227121925), 16); // 中州
    //}).setView(new L.LatLng(35.654543, 139.795534), 18); 豊洲
    // }).setView(new L.LatLng(35.598563, 139.475528), 18); 広袴

    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
        detectRetina: true,
        maxNativeZoom: 18
    }).addTo(map);

    var leafletView = new PruneClusterForLeaflet(1,1);  // (120,20)がデフォルト

	ws.onopen = function (event) {
	}

	var markers = [];

	//var helicopterIcon = L.icon({ iconUrl: 'http://sintef-9012.github.io/PruneCluster/examples/helicopter.png', iconSize: [48, 48] });
    //var airplaneIcon = L.icon({ iconUrl: 'http://sintef-9012.github.io/PruneCluster/examples/airplane.png', iconSize: [48, 48] });

	// 受信すると、勝手にここに飛んでくる
	ws.onmessage = function (event) {
		// データをJSON形式に変更
		var obj = JSON.parse(event.data);

		console.log("233");	
		console.log(obj.id);
		console.log(obj.lat);						
		console.log(obj.lng);	

		if (obj.id == 0){  // idが未登録の場合
			console.log("obj.id == 0")
			// データをマーカーとして登録
			var marker = new PruneCluster.Marker(obj.lat, obj.lng);

			// 参考資料  http://embed.plnkr.co/WmtpkEqSDJFuFeuiYP54/
			//var marker = new PruneCluster.Marker(obj.lat, obj.lng, {
			//	//popup: "Bell 206 " + i,
			//	icon: helicopterIcon
			//});


			console.log(marker.hashCode);		
			markers.push(marker);
	
			leafletView.RegisterMarker(marker);
	
			console.log(markers);
			console.log(markers.length)

			obj.id = marker.hashCode;
			//ws.send(marker.hashCode); // テキスト送信
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);			
		} else if ((Math.abs(obj.lat) > 90.0) || (Math.abs(obj.lng) > 180.0)){ // 異常な座標が入った場合は、マーカーを消去する
			console.log("Math.abs(obj.lat) > 180.0)")
			for (let i = 0; i < markers.length; ++i) {
				if (obj.id == markers[i].hashCode){
					console.log(i)
					console.log(obj.id)										
					console.log("obj.id == markers[i].hashCode")

					//leafletView.RemoveMarkers(markers[obj.id]);  // これでは消えてくれません
					// 1つのマーカーを消すのに、面倒でも以下の2行が必要
					var deleteList = markers.splice(i, 1);					
					leafletView.RemoveMarkers(deleteList);

					// 以下失敗例リスト
					//leafletView.RemoveMarkers(markers[i].hashCode);  //これはダメ
					//leafletView.RemoveMarkers(markers[obj.id],'item');
					//leafletView.ProcessView(); // 試しに入れてみる
					//leafletView.RemoveMarkers(markers[i-1]);
					//leafletView.RemoveMarkers(markers);					
					break;
				}
			}
			obj.lat = 91.0;
			obj.lng = 181.0;
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);				
		} else {
			// 位置情報更新
			console.log("else")
			for (let i = 0; i < markers.length; ++i) {
				if (obj.id == markers[i].hashCode){
					var ll = markers[i].position;
					ll.lat = obj.lat;
					ll.lng = obj.lng;
					break;
				}
			}
			var json_obj = JSON.stringify(obj);
			ws.send(json_obj);	
		}
	}

	// 位置情報の更新
    window.setInterval(function () {
        leafletView.ProcessView();  // 変更が行われたときに呼び出されれなければならない
	}, 1000);

	// サーバを止めると、ここに飛んでくる
	ws.onclose = function(event) {
		//print("CLOSE");
		ws = null;
	}


    map.addLayer(leafletView);
</script>



</body>
</html>
`))
// pm_proxy5_single_socket.go

/*
	このプログラムは、CSVファイルに記載された順番にエージェントの位置情報を読み取り、
	WebSocket を介してサーバーへ送信・更新する。

	サーバへ転送するプログラムは、server22-1.go

	- WebSocket 切断時に自動で再接続(最大5回リトライ)
	- エージェントが移動した場合のみサーバーへ通知
	- `sync.Mutex` を使用してスレッド安全な処理を実現
	- 位置情報が 999.0 以上の場合、エージェントを削除


	csv情報のサンプル (IDと緯度経度のみ使っている

	50044035447,139.629538,35.365357,00:00:00,WALK
	50044035447,139.629430,35.365151,00:00:30,WALK
	50044035447,139.629321,35.364945,00:01:00,WALK
	50044035447,139.629213,35.364738,00:01:30,WALK
	50044035447,139.629104,35.364532,00:02:00,WALK
	50044035447,139.628996,35.364325,00:02:30,WALK
	50044035447,139.628888,35.364119,00:03:00,WALK
	50044035447,139.628787,35.363937,00:03:30,WALK
	50044035447,139.628742,35.364159,00:04:00,WALK
	50044035447,139.628699,35.364375,00:04:30,WALK
	50044035447,139.628654,35.364592,00:05:00,WALK
	50044035447,139.628533,35.364724,00:05:30,WALK
	50044035447,139.628261,35.364691,00:06:00,WALK
	50044035447,139.627989,35.364658,00:06:30,WALK
	50044035447,139.627716,35.364625,00:07:00,WALK
	50044035447,139.627680,35.364620,00:07:30,WALK
	50044035447,999.9,999.9,00:08:00,WALK

	(50044035447, 999.9, 999.9, 00:08:00, WALK) でエージェントの移動が終了し、サーバからアイコンが消滅する

*/

package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"log"
	"math"
	"net/url"
	"os"
	"strconv"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

const (
	TopLeftLat     = 35.37574882601201
	TopLeftLon     = 139.61403393574466
	BottomRightLat = 35.36163108058289
	BottomRightLon = 139.6297897196359
)

type GetLoc struct {
	ID  int     `json:"id"`
	Lat float64 `json:"lat"`
	Lng float64 `json:"lng"`
}

type unmTbl struct {
	uniName string
	objType string
	simNum  int
	pmNum   int
	lon     float64
	lat     float64
}

var list = make([]unmTbl, 0)
var addr = flag.String("addr", "0.0.0.0:8080", "http service address")

var mutex sync.Mutex

func connectWebSocket() (*websocket.Conn, error) {
	u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo2"}

	for i := 0; i < 5; i++ {
		c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
		if err == nil {
			log.Println("Reconnected to WebSocket successfully.")
			return c, nil
		}
		log.Println("WebSocket reconnection attempt failed:", err)
		time.Sleep(2 * time.Second)
	}
	return nil, fmt.Errorf("failed to reconnect WebSocket after multiple attempts")
}

func main() {
	file, err := os.Open("agent_track_2018_101_end_and_order.csv")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	fmt.Println("Opened testtest.csv")
	reader := csv.NewReader(file)
	var line []string

	flag.Parse()
	log.SetFlags(0)

	c, err := connectWebSocket()
	if err != nil {
		log.Fatal("WebSocket connection failed:", err)
	}
	defer c.Close()

	for {
		time.Sleep(time.Millisecond * 10)

		line, err = reader.Read()
		if err != nil {
			break
		}

		uniName := line[0]
		objType := line[4]
		lon, _ := strconv.ParseFloat(line[1], 64)
		lat, _ := strconv.ParseFloat(line[2], 64)

		flag := 0

		for i := range list {
			if list[i].uniName == uniName {
				old_lat := list[i].lat
				old_lon := list[i].lon

				list[i].lon = lon
				list[i].lat = lat

				if math.Abs(list[i].lat-old_lat) > 0.000000001 || math.Abs(list[i].lon-old_lon) > 0.000000001 {
					gl := GetLoc{ID: list[i].pmNum, Lat: list[i].lat, Lng: list[i].lon}

					mutex.Lock()
					err = c.WriteJSON(gl)
					if err != nil {
						log.Println("write2 error:", err)
						mutex.Unlock() // **ロック解除**
						c.Close()
						c, err = connectWebSocket()
						if err != nil {
							log.Println("WebSocket reconnection failed:", err)
							return
						}
						continue
					}

					gl3 := new(GetLoc)
					err = c.ReadJSON(gl3)
					if err != nil {
						log.Println("read error:", err)
						mutex.Unlock() // **ロック解除**
						c.Close()
						c, err = connectWebSocket()
						if err != nil {
							log.Println("WebSocket reconnection failed:", err)
							return
						}
						continue
					}
					mutex.Unlock()

					println("move Object!")

					if list[i].lat > 999.0 || list[i].lon > 999.0 {
						list = append(list[:i], list[i+1:]...)
						println("-----------------------------------------------------------------> delete Object!")
					}
				}
				flag = 1
				break
			}
		}

		if flag == 0 {
			uniNum := len(list)
			ut := unmTbl{uniName: uniName, objType: objType, simNum: uniNum, lat: lat, lon: lon}

			gl := new(GetLoc)
			gl.ID = 0
			gl.Lat = ut.lat
			gl.Lng = ut.lon

			mutex.Lock()
			err := c.WriteJSON(gl)
			if err != nil {
				log.Println("write1 error:", err)
				mutex.Unlock() // **ロック解除**
				c.Close()
				c, err = connectWebSocket()
				if err != nil {
					log.Println("WebSocket reconnection failed:", err)
					return
				}
				continue
			}

			gl2 := new(GetLoc)
			err = c.ReadJSON(gl2)
			if err != nil {
				log.Println("read error:", err)
				mutex.Unlock() // **ロック解除**
				c.Close()
				c, err = connectWebSocket()
				if err != nil {
					log.Println("WebSocket reconnection failed:", err)
					return
				}
				continue
			}
			mutex.Unlock()

			ut.pmNum = gl2.ID
			list = append(list, ut)
			println("------------>generate Object!")
		}
	}
}

 

2025,江端さんの忘備録

VSCode(Visual Studio Code)は、Microsoftが開発した無料のオープンソースのコードエディタです。軽量でありながら高機能で、多くのプログラミング言語に対応しています。

VSCode (Visual Studio Code) is a free, open-source code editor developed by Microsoft. It is lightweight yet highly functional and supports many programming languages.

先日、VSCodeの拡張機能をアドインしたら、私のGo言語プログラムが全く動かなくなりました。

The other day, my Go program stopped working when I added an extension to VSCode.

このPCは、私の業務に関わるプログラムのほぼ全部を担当しているマシンなので、大袈裟ではなく「私の半分が殺された」といっても良い状態です。

This PC is the machine that is in charge of almost all of the programs related to my work, so it's not an exaggeration to say that “half of me has been killed.”

# 「人生の半分を損している」というレベルとは違います。

# This is not the same as “losing half of your life.”

ただ、経験的に、こういう時に慌てて色々なことを試みると、プログラム開発環境どころか、PCシステムそのものを回復不可能なまでに破壊する、ということを、私は良く知っています(というか、これまで壊したシステムの数は、3桁いっていると思います)。

However, from experience, I know that if you try various things in a panic in a situation like this, you can destroy the PC system itself beyond repair, not to mention the program development environment (or rather, I think the number of systems I've destroyed is in the triple digits).

-----

という訳で、動かなくなったGo言語環境を復旧する為にChatGPTの支援を受けながら、作業をしていました。

So, I was working to restore the Go language environment that had stopped working with the help of ChatGPT.

Go言語を再インストールして実行したら、『「go1.23.4.windows-amd64」ではダメだ。「go1.23.2.windows-amd64」をインストールしろ』、と指示されて、リビジョン番号の違うバイナリをダウンロードして、対応しました。

When I reinstalled Go and ran it, I was told to download a binary with a different revision number, which I did.

結果として、現在、プログラム環境は回復したように見えましたので、それはそれで良かったのですが、

As a result, the program environment now appeared to have recovered, so that was good, but

―― バージョンの枝番まで細かく命令されて、それに従っている私って・・・

"I'm being ordered to follow the version branch number in detail..."

という気持ちになりました。

I felt that way.

-----

まあ、私は、おそらくは300以上(1000を超えるかもしれない)自作プログラムを人質に取られているようなものですので、環境の命じる通りに作業するしかありません。

Well, I'm probably a hostage with over 300 (maybe over 1000) self-made programs, so I have no choice but to work as the environment commands.

しかし「VSCodeに隷属している」という気持ちは拭えません。

However, I can't shake the feeling that I am “subordinate to VSCode.”

まあ、しかし、今の私は、すでに「生成AIに隷属」している身の上です。

Well, but now I am already “enslaved to generative AI.”

ですから、『今さら何を』という気持ちもあります。

So, I also feel like, 'What is the point now?

-----

とは言え、VSCodeを使っていて、マルクスの『資本論』における「労働の疎外(Entfremdete Arbeit)(*)」を実感することになるとは思いませんでした。

However, I never thought that using VSCode would make me realize the “alienation of labor” in Marx's “Das Kapital” (*).

(*)本来人間が支配し利用するはずの道具(生産手段)が、資本主義社会では逆に人間を支配するようになるという逆転現象のこと

(*) A reversal in which the tools (means of production) humans should control and use end up controlling them in a capitalist society.

停滞主義とは(2)

2025,江端さんの技術メモ

vscodeでデバッグをする時に、同じディレクトリにmain()関数を持つGo言語プログラムが複数あると、デバッグができません。ファイル名を指定してデバッグすることはできないでしょうか。ただし、launch.json にファイル名を書き込むと、実行ファイルが固定されてしまうので、それは避けたいのですが。

launch.json を使うと、特定のGoファイルが環境として固定されるため、別のファイルをデバッグしたいときに launch.json を都度編集する必要があり、やや不便です。

ですが、以下の方法を使えば 環境を固定せずに、デバッグするファイルを柔軟に切り替えられます。


1. launch.json${file} を使う

環境を固定せずに、現在開いているGoファイルをデバッグする方法です。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Current File",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${file}"
        }
    ]
}

  • ${file} は、現在アクティブな(開いている)ファイルをデバッグ対象にする特殊変数です。
  • この設定にすると、エディタで開いているGoファイルがどれでも、F5 でデバッグが開始できます。

開いているGoのプログラムでデバッガーが動いた。これから作業がラクになるかな。

2025,江端さんの忘備録

私は、人工知能(Artifical Intelligent:AI)なるものは存在せず、これからも出現しない ―― と、ずっと言って続けてきた当事者です。

I have always said, “There is no such thing as artificial intelligence (AI), and there never will be.”

しかし、今や私は、『生成AIなしではもう生活が成り立たない』とまで断言できる、「生成AI依存者」です。

However, I am now a “generative AI addict” who can confidently say that I can't live without generative AI.

私、"知能"とか"知性"とかいうのは、もっと複雑で深淵で神秘的な"何か"と思ってきました。

I've always thought that “intelligence” and “intellect” were more complex, profound, and mysterious.

しかし、最近は、『もしかしたら、人間の知能というのは、生成AIのメカニズム程度の単純なものなのかもしれない』と、人間の知能/知性の方を下方修正しはじめています。

However, recently, I have begun to revise my view of human intelligence/intellect downward, thinking, “Perhaps human intelligence is as simple as the mechanism of generative AI.

人間の知能や知性というものが、生成AIと同程度に低レベルのものであるなら、「人工知能は、すでに存在している」と、自分の考え方を変更する準備があります。

If human intelligence and intellect are as low-level as generative AI, I am prepared to change my thinking and say, “Artificial intelligence already exists.”

いや、ぶっちゃけて言いましょう。

Let's be frank.

これは「変更」ではなく、「転向」ですね。

This is not a “change” but a “Turnaround”.

"江端" "転向"でwww.kobore.netをサーチしてみた

-----

生成AIによって、人間に仕事がなくなるという観点では、現在、劇的な人口減少が進行中の私たち日本人にとっては、ラッキーと言えるでしょう。

From the perspective that jobs will disappear for humans due to the creation of AI, we Japanese, who are currently experiencing a dramatic population decline, can be considered lucky.

人間が減っても、サービス品質が維持できるなら、それはラッキーでしょう。

It would be lucky if the quality of service could be maintained even if the number of people decreased.

ただ、職種が減っていくことは、就労条件が厳しくなることでですので、それはアンラッキーです。

However, the number of job types is decreasing because working conditions are becoming stricter, which is unlucky.

だからといって、「生成AIにできない仕事ことを探す」というアプローチは多分正しくないです。

That said, the approach of “finding work that generative AI cannot do” is probably incorrect.

ここは過去に学ぶべきです。

We should learn from the past.

-----

以前、『コンピュータ(パーソナルコンピュータを含む)が登場したら、私たちはやることがなくなる』と言われましたが、やることが死ぬほど増えました。そんでもって、ぶっちゃけ人類は、コンピュータで幸せになっていません。

It was once said that 'once computers (including personal computers) appeared, we would have nothing to do,' but we now have more to do than we can handle. And to be honest, computers haven't made us happy.

『核兵器が登場したら、人類は戦争をしなくなる』と言われましたが、核抑止力の枠組みの中で、制御された戦争が続けられています。

It has been said that “once nuclear weapons appeared, humanity would stop going to war,” but within the framework of nuclear deterrence, controlled warfare continues.

『ハーバー・ボッシュ法ができたから、人類は飢えることがなくなる』と言われ、論理的にはそうなっても良いはずなのですが、そうなっていません。

It is said that “since the Harbor-Bosch method was created, humanity will no longer starve,” and logically, this should be the case, but it is not.

この発明によって、人類は「食料不足を補う為に、領土を奪い合う戦争」というパラダイムを終了させた ―― はずでした。

『好きな時間に好きな音楽や映画を見られるようになったら、エンタメ産業は全滅する』と言われました ―― サブスク流行っていますが、エンタメ産業は全滅していません。

It was said that “if people can watch the music and movies they want, whenever they want, the entertainment industry will be wiped out” - - although subscriptions are popular, the entertainment industry has not been wiped out.

『リモートで仕事ができるようになったら、街はゴーストタウンになる』―― いや、そういう社会は大歓迎なのですが、そうなっていません。せっかく、世界的なパンデミックという稀有な機会を得た後でさえ、です。

'If we can work remotely, the town will become a ghost town' - no, we would welcome such a society, but it hasn't happened. Even after we had the rare opportunity of a global pandemic.

-----

このように、「生成AIが主流になれば、私たちは働けなくなる」とはなりません。

In this way, it is not the case that “if generative AI becomes mainstream, we will be unable to work.”

私たちは、さらに忙しくなります。それも私たちを不幸にする方向に、です。

We will become even busier, and in a way that will make us unhappy.

パソコンでもスマホでも、私たちは恩恵以上に、悪いものも沢山得てきたはずです。

Whether it's a computer or a smartphone, we've probably gained more bad things than good.

# 例えば、子供たちを自殺に追いやり続けるSNSとか、芸能人のギャラを搾取するサブスクとか、四六時中、気が休まらないチャットとか。

# For example, social networking services that continue to drive children to suicide, subscriptions that exploit the fees of celebrities, and chats that don't let you rest at all.

-----

ともあれ、就労については心配しなくても大丈夫でしょう。今と違う仕事が発生します。私たちがいちいち考えなくてもです。

Anyway, you don't need to worry about finding work. Different jobs will arise. We don't have to think about it every time,

ただし、その仕事で、私たちが幸せになれるか、については、私は断言できません。

However, I cannot say whether or not that work will make us happy.

私の個人的な見通しとしては、かなり「ネガティブ」です。

My outlook is quite negative.

未分類

江端です。

robintos>  先日は、デンバーにて昼食を御一緒できて、光栄でございました。

  こちらこそ、楽しい昼食会をありがとうございました。

robintos>  ホームページを見るほとんどの者が江端氏に対して抱くであろう
robintos>  像を、悲しい凡人の性で私も抱いておりましたが、お会いするや
robintos>  いなやその像は完膚なきまでに崩されました。
robintos>  あの孤高の、神の領域に立ち入る文章が、気位の高さを微塵にも
robintos>  感じさせないあまりにも人間的な人物により生み出されていたと
robintos>  いう事実に、驚愕の念を禁じ得ません。

  かなりの方が同じ様なことをおっしゃって下さるのですが、我が師匠にして
親友であるところの、エルカンによれば、

	「フェミニズムを標傍するだけの、エセ男女同権主義者」

  嫁さんによれば、

	「女性に興味を示さない文学青年を装う、本性全くその逆の男」

  その他、
	「革命家の仮面を被った小市民」「権威(*1)に従奴する小物」「亡国
	のスポーツ(*2)に興ずる売国奴」

  などとも呼ばれており、これらは、(*1)通産省の情報処理技術者の資格取得
に狂奔しているとか、(*2)スキーやテニスなどを華麗にプレイし、女性に取り
囲まれる運命にある私を妬む者たちの、言われのない中傷の数々の内のほんの
一部でございます。

  しかしながら、私の実体とは、出エジプト記3章14節にある、あの有名な一
節の中ですでに述べられている者です。

	----- 神はモーセに仰せられた。
		「わたしは、『わたしはある』という者である。」 
                  And God said to Moses, "I AM WHO I AM." -----
  
robintos>  むしろ私の凡庸な考えに誤りがあったということでしょう。何気
robintos>  無い人間らしい生活を真摯に重ねる者にこそ、人智の限界に達し
robintos>  うる高尚な思考が宿るとの考えに至りました。

  あのあまりにも有名な、

	"A Rolling stone gathers no moss."

  「転がる石は、やがてローリングストーンになる(*3)」と言う、日々の研鑽
を重ねていくことによって、やがては著名なロックンローラーになると言う、
この格言を胸に、私も日々鍛練に余念がありません。

  (*3)明かな誤訳

robintos>  最後に、お会いできたときの感想をもう一つ敢えて申し上げるな
robintos>  らば、ケビンコスナーの顔とはいかなるものだったか自分の記憶
robintos>  を疑ってしまったということです。

  禁酒法時代のアメリカ。犯罪王アル・カポネが君臨していたその時代に、彼
と対決するひとりの男が現れる。財務省捜査官エリオット・ネス。

  あの名作、アンタッチャブルを京都四条の映画館で見終わった後、私は私が、
単にケビンコスナーと容貌が似ていることのみならず、エリオット・ネスのそ
の生き様に、私の孤高の精神を写し見たのであります。

  この映画の観賞が終った後、私はその足で、京都岩倉にある私のアルバイト
先の学習塾にて、ケビンコスナーと私がいかに酷似していたかを滔々と語った
のであります。
  生徒達は、最初笑いながら私の話につきあっていましたが、私がその話を続
けている内に、そのうち不安げな顔になり、最後に心配そうに私に尋ねました。

 	「先生、何かあったの? 」
	「先生、疲れていない?」

  私には、未に、生徒達が何を言いたかったのか分かりません。

robintos>  駄文力のなさゆえ、気を抜くとすぐにツマラナイ文章を作成する
robintos>  に堕落してしまいます。
robintos>  駄文力こそ、文章の粋、忘れてはならないセンスであり、修辞法
robintos>  などという簡単な言葉では説明できないものしょう。人生にとっ
robintos>  ての不可欠なユーモアセンスとは、文章にとっての駄文力の関係
robintos>  に等しいのではないでしょうか。

  まさにおっしゃる通りでございます。

  駄文とは、まさに、知識、レトリック、習字方や修辞方を乗り越えた所にあ
る、最も困難にして、しかしながら全く何の役にも立たないものであり、文章
と言う記録媒体としてのプラグラティズムの対極に立つ、究極の無駄文化の一
形態でありましょう。

  しかしながら、時間と資源の浪費の限りを尽して作成するこの駄文こそが、
知的生命体である我々人類に許された、最高かつ贅沢な芳醇にして野趣豊かな
知的作業であると思うのです。
  畢竟、文化とは、あってもなくてもどーでもよいものと定義されるものであ
り、駄文とは、そのような意味で、文化の名に恥じないものであると、私は信
じています。

robintos>  当方、駄文力の重要性は認識しておるものの能力不足ゆえ、江端
robintos>  氏ホームページ参考資料(高村薫や落語CDなど、ホームページで
robintos>  引用されている資料)を通じて、研鑽していく所存です。言をま
robintos>  たないのですが、国民の四大義務の一つ「ホームページ本文の暗
robintos>  誦」は、成人前に完了しております。

  駄文力育成の為に、役に立ちそうな本を以下に紹介致します。
(http://www.kobore.net/tex/alone95/node21.html)

(1)左翼、あるいは右翼の運動や論理破綻、自己矛盾、自己否定に疲れたあな
   たへ
  	- 転向こそわが人生(江端智一著:「やさしい転向入門」より抜粋) 
	- 実践的転向派のための「はじめての『転向』」
	- さらに極めたいあなたのために「実用『転向』(上・下)」
	  「応用『転向』(上・下)」

(2)日本を代表する駄文作家の江端の半生を記録した書
      
  江端がいかにして、保守思想を勝ち得たかを問う、世紀末 最大にして最後
の、そして戦後50年に日本人に問いかける問題の書 

	「わが転向 -----D大学S自治寮寮長就任、そして粛正・・・ 日立
	  入社を経て、ホンダシビック購入まで -----」 
					江端書房より絶賛発売中!! 

  かつては理想に燃えていた一人の青年。世界革命の夢が潰え去り、 傷つい
た彼は、家庭的幸福に救いを求めようとするが・・・。没落した革命家の実像
に、全世界が震撼する話題作! 

     	「続・わが転向 -----婚約から破局まで・Y嬢よ、おまえもか!------」
	 近日刊行! 

  崩壊した家庭。荒んでしまった彼は、会社で「仕事? なにが仕事だ。 痔裂
分散システム?ふざけるなM主管!」と暴言を吐き、解雇される・・。ヤケに
なった人間は始末が悪い、と各界の同意を得る警世の書! 

     	「続々・わが転向 -----自暴自棄から失業まで-----」
     	本年中に刊行予定! 

  根無し草のように街から街へと彷徨する元革命家。 社会から疎外された彼
が行き着いた所は、麻薬と暴力が支配する闇の 世界だった・・。
  堕落した人間の、それでも自分の人生は間違っていなかったという 信念に、
「ええ加減にせい!」と世界中からつっこまれる奇書! 

	「続々々・わが転向 -----牢獄より・わが転向に悔いなし-----」
	 来年度刊行予定! 

2025,江端さんの忘備録

韓国の戒厳令の事件や、現米国大統領の施策を見ていると、改めて「大統領制というものは独裁制(の一態様)なのだなぁ」と実感しています。

Looking at the events of the Korean martial law and the policies of the current US president, I am once again realizing that “the presidential system is a form of dictatorship.”

ナチスドイツが、合法的な手段(国政選挙)によって権力を奪取して、合法的な法律を制定し、合法的に特定民族の迫害(殺害を含む)を行ってきたこと ―― これらの全ては、(人道や倫理の問題を棚上げにすれば)民主主義の手続が"正しく"実施された結果です。

The fact that Nazi Germany seized power through legal means (national elections), enacted legal laws, and legally persecuted (including killing) a specific ethnic group - all of these are the result of “proper” implementation of democratic procedures (if we set aside issues of humanity and ethics).

#「はみだしっ子」の12巻に記載されています。

# This is mentioned in volume 12 of “Hami-Dashi-Kko.”

―― 江端家のトイレライブラリの書架にある「はみだしっ子」が、娘たちに貸出された形跡がない

民主主義を標榜する国(まあ、世界の全部の国が"そう"言っていますけどね)は、一応、立憲/立法主義で支えられています。

Countries that advocate democracy (well, all countries in the world say they do) are supported mainly by constitutionalism/legislative democracy.

しかし、法律の主な目的は国益と国民の公平感の提供であって、正義でも人道でもありません(そう見せかけてはいますが)。

However, the law's primary purpose is to provide national interests and a sense of fairness for the people, not justice or humanity (although it may appear that way).

ですので、米国大統領がどんな大統領命令を発しようとも、米国の国民が決められた選挙システムによって合法的に選んだ以上、少なくとも米国国民は文句は言えません(言えますが、言えるだけです)。

So, no matter what kind of presidential order the US president issues, as long as the US citizens have legally chosen them through the established electoral system, at least the US citizens cannot complain.

他国も文句を言えますが、文句が言えるだけです。他国の大統領命令の発行を停止することはできません。

Other countries can complain, but that's all they can do. They can't stop the president of another country from issuing an order.

唯一の手段としては、国際法に基づく手続による宣戦布告と戦争の突入ですが、世界一強いジャイアン(アメリカ合衆国)に、喧嘩をふっかける勇気のある国があるとは思えません。

The only way to do this is to declare war and go to war through procedures based on international law, but I don't think there is a country that would have the courage to pick a fight with the world's strongest Gian (United States of America).

いや、あるはあるんですが ―― 自国の安全保障を無視する国や組織ならやります。

I would do some things, but I would only do them if the country or organization in question ignored its own national security.

(↑コラムに飛びます)

(Jump to the column)

------

今の、大統領を見てみると、1940年代の「パクス・アメリカーナ」への回顧を目指しているように見えます(というか、間違いなく、そうだろう)。

Looking at the current president, it seems (and it is the case) that he aims to restore the “Pax Americana” of the 1940s.

これは、壮大な社会実験です。しかも、我が国は、部外者でいることを許されず、被験者にさせられる運命にあります。

This is a grand social experiment. Furthermore, our country cannot remain an outsider and will be made a test subject.

米国の回顧主義が成功すれば、日本もそれに倣う可能性は高いです。

If American restorationism is successful, there is a high possibility that Japan will follow suit.

真っ先に「同性婚」が吹き飛ばされるでしょう。「LGBT」「夫婦別姓」も同様でしょう。

Same-sex marriage will be the first thing to be blown away. The same will probably be true for LGBT and different family names for married couples.

パワハラやセクハラまたは喫煙などが、一定の範囲で認容される世界線とかの再来の可能性もありえるかもしれません。

There is a possibility that the world line where power harassment, sexual harassment, and smoking are tolerated to a certain extent may reappear.

------

多様な価値観よりは、片手の数くらいの価値観(保守とリベラルとその間)の方が、国家を運営する側もラクでしょうしね。

It would be easier for those running the country if there were only a handful of values (conservative, liberal, and somewhere in between) rather than a diverse range of values.

新しい価値観は、それが社会に定着するまで、膨大なトライアンドエラーが必要になりますので、古い価値観の方が"ラク"と感じる人だっているでしょう。

New values require considerable trial and error before they become established in society, so people probably feel that old values are “easier.”

私、世界というのは、新しい価値観を求めて、トライアンドエラーを繰替えす面倒くさいシステムだと思っていましたけど ――

I used to think that the world was a complicated system that required a lot of trial and error to pursue new values, but...

「回顧主義という独裁」というのは、完全に盲点でした。

The “dictatorship of retrospection” was a complete blind spot for me.

さらに、これが「自由の国」を標榜する国から始まるとは、完全に予想外です。

Furthermore, it's completely unexpected that this would start in a country that advocates a “land of freedom.”

まあ、これも私の予見力のなさの結果だとは思いますが ―― まあ、多くの人も同じようなものだろうな、と思っています。

This is also the result of my lack of foresight, but I think many people are the same.

-----

で、私がこの状況をどう見ているかというと、「静観」です。ただの観測者です。

So, how do I see this situation? I'm just an observer.

私は、(1)健康と(2)年金と(3)苦痛のない死、3つが重大な関心事項であり、上記(3)までに、戦火や災禍が及ばないことを祈っているだけです。

I am only concerned about three things: (1) my health, (2) my pension, and (3) a painless death. I hope I won't have to worry about war or disaster before the (3) coming.

しかし、この回顧主義で不利益を被る人々は、闘わなけれなならないでしょう。厳しい闘いになると思います。

However, those who suffer from this retrospection will have to fight. I think it will be a tough fight.

-----

私は、影ながら声援を送り続けています。

I will continue to cheer you on from the shadows.

2025,江端さんの忘備録

さすがに3つの案件の同時並列処理は無理 ―― と、泣き言を言いながら、今、本当に泣きそうです。

I'm whining that “it's impossible to handle three projects simultaneously,” and I'm about to cry.

経験的に、こういう時『もっと大変な人が、沢山いる』という考え方をすることは、悪手です。

Empirically, thinking that “there are many people in worse situations” is a bad idea in a situation like this.

他人なんぞ、どーでもいい。

I don't care about other people.

「私が辛い」という状態だけで、必要かつ十分です。

The fact that I am in pain is sufficient.

-----

そういえば、今年の年賀状には、長女の結婚式の写真の下に、自分のコメントとして

Speaking of which, on this year's New Year's card, under the photo of my eldest daughter's wedding, I remember I wrote the following  comment 

『昨年、"うつ"になりました』

'I became depressed last year.'

と書いたのを思い出しました。

『これでは、長女の結婚で"うつ"になったように読める』と気がついたのは、年賀状をポストに投函した後でした。

It was only after I had posted the New Year's card in the post that I realized that it could be read as if I had become depressed because of my eldest daughter's marriage.

しかし、私を"うつ"にするのは、いつだって、仕事です。

However, it is always work that makes me depressed.

その正体の多くが、動かないプログラムであり、停止するシステムです。

Many are programs that don't work and systems that become stop.

世の中には「頼めない仕事」というものが、あるのです。

There are some jobs that I can't ask someone to do.

つまりですね、技術というのは、属人性が高く、他人への譲渡が恐しく困難なのです

未分類

「あなたの夢をあきらめないで」とか「負けないで」という歌がありましたよね。

There were songs like “Don't Give Up on Your Dreams” and “Don't Lose”.

それついて、コメントをしたものが以下のものになります。

The following are comments on this.

あなたの夢を諦めないで

今、あらためて気がついたのですが、この歌『女性から男性に向けたメッセージ』ですよね。

I've just realized this song is a message from a woman to a man.

男性から女性に対して、「あなたの夢をあきらめないで」とか「君の夢をあきらめないで」とかいう歌ってありますか。私は知らないんですよ。

Is there a song that says something like “Don't give up on your dreams” from a man to a woman? I don't know.

ChatGPTに尋ねてみたら、

I asked ChatGPT, and 

『現在のところ、男性が女性に向けて「あなたの夢をあきらめないで」や「君の夢をあきらめないで」と直接的に歌う楽曲は見当たりません』

'I have not found any songs in which men directly sing to women, saying “Don't give up on your dreams.”

と言われました。

The above was the response.

-----

これって、一見、どうでも良いようなことにも見えます。

At first glance, this may seem like something that doesn't matter.

しかし、私は、これは結構根深い深い社会的病理の一端を現わしていると思うのです。

However, I think this reveals a part of a relatively deep-rooted social pathology.

(1)女性に対する「あなたの夢をあきらめないで」という社会的ニーズがないか、あるいは認識できないほど小さい

(1) There is no social need for women to “not give up on your dreams,” or it is so tiny that it cannot be recognized.

(2)男性側から女性に対して「あなたの夢をあきらめないで」という考え方がない

(2) Men don't think to women, “Don't give up on your dreams.”

(3)女性自身に「あきらめないで」と言われるほどの困難性を伴う夢という概念がないか、あるいは認識できないほど小さい

(3) There is no concept of a dream so tricky that it would make a woman say to herself, “Don't give up,” or it is so tiny that it cannot be recognized.

上記の(1)~(3)が正解かどうかはさておき、そう思わせるだけの世相がある、とは言えると思います。これは、社会における価値観やジェンダーロールの固定観念が根深く関係していることが分かります。

Leaving aside whether (1) to (3) above is correct, I think it can be said that a social climate makes people feel that way. This shows that deeply rooted social values and gender role stereotypes are related.

このように考えていくと、男性から女性に向けた「あなたの夢をあきらめないで」という歌が存在しないことは、単なる音楽業界の傾向ではなく、より広範な社会構造の反映であることがわかります。

When I think about it like this, I can see no songs by men or women telling them not to give up on their dreams. This is not just a trend in the music industry but a reflection of a broader social structure.

過去も現代も、女性も仕事や夢を追いかける人は、ちゃんと追いかけていたと思いますが、どうやら彼女らは「応援の対象」にはならかったようです。

In the past and the present, women who pursued their work and dreams could do so, but they seem to have been not considered “worthy of support.”

-----

ならば作りましょう。男性から女性に捧げる「あなたの夢を諦めないで」という歌を。

Then, let's make a song for men to dedicate to women, saying, “Don't give up on your dreams.”

男性から女性に捧げる「あなたの夢をあきらめないで」の歌の中には「終生独身上等」「仕事第一」「育児キャンセル」「婚活不要」「老後は自己責任」が含まれるでしょう。

Songs with the phrases “Never give up on your dreams,” “Single for life,” “Work first,” “Cancel childcare,” “No need to get married,” and “You are responsible for your retirement” should be broadcast.

加えて、『僕が困ったときには、きっと君が助けてくれるから』という、男性サイドの願望も加えておきましょう。

In addition, let's add the male side's desire, “I know you'll help me when I'm in trouble.”

この歌は、若い男性アイドルグループからリリースされることが望ましいでしょう。

A young male idol group would best release this song.

日本の人口激減は避けられませんが、労働人口は上がるかもしれません。

Although a sharp decline in Japan's population is inevitable, the working population may increase.

非婚化と出生率低下は、もう打つ手がないと思います(予算を積めばどうにかなる、という問題ではないと思う)。

I don't think anything can be done about the declining birthrate and the trend towards non-marriage (I don't think it's a problem that can be solved by increasing the budget).

ならば、せめて労働力を確保すべく、女性に捧げる「あなたの夢をあきらめないで」を、プロデュースしていくべきでしょう。

Then, to at least secure labor, they should produce “Don't give up on your dreams” dedicated to women.

ただ、これを「政府」がやるのは ・・・ 無理かなぁ。

However, I don't think the government could do this...