Module:User:kc kennylau/map

local export = {}

local m_links = require("Module:links") local lang = require("Module:languages").getByCode("zh")

local radius = 0.001

local colors = { "d2502e", "6941c7", "9fdd42", "e7ff79", "b66063", "30bcff", "c6ceff", "02f291", "2e1200", "a4ff46", "ffcccf", "63001e", "c124de", "00ae2d", "ff4ce4", "6fff8b", "b900b1", "bfff6b", "0035b6", "fffe8d", "61008c", "adff9e", "d463ff", "3c8a00", "db0098", "00c97f", "a20090", "01a145", "ff5ec8", "59ffc6", "e50025", "01c0cc", "a60003", "02b9db", "d37200", "0151c6", "949900", "00156f", "ffa938", "290062", "b69700", "6d87ff", "c88100", "014592", "ff823e", "000f36", "bdffc4", "1e003b", "ffce7a", "320029", "d5ffea", "6a0050", "009267", "ff4c61", "019282", "fd98ff", "094300", "ad96ff", "965a00", "8eb0ff", "761f00", "9bd8ff", "490d00", "fbffe9", "1d000f", "feecff", "00141e", "ffddad", "001b14", "ff93ce", "004f23", "9d0050", "005e5e", "ffa291", "003e33", "ff9cac", "00536c", "ffc594", "0079b1", "5a3600", }

local grey = "ccccbf"

local groupZH = { ["Northeastern Mandarin"]	= "燕京官話", ["Jilu Mandarin"]			= "冀魯官話", ["Jiaoliao Mandarin"]		= "膠遼官話", ["Lanyin Mandarin"]			= "蘭銀官話", ["Central Plains Mandarin"]	= "中原官話", ["Southwestern Mandarin"]	= "西南官話", ["Jianghuai Mandarin"]		= "江淮官話", ['Mandarin'] = '官話', ['Cantonese'] = '粵語', ['Hakka'] = '客家話', ['Huizhou'] = '徽語', ['Gan'] = '贛語', ['Jin'] = '晉語', ['Jiuxing Yumin'] = '九姓漁民方言', ['Northern Min'] = '閩北語', ['Eastern Min'] = '閩東語', ['Southern Min'] = '閩南語', ['Puxian Min'] = '莆仙閩語', ['Zhongshan Min'] = '中山閩語', ['Central Min'] = '閩中語', ['Shaojiang Min'] = '邵將閩語', ['Southern Pinghua'] = '桂南平話', ['Northern Pinghua'] = '桂北平話', ['Shehua'] = '畬話', ['Waxiang'] = '瓦鄉話', ['Wu'] = '吳語', ['Xiang'] = '湘語', ['Xiangnan Tuhua'] = '湘南土話', ['Yuebei Tuhua'] = '粵北土話', }

function export.make_list(data) return "" .. table.concat(data,"") .. "" end

function export.map_header(text) return tostring(		mw.html.create("h2")			:wikitext(text)		:done	) end

function export.get_coords(lat,long,i,n) if n > 1 then return {long+radius*math.cos(2*math.pi*i/n),lat+radius*math.sin(2*math.pi*i/n)} else return {long,lat} end end

function export.make_point(lat,long,color,text,i,n) return { type = "Feature", properties = { title = text, ["marker-color"] = color, ["marker-size"] = "small", },		geometry = { type = "Point", coordinates = export.get_coords(lat,long,i,n) }	} end

function export.legend(colour, show, cat, hide) return tostring(		mw.html.create("div")			:addClass("zh-dial-map__legend-row")			:addClass((colour == grey and "zh-dial-map__legend-row-other" or nil))			:tag("div")				:addClass("vsSwitcher")				:attr("data-toggle-category", cat)				:attr("data-vs-showtext", "lects ▼")				:attr("data-vs-hidetext", "lects ▲")

:addClass("zh-dial-map__legend-row-dot") :css("background-color", "#" .. colour) :wikitext("") :done :tag("span") :addClass("vsToggleElement") :wikitext("") :done :wikitext(show) :tag("div") :addClass("vsHide") :wikitext(hide) :allDone ) end

