未分類

ベースはこちらです。

matsim_crs_verified_exporter.html 解説書(統合版)

以下が、matsim_live_map.go の修正版全文です。
主な修正点は次の3つです。

  • eventx,y があれば それを優先使用

  • x,y がなければ link から座標を求める

  • 先頭の event 属性を画面に表示して デバッグ可能 にした

起動方法は、
(1)go run matsim_live_map.go (I:\home\ebata\hakata\video3)
(2)ブラウザからlocalhost:8080
(3)起動したブラウザで
output_network.xml.gz と output_events.xml.gz をドラッグ&ドロップ(同時に行うところがポイント)
(4)対象イベントtypeは空欄にする

[matsim_live_map.go]

package main

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

var addr = flag.String("addr", "0.0.0.0:8080", "http service address")

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

	http.HandleFunc("/", home)
	log.Printf("listen on http://%s", *addr)
	log.Fatal(http.ListenAndServe(*addr, nil))
}

func home(w http.ResponseWriter, r *http.Request) {
	if err := pageTemplate.Execute(w, nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

var pageTemplate = template.Must(template.New("page").Parse(`
<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <title>MATSim Live Map Viewer</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <link
    rel="stylesheet"
    href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
    integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
    crossorigin=""
  />
  <script
    src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
    integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
    crossorigin=""
  ></script>

  <style>
    html, body {
      margin: 0;
      padding: 0;
      height: 100%;
      font-family: system-ui, sans-serif;
    }
    body {
      display: grid;
      grid-template-columns: 420px 1fr;
      overflow: hidden;
    }
    #side {
      border-right: 1px solid #ccc;
      padding: 12px;
      overflow: auto;
      background: #fafafa;
    }
    #map {
      width: 100%;
      height: 100%;
    }
    #drop {
      border: 2px dashed #777;
      border-radius: 12px;
      padding: 16px;
      background: white;
    }
    #drop.drag {
      background: #f0f0f0;
    }
    .row {
      margin-top: 10px;
    }
    label {
      display: block;
      font-size: 12px;
      color: #444;
      margin-bottom: 4px;
    }
    input, select, button {
      width: 100%;
      box-sizing: border-box;
      padding: 8px;
      font-size: 14px;
    }
    .btns {
      display: grid;
      grid-template-columns: 1fr 1fr 1fr;
      gap: 8px;
    }
    pre {
      white-space: pre-wrap;
      word-break: break-word;
      border: 1px solid #ddd;
      background: white;
      padding: 10px;
      height: 240px;
      overflow: auto;
      font-size: 12px;
    }
    .legend {
      position: absolute;
      top: 12px;
      right: 12px;
      z-index: 1000;
      background: rgba(255,255,255,0.95);
      border-radius: 8px;
      padding: 10px 12px;
      box-shadow: 0 2px 8px rgba(0,0,0,0.25);
      font-size: 13px;
      line-height: 1.5;
    }
    .dot {
      display: inline-block;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      margin-right: 6px;
      vertical-align: middle;
      border: 1px solid rgba(0,0,0,0.25);
    }
    .small {
      font-size: 12px;
      color: #666;
    }
    .stat {
      margin-top: 8px;
      padding: 8px;
      background: white;
      border: 1px solid #ddd;
      border-radius: 6px;
      font-size: 12px;
      white-space: pre-wrap;
    }
  </style>
</head>
<body>
  <div id="side">
    <h2>MATSim Live Map Viewer</h2>

    <div id="drop">
      <b>output_network.xml.gz</b> と <b>output_events.xml.gz</b> をここにドラッグ&ドロップ
      <div class="small" style="margin-top:8px">
        読み込み後、そのまま地図上でエージェントを再生する。<br>
        途中CSVは作らない。
      </div>
    </div>

    <div class="row">
      <label>対象イベント type(空なら広めに採用)</label>
      <input id="types" value="entered link,left link,departure,arrival,vehicle enters traffic,actstart,actend" />
    </div>

    <div class="row">
      <label>地域ヒント(経度,緯度)</label>
      <input id="hintLonLat" value="139.50,35.60" />
    </div>

    <div class="row">
      <label>ゾーン(自動選択後に手動変更可)</label>
      <select id="zoneSelect" disabled></select>
    </div>

    <div class="row">
      <label>再生速度(倍速)</label>
      <input id="speed" type="number" step="0.1" min="0.1" value="20" />
    </div>

    <div class="row">
      <div class="btns">
        <button id="prepare" disabled>解析</button>
        <button id="play" disabled>再生</button>
        <button id="pause" disabled>停止</button>
      </div>
    </div>

    <div class="row">
      <button id="reset" disabled>先頭に戻す</button>
    </div>

    <div class="stat" id="status">未読み込み</div>

    <div class="row">
      <label>プレビュー</label>
      <pre id="preview"></pre>
    </div>
  </div>

  <div style="position:relative">
    <div id="map"></div>
    <div class="legend">
      <div><span class="dot" style="background:#e74c3c"></span>Type1</div>
      <div><span class="dot" style="background:#3498db"></span>Type2</div>
      <div><span class="dot" style="background:#2ecc71"></span>Type3</div>
      <div><span class="dot" style="background:#f1c40f"></span>Type4</div>
      <hr>
      <div>time: <span id="timeText">(none)</span></div>
      <div>agents: <span id="agentCount">0</span></div>
    </div>
  </div>

<script>
let networkFile = null;
let eventsFile = null;

let parsedNetwork = null;
let preparedFrames = [];
let personMarkers = new Map();
let personState = new Map();

let timer = null;
let currentFrameIndex = 0;

const drop = document.getElementById("drop");
const prepareBtn = document.getElementById("prepare");
const playBtn = document.getElementById("play");
const pauseBtn = document.getElementById("pause");
const resetBtn = document.getElementById("reset");
const zoneSelect = document.getElementById("zoneSelect");
const statusEl = document.getElementById("status");
const previewEl = document.getElementById("preview");
const timeText = document.getElementById("timeText");
const agentCount = document.getElementById("agentCount");

const map = L.map("map", {
  attributionControl: false
}).setView([35.60, 139.50], 14);

L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
  maxZoom: 19
}).addTo(map);

function setStatus(s) {
  statusEl.textContent = s;
}

function setPreview(s) {
  previewEl.textContent = s;
}

drop.addEventListener("dragover", (e) => {
  e.preventDefault();
  drop.classList.add("drag");
});
drop.addEventListener("dragleave", () => {
  drop.classList.remove("drag");
});
drop.addEventListener("drop", (e) => {
  e.preventDefault();
  drop.classList.remove("drag");

  networkFile = null;
  eventsFile = null;

  for (const f of e.dataTransfer.files) {
    const n = f.name.toLowerCase();
    if (n.includes("network") && n.endsWith(".gz")) networkFile = f;
    if (n.includes("events") && n.endsWith(".gz")) eventsFile = f;
  }

  preparedFrames = [];
  clearMarkers();
  currentFrameIndex = 0;
  parsedNetwork = null;
  zoneSelect.innerHTML = "";
  zoneSelect.disabled = true;

  playBtn.disabled = true;
  pauseBtn.disabled = true;
  resetBtn.disabled = true;

  if (networkFile && eventsFile) {
    prepareBtn.disabled = false;
    setStatus("network/events 読み込み準備完了\n「解析」を押してください");
  } else {
    prepareBtn.disabled = true;
    setStatus("output_network.xml.gz と output_events.xml.gz の両方が必要");
  }
});

function clearMarkers() {
  for (const marker of personMarkers.values()) {
    map.removeLayer(marker);
  }
  personMarkers.clear();
  personState.clear();
  agentCount.textContent = "0";
  timeText.textContent = "(none)";
}

async function* ungzipTextChunks(file) {
  const ds = new DecompressionStream("gzip");
  const textStream = file.stream().pipeThrough(ds).pipeThrough(new TextDecoderStream("utf-8"));
  const reader = textStream.getReader();
  try {
    while (true) {
      const {value, done} = await reader.read();
      if (done) break;
      if (value) yield value;
    }
  } finally {
    reader.releaseLock();
  }
}

function parseAttrs(tagText) {
  const attrs = {};
  const re = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
  let m;
  while ((m = re.exec(tagText)) !== null) {
    attrs[m[1]] = (m[2] !== undefined) ? m[2] : m[3];
  }
  return attrs;
}

function normalizeTypeName(s) {
  return String(s || "").trim().toLowerCase();
}

const JPRCS = {
  1:  {lat0:33, lon0:129},
  2:  {lat0:33, lon0:131},
  3:  {lat0:36, lon0:132.1666666667},
  4:  {lat0:33, lon0:133.5},
  5:  {lat0:36, lon0:134.3333333333},
  6:  {lat0:36, lon0:136},
  7:  {lat0:36, lon0:137.1666666667},
  8:  {lat0:36, lon0:138.5},
  9:  {lat0:36, lon0:139.8333333333},
  10: {lat0:40, lon0:140.8333333333},
  11: {lat0:44, lon0:140.25},
  12: {lat0:44, lon0:142.25},
  13: {lat0:44, lon0:144.25},
  14: {lat0:26, lon0:142},
  15: {lat0:26, lon0:127.5},
  16: {lat0:26, lon0:124},
  17: {lat0:26, lon0:131},
  18: {lat0:20, lon0:136},
  19: {lat0:26, lon0:154},
};

function tmParamsFromZone(zone) {
  const z = JPRCS[zone];
  return {
    epsg: 6669 + zone,
    zone,
    a: 6378137.0,
    f: 1.0 / 298.257222101,
    k0: 0.9999,
    lat0: z.lat0 * Math.PI / 180,
    lon0: z.lon0 * Math.PI / 180,
    fe: 0.0,
    fn: 0.0,
    lat0deg: z.lat0,
    lon0deg: z.lon0,
  };
}

function invTM(x, y, p) {
  const a = p.a, f = p.f, k0 = p.k0;
  const e2 = 2*f - f*f;
  const ep2 = e2 / (1 - e2);

  const x1 = (x - p.fe) / k0;
  const y1 = (y - p.fn) / k0;

  const A0 = 1 - e2/4 - 3*e2*e2/64 - 5*e2*e2*e2/256;
  const A2 = 3*e2/8 + 3*e2*e2/32 + 45*e2*e2*e2/1024;
  const A4 = 15*e2*e2/256 + 45*e2*e2*e2/1024;
  const A6 = 35*e2*e2*e2/3072;

  function meridional(phi) {
    return a*(A0*phi - A2*Math.sin(2*phi) + A4*Math.sin(4*phi) - A6*Math.sin(6*phi));
  }

  const M0 = meridional(p.lat0);
  const M  = M0 + y1;
  const mu = M / (a*A0);

  const e1 = (1 - Math.sqrt(1-e2)) / (1 + Math.sqrt(1-e2));
  const J1 = 3*e1/2 - 27*Math.pow(e1,3)/32;
  const J2 = 21*e1*e1/16 - 55*Math.pow(e1,4)/32;
  const J3 = 151*Math.pow(e1,3)/96;
  const J4 = 1097*Math.pow(e1,4)/512;

  const fp = mu + J1*Math.sin(2*mu) + J2*Math.sin(4*mu) + J3*Math.sin(6*mu) + J4*Math.sin(8*mu);

  const sinfp = Math.sin(fp), cosfp = Math.cos(fp), tanfp = Math.tan(fp);

  const N1 = a / Math.sqrt(1 - e2*sinfp*sinfp);
  const R1 = a*(1-e2) / Math.pow(1 - e2*sinfp*sinfp, 1.5);
  const T1 = tanfp*tanfp;
  const C1 = ep2*cosfp*cosfp;
  const D  = x1 / N1;

  const Q1 = N1*tanfp / R1;
  const Q2 = (D*D)/2;
  const Q3 = (5 + 3*T1 + 10*C1 - 4*C1*C1 - 9*ep2) * Math.pow(D,4)/24;
  const Q4 = (61 + 90*T1 + 298*C1 + 45*T1*T1 - 252*ep2 - 3*C1*C1) * Math.pow(D,6)/720;

  const lat = fp - Q1*(Q2 - Q3 + Q4);

  const Q5 = D;
  const Q6 = (1 + 2*T1 + C1) * Math.pow(D,3)/6;
  const Q7 = (5 - 2*C1 + 28*T1 - 3*C1*C1 + 8*ep2 + 24*T1*T1) * Math.pow(D,5)/120;

  const lon = p.lon0 + (Q5 - Q6 + Q7) / cosfp;

  return {lat, lon};
}

function median(arr) {
  if (!arr.length) return NaN;
  const a = [...arr].sort((x, y) => x - y);
  const mid = Math.floor(a.length / 2);
  return (a.length % 2) ? a[mid] : (a[mid-1] + a[mid]) / 2;
}

function parseHint() {
  const s = (document.getElementById("hintLonLat").value || "").trim();
  const m = s.split(",").map(x => x.trim()).filter(Boolean);
  if (m.length !== 2) return {hintLon: 139.5, hintLat: 35.6};
  const hintLon = parseFloat(m[0]);
  const hintLat = parseFloat(m[1]);
  if (!Number.isFinite(hintLon) || !Number.isFinite(hintLat)) {
    return {hintLon: 139.5, hintLat: 35.6};
  }
  return {hintLon, hintLat};
}

function inferZonesByHint(sampleXY, hintLon, hintLat) {
  const results = [];
  for (let zone = 1; zone <= 19; zone++) {
    const p = tmParamsFromZone(zone);
    const lons = [];
    const lats = [];

    for (const [x, y] of sampleXY) {
      const ll = invTM(x, y, p);
      const lon = ll.lon * 180 / Math.PI;
      const lat = ll.lat * 180 / Math.PI;
      if (Number.isFinite(lon) && Number.isFinite(lat)) {
        lons.push(lon);
        lats.push(lat);
      }
    }

    const mlon = median(lons);
    const mlat = median(lats);
    const dLon = (mlon - hintLon) * Math.cos(hintLat * Math.PI / 180);
    const dLat = mlat - hintLat;
    const dist = Math.sqrt(dLon*dLon + dLat*dLat);
    const inJapan = (mlon >= 120 && mlon <= 155 && mlat >= 20 && mlat <= 47);
    const score = dist + (inJapan ? 0 : 999);

    results.push({zone, epsg: p.epsg, mlon, mlat, dist, score});
  }
  results.sort((a, b) => a.score - b.score);
  return results;
}

async function parseNetworkStream(file) {
  const nodes = new Map();
  const links = new Map();
  const sampleXY = [];
  let crsText = "";
  let buf = "";
  let nodeCount = 0;
  let linkCount = 0;
  let headerChecked = false;

  for await (const chunk of ungzipTextChunks(file)) {
    if (!headerChecked) {
      const head = (buf + chunk).slice(0, 200000);
      const m = /coordinateReferenceSystem[^>]*>([^<]+)</i.exec(head);
      if (m) crsText = m[1].trim();
      headerChecked = true;
    }

    buf += chunk;

    while (true) {
      const iNode = buf.indexOf("<node ");
      const iLink = buf.indexOf("<link ");
      let i = -1, kind = "";

      if (iNode === -1 && iLink === -1) break;
      if (iNode !== -1 && (iLink === -1 || iNode < iLink)) {
        i = iNode;
        kind = "node";
      } else {
        i = iLink;
        kind = "link";
      }

      const j = buf.indexOf(">", i);
      if (j === -1) break;

      const tagText = buf.slice(i, j + 1);
      buf = buf.slice(j + 1);

      const a = parseAttrs(tagText);

      if (kind === "node") {
        const id = a.id;
        const x = parseFloat(a.x);
        const y = parseFloat(a.y);
        if (id && Number.isFinite(x) && Number.isFinite(y)) {
          nodes.set(id, [x, y]);
          nodeCount++;
          if (sampleXY.length < 300) sampleXY.push([x, y]);
        }
      } else {
        const id = a.id;
        const from = a.from;
        const to = a.to;
        if (id && from && to) {
          links.set(id, [from, to]);
          linkCount++;
        }
      }
    }

    if ((nodeCount + linkCount) % 20000 === 0 && (nodeCount + linkCount) > 0) {
      setStatus("network解析中… nodes=" + nodeCount + " links=" + linkCount);
      await new Promise(r => setTimeout(r, 0));
    }
  }

  return {nodes, links, crsText, sampleXY};
}

function colorByType(t) {
  if (t === 1) return "#e74c3c";
  if (t === 2) return "#3498db";
  if (t === 3) return "#2ecc71";
  if (t === 4) return "#f1c40f";
  return "#666";
}

function typeFromPersonId(pid) {
  let h = 0;
  for (let i = 0; i < pid.length; i++) {
    h = (h * 31 + pid.charCodeAt(i)) >>> 0;
  }
  return (h % 4) + 1;
}

async function parseEventsToFrames(file, network, zone, wantTypes) {
  const tmParams = tmParamsFromZone(zone);
  const veh2person = new Map();
  const framesMap = new Map();
  const preview = [];
  const firstEvents = [];
  const seenTypes = new Map();

  let carry = "";
  let matched = 0;
  let skippedType = 0;
  let skippedNoLink = 0;
  let skippedNoXY = 0;
  let skippedNoPerson = 0;

  for await (const chunk of ungzipTextChunks(file)) {
    let text = carry + chunk;
    carry = "";

    while (true) {
      const i = text.indexOf("<event ");
      if (i === -1) {
        carry = text;
        break;
      }

      const j = text.indexOf("/>", i);
      if (j === -1) {
        carry = text.slice(i);
        break;
      }

      const tagText = text.slice(i, j + 2);
      text = text.slice(j + 2);

      const a = parseAttrs(tagText);

      if (firstEvents.length < 20) {
        firstEvents.push(JSON.stringify(a));
      }

      const rawType = a.type || "";
      const type = normalizeTypeName(rawType);
      seenTypes.set(rawType, (seenTypes.get(rawType) || 0) + 1);

      if (wantTypes.size && !wantTypes.has(type)) {
        skippedType++;
        continue;
      }

      if (type === "personentersvehicle") {
        const p = a.person;
        const v = a.vehicle;
        if (p && v) veh2person.set(v, p);
        continue;
      }

      let pid = a.person || "";
      if (!pid) {
        const v = a.vehicle || "";
        if (v && veh2person.has(v)) pid = veh2person.get(v);
      }
      if (!pid) {
        skippedNoPerson++;
        continue;
      }

      let x = null;
      let y = null;

      if (a.x !== undefined && a.y !== undefined) {
        x = parseFloat(a.x);
        y = parseFloat(a.y);
        if (!Number.isFinite(x) || !Number.isFinite(y)) {
          skippedNoXY++;
          continue;
        }
      } else if (a.link) {
        const lt = network.links.get(a.link);
        if (!lt) {
          skippedNoXY++;
          continue;
        }

        const p1 = network.nodes.get(lt[0]);
        const p2 = network.nodes.get(lt[1]);
        if (!p1 || !p2) {
          skippedNoXY++;
          continue;
        }

        x = (p1[0] + p2[0]) / 2.0;
        y = (p1[1] + p2[1]) / 2.0;
      } else {
        skippedNoLink++;
        continue;
      }

      const ll = invTM(x, y, tmParams);
      const lon = ll.lon * 180 / Math.PI;
      const lat = ll.lat * 180 / Math.PI;

      if (!Number.isFinite(lon) || !Number.isFinite(lat)) {
        skippedNoXY++;
        continue;
      }

      const sec = Math.floor(parseFloat(a.time || "0"));
      const typeId = typeFromPersonId(pid);

      if (!framesMap.has(sec)) framesMap.set(sec, []);
      framesMap.get(sec).push({
        time: sec,
        person: pid,
        lat: lat,
        lng: lon,
        eventType: rawType,
        typeId: typeId,
      });

      if (preview.length < 80) {
        preview.push(
          sec + "\t" + pid + "\t" + lat.toFixed(6) + "\t" + lon.toFixed(6) + "\t" + rawType + "\tType=" + typeId
        );
      }

      matched++;
      if (matched % 10000 === 0) {
        setStatus(
          "events解析中… matched=" + matched +
          "\nzone=" + zone + " EPSG:" + (6669 + zone) +
          "\nskip type=" + skippedType +
          " noLink=" + skippedNoLink +
          " noXY=" + skippedNoXY +
          " noPerson=" + skippedNoPerson
        );
        setPreview(preview.join("\n"));
        await new Promise(r => setTimeout(r, 0));
      }
    }
  }

  const times = Array.from(framesMap.keys()).sort((a, b) => a - b);
  const frames = times.map(sec => ({
    time: sec,
    items: framesMap.get(sec),
  }));

  return {
    frames,
    matched,
    skippedType,
    skippedNoLink,
    skippedNoXY,
    skippedNoPerson,
    previewText: preview.join("\n"),
    firstEvents: firstEvents,
    seenTypes: Array.from(seenTypes.entries()).sort((a, b) => b[1] - a[1])
  };
}

function secToHHMMSS(sec) {
  const h = Math.floor(sec / 3600);
  const m = Math.floor((sec % 3600) / 60);
  const s = sec % 60;
  return String(h).padStart(2, "0") + ":" +
         String(m).padStart(2, "0") + ":" +
         String(s).padStart(2, "0");
}

function applyFrame(frame) {
  for (const item of frame.items) {
    let marker = personMarkers.get(item.person);
    if (!marker) {
      marker = L.circleMarker([item.lat, item.lng], {
        radius: 5,
        color: colorByType(item.typeId),
        fillColor: colorByType(item.typeId),
        fillOpacity: 0.9,
        weight: 1
      }).addTo(map);
      marker.bindTooltip(item.person, {direction:"top"});
      personMarkers.set(item.person, marker);
    } else {
      marker.setLatLng([item.lat, item.lng]);
      marker.setStyle({
        color: colorByType(item.typeId),
        fillColor: colorByType(item.typeId)
      });
    }

    personState.set(item.person, {
      lat: item.lat,
      lng: item.lng,
      typeId: item.typeId,
      eventType: item.eventType
    });
  }

  timeText.textContent = secToHHMMSS(frame.time);
  agentCount.textContent = String(personMarkers.size);
}

function fitToCurrentMarkers() {
  if (personMarkers.size === 0) return;
  const arr = [];
  for (const m of personMarkers.values()) {
    arr.push(m.getLatLng());
  }
  const bounds = L.latLngBounds(arr);
  map.fitBounds(bounds.pad(0.2));
}

function stopPlayback() {
  if (timer) {
    clearInterval(timer);
    timer = null;
  }
}

prepareBtn.onclick = async function() {
  try {
    prepareBtn.disabled = true;
    playBtn.disabled = true;
    pauseBtn.disabled = true;
    resetBtn.disabled = true;
    stopPlayback();
    clearMarkers();
    currentFrameIndex = 0;
    preparedFrames = [];

    setStatus("network解析開始…");
    parsedNetwork = await parseNetworkStream(networkFile);

    const hint = parseHint();
    const inferred = inferZonesByHint(parsedNetwork.sampleXY, hint.hintLon, hint.hintLat);
    const defaultZone = inferred[0]?.zone || 9;

    zoneSelect.innerHTML = "";
    for (let z = 1; z <= 19; z++) {
      const opt = document.createElement("option");
      opt.value = String(z);
      opt.textContent = "第" + z + "系 (EPSG:" + (6669 + z) + ")";
      if (z === defaultZone) opt.selected = true;
      zoneSelect.appendChild(opt);
    }
    zoneSelect.disabled = false;

    const zoneMsg = inferred.slice(0, 5).map(r =>
      "zone" + r.zone + " median=(" + r.mlon.toFixed(5) + "," + r.mlat.toFixed(5) + ") dist=" + r.dist.toFixed(3)
    ).join("\n");

    setStatus(
      "network解析完了\n" +
      "nodes=" + parsedNetwork.nodes.size + " links=" + parsedNetwork.links.size + "\n" +
      "network記載CRS=" + (parsedNetwork.crsText || "(unknown)") + "\n\n" +
      "候補:\n" + zoneMsg + "\n\n" +
      "events解析を開始してください"
    );

    const typeStr = document.getElementById("types").value.trim();
    const wantTypes = new Set(
      typeStr
        ? typeStr.split(",").map(s => normalizeTypeName(s)).filter(Boolean)
        : []
    );

    const zone = parseInt(zoneSelect.value, 10) || defaultZone;

    setStatus("events解析中… zone=" + zone + " EPSG:" + (6669 + zone));
    const result = await parseEventsToFrames(eventsFile, parsedNetwork, zone, wantTypes);

    preparedFrames = result.frames;
    setPreview(result.previewText);

    const seenTypeText = result.seenTypes
      .map(([name, cnt]) => name + "=" + cnt)
      .join("\n");

    setStatus(
      "解析完了\n" +
      "frames=" + preparedFrames.length + "\n" +
      "matched=" + result.matched + "\n" +
      "skip type=" + result.skippedType +
      " noLink=" + result.skippedNoLink +
      " noXY=" + result.skippedNoXY +
      " noPerson=" + result.skippedNoPerson + "\n\n" +
      "events内のtype一覧:\n" + seenTypeText + "\n\n" +
      "先頭event例:\n" + result.firstEvents.join("\n")
    );

    if (preparedFrames.length > 0) {
      applyFrame(preparedFrames[0]);
      fitToCurrentMarkers();
    }

    playBtn.disabled = false;
    pauseBtn.disabled = false;
    resetBtn.disabled = false;
  } catch (e) {
    setStatus("エラー: " + (e?.message || e));
  } finally {
    prepareBtn.disabled = false;
  }
};

playBtn.onclick = function() {
  if (!preparedFrames.length) return;
  stopPlayback();

  const speed = parseFloat(document.getElementById("speed").value || "20");
  const intervalMs = 100;

  timer = setInterval(() => {
    if (currentFrameIndex >= preparedFrames.length) {
      stopPlayback();
      return;
    }

    const frame = preparedFrames[currentFrameIndex];
    applyFrame(frame);

    const nextIndex = currentFrameIndex + 1;
    if (nextIndex < preparedFrames.length) {
      const dt = preparedFrames[nextIndex].time - frame.time;
      const step = Math.max(1, Math.floor(Math.max(1, dt) / Math.max(0.1, speed)));
      currentFrameIndex += Math.max(1, step);
    } else {
      currentFrameIndex++;
    }
  }, intervalMs);
};

pauseBtn.onclick = function() {
  stopPlayback();
};

resetBtn.onclick = function() {
  stopPlayback();
  clearMarkers();
  currentFrameIndex = 0;
  if (preparedFrames.length > 0) {
    applyFrame(preparedFrames[0]);
    fitToCurrentMarkers();
  }
};
</script>
</body>
</html>
`))

2026,江端さんの忘備録

本日は、朝からグッタリしています。昨夜の悪夢で、相当に疲れてしまったからです。
I have been completely exhausted since this morning, because last night’s nightmare drained me considerably.

私が、早朝覚醒型の不眠症であることは、これまでも何度かお話してきました。そして、この対応策として「自律神経訓練法」と、精神安定剤(セルシン)の投与で対応しているというお話もしました。
I have mentioned several times before that I suffer from early-morning awakening insomnia. As a countermeasure, I have been using “autogenic training” and taking a tranquilizer (Cercine).

セルシンの投与が、悪夢を誘発しやすくなることは、こちらにも書きました。
I have also written that taking Cercine tends to make nightmares more likely.

『「薬剤(特にベンゾジアゼピン系)の副作用として「生々しい夢」や「悪夢の頻発」が報告されており、医学的にも無矛盾」となる理由を教えて下さい』とChatGPTに聞いてみた件

ただ、今回の悪夢は、セルシンの摂取前に見たもので、しかも、寝入り端の2時間ほどで発生しました。
However, this particular nightmare occurred before I had taken Cercine, and it appeared about two hours after I had fallen asleep.

---

昨夜、就寝前に、現在の連載の初回をレビューしていたのですが、どうやら、それが、悪夢を誘引させてしまったようです。
Last night, before going to bed, I was reviewing the first installment of my current series, and apparently that ended up triggering the nightmare.

(↑Jump to the column)

『"動かないシステム"というのは、本当に怖い』
“A system that doesn’t run is truly frightening.”

そして、
And,

『今まで動いていたシステムに、ちょっとした変更を加えたら、動かなくなることは死ぬほど恐しい』
“If you make a small change to a system that has been working and it suddenly stops running, that is terrifying beyond words.”

さらに、
Furthermore,

『元の状態に戻しても、再起動しないシステムというのは、PTSD(心的外傷後ストレス障害)になるレベルの恐怖である』
“A system that refuses to reboot even after reverting to the original state is frightening enough to cause PTSD (Post-Traumatic Stress Disorder).”

という、システムエンジニアの三大悪夢がフラッシュバック(再体験)するのは ―― 心底疲れるものです。
Having the three great nightmares of system engineers flash back (re-experienced) like that is utterly exhausting.

---

いや、PTSDという言葉を、こんなことで使うのは適切ではないのかもしれません。
Well, perhaps it is not appropriate to use the word PTSD in a situation like this.

PTSD(心的外傷後ストレス障害)とは、交通事故や災害、戦争、暴力など、強い恐怖や衝撃を伴う出来事を体験した後、その影響が長く続き、日常生活に支障をきたす精神的な状態のことです。
PTSD (Post-Traumatic Stress Disorder) refers to a psychological condition in which the effects of a traumatic event, such as a traffic accident, disaster, war, or violence, persist for a long time and interfere with daily life.

システムの停止程度のことで、この言葉を使うのは、やはり大袈裟でしょう。
Using that term for something like a system outage is, admittedly, an exaggeration.

それでも、システム開発、特にバックエンドを担当するエンジニアにとって、システム停止の恐怖は、かなり本気で胃に来るものなのです。
Even so, for engineers involved in system development?especially those responsible for the backend, the fear of a system failure genuinely hits the stomach.

たった1人で作っているようなシステム(またはサブシステム)の開発の場合は、特にそうです。
This is especially true when developing a system (or subsystem) built by a single person.

―― 他人のせいにできないシステム開発は、悪夢
"System development where you cannot blame anyone else is a nightmare."

です。
That is the reality.

こういうのは、たいていの場合、ファームウェアやミドルウェア、またはOSが悪さをしていることがあり、そのエンジニア一人が責を負わされるものではないはずなのですが、そういう理屈が"通じない"のが、この世界のしきたりです。
In many cases, the real culprit may be firmware, middleware, or the OS, and it should not be that engineer's sole responsibility. However, such reasoning rarely works in this world.

「他人が作ったモノに問題があれば、それを見付け出す。見つけ出した上で、その問題を回避する手段を考える」までが、『ワンオペエンジニア』の宿命です。
If there is a problem in something created by someone else, you must find it, and once you find it, you must devise a way to work around it. That is the fate of a “one-operator engineer.”

---

私、今期の仕事(今期の仕事も)、しんどかったです。
My work this term (and this term as well) has been quite exhausting.

- 当初の私の仮説を裏切る、膨大な計算結果の数々
- A vast number of computational results that betrayed my initial hypothesis

- 商用クラウドを使ったファイアウォールシステムの実装(×提案)
- Implementing (not merely proposing) a firewall system using a commercial cloud

『実装は研究員の仕事ではない』というのは、私の信条に反します。私の中にいる、エンジニアの私が私にこう言うからです。
The idea that “implementation is not a researcher’s job” runs counter to my beliefs. The engineer inside me says this to me.

―― お前、実際に動かすこともできないシステムを"提案"だけして、逃亡するのか?
"Are you going to propose a system you cannot actually run, and then run away?"

と。
That is what it says.

いや、「私の中のエンジニア」が言わなくても、研究依頼元や上司がそう言いますけどね。
Even if the engineer inside me did not say it, the client or my supervisor probably would.

だから、まあ、プロトタイプシステムでの稼動が確認できた時は ――― もう、そりゃあ『ヨッシャーーーー!』と、一人部屋の中で、拳を振り上げて、雄叫びを上げることになります。
So when the prototype system finally confirms operation, I end up shouting “YESSSSS!” alone in my room, raising my fist and roaring in triumph.

比して、稼動が確認できない日々の連続は、陰鬱とした時間が続くことになります。
In contrast, days when the system refuses to run are filled with gloom.

---

それに比べて、特許明細書や報告書やプレゼンテーションや論文は、(教授や上司や関連部門からツッコミは受けますが)、いつかは終了します、が、
Compared to that, patent specifications, reports, presentations, and papers, although they receive comments from professors, supervisors, and related departments, are not. will eventually come to an end.

―― 動かないシステムは、動かすまでは終わらない
"A system that does not run will not end until it runs."

これが、ドキュメンテーションとシステム開発の決定的な違いです。
That is the decisive difference between documentation work and system development.

どちらが良いとか悪いではないのですが、私の立場としては、『動かないシステム』に心を削られる日々に比べれば、100ページのドラフト作成などは、恐怖の対象ではありません ―― だって、睡眠時間を削れば、いつかは終わるのですから。
Neither is inherently better or worse, but from my perspective, compared to the days when a non-working system gnaws at my nerves, writing a 100-page draft is not something to fear because if I sacrifice enough sleep, it will eventually be finished.

---

いや、こういう言い方は、卑怯(我田引水)だな。
Well, putting it that way is a bit unfair (self-serving).

同じように「終わるまで終われない」仕事は、世の中にいくらでもあります。
Many jobs in this world do not end until they are finished.

- 営業はノルマが果たされなければ終わらない
- Salespeople cannot finish until their quotas are met.

- 作家は原稿を書き上げなければ終わらない
- Writers cannot finish until the manuscript is written.

- 裁判官は判決を書かなければ終わらない
- Judges cannot finish until the verdict is written.

- 農家は収穫しなければ終わらない
- Farmers cannot finish until the harvest is completed.

- 職人は品物を完成させなければ終わらない
- Craftsmen cannot finish until the product is completed.

これらの仕事も、「途中までがんばった」ということには、ほとんど価値が認められない種類の業務でしょう。
These jobs, too, are the kind where “I tried hard halfway through” is rarely considered valuable.

そういえば、
Come to think of it,

- 育児は子どもが自力でメシを食えるようになるまでは終わらない
- Parenting does not end until the child can feed themselves.

というのも、ここに加えてよいかもしれません。
That may also deserve to be added to the list.

---

動かないシステムは、動くまで終わらない。
A system that does not run does not end until it runs.

そして、動かない理由は、たいてい、すぐには分からない。
And the reason it does not run is usually not immediately clear.

しかも、その理由が自分のコードなのか、OSなのか、ミドルウェアなのか、ファームウェアなのか、あるいは宇宙線なのか―― それを切り分けるのも、『ワンオペエンジニア』です。
Moreover, determining whether the cause lies in your code, the OS, the middleware, the firmware, or perhaps even cosmic rays also falls to the “one-operator engineer.”

そういう仕事をしている人間が、夜中にシステムの停止を夢に見るというのは、まあ、自然なことなのでしょう。
So it may be only natural that someone doing such work dreams about system failures in the middle of the night.

……とはいえ、昨夜の夢は、ちょっと酷かった。
…Even so, last night’s dream was rather brutal.

悪夢で一度目が覚めて、『ああ、夢だった。よかった』と思って再び眠りに落ちたのですが、昨夜の悪夢は、悪夢のまま無矛盾のまま継続したのです。
I woke up once from the nightmare and thought, “Ah, it was just a dream. Thank goodness,” and fell asleep again, but the nightmare resumed seamlessly, without contradiction.

―― 悪夢のインターミッション(休憩)
"An intermission in a nightmare."

いや、本当に、悪夢にそんなサービスはいらないです。
Honestly, nightmares do not need such a service.

今朝の悪夢は、もうメチャクチャです。

未分類

参政党は外国人の何を問題としているのですか?

参政党が「外国人問題」として主張している内容は、いくつかの論点に分かれている。大きく整理すると、次の4つである。


1. 外国人労働者の増加

参政党が最も強く問題視しているのは、外国人労働者の受け入れ拡大である。

主張の骨子は次の通り。

  • 日本人の賃金が下がる可能性
  • 日本人の雇用機会が減る可能性
  • 技能実習・特定技能制度が「実質的移民政策」になっている
  • 低賃金労働力として利用されている

つまり
「日本は移民国家ではないのに、事実上の移民政策になっている」
という批判である。


2. 外国人による土地・不動産取得

参政党は、外国人(特に海外資本)が日本の土地を取得する問題も指摘している。

例として挙げられるのは

  • 水源地周辺の土地取得
  • 自衛隊基地周辺
  • 農地の取得

主張は

「安全保障の観点から規制が必要」

というもの。

これは参政党だけでなく、
自民党の一部や安全保障関係者も問題提起している論点である。


3. 社会保障・生活保護

外国人に対する社会保障の扱いについても問題提起している。

主張の例:

  • 外国人への生活保護は見直すべき
  • 社会保障は日本国民を優先すべき

ただし実際には

  • 外国人生活保護受給率は日本人より低い
  • 法的には「生活保護法対象ではなく行政措置」

という複雑な制度になっている。


4. 文化・社会秩序の問題

もう一つの主張は

文化的摩擦

である。

例として挙げられるのは

  • 地域コミュニティとの摩擦
  • ゴミ出し・生活習慣の違い
  • 学校教育の問題

この点について参政党は

「日本文化を守るべき」

という主張をしている。


まとめ(参政党の問題設定)

参政党の主張を整理すると、外国人そのものではなく

①移民政策化
②安全保障
③社会保障
④文化摩擦

の4点を問題にしている構図である。

ただし重要なのは、
これらの論点の中には

  • 事実として存在する政策問題
  • 誇張されている可能性のある問題

が混在していることである。


もし希望があれば、さらに踏み込んで

  • 参政党の外国人政策の実際の内容(公約)
  • なぜこのテーマが支持を集めているのか
  • データで見る外国人問題の実態

なども解説できる。
実は、このテーマは日本政治の構造をかなりよく表している。

参政党の主張に対して、ファクトチェックをお願いします。

参政党が主張している「外国人問題」について、主要な論点ごとに事実関係(統計・制度)と主張との関係を整理する。ここでは評価ではなく、公開データに基づくファクトチェックとして説明する。


1 外国人労働者増加は「移民政策」なのか

参政党の主張

「日本は移民政策を取っていないと言いながら、実質的には移民政策になっている」

事実

日本の外国人労働者数は確かに増えている。

  • 外国人労働者数
    • 2013年:約72万人
    • 2023年:約204万人

つまり約10年で約3倍になっている。

これは主に

  • 技能実習制度
  • 特定技能制度(2019開始)

によるものである。

ファクト評価

この点については

主張は概ね事実に基づいている

理由
政府自身が

「移民政策ではない」

と説明している一方で、

  • 長期滞在
  • 家族帯同(特定技能2号)

が可能になっており、

多くの研究者が

「実質的には移民政策に近い」

と指摘している。

ただし

外国人比率は

  • 日本:2.7%
  • ドイツ:約18%
  • フランス:約13%

であり、国際比較ではまだ低い


2 外国人による土地取得問題

参政党の主張

外国人が日本の土地(水源地・基地周辺)を買っている。

事実

外国人による土地購入は可能である。
日本には国籍による土地購入規制がほぼ存在しない。

ただし統計を見ると

外国人所有土地の割合は

全国で1%未満と推定されている。

また問題視されることの多い

「水源地買収」

については

具体的な被害事例はほとんど確認されていない。

ただし安全保障上の懸念から

2021年に

重要土地等調査法

が成立し

  • 自衛隊基地
  • 原発
  • 国境離島

周辺の土地利用を調査できるようになった。

ファクト評価

  • 外国人が土地を購入できる → 事実
  • それが広範な問題になっている → 証拠は限定的

つまり

制度的問題はあるが、被害規模は不明確

という状態である。


3 外国人の生活保護

参政党の主張

外国人が生活保護を受けている。

事実

外国人の生活保護受給は

法律上の権利ではない。

しかし

1954年の厚生省通知により

「人道的措置」

として支給されている。

受給者数

  • 外国人世帯:約4.7万世帯
  • 全体:約164万世帯

割合

約2〜3%

である。

外国人の人口割合は

約2.7%なので

人口比とほぼ同程度

である。

ファクト評価

  • 外国人が生活保護を受けている → 事実
  • 外国人が多く受給している → 統計上は確認できない

4 外国人犯罪増加

参政党支持層の議論でよく出る論点。

事実

外国人刑法犯検挙数

  • 2005年:約43,000件
  • 2022年:約10,000件

つまり

大幅に減少している。

また人口比でも

外国人犯罪率は

日本人と大差ない

とされている。

ファクト評価

「外国人犯罪が急増している」

という主張は

統計とは一致しない。


まとめ

参政党の外国人問題について、データとの関係を整理すると次のようになる。

論点 ファクト評価
外国人労働者増加 事実
日本が実質移民化 議論あり
外国人土地取得 制度的には可能
水源地買収問題 根拠は限定的
外国人生活保護 事実だが割合は人口比程度
外国人犯罪増加 データと一致しない

最後に重要なのは、この問題は単純な

「正しい/間違い」

ではなく

①人口減少
②労働力不足
③安全保障
④社会統合

という政策設計の問題であるという点である。


もし興味があれば、かなり面白い分析として

「なぜこのテーマで参政党が支持を伸ばしているのか」

を政治学・社会心理の観点から説明できる。
これは日本の政治構造のかなり核心に触れる話になる。

「なぜこのテーマで参政党が支持を伸ばしているのか」をお願いします

参政党が「外国人問題」を強く掲げることで支持を伸ばしている理由は、単純に政策の中身というより、社会心理・政治構造・メディア環境の3つの要因が重なっていると分析されている。主なポイントを整理する。


1 「不安の受け皿」としてのテーマ

日本社会では近年、次のような構造的な不安が広がっている。

  • 人口減少
  • 地域の衰退
  • 賃金停滞
  • 社会保障への不安
  • 治安や文化の変化への漠然とした不安

こうした不安は本来、

  • 経済政策
  • 産業構造
  • 社会制度

などの複雑な問題に関係している。

しかし人間の心理として、複雑な問題よりも「分かりやすい原因」を求める傾向がある。

そのため政治的には

「外国人問題」

というテーマが

不安の象徴的な対象

として機能しやすい。


2 既存政党が触れにくいテーマ

日本の主要政党(自民・立憲など)は、外国人問題を

  • 人権問題
  • 国際関係
  • 経済政策

とのバランスで扱う必要があるため、比較的慎重な表現を取る。

結果として

問題を率直に語る政治勢力が少ない

という状況が生まれる。

そこに

  • 参政党
  • 一部の保守系政治団体

が入り込み、

「他の政党が言わないことを言う」

という構図が成立する。

これは政治学で

ニッチ政党戦略

と呼ばれる典型的なパターンである。


3 SNS政治との相性

外国人問題は

  • 感情的
  • 分かりやすい
  • 短い言葉で伝えられる

という特徴があり、SNSと非常に相性が良い。

例えば

  • 「日本人が損をしている」
  • 「日本を守れ」

といったメッセージは、短い動画や投稿で拡散しやすい。

近年の日本政治では

SNSを通じて支持を広げる新興政党が増えており、参政党もその典型例とされている。


4 国際的に見ても典型的な現象

この現象は日本だけではない。

欧米でも似たパターンがある。

例:

  • フランス
    • マリーヌ・ル・ペン
  • ドイツ
    • ドイツのための選択肢
  • イタリア
    • ジョルジャ・メローニ

いずれも

  • 移民問題
  • 文化アイデンティティ
  • 国家主権

をテーマに支持を拡大している。

つまり参政党の現象は

世界的な政治トレンドの日本版

とも言える。


まとめ

参政党がこのテーマで支持を伸ばしている理由は主に次の4点である。

  1. 社会的不安を象徴するテーマになりやすい
  2. 既存政党が扱いにくい領域である
  3. SNS政治と相性が良い
  4. 世界的なポピュリズム政治の流れと一致している

もし興味があれば、もう一歩踏み込んだ分析として

「参政党支持層の特徴(年齢・職業・心理)」

も説明できる。
実はここに、日本社会のかなり深い構造が見える。

「参政党支持層の特徴(年齢・職業・心理)」もお願いします。

参政党の支持層については、まだ大規模な学術研究が十分に蓄積されているわけではない。ただし、選挙分析・世論調査・政治学者の観察などから、ある程度共通した傾向が指摘されている。主に「年齢」「職業・社会階層」「心理」の3つの側面で整理できる。


1 年齢層の特徴

既存政党と比べて、参政党支持層はやや特徴的な分布を持つと指摘されている。

比較的多い層:

  • 30〜50代
  • 子育て世代

これは、参政党が初期に

  • 食品安全
  • ワクチン
  • 教育
  • 子どもの健康

といったテーマを強く扱ったことと関係していると考えられる。

一方で

  • 70歳以上の高齢層

は自民党支持が依然として多い傾向がある。


2 職業・社会階層

研究者の分析では、参政党支持者には次のような傾向が見られるとされる。

比較的多いとされる層:

  • 自営業
  • 中小企業経営者
  • フリーランス
  • 会社員(中間管理職層)

共通する特徴は

「既存の大組織に強く依存していない」

ことである。

例えば

  • 公務員
  • 大企業正社員

などは既存政党支持が比較的多い。


3 都市 vs 地方

地域的には

  • 地方都市
  • 郊外地域

で一定の支持が見られる。

これは

  • 地域衰退
  • 人口減少
  • 外国人労働者増加

などを体感しやすい地域であることが関係していると考えられている。


4 心理的特徴(政治心理学)

政治心理学の観点からは、次の特徴が指摘されることが多い。

(1) 既存制度への不信

例:

  • 政府
  • 大企業
  • メディア
  • 医療制度

への不信が比較的強い傾向。

これは

  • コロナ政策
  • ワクチン政策

などをめぐる議論と関係していると分析されている。


(2) 自己決定志向

参政党の支持者は

  • 自分で調べる
  • 自分で判断する

という価値観を重視する傾向があると言われる。

そのため

  • オルタナティブメディア
  • YouTube
  • SNS

から情報を得る割合が高い。


(3) ナショナル・アイデンティティ

政治心理学では

「文化的アイデンティティの保護」

という動機も指摘される。

これは

  • 日本文化
  • 伝統
  • 食の安全
  • 家族観

などを重視する価値観と結びついている。


5 まとめ

現在の研究から見える参政党支持層の典型像をまとめると次のようになる。

項目 傾向
年齢 30〜50代
家族構成 子育て世代
職業 自営業・フリーランス・会社員
地域 地方都市・郊外
心理 既存制度への不信・自己決定志向

ただし重要なのは、

支持層は決して単一ではない

という点である。

  • 保守層
  • オルタナティブ志向層
  • 政治不信層

など、複数のグループが重なっている。


もし希望があれば、もう一歩踏み込んで

「参政党支持者と“陰謀論”の関係(かなり誤解が多い)」

についても、研究結果を踏まえて説明できる。これはかなり興味深いテーマである。

未分類

先程、昼食を作るためにリビングに降りていったところ、嫁さんが、NetFlixでワールドベースボールクラッシック(WBC)を見ていました。

ベネゼエラ v.s. 日本 で、ちょうど、ベネゼエラの選手が逆転ホームランを打ったところでした。

『ベネゼエラって、あのベネゼエラだよなぁ?』

―― と、思わず口に出してしまいました。

---

そういえば、ついこの前までニュースでは、ベネゼエラの大統領が米国の作戦で拘束されたとか、国外に連行されたとかいう話を見ていた気がします。国際政治のニュースでは、かなり物騒な話題として扱われていたはずです。

しかし、テレビの中では、そのベネゼエラの選手が、見事な逆転ホームランを打ってベースを回っています。スタンドは大歓声で、実況も興奮気味です。

政治ニュースで見る国名と、テレビの中でホームランを打っている国名が、頭の中でうまく結びつかないのです。

―― 政教分離ならぬ、政球分離(せいきゅうぶんり)といってもいいのかな

世界情勢とスポーツ中継というのは、どうやら、同じ国名でも、まったく別の世界の話として進行するものらしい、と思いました。

また、WBCとオリンピックやパラリンピックとも、随分な違いがあるのだなぁ、とも。

---

オリンピックでは、例えばロシアのように、国家として問題があると判断された場合、国旗や国名での参加が認められなかったり、場合によっては出場自体が制限されたりします。

ところが、WBCでは、国家元首が国外に連行されるような事件があっても、その国の代表チームは普通に試合をしています。

つまり、

オリンピックは政治問題で選手の扱いが変わることがあるが、WBCでは政治問題があっても試合は普通に続く

という違いがあるようですが ―― なんか違和感がありまして。

とはいえ、政球分離(せいきゅうぶんり)は、正しいと思います。

オリンピックにあっても、政競分離(せいきょうぶんり)(政治(政)と競技(競)の分離)であることが、そもそもオリンピックの精神だったと思いますが、政治とオリンピックがベタベタなのは、今に始まったことではありません。

---

この「政治とオリンピックがベタベタ」という構図は、実は今に始まった話ではありません。

例えば、日本でも経験があります。1980年のモスクワ五輪では、ソ連のアフガニスタン侵攻に対する抗議として、米国主導のボイコットに日本も参加し、結局、日本選手団は出場できませんでした。

その4年後の1984年ロサンゼルス五輪では、今度はソ連や東欧諸国が「安全上の理由」を名目に大会をボイコットしました。

さらに遡れば、1936年のベルリン五輪はナチス政権の国威発揚の舞台として利用されましたし、1968年メキシコ五輪では、アメリカの黒人選手が表彰台で人種差別への抗議を示すブラックパワー・サリュートを行いました。

1972年ミュンヘン五輪では、イスラエル選手団がパレスチナ武装組織に襲撃されるという事件まで起きています。

最近でも、ロシアの国家ドーピング問題で国旗の使用が制限されたり、ロシアのウクライナ侵攻後には参加資格そのものが議論されたりと、政治問題はオリンピックと常に絡み続けています。

つまり、

「政治とスポーツは分けるべきだ」という理念は昔から存在するものの、現実のオリンピックは、ほぼ常に政治と一緒に動いてきた

と言ってしまっても、あまり間違いではない気がします。

―― そう考えると、

WBCで普通に試合が続いている光景の方が、むしろ「本来の政競分離」に近いのかもしれない、などと、ちょっとだけ思いました。

2026,江端さんの忘備録

先日、「下を向いて歩こう」というコラムを掲載しました。
The other day, I published a column titled "Walk Looking Down."

もう一つの『下を向いて歩こう』の意義は、「高い目標を目指して歩む人生は、大体『コケる』」という、私の経験則です。

その話を家族でしていたところ、「『下を向いて歩こう』という生き方は、実際には成立しにくいのではないか」という指摘を受けました。
When I was talking about it with my family, someone pointed out that "a way of life based on ‘walking while looking down’ might actually be difficult to sustain in reality."

嫁さんが独身時代に働いていた銀行のような組織では、同期のライバルと競争しながら昇進を目指すことが当然であり、多くの人が常に"上"を目指して働いている、という経験談です。
She spoke from her experience working at a bank before we married, where it was natural to compete with peers for promotion, and where many people constantly worked aiming "upward."

このような環境では、「上を目指さない」という選択肢が実質的に存在しません。
In such an environment, the option of "not aiming upward" practically does not exist.

上昇を目指さなければ、そのまま留まるのではなく、むしろ"下に落ちる"という感覚になる。つまり、「自分の望む位置で安定して停止する」という状態が成立しないのです。
If one stops aiming upward, it does not mean remaining in place; rather, it feels like "falling downward." In other words, a state in which one can stabilize at a desired position does not exist.

その話を聞いて、
Hearing that,

―― なんという不安定な系だ
"I thought what an unstable system."

と思いました。
That was my reaction.

しかし、他の仕事では、この不安定な系がデフォルトのようです。特に、営業職では、この傾向が顕著で、世界観そのものが「上か下か。勝つか負けるか」によって構成されている場合が多いようです。
However, in many other professions, this unstable system seems to be the default. In particular, in sales jobs, this tendency is pronounced, where the worldview itself is often structured around "up or down, win or lose."

競争を続けること自体が仕事の一部であり、常に順位や成果が比較される環境では、「戦い続けること」が前提となります。
In environments where competition itself is part of the job, rankings and performance are constantly compared, and continuing to fight is taken as a given.

(なお、ここで述べられているのは、いわゆる「昭和的」な企業文化の経験談であり、現在の社会をそのまま正確に反映しているかは不明です)
(Incidentally, this refers to experiences from what might be called "Showa-era corporate culture," and it is unclear whether it accurately reflects present-day society.)

嫁さんは、私の働き方を見て驚いた、と言っていました。
My wife said she was surprised by the way I work.

- 仕事でありながら、「人と戦う」という視点がない
Even though it is work, there is no sense of "fighting other people."

- 仕事が競争の体をなしていない。
The job does not take the form of competition.

- 自分の内で完結しているように見える
It appears to be self-contained within oneself.

ということが、とても奇妙に感じた、とのことでした。
She said these things felt very strange to her.

それを聞いた私は、『それでは、まるで研究職が"ラク"な職業のように見える』と思いました。
Hearing that, I thought, "That would make research jobs look like an easy profession."

本当に、"ラク"なら本当に良いのですが、(他の人は知りませんが)私には全然"ラク"ではありませんでした。
If it really were easy, that would be wonderful, but (I cannot speak for others) it has never been easy for me.

研究職が他の職業より、「下を向いて歩こう」ができるのは否定できませんが、「下を向いて歩こう」は、"ラク"を意味している訳ではないのです。
It may be true that research jobs allow one to "walk looking down" more than other professions, but that does not mean the work is easy.

---

まず、"人"とは戦わないかもしれないが、"未知の課題"とは、四六時中バトルを繰り返しています。
First of all, we may not fight "people," but we battle "unknown problems" around the clock.

つまり、私たちは、『まだ、この世の中に出てきていない問題を掲げて、その解決手段を見つけ出さなければならない』というミッションを与えられています。
In other words, we are given the mission of identifying problems that do not yet exist and finding ways to solve them.

もちろん、この解決手段には、色々(お金とか政治力とか戦争とか)ありますが、私たちは、この手段が『技術しばり』になっています。
Of course, there are many possible ways to solve problems, such as money, political power, or even war, but for us, the constraint is that the solution must be technological.

『技術』というのは、基本的には「誰でもその恩恵を受けられる」という普遍的で公平な手段です。
Technology, in principle, is a universal and fair means that can potentially benefit anyone.

実際は資金力とか特許権とか技術力などがあり、完全に公平に恩恵を受けられる訳ではありませんが ―― 気合と、十分に長い時間を投資すれば、おおむね"公平"を担保できる手段です。
In reality, of course, funding, patents, and technological capability matter, so it is not perfectly fair, but with enough determination and enough time invested, it can roughly maintain fairness.

ところが、この"未知の課題"を解決する手段というのが ―― 恐ろしく難しい。難しいから"未知の課題"になっているのです。
However, finding a way to solve these "unknown problems" is extraordinarily difficult indeed; that difficulty is precisely why they are unknown problems.

それを『なにがなんでも解決しろ。1年以内に』てなこと、普通に言われるのが研究職です ―― 胃が痛いですよ、特に今のような年度末で、研究報告書を書かなければならない時期は、最悪です。
And yet researchers are often told things like, "Solve it no matter what within a year." It is enough to give you stomach pain, especially around the end of the fiscal year when research reports must be written.

ニュースで、桜の開花報告など聞くころになると ―― 気分は『断崖絶壁で、刑事に追いつめられた殺人犯』のような気分です。
By the time the news begins reporting the cherry blossoms blooming, I feel like a criminal cornered by a detective at the edge of a cliff.

---

ただ、"未知の課題"の"技術による解決方法"が『ない』、なんてことは普通にあります。当然です。
However, it is quite common for there to be no technological solution to an unknown problem. That is only natural.

そんなものがあれば、世界中の課題は全部『技術だけ』で解決できるはずです。
If such solutions always existed, every problem in the world could be solved purely by technology.

例えば、どこぞの米国大統領が、一方的に反米の国に軍事力をぶつけたりすることなんて必要ないのです ―― 石油以外のエネルギー生成手段が、世界中のどこでも無尽蔵に産み出せる技術があれば、ホルムズ海峡なんぞ、封鎖どころか、埋め立てして貰っても、全然OKです。
For example, would a U.S. president not need to use military force against anti-American countries unilaterally? If we had technology capable of generating limitless energy everywhere without relying on oil, the Strait of Hormuz being blocked would hardly matter.

そんな時(『ない』時)、研究員はどうすればいいのか?
So what should researchers do when such solutions do not exist?

―― あは。ダメでした。テヘペロ
"Ah, well. It didn’t work. Oops."

なんてことが許されるなら、研究員は世界でもっとも"ラク"な職業となっているはずです。
If that were acceptable, researchers would surely have the easiest job in the world.

違うんですよ。もっと過酷な命題を突き付けられるのです。
But that is not how it works. We are given a far harsher task.

『なぜ、これが技術的に解決できないのかを、論理的に説明せよ』という任務に置き換わるのです。
Instead, the task becomes: "Explain logically why this cannot be solved technologically."

これはどういうことか。
What does that mean?

―― 世界中で、あと1000人の研究員と、1兆円の資金と、100年の期間を投入しても"解決不能である"ことを証明せよ
"Prove that even if 1,000 more researchers, one trillion yen in funding, and a hundred years were invested worldwide, the problem would remain unsolved."

てなことを言われるのです。この、絶望的な証明をするのも、また研究員の仕事なのです。
In effect, that is what we are asked to do. Producing such a hopeless proof is also part of a researcher’s job.

これ、技術的に解決する手段を見つけるよりも難しい。しかし、それができない研究員は、研究員として食っていけないのです。
Sometimes this is even harder than finding a technical solution. Yet a researcher who cannot do this cannot survive.

ね? いやでしょ? こんな仕事。
See? Not a pleasant job, is it?

でも、そうして私たち研究員は日々を凌いで、飯を喰っているわけですよ。
And yet, in this way, we researchers manage to get through our days and earn our living.

で、そのような「絶望的な証明」が結果としては『ウソ』だった、ということも結構あったりするんですよ。
And sometimes those "hopeless proofs" later turn out to be wrong.

私が知る限り2つあります。
I know at least two examples.

太陽光発電(の商用利用)と、(一般人が普通に使えるAI)です。
Commercial solar power generation and AI that ordinary people can use in everyday life.

30年前には、この2つ、絶対に無理だと言われていたのです。
Thirty years ago, both were said to be impossible.

---

当時の議論を思い出すと、太陽光発電については「コストが高すぎる」「発電効率が低すぎる」「面積が必要すぎる」といった理由が並べられていました。
Looking back at the discussions at the time, arguments about solar power often listed reasons such as "the cost is far too high," "the power generation efficiency is too low," and "it requires too much area."

電力を支える基幹エネルギーになるなどという話は、ほとんど誰も真面目には受け取っていなかったと思います。研究としては面白いが、社会の主役になる技術ではない、という位置づけでした。
The idea that it could become a core energy source supporting the electric power system was not taken seriously by almost anyone. It was considered interesting as research, but not a technology that would become a main player in society.

AIも同じです。音声認識も画像認識も、研究室の中では動くけれど、一般の人が日常的に使うものにはならない、と言われていました。
AI was the same. Speech recognition and image recognition worked inside laboratories, but people said they would never become something ordinary people could use in everyday life.

計算量が大きすぎる、データが足りない、精度が実用レベルに届かない、など、もっともらしい理由が山ほど並んでいたのを覚えています。
I remember many plausible reasons being listed: the computational requirements were too large, the data was insufficient, and the accuracy did not reach practical levels.

ところが、結果としてどうなったか。
And yet, what happened in the end?

---

太陽光発電は、いつの間にか電力システムの一角を担う技術になりました。効率は上がり、コストは下がり、世界中の屋根や空き地にパネルが並ぶ時代になりました。
Solar power quietly became one of the technologies supporting the power system. Efficiency improved, costs fell, and we entered an era in which panels appear on rooftops and on open land across the world.

AIについては、もはや説明するまでもありません。いまや一般の人が、日常的にAIを使って文章を書いたり、翻訳したり、画像を作ったりする時代です。
As for AI, it hardly needs explanation anymore. We now live in a time when ordinary people routinely use AI to write text, translate languages, and create images.

つまり、「技術的に無理だ」と言われていたことが、ある日突然、当たり前の技術になってしまうことがあるのです。
In other words, things once deemed "technically impossible" can suddenly become ordinary technologies.

もちろん、研究員が「これは無理です」と説明したとき、それが間違いだったというわけではありません。その時点での技術水準、コスト、社会条件を前提にすれば、確かに『無理』だったのです。
Of course, when researchers said "this is impossible," it does not mean they were wrong. Given the technological level, costs, and social conditions at that time, it truly was impossible.

しかし技術というのは、ある時点までは全く動かないように見えて、ある閾値を越えると急に状況が変わることがあります。
However, technology sometimes appears stagnant for a long time, and then suddenly the situation changes once a certain threshold is crossed.

材料、製造技術、計算能力、社会制度など、いくつもの条件が重なった瞬間に、突然「できる技術」になってしまうのです。
At the moment when various conditions, materials, manufacturing technology, computational power, and social systems come together, something can suddenly become a "possible technology."

---

ですから、研究員が「技術的に解決できない」と説明するとき、それは「未来永劫不可能」という意味ではありません。「少なくとも、現在の技術体系の延長線上では、解決の見通しが立たない」という意味なのです。
Therefore, when researchers say that something "cannot be solved technologically," it does not mean it is impossible forever. It means that, at least within the current technological framework, there is no foreseeable solution.

そして、研究員にとって厄介なのは、その「延長線上では無理」という判断が、いつ覆るか分からないということです。
And what makes this troublesome for researchers is that no one knows when that judgment, "impossible along the current trajectory," will be made. may be overturned.

つまり私たちは、『解決できるかもしれない問題』と『本当に解決できない問題』の境界線の上で、ずっと作業を続けているようなものです。
In other words, we continue working along the boundary between "problems that might be solvable" and "problems that truly cannot be solved."

この境界線は、霧の中にあります。どこまでが可能で、どこからが不可能なのか、はっきり見えません。
This boundary lies in the fog. It is impossible to see where the possible ends and the impossible begins clearly.

だから研究員は、今日もまた「未知の課題」に向かって、下を向いて歩き続けるしかないのです。
That is why researchers can only keep walking forward, looking down, toward unknown problems.

---

まあ、今日のコラムで、あなたにご理解頂きたいことは、
What I would like you to understand from today’s column is this:

―― 「下を向いて歩こう」は、"ラク"を意味していることではないよ
"Walking while looking down" does not mean the work is easy.

ということなのです。
That is all I wanted to say.

つまり、私は「全力疾走」をしていて「普通」なのです。

2026,江端さんの忘備録

研究員だけでなく、たぶん多くの人が悩んでいると思うのですが、報告書などに対する上司のレビューで、こういうものがあります。
Not only researchers but probably many people struggle with this: when a supervisor reviews a report, there is a comment like this.

―― なんとなく分からん。
"I somehow don't get it."

多いです。というか、ほとんどこれです。
It happens often. In fact, it is almost always this.

そこでこちらが「どう直せばいいんでしょうか」と聞くと、「自分で考えて下さい」と言われる。
So when we ask, "How should I fix it?", we are told, "Please think about it yourself."

エンジニアの方なら分かると思いますが、「何が悪いのか分からないレビュー」というのは、かなりのダメージを受けます。
Engineers will understand this, but a review that does not explain what is wrong is extremely destructive.

バグなら楽です。「ここが壊れている」と言われれば直せます。設計でも同じで、「この構造では要件を満たせない」と言われれば作り直せます。
Bugs are easy. If someone says, "This part is broken," you can fix it. The same applies to design: if you are told "This structure cannot satisfy the requirements," you can redesign it.

しかし「なんとなく分からん」というレビューは、コンピュータで言えば仕様未定義エラーです。
However, a review saying "I somehow don't get it" is like an undefined-specification error in computing.

この指示では対策が取れません。無限の解空間の中の一つの解ベクトルが否定されただけのことだからです。
With such an instruction, there is no way to respond. It simply means that one vector in an infinite solution space has been rejected.

つまりこれは、「残りの無限数のベクトルを全部試せ」と言われているようなものです。
In other words, it is like being told, "Try all the remaining infinite vectors."

---

ただ、この話はエンジニアだけの問題ではないと思うのです。
However, I do not think this issue is limited to engineers.

私も被害者面だけをするつもりはありません。私だって、ちゃんと加害者やってきました。
I do not intend to play only the victim. I have also been a perpetrator.

皆さんも同じではないでしょうか。
I suspect many of you have done the same.

例えば創作作品に対して、「なんかこの映画、面白くなかった」「この本、評判ほど良くない」「この作品、何が言いたいのか分からん」などと言うことがあります。
For example, when it comes to creative works, we often say things like "That movie wasn't very interesting," "This book isn't as good as its reputation," or "I don't get what this work is trying to say."

理由も説明せず、改善点も1mmも示さない。それでもなぜか、こういうものが「批評」というジャンルとして成立しています。
We explain no reasons and suggest not even a millimeter of improvement. Yet somehow this still counts as a genre called "criticism."

私、思うんですが、人間の最もプリミティブな殺意って、実は「なんとなく分からん」から始まっているんじゃないでしょうか。
I sometimes think that the most primitive murderous impulse in humans actually begins with "I somehow don't get it."

---

さて、作業者や創作者側の視点から言えば、結論はシンプルです。
Now, from the perspective of workers or creators, the conclusion is simple.

「お前(レビューア)の頭が悪い」。
"The reviewer is simply stupid."

これです。この結論は、作業者や創作者に最も寄り添った、そして最も優しくて単純明快な回答です。
That's it. This conclusion is the most sympathetic to workers and creators, and the simplest and most comforting answer.

ただ、これだけでは世の中に溢れている「なんとなく分からん」というレビューに対応できません。ですので、レビューア側の視点からも少し考えてみます。
However, this alone does not help us address the flood of "I somehow don't get it" reviews worldwide. So let us also consider the reviewer's perspective.

レビューアが「なんとなく分からん」と感じる理由は、大体次のようなものです。
The reasons reviewers feel "I somehow don't get it" are roughly as follows.

(1)作者の頭の中ではつながっている論理が、文章や作品として十分に伝わっていない。
(1) The logic that is connected in the author's mind has not been sufficiently conveyed in the text or the work.

(2)作者の中では自然につながっている論理のジャンプに、読者が追いつけない。
(2) The reader cannot follow the logical jumps that feel natural to the author.

(3)全体構造が見えない。
(3) The overall structure is not visible.

(4)ロジック整理を読者に丸投げしている。
(4) The organization of logic is thrown entirely onto the reader.

(5)作者自身が評価基準を言語化できていない。
(5) The author has not verbalized their own evaluation criteria.

これを簡単に言うと「読みづらい」「論理が飛んでいる」「何かがおかしい」となるわけです。
In short, it means "hard to read," "logic jumps," or "something feels wrong."

---

ただ、この問題の原因は、実はかなり単純だったりします(正直、そう思いたくはないのですが)。
However, the cause of this problem is actually quite simple (though honestly, I would rather not admit it).

原因は、作者が作者の世界観の"内側"で作品を作っているからです。
The reason is that the author creates the work from within their own worldview.

例えば「異世界小説」を考えてみましょう。
For example, consider an isekai (other-world fantasy) novel.

作者の頭の中では、すでに世界が完成しています。
In the author's mind, the world is already complete.

『魔法は日常的な技術で、王国と帝国は長年戦争していて、空に浮かぶ島は古代文明の遺産』
"Magic is an everyday technology, the kingdom and the empire have been at war for years, and the floating islands are relics of an ancient civilization."

こういう設定がすべて共有されている。
All these assumptions are already shared in the author's mind.

だから作者は、「王国の魔導兵が浮遊島から攻撃を開始した」と普通に書けてしまう。
Therefore, the author can casually write, "The kingdom's magic soldiers began their attack from the floating island."

しかし読者にとっては、『なぜ島が浮いているのか、魔導兵とは何なのか、なぜ戦争しているのか』、何一つ分かりません。
But for the reader, nothing is clear: why the island floats, what magic soldiers are, or why there is a war.

作者の頭の中では整合している世界でも、読者から見れば「状況がよく分からない物語」です。
Even if the world is internally consistent in the author's mind, for the reader it becomes "a story whose situation is unclear."

つまり物語を書くには、物語だけでは足りません。その世界そのものを説明しなければならない。
In other words, writing the story itself is not enough; the world itself must be explained.

定量的に言えば、作品が1なら世界説明は100とか1000必要になる ―― これは、かなり地獄です。
Quantitatively speaking, if the story is "1," does the explanation of the world become "100" or "1000"? which is quite hellish.

---

そしてこの構造は、研究員の報告書でも全く同じです。
And this structure is exactly the same in research reports.

研究者の頭の中には、『研究背景、問題設定、既存研究、使用データ、分析手法、評価指標』がすでに整理されています。
In the researcher's mind, the research background, problem definition, prior studies, data used, analytical methods, and evaluation metrics are already organized.

ですから「本手法により接触機会の増加が確認された」と書けば済むような気がしてしまう。
So it feels sufficient to simply write, "This method confirmed an increase in contact opportunities."

しかし読む側からすると、『接触機会とは何なのか、何と比較しているのか、どの計算方法なのか、どのデータなのか』が分かりません。
However, from the reader's perspective, it is unclear what "contact opportunity" means, what it is compared with, how it is calculated, and what data it is based on.

研究者の頭の中の世界が、読者の頭の中にインストールされていないからです。
That is because the world inside the researcher's mind has not been installed inside the reader's mind.

つまりここでも、研究成果が1なら背景説明は100とか1000になる。
So here as well, if the research result is "1," the background explanation becomes "100" or "1000."

そして、この説明を省略したときに発生するレビューが、「なんとなく分からん」です。
And when that explanation is omitted, the resulting review becomes "I somehow don't get it."

---

私は、今、この「なんとなく分からん」というコメントを受けて、心底キレている最中です。
Right now, I am genuinely furious after receiving this "I somehow don't get it" comment.

ですので、こういうコラムを書いて自分自身を落ち着かせています。
So I write columns like this to calm myself down.

気分としては『写経』です。書いているものがお経ではないだけの、精神安定行為です。
It feels like copying sutras. The only difference is that what I am writing is not a Buddhist scripture; it is merely a form of mental stabilization.

私も、一応、大人なので「作者の説明が足りないのだ」と理解はしています。
I am, after all, an adult, so I understand that the author's explanation may be insufficient.

理解はしているのですが――それでも、私は『私の説明が足りないのではなく、世界の理解力が足りない』と考えたい。
I do understand that, but still, I would rather believe that it is not my explanation that is lacking, but the world's ability to understand.

---

この世の中は私のために存在しているのだから、本来ならば私の世界観を世界の方が理解すべきであり、努力が足りないのは私以外の全人類です。
Since the world exists for my sake, it is only natural that it should understand my worldview; therefore, those who lack effort are all humans other than myself.

という訳で、私の結論はいつもの通りです。
So, as always, my conclusion is the same.

―― 私は正しい。世界が間違っている
"I am right. The world simply does not try hard enough to understand me."

“初出”の“未定義”の用語を使った学生さんが、質問で、学会の顔役(重鎮)から『集中砲火』を浴びていました。

 

未分類

https://wp.kobore.net/2026/03/13/post-24507/ のコラムを参考にして、 「上を向いて歩こう」をベースとした「下を向いて歩こう」の替え歌の歌詞を考えて下さい

もう一つの『下を向いて歩こう』の意義は、「高い目標を目指して歩む人生は、大体『コケる』」という、私の経験則です。

江端さんのコラムの趣旨(「足元を見ることの重要性」や山道の現実的な教訓)を踏まえつつ、
坂本九の「上を向いて歩こう」の構造をゆるく借りた **替え歌(パロディ)**を作りました。
※原曲の完全コピーにならないよう、構造と雰囲気だけを借りています。


下を向いて歩こう

下を向いて歩こう
石ころ踏まぬように
転ばないように
夜道をゆこう

下を向いて歩こう
根っこにつまずかぬよう
ぬかるみよけて
静かにゆこう

思い出すのは
山道の教訓
上ばかり見れば
人はころぶ

下を向いて歩こう
足元照らしながら
小さな一歩を
確かめてゆこう

下を向いて歩こう
落ち葉に隠れた石
それでも前へ
ゆっくり進もう

見上げた空は
たまにでいいさ
まずはこの道
踏み外さぬよう

下を向いて歩こう
つまずかないように
そして時々
空も見よう


もしよろしければ、次のようなバージョンも作れます。

  • 江端コラム風ブラックユーモア版(かなり辛辣)
  • 登山ガチ版(山の教訓寄り)
  • 研究者版(理系替え歌)
  • 社会風刺版(かなり怖い)

江端コラムの文体に寄せると、実はかなり面白い替え歌になります。

研究者版(理系替え歌)をお願いします。

江端コラムの「現実を見る/足元を見る」という発想を、研究者・理系の日常に寄せた替え歌として作成した。
原曲の構造だけを借り、内容は研究・実験・論文・レビュー文化に寄せている。


下を向いて歩こう(研究者版)

下を向いて歩こう
データを見落とさぬよう
誤差を拾って
解析しよう

下を向いて歩こう
ノイズを踏まぬように
仮説を静かに
確かめよう

思い出すのは
レビューコメント
「なんとなく違う」
その一行

下を向いて歩こう
ログを追いながら
バグをひとつずつ
つぶしてゆこう

下を向いて歩こう
実験は裏切る
昨日の結果が
今日は出ない

見上げた理想は
遠くにあるけど
まずはこの値
再現しよう

下を向いて歩こう
統計を信じつつ
そして時々
空も見る


もし希望があれば、さらに江端コラムの文脈に寄せて

  • 「レビュー地獄版」(研究者あるある)
  • 「博士課程版」
  • 「企業研究所版」
  • 「AI研究版」

なども作れる。
特に **「レビュー地獄版」**はかなりリアルで、研究者には刺さる替え歌になる。

社会風刺版(かなり怖い)をお願いします。

コラムの含意(「足元を見ること」「理想やスローガンより現実を見ること」)を強め、社会風刺として少し不穏なトーンに寄せた替え歌を作成した。
原曲の構造は緩く借りつつ、内容は完全に別の歌詞になっている。


下を向いて歩こう(社会風刺版)

下を向いて歩こう
誰とも目を合わせず
静かに歩けば
揉め事はない

下を向いて歩こう
ニュースは見ぬように
知らないままで
暮らしていよう

思い出すのは
遠いスローガン
上を向こうよ
夢を持とう

だけどこの道
穴だらけだよ
見ていなければ
落ちてしまう

下を向いて歩こう
石ころよけながら
声を出さずに
通り過ぎよう

下を向いて歩こう
誰かが転んでも
立ち止まらずに
歩いていよう

見上げた空は
とてもきれいで
だから誰も
下を見ない

下を向いて歩こう
足元照らして
ほんとはそこに
何がある?


このテーマ、江端コラムの思想を突き詰めると、実はもう一段階怖い解釈ができます。

つまり

「上を向いて歩こう」は希望の歌だが、
「下を向いて歩こう」は“社会が壊れたときの生存戦略”になる。

この発想で作る 「最怖バージョン」(かなりブラックな社会風刺)も作れます。
江端コラムの思想には実はかなり近い構造になります。

2026,江端さんの忘備録

私はこれまで色々な人生のモットーを書いてきました ―― うっとうしいくらいに
I have written various mottos for life over the years—almost annoyingly so.

その中に、まだ書いていないことが一つあることに気がつきました
Among them, I realized that there was one I had not yet written about.

それは、
That is,

『下を向いて歩こう』
“Let’s walk while looking down.”

です。
That’s it.

---

本日、昼ごろにやっている近所の自然歩道でのウォーキングができなくて、ヘッドライトを付けて夜間に行ってきました。
Today I could not do my usual midday walk along the nearby nature trail, so I went out at night wearing a headlamp.

足元をライトで照らしながら、林間コースを歩いていた時に、『あ、まだ、このこと書いていなかったなぁ』と思い出しました。
While illuminating the ground with my light and walking along the wooded path, I suddenly remembered, “Ah, I haven’t written about this yet.”

「上を向いて歩こう」のパロディではなく、実際の登山などでは、結構重要な教訓なんです。
This is not a parody of “Sukiyaki (Ue o muite arukō / I Look Up As I Walk),” but rather a fairly important lesson in real mountaineering.

山を歩いたことがある人なら分かると思いますが、登山道というのは、たいてい「足元が一番危険」です。
Anyone who has walked in the mountains knows that on a mountain trail, the most dangerous place is usually under your feet.

濡れた石、浮いた小石、木の根、崩れかけた土。こういうものは、遠くを見ていると簡単に踏み外します。
Wet rocks, loose stones, tree roots, and crumbling soil—if you look too far ahead, it is easy to misstep on these.

これを、実際の生活で言えば、「締切を守る」「約束を守る」「小さな仕事も丁寧」というものになりますが、ごく普通の野望も何もない、日常のことを、誰に対しても公平に行う、ということは結構大切だと思っています。
In everyday life, this translates into things like meeting deadlines, keeping promises, and doing even small tasks carefully. I believe it is quite important to carry out such ordinary, unglamorous daily matters fairly toward everyone.

なぜそう思うかというと、私は、「私との締切を守れない」「私との約束を守れない」「私との小さな仕事を雑にやる」人間を、私の生活圏から即座に切り捨てるからです ―― 私に権力がなくても、私から恨まれた人は、それなりに鬱陶(うっとう)しい目に合うという爆弾を抱えることになります。
The reason I think so is that I immediately cut out of my life anyone who cannot meet deadlines with me, cannot keep promises with me, or treats small tasks involving me carelessly. Even though I have no authority, anyone who earns my resentment carries the bomb that they may eventually experience a rather annoying consequence.

私には権力はありませんが、私の恨みは、陰湿で、ねちっこく、そして無期限です。大学で『氷の江端』と評されていた私の陰湿な性格はダテではありません。
I have no power, but my grudges are insidious, persistent, and indefinite. My unpleasant personality—once described at university as “Ebata the Ice Man”—is no exaggeration.

そう考えると「下を向いて歩く」、つまり『下っ端であろうが、公平に取り扱う』ということの重要性は、(他の人のことは知りませんが)私にとっては、とても重要なことになるのです。
Seen that way, “walking while looking down”—that is, treating everyone fairly regardless of rank—is extremely important to me (though I cannot speak for others).

これは「反面教師」というよりも、「現物教師」というものでしょう。
This is less a “negative example” than a “living example.”

---

もう一つの『下を向いて歩こう』の意義は、「高い目標を目指して歩む人生は、大体『コケる』」という、私の経験則です。
Another meaning of “walk while looking down” is my rule of thumb: a life spent striving for lofty goals usually ends up in a stumble.

まず、高い目標を目指して歩む人生は、疲れます。そもそも、目標がない人生ですら疲れるのに、「目標を設定する」、そして、あろうことかそれが「高い目標」であるなんて ―― 私に言わせれば『正気の沙汰ではない』。
First of all, a life spent chasing lofty goals is exhausting. Life without goals is tiring enough, yet people deliberately set goals—and, unbelievably, high ones. To me, that borders on madness.

私にとって「正しい生き方」とは、目標を設定せずに、下を向きながら、できるだけラクな速度とパスで、他人から(時々は自分から)与えられたミッションに、ダラダラと辿りつくことです。
For me, the “right way to live” is to set no particular goal, keep looking down, and drift along at the easiest possible pace and path toward missions given by others (and sometimes by myself).

ただそのダラダラの中に、(1)ざっくりしたミッションの方向を向いていることと、(2)止まらないこと、の2つだけをルールとしていれば、それで足ります。
Within that drifting, it is enough to follow just two rules: (1) face roughly toward the direction of the mission, and (2) do not stop.

私の経験上、『目指すところはあそこだ!』とか叫んでいる奴から、大体、転げ落ちていくか、ドロップアウトするか、その"こと"を忘れます。
In my experience, the people who shout “That’s where I’m heading!” usually end up tumbling down, dropping out, or simply forgetting about it.

ええ、私は、このことを色々な局面で見てきました。
Yes, I have seen this in many different situations.

ダイエットをしている人の追跡調査でも見てきましたし、企業のキックオフや、期首朝礼でも見てきました ―― そもそもキックオフ会で始まったプロジェクトが、ちゃんとラップアップ会をしているのを、私は見たことがありません。期首朝礼と同じプレゼンテーションを表示して、期末反省会が行われたことも一度もありません。
I have seen it in follow-up studies of people on diets and in corporate kickoffs and start-of-term meetings. In fact, I have never seen a project that began with a kickoff meeting properly hold a wrap-up meeting. Nor have I ever seen an end-of-term review using the same presentation shown at the start-of-term meeting.

上を目指して、目指して、そして、それが届かずに、疲れ果てて、最悪の選択をしてしまった人も知っています。
I also know people who kept aiming upward, failed to reach it, became exhausted, and ended up making the worst possible choices.

大抵の"上"は届かないところにあるから"上"なんです。なんで、みんな、そんな簡単なことに気がつかないのだろう、と思います。
Most “tops” are out of reach precisely because they are “tops.” I often wonder why people fail to notice such a simple fact.

つまり、「上を向いて見たモノは、消えるか、あるいは意図的に消される」ことになっているんです。
In other words, the things people see while looking upward tend either to disappear or to be deliberately erased.

---

さらに加えて言わせて頂くのであれば、今"上"にいる人は、"上"を目指した訳ではないことが多いようです。
Furthermore, many of the people who are now “at the top” did not necessarily aim for the top.

下を向いてがむしゃらにやっていたら、「あらら、ここは"上"だったのか?」と気がつく人の方が多いのです。
More often, they kept working hard while looking down, and one day realized, “Oh, this turned out to be the top?”

キャリア研究では「Planned Happenstance(計画された偶発性)」という理論があり、キャリアの多くは当初の目標ではなく、偶然の出来事の積み重ねによって形成されるとされています(Mitchell, Levin & Krumboltz, 1999)[1][2][3]
In career research, there is a theory called “Planned Happenstance,” which suggests that many careers are formed not by initial goals but by an accumulation of chance events (Mitchell, Levin & Krumboltz, 1999) [1][2][3].

[1] Mitchell, K. E., Levin, A. S., & Krumboltz, J. D. (1999). *Planned Happenstance: Constructing Unexpected Career Opportunities.* Journal of Counseling & Development, 77(2), 115–124.
[2] Krumboltz, J. D. (2009). *The Happenstance Learning Theory.* Journal of Career Assessment, 17(2), 135–154.
[3] Pluchino, A., Biondo, A., & Rapisarda, A. (2018). *Talent vs Luck: The role of randomness in success and failure.*

それを才能と呼ぶか、努力と呼ぶか、それは知りませんが、『"上"にいる人が、"上"を目指していなかった』というのは、かなり皮肉な話です ―― なぜなら『"上"を向いていると、"上"には行けず、"下"を向いていると、"上"にいることがある』ということですから。
Whether one calls that talent or effort, I do not know. But the fact that people at the top often did not aim for the top is rather ironic—because looking upward may prevent you from reaching the top, while looking downward may place you there.

---

まあ、私は、"下"を向いていて、"下"のままですが、別段、それで構いません。
As for me, I keep looking down and remain down there, but that is perfectly fine.

ただ、最近大変うっとうしいと思うのは、他人(つまり私)を巻き込む"上"志向の奴らの振る舞いです。
What I find extremely annoying these days is the behavior of people with upward ambitions who drag others—namely me—into it.

まあ、「上を向いて歩こう」という人のジャマをするつもりはないのですが、私を巻き込まないで欲しいのです。
I have no intention of interfering with those who want to walk while looking up, but I would prefer that they not involve me.

私は、これまで同様に『下を向いて歩こう』でやっていきます ―― つまり『私に構わないで下さい』ということです。
I will continue, as always, to “walk while looking down”—which means: please leave me alone.

完璧を目指し、理想を叫び、自分で汗もかかずに、どこかの誰かがやってくれることを期待しているだけのヤツより、ずっとマシです。