bingo: planned status and capacity type
All checks were successful
Build and Deploy to Production / test (push) Successful in 23s
Build and Deploy to Production / build (push) Successful in 1m0s
Build and Deploy to Production / deploy (push) Successful in 39s

"MW" on the card mixed IT load, connected power, total site power,
design capacity and even MVA (Oxygen, Sber Yuzhny Port). Record which
one a figure is in a new mw_type column; the dialog tags the number
("64 MW · design") and MVA replaces the unit, while cells keep the bare
figure to stay readable. Add a "planned" status for projects not yet
under construction; like "building", it is left out of the operational
view.

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-10 06:59:04 +04:00
commit e5bd1c1ac7
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
9 changed files with 69 additions and 9 deletions

View file

@ -12,6 +12,8 @@ module Bingo
KINDS = %w[strike fire outage flood cooling other].freeze
ICONS = { 'strike' => '💥', 'fire' => '🔥', 'outage' => '⚡', 'flood' => '💧', 'cooling' => '🌡️', 'other' => '⚠️' }.freeze
SIZE = 5
STATUSES = %w[operational building planned].freeze
MW_TYPES = %w[it connected total design mva].freeze
# Every row, column and both diagonals, as 0-based cell indices.
LINES = (
@ -30,6 +32,8 @@ module Bingo
crossed: 'Зачёркнуто', lines: 'линий', updated: 'обновлено',
log: 'Журнал инцидентов', empty: 'Пока всё работает. Пока.',
bingo: 'БИНГО!', bingo_n: 'БИНГО ×%d!', full: 'ПОЛНАЯ КАРТА. Интернета больше нет.',
planned: 'планируется', mva: 'МВА',
mw_types: { 'it' => 'ИТ', 'connected' => 'подв.', 'total' => 'общ.', 'design' => 'проект' },
building: 'строится', mw: 'МВт', since: 'с %d г.', photo: 'Фото', source: 'Источник',
close: 'Закрыть', no_incidents: 'Инцидентов не зафиксировано.',
footer: 'Данные из открытых источников (2025–2026). Клетка зачёркивается только по публичному источнику.',
@ -46,6 +50,8 @@ module Bingo
crossed: 'Crossed out', lines: 'lines', updated: 'updated',
log: 'Incident log', empty: 'Everything is up. For now.',
bingo: 'BINGO!', bingo_n: 'BINGO ×%d!', full: 'FULL CARD. There is no more internet.',
planned: 'planned', mva: 'MVA',
mw_types: { 'it' => 'IT', 'connected' => 'connected', 'total' => 'total', 'design' => 'design' },
building: 'under construction', mw: 'MW', since: 'since %d', photo: 'Photo', source: 'Source',
close: 'Close', no_incidents: 'No incidents recorded.',
footer: 'Open-source data (2025–2026). A cell is crossed out only with a public source.',
@ -62,6 +68,8 @@ module Bingo
crossed: 'Закреслено', lines: 'ліній', updated: 'оновлено',
log: 'Журнал інцидентів', empty: 'Поки що все працює. Поки що.',
bingo: 'БІНГО!', bingo_n: 'БІНГО ×%d!', full: 'ПОВНА КАРТКА. Інтернету більше немає.',
planned: 'планується', mva: 'МВА',
mw_types: { 'it' => 'ІТ', 'connected' => 'підв.', 'total' => 'заг.', 'design' => 'проєкт' },
building: 'будується', mw: 'МВт', since: 'з %d р.', photo: 'Фото', source: 'Джерело',
close: 'Закрити', no_incidents: 'Інцидентів не зафіксовано.',
footer: 'Дані з відкритих джерел (2025–2026). Клітинка закреслюється лише за публічним джерелом.',
@ -88,6 +96,9 @@ module Bingo
super
end
def operational? = status == 'operational'
def planned? = status == 'planned'
def building?
status == 'building'
end

View file

@ -3,7 +3,7 @@ require 'uri'
# /admin/bingo/* on asxp.io: edit the card and record incidents for BingoWeb.
# Registered into AsxpioWeb, so AdminAuth (HTTP Basic) and CSRF apply.
module BingoAdmin
DC_TEXT = %w[name_ru name_en name_uk city_ru city_en city_uk operator mw status
DC_TEXT = %w[name_ru name_en name_uk city_ru city_en city_uk operator mw mw_type status
photo_credit photo_source_url info_url].freeze
module Helpers
@ -23,7 +23,8 @@ module BingoAdmin
def assign_dc(dc)
DC_TEXT.each { |f| dc[f.to_sym] = blank_nil(params[f]) }
dc.year = params[:year].to_s =~ /\A\d{4}\z/ ? params[:year].to_i : nil
dc.status = 'operational' unless %w[operational building].include?(dc.status)
dc.status = 'operational' unless Bingo::STATUSES.include?(dc.status)
dc.mw_type = nil unless Bingo::MW_TYPES.include?(dc.mw_type)
errs = []
errs << 'Name (ru), city (ru) and operator are required' if [dc.name_ru, dc.city_ru, dc.operator].any?(&:nil?)
errs << 'URLs must be http(s)' unless [dc.photo_source_url, dc.info_url].all? { |u| http_url?(u.to_s) }