function export.make_legends(legend) -- divide into five columns manually -- DO NOT replace with css column-count local r = #legend%5 local q = math.floor(#legend/5) local d1 = q+(r>0 and 1 or 0) local d2 = d1+q+(r>1 and 1 or 0) local d3 = d2+q+(r>2 and 1 or 0) local d4 = d3+q+(r>3 and 1 or 0) local l1 = table.concat(legend,"",1,d1) local l2 = table.concat(legend,"",d1+1,d2) local l3 = table.concat(legend,"",d2+1,d3) local l4 = table.concat(legend,"",d3+1,d4) local l5 = table.concat(legend,"",d4+1,#legend) local cell = {width="20%",["vertical-align"]="top"} return tostring(		mw.html.create("table"):css("width","100%"):tag("tr")			:tag("td"):css(cell):wikitext(l1):done			:tag("td"):css(cell):wikitext(l2):done			:tag("td"):css(cell):wikitext(l3):done			:tag("td"):css(cell):wikitext(l4):done			:tag("td"):css(cell):wikitext(l5):done		:allDone	) end

function export.make_map(frame,geojson,legend) return tostring(		mw.html.create("div")			:addClass("thumb")			:addClass("zh-dial-map__container")			:wikitext(frame:extensionTag("mapframe",mw.text.jsonEncode(geojson),{				class = "zh-dial-map__map",				mapstyle = "osm-intl",				width = 1200,				height = 600,				longitude = 104.1954,				latitude = 35.8617,				zoom = 4			}))			:done

:wikitext(legend) :done :done ) end

function export.show(frame) local geojson = {} local legend = {} local dial = mw.loadData("Module:zh/data/dial") local syn = mw.loadData("Module:zh/data/dial-syn/"..frame.args[1]).list local locs = {} local n = {} for _,lect in ipairs(dial) do		local syn_lect = syn[lect.key] or {""} if syn_lect[1] ~= "" and lect.lat then n[lect.key] = 0 -- `#` doesn't work with mw.loadData local lect_en = (lect.english or lect.key) .. " " .. lect.group local lect_zh = lect.chinese .. groupZH[lect.group] local i = 0 for _,form in ipairs(syn_lect) do				local notes = form:match(":(.+)") if not notes or not notes:find("GT",1,true) then i = i + 1 n[lect.key] = n[lect.key] + 1 form = form:gsub(":.+","") locs[form] = locs[form] or {} table.insert(locs[form],{						key=lect.key,						en=lect_en,						zh=lect_zh,						lat=lect.lat,						long=lect.long,						i=i}) end end end end local forms = {} for form,lects in pairs(locs) do		table.insert(forms,form) end table.sort(forms, function(fst, snd) return #locs[fst] > #locs[snd] end) local grey_limit = #forms > 80 and #locs[forms[81]] or 0 local greyed = false local greys = {} local grey_count = 0 for i,form in ipairs(forms) do		local lects = locs[form] greyed = greyed or (#lects <= grey_limit) local color = greyed and grey or colors[i] local legend_lects = {} for _,lect in ipairs(lects) do local display = lect.en .. " " .. lect.zh				.. ": "..form.."" table.insert(geojson,export.make_point(lect.lat,lect.long,color,display,lect.i,n[lect.key])) if not greyed then table.insert(legend_lects, lect.zh .. " (" .. lect.en .. ")")			end end local link = m_links.full_link({			lang = lang,			term = form:gsub("_[1-9]$", ""),			alt = form:gsub("_([1-9])$", "%1%2"),			tr = "-",		}) if greyed then for _,lect in ipairs(lects) do table.insert(greys, lect.zh .. " (" .. lect.en .. "): " .. link) end grey_count = grey_count + #lects else table.insert(legend, export.legend(color, link .. " (" .. #lects .. ")", form, export.make_list(legend_lects))) end end if greyed then table.insert(legend, export.legend(grey, "other terms ("..grey_count..")", "others", export.make_list(greys))) end local title = syn.title and syn.title ~= "" and syn.title or frame.args[1] title = title:gsub("[0-9%-]", "") .. "//"	local map_header = export.map_header(		"Map of Chinese dialectal equivalents for " .. m_links.full_link( {				lang = lang, term = title, gloss = syn.meaning, tr = '-' }		)	)	local legends = export.make_legends(legend) local map = export.make_map(frame, geojson, legends) return map_header .. map end

return export