跳转到内容
打开/关闭搜索
搜索
打开/关闭菜单
451
条目
808
文件
22
用户
9259
编辑
Blockland Wiki
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
打开/关闭外观设置菜单
无法加载外观设置。请检查您的网络连接并重试。
重试
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
创建账号
登录
查看“︁模块:OWMOMarket”︁的源代码
来自Blockland Wiki
查看
阅读
查看源代码
查看历史
相关页面
模块
讨论
更多操作
更多
工具
链入页面
相关更改
页面信息
Cargo数据
←
模块:OWMOMarket
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
local p = {} function p.renderSidebar(frame) local extData = mw.ext.externalData if not extData or not extData.getDbData then return "错误:未找到 External Data 接口" end -- 1. 获取最新期数并推算 8 期(1个月)前的起点 local latest_data = extData.getDbData{ db = 'wp_db', from = 'wp_owmc_currency_rates', ['order by'] = 'year DESC, month DESC', limit = 1, data = 'year=year, month=month' } if not latest_data or not latest_data[1] then return "暂无行情数据" end local max_y = tonumber(latest_data[1].year) local max_m = tonumber(latest_data[1].month) local max_abs = max_y * 104 + max_m local min_abs = max_abs - 7 -- 2. 一次性抓取这 8 期的所有行情数据 local where_clause = string.format("(year * 104 + month) >= %d", min_abs) local all_rates = extData.getDbData{ db = 'wp_db', from = 'wp_owmc_currency_rates', where = where_clause, limit = 5000, data = 'currency_code=currency_code, year=year, month=month, rate=rate' } local meta_data = extData.getDbData{ db = 'wp_db', from = 'wp_owmc_currency_meta', limit = 200, data = 'currency_code=currency_code, currency_name=currency_name' } -- 3. 梳理数据结构 & 动态计算 WPV (对数几何平均) local meta_map = {} if meta_data then for _, r in ipairs(meta_data) do meta_map[r.currency_code] = r.currency_name end end local rates_by_abs = {} local codes_set = {} if all_rates then for _, r in ipairs(all_rates) do local abs_p = tonumber(r.year) * 104 + tonumber(r.month) if not rates_by_abs[abs_p] then rates_by_abs[abs_p] = {} end rates_by_abs[abs_p][r.currency_code] = tonumber(r.rate) codes_set[r.currency_code] = true end end local wpv_by_abs = {} for abs_p = min_abs, max_abs do local rates = rates_by_abs[abs_p] if rates then local sum_log = 0; local count = 0 for code, rate in pairs(rates) do if rate > 0 then sum_log = sum_log + math.log(rate); count = count + 1 end end wpv_by_abs[abs_p] = count > 0 and math.exp(sum_log / count) or 1.0 else wpv_by_abs[abs_p] = 1.0 end end -- 4. 统计处理 (WMC归1标价,WPV核算涨跌与画图) local stats = {} local wmc_current = rates_by_abs[max_abs] and rates_by_abs[max_abs]['WMC'] or 1.0 for code, _ in pairs(codes_set) do local current_rate = rates_by_abs[max_abs] and rates_by_abs[max_abs][code] local old_rate = rates_by_abs[min_abs] and rates_by_abs[min_abs][code] if current_rate and old_rate and current_rate > 0 and old_rate > 0 then local val_current = wmc_current / current_rate local wpv_current = wpv_by_abs[max_abs] local wpv_old = wpv_by_abs[min_abs] local fwd_current = wpv_current / current_rate local fwd_old = wpv_old / old_rate local pct = ((fwd_current - fwd_old) / fwd_old) * 100 local history_vals = {} local min_val = math.huge local max_val = -math.huge for abs_p = min_abs, max_abs do local r = rates_by_abs[abs_p] and rates_by_abs[abs_p][code] if r and r > 0 then local w_val = wpv_by_abs[abs_p] / r table.insert(history_vals, w_val) if w_val < min_val then min_val = w_val end if w_val > max_val then max_val = w_val end else table.insert(history_vals, 0) end end table.insert(stats, { code = code, name = meta_map[code] or code, val = val_current, pct = pct, history = history_vals, min_v = min_val, max_v = max_val }) end end table.sort(stats, function(a, b) return a.pct > b.pct end) -- 5. 开始渲染 HTML local html = mw.html.create('div'):cssText("width: 100%; margin: 0; background: transparent; font-family: -apple-system, 'Segoe UI', sans-serif; padding: 4px 8px;") local function renderRow(item) local is_up = item.pct >= 0 local color = is_up and "#f43f5e" or "#10b981" local sign = is_up and "▲ +" or "▼ " local pct_str = string.format("%.2f%%", item.pct) local val_str = string.format("%.4f", item.val) local svg_w = 64 local svg_h = 28 local pts = {} local range_v = item.max_v - item.min_v if range_v == 0 then range_v = 1 end for i, h_val in ipairs(item.history) do local x = (i - 1) / (#item.history - 1) * svg_w local y = 2 + (1 - (h_val - item.min_v) / range_v) * (svg_h - 4) table.insert(pts, string.format("%.1f,%.1f", x, y)) end local line_path = "M" .. table.concat(pts, " L") local area_path = line_path .. string.format(" L%.1f,%.1f L0,%.1f Z", svg_w, svg_h, svg_h) local grad_id = "grad_" .. item.code -- 【无敌魔法】:生成带有 xmlns 的纯净 SVG 字符串 local raw_svg = string.format( '<svg width="%d" height="%d" viewBox="0 0 %d %d" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="%s" x1="0%%" y1="0%%" x2="0%%" y2="100%%"><stop offset="0%%" stop-color="%s" stop-opacity="0.35" /><stop offset="100%%" stop-color="%s" stop-opacity="0.0" /></linearGradient></defs><path d="%s" fill="url(#%s)" /><path d="%s" fill="none" stroke="%s" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" /></svg>', svg_w, svg_h, svg_w, svg_h, grad_id, color, color, area_path, grad_id, line_path, color ) -- 转码为 Base64,MediaWiki 解析器彻底瞎了 local b64_svg = mw.text.encodeBase64(raw_svg) -- 将图表作为 DIV 的背景图渲染 local sparkline = string.format('<div style="width: %dpx; height: %dpx; background-image: url(\'data:image/svg+xml;base64,%s\'); background-repeat: no-repeat; background-position: center; background-size: contain;"></div>', svg_w, svg_h, b64_svg) -- 行容器 return string.format([[ <div style="display: flex; justify-content: space-between; align-items: center; padding: 14px 10px; border-bottom: 1px solid #f1f5f9;"> <div style="flex: 1; text-align: left;"> <div style="font-weight: 900; color: #0f172a; font-size: 15px; font-family: 'Courier New', monospace;">%s</div> <div style="font-size: 12px; color: #64748b; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100px;">%s</div> </div> <div style="flex: 0 0 65px; text-align: center; display: flex; justify-content: center;">%s</div> <div style="flex: 1; text-align: right;"> <div style="font-weight: bold; font-family: 'Courier New', monospace; font-size: 15px; color: #0f172a;">%s</div> <div style="font-size: 12px; font-weight: 800; color: %s; letter-spacing: -0.5px;">%s%s</div> </div> </div> ]], item.code, item.name, sparkline, val_str, color, sign, pct_str) end local function renderHeader(title, color) return mw.html.create('div'):cssText(string.format("font-size: 13px; font-weight: 800; color: %s; text-transform: uppercase; margin-top: 14px; margin-bottom: 4px; padding-left: 10px;", color)):wikitext(title) end html:node(renderHeader("Core Assets / 主币", "#94a3b8")) local cores = {WMC=true, KCK=true, SKV=true, COS=true} for _, item in ipairs(stats) do if cores[item.code] then html:node(mw.html.create('div'):wikitext(renderRow(item))) end end html:node(renderHeader("Top Gainers / 领涨", "#f43f5e")) local count = 0 for _, item in ipairs(stats) do if not cores[item.code] and item.pct > 0 then html:node(mw.html.create('div'):wikitext(renderRow(item))) count = count + 1 if count >= 3 then break end end end html:node(renderHeader("Top Losers / 领跌", "#10b981")) count = 0 for i = #stats, 1, -1 do local item = stats[i] if not cores[item.code] and item.pct < 0 then html:node(mw.html.create('div'):wikitext(renderRow(item))) count = count + 1 if count >= 3 then break end end end html:node(mw.html.create('div') :cssText("text-align: center; font-size: 11px; color: #94a3b8; font-weight: 600; margin-top: 16px; padding-top: 12px; border-top: 1px dashed #e2e8f0;") :wikitext("数据来源: [https://blkl.fun/omoo OMOO (blkl.fun/omoo)]")) return tostring(html) end return p
此页面嵌入的页面:
模块:OWMOMarket/doc
(
查看源代码
)
返回
模块:OWMOMarket
。
查看“︁模块:OWMOMarket”︁的源代码
来自Blockland Wiki