Модуль:Mapframe для карток
Зовнішній вигляд
| Цей модуль позначений як К:реліз, готовий до загального вжитку (259). Він досягнув стадії готовності й вважається, що вільний від помилок і може використовуватись всюди, де знадобиться. Його можна згадувати на довідкових сторінках та інших сторінках Вікіпедії як можливість для навчання новачків. Аби зменшити навантаження на сервери та некоректний показ сторінок, його потрібно вдосконалювати через тестування у пісочниці[en], а не через застосування спроб і помилок. |
| Цей модуль позначено як К:такий, що потребує захищеного статусу (117). Завершені модулі використовуються в дуже великій кількості статей, або часто використовуються як підстановки. Позаяк акти вандалізму або помилки можуть вплинути на багато сторінок і навіть незначне редагування призведе до істотного навантаження на сервери, вони підлягають захисту від редагувань. |
| Цей модуль Lua використовується на близько 411 000 сторінках або близько 8% всіх сторінок. Для уникнення великомасштабних збоїв та непотрібного навантаження на сервер, будь-які зміни спочатку потрібно перевірити на підсторінках /пісочниці та /тестів цього модуля, або у вашій пісочниці модуля. Потім перевірені зміни можуть бути впроваджені на цій сторінці єдиним редагуванням. Будь ласка, обговорюйте будь-які зміни на сторінці обговорення перед їхнім впровадженням. |
Цей модуль впроваджує {{Mapframe для карток}}. Детальніше щодо його роботи, див. документацію шаблону.
Використання
Модуль можна викликати у вікітексті, використавши: {{#invoke:Mapframe для карток|main}}, однак для більшості випадків рекомендується використовувати відповідний шаблон.
Документація вище включена з Модуль:Mapframe для карток/документація. (ред. | історія)
Дописувачі можуть експериментувати на підсторінках пісочниці (ред. | різн.) та тести (створити) цього модуля.
Будь ласка, додавайте категорії до підсторінки /документація. Підсторінки цієї сторінки.
Дописувачі можуть експериментувати на підсторінках пісочниці (ред. | різн.) та тести (створити) цього модуля.
Будь ласка, додавайте категорії до підсторінки /документація. Підсторінки цієї сторінки.
--отримати текст виду <mapframe width=300 height=300 zoom=4 longitude=30 latitude=50 align=center frameless>{"type": "ExternalData","service": "geoshape","ids": "Q170036"}</mapframe> для вставки в шаблони-картки
local p = {}
--функція яка перевіряє чи присутнє певне значення в масиві
function value_in_array(tab, value)
for _ , v in ipairs(tab) do
if(v == value) then return true; end
end
return false
end
--функція яка перевіряє чи присутній кожен елемент в ланцюжку таблиць запиту до Вікіданих
local function is_wdvalue_exist(item, properties, value_name)
if item:getBestStatements(properties)[1] and item:getBestStatements(properties)[1].mainsnak and item:getBestStatements(properties)[1].mainsnak.datavalue and item:getBestStatements(properties)[1].mainsnak.datavalue.value and item:getBestStatements(properties)[1].mainsnak.datavalue.value[value_name] then
return true
end
return false
end
--функція яка перевіряє чи не є текстовий рядок порожнім (розміром 0 або значення nil)
function is_not_empty(var)
if(var) then
if(string.len(var)>0) then return true; else return false; end
else return false;
end
end
--функція для відображення одразу декількох контурів
function multiple_shapes(items)
shape_res = {}
start_str = '{"type": "ExternalData", "service": "';
end_str = '", "properties": {"fill-opacity": 0.2}},';
items_list = mw.text.split(items, ";");
for _ , q in ipairs(items_list) do
q = mw.text.split(q, " ")[1]
if(string.find(q, ".map")) then geo_type = 'page", "title": "'; else geo_type = 'geoshape", "ids": "'; end
table.insert(shape_res, start_str..geo_type..q..end_str);
end
return table.concat(shape_res);
end
function p.main(frame)
--отримуємо аргументи, передані до шаблону
parent = frame:getParent();
args = parent.args;
--при помилці буде повертатись таке значення
errormessage = "[[Категорія:Сторінки із некоректними мапами]]";
--шаблони, що використовують цей модуль, будуть включатись до спеціальної категорії
templatescat = "[[Категорія:Шаблони, в яких використовується mapframe]]";
--при відсутності властивості Вікіданих для географічних координат (P625), повернеться таке значення
no_p625 = "[[Категорія:Вікідані:P625:відсутня]]";
if(is_not_empty(args["no_p625"])) then no_p625 = "[["..args["no_p625"].."]]"; end
--при відсутності властивості Вікіданих для площі (P2046), повернеться таке значення
no_p2046 = "[[Категорія:Вікідані:P2046:відсутня]]";
if(is_not_empty(args["no_p2046"])) then no_p2046 = "[["..args["no_p2046"].."]]"; end
--змінні для збереження значень аргументів, або за їх відсутності, значень за замовчуванням
width = 300; height = 300; frameless = " frameless"; text = ""; align = "center";
--перевіряємо чи присутній аргумент елемента Вікіданих, якщо ні, то беремо елемент для поточної сторінки
if(is_not_empty(args["елемент"])) then element = args["елемент"];
else element = mw.wikibase.getEntityIdForCurrentPage(); end
if(not element) then return errormessage; end
--перевіряємо чи присутні аргументи ширини і висоти мапи, якщо ні, то залишаємо значення за замовчуванням
if(is_not_empty(args["ширина"])) then width = args["ширина"]; end
if(is_not_empty(args["висота"])) then height = args["висота"]; end
--перевіряємо чи присутні аргументи широти (північ-південь) та довготи (захід-схід), якщо ні, то пізніше їх отримаємо з Вікіданих
if(is_not_empty(args["широта"]) and is_not_empty(args["довгота"])) then latitude = args["широта"]; longitude = args["довгота"]; end
--перевіряємо чи присутній аргумент масштабу, якщо ні, то пізніше отримаємо з Вікіданих
if(is_not_empty(args["масштаб"])) then zoom = args["масштаб"]; end
--перевіряємо інші аргументи
if(is_not_empty(args["рамка"])) then frameless = ""; end
if(is_not_empty(args["текст"])) then text = args["текст"]; end
if(is_not_empty(args["вирівнювання"])) then align = args["вирівнювання"]; end
geo = "geoshape";
if(is_not_empty(args["geo"])) then geo = args["geo"]; end
if(is_not_empty(args["geoshape"])) then geo = "geoshape"; end
--перевіряємо чи були отримані координати та масштаб із аргументів, якщо ні то працюватимемо із Вікіданими
if( ((not latitude) and (not longitude)) or (not zoom) ) then
--отримуємо об'єкт для елемента Вікіданих
item = mw.wikibase.getEntity(element);
if(not item) then return errormessage; end
--отримуємо список властивостей для елемента
properties = item:getProperties()
--якщо вказані значення властивостей для крайніх точок, рахуємо координати та масштаб з них
if(value_in_array(properties, 'P1332') and value_in_array(properties, 'P1333') and value_in_array(properties, 'P1334') and value_in_array(properties, 'P1335')) and
(is_wdvalue_exist(item, 'P1332', 'latitude') and is_wdvalue_exist(item, 'P1333', 'latitude') and is_wdvalue_exist(item, 'P1334', 'longitude') and is_wdvalue_exist(item, 'P1335', 'longitude')) then
--отримуємо значення властивостей, що відповідають крайнім точкам
nlat = item:getBestStatements('P1332')[1].mainsnak.datavalue.value.latitude;
slat = item:getBestStatements('P1333')[1].mainsnak.datavalue.value.latitude;
wlon = item:getBestStatements('P1335')[1].mainsnak.datavalue.value.longitude;
elon = item:getBestStatements('P1334')[1].mainsnak.datavalue.value.longitude;
--якщо з аргументів не були отримані широта та довгота, отримуємо їх порахувавши середнє значення властивостей для крайніх точок
if( ((not latitude) and (not longitude)) ) then
latitude = tostring((nlat+slat)/2);
longitude = tostring((wlon+elon)/2);
end
--якщо з аргументу не був отриманий масштаб, отримуємо його за відстанню між крайніми точками
if(not zoom) then
wid = math.abs(elon-wlon); --відстань між західною та східною крайніми точками
hei = math.abs(nlat-slat); --відстань між північною та південною крайніми точками
if(hei>wid) then distance = hei; else distance = wid; end
if(hei>wid) then mapsize = height; else mapsize = width; end
zoom = math.floor(math.log((distance/360)*(300/mapsize))/math.log(1/2) - 0.2);
end
end
end
--якщо координатів досі нема, отримаємо їх з властивості для географічних координат
if( (not latitude) and (not longitude) and value_in_array(properties, 'P625') ) then
latitude = item:getBestStatements('P625')[1].mainsnak.datavalue.value.latitude;
longitude = item:getBestStatements('P625')[1].mainsnak.datavalue.value.longitude;
end
--якщо масштабу досі нема, отримаємо його з властивості для площі
if((not zoom) and value_in_array(properties, 'P2046')) then
area_obj = item:getBestStatements('P2046')[1].mainsnak.datavalue.value;
area = area_obj.amount;
area_unit = area_obj.unit;
area_unit = string.sub(area_unit, string.find(area_unit, "Q"), -1);
if(area_unit=="Q712226") then --кв км
elseif(area_unit=="Q35852") then area = area/100; --га
elseif(area_unit=="Q232291") then area = area*2.589988; --кв миля
elseif(area_unit=="Q25343") then area = area/1000000; --кв м
elseif(area_unit=="Q81292") then area = area*0.004046856; --акр
else return no_p2046; end
if (tonumber(area)<0.1) then zoom = 15 -- default zoom
else zoom = math.floor(15 - (math.log(2.5*area)/math.log(4)) ); end
end
zoom = zoom or 12
--якщо координати та масштаб визначені, повертаємо текстовий рядок з результатом
if(latitude and longitude and zoom) then
--якщо аргумент "текст" було задано, заміняємо в ньому лапки на html-коди
if(text~="") then
text = string.gsub(text, '"', """);
text = string.gsub(text, "'", "'")
text = ' text="' .. text .. '"';
end
--записуємо всі необхідні змінні в таблицю, об'єднуємо її в текстовий рядок, який повертаємо як результат
if(is_not_empty(args["контур"])) then shape = {'page","title": "', args["контур"]};
else shape = {geo,'","ids": "', element}; end --нас цікавить саме об'єкт, а не оточення - geoshape"
--можна задавати текст, який відображатиметься перед та після шаблону, якщо шаблон відображається
--якщо шаблон не відображається, то і цей текст не відображатиметься
--якщо префікс та постфкс не задані, присвоюємо їм порожнй рядок, щоб вони не мали значення nil
if(not is_not_empty(args["префікс"])) then args["префікс"] = ""; end
if(not is_not_empty(args["постфікс"])) then args["постфікс"] = ""; end
if(not is_not_empty(args["додатково"])) then args["додатково"] = ""; end
if(is_not_empty(args["перелік"])) then args["перелік"] = multiple_shapes(args["перелік"]); else args["перелік"] = ""; end
res = {args["префікс"], "{{anchor|map-osm}}<mapframe width=", width,
" height=", height, " zoom=", zoom, " latitude=", latitude,
" longitude=", longitude, " align=", align, frameless, text,
'>[', args["перелік"], args["додатково"], '{"type": "ExternalData","service": "', table.concat(shape),
'\","properties": {"fill-opacity": 0.3}}]</mapframe>', args["постфікс"]};
return frame:preprocess(table.concat(res));
--якщо ні, то додаємо сторінку до необхідної категорії спостереження
else
if(string.find(tostring(mw.title.getCurrentTitle()), "Шаблон:")) then
return templatescat;
else
if(not zoom) then return no_p2046; end
if( (not latitude) or (not longitude) ) then return no_p625; end
end
end
end
return p;