すれ違い・追いつきシュミレーションは、円状の道路を円の中心点から直線上の左右にA地点とB地点を設けて、円周の道路の距離、出発時間、出発速度をA・Bそれぞれ設定し、さらに円周の同方向または逆方向選択後、途中の休憩距離、休憩時間、休憩先からの出発速度を設定して、何時何府何秒にすれ違うか、追いつくかをシュミレーションします。

仕様
1.道路の円の直径を設定(k・m・cm)
2.A地点の出発時間の設定
3.B地点の出発時間の設定
4.A地点の時速 (km/h)の設定
5.B地点の時速 (km/h)の設定
6.休憩地点までの距離 (km)の設定(A・B)
7.休憩地点からの出発時速 (km/h)の設定(A・B)
8.休憩時間 (時:分:秒)の設定(A・B)
9.出発方向(同方向・逆方向の選択A・B)
10.印刷
ご利用について
各コードの追加・修正・変更・削除やCSSのデザイン変更など、ご自由にどうぞ。また、コピー&ペーストによる不具合等や計算違いなどが有りましても、管理者は責任を負う事は致しません。
※すべて変更なしでご使用された場合は、どこか片隅に小さくMOMOPLANと書いて頂くと嬉しいです。
HTML
デモページ
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>すれ違い・追いつきシュミレーション</title>
</head>
<link rel="stylesheet" href="style.css">
<body>
  <div class="gradation">【すれ違い・追いつきシュミレーション】</div>
  <form id="simulationForm">
    <!-- 道路の円の直径 -->
    <div class="form-group">
    <label>道路の円の直径:</label><br>
    <label>キロメートル (km): </label>
    <input type="number" id="diameterKm" min="0" step="1" required> (整数のみ) 
    <label>メートル (m): </label>
    <input type="number" id="diameterM" min="0" max="999" step="1" required> (最大999)<br><br>
    <label>センチメートル (cm): </label>
    <input type="number" id="diameterCm" min="0" max="99" step="1" required> (最大99)<br>
</div>
    <!-- 地点Aの出発時間 -->
    <div class="form-group">
    <label>A地点の出発時間: </label>
    <input type="time" id="startTimeA" step="1" required> (秒まで入力可能) 

    <!-- 地点Bの出発時間 -->
    <label>B地点の出発時間: </label>
    <input type="time" id="startTimeB" step="1" required> (秒まで入力可能)<br><br>

    <!-- A・Bの各時速 -->
    <label>A地点の時速 (km/h): </label>
    <input type="number" id="speedA" step="0.0001" required> (最小単位: cm毎秒) 
    <label>B地点の時速 (km/h): </label>
    <input type="number" id="speedB" step="0.0001" required> (最小単位: cm毎秒)<br>
</div>

    <!-- A地点の休憩地点までの距離 -->
    <div class="form-group">
    <label>A地点の休憩地点までの距離 (km): </label>
    <input type="number" id="restDistanceA" step="0.0001" value="0" required> 

    <!-- B地点の休憩地点までの距離 -->
    <label>B地点の休憩地点までの距離 (km): </label>
    <input type="number" id="restDistanceB" step="0.0001" value="0" required><br><br>

    <!-- A地点の休憩地点からの出発時速 -->
    <label>A地点の休憩地点からの出発時速 (km/h): </label>
    <input type="number" id="restSpeedA" step="0.0001" value="0" required> 

    <!-- B地点の休憩地点からの出発時速 -->
    <label>B地点の休憩地点からの出発時速 (km/h): </label>
    <input type="number" id="restSpeedB" step="0.0001" value="0" required> 

    <!-- 出発方向 -->
    <label>出発方向: </label>
    <select id="direction" required>
      <option value="same">同方向</option>
      <option value="opposite">逆方向</option>
    </select>
    <br>
  </div>
    <!-- 休憩時間 -->
    <div class="form-group">
    <label>A地点の休憩時間 (時:分:秒): </label>
    <input type="time" id="restTimeA" step="1" value="00:00:00" required>
    <label>B地点の休憩時間 (時:分:秒): </label>
    <input type="time" id="restTimeB" step="1" value="00:00:00" required><br>
