212 lines
10 KiB
Plaintext
212 lines
10 KiB
Plaintext
<%= form_with(model: game, class: "space-y-6") do |form| %>
|
||
<% if game.errors.any? %>
|
||
<div class="rounded-md bg-red-50 p-4 mb-6">
|
||
<div class="flex">
|
||
<div class="flex-shrink-0">
|
||
<svg class="h-5 w-5 text-red-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
|
||
</svg>
|
||
</div>
|
||
<div class="ml-3">
|
||
<h3 class="text-sm font-medium text-red-800">
|
||
<%= pluralize(game.errors.count, "error") %> prohibited this game from being saved:
|
||
</h3>
|
||
<div class="mt-2 text-sm text-red-700">
|
||
<ul class="list-disc pl-5 space-y-1">
|
||
<% game.errors.each do |error| %>
|
||
<li><%= error.full_message %></li>
|
||
<% end %>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<% end %>
|
||
|
||
<div>
|
||
<%= form.label :title, "ゲームタイトル", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.text_field :title, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md", placeholder: "例: 定例ディプロマシー会 #1" %>
|
||
</div>
|
||
</div>
|
||
|
||
<% unless game.persisted? %>
|
||
<% if current_user&.admin? %>
|
||
<div>
|
||
<%= form.label :game_mode, "ゲームモード", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.select :game_mode,
|
||
options_for_select([
|
||
['ソロモード (単独プレイ)', 'admin_mode'],
|
||
['マルチプレイヤーモード (複数プレイ)', 'player_mode']
|
||
], game.is_solo_mode ? 'admin_mode' : 'player_mode'),
|
||
{},
|
||
{ id: 'game-mode-select', class: 'shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md' } %>
|
||
</div>
|
||
</div>
|
||
<% end %>
|
||
|
||
<div id="participants-count-field" style="<%= game.solo_mode? ? 'display: none;' : '' %>">
|
||
<%= form.label :participants_count, "参加人数", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.number_field :participants_count, min: 1, max: 7, step: 1, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">1人から7人まで設定可能です。</p>
|
||
</div>
|
||
|
||
<div id="password-field" style="<%= game.solo_mode? ? 'display: none;' : '' %>">
|
||
<%= form.label :password, "パスワード (任意)", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.password_field :password, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">知人同士でプレイする場合など、アクセス制限をかけたい場合に設定してください。</p>
|
||
</div>
|
||
<% end %>
|
||
|
||
<div id="auto-fill-mode-field" style="<%= (game.solo_mode? && !game.persisted?) ? 'display: none;' : '' %>">
|
||
<%= form.label :auto_order_mode, "自動処理モード", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.select :auto_order_mode,
|
||
options_for_select([
|
||
['HOLD (待機)', 'hold'],
|
||
['ランダム動作', 'random']
|
||
], game.auto_order_mode || 'hold'),
|
||
{},
|
||
{ class: 'shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md' } %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">注文未入力の国や、プレイヤー不在の国の動作を設定します。</p>
|
||
</div>
|
||
|
||
<div id="turn-schedule-field" style="<%= (game.solo_mode? && !game.persisted?) ? 'display: none;' : '' %>">
|
||
<%= form.label :turn_schedule, "ターン進行方式", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<% current_schedule = game.turn_schedule.presence %>
|
||
<% preset_value = case current_schedule
|
||
when nil then "manual"
|
||
when "0" then "daily_0"
|
||
else "custom"
|
||
end %>
|
||
<select id="turn_schedule_preset"
|
||
class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
|
||
onchange="handleSchedulePresetChange(this)">
|
||
<option value="manual" <%= 'selected' if preset_value == 'manual' %>>手動(管理者が処理)</option>
|
||
<option value="daily_0" <%= 'selected' if preset_value == 'daily_0' %>>毎日1回(0時)</option>
|
||
<option value="custom" <%= 'selected' if preset_value == 'custom' %>>カスタム...</option>
|
||
</select>
|
||
</div>
|
||
<div id="custom-schedule-field" style="<%= preset_value == 'custom' ? '' : 'display: none;' %>" class="mt-2">
|
||
<input type="text" id="custom_schedule_input"
|
||
value="<%= current_schedule if preset_value == 'custom' %>"
|
||
class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md"
|
||
placeholder="例: 0,12,18(毎日0時・12時・18時)"
|
||
oninput="document.getElementById('turn_schedule_value').value = this.value">
|
||
</div>
|
||
<%= form.hidden_field :turn_schedule, id: "turn_schedule_value", value: current_schedule %>
|
||
<p class="mt-2 text-sm text-gray-500">
|
||
自動の場合、締切時刻を過ぎると未入力国はAutoOrderで処理され、ターンが自動進行します。
|
||
</p>
|
||
</div>
|
||
|
||
<script>
|
||
function handleSchedulePresetChange(select) {
|
||
const customField = document.getElementById('custom-schedule-field');
|
||
const hiddenField = document.getElementById('turn_schedule_value');
|
||
const customInput = document.getElementById('custom_schedule_input');
|
||
|
||
switch (select.value) {
|
||
case 'manual':
|
||
customField.style.display = 'none';
|
||
hiddenField.value = '';
|
||
break;
|
||
case 'daily_0':
|
||
customField.style.display = 'none';
|
||
hiddenField.value = '0';
|
||
break;
|
||
case 'custom':
|
||
customField.style.display = 'block';
|
||
hiddenField.value = customInput.value;
|
||
break;
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<div>
|
||
<%= form.label :memo, "メモ", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.textarea :memo, rows: 3, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">ゲームに関するメモや注意事項があれば記載してください。</p>
|
||
</div>
|
||
|
||
<!-- ハウスルール設定 -->
|
||
<div class="border-t border-gray-200 pt-6 mt-6">
|
||
<h3 class="text-lg font-medium text-gray-900 mb-4">ハウスルール</h3>
|
||
|
||
<div class="space-y-4">
|
||
<div>
|
||
<%= form.label :year_limit, "年数制限", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.number_field :year_limit, min: 1901, max: 1999, step: 1, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md", placeholder: "空欄 = 無制限" %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">指定した年を超えるとゲームが自動終了します(例: 1910)。空欄で無制限。</p>
|
||
</div>
|
||
|
||
<div>
|
||
<%= form.label :victory_sc_count, "目標SC数", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.number_field :victory_sc_count, min: 1, max: 34, step: 1, value: game.victory_sc_count || 18, class: "shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md" %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">ソロ勝利に必要なSC数(デフォルト: 18)。</p>
|
||
</div>
|
||
|
||
<div>
|
||
<%= form.label :scoring_system, "スコアリング方式", class: "block text-sm font-medium text-gray-700" %>
|
||
<div class="mt-1">
|
||
<%= form.select :scoring_system,
|
||
options_for_select([
|
||
['なし', 'none'],
|
||
['SC数(獲得SC数がスコア)', 'sc_count'],
|
||
['SC比率(全SC中の割合%)', 'sc_ratio'],
|
||
['DSS(生存国で均等分割)', 'dss'],
|
||
['SoS(二乗和比率)', 'sos']
|
||
], game.scoring_system || 'none'),
|
||
{},
|
||
{ class: 'shadow-sm focus:ring-indigo-500 focus:border-indigo-500 block w-full sm:text-sm border-gray-300 rounded-md' } %>
|
||
</div>
|
||
<p class="mt-2 text-sm text-gray-500">ゲーム終了時のスコア計算方式を選択します。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pt-5">
|
||
<div class="flex justify-end">
|
||
<%= form.submit "保存する", class: "ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const gameModeSelect = document.getElementById('game-mode-select');
|
||
const participantsField = document.getElementById('participants-count-field');
|
||
const passwordField = document.getElementById('password-field');
|
||
const autoFillField = document.getElementById('auto-fill-mode-field');
|
||
|
||
if (gameModeSelect) {
|
||
gameModeSelect.addEventListener('change', function() {
|
||
const isAdminMode = this.value === 'admin_mode';
|
||
|
||
if (isAdminMode) {
|
||
if(participantsField) participantsField.style.display = 'none';
|
||
if(passwordField) passwordField.style.display = 'none';
|
||
if(autoFillField) autoFillField.style.display = 'none';
|
||
} else {
|
||
if(participantsField) participantsField.style.display = 'block';
|
||
if(passwordField) passwordField.style.display = 'block';
|
||
if(autoFillField) autoFillField.style.display = 'block';
|
||
}
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
<% end %>
|