Модуль:НОТ Москвы (Bk;rl,&UKM Bkvtfd)
Модуль для построения списков маршрутов (и остановок маршрутов) наземного общественного транспорта Москвы. Модуль содержит следующие функции:
metro_mini
— список маршрутов для статьи о станции метро, МЦК или МЦД. Название станции можно передавать как для шаблона {{ММ}}, а можно как название статьи, то есть с последующим уточнением в скобках (за исключением тех станций, для которых шаблон {{ММ}} требует передавать название иначе, чем просто название статьи минус уточнение). Предназначен для карточки статьи.metro_midi
— то же, что и metro_mini, но каждый вид транспорта выводится в виде отдельного пункта маркированного списка. Предназначен для тела статьи.metro
— то же, что и metro_mini, но с основными остановками для каждого маршрута. По результатам опроса использование этого варианта не поддержано.railway_mini
— список маршрутов для статьи о железнодорожной станции, не входящей в МЦД; фильтрация по тегу или линку. Параметр — название статьи о железнодорожной станции. Предназначен для карточки статьи.railway_midi
— то же, что и railway_mini, но каждый вид транспорта выводится в виде отдельного пункта маркированного списка. Предназначен для тела статьи.railway
— то же, что и metro_mini, но с основными остановками для каждого маршрута. По результатам опроса использование этого варианта не поддержано.num
иnumfull
— один или несколько конкретных маршрутов в том же формате, как metro, с основными и всеми остановками соответственно. Функции поддерживают неограниченный список индексов маршрутов.firstlast
— начальная и конечная остановки через тире для заданного маршрута.
Для обращений к модулю создан шаблон {{НОТ Москвы}}.
Примеры вызова функций
[править код]По станциям метро / МЦК / МЦД
[править код]Краткий список маршрутов
[править код]{{#invoke:НОТ Москвы|metro_mini|Бульвар Рокоссовского}}
А: 3, 265, 311, 327, 680, 682; Тм: 4, 7, 13, 36, 46
{{#invoke:НОТ Москвы|metro_mini|Новодачная}}
А: 352, 563, 746
Чуть удлинённый список маршрутов
[править код]{{#invoke:НОТ Москвы|metro_midi|Бульвар Рокоссовского}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
{{#invoke:НОТ Москвы|metro_midi|Новодачная}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
- Автобусы: 352, 563, 746
Полный список маршрутов
[править код]{{#invoke:НОТ Москвы|metro|Бульвар Рокоссовского}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
«→» — остановки проходятся только при движении в прямом направлении; «←» — остановки проходятся только при движении в обратном направлении.
{{#invoke:НОТ Москвы|metro|Новодачная}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
Автобусы | |
---|---|
352: | Алтуфьево • Лианозово • Марк • Новодачная • Долгопрудная |
563: | Верхние Лихоборы • Селигерская • Яхромская • Лианозово • Марк (→) • Новодачная • Долгопрудная |
746: | Северный — 4-й микрорайон • Физтех • Новодачная • Долгопрудная |
«→» — остановки проходятся только при движении в прямом направлении; «←» — остановки проходятся только при движении в обратном направлении.
По ж/д станции, не входящей в МЦД
[править код]Краткий список маршрутов
[править код]{{#invoke:НОТ Москвы|railway_mini|Лось (платформа)}}
А: с15, 50, 176, 181, 183, 185, 346, 375, 605, 696, 774, т80
Чуть удлинённый список маршрутов
[править код]{{#invoke:НОТ Москвы|railway_midi|Лось (платформа)}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
- Автобусы: с15, 50, 176, 181, 183, 185, 346, 375, 605, 696, 774, т80
Полный список маршрутов
[править код]{{#invoke:НОТ Москвы|railway|Лось (платформа)}}
На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта[1]:
Автобусы | |
---|---|
с15: | Платформа Лось • Бабушкинская • Медведково • Малыгинский проезд |
50: | Платформа Лось • Медведково • 10-й квартал Медведкова |
176: | Платформа Лось • Свиблово • Проезд Русанова |
181: | Осташковская улица • Медведково • Бабушкинская • Платформа Лось |
183: | Платформа Лось • Институт пути |
185: | Платформа Лось • Свиблово • Ботанический сад |
346: | Платформа Лось • Бабушкинская • Проезд Шокальского |
375: | Платформа Лось • Ростокино • ВДНХ • ВДНХ (главный вход) |
605: | Юрловский проезд • Отрадное • Бабушкинская • Платформа Лось |
696: | Платформа Лось • Бабушкинская • Медведково • Осташковская улица |
774: | Лобненская улица • Марк (→) • Лианозово • Алтуфьево • Медведково • Платформа Лось |
т80: | 6-й микрорайон Бибирева • Алтуфьево • Медведково • Платформа Лось |
«→» — остановки проходятся только при движении в прямом направлении; «←» — остановки проходятся только при движении в обратном направлении.
Конечные пункты по конкретному маршруту
[править код]{{#invoke:НОТ Москвы|firstlast|А м6}}
Стадион «Лужники» (южная) — Дангауэровка
Список остановок по конкретным маршрутам
[править код]{{#invoke:НОТ Москвы|num|А м6|А е85|А 123}}
«→» — остановки проходятся только при движении в прямом направлении; «←» — остановки проходятся только при движении в обратном направлении.
Таблицы
[править код]Для полноценного функционирования модуля следует поддерживать в актуальном состоянии три таблицы. Они написаны в формате JSON. Когда требуются комментарии, следует использовать поле "desc". Например,
{
"bus": "А 627к",
"stop": "Амурский переулок",
"link": "Амурский переулок (Москва)",
"desc": "временно"
},
или, чтоб закомментировать элемент целиком,
{
"desc": {
"bus": "А т22",
"stop": "Комсомольская площадь",
"m": true
}
},
Если выдаётся сообщение, что поле desc уже занято, можно использовать нумерацию, например, desc1, desc2, desc3.
Нет необходимости заботиться о форматировании. Все отступы и переводы строк подставляются движком автоматически, при условии отсутствия сообщений о синтаксических ошибках в редакторе кода.
Таблица complexes (на странице Модуль:НОТ Москвы/data.json)
[править код]Таблица содержит все пересадочные узлы метро, в которых имеются разноимённые станции, а также все случаи, когда несколько разноимённых объектов надо рассматривать как одну остановку. Каждая строка таблицы соответствует одному пересадочному узлу. Все входящие в него несовпадающие названия станций метро заносятся в поля name1
, name2
, name3
, name4
, а других объектов — в поля tag1
, tag2
, tag3
, tag4
, причём и те, и другие в том же формате, как и в списке остановок (в полях stop
/alias
и link
/tag
соответственно).
Таблица buses (на странице Модуль:НОТ Москвы/data.json)
[править код]Таблица содержит все маршруты наземного общественного транспорта. Индекс таблицы состоит из префикса (А, Тб, Тм для автобусов, троллейбусов и трамваев соответственно), пробела и номера маршрута. Поля:
kind
— А, Тб или Тм;name
— номер, можно в виде викиссылки на статью, в которой описывается маршрут;comment
(опционально) — примечание, которое должно быть показано в конце списка остановок (скобки и форматирование уменьшенным шрифтом добавляются автоматически);status
— два варианта: '+' для временных маршрутов и '-' для временно отменённых;status_from
— дата (текстовое поле в формате 'YYYYMMDD'; если она известна), начиная с которой надо показывать временный маршрут либо помечать временно отменённый;status_to
— аналогично предыдущему, дата, по которую включительно это надо делать.
Таблица stops (на странице Модуль:НОТ Москвы/stops.json)
[править код]Таблица содержит основные остановки. Порядок перечисления маршрутов и остановок в этой таблице должен соответствовать желаемому порядку их перечисления в статье:
bus
— маршрут, как в индексе предыдущей таблицы;stop
— название остановки;link
— название статьи для викификации названия остановки; если совпадает со значением stop, то надо занести значение '=';alias
— то же, но для случая, когда остановка называется иначе: тогда в stop задаётся истинное название, а в alias название для поиска;m=true
(опционально) — признак, что остановка находится при станции метро/МЦК/МЦД и её название будет пропущено через шаблон {{ММ}}; в противном случае оно будет показано как в поле stop;i=true
(опционально) — признак, что остановка является важной; если функция выдаёт не все остановки, то будут выданы только помеченные как i=true и m=true;comment
(опционально) — аналогично примечанию в предыдущей таблице, но после конкретной остановки.
- ↑ 1 2 3 4 5 6 Реестр муниципальных маршрутов регулярных перевозок пассажиров и багажа автомобильным и наземным электрическим транспортом в городе Москве . Портал открытых данных правительства Москвы. Дата обращения: 26 сентября 2020.
local p = {}
local foundcomplex
local greatcomment='<small>«→» — остановки проходятся только при движении в прямом направлении; «←» — остановки проходятся только при движении в обратном направлении.</small>'
local greatfootnote='<ref name="module">{{cite web |author= |url=https://data.mos.ru/opendata/7704786030-reestr-munitsipalnyh-marshrutov-regulyarnyh-perevozok|title=Реестр муниципальных маршрутов регулярных перевозок пассажиров и багажа автомобильным и наземным электрическим транспортом в городе Москве|lang=ru |website=Портал открытых данных правительства Москвы|publisher= |date= |accessdate=2020-09-26}}</ref>'
local zeroedit='[[Категория:Википедия:Страницы с ежедневно совершаемой нулевой правкой]]'
-- Внимание! Данные перенесены в формат JSON, подробности по адресу https://ru.wikipedia.org/wiki/Модуль:НОТ_Москвы#Таблицы (в описании на текущей странице)
-- JSON part
local jsontable = mw.loadJsonData('Модуль:НОТ Москвы/data.json')
local stops = mw.loadJsonData('Модуль:НОТ Москвы/stops.json').stops
function deepcopy(original)
if (type(original) == 'nil') then
return nil
elseif (type(original) == 'number') then
return 0 + original
elseif (type(original) == 'string') then
return '' .. original
elseif (original == true) then
return true
elseif (original == false) then
return false
elseif (type(original) == 'function') then
return mw.clone(original)
elseif (type(original) ~= 'table') then
error('Unknown type: ' .. type(original))
end
local copy = {}
for key, value in pairs(original) do
copy[key] = deepcopy(value)
end
return copy
end
local complexes = jsontable.complexes
local kinds = jsontable.kinds
local buses = deepcopy(jsontable.buses)
function p.metro(frame)
return fu(frame,false,false,false,'На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта'
..frame:preprocess(greatfootnote)..':')
end
function p.street(frame)
return fu(frame,true,true,false,'Здесь проходят следующие маршруты городского пассажирского транспорта'
..frame:preprocess(greatfootnote)..':')
end
function p.railway(frame)
return fu(frame,true,false,false,'На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта'
..frame:preprocess(greatfootnote)..':')
end
function p.metro_mini(frame)
return fu(frame,false,false,true)
end
--function p.street_mini(frame)
-- return fu(frame,true,true,true)
--end
function p.railway_mini(frame)
return fu(frame,true,false,true)
end
function p.metro_midi(frame)
return fu(frame,false,false,true,'На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта'
..frame:preprocess(greatfootnote)..':')
end
function p.railway_midi(frame)
return fu(frame,true,false,true,'На этой станции можно пересесть на следующие маршруты городского пассажирского транспорта'
..frame:preprocess(greatfootnote)..':')
end
function p.num(frame)
return numloop(frame,false)
end
function p.numfull(frame)
return numloop(frame,true)
end
function numloop(frame,showall)
local rtn='{|style="line-height:130%; border-collapse:collapse"\r\n'
local z=false
for nBus,xBus in pairs(frame.args) do
if xBus~='' then
oBus=buses[xBus]
if oBus then
if bus_ok(oBus) then
rtn=rtn..onebus(xBus,oBus,'',true,showall,frame,false)
end
if zeroedit_needed(oBus) then
if onebus(xBus,oBus,'',true,showall,frame,true) then
z=true
end
end
else
rtn=rtn..'[[Категория:Статьи с несуществующим маршрутом при обращении к модулю НОТ Москвы]]\r\n'
end
end
end
rtn=rtn..'|}\r\n'..greatcomment..'\r\n'
if z then
rtn=rtn..zeroedit
end
return rtn
end
function p.firstlast(frame)
local bus=frame.args[1]
return firstorlast(frame,bus,'both')
end
function firstorlast(frame,bus,what)
local first=''
local last=''
local stop
for nnStop,xxStop in pairs(stops) do
if xxStop.bus==bus then
if what=='both' then
if xxStop.m then
stop=frame:expandTemplate{title='Московские маршруты',args={xxStop.stop}}
else
stop=xxStop.stop
end
if xxStop.link=='=' then
stop='[['..stop..']]'
elseif xxStop.link then
stop='[['..xxStop.link..'|'..stop..']]'
end
if xxStop.comment then
stop=stop..' <small>('..xxStop.comment..')</small>'
end
else
stop=xxStop.stop
end
if first=='' then
if what=='first' then
return stop
end
first=stop
end
last=stop
end
end
if what=='both' then
return first..' — '..last
elseif what=='last' then
return last
end
end
function fu(frame,bytag,showall,mini,intro)
local current=frame.args[1]
local z=false
if not bytag then
local pos=string.find(current,'(',1,true)
if pos then
current=string.sub(current,1,pos-2)
end
end
local rtnrtn=''
local cou=0
for nKind,xKind in pairs(kinds) do
local rtn=''
for nStop,xStop in pairs(stops) do
local oBus=buses[xStop.bus]
if oBus then
if oBus.kind==xKind.kind and oBus.done==nil then
if bus_ok(oBus) then
local mustdo
foundcomplex=nil
for nComplex,xComplex in pairs(complexes) do
if complex_found(xComplex,current,bytag) then
foundcomplex=xComplex
end
end
mustdo=stop_ok(xStop,current,bytag,false)
if mustdo then
cou=cou+1
oBus.done=true
if mini then
if rtn~='' then
rtn=rtn..', '
end
rtn=rtn..oBus.name
else
rtn=rtn..onebus(xStop.bus,oBus,current,bytag,showall,frame,false)
end
end
end
if zeroedit_needed(oBus) then
if onebus(xStop.bus,oBus,current,bytag,showall,frame,true) then
z=true
end
end
end
end
end
if rtn~='' then
if mini then
if intro then
if rtnrtn~='' then
rtnrtn=rtnrtn..'\r\n'
end
rtnrtn=rtnrtn..'* [['..xKind.link..'|'..xKind.title..']]: '..rtn
else
if rtnrtn~='' then
rtnrtn=rtnrtn..'; '
end
rtnrtn=rtnrtn..'[['..xKind.link..'|'..xKind.prefix..']]: '..rtn
end
else
rtnrtn=rtnrtn..'|-\r\n!colspan=2 align=left|[['..xKind.link..'|'..xKind.title..']]\r\n'..rtn
end
end
end
if rtnrtn=='' then
rtnrtn='[[Категория:Статьи с проблемой в исходных данных в модуле НОТ Москвы]]'
end
if mini then
if z then
rtnrtn=rtnrtn..zeroedit
end
if intro then
return intro..'\r\n'..rtnrtn
else
return rtnrtn
end
else
rtnrtn='{|style="line-height:130%; border-collapse:collapse"\r\n'..rtnrtn..'|}\r\n'..greatcomment..'\r\n'
if intro then
rtnrtn=intro..'\r\n'..rtnrtn
end
if z then
rtnrtn=rtnrtn..zeroedit
end
if cou>9 then
return frame:expandTemplate{title='Начало скрытого блока',args={'Список маршрутов'}}..'\r\n'..rtnrtn..'\r\n'..frame:expandTemplate{title='Конец скрытого блока',args={}}
else
return rtnrtn
end
end
end
function onebus(bus,oBus,current,bytag,showall,frame,for_zeroedit)
local name=oBus.name
local tmp=''
local first=firstorlast(frame,bus,'first')
local last=firstorlast(frame,bus,'last')
for nnStop,xxStop in pairs(stops) do
if xxStop.bus==bus then
local stop=''
local isCurrent=stop_ok(xxStop,current,bytag,true)
if isCurrent then
if for_zeroedit then
return true
end
stop=xxStop.stop
elseif xxStop.m then
stop=frame:expandTemplate{title='Московские маршруты',args={xxStop.stop}}
elseif xxStop.i or showall or xxStop.stop==first or xxStop.stop==last then
stop=xxStop.stop
end
if stop~='' then
if tmp~='' then
tmp=tmp..' <b>•</b> '
end
local i1=''
local i2=''
if stop_ok(xxStop,current,bytag,false) then
i1='<i>'
i2='</i>'
end
if isCurrent then
tmp=tmp..i1..stop..i2
elseif xxStop.link then
if xxStop.link=='=' then
tmp=tmp..i1..'[['..stop..']]'..i2
else
tmp=tmp..i1..'[['..xxStop.link..'|'..stop..']]'..i2
end
else
tmp=tmp..i1..stop..i2
end
if xxStop.comment then
tmp=tmp..' <small>('..xxStop.comment..')</small>'
end
end
end
end
if for_zeroedit then
return false
end
if oBus.comment then
tmp=tmp..' <small>('..oBus.comment..')</small>'
end
if oBus.status=='+' then
name=name..' <small>(временно введён)</small>'
elseif oBus.status=='-' and status_ok(oBus) then
name=name..' <small>(временно отменён)</small>'
end
return '|-\r\n!style="vertical-align:top; text-align:right; width:2.5em" nowrap|'..name..':\r\n|'..tmp..'\r\n'
end
function status_ok(oBus)
local today=os.date('%Y%m%d')
if oBus.status_from then
if today<oBus.status_from then
return false
end
end
if oBus.status_to then
if today>oBus.status_to then
return false
end
end
return true
end
function zeroedit_needed(oBus)
return oBus.status_from~=nil or oBus.status_to~=nil
end
function bus_ok(oBus)
if oBus.status=='+' and not status_ok(oBus) then
return false
elseif oBus.status=='-' and status_ok(oBus) then
return false
else
return true
end
end
function stop_ok(oStop,current,bytag,forlink)
if oStop.m then
cf=complex_found(foundcomplex,oStop.stop,false) or complex_found(foundcomplex,oStop.alias,false)
else
cf=complex_found(foundcomplex,oStop.tag,true) or complex_found(foundcomplex,oStop.tag2,true)
or complex_found(foundcomplex,oStop.link,true) or (oStop.link=='=' and complex_found(foundcomplex,oStop.stop,true))
end
if bytag then
return ((oStop.tag==current or oStop.tag2==current) and not forlink) or oStop.link==current or (oStop.link=='=' and oStop.stop==current)
or cf
else
return oStop.m==true and (oStop.stop==current or oStop.alias==current) or cf
end
end
function complex_found(oComplex,cur,bytag)
if cur==nil or oComplex==nil then
return false
end
if bytag then
return cur==oComplex.tag1 or cur==oComplex.tag2 or cur==oComplex.tag3 or cur==oComplex.tag4
else
return cur==oComplex.name1 or cur==oComplex.name2 or cur==oComplex.name3 or cur==oComplex.name4
end
end
return p
-- =p.list{args={'Боровицкая'}}