</div>
    <button type="button" onclick="simulate()">計算</button>
    <button type="button" onclick="printPage()">印刷</button>
  </form>
<!-- 計算結果を表示するテーブル -->
<div id="result"></div>

  <div id="result"></div>
  <script src="main.js"></script>
</body>
</html>
JS
function simulate() {
    // 初期化:以前の結果をリセット
  document.getElementById("result").innerText = ""; // 結果エリアをクリア

    // キロメートル、メートル、センチメートルを取得
    const diameterKm = parseInt(document.getElementById("diameterKm").value) || 0;
    const diameterM = parseInt(document.getElementById("diameterM").value) || 0;
    const diameterCm = parseInt(document.getElementById("diameterCm").value) || 0;
  
    // 総直径 (km 単位)
    const totalDiameterKm = diameterKm + (diameterM / 1000) + (diameterCm / 100000);
    if (totalDiameterKm <= 0) {
      alert("不可能な設定入力です:直径はゼロ以上である必要があります。");
      return;
    }
  
    // 道路の総距離 (周長)
    const totalDistance = Math.PI * totalDiameterKm;
  
    // 出発時速の取得
    const speedA = parseFloat(document.getElementById("speedA").value) || 0;
    const speedB = parseFloat(document.getElementById("speedB").value) || 0;
    const restSpeedA = parseFloat(document.getElementById("restSpeedA").value) || speedA; // デフォルトで出発時速
    const restSpeedB = parseFloat(document.getElementById("restSpeedB").value) || speedB; // デフォルトで出発時速
    const direction = document.getElementById("direction").value;
  
    if (speedA <= 0 || speedB <= 0) {
      alert("不可能な設定入力です:時速はゼロ以上である必要があります。");
      return;
    }
  
    // 休憩地点までの距離
    const restDistanceA = parseFloat(document.getElementById("restDistanceA").value) || 0;
    const restDistanceB = parseFloat(document.getElementById("restDistanceB").value) || 0;
  
    // 休憩時間を取得
    const restTimeA = document.getElementById("restTimeA").value || "00:00:00";
    const restTimeB = document.getElementById("restTimeB").value || "00:00:00";
  
    // 時間を秒単位に変換
    const [hoursA, minutesA, secondsA] = restTimeA.split(":").map(Number);
    const restSecondsA = hoursA * 3600 + minutesA * 60 + secondsA;
  
    const [hoursB, minutesB, secondsB] = restTimeB.split(":").map(Number);
    const restSecondsB = hoursB * 3600 + minutesB * 60 + secondsB;
  
    // A地点とB地点の実移動時間を計算 (休憩を考慮)
    const timeToRestA = restDistanceA / speedA * 3600; // 秒単位
    const timeToRestB = restDistanceB / speedB * 3600; // 秒単位
  
    const totalRestTimeA = timeToRestA + restSecondsA; // A地点が休憩完了後に再出発する時間
    const totalRestTimeB = timeToRestB + restSecondsB; // B地点が休憩完了後に再出発する時間
  
    // 相対速度とすれ違い距離の調整
    let meetTime = 0;
    let meetDistance = 0;
  
    if (direction === "opposite") {
      // 逆方向の場合
      const relativeSpeed = restSpeedA + restSpeedB;
      meetTime = totalDistance / relativeSpeed; // すれ違い時間
      meetDistance = meetTime * restSpeedA; // A地点からの距離
    } else if (direction === "same" && restSpeedA > restSpeedB) {
      // 同方向の場合 (休憩後速度を考慮)
      const relativeSpeed = restSpeedA - restSpeedB;
      meetTime = totalDistance / relativeSpeed; // すれ違い時間
      meetDistance = meetTime * restSpeedA; // A地点からの距離
    } else {
      alert("同方向では追いつきがありません!");
      return;
    }

  // 時間を「時間」「分」「秒」に分解
  const meetTimeSeconds = Math.floor(meetTime * 3600); // 秒単位に変換
  const hours = Math.floor(meetTimeSeconds / 3600); // 時間
  const minutes = Math.floor((meetTimeSeconds % 3600) / 60); // 分
  const seconds = meetTimeSeconds % 60; // 秒

   // テーブル形式で結果を表示
  let resultHTML = `<table border="1">
  <thead>
    <tr>
      <th colspan="2" style="text-align:center;">【すれ違い・追いつき結果】</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>道路の総距離</td>
      <td>${totalDistance.toFixed(5)} km</td>
    </tr>
    <tr>
      <td>A地点の出発時速</td>
      <td>${speedA.toFixed(5)} km/h</td>
    </tr>
    <tr>
      <td>B地点の出発時速</td>
      <td>${speedB.toFixed(5)} km/h</td>
    </tr>
    <tr>
      <td>A地点の休憩地点までの距離</td>
      <td>${restDistanceA.toFixed(5)} km</td>
    </tr>
    <tr>
      <td>B地点の休憩地点までの距離</td>
      <td>${restDistanceB.toFixed(5)} km</td>
    </tr>
    <tr>
      <td>A地点の休憩地点からの出発時速</td>
      <td>${restSpeedA.toFixed(5)} km/h</td>
    </tr>
    <tr>
      <td>B地点の休憩地点からの出発時速</td>
      <td>${restSpeedB.toFixed(5)} km/h</td>
    </tr>
    <tr>
      <td>すれ違い時間</td>
      <td>${hours} 時間 ${minutes}${seconds} 秒</td>
    </tr>
    <tr>
      <td>すれ違い距離</td>
      <td>${meetDistance.toFixed(5)} km</td>
    </tr>
  </tbody>
</table>`;
document.getElementById("result").innerHTML = resultHTML; // HTMLとして表示
}
// 印刷機能を追加
function printPage() {
  window.print(); // ページ全体を印刷
}
CSS
/* 全体の基本スタイル */
body {
  font-family: Arial, sans-serif;
  margin: 20px;
  color: #21135f;
  font-weight: bold;
  font-size: 16px;
  text-align: center;
  background-image: url("s-brick008.gif"); /* 背景を明るい色に設定 */
}

/* 入力項目のグループ枠 */
.form-group {
    border: 1px solid #ccc; /* グループ全体の枠線 */
    border-radius: 8px; /* 枠の角を丸める */
    padding: 10px; /* 内側の余白 */
    width: 98%;
    margin-bottom: 10px; /* 下部の余白を追加 */
    background-color: #e5f2fa; /* 背景を白色に設定 */
  }

/* 入力フィールドの罫線枠非表示 */
form input[type="number"],
form select {
  border: solid 2px #05411c;/* 枠を非表示 */
  background-color: #f4eeff; /* 背景色を明るくしてフィールドを目立たせる */
  width: 12%;
  border-radius: 8px; /* 枠の角を丸める */
  padding: 8px 18px;
  font-size: 16px;
  font-weight: bold;
  color: #053320;
}
/* ボタンのスタイル */
button {
  background-color: #176e54; /* 鮮やかな青色 */
  color: rgb(255, 255, 255);
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  margin-top: 20px;
}

button:hover {
  background-color: #484581; /* マウスオーバー時に暗い青色 */
  color: rgb(247, 235, 235);
}

/* テーブルスタイル */
table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 20px;
}

thead th {
  background-color: #0078d7; /* ヘッダーの背景色 */
  color: white; /* ヘッダーの文字色 */
  padding: 10px;
  text-align: left;
  font-size: 16px;
}

tbody td {
  padding: 10px;
  border: 1px solid #ddd; /* セルの境界線 */
  font-size: 14px;
}

/* レコードの背景色を交互に設定 */
tbody tr:nth-child(even) {
  background-color: #f2f2f2; /* 明るいグレー */
}

tbody tr:nth-child(odd) {
  background-color: #ffffff; /* 白色 */
}

.gradation {
  display: inline-block;
  font-size: 22px;
  font-family: "Roboto", sans-serif;
  font-weight: bold;
  background: linear-gradient(96deg, #e99322 0%, #2e31e0 55%, #27d369 80%, #d8b529 95%, #f7357f 90% 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

以上です、お粗末でした・・・。